diff --git a/CHANGELOG.md b/CHANGELOG.md index 2f713a54e6..875588b7ce 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,34 +6,151 @@ ### ✨ New Features -- **feat(antigravity):** integrate Antigravity provider with dynamic `maxOutputTokens` calculation (bumping to `thinkingBudget + 1`) and standard Cloud Code envelope payload sanitization (#2055, #2063) +- **feat(antigravity):** integrate Antigravity provider with dynamic `maxOutputTokens` calculation, identity fingerprinting overhaul, and Cloud Code envelope payload sanitization (#2055, #2063) - **feat(gemini-cli):** add custom projectId support for Gemini CLI transport (UI, DB, executor) (#1991) +- **feat(providers):** add KIE media provider support with dynamic polling, text models, and expanded video models catalog +- **feat(providers):** add Z.AI provider support with GLM quota handling and new quota labels +- **feat(providers):** add 9 new free AI providers — LLM7, Lepton, Kluster, UncloseAI, BazaarLink, Completions, Enally, FreeTheAi (#2096) +- **feat(providers):** batch delete provider connections via checkbox multi-select (#2094) +- **feat(cursor):** full OpenAI parity — tool calls, streaming, and session management (#2082) +- **feat(cli):** comprehensive CLI enhancement suite with 20+ new commands including `omniroute providers`, `omniroute combos`, `omniroute doctor` (#2074) +- **feat(cli):** add modular CLI setup and provider management commands (#2046) +- **feat(mcp):** add DeepSeek quota and limit monitoring feature (#2089) +- **feat(circuit-breaker):** classify 429 errors and apply per-kind cooldowns (#2116) +- **feat(multi):** manifest-aware tier routing — W1-W4 complete (#2014) +- **feat(combos):** add reset-aware routing strategy for quota-based providers +- **feat(combo):** add context_length input field to combo edit form (#2047) +- **feat(chat):** dynamic tool limit detection with proactive truncation (#2061) +- **feat(sse):** refresh Claude OAuth wire image to claude-cli/2.1.131 (#2011) +- **feat(github):** add `targetFormat: openai-responses` to all GitHub models (#2122) +- **feat(api):** allow configuration via API calls — open management routes to Bearer keys with manage scope (#2103) +- **feat(api):** update API bridge proxy timeout to 600,000ms (#2019) +- **feat(usage):** add service tier breakdown, codex fast service tier analytics, and account for fast tier +- **feat(chat):** add `STREAM_READINESS_TIMEOUT_MS` and integrate into chat handling +- **feat(combo):** add `fallbackDelayMs` to combo configuration and related settings +- **feat(chat):** enhance error handling for semaphore capacity with fallback logic +- **feat(qdrant):** embedding model discovery (#2086) +- **feat(auth):** per-session sticky routing for Codex (#1887) +- **feat(inworld):** enhance Inworld TTS support (#2123) +- **feat(kiro):** headless auth via kiro-cli SQLite, image support, tool overflow handling, and model list sync (#2129 — thanks @christlau) ### 🐛 Bug Fixes +- **fix(pricing):** make `getPricingForModel` fully case-insensitive to ensure custom prices correctly reflect in new incoming requests cost calculations +- **fix(gemini):** prevent `functionDeclarations` from being dropped by the sanitizer when `googleSearch` tool is present (#2077) +- **fix(pollinations):** add `jsonMode: true` flag in the request transformation to enforce correct JSON structure from Pollinations API (#2109) +- **fix(docker):** update Dockerfile to copy `/docs` directory during build ensuring API catalog availability at runtime (#2083) +- **fix(docker):** include OpenAPI spec in runtime image (#2007) - **fix(providers):** strip OpenAI-specific fields in Kiro translator to prevent 400 errors (#2037) +- **fix(kiro):** normalize tool-use payloads to prevent 400 errors from agents (#2104) +- **fix(kiro):** merge adjacent user history turns after role normalization (#2105) - **fix(ui):** resolve text contrast issues for zero-config warning banner in light mode (#2050) - **fix(core):** inject global system prompt correctly into downstream chat completions pipeline (#2080) +- **fix(core):** restore Claude Code adaptive thinking defaults and resolve audio transcription CORS regression - **fix(routing):** add missing v1beta rewrites to next.config to resolve 404 on Gemini models endpoint (#2102) +- **fix(routing):** fix bare GPT-5.5 routing for Codex-only installations (#2054) +- **fix(routing):** add fuzzy auto-combo routing for `auto/*` model prefix (#2010) - **fix(cache):** optimize cache_control preservation logic and explicitly align tool schema with upstream Claude Code expectations - **fix(db):** preserve legacy SQLite database path on Windows to prevent data loss (#1973) +- **fix(db):** reduce hot-path persistence overhead (#2039) +- **fix(db):** resolve migration conflict by renumbering overlapping migration entries (#2041) - **fix(settings):** resolve model alias persistence double stringification preventing UI updates (#2018) - **fix(routing):** dynamically filter bare model auto-resolution by active provider connections to prevent dead-routing (#2029) - **fix(embeddings):** add Google Gemini embeddings compatibility via OpenAI-compatible endpoint mapping (#2006) +- **fix(sse):** prevent Claude OAuth multi-account correlation via metadata.user_id (#2053) +- **fix(sse):** prevent Claude Code identity cloak overrides and fix fallback resilience (#2053) +- **fix(sse):** classify hour quota errors as QUOTA_EXHAUSTED (#2119) +- **fix(sse):** fix CC-compatible streaming bridge (#2118) +- **fix(antigravity):** sanitize Claude Cloud Code payloads (#2090) +- **fix(antigravity):** add duplex half for streaming bodies +- **fix(antigravity):** align identity protocol and behavior with official AM +- **fix(chatgpt-web):** plumb proxy through to native tls-client (#2022, #2023) +- **fix(codex):** expose native model IDs in catalog (#2012) +- **fix(glm):** add dedicated coding transport (#2087) +- **fix(compression):** support Responses input and expand Spanish compression rules (#2028) +- **fix(catalog):** auto-calculate combo context_length from target model limits (#2030) +- **fix(api):** fix usage analytics and API key identity (#2008, #2092) +- **fix(api-key):** allow Unicode letters in API key name validation (#1996) +- **fix(auth):** allow bootstrap without password (#2048) +- **fix(proxy):** clean up proxy page redundancy and fix 1proxy sync empty body error (#2052) +- **fix(dashboard):** resolve Unknown plan display in Provider Limits +- **fix(usage):** add extensible CURRENCY_SYMBOLS mapping for deepseek currencies +- **fix(runtime):** harden timer handling and model pricing fallback +- **fix(i18n):** complete Simplified Chinese translations (#2115) +- **fix(mitm):** add Linux cert install and skip sudo password when root (#1999) +- **fix(mitm):** prevent stub from loading at runtime via bypass module - **fix:** remove Anthropic-Beta header from non-Anthropic providers to fix identity contamination (#1989) - **fix(cli):** resolve .env loading failure for global npm installations +- **fix(export):** exclude telemetry/usage-history tables from JSON config backups by default to prevent unbounded file growth (#2125) +- **fix(translator):** preserve `body.system` in openai→claude translator when Claude Code sends native Anthropic system array through /chat/completions — fixes v3.7.9 regression where system prompt was silently dropped, triggering Anthropic 429 (#2130) +- **fix:** Follow OpenAI specification, handle throttling in batch and fix UI (#2045) ### 🔒 Security +- **fix(security):** remediate CodeQL vulnerabilities (ReDoS, cryptographic bias, stack trace exposure, and weak password hashing) (#216, #215, #211, #208, #206, #210) - **fix(security):** remediate regex validation backtracking path in core compression cleanup (#1990) - **fix(core):** harden input handling and stabilization for prompt compression edge cases +### 📝 Documentation + +- **docs:** add competitive marketing tables and SEO/AEO optimizations to README (#2091) +- **docs:** refresh providers, model catalogs, and docs for v3.8.0 (#2088) +- **docs:** update Claude MD and update GLM-CN max context to 200k (#2027) +- **docs(env):** add `GITLAB_DUO_OAUTH_CLIENT_ID` to `.env.example` (#2031) + ### 🧹 Chores & Maintenance - **chore(providers):** prune redundant local provider icon assets in favor of `@lobehub/icons` web fonts (#1992) +- **chore(providers):** remove deprecated models (#2033) +- **deps:** bump `fast-uri` from 3.1.0 to 3.1.2 (#2078) +- **deps:** bump `hono` from 4.12.14 to 4.12.18 (#2079) - **ci:** skip SonarCloud scan on main pushes to optimize CI time - **test:** stabilize cooldown abort coverage case in integration testing +### 🏆 v3.8.0 Community Contributors + +Thank you to all **38 community contributors** who made v3.8.0 possible! 🎉 + +| Contributor | PRs | Contributions | +| :--------------------------------------------------------- | :-: | :------------------------------------------------------------ | +| [@oyi77](https://github.com/oyi77) | 7 | #2010, #2014, #2041, #2052, #2061, #2074, #2091, #2094, #2096 | +| [@backryun](https://github.com/backryun) | 4 | #1992, #2033, #2088, #2123 | +| [@dhaern](https://github.com/dhaern) | 4 | #2028, #2039, #2087, #2090 | +| [@Tentoxa](https://github.com/Tentoxa) | 2 | #2011, #2053 | +| [@wauputr4](https://github.com/wauputr4) | 2 | #2009, #2046 | +| [@payne0420](https://github.com/payne0420) | 1 | #2082 | +| [@Tr0sT](https://github.com/Tr0sT) | 1 | #2012 | +| [@AveryanAlex](https://github.com/AveryanAlex) | 1 | #2008 | +| [@nickwizard](https://github.com/nickwizard) | 1 | #1991 | +| [@rodrigogbbr-stack](https://github.com/rodrigogbbr-stack) | 1 | #1996 | +| [@NekoMonci12](https://github.com/NekoMonci12) | 1 | #1999 | +| [@congvc-dev](https://github.com/congvc-dev) | 1 | #2004 | +| [@tatsster](https://github.com/tatsster) | 1 | #2007 | +| [@xssdem](https://github.com/xssdem) | 1 | #2023 | +| [@bypanghu](https://github.com/bypanghu) | 1 | #2027 | +| [@herjarsa](https://github.com/herjarsa) | 1 | #2030 | +| [@wucm667](https://github.com/wucm667) | 1 | #2031 | +| [@hartmark](https://github.com/hartmark) | 1 | #2045 | +| [@ddarkr](https://github.com/ddarkr) | 1 | #2047 | +| [@tces1](https://github.com/tces1) | 1 | #2048 | +| [@guanbear](https://github.com/guanbear) | 1 | #2054 | +| [@Gi99lin](https://github.com/Gi99lin) | 1 | #2055 | +| [@ivan-mezentsev](https://github.com/ivan-mezentsev) | 1 | #2063 | +| [@JxnLexn](https://github.com/JxnLexn) | 1 | #2019 | +| [@yoviarpauzi](https://github.com/yoviarpauzi) | 1 | #2092 | +| [@rafacpti23](https://github.com/rafacpti23) | 1 | #2086 | +| [@gleber](https://github.com/gleber) | 1 | #2103 | +| [@rilham97](https://github.com/rilham97) | 1 | #2104 | +| [@Gioxaa](https://github.com/Gioxaa) | 1 | #2105 | +| [@boa-z](https://github.com/boa-z) | 1 | #2115 | +| [@eleata](https://github.com/eleata) | 1 | #2116 | +| [@rdself](https://github.com/rdself) | 1 | #2118 | +| [@clousky2020](https://github.com/clousky2020) | 1 | #2119 | +| [@abhinavjnu](https://github.com/abhinavjnu) | 1 | #2122 | +| [@HoaPham98](https://github.com/HoaPham98) | 1 | #2089 | +| [@christlau](https://github.com/christlau) | 1 | #2129 | +| [@05dunski](https://github.com/05dunski) | 1 | #1978 (cherry-picked) | + ## [3.7.9] — 2026-05-03 ### ✨ New Features diff --git a/Dockerfile b/Dockerfile index ee090131d8..7500434464 100644 --- a/Dockerfile +++ b/Dockerfile @@ -56,9 +56,9 @@ COPY --from=builder /app/src/lib/db/migrations ./migrations ENV OMNIROUTE_MIGRATIONS_DIR=/app/migrations # MITM server.cjs is spawned at runtime via child_process — not traced by nft COPY --from=builder /app/src/mitm/server.cjs ./src/mitm/server.cjs -# OpenAPI spec is read from disk by /api/openapi/spec at runtime for the -# Endpoints dashboard. Next.js standalone tracing does not include it. -COPY --from=builder /app/docs/openapi.yaml ./docs/openapi.yaml +# Documentation files and OpenAPI spec are read from disk at runtime. +# Next.js standalone tracing does not include them. +COPY --from=builder /app/docs ./docs COPY --from=builder /app/scripts/run-standalone.mjs ./run-standalone.mjs COPY --from=builder /app/scripts/runtime-env.mjs ./runtime-env.mjs diff --git a/README.md b/README.md index 501c21dc6a..9eb7aa3814 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,121 @@ + + + + + + + + + + + + + + + + + + + + + + + +
# 🚀 OmniRoute — The Free AI Gateway -### Never stop coding. Save 15-95% eligible tokens with RTK+Caveman compression + auto-fallback to **FREE & low-cost AI models**. +### Never stop coding. Save 15-95% eligible tokens with RTK+Caveman compression + **Auto-Combo** intelligent routing to **FREE & low-cost AI models**. + +_Auto-Combo uses 7-factor scoring (health, quota, cost, latency, capability, stability, tier) to automatically pick the best model for each request with self-healing fallback._ _The most complete open-source AI proxy — **one endpoint**, **160+ providers**, **13 routing strategies**, zero downtime. Multi-platform: **Web**, **Desktop (Electron)**, **Mobile (PWA + Termux)**. Fully extensible via **MCP Server (37 tools)**, **A2A Protocol**, and **Memory/Skills** systems. Available in **40+ languages**._ @@ -229,6 +342,83 @@ _Connect any AI-powered IDE or CLI tool through OmniRoute — free API gateway f ✅ **MCP + A2A** — 29 MCP tools + agent-to-agent protocol, production-ready ✅ **Universal** — works with Claude Code, Codex, Gemini CLI, Cursor, Cline, OpenClaw, any CLI tool +### Why OmniRoute Wins + +| Capability | OmniRoute | LiteLLM | Bifrost | Routerly | +| ------------------ | :----------: | :-----: | :-----: | :------: | +| **Providers** | **160+** | 100+ | 15+ | 8 | +| **Free Providers** | **11** | 1 | 0 | 0 | +| **Token Savings** | **15-95%** | ❌ | ❌ | ❌ | +| **Auto-Combo** | **6-factor** | ❌ | ❌ | Basic | +| **MCP Tools** | **37** | 0 | 1 | 0 | +| **A2A Protocol** | **✅** | ❌ | ❌ | ❌ | +| **Desktop App** | **✅** | ❌ | ❌ | ❌ | +| **i18n** | **40+** | ❌ | ❌ | ❌ | +| **Open Source** | **✅** | ✅ | ❌ | ❌ | +| **Self-Hosted** | **Free** | $50/mo | $19/mo | $9.99/mo | + +--- + +## 🎯 Auto-Combo — Intelligent 6-Factor Routing + +> **Auto-Combo uses AI-powered scoring to automatically pick the best model for every request.** No manual combo configuration needed — it learns from your usage patterns and self-heals when providers fail. + +### How It Works + +Auto-Combo evaluates each request against **7 scoring factors**: + +| Factor | Description | Weight | +| ---------------------- | ------------------------------ | ------ | +| **Health** | Provider uptime and error rate | 25% | +| **Quota Availability** | Remaining rate limits | 20% | +| **Cost Efficiency** | Price per 1M tokens | 20% | +| **Latency** | Historical response time | 15% | +| **Capability Match** | Model strengths for task | 10% | +| **Stability** | Avoid same-provider clustering | 5% | +| **Tier Priority** | Subscription tier preference | 5% | + +### Mode Packs + +Auto-Combo includes pre-configured **mode packs** optimized for different use cases: + +- **🖥️ Coding Pack** — prioritizes reasoning + code generation models (Claude, DeepSeek, Qwen) +- **👁️ Vision Pack** — multimodal models with image understanding (GPT-5, Claude, Gemini) +- **📊 Analysis Pack** — complex reasoning + math capabilities (o3, DeepSeek-R1, GLM) +- **💬 Chat Pack** — balanced speed + quality for conversation (Claude Haiku, Gemini Flash) + +### Self-Healing + +When a provider fails (rate limit, outage, error), Auto-Combo automatically: + +1. Detects the failure within seconds +2. Scores all remaining options +3. Reroutes to the next best provider +4. Updates its scoring model for future requests + +### Auto-Combo vs Manual Combos + +| Feature | Auto-Combo | Manual Combo | +| -------------------- | ---------------------------------------------------- | --------------------- | +| **Configuration** | Zero config — works out of the box | Requires manual setup | +| **Adaptability** | Real-time scoring based on conditions | Static priority list | +| **Self-Healing** | Automatic rerouting on failure | Manual fallback only | +| **6-Factor Scoring** | ✅ Task, cost, latency, quota, capability, diversity | ❌ | +| **Mode Packs** | ✅ Coding, Vision, Analysis, Chat | ❌ | +| **Learning** | Improves over time based on usage | Static | + +### Competitor Comparison + +| Feature | OmniRoute Auto-Combo | Routerly | +| ---------------------- | ---------------------- | --------------------- | +| **6-Factor Scoring** | ✅ | ❌ (simple LLM-based) | +| **Self-Healing** | ✅ Automatic rerouting | ⚠️ Basic fallback | +| **Mode Packs** | ✅ 4 optimized packs | ❌ | +| **Free Providers** | ✅ 11 unlimited | ⚠️ 3 limited | +| **Prompt Compression** | ✅ RTK+Caveman 15-95% | ❌ | +| **Price** | **Free** (open-source) | $9.99/mo | + +📖 **Full Auto-Combo documentation:** [docs/AUTO-COMBO.md](docs/AUTO-COMBO.md) + --- ## 📧 Support @@ -1339,6 +1529,142 @@ See the [Proxy Guide](docs/PROXY_GUIDE.md) for setup instructions. 📖 **Full troubleshooting guide:** [`docs/TROUBLESHOOTING.md`](docs/TROUBLESHOOTING.md) +--- + +## 📊 Performance Benchmarks + +> OmniRoute is optimized for speed with minimal overhead. Run your own benchmarks to validate performance on your hardware. + +### Benchmark Your Instance + +```bash +# Install load testing tool +npm install -g autocannon + +# Test local OmniRoute instance +autocannon -c 10 -d 30 -m POST \ + -H "Authorization: Bearer your-api-key" \ + -H "Content-Type: application/json" \ + -b '{"model":"gpt-4o-mini","messages":[{"role":"user","content":"hi"}]}' \ + http://localhost:20128/v1/chat/completions +``` + +### Expected Performance + +| Metric | OmniRoute | LiteLLM | Bifrost (claimed) | +| -------------------- | --------- | ------- | ----------------- | +| **RPS (sustained)** | ~5,000+ | ~3,000 | ~13,925 | +| **Latency overhead** | <5ms | <10ms | <100µs | +| **Memory (idle)** | ~150MB | ~200MB | 32MB | +| **Cold start** | <2s | <5s | <1s | + +### What Impacts Performance + +- **Prompt compression** — RTK/Caveman adds ~1-3ms latency but saves 15-95% tokens +- **Format translation** — OpenAI ↔ Claude adds ~2-5ms for format conversion +- **Proxy overhead** — Global proxy adds ~10-50ms depending on proxy location +- **Caching** — Semantic cache hit avoids upstream entirely (0ms added) + +### Optimization Tips + +1. **Enable compression** — Lite/Standard mode adds minimal latency for significant savings +2. **Use local providers** — Same-region providers have lowest latency +3. **Configure circuit breakers** — Prevent cascading failures during high load +4. **Enable semantic cache** — Repeated queries hit cache without upstream call + +📖 **Full performance guide:** [`docs/PERFORMANCE.md`](docs/PERFORMANCE.md) + +--- + +## 🏆 Competitive Comparison + +> OmniRoute vs other AI Gateways — See why developers choose OmniRoute + +### Feature Comparison + +| Feature | OmniRoute | LiteLLM | Bifrost | Routerly | +| ------------------ | :--------------: | :-----: | :-----: | :------: | +| **Providers** | **160+** | 100+ | 15+ | 8 | +| **Token Savings** | **15-95%** | ❌ | ❌ | ❌ | +| **Free Tier** | **11 providers** | 1 | 0 | 0 | +| **Auto-Combo** | **6-factor** | ❌ | ❌ | basic | +| **MCP Server** | **37 tools** | ❌ | ✅ | ❌ | +| **A2A Protocol** | **✅** | ❌ | ❌ | ❌ | +| **Desktop App** | **✅** | ❌ | ❌ | ❌ | +| **Memory/Skills** | **✅** | ❌ | ❌ | ❌ | +| **i18n Languages** | **40+** | ❌ | ❌ | ❌ | +| **Price** | **Free** | $0 | $19/mo | $9.99/mo | + +### What Makes OmniRoute Unique + +#### 🗜️ **RTK+Caveman Compression** (Exclusive) + +No other gateway offers prompt compression. OmniRoute saves 15-95% tokens on eligible payloads using RTK (command-output) and Caveman (context condensation) engines. + +#### 🆓 **11 Free Providers** (Exclusive) + +- Kiro AI — Claude Sonnet/Haiku (50 credits/month) +- Qoder AI — Kimi-K2, Qwen3 unlimited +- Pollinations — GPT-5, no API key needed +- LongCat — 50M tokens/day +- 7 more + +#### 🤖 **Auto-Combo 6-Factor Routing** (Superior) + +OmniRoute scores each request on 7 factors (health, quota, cost, latency, capability, stability, tier) — smarter than Routerly's basic LLM-based routing. + +#### 🔧 **MCP Server + A2A Protocol** (Exclusive) + +37 MCP tools for IDE integration and agent-to-agent communication. No other gateway offers both. + +#### 🖥️ **Desktop App** (Exclusive) + +Electron desktop app for Windows/macOS/Linux with system tray, auto-start, and offline mode. + +--- + +## 🆓 Free Forever — No Credit Card Required + +> Use OmniRoute's free providers for $0 lifetime access to AI. No API key needed for some, others just sign up free. + +### Free Provider Directory + +| Provider | Models | Quota | Auth Required | +| ----------------- | --------------------------------- | --------------- | -------------- | +| **Kiro (AWS)** | Claude Sonnet/Haiku | Unlimited | OAuth | +| **Qoder** | kimi-k2, qwen3-coder, deepseek-r1 | Unlimited | PAT token | +| **Pollinations** | GPT-5, Claude, Llama 4 | No key needed | ❌ | +| **Qwen Code** | qwen3-coder-plus | Unlimited | Device code | +| **LongCat** | Flash-Lite | 50M tokens/day | API key (free) | +| **Gemini CLI** | gemini-2.5-flash | 180K/mo | OAuth | +| **Cloudflare AI** | 50+ models | 10K neurons/day | ❌ | +| **Groq** | Llama 3.3 70B | 30 RPM | API key (free) | +| **NVIDIA NIM** | 129 models | ~40 RPM | API key (free) | +| **Cerebras** | Qwen3 235B | 1M tokens/day | API key (free) | +| **Scaleway** | Qwen3 235B | 1M tokens | API key (free) | + +### Total Free Capacity + +- **~31,000+ requests/day** combined +- **~32B+ tokens/month** +- **500+ models** +- **$0 forever** + +### Quick Start with Free Stack + +```bash +# Point any tool to OmniRoute's free endpoint +Base URL: http://localhost:20128/v1 +API Key: any-string +Model: auto # Auto-Combo picks best free model +``` + +Or use the built-in **Free Stack** combo in `/dashboard/combos` — round-robins all free providers automatically. + +📖 **Full free provider guide:** [`docs/FREE_TIERS.md`](docs/FREE_TIERS.md) + +--- + ## 🛠️ Tech Stack
diff --git a/bin/cli-commands.mjs b/bin/cli-commands.mjs new file mode 100644 index 0000000000..bf9560caec --- /dev/null +++ b/bin/cli-commands.mjs @@ -0,0 +1,2822 @@ +#!/usr/bin/env node + +/** + * OmniRoute CLI - Production-grade CLI Integration Suite + * + * Commands: + * setup - Configure CLI tools to use OmniRoute + * doctor - Run health diagnostics + * status - Show comprehensive status + * logs - View application logs + * provider - Add OmniRoute as provider for tools + * config - Show current OmniRoute configuration + * test - Test provider/model connectivity + * update - Check for updates + */ + +import { + existsSync, + readFileSync, + writeFileSync, + mkdirSync, + readdirSync, + statSync, + copyFileSync, +} from "node:fs"; +import { join, dirname } from "node:path"; +import { fileURLToPath } from "node:url"; +import { homedir, platform, release } from "node:os"; +import { execSync, spawn } from "node:child_process"; + +const __filename = fileURLToPath(import.meta.url); +const __dirname = dirname(__filename); +const ROOT = join(__dirname, ".."); + +// ============================================================================ +// CONSTANTS +// ============================================================================ + +const DEFAULT_BASE_URL = "http://localhost:20128"; +const API_PORT = 20128; +const DASHBOARD_PORT = 20129; + +const CLI_TOOLS = { + claude: { + id: "claude", + name: "Claude Code", + command: "claude", + configPath: ".claude/settings.json", + type: "json", + }, + codex: { + id: "codex", + name: "Codex CLI", + command: "codex", + configPath: ".codex/config.toml", + type: "toml", + }, + opencode: { + id: "opencode", + name: "OpenCode", + command: "opencode", + configPath: ".config/opencode/opencode.json", + type: "json", + }, + cline: { + id: "cline", + name: "Cline", + command: "cline", + configPath: ".cline/data/globalState.json", + type: "json", + }, + kilo: { + id: "kilo", + name: "Kilo Code", + command: "kilocode", + configPath: ".config/kilocode/settings.json", + type: "json", + }, + continue: { + id: "continue", + name: "Continue", + command: "continue", + configPath: ".continue/config.json", + type: "json", + }, + openclaw: { + id: "openclaw", + name: "OpenClaw", + command: "openclaw", + configPath: ".openclaw/openclaw.json", + type: "json", + }, +}; + +const PROVIDER_HELP = { + opencode: `OpenCode configuration: +1. Add to ~/.config/opencode/opencode.json: +{ + "provider": { + "omniroute": { + "name": "OmniRoute", + "baseURL": "http://localhost:20128/v1" + } + } +} +2. Set environment: export OPENAI_API_KEY=your-key`, + + cursor: `Cursor configuration: +1. Open Cursor Settings +2. Go to Models → Add Model +3. Set Base URL to: http://localhost:20128/v1 +4. Set API Key to your OmniRoute key`, + + cline: `Cline configuration: +1. Open Cline Settings +2. Find "OpenAI Compatible" provider settings +3. Set Base URL: http://localhost:20128/v1 +4. Set API Key: your OmniRoute key`, + + vscode: `VS Code + MCP configuration: +1. Install Cline extension +2. Or use: omniroute --mcp for MCP server`, +}; + +// ============================================================================ +// UTILITY FUNCTIONS +// ============================================================================ + +function getHomeDir() { + return homedir(); +} + +function resolveConfigPath(relativePath) { + return join(getHomeDir(), relativePath); +} + +function execCommand(command, timeout = 3000) { + try { + const output = execSync(command, { + encoding: "utf8", + timeout, + stdio: ["pipe", "pipe", "pipe"], + }); + return { success: true, output: output.trim() }; + } catch (error) { + return { + success: false, + error: error.message, + code: error.status || error.signal, + }; + } +} + +function readJsonFile(filePath) { + try { + if (!existsSync(filePath)) return null; + const content = readFileSync(filePath, "utf8"); + return JSON.parse(content); + } catch (error) { + return null; + } +} + +function writeJsonFile(filePath, data) { + try { + const dir = dirname(filePath); + if (!existsSync(dir)) { + mkdirSync(dir, { recursive: true }); + } + writeFileSync(filePath, JSON.stringify(data, null, 2), "utf8"); + return true; + } catch (error) { + return false; + } +} + +function createBackup(filePath) { + if (!existsSync(filePath)) return null; + const backupPath = filePath + ".backup." + Date.now(); + try { + writeFileSync(backupPath, readFileSync(filePath), "utf8"); + return backupPath; + } catch { + return null; + } +} + +function colorize(text, color) { + const colors = { + green: "\x1b[32m", + red: "\x1b[31m", + yellow: "\x1b[33m", + blue: "\x1b[34m", + cyan: "\x1b[36m", + reset: "\x1b[0m", + dim: "\x1b[2m", + }; + return colors[color] ? `${colors[color]}${text}${colors.reset}` : text; +} + +function log(message, color = "reset") { + console.log(colorize(message, color)); +} + +function logSection(title) { + console.log("\n" + colorize("┌─ " + title + " ".repeat(50), "cyan")); +} + +function logEndSection() { + console.log(colorize("└" + "─".repeat(51), "cyan")); +} + +// ============================================================================ +// TOOL DETECTION +// ============================================================================ + +function detectInstalledTools() { + const results = []; + + for (const [id, tool] of Object.entries(CLI_TOOLS)) { + const result = execCommand(`which ${tool.command}`, 2000); + const installed = result.success; + let version = null; + + if (installed) { + const versionResult = execCommand(`${tool.command} --version`, 2000); + if (versionResult.success) { + version = versionResult.output.slice(0, 20); + } + } + + results.push({ + id, + name: tool.name, + installed, + version, + configPath: resolveConfigPath(tool.configPath), + configured: checkToolConfigured(id), + }); + } + + return results; +} + +function checkToolConfigured(toolId) { + const tool = CLI_TOOLS[toolId]; + if (!tool) return false; + + const configPath = resolveConfigPath(tool.configPath); + + try { + if (!existsSync(configPath)) return false; + + const content = readFileSync(configPath, "utf8").toLowerCase(); + const hasOmniRoute = + content.includes("omniroute") || + content.includes(`localhost:${API_PORT}`) || + content.includes(`127.0.0.1:${API_PORT}`); + return hasOmniRoute; + } catch { + return false; + } +} + +// ============================================================================ +// API FUNCTIONS +// ============================================================================ + +async function checkServerHealth() { + try { + const res = await fetch(`${DEFAULT_BASE_URL}/api/health`, { + method: "GET", + signal: AbortSignal.timeout(3000), + }); + return res.ok; + } catch { + return false; + } +} + +async function getCliToolsStatusFromApi() { + try { + const res = await fetch(`${DEFAULT_BASE_URL}/api/cli-tools/status`, { + method: "GET", + signal: AbortSignal.timeout(5000), + }); + if (res.ok) { + return await res.json(); + } + } catch {} + return null; +} + +async function getConsoleLogs(limit = 100, level = null) { + try { + const url = new URL(`${DEFAULT_BASE_URL}/api/logs/console`); + url.searchParams.set("limit", String(limit)); + if (level) url.searchParams.set("level", level); + + const res = await fetch(url.toString(), { + method: "GET", + signal: AbortSignal.timeout(5000), + }); + if (res.ok) { + return await res.json(); + } + } catch {} + return []; +} + +async function testProviderConnection(provider = "claude", model = "claude-sonnet-4-20250514") { + try { + const res = await fetch(`${DEFAULT_BASE_URL}/v1/chat/completions`, { + method: "POST", + headers: { + "Content-Type": "application/json", + Authorization: "Bearer sk-omniroute-cli-test", + }, + body: JSON.stringify({ + model, + messages: [{ role: "user", content: "Hi" }], + max_tokens: 10, + }), + signal: AbortSignal.timeout(10000), + }); + + if (res.ok) { + const data = await res.json(); + return { success: true, response: data.choices?.[0]?.message?.content || "OK" }; + } else { + const error = await res.text(); + return { success: false, error: `HTTP ${res.status}: ${error.slice(0, 100)}` }; + } + } catch (error) { + return { success: false, error: error.message }; + } +} + +// ============================================================================ +// CONFIG MANAGEMENT +// ============================================================================ + +function configureTool(toolId, baseUrl, apiKey) { + const tool = CLI_TOOLS[toolId]; + if (!tool) { + return { success: false, error: "Unknown tool: " + toolId }; + } + + const configPath = tool.configPath; + const fullPath = resolveConfigPath(configPath); + + // Create backup first + const backupPath = createBackup(fullPath); + + try { + // Ensure directory exists + const dir = dirname(fullPath); + if (!existsSync(dir)) { + mkdirSync(dir, { recursive: true }); + } + + // Read existing config or create new + let config = {}; + if (existsSync(fullPath)) { + const content = readFileSync(fullPath, "utf8"); + if (tool.type === "json") { + config = JSON.parse(content); + } + } + + // Apply tool-specific configuration + switch (toolId) { + case "claude": + config.api = config.api || {}; + config.api.omniroute = { + baseUrl: `${baseUrl}/v1`, + apiKey: apiKey, + model: "claude-sonnet-4-20250514", + }; + break; + + case "codex": + // For TOML, we need to append/modify + const tomlContent = `[openai] +base_url = "${baseUrl}/v1" +api_key = "${apiKey}" +model = "gpt-4o" +`; + writeFileSync(fullPath, tomlContent, "utf8"); + return { success: true, configPath: fullPath, backupPath }; + + case "opencode": + config.provider = config.provider || {}; + config.provider.omniroute = { + name: "OmniRoute", + baseURL: `${baseUrl}/v1`, + apiKey: apiKey, + }; + break; + + case "cline": + config.openAiBaseUrl = `${baseUrl}/v1`; + config.openAiApiKey = apiKey; + config.actModeApiProvider = "openai"; + config.planModeApiProvider = "openai"; + break; + + case "kilo": + config.apiUrl = `${baseUrl}/v1`; + config.apiKey = apiKey; + break; + + case "continue": + config.models = config.models || []; + config.models.push({ + name: "OmniRoute", + provider: "openai-compatible", + apiKey: apiKey, + baseUrl: `${baseUrl}/v1`, + }); + break; + + case "openclaw": + config.OPENAI_BASE_URL = `${baseUrl}/v1`; + config.OPENAI_API_KEY = apiKey; + break; + } + + // Write JSON configs + if (tool.type === "json") { + writeFileSync(fullPath, JSON.stringify(config, null, 2), "utf8"); + } + + return { success: true, configPath: fullPath, backupPath }; + } catch (error) { + // Restore backup on failure + if (backupPath && existsSync(backupPath)) { + try { + writeFileSync(fullPath, readFileSync(backupPath), "utf8"); + } catch {} + } + return { success: false, error: error.message }; + } +} + +// ============================================================================ +// CONFIG SHOW +// ============================================================================ + +function getOmniRouteConfig() { + const config = { + port: API_PORT, + dashboardPort: DASHBOARD_PORT, + baseUrl: `http://localhost:${API_PORT}`, + dataDir: resolveConfigPath(".omniroute"), + requireApiKey: process.env.REQUIRE_API_KEY === "true", + logLevel: process.env.LOG_LEVEL || "info", + }; + + // Check for existing providers + try { + const dbPath = join(config.dataDir, "storage.sqlite"); + config.hasDatabase = existsSync(dbPath); + } catch { + config.hasDatabase = false; + } + + // Node version + config.nodeVersion = process.version; + config.platform = platform(); + config.osRelease = release(); + + return config; +} + +// ============================================================================ +// COMMAND IMPLEMENTATIONS +// ============================================================================ + +export async function runSubcommand(cmd, args) { + switch (cmd) { + case "setup": + await runSetup(args); + break; + case "doctor": + await runDoctor(args); + break; + case "status": + await runStatus(args); + break; + case "logs": + await runLogs(args); + break; + case "provider": + await runProvider(args); + break; + case "config": + await runConfig(args); + break; + case "test": + await runTest(args); + break; + case "update": + await runUpdate(args); + break; + case "serve": + await runServe(args); + break; + case "stop": + await runStop(args); + break; + case "restart": + await runRestart(args); + break; + case "keys": + await runKeys(args); + break; + case "models": + await runModels(args); + break; + case "combo": + await runCombo(args); + break; + case "completion": + await runCompletion(args); + break; + case "dashboard": + await runDashboard(args); + break; + case "backup": + await runBackup(args); + break; + case "restore": + await runRestore(args); + break; + case "quota": + await runQuota(args); + break; + case "health": + await runHealth(args); + break; + case "cache": + await runCache(args); + break; + case "mcp": + await runMcp(args); + break; + case "a2a": + await runA2a(args); + break; + case "tunnel": + await runTunnel(args); + break; + case "env": + await runEnv(args); + break; + case "open": + await runDashboard(args); + break; + default: + log(`Unknown subcommand: ${cmd}`, "red"); + log("Run 'omniroute --help' for available commands", "dim"); + process.exit(1); + } +} + +async function runSetup(args) { + const toolsArg = args.find((a) => a.startsWith("--tools="))?.split("=")[1]; + const urlArg = args.find((a) => a.startsWith("--url="))?.split("=")[1] || DEFAULT_BASE_URL; + const keyArg = + args.find((a) => a.startsWith("--key="))?.split("=")[1] || "sk-omniroute-cli-configured"; + const listArg = args.includes("--list"); + + const baseUrl = urlArg.endsWith("/") ? urlArg.slice(0, -1) : urlArg; + + if (listArg) { + logSection("Available CLI Tools"); + const tools = detectInstalledTools(); + for (const tool of tools) { + const status = tool.installed + ? tool.configured + ? colorize("✓ configured", "green") + : colorize("✗ not configured", "yellow") + : colorize("✗ not installed", "red"); + log(` ${tool.name.padEnd(14)} ${status}`); + } + logEndSection(); + return; + } + + logSection("OmniRoute CLI Setup"); + + // Detect installed tools + const installed = detectInstalledTools().filter((t) => t.installed); + + if (installed.length === 0) { + log("No CLI tools detected. Install Claude Code, Codex, OpenCode, etc.", "yellow"); + return; + } + + log(`Found ${installed.length} installed tools:`, "dim"); + for (const tool of installed) { + log(` - ${tool.name}`); + } + console.log(); + + // Determine which tools to configure + const toolsToConfigure = toolsArg + ? toolsArg.split(",").filter((t) => CLI_TOOLS[t]) + : installed.map((t) => t.id); + + // Configure each tool + log(`Configuring ${toolsToConfigure.length} tool(s)...\n`, "cyan"); + + let successCount = 0; + let failCount = 0; + + for (const toolId of toolsToConfigure) { + const tool = CLI_TOOLS[toolId]; + log(`Configuring ${tool.name}...`, "dim"); + + const result = configureTool(toolId, baseUrl, keyArg); + + if (result.success) { + log(` ✓ Configured: ${result.configPath}`, "green"); + if (result.backupPath) { + log(` Backup: ${result.backupPath}`, "dim"); + } + successCount++; + } else { + log(` ✗ Failed: ${result.error}`, "red"); + failCount++; + } + } + + logEndSection(); + + console.log(); + if (successCount > 0) { + log(`✓ Successfully configured ${successCount} tool(s)`, "green"); + } + if (failCount > 0) { + log(`✗ Failed to configure ${failCount} tool(s)`, "red"); + } + + console.log(); + log("Next steps:", "cyan"); + log(" 1. Test: omniroute test", "dim"); + log(" 2. Status: omniroute status", "dim"); + log(" 3. Start server: omniroute", "dim"); +} + +async function runDoctor(args) { + const verbose = args.includes("--verbose"); + const serverRunning = await checkServerHealth(); + + logSection("OmniRoute Doctor"); + + // Server status + if (serverRunning) { + log("Server: " + colorize("✓ Running", "green")); + log(`API: http://localhost:${API_PORT}/v1`); + log(`Dashboard: http://localhost:${DASHBOARD_PORT}`); + } else { + log("Server: " + colorize("✗ Not running", "red")); + log("Run 'omniroute' to start the server", "dim"); + } + logEndSection(); + + // CLI Tools status + logSection("CLI Tools Status"); + + let tools; + let dataSource = "local"; + + if (serverRunning) { + const apiStatus = await getCliToolsStatusFromApi(); + if (apiStatus) { + dataSource = "api"; + tools = Object.entries(apiStatus).map(([id, data]) => ({ + id, + name: CLI_TOOLS[id]?.name || id, + installed: data.installed, + configured: data.configStatus === "configured", + runnable: data.runnable, + })); + } + } + + if (!tools) { + tools = detectInstalledTools(); + } + + // Sort: configured first, then installed, then not installed + tools.sort((a, b) => { + if (a.configured && !b.configured) return -1; + if (!a.configured && b.configured) return 1; + if (a.installed && !b.installed) return -1; + if (!a.installed && b.installed) return 1; + return 0; + }); + + for (const tool of tools) { + let status; + if (tool.configured) { + status = colorize("✓ configured", "green"); + } else if (tool.installed) { + status = colorize("○ not configured", "yellow"); + } else { + status = colorize("✗ not installed", "red"); + } + log(` ${tool.name.padEnd(12)} ${status}`); + } + + console.log( + `\n${colorize("Data source:", "dim")} ${dataSource === "api" ? "API (accurate)" : "Local detection"}` + ); + logEndSection(); + + // Recommendations + console.log(); + const notConfigured = tools.filter((t) => t.installed && !t.configured); + if (notConfigured.length > 0) { + log("Recommendations:", "cyan"); + log(` Run 'omniroute setup --tools=${notConfigured.map((t) => t.id).join(",")}' to configure`); + } + + if (!serverRunning) { + log(" Run 'omniroute' to start the server for full diagnostics", "dim"); + } + + if (verbose && serverRunning) { + console.log(); + logSection("System Info"); + log(`Node: ${process.version}`); + log(`Platform: ${platform()} ${release()}`); + log(`Home: ${getHomeDir()}`); + log(`Data Dir: ${resolveConfigPath(".omniroute")}`); + logEndSection(); + } +} + +async function runStatus(args) { + const json = args.includes("--json"); + const serverRunning = await checkServerHealth(); + + const config = getOmniRouteConfig(); + const tools = detectInstalledTools(); + const configuredCount = tools.filter((t) => t.configured).length; + const installedCount = tools.filter((t) => t.installed).length; + + if (json) { + console.log( + JSON.stringify( + { + server: { + running: serverRunning, + port: config.port, + url: config.baseUrl, + }, + dashboard: `http://localhost:${config.dashboardPort}`, + config: { + dataDir: config.dataDir, + requireApiKey: config.requireApiKey, + logLevel: config.logLevel, + }, + tools: { + total: Object.keys(CLI_TOOLS).length, + installed: installedCount, + configured: configuredCount, + }, + }, + null, + 2 + ) + ); + return; + } + + logSection("OmniRoute Status"); + log( + `Server: ${serverRunning ? colorize("✓ Running", "green") : colorize("✗ Stopped", "red")}` + ); + log(`API URL: ${config.baseUrl}/v1`); + log(`Dashboard: http://localhost:${config.dashboardPort}`); + log(`Data Dir: ${config.dataDir}`); + logEndSection(); + + logSection("CLI Tools"); + log(`Installed: ${installedCount}`); + log(`Configured: ${configuredCount}`); + console.log(); + + for (const tool of tools) { + const icon = tool.configured + ? colorize("●", "green") + : tool.installed + ? colorize("○", "yellow") + : colorize("×", "red"); + log(` ${icon} ${tool.name}`); + } + logEndSection(); +} + +async function runLogs(args) { + const linesArg = args.find((a) => a.startsWith("--lines="))?.split("=")[1] || "100"; + const levelArg = args.find((a) => a.startsWith("--level="))?.split("=")[1]; + const followArg = args.includes("--follow"); + const jsonArg = args.includes("--json"); + const searchArg = args.find((a) => a.startsWith("--search="))?.split("=")[1]; + + const limit = Math.min(Math.max(parseInt(linesArg) || 100, 10), 1000); + const level = levelArg || null; + + const serverRunning = await checkServerHealth(); + + if (!serverRunning) { + log("Server not running. Start with 'omniroute'", "red"); + return; + } + + if (jsonArg) { + const logs = await getConsoleLogs(limit, level); + console.log(JSON.stringify(logs, null, 2)); + return; + } + + logSection("Console Logs"); + log(`Fetching last ${limit} lines...`, "dim"); + if (level) log(`Filter: ${level}`, "dim"); + if (searchArg) log(`Search: ${searchArg}`, "dim"); + logEndSection(); + + let logs = await getConsoleLogs(limit, level); + + // Search filter + if (searchArg) { + const search = searchArg.toLowerCase(); + logs = logs.filter( + (l) => + (l.msg || l.message || "").toLowerCase().includes(search) || + (l.level || "").toLowerCase().includes(search) + ); + } + + if (logs.length === 0) { + log("No logs found", "yellow"); + return; + } + + for (const entry of logs) { + const timestamp = entry.time || entry.timestamp || ""; + const lvl = entry.level || entry.severity || "info"; + const msg = entry.msg || entry.message || ""; + + let color = "dim"; + if (lvl === "error" || lvl === "fatal") color = "red"; + else if (lvl === "warn") color = "yellow"; + else if (lvl === "debug") color = "dim"; + else color = "reset"; + + console.log(`${colorize(timestamp.slice(0, 24), "dim")} [${lvl.slice(0, 5).padEnd(5)}] ${msg}`); + } + + if (followArg) { + log("\nFollowing logs (Ctrl+C to exit)...", "cyan"); + // Simple polling implementation + let lastTime = logs[logs.length - 1]?.time || ""; + + const interval = setInterval(async () => { + const newLogs = await getConsoleLogs(50, level); + const filtered = newLogs.filter((l) => l.time > lastTime); + for (const entry of filtered) { + const timestamp = entry.time || ""; + const lvl = entry.level || "info"; + const msg = entry.msg || ""; + let color = lvl === "error" ? "red" : lvl === "warn" ? "yellow" : "dim"; + console.log( + `${colorize(timestamp.slice(0, 24), "dim")} [${lvl.slice(0, 5).padEnd(5)}] ${msg}` + ); + lastTime = entry.time; + } + }, 2000); + + // Handle interrupt + process.on("SIGINT", () => { + clearInterval(interval); + log("\nStopped following", "yellow"); + process.exit(0); + }); + } +} + +async function runProvider(args) { + const action = args[0] || "list"; + + if (action === "list") { + logSection("Available Provider Integrations"); + for (const [id, name] of Object.entries({ + opencode: "OpenCode", + cursor: "Cursor", + cline: "Cline", + vscode: "VS Code", + })) { + log(` ${name}`); + } + logEndSection(); + log("\nUsage: omniroute provider add ", "dim"); + return; + } + + if (action === "add") { + const provider = args[1]; + if (!provider || !PROVIDER_HELP[provider]) { + log(`Unknown provider: ${provider}`, "red"); + log("Available: " + Object.keys(PROVIDER_HELP).join(", "), "dim"); + return; + } + + logSection(`Configure ${provider}`); + console.log(PROVIDER_HELP[provider]); + logEndSection(); + return; + } + + log(`Unknown action: ${action}`, "red"); + log("Usage: omniroute provider [list|add ]", "dim"); +} + +async function runConfig(args) { + const action = args[0] || "show"; + + if (action === "show") { + const config = getOmniRouteConfig(); + + logSection("OmniRoute Configuration"); + log(`API Port: ${config.port}`); + log(`Dashboard Port: ${config.dashboardPort}`); + log(`Base URL: ${config.baseUrl}`); + log(`Data Directory: ${config.dataDir}`); + log(`Require API Key: ${config.requireApiKey ? "Yes" : "No"}`); + log(`Log Level: ${config.logLevel}`); + log(`Node Version: ${config.nodeVersion}`); + log(`Platform: ${config.platform} ${config.osRelease}`); + logEndSection(); + return; + } + + log(`Unknown action: ${action}`, "red"); + log("Usage: omniroute config show", "dim"); +} + +async function runTest(args) { + const providerArg = args.find((a) => a.startsWith("--provider="))?.split("=")[1]; + const modelArg = args.find((a) => a.startsWith("--model="))?.split("=")[1]; + + const serverRunning = await checkServerHealth(); + + if (!serverRunning) { + log("Server not running. Start with 'omniroute'", "red"); + return; + } + + const provider = providerArg || "claude"; + const model = modelArg || "claude-sonnet-4-20250514"; + + logSection("Testing Provider Connection"); + log(`Provider: ${provider}`); + log(`Model: ${model}`); + log("Connecting...", "dim"); + console.log(); + + const result = await testProviderConnection(provider, model); + + if (result.success) { + log("✓ Connection successful!", "green"); + log(`Response: ${result.response}`, "dim"); + } else { + log("✗ Connection failed!", "red"); + log(`Error: ${result.error}`, "yellow"); + } + + logEndSection(); +} + +async function runUpdate(args) { + logSection("Checking for Updates"); + + // Get current version + try { + const pkgPath = join(ROOT, "package.json"); + const pkg = JSON.parse(readFileSync(pkgPath, "utf8")); + log(`Current version: ${colorize(pkg.version, "cyan")}`); + } catch { + log("Current version: unknown", "yellow"); + } + + // Get latest version from npm + log("Checking npm...", "dim"); + const npmResult = execCommand("npm view omniroute version", 10000); + + if (npmResult.success) { + const latest = npmResult.output.trim(); + // Try to get current version again for comparison + const pkgPath = join(ROOT, "package.json"); + const current = JSON.parse(readFileSync(pkgPath, "utf8")).version; + + console.log(); + if (latest !== current) { + log(`Latest version: ${colorize(latest, "green")}`); + log(`Update available! Run:`, "yellow"); + log(` npm install -g omniroute@latest`, "dim"); + } else { + log(`Latest version: ${colorize(latest, "green")}`); + log("Already on the latest version!", "green"); + } + } else { + log("Could not check for updates (npm not available)", "yellow"); + } + + logEndSection(); +} + +// ============================================================================ +// PID FILE MANAGEMENT +// ============================================================================ + +function getPidFilePath() { + return join(resolveConfigPath(".omniroute"), "server.pid"); +} + +function writePidFile(pid) { + try { + const dir = dirname(getPidFilePath()); + if (!existsSync(dir)) { + mkdirSync(dir, { recursive: true }); + } + writeFileSync(getPidFilePath(), String(pid), "utf8"); + return true; + } catch { + return false; + } +} + +function readPidFile() { + try { + const path = getPidFilePath(); + if (!existsSync(path)) return null; + const content = readFileSync(path, "utf8").trim(); + return content ? parseInt(content, 10) : null; + } catch { + return null; + } +} + +function isPidRunning(pid) { + if (!pid) return false; + try { + process.kill(pid, 0); + return true; + } catch { + return false; + } +} + +function cleanupPidFile() { + try { + const path = getPidFilePath(); + if (existsSync(path)) { + const fs = require("node:fs"); + fs.unlinkSync(path); + } + } catch {} +} + +function sleep(ms) { + return new Promise((resolve) => setTimeout(resolve, ms)); +} + +async function waitForServer(port, timeout = 15000) { + const start = Date.now(); + while (Date.now() - start < timeout) { + try { + const res = await fetch(`http://localhost:${port}/api/health`, { + signal: AbortSignal.timeout(2000), + }); + if (res.ok) return true; + } catch {} + await sleep(500); + } + return false; +} + +// ============================================================================ +// SERVER MANAGEMENT COMMANDS +// ============================================================================ + +async function runServe(args) { + const portArg = args.find((a) => a.startsWith("--port="))?.split("=")[1]; + const port = portArg ? parseInt(portArg) : API_PORT; + const daemonArg = args.includes("--daemon"); + + logSection("Starting OmniRoute Server"); + + // Check if already running via PID file + const existingPid = readPidFile(); + if (existingPid && isPidRunning(existingPid)) { + log(`Server already running (PID: ${existingPid})`, "red"); + log(`API: http://localhost:${port}/v1`); + log(`Dashboard: http://localhost:${port + 1}`); + logEndSection(); + return; + } + + // Check if port is in use + const portCheck = execCommand(`lsof -ti:${port} 2>/dev/null || true`, 2000); + if (portCheck.success && portCheck.output.trim()) { + log(`Port ${port} is already in use`, "red"); + log("Stop the existing server or use a different port", "dim"); + logEndSection(); + return; + } + + const appDir = join(ROOT, "app"); + const serverWsJs = join(appDir, "server-ws.mjs"); + const serverJs = existsSync(serverWsJs) ? serverWsJs : join(appDir, "server.js"); + + if (!existsSync(serverJs)) { + log("Server not found. Run 'npm run build' first.", "red"); + logEndSection(); + return; + } + + log(`Starting server on port ${port}...`, "dim"); + + const env = { + ...process.env, + OMNIROUTE_PORT: String(port), + PORT: String(port + 1), + DASHBOARD_PORT: String(port + 1), + API_PORT: String(port), + HOSTNAME: "0.0.0.0", + NODE_ENV: "production", + }; + + const server = spawn("node", [serverJs], { + cwd: appDir, + env, + stdio: daemonArg ? "ignore" : "pipe", + }); + + // Write PID file + writePidFile(server.pid); + + if (daemonArg) { + log(`Server started in background (PID: ${server.pid})`, "green"); + log(`API: http://localhost:${port}/v1`); + log(`Dashboard: http://localhost:${port + 1}`); + } else { + // Wait for server to be ready + const ready = await waitForServer(port); + if (ready) { + log(`Server running!`, "green"); + log(`API: http://localhost:${port}/v1`); + log(`Dashboard: http://localhost:${port + 1}`); + log(""); + log("Press Ctrl+C to stop", "dim"); + } else { + log("Server may not have started properly", "yellow"); + } + } + + logEndSection(); + + if (!daemonArg) { + // Keep process alive, handle shutdown + process.on("SIGINT", () => { + log("\nShutting down...", "yellow"); + server.kill("SIGTERM"); + cleanupPidFile(); + process.exit(0); + }); + + server.on("exit", (code) => { + cleanupPidFile(); + if (code !== 0) { + log(`Server exited with code ${code}`, "red"); + } + process.exit(code || 0); + }); + } +} + +async function runStop(args) { + logSection("Stopping OmniRoute Server"); + + const pid = readPidFile(); + + if (pid && isPidRunning(pid)) { + log(`Sending SIGTERM to PID ${pid}...`, "dim"); + + try { + process.kill(pid, "SIGTERM"); + + // Wait for graceful shutdown + let waited = 0; + while (waited < 5000 && isPidRunning(pid)) { + await sleep(100); + waited += 100; + } + + if (isPidRunning(pid)) { + log("Force killing...", "yellow"); + process.kill(pid, "SIGKILL"); + await sleep(500); + } + + cleanupPidFile(); + log("Server stopped", "green"); + } catch (err) { + log(`Error stopping server: ${err.message}`, "red"); + } + } else { + // Fallback: try to kill by port + log("No PID file, trying port-based cleanup...", "dim"); + + try { + // Try multiple methods + execCommand("lsof -ti:20128 | xargs kill -9 2>/dev/null || true", 2000); + execCommand("lsof -ti:20129 | xargs kill -9 2>/dev/null || true", 2000); + cleanupPidFile(); + log("Server stopped (port-based)", "green"); + } catch { + log("No server running", "yellow"); + } + } + + logEndSection(); +} + +async function runRestart(args) { + logSection("Restarting OmniRoute Server"); + + const portArg = args.find((a) => a.startsWith("--port="))?.split("=")[1] || String(API_PORT); + + // Stop first + await runStop([]); + + // Small delay + await sleep(1000); + + // Start with same port + log("Starting server...", "dim"); + await runServe(["--port=" + portArg]); + + logEndSection(); +} + +// ============================================================================ +// API KEY MANAGEMENT +// ============================================================================ + +const VALID_PROVIDERS = [ + "openai", + "anthropic", + "google", + "deepseek", + "groq", + "mistral", + "xai", + "cohere", + "google-generativeai", + "azure", + "aws", + "bedrock", + "perplexity", + "together", + "fireworks", + "huggingface", + "nvidia", + "cerebras", + "siliconflow", + "nebius", + "openrouter", + "ollama", +]; + +async function runKeys(args) { + const action = args[0]; + + if (!action) { + logSection("API Key Management"); + log("Usage:"); + log(" omniroute keys add "); + log(" omniroute keys list"); + log(" omniroute keys remove "); + log(""); + log(`Valid providers: ${VALID_PROVIDERS.join(", ")}`, "dim"); + logEndSection(); + return; + } + + switch (action) { + case "add": + await runKeysAdd(args.slice(1)); + break; + case "list": + await runKeysList(args.slice(1)); + break; + case "remove": + await runKeysRemove(args.slice(1)); + break; + default: + log(`Unknown action: ${action}`, "red"); + log("Valid actions: add, list, remove", "dim"); + } +} + +async function runKeysAdd(args) { + const provider = args[0]; + const apiKey = args[1]; + + if (!provider || !apiKey) { + log("Usage: omniroute keys add ", "red"); + return; + } + + const providerLower = provider.toLowerCase(); + if (!VALID_PROVIDERS.includes(providerLower)) { + log(`Invalid provider. Valid: ${VALID_PROVIDERS.join(", ")}`, "red"); + return; + } + + logSection(`Adding API Key for ${provider}`); + + // Try API first + const serverRunning = await checkServerHealth(); + + if (serverRunning) { + try { + const res = await fetch(`${DEFAULT_BASE_URL}/api/v1/providers/keys`, { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify({ provider: providerLower, apiKey }), + }); + + if (res.ok) { + log(`API key for ${provider} added successfully via API`, "green"); + logEndSection(); + return; + } + } catch {} + } + + // Direct DB fallback + const dataDir = resolveConfigPath(".omniroute"); + const dbPath = join(dataDir, "storage.sqlite"); + + if (!existsSync(dbPath)) { + log("Database not found. Start server first.", "red"); + logEndSection(); + return; + } + + try { + const { createRequire } = await import("node:module"); + const require = createRequire(import.meta.url); + const Database = require("better-sqlite3"); + const db = new Database(dbPath); + + // Check if connection exists + const existing = db + .prepare("SELECT id FROM provider_connections WHERE provider_id = ?") + .get(providerLower); + + if (existing) { + db.prepare("UPDATE provider_connections SET api_key = ? WHERE provider_id = ?").run( + apiKey, + providerLower + ); + log(`API key for ${provider} updated`, "green"); + } else { + db.prepare( + "INSERT INTO provider_connections (provider_id, api_key, name, enabled) VALUES (?, ?, ?, 1)" + ).run(providerLower, apiKey, provider); + log(`API key for ${provider} added`, "green"); + } + + db.close(); + } catch (err) { + log(`Failed to save key: ${err.message}`, "red"); + } + + logEndSection(); +} + +async function runKeysList(args) { + logSection("Configured API Keys"); + + const dataDir = resolveConfigPath(".omniroute"); + const dbPath = join(dataDir, "storage.sqlite"); + + if (!existsSync(dbPath)) { + log("Database not found. Start server first.", "yellow"); + logEndSection(); + return; + } + + try { + const { createRequire } = await import("node:module"); + const require = createRequire(import.meta.url); + const Database = require("better-sqlite3"); + const db = new Database(dbPath); + + const keys = db + .prepare( + ` + SELECT provider_id, api_key, enabled + FROM provider_connections + WHERE api_key IS NOT NULL AND api_key != '' + ` + ) + .all(); + + db.close(); + + if (keys.length === 0) { + log("No API keys configured", "yellow"); + } else { + for (const key of keys) { + const masked = + key.api_key && key.api_key.length > 8 + ? key.api_key.slice(0, 6) + "***" + key.api_key.slice(-4) + : "***"; + const status = key.enabled + ? colorize("● enabled", "green") + : colorize("○ disabled", "yellow"); + log(` ${key.provider_id.padEnd(20)} ${masked.padEnd(20)} ${status}`); + } + } + } catch (err) { + log(`Error reading keys: ${err.message}`, "red"); + } + + logEndSection(); +} + +async function runKeysRemove(args) { + const provider = args[0]; + + if (!provider) { + log("Usage: omniroute keys remove ", "red"); + return; + } + + logSection(`Removing API Key for ${provider}`); + + const dataDir = resolveConfigPath(".omniroute"); + const dbPath = join(dataDir, "storage.sqlite"); + + if (!existsSync(dbPath)) { + log("Database not found. Start server first.", "red"); + logEndSection(); + return; + } + + try { + const { createRequire } = await import("node:module"); + const require = createRequire(import.meta.url); + const Database = require("better-sqlite3"); + const db = new Database(dbPath); + + const result = db + .prepare("DELETE FROM provider_connections WHERE provider_id = ?") + .run(provider.toLowerCase()); + + if (result.changes > 0) { + log(`API key for ${provider} removed`, "green"); + } else { + log(`No API key found for ${provider}`, "yellow"); + } + + db.close(); + } catch (err) { + log(`Failed to remove key: ${err.message}`, "red"); + } + + logEndSection(); +} + +// ============================================================================ +// MODEL BROWSER +// ============================================================================ + +async function runModels(args) { + const providerFilter = args[0] && !args[0].startsWith("--") ? args[0] : null; + const jsonOutput = args.includes("--json"); + const searchQuery = args.find((a) => a.startsWith("--search="))?.split("=")[1]; + + logSection("Available Models"); + + const serverRunning = await checkServerHealth(); + + if (!serverRunning) { + log("Server not running. Start with 'omniroute serve' or 'omniroute'", "red"); + logEndSection(); + return; + } + + try { + // Try various endpoints + let models = []; + + try { + const res = await fetch(`${DEFAULT_BASE_URL}/api/models`, { + signal: AbortSignal.timeout(5000), + }); + if (res.ok) { + const data = await res.json(); + models = data.models || data || []; + } + } catch {} + + // Fallback: try provider registry + if (models.length === 0) { + try { + const res = await fetch(`${DEFAULT_BASE_URL}/api/v1/models`, { + signal: AbortSignal.timeout(5000), + }); + if (res.ok) { + models = await res.json(); + } + } catch {} + } + + // Filter by provider if specified + if (providerFilter) { + const filter = providerFilter.toLowerCase(); + models = models.filter( + (m) => + (m.provider && m.provider.toLowerCase().includes(filter)) || + (m.id && m.id.toLowerCase().startsWith(filter)) || + (m.name && m.name.toLowerCase().includes(filter)) + ); + } + + // Search filter + if (searchQuery) { + const search = searchQuery.toLowerCase(); + models = models.filter( + (m) => + (m.id && m.id.toLowerCase().includes(search)) || + (m.name && m.name.toLowerCase().includes(search)) || + (m.provider && m.provider.toLowerCase().includes(search)) || + (m.description && m.description.toLowerCase().includes(search)) + ); + } + + if (jsonOutput) { + console.log(JSON.stringify(models, null, 2)); + logEndSection(); + return; + } + + if (models.length === 0) { + log("No models found", "yellow"); + logEndSection(); + return; + } + + // Display as formatted table + console.log(); + console.log(colorize(" Model".padEnd(45) + "Provider".padEnd(20) + "Context", "cyan")); + console.log( + colorize(" " + "─".repeat(44) + " " + "─".repeat(19) + " " + "─".repeat(10), "dim") + ); + + const displayModels = models.slice(0, 50); + for (const model of displayModels) { + const name = (model.id || model.name || "unknown").slice(0, 43); + const provider = (model.provider || "unknown").slice(0, 18); + const context = model.context_length || model.max_tokens || model.contextWindow || "-"; + console.log(` ${name.padEnd(45)}${provider.padEnd(20)}${String(context).padEnd(10)}`); + } + + console.log(); + if (models.length > 50) { + log(`... and ${models.length - 50} more models. Use --json for full list.`, "dim"); + } + + log(`Total: ${models.length} models`, "green"); + } catch (err) { + log(`Failed to fetch models: ${err.message}`, "red"); + } + + logEndSection(); +} + +// ============================================================================ +// COMBO MANAGEMENT +// ============================================================================ + +async function runCombo(args) { + const action = args[0]; + + if (!action) { + logSection("Combo Management"); + log("Usage:"); + log(" omniroute combo list"); + log(" omniroute combo switch "); + log(" omniroute combo create "); + log(" omniroute combo delete "); + log(""); + log("Strategies: priority, weighted, round-robin, p2c, random, auto, lkgp", "dim"); + logEndSection(); + return; + } + + switch (action) { + case "list": + await runComboList(args.slice(1)); + break; + case "switch": + await runComboSwitch(args.slice(1)); + break; + case "create": + await runComboCreate(args.slice(1)); + break; + case "delete": + await runComboDelete(args.slice(1)); + break; + default: + log(`Unknown action: ${action}`, "red"); + log("Valid actions: list, switch, create, delete", "dim"); + } +} + +async function runComboList(args) { + const jsonOutput = args.includes("--json"); + + logSection("Routing Combos"); + + const dataDir = resolveConfigPath(".omniroute"); + const dbPath = join(dataDir, "storage.sqlite"); + + if (!existsSync(dbPath)) { + log("Database not found. Start server first.", "yellow"); + logEndSection(); + return; + } + + try { + const { createRequire } = await import("node:module"); + const require = createRequire(import.meta.url); + const Database = require("better-sqlite3"); + const db = new Database(dbPath); + + const combos = db + .prepare( + ` + SELECT id, name, strategy, enabled, target_count + FROM combos + ORDER BY name + ` + ) + .all(); + + // Get active combo + let activeCombo = null; + try { + const res = await fetch(`${DEFAULT_BASE_URL}/api/combos/active`, { + signal: AbortSignal.timeout(3000), + }); + if (res.ok) { + const data = await res.json(); + activeCombo = data.active || data.name || data.combo; + } + } catch {} + + db.close(); + + if (jsonOutput) { + console.log(JSON.stringify({ combos, active: activeCombo }, null, 2)); + logEndSection(); + return; + } + + if (combos.length === 0) { + log("No combos configured", "yellow"); + } else { + for (const combo of combos) { + const isActive = activeCombo && (combo.name === activeCombo || combo.id === activeCombo); + const icon = isActive ? colorize("●", "green") : colorize("○", "dim"); + const status = combo.enabled ? colorize("enabled", "green") : colorize("disabled", "red"); + const strategy = combo.strategy || "priority"; + console.log(` ${icon} ${combo.name.padEnd(25)} [${strategy.padEnd(12)}] ${status}`); + } + } + } catch (err) { + log(`Error reading combos: ${err.message}`, "red"); + } + + logEndSection(); +} + +async function runComboSwitch(args) { + const name = args[0]; + + if (!name) { + log("Usage: omniroute combo switch ", "red"); + return; + } + + logSection(`Switching to Combo: ${name}`); + + // Try API first + const serverRunning = await checkServerHealth(); + + if (serverRunning) { + try { + const res = await fetch(`${DEFAULT_BASE_URL}/api/combos/switch`, { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify({ name }), + }); + + if (res.ok) { + log(`Switched to combo '${name}'`, "green"); + logEndSection(); + return; + } + } catch {} + } + + // Direct DB fallback + const dataDir = resolveConfigPath(".omniroute"); + const dbPath = join(dataDir, "storage.sqlite"); + + if (!existsSync(dbPath)) { + log("Database not found. Start server first.", "red"); + logEndSection(); + return; + } + + try { + const { createRequire } = await import("node:module"); + const require = createRequire(import.meta.url); + const Database = require("better-sqlite3"); + const db = new Database(dbPath); + + // Check combo exists + const combo = db.prepare("SELECT id FROM combos WHERE name = ?").get(name); + + if (!combo) { + log(`Combo '${name}' not found`, "red"); + db.close(); + logEndSection(); + return; + } + + // Update settings to set active combo + const settingsPath = join(dataDir, "settings.json"); + let settings = {}; + if (existsSync(settingsPath)) { + try { + settings = JSON.parse(readFileSync(settingsPath, "utf8")); + } catch {} + } + + settings.activeCombo = name; + writeFileSync(settingsPath, JSON.stringify(settings, null, 2), "utf8"); + + log(`Switched to combo '${name}'`, "green"); + db.close(); + } catch (err) { + log(`Failed to switch combo: ${err.message}`, "red"); + } + + logEndSection(); +} + +async function runComboCreate(args) { + const name = args[0]; + const strategy = args[1] || "priority"; + + if (!name) { + log("Usage: omniroute combo create [strategy]", "red"); + return; + } + + const validStrategies = [ + "priority", + "weighted", + "round-robin", + "p2c", + "random", + "auto", + "lkgp", + "context-optimized", + "context-relay", + ]; + if (!validStrategies.includes(strategy)) { + log(`Invalid strategy. Valid: ${validStrategies.join(", ")}`, "red"); + return; + } + + logSection(`Creating Combo: ${name}`); + + const dataDir = resolveConfigPath(".omniroute"); + const dbPath = join(dataDir, "storage.sqlite"); + + if (!existsSync(dbPath)) { + log("Database not found. Start server first.", "red"); + logEndSection(); + return; + } + + try { + const { createRequire } = await import("node:module"); + const require = createRequire(import.meta.url); + const Database = require("better-sqlite3"); + const db = new Database(dbPath); + + // Check if combo already exists + const existing = db.prepare("SELECT id FROM combos WHERE name = ?").get(name); + + if (existing) { + log(`Combo '${name}' already exists. Use 'combo delete' first.`, "red"); + db.close(); + logEndSection(); + return; + } + + // Insert new combo + db.prepare( + ` + INSERT INTO combos (name, strategy, enabled, target_count) + VALUES (?, ?, 1, 0) + ` + ).run(name, strategy); + + log(`Combo '${name}' created with strategy '${strategy}'`, "green"); + log("Use 'omniroute combo switch " + name + "' to activate", "dim"); + db.close(); + } catch (err) { + log(`Failed to create combo: ${err.message}`, "red"); + } + + logEndSection(); +} + +async function runComboDelete(args) { + const name = args[0]; + + if (!name) { + log("Usage: omniroute combo delete ", "red"); + return; + } + + logSection(`Deleting Combo: ${name}`); + + const dataDir = resolveConfigPath(".omniroute"); + const dbPath = join(dataDir, "storage.sqlite"); + + if (!existsSync(dbPath)) { + log("Database not found. Start server first.", "red"); + logEndSection(); + return; + } + + try { + const { createRequire } = await import("node:module"); + const require = createRequire(import.meta.url); + const Database = require("better-sqlite3"); + const db = new Database(dbPath); + + const result = db.prepare("DELETE FROM combos WHERE name = ?").run(name); + + if (result.changes > 0) { + log(`Combo '${name}' deleted`, "green"); + } else { + log(`Combo '${name}' not found`, "yellow"); + } + + db.close(); + } catch (err) { + log(`Failed to delete combo: ${err.message}`, "red"); + } + + logEndSection(); +} + +// ============================================================================ +// SHELL COMPLETION +// ============================================================================ + +const VALID_SHELLS = ["bash", "zsh", "fish"]; + +async function runCompletion(args) { + const shell = args[0]; + + if (!shell) { + logSection("Shell Completion"); + log("Usage:"); + log(" omniroute completion bash"); + log(" omniroute completion zsh"); + log(" omniroute completion fish"); + log(""); + log("To install:"); + log(" bash: omniroute completion bash > ~/.bash_completion"); + log(" zsh: omniroute completion zsh > ~/.zsh/completions/_omniroute", "dim"); + logEndSection(); + return; + } + + if (!VALID_SHELLS.includes(shell)) { + log(`Invalid shell. Valid: ${VALID_SHELLS.join(", ")}`, "red"); + return; + } + + switch (shell) { + case "bash": + console.log(generateBashCompletion()); + break; + case "zsh": + console.log(generateZshCompletion()); + break; + case "fish": + console.log(generateFishCompletion()); + break; + } +} + +function generateBashCompletion() { + const script = `#!/bin/bash +# OmniRoute CLI Bash Completion + +_omniroute() { + local cur prev opts cmds + COMPREPLY=() + cur="\${COMP_WORDS[COMP_CWORD]}" + prev="\${COMP_WORDS[COMP_CWORD-1]}" + + opts="--help --version" + cmds="setup doctor status logs provider config test update serve stop restart keys models combo completion dashboard" + + # Command-specific options + case "\${prev}" in + setup) + COMPREPLY=($(compgen -W "--tools --url --key --list" -- \${cur})) + return 0 + ;; + logs) + COMPREPLY=($(compgen -W "--lines --level --follow" -- \${cur})) + return 0 + ;; + doctor) + COMPREPLY=($(compgen -W "--verbose" -- \${cur})) + return 0 + ;; + status) + COMPREPLY=($(compgen -W "--json" -- \${cur})) + return 0 + ;; + keys) + COMPREPLY=($(compgen -W "add list remove" -- \${cur})) + return 0 + ;; + keys add) + COMPREPLY=($(compgen -W "openai anthropic google deepseek groq mistral xai cohere" -- \${cur})) + return 0 + ;; + models) + COMPREPLY=($(compgen -W "--json openai anthropic google deepseek groq" -- \${cur})) + return 0 + ;; + combo) + COMPREPLY=($(compgen -W "list switch create delete" -- \${cur})) + return 0 + ;; + provider) + COMPREPLY=($(compgen -W "list add" -- \${cur})) + return 0 + ;; + completion) + COMPREPLY=($(compgen -W "bash zsh fish" -- \${cur})) + return 0 + ;; + serve) + COMPREPLY=($(compgen -W "--port --daemon" -- \${cur})) + return 0 + ;; + test) + COMPREPLY=($(compgen -W "--provider --model" -- \${cur})) + return 0 + ;; + dashboard) + COMPREPLY=($(compgen -W "--url" -- \${cur})) + return 0 + ;; + config) + COMPREPLY=($(compgen -W "show" -- \${cur})) + return 0 + ;; + *) + COMPREPLY=($(compgen -W "\${cmds} \${opts}" -- \${cur})) + return 0 + ;; + esac +} + +complete -F _omniroute omniroute +`; + return script; +} + +function generateZshCompletion() { + return `#compdef omniroute + +local -a commands +commands=( + 'setup:Configure CLI tools to use OmniRoute' + 'doctor:Run health diagnostics' + 'status:Show server and tools status' + 'logs:View application logs' + 'provider:Add OmniRoute as provider' + 'config:Show configuration' + 'test:Test provider connectivity' + 'update:Check for updates' + 'serve:Start the server' + 'stop:Stop the server' + 'restart:Restart the server' + 'keys:Manage API keys' + 'models:Browse available models' + 'combo:Manage routing combos' + 'completion:Generate shell completion' + 'dashboard:Open dashboard' +) + +_arguments -C \\ + '1: :->command' \\ + '*:: :->arg' \\ + && return 0 + +case $state in + command) + _describe 'command' commands + ;; + arg) + case $words[1] in + setup) + _arguments '--tools[Tools to configure]:tools:(claude codex opencode cline kilo continue openclaw)' '--url[Base URL]:url:' '--key[API Key]:key:' '--list[List available tools' + ;; + keys) + case $words[2] in + add) + _arguments '2:provider:(openai anthropic google deepseek groq mistral xai cohere)' '3:api-key:' + ;; + remove) + _arguments '2:provider:(openai anthropic google deepseek groq mistral xai cohere)' + ;; + *) + _describe 'subcommand' 'add:Add API key' 'list:List keys' 'remove:Remove key' + ;; + esac + ;; + combo) + _describe 'subcommand' 'list:List combos' 'switch:Switch combo' 'create:Create combo' 'delete:Delete combo' + ;; + completion) + _arguments '2:shell:(bash zsh fish)' + ;; + serve) + _arguments '--port[Port number]:port:' '--daemon[Run in background' + ;; + models) + _arguments '--json[JSON output]' '2:provider:(openai anthropic google deepseek groq)' + ;; + logs) + _arguments '--lines[Number of lines]:lines:' '--level[Log level]:level:(debug info warn error)' '--follow[Follow logs]' + ;; + esac + ;; +esac +`; +} + +function generateFishCompletion() { + return `# OmniRoute CLI Fish Completion + +complete -c omniroute -f + +# Main commands +complete -c omniroute -n '__fish_is_nth_arg 1' -a 'setup' -d 'Configure CLI tools' +complete -c omniroute -n '__fish_is_nth_arg 1' -a 'doctor' -d 'Run health diagnostics' +complete -c omniroute -n '__fish_is_nth_arg 1' -a 'status' -d 'Show status' +complete -c omniroute -n '__fish_is_nth_arg 1' -a 'logs' -d 'View logs' +complete -c omniroute -n '__fish_is_nth_arg 1' -a 'provider' -d 'Provider management' +complete -c omniroute -n '__fish_is_nth_arg 1' -a 'config' -d 'Show config' +complete -c omniroute -n '__fish_is_nth_arg 1' -a 'test' -d 'Test connectivity' +complete -c omniroute -n '__fish_is_nth_arg 1' -a 'update' -d 'Check updates' +complete -c omniroute -n '__fish_is_nth_arg 1' -a 'serve' -d 'Start server' +complete -c omniroute -n '__fish_is_nth_arg 1' -a 'stop' -d 'Stop server' +complete -c omniroute -n '__fish_is_nth_arg 1' -a 'restart' -d 'Restart server' +complete -c omniroute -n '__fish_is_nth_arg 1' -a 'keys' -d 'API key management' +complete -c omniroute -n '__fish_is_nth_arg 1' -a 'models' -d 'Browse models' +complete -c omniroute -n '__fish_is_nth_arg 1' -a 'combo' -d 'Combo management' +complete -c omniroute -n '__fish_is_nth_arg 1' -a 'completion' -d 'Shell completion' +complete -c omniroute -n '__fish_is_nth_arg 1' -a 'dashboard' -d 'Open dashboard' + +# Subcommands +complete -c omniroute -n '__fish_seen_subcommand_from keys' -a 'add' -d 'Add key' +complete -c omniroute -n '__fish_seen_subcommand_from keys' -a 'list' -d 'List keys' +complete -c omniroute -n '__fish_seen_subcommand_from keys' -a 'remove' -d 'Remove key' + +complete -c omniroute -n '__fish_seen_subcommand_from combo' -a 'list' -d 'List combos' +complete -c omniroute -n '__fish_seen_subcommand_from combo' -a 'switch' -d 'Switch combo' +complete -c omniroute -n '__fish_seen_subcommand_from combo' -a 'create' -d 'Create combo' +complete -c omniroute -n '__fish_seen_subcommand_from combo' -a 'delete' -d 'Delete combo' + +complete -c omniroute -n '__fish_seen_subcommand_from completion' -a 'bash' -d 'Bash completion' +complete -c omniroute -n '__fish_seen_subcommand_from completion' -a 'zsh' -d 'Zsh completion' +complete -c omniroute -n '__fish_seen_subcommand_from completion' -a 'fish' -d 'Fish completion' +`; +} + +// ============================================================================ +// DASHBOARD COMMAND +// ============================================================================ + +async function runDashboard(args) { + const urlOnly = args.includes("--url"); + + const dashboardUrl = `http://localhost:${DASHBOARD_PORT}`; + + if (urlOnly) { + console.log(dashboardUrl); + return; + } + + logSection("Opening Dashboard"); + + try { + const { execSync } = require("node:child_process"); + const platform = process.platform; + + let command; + if (platform === "darwin") { + command = `open "${dashboardUrl}"`; + } else if (platform === "win32") { + command = `start "" "${dashboardUrl}"`; + } else { + command = `xdg-open "${dashboardUrl}" 2>/dev/null || sensible-browser "${dashboardUrl}" 2>/dev/null || echo "Cannot open browser. Go to: ${dashboardUrl}"`; + } + + execSync(command, { stdio: "ignore" }); + log(`Opening: ${dashboardUrl}`, "green"); + } catch { + log(`Open in browser: ${dashboardUrl}`, "yellow"); + } + + logEndSection(); +} + +// ============================================================================ +// BACKUP & RESTORE +// ============================================================================ + +async function runBackup(args) { + const dataDir = resolveConfigPath(".omniroute"); + const timestamp = new Date().toISOString().replace(/[:.]/g, "-").slice(0, 19); + const backupDir = join(dataDir, "backups"); + const backupName = `omniroute-backup-${timestamp}`; + const backupPath = join(backupDir, backupName); + + logSection("Creating Backup"); + + try { + // Ensure backup directory exists + if (!existsSync(backupDir)) { + mkdirSync(backupDir, { recursive: true }); + } + + // Files to backup + const filesToBackup = [ + { name: "storage.sqlite", dest: "storage.sqlite" }, + { name: "settings.json", dest: "settings.json" }, + { name: "combos.json", dest: "combos.json" }, + { name: "providers.json", dest: "providers.json" }, + ]; + + let backedUp = 0; + let skipped = 0; + + for (const file of filesToBackup) { + const sourcePath = join(dataDir, file.name); + if (existsSync(sourcePath)) { + const destPath = join(backupPath, file.dest); + mkdirSync(dirname(destPath), { recursive: true }); + copyFileSync(sourcePath, destPath); + backedUp++; + } else { + skipped++; + } + } + + if (backedUp > 0) { + // Create backup info + const info = { + timestamp: new Date().toISOString(), + version: "omniroute-cli-v1", + files: filesToBackup.filter((f) => existsSync(join(dataDir, f.name))).map((f) => f.name), + }; + writeFileSync(join(backupPath, "backup-info.json"), JSON.stringify(info, null, 2), "utf8"); + + log(`Backup created: ${backupName}`, "green"); + log(`Files: ${backedUp} backed up, ${skipped} skipped`, "dim"); + log(`Location: ${backupPath}`, "dim"); + } else { + log("No files to backup (database not initialized)", "yellow"); + } + } catch (err) { + log(`Backup failed: ${err.message}`, "red"); + } + + logEndSection(); +} + +async function runRestore(args) { + const backupName = args[0]; + const dataDir = resolveConfigPath(".omniroute"); + const backupDir = join(dataDir, "backups"); + + if (!backupName) { + logSection("Available Backups"); + if (!existsSync(backupDir)) { + log("No backups found", "yellow"); + logEndSection(); + return; + } + + try { + const dirs = readdirSync(backupDir).filter((f) => f.startsWith("omniroute-backup-")); + if (dirs.length === 0) { + log("No backups found", "yellow"); + } else { + for (const dir of dirs.sort().reverse()) { + const infoPath = join(backupDir, dir, "backup-info.json"); + if (existsSync(infoPath)) { + const info = JSON.parse(readFileSync(infoPath, "utf8")); + log(` ${dir.replace("omniroute-backup-", "")}`); + log( + ` ${new Date(info.timestamp).toLocaleString()} - ${info.files?.length || 0} files`, + "dim" + ); + } else { + log(` ${dir.replace("omniroute-backup-", "")}`, "dim"); + } + } + } + } catch (err) { + log(`Error listing backups: ${err.message}`, "red"); + } + logEndSection(); + console.log("Usage: omniroute restore "); + return; + } + + logSection(`Restoring from: ${backupName}`); + + const backupPath = join(backupDir, `omniroute-backup-${backupName}`); + + if (!existsSync(backupPath)) { + log(`Backup not found: ${backupName}`, "red"); + logEndSection(); + return; + } + + try { + // Restore files + const filesToRestore = [ + { name: "storage.sqlite", dest: "storage.sqlite" }, + { name: "settings.json", dest: "settings.json" }, + { name: "combos.json", dest: "combos.json" }, + { name: "providers.json", dest: "providers.json" }, + ]; + + for (const file of filesToRestore) { + const sourcePath = join(backupPath, file.dest); + if (existsSync(sourcePath)) { + const destPath = join(dataDir, file.name); + copyFileSync(sourcePath, destPath); + log(`Restored: ${file.name}`, "dim"); + } + } + + log("Backup restored successfully!", "green"); + log("Restart OmniRoute to load restored data", "dim"); + } catch (err) { + log(`Restore failed: ${err.message}`, "red"); + } + + logEndSection(); +} + +// ============================================================================ +// QUOTA MANAGEMENT +// ============================================================================ + +async function runQuota(args) { + const jsonOutput = args.includes("--json"); + + logSection("Provider Quota Usage"); + + const serverRunning = await checkServerHealth(); + + if (!serverRunning) { + log("Server not running. Start with 'omniroute serve'", "red"); + logEndSection(); + return; + } + + try { + // Try quota endpoint + let quotaData = null; + try { + const res = await fetch(`${DEFAULT_BASE_URL}/api/quota`, { + signal: AbortSignal.timeout(5000), + }); + if (res.ok) { + quotaData = await res.json(); + } + } catch {} + + // Fallback: get from providers + if (!quotaData) { + try { + const res = await fetch(`${DEFAULT_BASE_URL}/api/v1/providers`, { + signal: AbortSignal.timeout(5000), + }); + if (res.ok) { + const providers = await res.json(); + quotaData = { + providers: providers.map((p) => ({ + provider: p.name || p.id, + quota: p.quota || p.remaining || "N/A", + used: p.used || 0, + reset: p.resetAt || "N/A", + })), + }; + } + } catch {} + } + + if (jsonOutput) { + console.log(JSON.stringify(quotaData || { error: "No quota data" }, null, 2)); + logEndSection(); + return; + } + + if (!quotaData?.providers) { + log("No quota information available", "yellow"); + logEndSection(); + return; + } + + console.log(); + console.log( + colorize( + " Provider".padEnd(25) + "Used".padEnd(15) + "Remaining".padEnd(20) + "Reset", + "cyan" + ) + ); + console.log( + colorize( + " " + "─".repeat(24) + " " + "─".repeat(14) + " " + "─".repeat(19) + " " + "─".repeat(15), + "dim" + ) + ); + + for (const p of quotaData.providers) { + const provider = (p.provider || "unknown").slice(0, 23); + const used = String(p.used || 0).padEnd(14); + const remaining = (p.quota || p.remaining || "N/A").toString().slice(0, 18); + const reset = p.reset || "N/A"; + console.log(` ${provider.padEnd(25)}${used.padEnd(15)}${remaining.padEnd(20)}${reset}`); + } + + log(`Total: ${quotaData.providers.length} providers`, "green"); + } catch (err) { + log(`Failed to fetch quota: ${err.message}`, "red"); + } + + logEndSection(); +} + +// ============================================================================ +// HEALTH STATUS +// ============================================================================ + +async function runHealth(args) { + const verbose = args.includes("--verbose"); + const jsonOutput = args.includes("--json"); + + logSection("OmniRoute Health"); + + const serverRunning = await checkServerHealth(); + + if (!serverRunning) { + log("Server not running. Start with 'omniroute serve'", "red"); + logEndSection(); + return; + } + + try { + const res = await fetch(`${DEFAULT_BASE_URL}/api/health`, { + signal: AbortSignal.timeout(5000), + }); + + if (res.ok) { + const health = await res.json(); + + if (jsonOutput) { + console.log(JSON.stringify(health, null, 2)); + logEndSection(); + return; + } + + // Display health info + log(`Status: ${colorize("healthy", "green")}`); + log(`Uptime: ${health.uptime || "N/A"}`); + log(`Version: ${health.version || "N/A"}`); + + if (health.breakers) { + console.log(); + logSection("Circuit Breakers"); + for (const [name, status] of Object.entries(health.breakers)) { + const state = + status.state === "closed" + ? colorize("● closed", "green") + : colorize("○ open", "yellow"); + log(` ${name.padEnd(20)} ${state}`); + } + } + + if (health.cache) { + console.log(); + logSection("Cache Status"); + log(` Semantic: ${health.cache.semanticHits || 0} hits`); + log(` Signature: ${health.cache.signatureHits || 0} hits`); + } + + if (verbose && health.memory) { + console.log(); + logSection("Memory"); + log(` RSS: ${health.memory.rss || "N/A"}`); + log(` Heap Used: ${health.memory.heapUsed || "N/A"}`); + } + } + } catch (err) { + log(`Failed to get health: ${err.message}`, "red"); + } + + logEndSection(); +} + +// ============================================================================ +// CACHE MANAGEMENT +// ============================================================================ + +async function runCache(args) { + const action = args[0]; + + if (!action || action === "status") { + logSection("Cache Status"); + + const serverRunning = await checkServerHealth(); + + if (!serverRunning) { + log("Server not running. Start with 'omniroute serve'", "yellow"); + logEndSection(); + return; + } + + try { + const res = await fetch(`${DEFAULT_BASE_URL}/api/cache/stats`, { + signal: AbortSignal.timeout(5000), + }); + if (res.ok) { + const stats = await res.json(); + log(`Semantic Cache: ${stats.semanticHits || 0} hits`); + log(`Signature Cache: ${stats.signatureHits || 0} hits`); + } else { + log("Cache stats not available", "yellow"); + } + } catch { + log("Cache stats not available", "yellow"); + } + logEndSection(); + return; + } + + if (action === "clear") { + logSection("Clearing Cache"); + + const serverRunning = await checkServerHealth(); + + if (!serverRunning) { + log("Server not running. Cannot clear cache.", "red"); + logEndSection(); + return; + } + + try { + const res = await fetch(`${DEFAULT_BASE_URL}/api/cache/clear`, { + method: "POST", + signal: AbortSignal.timeout(5000), + }); + + if (res.ok) { + log("Cache cleared successfully!", "green"); + } else { + log("Failed to clear cache", "red"); + } + } catch (err) { + log(`Error: ${err.message}`, "red"); + } + logEndSection(); + return; + } + + log(`Unknown cache action: ${action}`, "red"); + log("Valid actions: status, clear", "dim"); +} + +// ============================================================================ +// MCP SERVER STATUS +// ============================================================================ + +async function runMcp(args) { + const action = args[0] || "status"; + + logSection("MCP Server"); + + const serverRunning = await checkServerHealth(); + + if (!serverRunning) { + log("Server not running. Start with 'omniroute serve'", "red"); + logEndSection(); + return; + } + + if (action === "status" || action === "list") { + try { + const res = await fetch(`${DEFAULT_BASE_URL}/api/mcp/status`, { + signal: AbortSignal.timeout(5000), + }); + + if (res.ok) { + const status = await res.json(); + log( + `Status: ${status.running ? colorize("running", "green") : colorize("stopped", "red")}` + ); + log(`Tools: ${status.toolsCount || 0}`); + log(`Transport: ${status.transport || "stdio"}`); + + if (status.scopes) { + console.log(); + log("Scopes:"); + for (const scope of status.scopes) { + log(` - ${scope}`); + } + } + } else { + log("MCP status not available", "yellow"); + } + } catch (err) { + log(`Error: ${err.message}`, "red"); + } + } else if (action === "restart") { + try { + const res = await fetch(`${DEFAULT_BASE_URL}/api/mcp/restart`, { + method: "POST", + signal: AbortSignal.timeout(10000), + }); + + if (res.ok) { + log("MCP server restarted", "green"); + } else { + log("Failed to restart MCP", "red"); + } + } catch (err) { + log(`Error: ${err.message}`, "red"); + } + } else { + log(`Unknown action: ${action}`, "red"); + log("Valid actions: status, list, restart", "dim"); + } + + logEndSection(); +} + +// ============================================================================ +// A2A SERVER STATUS +// ============================================================================ + +async function runA2a(args) { + const action = args[0] || "status"; + + logSection("A2A Server"); + + const serverRunning = await checkServerHealth(); + + if (!serverRunning) { + log("Server not running. Start with 'omniroute serve'", "red"); + logEndSection(); + return; + } + + if (action === "status" || action === "list") { + try { + const res = await fetch(`${DEFAULT_BASE_URL}/api/a2a/status`, { + signal: AbortSignal.timeout(5000), + }); + + if (res.ok) { + const status = await res.json(); + log( + `Status: ${status.running ? colorize("running", "green") : colorize("stopped", "red")}` + ); + log(`Protocol: ${status.protocol || "JSON-RPC 2.0"}`); + log(`Tasks: ${status.activeTasks || 0} active`); + + if (status.skills) { + console.log(); + log("Skills:"); + for (const skill of status.skills) { + log(` - ${skill.name}: ${skill.description || "N/A"}`, "dim"); + } + } + } else { + log("A2A status not available", "yellow"); + } + } catch (err) { + log(`Error: ${err.message}`, "red"); + } + } else if (action === "card") { + try { + const res = await fetch(`${DEFAULT_BASE_URL}/.well-known/agent.json`, { + signal: AbortSignal.timeout(5000), + }); + + if (res.ok) { + const card = await res.json(); + console.log(JSON.stringify(card, null, 2)); + } else { + log("Agent card not available", "yellow"); + } + } catch (err) { + log(`Error: ${err.message}`, "red"); + } + } else { + log(`Unknown action: ${action}`, "red"); + log("Valid actions: status, list, card", "dim"); + } + + logEndSection(); +} + +// ============================================================================ +// TUNNEL MANAGEMENT +// ============================================================================ + +async function runTunnel(args) { + const action = args[0]; + + logSection("Tunnel Management"); + + const serverRunning = await checkServerHealth(); + + if (!serverRunning) { + log("Server not running. Start with 'omniroute serve'", "red"); + logEndSection(); + return; + } + + if (!action || action === "list") { + try { + const res = await fetch(`${DEFAULT_BASE_URL}/api/tunnels`, { + signal: AbortSignal.timeout(5000), + }); + + if (res.ok) { + const tunnels = await res.json(); + + if (tunnels.length === 0) { + log("No active tunnels", "yellow"); + } else { + for (const t of tunnels) { + const status = t.active ? colorize("● active", "green") : colorize("○ inactive", "dim"); + log(` ${t.type || "unknown"}: ${t.url || "N/A"} ${status}`); + } + } + } else { + log("Tunnel info not available", "yellow"); + } + } catch (err) { + log(`Error: ${err.message}`, "red"); + } + } else if (action === "create" || action === "add") { + const tunnelType = args[1] || "cloudflare"; + + try { + const res = await fetch(`${DEFAULT_BASE_URL}/api/tunnels`, { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify({ type: tunnelType }), + signal: AbortSignal.timeout(15000), + }); + + if (res.ok) { + const result = await res.json(); + log(`Tunnel created: ${result.url}`, "green"); + } else { + log("Failed to create tunnel", "red"); + } + } catch (err) { + log(`Error: ${err.message}`, "red"); + } + } else if (action === "stop" || action === "delete") { + const tunnelType = args[1]; + + try { + const res = await fetch(`${DEFAULT_BASE_URL}/api/tunnels/${tunnelType}`, { + method: "DELETE", + signal: AbortSignal.timeout(5000), + }); + + if (res.ok) { + log(`Tunnel ${tunnelType} stopped`, "green"); + } else { + log("Failed to stop tunnel", "red"); + } + } catch (err) { + log(`Error: ${err.message}`, "red"); + } + } else { + log("Valid actions: list, create , stop "); + log("Types: cloudflare, tailscale, ngrok", "dim"); + } + + logEndSection(); +} + +// ============================================================================ +// ENVIRONMENT VARIABLES +// ============================================================================ + +async function runEnv(args) { + const action = args[0]; + + if (!action || action === "show" || action === "list") { + logSection("Environment Variables"); + + const importantVars = [ + "PORT", + "API_PORT", + "DASHBOARD_PORT", + "DATA_DIR", + "REQUIRE_API_KEY", + "LOG_LEVEL", + "NODE_ENV", + "REQUEST_TIMEOUT_MS", + "ENABLE_SOCKS5_PROXY", + ]; + + log("Current configuration:"); + console.log(); + + for (const key of importantVars) { + const value = process.env[key]; + if (value !== undefined) { + log(` ${key.padEnd(25)} ${value}`, "dim"); + } + } + + console.log(); + log("Defaults:", "dim"); + log(" PORT 20128"); + log(" DASHBOARD_PORT 20129"); + log(" DATA_DIR ~/.omniroute"); + logEndSection(); + return; + } + + if (action === "get") { + const key = args[1]; + if (!key) { + log("Usage: omniroute env get ", "red"); + return; + } + console.log(process.env[key] || ""); + return; + } + + if (action === "set") { + const key = args[1]; + const value = args[2]; + + if (!key || value === undefined) { + log("Usage: omniroute env set ", "red"); + return; + } + + log(`Setting ${key}=${value} (temporary - only affects current session)`, "yellow"); + process.env[key] = value; + log("Set successfully (note: this is temporary)", "green"); + return; + } + + log("Valid actions: show, get , set ", "dim"); +} diff --git a/bin/omniroute.mjs b/bin/omniroute.mjs index 8202818956..1ce5ca86f7 100644 --- a/bin/omniroute.mjs +++ b/bin/omniroute.mjs @@ -106,6 +106,67 @@ if (args.includes("--help") || args.includes("-h")) { omniroute --no-open Don't open browser automatically omniroute --mcp Start MCP server (stdio transport for IDEs) omniroute reset-encrypted-columns Reset encrypted credentials (recovery) + + \x1b[1mServer Management:\x1b[0m + omniroute serve Start the OmniRoute server + omniroute stop Stop the running server + omniroute restart Restart the server + omniroute dashboard Open dashboard in browser + omniroute open Alias for dashboard (same as dashboard) + + \x1b[1mCLI Integration Suite:\x1b[0m + omniroute setup Interactive wizard to configure CLI tools + omniroute doctor Run health diagnostics + omniroute status Show comprehensive status + omniroute logs Stream request logs (--json, --search, --follow) + omniroute config show Display current configuration + + \x1b[1mProvider & Keys:\x1b[0m + omniroute provider list List available providers + omniroute provider add Add OmniRoute as provider + omniroute keys add Add API key for provider + omniroute keys list List configured API keys + omniroute keys remove Remove API key + + \x1b[1mModels & Combos:\x1b[0m + omniroute models List available models (--json, --search) + omniroute models Filter models by provider + omniroute combo list List routing combos + omniroute combo switch Switch active combo + omniroute combo create Create new combo + omniroute combo delete Delete a combo + + \x1b[1mBackup & Restore:\x1b[0m + omniroute backup Create backup of config & DB + omniroute restore Restore from backup (list or specify timestamp) + + \x1b[1mMonitoring:\x1b[0m + omniroute health Detailed health (breakers, cache, memory) + omniroute quota Show provider quota usage + omniroute cache Show cache status + omniroute cache clear Clear semantic/signature cache + + \x1b[1mProtocols:\x1b[0m + omniroute mcp status MCP server status + omniroute mcp restart Restart MCP server + omniroute a2a status A2A server status + omniroute a2a card Show A2A agent card + + \x1b[1mTunnels & Network:\x1b[0m + omniroute tunnel list List active tunnels + omniroute tunnel create Create tunnel (cloudflare/tailscale/ngrok) + omniroute tunnel stop Stop a tunnel + + \x1b[1mEnvironment:\x1b[0m + omniroute env show Show environment variables + omniroute env get Get specific env var + omniroute env set Set env var (temporary) + + \x1b[1mTools & Utils:\x1b[0m + omniroute test Test provider connectivity + omniroute update Check for updates + omniroute completion Generate shell completion + omniroute --help Show this help omniroute --version Show version @@ -160,6 +221,24 @@ if (args.includes("--version") || args.includes("-v")) { process.exit(0); } +// ── CLI Integration Suite subcommands ─────────────────────────────────────── +const subcommands = [ + "setup", "doctor", "status", "logs", "provider", "config", "test", "update", + "serve", "stop", "restart", + "keys", "models", "combo", + "completion", "dashboard", + "backup", "restore", "quota", "health", + "cache", "mcp", "a2a", "tunnel", + "env", "open" +]; +const subcommand = args[0]; + +if (subcommands.includes(subcommand)) { + const { runSubcommand } = await import("./cli-commands.mjs"); + await runSubcommand(subcommand, args.slice(1)); + process.exit(0); +} + // ── reset-encrypted-columns subcommand ────────────────────────────────────── // Recovery tool for users who lost STORAGE_ENCRYPTION_KEY after upgrade (#1622) if (args.includes("reset-encrypted-columns")) { diff --git a/docs/i18n/ar/CHANGELOG.md b/docs/i18n/ar/CHANGELOG.md index a5a4011886..538f4faa10 100644 --- a/docs/i18n/ar/CHANGELOG.md +++ b/docs/i18n/ar/CHANGELOG.md @@ -10,30 +10,148 @@ ### ✨ New Features -- **feat(antigravity):** integrate Antigravity provider with dynamic `maxOutputTokens` calculation (bumping to `thinkingBudget + 1`) and standard Cloud Code envelope payload sanitization (#2055, #2063) +- **feat(antigravity):** integrate Antigravity provider with dynamic `maxOutputTokens` calculation, identity fingerprinting overhaul, and Cloud Code envelope payload sanitization (#2055, #2063) - **feat(gemini-cli):** add custom projectId support for Gemini CLI transport (UI, DB, executor) (#1991) +- **feat(providers):** add KIE media provider support with dynamic polling, text models, and expanded video models catalog +- **feat(providers):** add Z.AI provider support with GLM quota handling and new quota labels +- **feat(providers):** add 9 new free AI providers — LLM7, Lepton, Kluster, UncloseAI, BazaarLink, Completions, Enally, FreeTheAi (#2096) +- **feat(providers):** batch delete provider connections via checkbox multi-select (#2094) +- **feat(cursor):** full OpenAI parity — tool calls, streaming, and session management (#2082) +- **feat(cli):** comprehensive CLI enhancement suite with 20+ new commands including `omniroute providers`, `omniroute combos`, `omniroute doctor` (#2074) +- **feat(cli):** add modular CLI setup and provider management commands (#2046) +- **feat(mcp):** add DeepSeek quota and limit monitoring feature (#2089) +- **feat(circuit-breaker):** classify 429 errors and apply per-kind cooldowns (#2116) +- **feat(multi):** manifest-aware tier routing — W1-W4 complete (#2014) +- **feat(combos):** add reset-aware routing strategy for quota-based providers +- **feat(combo):** add context_length input field to combo edit form (#2047) +- **feat(chat):** dynamic tool limit detection with proactive truncation (#2061) +- **feat(sse):** refresh Claude OAuth wire image to claude-cli/2.1.131 (#2011) +- **feat(github):** add `targetFormat: openai-responses` to all GitHub models (#2122) +- **feat(api):** allow configuration via API calls — open management routes to Bearer keys with manage scope (#2103) +- **feat(api):** update API bridge proxy timeout to 600,000ms (#2019) +- **feat(usage):** add service tier breakdown, codex fast service tier analytics, and account for fast tier +- **feat(chat):** add `STREAM_READINESS_TIMEOUT_MS` and integrate into chat handling +- **feat(combo):** add `fallbackDelayMs` to combo configuration and related settings +- **feat(chat):** enhance error handling for semaphore capacity with fallback logic +- **feat(qdrant):** embedding model discovery (#2086) +- **feat(auth):** per-session sticky routing for Codex (#1887) +- **feat(inworld):** enhance Inworld TTS support (#2123) ### 🐛 Bug Fixes +- **fix(pricing):** make `getPricingForModel` fully case-insensitive to ensure custom prices correctly reflect in new incoming requests cost calculations +- **fix(gemini):** prevent `functionDeclarations` from being dropped by the sanitizer when `googleSearch` tool is present (#2077) +- **fix(pollinations):** add `jsonMode: true` flag in the request transformation to enforce correct JSON structure from Pollinations API (#2109) +- **fix(docker):** update Dockerfile to copy `/docs` directory during build ensuring API catalog availability at runtime (#2083) +- **fix(docker):** include OpenAPI spec in runtime image (#2007) +- **fix(providers):** strip OpenAI-specific fields in Kiro translator to prevent 400 errors (#2037) +- **fix(kiro):** normalize tool-use payloads to prevent 400 errors from agents (#2104) +- **fix(kiro):** merge adjacent user history turns after role normalization (#2105) +- **fix(ui):** resolve text contrast issues for zero-config warning banner in light mode (#2050) +- **fix(core):** inject global system prompt correctly into downstream chat completions pipeline (#2080) +- **fix(core):** restore Claude Code adaptive thinking defaults and resolve audio transcription CORS regression +- **fix(routing):** add missing v1beta rewrites to next.config to resolve 404 on Gemini models endpoint (#2102) +- **fix(routing):** fix bare GPT-5.5 routing for Codex-only installations (#2054) +- **fix(routing):** add fuzzy auto-combo routing for `auto/*` model prefix (#2010) - **fix(cache):** optimize cache_control preservation logic and explicitly align tool schema with upstream Claude Code expectations - **fix(db):** preserve legacy SQLite database path on Windows to prevent data loss (#1973) +- **fix(db):** reduce hot-path persistence overhead (#2039) +- **fix(db):** resolve migration conflict by renumbering overlapping migration entries (#2041) - **fix(settings):** resolve model alias persistence double stringification preventing UI updates (#2018) - **fix(routing):** dynamically filter bare model auto-resolution by active provider connections to prevent dead-routing (#2029) - **fix(embeddings):** add Google Gemini embeddings compatibility via OpenAI-compatible endpoint mapping (#2006) +- **fix(sse):** prevent Claude OAuth multi-account correlation via metadata.user_id (#2053) +- **fix(sse):** prevent Claude Code identity cloak overrides and fix fallback resilience (#2053) +- **fix(sse):** classify hour quota errors as QUOTA_EXHAUSTED (#2119) +- **fix(sse):** fix CC-compatible streaming bridge (#2118) +- **fix(antigravity):** sanitize Claude Cloud Code payloads (#2090) +- **fix(antigravity):** add duplex half for streaming bodies +- **fix(antigravity):** align identity protocol and behavior with official AM +- **fix(chatgpt-web):** plumb proxy through to native tls-client (#2022, #2023) +- **fix(codex):** expose native model IDs in catalog (#2012) +- **fix(glm):** add dedicated coding transport (#2087) +- **fix(compression):** support Responses input and expand Spanish compression rules (#2028) +- **fix(catalog):** auto-calculate combo context_length from target model limits (#2030) +- **fix(api):** fix usage analytics and API key identity (#2008, #2092) +- **fix(api-key):** allow Unicode letters in API key name validation (#1996) +- **fix(auth):** allow bootstrap without password (#2048) +- **fix(proxy):** clean up proxy page redundancy and fix 1proxy sync empty body error (#2052) +- **fix(dashboard):** resolve Unknown plan display in Provider Limits +- **fix(usage):** add extensible CURRENCY_SYMBOLS mapping for deepseek currencies +- **fix(runtime):** harden timer handling and model pricing fallback +- **fix(i18n):** complete Simplified Chinese translations (#2115) +- **fix(mitm):** add Linux cert install and skip sudo password when root (#1999) +- **fix(mitm):** prevent stub from loading at runtime via bypass module - **fix:** remove Anthropic-Beta header from non-Anthropic providers to fix identity contamination (#1989) - **fix(cli):** resolve .env loading failure for global npm installations +- **fix(export):** exclude telemetry/usage-history tables from JSON config backups by default to prevent unbounded file growth (#2125) +- **fix:** Follow OpenAI specification, handle throttling in batch and fix UI (#2045) -### 🔒 Security +### الأمان +- **fix(security):** remediate CodeQL vulnerabilities (ReDoS, cryptographic bias, stack trace exposure, and weak password hashing) (#216, #215, #211, #208, #206, #210) - **fix(security):** remediate regex validation backtracking path in core compression cleanup (#1990) - **fix(core):** harden input handling and stabilization for prompt compression edge cases +### التوثيق + +- **docs:** add competitive marketing tables and SEO/AEO optimizations to README (#2091) +- **docs:** refresh providers, model catalogs, and docs for v3.8.0 (#2088) +- **docs:** update Claude MD and update GLM-CN max context to 200k (#2027) +- **docs(env):** add `GITLAB_DUO_OAUTH_CLIENT_ID` to `.env.example` (#2031) + ### 🧹 Chores & Maintenance - **chore(providers):** prune redundant local provider icon assets in favor of `@lobehub/icons` web fonts (#1992) +- **chore(providers):** remove deprecated models (#2033) +- **deps:** bump `fast-uri` from 3.1.0 to 3.1.2 (#2078) +- **deps:** bump `hono` from 4.12.14 to 4.12.18 (#2079) - **ci:** skip SonarCloud scan on main pushes to optimize CI time - **test:** stabilize cooldown abort coverage case in integration testing +### 🏆 v3.8.0 Community Contributors + +Thank you to all **38 community contributors** who made v3.8.0 possible! 🎉 + +| Contributor | PRs | Contributions | +| :--------------------------------------------------------- | :-: | :------------------------------------------------------------ | +| [@oyi77](https://github.com/oyi77) | 7 | #2010, #2014, #2041, #2052, #2061, #2074, #2091, #2094, #2096 | +| [@backryun](https://github.com/backryun) | 4 | #1992, #2033, #2088, #2123 | +| [@dhaern](https://github.com/dhaern) | 4 | #2028, #2039, #2087, #2090 | +| [@Tentoxa](https://github.com/Tentoxa) | 2 | #2011, #2053 | +| [@wauputr4](https://github.com/wauputr4) | 2 | #2009, #2046 | +| [@payne0420](https://github.com/payne0420) | 1 | #2082 | +| [@Tr0sT](https://github.com/Tr0sT) | 1 | #2012 | +| [@AveryanAlex](https://github.com/AveryanAlex) | 1 | #2008 | +| [@nickwizard](https://github.com/nickwizard) | 1 | #1991 | +| [@rodrigogbbr-stack](https://github.com/rodrigogbbr-stack) | 1 | #1996 | +| [@NekoMonci12](https://github.com/NekoMonci12) | 1 | #1999 | +| [@congvc-dev](https://github.com/congvc-dev) | 1 | #2004 | +| [@tatsster](https://github.com/tatsster) | 1 | #2007 | +| [@xssdem](https://github.com/xssdem) | 1 | #2023 | +| [@bypanghu](https://github.com/bypanghu) | 1 | #2027 | +| [@herjarsa](https://github.com/herjarsa) | 1 | #2030 | +| [@wucm667](https://github.com/wucm667) | 1 | #2031 | +| [@hartmark](https://github.com/hartmark) | 1 | #2045 | +| [@ddarkr](https://github.com/ddarkr) | 1 | #2047 | +| [@tces1](https://github.com/tces1) | 1 | #2048 | +| [@guanbear](https://github.com/guanbear) | 1 | #2054 | +| [@Gi99lin](https://github.com/Gi99lin) | 1 | #2055 | +| [@ivan-mezentsev](https://github.com/ivan-mezentsev) | 1 | #2063 | +| [@JxnLexn](https://github.com/JxnLexn) | 1 | #2019 | +| [@yoviarpauzi](https://github.com/yoviarpauzi) | 1 | #2092 | +| [@rafacpti23](https://github.com/rafacpti23) | 1 | #2086 | +| [@gleber](https://github.com/gleber) | 1 | #2103 | +| [@rilham97](https://github.com/rilham97) | 1 | #2104 | +| [@Gioxaa](https://github.com/Gioxaa) | 1 | #2105 | +| [@boa-z](https://github.com/boa-z) | 1 | #2115 | +| [@eleata](https://github.com/eleata) | 1 | #2116 | +| [@rdself](https://github.com/rdself) | 1 | #2118 | +| [@clousky2020](https://github.com/clousky2020) | 1 | #2119 | +| [@abhinavjnu](https://github.com/abhinavjnu) | 1 | #2122 | +| [@HoaPham98](https://github.com/HoaPham98) | 1 | #2089 | +| [@05dunski](https://github.com/05dunski) | 1 | #1978 (cherry-picked) | + ## [3.7.9] — 2026-05-03 ### ✨ New Features @@ -102,7 +220,7 @@ - **chore(provider):** Add reka models list (#1956 — thanks @backryun) - **chore(model):** Update new models, Delete Deprecated models (#1949 — thanks @backryun) -### 📝 Documentation +### التوثيق - **docs(compression):** document RTK+Caveman stacked savings ranges @@ -201,7 +319,7 @@ - **feat(db):** auto-restore probe-failed database on startup to prevent data loss after failed upgrades (#1810) - **feat(analytics):** add cost-based usage insights and activity streaks in the analytics dashboard -### 🔒 Security +### الأمان - **fix(security):** resolve ReDoS vulnerability in Codex executor regex patterns (#1797, #1789) @@ -354,7 +472,7 @@ We identified that **155 community PRs** across the entire project history (from - **feat(proxy):** implement bulk proxy import via pipe-delimited parser with update-or-create (upsert) logic and real-time preview table - **feat(pwa):** add fullscreen installable PWA with manifest, service worker, and cross-platform app icons (#1728) -### 🔒 Security +### الأمان - **security:** replace insecure `Math.random` with `crypto.getRandomValues` for fallback UUID generation to resolve CodeQL CWE-338 finding (#182) @@ -519,7 +637,7 @@ We identified that **155 community PRs** across the entire project history (from - **fix(transport):** Prevent memory bloat and database exhaustion from large, fragmented streaming responses. Implemented `ByteQueue` in `kiro.ts` for zero-copy binary accumulation, refactored `antigravity.ts` for incremental SSE parsing, and enforced a strict 512KB tiered truncation limit (`MAX_CALL_LOG_ARTIFACT_BYTES`) on stream request logs and call artifacts (#1647). - **chore(ci):** Update build environment dependencies — bump Node to `24.15.0`, `actions/checkout@v6`, `docker/build-push-action@v7`, pin `actions/setup-python` to major tag (#1646 — thanks @backryun). -### 📝 Documentation +### التوثيق - **docs(env):** Add `OMNIROUTE_ALLOW_PRIVATE_PROVIDER_URLS` to `.env.example` with documentation for LM Studio and other local provider use cases (#1623). @@ -669,7 +787,7 @@ We identified that **155 community PRs** across the entire project history (from - **test(next):** Align transpile package expectations for the Next.js standalone build. - **test(ci):** Fix CI-only test failures from environment differences — clear `INITIAL_PASSWORD` and `JWT_SECRET` in integration tests, handle `XDG_CONFIG_HOME` for guide-settings tests. -### 📚 Documentation +### التوثيق - **docs:** Update the root changelog with all release-branch changes through 2026-04-24, including PRs #1544, #1555, #1551, #1550, #1548, #1547, #1541, #1538, #1536, and #1527. - **docs:** Fix broken README and localized documentation links. (#1536) @@ -811,7 +929,7 @@ We identified that **155 community PRs** across the entire project history (from - **feat(providers):** Expand image provider registry with extended model support including SD3.5, FLUX, and DALL-E 3 HD configurations - **feat(combos):** Add new routing strategies and full i18n support for agent features section across 31 languages -### 🔒 Security +### الأمان - **security:** Resolve 18 GitHub CodeQL scan alerts including ReDoS, incomplete sanitization, and bad HTML filtering regexp patterns - **fix(auth):** Seal privilege escalation vector by enforcing JWT session checking exclusively on `/api/keys` management endpoints (#1353) @@ -1078,7 +1196,7 @@ We identified that **155 community PRs** across the entire project history (from - **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 - **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 -### 🔒 Security +### الأمان - **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 - **Auth Guard on Translator Save:** Added `isAuthenticated` guard to `/api/translator/save` for defense-in-depth consistency @@ -1483,7 +1601,7 @@ We identified that **155 community PRs** across the entire project history (from - **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). -### 📚 Documentation +### التوثيق - **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. - **Context Relay Delivery Notes:** Documented the current architecture, runtime flow, and Codex-focused scope in the feature docs, changelog, and agent guidance. @@ -1559,7 +1677,7 @@ We identified that **155 community PRs** across the entire project history (from ## [3.5.3] - 2026-04-07 -### Security +### الأمان - **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. - **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. @@ -1575,7 +1693,7 @@ We identified that **155 community PRs** across the entire project history (from - **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. -### Documentation +### التوثيق - **I18n Engine:** Synchronized and pushed deep Machine Translation updates across all 32 natively-supported languages (682 translation nodes aligned). @@ -1736,7 +1854,7 @@ We identified that **155 community PRs** across the entire project history (from ## [3.4.8] — 2026-04-03 -### Security +### الأمان - Fully remediated all outstanding Github Advanced Security (CodeQL) findings and Dependabot alerts. - Fixed insecure randomness vulnerabilities by migrating from `Math.random` to `crypto.randomUUID()`. @@ -1748,7 +1866,7 @@ We identified that **155 community PRs** across the entire project history (from ## [3.4.7] — 2026-04-03 -### Features +### الميزات - Added `Cryptography` node to Monitoring and MCP health checks (#798) - Hardened model-catalog route permissions mapping (`/models`) (#781) @@ -1764,7 +1882,7 @@ We identified that **155 community PRs** across the entire project history (from - Fixed MCP standalone module-resolution (`ERR_MODULE_NOT_FOUND`) via `esbuild` (#936) - Fixed NVIDIA NIM routing credential resolution alias mismatch (#931) -### Security +### الأمان - Added safe strict input boundary protection against raw `shell: true` remote-code execution injections. @@ -2011,7 +2129,7 @@ We identified that **155 community PRs** across the entire project history (from ## [3.4.0] - 2026-03-31 -### 🚀 Features +### الميزات - **Subscription Utilization Analytics:** Added quota snapshot time-series tracking, Provider Utilization and Combo Health tabs with recharts visualizations, and corresponding API endpoints (#847) - **SQLite Backup Control:** New `OMNIROUTE_DISABLE_AUTO_BACKUP` env flag to disable automatic SQLite backups (#846) @@ -2063,7 +2181,7 @@ We identified that **155 community PRs** across the entire project history (from ## [3.3.8] - 2026-03-30 -### 🚀 Features +### الميزات - **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) - **Qoder Integration:** Native integration for Qoder AI natively replacing the legacy iFlow platform mappings (#660) @@ -2889,7 +3007,7 @@ We identified that **155 community PRs** across the entire project history (from - **NaN tokens in Claude Code / client responses (#617):** - `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 -### 🔒 Security +### الأمان - Updated `yaml` package to fix stack overflow vulnerability (GHSA-48c2-rrv3-qjmp) @@ -3565,7 +3683,7 @@ docker pull diegosouzapw/omniroute:3.0.0 - **SVG fallback**: `ProviderIcon` component updated with 4-tier strategy: Lobehub → PNG → SVG → Generic icon - **Agents fingerprinting**: Synced with CLI tools — added droid, openclaw, copilot, opencode to fingerprint list (14 total) -### 🔒 Security +### الأمان - **CVE fix**: Resolved dompurify XSS vulnerability (GHSA-v2wj-7wpq-c8vv) via npm overrides forcing `dompurify@^3.3.2` - `npm audit` now reports **0 vulnerabilities** @@ -3928,7 +4046,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **#510** — Windows: MSYS2/Git-Bash paths (`/c/Program Files/...`) are now normalized to `C:\Program Files\...` - **#492** — `omniroute` CLI now detects `mise`/`nvm` when `app/server.js` is missing and shows targeted fix -### 📖 Documentation +### التوثيق - **#513** — Docker password reset: `INITIAL_PASSWORD` env var workaround documented - **#520** — pnpm: `pnpm approve-builds better-sqlite3` documented @@ -4025,7 +4143,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **feat(executors/cloudflare-ai)**: New `CloudflareAIExecutor` — dynamic URL construction requires `accountId` in provider credentials - **feat(executors)**: Register `pollinations`, `pol`, `cloudflare-ai`, `cf` executor mappings -### 📝 Documentation +### التوثيق - **docs(readme)**: Expanded free combo stack to 11 providers ($0 forever) - **docs(readme)**: Added 4 new free provider sections (LongCat, Pollinations, Cloudflare AI, Scaleway) with model tables @@ -4177,7 +4295,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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). -### Features +### الميزات - **"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. @@ -4205,7 +4323,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Merge PR #494 (MiniMax role fix), fix KIRO MITM dashboard, triage 8 issues. -### Features +### الميزات - **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. - **roleNormalizer**: `normalizeDeveloperRole()` now accepts `preserveDeveloperRole` parameter with tri-state behavior (undefined=keep, true=keep, false=convert). @@ -4261,7 +4379,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Gemini CLI deprecation, VM guide i18n fix, dependabot security fix, provider schema expansion. -### Features +### الميزات - **Gemini CLI Deprecation** (#462): Mark `gemini-cli` provider as deprecated with warning — Google restricts third-party OAuth usage from March 2026 - **Provider Schema** (#462): Expand Zod validation with `deprecated`, `deprecationReason`, `hasFree`, `freeNote`, `authHint`, `apiHint` optional fields @@ -4270,7 +4388,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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) -### Security +### الأمان - **deps**: Bump `flatted` 3.3.3 → 3.4.2 — fixes CWE-1321 prototype pollution (#484, @dependabot) @@ -4290,7 +4408,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Czech i18n, SSE protocol fix, VM guide translation. -### Features +### الميزات - **Czech Language** (#482): Full Czech (cs) i18n — 22 docs, 2606 UI strings, language switcher updates (@zen0bit) - **VM Deployment Guide**: Translated from Portuguese to English as the source document (@zen0bit) @@ -4309,7 +4427,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: 2 merged PRs, model aliases routing fix, log export, and issue triage. -### Features +### الميزات - **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) @@ -4329,7 +4447,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Five community PRs — streaming call log fixes, Kiro compatibility, cache token analytics, Chinese translation, and configurable tool call IDs. -### ✨ Features +### الميزات - **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) - **feat(providers)**: Per-model configurable 9-char tool call ID normalization (Mistral-style) — only models with the option enabled get truncated IDs (#470) @@ -4359,7 +4477,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Bailian Coding Plan provider with editable base URLs, plus community contributions for Alibaba Cloud and Kimi Coding. -### ✨ Features +### الميزات - **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) - **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) @@ -4374,7 +4492,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Two new community-contributed providers (Alibaba Cloud Coding, Kimi Coding API-key) and Docker pino fix. -### ✨ Features +### الميزات - **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) - **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) @@ -4399,7 +4517,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Codex responses subpath passthrough natively supported, Windows MITM crash fixed, and Combos agent schemas adjusted. -### ✨ Features +### الميزات - **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) @@ -4439,7 +4557,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **fix(budget)**: "Save Limits" no longer returns 422 — `warningThreshold` is now correctly sent as fraction (0–1) instead of percentage (0–100) (#451) - **fix(combos)**: `` internal cache tag is now stripped before forwarding requests to providers, preventing cache session breaks (#454) -### ✨ Features +### الميزات - **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) @@ -4495,7 +4613,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Search Tools dashboard, i18n fixes, Copilot limits, Serper validation fix. -### 🚀 Features +### الميزات - **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) - New route: `/dashboard/search-tools` @@ -4595,7 +4713,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - DB migration: `request_type` column on `call_logs` for non-chat request tracking - Zod validation (`v1SearchSchema`), auth-gated, cost recorded via `recordCost()` -### 🔒 Security +### الأمان - **deps**: Next.js 16.1.6 → 16.1.7 — fixes 6 CVEs: - **Critical**: CVE-2026-29057 (HTTP request smuggling via http-proxy) @@ -4725,7 +4843,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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**: New `request_detail_logs` table with 500-entry ring-buffer trigger, opt-in via settings toggle -### ✨ Features +### الميزات - **feat(combo)**: System Message Override per Combo (#399 — `system_message` field replaces or injects system prompt before forwarding to provider) - **feat(combo)**: Tool Filter Regex per Combo (#399 — `tool_filter_regex` keeps only tools matching pattern; supports OpenAI + Anthropic formats) @@ -4740,7 +4858,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: SSE improvements, local provider_nodes extensions, proxy registry, Claude passthrough fixes. -### ✨ Features +### الميزات - **feat(health)**: Background health check for local `provider_nodes` with exponential backoff (30s→300s) and `Promise.allSettled` to avoid blocking (#423, @Regis-RCR) - **feat(embeddings)**: Route `/v1/embeddings` to local `provider_nodes` — `buildDynamicEmbeddingProvider()` with hostname validation (#422, @Regis-RCR) @@ -4882,7 +5000,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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 - **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). -### ✨ Features +### الميزات - **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) @@ -4912,7 +5030,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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) - **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) -### ✨ Features +### الميزات - **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) - **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. @@ -4971,7 +5089,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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) - **fix(logs)**: Request log table is now readable in light mode — status badges, token counts, and combo tags use adaptive `dark:` color classes (#378) -### ✨ Features +### الميزات - **feat(kiro)**: Kiro credit tracking added to usage fetcher — queries `getUserCredits` from AWS CodeWhisperer endpoint (#337) @@ -5372,7 +5490,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > **Major release** — Free Stack ecosystem, transcription playground overhaul, 44+ providers, comprehensive free tier documentation, and UI improvements across the board. -### ✨ Features +### الميزات - **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. - **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. @@ -5383,7 +5501,7 @@ OmniRoute now automatically refreshes model lists for connected providers every ## [2.3.16] - 2026-03-13 -### 📖 Documentation +### التوثيق - **README: 44+ Providers** — Updated all 3 occurrences of "36+ providers" to "44+" reflecting the actual codebase count (44 providers in providers.ts) - **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. @@ -5393,7 +5511,7 @@ OmniRoute now automatically refreshes model lists for connected providers every ## [2.3.15] - 2026-03-13 -### ✨ Features +### الميزات - **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. - **i18n — autoCombo section**: Added 20 new translation keys for the Auto-Combo dashboard (`title`, `status`, `modePack`, `providerScores`, `factorTierPriority`, etc.) to all 30 language files. diff --git a/docs/i18n/bg/CHANGELOG.md b/docs/i18n/bg/CHANGELOG.md index 733161f130..faeb5ab80c 100644 --- a/docs/i18n/bg/CHANGELOG.md +++ b/docs/i18n/bg/CHANGELOG.md @@ -10,30 +10,148 @@ ### ✨ New Features -- **feat(antigravity):** integrate Antigravity provider with dynamic `maxOutputTokens` calculation (bumping to `thinkingBudget + 1`) and standard Cloud Code envelope payload sanitization (#2055, #2063) +- **feat(antigravity):** integrate Antigravity provider with dynamic `maxOutputTokens` calculation, identity fingerprinting overhaul, and Cloud Code envelope payload sanitization (#2055, #2063) - **feat(gemini-cli):** add custom projectId support for Gemini CLI transport (UI, DB, executor) (#1991) +- **feat(providers):** add KIE media provider support with dynamic polling, text models, and expanded video models catalog +- **feat(providers):** add Z.AI provider support with GLM quota handling and new quota labels +- **feat(providers):** add 9 new free AI providers — LLM7, Lepton, Kluster, UncloseAI, BazaarLink, Completions, Enally, FreeTheAi (#2096) +- **feat(providers):** batch delete provider connections via checkbox multi-select (#2094) +- **feat(cursor):** full OpenAI parity — tool calls, streaming, and session management (#2082) +- **feat(cli):** comprehensive CLI enhancement suite with 20+ new commands including `omniroute providers`, `omniroute combos`, `omniroute doctor` (#2074) +- **feat(cli):** add modular CLI setup and provider management commands (#2046) +- **feat(mcp):** add DeepSeek quota and limit monitoring feature (#2089) +- **feat(circuit-breaker):** classify 429 errors and apply per-kind cooldowns (#2116) +- **feat(multi):** manifest-aware tier routing — W1-W4 complete (#2014) +- **feat(combos):** add reset-aware routing strategy for quota-based providers +- **feat(combo):** add context_length input field to combo edit form (#2047) +- **feat(chat):** dynamic tool limit detection with proactive truncation (#2061) +- **feat(sse):** refresh Claude OAuth wire image to claude-cli/2.1.131 (#2011) +- **feat(github):** add `targetFormat: openai-responses` to all GitHub models (#2122) +- **feat(api):** allow configuration via API calls — open management routes to Bearer keys with manage scope (#2103) +- **feat(api):** update API bridge proxy timeout to 600,000ms (#2019) +- **feat(usage):** add service tier breakdown, codex fast service tier analytics, and account for fast tier +- **feat(chat):** add `STREAM_READINESS_TIMEOUT_MS` and integrate into chat handling +- **feat(combo):** add `fallbackDelayMs` to combo configuration and related settings +- **feat(chat):** enhance error handling for semaphore capacity with fallback logic +- **feat(qdrant):** embedding model discovery (#2086) +- **feat(auth):** per-session sticky routing for Codex (#1887) +- **feat(inworld):** enhance Inworld TTS support (#2123) ### 🐛 Bug Fixes +- **fix(pricing):** make `getPricingForModel` fully case-insensitive to ensure custom prices correctly reflect in new incoming requests cost calculations +- **fix(gemini):** prevent `functionDeclarations` from being dropped by the sanitizer when `googleSearch` tool is present (#2077) +- **fix(pollinations):** add `jsonMode: true` flag in the request transformation to enforce correct JSON structure from Pollinations API (#2109) +- **fix(docker):** update Dockerfile to copy `/docs` directory during build ensuring API catalog availability at runtime (#2083) +- **fix(docker):** include OpenAPI spec in runtime image (#2007) +- **fix(providers):** strip OpenAI-specific fields in Kiro translator to prevent 400 errors (#2037) +- **fix(kiro):** normalize tool-use payloads to prevent 400 errors from agents (#2104) +- **fix(kiro):** merge adjacent user history turns after role normalization (#2105) +- **fix(ui):** resolve text contrast issues for zero-config warning banner in light mode (#2050) +- **fix(core):** inject global system prompt correctly into downstream chat completions pipeline (#2080) +- **fix(core):** restore Claude Code adaptive thinking defaults and resolve audio transcription CORS regression +- **fix(routing):** add missing v1beta rewrites to next.config to resolve 404 on Gemini models endpoint (#2102) +- **fix(routing):** fix bare GPT-5.5 routing for Codex-only installations (#2054) +- **fix(routing):** add fuzzy auto-combo routing for `auto/*` model prefix (#2010) - **fix(cache):** optimize cache_control preservation logic and explicitly align tool schema with upstream Claude Code expectations - **fix(db):** preserve legacy SQLite database path on Windows to prevent data loss (#1973) +- **fix(db):** reduce hot-path persistence overhead (#2039) +- **fix(db):** resolve migration conflict by renumbering overlapping migration entries (#2041) - **fix(settings):** resolve model alias persistence double stringification preventing UI updates (#2018) - **fix(routing):** dynamically filter bare model auto-resolution by active provider connections to prevent dead-routing (#2029) - **fix(embeddings):** add Google Gemini embeddings compatibility via OpenAI-compatible endpoint mapping (#2006) +- **fix(sse):** prevent Claude OAuth multi-account correlation via metadata.user_id (#2053) +- **fix(sse):** prevent Claude Code identity cloak overrides and fix fallback resilience (#2053) +- **fix(sse):** classify hour quota errors as QUOTA_EXHAUSTED (#2119) +- **fix(sse):** fix CC-compatible streaming bridge (#2118) +- **fix(antigravity):** sanitize Claude Cloud Code payloads (#2090) +- **fix(antigravity):** add duplex half for streaming bodies +- **fix(antigravity):** align identity protocol and behavior with official AM +- **fix(chatgpt-web):** plumb proxy through to native tls-client (#2022, #2023) +- **fix(codex):** expose native model IDs in catalog (#2012) +- **fix(glm):** add dedicated coding transport (#2087) +- **fix(compression):** support Responses input and expand Spanish compression rules (#2028) +- **fix(catalog):** auto-calculate combo context_length from target model limits (#2030) +- **fix(api):** fix usage analytics and API key identity (#2008, #2092) +- **fix(api-key):** allow Unicode letters in API key name validation (#1996) +- **fix(auth):** allow bootstrap without password (#2048) +- **fix(proxy):** clean up proxy page redundancy and fix 1proxy sync empty body error (#2052) +- **fix(dashboard):** resolve Unknown plan display in Provider Limits +- **fix(usage):** add extensible CURRENCY_SYMBOLS mapping for deepseek currencies +- **fix(runtime):** harden timer handling and model pricing fallback +- **fix(i18n):** complete Simplified Chinese translations (#2115) +- **fix(mitm):** add Linux cert install and skip sudo password when root (#1999) +- **fix(mitm):** prevent stub from loading at runtime via bypass module - **fix:** remove Anthropic-Beta header from non-Anthropic providers to fix identity contamination (#1989) - **fix(cli):** resolve .env loading failure for global npm installations +- **fix(export):** exclude telemetry/usage-history tables from JSON config backups by default to prevent unbounded file growth (#2125) +- **fix:** Follow OpenAI specification, handle throttling in batch and fix UI (#2045) -### 🔒 Security +### Сигурност +- **fix(security):** remediate CodeQL vulnerabilities (ReDoS, cryptographic bias, stack trace exposure, and weak password hashing) (#216, #215, #211, #208, #206, #210) - **fix(security):** remediate regex validation backtracking path in core compression cleanup (#1990) - **fix(core):** harden input handling and stabilization for prompt compression edge cases +### Документация + +- **docs:** add competitive marketing tables and SEO/AEO optimizations to README (#2091) +- **docs:** refresh providers, model catalogs, and docs for v3.8.0 (#2088) +- **docs:** update Claude MD and update GLM-CN max context to 200k (#2027) +- **docs(env):** add `GITLAB_DUO_OAUTH_CLIENT_ID` to `.env.example` (#2031) + ### 🧹 Chores & Maintenance - **chore(providers):** prune redundant local provider icon assets in favor of `@lobehub/icons` web fonts (#1992) +- **chore(providers):** remove deprecated models (#2033) +- **deps:** bump `fast-uri` from 3.1.0 to 3.1.2 (#2078) +- **deps:** bump `hono` from 4.12.14 to 4.12.18 (#2079) - **ci:** skip SonarCloud scan on main pushes to optimize CI time - **test:** stabilize cooldown abort coverage case in integration testing +### 🏆 v3.8.0 Community Contributors + +Thank you to all **38 community contributors** who made v3.8.0 possible! 🎉 + +| Contributor | PRs | Contributions | +| :--------------------------------------------------------- | :-: | :------------------------------------------------------------ | +| [@oyi77](https://github.com/oyi77) | 7 | #2010, #2014, #2041, #2052, #2061, #2074, #2091, #2094, #2096 | +| [@backryun](https://github.com/backryun) | 4 | #1992, #2033, #2088, #2123 | +| [@dhaern](https://github.com/dhaern) | 4 | #2028, #2039, #2087, #2090 | +| [@Tentoxa](https://github.com/Tentoxa) | 2 | #2011, #2053 | +| [@wauputr4](https://github.com/wauputr4) | 2 | #2009, #2046 | +| [@payne0420](https://github.com/payne0420) | 1 | #2082 | +| [@Tr0sT](https://github.com/Tr0sT) | 1 | #2012 | +| [@AveryanAlex](https://github.com/AveryanAlex) | 1 | #2008 | +| [@nickwizard](https://github.com/nickwizard) | 1 | #1991 | +| [@rodrigogbbr-stack](https://github.com/rodrigogbbr-stack) | 1 | #1996 | +| [@NekoMonci12](https://github.com/NekoMonci12) | 1 | #1999 | +| [@congvc-dev](https://github.com/congvc-dev) | 1 | #2004 | +| [@tatsster](https://github.com/tatsster) | 1 | #2007 | +| [@xssdem](https://github.com/xssdem) | 1 | #2023 | +| [@bypanghu](https://github.com/bypanghu) | 1 | #2027 | +| [@herjarsa](https://github.com/herjarsa) | 1 | #2030 | +| [@wucm667](https://github.com/wucm667) | 1 | #2031 | +| [@hartmark](https://github.com/hartmark) | 1 | #2045 | +| [@ddarkr](https://github.com/ddarkr) | 1 | #2047 | +| [@tces1](https://github.com/tces1) | 1 | #2048 | +| [@guanbear](https://github.com/guanbear) | 1 | #2054 | +| [@Gi99lin](https://github.com/Gi99lin) | 1 | #2055 | +| [@ivan-mezentsev](https://github.com/ivan-mezentsev) | 1 | #2063 | +| [@JxnLexn](https://github.com/JxnLexn) | 1 | #2019 | +| [@yoviarpauzi](https://github.com/yoviarpauzi) | 1 | #2092 | +| [@rafacpti23](https://github.com/rafacpti23) | 1 | #2086 | +| [@gleber](https://github.com/gleber) | 1 | #2103 | +| [@rilham97](https://github.com/rilham97) | 1 | #2104 | +| [@Gioxaa](https://github.com/Gioxaa) | 1 | #2105 | +| [@boa-z](https://github.com/boa-z) | 1 | #2115 | +| [@eleata](https://github.com/eleata) | 1 | #2116 | +| [@rdself](https://github.com/rdself) | 1 | #2118 | +| [@clousky2020](https://github.com/clousky2020) | 1 | #2119 | +| [@abhinavjnu](https://github.com/abhinavjnu) | 1 | #2122 | +| [@HoaPham98](https://github.com/HoaPham98) | 1 | #2089 | +| [@05dunski](https://github.com/05dunski) | 1 | #1978 (cherry-picked) | + ## [3.7.9] — 2026-05-03 ### ✨ New Features @@ -102,7 +220,7 @@ - **chore(provider):** Add reka models list (#1956 — thanks @backryun) - **chore(model):** Update new models, Delete Deprecated models (#1949 — thanks @backryun) -### 📝 Documentation +### Документация - **docs(compression):** document RTK+Caveman stacked savings ranges @@ -201,7 +319,7 @@ - **feat(db):** auto-restore probe-failed database on startup to prevent data loss after failed upgrades (#1810) - **feat(analytics):** add cost-based usage insights and activity streaks in the analytics dashboard -### 🔒 Security +### Сигурност - **fix(security):** resolve ReDoS vulnerability in Codex executor regex patterns (#1797, #1789) @@ -354,7 +472,7 @@ We identified that **155 community PRs** across the entire project history (from - **feat(proxy):** implement bulk proxy import via pipe-delimited parser with update-or-create (upsert) logic and real-time preview table - **feat(pwa):** add fullscreen installable PWA with manifest, service worker, and cross-platform app icons (#1728) -### 🔒 Security +### Сигурност - **security:** replace insecure `Math.random` with `crypto.getRandomValues` for fallback UUID generation to resolve CodeQL CWE-338 finding (#182) @@ -519,7 +637,7 @@ We identified that **155 community PRs** across the entire project history (from - **fix(transport):** Prevent memory bloat and database exhaustion from large, fragmented streaming responses. Implemented `ByteQueue` in `kiro.ts` for zero-copy binary accumulation, refactored `antigravity.ts` for incremental SSE parsing, and enforced a strict 512KB tiered truncation limit (`MAX_CALL_LOG_ARTIFACT_BYTES`) on stream request logs and call artifacts (#1647). - **chore(ci):** Update build environment dependencies — bump Node to `24.15.0`, `actions/checkout@v6`, `docker/build-push-action@v7`, pin `actions/setup-python` to major tag (#1646 — thanks @backryun). -### 📝 Documentation +### Документация - **docs(env):** Add `OMNIROUTE_ALLOW_PRIVATE_PROVIDER_URLS` to `.env.example` with documentation for LM Studio and other local provider use cases (#1623). @@ -669,7 +787,7 @@ We identified that **155 community PRs** across the entire project history (from - **test(next):** Align transpile package expectations for the Next.js standalone build. - **test(ci):** Fix CI-only test failures from environment differences — clear `INITIAL_PASSWORD` and `JWT_SECRET` in integration tests, handle `XDG_CONFIG_HOME` for guide-settings tests. -### 📚 Documentation +### Документация - **docs:** Update the root changelog with all release-branch changes through 2026-04-24, including PRs #1544, #1555, #1551, #1550, #1548, #1547, #1541, #1538, #1536, and #1527. - **docs:** Fix broken README and localized documentation links. (#1536) @@ -811,7 +929,7 @@ We identified that **155 community PRs** across the entire project history (from - **feat(providers):** Expand image provider registry with extended model support including SD3.5, FLUX, and DALL-E 3 HD configurations - **feat(combos):** Add new routing strategies and full i18n support for agent features section across 31 languages -### 🔒 Security +### Сигурност - **security:** Resolve 18 GitHub CodeQL scan alerts including ReDoS, incomplete sanitization, and bad HTML filtering regexp patterns - **fix(auth):** Seal privilege escalation vector by enforcing JWT session checking exclusively on `/api/keys` management endpoints (#1353) @@ -1078,7 +1196,7 @@ We identified that **155 community PRs** across the entire project history (from - **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 - **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 -### 🔒 Security +### Сигурност - **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 - **Auth Guard on Translator Save:** Added `isAuthenticated` guard to `/api/translator/save` for defense-in-depth consistency @@ -1483,7 +1601,7 @@ We identified that **155 community PRs** across the entire project history (from - **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). -### 📚 Documentation +### Документация - **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. - **Context Relay Delivery Notes:** Documented the current architecture, runtime flow, and Codex-focused scope in the feature docs, changelog, and agent guidance. @@ -1559,7 +1677,7 @@ We identified that **155 community PRs** across the entire project history (from ## [3.5.3] - 2026-04-07 -### Security +### Сигурност - **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. - **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. @@ -1575,7 +1693,7 @@ We identified that **155 community PRs** across the entire project history (from - **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. -### Documentation +### Документация - **I18n Engine:** Synchronized and pushed deep Machine Translation updates across all 32 natively-supported languages (682 translation nodes aligned). @@ -1736,7 +1854,7 @@ We identified that **155 community PRs** across the entire project history (from ## [3.4.8] — 2026-04-03 -### Security +### Сигурност - Fully remediated all outstanding Github Advanced Security (CodeQL) findings and Dependabot alerts. - Fixed insecure randomness vulnerabilities by migrating from `Math.random` to `crypto.randomUUID()`. @@ -1748,7 +1866,7 @@ We identified that **155 community PRs** across the entire project history (from ## [3.4.7] — 2026-04-03 -### Features +### Функции - Added `Cryptography` node to Monitoring and MCP health checks (#798) - Hardened model-catalog route permissions mapping (`/models`) (#781) @@ -1764,7 +1882,7 @@ We identified that **155 community PRs** across the entire project history (from - Fixed MCP standalone module-resolution (`ERR_MODULE_NOT_FOUND`) via `esbuild` (#936) - Fixed NVIDIA NIM routing credential resolution alias mismatch (#931) -### Security +### Сигурност - Added safe strict input boundary protection against raw `shell: true` remote-code execution injections. @@ -2011,7 +2129,7 @@ We identified that **155 community PRs** across the entire project history (from ## [3.4.0] - 2026-03-31 -### 🚀 Features +### Функции - **Subscription Utilization Analytics:** Added quota snapshot time-series tracking, Provider Utilization and Combo Health tabs with recharts visualizations, and corresponding API endpoints (#847) - **SQLite Backup Control:** New `OMNIROUTE_DISABLE_AUTO_BACKUP` env flag to disable automatic SQLite backups (#846) @@ -2063,7 +2181,7 @@ We identified that **155 community PRs** across the entire project history (from ## [3.3.8] - 2026-03-30 -### 🚀 Features +### Функции - **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) - **Qoder Integration:** Native integration for Qoder AI natively replacing the legacy iFlow platform mappings (#660) @@ -2889,7 +3007,7 @@ We identified that **155 community PRs** across the entire project history (from - **NaN tokens in Claude Code / client responses (#617):** - `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 -### 🔒 Security +### Сигурност - Updated `yaml` package to fix stack overflow vulnerability (GHSA-48c2-rrv3-qjmp) @@ -3565,7 +3683,7 @@ docker pull diegosouzapw/omniroute:3.0.0 - **SVG fallback**: `ProviderIcon` component updated with 4-tier strategy: Lobehub → PNG → SVG → Generic icon - **Agents fingerprinting**: Synced with CLI tools — added droid, openclaw, copilot, opencode to fingerprint list (14 total) -### 🔒 Security +### Сигурност - **CVE fix**: Resolved dompurify XSS vulnerability (GHSA-v2wj-7wpq-c8vv) via npm overrides forcing `dompurify@^3.3.2` - `npm audit` now reports **0 vulnerabilities** @@ -3928,7 +4046,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **#510** — Windows: MSYS2/Git-Bash paths (`/c/Program Files/...`) are now normalized to `C:\Program Files\...` - **#492** — `omniroute` CLI now detects `mise`/`nvm` when `app/server.js` is missing and shows targeted fix -### 📖 Documentation +### Документация - **#513** — Docker password reset: `INITIAL_PASSWORD` env var workaround documented - **#520** — pnpm: `pnpm approve-builds better-sqlite3` documented @@ -4025,7 +4143,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **feat(executors/cloudflare-ai)**: New `CloudflareAIExecutor` — dynamic URL construction requires `accountId` in provider credentials - **feat(executors)**: Register `pollinations`, `pol`, `cloudflare-ai`, `cf` executor mappings -### 📝 Documentation +### Документация - **docs(readme)**: Expanded free combo stack to 11 providers ($0 forever) - **docs(readme)**: Added 4 new free provider sections (LongCat, Pollinations, Cloudflare AI, Scaleway) with model tables @@ -4177,7 +4295,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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). -### Features +### Функции - **"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. @@ -4205,7 +4323,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Merge PR #494 (MiniMax role fix), fix KIRO MITM dashboard, triage 8 issues. -### Features +### Функции - **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. - **roleNormalizer**: `normalizeDeveloperRole()` now accepts `preserveDeveloperRole` parameter with tri-state behavior (undefined=keep, true=keep, false=convert). @@ -4261,7 +4379,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Gemini CLI deprecation, VM guide i18n fix, dependabot security fix, provider schema expansion. -### Features +### Функции - **Gemini CLI Deprecation** (#462): Mark `gemini-cli` provider as deprecated with warning — Google restricts third-party OAuth usage from March 2026 - **Provider Schema** (#462): Expand Zod validation with `deprecated`, `deprecationReason`, `hasFree`, `freeNote`, `authHint`, `apiHint` optional fields @@ -4270,7 +4388,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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) -### Security +### Сигурност - **deps**: Bump `flatted` 3.3.3 → 3.4.2 — fixes CWE-1321 prototype pollution (#484, @dependabot) @@ -4290,7 +4408,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Czech i18n, SSE protocol fix, VM guide translation. -### Features +### Функции - **Czech Language** (#482): Full Czech (cs) i18n — 22 docs, 2606 UI strings, language switcher updates (@zen0bit) - **VM Deployment Guide**: Translated from Portuguese to English as the source document (@zen0bit) @@ -4309,7 +4427,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: 2 merged PRs, model aliases routing fix, log export, and issue triage. -### Features +### Функции - **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) @@ -4329,7 +4447,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Five community PRs — streaming call log fixes, Kiro compatibility, cache token analytics, Chinese translation, and configurable tool call IDs. -### ✨ Features +### Функции - **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) - **feat(providers)**: Per-model configurable 9-char tool call ID normalization (Mistral-style) — only models with the option enabled get truncated IDs (#470) @@ -4359,7 +4477,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Bailian Coding Plan provider with editable base URLs, plus community contributions for Alibaba Cloud and Kimi Coding. -### ✨ Features +### Функции - **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) - **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) @@ -4374,7 +4492,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Two new community-contributed providers (Alibaba Cloud Coding, Kimi Coding API-key) and Docker pino fix. -### ✨ Features +### Функции - **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) - **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) @@ -4399,7 +4517,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Codex responses subpath passthrough natively supported, Windows MITM crash fixed, and Combos agent schemas adjusted. -### ✨ Features +### Функции - **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) @@ -4439,7 +4557,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **fix(budget)**: "Save Limits" no longer returns 422 — `warningThreshold` is now correctly sent as fraction (0–1) instead of percentage (0–100) (#451) - **fix(combos)**: `` internal cache tag is now stripped before forwarding requests to providers, preventing cache session breaks (#454) -### ✨ Features +### Функции - **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) @@ -4495,7 +4613,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Search Tools dashboard, i18n fixes, Copilot limits, Serper validation fix. -### 🚀 Features +### Функции - **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) - New route: `/dashboard/search-tools` @@ -4595,7 +4713,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - DB migration: `request_type` column on `call_logs` for non-chat request tracking - Zod validation (`v1SearchSchema`), auth-gated, cost recorded via `recordCost()` -### 🔒 Security +### Сигурност - **deps**: Next.js 16.1.6 → 16.1.7 — fixes 6 CVEs: - **Critical**: CVE-2026-29057 (HTTP request smuggling via http-proxy) @@ -4725,7 +4843,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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**: New `request_detail_logs` table with 500-entry ring-buffer trigger, opt-in via settings toggle -### ✨ Features +### Функции - **feat(combo)**: System Message Override per Combo (#399 — `system_message` field replaces or injects system prompt before forwarding to provider) - **feat(combo)**: Tool Filter Regex per Combo (#399 — `tool_filter_regex` keeps only tools matching pattern; supports OpenAI + Anthropic formats) @@ -4740,7 +4858,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: SSE improvements, local provider_nodes extensions, proxy registry, Claude passthrough fixes. -### ✨ Features +### Функции - **feat(health)**: Background health check for local `provider_nodes` with exponential backoff (30s→300s) and `Promise.allSettled` to avoid blocking (#423, @Regis-RCR) - **feat(embeddings)**: Route `/v1/embeddings` to local `provider_nodes` — `buildDynamicEmbeddingProvider()` with hostname validation (#422, @Regis-RCR) @@ -4882,7 +5000,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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 - **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). -### ✨ Features +### Функции - **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) @@ -4912,7 +5030,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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) - **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) -### ✨ Features +### Функции - **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) - **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. @@ -4971,7 +5089,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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) - **fix(logs)**: Request log table is now readable in light mode — status badges, token counts, and combo tags use adaptive `dark:` color classes (#378) -### ✨ Features +### Функции - **feat(kiro)**: Kiro credit tracking added to usage fetcher — queries `getUserCredits` from AWS CodeWhisperer endpoint (#337) @@ -5372,7 +5490,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > **Major release** — Free Stack ecosystem, transcription playground overhaul, 44+ providers, comprehensive free tier documentation, and UI improvements across the board. -### ✨ Features +### Функции - **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. - **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. @@ -5383,7 +5501,7 @@ OmniRoute now automatically refreshes model lists for connected providers every ## [2.3.16] - 2026-03-13 -### 📖 Documentation +### Документация - **README: 44+ Providers** — Updated all 3 occurrences of "36+ providers" to "44+" reflecting the actual codebase count (44 providers in providers.ts) - **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. @@ -5393,7 +5511,7 @@ OmniRoute now automatically refreshes model lists for connected providers every ## [2.3.15] - 2026-03-13 -### ✨ Features +### Функции - **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. - **i18n — autoCombo section**: Added 20 new translation keys for the Auto-Combo dashboard (`title`, `status`, `modePack`, `providerScores`, `factorTierPriority`, etc.) to all 30 language files. diff --git a/docs/i18n/bn/CHANGELOG.md b/docs/i18n/bn/CHANGELOG.md index dabaada362..ff78a5c462 100644 --- a/docs/i18n/bn/CHANGELOG.md +++ b/docs/i18n/bn/CHANGELOG.md @@ -10,30 +10,148 @@ ### ✨ New Features -- **feat(antigravity):** integrate Antigravity provider with dynamic `maxOutputTokens` calculation (bumping to `thinkingBudget + 1`) and standard Cloud Code envelope payload sanitization (#2055, #2063) +- **feat(antigravity):** integrate Antigravity provider with dynamic `maxOutputTokens` calculation, identity fingerprinting overhaul, and Cloud Code envelope payload sanitization (#2055, #2063) - **feat(gemini-cli):** add custom projectId support for Gemini CLI transport (UI, DB, executor) (#1991) +- **feat(providers):** add KIE media provider support with dynamic polling, text models, and expanded video models catalog +- **feat(providers):** add Z.AI provider support with GLM quota handling and new quota labels +- **feat(providers):** add 9 new free AI providers — LLM7, Lepton, Kluster, UncloseAI, BazaarLink, Completions, Enally, FreeTheAi (#2096) +- **feat(providers):** batch delete provider connections via checkbox multi-select (#2094) +- **feat(cursor):** full OpenAI parity — tool calls, streaming, and session management (#2082) +- **feat(cli):** comprehensive CLI enhancement suite with 20+ new commands including `omniroute providers`, `omniroute combos`, `omniroute doctor` (#2074) +- **feat(cli):** add modular CLI setup and provider management commands (#2046) +- **feat(mcp):** add DeepSeek quota and limit monitoring feature (#2089) +- **feat(circuit-breaker):** classify 429 errors and apply per-kind cooldowns (#2116) +- **feat(multi):** manifest-aware tier routing — W1-W4 complete (#2014) +- **feat(combos):** add reset-aware routing strategy for quota-based providers +- **feat(combo):** add context_length input field to combo edit form (#2047) +- **feat(chat):** dynamic tool limit detection with proactive truncation (#2061) +- **feat(sse):** refresh Claude OAuth wire image to claude-cli/2.1.131 (#2011) +- **feat(github):** add `targetFormat: openai-responses` to all GitHub models (#2122) +- **feat(api):** allow configuration via API calls — open management routes to Bearer keys with manage scope (#2103) +- **feat(api):** update API bridge proxy timeout to 600,000ms (#2019) +- **feat(usage):** add service tier breakdown, codex fast service tier analytics, and account for fast tier +- **feat(chat):** add `STREAM_READINESS_TIMEOUT_MS` and integrate into chat handling +- **feat(combo):** add `fallbackDelayMs` to combo configuration and related settings +- **feat(chat):** enhance error handling for semaphore capacity with fallback logic +- **feat(qdrant):** embedding model discovery (#2086) +- **feat(auth):** per-session sticky routing for Codex (#1887) +- **feat(inworld):** enhance Inworld TTS support (#2123) ### 🐛 Bug Fixes +- **fix(pricing):** make `getPricingForModel` fully case-insensitive to ensure custom prices correctly reflect in new incoming requests cost calculations +- **fix(gemini):** prevent `functionDeclarations` from being dropped by the sanitizer when `googleSearch` tool is present (#2077) +- **fix(pollinations):** add `jsonMode: true` flag in the request transformation to enforce correct JSON structure from Pollinations API (#2109) +- **fix(docker):** update Dockerfile to copy `/docs` directory during build ensuring API catalog availability at runtime (#2083) +- **fix(docker):** include OpenAPI spec in runtime image (#2007) +- **fix(providers):** strip OpenAI-specific fields in Kiro translator to prevent 400 errors (#2037) +- **fix(kiro):** normalize tool-use payloads to prevent 400 errors from agents (#2104) +- **fix(kiro):** merge adjacent user history turns after role normalization (#2105) +- **fix(ui):** resolve text contrast issues for zero-config warning banner in light mode (#2050) +- **fix(core):** inject global system prompt correctly into downstream chat completions pipeline (#2080) +- **fix(core):** restore Claude Code adaptive thinking defaults and resolve audio transcription CORS regression +- **fix(routing):** add missing v1beta rewrites to next.config to resolve 404 on Gemini models endpoint (#2102) +- **fix(routing):** fix bare GPT-5.5 routing for Codex-only installations (#2054) +- **fix(routing):** add fuzzy auto-combo routing for `auto/*` model prefix (#2010) - **fix(cache):** optimize cache_control preservation logic and explicitly align tool schema with upstream Claude Code expectations - **fix(db):** preserve legacy SQLite database path on Windows to prevent data loss (#1973) +- **fix(db):** reduce hot-path persistence overhead (#2039) +- **fix(db):** resolve migration conflict by renumbering overlapping migration entries (#2041) - **fix(settings):** resolve model alias persistence double stringification preventing UI updates (#2018) - **fix(routing):** dynamically filter bare model auto-resolution by active provider connections to prevent dead-routing (#2029) - **fix(embeddings):** add Google Gemini embeddings compatibility via OpenAI-compatible endpoint mapping (#2006) +- **fix(sse):** prevent Claude OAuth multi-account correlation via metadata.user_id (#2053) +- **fix(sse):** prevent Claude Code identity cloak overrides and fix fallback resilience (#2053) +- **fix(sse):** classify hour quota errors as QUOTA_EXHAUSTED (#2119) +- **fix(sse):** fix CC-compatible streaming bridge (#2118) +- **fix(antigravity):** sanitize Claude Cloud Code payloads (#2090) +- **fix(antigravity):** add duplex half for streaming bodies +- **fix(antigravity):** align identity protocol and behavior with official AM +- **fix(chatgpt-web):** plumb proxy through to native tls-client (#2022, #2023) +- **fix(codex):** expose native model IDs in catalog (#2012) +- **fix(glm):** add dedicated coding transport (#2087) +- **fix(compression):** support Responses input and expand Spanish compression rules (#2028) +- **fix(catalog):** auto-calculate combo context_length from target model limits (#2030) +- **fix(api):** fix usage analytics and API key identity (#2008, #2092) +- **fix(api-key):** allow Unicode letters in API key name validation (#1996) +- **fix(auth):** allow bootstrap without password (#2048) +- **fix(proxy):** clean up proxy page redundancy and fix 1proxy sync empty body error (#2052) +- **fix(dashboard):** resolve Unknown plan display in Provider Limits +- **fix(usage):** add extensible CURRENCY_SYMBOLS mapping for deepseek currencies +- **fix(runtime):** harden timer handling and model pricing fallback +- **fix(i18n):** complete Simplified Chinese translations (#2115) +- **fix(mitm):** add Linux cert install and skip sudo password when root (#1999) +- **fix(mitm):** prevent stub from loading at runtime via bypass module - **fix:** remove Anthropic-Beta header from non-Anthropic providers to fix identity contamination (#1989) - **fix(cli):** resolve .env loading failure for global npm installations +- **fix(export):** exclude telemetry/usage-history tables from JSON config backups by default to prevent unbounded file growth (#2125) +- **fix:** Follow OpenAI specification, handle throttling in batch and fix UI (#2045) -### 🔒 Security +### Seguridad +- **fix(security):** remediate CodeQL vulnerabilities (ReDoS, cryptographic bias, stack trace exposure, and weak password hashing) (#216, #215, #211, #208, #206, #210) - **fix(security):** remediate regex validation backtracking path in core compression cleanup (#1990) - **fix(core):** harden input handling and stabilization for prompt compression edge cases +### Documentación + +- **docs:** add competitive marketing tables and SEO/AEO optimizations to README (#2091) +- **docs:** refresh providers, model catalogs, and docs for v3.8.0 (#2088) +- **docs:** update Claude MD and update GLM-CN max context to 200k (#2027) +- **docs(env):** add `GITLAB_DUO_OAUTH_CLIENT_ID` to `.env.example` (#2031) + ### 🧹 Chores & Maintenance - **chore(providers):** prune redundant local provider icon assets in favor of `@lobehub/icons` web fonts (#1992) +- **chore(providers):** remove deprecated models (#2033) +- **deps:** bump `fast-uri` from 3.1.0 to 3.1.2 (#2078) +- **deps:** bump `hono` from 4.12.14 to 4.12.18 (#2079) - **ci:** skip SonarCloud scan on main pushes to optimize CI time - **test:** stabilize cooldown abort coverage case in integration testing +### 🏆 v3.8.0 Community Contributors + +Thank you to all **38 community contributors** who made v3.8.0 possible! 🎉 + +| Contributor | PRs | Contributions | +| :--------------------------------------------------------- | :-: | :------------------------------------------------------------ | +| [@oyi77](https://github.com/oyi77) | 7 | #2010, #2014, #2041, #2052, #2061, #2074, #2091, #2094, #2096 | +| [@backryun](https://github.com/backryun) | 4 | #1992, #2033, #2088, #2123 | +| [@dhaern](https://github.com/dhaern) | 4 | #2028, #2039, #2087, #2090 | +| [@Tentoxa](https://github.com/Tentoxa) | 2 | #2011, #2053 | +| [@wauputr4](https://github.com/wauputr4) | 2 | #2009, #2046 | +| [@payne0420](https://github.com/payne0420) | 1 | #2082 | +| [@Tr0sT](https://github.com/Tr0sT) | 1 | #2012 | +| [@AveryanAlex](https://github.com/AveryanAlex) | 1 | #2008 | +| [@nickwizard](https://github.com/nickwizard) | 1 | #1991 | +| [@rodrigogbbr-stack](https://github.com/rodrigogbbr-stack) | 1 | #1996 | +| [@NekoMonci12](https://github.com/NekoMonci12) | 1 | #1999 | +| [@congvc-dev](https://github.com/congvc-dev) | 1 | #2004 | +| [@tatsster](https://github.com/tatsster) | 1 | #2007 | +| [@xssdem](https://github.com/xssdem) | 1 | #2023 | +| [@bypanghu](https://github.com/bypanghu) | 1 | #2027 | +| [@herjarsa](https://github.com/herjarsa) | 1 | #2030 | +| [@wucm667](https://github.com/wucm667) | 1 | #2031 | +| [@hartmark](https://github.com/hartmark) | 1 | #2045 | +| [@ddarkr](https://github.com/ddarkr) | 1 | #2047 | +| [@tces1](https://github.com/tces1) | 1 | #2048 | +| [@guanbear](https://github.com/guanbear) | 1 | #2054 | +| [@Gi99lin](https://github.com/Gi99lin) | 1 | #2055 | +| [@ivan-mezentsev](https://github.com/ivan-mezentsev) | 1 | #2063 | +| [@JxnLexn](https://github.com/JxnLexn) | 1 | #2019 | +| [@yoviarpauzi](https://github.com/yoviarpauzi) | 1 | #2092 | +| [@rafacpti23](https://github.com/rafacpti23) | 1 | #2086 | +| [@gleber](https://github.com/gleber) | 1 | #2103 | +| [@rilham97](https://github.com/rilham97) | 1 | #2104 | +| [@Gioxaa](https://github.com/Gioxaa) | 1 | #2105 | +| [@boa-z](https://github.com/boa-z) | 1 | #2115 | +| [@eleata](https://github.com/eleata) | 1 | #2116 | +| [@rdself](https://github.com/rdself) | 1 | #2118 | +| [@clousky2020](https://github.com/clousky2020) | 1 | #2119 | +| [@abhinavjnu](https://github.com/abhinavjnu) | 1 | #2122 | +| [@HoaPham98](https://github.com/HoaPham98) | 1 | #2089 | +| [@05dunski](https://github.com/05dunski) | 1 | #1978 (cherry-picked) | + ## [3.7.9] — 2026-05-03 ### ✨ New Features @@ -102,7 +220,7 @@ - **chore(provider):** Add reka models list (#1956 — thanks @backryun) - **chore(model):** Update new models, Delete Deprecated models (#1949 — thanks @backryun) -### 📝 Documentation +### Documentación - **docs(compression):** document RTK+Caveman stacked savings ranges @@ -201,7 +319,7 @@ - **feat(db):** auto-restore probe-failed database on startup to prevent data loss after failed upgrades (#1810) - **feat(analytics):** add cost-based usage insights and activity streaks in the analytics dashboard -### 🔒 Security +### Seguridad - **fix(security):** resolve ReDoS vulnerability in Codex executor regex patterns (#1797, #1789) @@ -354,7 +472,7 @@ We identified that **155 community PRs** across the entire project history (from - **feat(proxy):** implement bulk proxy import via pipe-delimited parser with update-or-create (upsert) logic and real-time preview table - **feat(pwa):** add fullscreen installable PWA with manifest, service worker, and cross-platform app icons (#1728) -### 🔒 Security +### Seguridad - **security:** replace insecure `Math.random` with `crypto.getRandomValues` for fallback UUID generation to resolve CodeQL CWE-338 finding (#182) @@ -519,7 +637,7 @@ We identified that **155 community PRs** across the entire project history (from - **fix(transport):** Prevent memory bloat and database exhaustion from large, fragmented streaming responses. Implemented `ByteQueue` in `kiro.ts` for zero-copy binary accumulation, refactored `antigravity.ts` for incremental SSE parsing, and enforced a strict 512KB tiered truncation limit (`MAX_CALL_LOG_ARTIFACT_BYTES`) on stream request logs and call artifacts (#1647). - **chore(ci):** Update build environment dependencies — bump Node to `24.15.0`, `actions/checkout@v6`, `docker/build-push-action@v7`, pin `actions/setup-python` to major tag (#1646 — thanks @backryun). -### 📝 Documentation +### Documentación - **docs(env):** Add `OMNIROUTE_ALLOW_PRIVATE_PROVIDER_URLS` to `.env.example` with documentation for LM Studio and other local provider use cases (#1623). @@ -669,7 +787,7 @@ We identified that **155 community PRs** across the entire project history (from - **test(next):** Align transpile package expectations for the Next.js standalone build. - **test(ci):** Fix CI-only test failures from environment differences — clear `INITIAL_PASSWORD` and `JWT_SECRET` in integration tests, handle `XDG_CONFIG_HOME` for guide-settings tests. -### 📚 Documentation +### Documentación - **docs:** Update the root changelog with all release-branch changes through 2026-04-24, including PRs #1544, #1555, #1551, #1550, #1548, #1547, #1541, #1538, #1536, and #1527. - **docs:** Fix broken README and localized documentation links. (#1536) @@ -811,7 +929,7 @@ We identified that **155 community PRs** across the entire project history (from - **feat(providers):** Expand image provider registry with extended model support including SD3.5, FLUX, and DALL-E 3 HD configurations - **feat(combos):** Add new routing strategies and full i18n support for agent features section across 31 languages -### 🔒 Security +### Seguridad - **security:** Resolve 18 GitHub CodeQL scan alerts including ReDoS, incomplete sanitization, and bad HTML filtering regexp patterns - **fix(auth):** Seal privilege escalation vector by enforcing JWT session checking exclusively on `/api/keys` management endpoints (#1353) @@ -1078,7 +1196,7 @@ We identified that **155 community PRs** across the entire project history (from - **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 - **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 -### 🔒 Security +### Seguridad - **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 - **Auth Guard on Translator Save:** Added `isAuthenticated` guard to `/api/translator/save` for defense-in-depth consistency @@ -1483,7 +1601,7 @@ We identified that **155 community PRs** across the entire project history (from - **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). -### 📚 Documentation +### Documentació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. - **Context Relay Delivery Notes:** Documented the current architecture, runtime flow, and Codex-focused scope in the feature docs, changelog, and agent guidance. @@ -1559,7 +1677,7 @@ We identified that **155 community PRs** across the entire project history (from ## [3.5.3] - 2026-04-07 -### Security +### Seguridad - **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. - **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. @@ -1575,7 +1693,7 @@ We identified that **155 community PRs** across the entire project history (from - **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. -### Documentation +### Documentación - **I18n Engine:** Synchronized and pushed deep Machine Translation updates across all 32 natively-supported languages (682 translation nodes aligned). @@ -1736,7 +1854,7 @@ We identified that **155 community PRs** across the entire project history (from ## [3.4.8] — 2026-04-03 -### Security +### Seguridad - Fully remediated all outstanding Github Advanced Security (CodeQL) findings and Dependabot alerts. - Fixed insecure randomness vulnerabilities by migrating from `Math.random` to `crypto.randomUUID()`. @@ -1748,7 +1866,7 @@ We identified that **155 community PRs** across the entire project history (from ## [3.4.7] — 2026-04-03 -### Features +### Funcionalidades - Added `Cryptography` node to Monitoring and MCP health checks (#798) - Hardened model-catalog route permissions mapping (`/models`) (#781) @@ -1764,7 +1882,7 @@ We identified that **155 community PRs** across the entire project history (from - Fixed MCP standalone module-resolution (`ERR_MODULE_NOT_FOUND`) via `esbuild` (#936) - Fixed NVIDIA NIM routing credential resolution alias mismatch (#931) -### Security +### Seguridad - Added safe strict input boundary protection against raw `shell: true` remote-code execution injections. @@ -2011,7 +2129,7 @@ We identified that **155 community PRs** across the entire project history (from ## [3.4.0] - 2026-03-31 -### 🚀 Features +### Funcionalidades - **Subscription Utilization Analytics:** Added quota snapshot time-series tracking, Provider Utilization and Combo Health tabs with recharts visualizations, and corresponding API endpoints (#847) - **SQLite Backup Control:** New `OMNIROUTE_DISABLE_AUTO_BACKUP` env flag to disable automatic SQLite backups (#846) @@ -2063,7 +2181,7 @@ We identified that **155 community PRs** across the entire project history (from ## [3.3.8] - 2026-03-30 -### 🚀 Features +### Funcionalidades - **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) - **Qoder Integration:** Native integration for Qoder AI natively replacing the legacy iFlow platform mappings (#660) @@ -2889,7 +3007,7 @@ We identified that **155 community PRs** across the entire project history (from - **NaN tokens in Claude Code / client responses (#617):** - `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 -### 🔒 Security +### Seguridad - Updated `yaml` package to fix stack overflow vulnerability (GHSA-48c2-rrv3-qjmp) @@ -3565,7 +3683,7 @@ docker pull diegosouzapw/omniroute:3.0.0 - **SVG fallback**: `ProviderIcon` component updated with 4-tier strategy: Lobehub → PNG → SVG → Generic icon - **Agents fingerprinting**: Synced with CLI tools — added droid, openclaw, copilot, opencode to fingerprint list (14 total) -### 🔒 Security +### Seguridad - **CVE fix**: Resolved dompurify XSS vulnerability (GHSA-v2wj-7wpq-c8vv) via npm overrides forcing `dompurify@^3.3.2` - `npm audit` now reports **0 vulnerabilities** @@ -3928,7 +4046,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **#510** — Windows: MSYS2/Git-Bash paths (`/c/Program Files/...`) are now normalized to `C:\Program Files\...` - **#492** — `omniroute` CLI now detects `mise`/`nvm` when `app/server.js` is missing and shows targeted fix -### 📖 Documentation +### Documentación - **#513** — Docker password reset: `INITIAL_PASSWORD` env var workaround documented - **#520** — pnpm: `pnpm approve-builds better-sqlite3` documented @@ -4025,7 +4143,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **feat(executors/cloudflare-ai)**: New `CloudflareAIExecutor` — dynamic URL construction requires `accountId` in provider credentials - **feat(executors)**: Register `pollinations`, `pol`, `cloudflare-ai`, `cf` executor mappings -### 📝 Documentation +### Documentación - **docs(readme)**: Expanded free combo stack to 11 providers ($0 forever) - **docs(readme)**: Added 4 new free provider sections (LongCat, Pollinations, Cloudflare AI, Scaleway) with model tables @@ -4177,7 +4295,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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). -### Features +### Funcionalidades - **"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. @@ -4205,7 +4323,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Merge PR #494 (MiniMax role fix), fix KIRO MITM dashboard, triage 8 issues. -### Features +### Funcionalidades - **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. - **roleNormalizer**: `normalizeDeveloperRole()` now accepts `preserveDeveloperRole` parameter with tri-state behavior (undefined=keep, true=keep, false=convert). @@ -4261,7 +4379,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Gemini CLI deprecation, VM guide i18n fix, dependabot security fix, provider schema expansion. -### Features +### Funcionalidades - **Gemini CLI Deprecation** (#462): Mark `gemini-cli` provider as deprecated with warning — Google restricts third-party OAuth usage from March 2026 - **Provider Schema** (#462): Expand Zod validation with `deprecated`, `deprecationReason`, `hasFree`, `freeNote`, `authHint`, `apiHint` optional fields @@ -4270,7 +4388,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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) -### Security +### Seguridad - **deps**: Bump `flatted` 3.3.3 → 3.4.2 — fixes CWE-1321 prototype pollution (#484, @dependabot) @@ -4290,7 +4408,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Czech i18n, SSE protocol fix, VM guide translation. -### Features +### Funcionalidades - **Czech Language** (#482): Full Czech (cs) i18n — 22 docs, 2606 UI strings, language switcher updates (@zen0bit) - **VM Deployment Guide**: Translated from Portuguese to English as the source document (@zen0bit) @@ -4309,7 +4427,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: 2 merged PRs, model aliases routing fix, log export, and issue triage. -### Features +### Funcionalidades - **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) @@ -4329,7 +4447,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Five community PRs — streaming call log fixes, Kiro compatibility, cache token analytics, Chinese translation, and configurable tool call IDs. -### ✨ Features +### Funcionalidades - **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) - **feat(providers)**: Per-model configurable 9-char tool call ID normalization (Mistral-style) — only models with the option enabled get truncated IDs (#470) @@ -4359,7 +4477,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Bailian Coding Plan provider with editable base URLs, plus community contributions for Alibaba Cloud and Kimi Coding. -### ✨ Features +### Funcionalidades - **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) - **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) @@ -4374,7 +4492,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Two new community-contributed providers (Alibaba Cloud Coding, Kimi Coding API-key) and Docker pino fix. -### ✨ Features +### Funcionalidades - **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) - **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) @@ -4399,7 +4517,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Codex responses subpath passthrough natively supported, Windows MITM crash fixed, and Combos agent schemas adjusted. -### ✨ Features +### Funcionalidades - **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) @@ -4439,7 +4557,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **fix(budget)**: "Save Limits" no longer returns 422 — `warningThreshold` is now correctly sent as fraction (0–1) instead of percentage (0–100) (#451) - **fix(combos)**: `` internal cache tag is now stripped before forwarding requests to providers, preventing cache session breaks (#454) -### ✨ Features +### Funcionalidades - **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) @@ -4495,7 +4613,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Search Tools dashboard, i18n fixes, Copilot limits, Serper validation fix. -### 🚀 Features +### Funcionalidades - **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) - New route: `/dashboard/search-tools` @@ -4595,7 +4713,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - DB migration: `request_type` column on `call_logs` for non-chat request tracking - Zod validation (`v1SearchSchema`), auth-gated, cost recorded via `recordCost()` -### 🔒 Security +### Seguridad - **deps**: Next.js 16.1.6 → 16.1.7 — fixes 6 CVEs: - **Critical**: CVE-2026-29057 (HTTP request smuggling via http-proxy) @@ -4725,7 +4843,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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**: New `request_detail_logs` table with 500-entry ring-buffer trigger, opt-in via settings toggle -### ✨ Features +### Funcionalidades - **feat(combo)**: System Message Override per Combo (#399 — `system_message` field replaces or injects system prompt before forwarding to provider) - **feat(combo)**: Tool Filter Regex per Combo (#399 — `tool_filter_regex` keeps only tools matching pattern; supports OpenAI + Anthropic formats) @@ -4740,7 +4858,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: SSE improvements, local provider_nodes extensions, proxy registry, Claude passthrough fixes. -### ✨ Features +### Funcionalidades - **feat(health)**: Background health check for local `provider_nodes` with exponential backoff (30s→300s) and `Promise.allSettled` to avoid blocking (#423, @Regis-RCR) - **feat(embeddings)**: Route `/v1/embeddings` to local `provider_nodes` — `buildDynamicEmbeddingProvider()` with hostname validation (#422, @Regis-RCR) @@ -4882,7 +5000,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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 - **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). -### ✨ Features +### Funcionalidades - **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) @@ -4912,7 +5030,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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) - **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) -### ✨ Features +### Funcionalidades - **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) - **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. @@ -4971,7 +5089,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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) - **fix(logs)**: Request log table is now readable in light mode — status badges, token counts, and combo tags use adaptive `dark:` color classes (#378) -### ✨ Features +### Funcionalidades - **feat(kiro)**: Kiro credit tracking added to usage fetcher — queries `getUserCredits` from AWS CodeWhisperer endpoint (#337) @@ -5372,7 +5490,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > **Major release** — Free Stack ecosystem, transcription playground overhaul, 44+ providers, comprehensive free tier documentation, and UI improvements across the board. -### ✨ Features +### Funcionalidades - **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. - **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. @@ -5383,7 +5501,7 @@ OmniRoute now automatically refreshes model lists for connected providers every ## [2.3.16] - 2026-03-13 -### 📖 Documentation +### Documentación - **README: 44+ Providers** — Updated all 3 occurrences of "36+ providers" to "44+" reflecting the actual codebase count (44 providers in providers.ts) - **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. @@ -5393,7 +5511,7 @@ OmniRoute now automatically refreshes model lists for connected providers every ## [2.3.15] - 2026-03-13 -### ✨ Features +### Funcionalidades - **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. - **i18n — autoCombo section**: Added 20 new translation keys for the Auto-Combo dashboard (`title`, `status`, `modePack`, `providerScores`, `factorTierPriority`, etc.) to all 30 language files. diff --git a/docs/i18n/cs/CHANGELOG.md b/docs/i18n/cs/CHANGELOG.md index 4c54214645..81f60f41a1 100644 --- a/docs/i18n/cs/CHANGELOG.md +++ b/docs/i18n/cs/CHANGELOG.md @@ -10,30 +10,148 @@ ### ✨ New Features -- **feat(antigravity):** integrate Antigravity provider with dynamic `maxOutputTokens` calculation (bumping to `thinkingBudget + 1`) and standard Cloud Code envelope payload sanitization (#2055, #2063) +- **feat(antigravity):** integrate Antigravity provider with dynamic `maxOutputTokens` calculation, identity fingerprinting overhaul, and Cloud Code envelope payload sanitization (#2055, #2063) - **feat(gemini-cli):** add custom projectId support for Gemini CLI transport (UI, DB, executor) (#1991) +- **feat(providers):** add KIE media provider support with dynamic polling, text models, and expanded video models catalog +- **feat(providers):** add Z.AI provider support with GLM quota handling and new quota labels +- **feat(providers):** add 9 new free AI providers — LLM7, Lepton, Kluster, UncloseAI, BazaarLink, Completions, Enally, FreeTheAi (#2096) +- **feat(providers):** batch delete provider connections via checkbox multi-select (#2094) +- **feat(cursor):** full OpenAI parity — tool calls, streaming, and session management (#2082) +- **feat(cli):** comprehensive CLI enhancement suite with 20+ new commands including `omniroute providers`, `omniroute combos`, `omniroute doctor` (#2074) +- **feat(cli):** add modular CLI setup and provider management commands (#2046) +- **feat(mcp):** add DeepSeek quota and limit monitoring feature (#2089) +- **feat(circuit-breaker):** classify 429 errors and apply per-kind cooldowns (#2116) +- **feat(multi):** manifest-aware tier routing — W1-W4 complete (#2014) +- **feat(combos):** add reset-aware routing strategy for quota-based providers +- **feat(combo):** add context_length input field to combo edit form (#2047) +- **feat(chat):** dynamic tool limit detection with proactive truncation (#2061) +- **feat(sse):** refresh Claude OAuth wire image to claude-cli/2.1.131 (#2011) +- **feat(github):** add `targetFormat: openai-responses` to all GitHub models (#2122) +- **feat(api):** allow configuration via API calls — open management routes to Bearer keys with manage scope (#2103) +- **feat(api):** update API bridge proxy timeout to 600,000ms (#2019) +- **feat(usage):** add service tier breakdown, codex fast service tier analytics, and account for fast tier +- **feat(chat):** add `STREAM_READINESS_TIMEOUT_MS` and integrate into chat handling +- **feat(combo):** add `fallbackDelayMs` to combo configuration and related settings +- **feat(chat):** enhance error handling for semaphore capacity with fallback logic +- **feat(qdrant):** embedding model discovery (#2086) +- **feat(auth):** per-session sticky routing for Codex (#1887) +- **feat(inworld):** enhance Inworld TTS support (#2123) ### 🐛 Bug Fixes +- **fix(pricing):** make `getPricingForModel` fully case-insensitive to ensure custom prices correctly reflect in new incoming requests cost calculations +- **fix(gemini):** prevent `functionDeclarations` from being dropped by the sanitizer when `googleSearch` tool is present (#2077) +- **fix(pollinations):** add `jsonMode: true` flag in the request transformation to enforce correct JSON structure from Pollinations API (#2109) +- **fix(docker):** update Dockerfile to copy `/docs` directory during build ensuring API catalog availability at runtime (#2083) +- **fix(docker):** include OpenAPI spec in runtime image (#2007) +- **fix(providers):** strip OpenAI-specific fields in Kiro translator to prevent 400 errors (#2037) +- **fix(kiro):** normalize tool-use payloads to prevent 400 errors from agents (#2104) +- **fix(kiro):** merge adjacent user history turns after role normalization (#2105) +- **fix(ui):** resolve text contrast issues for zero-config warning banner in light mode (#2050) +- **fix(core):** inject global system prompt correctly into downstream chat completions pipeline (#2080) +- **fix(core):** restore Claude Code adaptive thinking defaults and resolve audio transcription CORS regression +- **fix(routing):** add missing v1beta rewrites to next.config to resolve 404 on Gemini models endpoint (#2102) +- **fix(routing):** fix bare GPT-5.5 routing for Codex-only installations (#2054) +- **fix(routing):** add fuzzy auto-combo routing for `auto/*` model prefix (#2010) - **fix(cache):** optimize cache_control preservation logic and explicitly align tool schema with upstream Claude Code expectations - **fix(db):** preserve legacy SQLite database path on Windows to prevent data loss (#1973) +- **fix(db):** reduce hot-path persistence overhead (#2039) +- **fix(db):** resolve migration conflict by renumbering overlapping migration entries (#2041) - **fix(settings):** resolve model alias persistence double stringification preventing UI updates (#2018) - **fix(routing):** dynamically filter bare model auto-resolution by active provider connections to prevent dead-routing (#2029) - **fix(embeddings):** add Google Gemini embeddings compatibility via OpenAI-compatible endpoint mapping (#2006) +- **fix(sse):** prevent Claude OAuth multi-account correlation via metadata.user_id (#2053) +- **fix(sse):** prevent Claude Code identity cloak overrides and fix fallback resilience (#2053) +- **fix(sse):** classify hour quota errors as QUOTA_EXHAUSTED (#2119) +- **fix(sse):** fix CC-compatible streaming bridge (#2118) +- **fix(antigravity):** sanitize Claude Cloud Code payloads (#2090) +- **fix(antigravity):** add duplex half for streaming bodies +- **fix(antigravity):** align identity protocol and behavior with official AM +- **fix(chatgpt-web):** plumb proxy through to native tls-client (#2022, #2023) +- **fix(codex):** expose native model IDs in catalog (#2012) +- **fix(glm):** add dedicated coding transport (#2087) +- **fix(compression):** support Responses input and expand Spanish compression rules (#2028) +- **fix(catalog):** auto-calculate combo context_length from target model limits (#2030) +- **fix(api):** fix usage analytics and API key identity (#2008, #2092) +- **fix(api-key):** allow Unicode letters in API key name validation (#1996) +- **fix(auth):** allow bootstrap without password (#2048) +- **fix(proxy):** clean up proxy page redundancy and fix 1proxy sync empty body error (#2052) +- **fix(dashboard):** resolve Unknown plan display in Provider Limits +- **fix(usage):** add extensible CURRENCY_SYMBOLS mapping for deepseek currencies +- **fix(runtime):** harden timer handling and model pricing fallback +- **fix(i18n):** complete Simplified Chinese translations (#2115) +- **fix(mitm):** add Linux cert install and skip sudo password when root (#1999) +- **fix(mitm):** prevent stub from loading at runtime via bypass module - **fix:** remove Anthropic-Beta header from non-Anthropic providers to fix identity contamination (#1989) - **fix(cli):** resolve .env loading failure for global npm installations +- **fix(export):** exclude telemetry/usage-history tables from JSON config backups by default to prevent unbounded file growth (#2125) +- **fix:** Follow OpenAI specification, handle throttling in batch and fix UI (#2045) -### 🔒 Security +### Bezpečnost +- **fix(security):** remediate CodeQL vulnerabilities (ReDoS, cryptographic bias, stack trace exposure, and weak password hashing) (#216, #215, #211, #208, #206, #210) - **fix(security):** remediate regex validation backtracking path in core compression cleanup (#1990) - **fix(core):** harden input handling and stabilization for prompt compression edge cases +### Dokumentace + +- **docs:** add competitive marketing tables and SEO/AEO optimizations to README (#2091) +- **docs:** refresh providers, model catalogs, and docs for v3.8.0 (#2088) +- **docs:** update Claude MD and update GLM-CN max context to 200k (#2027) +- **docs(env):** add `GITLAB_DUO_OAUTH_CLIENT_ID` to `.env.example` (#2031) + ### 🧹 Chores & Maintenance - **chore(providers):** prune redundant local provider icon assets in favor of `@lobehub/icons` web fonts (#1992) +- **chore(providers):** remove deprecated models (#2033) +- **deps:** bump `fast-uri` from 3.1.0 to 3.1.2 (#2078) +- **deps:** bump `hono` from 4.12.14 to 4.12.18 (#2079) - **ci:** skip SonarCloud scan on main pushes to optimize CI time - **test:** stabilize cooldown abort coverage case in integration testing +### 🏆 v3.8.0 Community Contributors + +Thank you to all **38 community contributors** who made v3.8.0 possible! 🎉 + +| Contributor | PRs | Contributions | +| :--------------------------------------------------------- | :-: | :------------------------------------------------------------ | +| [@oyi77](https://github.com/oyi77) | 7 | #2010, #2014, #2041, #2052, #2061, #2074, #2091, #2094, #2096 | +| [@backryun](https://github.com/backryun) | 4 | #1992, #2033, #2088, #2123 | +| [@dhaern](https://github.com/dhaern) | 4 | #2028, #2039, #2087, #2090 | +| [@Tentoxa](https://github.com/Tentoxa) | 2 | #2011, #2053 | +| [@wauputr4](https://github.com/wauputr4) | 2 | #2009, #2046 | +| [@payne0420](https://github.com/payne0420) | 1 | #2082 | +| [@Tr0sT](https://github.com/Tr0sT) | 1 | #2012 | +| [@AveryanAlex](https://github.com/AveryanAlex) | 1 | #2008 | +| [@nickwizard](https://github.com/nickwizard) | 1 | #1991 | +| [@rodrigogbbr-stack](https://github.com/rodrigogbbr-stack) | 1 | #1996 | +| [@NekoMonci12](https://github.com/NekoMonci12) | 1 | #1999 | +| [@congvc-dev](https://github.com/congvc-dev) | 1 | #2004 | +| [@tatsster](https://github.com/tatsster) | 1 | #2007 | +| [@xssdem](https://github.com/xssdem) | 1 | #2023 | +| [@bypanghu](https://github.com/bypanghu) | 1 | #2027 | +| [@herjarsa](https://github.com/herjarsa) | 1 | #2030 | +| [@wucm667](https://github.com/wucm667) | 1 | #2031 | +| [@hartmark](https://github.com/hartmark) | 1 | #2045 | +| [@ddarkr](https://github.com/ddarkr) | 1 | #2047 | +| [@tces1](https://github.com/tces1) | 1 | #2048 | +| [@guanbear](https://github.com/guanbear) | 1 | #2054 | +| [@Gi99lin](https://github.com/Gi99lin) | 1 | #2055 | +| [@ivan-mezentsev](https://github.com/ivan-mezentsev) | 1 | #2063 | +| [@JxnLexn](https://github.com/JxnLexn) | 1 | #2019 | +| [@yoviarpauzi](https://github.com/yoviarpauzi) | 1 | #2092 | +| [@rafacpti23](https://github.com/rafacpti23) | 1 | #2086 | +| [@gleber](https://github.com/gleber) | 1 | #2103 | +| [@rilham97](https://github.com/rilham97) | 1 | #2104 | +| [@Gioxaa](https://github.com/Gioxaa) | 1 | #2105 | +| [@boa-z](https://github.com/boa-z) | 1 | #2115 | +| [@eleata](https://github.com/eleata) | 1 | #2116 | +| [@rdself](https://github.com/rdself) | 1 | #2118 | +| [@clousky2020](https://github.com/clousky2020) | 1 | #2119 | +| [@abhinavjnu](https://github.com/abhinavjnu) | 1 | #2122 | +| [@HoaPham98](https://github.com/HoaPham98) | 1 | #2089 | +| [@05dunski](https://github.com/05dunski) | 1 | #1978 (cherry-picked) | + ## [3.7.9] — 2026-05-03 ### ✨ New Features @@ -102,7 +220,7 @@ - **chore(provider):** Add reka models list (#1956 — thanks @backryun) - **chore(model):** Update new models, Delete Deprecated models (#1949 — thanks @backryun) -### 📝 Documentation +### Dokumentace - **docs(compression):** document RTK+Caveman stacked savings ranges @@ -201,7 +319,7 @@ - **feat(db):** auto-restore probe-failed database on startup to prevent data loss after failed upgrades (#1810) - **feat(analytics):** add cost-based usage insights and activity streaks in the analytics dashboard -### 🔒 Security +### Bezpečnost - **fix(security):** resolve ReDoS vulnerability in Codex executor regex patterns (#1797, #1789) @@ -354,7 +472,7 @@ We identified that **155 community PRs** across the entire project history (from - **feat(proxy):** implement bulk proxy import via pipe-delimited parser with update-or-create (upsert) logic and real-time preview table - **feat(pwa):** add fullscreen installable PWA with manifest, service worker, and cross-platform app icons (#1728) -### 🔒 Security +### Bezpečnost - **security:** replace insecure `Math.random` with `crypto.getRandomValues` for fallback UUID generation to resolve CodeQL CWE-338 finding (#182) @@ -519,7 +637,7 @@ We identified that **155 community PRs** across the entire project history (from - **fix(transport):** Prevent memory bloat and database exhaustion from large, fragmented streaming responses. Implemented `ByteQueue` in `kiro.ts` for zero-copy binary accumulation, refactored `antigravity.ts` for incremental SSE parsing, and enforced a strict 512KB tiered truncation limit (`MAX_CALL_LOG_ARTIFACT_BYTES`) on stream request logs and call artifacts (#1647). - **chore(ci):** Update build environment dependencies — bump Node to `24.15.0`, `actions/checkout@v6`, `docker/build-push-action@v7`, pin `actions/setup-python` to major tag (#1646 — thanks @backryun). -### 📝 Documentation +### Dokumentace - **docs(env):** Add `OMNIROUTE_ALLOW_PRIVATE_PROVIDER_URLS` to `.env.example` with documentation for LM Studio and other local provider use cases (#1623). @@ -669,7 +787,7 @@ We identified that **155 community PRs** across the entire project history (from - **test(next):** Align transpile package expectations for the Next.js standalone build. - **test(ci):** Fix CI-only test failures from environment differences — clear `INITIAL_PASSWORD` and `JWT_SECRET` in integration tests, handle `XDG_CONFIG_HOME` for guide-settings tests. -### 📚 Documentation +### Dokumentace - **docs:** Update the root changelog with all release-branch changes through 2026-04-24, including PRs #1544, #1555, #1551, #1550, #1548, #1547, #1541, #1538, #1536, and #1527. - **docs:** Fix broken README and localized documentation links. (#1536) @@ -811,7 +929,7 @@ We identified that **155 community PRs** across the entire project history (from - **feat(providers):** Expand image provider registry with extended model support including SD3.5, FLUX, and DALL-E 3 HD configurations - **feat(combos):** Add new routing strategies and full i18n support for agent features section across 31 languages -### 🔒 Security +### Bezpečnost - **security:** Resolve 18 GitHub CodeQL scan alerts including ReDoS, incomplete sanitization, and bad HTML filtering regexp patterns - **fix(auth):** Seal privilege escalation vector by enforcing JWT session checking exclusively on `/api/keys` management endpoints (#1353) @@ -1078,7 +1196,7 @@ We identified that **155 community PRs** across the entire project history (from - **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 - **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 -### 🔒 Security +### Bezpečnost - **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 - **Auth Guard on Translator Save:** Added `isAuthenticated` guard to `/api/translator/save` for defense-in-depth consistency @@ -1483,7 +1601,7 @@ We identified that **155 community PRs** across the entire project history (from - **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). -### 📚 Documentation +### Dokumentace - **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. - **Context Relay Delivery Notes:** Documented the current architecture, runtime flow, and Codex-focused scope in the feature docs, changelog, and agent guidance. @@ -1559,7 +1677,7 @@ We identified that **155 community PRs** across the entire project history (from ## [3.5.3] - 2026-04-07 -### Security +### Bezpečnost - **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. - **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. @@ -1575,7 +1693,7 @@ We identified that **155 community PRs** across the entire project history (from - **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. -### Documentation +### Dokumentace - **I18n Engine:** Synchronized and pushed deep Machine Translation updates across all 32 natively-supported languages (682 translation nodes aligned). @@ -1736,7 +1854,7 @@ We identified that **155 community PRs** across the entire project history (from ## [3.4.8] — 2026-04-03 -### Security +### Bezpečnost - Fully remediated all outstanding Github Advanced Security (CodeQL) findings and Dependabot alerts. - Fixed insecure randomness vulnerabilities by migrating from `Math.random` to `crypto.randomUUID()`. @@ -1748,7 +1866,7 @@ We identified that **155 community PRs** across the entire project history (from ## [3.4.7] — 2026-04-03 -### Features +### Funkce - Added `Cryptography` node to Monitoring and MCP health checks (#798) - Hardened model-catalog route permissions mapping (`/models`) (#781) @@ -1764,7 +1882,7 @@ We identified that **155 community PRs** across the entire project history (from - Fixed MCP standalone module-resolution (`ERR_MODULE_NOT_FOUND`) via `esbuild` (#936) - Fixed NVIDIA NIM routing credential resolution alias mismatch (#931) -### Security +### Bezpečnost - Added safe strict input boundary protection against raw `shell: true` remote-code execution injections. @@ -2011,7 +2129,7 @@ We identified that **155 community PRs** across the entire project history (from ## [3.4.0] - 2026-03-31 -### 🚀 Features +### Funkce - **Subscription Utilization Analytics:** Added quota snapshot time-series tracking, Provider Utilization and Combo Health tabs with recharts visualizations, and corresponding API endpoints (#847) - **SQLite Backup Control:** New `OMNIROUTE_DISABLE_AUTO_BACKUP` env flag to disable automatic SQLite backups (#846) @@ -2063,7 +2181,7 @@ We identified that **155 community PRs** across the entire project history (from ## [3.3.8] - 2026-03-30 -### 🚀 Features +### Funkce - **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) - **Qoder Integration:** Native integration for Qoder AI natively replacing the legacy iFlow platform mappings (#660) @@ -2889,7 +3007,7 @@ We identified that **155 community PRs** across the entire project history (from - **NaN tokens in Claude Code / client responses (#617):** - `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 -### 🔒 Security +### Bezpečnost - Updated `yaml` package to fix stack overflow vulnerability (GHSA-48c2-rrv3-qjmp) @@ -3565,7 +3683,7 @@ docker pull diegosouzapw/omniroute:3.0.0 - **SVG fallback**: `ProviderIcon` component updated with 4-tier strategy: Lobehub → PNG → SVG → Generic icon - **Agents fingerprinting**: Synced with CLI tools — added droid, openclaw, copilot, opencode to fingerprint list (14 total) -### 🔒 Security +### Bezpečnost - **CVE fix**: Resolved dompurify XSS vulnerability (GHSA-v2wj-7wpq-c8vv) via npm overrides forcing `dompurify@^3.3.2` - `npm audit` now reports **0 vulnerabilities** @@ -3928,7 +4046,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **#510** — Windows: MSYS2/Git-Bash paths (`/c/Program Files/...`) are now normalized to `C:\Program Files\...` - **#492** — `omniroute` CLI now detects `mise`/`nvm` when `app/server.js` is missing and shows targeted fix -### 📖 Documentation +### Dokumentace - **#513** — Docker password reset: `INITIAL_PASSWORD` env var workaround documented - **#520** — pnpm: `pnpm approve-builds better-sqlite3` documented @@ -4025,7 +4143,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **feat(executors/cloudflare-ai)**: New `CloudflareAIExecutor` — dynamic URL construction requires `accountId` in provider credentials - **feat(executors)**: Register `pollinations`, `pol`, `cloudflare-ai`, `cf` executor mappings -### 📝 Documentation +### Dokumentace - **docs(readme)**: Expanded free combo stack to 11 providers ($0 forever) - **docs(readme)**: Added 4 new free provider sections (LongCat, Pollinations, Cloudflare AI, Scaleway) with model tables @@ -4177,7 +4295,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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). -### Features +### Funkce - **"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. @@ -4205,7 +4323,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Merge PR #494 (MiniMax role fix), fix KIRO MITM dashboard, triage 8 issues. -### Features +### Funkce - **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. - **roleNormalizer**: `normalizeDeveloperRole()` now accepts `preserveDeveloperRole` parameter with tri-state behavior (undefined=keep, true=keep, false=convert). @@ -4261,7 +4379,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Gemini CLI deprecation, VM guide i18n fix, dependabot security fix, provider schema expansion. -### Features +### Funkce - **Gemini CLI Deprecation** (#462): Mark `gemini-cli` provider as deprecated with warning — Google restricts third-party OAuth usage from March 2026 - **Provider Schema** (#462): Expand Zod validation with `deprecated`, `deprecationReason`, `hasFree`, `freeNote`, `authHint`, `apiHint` optional fields @@ -4270,7 +4388,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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) -### Security +### Bezpečnost - **deps**: Bump `flatted` 3.3.3 → 3.4.2 — fixes CWE-1321 prototype pollution (#484, @dependabot) @@ -4290,7 +4408,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Czech i18n, SSE protocol fix, VM guide translation. -### Features +### Funkce - **Czech Language** (#482): Full Czech (cs) i18n — 22 docs, 2606 UI strings, language switcher updates (@zen0bit) - **VM Deployment Guide**: Translated from Portuguese to English as the source document (@zen0bit) @@ -4309,7 +4427,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: 2 merged PRs, model aliases routing fix, log export, and issue triage. -### Features +### Funkce - **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) @@ -4329,7 +4447,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Five community PRs — streaming call log fixes, Kiro compatibility, cache token analytics, Chinese translation, and configurable tool call IDs. -### ✨ Features +### Funkce - **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) - **feat(providers)**: Per-model configurable 9-char tool call ID normalization (Mistral-style) — only models with the option enabled get truncated IDs (#470) @@ -4359,7 +4477,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Bailian Coding Plan provider with editable base URLs, plus community contributions for Alibaba Cloud and Kimi Coding. -### ✨ Features +### Funkce - **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) - **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) @@ -4374,7 +4492,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Two new community-contributed providers (Alibaba Cloud Coding, Kimi Coding API-key) and Docker pino fix. -### ✨ Features +### Funkce - **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) - **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) @@ -4399,7 +4517,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Codex responses subpath passthrough natively supported, Windows MITM crash fixed, and Combos agent schemas adjusted. -### ✨ Features +### Funkce - **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) @@ -4439,7 +4557,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **fix(budget)**: "Save Limits" no longer returns 422 — `warningThreshold` is now correctly sent as fraction (0–1) instead of percentage (0–100) (#451) - **fix(combos)**: `` internal cache tag is now stripped before forwarding requests to providers, preventing cache session breaks (#454) -### ✨ Features +### Funkce - **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) @@ -4495,7 +4613,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Search Tools dashboard, i18n fixes, Copilot limits, Serper validation fix. -### 🚀 Features +### Funkce - **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) - New route: `/dashboard/search-tools` @@ -4595,7 +4713,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - DB migration: `request_type` column on `call_logs` for non-chat request tracking - Zod validation (`v1SearchSchema`), auth-gated, cost recorded via `recordCost()` -### 🔒 Security +### Bezpečnost - **deps**: Next.js 16.1.6 → 16.1.7 — fixes 6 CVEs: - **Critical**: CVE-2026-29057 (HTTP request smuggling via http-proxy) @@ -4725,7 +4843,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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**: New `request_detail_logs` table with 500-entry ring-buffer trigger, opt-in via settings toggle -### ✨ Features +### Funkce - **feat(combo)**: System Message Override per Combo (#399 — `system_message` field replaces or injects system prompt before forwarding to provider) - **feat(combo)**: Tool Filter Regex per Combo (#399 — `tool_filter_regex` keeps only tools matching pattern; supports OpenAI + Anthropic formats) @@ -4740,7 +4858,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: SSE improvements, local provider_nodes extensions, proxy registry, Claude passthrough fixes. -### ✨ Features +### Funkce - **feat(health)**: Background health check for local `provider_nodes` with exponential backoff (30s→300s) and `Promise.allSettled` to avoid blocking (#423, @Regis-RCR) - **feat(embeddings)**: Route `/v1/embeddings` to local `provider_nodes` — `buildDynamicEmbeddingProvider()` with hostname validation (#422, @Regis-RCR) @@ -4882,7 +5000,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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 - **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). -### ✨ Features +### Funkce - **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) @@ -4912,7 +5030,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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) - **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) -### ✨ Features +### Funkce - **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) - **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. @@ -4971,7 +5089,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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) - **fix(logs)**: Request log table is now readable in light mode — status badges, token counts, and combo tags use adaptive `dark:` color classes (#378) -### ✨ Features +### Funkce - **feat(kiro)**: Kiro credit tracking added to usage fetcher — queries `getUserCredits` from AWS CodeWhisperer endpoint (#337) @@ -5372,7 +5490,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > **Major release** — Free Stack ecosystem, transcription playground overhaul, 44+ providers, comprehensive free tier documentation, and UI improvements across the board. -### ✨ Features +### Funkce - **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. - **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. @@ -5383,7 +5501,7 @@ OmniRoute now automatically refreshes model lists for connected providers every ## [2.3.16] - 2026-03-13 -### 📖 Documentation +### Dokumentace - **README: 44+ Providers** — Updated all 3 occurrences of "36+ providers" to "44+" reflecting the actual codebase count (44 providers in providers.ts) - **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. @@ -5393,7 +5511,7 @@ OmniRoute now automatically refreshes model lists for connected providers every ## [2.3.15] - 2026-03-13 -### ✨ Features +### Funkce - **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. - **i18n — autoCombo section**: Added 20 new translation keys for the Auto-Combo dashboard (`title`, `status`, `modePack`, `providerScores`, `factorTierPriority`, etc.) to all 30 language files. diff --git a/docs/i18n/da/CHANGELOG.md b/docs/i18n/da/CHANGELOG.md index 1ee699b1e4..9cf4b6a14a 100644 --- a/docs/i18n/da/CHANGELOG.md +++ b/docs/i18n/da/CHANGELOG.md @@ -10,30 +10,148 @@ ### ✨ New Features -- **feat(antigravity):** integrate Antigravity provider with dynamic `maxOutputTokens` calculation (bumping to `thinkingBudget + 1`) and standard Cloud Code envelope payload sanitization (#2055, #2063) +- **feat(antigravity):** integrate Antigravity provider with dynamic `maxOutputTokens` calculation, identity fingerprinting overhaul, and Cloud Code envelope payload sanitization (#2055, #2063) - **feat(gemini-cli):** add custom projectId support for Gemini CLI transport (UI, DB, executor) (#1991) +- **feat(providers):** add KIE media provider support with dynamic polling, text models, and expanded video models catalog +- **feat(providers):** add Z.AI provider support with GLM quota handling and new quota labels +- **feat(providers):** add 9 new free AI providers — LLM7, Lepton, Kluster, UncloseAI, BazaarLink, Completions, Enally, FreeTheAi (#2096) +- **feat(providers):** batch delete provider connections via checkbox multi-select (#2094) +- **feat(cursor):** full OpenAI parity — tool calls, streaming, and session management (#2082) +- **feat(cli):** comprehensive CLI enhancement suite with 20+ new commands including `omniroute providers`, `omniroute combos`, `omniroute doctor` (#2074) +- **feat(cli):** add modular CLI setup and provider management commands (#2046) +- **feat(mcp):** add DeepSeek quota and limit monitoring feature (#2089) +- **feat(circuit-breaker):** classify 429 errors and apply per-kind cooldowns (#2116) +- **feat(multi):** manifest-aware tier routing — W1-W4 complete (#2014) +- **feat(combos):** add reset-aware routing strategy for quota-based providers +- **feat(combo):** add context_length input field to combo edit form (#2047) +- **feat(chat):** dynamic tool limit detection with proactive truncation (#2061) +- **feat(sse):** refresh Claude OAuth wire image to claude-cli/2.1.131 (#2011) +- **feat(github):** add `targetFormat: openai-responses` to all GitHub models (#2122) +- **feat(api):** allow configuration via API calls — open management routes to Bearer keys with manage scope (#2103) +- **feat(api):** update API bridge proxy timeout to 600,000ms (#2019) +- **feat(usage):** add service tier breakdown, codex fast service tier analytics, and account for fast tier +- **feat(chat):** add `STREAM_READINESS_TIMEOUT_MS` and integrate into chat handling +- **feat(combo):** add `fallbackDelayMs` to combo configuration and related settings +- **feat(chat):** enhance error handling for semaphore capacity with fallback logic +- **feat(qdrant):** embedding model discovery (#2086) +- **feat(auth):** per-session sticky routing for Codex (#1887) +- **feat(inworld):** enhance Inworld TTS support (#2123) ### 🐛 Bug Fixes +- **fix(pricing):** make `getPricingForModel` fully case-insensitive to ensure custom prices correctly reflect in new incoming requests cost calculations +- **fix(gemini):** prevent `functionDeclarations` from being dropped by the sanitizer when `googleSearch` tool is present (#2077) +- **fix(pollinations):** add `jsonMode: true` flag in the request transformation to enforce correct JSON structure from Pollinations API (#2109) +- **fix(docker):** update Dockerfile to copy `/docs` directory during build ensuring API catalog availability at runtime (#2083) +- **fix(docker):** include OpenAPI spec in runtime image (#2007) +- **fix(providers):** strip OpenAI-specific fields in Kiro translator to prevent 400 errors (#2037) +- **fix(kiro):** normalize tool-use payloads to prevent 400 errors from agents (#2104) +- **fix(kiro):** merge adjacent user history turns after role normalization (#2105) +- **fix(ui):** resolve text contrast issues for zero-config warning banner in light mode (#2050) +- **fix(core):** inject global system prompt correctly into downstream chat completions pipeline (#2080) +- **fix(core):** restore Claude Code adaptive thinking defaults and resolve audio transcription CORS regression +- **fix(routing):** add missing v1beta rewrites to next.config to resolve 404 on Gemini models endpoint (#2102) +- **fix(routing):** fix bare GPT-5.5 routing for Codex-only installations (#2054) +- **fix(routing):** add fuzzy auto-combo routing for `auto/*` model prefix (#2010) - **fix(cache):** optimize cache_control preservation logic and explicitly align tool schema with upstream Claude Code expectations - **fix(db):** preserve legacy SQLite database path on Windows to prevent data loss (#1973) +- **fix(db):** reduce hot-path persistence overhead (#2039) +- **fix(db):** resolve migration conflict by renumbering overlapping migration entries (#2041) - **fix(settings):** resolve model alias persistence double stringification preventing UI updates (#2018) - **fix(routing):** dynamically filter bare model auto-resolution by active provider connections to prevent dead-routing (#2029) - **fix(embeddings):** add Google Gemini embeddings compatibility via OpenAI-compatible endpoint mapping (#2006) +- **fix(sse):** prevent Claude OAuth multi-account correlation via metadata.user_id (#2053) +- **fix(sse):** prevent Claude Code identity cloak overrides and fix fallback resilience (#2053) +- **fix(sse):** classify hour quota errors as QUOTA_EXHAUSTED (#2119) +- **fix(sse):** fix CC-compatible streaming bridge (#2118) +- **fix(antigravity):** sanitize Claude Cloud Code payloads (#2090) +- **fix(antigravity):** add duplex half for streaming bodies +- **fix(antigravity):** align identity protocol and behavior with official AM +- **fix(chatgpt-web):** plumb proxy through to native tls-client (#2022, #2023) +- **fix(codex):** expose native model IDs in catalog (#2012) +- **fix(glm):** add dedicated coding transport (#2087) +- **fix(compression):** support Responses input and expand Spanish compression rules (#2028) +- **fix(catalog):** auto-calculate combo context_length from target model limits (#2030) +- **fix(api):** fix usage analytics and API key identity (#2008, #2092) +- **fix(api-key):** allow Unicode letters in API key name validation (#1996) +- **fix(auth):** allow bootstrap without password (#2048) +- **fix(proxy):** clean up proxy page redundancy and fix 1proxy sync empty body error (#2052) +- **fix(dashboard):** resolve Unknown plan display in Provider Limits +- **fix(usage):** add extensible CURRENCY_SYMBOLS mapping for deepseek currencies +- **fix(runtime):** harden timer handling and model pricing fallback +- **fix(i18n):** complete Simplified Chinese translations (#2115) +- **fix(mitm):** add Linux cert install and skip sudo password when root (#1999) +- **fix(mitm):** prevent stub from loading at runtime via bypass module - **fix:** remove Anthropic-Beta header from non-Anthropic providers to fix identity contamination (#1989) - **fix(cli):** resolve .env loading failure for global npm installations +- **fix(export):** exclude telemetry/usage-history tables from JSON config backups by default to prevent unbounded file growth (#2125) +- **fix:** Follow OpenAI specification, handle throttling in batch and fix UI (#2045) -### 🔒 Security +### Sikkerhed +- **fix(security):** remediate CodeQL vulnerabilities (ReDoS, cryptographic bias, stack trace exposure, and weak password hashing) (#216, #215, #211, #208, #206, #210) - **fix(security):** remediate regex validation backtracking path in core compression cleanup (#1990) - **fix(core):** harden input handling and stabilization for prompt compression edge cases +### Dokumentation + +- **docs:** add competitive marketing tables and SEO/AEO optimizations to README (#2091) +- **docs:** refresh providers, model catalogs, and docs for v3.8.0 (#2088) +- **docs:** update Claude MD and update GLM-CN max context to 200k (#2027) +- **docs(env):** add `GITLAB_DUO_OAUTH_CLIENT_ID` to `.env.example` (#2031) + ### 🧹 Chores & Maintenance - **chore(providers):** prune redundant local provider icon assets in favor of `@lobehub/icons` web fonts (#1992) +- **chore(providers):** remove deprecated models (#2033) +- **deps:** bump `fast-uri` from 3.1.0 to 3.1.2 (#2078) +- **deps:** bump `hono` from 4.12.14 to 4.12.18 (#2079) - **ci:** skip SonarCloud scan on main pushes to optimize CI time - **test:** stabilize cooldown abort coverage case in integration testing +### 🏆 v3.8.0 Community Contributors + +Thank you to all **38 community contributors** who made v3.8.0 possible! 🎉 + +| Contributor | PRs | Contributions | +| :--------------------------------------------------------- | :-: | :------------------------------------------------------------ | +| [@oyi77](https://github.com/oyi77) | 7 | #2010, #2014, #2041, #2052, #2061, #2074, #2091, #2094, #2096 | +| [@backryun](https://github.com/backryun) | 4 | #1992, #2033, #2088, #2123 | +| [@dhaern](https://github.com/dhaern) | 4 | #2028, #2039, #2087, #2090 | +| [@Tentoxa](https://github.com/Tentoxa) | 2 | #2011, #2053 | +| [@wauputr4](https://github.com/wauputr4) | 2 | #2009, #2046 | +| [@payne0420](https://github.com/payne0420) | 1 | #2082 | +| [@Tr0sT](https://github.com/Tr0sT) | 1 | #2012 | +| [@AveryanAlex](https://github.com/AveryanAlex) | 1 | #2008 | +| [@nickwizard](https://github.com/nickwizard) | 1 | #1991 | +| [@rodrigogbbr-stack](https://github.com/rodrigogbbr-stack) | 1 | #1996 | +| [@NekoMonci12](https://github.com/NekoMonci12) | 1 | #1999 | +| [@congvc-dev](https://github.com/congvc-dev) | 1 | #2004 | +| [@tatsster](https://github.com/tatsster) | 1 | #2007 | +| [@xssdem](https://github.com/xssdem) | 1 | #2023 | +| [@bypanghu](https://github.com/bypanghu) | 1 | #2027 | +| [@herjarsa](https://github.com/herjarsa) | 1 | #2030 | +| [@wucm667](https://github.com/wucm667) | 1 | #2031 | +| [@hartmark](https://github.com/hartmark) | 1 | #2045 | +| [@ddarkr](https://github.com/ddarkr) | 1 | #2047 | +| [@tces1](https://github.com/tces1) | 1 | #2048 | +| [@guanbear](https://github.com/guanbear) | 1 | #2054 | +| [@Gi99lin](https://github.com/Gi99lin) | 1 | #2055 | +| [@ivan-mezentsev](https://github.com/ivan-mezentsev) | 1 | #2063 | +| [@JxnLexn](https://github.com/JxnLexn) | 1 | #2019 | +| [@yoviarpauzi](https://github.com/yoviarpauzi) | 1 | #2092 | +| [@rafacpti23](https://github.com/rafacpti23) | 1 | #2086 | +| [@gleber](https://github.com/gleber) | 1 | #2103 | +| [@rilham97](https://github.com/rilham97) | 1 | #2104 | +| [@Gioxaa](https://github.com/Gioxaa) | 1 | #2105 | +| [@boa-z](https://github.com/boa-z) | 1 | #2115 | +| [@eleata](https://github.com/eleata) | 1 | #2116 | +| [@rdself](https://github.com/rdself) | 1 | #2118 | +| [@clousky2020](https://github.com/clousky2020) | 1 | #2119 | +| [@abhinavjnu](https://github.com/abhinavjnu) | 1 | #2122 | +| [@HoaPham98](https://github.com/HoaPham98) | 1 | #2089 | +| [@05dunski](https://github.com/05dunski) | 1 | #1978 (cherry-picked) | + ## [3.7.9] — 2026-05-03 ### ✨ New Features @@ -102,7 +220,7 @@ - **chore(provider):** Add reka models list (#1956 — thanks @backryun) - **chore(model):** Update new models, Delete Deprecated models (#1949 — thanks @backryun) -### 📝 Documentation +### Dokumentation - **docs(compression):** document RTK+Caveman stacked savings ranges @@ -201,7 +319,7 @@ - **feat(db):** auto-restore probe-failed database on startup to prevent data loss after failed upgrades (#1810) - **feat(analytics):** add cost-based usage insights and activity streaks in the analytics dashboard -### 🔒 Security +### Sikkerhed - **fix(security):** resolve ReDoS vulnerability in Codex executor regex patterns (#1797, #1789) @@ -354,7 +472,7 @@ We identified that **155 community PRs** across the entire project history (from - **feat(proxy):** implement bulk proxy import via pipe-delimited parser with update-or-create (upsert) logic and real-time preview table - **feat(pwa):** add fullscreen installable PWA with manifest, service worker, and cross-platform app icons (#1728) -### 🔒 Security +### Sikkerhed - **security:** replace insecure `Math.random` with `crypto.getRandomValues` for fallback UUID generation to resolve CodeQL CWE-338 finding (#182) @@ -519,7 +637,7 @@ We identified that **155 community PRs** across the entire project history (from - **fix(transport):** Prevent memory bloat and database exhaustion from large, fragmented streaming responses. Implemented `ByteQueue` in `kiro.ts` for zero-copy binary accumulation, refactored `antigravity.ts` for incremental SSE parsing, and enforced a strict 512KB tiered truncation limit (`MAX_CALL_LOG_ARTIFACT_BYTES`) on stream request logs and call artifacts (#1647). - **chore(ci):** Update build environment dependencies — bump Node to `24.15.0`, `actions/checkout@v6`, `docker/build-push-action@v7`, pin `actions/setup-python` to major tag (#1646 — thanks @backryun). -### 📝 Documentation +### Dokumentation - **docs(env):** Add `OMNIROUTE_ALLOW_PRIVATE_PROVIDER_URLS` to `.env.example` with documentation for LM Studio and other local provider use cases (#1623). @@ -669,7 +787,7 @@ We identified that **155 community PRs** across the entire project history (from - **test(next):** Align transpile package expectations for the Next.js standalone build. - **test(ci):** Fix CI-only test failures from environment differences — clear `INITIAL_PASSWORD` and `JWT_SECRET` in integration tests, handle `XDG_CONFIG_HOME` for guide-settings tests. -### 📚 Documentation +### Dokumentation - **docs:** Update the root changelog with all release-branch changes through 2026-04-24, including PRs #1544, #1555, #1551, #1550, #1548, #1547, #1541, #1538, #1536, and #1527. - **docs:** Fix broken README and localized documentation links. (#1536) @@ -811,7 +929,7 @@ We identified that **155 community PRs** across the entire project history (from - **feat(providers):** Expand image provider registry with extended model support including SD3.5, FLUX, and DALL-E 3 HD configurations - **feat(combos):** Add new routing strategies and full i18n support for agent features section across 31 languages -### 🔒 Security +### Sikkerhed - **security:** Resolve 18 GitHub CodeQL scan alerts including ReDoS, incomplete sanitization, and bad HTML filtering regexp patterns - **fix(auth):** Seal privilege escalation vector by enforcing JWT session checking exclusively on `/api/keys` management endpoints (#1353) @@ -1078,7 +1196,7 @@ We identified that **155 community PRs** across the entire project history (from - **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 - **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 -### 🔒 Security +### Sikkerhed - **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 - **Auth Guard on Translator Save:** Added `isAuthenticated` guard to `/api/translator/save` for defense-in-depth consistency @@ -1483,7 +1601,7 @@ We identified that **155 community PRs** across the entire project history (from - **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). -### 📚 Documentation +### Dokumentation - **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. - **Context Relay Delivery Notes:** Documented the current architecture, runtime flow, and Codex-focused scope in the feature docs, changelog, and agent guidance. @@ -1559,7 +1677,7 @@ We identified that **155 community PRs** across the entire project history (from ## [3.5.3] - 2026-04-07 -### Security +### Sikkerhed - **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. - **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. @@ -1575,7 +1693,7 @@ We identified that **155 community PRs** across the entire project history (from - **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. -### Documentation +### Dokumentation - **I18n Engine:** Synchronized and pushed deep Machine Translation updates across all 32 natively-supported languages (682 translation nodes aligned). @@ -1736,7 +1854,7 @@ We identified that **155 community PRs** across the entire project history (from ## [3.4.8] — 2026-04-03 -### Security +### Sikkerhed - Fully remediated all outstanding Github Advanced Security (CodeQL) findings and Dependabot alerts. - Fixed insecure randomness vulnerabilities by migrating from `Math.random` to `crypto.randomUUID()`. @@ -1748,7 +1866,7 @@ We identified that **155 community PRs** across the entire project history (from ## [3.4.7] — 2026-04-03 -### Features +### Funktioner - Added `Cryptography` node to Monitoring and MCP health checks (#798) - Hardened model-catalog route permissions mapping (`/models`) (#781) @@ -1764,7 +1882,7 @@ We identified that **155 community PRs** across the entire project history (from - Fixed MCP standalone module-resolution (`ERR_MODULE_NOT_FOUND`) via `esbuild` (#936) - Fixed NVIDIA NIM routing credential resolution alias mismatch (#931) -### Security +### Sikkerhed - Added safe strict input boundary protection against raw `shell: true` remote-code execution injections. @@ -2011,7 +2129,7 @@ We identified that **155 community PRs** across the entire project history (from ## [3.4.0] - 2026-03-31 -### 🚀 Features +### Funktioner - **Subscription Utilization Analytics:** Added quota snapshot time-series tracking, Provider Utilization and Combo Health tabs with recharts visualizations, and corresponding API endpoints (#847) - **SQLite Backup Control:** New `OMNIROUTE_DISABLE_AUTO_BACKUP` env flag to disable automatic SQLite backups (#846) @@ -2063,7 +2181,7 @@ We identified that **155 community PRs** across the entire project history (from ## [3.3.8] - 2026-03-30 -### 🚀 Features +### Funktioner - **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) - **Qoder Integration:** Native integration for Qoder AI natively replacing the legacy iFlow platform mappings (#660) @@ -2889,7 +3007,7 @@ We identified that **155 community PRs** across the entire project history (from - **NaN tokens in Claude Code / client responses (#617):** - `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 -### 🔒 Security +### Sikkerhed - Updated `yaml` package to fix stack overflow vulnerability (GHSA-48c2-rrv3-qjmp) @@ -3565,7 +3683,7 @@ docker pull diegosouzapw/omniroute:3.0.0 - **SVG fallback**: `ProviderIcon` component updated with 4-tier strategy: Lobehub → PNG → SVG → Generic icon - **Agents fingerprinting**: Synced with CLI tools — added droid, openclaw, copilot, opencode to fingerprint list (14 total) -### 🔒 Security +### Sikkerhed - **CVE fix**: Resolved dompurify XSS vulnerability (GHSA-v2wj-7wpq-c8vv) via npm overrides forcing `dompurify@^3.3.2` - `npm audit` now reports **0 vulnerabilities** @@ -3928,7 +4046,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **#510** — Windows: MSYS2/Git-Bash paths (`/c/Program Files/...`) are now normalized to `C:\Program Files\...` - **#492** — `omniroute` CLI now detects `mise`/`nvm` when `app/server.js` is missing and shows targeted fix -### 📖 Documentation +### Dokumentation - **#513** — Docker password reset: `INITIAL_PASSWORD` env var workaround documented - **#520** — pnpm: `pnpm approve-builds better-sqlite3` documented @@ -4025,7 +4143,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **feat(executors/cloudflare-ai)**: New `CloudflareAIExecutor` — dynamic URL construction requires `accountId` in provider credentials - **feat(executors)**: Register `pollinations`, `pol`, `cloudflare-ai`, `cf` executor mappings -### 📝 Documentation +### Dokumentation - **docs(readme)**: Expanded free combo stack to 11 providers ($0 forever) - **docs(readme)**: Added 4 new free provider sections (LongCat, Pollinations, Cloudflare AI, Scaleway) with model tables @@ -4177,7 +4295,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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). -### Features +### Funktioner - **"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. @@ -4205,7 +4323,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Merge PR #494 (MiniMax role fix), fix KIRO MITM dashboard, triage 8 issues. -### Features +### Funktioner - **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. - **roleNormalizer**: `normalizeDeveloperRole()` now accepts `preserveDeveloperRole` parameter with tri-state behavior (undefined=keep, true=keep, false=convert). @@ -4261,7 +4379,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Gemini CLI deprecation, VM guide i18n fix, dependabot security fix, provider schema expansion. -### Features +### Funktioner - **Gemini CLI Deprecation** (#462): Mark `gemini-cli` provider as deprecated with warning — Google restricts third-party OAuth usage from March 2026 - **Provider Schema** (#462): Expand Zod validation with `deprecated`, `deprecationReason`, `hasFree`, `freeNote`, `authHint`, `apiHint` optional fields @@ -4270,7 +4388,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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) -### Security +### Sikkerhed - **deps**: Bump `flatted` 3.3.3 → 3.4.2 — fixes CWE-1321 prototype pollution (#484, @dependabot) @@ -4290,7 +4408,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Czech i18n, SSE protocol fix, VM guide translation. -### Features +### Funktioner - **Czech Language** (#482): Full Czech (cs) i18n — 22 docs, 2606 UI strings, language switcher updates (@zen0bit) - **VM Deployment Guide**: Translated from Portuguese to English as the source document (@zen0bit) @@ -4309,7 +4427,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: 2 merged PRs, model aliases routing fix, log export, and issue triage. -### Features +### Funktioner - **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) @@ -4329,7 +4447,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Five community PRs — streaming call log fixes, Kiro compatibility, cache token analytics, Chinese translation, and configurable tool call IDs. -### ✨ Features +### Funktioner - **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) - **feat(providers)**: Per-model configurable 9-char tool call ID normalization (Mistral-style) — only models with the option enabled get truncated IDs (#470) @@ -4359,7 +4477,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Bailian Coding Plan provider with editable base URLs, plus community contributions for Alibaba Cloud and Kimi Coding. -### ✨ Features +### Funktioner - **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) - **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) @@ -4374,7 +4492,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Two new community-contributed providers (Alibaba Cloud Coding, Kimi Coding API-key) and Docker pino fix. -### ✨ Features +### Funktioner - **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) - **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) @@ -4399,7 +4517,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Codex responses subpath passthrough natively supported, Windows MITM crash fixed, and Combos agent schemas adjusted. -### ✨ Features +### Funktioner - **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) @@ -4439,7 +4557,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **fix(budget)**: "Save Limits" no longer returns 422 — `warningThreshold` is now correctly sent as fraction (0–1) instead of percentage (0–100) (#451) - **fix(combos)**: `` internal cache tag is now stripped before forwarding requests to providers, preventing cache session breaks (#454) -### ✨ Features +### Funktioner - **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) @@ -4495,7 +4613,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Search Tools dashboard, i18n fixes, Copilot limits, Serper validation fix. -### 🚀 Features +### Funktioner - **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) - New route: `/dashboard/search-tools` @@ -4595,7 +4713,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - DB migration: `request_type` column on `call_logs` for non-chat request tracking - Zod validation (`v1SearchSchema`), auth-gated, cost recorded via `recordCost()` -### 🔒 Security +### Sikkerhed - **deps**: Next.js 16.1.6 → 16.1.7 — fixes 6 CVEs: - **Critical**: CVE-2026-29057 (HTTP request smuggling via http-proxy) @@ -4725,7 +4843,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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**: New `request_detail_logs` table with 500-entry ring-buffer trigger, opt-in via settings toggle -### ✨ Features +### Funktioner - **feat(combo)**: System Message Override per Combo (#399 — `system_message` field replaces or injects system prompt before forwarding to provider) - **feat(combo)**: Tool Filter Regex per Combo (#399 — `tool_filter_regex` keeps only tools matching pattern; supports OpenAI + Anthropic formats) @@ -4740,7 +4858,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: SSE improvements, local provider_nodes extensions, proxy registry, Claude passthrough fixes. -### ✨ Features +### Funktioner - **feat(health)**: Background health check for local `provider_nodes` with exponential backoff (30s→300s) and `Promise.allSettled` to avoid blocking (#423, @Regis-RCR) - **feat(embeddings)**: Route `/v1/embeddings` to local `provider_nodes` — `buildDynamicEmbeddingProvider()` with hostname validation (#422, @Regis-RCR) @@ -4882,7 +5000,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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 - **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). -### ✨ Features +### Funktioner - **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) @@ -4912,7 +5030,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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) - **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) -### ✨ Features +### Funktioner - **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) - **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. @@ -4971,7 +5089,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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) - **fix(logs)**: Request log table is now readable in light mode — status badges, token counts, and combo tags use adaptive `dark:` color classes (#378) -### ✨ Features +### Funktioner - **feat(kiro)**: Kiro credit tracking added to usage fetcher — queries `getUserCredits` from AWS CodeWhisperer endpoint (#337) @@ -5372,7 +5490,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > **Major release** — Free Stack ecosystem, transcription playground overhaul, 44+ providers, comprehensive free tier documentation, and UI improvements across the board. -### ✨ Features +### Funktioner - **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. - **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. @@ -5383,7 +5501,7 @@ OmniRoute now automatically refreshes model lists for connected providers every ## [2.3.16] - 2026-03-13 -### 📖 Documentation +### Dokumentation - **README: 44+ Providers** — Updated all 3 occurrences of "36+ providers" to "44+" reflecting the actual codebase count (44 providers in providers.ts) - **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. @@ -5393,7 +5511,7 @@ OmniRoute now automatically refreshes model lists for connected providers every ## [2.3.15] - 2026-03-13 -### ✨ Features +### Funktioner - **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. - **i18n — autoCombo section**: Added 20 new translation keys for the Auto-Combo dashboard (`title`, `status`, `modePack`, `providerScores`, `factorTierPriority`, etc.) to all 30 language files. diff --git a/docs/i18n/de/CHANGELOG.md b/docs/i18n/de/CHANGELOG.md index ae57bf3ab3..3ac010af16 100644 --- a/docs/i18n/de/CHANGELOG.md +++ b/docs/i18n/de/CHANGELOG.md @@ -10,30 +10,148 @@ ### ✨ New Features -- **feat(antigravity):** integrate Antigravity provider with dynamic `maxOutputTokens` calculation (bumping to `thinkingBudget + 1`) and standard Cloud Code envelope payload sanitization (#2055, #2063) +- **feat(antigravity):** integrate Antigravity provider with dynamic `maxOutputTokens` calculation, identity fingerprinting overhaul, and Cloud Code envelope payload sanitization (#2055, #2063) - **feat(gemini-cli):** add custom projectId support for Gemini CLI transport (UI, DB, executor) (#1991) +- **feat(providers):** add KIE media provider support with dynamic polling, text models, and expanded video models catalog +- **feat(providers):** add Z.AI provider support with GLM quota handling and new quota labels +- **feat(providers):** add 9 new free AI providers — LLM7, Lepton, Kluster, UncloseAI, BazaarLink, Completions, Enally, FreeTheAi (#2096) +- **feat(providers):** batch delete provider connections via checkbox multi-select (#2094) +- **feat(cursor):** full OpenAI parity — tool calls, streaming, and session management (#2082) +- **feat(cli):** comprehensive CLI enhancement suite with 20+ new commands including `omniroute providers`, `omniroute combos`, `omniroute doctor` (#2074) +- **feat(cli):** add modular CLI setup and provider management commands (#2046) +- **feat(mcp):** add DeepSeek quota and limit monitoring feature (#2089) +- **feat(circuit-breaker):** classify 429 errors and apply per-kind cooldowns (#2116) +- **feat(multi):** manifest-aware tier routing — W1-W4 complete (#2014) +- **feat(combos):** add reset-aware routing strategy for quota-based providers +- **feat(combo):** add context_length input field to combo edit form (#2047) +- **feat(chat):** dynamic tool limit detection with proactive truncation (#2061) +- **feat(sse):** refresh Claude OAuth wire image to claude-cli/2.1.131 (#2011) +- **feat(github):** add `targetFormat: openai-responses` to all GitHub models (#2122) +- **feat(api):** allow configuration via API calls — open management routes to Bearer keys with manage scope (#2103) +- **feat(api):** update API bridge proxy timeout to 600,000ms (#2019) +- **feat(usage):** add service tier breakdown, codex fast service tier analytics, and account for fast tier +- **feat(chat):** add `STREAM_READINESS_TIMEOUT_MS` and integrate into chat handling +- **feat(combo):** add `fallbackDelayMs` to combo configuration and related settings +- **feat(chat):** enhance error handling for semaphore capacity with fallback logic +- **feat(qdrant):** embedding model discovery (#2086) +- **feat(auth):** per-session sticky routing for Codex (#1887) +- **feat(inworld):** enhance Inworld TTS support (#2123) ### 🐛 Bug Fixes +- **fix(pricing):** make `getPricingForModel` fully case-insensitive to ensure custom prices correctly reflect in new incoming requests cost calculations +- **fix(gemini):** prevent `functionDeclarations` from being dropped by the sanitizer when `googleSearch` tool is present (#2077) +- **fix(pollinations):** add `jsonMode: true` flag in the request transformation to enforce correct JSON structure from Pollinations API (#2109) +- **fix(docker):** update Dockerfile to copy `/docs` directory during build ensuring API catalog availability at runtime (#2083) +- **fix(docker):** include OpenAPI spec in runtime image (#2007) +- **fix(providers):** strip OpenAI-specific fields in Kiro translator to prevent 400 errors (#2037) +- **fix(kiro):** normalize tool-use payloads to prevent 400 errors from agents (#2104) +- **fix(kiro):** merge adjacent user history turns after role normalization (#2105) +- **fix(ui):** resolve text contrast issues for zero-config warning banner in light mode (#2050) +- **fix(core):** inject global system prompt correctly into downstream chat completions pipeline (#2080) +- **fix(core):** restore Claude Code adaptive thinking defaults and resolve audio transcription CORS regression +- **fix(routing):** add missing v1beta rewrites to next.config to resolve 404 on Gemini models endpoint (#2102) +- **fix(routing):** fix bare GPT-5.5 routing for Codex-only installations (#2054) +- **fix(routing):** add fuzzy auto-combo routing for `auto/*` model prefix (#2010) - **fix(cache):** optimize cache_control preservation logic and explicitly align tool schema with upstream Claude Code expectations - **fix(db):** preserve legacy SQLite database path on Windows to prevent data loss (#1973) +- **fix(db):** reduce hot-path persistence overhead (#2039) +- **fix(db):** resolve migration conflict by renumbering overlapping migration entries (#2041) - **fix(settings):** resolve model alias persistence double stringification preventing UI updates (#2018) - **fix(routing):** dynamically filter bare model auto-resolution by active provider connections to prevent dead-routing (#2029) - **fix(embeddings):** add Google Gemini embeddings compatibility via OpenAI-compatible endpoint mapping (#2006) +- **fix(sse):** prevent Claude OAuth multi-account correlation via metadata.user_id (#2053) +- **fix(sse):** prevent Claude Code identity cloak overrides and fix fallback resilience (#2053) +- **fix(sse):** classify hour quota errors as QUOTA_EXHAUSTED (#2119) +- **fix(sse):** fix CC-compatible streaming bridge (#2118) +- **fix(antigravity):** sanitize Claude Cloud Code payloads (#2090) +- **fix(antigravity):** add duplex half for streaming bodies +- **fix(antigravity):** align identity protocol and behavior with official AM +- **fix(chatgpt-web):** plumb proxy through to native tls-client (#2022, #2023) +- **fix(codex):** expose native model IDs in catalog (#2012) +- **fix(glm):** add dedicated coding transport (#2087) +- **fix(compression):** support Responses input and expand Spanish compression rules (#2028) +- **fix(catalog):** auto-calculate combo context_length from target model limits (#2030) +- **fix(api):** fix usage analytics and API key identity (#2008, #2092) +- **fix(api-key):** allow Unicode letters in API key name validation (#1996) +- **fix(auth):** allow bootstrap without password (#2048) +- **fix(proxy):** clean up proxy page redundancy and fix 1proxy sync empty body error (#2052) +- **fix(dashboard):** resolve Unknown plan display in Provider Limits +- **fix(usage):** add extensible CURRENCY_SYMBOLS mapping for deepseek currencies +- **fix(runtime):** harden timer handling and model pricing fallback +- **fix(i18n):** complete Simplified Chinese translations (#2115) +- **fix(mitm):** add Linux cert install and skip sudo password when root (#1999) +- **fix(mitm):** prevent stub from loading at runtime via bypass module - **fix:** remove Anthropic-Beta header from non-Anthropic providers to fix identity contamination (#1989) - **fix(cli):** resolve .env loading failure for global npm installations +- **fix(export):** exclude telemetry/usage-history tables from JSON config backups by default to prevent unbounded file growth (#2125) +- **fix:** Follow OpenAI specification, handle throttling in batch and fix UI (#2045) -### 🔒 Security +### Sicherheit +- **fix(security):** remediate CodeQL vulnerabilities (ReDoS, cryptographic bias, stack trace exposure, and weak password hashing) (#216, #215, #211, #208, #206, #210) - **fix(security):** remediate regex validation backtracking path in core compression cleanup (#1990) - **fix(core):** harden input handling and stabilization for prompt compression edge cases +### Dokumentation + +- **docs:** add competitive marketing tables and SEO/AEO optimizations to README (#2091) +- **docs:** refresh providers, model catalogs, and docs for v3.8.0 (#2088) +- **docs:** update Claude MD and update GLM-CN max context to 200k (#2027) +- **docs(env):** add `GITLAB_DUO_OAUTH_CLIENT_ID` to `.env.example` (#2031) + ### 🧹 Chores & Maintenance - **chore(providers):** prune redundant local provider icon assets in favor of `@lobehub/icons` web fonts (#1992) +- **chore(providers):** remove deprecated models (#2033) +- **deps:** bump `fast-uri` from 3.1.0 to 3.1.2 (#2078) +- **deps:** bump `hono` from 4.12.14 to 4.12.18 (#2079) - **ci:** skip SonarCloud scan on main pushes to optimize CI time - **test:** stabilize cooldown abort coverage case in integration testing +### 🏆 v3.8.0 Community Contributors + +Thank you to all **38 community contributors** who made v3.8.0 possible! 🎉 + +| Contributor | PRs | Contributions | +| :--------------------------------------------------------- | :-: | :------------------------------------------------------------ | +| [@oyi77](https://github.com/oyi77) | 7 | #2010, #2014, #2041, #2052, #2061, #2074, #2091, #2094, #2096 | +| [@backryun](https://github.com/backryun) | 4 | #1992, #2033, #2088, #2123 | +| [@dhaern](https://github.com/dhaern) | 4 | #2028, #2039, #2087, #2090 | +| [@Tentoxa](https://github.com/Tentoxa) | 2 | #2011, #2053 | +| [@wauputr4](https://github.com/wauputr4) | 2 | #2009, #2046 | +| [@payne0420](https://github.com/payne0420) | 1 | #2082 | +| [@Tr0sT](https://github.com/Tr0sT) | 1 | #2012 | +| [@AveryanAlex](https://github.com/AveryanAlex) | 1 | #2008 | +| [@nickwizard](https://github.com/nickwizard) | 1 | #1991 | +| [@rodrigogbbr-stack](https://github.com/rodrigogbbr-stack) | 1 | #1996 | +| [@NekoMonci12](https://github.com/NekoMonci12) | 1 | #1999 | +| [@congvc-dev](https://github.com/congvc-dev) | 1 | #2004 | +| [@tatsster](https://github.com/tatsster) | 1 | #2007 | +| [@xssdem](https://github.com/xssdem) | 1 | #2023 | +| [@bypanghu](https://github.com/bypanghu) | 1 | #2027 | +| [@herjarsa](https://github.com/herjarsa) | 1 | #2030 | +| [@wucm667](https://github.com/wucm667) | 1 | #2031 | +| [@hartmark](https://github.com/hartmark) | 1 | #2045 | +| [@ddarkr](https://github.com/ddarkr) | 1 | #2047 | +| [@tces1](https://github.com/tces1) | 1 | #2048 | +| [@guanbear](https://github.com/guanbear) | 1 | #2054 | +| [@Gi99lin](https://github.com/Gi99lin) | 1 | #2055 | +| [@ivan-mezentsev](https://github.com/ivan-mezentsev) | 1 | #2063 | +| [@JxnLexn](https://github.com/JxnLexn) | 1 | #2019 | +| [@yoviarpauzi](https://github.com/yoviarpauzi) | 1 | #2092 | +| [@rafacpti23](https://github.com/rafacpti23) | 1 | #2086 | +| [@gleber](https://github.com/gleber) | 1 | #2103 | +| [@rilham97](https://github.com/rilham97) | 1 | #2104 | +| [@Gioxaa](https://github.com/Gioxaa) | 1 | #2105 | +| [@boa-z](https://github.com/boa-z) | 1 | #2115 | +| [@eleata](https://github.com/eleata) | 1 | #2116 | +| [@rdself](https://github.com/rdself) | 1 | #2118 | +| [@clousky2020](https://github.com/clousky2020) | 1 | #2119 | +| [@abhinavjnu](https://github.com/abhinavjnu) | 1 | #2122 | +| [@HoaPham98](https://github.com/HoaPham98) | 1 | #2089 | +| [@05dunski](https://github.com/05dunski) | 1 | #1978 (cherry-picked) | + ## [3.7.9] — 2026-05-03 ### ✨ New Features @@ -102,7 +220,7 @@ - **chore(provider):** Add reka models list (#1956 — thanks @backryun) - **chore(model):** Update new models, Delete Deprecated models (#1949 — thanks @backryun) -### 📝 Documentation +### Dokumentation - **docs(compression):** document RTK+Caveman stacked savings ranges @@ -201,7 +319,7 @@ - **feat(db):** auto-restore probe-failed database on startup to prevent data loss after failed upgrades (#1810) - **feat(analytics):** add cost-based usage insights and activity streaks in the analytics dashboard -### 🔒 Security +### Sicherheit - **fix(security):** resolve ReDoS vulnerability in Codex executor regex patterns (#1797, #1789) @@ -354,7 +472,7 @@ We identified that **155 community PRs** across the entire project history (from - **feat(proxy):** implement bulk proxy import via pipe-delimited parser with update-or-create (upsert) logic and real-time preview table - **feat(pwa):** add fullscreen installable PWA with manifest, service worker, and cross-platform app icons (#1728) -### 🔒 Security +### Sicherheit - **security:** replace insecure `Math.random` with `crypto.getRandomValues` for fallback UUID generation to resolve CodeQL CWE-338 finding (#182) @@ -519,7 +637,7 @@ We identified that **155 community PRs** across the entire project history (from - **fix(transport):** Prevent memory bloat and database exhaustion from large, fragmented streaming responses. Implemented `ByteQueue` in `kiro.ts` for zero-copy binary accumulation, refactored `antigravity.ts` for incremental SSE parsing, and enforced a strict 512KB tiered truncation limit (`MAX_CALL_LOG_ARTIFACT_BYTES`) on stream request logs and call artifacts (#1647). - **chore(ci):** Update build environment dependencies — bump Node to `24.15.0`, `actions/checkout@v6`, `docker/build-push-action@v7`, pin `actions/setup-python` to major tag (#1646 — thanks @backryun). -### 📝 Documentation +### Dokumentation - **docs(env):** Add `OMNIROUTE_ALLOW_PRIVATE_PROVIDER_URLS` to `.env.example` with documentation for LM Studio and other local provider use cases (#1623). @@ -669,7 +787,7 @@ We identified that **155 community PRs** across the entire project history (from - **test(next):** Align transpile package expectations for the Next.js standalone build. - **test(ci):** Fix CI-only test failures from environment differences — clear `INITIAL_PASSWORD` and `JWT_SECRET` in integration tests, handle `XDG_CONFIG_HOME` for guide-settings tests. -### 📚 Documentation +### Dokumentation - **docs:** Update the root changelog with all release-branch changes through 2026-04-24, including PRs #1544, #1555, #1551, #1550, #1548, #1547, #1541, #1538, #1536, and #1527. - **docs:** Fix broken README and localized documentation links. (#1536) @@ -811,7 +929,7 @@ We identified that **155 community PRs** across the entire project history (from - **feat(providers):** Expand image provider registry with extended model support including SD3.5, FLUX, and DALL-E 3 HD configurations - **feat(combos):** Add new routing strategies and full i18n support for agent features section across 31 languages -### 🔒 Security +### Sicherheit - **security:** Resolve 18 GitHub CodeQL scan alerts including ReDoS, incomplete sanitization, and bad HTML filtering regexp patterns - **fix(auth):** Seal privilege escalation vector by enforcing JWT session checking exclusively on `/api/keys` management endpoints (#1353) @@ -1078,7 +1196,7 @@ We identified that **155 community PRs** across the entire project history (from - **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 - **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 -### 🔒 Security +### Sicherheit - **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 - **Auth Guard on Translator Save:** Added `isAuthenticated` guard to `/api/translator/save` for defense-in-depth consistency @@ -1483,7 +1601,7 @@ We identified that **155 community PRs** across the entire project history (from - **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). -### 📚 Documentation +### Dokumentation - **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. - **Context Relay Delivery Notes:** Documented the current architecture, runtime flow, and Codex-focused scope in the feature docs, changelog, and agent guidance. @@ -1559,7 +1677,7 @@ We identified that **155 community PRs** across the entire project history (from ## [3.5.3] - 2026-04-07 -### Security +### Sicherheit - **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. - **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. @@ -1575,7 +1693,7 @@ We identified that **155 community PRs** across the entire project history (from - **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. -### Documentation +### Dokumentation - **I18n Engine:** Synchronized and pushed deep Machine Translation updates across all 32 natively-supported languages (682 translation nodes aligned). @@ -1736,7 +1854,7 @@ We identified that **155 community PRs** across the entire project history (from ## [3.4.8] — 2026-04-03 -### Security +### Sicherheit - Fully remediated all outstanding Github Advanced Security (CodeQL) findings and Dependabot alerts. - Fixed insecure randomness vulnerabilities by migrating from `Math.random` to `crypto.randomUUID()`. @@ -1748,7 +1866,7 @@ We identified that **155 community PRs** across the entire project history (from ## [3.4.7] — 2026-04-03 -### Features +### Funktionen - Added `Cryptography` node to Monitoring and MCP health checks (#798) - Hardened model-catalog route permissions mapping (`/models`) (#781) @@ -1764,7 +1882,7 @@ We identified that **155 community PRs** across the entire project history (from - Fixed MCP standalone module-resolution (`ERR_MODULE_NOT_FOUND`) via `esbuild` (#936) - Fixed NVIDIA NIM routing credential resolution alias mismatch (#931) -### Security +### Sicherheit - Added safe strict input boundary protection against raw `shell: true` remote-code execution injections. @@ -2011,7 +2129,7 @@ We identified that **155 community PRs** across the entire project history (from ## [3.4.0] - 2026-03-31 -### 🚀 Features +### Funktionen - **Subscription Utilization Analytics:** Added quota snapshot time-series tracking, Provider Utilization and Combo Health tabs with recharts visualizations, and corresponding API endpoints (#847) - **SQLite Backup Control:** New `OMNIROUTE_DISABLE_AUTO_BACKUP` env flag to disable automatic SQLite backups (#846) @@ -2063,7 +2181,7 @@ We identified that **155 community PRs** across the entire project history (from ## [3.3.8] - 2026-03-30 -### 🚀 Features +### Funktionen - **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) - **Qoder Integration:** Native integration for Qoder AI natively replacing the legacy iFlow platform mappings (#660) @@ -2889,7 +3007,7 @@ We identified that **155 community PRs** across the entire project history (from - **NaN tokens in Claude Code / client responses (#617):** - `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 -### 🔒 Security +### Sicherheit - Updated `yaml` package to fix stack overflow vulnerability (GHSA-48c2-rrv3-qjmp) @@ -3565,7 +3683,7 @@ docker pull diegosouzapw/omniroute:3.0.0 - **SVG fallback**: `ProviderIcon` component updated with 4-tier strategy: Lobehub → PNG → SVG → Generic icon - **Agents fingerprinting**: Synced with CLI tools — added droid, openclaw, copilot, opencode to fingerprint list (14 total) -### 🔒 Security +### Sicherheit - **CVE fix**: Resolved dompurify XSS vulnerability (GHSA-v2wj-7wpq-c8vv) via npm overrides forcing `dompurify@^3.3.2` - `npm audit` now reports **0 vulnerabilities** @@ -3928,7 +4046,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **#510** — Windows: MSYS2/Git-Bash paths (`/c/Program Files/...`) are now normalized to `C:\Program Files\...` - **#492** — `omniroute` CLI now detects `mise`/`nvm` when `app/server.js` is missing and shows targeted fix -### 📖 Documentation +### Dokumentation - **#513** — Docker password reset: `INITIAL_PASSWORD` env var workaround documented - **#520** — pnpm: `pnpm approve-builds better-sqlite3` documented @@ -4025,7 +4143,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **feat(executors/cloudflare-ai)**: New `CloudflareAIExecutor` — dynamic URL construction requires `accountId` in provider credentials - **feat(executors)**: Register `pollinations`, `pol`, `cloudflare-ai`, `cf` executor mappings -### 📝 Documentation +### Dokumentation - **docs(readme)**: Expanded free combo stack to 11 providers ($0 forever) - **docs(readme)**: Added 4 new free provider sections (LongCat, Pollinations, Cloudflare AI, Scaleway) with model tables @@ -4177,7 +4295,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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). -### Features +### Funktionen - **"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. @@ -4205,7 +4323,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Merge PR #494 (MiniMax role fix), fix KIRO MITM dashboard, triage 8 issues. -### Features +### Funktionen - **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. - **roleNormalizer**: `normalizeDeveloperRole()` now accepts `preserveDeveloperRole` parameter with tri-state behavior (undefined=keep, true=keep, false=convert). @@ -4261,7 +4379,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Gemini CLI deprecation, VM guide i18n fix, dependabot security fix, provider schema expansion. -### Features +### Funktionen - **Gemini CLI Deprecation** (#462): Mark `gemini-cli` provider as deprecated with warning — Google restricts third-party OAuth usage from March 2026 - **Provider Schema** (#462): Expand Zod validation with `deprecated`, `deprecationReason`, `hasFree`, `freeNote`, `authHint`, `apiHint` optional fields @@ -4270,7 +4388,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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) -### Security +### Sicherheit - **deps**: Bump `flatted` 3.3.3 → 3.4.2 — fixes CWE-1321 prototype pollution (#484, @dependabot) @@ -4290,7 +4408,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Czech i18n, SSE protocol fix, VM guide translation. -### Features +### Funktionen - **Czech Language** (#482): Full Czech (cs) i18n — 22 docs, 2606 UI strings, language switcher updates (@zen0bit) - **VM Deployment Guide**: Translated from Portuguese to English as the source document (@zen0bit) @@ -4309,7 +4427,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: 2 merged PRs, model aliases routing fix, log export, and issue triage. -### Features +### Funktionen - **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) @@ -4329,7 +4447,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Five community PRs — streaming call log fixes, Kiro compatibility, cache token analytics, Chinese translation, and configurable tool call IDs. -### ✨ Features +### Funktionen - **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) - **feat(providers)**: Per-model configurable 9-char tool call ID normalization (Mistral-style) — only models with the option enabled get truncated IDs (#470) @@ -4359,7 +4477,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Bailian Coding Plan provider with editable base URLs, plus community contributions for Alibaba Cloud and Kimi Coding. -### ✨ Features +### Funktionen - **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) - **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) @@ -4374,7 +4492,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Two new community-contributed providers (Alibaba Cloud Coding, Kimi Coding API-key) and Docker pino fix. -### ✨ Features +### Funktionen - **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) - **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) @@ -4399,7 +4517,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Codex responses subpath passthrough natively supported, Windows MITM crash fixed, and Combos agent schemas adjusted. -### ✨ Features +### Funktionen - **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) @@ -4439,7 +4557,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **fix(budget)**: "Save Limits" no longer returns 422 — `warningThreshold` is now correctly sent as fraction (0–1) instead of percentage (0–100) (#451) - **fix(combos)**: `` internal cache tag is now stripped before forwarding requests to providers, preventing cache session breaks (#454) -### ✨ Features +### Funktionen - **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) @@ -4495,7 +4613,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Search Tools dashboard, i18n fixes, Copilot limits, Serper validation fix. -### 🚀 Features +### Funktionen - **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) - New route: `/dashboard/search-tools` @@ -4595,7 +4713,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - DB migration: `request_type` column on `call_logs` for non-chat request tracking - Zod validation (`v1SearchSchema`), auth-gated, cost recorded via `recordCost()` -### 🔒 Security +### Sicherheit - **deps**: Next.js 16.1.6 → 16.1.7 — fixes 6 CVEs: - **Critical**: CVE-2026-29057 (HTTP request smuggling via http-proxy) @@ -4725,7 +4843,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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**: New `request_detail_logs` table with 500-entry ring-buffer trigger, opt-in via settings toggle -### ✨ Features +### Funktionen - **feat(combo)**: System Message Override per Combo (#399 — `system_message` field replaces or injects system prompt before forwarding to provider) - **feat(combo)**: Tool Filter Regex per Combo (#399 — `tool_filter_regex` keeps only tools matching pattern; supports OpenAI + Anthropic formats) @@ -4740,7 +4858,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: SSE improvements, local provider_nodes extensions, proxy registry, Claude passthrough fixes. -### ✨ Features +### Funktionen - **feat(health)**: Background health check for local `provider_nodes` with exponential backoff (30s→300s) and `Promise.allSettled` to avoid blocking (#423, @Regis-RCR) - **feat(embeddings)**: Route `/v1/embeddings` to local `provider_nodes` — `buildDynamicEmbeddingProvider()` with hostname validation (#422, @Regis-RCR) @@ -4882,7 +5000,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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 - **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). -### ✨ Features +### Funktionen - **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) @@ -4912,7 +5030,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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) - **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) -### ✨ Features +### Funktionen - **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) - **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. @@ -4971,7 +5089,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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) - **fix(logs)**: Request log table is now readable in light mode — status badges, token counts, and combo tags use adaptive `dark:` color classes (#378) -### ✨ Features +### Funktionen - **feat(kiro)**: Kiro credit tracking added to usage fetcher — queries `getUserCredits` from AWS CodeWhisperer endpoint (#337) @@ -5372,7 +5490,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > **Major release** — Free Stack ecosystem, transcription playground overhaul, 44+ providers, comprehensive free tier documentation, and UI improvements across the board. -### ✨ Features +### Funktionen - **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. - **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. @@ -5383,7 +5501,7 @@ OmniRoute now automatically refreshes model lists for connected providers every ## [2.3.16] - 2026-03-13 -### 📖 Documentation +### Dokumentation - **README: 44+ Providers** — Updated all 3 occurrences of "36+ providers" to "44+" reflecting the actual codebase count (44 providers in providers.ts) - **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. @@ -5393,7 +5511,7 @@ OmniRoute now automatically refreshes model lists for connected providers every ## [2.3.15] - 2026-03-13 -### ✨ Features +### Funktionen - **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. - **i18n — autoCombo section**: Added 20 new translation keys for the Auto-Combo dashboard (`title`, `status`, `modePack`, `providerScores`, `factorTierPriority`, etc.) to all 30 language files. diff --git a/docs/i18n/es/CHANGELOG.md b/docs/i18n/es/CHANGELOG.md index 584b0b0711..913b323c61 100644 --- a/docs/i18n/es/CHANGELOG.md +++ b/docs/i18n/es/CHANGELOG.md @@ -10,30 +10,148 @@ ### ✨ New Features -- **feat(antigravity):** integrate Antigravity provider with dynamic `maxOutputTokens` calculation (bumping to `thinkingBudget + 1`) and standard Cloud Code envelope payload sanitization (#2055, #2063) +- **feat(antigravity):** integrate Antigravity provider with dynamic `maxOutputTokens` calculation, identity fingerprinting overhaul, and Cloud Code envelope payload sanitization (#2055, #2063) - **feat(gemini-cli):** add custom projectId support for Gemini CLI transport (UI, DB, executor) (#1991) +- **feat(providers):** add KIE media provider support with dynamic polling, text models, and expanded video models catalog +- **feat(providers):** add Z.AI provider support with GLM quota handling and new quota labels +- **feat(providers):** add 9 new free AI providers — LLM7, Lepton, Kluster, UncloseAI, BazaarLink, Completions, Enally, FreeTheAi (#2096) +- **feat(providers):** batch delete provider connections via checkbox multi-select (#2094) +- **feat(cursor):** full OpenAI parity — tool calls, streaming, and session management (#2082) +- **feat(cli):** comprehensive CLI enhancement suite with 20+ new commands including `omniroute providers`, `omniroute combos`, `omniroute doctor` (#2074) +- **feat(cli):** add modular CLI setup and provider management commands (#2046) +- **feat(mcp):** add DeepSeek quota and limit monitoring feature (#2089) +- **feat(circuit-breaker):** classify 429 errors and apply per-kind cooldowns (#2116) +- **feat(multi):** manifest-aware tier routing — W1-W4 complete (#2014) +- **feat(combos):** add reset-aware routing strategy for quota-based providers +- **feat(combo):** add context_length input field to combo edit form (#2047) +- **feat(chat):** dynamic tool limit detection with proactive truncation (#2061) +- **feat(sse):** refresh Claude OAuth wire image to claude-cli/2.1.131 (#2011) +- **feat(github):** add `targetFormat: openai-responses` to all GitHub models (#2122) +- **feat(api):** allow configuration via API calls — open management routes to Bearer keys with manage scope (#2103) +- **feat(api):** update API bridge proxy timeout to 600,000ms (#2019) +- **feat(usage):** add service tier breakdown, codex fast service tier analytics, and account for fast tier +- **feat(chat):** add `STREAM_READINESS_TIMEOUT_MS` and integrate into chat handling +- **feat(combo):** add `fallbackDelayMs` to combo configuration and related settings +- **feat(chat):** enhance error handling for semaphore capacity with fallback logic +- **feat(qdrant):** embedding model discovery (#2086) +- **feat(auth):** per-session sticky routing for Codex (#1887) +- **feat(inworld):** enhance Inworld TTS support (#2123) ### 🐛 Bug Fixes +- **fix(pricing):** make `getPricingForModel` fully case-insensitive to ensure custom prices correctly reflect in new incoming requests cost calculations +- **fix(gemini):** prevent `functionDeclarations` from being dropped by the sanitizer when `googleSearch` tool is present (#2077) +- **fix(pollinations):** add `jsonMode: true` flag in the request transformation to enforce correct JSON structure from Pollinations API (#2109) +- **fix(docker):** update Dockerfile to copy `/docs` directory during build ensuring API catalog availability at runtime (#2083) +- **fix(docker):** include OpenAPI spec in runtime image (#2007) +- **fix(providers):** strip OpenAI-specific fields in Kiro translator to prevent 400 errors (#2037) +- **fix(kiro):** normalize tool-use payloads to prevent 400 errors from agents (#2104) +- **fix(kiro):** merge adjacent user history turns after role normalization (#2105) +- **fix(ui):** resolve text contrast issues for zero-config warning banner in light mode (#2050) +- **fix(core):** inject global system prompt correctly into downstream chat completions pipeline (#2080) +- **fix(core):** restore Claude Code adaptive thinking defaults and resolve audio transcription CORS regression +- **fix(routing):** add missing v1beta rewrites to next.config to resolve 404 on Gemini models endpoint (#2102) +- **fix(routing):** fix bare GPT-5.5 routing for Codex-only installations (#2054) +- **fix(routing):** add fuzzy auto-combo routing for `auto/*` model prefix (#2010) - **fix(cache):** optimize cache_control preservation logic and explicitly align tool schema with upstream Claude Code expectations - **fix(db):** preserve legacy SQLite database path on Windows to prevent data loss (#1973) +- **fix(db):** reduce hot-path persistence overhead (#2039) +- **fix(db):** resolve migration conflict by renumbering overlapping migration entries (#2041) - **fix(settings):** resolve model alias persistence double stringification preventing UI updates (#2018) - **fix(routing):** dynamically filter bare model auto-resolution by active provider connections to prevent dead-routing (#2029) - **fix(embeddings):** add Google Gemini embeddings compatibility via OpenAI-compatible endpoint mapping (#2006) +- **fix(sse):** prevent Claude OAuth multi-account correlation via metadata.user_id (#2053) +- **fix(sse):** prevent Claude Code identity cloak overrides and fix fallback resilience (#2053) +- **fix(sse):** classify hour quota errors as QUOTA_EXHAUSTED (#2119) +- **fix(sse):** fix CC-compatible streaming bridge (#2118) +- **fix(antigravity):** sanitize Claude Cloud Code payloads (#2090) +- **fix(antigravity):** add duplex half for streaming bodies +- **fix(antigravity):** align identity protocol and behavior with official AM +- **fix(chatgpt-web):** plumb proxy through to native tls-client (#2022, #2023) +- **fix(codex):** expose native model IDs in catalog (#2012) +- **fix(glm):** add dedicated coding transport (#2087) +- **fix(compression):** support Responses input and expand Spanish compression rules (#2028) +- **fix(catalog):** auto-calculate combo context_length from target model limits (#2030) +- **fix(api):** fix usage analytics and API key identity (#2008, #2092) +- **fix(api-key):** allow Unicode letters in API key name validation (#1996) +- **fix(auth):** allow bootstrap without password (#2048) +- **fix(proxy):** clean up proxy page redundancy and fix 1proxy sync empty body error (#2052) +- **fix(dashboard):** resolve Unknown plan display in Provider Limits +- **fix(usage):** add extensible CURRENCY_SYMBOLS mapping for deepseek currencies +- **fix(runtime):** harden timer handling and model pricing fallback +- **fix(i18n):** complete Simplified Chinese translations (#2115) +- **fix(mitm):** add Linux cert install and skip sudo password when root (#1999) +- **fix(mitm):** prevent stub from loading at runtime via bypass module - **fix:** remove Anthropic-Beta header from non-Anthropic providers to fix identity contamination (#1989) - **fix(cli):** resolve .env loading failure for global npm installations +- **fix(export):** exclude telemetry/usage-history tables from JSON config backups by default to prevent unbounded file growth (#2125) +- **fix:** Follow OpenAI specification, handle throttling in batch and fix UI (#2045) -### 🔒 Security +### Seguridad +- **fix(security):** remediate CodeQL vulnerabilities (ReDoS, cryptographic bias, stack trace exposure, and weak password hashing) (#216, #215, #211, #208, #206, #210) - **fix(security):** remediate regex validation backtracking path in core compression cleanup (#1990) - **fix(core):** harden input handling and stabilization for prompt compression edge cases +### Documentación + +- **docs:** add competitive marketing tables and SEO/AEO optimizations to README (#2091) +- **docs:** refresh providers, model catalogs, and docs for v3.8.0 (#2088) +- **docs:** update Claude MD and update GLM-CN max context to 200k (#2027) +- **docs(env):** add `GITLAB_DUO_OAUTH_CLIENT_ID` to `.env.example` (#2031) + ### 🧹 Chores & Maintenance - **chore(providers):** prune redundant local provider icon assets in favor of `@lobehub/icons` web fonts (#1992) +- **chore(providers):** remove deprecated models (#2033) +- **deps:** bump `fast-uri` from 3.1.0 to 3.1.2 (#2078) +- **deps:** bump `hono` from 4.12.14 to 4.12.18 (#2079) - **ci:** skip SonarCloud scan on main pushes to optimize CI time - **test:** stabilize cooldown abort coverage case in integration testing +### 🏆 v3.8.0 Community Contributors + +Thank you to all **38 community contributors** who made v3.8.0 possible! 🎉 + +| Contributor | PRs | Contributions | +| :--------------------------------------------------------- | :-: | :------------------------------------------------------------ | +| [@oyi77](https://github.com/oyi77) | 7 | #2010, #2014, #2041, #2052, #2061, #2074, #2091, #2094, #2096 | +| [@backryun](https://github.com/backryun) | 4 | #1992, #2033, #2088, #2123 | +| [@dhaern](https://github.com/dhaern) | 4 | #2028, #2039, #2087, #2090 | +| [@Tentoxa](https://github.com/Tentoxa) | 2 | #2011, #2053 | +| [@wauputr4](https://github.com/wauputr4) | 2 | #2009, #2046 | +| [@payne0420](https://github.com/payne0420) | 1 | #2082 | +| [@Tr0sT](https://github.com/Tr0sT) | 1 | #2012 | +| [@AveryanAlex](https://github.com/AveryanAlex) | 1 | #2008 | +| [@nickwizard](https://github.com/nickwizard) | 1 | #1991 | +| [@rodrigogbbr-stack](https://github.com/rodrigogbbr-stack) | 1 | #1996 | +| [@NekoMonci12](https://github.com/NekoMonci12) | 1 | #1999 | +| [@congvc-dev](https://github.com/congvc-dev) | 1 | #2004 | +| [@tatsster](https://github.com/tatsster) | 1 | #2007 | +| [@xssdem](https://github.com/xssdem) | 1 | #2023 | +| [@bypanghu](https://github.com/bypanghu) | 1 | #2027 | +| [@herjarsa](https://github.com/herjarsa) | 1 | #2030 | +| [@wucm667](https://github.com/wucm667) | 1 | #2031 | +| [@hartmark](https://github.com/hartmark) | 1 | #2045 | +| [@ddarkr](https://github.com/ddarkr) | 1 | #2047 | +| [@tces1](https://github.com/tces1) | 1 | #2048 | +| [@guanbear](https://github.com/guanbear) | 1 | #2054 | +| [@Gi99lin](https://github.com/Gi99lin) | 1 | #2055 | +| [@ivan-mezentsev](https://github.com/ivan-mezentsev) | 1 | #2063 | +| [@JxnLexn](https://github.com/JxnLexn) | 1 | #2019 | +| [@yoviarpauzi](https://github.com/yoviarpauzi) | 1 | #2092 | +| [@rafacpti23](https://github.com/rafacpti23) | 1 | #2086 | +| [@gleber](https://github.com/gleber) | 1 | #2103 | +| [@rilham97](https://github.com/rilham97) | 1 | #2104 | +| [@Gioxaa](https://github.com/Gioxaa) | 1 | #2105 | +| [@boa-z](https://github.com/boa-z) | 1 | #2115 | +| [@eleata](https://github.com/eleata) | 1 | #2116 | +| [@rdself](https://github.com/rdself) | 1 | #2118 | +| [@clousky2020](https://github.com/clousky2020) | 1 | #2119 | +| [@abhinavjnu](https://github.com/abhinavjnu) | 1 | #2122 | +| [@HoaPham98](https://github.com/HoaPham98) | 1 | #2089 | +| [@05dunski](https://github.com/05dunski) | 1 | #1978 (cherry-picked) | + ## [3.7.9] — 2026-05-03 ### ✨ New Features @@ -102,7 +220,7 @@ - **chore(provider):** Add reka models list (#1956 — thanks @backryun) - **chore(model):** Update new models, Delete Deprecated models (#1949 — thanks @backryun) -### 📝 Documentation +### Documentación - **docs(compression):** document RTK+Caveman stacked savings ranges @@ -201,7 +319,7 @@ - **feat(db):** auto-restore probe-failed database on startup to prevent data loss after failed upgrades (#1810) - **feat(analytics):** add cost-based usage insights and activity streaks in the analytics dashboard -### 🔒 Security +### Seguridad - **fix(security):** resolve ReDoS vulnerability in Codex executor regex patterns (#1797, #1789) @@ -354,7 +472,7 @@ We identified that **155 community PRs** across the entire project history (from - **feat(proxy):** implement bulk proxy import via pipe-delimited parser with update-or-create (upsert) logic and real-time preview table - **feat(pwa):** add fullscreen installable PWA with manifest, service worker, and cross-platform app icons (#1728) -### 🔒 Security +### Seguridad - **security:** replace insecure `Math.random` with `crypto.getRandomValues` for fallback UUID generation to resolve CodeQL CWE-338 finding (#182) @@ -519,7 +637,7 @@ We identified that **155 community PRs** across the entire project history (from - **fix(transport):** Prevent memory bloat and database exhaustion from large, fragmented streaming responses. Implemented `ByteQueue` in `kiro.ts` for zero-copy binary accumulation, refactored `antigravity.ts` for incremental SSE parsing, and enforced a strict 512KB tiered truncation limit (`MAX_CALL_LOG_ARTIFACT_BYTES`) on stream request logs and call artifacts (#1647). - **chore(ci):** Update build environment dependencies — bump Node to `24.15.0`, `actions/checkout@v6`, `docker/build-push-action@v7`, pin `actions/setup-python` to major tag (#1646 — thanks @backryun). -### 📝 Documentation +### Documentación - **docs(env):** Add `OMNIROUTE_ALLOW_PRIVATE_PROVIDER_URLS` to `.env.example` with documentation for LM Studio and other local provider use cases (#1623). @@ -669,7 +787,7 @@ We identified that **155 community PRs** across the entire project history (from - **test(next):** Align transpile package expectations for the Next.js standalone build. - **test(ci):** Fix CI-only test failures from environment differences — clear `INITIAL_PASSWORD` and `JWT_SECRET` in integration tests, handle `XDG_CONFIG_HOME` for guide-settings tests. -### 📚 Documentation +### Documentación - **docs:** Update the root changelog with all release-branch changes through 2026-04-24, including PRs #1544, #1555, #1551, #1550, #1548, #1547, #1541, #1538, #1536, and #1527. - **docs:** Fix broken README and localized documentation links. (#1536) @@ -811,7 +929,7 @@ We identified that **155 community PRs** across the entire project history (from - **feat(providers):** Expand image provider registry with extended model support including SD3.5, FLUX, and DALL-E 3 HD configurations - **feat(combos):** Add new routing strategies and full i18n support for agent features section across 31 languages -### 🔒 Security +### Seguridad - **security:** Resolve 18 GitHub CodeQL scan alerts including ReDoS, incomplete sanitization, and bad HTML filtering regexp patterns - **fix(auth):** Seal privilege escalation vector by enforcing JWT session checking exclusively on `/api/keys` management endpoints (#1353) @@ -1078,7 +1196,7 @@ We identified that **155 community PRs** across the entire project history (from - **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 - **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 -### 🔒 Security +### Seguridad - **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 - **Auth Guard on Translator Save:** Added `isAuthenticated` guard to `/api/translator/save` for defense-in-depth consistency @@ -1483,7 +1601,7 @@ We identified that **155 community PRs** across the entire project history (from - **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). -### 📚 Documentation +### Documentació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. - **Context Relay Delivery Notes:** Documented the current architecture, runtime flow, and Codex-focused scope in the feature docs, changelog, and agent guidance. @@ -1559,7 +1677,7 @@ We identified that **155 community PRs** across the entire project history (from ## [3.5.3] - 2026-04-07 -### Security +### Seguridad - **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. - **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. @@ -1575,7 +1693,7 @@ We identified that **155 community PRs** across the entire project history (from - **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. -### Documentation +### Documentación - **I18n Engine:** Synchronized and pushed deep Machine Translation updates across all 32 natively-supported languages (682 translation nodes aligned). @@ -1736,7 +1854,7 @@ We identified that **155 community PRs** across the entire project history (from ## [3.4.8] — 2026-04-03 -### Security +### Seguridad - Fully remediated all outstanding Github Advanced Security (CodeQL) findings and Dependabot alerts. - Fixed insecure randomness vulnerabilities by migrating from `Math.random` to `crypto.randomUUID()`. @@ -1748,7 +1866,7 @@ We identified that **155 community PRs** across the entire project history (from ## [3.4.7] — 2026-04-03 -### Features +### Funcionalidades - Added `Cryptography` node to Monitoring and MCP health checks (#798) - Hardened model-catalog route permissions mapping (`/models`) (#781) @@ -1764,7 +1882,7 @@ We identified that **155 community PRs** across the entire project history (from - Fixed MCP standalone module-resolution (`ERR_MODULE_NOT_FOUND`) via `esbuild` (#936) - Fixed NVIDIA NIM routing credential resolution alias mismatch (#931) -### Security +### Seguridad - Added safe strict input boundary protection against raw `shell: true` remote-code execution injections. @@ -2011,7 +2129,7 @@ We identified that **155 community PRs** across the entire project history (from ## [3.4.0] - 2026-03-31 -### 🚀 Features +### Funcionalidades - **Subscription Utilization Analytics:** Added quota snapshot time-series tracking, Provider Utilization and Combo Health tabs with recharts visualizations, and corresponding API endpoints (#847) - **SQLite Backup Control:** New `OMNIROUTE_DISABLE_AUTO_BACKUP` env flag to disable automatic SQLite backups (#846) @@ -2063,7 +2181,7 @@ We identified that **155 community PRs** across the entire project history (from ## [3.3.8] - 2026-03-30 -### 🚀 Features +### Funcionalidades - **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) - **Qoder Integration:** Native integration for Qoder AI natively replacing the legacy iFlow platform mappings (#660) @@ -2889,7 +3007,7 @@ We identified that **155 community PRs** across the entire project history (from - **NaN tokens in Claude Code / client responses (#617):** - `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 -### 🔒 Security +### Seguridad - Updated `yaml` package to fix stack overflow vulnerability (GHSA-48c2-rrv3-qjmp) @@ -3565,7 +3683,7 @@ docker pull diegosouzapw/omniroute:3.0.0 - **SVG fallback**: `ProviderIcon` component updated with 4-tier strategy: Lobehub → PNG → SVG → Generic icon - **Agents fingerprinting**: Synced with CLI tools — added droid, openclaw, copilot, opencode to fingerprint list (14 total) -### 🔒 Security +### Seguridad - **CVE fix**: Resolved dompurify XSS vulnerability (GHSA-v2wj-7wpq-c8vv) via npm overrides forcing `dompurify@^3.3.2` - `npm audit` now reports **0 vulnerabilities** @@ -3928,7 +4046,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **#510** — Windows: MSYS2/Git-Bash paths (`/c/Program Files/...`) are now normalized to `C:\Program Files\...` - **#492** — `omniroute` CLI now detects `mise`/`nvm` when `app/server.js` is missing and shows targeted fix -### 📖 Documentation +### Documentación - **#513** — Docker password reset: `INITIAL_PASSWORD` env var workaround documented - **#520** — pnpm: `pnpm approve-builds better-sqlite3` documented @@ -4025,7 +4143,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **feat(executors/cloudflare-ai)**: New `CloudflareAIExecutor` — dynamic URL construction requires `accountId` in provider credentials - **feat(executors)**: Register `pollinations`, `pol`, `cloudflare-ai`, `cf` executor mappings -### 📝 Documentation +### Documentación - **docs(readme)**: Expanded free combo stack to 11 providers ($0 forever) - **docs(readme)**: Added 4 new free provider sections (LongCat, Pollinations, Cloudflare AI, Scaleway) with model tables @@ -4177,7 +4295,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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). -### Features +### Funcionalidades - **"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. @@ -4205,7 +4323,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Merge PR #494 (MiniMax role fix), fix KIRO MITM dashboard, triage 8 issues. -### Features +### Funcionalidades - **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. - **roleNormalizer**: `normalizeDeveloperRole()` now accepts `preserveDeveloperRole` parameter with tri-state behavior (undefined=keep, true=keep, false=convert). @@ -4261,7 +4379,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Gemini CLI deprecation, VM guide i18n fix, dependabot security fix, provider schema expansion. -### Features +### Funcionalidades - **Gemini CLI Deprecation** (#462): Mark `gemini-cli` provider as deprecated with warning — Google restricts third-party OAuth usage from March 2026 - **Provider Schema** (#462): Expand Zod validation with `deprecated`, `deprecationReason`, `hasFree`, `freeNote`, `authHint`, `apiHint` optional fields @@ -4270,7 +4388,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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) -### Security +### Seguridad - **deps**: Bump `flatted` 3.3.3 → 3.4.2 — fixes CWE-1321 prototype pollution (#484, @dependabot) @@ -4290,7 +4408,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Czech i18n, SSE protocol fix, VM guide translation. -### Features +### Funcionalidades - **Czech Language** (#482): Full Czech (cs) i18n — 22 docs, 2606 UI strings, language switcher updates (@zen0bit) - **VM Deployment Guide**: Translated from Portuguese to English as the source document (@zen0bit) @@ -4309,7 +4427,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: 2 merged PRs, model aliases routing fix, log export, and issue triage. -### Features +### Funcionalidades - **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) @@ -4329,7 +4447,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Five community PRs — streaming call log fixes, Kiro compatibility, cache token analytics, Chinese translation, and configurable tool call IDs. -### ✨ Features +### Funcionalidades - **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) - **feat(providers)**: Per-model configurable 9-char tool call ID normalization (Mistral-style) — only models with the option enabled get truncated IDs (#470) @@ -4359,7 +4477,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Bailian Coding Plan provider with editable base URLs, plus community contributions for Alibaba Cloud and Kimi Coding. -### ✨ Features +### Funcionalidades - **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) - **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) @@ -4374,7 +4492,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Two new community-contributed providers (Alibaba Cloud Coding, Kimi Coding API-key) and Docker pino fix. -### ✨ Features +### Funcionalidades - **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) - **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) @@ -4399,7 +4517,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Codex responses subpath passthrough natively supported, Windows MITM crash fixed, and Combos agent schemas adjusted. -### ✨ Features +### Funcionalidades - **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) @@ -4439,7 +4557,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **fix(budget)**: "Save Limits" no longer returns 422 — `warningThreshold` is now correctly sent as fraction (0–1) instead of percentage (0–100) (#451) - **fix(combos)**: `` internal cache tag is now stripped before forwarding requests to providers, preventing cache session breaks (#454) -### ✨ Features +### Funcionalidades - **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) @@ -4495,7 +4613,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Search Tools dashboard, i18n fixes, Copilot limits, Serper validation fix. -### 🚀 Features +### Funcionalidades - **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) - New route: `/dashboard/search-tools` @@ -4595,7 +4713,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - DB migration: `request_type` column on `call_logs` for non-chat request tracking - Zod validation (`v1SearchSchema`), auth-gated, cost recorded via `recordCost()` -### 🔒 Security +### Seguridad - **deps**: Next.js 16.1.6 → 16.1.7 — fixes 6 CVEs: - **Critical**: CVE-2026-29057 (HTTP request smuggling via http-proxy) @@ -4725,7 +4843,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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**: New `request_detail_logs` table with 500-entry ring-buffer trigger, opt-in via settings toggle -### ✨ Features +### Funcionalidades - **feat(combo)**: System Message Override per Combo (#399 — `system_message` field replaces or injects system prompt before forwarding to provider) - **feat(combo)**: Tool Filter Regex per Combo (#399 — `tool_filter_regex` keeps only tools matching pattern; supports OpenAI + Anthropic formats) @@ -4740,7 +4858,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: SSE improvements, local provider_nodes extensions, proxy registry, Claude passthrough fixes. -### ✨ Features +### Funcionalidades - **feat(health)**: Background health check for local `provider_nodes` with exponential backoff (30s→300s) and `Promise.allSettled` to avoid blocking (#423, @Regis-RCR) - **feat(embeddings)**: Route `/v1/embeddings` to local `provider_nodes` — `buildDynamicEmbeddingProvider()` with hostname validation (#422, @Regis-RCR) @@ -4882,7 +5000,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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 - **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). -### ✨ Features +### Funcionalidades - **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) @@ -4912,7 +5030,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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) - **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) -### ✨ Features +### Funcionalidades - **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) - **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. @@ -4971,7 +5089,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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) - **fix(logs)**: Request log table is now readable in light mode — status badges, token counts, and combo tags use adaptive `dark:` color classes (#378) -### ✨ Features +### Funcionalidades - **feat(kiro)**: Kiro credit tracking added to usage fetcher — queries `getUserCredits` from AWS CodeWhisperer endpoint (#337) @@ -5372,7 +5490,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > **Major release** — Free Stack ecosystem, transcription playground overhaul, 44+ providers, comprehensive free tier documentation, and UI improvements across the board. -### ✨ Features +### Funcionalidades - **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. - **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. @@ -5383,7 +5501,7 @@ OmniRoute now automatically refreshes model lists for connected providers every ## [2.3.16] - 2026-03-13 -### 📖 Documentation +### Documentación - **README: 44+ Providers** — Updated all 3 occurrences of "36+ providers" to "44+" reflecting the actual codebase count (44 providers in providers.ts) - **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. @@ -5393,7 +5511,7 @@ OmniRoute now automatically refreshes model lists for connected providers every ## [2.3.15] - 2026-03-13 -### ✨ Features +### Funcionalidades - **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. - **i18n — autoCombo section**: Added 20 new translation keys for the Auto-Combo dashboard (`title`, `status`, `modePack`, `providerScores`, `factorTierPriority`, etc.) to all 30 language files. diff --git a/docs/i18n/fa/CHANGELOG.md b/docs/i18n/fa/CHANGELOG.md index 057c405923..bcfe7dd067 100644 --- a/docs/i18n/fa/CHANGELOG.md +++ b/docs/i18n/fa/CHANGELOG.md @@ -10,30 +10,148 @@ ### ✨ New Features -- **feat(antigravity):** integrate Antigravity provider with dynamic `maxOutputTokens` calculation (bumping to `thinkingBudget + 1`) and standard Cloud Code envelope payload sanitization (#2055, #2063) +- **feat(antigravity):** integrate Antigravity provider with dynamic `maxOutputTokens` calculation, identity fingerprinting overhaul, and Cloud Code envelope payload sanitization (#2055, #2063) - **feat(gemini-cli):** add custom projectId support for Gemini CLI transport (UI, DB, executor) (#1991) +- **feat(providers):** add KIE media provider support with dynamic polling, text models, and expanded video models catalog +- **feat(providers):** add Z.AI provider support with GLM quota handling and new quota labels +- **feat(providers):** add 9 new free AI providers — LLM7, Lepton, Kluster, UncloseAI, BazaarLink, Completions, Enally, FreeTheAi (#2096) +- **feat(providers):** batch delete provider connections via checkbox multi-select (#2094) +- **feat(cursor):** full OpenAI parity — tool calls, streaming, and session management (#2082) +- **feat(cli):** comprehensive CLI enhancement suite with 20+ new commands including `omniroute providers`, `omniroute combos`, `omniroute doctor` (#2074) +- **feat(cli):** add modular CLI setup and provider management commands (#2046) +- **feat(mcp):** add DeepSeek quota and limit monitoring feature (#2089) +- **feat(circuit-breaker):** classify 429 errors and apply per-kind cooldowns (#2116) +- **feat(multi):** manifest-aware tier routing — W1-W4 complete (#2014) +- **feat(combos):** add reset-aware routing strategy for quota-based providers +- **feat(combo):** add context_length input field to combo edit form (#2047) +- **feat(chat):** dynamic tool limit detection with proactive truncation (#2061) +- **feat(sse):** refresh Claude OAuth wire image to claude-cli/2.1.131 (#2011) +- **feat(github):** add `targetFormat: openai-responses` to all GitHub models (#2122) +- **feat(api):** allow configuration via API calls — open management routes to Bearer keys with manage scope (#2103) +- **feat(api):** update API bridge proxy timeout to 600,000ms (#2019) +- **feat(usage):** add service tier breakdown, codex fast service tier analytics, and account for fast tier +- **feat(chat):** add `STREAM_READINESS_TIMEOUT_MS` and integrate into chat handling +- **feat(combo):** add `fallbackDelayMs` to combo configuration and related settings +- **feat(chat):** enhance error handling for semaphore capacity with fallback logic +- **feat(qdrant):** embedding model discovery (#2086) +- **feat(auth):** per-session sticky routing for Codex (#1887) +- **feat(inworld):** enhance Inworld TTS support (#2123) ### 🐛 Bug Fixes +- **fix(pricing):** make `getPricingForModel` fully case-insensitive to ensure custom prices correctly reflect in new incoming requests cost calculations +- **fix(gemini):** prevent `functionDeclarations` from being dropped by the sanitizer when `googleSearch` tool is present (#2077) +- **fix(pollinations):** add `jsonMode: true` flag in the request transformation to enforce correct JSON structure from Pollinations API (#2109) +- **fix(docker):** update Dockerfile to copy `/docs` directory during build ensuring API catalog availability at runtime (#2083) +- **fix(docker):** include OpenAPI spec in runtime image (#2007) +- **fix(providers):** strip OpenAI-specific fields in Kiro translator to prevent 400 errors (#2037) +- **fix(kiro):** normalize tool-use payloads to prevent 400 errors from agents (#2104) +- **fix(kiro):** merge adjacent user history turns after role normalization (#2105) +- **fix(ui):** resolve text contrast issues for zero-config warning banner in light mode (#2050) +- **fix(core):** inject global system prompt correctly into downstream chat completions pipeline (#2080) +- **fix(core):** restore Claude Code adaptive thinking defaults and resolve audio transcription CORS regression +- **fix(routing):** add missing v1beta rewrites to next.config to resolve 404 on Gemini models endpoint (#2102) +- **fix(routing):** fix bare GPT-5.5 routing for Codex-only installations (#2054) +- **fix(routing):** add fuzzy auto-combo routing for `auto/*` model prefix (#2010) - **fix(cache):** optimize cache_control preservation logic and explicitly align tool schema with upstream Claude Code expectations - **fix(db):** preserve legacy SQLite database path on Windows to prevent data loss (#1973) +- **fix(db):** reduce hot-path persistence overhead (#2039) +- **fix(db):** resolve migration conflict by renumbering overlapping migration entries (#2041) - **fix(settings):** resolve model alias persistence double stringification preventing UI updates (#2018) - **fix(routing):** dynamically filter bare model auto-resolution by active provider connections to prevent dead-routing (#2029) - **fix(embeddings):** add Google Gemini embeddings compatibility via OpenAI-compatible endpoint mapping (#2006) +- **fix(sse):** prevent Claude OAuth multi-account correlation via metadata.user_id (#2053) +- **fix(sse):** prevent Claude Code identity cloak overrides and fix fallback resilience (#2053) +- **fix(sse):** classify hour quota errors as QUOTA_EXHAUSTED (#2119) +- **fix(sse):** fix CC-compatible streaming bridge (#2118) +- **fix(antigravity):** sanitize Claude Cloud Code payloads (#2090) +- **fix(antigravity):** add duplex half for streaming bodies +- **fix(antigravity):** align identity protocol and behavior with official AM +- **fix(chatgpt-web):** plumb proxy through to native tls-client (#2022, #2023) +- **fix(codex):** expose native model IDs in catalog (#2012) +- **fix(glm):** add dedicated coding transport (#2087) +- **fix(compression):** support Responses input and expand Spanish compression rules (#2028) +- **fix(catalog):** auto-calculate combo context_length from target model limits (#2030) +- **fix(api):** fix usage analytics and API key identity (#2008, #2092) +- **fix(api-key):** allow Unicode letters in API key name validation (#1996) +- **fix(auth):** allow bootstrap without password (#2048) +- **fix(proxy):** clean up proxy page redundancy and fix 1proxy sync empty body error (#2052) +- **fix(dashboard):** resolve Unknown plan display in Provider Limits +- **fix(usage):** add extensible CURRENCY_SYMBOLS mapping for deepseek currencies +- **fix(runtime):** harden timer handling and model pricing fallback +- **fix(i18n):** complete Simplified Chinese translations (#2115) +- **fix(mitm):** add Linux cert install and skip sudo password when root (#1999) +- **fix(mitm):** prevent stub from loading at runtime via bypass module - **fix:** remove Anthropic-Beta header from non-Anthropic providers to fix identity contamination (#1989) - **fix(cli):** resolve .env loading failure for global npm installations +- **fix(export):** exclude telemetry/usage-history tables from JSON config backups by default to prevent unbounded file growth (#2125) +- **fix:** Follow OpenAI specification, handle throttling in batch and fix UI (#2045) -### 🔒 Security +### Seguridad +- **fix(security):** remediate CodeQL vulnerabilities (ReDoS, cryptographic bias, stack trace exposure, and weak password hashing) (#216, #215, #211, #208, #206, #210) - **fix(security):** remediate regex validation backtracking path in core compression cleanup (#1990) - **fix(core):** harden input handling and stabilization for prompt compression edge cases +### Documentación + +- **docs:** add competitive marketing tables and SEO/AEO optimizations to README (#2091) +- **docs:** refresh providers, model catalogs, and docs for v3.8.0 (#2088) +- **docs:** update Claude MD and update GLM-CN max context to 200k (#2027) +- **docs(env):** add `GITLAB_DUO_OAUTH_CLIENT_ID` to `.env.example` (#2031) + ### 🧹 Chores & Maintenance - **chore(providers):** prune redundant local provider icon assets in favor of `@lobehub/icons` web fonts (#1992) +- **chore(providers):** remove deprecated models (#2033) +- **deps:** bump `fast-uri` from 3.1.0 to 3.1.2 (#2078) +- **deps:** bump `hono` from 4.12.14 to 4.12.18 (#2079) - **ci:** skip SonarCloud scan on main pushes to optimize CI time - **test:** stabilize cooldown abort coverage case in integration testing +### 🏆 v3.8.0 Community Contributors + +Thank you to all **38 community contributors** who made v3.8.0 possible! 🎉 + +| Contributor | PRs | Contributions | +| :--------------------------------------------------------- | :-: | :------------------------------------------------------------ | +| [@oyi77](https://github.com/oyi77) | 7 | #2010, #2014, #2041, #2052, #2061, #2074, #2091, #2094, #2096 | +| [@backryun](https://github.com/backryun) | 4 | #1992, #2033, #2088, #2123 | +| [@dhaern](https://github.com/dhaern) | 4 | #2028, #2039, #2087, #2090 | +| [@Tentoxa](https://github.com/Tentoxa) | 2 | #2011, #2053 | +| [@wauputr4](https://github.com/wauputr4) | 2 | #2009, #2046 | +| [@payne0420](https://github.com/payne0420) | 1 | #2082 | +| [@Tr0sT](https://github.com/Tr0sT) | 1 | #2012 | +| [@AveryanAlex](https://github.com/AveryanAlex) | 1 | #2008 | +| [@nickwizard](https://github.com/nickwizard) | 1 | #1991 | +| [@rodrigogbbr-stack](https://github.com/rodrigogbbr-stack) | 1 | #1996 | +| [@NekoMonci12](https://github.com/NekoMonci12) | 1 | #1999 | +| [@congvc-dev](https://github.com/congvc-dev) | 1 | #2004 | +| [@tatsster](https://github.com/tatsster) | 1 | #2007 | +| [@xssdem](https://github.com/xssdem) | 1 | #2023 | +| [@bypanghu](https://github.com/bypanghu) | 1 | #2027 | +| [@herjarsa](https://github.com/herjarsa) | 1 | #2030 | +| [@wucm667](https://github.com/wucm667) | 1 | #2031 | +| [@hartmark](https://github.com/hartmark) | 1 | #2045 | +| [@ddarkr](https://github.com/ddarkr) | 1 | #2047 | +| [@tces1](https://github.com/tces1) | 1 | #2048 | +| [@guanbear](https://github.com/guanbear) | 1 | #2054 | +| [@Gi99lin](https://github.com/Gi99lin) | 1 | #2055 | +| [@ivan-mezentsev](https://github.com/ivan-mezentsev) | 1 | #2063 | +| [@JxnLexn](https://github.com/JxnLexn) | 1 | #2019 | +| [@yoviarpauzi](https://github.com/yoviarpauzi) | 1 | #2092 | +| [@rafacpti23](https://github.com/rafacpti23) | 1 | #2086 | +| [@gleber](https://github.com/gleber) | 1 | #2103 | +| [@rilham97](https://github.com/rilham97) | 1 | #2104 | +| [@Gioxaa](https://github.com/Gioxaa) | 1 | #2105 | +| [@boa-z](https://github.com/boa-z) | 1 | #2115 | +| [@eleata](https://github.com/eleata) | 1 | #2116 | +| [@rdself](https://github.com/rdself) | 1 | #2118 | +| [@clousky2020](https://github.com/clousky2020) | 1 | #2119 | +| [@abhinavjnu](https://github.com/abhinavjnu) | 1 | #2122 | +| [@HoaPham98](https://github.com/HoaPham98) | 1 | #2089 | +| [@05dunski](https://github.com/05dunski) | 1 | #1978 (cherry-picked) | + ## [3.7.9] — 2026-05-03 ### ✨ New Features @@ -102,7 +220,7 @@ - **chore(provider):** Add reka models list (#1956 — thanks @backryun) - **chore(model):** Update new models, Delete Deprecated models (#1949 — thanks @backryun) -### 📝 Documentation +### Documentación - **docs(compression):** document RTK+Caveman stacked savings ranges @@ -201,7 +319,7 @@ - **feat(db):** auto-restore probe-failed database on startup to prevent data loss after failed upgrades (#1810) - **feat(analytics):** add cost-based usage insights and activity streaks in the analytics dashboard -### 🔒 Security +### Seguridad - **fix(security):** resolve ReDoS vulnerability in Codex executor regex patterns (#1797, #1789) @@ -354,7 +472,7 @@ We identified that **155 community PRs** across the entire project history (from - **feat(proxy):** implement bulk proxy import via pipe-delimited parser with update-or-create (upsert) logic and real-time preview table - **feat(pwa):** add fullscreen installable PWA with manifest, service worker, and cross-platform app icons (#1728) -### 🔒 Security +### Seguridad - **security:** replace insecure `Math.random` with `crypto.getRandomValues` for fallback UUID generation to resolve CodeQL CWE-338 finding (#182) @@ -519,7 +637,7 @@ We identified that **155 community PRs** across the entire project history (from - **fix(transport):** Prevent memory bloat and database exhaustion from large, fragmented streaming responses. Implemented `ByteQueue` in `kiro.ts` for zero-copy binary accumulation, refactored `antigravity.ts` for incremental SSE parsing, and enforced a strict 512KB tiered truncation limit (`MAX_CALL_LOG_ARTIFACT_BYTES`) on stream request logs and call artifacts (#1647). - **chore(ci):** Update build environment dependencies — bump Node to `24.15.0`, `actions/checkout@v6`, `docker/build-push-action@v7`, pin `actions/setup-python` to major tag (#1646 — thanks @backryun). -### 📝 Documentation +### Documentación - **docs(env):** Add `OMNIROUTE_ALLOW_PRIVATE_PROVIDER_URLS` to `.env.example` with documentation for LM Studio and other local provider use cases (#1623). @@ -669,7 +787,7 @@ We identified that **155 community PRs** across the entire project history (from - **test(next):** Align transpile package expectations for the Next.js standalone build. - **test(ci):** Fix CI-only test failures from environment differences — clear `INITIAL_PASSWORD` and `JWT_SECRET` in integration tests, handle `XDG_CONFIG_HOME` for guide-settings tests. -### 📚 Documentation +### Documentación - **docs:** Update the root changelog with all release-branch changes through 2026-04-24, including PRs #1544, #1555, #1551, #1550, #1548, #1547, #1541, #1538, #1536, and #1527. - **docs:** Fix broken README and localized documentation links. (#1536) @@ -811,7 +929,7 @@ We identified that **155 community PRs** across the entire project history (from - **feat(providers):** Expand image provider registry with extended model support including SD3.5, FLUX, and DALL-E 3 HD configurations - **feat(combos):** Add new routing strategies and full i18n support for agent features section across 31 languages -### 🔒 Security +### Seguridad - **security:** Resolve 18 GitHub CodeQL scan alerts including ReDoS, incomplete sanitization, and bad HTML filtering regexp patterns - **fix(auth):** Seal privilege escalation vector by enforcing JWT session checking exclusively on `/api/keys` management endpoints (#1353) @@ -1078,7 +1196,7 @@ We identified that **155 community PRs** across the entire project history (from - **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 - **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 -### 🔒 Security +### Seguridad - **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 - **Auth Guard on Translator Save:** Added `isAuthenticated` guard to `/api/translator/save` for defense-in-depth consistency @@ -1483,7 +1601,7 @@ We identified that **155 community PRs** across the entire project history (from - **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). -### 📚 Documentation +### Documentació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. - **Context Relay Delivery Notes:** Documented the current architecture, runtime flow, and Codex-focused scope in the feature docs, changelog, and agent guidance. @@ -1559,7 +1677,7 @@ We identified that **155 community PRs** across the entire project history (from ## [3.5.3] - 2026-04-07 -### Security +### Seguridad - **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. - **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. @@ -1575,7 +1693,7 @@ We identified that **155 community PRs** across the entire project history (from - **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. -### Documentation +### Documentación - **I18n Engine:** Synchronized and pushed deep Machine Translation updates across all 32 natively-supported languages (682 translation nodes aligned). @@ -1736,7 +1854,7 @@ We identified that **155 community PRs** across the entire project history (from ## [3.4.8] — 2026-04-03 -### Security +### Seguridad - Fully remediated all outstanding Github Advanced Security (CodeQL) findings and Dependabot alerts. - Fixed insecure randomness vulnerabilities by migrating from `Math.random` to `crypto.randomUUID()`. @@ -1748,7 +1866,7 @@ We identified that **155 community PRs** across the entire project history (from ## [3.4.7] — 2026-04-03 -### Features +### Funcionalidades - Added `Cryptography` node to Monitoring and MCP health checks (#798) - Hardened model-catalog route permissions mapping (`/models`) (#781) @@ -1764,7 +1882,7 @@ We identified that **155 community PRs** across the entire project history (from - Fixed MCP standalone module-resolution (`ERR_MODULE_NOT_FOUND`) via `esbuild` (#936) - Fixed NVIDIA NIM routing credential resolution alias mismatch (#931) -### Security +### Seguridad - Added safe strict input boundary protection against raw `shell: true` remote-code execution injections. @@ -2011,7 +2129,7 @@ We identified that **155 community PRs** across the entire project history (from ## [3.4.0] - 2026-03-31 -### 🚀 Features +### Funcionalidades - **Subscription Utilization Analytics:** Added quota snapshot time-series tracking, Provider Utilization and Combo Health tabs with recharts visualizations, and corresponding API endpoints (#847) - **SQLite Backup Control:** New `OMNIROUTE_DISABLE_AUTO_BACKUP` env flag to disable automatic SQLite backups (#846) @@ -2063,7 +2181,7 @@ We identified that **155 community PRs** across the entire project history (from ## [3.3.8] - 2026-03-30 -### 🚀 Features +### Funcionalidades - **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) - **Qoder Integration:** Native integration for Qoder AI natively replacing the legacy iFlow platform mappings (#660) @@ -2889,7 +3007,7 @@ We identified that **155 community PRs** across the entire project history (from - **NaN tokens in Claude Code / client responses (#617):** - `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 -### 🔒 Security +### Seguridad - Updated `yaml` package to fix stack overflow vulnerability (GHSA-48c2-rrv3-qjmp) @@ -3565,7 +3683,7 @@ docker pull diegosouzapw/omniroute:3.0.0 - **SVG fallback**: `ProviderIcon` component updated with 4-tier strategy: Lobehub → PNG → SVG → Generic icon - **Agents fingerprinting**: Synced with CLI tools — added droid, openclaw, copilot, opencode to fingerprint list (14 total) -### 🔒 Security +### Seguridad - **CVE fix**: Resolved dompurify XSS vulnerability (GHSA-v2wj-7wpq-c8vv) via npm overrides forcing `dompurify@^3.3.2` - `npm audit` now reports **0 vulnerabilities** @@ -3928,7 +4046,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **#510** — Windows: MSYS2/Git-Bash paths (`/c/Program Files/...`) are now normalized to `C:\Program Files\...` - **#492** — `omniroute` CLI now detects `mise`/`nvm` when `app/server.js` is missing and shows targeted fix -### 📖 Documentation +### Documentación - **#513** — Docker password reset: `INITIAL_PASSWORD` env var workaround documented - **#520** — pnpm: `pnpm approve-builds better-sqlite3` documented @@ -4025,7 +4143,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **feat(executors/cloudflare-ai)**: New `CloudflareAIExecutor` — dynamic URL construction requires `accountId` in provider credentials - **feat(executors)**: Register `pollinations`, `pol`, `cloudflare-ai`, `cf` executor mappings -### 📝 Documentation +### Documentación - **docs(readme)**: Expanded free combo stack to 11 providers ($0 forever) - **docs(readme)**: Added 4 new free provider sections (LongCat, Pollinations, Cloudflare AI, Scaleway) with model tables @@ -4177,7 +4295,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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). -### Features +### Funcionalidades - **"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. @@ -4205,7 +4323,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Merge PR #494 (MiniMax role fix), fix KIRO MITM dashboard, triage 8 issues. -### Features +### Funcionalidades - **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. - **roleNormalizer**: `normalizeDeveloperRole()` now accepts `preserveDeveloperRole` parameter with tri-state behavior (undefined=keep, true=keep, false=convert). @@ -4261,7 +4379,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Gemini CLI deprecation, VM guide i18n fix, dependabot security fix, provider schema expansion. -### Features +### Funcionalidades - **Gemini CLI Deprecation** (#462): Mark `gemini-cli` provider as deprecated with warning — Google restricts third-party OAuth usage from March 2026 - **Provider Schema** (#462): Expand Zod validation with `deprecated`, `deprecationReason`, `hasFree`, `freeNote`, `authHint`, `apiHint` optional fields @@ -4270,7 +4388,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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) -### Security +### Seguridad - **deps**: Bump `flatted` 3.3.3 → 3.4.2 — fixes CWE-1321 prototype pollution (#484, @dependabot) @@ -4290,7 +4408,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Czech i18n, SSE protocol fix, VM guide translation. -### Features +### Funcionalidades - **Czech Language** (#482): Full Czech (cs) i18n — 22 docs, 2606 UI strings, language switcher updates (@zen0bit) - **VM Deployment Guide**: Translated from Portuguese to English as the source document (@zen0bit) @@ -4309,7 +4427,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: 2 merged PRs, model aliases routing fix, log export, and issue triage. -### Features +### Funcionalidades - **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) @@ -4329,7 +4447,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Five community PRs — streaming call log fixes, Kiro compatibility, cache token analytics, Chinese translation, and configurable tool call IDs. -### ✨ Features +### Funcionalidades - **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) - **feat(providers)**: Per-model configurable 9-char tool call ID normalization (Mistral-style) — only models with the option enabled get truncated IDs (#470) @@ -4359,7 +4477,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Bailian Coding Plan provider with editable base URLs, plus community contributions for Alibaba Cloud and Kimi Coding. -### ✨ Features +### Funcionalidades - **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) - **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) @@ -4374,7 +4492,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Two new community-contributed providers (Alibaba Cloud Coding, Kimi Coding API-key) and Docker pino fix. -### ✨ Features +### Funcionalidades - **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) - **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) @@ -4399,7 +4517,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Codex responses subpath passthrough natively supported, Windows MITM crash fixed, and Combos agent schemas adjusted. -### ✨ Features +### Funcionalidades - **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) @@ -4439,7 +4557,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **fix(budget)**: "Save Limits" no longer returns 422 — `warningThreshold` is now correctly sent as fraction (0–1) instead of percentage (0–100) (#451) - **fix(combos)**: `` internal cache tag is now stripped before forwarding requests to providers, preventing cache session breaks (#454) -### ✨ Features +### Funcionalidades - **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) @@ -4495,7 +4613,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Search Tools dashboard, i18n fixes, Copilot limits, Serper validation fix. -### 🚀 Features +### Funcionalidades - **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) - New route: `/dashboard/search-tools` @@ -4595,7 +4713,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - DB migration: `request_type` column on `call_logs` for non-chat request tracking - Zod validation (`v1SearchSchema`), auth-gated, cost recorded via `recordCost()` -### 🔒 Security +### Seguridad - **deps**: Next.js 16.1.6 → 16.1.7 — fixes 6 CVEs: - **Critical**: CVE-2026-29057 (HTTP request smuggling via http-proxy) @@ -4725,7 +4843,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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**: New `request_detail_logs` table with 500-entry ring-buffer trigger, opt-in via settings toggle -### ✨ Features +### Funcionalidades - **feat(combo)**: System Message Override per Combo (#399 — `system_message` field replaces or injects system prompt before forwarding to provider) - **feat(combo)**: Tool Filter Regex per Combo (#399 — `tool_filter_regex` keeps only tools matching pattern; supports OpenAI + Anthropic formats) @@ -4740,7 +4858,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: SSE improvements, local provider_nodes extensions, proxy registry, Claude passthrough fixes. -### ✨ Features +### Funcionalidades - **feat(health)**: Background health check for local `provider_nodes` with exponential backoff (30s→300s) and `Promise.allSettled` to avoid blocking (#423, @Regis-RCR) - **feat(embeddings)**: Route `/v1/embeddings` to local `provider_nodes` — `buildDynamicEmbeddingProvider()` with hostname validation (#422, @Regis-RCR) @@ -4882,7 +5000,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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 - **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). -### ✨ Features +### Funcionalidades - **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) @@ -4912,7 +5030,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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) - **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) -### ✨ Features +### Funcionalidades - **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) - **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. @@ -4971,7 +5089,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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) - **fix(logs)**: Request log table is now readable in light mode — status badges, token counts, and combo tags use adaptive `dark:` color classes (#378) -### ✨ Features +### Funcionalidades - **feat(kiro)**: Kiro credit tracking added to usage fetcher — queries `getUserCredits` from AWS CodeWhisperer endpoint (#337) @@ -5372,7 +5490,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > **Major release** — Free Stack ecosystem, transcription playground overhaul, 44+ providers, comprehensive free tier documentation, and UI improvements across the board. -### ✨ Features +### Funcionalidades - **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. - **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. @@ -5383,7 +5501,7 @@ OmniRoute now automatically refreshes model lists for connected providers every ## [2.3.16] - 2026-03-13 -### 📖 Documentation +### Documentación - **README: 44+ Providers** — Updated all 3 occurrences of "36+ providers" to "44+" reflecting the actual codebase count (44 providers in providers.ts) - **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. @@ -5393,7 +5511,7 @@ OmniRoute now automatically refreshes model lists for connected providers every ## [2.3.15] - 2026-03-13 -### ✨ Features +### Funcionalidades - **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. - **i18n — autoCombo section**: Added 20 new translation keys for the Auto-Combo dashboard (`title`, `status`, `modePack`, `providerScores`, `factorTierPriority`, etc.) to all 30 language files. diff --git a/docs/i18n/fi/CHANGELOG.md b/docs/i18n/fi/CHANGELOG.md index d7fe8b9116..f7f5a57c95 100644 --- a/docs/i18n/fi/CHANGELOG.md +++ b/docs/i18n/fi/CHANGELOG.md @@ -10,30 +10,148 @@ ### ✨ New Features -- **feat(antigravity):** integrate Antigravity provider with dynamic `maxOutputTokens` calculation (bumping to `thinkingBudget + 1`) and standard Cloud Code envelope payload sanitization (#2055, #2063) +- **feat(antigravity):** integrate Antigravity provider with dynamic `maxOutputTokens` calculation, identity fingerprinting overhaul, and Cloud Code envelope payload sanitization (#2055, #2063) - **feat(gemini-cli):** add custom projectId support for Gemini CLI transport (UI, DB, executor) (#1991) +- **feat(providers):** add KIE media provider support with dynamic polling, text models, and expanded video models catalog +- **feat(providers):** add Z.AI provider support with GLM quota handling and new quota labels +- **feat(providers):** add 9 new free AI providers — LLM7, Lepton, Kluster, UncloseAI, BazaarLink, Completions, Enally, FreeTheAi (#2096) +- **feat(providers):** batch delete provider connections via checkbox multi-select (#2094) +- **feat(cursor):** full OpenAI parity — tool calls, streaming, and session management (#2082) +- **feat(cli):** comprehensive CLI enhancement suite with 20+ new commands including `omniroute providers`, `omniroute combos`, `omniroute doctor` (#2074) +- **feat(cli):** add modular CLI setup and provider management commands (#2046) +- **feat(mcp):** add DeepSeek quota and limit monitoring feature (#2089) +- **feat(circuit-breaker):** classify 429 errors and apply per-kind cooldowns (#2116) +- **feat(multi):** manifest-aware tier routing — W1-W4 complete (#2014) +- **feat(combos):** add reset-aware routing strategy for quota-based providers +- **feat(combo):** add context_length input field to combo edit form (#2047) +- **feat(chat):** dynamic tool limit detection with proactive truncation (#2061) +- **feat(sse):** refresh Claude OAuth wire image to claude-cli/2.1.131 (#2011) +- **feat(github):** add `targetFormat: openai-responses` to all GitHub models (#2122) +- **feat(api):** allow configuration via API calls — open management routes to Bearer keys with manage scope (#2103) +- **feat(api):** update API bridge proxy timeout to 600,000ms (#2019) +- **feat(usage):** add service tier breakdown, codex fast service tier analytics, and account for fast tier +- **feat(chat):** add `STREAM_READINESS_TIMEOUT_MS` and integrate into chat handling +- **feat(combo):** add `fallbackDelayMs` to combo configuration and related settings +- **feat(chat):** enhance error handling for semaphore capacity with fallback logic +- **feat(qdrant):** embedding model discovery (#2086) +- **feat(auth):** per-session sticky routing for Codex (#1887) +- **feat(inworld):** enhance Inworld TTS support (#2123) ### 🐛 Bug Fixes +- **fix(pricing):** make `getPricingForModel` fully case-insensitive to ensure custom prices correctly reflect in new incoming requests cost calculations +- **fix(gemini):** prevent `functionDeclarations` from being dropped by the sanitizer when `googleSearch` tool is present (#2077) +- **fix(pollinations):** add `jsonMode: true` flag in the request transformation to enforce correct JSON structure from Pollinations API (#2109) +- **fix(docker):** update Dockerfile to copy `/docs` directory during build ensuring API catalog availability at runtime (#2083) +- **fix(docker):** include OpenAPI spec in runtime image (#2007) +- **fix(providers):** strip OpenAI-specific fields in Kiro translator to prevent 400 errors (#2037) +- **fix(kiro):** normalize tool-use payloads to prevent 400 errors from agents (#2104) +- **fix(kiro):** merge adjacent user history turns after role normalization (#2105) +- **fix(ui):** resolve text contrast issues for zero-config warning banner in light mode (#2050) +- **fix(core):** inject global system prompt correctly into downstream chat completions pipeline (#2080) +- **fix(core):** restore Claude Code adaptive thinking defaults and resolve audio transcription CORS regression +- **fix(routing):** add missing v1beta rewrites to next.config to resolve 404 on Gemini models endpoint (#2102) +- **fix(routing):** fix bare GPT-5.5 routing for Codex-only installations (#2054) +- **fix(routing):** add fuzzy auto-combo routing for `auto/*` model prefix (#2010) - **fix(cache):** optimize cache_control preservation logic and explicitly align tool schema with upstream Claude Code expectations - **fix(db):** preserve legacy SQLite database path on Windows to prevent data loss (#1973) +- **fix(db):** reduce hot-path persistence overhead (#2039) +- **fix(db):** resolve migration conflict by renumbering overlapping migration entries (#2041) - **fix(settings):** resolve model alias persistence double stringification preventing UI updates (#2018) - **fix(routing):** dynamically filter bare model auto-resolution by active provider connections to prevent dead-routing (#2029) - **fix(embeddings):** add Google Gemini embeddings compatibility via OpenAI-compatible endpoint mapping (#2006) +- **fix(sse):** prevent Claude OAuth multi-account correlation via metadata.user_id (#2053) +- **fix(sse):** prevent Claude Code identity cloak overrides and fix fallback resilience (#2053) +- **fix(sse):** classify hour quota errors as QUOTA_EXHAUSTED (#2119) +- **fix(sse):** fix CC-compatible streaming bridge (#2118) +- **fix(antigravity):** sanitize Claude Cloud Code payloads (#2090) +- **fix(antigravity):** add duplex half for streaming bodies +- **fix(antigravity):** align identity protocol and behavior with official AM +- **fix(chatgpt-web):** plumb proxy through to native tls-client (#2022, #2023) +- **fix(codex):** expose native model IDs in catalog (#2012) +- **fix(glm):** add dedicated coding transport (#2087) +- **fix(compression):** support Responses input and expand Spanish compression rules (#2028) +- **fix(catalog):** auto-calculate combo context_length from target model limits (#2030) +- **fix(api):** fix usage analytics and API key identity (#2008, #2092) +- **fix(api-key):** allow Unicode letters in API key name validation (#1996) +- **fix(auth):** allow bootstrap without password (#2048) +- **fix(proxy):** clean up proxy page redundancy and fix 1proxy sync empty body error (#2052) +- **fix(dashboard):** resolve Unknown plan display in Provider Limits +- **fix(usage):** add extensible CURRENCY_SYMBOLS mapping for deepseek currencies +- **fix(runtime):** harden timer handling and model pricing fallback +- **fix(i18n):** complete Simplified Chinese translations (#2115) +- **fix(mitm):** add Linux cert install and skip sudo password when root (#1999) +- **fix(mitm):** prevent stub from loading at runtime via bypass module - **fix:** remove Anthropic-Beta header from non-Anthropic providers to fix identity contamination (#1989) - **fix(cli):** resolve .env loading failure for global npm installations +- **fix(export):** exclude telemetry/usage-history tables from JSON config backups by default to prevent unbounded file growth (#2125) +- **fix:** Follow OpenAI specification, handle throttling in batch and fix UI (#2045) -### 🔒 Security +### Turvallisuus +- **fix(security):** remediate CodeQL vulnerabilities (ReDoS, cryptographic bias, stack trace exposure, and weak password hashing) (#216, #215, #211, #208, #206, #210) - **fix(security):** remediate regex validation backtracking path in core compression cleanup (#1990) - **fix(core):** harden input handling and stabilization for prompt compression edge cases +### Dokumentaatio + +- **docs:** add competitive marketing tables and SEO/AEO optimizations to README (#2091) +- **docs:** refresh providers, model catalogs, and docs for v3.8.0 (#2088) +- **docs:** update Claude MD and update GLM-CN max context to 200k (#2027) +- **docs(env):** add `GITLAB_DUO_OAUTH_CLIENT_ID` to `.env.example` (#2031) + ### 🧹 Chores & Maintenance - **chore(providers):** prune redundant local provider icon assets in favor of `@lobehub/icons` web fonts (#1992) +- **chore(providers):** remove deprecated models (#2033) +- **deps:** bump `fast-uri` from 3.1.0 to 3.1.2 (#2078) +- **deps:** bump `hono` from 4.12.14 to 4.12.18 (#2079) - **ci:** skip SonarCloud scan on main pushes to optimize CI time - **test:** stabilize cooldown abort coverage case in integration testing +### 🏆 v3.8.0 Community Contributors + +Thank you to all **38 community contributors** who made v3.8.0 possible! 🎉 + +| Contributor | PRs | Contributions | +| :--------------------------------------------------------- | :-: | :------------------------------------------------------------ | +| [@oyi77](https://github.com/oyi77) | 7 | #2010, #2014, #2041, #2052, #2061, #2074, #2091, #2094, #2096 | +| [@backryun](https://github.com/backryun) | 4 | #1992, #2033, #2088, #2123 | +| [@dhaern](https://github.com/dhaern) | 4 | #2028, #2039, #2087, #2090 | +| [@Tentoxa](https://github.com/Tentoxa) | 2 | #2011, #2053 | +| [@wauputr4](https://github.com/wauputr4) | 2 | #2009, #2046 | +| [@payne0420](https://github.com/payne0420) | 1 | #2082 | +| [@Tr0sT](https://github.com/Tr0sT) | 1 | #2012 | +| [@AveryanAlex](https://github.com/AveryanAlex) | 1 | #2008 | +| [@nickwizard](https://github.com/nickwizard) | 1 | #1991 | +| [@rodrigogbbr-stack](https://github.com/rodrigogbbr-stack) | 1 | #1996 | +| [@NekoMonci12](https://github.com/NekoMonci12) | 1 | #1999 | +| [@congvc-dev](https://github.com/congvc-dev) | 1 | #2004 | +| [@tatsster](https://github.com/tatsster) | 1 | #2007 | +| [@xssdem](https://github.com/xssdem) | 1 | #2023 | +| [@bypanghu](https://github.com/bypanghu) | 1 | #2027 | +| [@herjarsa](https://github.com/herjarsa) | 1 | #2030 | +| [@wucm667](https://github.com/wucm667) | 1 | #2031 | +| [@hartmark](https://github.com/hartmark) | 1 | #2045 | +| [@ddarkr](https://github.com/ddarkr) | 1 | #2047 | +| [@tces1](https://github.com/tces1) | 1 | #2048 | +| [@guanbear](https://github.com/guanbear) | 1 | #2054 | +| [@Gi99lin](https://github.com/Gi99lin) | 1 | #2055 | +| [@ivan-mezentsev](https://github.com/ivan-mezentsev) | 1 | #2063 | +| [@JxnLexn](https://github.com/JxnLexn) | 1 | #2019 | +| [@yoviarpauzi](https://github.com/yoviarpauzi) | 1 | #2092 | +| [@rafacpti23](https://github.com/rafacpti23) | 1 | #2086 | +| [@gleber](https://github.com/gleber) | 1 | #2103 | +| [@rilham97](https://github.com/rilham97) | 1 | #2104 | +| [@Gioxaa](https://github.com/Gioxaa) | 1 | #2105 | +| [@boa-z](https://github.com/boa-z) | 1 | #2115 | +| [@eleata](https://github.com/eleata) | 1 | #2116 | +| [@rdself](https://github.com/rdself) | 1 | #2118 | +| [@clousky2020](https://github.com/clousky2020) | 1 | #2119 | +| [@abhinavjnu](https://github.com/abhinavjnu) | 1 | #2122 | +| [@HoaPham98](https://github.com/HoaPham98) | 1 | #2089 | +| [@05dunski](https://github.com/05dunski) | 1 | #1978 (cherry-picked) | + ## [3.7.9] — 2026-05-03 ### ✨ New Features @@ -102,7 +220,7 @@ - **chore(provider):** Add reka models list (#1956 — thanks @backryun) - **chore(model):** Update new models, Delete Deprecated models (#1949 — thanks @backryun) -### 📝 Documentation +### Dokumentaatio - **docs(compression):** document RTK+Caveman stacked savings ranges @@ -201,7 +319,7 @@ - **feat(db):** auto-restore probe-failed database on startup to prevent data loss after failed upgrades (#1810) - **feat(analytics):** add cost-based usage insights and activity streaks in the analytics dashboard -### 🔒 Security +### Turvallisuus - **fix(security):** resolve ReDoS vulnerability in Codex executor regex patterns (#1797, #1789) @@ -354,7 +472,7 @@ We identified that **155 community PRs** across the entire project history (from - **feat(proxy):** implement bulk proxy import via pipe-delimited parser with update-or-create (upsert) logic and real-time preview table - **feat(pwa):** add fullscreen installable PWA with manifest, service worker, and cross-platform app icons (#1728) -### 🔒 Security +### Turvallisuus - **security:** replace insecure `Math.random` with `crypto.getRandomValues` for fallback UUID generation to resolve CodeQL CWE-338 finding (#182) @@ -519,7 +637,7 @@ We identified that **155 community PRs** across the entire project history (from - **fix(transport):** Prevent memory bloat and database exhaustion from large, fragmented streaming responses. Implemented `ByteQueue` in `kiro.ts` for zero-copy binary accumulation, refactored `antigravity.ts` for incremental SSE parsing, and enforced a strict 512KB tiered truncation limit (`MAX_CALL_LOG_ARTIFACT_BYTES`) on stream request logs and call artifacts (#1647). - **chore(ci):** Update build environment dependencies — bump Node to `24.15.0`, `actions/checkout@v6`, `docker/build-push-action@v7`, pin `actions/setup-python` to major tag (#1646 — thanks @backryun). -### 📝 Documentation +### Dokumentaatio - **docs(env):** Add `OMNIROUTE_ALLOW_PRIVATE_PROVIDER_URLS` to `.env.example` with documentation for LM Studio and other local provider use cases (#1623). @@ -669,7 +787,7 @@ We identified that **155 community PRs** across the entire project history (from - **test(next):** Align transpile package expectations for the Next.js standalone build. - **test(ci):** Fix CI-only test failures from environment differences — clear `INITIAL_PASSWORD` and `JWT_SECRET` in integration tests, handle `XDG_CONFIG_HOME` for guide-settings tests. -### 📚 Documentation +### Dokumentaatio - **docs:** Update the root changelog with all release-branch changes through 2026-04-24, including PRs #1544, #1555, #1551, #1550, #1548, #1547, #1541, #1538, #1536, and #1527. - **docs:** Fix broken README and localized documentation links. (#1536) @@ -811,7 +929,7 @@ We identified that **155 community PRs** across the entire project history (from - **feat(providers):** Expand image provider registry with extended model support including SD3.5, FLUX, and DALL-E 3 HD configurations - **feat(combos):** Add new routing strategies and full i18n support for agent features section across 31 languages -### 🔒 Security +### Turvallisuus - **security:** Resolve 18 GitHub CodeQL scan alerts including ReDoS, incomplete sanitization, and bad HTML filtering regexp patterns - **fix(auth):** Seal privilege escalation vector by enforcing JWT session checking exclusively on `/api/keys` management endpoints (#1353) @@ -1078,7 +1196,7 @@ We identified that **155 community PRs** across the entire project history (from - **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 - **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 -### 🔒 Security +### Turvallisuus - **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 - **Auth Guard on Translator Save:** Added `isAuthenticated` guard to `/api/translator/save` for defense-in-depth consistency @@ -1483,7 +1601,7 @@ We identified that **155 community PRs** across the entire project history (from - **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). -### 📚 Documentation +### Dokumentaatio - **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. - **Context Relay Delivery Notes:** Documented the current architecture, runtime flow, and Codex-focused scope in the feature docs, changelog, and agent guidance. @@ -1559,7 +1677,7 @@ We identified that **155 community PRs** across the entire project history (from ## [3.5.3] - 2026-04-07 -### Security +### Turvallisuus - **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. - **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. @@ -1575,7 +1693,7 @@ We identified that **155 community PRs** across the entire project history (from - **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. -### Documentation +### Dokumentaatio - **I18n Engine:** Synchronized and pushed deep Machine Translation updates across all 32 natively-supported languages (682 translation nodes aligned). @@ -1736,7 +1854,7 @@ We identified that **155 community PRs** across the entire project history (from ## [3.4.8] — 2026-04-03 -### Security +### Turvallisuus - Fully remediated all outstanding Github Advanced Security (CodeQL) findings and Dependabot alerts. - Fixed insecure randomness vulnerabilities by migrating from `Math.random` to `crypto.randomUUID()`. @@ -1748,7 +1866,7 @@ We identified that **155 community PRs** across the entire project history (from ## [3.4.7] — 2026-04-03 -### Features +### Ominaisuudet - Added `Cryptography` node to Monitoring and MCP health checks (#798) - Hardened model-catalog route permissions mapping (`/models`) (#781) @@ -1764,7 +1882,7 @@ We identified that **155 community PRs** across the entire project history (from - Fixed MCP standalone module-resolution (`ERR_MODULE_NOT_FOUND`) via `esbuild` (#936) - Fixed NVIDIA NIM routing credential resolution alias mismatch (#931) -### Security +### Turvallisuus - Added safe strict input boundary protection against raw `shell: true` remote-code execution injections. @@ -2011,7 +2129,7 @@ We identified that **155 community PRs** across the entire project history (from ## [3.4.0] - 2026-03-31 -### 🚀 Features +### Ominaisuudet - **Subscription Utilization Analytics:** Added quota snapshot time-series tracking, Provider Utilization and Combo Health tabs with recharts visualizations, and corresponding API endpoints (#847) - **SQLite Backup Control:** New `OMNIROUTE_DISABLE_AUTO_BACKUP` env flag to disable automatic SQLite backups (#846) @@ -2063,7 +2181,7 @@ We identified that **155 community PRs** across the entire project history (from ## [3.3.8] - 2026-03-30 -### 🚀 Features +### Ominaisuudet - **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) - **Qoder Integration:** Native integration for Qoder AI natively replacing the legacy iFlow platform mappings (#660) @@ -2889,7 +3007,7 @@ We identified that **155 community PRs** across the entire project history (from - **NaN tokens in Claude Code / client responses (#617):** - `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 -### 🔒 Security +### Turvallisuus - Updated `yaml` package to fix stack overflow vulnerability (GHSA-48c2-rrv3-qjmp) @@ -3565,7 +3683,7 @@ docker pull diegosouzapw/omniroute:3.0.0 - **SVG fallback**: `ProviderIcon` component updated with 4-tier strategy: Lobehub → PNG → SVG → Generic icon - **Agents fingerprinting**: Synced with CLI tools — added droid, openclaw, copilot, opencode to fingerprint list (14 total) -### 🔒 Security +### Turvallisuus - **CVE fix**: Resolved dompurify XSS vulnerability (GHSA-v2wj-7wpq-c8vv) via npm overrides forcing `dompurify@^3.3.2` - `npm audit` now reports **0 vulnerabilities** @@ -3928,7 +4046,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **#510** — Windows: MSYS2/Git-Bash paths (`/c/Program Files/...`) are now normalized to `C:\Program Files\...` - **#492** — `omniroute` CLI now detects `mise`/`nvm` when `app/server.js` is missing and shows targeted fix -### 📖 Documentation +### Dokumentaatio - **#513** — Docker password reset: `INITIAL_PASSWORD` env var workaround documented - **#520** — pnpm: `pnpm approve-builds better-sqlite3` documented @@ -4025,7 +4143,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **feat(executors/cloudflare-ai)**: New `CloudflareAIExecutor` — dynamic URL construction requires `accountId` in provider credentials - **feat(executors)**: Register `pollinations`, `pol`, `cloudflare-ai`, `cf` executor mappings -### 📝 Documentation +### Dokumentaatio - **docs(readme)**: Expanded free combo stack to 11 providers ($0 forever) - **docs(readme)**: Added 4 new free provider sections (LongCat, Pollinations, Cloudflare AI, Scaleway) with model tables @@ -4177,7 +4295,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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). -### Features +### Ominaisuudet - **"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. @@ -4205,7 +4323,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Merge PR #494 (MiniMax role fix), fix KIRO MITM dashboard, triage 8 issues. -### Features +### Ominaisuudet - **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. - **roleNormalizer**: `normalizeDeveloperRole()` now accepts `preserveDeveloperRole` parameter with tri-state behavior (undefined=keep, true=keep, false=convert). @@ -4261,7 +4379,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Gemini CLI deprecation, VM guide i18n fix, dependabot security fix, provider schema expansion. -### Features +### Ominaisuudet - **Gemini CLI Deprecation** (#462): Mark `gemini-cli` provider as deprecated with warning — Google restricts third-party OAuth usage from March 2026 - **Provider Schema** (#462): Expand Zod validation with `deprecated`, `deprecationReason`, `hasFree`, `freeNote`, `authHint`, `apiHint` optional fields @@ -4270,7 +4388,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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) -### Security +### Turvallisuus - **deps**: Bump `flatted` 3.3.3 → 3.4.2 — fixes CWE-1321 prototype pollution (#484, @dependabot) @@ -4290,7 +4408,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Czech i18n, SSE protocol fix, VM guide translation. -### Features +### Ominaisuudet - **Czech Language** (#482): Full Czech (cs) i18n — 22 docs, 2606 UI strings, language switcher updates (@zen0bit) - **VM Deployment Guide**: Translated from Portuguese to English as the source document (@zen0bit) @@ -4309,7 +4427,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: 2 merged PRs, model aliases routing fix, log export, and issue triage. -### Features +### Ominaisuudet - **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) @@ -4329,7 +4447,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Five community PRs — streaming call log fixes, Kiro compatibility, cache token analytics, Chinese translation, and configurable tool call IDs. -### ✨ Features +### Ominaisuudet - **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) - **feat(providers)**: Per-model configurable 9-char tool call ID normalization (Mistral-style) — only models with the option enabled get truncated IDs (#470) @@ -4359,7 +4477,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Bailian Coding Plan provider with editable base URLs, plus community contributions for Alibaba Cloud and Kimi Coding. -### ✨ Features +### Ominaisuudet - **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) - **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) @@ -4374,7 +4492,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Two new community-contributed providers (Alibaba Cloud Coding, Kimi Coding API-key) and Docker pino fix. -### ✨ Features +### Ominaisuudet - **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) - **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) @@ -4399,7 +4517,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Codex responses subpath passthrough natively supported, Windows MITM crash fixed, and Combos agent schemas adjusted. -### ✨ Features +### Ominaisuudet - **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) @@ -4439,7 +4557,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **fix(budget)**: "Save Limits" no longer returns 422 — `warningThreshold` is now correctly sent as fraction (0–1) instead of percentage (0–100) (#451) - **fix(combos)**: `` internal cache tag is now stripped before forwarding requests to providers, preventing cache session breaks (#454) -### ✨ Features +### Ominaisuudet - **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) @@ -4495,7 +4613,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Search Tools dashboard, i18n fixes, Copilot limits, Serper validation fix. -### 🚀 Features +### Ominaisuudet - **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) - New route: `/dashboard/search-tools` @@ -4595,7 +4713,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - DB migration: `request_type` column on `call_logs` for non-chat request tracking - Zod validation (`v1SearchSchema`), auth-gated, cost recorded via `recordCost()` -### 🔒 Security +### Turvallisuus - **deps**: Next.js 16.1.6 → 16.1.7 — fixes 6 CVEs: - **Critical**: CVE-2026-29057 (HTTP request smuggling via http-proxy) @@ -4725,7 +4843,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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**: New `request_detail_logs` table with 500-entry ring-buffer trigger, opt-in via settings toggle -### ✨ Features +### Ominaisuudet - **feat(combo)**: System Message Override per Combo (#399 — `system_message` field replaces or injects system prompt before forwarding to provider) - **feat(combo)**: Tool Filter Regex per Combo (#399 — `tool_filter_regex` keeps only tools matching pattern; supports OpenAI + Anthropic formats) @@ -4740,7 +4858,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: SSE improvements, local provider_nodes extensions, proxy registry, Claude passthrough fixes. -### ✨ Features +### Ominaisuudet - **feat(health)**: Background health check for local `provider_nodes` with exponential backoff (30s→300s) and `Promise.allSettled` to avoid blocking (#423, @Regis-RCR) - **feat(embeddings)**: Route `/v1/embeddings` to local `provider_nodes` — `buildDynamicEmbeddingProvider()` with hostname validation (#422, @Regis-RCR) @@ -4882,7 +5000,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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 - **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). -### ✨ Features +### Ominaisuudet - **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) @@ -4912,7 +5030,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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) - **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) -### ✨ Features +### Ominaisuudet - **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) - **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. @@ -4971,7 +5089,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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) - **fix(logs)**: Request log table is now readable in light mode — status badges, token counts, and combo tags use adaptive `dark:` color classes (#378) -### ✨ Features +### Ominaisuudet - **feat(kiro)**: Kiro credit tracking added to usage fetcher — queries `getUserCredits` from AWS CodeWhisperer endpoint (#337) @@ -5372,7 +5490,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > **Major release** — Free Stack ecosystem, transcription playground overhaul, 44+ providers, comprehensive free tier documentation, and UI improvements across the board. -### ✨ Features +### Ominaisuudet - **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. - **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. @@ -5383,7 +5501,7 @@ OmniRoute now automatically refreshes model lists for connected providers every ## [2.3.16] - 2026-03-13 -### 📖 Documentation +### Dokumentaatio - **README: 44+ Providers** — Updated all 3 occurrences of "36+ providers" to "44+" reflecting the actual codebase count (44 providers in providers.ts) - **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. @@ -5393,7 +5511,7 @@ OmniRoute now automatically refreshes model lists for connected providers every ## [2.3.15] - 2026-03-13 -### ✨ Features +### Ominaisuudet - **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. - **i18n — autoCombo section**: Added 20 new translation keys for the Auto-Combo dashboard (`title`, `status`, `modePack`, `providerScores`, `factorTierPriority`, etc.) to all 30 language files. diff --git a/docs/i18n/fr/CHANGELOG.md b/docs/i18n/fr/CHANGELOG.md index 97d2de860a..14f650e21f 100644 --- a/docs/i18n/fr/CHANGELOG.md +++ b/docs/i18n/fr/CHANGELOG.md @@ -10,30 +10,148 @@ ### ✨ New Features -- **feat(antigravity):** integrate Antigravity provider with dynamic `maxOutputTokens` calculation (bumping to `thinkingBudget + 1`) and standard Cloud Code envelope payload sanitization (#2055, #2063) +- **feat(antigravity):** integrate Antigravity provider with dynamic `maxOutputTokens` calculation, identity fingerprinting overhaul, and Cloud Code envelope payload sanitization (#2055, #2063) - **feat(gemini-cli):** add custom projectId support for Gemini CLI transport (UI, DB, executor) (#1991) +- **feat(providers):** add KIE media provider support with dynamic polling, text models, and expanded video models catalog +- **feat(providers):** add Z.AI provider support with GLM quota handling and new quota labels +- **feat(providers):** add 9 new free AI providers — LLM7, Lepton, Kluster, UncloseAI, BazaarLink, Completions, Enally, FreeTheAi (#2096) +- **feat(providers):** batch delete provider connections via checkbox multi-select (#2094) +- **feat(cursor):** full OpenAI parity — tool calls, streaming, and session management (#2082) +- **feat(cli):** comprehensive CLI enhancement suite with 20+ new commands including `omniroute providers`, `omniroute combos`, `omniroute doctor` (#2074) +- **feat(cli):** add modular CLI setup and provider management commands (#2046) +- **feat(mcp):** add DeepSeek quota and limit monitoring feature (#2089) +- **feat(circuit-breaker):** classify 429 errors and apply per-kind cooldowns (#2116) +- **feat(multi):** manifest-aware tier routing — W1-W4 complete (#2014) +- **feat(combos):** add reset-aware routing strategy for quota-based providers +- **feat(combo):** add context_length input field to combo edit form (#2047) +- **feat(chat):** dynamic tool limit detection with proactive truncation (#2061) +- **feat(sse):** refresh Claude OAuth wire image to claude-cli/2.1.131 (#2011) +- **feat(github):** add `targetFormat: openai-responses` to all GitHub models (#2122) +- **feat(api):** allow configuration via API calls — open management routes to Bearer keys with manage scope (#2103) +- **feat(api):** update API bridge proxy timeout to 600,000ms (#2019) +- **feat(usage):** add service tier breakdown, codex fast service tier analytics, and account for fast tier +- **feat(chat):** add `STREAM_READINESS_TIMEOUT_MS` and integrate into chat handling +- **feat(combo):** add `fallbackDelayMs` to combo configuration and related settings +- **feat(chat):** enhance error handling for semaphore capacity with fallback logic +- **feat(qdrant):** embedding model discovery (#2086) +- **feat(auth):** per-session sticky routing for Codex (#1887) +- **feat(inworld):** enhance Inworld TTS support (#2123) ### 🐛 Bug Fixes +- **fix(pricing):** make `getPricingForModel` fully case-insensitive to ensure custom prices correctly reflect in new incoming requests cost calculations +- **fix(gemini):** prevent `functionDeclarations` from being dropped by the sanitizer when `googleSearch` tool is present (#2077) +- **fix(pollinations):** add `jsonMode: true` flag in the request transformation to enforce correct JSON structure from Pollinations API (#2109) +- **fix(docker):** update Dockerfile to copy `/docs` directory during build ensuring API catalog availability at runtime (#2083) +- **fix(docker):** include OpenAPI spec in runtime image (#2007) +- **fix(providers):** strip OpenAI-specific fields in Kiro translator to prevent 400 errors (#2037) +- **fix(kiro):** normalize tool-use payloads to prevent 400 errors from agents (#2104) +- **fix(kiro):** merge adjacent user history turns after role normalization (#2105) +- **fix(ui):** resolve text contrast issues for zero-config warning banner in light mode (#2050) +- **fix(core):** inject global system prompt correctly into downstream chat completions pipeline (#2080) +- **fix(core):** restore Claude Code adaptive thinking defaults and resolve audio transcription CORS regression +- **fix(routing):** add missing v1beta rewrites to next.config to resolve 404 on Gemini models endpoint (#2102) +- **fix(routing):** fix bare GPT-5.5 routing for Codex-only installations (#2054) +- **fix(routing):** add fuzzy auto-combo routing for `auto/*` model prefix (#2010) - **fix(cache):** optimize cache_control preservation logic and explicitly align tool schema with upstream Claude Code expectations - **fix(db):** preserve legacy SQLite database path on Windows to prevent data loss (#1973) +- **fix(db):** reduce hot-path persistence overhead (#2039) +- **fix(db):** resolve migration conflict by renumbering overlapping migration entries (#2041) - **fix(settings):** resolve model alias persistence double stringification preventing UI updates (#2018) - **fix(routing):** dynamically filter bare model auto-resolution by active provider connections to prevent dead-routing (#2029) - **fix(embeddings):** add Google Gemini embeddings compatibility via OpenAI-compatible endpoint mapping (#2006) +- **fix(sse):** prevent Claude OAuth multi-account correlation via metadata.user_id (#2053) +- **fix(sse):** prevent Claude Code identity cloak overrides and fix fallback resilience (#2053) +- **fix(sse):** classify hour quota errors as QUOTA_EXHAUSTED (#2119) +- **fix(sse):** fix CC-compatible streaming bridge (#2118) +- **fix(antigravity):** sanitize Claude Cloud Code payloads (#2090) +- **fix(antigravity):** add duplex half for streaming bodies +- **fix(antigravity):** align identity protocol and behavior with official AM +- **fix(chatgpt-web):** plumb proxy through to native tls-client (#2022, #2023) +- **fix(codex):** expose native model IDs in catalog (#2012) +- **fix(glm):** add dedicated coding transport (#2087) +- **fix(compression):** support Responses input and expand Spanish compression rules (#2028) +- **fix(catalog):** auto-calculate combo context_length from target model limits (#2030) +- **fix(api):** fix usage analytics and API key identity (#2008, #2092) +- **fix(api-key):** allow Unicode letters in API key name validation (#1996) +- **fix(auth):** allow bootstrap without password (#2048) +- **fix(proxy):** clean up proxy page redundancy and fix 1proxy sync empty body error (#2052) +- **fix(dashboard):** resolve Unknown plan display in Provider Limits +- **fix(usage):** add extensible CURRENCY_SYMBOLS mapping for deepseek currencies +- **fix(runtime):** harden timer handling and model pricing fallback +- **fix(i18n):** complete Simplified Chinese translations (#2115) +- **fix(mitm):** add Linux cert install and skip sudo password when root (#1999) +- **fix(mitm):** prevent stub from loading at runtime via bypass module - **fix:** remove Anthropic-Beta header from non-Anthropic providers to fix identity contamination (#1989) - **fix(cli):** resolve .env loading failure for global npm installations +- **fix(export):** exclude telemetry/usage-history tables from JSON config backups by default to prevent unbounded file growth (#2125) +- **fix:** Follow OpenAI specification, handle throttling in batch and fix UI (#2045) -### 🔒 Security +### Sécurité +- **fix(security):** remediate CodeQL vulnerabilities (ReDoS, cryptographic bias, stack trace exposure, and weak password hashing) (#216, #215, #211, #208, #206, #210) - **fix(security):** remediate regex validation backtracking path in core compression cleanup (#1990) - **fix(core):** harden input handling and stabilization for prompt compression edge cases +### Documentation + +- **docs:** add competitive marketing tables and SEO/AEO optimizations to README (#2091) +- **docs:** refresh providers, model catalogs, and docs for v3.8.0 (#2088) +- **docs:** update Claude MD and update GLM-CN max context to 200k (#2027) +- **docs(env):** add `GITLAB_DUO_OAUTH_CLIENT_ID` to `.env.example` (#2031) + ### 🧹 Chores & Maintenance - **chore(providers):** prune redundant local provider icon assets in favor of `@lobehub/icons` web fonts (#1992) +- **chore(providers):** remove deprecated models (#2033) +- **deps:** bump `fast-uri` from 3.1.0 to 3.1.2 (#2078) +- **deps:** bump `hono` from 4.12.14 to 4.12.18 (#2079) - **ci:** skip SonarCloud scan on main pushes to optimize CI time - **test:** stabilize cooldown abort coverage case in integration testing +### 🏆 v3.8.0 Community Contributors + +Thank you to all **38 community contributors** who made v3.8.0 possible! 🎉 + +| Contributor | PRs | Contributions | +| :--------------------------------------------------------- | :-: | :------------------------------------------------------------ | +| [@oyi77](https://github.com/oyi77) | 7 | #2010, #2014, #2041, #2052, #2061, #2074, #2091, #2094, #2096 | +| [@backryun](https://github.com/backryun) | 4 | #1992, #2033, #2088, #2123 | +| [@dhaern](https://github.com/dhaern) | 4 | #2028, #2039, #2087, #2090 | +| [@Tentoxa](https://github.com/Tentoxa) | 2 | #2011, #2053 | +| [@wauputr4](https://github.com/wauputr4) | 2 | #2009, #2046 | +| [@payne0420](https://github.com/payne0420) | 1 | #2082 | +| [@Tr0sT](https://github.com/Tr0sT) | 1 | #2012 | +| [@AveryanAlex](https://github.com/AveryanAlex) | 1 | #2008 | +| [@nickwizard](https://github.com/nickwizard) | 1 | #1991 | +| [@rodrigogbbr-stack](https://github.com/rodrigogbbr-stack) | 1 | #1996 | +| [@NekoMonci12](https://github.com/NekoMonci12) | 1 | #1999 | +| [@congvc-dev](https://github.com/congvc-dev) | 1 | #2004 | +| [@tatsster](https://github.com/tatsster) | 1 | #2007 | +| [@xssdem](https://github.com/xssdem) | 1 | #2023 | +| [@bypanghu](https://github.com/bypanghu) | 1 | #2027 | +| [@herjarsa](https://github.com/herjarsa) | 1 | #2030 | +| [@wucm667](https://github.com/wucm667) | 1 | #2031 | +| [@hartmark](https://github.com/hartmark) | 1 | #2045 | +| [@ddarkr](https://github.com/ddarkr) | 1 | #2047 | +| [@tces1](https://github.com/tces1) | 1 | #2048 | +| [@guanbear](https://github.com/guanbear) | 1 | #2054 | +| [@Gi99lin](https://github.com/Gi99lin) | 1 | #2055 | +| [@ivan-mezentsev](https://github.com/ivan-mezentsev) | 1 | #2063 | +| [@JxnLexn](https://github.com/JxnLexn) | 1 | #2019 | +| [@yoviarpauzi](https://github.com/yoviarpauzi) | 1 | #2092 | +| [@rafacpti23](https://github.com/rafacpti23) | 1 | #2086 | +| [@gleber](https://github.com/gleber) | 1 | #2103 | +| [@rilham97](https://github.com/rilham97) | 1 | #2104 | +| [@Gioxaa](https://github.com/Gioxaa) | 1 | #2105 | +| [@boa-z](https://github.com/boa-z) | 1 | #2115 | +| [@eleata](https://github.com/eleata) | 1 | #2116 | +| [@rdself](https://github.com/rdself) | 1 | #2118 | +| [@clousky2020](https://github.com/clousky2020) | 1 | #2119 | +| [@abhinavjnu](https://github.com/abhinavjnu) | 1 | #2122 | +| [@HoaPham98](https://github.com/HoaPham98) | 1 | #2089 | +| [@05dunski](https://github.com/05dunski) | 1 | #1978 (cherry-picked) | + ## [3.7.9] — 2026-05-03 ### ✨ New Features @@ -102,7 +220,7 @@ - **chore(provider):** Add reka models list (#1956 — thanks @backryun) - **chore(model):** Update new models, Delete Deprecated models (#1949 — thanks @backryun) -### 📝 Documentation +### Documentation - **docs(compression):** document RTK+Caveman stacked savings ranges @@ -201,7 +319,7 @@ - **feat(db):** auto-restore probe-failed database on startup to prevent data loss after failed upgrades (#1810) - **feat(analytics):** add cost-based usage insights and activity streaks in the analytics dashboard -### 🔒 Security +### Sécurité - **fix(security):** resolve ReDoS vulnerability in Codex executor regex patterns (#1797, #1789) @@ -354,7 +472,7 @@ We identified that **155 community PRs** across the entire project history (from - **feat(proxy):** implement bulk proxy import via pipe-delimited parser with update-or-create (upsert) logic and real-time preview table - **feat(pwa):** add fullscreen installable PWA with manifest, service worker, and cross-platform app icons (#1728) -### 🔒 Security +### Sécurité - **security:** replace insecure `Math.random` with `crypto.getRandomValues` for fallback UUID generation to resolve CodeQL CWE-338 finding (#182) @@ -519,7 +637,7 @@ We identified that **155 community PRs** across the entire project history (from - **fix(transport):** Prevent memory bloat and database exhaustion from large, fragmented streaming responses. Implemented `ByteQueue` in `kiro.ts` for zero-copy binary accumulation, refactored `antigravity.ts` for incremental SSE parsing, and enforced a strict 512KB tiered truncation limit (`MAX_CALL_LOG_ARTIFACT_BYTES`) on stream request logs and call artifacts (#1647). - **chore(ci):** Update build environment dependencies — bump Node to `24.15.0`, `actions/checkout@v6`, `docker/build-push-action@v7`, pin `actions/setup-python` to major tag (#1646 — thanks @backryun). -### 📝 Documentation +### Documentation - **docs(env):** Add `OMNIROUTE_ALLOW_PRIVATE_PROVIDER_URLS` to `.env.example` with documentation for LM Studio and other local provider use cases (#1623). @@ -669,7 +787,7 @@ We identified that **155 community PRs** across the entire project history (from - **test(next):** Align transpile package expectations for the Next.js standalone build. - **test(ci):** Fix CI-only test failures from environment differences — clear `INITIAL_PASSWORD` and `JWT_SECRET` in integration tests, handle `XDG_CONFIG_HOME` for guide-settings tests. -### 📚 Documentation +### Documentation - **docs:** Update the root changelog with all release-branch changes through 2026-04-24, including PRs #1544, #1555, #1551, #1550, #1548, #1547, #1541, #1538, #1536, and #1527. - **docs:** Fix broken README and localized documentation links. (#1536) @@ -811,7 +929,7 @@ We identified that **155 community PRs** across the entire project history (from - **feat(providers):** Expand image provider registry with extended model support including SD3.5, FLUX, and DALL-E 3 HD configurations - **feat(combos):** Add new routing strategies and full i18n support for agent features section across 31 languages -### 🔒 Security +### Sécurité - **security:** Resolve 18 GitHub CodeQL scan alerts including ReDoS, incomplete sanitization, and bad HTML filtering regexp patterns - **fix(auth):** Seal privilege escalation vector by enforcing JWT session checking exclusively on `/api/keys` management endpoints (#1353) @@ -1078,7 +1196,7 @@ We identified that **155 community PRs** across the entire project history (from - **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 - **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 -### 🔒 Security +### Sécurité - **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 - **Auth Guard on Translator Save:** Added `isAuthenticated` guard to `/api/translator/save` for defense-in-depth consistency @@ -1483,7 +1601,7 @@ We identified that **155 community PRs** across the entire project history (from - **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). -### 📚 Documentation +### Documentation - **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. - **Context Relay Delivery Notes:** Documented the current architecture, runtime flow, and Codex-focused scope in the feature docs, changelog, and agent guidance. @@ -1559,7 +1677,7 @@ We identified that **155 community PRs** across the entire project history (from ## [3.5.3] - 2026-04-07 -### Security +### Sécurité - **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. - **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. @@ -1736,7 +1854,7 @@ We identified that **155 community PRs** across the entire project history (from ## [3.4.8] — 2026-04-03 -### Security +### Sécurité - Fully remediated all outstanding Github Advanced Security (CodeQL) findings and Dependabot alerts. - Fixed insecure randomness vulnerabilities by migrating from `Math.random` to `crypto.randomUUID()`. @@ -1748,7 +1866,7 @@ We identified that **155 community PRs** across the entire project history (from ## [3.4.7] — 2026-04-03 -### Features +### Fonctionnalités - Added `Cryptography` node to Monitoring and MCP health checks (#798) - Hardened model-catalog route permissions mapping (`/models`) (#781) @@ -1764,7 +1882,7 @@ We identified that **155 community PRs** across the entire project history (from - Fixed MCP standalone module-resolution (`ERR_MODULE_NOT_FOUND`) via `esbuild` (#936) - Fixed NVIDIA NIM routing credential resolution alias mismatch (#931) -### Security +### Sécurité - Added safe strict input boundary protection against raw `shell: true` remote-code execution injections. @@ -2011,7 +2129,7 @@ We identified that **155 community PRs** across the entire project history (from ## [3.4.0] - 2026-03-31 -### 🚀 Features +### Fonctionnalités - **Subscription Utilization Analytics:** Added quota snapshot time-series tracking, Provider Utilization and Combo Health tabs with recharts visualizations, and corresponding API endpoints (#847) - **SQLite Backup Control:** New `OMNIROUTE_DISABLE_AUTO_BACKUP` env flag to disable automatic SQLite backups (#846) @@ -2063,7 +2181,7 @@ We identified that **155 community PRs** across the entire project history (from ## [3.3.8] - 2026-03-30 -### 🚀 Features +### Fonctionnalités - **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) - **Qoder Integration:** Native integration for Qoder AI natively replacing the legacy iFlow platform mappings (#660) @@ -2889,7 +3007,7 @@ We identified that **155 community PRs** across the entire project history (from - **NaN tokens in Claude Code / client responses (#617):** - `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 -### 🔒 Security +### Sécurité - Updated `yaml` package to fix stack overflow vulnerability (GHSA-48c2-rrv3-qjmp) @@ -3565,7 +3683,7 @@ docker pull diegosouzapw/omniroute:3.0.0 - **SVG fallback**: `ProviderIcon` component updated with 4-tier strategy: Lobehub → PNG → SVG → Generic icon - **Agents fingerprinting**: Synced with CLI tools — added droid, openclaw, copilot, opencode to fingerprint list (14 total) -### 🔒 Security +### Sécurité - **CVE fix**: Resolved dompurify XSS vulnerability (GHSA-v2wj-7wpq-c8vv) via npm overrides forcing `dompurify@^3.3.2` - `npm audit` now reports **0 vulnerabilities** @@ -3928,7 +4046,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **#510** — Windows: MSYS2/Git-Bash paths (`/c/Program Files/...`) are now normalized to `C:\Program Files\...` - **#492** — `omniroute` CLI now detects `mise`/`nvm` when `app/server.js` is missing and shows targeted fix -### 📖 Documentation +### Documentation - **#513** — Docker password reset: `INITIAL_PASSWORD` env var workaround documented - **#520** — pnpm: `pnpm approve-builds better-sqlite3` documented @@ -4025,7 +4143,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **feat(executors/cloudflare-ai)**: New `CloudflareAIExecutor` — dynamic URL construction requires `accountId` in provider credentials - **feat(executors)**: Register `pollinations`, `pol`, `cloudflare-ai`, `cf` executor mappings -### 📝 Documentation +### Documentation - **docs(readme)**: Expanded free combo stack to 11 providers ($0 forever) - **docs(readme)**: Added 4 new free provider sections (LongCat, Pollinations, Cloudflare AI, Scaleway) with model tables @@ -4177,7 +4295,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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). -### Features +### Fonctionnalités - **"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. @@ -4205,7 +4323,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Merge PR #494 (MiniMax role fix), fix KIRO MITM dashboard, triage 8 issues. -### Features +### Fonctionnalités - **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. - **roleNormalizer**: `normalizeDeveloperRole()` now accepts `preserveDeveloperRole` parameter with tri-state behavior (undefined=keep, true=keep, false=convert). @@ -4261,7 +4379,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Gemini CLI deprecation, VM guide i18n fix, dependabot security fix, provider schema expansion. -### Features +### Fonctionnalités - **Gemini CLI Deprecation** (#462): Mark `gemini-cli` provider as deprecated with warning — Google restricts third-party OAuth usage from March 2026 - **Provider Schema** (#462): Expand Zod validation with `deprecated`, `deprecationReason`, `hasFree`, `freeNote`, `authHint`, `apiHint` optional fields @@ -4270,7 +4388,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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) -### Security +### Sécurité - **deps**: Bump `flatted` 3.3.3 → 3.4.2 — fixes CWE-1321 prototype pollution (#484, @dependabot) @@ -4290,7 +4408,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Czech i18n, SSE protocol fix, VM guide translation. -### Features +### Fonctionnalités - **Czech Language** (#482): Full Czech (cs) i18n — 22 docs, 2606 UI strings, language switcher updates (@zen0bit) - **VM Deployment Guide**: Translated from Portuguese to English as the source document (@zen0bit) @@ -4309,7 +4427,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: 2 merged PRs, model aliases routing fix, log export, and issue triage. -### Features +### Fonctionnalités - **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) @@ -4329,7 +4447,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Five community PRs — streaming call log fixes, Kiro compatibility, cache token analytics, Chinese translation, and configurable tool call IDs. -### ✨ Features +### Fonctionnalités - **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) - **feat(providers)**: Per-model configurable 9-char tool call ID normalization (Mistral-style) — only models with the option enabled get truncated IDs (#470) @@ -4359,7 +4477,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Bailian Coding Plan provider with editable base URLs, plus community contributions for Alibaba Cloud and Kimi Coding. -### ✨ Features +### Fonctionnalités - **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) - **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) @@ -4374,7 +4492,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Two new community-contributed providers (Alibaba Cloud Coding, Kimi Coding API-key) and Docker pino fix. -### ✨ Features +### Fonctionnalités - **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) - **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) @@ -4399,7 +4517,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Codex responses subpath passthrough natively supported, Windows MITM crash fixed, and Combos agent schemas adjusted. -### ✨ Features +### Fonctionnalités - **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) @@ -4439,7 +4557,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **fix(budget)**: "Save Limits" no longer returns 422 — `warningThreshold` is now correctly sent as fraction (0–1) instead of percentage (0–100) (#451) - **fix(combos)**: `` internal cache tag is now stripped before forwarding requests to providers, preventing cache session breaks (#454) -### ✨ Features +### Fonctionnalités - **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) @@ -4495,7 +4613,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Search Tools dashboard, i18n fixes, Copilot limits, Serper validation fix. -### 🚀 Features +### Fonctionnalités - **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) - New route: `/dashboard/search-tools` @@ -4595,7 +4713,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - DB migration: `request_type` column on `call_logs` for non-chat request tracking - Zod validation (`v1SearchSchema`), auth-gated, cost recorded via `recordCost()` -### 🔒 Security +### Sécurité - **deps**: Next.js 16.1.6 → 16.1.7 — fixes 6 CVEs: - **Critical**: CVE-2026-29057 (HTTP request smuggling via http-proxy) @@ -4725,7 +4843,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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**: New `request_detail_logs` table with 500-entry ring-buffer trigger, opt-in via settings toggle -### ✨ Features +### Fonctionnalités - **feat(combo)**: System Message Override per Combo (#399 — `system_message` field replaces or injects system prompt before forwarding to provider) - **feat(combo)**: Tool Filter Regex per Combo (#399 — `tool_filter_regex` keeps only tools matching pattern; supports OpenAI + Anthropic formats) @@ -4740,7 +4858,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: SSE improvements, local provider_nodes extensions, proxy registry, Claude passthrough fixes. -### ✨ Features +### Fonctionnalités - **feat(health)**: Background health check for local `provider_nodes` with exponential backoff (30s→300s) and `Promise.allSettled` to avoid blocking (#423, @Regis-RCR) - **feat(embeddings)**: Route `/v1/embeddings` to local `provider_nodes` — `buildDynamicEmbeddingProvider()` with hostname validation (#422, @Regis-RCR) @@ -4882,7 +5000,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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 - **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). -### ✨ Features +### Fonctionnalités - **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) @@ -4912,7 +5030,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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) - **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) -### ✨ Features +### Fonctionnalités - **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) - **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. @@ -4971,7 +5089,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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) - **fix(logs)**: Request log table is now readable in light mode — status badges, token counts, and combo tags use adaptive `dark:` color classes (#378) -### ✨ Features +### Fonctionnalités - **feat(kiro)**: Kiro credit tracking added to usage fetcher — queries `getUserCredits` from AWS CodeWhisperer endpoint (#337) @@ -5372,7 +5490,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > **Major release** — Free Stack ecosystem, transcription playground overhaul, 44+ providers, comprehensive free tier documentation, and UI improvements across the board. -### ✨ Features +### Fonctionnalités - **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. - **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. @@ -5383,7 +5501,7 @@ OmniRoute now automatically refreshes model lists for connected providers every ## [2.3.16] - 2026-03-13 -### 📖 Documentation +### Documentation - **README: 44+ Providers** — Updated all 3 occurrences of "36+ providers" to "44+" reflecting the actual codebase count (44 providers in providers.ts) - **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. @@ -5393,7 +5511,7 @@ OmniRoute now automatically refreshes model lists for connected providers every ## [2.3.15] - 2026-03-13 -### ✨ Features +### Fonctionnalités - **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. - **i18n — autoCombo section**: Added 20 new translation keys for the Auto-Combo dashboard (`title`, `status`, `modePack`, `providerScores`, `factorTierPriority`, etc.) to all 30 language files. diff --git a/docs/i18n/gu/CHANGELOG.md b/docs/i18n/gu/CHANGELOG.md index 8c33126af4..2349d186b8 100644 --- a/docs/i18n/gu/CHANGELOG.md +++ b/docs/i18n/gu/CHANGELOG.md @@ -10,30 +10,148 @@ ### ✨ New Features -- **feat(antigravity):** integrate Antigravity provider with dynamic `maxOutputTokens` calculation (bumping to `thinkingBudget + 1`) and standard Cloud Code envelope payload sanitization (#2055, #2063) +- **feat(antigravity):** integrate Antigravity provider with dynamic `maxOutputTokens` calculation, identity fingerprinting overhaul, and Cloud Code envelope payload sanitization (#2055, #2063) - **feat(gemini-cli):** add custom projectId support for Gemini CLI transport (UI, DB, executor) (#1991) +- **feat(providers):** add KIE media provider support with dynamic polling, text models, and expanded video models catalog +- **feat(providers):** add Z.AI provider support with GLM quota handling and new quota labels +- **feat(providers):** add 9 new free AI providers — LLM7, Lepton, Kluster, UncloseAI, BazaarLink, Completions, Enally, FreeTheAi (#2096) +- **feat(providers):** batch delete provider connections via checkbox multi-select (#2094) +- **feat(cursor):** full OpenAI parity — tool calls, streaming, and session management (#2082) +- **feat(cli):** comprehensive CLI enhancement suite with 20+ new commands including `omniroute providers`, `omniroute combos`, `omniroute doctor` (#2074) +- **feat(cli):** add modular CLI setup and provider management commands (#2046) +- **feat(mcp):** add DeepSeek quota and limit monitoring feature (#2089) +- **feat(circuit-breaker):** classify 429 errors and apply per-kind cooldowns (#2116) +- **feat(multi):** manifest-aware tier routing — W1-W4 complete (#2014) +- **feat(combos):** add reset-aware routing strategy for quota-based providers +- **feat(combo):** add context_length input field to combo edit form (#2047) +- **feat(chat):** dynamic tool limit detection with proactive truncation (#2061) +- **feat(sse):** refresh Claude OAuth wire image to claude-cli/2.1.131 (#2011) +- **feat(github):** add `targetFormat: openai-responses` to all GitHub models (#2122) +- **feat(api):** allow configuration via API calls — open management routes to Bearer keys with manage scope (#2103) +- **feat(api):** update API bridge proxy timeout to 600,000ms (#2019) +- **feat(usage):** add service tier breakdown, codex fast service tier analytics, and account for fast tier +- **feat(chat):** add `STREAM_READINESS_TIMEOUT_MS` and integrate into chat handling +- **feat(combo):** add `fallbackDelayMs` to combo configuration and related settings +- **feat(chat):** enhance error handling for semaphore capacity with fallback logic +- **feat(qdrant):** embedding model discovery (#2086) +- **feat(auth):** per-session sticky routing for Codex (#1887) +- **feat(inworld):** enhance Inworld TTS support (#2123) ### 🐛 Bug Fixes +- **fix(pricing):** make `getPricingForModel` fully case-insensitive to ensure custom prices correctly reflect in new incoming requests cost calculations +- **fix(gemini):** prevent `functionDeclarations` from being dropped by the sanitizer when `googleSearch` tool is present (#2077) +- **fix(pollinations):** add `jsonMode: true` flag in the request transformation to enforce correct JSON structure from Pollinations API (#2109) +- **fix(docker):** update Dockerfile to copy `/docs` directory during build ensuring API catalog availability at runtime (#2083) +- **fix(docker):** include OpenAPI spec in runtime image (#2007) +- **fix(providers):** strip OpenAI-specific fields in Kiro translator to prevent 400 errors (#2037) +- **fix(kiro):** normalize tool-use payloads to prevent 400 errors from agents (#2104) +- **fix(kiro):** merge adjacent user history turns after role normalization (#2105) +- **fix(ui):** resolve text contrast issues for zero-config warning banner in light mode (#2050) +- **fix(core):** inject global system prompt correctly into downstream chat completions pipeline (#2080) +- **fix(core):** restore Claude Code adaptive thinking defaults and resolve audio transcription CORS regression +- **fix(routing):** add missing v1beta rewrites to next.config to resolve 404 on Gemini models endpoint (#2102) +- **fix(routing):** fix bare GPT-5.5 routing for Codex-only installations (#2054) +- **fix(routing):** add fuzzy auto-combo routing for `auto/*` model prefix (#2010) - **fix(cache):** optimize cache_control preservation logic and explicitly align tool schema with upstream Claude Code expectations - **fix(db):** preserve legacy SQLite database path on Windows to prevent data loss (#1973) +- **fix(db):** reduce hot-path persistence overhead (#2039) +- **fix(db):** resolve migration conflict by renumbering overlapping migration entries (#2041) - **fix(settings):** resolve model alias persistence double stringification preventing UI updates (#2018) - **fix(routing):** dynamically filter bare model auto-resolution by active provider connections to prevent dead-routing (#2029) - **fix(embeddings):** add Google Gemini embeddings compatibility via OpenAI-compatible endpoint mapping (#2006) +- **fix(sse):** prevent Claude OAuth multi-account correlation via metadata.user_id (#2053) +- **fix(sse):** prevent Claude Code identity cloak overrides and fix fallback resilience (#2053) +- **fix(sse):** classify hour quota errors as QUOTA_EXHAUSTED (#2119) +- **fix(sse):** fix CC-compatible streaming bridge (#2118) +- **fix(antigravity):** sanitize Claude Cloud Code payloads (#2090) +- **fix(antigravity):** add duplex half for streaming bodies +- **fix(antigravity):** align identity protocol and behavior with official AM +- **fix(chatgpt-web):** plumb proxy through to native tls-client (#2022, #2023) +- **fix(codex):** expose native model IDs in catalog (#2012) +- **fix(glm):** add dedicated coding transport (#2087) +- **fix(compression):** support Responses input and expand Spanish compression rules (#2028) +- **fix(catalog):** auto-calculate combo context_length from target model limits (#2030) +- **fix(api):** fix usage analytics and API key identity (#2008, #2092) +- **fix(api-key):** allow Unicode letters in API key name validation (#1996) +- **fix(auth):** allow bootstrap without password (#2048) +- **fix(proxy):** clean up proxy page redundancy and fix 1proxy sync empty body error (#2052) +- **fix(dashboard):** resolve Unknown plan display in Provider Limits +- **fix(usage):** add extensible CURRENCY_SYMBOLS mapping for deepseek currencies +- **fix(runtime):** harden timer handling and model pricing fallback +- **fix(i18n):** complete Simplified Chinese translations (#2115) +- **fix(mitm):** add Linux cert install and skip sudo password when root (#1999) +- **fix(mitm):** prevent stub from loading at runtime via bypass module - **fix:** remove Anthropic-Beta header from non-Anthropic providers to fix identity contamination (#1989) - **fix(cli):** resolve .env loading failure for global npm installations +- **fix(export):** exclude telemetry/usage-history tables from JSON config backups by default to prevent unbounded file growth (#2125) +- **fix:** Follow OpenAI specification, handle throttling in batch and fix UI (#2045) -### 🔒 Security +### Seguridad +- **fix(security):** remediate CodeQL vulnerabilities (ReDoS, cryptographic bias, stack trace exposure, and weak password hashing) (#216, #215, #211, #208, #206, #210) - **fix(security):** remediate regex validation backtracking path in core compression cleanup (#1990) - **fix(core):** harden input handling and stabilization for prompt compression edge cases +### Documentación + +- **docs:** add competitive marketing tables and SEO/AEO optimizations to README (#2091) +- **docs:** refresh providers, model catalogs, and docs for v3.8.0 (#2088) +- **docs:** update Claude MD and update GLM-CN max context to 200k (#2027) +- **docs(env):** add `GITLAB_DUO_OAUTH_CLIENT_ID` to `.env.example` (#2031) + ### 🧹 Chores & Maintenance - **chore(providers):** prune redundant local provider icon assets in favor of `@lobehub/icons` web fonts (#1992) +- **chore(providers):** remove deprecated models (#2033) +- **deps:** bump `fast-uri` from 3.1.0 to 3.1.2 (#2078) +- **deps:** bump `hono` from 4.12.14 to 4.12.18 (#2079) - **ci:** skip SonarCloud scan on main pushes to optimize CI time - **test:** stabilize cooldown abort coverage case in integration testing +### 🏆 v3.8.0 Community Contributors + +Thank you to all **38 community contributors** who made v3.8.0 possible! 🎉 + +| Contributor | PRs | Contributions | +| :--------------------------------------------------------- | :-: | :------------------------------------------------------------ | +| [@oyi77](https://github.com/oyi77) | 7 | #2010, #2014, #2041, #2052, #2061, #2074, #2091, #2094, #2096 | +| [@backryun](https://github.com/backryun) | 4 | #1992, #2033, #2088, #2123 | +| [@dhaern](https://github.com/dhaern) | 4 | #2028, #2039, #2087, #2090 | +| [@Tentoxa](https://github.com/Tentoxa) | 2 | #2011, #2053 | +| [@wauputr4](https://github.com/wauputr4) | 2 | #2009, #2046 | +| [@payne0420](https://github.com/payne0420) | 1 | #2082 | +| [@Tr0sT](https://github.com/Tr0sT) | 1 | #2012 | +| [@AveryanAlex](https://github.com/AveryanAlex) | 1 | #2008 | +| [@nickwizard](https://github.com/nickwizard) | 1 | #1991 | +| [@rodrigogbbr-stack](https://github.com/rodrigogbbr-stack) | 1 | #1996 | +| [@NekoMonci12](https://github.com/NekoMonci12) | 1 | #1999 | +| [@congvc-dev](https://github.com/congvc-dev) | 1 | #2004 | +| [@tatsster](https://github.com/tatsster) | 1 | #2007 | +| [@xssdem](https://github.com/xssdem) | 1 | #2023 | +| [@bypanghu](https://github.com/bypanghu) | 1 | #2027 | +| [@herjarsa](https://github.com/herjarsa) | 1 | #2030 | +| [@wucm667](https://github.com/wucm667) | 1 | #2031 | +| [@hartmark](https://github.com/hartmark) | 1 | #2045 | +| [@ddarkr](https://github.com/ddarkr) | 1 | #2047 | +| [@tces1](https://github.com/tces1) | 1 | #2048 | +| [@guanbear](https://github.com/guanbear) | 1 | #2054 | +| [@Gi99lin](https://github.com/Gi99lin) | 1 | #2055 | +| [@ivan-mezentsev](https://github.com/ivan-mezentsev) | 1 | #2063 | +| [@JxnLexn](https://github.com/JxnLexn) | 1 | #2019 | +| [@yoviarpauzi](https://github.com/yoviarpauzi) | 1 | #2092 | +| [@rafacpti23](https://github.com/rafacpti23) | 1 | #2086 | +| [@gleber](https://github.com/gleber) | 1 | #2103 | +| [@rilham97](https://github.com/rilham97) | 1 | #2104 | +| [@Gioxaa](https://github.com/Gioxaa) | 1 | #2105 | +| [@boa-z](https://github.com/boa-z) | 1 | #2115 | +| [@eleata](https://github.com/eleata) | 1 | #2116 | +| [@rdself](https://github.com/rdself) | 1 | #2118 | +| [@clousky2020](https://github.com/clousky2020) | 1 | #2119 | +| [@abhinavjnu](https://github.com/abhinavjnu) | 1 | #2122 | +| [@HoaPham98](https://github.com/HoaPham98) | 1 | #2089 | +| [@05dunski](https://github.com/05dunski) | 1 | #1978 (cherry-picked) | + ## [3.7.9] — 2026-05-03 ### ✨ New Features @@ -102,7 +220,7 @@ - **chore(provider):** Add reka models list (#1956 — thanks @backryun) - **chore(model):** Update new models, Delete Deprecated models (#1949 — thanks @backryun) -### 📝 Documentation +### Documentación - **docs(compression):** document RTK+Caveman stacked savings ranges @@ -201,7 +319,7 @@ - **feat(db):** auto-restore probe-failed database on startup to prevent data loss after failed upgrades (#1810) - **feat(analytics):** add cost-based usage insights and activity streaks in the analytics dashboard -### 🔒 Security +### Seguridad - **fix(security):** resolve ReDoS vulnerability in Codex executor regex patterns (#1797, #1789) @@ -354,7 +472,7 @@ We identified that **155 community PRs** across the entire project history (from - **feat(proxy):** implement bulk proxy import via pipe-delimited parser with update-or-create (upsert) logic and real-time preview table - **feat(pwa):** add fullscreen installable PWA with manifest, service worker, and cross-platform app icons (#1728) -### 🔒 Security +### Seguridad - **security:** replace insecure `Math.random` with `crypto.getRandomValues` for fallback UUID generation to resolve CodeQL CWE-338 finding (#182) @@ -519,7 +637,7 @@ We identified that **155 community PRs** across the entire project history (from - **fix(transport):** Prevent memory bloat and database exhaustion from large, fragmented streaming responses. Implemented `ByteQueue` in `kiro.ts` for zero-copy binary accumulation, refactored `antigravity.ts` for incremental SSE parsing, and enforced a strict 512KB tiered truncation limit (`MAX_CALL_LOG_ARTIFACT_BYTES`) on stream request logs and call artifacts (#1647). - **chore(ci):** Update build environment dependencies — bump Node to `24.15.0`, `actions/checkout@v6`, `docker/build-push-action@v7`, pin `actions/setup-python` to major tag (#1646 — thanks @backryun). -### 📝 Documentation +### Documentación - **docs(env):** Add `OMNIROUTE_ALLOW_PRIVATE_PROVIDER_URLS` to `.env.example` with documentation for LM Studio and other local provider use cases (#1623). @@ -669,7 +787,7 @@ We identified that **155 community PRs** across the entire project history (from - **test(next):** Align transpile package expectations for the Next.js standalone build. - **test(ci):** Fix CI-only test failures from environment differences — clear `INITIAL_PASSWORD` and `JWT_SECRET` in integration tests, handle `XDG_CONFIG_HOME` for guide-settings tests. -### 📚 Documentation +### Documentación - **docs:** Update the root changelog with all release-branch changes through 2026-04-24, including PRs #1544, #1555, #1551, #1550, #1548, #1547, #1541, #1538, #1536, and #1527. - **docs:** Fix broken README and localized documentation links. (#1536) @@ -811,7 +929,7 @@ We identified that **155 community PRs** across the entire project history (from - **feat(providers):** Expand image provider registry with extended model support including SD3.5, FLUX, and DALL-E 3 HD configurations - **feat(combos):** Add new routing strategies and full i18n support for agent features section across 31 languages -### 🔒 Security +### Seguridad - **security:** Resolve 18 GitHub CodeQL scan alerts including ReDoS, incomplete sanitization, and bad HTML filtering regexp patterns - **fix(auth):** Seal privilege escalation vector by enforcing JWT session checking exclusively on `/api/keys` management endpoints (#1353) @@ -1078,7 +1196,7 @@ We identified that **155 community PRs** across the entire project history (from - **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 - **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 -### 🔒 Security +### Seguridad - **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 - **Auth Guard on Translator Save:** Added `isAuthenticated` guard to `/api/translator/save` for defense-in-depth consistency @@ -1483,7 +1601,7 @@ We identified that **155 community PRs** across the entire project history (from - **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). -### 📚 Documentation +### Documentació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. - **Context Relay Delivery Notes:** Documented the current architecture, runtime flow, and Codex-focused scope in the feature docs, changelog, and agent guidance. @@ -1559,7 +1677,7 @@ We identified that **155 community PRs** across the entire project history (from ## [3.5.3] - 2026-04-07 -### Security +### Seguridad - **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. - **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. @@ -1575,7 +1693,7 @@ We identified that **155 community PRs** across the entire project history (from - **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. -### Documentation +### Documentación - **I18n Engine:** Synchronized and pushed deep Machine Translation updates across all 32 natively-supported languages (682 translation nodes aligned). @@ -1736,7 +1854,7 @@ We identified that **155 community PRs** across the entire project history (from ## [3.4.8] — 2026-04-03 -### Security +### Seguridad - Fully remediated all outstanding Github Advanced Security (CodeQL) findings and Dependabot alerts. - Fixed insecure randomness vulnerabilities by migrating from `Math.random` to `crypto.randomUUID()`. @@ -1748,7 +1866,7 @@ We identified that **155 community PRs** across the entire project history (from ## [3.4.7] — 2026-04-03 -### Features +### Funcionalidades - Added `Cryptography` node to Monitoring and MCP health checks (#798) - Hardened model-catalog route permissions mapping (`/models`) (#781) @@ -1764,7 +1882,7 @@ We identified that **155 community PRs** across the entire project history (from - Fixed MCP standalone module-resolution (`ERR_MODULE_NOT_FOUND`) via `esbuild` (#936) - Fixed NVIDIA NIM routing credential resolution alias mismatch (#931) -### Security +### Seguridad - Added safe strict input boundary protection against raw `shell: true` remote-code execution injections. @@ -2011,7 +2129,7 @@ We identified that **155 community PRs** across the entire project history (from ## [3.4.0] - 2026-03-31 -### 🚀 Features +### Funcionalidades - **Subscription Utilization Analytics:** Added quota snapshot time-series tracking, Provider Utilization and Combo Health tabs with recharts visualizations, and corresponding API endpoints (#847) - **SQLite Backup Control:** New `OMNIROUTE_DISABLE_AUTO_BACKUP` env flag to disable automatic SQLite backups (#846) @@ -2063,7 +2181,7 @@ We identified that **155 community PRs** across the entire project history (from ## [3.3.8] - 2026-03-30 -### 🚀 Features +### Funcionalidades - **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) - **Qoder Integration:** Native integration for Qoder AI natively replacing the legacy iFlow platform mappings (#660) @@ -2889,7 +3007,7 @@ We identified that **155 community PRs** across the entire project history (from - **NaN tokens in Claude Code / client responses (#617):** - `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 -### 🔒 Security +### Seguridad - Updated `yaml` package to fix stack overflow vulnerability (GHSA-48c2-rrv3-qjmp) @@ -3565,7 +3683,7 @@ docker pull diegosouzapw/omniroute:3.0.0 - **SVG fallback**: `ProviderIcon` component updated with 4-tier strategy: Lobehub → PNG → SVG → Generic icon - **Agents fingerprinting**: Synced with CLI tools — added droid, openclaw, copilot, opencode to fingerprint list (14 total) -### 🔒 Security +### Seguridad - **CVE fix**: Resolved dompurify XSS vulnerability (GHSA-v2wj-7wpq-c8vv) via npm overrides forcing `dompurify@^3.3.2` - `npm audit` now reports **0 vulnerabilities** @@ -3928,7 +4046,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **#510** — Windows: MSYS2/Git-Bash paths (`/c/Program Files/...`) are now normalized to `C:\Program Files\...` - **#492** — `omniroute` CLI now detects `mise`/`nvm` when `app/server.js` is missing and shows targeted fix -### 📖 Documentation +### Documentación - **#513** — Docker password reset: `INITIAL_PASSWORD` env var workaround documented - **#520** — pnpm: `pnpm approve-builds better-sqlite3` documented @@ -4025,7 +4143,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **feat(executors/cloudflare-ai)**: New `CloudflareAIExecutor` — dynamic URL construction requires `accountId` in provider credentials - **feat(executors)**: Register `pollinations`, `pol`, `cloudflare-ai`, `cf` executor mappings -### 📝 Documentation +### Documentación - **docs(readme)**: Expanded free combo stack to 11 providers ($0 forever) - **docs(readme)**: Added 4 new free provider sections (LongCat, Pollinations, Cloudflare AI, Scaleway) with model tables @@ -4177,7 +4295,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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). -### Features +### Funcionalidades - **"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. @@ -4205,7 +4323,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Merge PR #494 (MiniMax role fix), fix KIRO MITM dashboard, triage 8 issues. -### Features +### Funcionalidades - **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. - **roleNormalizer**: `normalizeDeveloperRole()` now accepts `preserveDeveloperRole` parameter with tri-state behavior (undefined=keep, true=keep, false=convert). @@ -4261,7 +4379,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Gemini CLI deprecation, VM guide i18n fix, dependabot security fix, provider schema expansion. -### Features +### Funcionalidades - **Gemini CLI Deprecation** (#462): Mark `gemini-cli` provider as deprecated with warning — Google restricts third-party OAuth usage from March 2026 - **Provider Schema** (#462): Expand Zod validation with `deprecated`, `deprecationReason`, `hasFree`, `freeNote`, `authHint`, `apiHint` optional fields @@ -4270,7 +4388,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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) -### Security +### Seguridad - **deps**: Bump `flatted` 3.3.3 → 3.4.2 — fixes CWE-1321 prototype pollution (#484, @dependabot) @@ -4290,7 +4408,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Czech i18n, SSE protocol fix, VM guide translation. -### Features +### Funcionalidades - **Czech Language** (#482): Full Czech (cs) i18n — 22 docs, 2606 UI strings, language switcher updates (@zen0bit) - **VM Deployment Guide**: Translated from Portuguese to English as the source document (@zen0bit) @@ -4309,7 +4427,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: 2 merged PRs, model aliases routing fix, log export, and issue triage. -### Features +### Funcionalidades - **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) @@ -4329,7 +4447,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Five community PRs — streaming call log fixes, Kiro compatibility, cache token analytics, Chinese translation, and configurable tool call IDs. -### ✨ Features +### Funcionalidades - **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) - **feat(providers)**: Per-model configurable 9-char tool call ID normalization (Mistral-style) — only models with the option enabled get truncated IDs (#470) @@ -4359,7 +4477,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Bailian Coding Plan provider with editable base URLs, plus community contributions for Alibaba Cloud and Kimi Coding. -### ✨ Features +### Funcionalidades - **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) - **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) @@ -4374,7 +4492,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Two new community-contributed providers (Alibaba Cloud Coding, Kimi Coding API-key) and Docker pino fix. -### ✨ Features +### Funcionalidades - **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) - **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) @@ -4399,7 +4517,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Codex responses subpath passthrough natively supported, Windows MITM crash fixed, and Combos agent schemas adjusted. -### ✨ Features +### Funcionalidades - **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) @@ -4439,7 +4557,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **fix(budget)**: "Save Limits" no longer returns 422 — `warningThreshold` is now correctly sent as fraction (0–1) instead of percentage (0–100) (#451) - **fix(combos)**: `` internal cache tag is now stripped before forwarding requests to providers, preventing cache session breaks (#454) -### ✨ Features +### Funcionalidades - **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) @@ -4495,7 +4613,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Search Tools dashboard, i18n fixes, Copilot limits, Serper validation fix. -### 🚀 Features +### Funcionalidades - **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) - New route: `/dashboard/search-tools` @@ -4595,7 +4713,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - DB migration: `request_type` column on `call_logs` for non-chat request tracking - Zod validation (`v1SearchSchema`), auth-gated, cost recorded via `recordCost()` -### 🔒 Security +### Seguridad - **deps**: Next.js 16.1.6 → 16.1.7 — fixes 6 CVEs: - **Critical**: CVE-2026-29057 (HTTP request smuggling via http-proxy) @@ -4725,7 +4843,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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**: New `request_detail_logs` table with 500-entry ring-buffer trigger, opt-in via settings toggle -### ✨ Features +### Funcionalidades - **feat(combo)**: System Message Override per Combo (#399 — `system_message` field replaces or injects system prompt before forwarding to provider) - **feat(combo)**: Tool Filter Regex per Combo (#399 — `tool_filter_regex` keeps only tools matching pattern; supports OpenAI + Anthropic formats) @@ -4740,7 +4858,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: SSE improvements, local provider_nodes extensions, proxy registry, Claude passthrough fixes. -### ✨ Features +### Funcionalidades - **feat(health)**: Background health check for local `provider_nodes` with exponential backoff (30s→300s) and `Promise.allSettled` to avoid blocking (#423, @Regis-RCR) - **feat(embeddings)**: Route `/v1/embeddings` to local `provider_nodes` — `buildDynamicEmbeddingProvider()` with hostname validation (#422, @Regis-RCR) @@ -4882,7 +5000,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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 - **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). -### ✨ Features +### Funcionalidades - **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) @@ -4912,7 +5030,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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) - **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) -### ✨ Features +### Funcionalidades - **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) - **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. @@ -4971,7 +5089,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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) - **fix(logs)**: Request log table is now readable in light mode — status badges, token counts, and combo tags use adaptive `dark:` color classes (#378) -### ✨ Features +### Funcionalidades - **feat(kiro)**: Kiro credit tracking added to usage fetcher — queries `getUserCredits` from AWS CodeWhisperer endpoint (#337) @@ -5372,7 +5490,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > **Major release** — Free Stack ecosystem, transcription playground overhaul, 44+ providers, comprehensive free tier documentation, and UI improvements across the board. -### ✨ Features +### Funcionalidades - **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. - **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. @@ -5383,7 +5501,7 @@ OmniRoute now automatically refreshes model lists for connected providers every ## [2.3.16] - 2026-03-13 -### 📖 Documentation +### Documentación - **README: 44+ Providers** — Updated all 3 occurrences of "36+ providers" to "44+" reflecting the actual codebase count (44 providers in providers.ts) - **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. @@ -5393,7 +5511,7 @@ OmniRoute now automatically refreshes model lists for connected providers every ## [2.3.15] - 2026-03-13 -### ✨ Features +### Funcionalidades - **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. - **i18n — autoCombo section**: Added 20 new translation keys for the Auto-Combo dashboard (`title`, `status`, `modePack`, `providerScores`, `factorTierPriority`, etc.) to all 30 language files. diff --git a/docs/i18n/he/CHANGELOG.md b/docs/i18n/he/CHANGELOG.md index 06e11b13ba..86de7f2cd1 100644 --- a/docs/i18n/he/CHANGELOG.md +++ b/docs/i18n/he/CHANGELOG.md @@ -10,30 +10,148 @@ ### ✨ New Features -- **feat(antigravity):** integrate Antigravity provider with dynamic `maxOutputTokens` calculation (bumping to `thinkingBudget + 1`) and standard Cloud Code envelope payload sanitization (#2055, #2063) +- **feat(antigravity):** integrate Antigravity provider with dynamic `maxOutputTokens` calculation, identity fingerprinting overhaul, and Cloud Code envelope payload sanitization (#2055, #2063) - **feat(gemini-cli):** add custom projectId support for Gemini CLI transport (UI, DB, executor) (#1991) +- **feat(providers):** add KIE media provider support with dynamic polling, text models, and expanded video models catalog +- **feat(providers):** add Z.AI provider support with GLM quota handling and new quota labels +- **feat(providers):** add 9 new free AI providers — LLM7, Lepton, Kluster, UncloseAI, BazaarLink, Completions, Enally, FreeTheAi (#2096) +- **feat(providers):** batch delete provider connections via checkbox multi-select (#2094) +- **feat(cursor):** full OpenAI parity — tool calls, streaming, and session management (#2082) +- **feat(cli):** comprehensive CLI enhancement suite with 20+ new commands including `omniroute providers`, `omniroute combos`, `omniroute doctor` (#2074) +- **feat(cli):** add modular CLI setup and provider management commands (#2046) +- **feat(mcp):** add DeepSeek quota and limit monitoring feature (#2089) +- **feat(circuit-breaker):** classify 429 errors and apply per-kind cooldowns (#2116) +- **feat(multi):** manifest-aware tier routing — W1-W4 complete (#2014) +- **feat(combos):** add reset-aware routing strategy for quota-based providers +- **feat(combo):** add context_length input field to combo edit form (#2047) +- **feat(chat):** dynamic tool limit detection with proactive truncation (#2061) +- **feat(sse):** refresh Claude OAuth wire image to claude-cli/2.1.131 (#2011) +- **feat(github):** add `targetFormat: openai-responses` to all GitHub models (#2122) +- **feat(api):** allow configuration via API calls — open management routes to Bearer keys with manage scope (#2103) +- **feat(api):** update API bridge proxy timeout to 600,000ms (#2019) +- **feat(usage):** add service tier breakdown, codex fast service tier analytics, and account for fast tier +- **feat(chat):** add `STREAM_READINESS_TIMEOUT_MS` and integrate into chat handling +- **feat(combo):** add `fallbackDelayMs` to combo configuration and related settings +- **feat(chat):** enhance error handling for semaphore capacity with fallback logic +- **feat(qdrant):** embedding model discovery (#2086) +- **feat(auth):** per-session sticky routing for Codex (#1887) +- **feat(inworld):** enhance Inworld TTS support (#2123) ### 🐛 Bug Fixes +- **fix(pricing):** make `getPricingForModel` fully case-insensitive to ensure custom prices correctly reflect in new incoming requests cost calculations +- **fix(gemini):** prevent `functionDeclarations` from being dropped by the sanitizer when `googleSearch` tool is present (#2077) +- **fix(pollinations):** add `jsonMode: true` flag in the request transformation to enforce correct JSON structure from Pollinations API (#2109) +- **fix(docker):** update Dockerfile to copy `/docs` directory during build ensuring API catalog availability at runtime (#2083) +- **fix(docker):** include OpenAPI spec in runtime image (#2007) +- **fix(providers):** strip OpenAI-specific fields in Kiro translator to prevent 400 errors (#2037) +- **fix(kiro):** normalize tool-use payloads to prevent 400 errors from agents (#2104) +- **fix(kiro):** merge adjacent user history turns after role normalization (#2105) +- **fix(ui):** resolve text contrast issues for zero-config warning banner in light mode (#2050) +- **fix(core):** inject global system prompt correctly into downstream chat completions pipeline (#2080) +- **fix(core):** restore Claude Code adaptive thinking defaults and resolve audio transcription CORS regression +- **fix(routing):** add missing v1beta rewrites to next.config to resolve 404 on Gemini models endpoint (#2102) +- **fix(routing):** fix bare GPT-5.5 routing for Codex-only installations (#2054) +- **fix(routing):** add fuzzy auto-combo routing for `auto/*` model prefix (#2010) - **fix(cache):** optimize cache_control preservation logic and explicitly align tool schema with upstream Claude Code expectations - **fix(db):** preserve legacy SQLite database path on Windows to prevent data loss (#1973) +- **fix(db):** reduce hot-path persistence overhead (#2039) +- **fix(db):** resolve migration conflict by renumbering overlapping migration entries (#2041) - **fix(settings):** resolve model alias persistence double stringification preventing UI updates (#2018) - **fix(routing):** dynamically filter bare model auto-resolution by active provider connections to prevent dead-routing (#2029) - **fix(embeddings):** add Google Gemini embeddings compatibility via OpenAI-compatible endpoint mapping (#2006) +- **fix(sse):** prevent Claude OAuth multi-account correlation via metadata.user_id (#2053) +- **fix(sse):** prevent Claude Code identity cloak overrides and fix fallback resilience (#2053) +- **fix(sse):** classify hour quota errors as QUOTA_EXHAUSTED (#2119) +- **fix(sse):** fix CC-compatible streaming bridge (#2118) +- **fix(antigravity):** sanitize Claude Cloud Code payloads (#2090) +- **fix(antigravity):** add duplex half for streaming bodies +- **fix(antigravity):** align identity protocol and behavior with official AM +- **fix(chatgpt-web):** plumb proxy through to native tls-client (#2022, #2023) +- **fix(codex):** expose native model IDs in catalog (#2012) +- **fix(glm):** add dedicated coding transport (#2087) +- **fix(compression):** support Responses input and expand Spanish compression rules (#2028) +- **fix(catalog):** auto-calculate combo context_length from target model limits (#2030) +- **fix(api):** fix usage analytics and API key identity (#2008, #2092) +- **fix(api-key):** allow Unicode letters in API key name validation (#1996) +- **fix(auth):** allow bootstrap without password (#2048) +- **fix(proxy):** clean up proxy page redundancy and fix 1proxy sync empty body error (#2052) +- **fix(dashboard):** resolve Unknown plan display in Provider Limits +- **fix(usage):** add extensible CURRENCY_SYMBOLS mapping for deepseek currencies +- **fix(runtime):** harden timer handling and model pricing fallback +- **fix(i18n):** complete Simplified Chinese translations (#2115) +- **fix(mitm):** add Linux cert install and skip sudo password when root (#1999) +- **fix(mitm):** prevent stub from loading at runtime via bypass module - **fix:** remove Anthropic-Beta header from non-Anthropic providers to fix identity contamination (#1989) - **fix(cli):** resolve .env loading failure for global npm installations +- **fix(export):** exclude telemetry/usage-history tables from JSON config backups by default to prevent unbounded file growth (#2125) +- **fix:** Follow OpenAI specification, handle throttling in batch and fix UI (#2045) -### 🔒 Security +### אבטחה +- **fix(security):** remediate CodeQL vulnerabilities (ReDoS, cryptographic bias, stack trace exposure, and weak password hashing) (#216, #215, #211, #208, #206, #210) - **fix(security):** remediate regex validation backtracking path in core compression cleanup (#1990) - **fix(core):** harden input handling and stabilization for prompt compression edge cases +### תיעוד + +- **docs:** add competitive marketing tables and SEO/AEO optimizations to README (#2091) +- **docs:** refresh providers, model catalogs, and docs for v3.8.0 (#2088) +- **docs:** update Claude MD and update GLM-CN max context to 200k (#2027) +- **docs(env):** add `GITLAB_DUO_OAUTH_CLIENT_ID` to `.env.example` (#2031) + ### 🧹 Chores & Maintenance - **chore(providers):** prune redundant local provider icon assets in favor of `@lobehub/icons` web fonts (#1992) +- **chore(providers):** remove deprecated models (#2033) +- **deps:** bump `fast-uri` from 3.1.0 to 3.1.2 (#2078) +- **deps:** bump `hono` from 4.12.14 to 4.12.18 (#2079) - **ci:** skip SonarCloud scan on main pushes to optimize CI time - **test:** stabilize cooldown abort coverage case in integration testing +### 🏆 v3.8.0 Community Contributors + +Thank you to all **38 community contributors** who made v3.8.0 possible! 🎉 + +| Contributor | PRs | Contributions | +| :--------------------------------------------------------- | :-: | :------------------------------------------------------------ | +| [@oyi77](https://github.com/oyi77) | 7 | #2010, #2014, #2041, #2052, #2061, #2074, #2091, #2094, #2096 | +| [@backryun](https://github.com/backryun) | 4 | #1992, #2033, #2088, #2123 | +| [@dhaern](https://github.com/dhaern) | 4 | #2028, #2039, #2087, #2090 | +| [@Tentoxa](https://github.com/Tentoxa) | 2 | #2011, #2053 | +| [@wauputr4](https://github.com/wauputr4) | 2 | #2009, #2046 | +| [@payne0420](https://github.com/payne0420) | 1 | #2082 | +| [@Tr0sT](https://github.com/Tr0sT) | 1 | #2012 | +| [@AveryanAlex](https://github.com/AveryanAlex) | 1 | #2008 | +| [@nickwizard](https://github.com/nickwizard) | 1 | #1991 | +| [@rodrigogbbr-stack](https://github.com/rodrigogbbr-stack) | 1 | #1996 | +| [@NekoMonci12](https://github.com/NekoMonci12) | 1 | #1999 | +| [@congvc-dev](https://github.com/congvc-dev) | 1 | #2004 | +| [@tatsster](https://github.com/tatsster) | 1 | #2007 | +| [@xssdem](https://github.com/xssdem) | 1 | #2023 | +| [@bypanghu](https://github.com/bypanghu) | 1 | #2027 | +| [@herjarsa](https://github.com/herjarsa) | 1 | #2030 | +| [@wucm667](https://github.com/wucm667) | 1 | #2031 | +| [@hartmark](https://github.com/hartmark) | 1 | #2045 | +| [@ddarkr](https://github.com/ddarkr) | 1 | #2047 | +| [@tces1](https://github.com/tces1) | 1 | #2048 | +| [@guanbear](https://github.com/guanbear) | 1 | #2054 | +| [@Gi99lin](https://github.com/Gi99lin) | 1 | #2055 | +| [@ivan-mezentsev](https://github.com/ivan-mezentsev) | 1 | #2063 | +| [@JxnLexn](https://github.com/JxnLexn) | 1 | #2019 | +| [@yoviarpauzi](https://github.com/yoviarpauzi) | 1 | #2092 | +| [@rafacpti23](https://github.com/rafacpti23) | 1 | #2086 | +| [@gleber](https://github.com/gleber) | 1 | #2103 | +| [@rilham97](https://github.com/rilham97) | 1 | #2104 | +| [@Gioxaa](https://github.com/Gioxaa) | 1 | #2105 | +| [@boa-z](https://github.com/boa-z) | 1 | #2115 | +| [@eleata](https://github.com/eleata) | 1 | #2116 | +| [@rdself](https://github.com/rdself) | 1 | #2118 | +| [@clousky2020](https://github.com/clousky2020) | 1 | #2119 | +| [@abhinavjnu](https://github.com/abhinavjnu) | 1 | #2122 | +| [@HoaPham98](https://github.com/HoaPham98) | 1 | #2089 | +| [@05dunski](https://github.com/05dunski) | 1 | #1978 (cherry-picked) | + ## [3.7.9] — 2026-05-03 ### ✨ New Features @@ -102,7 +220,7 @@ - **chore(provider):** Add reka models list (#1956 — thanks @backryun) - **chore(model):** Update new models, Delete Deprecated models (#1949 — thanks @backryun) -### 📝 Documentation +### תיעוד - **docs(compression):** document RTK+Caveman stacked savings ranges @@ -201,7 +319,7 @@ - **feat(db):** auto-restore probe-failed database on startup to prevent data loss after failed upgrades (#1810) - **feat(analytics):** add cost-based usage insights and activity streaks in the analytics dashboard -### 🔒 Security +### אבטחה - **fix(security):** resolve ReDoS vulnerability in Codex executor regex patterns (#1797, #1789) @@ -354,7 +472,7 @@ We identified that **155 community PRs** across the entire project history (from - **feat(proxy):** implement bulk proxy import via pipe-delimited parser with update-or-create (upsert) logic and real-time preview table - **feat(pwa):** add fullscreen installable PWA with manifest, service worker, and cross-platform app icons (#1728) -### 🔒 Security +### אבטחה - **security:** replace insecure `Math.random` with `crypto.getRandomValues` for fallback UUID generation to resolve CodeQL CWE-338 finding (#182) @@ -519,7 +637,7 @@ We identified that **155 community PRs** across the entire project history (from - **fix(transport):** Prevent memory bloat and database exhaustion from large, fragmented streaming responses. Implemented `ByteQueue` in `kiro.ts` for zero-copy binary accumulation, refactored `antigravity.ts` for incremental SSE parsing, and enforced a strict 512KB tiered truncation limit (`MAX_CALL_LOG_ARTIFACT_BYTES`) on stream request logs and call artifacts (#1647). - **chore(ci):** Update build environment dependencies — bump Node to `24.15.0`, `actions/checkout@v6`, `docker/build-push-action@v7`, pin `actions/setup-python` to major tag (#1646 — thanks @backryun). -### 📝 Documentation +### תיעוד - **docs(env):** Add `OMNIROUTE_ALLOW_PRIVATE_PROVIDER_URLS` to `.env.example` with documentation for LM Studio and other local provider use cases (#1623). @@ -669,7 +787,7 @@ We identified that **155 community PRs** across the entire project history (from - **test(next):** Align transpile package expectations for the Next.js standalone build. - **test(ci):** Fix CI-only test failures from environment differences — clear `INITIAL_PASSWORD` and `JWT_SECRET` in integration tests, handle `XDG_CONFIG_HOME` for guide-settings tests. -### 📚 Documentation +### תיעוד - **docs:** Update the root changelog with all release-branch changes through 2026-04-24, including PRs #1544, #1555, #1551, #1550, #1548, #1547, #1541, #1538, #1536, and #1527. - **docs:** Fix broken README and localized documentation links. (#1536) @@ -811,7 +929,7 @@ We identified that **155 community PRs** across the entire project history (from - **feat(providers):** Expand image provider registry with extended model support including SD3.5, FLUX, and DALL-E 3 HD configurations - **feat(combos):** Add new routing strategies and full i18n support for agent features section across 31 languages -### 🔒 Security +### אבטחה - **security:** Resolve 18 GitHub CodeQL scan alerts including ReDoS, incomplete sanitization, and bad HTML filtering regexp patterns - **fix(auth):** Seal privilege escalation vector by enforcing JWT session checking exclusively on `/api/keys` management endpoints (#1353) @@ -1078,7 +1196,7 @@ We identified that **155 community PRs** across the entire project history (from - **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 - **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 -### 🔒 Security +### אבטחה - **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 - **Auth Guard on Translator Save:** Added `isAuthenticated` guard to `/api/translator/save` for defense-in-depth consistency @@ -1483,7 +1601,7 @@ We identified that **155 community PRs** across the entire project history (from - **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). -### 📚 Documentation +### תיעוד - **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. - **Context Relay Delivery Notes:** Documented the current architecture, runtime flow, and Codex-focused scope in the feature docs, changelog, and agent guidance. @@ -1559,7 +1677,7 @@ We identified that **155 community PRs** across the entire project history (from ## [3.5.3] - 2026-04-07 -### Security +### אבטחה - **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. - **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. @@ -1575,7 +1693,7 @@ We identified that **155 community PRs** across the entire project history (from - **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. -### Documentation +### תיעוד - **I18n Engine:** Synchronized and pushed deep Machine Translation updates across all 32 natively-supported languages (682 translation nodes aligned). @@ -1736,7 +1854,7 @@ We identified that **155 community PRs** across the entire project history (from ## [3.4.8] — 2026-04-03 -### Security +### אבטחה - Fully remediated all outstanding Github Advanced Security (CodeQL) findings and Dependabot alerts. - Fixed insecure randomness vulnerabilities by migrating from `Math.random` to `crypto.randomUUID()`. @@ -1748,7 +1866,7 @@ We identified that **155 community PRs** across the entire project history (from ## [3.4.7] — 2026-04-03 -### Features +### תכונות - Added `Cryptography` node to Monitoring and MCP health checks (#798) - Hardened model-catalog route permissions mapping (`/models`) (#781) @@ -1764,7 +1882,7 @@ We identified that **155 community PRs** across the entire project history (from - Fixed MCP standalone module-resolution (`ERR_MODULE_NOT_FOUND`) via `esbuild` (#936) - Fixed NVIDIA NIM routing credential resolution alias mismatch (#931) -### Security +### אבטחה - Added safe strict input boundary protection against raw `shell: true` remote-code execution injections. @@ -2011,7 +2129,7 @@ We identified that **155 community PRs** across the entire project history (from ## [3.4.0] - 2026-03-31 -### 🚀 Features +### תכונות - **Subscription Utilization Analytics:** Added quota snapshot time-series tracking, Provider Utilization and Combo Health tabs with recharts visualizations, and corresponding API endpoints (#847) - **SQLite Backup Control:** New `OMNIROUTE_DISABLE_AUTO_BACKUP` env flag to disable automatic SQLite backups (#846) @@ -2063,7 +2181,7 @@ We identified that **155 community PRs** across the entire project history (from ## [3.3.8] - 2026-03-30 -### 🚀 Features +### תכונות - **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) - **Qoder Integration:** Native integration for Qoder AI natively replacing the legacy iFlow platform mappings (#660) @@ -2889,7 +3007,7 @@ We identified that **155 community PRs** across the entire project history (from - **NaN tokens in Claude Code / client responses (#617):** - `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 -### 🔒 Security +### אבטחה - Updated `yaml` package to fix stack overflow vulnerability (GHSA-48c2-rrv3-qjmp) @@ -3565,7 +3683,7 @@ docker pull diegosouzapw/omniroute:3.0.0 - **SVG fallback**: `ProviderIcon` component updated with 4-tier strategy: Lobehub → PNG → SVG → Generic icon - **Agents fingerprinting**: Synced with CLI tools — added droid, openclaw, copilot, opencode to fingerprint list (14 total) -### 🔒 Security +### אבטחה - **CVE fix**: Resolved dompurify XSS vulnerability (GHSA-v2wj-7wpq-c8vv) via npm overrides forcing `dompurify@^3.3.2` - `npm audit` now reports **0 vulnerabilities** @@ -3928,7 +4046,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **#510** — Windows: MSYS2/Git-Bash paths (`/c/Program Files/...`) are now normalized to `C:\Program Files\...` - **#492** — `omniroute` CLI now detects `mise`/`nvm` when `app/server.js` is missing and shows targeted fix -### 📖 Documentation +### תיעוד - **#513** — Docker password reset: `INITIAL_PASSWORD` env var workaround documented - **#520** — pnpm: `pnpm approve-builds better-sqlite3` documented @@ -4025,7 +4143,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **feat(executors/cloudflare-ai)**: New `CloudflareAIExecutor` — dynamic URL construction requires `accountId` in provider credentials - **feat(executors)**: Register `pollinations`, `pol`, `cloudflare-ai`, `cf` executor mappings -### 📝 Documentation +### תיעוד - **docs(readme)**: Expanded free combo stack to 11 providers ($0 forever) - **docs(readme)**: Added 4 new free provider sections (LongCat, Pollinations, Cloudflare AI, Scaleway) with model tables @@ -4177,7 +4295,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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). -### Features +### תכונות - **"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. @@ -4205,7 +4323,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Merge PR #494 (MiniMax role fix), fix KIRO MITM dashboard, triage 8 issues. -### Features +### תכונות - **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. - **roleNormalizer**: `normalizeDeveloperRole()` now accepts `preserveDeveloperRole` parameter with tri-state behavior (undefined=keep, true=keep, false=convert). @@ -4261,7 +4379,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Gemini CLI deprecation, VM guide i18n fix, dependabot security fix, provider schema expansion. -### Features +### תכונות - **Gemini CLI Deprecation** (#462): Mark `gemini-cli` provider as deprecated with warning — Google restricts third-party OAuth usage from March 2026 - **Provider Schema** (#462): Expand Zod validation with `deprecated`, `deprecationReason`, `hasFree`, `freeNote`, `authHint`, `apiHint` optional fields @@ -4270,7 +4388,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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) -### Security +### אבטחה - **deps**: Bump `flatted` 3.3.3 → 3.4.2 — fixes CWE-1321 prototype pollution (#484, @dependabot) @@ -4290,7 +4408,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Czech i18n, SSE protocol fix, VM guide translation. -### Features +### תכונות - **Czech Language** (#482): Full Czech (cs) i18n — 22 docs, 2606 UI strings, language switcher updates (@zen0bit) - **VM Deployment Guide**: Translated from Portuguese to English as the source document (@zen0bit) @@ -4309,7 +4427,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: 2 merged PRs, model aliases routing fix, log export, and issue triage. -### Features +### תכונות - **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) @@ -4329,7 +4447,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Five community PRs — streaming call log fixes, Kiro compatibility, cache token analytics, Chinese translation, and configurable tool call IDs. -### ✨ Features +### תכונות - **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) - **feat(providers)**: Per-model configurable 9-char tool call ID normalization (Mistral-style) — only models with the option enabled get truncated IDs (#470) @@ -4359,7 +4477,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Bailian Coding Plan provider with editable base URLs, plus community contributions for Alibaba Cloud and Kimi Coding. -### ✨ Features +### תכונות - **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) - **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) @@ -4374,7 +4492,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Two new community-contributed providers (Alibaba Cloud Coding, Kimi Coding API-key) and Docker pino fix. -### ✨ Features +### תכונות - **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) - **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) @@ -4399,7 +4517,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Codex responses subpath passthrough natively supported, Windows MITM crash fixed, and Combos agent schemas adjusted. -### ✨ Features +### תכונות - **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) @@ -4439,7 +4557,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **fix(budget)**: "Save Limits" no longer returns 422 — `warningThreshold` is now correctly sent as fraction (0–1) instead of percentage (0–100) (#451) - **fix(combos)**: `` internal cache tag is now stripped before forwarding requests to providers, preventing cache session breaks (#454) -### ✨ Features +### תכונות - **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) @@ -4495,7 +4613,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Search Tools dashboard, i18n fixes, Copilot limits, Serper validation fix. -### 🚀 Features +### תכונות - **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) - New route: `/dashboard/search-tools` @@ -4595,7 +4713,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - DB migration: `request_type` column on `call_logs` for non-chat request tracking - Zod validation (`v1SearchSchema`), auth-gated, cost recorded via `recordCost()` -### 🔒 Security +### אבטחה - **deps**: Next.js 16.1.6 → 16.1.7 — fixes 6 CVEs: - **Critical**: CVE-2026-29057 (HTTP request smuggling via http-proxy) @@ -4725,7 +4843,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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**: New `request_detail_logs` table with 500-entry ring-buffer trigger, opt-in via settings toggle -### ✨ Features +### תכונות - **feat(combo)**: System Message Override per Combo (#399 — `system_message` field replaces or injects system prompt before forwarding to provider) - **feat(combo)**: Tool Filter Regex per Combo (#399 — `tool_filter_regex` keeps only tools matching pattern; supports OpenAI + Anthropic formats) @@ -4740,7 +4858,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: SSE improvements, local provider_nodes extensions, proxy registry, Claude passthrough fixes. -### ✨ Features +### תכונות - **feat(health)**: Background health check for local `provider_nodes` with exponential backoff (30s→300s) and `Promise.allSettled` to avoid blocking (#423, @Regis-RCR) - **feat(embeddings)**: Route `/v1/embeddings` to local `provider_nodes` — `buildDynamicEmbeddingProvider()` with hostname validation (#422, @Regis-RCR) @@ -4882,7 +5000,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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 - **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). -### ✨ Features +### תכונות - **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) @@ -4912,7 +5030,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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) - **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) -### ✨ Features +### תכונות - **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) - **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. @@ -4971,7 +5089,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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) - **fix(logs)**: Request log table is now readable in light mode — status badges, token counts, and combo tags use adaptive `dark:` color classes (#378) -### ✨ Features +### תכונות - **feat(kiro)**: Kiro credit tracking added to usage fetcher — queries `getUserCredits` from AWS CodeWhisperer endpoint (#337) @@ -5372,7 +5490,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > **Major release** — Free Stack ecosystem, transcription playground overhaul, 44+ providers, comprehensive free tier documentation, and UI improvements across the board. -### ✨ Features +### תכונות - **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. - **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. @@ -5383,7 +5501,7 @@ OmniRoute now automatically refreshes model lists for connected providers every ## [2.3.16] - 2026-03-13 -### 📖 Documentation +### תיעוד - **README: 44+ Providers** — Updated all 3 occurrences of "36+ providers" to "44+" reflecting the actual codebase count (44 providers in providers.ts) - **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. @@ -5393,7 +5511,7 @@ OmniRoute now automatically refreshes model lists for connected providers every ## [2.3.15] - 2026-03-13 -### ✨ Features +### תכונות - **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. - **i18n — autoCombo section**: Added 20 new translation keys for the Auto-Combo dashboard (`title`, `status`, `modePack`, `providerScores`, `factorTierPriority`, etc.) to all 30 language files. diff --git a/docs/i18n/hi/CHANGELOG.md b/docs/i18n/hi/CHANGELOG.md index 89c19e40ae..bbbbfd6766 100644 --- a/docs/i18n/hi/CHANGELOG.md +++ b/docs/i18n/hi/CHANGELOG.md @@ -10,30 +10,148 @@ ### ✨ New Features -- **feat(antigravity):** integrate Antigravity provider with dynamic `maxOutputTokens` calculation (bumping to `thinkingBudget + 1`) and standard Cloud Code envelope payload sanitization (#2055, #2063) +- **feat(antigravity):** integrate Antigravity provider with dynamic `maxOutputTokens` calculation, identity fingerprinting overhaul, and Cloud Code envelope payload sanitization (#2055, #2063) - **feat(gemini-cli):** add custom projectId support for Gemini CLI transport (UI, DB, executor) (#1991) +- **feat(providers):** add KIE media provider support with dynamic polling, text models, and expanded video models catalog +- **feat(providers):** add Z.AI provider support with GLM quota handling and new quota labels +- **feat(providers):** add 9 new free AI providers — LLM7, Lepton, Kluster, UncloseAI, BazaarLink, Completions, Enally, FreeTheAi (#2096) +- **feat(providers):** batch delete provider connections via checkbox multi-select (#2094) +- **feat(cursor):** full OpenAI parity — tool calls, streaming, and session management (#2082) +- **feat(cli):** comprehensive CLI enhancement suite with 20+ new commands including `omniroute providers`, `omniroute combos`, `omniroute doctor` (#2074) +- **feat(cli):** add modular CLI setup and provider management commands (#2046) +- **feat(mcp):** add DeepSeek quota and limit monitoring feature (#2089) +- **feat(circuit-breaker):** classify 429 errors and apply per-kind cooldowns (#2116) +- **feat(multi):** manifest-aware tier routing — W1-W4 complete (#2014) +- **feat(combos):** add reset-aware routing strategy for quota-based providers +- **feat(combo):** add context_length input field to combo edit form (#2047) +- **feat(chat):** dynamic tool limit detection with proactive truncation (#2061) +- **feat(sse):** refresh Claude OAuth wire image to claude-cli/2.1.131 (#2011) +- **feat(github):** add `targetFormat: openai-responses` to all GitHub models (#2122) +- **feat(api):** allow configuration via API calls — open management routes to Bearer keys with manage scope (#2103) +- **feat(api):** update API bridge proxy timeout to 600,000ms (#2019) +- **feat(usage):** add service tier breakdown, codex fast service tier analytics, and account for fast tier +- **feat(chat):** add `STREAM_READINESS_TIMEOUT_MS` and integrate into chat handling +- **feat(combo):** add `fallbackDelayMs` to combo configuration and related settings +- **feat(chat):** enhance error handling for semaphore capacity with fallback logic +- **feat(qdrant):** embedding model discovery (#2086) +- **feat(auth):** per-session sticky routing for Codex (#1887) +- **feat(inworld):** enhance Inworld TTS support (#2123) ### 🐛 Bug Fixes +- **fix(pricing):** make `getPricingForModel` fully case-insensitive to ensure custom prices correctly reflect in new incoming requests cost calculations +- **fix(gemini):** prevent `functionDeclarations` from being dropped by the sanitizer when `googleSearch` tool is present (#2077) +- **fix(pollinations):** add `jsonMode: true` flag in the request transformation to enforce correct JSON structure from Pollinations API (#2109) +- **fix(docker):** update Dockerfile to copy `/docs` directory during build ensuring API catalog availability at runtime (#2083) +- **fix(docker):** include OpenAPI spec in runtime image (#2007) +- **fix(providers):** strip OpenAI-specific fields in Kiro translator to prevent 400 errors (#2037) +- **fix(kiro):** normalize tool-use payloads to prevent 400 errors from agents (#2104) +- **fix(kiro):** merge adjacent user history turns after role normalization (#2105) +- **fix(ui):** resolve text contrast issues for zero-config warning banner in light mode (#2050) +- **fix(core):** inject global system prompt correctly into downstream chat completions pipeline (#2080) +- **fix(core):** restore Claude Code adaptive thinking defaults and resolve audio transcription CORS regression +- **fix(routing):** add missing v1beta rewrites to next.config to resolve 404 on Gemini models endpoint (#2102) +- **fix(routing):** fix bare GPT-5.5 routing for Codex-only installations (#2054) +- **fix(routing):** add fuzzy auto-combo routing for `auto/*` model prefix (#2010) - **fix(cache):** optimize cache_control preservation logic and explicitly align tool schema with upstream Claude Code expectations - **fix(db):** preserve legacy SQLite database path on Windows to prevent data loss (#1973) +- **fix(db):** reduce hot-path persistence overhead (#2039) +- **fix(db):** resolve migration conflict by renumbering overlapping migration entries (#2041) - **fix(settings):** resolve model alias persistence double stringification preventing UI updates (#2018) - **fix(routing):** dynamically filter bare model auto-resolution by active provider connections to prevent dead-routing (#2029) - **fix(embeddings):** add Google Gemini embeddings compatibility via OpenAI-compatible endpoint mapping (#2006) +- **fix(sse):** prevent Claude OAuth multi-account correlation via metadata.user_id (#2053) +- **fix(sse):** prevent Claude Code identity cloak overrides and fix fallback resilience (#2053) +- **fix(sse):** classify hour quota errors as QUOTA_EXHAUSTED (#2119) +- **fix(sse):** fix CC-compatible streaming bridge (#2118) +- **fix(antigravity):** sanitize Claude Cloud Code payloads (#2090) +- **fix(antigravity):** add duplex half for streaming bodies +- **fix(antigravity):** align identity protocol and behavior with official AM +- **fix(chatgpt-web):** plumb proxy through to native tls-client (#2022, #2023) +- **fix(codex):** expose native model IDs in catalog (#2012) +- **fix(glm):** add dedicated coding transport (#2087) +- **fix(compression):** support Responses input and expand Spanish compression rules (#2028) +- **fix(catalog):** auto-calculate combo context_length from target model limits (#2030) +- **fix(api):** fix usage analytics and API key identity (#2008, #2092) +- **fix(api-key):** allow Unicode letters in API key name validation (#1996) +- **fix(auth):** allow bootstrap without password (#2048) +- **fix(proxy):** clean up proxy page redundancy and fix 1proxy sync empty body error (#2052) +- **fix(dashboard):** resolve Unknown plan display in Provider Limits +- **fix(usage):** add extensible CURRENCY_SYMBOLS mapping for deepseek currencies +- **fix(runtime):** harden timer handling and model pricing fallback +- **fix(i18n):** complete Simplified Chinese translations (#2115) +- **fix(mitm):** add Linux cert install and skip sudo password when root (#1999) +- **fix(mitm):** prevent stub from loading at runtime via bypass module - **fix:** remove Anthropic-Beta header from non-Anthropic providers to fix identity contamination (#1989) - **fix(cli):** resolve .env loading failure for global npm installations +- **fix(export):** exclude telemetry/usage-history tables from JSON config backups by default to prevent unbounded file growth (#2125) +- **fix:** Follow OpenAI specification, handle throttling in batch and fix UI (#2045) -### 🔒 Security +### सुरक्षा +- **fix(security):** remediate CodeQL vulnerabilities (ReDoS, cryptographic bias, stack trace exposure, and weak password hashing) (#216, #215, #211, #208, #206, #210) - **fix(security):** remediate regex validation backtracking path in core compression cleanup (#1990) - **fix(core):** harden input handling and stabilization for prompt compression edge cases +### दस्तावेज़ + +- **docs:** add competitive marketing tables and SEO/AEO optimizations to README (#2091) +- **docs:** refresh providers, model catalogs, and docs for v3.8.0 (#2088) +- **docs:** update Claude MD and update GLM-CN max context to 200k (#2027) +- **docs(env):** add `GITLAB_DUO_OAUTH_CLIENT_ID` to `.env.example` (#2031) + ### 🧹 Chores & Maintenance - **chore(providers):** prune redundant local provider icon assets in favor of `@lobehub/icons` web fonts (#1992) +- **chore(providers):** remove deprecated models (#2033) +- **deps:** bump `fast-uri` from 3.1.0 to 3.1.2 (#2078) +- **deps:** bump `hono` from 4.12.14 to 4.12.18 (#2079) - **ci:** skip SonarCloud scan on main pushes to optimize CI time - **test:** stabilize cooldown abort coverage case in integration testing +### 🏆 v3.8.0 Community Contributors + +Thank you to all **38 community contributors** who made v3.8.0 possible! 🎉 + +| Contributor | PRs | Contributions | +| :--------------------------------------------------------- | :-: | :------------------------------------------------------------ | +| [@oyi77](https://github.com/oyi77) | 7 | #2010, #2014, #2041, #2052, #2061, #2074, #2091, #2094, #2096 | +| [@backryun](https://github.com/backryun) | 4 | #1992, #2033, #2088, #2123 | +| [@dhaern](https://github.com/dhaern) | 4 | #2028, #2039, #2087, #2090 | +| [@Tentoxa](https://github.com/Tentoxa) | 2 | #2011, #2053 | +| [@wauputr4](https://github.com/wauputr4) | 2 | #2009, #2046 | +| [@payne0420](https://github.com/payne0420) | 1 | #2082 | +| [@Tr0sT](https://github.com/Tr0sT) | 1 | #2012 | +| [@AveryanAlex](https://github.com/AveryanAlex) | 1 | #2008 | +| [@nickwizard](https://github.com/nickwizard) | 1 | #1991 | +| [@rodrigogbbr-stack](https://github.com/rodrigogbbr-stack) | 1 | #1996 | +| [@NekoMonci12](https://github.com/NekoMonci12) | 1 | #1999 | +| [@congvc-dev](https://github.com/congvc-dev) | 1 | #2004 | +| [@tatsster](https://github.com/tatsster) | 1 | #2007 | +| [@xssdem](https://github.com/xssdem) | 1 | #2023 | +| [@bypanghu](https://github.com/bypanghu) | 1 | #2027 | +| [@herjarsa](https://github.com/herjarsa) | 1 | #2030 | +| [@wucm667](https://github.com/wucm667) | 1 | #2031 | +| [@hartmark](https://github.com/hartmark) | 1 | #2045 | +| [@ddarkr](https://github.com/ddarkr) | 1 | #2047 | +| [@tces1](https://github.com/tces1) | 1 | #2048 | +| [@guanbear](https://github.com/guanbear) | 1 | #2054 | +| [@Gi99lin](https://github.com/Gi99lin) | 1 | #2055 | +| [@ivan-mezentsev](https://github.com/ivan-mezentsev) | 1 | #2063 | +| [@JxnLexn](https://github.com/JxnLexn) | 1 | #2019 | +| [@yoviarpauzi](https://github.com/yoviarpauzi) | 1 | #2092 | +| [@rafacpti23](https://github.com/rafacpti23) | 1 | #2086 | +| [@gleber](https://github.com/gleber) | 1 | #2103 | +| [@rilham97](https://github.com/rilham97) | 1 | #2104 | +| [@Gioxaa](https://github.com/Gioxaa) | 1 | #2105 | +| [@boa-z](https://github.com/boa-z) | 1 | #2115 | +| [@eleata](https://github.com/eleata) | 1 | #2116 | +| [@rdself](https://github.com/rdself) | 1 | #2118 | +| [@clousky2020](https://github.com/clousky2020) | 1 | #2119 | +| [@abhinavjnu](https://github.com/abhinavjnu) | 1 | #2122 | +| [@HoaPham98](https://github.com/HoaPham98) | 1 | #2089 | +| [@05dunski](https://github.com/05dunski) | 1 | #1978 (cherry-picked) | + ## [3.7.9] — 2026-05-03 ### ✨ New Features @@ -102,7 +220,7 @@ - **chore(provider):** Add reka models list (#1956 — thanks @backryun) - **chore(model):** Update new models, Delete Deprecated models (#1949 — thanks @backryun) -### 📝 Documentation +### दस्तावेज़ - **docs(compression):** document RTK+Caveman stacked savings ranges @@ -201,7 +319,7 @@ - **feat(db):** auto-restore probe-failed database on startup to prevent data loss after failed upgrades (#1810) - **feat(analytics):** add cost-based usage insights and activity streaks in the analytics dashboard -### 🔒 Security +### सुरक्षा - **fix(security):** resolve ReDoS vulnerability in Codex executor regex patterns (#1797, #1789) @@ -354,7 +472,7 @@ We identified that **155 community PRs** across the entire project history (from - **feat(proxy):** implement bulk proxy import via pipe-delimited parser with update-or-create (upsert) logic and real-time preview table - **feat(pwa):** add fullscreen installable PWA with manifest, service worker, and cross-platform app icons (#1728) -### 🔒 Security +### सुरक्षा - **security:** replace insecure `Math.random` with `crypto.getRandomValues` for fallback UUID generation to resolve CodeQL CWE-338 finding (#182) @@ -519,7 +637,7 @@ We identified that **155 community PRs** across the entire project history (from - **fix(transport):** Prevent memory bloat and database exhaustion from large, fragmented streaming responses. Implemented `ByteQueue` in `kiro.ts` for zero-copy binary accumulation, refactored `antigravity.ts` for incremental SSE parsing, and enforced a strict 512KB tiered truncation limit (`MAX_CALL_LOG_ARTIFACT_BYTES`) on stream request logs and call artifacts (#1647). - **chore(ci):** Update build environment dependencies — bump Node to `24.15.0`, `actions/checkout@v6`, `docker/build-push-action@v7`, pin `actions/setup-python` to major tag (#1646 — thanks @backryun). -### 📝 Documentation +### दस्तावेज़ - **docs(env):** Add `OMNIROUTE_ALLOW_PRIVATE_PROVIDER_URLS` to `.env.example` with documentation for LM Studio and other local provider use cases (#1623). @@ -669,7 +787,7 @@ We identified that **155 community PRs** across the entire project history (from - **test(next):** Align transpile package expectations for the Next.js standalone build. - **test(ci):** Fix CI-only test failures from environment differences — clear `INITIAL_PASSWORD` and `JWT_SECRET` in integration tests, handle `XDG_CONFIG_HOME` for guide-settings tests. -### 📚 Documentation +### दस्तावेज़ - **docs:** Update the root changelog with all release-branch changes through 2026-04-24, including PRs #1544, #1555, #1551, #1550, #1548, #1547, #1541, #1538, #1536, and #1527. - **docs:** Fix broken README and localized documentation links. (#1536) @@ -811,7 +929,7 @@ We identified that **155 community PRs** across the entire project history (from - **feat(providers):** Expand image provider registry with extended model support including SD3.5, FLUX, and DALL-E 3 HD configurations - **feat(combos):** Add new routing strategies and full i18n support for agent features section across 31 languages -### 🔒 Security +### सुरक्षा - **security:** Resolve 18 GitHub CodeQL scan alerts including ReDoS, incomplete sanitization, and bad HTML filtering regexp patterns - **fix(auth):** Seal privilege escalation vector by enforcing JWT session checking exclusively on `/api/keys` management endpoints (#1353) @@ -1078,7 +1196,7 @@ We identified that **155 community PRs** across the entire project history (from - **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 - **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 -### 🔒 Security +### सुरक्षा - **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 - **Auth Guard on Translator Save:** Added `isAuthenticated` guard to `/api/translator/save` for defense-in-depth consistency @@ -1483,7 +1601,7 @@ We identified that **155 community PRs** across the entire project history (from - **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). -### 📚 Documentation +### दस्तावेज़ - **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. - **Context Relay Delivery Notes:** Documented the current architecture, runtime flow, and Codex-focused scope in the feature docs, changelog, and agent guidance. @@ -1559,7 +1677,7 @@ We identified that **155 community PRs** across the entire project history (from ## [3.5.3] - 2026-04-07 -### Security +### सुरक्षा - **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. - **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. @@ -1575,7 +1693,7 @@ We identified that **155 community PRs** across the entire project history (from - **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. -### Documentation +### दस्तावेज़ - **I18n Engine:** Synchronized and pushed deep Machine Translation updates across all 32 natively-supported languages (682 translation nodes aligned). @@ -1736,7 +1854,7 @@ We identified that **155 community PRs** across the entire project history (from ## [3.4.8] — 2026-04-03 -### Security +### सुरक्षा - Fully remediated all outstanding Github Advanced Security (CodeQL) findings and Dependabot alerts. - Fixed insecure randomness vulnerabilities by migrating from `Math.random` to `crypto.randomUUID()`. @@ -1748,7 +1866,7 @@ We identified that **155 community PRs** across the entire project history (from ## [3.4.7] — 2026-04-03 -### Features +### विशेषताएं - Added `Cryptography` node to Monitoring and MCP health checks (#798) - Hardened model-catalog route permissions mapping (`/models`) (#781) @@ -1764,7 +1882,7 @@ We identified that **155 community PRs** across the entire project history (from - Fixed MCP standalone module-resolution (`ERR_MODULE_NOT_FOUND`) via `esbuild` (#936) - Fixed NVIDIA NIM routing credential resolution alias mismatch (#931) -### Security +### सुरक्षा - Added safe strict input boundary protection against raw `shell: true` remote-code execution injections. @@ -2011,7 +2129,7 @@ We identified that **155 community PRs** across the entire project history (from ## [3.4.0] - 2026-03-31 -### 🚀 Features +### विशेषताएं - **Subscription Utilization Analytics:** Added quota snapshot time-series tracking, Provider Utilization and Combo Health tabs with recharts visualizations, and corresponding API endpoints (#847) - **SQLite Backup Control:** New `OMNIROUTE_DISABLE_AUTO_BACKUP` env flag to disable automatic SQLite backups (#846) @@ -2063,7 +2181,7 @@ We identified that **155 community PRs** across the entire project history (from ## [3.3.8] - 2026-03-30 -### 🚀 Features +### विशेषताएं - **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) - **Qoder Integration:** Native integration for Qoder AI natively replacing the legacy iFlow platform mappings (#660) @@ -2889,7 +3007,7 @@ We identified that **155 community PRs** across the entire project history (from - **NaN tokens in Claude Code / client responses (#617):** - `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 -### 🔒 Security +### सुरक्षा - Updated `yaml` package to fix stack overflow vulnerability (GHSA-48c2-rrv3-qjmp) @@ -3565,7 +3683,7 @@ docker pull diegosouzapw/omniroute:3.0.0 - **SVG fallback**: `ProviderIcon` component updated with 4-tier strategy: Lobehub → PNG → SVG → Generic icon - **Agents fingerprinting**: Synced with CLI tools — added droid, openclaw, copilot, opencode to fingerprint list (14 total) -### 🔒 Security +### सुरक्षा - **CVE fix**: Resolved dompurify XSS vulnerability (GHSA-v2wj-7wpq-c8vv) via npm overrides forcing `dompurify@^3.3.2` - `npm audit` now reports **0 vulnerabilities** @@ -3928,7 +4046,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **#510** — Windows: MSYS2/Git-Bash paths (`/c/Program Files/...`) are now normalized to `C:\Program Files\...` - **#492** — `omniroute` CLI now detects `mise`/`nvm` when `app/server.js` is missing and shows targeted fix -### 📖 Documentation +### दस्तावेज़ - **#513** — Docker password reset: `INITIAL_PASSWORD` env var workaround documented - **#520** — pnpm: `pnpm approve-builds better-sqlite3` documented @@ -4025,7 +4143,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **feat(executors/cloudflare-ai)**: New `CloudflareAIExecutor` — dynamic URL construction requires `accountId` in provider credentials - **feat(executors)**: Register `pollinations`, `pol`, `cloudflare-ai`, `cf` executor mappings -### 📝 Documentation +### दस्तावेज़ - **docs(readme)**: Expanded free combo stack to 11 providers ($0 forever) - **docs(readme)**: Added 4 new free provider sections (LongCat, Pollinations, Cloudflare AI, Scaleway) with model tables @@ -4177,7 +4295,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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). -### Features +### विशेषताएं - **"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. @@ -4205,7 +4323,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Merge PR #494 (MiniMax role fix), fix KIRO MITM dashboard, triage 8 issues. -### Features +### विशेषताएं - **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. - **roleNormalizer**: `normalizeDeveloperRole()` now accepts `preserveDeveloperRole` parameter with tri-state behavior (undefined=keep, true=keep, false=convert). @@ -4261,7 +4379,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Gemini CLI deprecation, VM guide i18n fix, dependabot security fix, provider schema expansion. -### Features +### विशेषताएं - **Gemini CLI Deprecation** (#462): Mark `gemini-cli` provider as deprecated with warning — Google restricts third-party OAuth usage from March 2026 - **Provider Schema** (#462): Expand Zod validation with `deprecated`, `deprecationReason`, `hasFree`, `freeNote`, `authHint`, `apiHint` optional fields @@ -4270,7 +4388,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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) -### Security +### सुरक्षा - **deps**: Bump `flatted` 3.3.3 → 3.4.2 — fixes CWE-1321 prototype pollution (#484, @dependabot) @@ -4290,7 +4408,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Czech i18n, SSE protocol fix, VM guide translation. -### Features +### विशेषताएं - **Czech Language** (#482): Full Czech (cs) i18n — 22 docs, 2606 UI strings, language switcher updates (@zen0bit) - **VM Deployment Guide**: Translated from Portuguese to English as the source document (@zen0bit) @@ -4309,7 +4427,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: 2 merged PRs, model aliases routing fix, log export, and issue triage. -### Features +### विशेषताएं - **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) @@ -4329,7 +4447,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Five community PRs — streaming call log fixes, Kiro compatibility, cache token analytics, Chinese translation, and configurable tool call IDs. -### ✨ Features +### विशेषताएं - **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) - **feat(providers)**: Per-model configurable 9-char tool call ID normalization (Mistral-style) — only models with the option enabled get truncated IDs (#470) @@ -4359,7 +4477,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Bailian Coding Plan provider with editable base URLs, plus community contributions for Alibaba Cloud and Kimi Coding. -### ✨ Features +### विशेषताएं - **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) - **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) @@ -4374,7 +4492,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Two new community-contributed providers (Alibaba Cloud Coding, Kimi Coding API-key) and Docker pino fix. -### ✨ Features +### विशेषताएं - **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) - **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) @@ -4399,7 +4517,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Codex responses subpath passthrough natively supported, Windows MITM crash fixed, and Combos agent schemas adjusted. -### ✨ Features +### विशेषताएं - **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) @@ -4439,7 +4557,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **fix(budget)**: "Save Limits" no longer returns 422 — `warningThreshold` is now correctly sent as fraction (0–1) instead of percentage (0–100) (#451) - **fix(combos)**: `` internal cache tag is now stripped before forwarding requests to providers, preventing cache session breaks (#454) -### ✨ Features +### विशेषताएं - **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) @@ -4495,7 +4613,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Search Tools dashboard, i18n fixes, Copilot limits, Serper validation fix. -### 🚀 Features +### विशेषताएं - **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) - New route: `/dashboard/search-tools` @@ -4595,7 +4713,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - DB migration: `request_type` column on `call_logs` for non-chat request tracking - Zod validation (`v1SearchSchema`), auth-gated, cost recorded via `recordCost()` -### 🔒 Security +### सुरक्षा - **deps**: Next.js 16.1.6 → 16.1.7 — fixes 6 CVEs: - **Critical**: CVE-2026-29057 (HTTP request smuggling via http-proxy) @@ -4725,7 +4843,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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**: New `request_detail_logs` table with 500-entry ring-buffer trigger, opt-in via settings toggle -### ✨ Features +### विशेषताएं - **feat(combo)**: System Message Override per Combo (#399 — `system_message` field replaces or injects system prompt before forwarding to provider) - **feat(combo)**: Tool Filter Regex per Combo (#399 — `tool_filter_regex` keeps only tools matching pattern; supports OpenAI + Anthropic formats) @@ -4740,7 +4858,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: SSE improvements, local provider_nodes extensions, proxy registry, Claude passthrough fixes. -### ✨ Features +### विशेषताएं - **feat(health)**: Background health check for local `provider_nodes` with exponential backoff (30s→300s) and `Promise.allSettled` to avoid blocking (#423, @Regis-RCR) - **feat(embeddings)**: Route `/v1/embeddings` to local `provider_nodes` — `buildDynamicEmbeddingProvider()` with hostname validation (#422, @Regis-RCR) @@ -4882,7 +5000,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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 - **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). -### ✨ Features +### विशेषताएं - **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) @@ -4912,7 +5030,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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) - **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) -### ✨ Features +### विशेषताएं - **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) - **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. @@ -4971,7 +5089,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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) - **fix(logs)**: Request log table is now readable in light mode — status badges, token counts, and combo tags use adaptive `dark:` color classes (#378) -### ✨ Features +### विशेषताएं - **feat(kiro)**: Kiro credit tracking added to usage fetcher — queries `getUserCredits` from AWS CodeWhisperer endpoint (#337) @@ -5372,7 +5490,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > **Major release** — Free Stack ecosystem, transcription playground overhaul, 44+ providers, comprehensive free tier documentation, and UI improvements across the board. -### ✨ Features +### विशेषताएं - **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. - **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. @@ -5383,7 +5501,7 @@ OmniRoute now automatically refreshes model lists for connected providers every ## [2.3.16] - 2026-03-13 -### 📖 Documentation +### दस्तावेज़ - **README: 44+ Providers** — Updated all 3 occurrences of "36+ providers" to "44+" reflecting the actual codebase count (44 providers in providers.ts) - **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. @@ -5393,7 +5511,7 @@ OmniRoute now automatically refreshes model lists for connected providers every ## [2.3.15] - 2026-03-13 -### ✨ Features +### विशेषताएं - **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. - **i18n — autoCombo section**: Added 20 new translation keys for the Auto-Combo dashboard (`title`, `status`, `modePack`, `providerScores`, `factorTierPriority`, etc.) to all 30 language files. diff --git a/docs/i18n/hu/CHANGELOG.md b/docs/i18n/hu/CHANGELOG.md index 79f97153c7..a00a13ec91 100644 --- a/docs/i18n/hu/CHANGELOG.md +++ b/docs/i18n/hu/CHANGELOG.md @@ -10,30 +10,148 @@ ### ✨ New Features -- **feat(antigravity):** integrate Antigravity provider with dynamic `maxOutputTokens` calculation (bumping to `thinkingBudget + 1`) and standard Cloud Code envelope payload sanitization (#2055, #2063) +- **feat(antigravity):** integrate Antigravity provider with dynamic `maxOutputTokens` calculation, identity fingerprinting overhaul, and Cloud Code envelope payload sanitization (#2055, #2063) - **feat(gemini-cli):** add custom projectId support for Gemini CLI transport (UI, DB, executor) (#1991) +- **feat(providers):** add KIE media provider support with dynamic polling, text models, and expanded video models catalog +- **feat(providers):** add Z.AI provider support with GLM quota handling and new quota labels +- **feat(providers):** add 9 new free AI providers — LLM7, Lepton, Kluster, UncloseAI, BazaarLink, Completions, Enally, FreeTheAi (#2096) +- **feat(providers):** batch delete provider connections via checkbox multi-select (#2094) +- **feat(cursor):** full OpenAI parity — tool calls, streaming, and session management (#2082) +- **feat(cli):** comprehensive CLI enhancement suite with 20+ new commands including `omniroute providers`, `omniroute combos`, `omniroute doctor` (#2074) +- **feat(cli):** add modular CLI setup and provider management commands (#2046) +- **feat(mcp):** add DeepSeek quota and limit monitoring feature (#2089) +- **feat(circuit-breaker):** classify 429 errors and apply per-kind cooldowns (#2116) +- **feat(multi):** manifest-aware tier routing — W1-W4 complete (#2014) +- **feat(combos):** add reset-aware routing strategy for quota-based providers +- **feat(combo):** add context_length input field to combo edit form (#2047) +- **feat(chat):** dynamic tool limit detection with proactive truncation (#2061) +- **feat(sse):** refresh Claude OAuth wire image to claude-cli/2.1.131 (#2011) +- **feat(github):** add `targetFormat: openai-responses` to all GitHub models (#2122) +- **feat(api):** allow configuration via API calls — open management routes to Bearer keys with manage scope (#2103) +- **feat(api):** update API bridge proxy timeout to 600,000ms (#2019) +- **feat(usage):** add service tier breakdown, codex fast service tier analytics, and account for fast tier +- **feat(chat):** add `STREAM_READINESS_TIMEOUT_MS` and integrate into chat handling +- **feat(combo):** add `fallbackDelayMs` to combo configuration and related settings +- **feat(chat):** enhance error handling for semaphore capacity with fallback logic +- **feat(qdrant):** embedding model discovery (#2086) +- **feat(auth):** per-session sticky routing for Codex (#1887) +- **feat(inworld):** enhance Inworld TTS support (#2123) ### 🐛 Bug Fixes +- **fix(pricing):** make `getPricingForModel` fully case-insensitive to ensure custom prices correctly reflect in new incoming requests cost calculations +- **fix(gemini):** prevent `functionDeclarations` from being dropped by the sanitizer when `googleSearch` tool is present (#2077) +- **fix(pollinations):** add `jsonMode: true` flag in the request transformation to enforce correct JSON structure from Pollinations API (#2109) +- **fix(docker):** update Dockerfile to copy `/docs` directory during build ensuring API catalog availability at runtime (#2083) +- **fix(docker):** include OpenAPI spec in runtime image (#2007) +- **fix(providers):** strip OpenAI-specific fields in Kiro translator to prevent 400 errors (#2037) +- **fix(kiro):** normalize tool-use payloads to prevent 400 errors from agents (#2104) +- **fix(kiro):** merge adjacent user history turns after role normalization (#2105) +- **fix(ui):** resolve text contrast issues for zero-config warning banner in light mode (#2050) +- **fix(core):** inject global system prompt correctly into downstream chat completions pipeline (#2080) +- **fix(core):** restore Claude Code adaptive thinking defaults and resolve audio transcription CORS regression +- **fix(routing):** add missing v1beta rewrites to next.config to resolve 404 on Gemini models endpoint (#2102) +- **fix(routing):** fix bare GPT-5.5 routing for Codex-only installations (#2054) +- **fix(routing):** add fuzzy auto-combo routing for `auto/*` model prefix (#2010) - **fix(cache):** optimize cache_control preservation logic and explicitly align tool schema with upstream Claude Code expectations - **fix(db):** preserve legacy SQLite database path on Windows to prevent data loss (#1973) +- **fix(db):** reduce hot-path persistence overhead (#2039) +- **fix(db):** resolve migration conflict by renumbering overlapping migration entries (#2041) - **fix(settings):** resolve model alias persistence double stringification preventing UI updates (#2018) - **fix(routing):** dynamically filter bare model auto-resolution by active provider connections to prevent dead-routing (#2029) - **fix(embeddings):** add Google Gemini embeddings compatibility via OpenAI-compatible endpoint mapping (#2006) +- **fix(sse):** prevent Claude OAuth multi-account correlation via metadata.user_id (#2053) +- **fix(sse):** prevent Claude Code identity cloak overrides and fix fallback resilience (#2053) +- **fix(sse):** classify hour quota errors as QUOTA_EXHAUSTED (#2119) +- **fix(sse):** fix CC-compatible streaming bridge (#2118) +- **fix(antigravity):** sanitize Claude Cloud Code payloads (#2090) +- **fix(antigravity):** add duplex half for streaming bodies +- **fix(antigravity):** align identity protocol and behavior with official AM +- **fix(chatgpt-web):** plumb proxy through to native tls-client (#2022, #2023) +- **fix(codex):** expose native model IDs in catalog (#2012) +- **fix(glm):** add dedicated coding transport (#2087) +- **fix(compression):** support Responses input and expand Spanish compression rules (#2028) +- **fix(catalog):** auto-calculate combo context_length from target model limits (#2030) +- **fix(api):** fix usage analytics and API key identity (#2008, #2092) +- **fix(api-key):** allow Unicode letters in API key name validation (#1996) +- **fix(auth):** allow bootstrap without password (#2048) +- **fix(proxy):** clean up proxy page redundancy and fix 1proxy sync empty body error (#2052) +- **fix(dashboard):** resolve Unknown plan display in Provider Limits +- **fix(usage):** add extensible CURRENCY_SYMBOLS mapping for deepseek currencies +- **fix(runtime):** harden timer handling and model pricing fallback +- **fix(i18n):** complete Simplified Chinese translations (#2115) +- **fix(mitm):** add Linux cert install and skip sudo password when root (#1999) +- **fix(mitm):** prevent stub from loading at runtime via bypass module - **fix:** remove Anthropic-Beta header from non-Anthropic providers to fix identity contamination (#1989) - **fix(cli):** resolve .env loading failure for global npm installations +- **fix(export):** exclude telemetry/usage-history tables from JSON config backups by default to prevent unbounded file growth (#2125) +- **fix:** Follow OpenAI specification, handle throttling in batch and fix UI (#2045) -### 🔒 Security +### Biztonság +- **fix(security):** remediate CodeQL vulnerabilities (ReDoS, cryptographic bias, stack trace exposure, and weak password hashing) (#216, #215, #211, #208, #206, #210) - **fix(security):** remediate regex validation backtracking path in core compression cleanup (#1990) - **fix(core):** harden input handling and stabilization for prompt compression edge cases +### Dokumentáció + +- **docs:** add competitive marketing tables and SEO/AEO optimizations to README (#2091) +- **docs:** refresh providers, model catalogs, and docs for v3.8.0 (#2088) +- **docs:** update Claude MD and update GLM-CN max context to 200k (#2027) +- **docs(env):** add `GITLAB_DUO_OAUTH_CLIENT_ID` to `.env.example` (#2031) + ### 🧹 Chores & Maintenance - **chore(providers):** prune redundant local provider icon assets in favor of `@lobehub/icons` web fonts (#1992) +- **chore(providers):** remove deprecated models (#2033) +- **deps:** bump `fast-uri` from 3.1.0 to 3.1.2 (#2078) +- **deps:** bump `hono` from 4.12.14 to 4.12.18 (#2079) - **ci:** skip SonarCloud scan on main pushes to optimize CI time - **test:** stabilize cooldown abort coverage case in integration testing +### 🏆 v3.8.0 Community Contributors + +Thank you to all **38 community contributors** who made v3.8.0 possible! 🎉 + +| Contributor | PRs | Contributions | +| :--------------------------------------------------------- | :-: | :------------------------------------------------------------ | +| [@oyi77](https://github.com/oyi77) | 7 | #2010, #2014, #2041, #2052, #2061, #2074, #2091, #2094, #2096 | +| [@backryun](https://github.com/backryun) | 4 | #1992, #2033, #2088, #2123 | +| [@dhaern](https://github.com/dhaern) | 4 | #2028, #2039, #2087, #2090 | +| [@Tentoxa](https://github.com/Tentoxa) | 2 | #2011, #2053 | +| [@wauputr4](https://github.com/wauputr4) | 2 | #2009, #2046 | +| [@payne0420](https://github.com/payne0420) | 1 | #2082 | +| [@Tr0sT](https://github.com/Tr0sT) | 1 | #2012 | +| [@AveryanAlex](https://github.com/AveryanAlex) | 1 | #2008 | +| [@nickwizard](https://github.com/nickwizard) | 1 | #1991 | +| [@rodrigogbbr-stack](https://github.com/rodrigogbbr-stack) | 1 | #1996 | +| [@NekoMonci12](https://github.com/NekoMonci12) | 1 | #1999 | +| [@congvc-dev](https://github.com/congvc-dev) | 1 | #2004 | +| [@tatsster](https://github.com/tatsster) | 1 | #2007 | +| [@xssdem](https://github.com/xssdem) | 1 | #2023 | +| [@bypanghu](https://github.com/bypanghu) | 1 | #2027 | +| [@herjarsa](https://github.com/herjarsa) | 1 | #2030 | +| [@wucm667](https://github.com/wucm667) | 1 | #2031 | +| [@hartmark](https://github.com/hartmark) | 1 | #2045 | +| [@ddarkr](https://github.com/ddarkr) | 1 | #2047 | +| [@tces1](https://github.com/tces1) | 1 | #2048 | +| [@guanbear](https://github.com/guanbear) | 1 | #2054 | +| [@Gi99lin](https://github.com/Gi99lin) | 1 | #2055 | +| [@ivan-mezentsev](https://github.com/ivan-mezentsev) | 1 | #2063 | +| [@JxnLexn](https://github.com/JxnLexn) | 1 | #2019 | +| [@yoviarpauzi](https://github.com/yoviarpauzi) | 1 | #2092 | +| [@rafacpti23](https://github.com/rafacpti23) | 1 | #2086 | +| [@gleber](https://github.com/gleber) | 1 | #2103 | +| [@rilham97](https://github.com/rilham97) | 1 | #2104 | +| [@Gioxaa](https://github.com/Gioxaa) | 1 | #2105 | +| [@boa-z](https://github.com/boa-z) | 1 | #2115 | +| [@eleata](https://github.com/eleata) | 1 | #2116 | +| [@rdself](https://github.com/rdself) | 1 | #2118 | +| [@clousky2020](https://github.com/clousky2020) | 1 | #2119 | +| [@abhinavjnu](https://github.com/abhinavjnu) | 1 | #2122 | +| [@HoaPham98](https://github.com/HoaPham98) | 1 | #2089 | +| [@05dunski](https://github.com/05dunski) | 1 | #1978 (cherry-picked) | + ## [3.7.9] — 2026-05-03 ### ✨ New Features @@ -102,7 +220,7 @@ - **chore(provider):** Add reka models list (#1956 — thanks @backryun) - **chore(model):** Update new models, Delete Deprecated models (#1949 — thanks @backryun) -### 📝 Documentation +### Dokumentáció - **docs(compression):** document RTK+Caveman stacked savings ranges @@ -201,7 +319,7 @@ - **feat(db):** auto-restore probe-failed database on startup to prevent data loss after failed upgrades (#1810) - **feat(analytics):** add cost-based usage insights and activity streaks in the analytics dashboard -### 🔒 Security +### Biztonság - **fix(security):** resolve ReDoS vulnerability in Codex executor regex patterns (#1797, #1789) @@ -354,7 +472,7 @@ We identified that **155 community PRs** across the entire project history (from - **feat(proxy):** implement bulk proxy import via pipe-delimited parser with update-or-create (upsert) logic and real-time preview table - **feat(pwa):** add fullscreen installable PWA with manifest, service worker, and cross-platform app icons (#1728) -### 🔒 Security +### Biztonság - **security:** replace insecure `Math.random` with `crypto.getRandomValues` for fallback UUID generation to resolve CodeQL CWE-338 finding (#182) @@ -519,7 +637,7 @@ We identified that **155 community PRs** across the entire project history (from - **fix(transport):** Prevent memory bloat and database exhaustion from large, fragmented streaming responses. Implemented `ByteQueue` in `kiro.ts` for zero-copy binary accumulation, refactored `antigravity.ts` for incremental SSE parsing, and enforced a strict 512KB tiered truncation limit (`MAX_CALL_LOG_ARTIFACT_BYTES`) on stream request logs and call artifacts (#1647). - **chore(ci):** Update build environment dependencies — bump Node to `24.15.0`, `actions/checkout@v6`, `docker/build-push-action@v7`, pin `actions/setup-python` to major tag (#1646 — thanks @backryun). -### 📝 Documentation +### Dokumentáció - **docs(env):** Add `OMNIROUTE_ALLOW_PRIVATE_PROVIDER_URLS` to `.env.example` with documentation for LM Studio and other local provider use cases (#1623). @@ -669,7 +787,7 @@ We identified that **155 community PRs** across the entire project history (from - **test(next):** Align transpile package expectations for the Next.js standalone build. - **test(ci):** Fix CI-only test failures from environment differences — clear `INITIAL_PASSWORD` and `JWT_SECRET` in integration tests, handle `XDG_CONFIG_HOME` for guide-settings tests. -### 📚 Documentation +### Dokumentáció - **docs:** Update the root changelog with all release-branch changes through 2026-04-24, including PRs #1544, #1555, #1551, #1550, #1548, #1547, #1541, #1538, #1536, and #1527. - **docs:** Fix broken README and localized documentation links. (#1536) @@ -811,7 +929,7 @@ We identified that **155 community PRs** across the entire project history (from - **feat(providers):** Expand image provider registry with extended model support including SD3.5, FLUX, and DALL-E 3 HD configurations - **feat(combos):** Add new routing strategies and full i18n support for agent features section across 31 languages -### 🔒 Security +### Biztonság - **security:** Resolve 18 GitHub CodeQL scan alerts including ReDoS, incomplete sanitization, and bad HTML filtering regexp patterns - **fix(auth):** Seal privilege escalation vector by enforcing JWT session checking exclusively on `/api/keys` management endpoints (#1353) @@ -1078,7 +1196,7 @@ We identified that **155 community PRs** across the entire project history (from - **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 - **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 -### 🔒 Security +### Biztonság - **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 - **Auth Guard on Translator Save:** Added `isAuthenticated` guard to `/api/translator/save` for defense-in-depth consistency @@ -1483,7 +1601,7 @@ We identified that **155 community PRs** across the entire project history (from - **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). -### 📚 Documentation +### Dokumentáció - **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. - **Context Relay Delivery Notes:** Documented the current architecture, runtime flow, and Codex-focused scope in the feature docs, changelog, and agent guidance. @@ -1559,7 +1677,7 @@ We identified that **155 community PRs** across the entire project history (from ## [3.5.3] - 2026-04-07 -### Security +### Biztonság - **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. - **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. @@ -1575,7 +1693,7 @@ We identified that **155 community PRs** across the entire project history (from - **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. -### Documentation +### Dokumentáció - **I18n Engine:** Synchronized and pushed deep Machine Translation updates across all 32 natively-supported languages (682 translation nodes aligned). @@ -1736,7 +1854,7 @@ We identified that **155 community PRs** across the entire project history (from ## [3.4.8] — 2026-04-03 -### Security +### Biztonság - Fully remediated all outstanding Github Advanced Security (CodeQL) findings and Dependabot alerts. - Fixed insecure randomness vulnerabilities by migrating from `Math.random` to `crypto.randomUUID()`. @@ -1748,7 +1866,7 @@ We identified that **155 community PRs** across the entire project history (from ## [3.4.7] — 2026-04-03 -### Features +### Funkciók - Added `Cryptography` node to Monitoring and MCP health checks (#798) - Hardened model-catalog route permissions mapping (`/models`) (#781) @@ -1764,7 +1882,7 @@ We identified that **155 community PRs** across the entire project history (from - Fixed MCP standalone module-resolution (`ERR_MODULE_NOT_FOUND`) via `esbuild` (#936) - Fixed NVIDIA NIM routing credential resolution alias mismatch (#931) -### Security +### Biztonság - Added safe strict input boundary protection against raw `shell: true` remote-code execution injections. @@ -2011,7 +2129,7 @@ We identified that **155 community PRs** across the entire project history (from ## [3.4.0] - 2026-03-31 -### 🚀 Features +### Funkciók - **Subscription Utilization Analytics:** Added quota snapshot time-series tracking, Provider Utilization and Combo Health tabs with recharts visualizations, and corresponding API endpoints (#847) - **SQLite Backup Control:** New `OMNIROUTE_DISABLE_AUTO_BACKUP` env flag to disable automatic SQLite backups (#846) @@ -2063,7 +2181,7 @@ We identified that **155 community PRs** across the entire project history (from ## [3.3.8] - 2026-03-30 -### 🚀 Features +### Funkciók - **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) - **Qoder Integration:** Native integration for Qoder AI natively replacing the legacy iFlow platform mappings (#660) @@ -2889,7 +3007,7 @@ We identified that **155 community PRs** across the entire project history (from - **NaN tokens in Claude Code / client responses (#617):** - `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 -### 🔒 Security +### Biztonság - Updated `yaml` package to fix stack overflow vulnerability (GHSA-48c2-rrv3-qjmp) @@ -3565,7 +3683,7 @@ docker pull diegosouzapw/omniroute:3.0.0 - **SVG fallback**: `ProviderIcon` component updated with 4-tier strategy: Lobehub → PNG → SVG → Generic icon - **Agents fingerprinting**: Synced with CLI tools — added droid, openclaw, copilot, opencode to fingerprint list (14 total) -### 🔒 Security +### Biztonság - **CVE fix**: Resolved dompurify XSS vulnerability (GHSA-v2wj-7wpq-c8vv) via npm overrides forcing `dompurify@^3.3.2` - `npm audit` now reports **0 vulnerabilities** @@ -3928,7 +4046,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **#510** — Windows: MSYS2/Git-Bash paths (`/c/Program Files/...`) are now normalized to `C:\Program Files\...` - **#492** — `omniroute` CLI now detects `mise`/`nvm` when `app/server.js` is missing and shows targeted fix -### 📖 Documentation +### Dokumentáció - **#513** — Docker password reset: `INITIAL_PASSWORD` env var workaround documented - **#520** — pnpm: `pnpm approve-builds better-sqlite3` documented @@ -4025,7 +4143,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **feat(executors/cloudflare-ai)**: New `CloudflareAIExecutor` — dynamic URL construction requires `accountId` in provider credentials - **feat(executors)**: Register `pollinations`, `pol`, `cloudflare-ai`, `cf` executor mappings -### 📝 Documentation +### Dokumentáció - **docs(readme)**: Expanded free combo stack to 11 providers ($0 forever) - **docs(readme)**: Added 4 new free provider sections (LongCat, Pollinations, Cloudflare AI, Scaleway) with model tables @@ -4177,7 +4295,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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). -### Features +### Funkciók - **"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. @@ -4205,7 +4323,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Merge PR #494 (MiniMax role fix), fix KIRO MITM dashboard, triage 8 issues. -### Features +### Funkciók - **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. - **roleNormalizer**: `normalizeDeveloperRole()` now accepts `preserveDeveloperRole` parameter with tri-state behavior (undefined=keep, true=keep, false=convert). @@ -4261,7 +4379,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Gemini CLI deprecation, VM guide i18n fix, dependabot security fix, provider schema expansion. -### Features +### Funkciók - **Gemini CLI Deprecation** (#462): Mark `gemini-cli` provider as deprecated with warning — Google restricts third-party OAuth usage from March 2026 - **Provider Schema** (#462): Expand Zod validation with `deprecated`, `deprecationReason`, `hasFree`, `freeNote`, `authHint`, `apiHint` optional fields @@ -4270,7 +4388,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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) -### Security +### Biztonság - **deps**: Bump `flatted` 3.3.3 → 3.4.2 — fixes CWE-1321 prototype pollution (#484, @dependabot) @@ -4290,7 +4408,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Czech i18n, SSE protocol fix, VM guide translation. -### Features +### Funkciók - **Czech Language** (#482): Full Czech (cs) i18n — 22 docs, 2606 UI strings, language switcher updates (@zen0bit) - **VM Deployment Guide**: Translated from Portuguese to English as the source document (@zen0bit) @@ -4309,7 +4427,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: 2 merged PRs, model aliases routing fix, log export, and issue triage. -### Features +### Funkciók - **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) @@ -4329,7 +4447,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Five community PRs — streaming call log fixes, Kiro compatibility, cache token analytics, Chinese translation, and configurable tool call IDs. -### ✨ Features +### Funkciók - **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) - **feat(providers)**: Per-model configurable 9-char tool call ID normalization (Mistral-style) — only models with the option enabled get truncated IDs (#470) @@ -4359,7 +4477,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Bailian Coding Plan provider with editable base URLs, plus community contributions for Alibaba Cloud and Kimi Coding. -### ✨ Features +### Funkciók - **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) - **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) @@ -4374,7 +4492,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Two new community-contributed providers (Alibaba Cloud Coding, Kimi Coding API-key) and Docker pino fix. -### ✨ Features +### Funkciók - **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) - **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) @@ -4399,7 +4517,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Codex responses subpath passthrough natively supported, Windows MITM crash fixed, and Combos agent schemas adjusted. -### ✨ Features +### Funkciók - **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) @@ -4439,7 +4557,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **fix(budget)**: "Save Limits" no longer returns 422 — `warningThreshold` is now correctly sent as fraction (0–1) instead of percentage (0–100) (#451) - **fix(combos)**: `` internal cache tag is now stripped before forwarding requests to providers, preventing cache session breaks (#454) -### ✨ Features +### Funkciók - **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) @@ -4495,7 +4613,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Search Tools dashboard, i18n fixes, Copilot limits, Serper validation fix. -### 🚀 Features +### Funkciók - **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) - New route: `/dashboard/search-tools` @@ -4595,7 +4713,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - DB migration: `request_type` column on `call_logs` for non-chat request tracking - Zod validation (`v1SearchSchema`), auth-gated, cost recorded via `recordCost()` -### 🔒 Security +### Biztonság - **deps**: Next.js 16.1.6 → 16.1.7 — fixes 6 CVEs: - **Critical**: CVE-2026-29057 (HTTP request smuggling via http-proxy) @@ -4725,7 +4843,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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**: New `request_detail_logs` table with 500-entry ring-buffer trigger, opt-in via settings toggle -### ✨ Features +### Funkciók - **feat(combo)**: System Message Override per Combo (#399 — `system_message` field replaces or injects system prompt before forwarding to provider) - **feat(combo)**: Tool Filter Regex per Combo (#399 — `tool_filter_regex` keeps only tools matching pattern; supports OpenAI + Anthropic formats) @@ -4740,7 +4858,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: SSE improvements, local provider_nodes extensions, proxy registry, Claude passthrough fixes. -### ✨ Features +### Funkciók - **feat(health)**: Background health check for local `provider_nodes` with exponential backoff (30s→300s) and `Promise.allSettled` to avoid blocking (#423, @Regis-RCR) - **feat(embeddings)**: Route `/v1/embeddings` to local `provider_nodes` — `buildDynamicEmbeddingProvider()` with hostname validation (#422, @Regis-RCR) @@ -4882,7 +5000,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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 - **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). -### ✨ Features +### Funkciók - **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) @@ -4912,7 +5030,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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) - **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) -### ✨ Features +### Funkciók - **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) - **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. @@ -4971,7 +5089,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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) - **fix(logs)**: Request log table is now readable in light mode — status badges, token counts, and combo tags use adaptive `dark:` color classes (#378) -### ✨ Features +### Funkciók - **feat(kiro)**: Kiro credit tracking added to usage fetcher — queries `getUserCredits` from AWS CodeWhisperer endpoint (#337) @@ -5372,7 +5490,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > **Major release** — Free Stack ecosystem, transcription playground overhaul, 44+ providers, comprehensive free tier documentation, and UI improvements across the board. -### ✨ Features +### Funkciók - **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. - **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. @@ -5383,7 +5501,7 @@ OmniRoute now automatically refreshes model lists for connected providers every ## [2.3.16] - 2026-03-13 -### 📖 Documentation +### Dokumentáció - **README: 44+ Providers** — Updated all 3 occurrences of "36+ providers" to "44+" reflecting the actual codebase count (44 providers in providers.ts) - **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. @@ -5393,7 +5511,7 @@ OmniRoute now automatically refreshes model lists for connected providers every ## [2.3.15] - 2026-03-13 -### ✨ Features +### Funkciók - **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. - **i18n — autoCombo section**: Added 20 new translation keys for the Auto-Combo dashboard (`title`, `status`, `modePack`, `providerScores`, `factorTierPriority`, etc.) to all 30 language files. diff --git a/docs/i18n/id/CHANGELOG.md b/docs/i18n/id/CHANGELOG.md index 25687c52f7..b1753e51e4 100644 --- a/docs/i18n/id/CHANGELOG.md +++ b/docs/i18n/id/CHANGELOG.md @@ -10,30 +10,148 @@ ### ✨ New Features -- **feat(antigravity):** integrate Antigravity provider with dynamic `maxOutputTokens` calculation (bumping to `thinkingBudget + 1`) and standard Cloud Code envelope payload sanitization (#2055, #2063) +- **feat(antigravity):** integrate Antigravity provider with dynamic `maxOutputTokens` calculation, identity fingerprinting overhaul, and Cloud Code envelope payload sanitization (#2055, #2063) - **feat(gemini-cli):** add custom projectId support for Gemini CLI transport (UI, DB, executor) (#1991) +- **feat(providers):** add KIE media provider support with dynamic polling, text models, and expanded video models catalog +- **feat(providers):** add Z.AI provider support with GLM quota handling and new quota labels +- **feat(providers):** add 9 new free AI providers — LLM7, Lepton, Kluster, UncloseAI, BazaarLink, Completions, Enally, FreeTheAi (#2096) +- **feat(providers):** batch delete provider connections via checkbox multi-select (#2094) +- **feat(cursor):** full OpenAI parity — tool calls, streaming, and session management (#2082) +- **feat(cli):** comprehensive CLI enhancement suite with 20+ new commands including `omniroute providers`, `omniroute combos`, `omniroute doctor` (#2074) +- **feat(cli):** add modular CLI setup and provider management commands (#2046) +- **feat(mcp):** add DeepSeek quota and limit monitoring feature (#2089) +- **feat(circuit-breaker):** classify 429 errors and apply per-kind cooldowns (#2116) +- **feat(multi):** manifest-aware tier routing — W1-W4 complete (#2014) +- **feat(combos):** add reset-aware routing strategy for quota-based providers +- **feat(combo):** add context_length input field to combo edit form (#2047) +- **feat(chat):** dynamic tool limit detection with proactive truncation (#2061) +- **feat(sse):** refresh Claude OAuth wire image to claude-cli/2.1.131 (#2011) +- **feat(github):** add `targetFormat: openai-responses` to all GitHub models (#2122) +- **feat(api):** allow configuration via API calls — open management routes to Bearer keys with manage scope (#2103) +- **feat(api):** update API bridge proxy timeout to 600,000ms (#2019) +- **feat(usage):** add service tier breakdown, codex fast service tier analytics, and account for fast tier +- **feat(chat):** add `STREAM_READINESS_TIMEOUT_MS` and integrate into chat handling +- **feat(combo):** add `fallbackDelayMs` to combo configuration and related settings +- **feat(chat):** enhance error handling for semaphore capacity with fallback logic +- **feat(qdrant):** embedding model discovery (#2086) +- **feat(auth):** per-session sticky routing for Codex (#1887) +- **feat(inworld):** enhance Inworld TTS support (#2123) ### 🐛 Bug Fixes +- **fix(pricing):** make `getPricingForModel` fully case-insensitive to ensure custom prices correctly reflect in new incoming requests cost calculations +- **fix(gemini):** prevent `functionDeclarations` from being dropped by the sanitizer when `googleSearch` tool is present (#2077) +- **fix(pollinations):** add `jsonMode: true` flag in the request transformation to enforce correct JSON structure from Pollinations API (#2109) +- **fix(docker):** update Dockerfile to copy `/docs` directory during build ensuring API catalog availability at runtime (#2083) +- **fix(docker):** include OpenAPI spec in runtime image (#2007) +- **fix(providers):** strip OpenAI-specific fields in Kiro translator to prevent 400 errors (#2037) +- **fix(kiro):** normalize tool-use payloads to prevent 400 errors from agents (#2104) +- **fix(kiro):** merge adjacent user history turns after role normalization (#2105) +- **fix(ui):** resolve text contrast issues for zero-config warning banner in light mode (#2050) +- **fix(core):** inject global system prompt correctly into downstream chat completions pipeline (#2080) +- **fix(core):** restore Claude Code adaptive thinking defaults and resolve audio transcription CORS regression +- **fix(routing):** add missing v1beta rewrites to next.config to resolve 404 on Gemini models endpoint (#2102) +- **fix(routing):** fix bare GPT-5.5 routing for Codex-only installations (#2054) +- **fix(routing):** add fuzzy auto-combo routing for `auto/*` model prefix (#2010) - **fix(cache):** optimize cache_control preservation logic and explicitly align tool schema with upstream Claude Code expectations - **fix(db):** preserve legacy SQLite database path on Windows to prevent data loss (#1973) +- **fix(db):** reduce hot-path persistence overhead (#2039) +- **fix(db):** resolve migration conflict by renumbering overlapping migration entries (#2041) - **fix(settings):** resolve model alias persistence double stringification preventing UI updates (#2018) - **fix(routing):** dynamically filter bare model auto-resolution by active provider connections to prevent dead-routing (#2029) - **fix(embeddings):** add Google Gemini embeddings compatibility via OpenAI-compatible endpoint mapping (#2006) +- **fix(sse):** prevent Claude OAuth multi-account correlation via metadata.user_id (#2053) +- **fix(sse):** prevent Claude Code identity cloak overrides and fix fallback resilience (#2053) +- **fix(sse):** classify hour quota errors as QUOTA_EXHAUSTED (#2119) +- **fix(sse):** fix CC-compatible streaming bridge (#2118) +- **fix(antigravity):** sanitize Claude Cloud Code payloads (#2090) +- **fix(antigravity):** add duplex half for streaming bodies +- **fix(antigravity):** align identity protocol and behavior with official AM +- **fix(chatgpt-web):** plumb proxy through to native tls-client (#2022, #2023) +- **fix(codex):** expose native model IDs in catalog (#2012) +- **fix(glm):** add dedicated coding transport (#2087) +- **fix(compression):** support Responses input and expand Spanish compression rules (#2028) +- **fix(catalog):** auto-calculate combo context_length from target model limits (#2030) +- **fix(api):** fix usage analytics and API key identity (#2008, #2092) +- **fix(api-key):** allow Unicode letters in API key name validation (#1996) +- **fix(auth):** allow bootstrap without password (#2048) +- **fix(proxy):** clean up proxy page redundancy and fix 1proxy sync empty body error (#2052) +- **fix(dashboard):** resolve Unknown plan display in Provider Limits +- **fix(usage):** add extensible CURRENCY_SYMBOLS mapping for deepseek currencies +- **fix(runtime):** harden timer handling and model pricing fallback +- **fix(i18n):** complete Simplified Chinese translations (#2115) +- **fix(mitm):** add Linux cert install and skip sudo password when root (#1999) +- **fix(mitm):** prevent stub from loading at runtime via bypass module - **fix:** remove Anthropic-Beta header from non-Anthropic providers to fix identity contamination (#1989) - **fix(cli):** resolve .env loading failure for global npm installations +- **fix(export):** exclude telemetry/usage-history tables from JSON config backups by default to prevent unbounded file growth (#2125) +- **fix:** Follow OpenAI specification, handle throttling in batch and fix UI (#2045) -### 🔒 Security +### Keamanan +- **fix(security):** remediate CodeQL vulnerabilities (ReDoS, cryptographic bias, stack trace exposure, and weak password hashing) (#216, #215, #211, #208, #206, #210) - **fix(security):** remediate regex validation backtracking path in core compression cleanup (#1990) - **fix(core):** harden input handling and stabilization for prompt compression edge cases +### Dokumentasi + +- **docs:** add competitive marketing tables and SEO/AEO optimizations to README (#2091) +- **docs:** refresh providers, model catalogs, and docs for v3.8.0 (#2088) +- **docs:** update Claude MD and update GLM-CN max context to 200k (#2027) +- **docs(env):** add `GITLAB_DUO_OAUTH_CLIENT_ID` to `.env.example` (#2031) + ### 🧹 Chores & Maintenance - **chore(providers):** prune redundant local provider icon assets in favor of `@lobehub/icons` web fonts (#1992) +- **chore(providers):** remove deprecated models (#2033) +- **deps:** bump `fast-uri` from 3.1.0 to 3.1.2 (#2078) +- **deps:** bump `hono` from 4.12.14 to 4.12.18 (#2079) - **ci:** skip SonarCloud scan on main pushes to optimize CI time - **test:** stabilize cooldown abort coverage case in integration testing +### 🏆 v3.8.0 Community Contributors + +Thank you to all **38 community contributors** who made v3.8.0 possible! 🎉 + +| Contributor | PRs | Contributions | +| :--------------------------------------------------------- | :-: | :------------------------------------------------------------ | +| [@oyi77](https://github.com/oyi77) | 7 | #2010, #2014, #2041, #2052, #2061, #2074, #2091, #2094, #2096 | +| [@backryun](https://github.com/backryun) | 4 | #1992, #2033, #2088, #2123 | +| [@dhaern](https://github.com/dhaern) | 4 | #2028, #2039, #2087, #2090 | +| [@Tentoxa](https://github.com/Tentoxa) | 2 | #2011, #2053 | +| [@wauputr4](https://github.com/wauputr4) | 2 | #2009, #2046 | +| [@payne0420](https://github.com/payne0420) | 1 | #2082 | +| [@Tr0sT](https://github.com/Tr0sT) | 1 | #2012 | +| [@AveryanAlex](https://github.com/AveryanAlex) | 1 | #2008 | +| [@nickwizard](https://github.com/nickwizard) | 1 | #1991 | +| [@rodrigogbbr-stack](https://github.com/rodrigogbbr-stack) | 1 | #1996 | +| [@NekoMonci12](https://github.com/NekoMonci12) | 1 | #1999 | +| [@congvc-dev](https://github.com/congvc-dev) | 1 | #2004 | +| [@tatsster](https://github.com/tatsster) | 1 | #2007 | +| [@xssdem](https://github.com/xssdem) | 1 | #2023 | +| [@bypanghu](https://github.com/bypanghu) | 1 | #2027 | +| [@herjarsa](https://github.com/herjarsa) | 1 | #2030 | +| [@wucm667](https://github.com/wucm667) | 1 | #2031 | +| [@hartmark](https://github.com/hartmark) | 1 | #2045 | +| [@ddarkr](https://github.com/ddarkr) | 1 | #2047 | +| [@tces1](https://github.com/tces1) | 1 | #2048 | +| [@guanbear](https://github.com/guanbear) | 1 | #2054 | +| [@Gi99lin](https://github.com/Gi99lin) | 1 | #2055 | +| [@ivan-mezentsev](https://github.com/ivan-mezentsev) | 1 | #2063 | +| [@JxnLexn](https://github.com/JxnLexn) | 1 | #2019 | +| [@yoviarpauzi](https://github.com/yoviarpauzi) | 1 | #2092 | +| [@rafacpti23](https://github.com/rafacpti23) | 1 | #2086 | +| [@gleber](https://github.com/gleber) | 1 | #2103 | +| [@rilham97](https://github.com/rilham97) | 1 | #2104 | +| [@Gioxaa](https://github.com/Gioxaa) | 1 | #2105 | +| [@boa-z](https://github.com/boa-z) | 1 | #2115 | +| [@eleata](https://github.com/eleata) | 1 | #2116 | +| [@rdself](https://github.com/rdself) | 1 | #2118 | +| [@clousky2020](https://github.com/clousky2020) | 1 | #2119 | +| [@abhinavjnu](https://github.com/abhinavjnu) | 1 | #2122 | +| [@HoaPham98](https://github.com/HoaPham98) | 1 | #2089 | +| [@05dunski](https://github.com/05dunski) | 1 | #1978 (cherry-picked) | + ## [3.7.9] — 2026-05-03 ### ✨ New Features @@ -102,7 +220,7 @@ - **chore(provider):** Add reka models list (#1956 — thanks @backryun) - **chore(model):** Update new models, Delete Deprecated models (#1949 — thanks @backryun) -### 📝 Documentation +### Dokumentasi - **docs(compression):** document RTK+Caveman stacked savings ranges @@ -201,7 +319,7 @@ - **feat(db):** auto-restore probe-failed database on startup to prevent data loss after failed upgrades (#1810) - **feat(analytics):** add cost-based usage insights and activity streaks in the analytics dashboard -### 🔒 Security +### Keamanan - **fix(security):** resolve ReDoS vulnerability in Codex executor regex patterns (#1797, #1789) @@ -354,7 +472,7 @@ We identified that **155 community PRs** across the entire project history (from - **feat(proxy):** implement bulk proxy import via pipe-delimited parser with update-or-create (upsert) logic and real-time preview table - **feat(pwa):** add fullscreen installable PWA with manifest, service worker, and cross-platform app icons (#1728) -### 🔒 Security +### Keamanan - **security:** replace insecure `Math.random` with `crypto.getRandomValues` for fallback UUID generation to resolve CodeQL CWE-338 finding (#182) @@ -519,7 +637,7 @@ We identified that **155 community PRs** across the entire project history (from - **fix(transport):** Prevent memory bloat and database exhaustion from large, fragmented streaming responses. Implemented `ByteQueue` in `kiro.ts` for zero-copy binary accumulation, refactored `antigravity.ts` for incremental SSE parsing, and enforced a strict 512KB tiered truncation limit (`MAX_CALL_LOG_ARTIFACT_BYTES`) on stream request logs and call artifacts (#1647). - **chore(ci):** Update build environment dependencies — bump Node to `24.15.0`, `actions/checkout@v6`, `docker/build-push-action@v7`, pin `actions/setup-python` to major tag (#1646 — thanks @backryun). -### 📝 Documentation +### Dokumentasi - **docs(env):** Add `OMNIROUTE_ALLOW_PRIVATE_PROVIDER_URLS` to `.env.example` with documentation for LM Studio and other local provider use cases (#1623). @@ -669,7 +787,7 @@ We identified that **155 community PRs** across the entire project history (from - **test(next):** Align transpile package expectations for the Next.js standalone build. - **test(ci):** Fix CI-only test failures from environment differences — clear `INITIAL_PASSWORD` and `JWT_SECRET` in integration tests, handle `XDG_CONFIG_HOME` for guide-settings tests. -### 📚 Documentation +### Dokumentasi - **docs:** Update the root changelog with all release-branch changes through 2026-04-24, including PRs #1544, #1555, #1551, #1550, #1548, #1547, #1541, #1538, #1536, and #1527. - **docs:** Fix broken README and localized documentation links. (#1536) @@ -811,7 +929,7 @@ We identified that **155 community PRs** across the entire project history (from - **feat(providers):** Expand image provider registry with extended model support including SD3.5, FLUX, and DALL-E 3 HD configurations - **feat(combos):** Add new routing strategies and full i18n support for agent features section across 31 languages -### 🔒 Security +### Keamanan - **security:** Resolve 18 GitHub CodeQL scan alerts including ReDoS, incomplete sanitization, and bad HTML filtering regexp patterns - **fix(auth):** Seal privilege escalation vector by enforcing JWT session checking exclusively on `/api/keys` management endpoints (#1353) @@ -1078,7 +1196,7 @@ We identified that **155 community PRs** across the entire project history (from - **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 - **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 -### 🔒 Security +### Keamanan - **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 - **Auth Guard on Translator Save:** Added `isAuthenticated` guard to `/api/translator/save` for defense-in-depth consistency @@ -1483,7 +1601,7 @@ We identified that **155 community PRs** across the entire project history (from - **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). -### 📚 Documentation +### Dokumentasi - **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. - **Context Relay Delivery Notes:** Documented the current architecture, runtime flow, and Codex-focused scope in the feature docs, changelog, and agent guidance. @@ -1559,7 +1677,7 @@ We identified that **155 community PRs** across the entire project history (from ## [3.5.3] - 2026-04-07 -### Security +### Keamanan - **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. - **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. @@ -1575,7 +1693,7 @@ We identified that **155 community PRs** across the entire project history (from - **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. -### Documentation +### Dokumentasi - **I18n Engine:** Synchronized and pushed deep Machine Translation updates across all 32 natively-supported languages (682 translation nodes aligned). @@ -1736,7 +1854,7 @@ We identified that **155 community PRs** across the entire project history (from ## [3.4.8] — 2026-04-03 -### Security +### Keamanan - Fully remediated all outstanding Github Advanced Security (CodeQL) findings and Dependabot alerts. - Fixed insecure randomness vulnerabilities by migrating from `Math.random` to `crypto.randomUUID()`. @@ -1748,7 +1866,7 @@ We identified that **155 community PRs** across the entire project history (from ## [3.4.7] — 2026-04-03 -### Features +### Fitur - Added `Cryptography` node to Monitoring and MCP health checks (#798) - Hardened model-catalog route permissions mapping (`/models`) (#781) @@ -1764,7 +1882,7 @@ We identified that **155 community PRs** across the entire project history (from - Fixed MCP standalone module-resolution (`ERR_MODULE_NOT_FOUND`) via `esbuild` (#936) - Fixed NVIDIA NIM routing credential resolution alias mismatch (#931) -### Security +### Keamanan - Added safe strict input boundary protection against raw `shell: true` remote-code execution injections. @@ -2011,7 +2129,7 @@ We identified that **155 community PRs** across the entire project history (from ## [3.4.0] - 2026-03-31 -### 🚀 Features +### Fitur - **Subscription Utilization Analytics:** Added quota snapshot time-series tracking, Provider Utilization and Combo Health tabs with recharts visualizations, and corresponding API endpoints (#847) - **SQLite Backup Control:** New `OMNIROUTE_DISABLE_AUTO_BACKUP` env flag to disable automatic SQLite backups (#846) @@ -2063,7 +2181,7 @@ We identified that **155 community PRs** across the entire project history (from ## [3.3.8] - 2026-03-30 -### 🚀 Features +### Fitur - **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) - **Qoder Integration:** Native integration for Qoder AI natively replacing the legacy iFlow platform mappings (#660) @@ -2889,7 +3007,7 @@ We identified that **155 community PRs** across the entire project history (from - **NaN tokens in Claude Code / client responses (#617):** - `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 -### 🔒 Security +### Keamanan - Updated `yaml` package to fix stack overflow vulnerability (GHSA-48c2-rrv3-qjmp) @@ -3565,7 +3683,7 @@ docker pull diegosouzapw/omniroute:3.0.0 - **SVG fallback**: `ProviderIcon` component updated with 4-tier strategy: Lobehub → PNG → SVG → Generic icon - **Agents fingerprinting**: Synced with CLI tools — added droid, openclaw, copilot, opencode to fingerprint list (14 total) -### 🔒 Security +### Keamanan - **CVE fix**: Resolved dompurify XSS vulnerability (GHSA-v2wj-7wpq-c8vv) via npm overrides forcing `dompurify@^3.3.2` - `npm audit` now reports **0 vulnerabilities** @@ -3928,7 +4046,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **#510** — Windows: MSYS2/Git-Bash paths (`/c/Program Files/...`) are now normalized to `C:\Program Files\...` - **#492** — `omniroute` CLI now detects `mise`/`nvm` when `app/server.js` is missing and shows targeted fix -### 📖 Documentation +### Dokumentasi - **#513** — Docker password reset: `INITIAL_PASSWORD` env var workaround documented - **#520** — pnpm: `pnpm approve-builds better-sqlite3` documented @@ -4025,7 +4143,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **feat(executors/cloudflare-ai)**: New `CloudflareAIExecutor` — dynamic URL construction requires `accountId` in provider credentials - **feat(executors)**: Register `pollinations`, `pol`, `cloudflare-ai`, `cf` executor mappings -### 📝 Documentation +### Dokumentasi - **docs(readme)**: Expanded free combo stack to 11 providers ($0 forever) - **docs(readme)**: Added 4 new free provider sections (LongCat, Pollinations, Cloudflare AI, Scaleway) with model tables @@ -4177,7 +4295,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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). -### Features +### Fitur - **"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. @@ -4205,7 +4323,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Merge PR #494 (MiniMax role fix), fix KIRO MITM dashboard, triage 8 issues. -### Features +### Fitur - **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. - **roleNormalizer**: `normalizeDeveloperRole()` now accepts `preserveDeveloperRole` parameter with tri-state behavior (undefined=keep, true=keep, false=convert). @@ -4261,7 +4379,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Gemini CLI deprecation, VM guide i18n fix, dependabot security fix, provider schema expansion. -### Features +### Fitur - **Gemini CLI Deprecation** (#462): Mark `gemini-cli` provider as deprecated with warning — Google restricts third-party OAuth usage from March 2026 - **Provider Schema** (#462): Expand Zod validation with `deprecated`, `deprecationReason`, `hasFree`, `freeNote`, `authHint`, `apiHint` optional fields @@ -4270,7 +4388,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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) -### Security +### Keamanan - **deps**: Bump `flatted` 3.3.3 → 3.4.2 — fixes CWE-1321 prototype pollution (#484, @dependabot) @@ -4290,7 +4408,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Czech i18n, SSE protocol fix, VM guide translation. -### Features +### Fitur - **Czech Language** (#482): Full Czech (cs) i18n — 22 docs, 2606 UI strings, language switcher updates (@zen0bit) - **VM Deployment Guide**: Translated from Portuguese to English as the source document (@zen0bit) @@ -4309,7 +4427,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: 2 merged PRs, model aliases routing fix, log export, and issue triage. -### Features +### Fitur - **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) @@ -4329,7 +4447,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Five community PRs — streaming call log fixes, Kiro compatibility, cache token analytics, Chinese translation, and configurable tool call IDs. -### ✨ Features +### Fitur - **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) - **feat(providers)**: Per-model configurable 9-char tool call ID normalization (Mistral-style) — only models with the option enabled get truncated IDs (#470) @@ -4359,7 +4477,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Bailian Coding Plan provider with editable base URLs, plus community contributions for Alibaba Cloud and Kimi Coding. -### ✨ Features +### Fitur - **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) - **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) @@ -4374,7 +4492,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Two new community-contributed providers (Alibaba Cloud Coding, Kimi Coding API-key) and Docker pino fix. -### ✨ Features +### Fitur - **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) - **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) @@ -4399,7 +4517,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Codex responses subpath passthrough natively supported, Windows MITM crash fixed, and Combos agent schemas adjusted. -### ✨ Features +### Fitur - **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) @@ -4439,7 +4557,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **fix(budget)**: "Save Limits" no longer returns 422 — `warningThreshold` is now correctly sent as fraction (0–1) instead of percentage (0–100) (#451) - **fix(combos)**: `` internal cache tag is now stripped before forwarding requests to providers, preventing cache session breaks (#454) -### ✨ Features +### Fitur - **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) @@ -4495,7 +4613,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Search Tools dashboard, i18n fixes, Copilot limits, Serper validation fix. -### 🚀 Features +### Fitur - **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) - New route: `/dashboard/search-tools` @@ -4595,7 +4713,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - DB migration: `request_type` column on `call_logs` for non-chat request tracking - Zod validation (`v1SearchSchema`), auth-gated, cost recorded via `recordCost()` -### 🔒 Security +### Keamanan - **deps**: Next.js 16.1.6 → 16.1.7 — fixes 6 CVEs: - **Critical**: CVE-2026-29057 (HTTP request smuggling via http-proxy) @@ -4725,7 +4843,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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**: New `request_detail_logs` table with 500-entry ring-buffer trigger, opt-in via settings toggle -### ✨ Features +### Fitur - **feat(combo)**: System Message Override per Combo (#399 — `system_message` field replaces or injects system prompt before forwarding to provider) - **feat(combo)**: Tool Filter Regex per Combo (#399 — `tool_filter_regex` keeps only tools matching pattern; supports OpenAI + Anthropic formats) @@ -4740,7 +4858,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: SSE improvements, local provider_nodes extensions, proxy registry, Claude passthrough fixes. -### ✨ Features +### Fitur - **feat(health)**: Background health check for local `provider_nodes` with exponential backoff (30s→300s) and `Promise.allSettled` to avoid blocking (#423, @Regis-RCR) - **feat(embeddings)**: Route `/v1/embeddings` to local `provider_nodes` — `buildDynamicEmbeddingProvider()` with hostname validation (#422, @Regis-RCR) @@ -4882,7 +5000,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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 - **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). -### ✨ Features +### Fitur - **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) @@ -4912,7 +5030,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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) - **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) -### ✨ Features +### Fitur - **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) - **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. @@ -4971,7 +5089,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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) - **fix(logs)**: Request log table is now readable in light mode — status badges, token counts, and combo tags use adaptive `dark:` color classes (#378) -### ✨ Features +### Fitur - **feat(kiro)**: Kiro credit tracking added to usage fetcher — queries `getUserCredits` from AWS CodeWhisperer endpoint (#337) @@ -5372,7 +5490,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > **Major release** — Free Stack ecosystem, transcription playground overhaul, 44+ providers, comprehensive free tier documentation, and UI improvements across the board. -### ✨ Features +### Fitur - **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. - **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. @@ -5383,7 +5501,7 @@ OmniRoute now automatically refreshes model lists for connected providers every ## [2.3.16] - 2026-03-13 -### 📖 Documentation +### Dokumentasi - **README: 44+ Providers** — Updated all 3 occurrences of "36+ providers" to "44+" reflecting the actual codebase count (44 providers in providers.ts) - **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. @@ -5393,7 +5511,7 @@ OmniRoute now automatically refreshes model lists for connected providers every ## [2.3.15] - 2026-03-13 -### ✨ Features +### Fitur - **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. - **i18n — autoCombo section**: Added 20 new translation keys for the Auto-Combo dashboard (`title`, `status`, `modePack`, `providerScores`, `factorTierPriority`, etc.) to all 30 language files. diff --git a/docs/i18n/it/CHANGELOG.md b/docs/i18n/it/CHANGELOG.md index 23603a46bf..348d38da98 100644 --- a/docs/i18n/it/CHANGELOG.md +++ b/docs/i18n/it/CHANGELOG.md @@ -10,30 +10,148 @@ ### ✨ New Features -- **feat(antigravity):** integrate Antigravity provider with dynamic `maxOutputTokens` calculation (bumping to `thinkingBudget + 1`) and standard Cloud Code envelope payload sanitization (#2055, #2063) +- **feat(antigravity):** integrate Antigravity provider with dynamic `maxOutputTokens` calculation, identity fingerprinting overhaul, and Cloud Code envelope payload sanitization (#2055, #2063) - **feat(gemini-cli):** add custom projectId support for Gemini CLI transport (UI, DB, executor) (#1991) +- **feat(providers):** add KIE media provider support with dynamic polling, text models, and expanded video models catalog +- **feat(providers):** add Z.AI provider support with GLM quota handling and new quota labels +- **feat(providers):** add 9 new free AI providers — LLM7, Lepton, Kluster, UncloseAI, BazaarLink, Completions, Enally, FreeTheAi (#2096) +- **feat(providers):** batch delete provider connections via checkbox multi-select (#2094) +- **feat(cursor):** full OpenAI parity — tool calls, streaming, and session management (#2082) +- **feat(cli):** comprehensive CLI enhancement suite with 20+ new commands including `omniroute providers`, `omniroute combos`, `omniroute doctor` (#2074) +- **feat(cli):** add modular CLI setup and provider management commands (#2046) +- **feat(mcp):** add DeepSeek quota and limit monitoring feature (#2089) +- **feat(circuit-breaker):** classify 429 errors and apply per-kind cooldowns (#2116) +- **feat(multi):** manifest-aware tier routing — W1-W4 complete (#2014) +- **feat(combos):** add reset-aware routing strategy for quota-based providers +- **feat(combo):** add context_length input field to combo edit form (#2047) +- **feat(chat):** dynamic tool limit detection with proactive truncation (#2061) +- **feat(sse):** refresh Claude OAuth wire image to claude-cli/2.1.131 (#2011) +- **feat(github):** add `targetFormat: openai-responses` to all GitHub models (#2122) +- **feat(api):** allow configuration via API calls — open management routes to Bearer keys with manage scope (#2103) +- **feat(api):** update API bridge proxy timeout to 600,000ms (#2019) +- **feat(usage):** add service tier breakdown, codex fast service tier analytics, and account for fast tier +- **feat(chat):** add `STREAM_READINESS_TIMEOUT_MS` and integrate into chat handling +- **feat(combo):** add `fallbackDelayMs` to combo configuration and related settings +- **feat(chat):** enhance error handling for semaphore capacity with fallback logic +- **feat(qdrant):** embedding model discovery (#2086) +- **feat(auth):** per-session sticky routing for Codex (#1887) +- **feat(inworld):** enhance Inworld TTS support (#2123) ### 🐛 Bug Fixes +- **fix(pricing):** make `getPricingForModel` fully case-insensitive to ensure custom prices correctly reflect in new incoming requests cost calculations +- **fix(gemini):** prevent `functionDeclarations` from being dropped by the sanitizer when `googleSearch` tool is present (#2077) +- **fix(pollinations):** add `jsonMode: true` flag in the request transformation to enforce correct JSON structure from Pollinations API (#2109) +- **fix(docker):** update Dockerfile to copy `/docs` directory during build ensuring API catalog availability at runtime (#2083) +- **fix(docker):** include OpenAPI spec in runtime image (#2007) +- **fix(providers):** strip OpenAI-specific fields in Kiro translator to prevent 400 errors (#2037) +- **fix(kiro):** normalize tool-use payloads to prevent 400 errors from agents (#2104) +- **fix(kiro):** merge adjacent user history turns after role normalization (#2105) +- **fix(ui):** resolve text contrast issues for zero-config warning banner in light mode (#2050) +- **fix(core):** inject global system prompt correctly into downstream chat completions pipeline (#2080) +- **fix(core):** restore Claude Code adaptive thinking defaults and resolve audio transcription CORS regression +- **fix(routing):** add missing v1beta rewrites to next.config to resolve 404 on Gemini models endpoint (#2102) +- **fix(routing):** fix bare GPT-5.5 routing for Codex-only installations (#2054) +- **fix(routing):** add fuzzy auto-combo routing for `auto/*` model prefix (#2010) - **fix(cache):** optimize cache_control preservation logic and explicitly align tool schema with upstream Claude Code expectations - **fix(db):** preserve legacy SQLite database path on Windows to prevent data loss (#1973) +- **fix(db):** reduce hot-path persistence overhead (#2039) +- **fix(db):** resolve migration conflict by renumbering overlapping migration entries (#2041) - **fix(settings):** resolve model alias persistence double stringification preventing UI updates (#2018) - **fix(routing):** dynamically filter bare model auto-resolution by active provider connections to prevent dead-routing (#2029) - **fix(embeddings):** add Google Gemini embeddings compatibility via OpenAI-compatible endpoint mapping (#2006) +- **fix(sse):** prevent Claude OAuth multi-account correlation via metadata.user_id (#2053) +- **fix(sse):** prevent Claude Code identity cloak overrides and fix fallback resilience (#2053) +- **fix(sse):** classify hour quota errors as QUOTA_EXHAUSTED (#2119) +- **fix(sse):** fix CC-compatible streaming bridge (#2118) +- **fix(antigravity):** sanitize Claude Cloud Code payloads (#2090) +- **fix(antigravity):** add duplex half for streaming bodies +- **fix(antigravity):** align identity protocol and behavior with official AM +- **fix(chatgpt-web):** plumb proxy through to native tls-client (#2022, #2023) +- **fix(codex):** expose native model IDs in catalog (#2012) +- **fix(glm):** add dedicated coding transport (#2087) +- **fix(compression):** support Responses input and expand Spanish compression rules (#2028) +- **fix(catalog):** auto-calculate combo context_length from target model limits (#2030) +- **fix(api):** fix usage analytics and API key identity (#2008, #2092) +- **fix(api-key):** allow Unicode letters in API key name validation (#1996) +- **fix(auth):** allow bootstrap without password (#2048) +- **fix(proxy):** clean up proxy page redundancy and fix 1proxy sync empty body error (#2052) +- **fix(dashboard):** resolve Unknown plan display in Provider Limits +- **fix(usage):** add extensible CURRENCY_SYMBOLS mapping for deepseek currencies +- **fix(runtime):** harden timer handling and model pricing fallback +- **fix(i18n):** complete Simplified Chinese translations (#2115) +- **fix(mitm):** add Linux cert install and skip sudo password when root (#1999) +- **fix(mitm):** prevent stub from loading at runtime via bypass module - **fix:** remove Anthropic-Beta header from non-Anthropic providers to fix identity contamination (#1989) - **fix(cli):** resolve .env loading failure for global npm installations +- **fix(export):** exclude telemetry/usage-history tables from JSON config backups by default to prevent unbounded file growth (#2125) +- **fix:** Follow OpenAI specification, handle throttling in batch and fix UI (#2045) -### 🔒 Security +### Sicurezza +- **fix(security):** remediate CodeQL vulnerabilities (ReDoS, cryptographic bias, stack trace exposure, and weak password hashing) (#216, #215, #211, #208, #206, #210) - **fix(security):** remediate regex validation backtracking path in core compression cleanup (#1990) - **fix(core):** harden input handling and stabilization for prompt compression edge cases +### Documentazione + +- **docs:** add competitive marketing tables and SEO/AEO optimizations to README (#2091) +- **docs:** refresh providers, model catalogs, and docs for v3.8.0 (#2088) +- **docs:** update Claude MD and update GLM-CN max context to 200k (#2027) +- **docs(env):** add `GITLAB_DUO_OAUTH_CLIENT_ID` to `.env.example` (#2031) + ### 🧹 Chores & Maintenance - **chore(providers):** prune redundant local provider icon assets in favor of `@lobehub/icons` web fonts (#1992) +- **chore(providers):** remove deprecated models (#2033) +- **deps:** bump `fast-uri` from 3.1.0 to 3.1.2 (#2078) +- **deps:** bump `hono` from 4.12.14 to 4.12.18 (#2079) - **ci:** skip SonarCloud scan on main pushes to optimize CI time - **test:** stabilize cooldown abort coverage case in integration testing +### 🏆 v3.8.0 Community Contributors + +Thank you to all **38 community contributors** who made v3.8.0 possible! 🎉 + +| Contributor | PRs | Contributions | +| :--------------------------------------------------------- | :-: | :------------------------------------------------------------ | +| [@oyi77](https://github.com/oyi77) | 7 | #2010, #2014, #2041, #2052, #2061, #2074, #2091, #2094, #2096 | +| [@backryun](https://github.com/backryun) | 4 | #1992, #2033, #2088, #2123 | +| [@dhaern](https://github.com/dhaern) | 4 | #2028, #2039, #2087, #2090 | +| [@Tentoxa](https://github.com/Tentoxa) | 2 | #2011, #2053 | +| [@wauputr4](https://github.com/wauputr4) | 2 | #2009, #2046 | +| [@payne0420](https://github.com/payne0420) | 1 | #2082 | +| [@Tr0sT](https://github.com/Tr0sT) | 1 | #2012 | +| [@AveryanAlex](https://github.com/AveryanAlex) | 1 | #2008 | +| [@nickwizard](https://github.com/nickwizard) | 1 | #1991 | +| [@rodrigogbbr-stack](https://github.com/rodrigogbbr-stack) | 1 | #1996 | +| [@NekoMonci12](https://github.com/NekoMonci12) | 1 | #1999 | +| [@congvc-dev](https://github.com/congvc-dev) | 1 | #2004 | +| [@tatsster](https://github.com/tatsster) | 1 | #2007 | +| [@xssdem](https://github.com/xssdem) | 1 | #2023 | +| [@bypanghu](https://github.com/bypanghu) | 1 | #2027 | +| [@herjarsa](https://github.com/herjarsa) | 1 | #2030 | +| [@wucm667](https://github.com/wucm667) | 1 | #2031 | +| [@hartmark](https://github.com/hartmark) | 1 | #2045 | +| [@ddarkr](https://github.com/ddarkr) | 1 | #2047 | +| [@tces1](https://github.com/tces1) | 1 | #2048 | +| [@guanbear](https://github.com/guanbear) | 1 | #2054 | +| [@Gi99lin](https://github.com/Gi99lin) | 1 | #2055 | +| [@ivan-mezentsev](https://github.com/ivan-mezentsev) | 1 | #2063 | +| [@JxnLexn](https://github.com/JxnLexn) | 1 | #2019 | +| [@yoviarpauzi](https://github.com/yoviarpauzi) | 1 | #2092 | +| [@rafacpti23](https://github.com/rafacpti23) | 1 | #2086 | +| [@gleber](https://github.com/gleber) | 1 | #2103 | +| [@rilham97](https://github.com/rilham97) | 1 | #2104 | +| [@Gioxaa](https://github.com/Gioxaa) | 1 | #2105 | +| [@boa-z](https://github.com/boa-z) | 1 | #2115 | +| [@eleata](https://github.com/eleata) | 1 | #2116 | +| [@rdself](https://github.com/rdself) | 1 | #2118 | +| [@clousky2020](https://github.com/clousky2020) | 1 | #2119 | +| [@abhinavjnu](https://github.com/abhinavjnu) | 1 | #2122 | +| [@HoaPham98](https://github.com/HoaPham98) | 1 | #2089 | +| [@05dunski](https://github.com/05dunski) | 1 | #1978 (cherry-picked) | + ## [3.7.9] — 2026-05-03 ### ✨ New Features @@ -102,7 +220,7 @@ - **chore(provider):** Add reka models list (#1956 — thanks @backryun) - **chore(model):** Update new models, Delete Deprecated models (#1949 — thanks @backryun) -### 📝 Documentation +### Documentazione - **docs(compression):** document RTK+Caveman stacked savings ranges @@ -201,7 +319,7 @@ - **feat(db):** auto-restore probe-failed database on startup to prevent data loss after failed upgrades (#1810) - **feat(analytics):** add cost-based usage insights and activity streaks in the analytics dashboard -### 🔒 Security +### Sicurezza - **fix(security):** resolve ReDoS vulnerability in Codex executor regex patterns (#1797, #1789) @@ -354,7 +472,7 @@ We identified that **155 community PRs** across the entire project history (from - **feat(proxy):** implement bulk proxy import via pipe-delimited parser with update-or-create (upsert) logic and real-time preview table - **feat(pwa):** add fullscreen installable PWA with manifest, service worker, and cross-platform app icons (#1728) -### 🔒 Security +### Sicurezza - **security:** replace insecure `Math.random` with `crypto.getRandomValues` for fallback UUID generation to resolve CodeQL CWE-338 finding (#182) @@ -519,7 +637,7 @@ We identified that **155 community PRs** across the entire project history (from - **fix(transport):** Prevent memory bloat and database exhaustion from large, fragmented streaming responses. Implemented `ByteQueue` in `kiro.ts` for zero-copy binary accumulation, refactored `antigravity.ts` for incremental SSE parsing, and enforced a strict 512KB tiered truncation limit (`MAX_CALL_LOG_ARTIFACT_BYTES`) on stream request logs and call artifacts (#1647). - **chore(ci):** Update build environment dependencies — bump Node to `24.15.0`, `actions/checkout@v6`, `docker/build-push-action@v7`, pin `actions/setup-python` to major tag (#1646 — thanks @backryun). -### 📝 Documentation +### Documentazione - **docs(env):** Add `OMNIROUTE_ALLOW_PRIVATE_PROVIDER_URLS` to `.env.example` with documentation for LM Studio and other local provider use cases (#1623). @@ -669,7 +787,7 @@ We identified that **155 community PRs** across the entire project history (from - **test(next):** Align transpile package expectations for the Next.js standalone build. - **test(ci):** Fix CI-only test failures from environment differences — clear `INITIAL_PASSWORD` and `JWT_SECRET` in integration tests, handle `XDG_CONFIG_HOME` for guide-settings tests. -### 📚 Documentation +### Documentazione - **docs:** Update the root changelog with all release-branch changes through 2026-04-24, including PRs #1544, #1555, #1551, #1550, #1548, #1547, #1541, #1538, #1536, and #1527. - **docs:** Fix broken README and localized documentation links. (#1536) @@ -811,7 +929,7 @@ We identified that **155 community PRs** across the entire project history (from - **feat(providers):** Expand image provider registry with extended model support including SD3.5, FLUX, and DALL-E 3 HD configurations - **feat(combos):** Add new routing strategies and full i18n support for agent features section across 31 languages -### 🔒 Security +### Sicurezza - **security:** Resolve 18 GitHub CodeQL scan alerts including ReDoS, incomplete sanitization, and bad HTML filtering regexp patterns - **fix(auth):** Seal privilege escalation vector by enforcing JWT session checking exclusively on `/api/keys` management endpoints (#1353) @@ -1078,7 +1196,7 @@ We identified that **155 community PRs** across the entire project history (from - **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 - **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 -### 🔒 Security +### Sicurezza - **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 - **Auth Guard on Translator Save:** Added `isAuthenticated` guard to `/api/translator/save` for defense-in-depth consistency @@ -1483,7 +1601,7 @@ We identified that **155 community PRs** across the entire project history (from - **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). -### 📚 Documentation +### Documentazione - **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. - **Context Relay Delivery Notes:** Documented the current architecture, runtime flow, and Codex-focused scope in the feature docs, changelog, and agent guidance. @@ -1559,7 +1677,7 @@ We identified that **155 community PRs** across the entire project history (from ## [3.5.3] - 2026-04-07 -### Security +### Sicurezza - **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. - **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. @@ -1575,7 +1693,7 @@ We identified that **155 community PRs** across the entire project history (from - **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. -### Documentation +### Documentazione - **I18n Engine:** Synchronized and pushed deep Machine Translation updates across all 32 natively-supported languages (682 translation nodes aligned). @@ -1736,7 +1854,7 @@ We identified that **155 community PRs** across the entire project history (from ## [3.4.8] — 2026-04-03 -### Security +### Sicurezza - Fully remediated all outstanding Github Advanced Security (CodeQL) findings and Dependabot alerts. - Fixed insecure randomness vulnerabilities by migrating from `Math.random` to `crypto.randomUUID()`. @@ -1748,7 +1866,7 @@ We identified that **155 community PRs** across the entire project history (from ## [3.4.7] — 2026-04-03 -### Features +### Funzionalità - Added `Cryptography` node to Monitoring and MCP health checks (#798) - Hardened model-catalog route permissions mapping (`/models`) (#781) @@ -1764,7 +1882,7 @@ We identified that **155 community PRs** across the entire project history (from - Fixed MCP standalone module-resolution (`ERR_MODULE_NOT_FOUND`) via `esbuild` (#936) - Fixed NVIDIA NIM routing credential resolution alias mismatch (#931) -### Security +### Sicurezza - Added safe strict input boundary protection against raw `shell: true` remote-code execution injections. @@ -2011,7 +2129,7 @@ We identified that **155 community PRs** across the entire project history (from ## [3.4.0] - 2026-03-31 -### 🚀 Features +### Funzionalità - **Subscription Utilization Analytics:** Added quota snapshot time-series tracking, Provider Utilization and Combo Health tabs with recharts visualizations, and corresponding API endpoints (#847) - **SQLite Backup Control:** New `OMNIROUTE_DISABLE_AUTO_BACKUP` env flag to disable automatic SQLite backups (#846) @@ -2063,7 +2181,7 @@ We identified that **155 community PRs** across the entire project history (from ## [3.3.8] - 2026-03-30 -### 🚀 Features +### Funzionalità - **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) - **Qoder Integration:** Native integration for Qoder AI natively replacing the legacy iFlow platform mappings (#660) @@ -2889,7 +3007,7 @@ We identified that **155 community PRs** across the entire project history (from - **NaN tokens in Claude Code / client responses (#617):** - `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 -### 🔒 Security +### Sicurezza - Updated `yaml` package to fix stack overflow vulnerability (GHSA-48c2-rrv3-qjmp) @@ -3565,7 +3683,7 @@ docker pull diegosouzapw/omniroute:3.0.0 - **SVG fallback**: `ProviderIcon` component updated with 4-tier strategy: Lobehub → PNG → SVG → Generic icon - **Agents fingerprinting**: Synced with CLI tools — added droid, openclaw, copilot, opencode to fingerprint list (14 total) -### 🔒 Security +### Sicurezza - **CVE fix**: Resolved dompurify XSS vulnerability (GHSA-v2wj-7wpq-c8vv) via npm overrides forcing `dompurify@^3.3.2` - `npm audit` now reports **0 vulnerabilities** @@ -3928,7 +4046,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **#510** — Windows: MSYS2/Git-Bash paths (`/c/Program Files/...`) are now normalized to `C:\Program Files\...` - **#492** — `omniroute` CLI now detects `mise`/`nvm` when `app/server.js` is missing and shows targeted fix -### 📖 Documentation +### Documentazione - **#513** — Docker password reset: `INITIAL_PASSWORD` env var workaround documented - **#520** — pnpm: `pnpm approve-builds better-sqlite3` documented @@ -4025,7 +4143,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **feat(executors/cloudflare-ai)**: New `CloudflareAIExecutor` — dynamic URL construction requires `accountId` in provider credentials - **feat(executors)**: Register `pollinations`, `pol`, `cloudflare-ai`, `cf` executor mappings -### 📝 Documentation +### Documentazione - **docs(readme)**: Expanded free combo stack to 11 providers ($0 forever) - **docs(readme)**: Added 4 new free provider sections (LongCat, Pollinations, Cloudflare AI, Scaleway) with model tables @@ -4177,7 +4295,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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). -### Features +### Funzionalità - **"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. @@ -4205,7 +4323,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Merge PR #494 (MiniMax role fix), fix KIRO MITM dashboard, triage 8 issues. -### Features +### Funzionalità - **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. - **roleNormalizer**: `normalizeDeveloperRole()` now accepts `preserveDeveloperRole` parameter with tri-state behavior (undefined=keep, true=keep, false=convert). @@ -4261,7 +4379,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Gemini CLI deprecation, VM guide i18n fix, dependabot security fix, provider schema expansion. -### Features +### Funzionalità - **Gemini CLI Deprecation** (#462): Mark `gemini-cli` provider as deprecated with warning — Google restricts third-party OAuth usage from March 2026 - **Provider Schema** (#462): Expand Zod validation with `deprecated`, `deprecationReason`, `hasFree`, `freeNote`, `authHint`, `apiHint` optional fields @@ -4270,7 +4388,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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) -### Security +### Sicurezza - **deps**: Bump `flatted` 3.3.3 → 3.4.2 — fixes CWE-1321 prototype pollution (#484, @dependabot) @@ -4290,7 +4408,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Czech i18n, SSE protocol fix, VM guide translation. -### Features +### Funzionalità - **Czech Language** (#482): Full Czech (cs) i18n — 22 docs, 2606 UI strings, language switcher updates (@zen0bit) - **VM Deployment Guide**: Translated from Portuguese to English as the source document (@zen0bit) @@ -4309,7 +4427,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: 2 merged PRs, model aliases routing fix, log export, and issue triage. -### Features +### Funzionalità - **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) @@ -4329,7 +4447,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Five community PRs — streaming call log fixes, Kiro compatibility, cache token analytics, Chinese translation, and configurable tool call IDs. -### ✨ Features +### Funzionalità - **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) - **feat(providers)**: Per-model configurable 9-char tool call ID normalization (Mistral-style) — only models with the option enabled get truncated IDs (#470) @@ -4359,7 +4477,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Bailian Coding Plan provider with editable base URLs, plus community contributions for Alibaba Cloud and Kimi Coding. -### ✨ Features +### Funzionalità - **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) - **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) @@ -4374,7 +4492,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Two new community-contributed providers (Alibaba Cloud Coding, Kimi Coding API-key) and Docker pino fix. -### ✨ Features +### Funzionalità - **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) - **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) @@ -4399,7 +4517,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Codex responses subpath passthrough natively supported, Windows MITM crash fixed, and Combos agent schemas adjusted. -### ✨ Features +### Funzionalità - **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) @@ -4439,7 +4557,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **fix(budget)**: "Save Limits" no longer returns 422 — `warningThreshold` is now correctly sent as fraction (0–1) instead of percentage (0–100) (#451) - **fix(combos)**: `` internal cache tag is now stripped before forwarding requests to providers, preventing cache session breaks (#454) -### ✨ Features +### Funzionalità - **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) @@ -4495,7 +4613,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Search Tools dashboard, i18n fixes, Copilot limits, Serper validation fix. -### 🚀 Features +### Funzionalità - **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) - New route: `/dashboard/search-tools` @@ -4595,7 +4713,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - DB migration: `request_type` column on `call_logs` for non-chat request tracking - Zod validation (`v1SearchSchema`), auth-gated, cost recorded via `recordCost()` -### 🔒 Security +### Sicurezza - **deps**: Next.js 16.1.6 → 16.1.7 — fixes 6 CVEs: - **Critical**: CVE-2026-29057 (HTTP request smuggling via http-proxy) @@ -4725,7 +4843,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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**: New `request_detail_logs` table with 500-entry ring-buffer trigger, opt-in via settings toggle -### ✨ Features +### Funzionalità - **feat(combo)**: System Message Override per Combo (#399 — `system_message` field replaces or injects system prompt before forwarding to provider) - **feat(combo)**: Tool Filter Regex per Combo (#399 — `tool_filter_regex` keeps only tools matching pattern; supports OpenAI + Anthropic formats) @@ -4740,7 +4858,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: SSE improvements, local provider_nodes extensions, proxy registry, Claude passthrough fixes. -### ✨ Features +### Funzionalità - **feat(health)**: Background health check for local `provider_nodes` with exponential backoff (30s→300s) and `Promise.allSettled` to avoid blocking (#423, @Regis-RCR) - **feat(embeddings)**: Route `/v1/embeddings` to local `provider_nodes` — `buildDynamicEmbeddingProvider()` with hostname validation (#422, @Regis-RCR) @@ -4882,7 +5000,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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 - **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). -### ✨ Features +### Funzionalità - **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) @@ -4912,7 +5030,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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) - **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) -### ✨ Features +### Funzionalità - **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) - **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. @@ -4971,7 +5089,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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) - **fix(logs)**: Request log table is now readable in light mode — status badges, token counts, and combo tags use adaptive `dark:` color classes (#378) -### ✨ Features +### Funzionalità - **feat(kiro)**: Kiro credit tracking added to usage fetcher — queries `getUserCredits` from AWS CodeWhisperer endpoint (#337) @@ -5372,7 +5490,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > **Major release** — Free Stack ecosystem, transcription playground overhaul, 44+ providers, comprehensive free tier documentation, and UI improvements across the board. -### ✨ Features +### Funzionalità - **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. - **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. @@ -5383,7 +5501,7 @@ OmniRoute now automatically refreshes model lists for connected providers every ## [2.3.16] - 2026-03-13 -### 📖 Documentation +### Documentazione - **README: 44+ Providers** — Updated all 3 occurrences of "36+ providers" to "44+" reflecting the actual codebase count (44 providers in providers.ts) - **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. @@ -5393,7 +5511,7 @@ OmniRoute now automatically refreshes model lists for connected providers every ## [2.3.15] - 2026-03-13 -### ✨ Features +### Funzionalità - **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. - **i18n — autoCombo section**: Added 20 new translation keys for the Auto-Combo dashboard (`title`, `status`, `modePack`, `providerScores`, `factorTierPriority`, etc.) to all 30 language files. diff --git a/docs/i18n/ja/CHANGELOG.md b/docs/i18n/ja/CHANGELOG.md index 623fc31eff..dec6ed89f1 100644 --- a/docs/i18n/ja/CHANGELOG.md +++ b/docs/i18n/ja/CHANGELOG.md @@ -10,30 +10,148 @@ ### ✨ New Features -- **feat(antigravity):** integrate Antigravity provider with dynamic `maxOutputTokens` calculation (bumping to `thinkingBudget + 1`) and standard Cloud Code envelope payload sanitization (#2055, #2063) +- **feat(antigravity):** integrate Antigravity provider with dynamic `maxOutputTokens` calculation, identity fingerprinting overhaul, and Cloud Code envelope payload sanitization (#2055, #2063) - **feat(gemini-cli):** add custom projectId support for Gemini CLI transport (UI, DB, executor) (#1991) +- **feat(providers):** add KIE media provider support with dynamic polling, text models, and expanded video models catalog +- **feat(providers):** add Z.AI provider support with GLM quota handling and new quota labels +- **feat(providers):** add 9 new free AI providers — LLM7, Lepton, Kluster, UncloseAI, BazaarLink, Completions, Enally, FreeTheAi (#2096) +- **feat(providers):** batch delete provider connections via checkbox multi-select (#2094) +- **feat(cursor):** full OpenAI parity — tool calls, streaming, and session management (#2082) +- **feat(cli):** comprehensive CLI enhancement suite with 20+ new commands including `omniroute providers`, `omniroute combos`, `omniroute doctor` (#2074) +- **feat(cli):** add modular CLI setup and provider management commands (#2046) +- **feat(mcp):** add DeepSeek quota and limit monitoring feature (#2089) +- **feat(circuit-breaker):** classify 429 errors and apply per-kind cooldowns (#2116) +- **feat(multi):** manifest-aware tier routing — W1-W4 complete (#2014) +- **feat(combos):** add reset-aware routing strategy for quota-based providers +- **feat(combo):** add context_length input field to combo edit form (#2047) +- **feat(chat):** dynamic tool limit detection with proactive truncation (#2061) +- **feat(sse):** refresh Claude OAuth wire image to claude-cli/2.1.131 (#2011) +- **feat(github):** add `targetFormat: openai-responses` to all GitHub models (#2122) +- **feat(api):** allow configuration via API calls — open management routes to Bearer keys with manage scope (#2103) +- **feat(api):** update API bridge proxy timeout to 600,000ms (#2019) +- **feat(usage):** add service tier breakdown, codex fast service tier analytics, and account for fast tier +- **feat(chat):** add `STREAM_READINESS_TIMEOUT_MS` and integrate into chat handling +- **feat(combo):** add `fallbackDelayMs` to combo configuration and related settings +- **feat(chat):** enhance error handling for semaphore capacity with fallback logic +- **feat(qdrant):** embedding model discovery (#2086) +- **feat(auth):** per-session sticky routing for Codex (#1887) +- **feat(inworld):** enhance Inworld TTS support (#2123) ### 🐛 Bug Fixes +- **fix(pricing):** make `getPricingForModel` fully case-insensitive to ensure custom prices correctly reflect in new incoming requests cost calculations +- **fix(gemini):** prevent `functionDeclarations` from being dropped by the sanitizer when `googleSearch` tool is present (#2077) +- **fix(pollinations):** add `jsonMode: true` flag in the request transformation to enforce correct JSON structure from Pollinations API (#2109) +- **fix(docker):** update Dockerfile to copy `/docs` directory during build ensuring API catalog availability at runtime (#2083) +- **fix(docker):** include OpenAPI spec in runtime image (#2007) +- **fix(providers):** strip OpenAI-specific fields in Kiro translator to prevent 400 errors (#2037) +- **fix(kiro):** normalize tool-use payloads to prevent 400 errors from agents (#2104) +- **fix(kiro):** merge adjacent user history turns after role normalization (#2105) +- **fix(ui):** resolve text contrast issues for zero-config warning banner in light mode (#2050) +- **fix(core):** inject global system prompt correctly into downstream chat completions pipeline (#2080) +- **fix(core):** restore Claude Code adaptive thinking defaults and resolve audio transcription CORS regression +- **fix(routing):** add missing v1beta rewrites to next.config to resolve 404 on Gemini models endpoint (#2102) +- **fix(routing):** fix bare GPT-5.5 routing for Codex-only installations (#2054) +- **fix(routing):** add fuzzy auto-combo routing for `auto/*` model prefix (#2010) - **fix(cache):** optimize cache_control preservation logic and explicitly align tool schema with upstream Claude Code expectations - **fix(db):** preserve legacy SQLite database path on Windows to prevent data loss (#1973) +- **fix(db):** reduce hot-path persistence overhead (#2039) +- **fix(db):** resolve migration conflict by renumbering overlapping migration entries (#2041) - **fix(settings):** resolve model alias persistence double stringification preventing UI updates (#2018) - **fix(routing):** dynamically filter bare model auto-resolution by active provider connections to prevent dead-routing (#2029) - **fix(embeddings):** add Google Gemini embeddings compatibility via OpenAI-compatible endpoint mapping (#2006) +- **fix(sse):** prevent Claude OAuth multi-account correlation via metadata.user_id (#2053) +- **fix(sse):** prevent Claude Code identity cloak overrides and fix fallback resilience (#2053) +- **fix(sse):** classify hour quota errors as QUOTA_EXHAUSTED (#2119) +- **fix(sse):** fix CC-compatible streaming bridge (#2118) +- **fix(antigravity):** sanitize Claude Cloud Code payloads (#2090) +- **fix(antigravity):** add duplex half for streaming bodies +- **fix(antigravity):** align identity protocol and behavior with official AM +- **fix(chatgpt-web):** plumb proxy through to native tls-client (#2022, #2023) +- **fix(codex):** expose native model IDs in catalog (#2012) +- **fix(glm):** add dedicated coding transport (#2087) +- **fix(compression):** support Responses input and expand Spanish compression rules (#2028) +- **fix(catalog):** auto-calculate combo context_length from target model limits (#2030) +- **fix(api):** fix usage analytics and API key identity (#2008, #2092) +- **fix(api-key):** allow Unicode letters in API key name validation (#1996) +- **fix(auth):** allow bootstrap without password (#2048) +- **fix(proxy):** clean up proxy page redundancy and fix 1proxy sync empty body error (#2052) +- **fix(dashboard):** resolve Unknown plan display in Provider Limits +- **fix(usage):** add extensible CURRENCY_SYMBOLS mapping for deepseek currencies +- **fix(runtime):** harden timer handling and model pricing fallback +- **fix(i18n):** complete Simplified Chinese translations (#2115) +- **fix(mitm):** add Linux cert install and skip sudo password when root (#1999) +- **fix(mitm):** prevent stub from loading at runtime via bypass module - **fix:** remove Anthropic-Beta header from non-Anthropic providers to fix identity contamination (#1989) - **fix(cli):** resolve .env loading failure for global npm installations +- **fix(export):** exclude telemetry/usage-history tables from JSON config backups by default to prevent unbounded file growth (#2125) +- **fix:** Follow OpenAI specification, handle throttling in batch and fix UI (#2045) -### 🔒 Security +### セキュリティ +- **fix(security):** remediate CodeQL vulnerabilities (ReDoS, cryptographic bias, stack trace exposure, and weak password hashing) (#216, #215, #211, #208, #206, #210) - **fix(security):** remediate regex validation backtracking path in core compression cleanup (#1990) - **fix(core):** harden input handling and stabilization for prompt compression edge cases +### ドキュメント + +- **docs:** add competitive marketing tables and SEO/AEO optimizations to README (#2091) +- **docs:** refresh providers, model catalogs, and docs for v3.8.0 (#2088) +- **docs:** update Claude MD and update GLM-CN max context to 200k (#2027) +- **docs(env):** add `GITLAB_DUO_OAUTH_CLIENT_ID` to `.env.example` (#2031) + ### 🧹 Chores & Maintenance - **chore(providers):** prune redundant local provider icon assets in favor of `@lobehub/icons` web fonts (#1992) +- **chore(providers):** remove deprecated models (#2033) +- **deps:** bump `fast-uri` from 3.1.0 to 3.1.2 (#2078) +- **deps:** bump `hono` from 4.12.14 to 4.12.18 (#2079) - **ci:** skip SonarCloud scan on main pushes to optimize CI time - **test:** stabilize cooldown abort coverage case in integration testing +### 🏆 v3.8.0 Community Contributors + +Thank you to all **38 community contributors** who made v3.8.0 possible! 🎉 + +| Contributor | PRs | Contributions | +| :--------------------------------------------------------- | :-: | :------------------------------------------------------------ | +| [@oyi77](https://github.com/oyi77) | 7 | #2010, #2014, #2041, #2052, #2061, #2074, #2091, #2094, #2096 | +| [@backryun](https://github.com/backryun) | 4 | #1992, #2033, #2088, #2123 | +| [@dhaern](https://github.com/dhaern) | 4 | #2028, #2039, #2087, #2090 | +| [@Tentoxa](https://github.com/Tentoxa) | 2 | #2011, #2053 | +| [@wauputr4](https://github.com/wauputr4) | 2 | #2009, #2046 | +| [@payne0420](https://github.com/payne0420) | 1 | #2082 | +| [@Tr0sT](https://github.com/Tr0sT) | 1 | #2012 | +| [@AveryanAlex](https://github.com/AveryanAlex) | 1 | #2008 | +| [@nickwizard](https://github.com/nickwizard) | 1 | #1991 | +| [@rodrigogbbr-stack](https://github.com/rodrigogbbr-stack) | 1 | #1996 | +| [@NekoMonci12](https://github.com/NekoMonci12) | 1 | #1999 | +| [@congvc-dev](https://github.com/congvc-dev) | 1 | #2004 | +| [@tatsster](https://github.com/tatsster) | 1 | #2007 | +| [@xssdem](https://github.com/xssdem) | 1 | #2023 | +| [@bypanghu](https://github.com/bypanghu) | 1 | #2027 | +| [@herjarsa](https://github.com/herjarsa) | 1 | #2030 | +| [@wucm667](https://github.com/wucm667) | 1 | #2031 | +| [@hartmark](https://github.com/hartmark) | 1 | #2045 | +| [@ddarkr](https://github.com/ddarkr) | 1 | #2047 | +| [@tces1](https://github.com/tces1) | 1 | #2048 | +| [@guanbear](https://github.com/guanbear) | 1 | #2054 | +| [@Gi99lin](https://github.com/Gi99lin) | 1 | #2055 | +| [@ivan-mezentsev](https://github.com/ivan-mezentsev) | 1 | #2063 | +| [@JxnLexn](https://github.com/JxnLexn) | 1 | #2019 | +| [@yoviarpauzi](https://github.com/yoviarpauzi) | 1 | #2092 | +| [@rafacpti23](https://github.com/rafacpti23) | 1 | #2086 | +| [@gleber](https://github.com/gleber) | 1 | #2103 | +| [@rilham97](https://github.com/rilham97) | 1 | #2104 | +| [@Gioxaa](https://github.com/Gioxaa) | 1 | #2105 | +| [@boa-z](https://github.com/boa-z) | 1 | #2115 | +| [@eleata](https://github.com/eleata) | 1 | #2116 | +| [@rdself](https://github.com/rdself) | 1 | #2118 | +| [@clousky2020](https://github.com/clousky2020) | 1 | #2119 | +| [@abhinavjnu](https://github.com/abhinavjnu) | 1 | #2122 | +| [@HoaPham98](https://github.com/HoaPham98) | 1 | #2089 | +| [@05dunski](https://github.com/05dunski) | 1 | #1978 (cherry-picked) | + ## [3.7.9] — 2026-05-03 ### ✨ New Features @@ -102,7 +220,7 @@ - **chore(provider):** Add reka models list (#1956 — thanks @backryun) - **chore(model):** Update new models, Delete Deprecated models (#1949 — thanks @backryun) -### 📝 Documentation +### ドキュメント - **docs(compression):** document RTK+Caveman stacked savings ranges @@ -201,7 +319,7 @@ - **feat(db):** auto-restore probe-failed database on startup to prevent data loss after failed upgrades (#1810) - **feat(analytics):** add cost-based usage insights and activity streaks in the analytics dashboard -### 🔒 Security +### セキュリティ - **fix(security):** resolve ReDoS vulnerability in Codex executor regex patterns (#1797, #1789) @@ -354,7 +472,7 @@ We identified that **155 community PRs** across the entire project history (from - **feat(proxy):** implement bulk proxy import via pipe-delimited parser with update-or-create (upsert) logic and real-time preview table - **feat(pwa):** add fullscreen installable PWA with manifest, service worker, and cross-platform app icons (#1728) -### 🔒 Security +### セキュリティ - **security:** replace insecure `Math.random` with `crypto.getRandomValues` for fallback UUID generation to resolve CodeQL CWE-338 finding (#182) @@ -519,7 +637,7 @@ We identified that **155 community PRs** across the entire project history (from - **fix(transport):** Prevent memory bloat and database exhaustion from large, fragmented streaming responses. Implemented `ByteQueue` in `kiro.ts` for zero-copy binary accumulation, refactored `antigravity.ts` for incremental SSE parsing, and enforced a strict 512KB tiered truncation limit (`MAX_CALL_LOG_ARTIFACT_BYTES`) on stream request logs and call artifacts (#1647). - **chore(ci):** Update build environment dependencies — bump Node to `24.15.0`, `actions/checkout@v6`, `docker/build-push-action@v7`, pin `actions/setup-python` to major tag (#1646 — thanks @backryun). -### 📝 Documentation +### ドキュメント - **docs(env):** Add `OMNIROUTE_ALLOW_PRIVATE_PROVIDER_URLS` to `.env.example` with documentation for LM Studio and other local provider use cases (#1623). @@ -669,7 +787,7 @@ We identified that **155 community PRs** across the entire project history (from - **test(next):** Align transpile package expectations for the Next.js standalone build. - **test(ci):** Fix CI-only test failures from environment differences — clear `INITIAL_PASSWORD` and `JWT_SECRET` in integration tests, handle `XDG_CONFIG_HOME` for guide-settings tests. -### 📚 Documentation +### ドキュメント - **docs:** Update the root changelog with all release-branch changes through 2026-04-24, including PRs #1544, #1555, #1551, #1550, #1548, #1547, #1541, #1538, #1536, and #1527. - **docs:** Fix broken README and localized documentation links. (#1536) @@ -811,7 +929,7 @@ We identified that **155 community PRs** across the entire project history (from - **feat(providers):** Expand image provider registry with extended model support including SD3.5, FLUX, and DALL-E 3 HD configurations - **feat(combos):** Add new routing strategies and full i18n support for agent features section across 31 languages -### 🔒 Security +### セキュリティ - **security:** Resolve 18 GitHub CodeQL scan alerts including ReDoS, incomplete sanitization, and bad HTML filtering regexp patterns - **fix(auth):** Seal privilege escalation vector by enforcing JWT session checking exclusively on `/api/keys` management endpoints (#1353) @@ -1078,7 +1196,7 @@ We identified that **155 community PRs** across the entire project history (from - **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 - **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 -### 🔒 Security +### セキュリティ - **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 - **Auth Guard on Translator Save:** Added `isAuthenticated` guard to `/api/translator/save` for defense-in-depth consistency @@ -1483,7 +1601,7 @@ We identified that **155 community PRs** across the entire project history (from - **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). -### 📚 Documentation +### ドキュメント - **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. - **Context Relay Delivery Notes:** Documented the current architecture, runtime flow, and Codex-focused scope in the feature docs, changelog, and agent guidance. @@ -1559,7 +1677,7 @@ We identified that **155 community PRs** across the entire project history (from ## [3.5.3] - 2026-04-07 -### Security +### セキュリティ - **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. - **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. @@ -1575,7 +1693,7 @@ We identified that **155 community PRs** across the entire project history (from - **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. -### Documentation +### ドキュメント - **I18n Engine:** Synchronized and pushed deep Machine Translation updates across all 32 natively-supported languages (682 translation nodes aligned). @@ -1736,7 +1854,7 @@ We identified that **155 community PRs** across the entire project history (from ## [3.4.8] — 2026-04-03 -### Security +### セキュリティ - Fully remediated all outstanding Github Advanced Security (CodeQL) findings and Dependabot alerts. - Fixed insecure randomness vulnerabilities by migrating from `Math.random` to `crypto.randomUUID()`. @@ -1748,7 +1866,7 @@ We identified that **155 community PRs** across the entire project history (from ## [3.4.7] — 2026-04-03 -### Features +### 機能 - Added `Cryptography` node to Monitoring and MCP health checks (#798) - Hardened model-catalog route permissions mapping (`/models`) (#781) @@ -1764,7 +1882,7 @@ We identified that **155 community PRs** across the entire project history (from - Fixed MCP standalone module-resolution (`ERR_MODULE_NOT_FOUND`) via `esbuild` (#936) - Fixed NVIDIA NIM routing credential resolution alias mismatch (#931) -### Security +### セキュリティ - Added safe strict input boundary protection against raw `shell: true` remote-code execution injections. @@ -2011,7 +2129,7 @@ We identified that **155 community PRs** across the entire project history (from ## [3.4.0] - 2026-03-31 -### 🚀 Features +### 機能 - **Subscription Utilization Analytics:** Added quota snapshot time-series tracking, Provider Utilization and Combo Health tabs with recharts visualizations, and corresponding API endpoints (#847) - **SQLite Backup Control:** New `OMNIROUTE_DISABLE_AUTO_BACKUP` env flag to disable automatic SQLite backups (#846) @@ -2063,7 +2181,7 @@ We identified that **155 community PRs** across the entire project history (from ## [3.3.8] - 2026-03-30 -### 🚀 Features +### 機能 - **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) - **Qoder Integration:** Native integration for Qoder AI natively replacing the legacy iFlow platform mappings (#660) @@ -2889,7 +3007,7 @@ We identified that **155 community PRs** across the entire project history (from - **NaN tokens in Claude Code / client responses (#617):** - `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 -### 🔒 Security +### セキュリティ - Updated `yaml` package to fix stack overflow vulnerability (GHSA-48c2-rrv3-qjmp) @@ -3565,7 +3683,7 @@ docker pull diegosouzapw/omniroute:3.0.0 - **SVG fallback**: `ProviderIcon` component updated with 4-tier strategy: Lobehub → PNG → SVG → Generic icon - **Agents fingerprinting**: Synced with CLI tools — added droid, openclaw, copilot, opencode to fingerprint list (14 total) -### 🔒 Security +### セキュリティ - **CVE fix**: Resolved dompurify XSS vulnerability (GHSA-v2wj-7wpq-c8vv) via npm overrides forcing `dompurify@^3.3.2` - `npm audit` now reports **0 vulnerabilities** @@ -3928,7 +4046,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **#510** — Windows: MSYS2/Git-Bash paths (`/c/Program Files/...`) are now normalized to `C:\Program Files\...` - **#492** — `omniroute` CLI now detects `mise`/`nvm` when `app/server.js` is missing and shows targeted fix -### 📖 Documentation +### ドキュメント - **#513** — Docker password reset: `INITIAL_PASSWORD` env var workaround documented - **#520** — pnpm: `pnpm approve-builds better-sqlite3` documented @@ -4025,7 +4143,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **feat(executors/cloudflare-ai)**: New `CloudflareAIExecutor` — dynamic URL construction requires `accountId` in provider credentials - **feat(executors)**: Register `pollinations`, `pol`, `cloudflare-ai`, `cf` executor mappings -### 📝 Documentation +### ドキュメント - **docs(readme)**: Expanded free combo stack to 11 providers ($0 forever) - **docs(readme)**: Added 4 new free provider sections (LongCat, Pollinations, Cloudflare AI, Scaleway) with model tables @@ -4177,7 +4295,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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). -### Features +### 機能 - **"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. @@ -4205,7 +4323,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Merge PR #494 (MiniMax role fix), fix KIRO MITM dashboard, triage 8 issues. -### Features +### 機能 - **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. - **roleNormalizer**: `normalizeDeveloperRole()` now accepts `preserveDeveloperRole` parameter with tri-state behavior (undefined=keep, true=keep, false=convert). @@ -4261,7 +4379,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Gemini CLI deprecation, VM guide i18n fix, dependabot security fix, provider schema expansion. -### Features +### 機能 - **Gemini CLI Deprecation** (#462): Mark `gemini-cli` provider as deprecated with warning — Google restricts third-party OAuth usage from March 2026 - **Provider Schema** (#462): Expand Zod validation with `deprecated`, `deprecationReason`, `hasFree`, `freeNote`, `authHint`, `apiHint` optional fields @@ -4270,7 +4388,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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) -### Security +### セキュリティ - **deps**: Bump `flatted` 3.3.3 → 3.4.2 — fixes CWE-1321 prototype pollution (#484, @dependabot) @@ -4290,7 +4408,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Czech i18n, SSE protocol fix, VM guide translation. -### Features +### 機能 - **Czech Language** (#482): Full Czech (cs) i18n — 22 docs, 2606 UI strings, language switcher updates (@zen0bit) - **VM Deployment Guide**: Translated from Portuguese to English as the source document (@zen0bit) @@ -4309,7 +4427,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: 2 merged PRs, model aliases routing fix, log export, and issue triage. -### Features +### 機能 - **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) @@ -4329,7 +4447,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Five community PRs — streaming call log fixes, Kiro compatibility, cache token analytics, Chinese translation, and configurable tool call IDs. -### ✨ Features +### 機能 - **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) - **feat(providers)**: Per-model configurable 9-char tool call ID normalization (Mistral-style) — only models with the option enabled get truncated IDs (#470) @@ -4359,7 +4477,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Bailian Coding Plan provider with editable base URLs, plus community contributions for Alibaba Cloud and Kimi Coding. -### ✨ Features +### 機能 - **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) - **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) @@ -4374,7 +4492,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Two new community-contributed providers (Alibaba Cloud Coding, Kimi Coding API-key) and Docker pino fix. -### ✨ Features +### 機能 - **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) - **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) @@ -4399,7 +4517,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Codex responses subpath passthrough natively supported, Windows MITM crash fixed, and Combos agent schemas adjusted. -### ✨ Features +### 機能 - **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) @@ -4439,7 +4557,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **fix(budget)**: "Save Limits" no longer returns 422 — `warningThreshold` is now correctly sent as fraction (0–1) instead of percentage (0–100) (#451) - **fix(combos)**: `` internal cache tag is now stripped before forwarding requests to providers, preventing cache session breaks (#454) -### ✨ Features +### 機能 - **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) @@ -4495,7 +4613,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Search Tools dashboard, i18n fixes, Copilot limits, Serper validation fix. -### 🚀 Features +### 機能 - **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) - New route: `/dashboard/search-tools` @@ -4595,7 +4713,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - DB migration: `request_type` column on `call_logs` for non-chat request tracking - Zod validation (`v1SearchSchema`), auth-gated, cost recorded via `recordCost()` -### 🔒 Security +### セキュリティ - **deps**: Next.js 16.1.6 → 16.1.7 — fixes 6 CVEs: - **Critical**: CVE-2026-29057 (HTTP request smuggling via http-proxy) @@ -4725,7 +4843,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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**: New `request_detail_logs` table with 500-entry ring-buffer trigger, opt-in via settings toggle -### ✨ Features +### 機能 - **feat(combo)**: System Message Override per Combo (#399 — `system_message` field replaces or injects system prompt before forwarding to provider) - **feat(combo)**: Tool Filter Regex per Combo (#399 — `tool_filter_regex` keeps only tools matching pattern; supports OpenAI + Anthropic formats) @@ -4740,7 +4858,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: SSE improvements, local provider_nodes extensions, proxy registry, Claude passthrough fixes. -### ✨ Features +### 機能 - **feat(health)**: Background health check for local `provider_nodes` with exponential backoff (30s→300s) and `Promise.allSettled` to avoid blocking (#423, @Regis-RCR) - **feat(embeddings)**: Route `/v1/embeddings` to local `provider_nodes` — `buildDynamicEmbeddingProvider()` with hostname validation (#422, @Regis-RCR) @@ -4882,7 +5000,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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 - **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). -### ✨ Features +### 機能 - **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) @@ -4912,7 +5030,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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) - **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) -### ✨ Features +### 機能 - **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) - **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. @@ -4971,7 +5089,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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) - **fix(logs)**: Request log table is now readable in light mode — status badges, token counts, and combo tags use adaptive `dark:` color classes (#378) -### ✨ Features +### 機能 - **feat(kiro)**: Kiro credit tracking added to usage fetcher — queries `getUserCredits` from AWS CodeWhisperer endpoint (#337) @@ -5372,7 +5490,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > **Major release** — Free Stack ecosystem, transcription playground overhaul, 44+ providers, comprehensive free tier documentation, and UI improvements across the board. -### ✨ Features +### 機能 - **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. - **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. @@ -5383,7 +5501,7 @@ OmniRoute now automatically refreshes model lists for connected providers every ## [2.3.16] - 2026-03-13 -### 📖 Documentation +### ドキュメント - **README: 44+ Providers** — Updated all 3 occurrences of "36+ providers" to "44+" reflecting the actual codebase count (44 providers in providers.ts) - **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. @@ -5393,7 +5511,7 @@ OmniRoute now automatically refreshes model lists for connected providers every ## [2.3.15] - 2026-03-13 -### ✨ Features +### 機能 - **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. - **i18n — autoCombo section**: Added 20 new translation keys for the Auto-Combo dashboard (`title`, `status`, `modePack`, `providerScores`, `factorTierPriority`, etc.) to all 30 language files. diff --git a/docs/i18n/ko/CHANGELOG.md b/docs/i18n/ko/CHANGELOG.md index 33abbb178f..dc62bdbbd3 100644 --- a/docs/i18n/ko/CHANGELOG.md +++ b/docs/i18n/ko/CHANGELOG.md @@ -10,30 +10,148 @@ ### ✨ New Features -- **feat(antigravity):** integrate Antigravity provider with dynamic `maxOutputTokens` calculation (bumping to `thinkingBudget + 1`) and standard Cloud Code envelope payload sanitization (#2055, #2063) +- **feat(antigravity):** integrate Antigravity provider with dynamic `maxOutputTokens` calculation, identity fingerprinting overhaul, and Cloud Code envelope payload sanitization (#2055, #2063) - **feat(gemini-cli):** add custom projectId support for Gemini CLI transport (UI, DB, executor) (#1991) +- **feat(providers):** add KIE media provider support with dynamic polling, text models, and expanded video models catalog +- **feat(providers):** add Z.AI provider support with GLM quota handling and new quota labels +- **feat(providers):** add 9 new free AI providers — LLM7, Lepton, Kluster, UncloseAI, BazaarLink, Completions, Enally, FreeTheAi (#2096) +- **feat(providers):** batch delete provider connections via checkbox multi-select (#2094) +- **feat(cursor):** full OpenAI parity — tool calls, streaming, and session management (#2082) +- **feat(cli):** comprehensive CLI enhancement suite with 20+ new commands including `omniroute providers`, `omniroute combos`, `omniroute doctor` (#2074) +- **feat(cli):** add modular CLI setup and provider management commands (#2046) +- **feat(mcp):** add DeepSeek quota and limit monitoring feature (#2089) +- **feat(circuit-breaker):** classify 429 errors and apply per-kind cooldowns (#2116) +- **feat(multi):** manifest-aware tier routing — W1-W4 complete (#2014) +- **feat(combos):** add reset-aware routing strategy for quota-based providers +- **feat(combo):** add context_length input field to combo edit form (#2047) +- **feat(chat):** dynamic tool limit detection with proactive truncation (#2061) +- **feat(sse):** refresh Claude OAuth wire image to claude-cli/2.1.131 (#2011) +- **feat(github):** add `targetFormat: openai-responses` to all GitHub models (#2122) +- **feat(api):** allow configuration via API calls — open management routes to Bearer keys with manage scope (#2103) +- **feat(api):** update API bridge proxy timeout to 600,000ms (#2019) +- **feat(usage):** add service tier breakdown, codex fast service tier analytics, and account for fast tier +- **feat(chat):** add `STREAM_READINESS_TIMEOUT_MS` and integrate into chat handling +- **feat(combo):** add `fallbackDelayMs` to combo configuration and related settings +- **feat(chat):** enhance error handling for semaphore capacity with fallback logic +- **feat(qdrant):** embedding model discovery (#2086) +- **feat(auth):** per-session sticky routing for Codex (#1887) +- **feat(inworld):** enhance Inworld TTS support (#2123) ### 🐛 Bug Fixes +- **fix(pricing):** make `getPricingForModel` fully case-insensitive to ensure custom prices correctly reflect in new incoming requests cost calculations +- **fix(gemini):** prevent `functionDeclarations` from being dropped by the sanitizer when `googleSearch` tool is present (#2077) +- **fix(pollinations):** add `jsonMode: true` flag in the request transformation to enforce correct JSON structure from Pollinations API (#2109) +- **fix(docker):** update Dockerfile to copy `/docs` directory during build ensuring API catalog availability at runtime (#2083) +- **fix(docker):** include OpenAPI spec in runtime image (#2007) +- **fix(providers):** strip OpenAI-specific fields in Kiro translator to prevent 400 errors (#2037) +- **fix(kiro):** normalize tool-use payloads to prevent 400 errors from agents (#2104) +- **fix(kiro):** merge adjacent user history turns after role normalization (#2105) +- **fix(ui):** resolve text contrast issues for zero-config warning banner in light mode (#2050) +- **fix(core):** inject global system prompt correctly into downstream chat completions pipeline (#2080) +- **fix(core):** restore Claude Code adaptive thinking defaults and resolve audio transcription CORS regression +- **fix(routing):** add missing v1beta rewrites to next.config to resolve 404 on Gemini models endpoint (#2102) +- **fix(routing):** fix bare GPT-5.5 routing for Codex-only installations (#2054) +- **fix(routing):** add fuzzy auto-combo routing for `auto/*` model prefix (#2010) - **fix(cache):** optimize cache_control preservation logic and explicitly align tool schema with upstream Claude Code expectations - **fix(db):** preserve legacy SQLite database path on Windows to prevent data loss (#1973) +- **fix(db):** reduce hot-path persistence overhead (#2039) +- **fix(db):** resolve migration conflict by renumbering overlapping migration entries (#2041) - **fix(settings):** resolve model alias persistence double stringification preventing UI updates (#2018) - **fix(routing):** dynamically filter bare model auto-resolution by active provider connections to prevent dead-routing (#2029) - **fix(embeddings):** add Google Gemini embeddings compatibility via OpenAI-compatible endpoint mapping (#2006) +- **fix(sse):** prevent Claude OAuth multi-account correlation via metadata.user_id (#2053) +- **fix(sse):** prevent Claude Code identity cloak overrides and fix fallback resilience (#2053) +- **fix(sse):** classify hour quota errors as QUOTA_EXHAUSTED (#2119) +- **fix(sse):** fix CC-compatible streaming bridge (#2118) +- **fix(antigravity):** sanitize Claude Cloud Code payloads (#2090) +- **fix(antigravity):** add duplex half for streaming bodies +- **fix(antigravity):** align identity protocol and behavior with official AM +- **fix(chatgpt-web):** plumb proxy through to native tls-client (#2022, #2023) +- **fix(codex):** expose native model IDs in catalog (#2012) +- **fix(glm):** add dedicated coding transport (#2087) +- **fix(compression):** support Responses input and expand Spanish compression rules (#2028) +- **fix(catalog):** auto-calculate combo context_length from target model limits (#2030) +- **fix(api):** fix usage analytics and API key identity (#2008, #2092) +- **fix(api-key):** allow Unicode letters in API key name validation (#1996) +- **fix(auth):** allow bootstrap without password (#2048) +- **fix(proxy):** clean up proxy page redundancy and fix 1proxy sync empty body error (#2052) +- **fix(dashboard):** resolve Unknown plan display in Provider Limits +- **fix(usage):** add extensible CURRENCY_SYMBOLS mapping for deepseek currencies +- **fix(runtime):** harden timer handling and model pricing fallback +- **fix(i18n):** complete Simplified Chinese translations (#2115) +- **fix(mitm):** add Linux cert install and skip sudo password when root (#1999) +- **fix(mitm):** prevent stub from loading at runtime via bypass module - **fix:** remove Anthropic-Beta header from non-Anthropic providers to fix identity contamination (#1989) - **fix(cli):** resolve .env loading failure for global npm installations +- **fix(export):** exclude telemetry/usage-history tables from JSON config backups by default to prevent unbounded file growth (#2125) +- **fix:** Follow OpenAI specification, handle throttling in batch and fix UI (#2045) -### 🔒 Security +### 보안 +- **fix(security):** remediate CodeQL vulnerabilities (ReDoS, cryptographic bias, stack trace exposure, and weak password hashing) (#216, #215, #211, #208, #206, #210) - **fix(security):** remediate regex validation backtracking path in core compression cleanup (#1990) - **fix(core):** harden input handling and stabilization for prompt compression edge cases +### 문서 + +- **docs:** add competitive marketing tables and SEO/AEO optimizations to README (#2091) +- **docs:** refresh providers, model catalogs, and docs for v3.8.0 (#2088) +- **docs:** update Claude MD and update GLM-CN max context to 200k (#2027) +- **docs(env):** add `GITLAB_DUO_OAUTH_CLIENT_ID` to `.env.example` (#2031) + ### 🧹 Chores & Maintenance - **chore(providers):** prune redundant local provider icon assets in favor of `@lobehub/icons` web fonts (#1992) +- **chore(providers):** remove deprecated models (#2033) +- **deps:** bump `fast-uri` from 3.1.0 to 3.1.2 (#2078) +- **deps:** bump `hono` from 4.12.14 to 4.12.18 (#2079) - **ci:** skip SonarCloud scan on main pushes to optimize CI time - **test:** stabilize cooldown abort coverage case in integration testing +### 🏆 v3.8.0 Community Contributors + +Thank you to all **38 community contributors** who made v3.8.0 possible! 🎉 + +| Contributor | PRs | Contributions | +| :--------------------------------------------------------- | :-: | :------------------------------------------------------------ | +| [@oyi77](https://github.com/oyi77) | 7 | #2010, #2014, #2041, #2052, #2061, #2074, #2091, #2094, #2096 | +| [@backryun](https://github.com/backryun) | 4 | #1992, #2033, #2088, #2123 | +| [@dhaern](https://github.com/dhaern) | 4 | #2028, #2039, #2087, #2090 | +| [@Tentoxa](https://github.com/Tentoxa) | 2 | #2011, #2053 | +| [@wauputr4](https://github.com/wauputr4) | 2 | #2009, #2046 | +| [@payne0420](https://github.com/payne0420) | 1 | #2082 | +| [@Tr0sT](https://github.com/Tr0sT) | 1 | #2012 | +| [@AveryanAlex](https://github.com/AveryanAlex) | 1 | #2008 | +| [@nickwizard](https://github.com/nickwizard) | 1 | #1991 | +| [@rodrigogbbr-stack](https://github.com/rodrigogbbr-stack) | 1 | #1996 | +| [@NekoMonci12](https://github.com/NekoMonci12) | 1 | #1999 | +| [@congvc-dev](https://github.com/congvc-dev) | 1 | #2004 | +| [@tatsster](https://github.com/tatsster) | 1 | #2007 | +| [@xssdem](https://github.com/xssdem) | 1 | #2023 | +| [@bypanghu](https://github.com/bypanghu) | 1 | #2027 | +| [@herjarsa](https://github.com/herjarsa) | 1 | #2030 | +| [@wucm667](https://github.com/wucm667) | 1 | #2031 | +| [@hartmark](https://github.com/hartmark) | 1 | #2045 | +| [@ddarkr](https://github.com/ddarkr) | 1 | #2047 | +| [@tces1](https://github.com/tces1) | 1 | #2048 | +| [@guanbear](https://github.com/guanbear) | 1 | #2054 | +| [@Gi99lin](https://github.com/Gi99lin) | 1 | #2055 | +| [@ivan-mezentsev](https://github.com/ivan-mezentsev) | 1 | #2063 | +| [@JxnLexn](https://github.com/JxnLexn) | 1 | #2019 | +| [@yoviarpauzi](https://github.com/yoviarpauzi) | 1 | #2092 | +| [@rafacpti23](https://github.com/rafacpti23) | 1 | #2086 | +| [@gleber](https://github.com/gleber) | 1 | #2103 | +| [@rilham97](https://github.com/rilham97) | 1 | #2104 | +| [@Gioxaa](https://github.com/Gioxaa) | 1 | #2105 | +| [@boa-z](https://github.com/boa-z) | 1 | #2115 | +| [@eleata](https://github.com/eleata) | 1 | #2116 | +| [@rdself](https://github.com/rdself) | 1 | #2118 | +| [@clousky2020](https://github.com/clousky2020) | 1 | #2119 | +| [@abhinavjnu](https://github.com/abhinavjnu) | 1 | #2122 | +| [@HoaPham98](https://github.com/HoaPham98) | 1 | #2089 | +| [@05dunski](https://github.com/05dunski) | 1 | #1978 (cherry-picked) | + ## [3.7.9] — 2026-05-03 ### ✨ New Features @@ -102,7 +220,7 @@ - **chore(provider):** Add reka models list (#1956 — thanks @backryun) - **chore(model):** Update new models, Delete Deprecated models (#1949 — thanks @backryun) -### 📝 Documentation +### 문서 - **docs(compression):** document RTK+Caveman stacked savings ranges @@ -201,7 +319,7 @@ - **feat(db):** auto-restore probe-failed database on startup to prevent data loss after failed upgrades (#1810) - **feat(analytics):** add cost-based usage insights and activity streaks in the analytics dashboard -### 🔒 Security +### 보안 - **fix(security):** resolve ReDoS vulnerability in Codex executor regex patterns (#1797, #1789) @@ -354,7 +472,7 @@ We identified that **155 community PRs** across the entire project history (from - **feat(proxy):** implement bulk proxy import via pipe-delimited parser with update-or-create (upsert) logic and real-time preview table - **feat(pwa):** add fullscreen installable PWA with manifest, service worker, and cross-platform app icons (#1728) -### 🔒 Security +### 보안 - **security:** replace insecure `Math.random` with `crypto.getRandomValues` for fallback UUID generation to resolve CodeQL CWE-338 finding (#182) @@ -519,7 +637,7 @@ We identified that **155 community PRs** across the entire project history (from - **fix(transport):** Prevent memory bloat and database exhaustion from large, fragmented streaming responses. Implemented `ByteQueue` in `kiro.ts` for zero-copy binary accumulation, refactored `antigravity.ts` for incremental SSE parsing, and enforced a strict 512KB tiered truncation limit (`MAX_CALL_LOG_ARTIFACT_BYTES`) on stream request logs and call artifacts (#1647). - **chore(ci):** Update build environment dependencies — bump Node to `24.15.0`, `actions/checkout@v6`, `docker/build-push-action@v7`, pin `actions/setup-python` to major tag (#1646 — thanks @backryun). -### 📝 Documentation +### 문서 - **docs(env):** Add `OMNIROUTE_ALLOW_PRIVATE_PROVIDER_URLS` to `.env.example` with documentation for LM Studio and other local provider use cases (#1623). @@ -669,7 +787,7 @@ We identified that **155 community PRs** across the entire project history (from - **test(next):** Align transpile package expectations for the Next.js standalone build. - **test(ci):** Fix CI-only test failures from environment differences — clear `INITIAL_PASSWORD` and `JWT_SECRET` in integration tests, handle `XDG_CONFIG_HOME` for guide-settings tests. -### 📚 Documentation +### 문서 - **docs:** Update the root changelog with all release-branch changes through 2026-04-24, including PRs #1544, #1555, #1551, #1550, #1548, #1547, #1541, #1538, #1536, and #1527. - **docs:** Fix broken README and localized documentation links. (#1536) @@ -811,7 +929,7 @@ We identified that **155 community PRs** across the entire project history (from - **feat(providers):** Expand image provider registry with extended model support including SD3.5, FLUX, and DALL-E 3 HD configurations - **feat(combos):** Add new routing strategies and full i18n support for agent features section across 31 languages -### 🔒 Security +### 보안 - **security:** Resolve 18 GitHub CodeQL scan alerts including ReDoS, incomplete sanitization, and bad HTML filtering regexp patterns - **fix(auth):** Seal privilege escalation vector by enforcing JWT session checking exclusively on `/api/keys` management endpoints (#1353) @@ -1078,7 +1196,7 @@ We identified that **155 community PRs** across the entire project history (from - **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 - **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 -### 🔒 Security +### 보안 - **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 - **Auth Guard on Translator Save:** Added `isAuthenticated` guard to `/api/translator/save` for defense-in-depth consistency @@ -1483,7 +1601,7 @@ We identified that **155 community PRs** across the entire project history (from - **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). -### 📚 Documentation +### 문서 - **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. - **Context Relay Delivery Notes:** Documented the current architecture, runtime flow, and Codex-focused scope in the feature docs, changelog, and agent guidance. @@ -1559,7 +1677,7 @@ We identified that **155 community PRs** across the entire project history (from ## [3.5.3] - 2026-04-07 -### Security +### 보안 - **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. - **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. @@ -1575,7 +1693,7 @@ We identified that **155 community PRs** across the entire project history (from - **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. -### Documentation +### 문서 - **I18n Engine:** Synchronized and pushed deep Machine Translation updates across all 32 natively-supported languages (682 translation nodes aligned). @@ -1736,7 +1854,7 @@ We identified that **155 community PRs** across the entire project history (from ## [3.4.8] — 2026-04-03 -### Security +### 보안 - Fully remediated all outstanding Github Advanced Security (CodeQL) findings and Dependabot alerts. - Fixed insecure randomness vulnerabilities by migrating from `Math.random` to `crypto.randomUUID()`. @@ -1748,7 +1866,7 @@ We identified that **155 community PRs** across the entire project history (from ## [3.4.7] — 2026-04-03 -### Features +### 기능 - Added `Cryptography` node to Monitoring and MCP health checks (#798) - Hardened model-catalog route permissions mapping (`/models`) (#781) @@ -1764,7 +1882,7 @@ We identified that **155 community PRs** across the entire project history (from - Fixed MCP standalone module-resolution (`ERR_MODULE_NOT_FOUND`) via `esbuild` (#936) - Fixed NVIDIA NIM routing credential resolution alias mismatch (#931) -### Security +### 보안 - Added safe strict input boundary protection against raw `shell: true` remote-code execution injections. @@ -2011,7 +2129,7 @@ We identified that **155 community PRs** across the entire project history (from ## [3.4.0] - 2026-03-31 -### 🚀 Features +### 기능 - **Subscription Utilization Analytics:** Added quota snapshot time-series tracking, Provider Utilization and Combo Health tabs with recharts visualizations, and corresponding API endpoints (#847) - **SQLite Backup Control:** New `OMNIROUTE_DISABLE_AUTO_BACKUP` env flag to disable automatic SQLite backups (#846) @@ -2063,7 +2181,7 @@ We identified that **155 community PRs** across the entire project history (from ## [3.3.8] - 2026-03-30 -### 🚀 Features +### 기능 - **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) - **Qoder Integration:** Native integration for Qoder AI natively replacing the legacy iFlow platform mappings (#660) @@ -2889,7 +3007,7 @@ We identified that **155 community PRs** across the entire project history (from - **NaN tokens in Claude Code / client responses (#617):** - `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 -### 🔒 Security +### 보안 - Updated `yaml` package to fix stack overflow vulnerability (GHSA-48c2-rrv3-qjmp) @@ -3565,7 +3683,7 @@ docker pull diegosouzapw/omniroute:3.0.0 - **SVG fallback**: `ProviderIcon` component updated with 4-tier strategy: Lobehub → PNG → SVG → Generic icon - **Agents fingerprinting**: Synced with CLI tools — added droid, openclaw, copilot, opencode to fingerprint list (14 total) -### 🔒 Security +### 보안 - **CVE fix**: Resolved dompurify XSS vulnerability (GHSA-v2wj-7wpq-c8vv) via npm overrides forcing `dompurify@^3.3.2` - `npm audit` now reports **0 vulnerabilities** @@ -3928,7 +4046,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **#510** — Windows: MSYS2/Git-Bash paths (`/c/Program Files/...`) are now normalized to `C:\Program Files\...` - **#492** — `omniroute` CLI now detects `mise`/`nvm` when `app/server.js` is missing and shows targeted fix -### 📖 Documentation +### 문서 - **#513** — Docker password reset: `INITIAL_PASSWORD` env var workaround documented - **#520** — pnpm: `pnpm approve-builds better-sqlite3` documented @@ -4025,7 +4143,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **feat(executors/cloudflare-ai)**: New `CloudflareAIExecutor` — dynamic URL construction requires `accountId` in provider credentials - **feat(executors)**: Register `pollinations`, `pol`, `cloudflare-ai`, `cf` executor mappings -### 📝 Documentation +### 문서 - **docs(readme)**: Expanded free combo stack to 11 providers ($0 forever) - **docs(readme)**: Added 4 new free provider sections (LongCat, Pollinations, Cloudflare AI, Scaleway) with model tables @@ -4177,7 +4295,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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). -### Features +### 기능 - **"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. @@ -4205,7 +4323,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Merge PR #494 (MiniMax role fix), fix KIRO MITM dashboard, triage 8 issues. -### Features +### 기능 - **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. - **roleNormalizer**: `normalizeDeveloperRole()` now accepts `preserveDeveloperRole` parameter with tri-state behavior (undefined=keep, true=keep, false=convert). @@ -4261,7 +4379,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Gemini CLI deprecation, VM guide i18n fix, dependabot security fix, provider schema expansion. -### Features +### 기능 - **Gemini CLI Deprecation** (#462): Mark `gemini-cli` provider as deprecated with warning — Google restricts third-party OAuth usage from March 2026 - **Provider Schema** (#462): Expand Zod validation with `deprecated`, `deprecationReason`, `hasFree`, `freeNote`, `authHint`, `apiHint` optional fields @@ -4270,7 +4388,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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) -### Security +### 보안 - **deps**: Bump `flatted` 3.3.3 → 3.4.2 — fixes CWE-1321 prototype pollution (#484, @dependabot) @@ -4290,7 +4408,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Czech i18n, SSE protocol fix, VM guide translation. -### Features +### 기능 - **Czech Language** (#482): Full Czech (cs) i18n — 22 docs, 2606 UI strings, language switcher updates (@zen0bit) - **VM Deployment Guide**: Translated from Portuguese to English as the source document (@zen0bit) @@ -4309,7 +4427,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: 2 merged PRs, model aliases routing fix, log export, and issue triage. -### Features +### 기능 - **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) @@ -4329,7 +4447,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Five community PRs — streaming call log fixes, Kiro compatibility, cache token analytics, Chinese translation, and configurable tool call IDs. -### ✨ Features +### 기능 - **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) - **feat(providers)**: Per-model configurable 9-char tool call ID normalization (Mistral-style) — only models with the option enabled get truncated IDs (#470) @@ -4359,7 +4477,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Bailian Coding Plan provider with editable base URLs, plus community contributions for Alibaba Cloud and Kimi Coding. -### ✨ Features +### 기능 - **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) - **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) @@ -4374,7 +4492,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Two new community-contributed providers (Alibaba Cloud Coding, Kimi Coding API-key) and Docker pino fix. -### ✨ Features +### 기능 - **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) - **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) @@ -4399,7 +4517,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Codex responses subpath passthrough natively supported, Windows MITM crash fixed, and Combos agent schemas adjusted. -### ✨ Features +### 기능 - **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) @@ -4439,7 +4557,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **fix(budget)**: "Save Limits" no longer returns 422 — `warningThreshold` is now correctly sent as fraction (0–1) instead of percentage (0–100) (#451) - **fix(combos)**: `` internal cache tag is now stripped before forwarding requests to providers, preventing cache session breaks (#454) -### ✨ Features +### 기능 - **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) @@ -4495,7 +4613,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Search Tools dashboard, i18n fixes, Copilot limits, Serper validation fix. -### 🚀 Features +### 기능 - **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) - New route: `/dashboard/search-tools` @@ -4595,7 +4713,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - DB migration: `request_type` column on `call_logs` for non-chat request tracking - Zod validation (`v1SearchSchema`), auth-gated, cost recorded via `recordCost()` -### 🔒 Security +### 보안 - **deps**: Next.js 16.1.6 → 16.1.7 — fixes 6 CVEs: - **Critical**: CVE-2026-29057 (HTTP request smuggling via http-proxy) @@ -4725,7 +4843,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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**: New `request_detail_logs` table with 500-entry ring-buffer trigger, opt-in via settings toggle -### ✨ Features +### 기능 - **feat(combo)**: System Message Override per Combo (#399 — `system_message` field replaces or injects system prompt before forwarding to provider) - **feat(combo)**: Tool Filter Regex per Combo (#399 — `tool_filter_regex` keeps only tools matching pattern; supports OpenAI + Anthropic formats) @@ -4740,7 +4858,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: SSE improvements, local provider_nodes extensions, proxy registry, Claude passthrough fixes. -### ✨ Features +### 기능 - **feat(health)**: Background health check for local `provider_nodes` with exponential backoff (30s→300s) and `Promise.allSettled` to avoid blocking (#423, @Regis-RCR) - **feat(embeddings)**: Route `/v1/embeddings` to local `provider_nodes` — `buildDynamicEmbeddingProvider()` with hostname validation (#422, @Regis-RCR) @@ -4882,7 +5000,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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 - **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). -### ✨ Features +### 기능 - **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) @@ -4912,7 +5030,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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) - **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) -### ✨ Features +### 기능 - **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) - **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. @@ -4971,7 +5089,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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) - **fix(logs)**: Request log table is now readable in light mode — status badges, token counts, and combo tags use adaptive `dark:` color classes (#378) -### ✨ Features +### 기능 - **feat(kiro)**: Kiro credit tracking added to usage fetcher — queries `getUserCredits` from AWS CodeWhisperer endpoint (#337) @@ -5372,7 +5490,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > **Major release** — Free Stack ecosystem, transcription playground overhaul, 44+ providers, comprehensive free tier documentation, and UI improvements across the board. -### ✨ Features +### 기능 - **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. - **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. @@ -5383,7 +5501,7 @@ OmniRoute now automatically refreshes model lists for connected providers every ## [2.3.16] - 2026-03-13 -### 📖 Documentation +### 문서 - **README: 44+ Providers** — Updated all 3 occurrences of "36+ providers" to "44+" reflecting the actual codebase count (44 providers in providers.ts) - **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. @@ -5393,7 +5511,7 @@ OmniRoute now automatically refreshes model lists for connected providers every ## [2.3.15] - 2026-03-13 -### ✨ Features +### 기능 - **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. - **i18n — autoCombo section**: Added 20 new translation keys for the Auto-Combo dashboard (`title`, `status`, `modePack`, `providerScores`, `factorTierPriority`, etc.) to all 30 language files. diff --git a/docs/i18n/mr/CHANGELOG.md b/docs/i18n/mr/CHANGELOG.md index bc787d54a6..29f28182c6 100644 --- a/docs/i18n/mr/CHANGELOG.md +++ b/docs/i18n/mr/CHANGELOG.md @@ -10,30 +10,148 @@ ### ✨ New Features -- **feat(antigravity):** integrate Antigravity provider with dynamic `maxOutputTokens` calculation (bumping to `thinkingBudget + 1`) and standard Cloud Code envelope payload sanitization (#2055, #2063) +- **feat(antigravity):** integrate Antigravity provider with dynamic `maxOutputTokens` calculation, identity fingerprinting overhaul, and Cloud Code envelope payload sanitization (#2055, #2063) - **feat(gemini-cli):** add custom projectId support for Gemini CLI transport (UI, DB, executor) (#1991) +- **feat(providers):** add KIE media provider support with dynamic polling, text models, and expanded video models catalog +- **feat(providers):** add Z.AI provider support with GLM quota handling and new quota labels +- **feat(providers):** add 9 new free AI providers — LLM7, Lepton, Kluster, UncloseAI, BazaarLink, Completions, Enally, FreeTheAi (#2096) +- **feat(providers):** batch delete provider connections via checkbox multi-select (#2094) +- **feat(cursor):** full OpenAI parity — tool calls, streaming, and session management (#2082) +- **feat(cli):** comprehensive CLI enhancement suite with 20+ new commands including `omniroute providers`, `omniroute combos`, `omniroute doctor` (#2074) +- **feat(cli):** add modular CLI setup and provider management commands (#2046) +- **feat(mcp):** add DeepSeek quota and limit monitoring feature (#2089) +- **feat(circuit-breaker):** classify 429 errors and apply per-kind cooldowns (#2116) +- **feat(multi):** manifest-aware tier routing — W1-W4 complete (#2014) +- **feat(combos):** add reset-aware routing strategy for quota-based providers +- **feat(combo):** add context_length input field to combo edit form (#2047) +- **feat(chat):** dynamic tool limit detection with proactive truncation (#2061) +- **feat(sse):** refresh Claude OAuth wire image to claude-cli/2.1.131 (#2011) +- **feat(github):** add `targetFormat: openai-responses` to all GitHub models (#2122) +- **feat(api):** allow configuration via API calls — open management routes to Bearer keys with manage scope (#2103) +- **feat(api):** update API bridge proxy timeout to 600,000ms (#2019) +- **feat(usage):** add service tier breakdown, codex fast service tier analytics, and account for fast tier +- **feat(chat):** add `STREAM_READINESS_TIMEOUT_MS` and integrate into chat handling +- **feat(combo):** add `fallbackDelayMs` to combo configuration and related settings +- **feat(chat):** enhance error handling for semaphore capacity with fallback logic +- **feat(qdrant):** embedding model discovery (#2086) +- **feat(auth):** per-session sticky routing for Codex (#1887) +- **feat(inworld):** enhance Inworld TTS support (#2123) ### 🐛 Bug Fixes +- **fix(pricing):** make `getPricingForModel` fully case-insensitive to ensure custom prices correctly reflect in new incoming requests cost calculations +- **fix(gemini):** prevent `functionDeclarations` from being dropped by the sanitizer when `googleSearch` tool is present (#2077) +- **fix(pollinations):** add `jsonMode: true` flag in the request transformation to enforce correct JSON structure from Pollinations API (#2109) +- **fix(docker):** update Dockerfile to copy `/docs` directory during build ensuring API catalog availability at runtime (#2083) +- **fix(docker):** include OpenAPI spec in runtime image (#2007) +- **fix(providers):** strip OpenAI-specific fields in Kiro translator to prevent 400 errors (#2037) +- **fix(kiro):** normalize tool-use payloads to prevent 400 errors from agents (#2104) +- **fix(kiro):** merge adjacent user history turns after role normalization (#2105) +- **fix(ui):** resolve text contrast issues for zero-config warning banner in light mode (#2050) +- **fix(core):** inject global system prompt correctly into downstream chat completions pipeline (#2080) +- **fix(core):** restore Claude Code adaptive thinking defaults and resolve audio transcription CORS regression +- **fix(routing):** add missing v1beta rewrites to next.config to resolve 404 on Gemini models endpoint (#2102) +- **fix(routing):** fix bare GPT-5.5 routing for Codex-only installations (#2054) +- **fix(routing):** add fuzzy auto-combo routing for `auto/*` model prefix (#2010) - **fix(cache):** optimize cache_control preservation logic and explicitly align tool schema with upstream Claude Code expectations - **fix(db):** preserve legacy SQLite database path on Windows to prevent data loss (#1973) +- **fix(db):** reduce hot-path persistence overhead (#2039) +- **fix(db):** resolve migration conflict by renumbering overlapping migration entries (#2041) - **fix(settings):** resolve model alias persistence double stringification preventing UI updates (#2018) - **fix(routing):** dynamically filter bare model auto-resolution by active provider connections to prevent dead-routing (#2029) - **fix(embeddings):** add Google Gemini embeddings compatibility via OpenAI-compatible endpoint mapping (#2006) +- **fix(sse):** prevent Claude OAuth multi-account correlation via metadata.user_id (#2053) +- **fix(sse):** prevent Claude Code identity cloak overrides and fix fallback resilience (#2053) +- **fix(sse):** classify hour quota errors as QUOTA_EXHAUSTED (#2119) +- **fix(sse):** fix CC-compatible streaming bridge (#2118) +- **fix(antigravity):** sanitize Claude Cloud Code payloads (#2090) +- **fix(antigravity):** add duplex half for streaming bodies +- **fix(antigravity):** align identity protocol and behavior with official AM +- **fix(chatgpt-web):** plumb proxy through to native tls-client (#2022, #2023) +- **fix(codex):** expose native model IDs in catalog (#2012) +- **fix(glm):** add dedicated coding transport (#2087) +- **fix(compression):** support Responses input and expand Spanish compression rules (#2028) +- **fix(catalog):** auto-calculate combo context_length from target model limits (#2030) +- **fix(api):** fix usage analytics and API key identity (#2008, #2092) +- **fix(api-key):** allow Unicode letters in API key name validation (#1996) +- **fix(auth):** allow bootstrap without password (#2048) +- **fix(proxy):** clean up proxy page redundancy and fix 1proxy sync empty body error (#2052) +- **fix(dashboard):** resolve Unknown plan display in Provider Limits +- **fix(usage):** add extensible CURRENCY_SYMBOLS mapping for deepseek currencies +- **fix(runtime):** harden timer handling and model pricing fallback +- **fix(i18n):** complete Simplified Chinese translations (#2115) +- **fix(mitm):** add Linux cert install and skip sudo password when root (#1999) +- **fix(mitm):** prevent stub from loading at runtime via bypass module - **fix:** remove Anthropic-Beta header from non-Anthropic providers to fix identity contamination (#1989) - **fix(cli):** resolve .env loading failure for global npm installations +- **fix(export):** exclude telemetry/usage-history tables from JSON config backups by default to prevent unbounded file growth (#2125) +- **fix:** Follow OpenAI specification, handle throttling in batch and fix UI (#2045) -### 🔒 Security +### Seguridad +- **fix(security):** remediate CodeQL vulnerabilities (ReDoS, cryptographic bias, stack trace exposure, and weak password hashing) (#216, #215, #211, #208, #206, #210) - **fix(security):** remediate regex validation backtracking path in core compression cleanup (#1990) - **fix(core):** harden input handling and stabilization for prompt compression edge cases +### Documentación + +- **docs:** add competitive marketing tables and SEO/AEO optimizations to README (#2091) +- **docs:** refresh providers, model catalogs, and docs for v3.8.0 (#2088) +- **docs:** update Claude MD and update GLM-CN max context to 200k (#2027) +- **docs(env):** add `GITLAB_DUO_OAUTH_CLIENT_ID` to `.env.example` (#2031) + ### 🧹 Chores & Maintenance - **chore(providers):** prune redundant local provider icon assets in favor of `@lobehub/icons` web fonts (#1992) +- **chore(providers):** remove deprecated models (#2033) +- **deps:** bump `fast-uri` from 3.1.0 to 3.1.2 (#2078) +- **deps:** bump `hono` from 4.12.14 to 4.12.18 (#2079) - **ci:** skip SonarCloud scan on main pushes to optimize CI time - **test:** stabilize cooldown abort coverage case in integration testing +### 🏆 v3.8.0 Community Contributors + +Thank you to all **38 community contributors** who made v3.8.0 possible! 🎉 + +| Contributor | PRs | Contributions | +| :--------------------------------------------------------- | :-: | :------------------------------------------------------------ | +| [@oyi77](https://github.com/oyi77) | 7 | #2010, #2014, #2041, #2052, #2061, #2074, #2091, #2094, #2096 | +| [@backryun](https://github.com/backryun) | 4 | #1992, #2033, #2088, #2123 | +| [@dhaern](https://github.com/dhaern) | 4 | #2028, #2039, #2087, #2090 | +| [@Tentoxa](https://github.com/Tentoxa) | 2 | #2011, #2053 | +| [@wauputr4](https://github.com/wauputr4) | 2 | #2009, #2046 | +| [@payne0420](https://github.com/payne0420) | 1 | #2082 | +| [@Tr0sT](https://github.com/Tr0sT) | 1 | #2012 | +| [@AveryanAlex](https://github.com/AveryanAlex) | 1 | #2008 | +| [@nickwizard](https://github.com/nickwizard) | 1 | #1991 | +| [@rodrigogbbr-stack](https://github.com/rodrigogbbr-stack) | 1 | #1996 | +| [@NekoMonci12](https://github.com/NekoMonci12) | 1 | #1999 | +| [@congvc-dev](https://github.com/congvc-dev) | 1 | #2004 | +| [@tatsster](https://github.com/tatsster) | 1 | #2007 | +| [@xssdem](https://github.com/xssdem) | 1 | #2023 | +| [@bypanghu](https://github.com/bypanghu) | 1 | #2027 | +| [@herjarsa](https://github.com/herjarsa) | 1 | #2030 | +| [@wucm667](https://github.com/wucm667) | 1 | #2031 | +| [@hartmark](https://github.com/hartmark) | 1 | #2045 | +| [@ddarkr](https://github.com/ddarkr) | 1 | #2047 | +| [@tces1](https://github.com/tces1) | 1 | #2048 | +| [@guanbear](https://github.com/guanbear) | 1 | #2054 | +| [@Gi99lin](https://github.com/Gi99lin) | 1 | #2055 | +| [@ivan-mezentsev](https://github.com/ivan-mezentsev) | 1 | #2063 | +| [@JxnLexn](https://github.com/JxnLexn) | 1 | #2019 | +| [@yoviarpauzi](https://github.com/yoviarpauzi) | 1 | #2092 | +| [@rafacpti23](https://github.com/rafacpti23) | 1 | #2086 | +| [@gleber](https://github.com/gleber) | 1 | #2103 | +| [@rilham97](https://github.com/rilham97) | 1 | #2104 | +| [@Gioxaa](https://github.com/Gioxaa) | 1 | #2105 | +| [@boa-z](https://github.com/boa-z) | 1 | #2115 | +| [@eleata](https://github.com/eleata) | 1 | #2116 | +| [@rdself](https://github.com/rdself) | 1 | #2118 | +| [@clousky2020](https://github.com/clousky2020) | 1 | #2119 | +| [@abhinavjnu](https://github.com/abhinavjnu) | 1 | #2122 | +| [@HoaPham98](https://github.com/HoaPham98) | 1 | #2089 | +| [@05dunski](https://github.com/05dunski) | 1 | #1978 (cherry-picked) | + ## [3.7.9] — 2026-05-03 ### ✨ New Features @@ -102,7 +220,7 @@ - **chore(provider):** Add reka models list (#1956 — thanks @backryun) - **chore(model):** Update new models, Delete Deprecated models (#1949 — thanks @backryun) -### 📝 Documentation +### Documentación - **docs(compression):** document RTK+Caveman stacked savings ranges @@ -201,7 +319,7 @@ - **feat(db):** auto-restore probe-failed database on startup to prevent data loss after failed upgrades (#1810) - **feat(analytics):** add cost-based usage insights and activity streaks in the analytics dashboard -### 🔒 Security +### Seguridad - **fix(security):** resolve ReDoS vulnerability in Codex executor regex patterns (#1797, #1789) @@ -354,7 +472,7 @@ We identified that **155 community PRs** across the entire project history (from - **feat(proxy):** implement bulk proxy import via pipe-delimited parser with update-or-create (upsert) logic and real-time preview table - **feat(pwa):** add fullscreen installable PWA with manifest, service worker, and cross-platform app icons (#1728) -### 🔒 Security +### Seguridad - **security:** replace insecure `Math.random` with `crypto.getRandomValues` for fallback UUID generation to resolve CodeQL CWE-338 finding (#182) @@ -519,7 +637,7 @@ We identified that **155 community PRs** across the entire project history (from - **fix(transport):** Prevent memory bloat and database exhaustion from large, fragmented streaming responses. Implemented `ByteQueue` in `kiro.ts` for zero-copy binary accumulation, refactored `antigravity.ts` for incremental SSE parsing, and enforced a strict 512KB tiered truncation limit (`MAX_CALL_LOG_ARTIFACT_BYTES`) on stream request logs and call artifacts (#1647). - **chore(ci):** Update build environment dependencies — bump Node to `24.15.0`, `actions/checkout@v6`, `docker/build-push-action@v7`, pin `actions/setup-python` to major tag (#1646 — thanks @backryun). -### 📝 Documentation +### Documentación - **docs(env):** Add `OMNIROUTE_ALLOW_PRIVATE_PROVIDER_URLS` to `.env.example` with documentation for LM Studio and other local provider use cases (#1623). @@ -669,7 +787,7 @@ We identified that **155 community PRs** across the entire project history (from - **test(next):** Align transpile package expectations for the Next.js standalone build. - **test(ci):** Fix CI-only test failures from environment differences — clear `INITIAL_PASSWORD` and `JWT_SECRET` in integration tests, handle `XDG_CONFIG_HOME` for guide-settings tests. -### 📚 Documentation +### Documentación - **docs:** Update the root changelog with all release-branch changes through 2026-04-24, including PRs #1544, #1555, #1551, #1550, #1548, #1547, #1541, #1538, #1536, and #1527. - **docs:** Fix broken README and localized documentation links. (#1536) @@ -811,7 +929,7 @@ We identified that **155 community PRs** across the entire project history (from - **feat(providers):** Expand image provider registry with extended model support including SD3.5, FLUX, and DALL-E 3 HD configurations - **feat(combos):** Add new routing strategies and full i18n support for agent features section across 31 languages -### 🔒 Security +### Seguridad - **security:** Resolve 18 GitHub CodeQL scan alerts including ReDoS, incomplete sanitization, and bad HTML filtering regexp patterns - **fix(auth):** Seal privilege escalation vector by enforcing JWT session checking exclusively on `/api/keys` management endpoints (#1353) @@ -1078,7 +1196,7 @@ We identified that **155 community PRs** across the entire project history (from - **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 - **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 -### 🔒 Security +### Seguridad - **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 - **Auth Guard on Translator Save:** Added `isAuthenticated` guard to `/api/translator/save` for defense-in-depth consistency @@ -1483,7 +1601,7 @@ We identified that **155 community PRs** across the entire project history (from - **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). -### 📚 Documentation +### Documentació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. - **Context Relay Delivery Notes:** Documented the current architecture, runtime flow, and Codex-focused scope in the feature docs, changelog, and agent guidance. @@ -1559,7 +1677,7 @@ We identified that **155 community PRs** across the entire project history (from ## [3.5.3] - 2026-04-07 -### Security +### Seguridad - **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. - **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. @@ -1575,7 +1693,7 @@ We identified that **155 community PRs** across the entire project history (from - **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. -### Documentation +### Documentación - **I18n Engine:** Synchronized and pushed deep Machine Translation updates across all 32 natively-supported languages (682 translation nodes aligned). @@ -1736,7 +1854,7 @@ We identified that **155 community PRs** across the entire project history (from ## [3.4.8] — 2026-04-03 -### Security +### Seguridad - Fully remediated all outstanding Github Advanced Security (CodeQL) findings and Dependabot alerts. - Fixed insecure randomness vulnerabilities by migrating from `Math.random` to `crypto.randomUUID()`. @@ -1748,7 +1866,7 @@ We identified that **155 community PRs** across the entire project history (from ## [3.4.7] — 2026-04-03 -### Features +### Funcionalidades - Added `Cryptography` node to Monitoring and MCP health checks (#798) - Hardened model-catalog route permissions mapping (`/models`) (#781) @@ -1764,7 +1882,7 @@ We identified that **155 community PRs** across the entire project history (from - Fixed MCP standalone module-resolution (`ERR_MODULE_NOT_FOUND`) via `esbuild` (#936) - Fixed NVIDIA NIM routing credential resolution alias mismatch (#931) -### Security +### Seguridad - Added safe strict input boundary protection against raw `shell: true` remote-code execution injections. @@ -2011,7 +2129,7 @@ We identified that **155 community PRs** across the entire project history (from ## [3.4.0] - 2026-03-31 -### 🚀 Features +### Funcionalidades - **Subscription Utilization Analytics:** Added quota snapshot time-series tracking, Provider Utilization and Combo Health tabs with recharts visualizations, and corresponding API endpoints (#847) - **SQLite Backup Control:** New `OMNIROUTE_DISABLE_AUTO_BACKUP` env flag to disable automatic SQLite backups (#846) @@ -2063,7 +2181,7 @@ We identified that **155 community PRs** across the entire project history (from ## [3.3.8] - 2026-03-30 -### 🚀 Features +### Funcionalidades - **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) - **Qoder Integration:** Native integration for Qoder AI natively replacing the legacy iFlow platform mappings (#660) @@ -2889,7 +3007,7 @@ We identified that **155 community PRs** across the entire project history (from - **NaN tokens in Claude Code / client responses (#617):** - `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 -### 🔒 Security +### Seguridad - Updated `yaml` package to fix stack overflow vulnerability (GHSA-48c2-rrv3-qjmp) @@ -3565,7 +3683,7 @@ docker pull diegosouzapw/omniroute:3.0.0 - **SVG fallback**: `ProviderIcon` component updated with 4-tier strategy: Lobehub → PNG → SVG → Generic icon - **Agents fingerprinting**: Synced with CLI tools — added droid, openclaw, copilot, opencode to fingerprint list (14 total) -### 🔒 Security +### Seguridad - **CVE fix**: Resolved dompurify XSS vulnerability (GHSA-v2wj-7wpq-c8vv) via npm overrides forcing `dompurify@^3.3.2` - `npm audit` now reports **0 vulnerabilities** @@ -3928,7 +4046,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **#510** — Windows: MSYS2/Git-Bash paths (`/c/Program Files/...`) are now normalized to `C:\Program Files\...` - **#492** — `omniroute` CLI now detects `mise`/`nvm` when `app/server.js` is missing and shows targeted fix -### 📖 Documentation +### Documentación - **#513** — Docker password reset: `INITIAL_PASSWORD` env var workaround documented - **#520** — pnpm: `pnpm approve-builds better-sqlite3` documented @@ -4025,7 +4143,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **feat(executors/cloudflare-ai)**: New `CloudflareAIExecutor` — dynamic URL construction requires `accountId` in provider credentials - **feat(executors)**: Register `pollinations`, `pol`, `cloudflare-ai`, `cf` executor mappings -### 📝 Documentation +### Documentación - **docs(readme)**: Expanded free combo stack to 11 providers ($0 forever) - **docs(readme)**: Added 4 new free provider sections (LongCat, Pollinations, Cloudflare AI, Scaleway) with model tables @@ -4177,7 +4295,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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). -### Features +### Funcionalidades - **"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. @@ -4205,7 +4323,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Merge PR #494 (MiniMax role fix), fix KIRO MITM dashboard, triage 8 issues. -### Features +### Funcionalidades - **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. - **roleNormalizer**: `normalizeDeveloperRole()` now accepts `preserveDeveloperRole` parameter with tri-state behavior (undefined=keep, true=keep, false=convert). @@ -4261,7 +4379,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Gemini CLI deprecation, VM guide i18n fix, dependabot security fix, provider schema expansion. -### Features +### Funcionalidades - **Gemini CLI Deprecation** (#462): Mark `gemini-cli` provider as deprecated with warning — Google restricts third-party OAuth usage from March 2026 - **Provider Schema** (#462): Expand Zod validation with `deprecated`, `deprecationReason`, `hasFree`, `freeNote`, `authHint`, `apiHint` optional fields @@ -4270,7 +4388,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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) -### Security +### Seguridad - **deps**: Bump `flatted` 3.3.3 → 3.4.2 — fixes CWE-1321 prototype pollution (#484, @dependabot) @@ -4290,7 +4408,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Czech i18n, SSE protocol fix, VM guide translation. -### Features +### Funcionalidades - **Czech Language** (#482): Full Czech (cs) i18n — 22 docs, 2606 UI strings, language switcher updates (@zen0bit) - **VM Deployment Guide**: Translated from Portuguese to English as the source document (@zen0bit) @@ -4309,7 +4427,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: 2 merged PRs, model aliases routing fix, log export, and issue triage. -### Features +### Funcionalidades - **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) @@ -4329,7 +4447,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Five community PRs — streaming call log fixes, Kiro compatibility, cache token analytics, Chinese translation, and configurable tool call IDs. -### ✨ Features +### Funcionalidades - **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) - **feat(providers)**: Per-model configurable 9-char tool call ID normalization (Mistral-style) — only models with the option enabled get truncated IDs (#470) @@ -4359,7 +4477,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Bailian Coding Plan provider with editable base URLs, plus community contributions for Alibaba Cloud and Kimi Coding. -### ✨ Features +### Funcionalidades - **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) - **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) @@ -4374,7 +4492,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Two new community-contributed providers (Alibaba Cloud Coding, Kimi Coding API-key) and Docker pino fix. -### ✨ Features +### Funcionalidades - **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) - **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) @@ -4399,7 +4517,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Codex responses subpath passthrough natively supported, Windows MITM crash fixed, and Combos agent schemas adjusted. -### ✨ Features +### Funcionalidades - **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) @@ -4439,7 +4557,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **fix(budget)**: "Save Limits" no longer returns 422 — `warningThreshold` is now correctly sent as fraction (0–1) instead of percentage (0–100) (#451) - **fix(combos)**: `` internal cache tag is now stripped before forwarding requests to providers, preventing cache session breaks (#454) -### ✨ Features +### Funcionalidades - **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) @@ -4495,7 +4613,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Search Tools dashboard, i18n fixes, Copilot limits, Serper validation fix. -### 🚀 Features +### Funcionalidades - **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) - New route: `/dashboard/search-tools` @@ -4595,7 +4713,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - DB migration: `request_type` column on `call_logs` for non-chat request tracking - Zod validation (`v1SearchSchema`), auth-gated, cost recorded via `recordCost()` -### 🔒 Security +### Seguridad - **deps**: Next.js 16.1.6 → 16.1.7 — fixes 6 CVEs: - **Critical**: CVE-2026-29057 (HTTP request smuggling via http-proxy) @@ -4725,7 +4843,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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**: New `request_detail_logs` table with 500-entry ring-buffer trigger, opt-in via settings toggle -### ✨ Features +### Funcionalidades - **feat(combo)**: System Message Override per Combo (#399 — `system_message` field replaces or injects system prompt before forwarding to provider) - **feat(combo)**: Tool Filter Regex per Combo (#399 — `tool_filter_regex` keeps only tools matching pattern; supports OpenAI + Anthropic formats) @@ -4740,7 +4858,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: SSE improvements, local provider_nodes extensions, proxy registry, Claude passthrough fixes. -### ✨ Features +### Funcionalidades - **feat(health)**: Background health check for local `provider_nodes` with exponential backoff (30s→300s) and `Promise.allSettled` to avoid blocking (#423, @Regis-RCR) - **feat(embeddings)**: Route `/v1/embeddings` to local `provider_nodes` — `buildDynamicEmbeddingProvider()` with hostname validation (#422, @Regis-RCR) @@ -4882,7 +5000,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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 - **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). -### ✨ Features +### Funcionalidades - **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) @@ -4912,7 +5030,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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) - **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) -### ✨ Features +### Funcionalidades - **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) - **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. @@ -4971,7 +5089,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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) - **fix(logs)**: Request log table is now readable in light mode — status badges, token counts, and combo tags use adaptive `dark:` color classes (#378) -### ✨ Features +### Funcionalidades - **feat(kiro)**: Kiro credit tracking added to usage fetcher — queries `getUserCredits` from AWS CodeWhisperer endpoint (#337) @@ -5372,7 +5490,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > **Major release** — Free Stack ecosystem, transcription playground overhaul, 44+ providers, comprehensive free tier documentation, and UI improvements across the board. -### ✨ Features +### Funcionalidades - **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. - **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. @@ -5383,7 +5501,7 @@ OmniRoute now automatically refreshes model lists for connected providers every ## [2.3.16] - 2026-03-13 -### 📖 Documentation +### Documentación - **README: 44+ Providers** — Updated all 3 occurrences of "36+ providers" to "44+" reflecting the actual codebase count (44 providers in providers.ts) - **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. @@ -5393,7 +5511,7 @@ OmniRoute now automatically refreshes model lists for connected providers every ## [2.3.15] - 2026-03-13 -### ✨ Features +### Funcionalidades - **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. - **i18n — autoCombo section**: Added 20 new translation keys for the Auto-Combo dashboard (`title`, `status`, `modePack`, `providerScores`, `factorTierPriority`, etc.) to all 30 language files. diff --git a/docs/i18n/ms/CHANGELOG.md b/docs/i18n/ms/CHANGELOG.md index 8eac0b295b..19807106c2 100644 --- a/docs/i18n/ms/CHANGELOG.md +++ b/docs/i18n/ms/CHANGELOG.md @@ -10,30 +10,148 @@ ### ✨ New Features -- **feat(antigravity):** integrate Antigravity provider with dynamic `maxOutputTokens` calculation (bumping to `thinkingBudget + 1`) and standard Cloud Code envelope payload sanitization (#2055, #2063) +- **feat(antigravity):** integrate Antigravity provider with dynamic `maxOutputTokens` calculation, identity fingerprinting overhaul, and Cloud Code envelope payload sanitization (#2055, #2063) - **feat(gemini-cli):** add custom projectId support for Gemini CLI transport (UI, DB, executor) (#1991) +- **feat(providers):** add KIE media provider support with dynamic polling, text models, and expanded video models catalog +- **feat(providers):** add Z.AI provider support with GLM quota handling and new quota labels +- **feat(providers):** add 9 new free AI providers — LLM7, Lepton, Kluster, UncloseAI, BazaarLink, Completions, Enally, FreeTheAi (#2096) +- **feat(providers):** batch delete provider connections via checkbox multi-select (#2094) +- **feat(cursor):** full OpenAI parity — tool calls, streaming, and session management (#2082) +- **feat(cli):** comprehensive CLI enhancement suite with 20+ new commands including `omniroute providers`, `omniroute combos`, `omniroute doctor` (#2074) +- **feat(cli):** add modular CLI setup and provider management commands (#2046) +- **feat(mcp):** add DeepSeek quota and limit monitoring feature (#2089) +- **feat(circuit-breaker):** classify 429 errors and apply per-kind cooldowns (#2116) +- **feat(multi):** manifest-aware tier routing — W1-W4 complete (#2014) +- **feat(combos):** add reset-aware routing strategy for quota-based providers +- **feat(combo):** add context_length input field to combo edit form (#2047) +- **feat(chat):** dynamic tool limit detection with proactive truncation (#2061) +- **feat(sse):** refresh Claude OAuth wire image to claude-cli/2.1.131 (#2011) +- **feat(github):** add `targetFormat: openai-responses` to all GitHub models (#2122) +- **feat(api):** allow configuration via API calls — open management routes to Bearer keys with manage scope (#2103) +- **feat(api):** update API bridge proxy timeout to 600,000ms (#2019) +- **feat(usage):** add service tier breakdown, codex fast service tier analytics, and account for fast tier +- **feat(chat):** add `STREAM_READINESS_TIMEOUT_MS` and integrate into chat handling +- **feat(combo):** add `fallbackDelayMs` to combo configuration and related settings +- **feat(chat):** enhance error handling for semaphore capacity with fallback logic +- **feat(qdrant):** embedding model discovery (#2086) +- **feat(auth):** per-session sticky routing for Codex (#1887) +- **feat(inworld):** enhance Inworld TTS support (#2123) ### 🐛 Bug Fixes +- **fix(pricing):** make `getPricingForModel` fully case-insensitive to ensure custom prices correctly reflect in new incoming requests cost calculations +- **fix(gemini):** prevent `functionDeclarations` from being dropped by the sanitizer when `googleSearch` tool is present (#2077) +- **fix(pollinations):** add `jsonMode: true` flag in the request transformation to enforce correct JSON structure from Pollinations API (#2109) +- **fix(docker):** update Dockerfile to copy `/docs` directory during build ensuring API catalog availability at runtime (#2083) +- **fix(docker):** include OpenAPI spec in runtime image (#2007) +- **fix(providers):** strip OpenAI-specific fields in Kiro translator to prevent 400 errors (#2037) +- **fix(kiro):** normalize tool-use payloads to prevent 400 errors from agents (#2104) +- **fix(kiro):** merge adjacent user history turns after role normalization (#2105) +- **fix(ui):** resolve text contrast issues for zero-config warning banner in light mode (#2050) +- **fix(core):** inject global system prompt correctly into downstream chat completions pipeline (#2080) +- **fix(core):** restore Claude Code adaptive thinking defaults and resolve audio transcription CORS regression +- **fix(routing):** add missing v1beta rewrites to next.config to resolve 404 on Gemini models endpoint (#2102) +- **fix(routing):** fix bare GPT-5.5 routing for Codex-only installations (#2054) +- **fix(routing):** add fuzzy auto-combo routing for `auto/*` model prefix (#2010) - **fix(cache):** optimize cache_control preservation logic and explicitly align tool schema with upstream Claude Code expectations - **fix(db):** preserve legacy SQLite database path on Windows to prevent data loss (#1973) +- **fix(db):** reduce hot-path persistence overhead (#2039) +- **fix(db):** resolve migration conflict by renumbering overlapping migration entries (#2041) - **fix(settings):** resolve model alias persistence double stringification preventing UI updates (#2018) - **fix(routing):** dynamically filter bare model auto-resolution by active provider connections to prevent dead-routing (#2029) - **fix(embeddings):** add Google Gemini embeddings compatibility via OpenAI-compatible endpoint mapping (#2006) +- **fix(sse):** prevent Claude OAuth multi-account correlation via metadata.user_id (#2053) +- **fix(sse):** prevent Claude Code identity cloak overrides and fix fallback resilience (#2053) +- **fix(sse):** classify hour quota errors as QUOTA_EXHAUSTED (#2119) +- **fix(sse):** fix CC-compatible streaming bridge (#2118) +- **fix(antigravity):** sanitize Claude Cloud Code payloads (#2090) +- **fix(antigravity):** add duplex half for streaming bodies +- **fix(antigravity):** align identity protocol and behavior with official AM +- **fix(chatgpt-web):** plumb proxy through to native tls-client (#2022, #2023) +- **fix(codex):** expose native model IDs in catalog (#2012) +- **fix(glm):** add dedicated coding transport (#2087) +- **fix(compression):** support Responses input and expand Spanish compression rules (#2028) +- **fix(catalog):** auto-calculate combo context_length from target model limits (#2030) +- **fix(api):** fix usage analytics and API key identity (#2008, #2092) +- **fix(api-key):** allow Unicode letters in API key name validation (#1996) +- **fix(auth):** allow bootstrap without password (#2048) +- **fix(proxy):** clean up proxy page redundancy and fix 1proxy sync empty body error (#2052) +- **fix(dashboard):** resolve Unknown plan display in Provider Limits +- **fix(usage):** add extensible CURRENCY_SYMBOLS mapping for deepseek currencies +- **fix(runtime):** harden timer handling and model pricing fallback +- **fix(i18n):** complete Simplified Chinese translations (#2115) +- **fix(mitm):** add Linux cert install and skip sudo password when root (#1999) +- **fix(mitm):** prevent stub from loading at runtime via bypass module - **fix:** remove Anthropic-Beta header from non-Anthropic providers to fix identity contamination (#1989) - **fix(cli):** resolve .env loading failure for global npm installations +- **fix(export):** exclude telemetry/usage-history tables from JSON config backups by default to prevent unbounded file growth (#2125) +- **fix:** Follow OpenAI specification, handle throttling in batch and fix UI (#2045) -### 🔒 Security +### Keselamatan +- **fix(security):** remediate CodeQL vulnerabilities (ReDoS, cryptographic bias, stack trace exposure, and weak password hashing) (#216, #215, #211, #208, #206, #210) - **fix(security):** remediate regex validation backtracking path in core compression cleanup (#1990) - **fix(core):** harden input handling and stabilization for prompt compression edge cases +### Dokumentasi + +- **docs:** add competitive marketing tables and SEO/AEO optimizations to README (#2091) +- **docs:** refresh providers, model catalogs, and docs for v3.8.0 (#2088) +- **docs:** update Claude MD and update GLM-CN max context to 200k (#2027) +- **docs(env):** add `GITLAB_DUO_OAUTH_CLIENT_ID` to `.env.example` (#2031) + ### 🧹 Chores & Maintenance - **chore(providers):** prune redundant local provider icon assets in favor of `@lobehub/icons` web fonts (#1992) +- **chore(providers):** remove deprecated models (#2033) +- **deps:** bump `fast-uri` from 3.1.0 to 3.1.2 (#2078) +- **deps:** bump `hono` from 4.12.14 to 4.12.18 (#2079) - **ci:** skip SonarCloud scan on main pushes to optimize CI time - **test:** stabilize cooldown abort coverage case in integration testing +### 🏆 v3.8.0 Community Contributors + +Thank you to all **38 community contributors** who made v3.8.0 possible! 🎉 + +| Contributor | PRs | Contributions | +| :--------------------------------------------------------- | :-: | :------------------------------------------------------------ | +| [@oyi77](https://github.com/oyi77) | 7 | #2010, #2014, #2041, #2052, #2061, #2074, #2091, #2094, #2096 | +| [@backryun](https://github.com/backryun) | 4 | #1992, #2033, #2088, #2123 | +| [@dhaern](https://github.com/dhaern) | 4 | #2028, #2039, #2087, #2090 | +| [@Tentoxa](https://github.com/Tentoxa) | 2 | #2011, #2053 | +| [@wauputr4](https://github.com/wauputr4) | 2 | #2009, #2046 | +| [@payne0420](https://github.com/payne0420) | 1 | #2082 | +| [@Tr0sT](https://github.com/Tr0sT) | 1 | #2012 | +| [@AveryanAlex](https://github.com/AveryanAlex) | 1 | #2008 | +| [@nickwizard](https://github.com/nickwizard) | 1 | #1991 | +| [@rodrigogbbr-stack](https://github.com/rodrigogbbr-stack) | 1 | #1996 | +| [@NekoMonci12](https://github.com/NekoMonci12) | 1 | #1999 | +| [@congvc-dev](https://github.com/congvc-dev) | 1 | #2004 | +| [@tatsster](https://github.com/tatsster) | 1 | #2007 | +| [@xssdem](https://github.com/xssdem) | 1 | #2023 | +| [@bypanghu](https://github.com/bypanghu) | 1 | #2027 | +| [@herjarsa](https://github.com/herjarsa) | 1 | #2030 | +| [@wucm667](https://github.com/wucm667) | 1 | #2031 | +| [@hartmark](https://github.com/hartmark) | 1 | #2045 | +| [@ddarkr](https://github.com/ddarkr) | 1 | #2047 | +| [@tces1](https://github.com/tces1) | 1 | #2048 | +| [@guanbear](https://github.com/guanbear) | 1 | #2054 | +| [@Gi99lin](https://github.com/Gi99lin) | 1 | #2055 | +| [@ivan-mezentsev](https://github.com/ivan-mezentsev) | 1 | #2063 | +| [@JxnLexn](https://github.com/JxnLexn) | 1 | #2019 | +| [@yoviarpauzi](https://github.com/yoviarpauzi) | 1 | #2092 | +| [@rafacpti23](https://github.com/rafacpti23) | 1 | #2086 | +| [@gleber](https://github.com/gleber) | 1 | #2103 | +| [@rilham97](https://github.com/rilham97) | 1 | #2104 | +| [@Gioxaa](https://github.com/Gioxaa) | 1 | #2105 | +| [@boa-z](https://github.com/boa-z) | 1 | #2115 | +| [@eleata](https://github.com/eleata) | 1 | #2116 | +| [@rdself](https://github.com/rdself) | 1 | #2118 | +| [@clousky2020](https://github.com/clousky2020) | 1 | #2119 | +| [@abhinavjnu](https://github.com/abhinavjnu) | 1 | #2122 | +| [@HoaPham98](https://github.com/HoaPham98) | 1 | #2089 | +| [@05dunski](https://github.com/05dunski) | 1 | #1978 (cherry-picked) | + ## [3.7.9] — 2026-05-03 ### ✨ New Features @@ -102,7 +220,7 @@ - **chore(provider):** Add reka models list (#1956 — thanks @backryun) - **chore(model):** Update new models, Delete Deprecated models (#1949 — thanks @backryun) -### 📝 Documentation +### Dokumentasi - **docs(compression):** document RTK+Caveman stacked savings ranges @@ -201,7 +319,7 @@ - **feat(db):** auto-restore probe-failed database on startup to prevent data loss after failed upgrades (#1810) - **feat(analytics):** add cost-based usage insights and activity streaks in the analytics dashboard -### 🔒 Security +### Keselamatan - **fix(security):** resolve ReDoS vulnerability in Codex executor regex patterns (#1797, #1789) @@ -354,7 +472,7 @@ We identified that **155 community PRs** across the entire project history (from - **feat(proxy):** implement bulk proxy import via pipe-delimited parser with update-or-create (upsert) logic and real-time preview table - **feat(pwa):** add fullscreen installable PWA with manifest, service worker, and cross-platform app icons (#1728) -### 🔒 Security +### Keselamatan - **security:** replace insecure `Math.random` with `crypto.getRandomValues` for fallback UUID generation to resolve CodeQL CWE-338 finding (#182) @@ -519,7 +637,7 @@ We identified that **155 community PRs** across the entire project history (from - **fix(transport):** Prevent memory bloat and database exhaustion from large, fragmented streaming responses. Implemented `ByteQueue` in `kiro.ts` for zero-copy binary accumulation, refactored `antigravity.ts` for incremental SSE parsing, and enforced a strict 512KB tiered truncation limit (`MAX_CALL_LOG_ARTIFACT_BYTES`) on stream request logs and call artifacts (#1647). - **chore(ci):** Update build environment dependencies — bump Node to `24.15.0`, `actions/checkout@v6`, `docker/build-push-action@v7`, pin `actions/setup-python` to major tag (#1646 — thanks @backryun). -### 📝 Documentation +### Dokumentasi - **docs(env):** Add `OMNIROUTE_ALLOW_PRIVATE_PROVIDER_URLS` to `.env.example` with documentation for LM Studio and other local provider use cases (#1623). @@ -669,7 +787,7 @@ We identified that **155 community PRs** across the entire project history (from - **test(next):** Align transpile package expectations for the Next.js standalone build. - **test(ci):** Fix CI-only test failures from environment differences — clear `INITIAL_PASSWORD` and `JWT_SECRET` in integration tests, handle `XDG_CONFIG_HOME` for guide-settings tests. -### 📚 Documentation +### Dokumentasi - **docs:** Update the root changelog with all release-branch changes through 2026-04-24, including PRs #1544, #1555, #1551, #1550, #1548, #1547, #1541, #1538, #1536, and #1527. - **docs:** Fix broken README and localized documentation links. (#1536) @@ -811,7 +929,7 @@ We identified that **155 community PRs** across the entire project history (from - **feat(providers):** Expand image provider registry with extended model support including SD3.5, FLUX, and DALL-E 3 HD configurations - **feat(combos):** Add new routing strategies and full i18n support for agent features section across 31 languages -### 🔒 Security +### Keselamatan - **security:** Resolve 18 GitHub CodeQL scan alerts including ReDoS, incomplete sanitization, and bad HTML filtering regexp patterns - **fix(auth):** Seal privilege escalation vector by enforcing JWT session checking exclusively on `/api/keys` management endpoints (#1353) @@ -1078,7 +1196,7 @@ We identified that **155 community PRs** across the entire project history (from - **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 - **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 -### 🔒 Security +### Keselamatan - **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 - **Auth Guard on Translator Save:** Added `isAuthenticated` guard to `/api/translator/save` for defense-in-depth consistency @@ -1483,7 +1601,7 @@ We identified that **155 community PRs** across the entire project history (from - **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). -### 📚 Documentation +### Dokumentasi - **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. - **Context Relay Delivery Notes:** Documented the current architecture, runtime flow, and Codex-focused scope in the feature docs, changelog, and agent guidance. @@ -1559,7 +1677,7 @@ We identified that **155 community PRs** across the entire project history (from ## [3.5.3] - 2026-04-07 -### Security +### Keselamatan - **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. - **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. @@ -1575,7 +1693,7 @@ We identified that **155 community PRs** across the entire project history (from - **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. -### Documentation +### Dokumentasi - **I18n Engine:** Synchronized and pushed deep Machine Translation updates across all 32 natively-supported languages (682 translation nodes aligned). @@ -1736,7 +1854,7 @@ We identified that **155 community PRs** across the entire project history (from ## [3.4.8] — 2026-04-03 -### Security +### Keselamatan - Fully remediated all outstanding Github Advanced Security (CodeQL) findings and Dependabot alerts. - Fixed insecure randomness vulnerabilities by migrating from `Math.random` to `crypto.randomUUID()`. @@ -1748,7 +1866,7 @@ We identified that **155 community PRs** across the entire project history (from ## [3.4.7] — 2026-04-03 -### Features +### Ciri-ciri - Added `Cryptography` node to Monitoring and MCP health checks (#798) - Hardened model-catalog route permissions mapping (`/models`) (#781) @@ -1764,7 +1882,7 @@ We identified that **155 community PRs** across the entire project history (from - Fixed MCP standalone module-resolution (`ERR_MODULE_NOT_FOUND`) via `esbuild` (#936) - Fixed NVIDIA NIM routing credential resolution alias mismatch (#931) -### Security +### Keselamatan - Added safe strict input boundary protection against raw `shell: true` remote-code execution injections. @@ -2011,7 +2129,7 @@ We identified that **155 community PRs** across the entire project history (from ## [3.4.0] - 2026-03-31 -### 🚀 Features +### Ciri-ciri - **Subscription Utilization Analytics:** Added quota snapshot time-series tracking, Provider Utilization and Combo Health tabs with recharts visualizations, and corresponding API endpoints (#847) - **SQLite Backup Control:** New `OMNIROUTE_DISABLE_AUTO_BACKUP` env flag to disable automatic SQLite backups (#846) @@ -2063,7 +2181,7 @@ We identified that **155 community PRs** across the entire project history (from ## [3.3.8] - 2026-03-30 -### 🚀 Features +### Ciri-ciri - **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) - **Qoder Integration:** Native integration for Qoder AI natively replacing the legacy iFlow platform mappings (#660) @@ -2889,7 +3007,7 @@ We identified that **155 community PRs** across the entire project history (from - **NaN tokens in Claude Code / client responses (#617):** - `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 -### 🔒 Security +### Keselamatan - Updated `yaml` package to fix stack overflow vulnerability (GHSA-48c2-rrv3-qjmp) @@ -3565,7 +3683,7 @@ docker pull diegosouzapw/omniroute:3.0.0 - **SVG fallback**: `ProviderIcon` component updated with 4-tier strategy: Lobehub → PNG → SVG → Generic icon - **Agents fingerprinting**: Synced with CLI tools — added droid, openclaw, copilot, opencode to fingerprint list (14 total) -### 🔒 Security +### Keselamatan - **CVE fix**: Resolved dompurify XSS vulnerability (GHSA-v2wj-7wpq-c8vv) via npm overrides forcing `dompurify@^3.3.2` - `npm audit` now reports **0 vulnerabilities** @@ -3928,7 +4046,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **#510** — Windows: MSYS2/Git-Bash paths (`/c/Program Files/...`) are now normalized to `C:\Program Files\...` - **#492** — `omniroute` CLI now detects `mise`/`nvm` when `app/server.js` is missing and shows targeted fix -### 📖 Documentation +### Dokumentasi - **#513** — Docker password reset: `INITIAL_PASSWORD` env var workaround documented - **#520** — pnpm: `pnpm approve-builds better-sqlite3` documented @@ -4025,7 +4143,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **feat(executors/cloudflare-ai)**: New `CloudflareAIExecutor` — dynamic URL construction requires `accountId` in provider credentials - **feat(executors)**: Register `pollinations`, `pol`, `cloudflare-ai`, `cf` executor mappings -### 📝 Documentation +### Dokumentasi - **docs(readme)**: Expanded free combo stack to 11 providers ($0 forever) - **docs(readme)**: Added 4 new free provider sections (LongCat, Pollinations, Cloudflare AI, Scaleway) with model tables @@ -4177,7 +4295,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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). -### Features +### Ciri-ciri - **"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. @@ -4205,7 +4323,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Merge PR #494 (MiniMax role fix), fix KIRO MITM dashboard, triage 8 issues. -### Features +### Ciri-ciri - **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. - **roleNormalizer**: `normalizeDeveloperRole()` now accepts `preserveDeveloperRole` parameter with tri-state behavior (undefined=keep, true=keep, false=convert). @@ -4261,7 +4379,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Gemini CLI deprecation, VM guide i18n fix, dependabot security fix, provider schema expansion. -### Features +### Ciri-ciri - **Gemini CLI Deprecation** (#462): Mark `gemini-cli` provider as deprecated with warning — Google restricts third-party OAuth usage from March 2026 - **Provider Schema** (#462): Expand Zod validation with `deprecated`, `deprecationReason`, `hasFree`, `freeNote`, `authHint`, `apiHint` optional fields @@ -4270,7 +4388,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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) -### Security +### Keselamatan - **deps**: Bump `flatted` 3.3.3 → 3.4.2 — fixes CWE-1321 prototype pollution (#484, @dependabot) @@ -4290,7 +4408,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Czech i18n, SSE protocol fix, VM guide translation. -### Features +### Ciri-ciri - **Czech Language** (#482): Full Czech (cs) i18n — 22 docs, 2606 UI strings, language switcher updates (@zen0bit) - **VM Deployment Guide**: Translated from Portuguese to English as the source document (@zen0bit) @@ -4309,7 +4427,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: 2 merged PRs, model aliases routing fix, log export, and issue triage. -### Features +### Ciri-ciri - **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) @@ -4329,7 +4447,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Five community PRs — streaming call log fixes, Kiro compatibility, cache token analytics, Chinese translation, and configurable tool call IDs. -### ✨ Features +### Ciri-ciri - **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) - **feat(providers)**: Per-model configurable 9-char tool call ID normalization (Mistral-style) — only models with the option enabled get truncated IDs (#470) @@ -4359,7 +4477,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Bailian Coding Plan provider with editable base URLs, plus community contributions for Alibaba Cloud and Kimi Coding. -### ✨ Features +### Ciri-ciri - **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) - **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) @@ -4374,7 +4492,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Two new community-contributed providers (Alibaba Cloud Coding, Kimi Coding API-key) and Docker pino fix. -### ✨ Features +### Ciri-ciri - **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) - **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) @@ -4399,7 +4517,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Codex responses subpath passthrough natively supported, Windows MITM crash fixed, and Combos agent schemas adjusted. -### ✨ Features +### Ciri-ciri - **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) @@ -4439,7 +4557,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **fix(budget)**: "Save Limits" no longer returns 422 — `warningThreshold` is now correctly sent as fraction (0–1) instead of percentage (0–100) (#451) - **fix(combos)**: `` internal cache tag is now stripped before forwarding requests to providers, preventing cache session breaks (#454) -### ✨ Features +### Ciri-ciri - **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) @@ -4495,7 +4613,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Search Tools dashboard, i18n fixes, Copilot limits, Serper validation fix. -### 🚀 Features +### Ciri-ciri - **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) - New route: `/dashboard/search-tools` @@ -4595,7 +4713,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - DB migration: `request_type` column on `call_logs` for non-chat request tracking - Zod validation (`v1SearchSchema`), auth-gated, cost recorded via `recordCost()` -### 🔒 Security +### Keselamatan - **deps**: Next.js 16.1.6 → 16.1.7 — fixes 6 CVEs: - **Critical**: CVE-2026-29057 (HTTP request smuggling via http-proxy) @@ -4725,7 +4843,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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**: New `request_detail_logs` table with 500-entry ring-buffer trigger, opt-in via settings toggle -### ✨ Features +### Ciri-ciri - **feat(combo)**: System Message Override per Combo (#399 — `system_message` field replaces or injects system prompt before forwarding to provider) - **feat(combo)**: Tool Filter Regex per Combo (#399 — `tool_filter_regex` keeps only tools matching pattern; supports OpenAI + Anthropic formats) @@ -4740,7 +4858,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: SSE improvements, local provider_nodes extensions, proxy registry, Claude passthrough fixes. -### ✨ Features +### Ciri-ciri - **feat(health)**: Background health check for local `provider_nodes` with exponential backoff (30s→300s) and `Promise.allSettled` to avoid blocking (#423, @Regis-RCR) - **feat(embeddings)**: Route `/v1/embeddings` to local `provider_nodes` — `buildDynamicEmbeddingProvider()` with hostname validation (#422, @Regis-RCR) @@ -4882,7 +5000,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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 - **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). -### ✨ Features +### Ciri-ciri - **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) @@ -4912,7 +5030,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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) - **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) -### ✨ Features +### Ciri-ciri - **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) - **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. @@ -4971,7 +5089,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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) - **fix(logs)**: Request log table is now readable in light mode — status badges, token counts, and combo tags use adaptive `dark:` color classes (#378) -### ✨ Features +### Ciri-ciri - **feat(kiro)**: Kiro credit tracking added to usage fetcher — queries `getUserCredits` from AWS CodeWhisperer endpoint (#337) @@ -5372,7 +5490,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > **Major release** — Free Stack ecosystem, transcription playground overhaul, 44+ providers, comprehensive free tier documentation, and UI improvements across the board. -### ✨ Features +### Ciri-ciri - **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. - **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. @@ -5383,7 +5501,7 @@ OmniRoute now automatically refreshes model lists for connected providers every ## [2.3.16] - 2026-03-13 -### 📖 Documentation +### Dokumentasi - **README: 44+ Providers** — Updated all 3 occurrences of "36+ providers" to "44+" reflecting the actual codebase count (44 providers in providers.ts) - **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. @@ -5393,7 +5511,7 @@ OmniRoute now automatically refreshes model lists for connected providers every ## [2.3.15] - 2026-03-13 -### ✨ Features +### Ciri-ciri - **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. - **i18n — autoCombo section**: Added 20 new translation keys for the Auto-Combo dashboard (`title`, `status`, `modePack`, `providerScores`, `factorTierPriority`, etc.) to all 30 language files. diff --git a/docs/i18n/nl/CHANGELOG.md b/docs/i18n/nl/CHANGELOG.md index a8aabfc653..b7d1d9ddb9 100644 --- a/docs/i18n/nl/CHANGELOG.md +++ b/docs/i18n/nl/CHANGELOG.md @@ -10,30 +10,148 @@ ### ✨ New Features -- **feat(antigravity):** integrate Antigravity provider with dynamic `maxOutputTokens` calculation (bumping to `thinkingBudget + 1`) and standard Cloud Code envelope payload sanitization (#2055, #2063) +- **feat(antigravity):** integrate Antigravity provider with dynamic `maxOutputTokens` calculation, identity fingerprinting overhaul, and Cloud Code envelope payload sanitization (#2055, #2063) - **feat(gemini-cli):** add custom projectId support for Gemini CLI transport (UI, DB, executor) (#1991) +- **feat(providers):** add KIE media provider support with dynamic polling, text models, and expanded video models catalog +- **feat(providers):** add Z.AI provider support with GLM quota handling and new quota labels +- **feat(providers):** add 9 new free AI providers — LLM7, Lepton, Kluster, UncloseAI, BazaarLink, Completions, Enally, FreeTheAi (#2096) +- **feat(providers):** batch delete provider connections via checkbox multi-select (#2094) +- **feat(cursor):** full OpenAI parity — tool calls, streaming, and session management (#2082) +- **feat(cli):** comprehensive CLI enhancement suite with 20+ new commands including `omniroute providers`, `omniroute combos`, `omniroute doctor` (#2074) +- **feat(cli):** add modular CLI setup and provider management commands (#2046) +- **feat(mcp):** add DeepSeek quota and limit monitoring feature (#2089) +- **feat(circuit-breaker):** classify 429 errors and apply per-kind cooldowns (#2116) +- **feat(multi):** manifest-aware tier routing — W1-W4 complete (#2014) +- **feat(combos):** add reset-aware routing strategy for quota-based providers +- **feat(combo):** add context_length input field to combo edit form (#2047) +- **feat(chat):** dynamic tool limit detection with proactive truncation (#2061) +- **feat(sse):** refresh Claude OAuth wire image to claude-cli/2.1.131 (#2011) +- **feat(github):** add `targetFormat: openai-responses` to all GitHub models (#2122) +- **feat(api):** allow configuration via API calls — open management routes to Bearer keys with manage scope (#2103) +- **feat(api):** update API bridge proxy timeout to 600,000ms (#2019) +- **feat(usage):** add service tier breakdown, codex fast service tier analytics, and account for fast tier +- **feat(chat):** add `STREAM_READINESS_TIMEOUT_MS` and integrate into chat handling +- **feat(combo):** add `fallbackDelayMs` to combo configuration and related settings +- **feat(chat):** enhance error handling for semaphore capacity with fallback logic +- **feat(qdrant):** embedding model discovery (#2086) +- **feat(auth):** per-session sticky routing for Codex (#1887) +- **feat(inworld):** enhance Inworld TTS support (#2123) ### 🐛 Bug Fixes +- **fix(pricing):** make `getPricingForModel` fully case-insensitive to ensure custom prices correctly reflect in new incoming requests cost calculations +- **fix(gemini):** prevent `functionDeclarations` from being dropped by the sanitizer when `googleSearch` tool is present (#2077) +- **fix(pollinations):** add `jsonMode: true` flag in the request transformation to enforce correct JSON structure from Pollinations API (#2109) +- **fix(docker):** update Dockerfile to copy `/docs` directory during build ensuring API catalog availability at runtime (#2083) +- **fix(docker):** include OpenAPI spec in runtime image (#2007) +- **fix(providers):** strip OpenAI-specific fields in Kiro translator to prevent 400 errors (#2037) +- **fix(kiro):** normalize tool-use payloads to prevent 400 errors from agents (#2104) +- **fix(kiro):** merge adjacent user history turns after role normalization (#2105) +- **fix(ui):** resolve text contrast issues for zero-config warning banner in light mode (#2050) +- **fix(core):** inject global system prompt correctly into downstream chat completions pipeline (#2080) +- **fix(core):** restore Claude Code adaptive thinking defaults and resolve audio transcription CORS regression +- **fix(routing):** add missing v1beta rewrites to next.config to resolve 404 on Gemini models endpoint (#2102) +- **fix(routing):** fix bare GPT-5.5 routing for Codex-only installations (#2054) +- **fix(routing):** add fuzzy auto-combo routing for `auto/*` model prefix (#2010) - **fix(cache):** optimize cache_control preservation logic and explicitly align tool schema with upstream Claude Code expectations - **fix(db):** preserve legacy SQLite database path on Windows to prevent data loss (#1973) +- **fix(db):** reduce hot-path persistence overhead (#2039) +- **fix(db):** resolve migration conflict by renumbering overlapping migration entries (#2041) - **fix(settings):** resolve model alias persistence double stringification preventing UI updates (#2018) - **fix(routing):** dynamically filter bare model auto-resolution by active provider connections to prevent dead-routing (#2029) - **fix(embeddings):** add Google Gemini embeddings compatibility via OpenAI-compatible endpoint mapping (#2006) +- **fix(sse):** prevent Claude OAuth multi-account correlation via metadata.user_id (#2053) +- **fix(sse):** prevent Claude Code identity cloak overrides and fix fallback resilience (#2053) +- **fix(sse):** classify hour quota errors as QUOTA_EXHAUSTED (#2119) +- **fix(sse):** fix CC-compatible streaming bridge (#2118) +- **fix(antigravity):** sanitize Claude Cloud Code payloads (#2090) +- **fix(antigravity):** add duplex half for streaming bodies +- **fix(antigravity):** align identity protocol and behavior with official AM +- **fix(chatgpt-web):** plumb proxy through to native tls-client (#2022, #2023) +- **fix(codex):** expose native model IDs in catalog (#2012) +- **fix(glm):** add dedicated coding transport (#2087) +- **fix(compression):** support Responses input and expand Spanish compression rules (#2028) +- **fix(catalog):** auto-calculate combo context_length from target model limits (#2030) +- **fix(api):** fix usage analytics and API key identity (#2008, #2092) +- **fix(api-key):** allow Unicode letters in API key name validation (#1996) +- **fix(auth):** allow bootstrap without password (#2048) +- **fix(proxy):** clean up proxy page redundancy and fix 1proxy sync empty body error (#2052) +- **fix(dashboard):** resolve Unknown plan display in Provider Limits +- **fix(usage):** add extensible CURRENCY_SYMBOLS mapping for deepseek currencies +- **fix(runtime):** harden timer handling and model pricing fallback +- **fix(i18n):** complete Simplified Chinese translations (#2115) +- **fix(mitm):** add Linux cert install and skip sudo password when root (#1999) +- **fix(mitm):** prevent stub from loading at runtime via bypass module - **fix:** remove Anthropic-Beta header from non-Anthropic providers to fix identity contamination (#1989) - **fix(cli):** resolve .env loading failure for global npm installations +- **fix(export):** exclude telemetry/usage-history tables from JSON config backups by default to prevent unbounded file growth (#2125) +- **fix:** Follow OpenAI specification, handle throttling in batch and fix UI (#2045) -### 🔒 Security +### Beveiliging +- **fix(security):** remediate CodeQL vulnerabilities (ReDoS, cryptographic bias, stack trace exposure, and weak password hashing) (#216, #215, #211, #208, #206, #210) - **fix(security):** remediate regex validation backtracking path in core compression cleanup (#1990) - **fix(core):** harden input handling and stabilization for prompt compression edge cases +### Documentatie + +- **docs:** add competitive marketing tables and SEO/AEO optimizations to README (#2091) +- **docs:** refresh providers, model catalogs, and docs for v3.8.0 (#2088) +- **docs:** update Claude MD and update GLM-CN max context to 200k (#2027) +- **docs(env):** add `GITLAB_DUO_OAUTH_CLIENT_ID` to `.env.example` (#2031) + ### 🧹 Chores & Maintenance - **chore(providers):** prune redundant local provider icon assets in favor of `@lobehub/icons` web fonts (#1992) +- **chore(providers):** remove deprecated models (#2033) +- **deps:** bump `fast-uri` from 3.1.0 to 3.1.2 (#2078) +- **deps:** bump `hono` from 4.12.14 to 4.12.18 (#2079) - **ci:** skip SonarCloud scan on main pushes to optimize CI time - **test:** stabilize cooldown abort coverage case in integration testing +### 🏆 v3.8.0 Community Contributors + +Thank you to all **38 community contributors** who made v3.8.0 possible! 🎉 + +| Contributor | PRs | Contributions | +| :--------------------------------------------------------- | :-: | :------------------------------------------------------------ | +| [@oyi77](https://github.com/oyi77) | 7 | #2010, #2014, #2041, #2052, #2061, #2074, #2091, #2094, #2096 | +| [@backryun](https://github.com/backryun) | 4 | #1992, #2033, #2088, #2123 | +| [@dhaern](https://github.com/dhaern) | 4 | #2028, #2039, #2087, #2090 | +| [@Tentoxa](https://github.com/Tentoxa) | 2 | #2011, #2053 | +| [@wauputr4](https://github.com/wauputr4) | 2 | #2009, #2046 | +| [@payne0420](https://github.com/payne0420) | 1 | #2082 | +| [@Tr0sT](https://github.com/Tr0sT) | 1 | #2012 | +| [@AveryanAlex](https://github.com/AveryanAlex) | 1 | #2008 | +| [@nickwizard](https://github.com/nickwizard) | 1 | #1991 | +| [@rodrigogbbr-stack](https://github.com/rodrigogbbr-stack) | 1 | #1996 | +| [@NekoMonci12](https://github.com/NekoMonci12) | 1 | #1999 | +| [@congvc-dev](https://github.com/congvc-dev) | 1 | #2004 | +| [@tatsster](https://github.com/tatsster) | 1 | #2007 | +| [@xssdem](https://github.com/xssdem) | 1 | #2023 | +| [@bypanghu](https://github.com/bypanghu) | 1 | #2027 | +| [@herjarsa](https://github.com/herjarsa) | 1 | #2030 | +| [@wucm667](https://github.com/wucm667) | 1 | #2031 | +| [@hartmark](https://github.com/hartmark) | 1 | #2045 | +| [@ddarkr](https://github.com/ddarkr) | 1 | #2047 | +| [@tces1](https://github.com/tces1) | 1 | #2048 | +| [@guanbear](https://github.com/guanbear) | 1 | #2054 | +| [@Gi99lin](https://github.com/Gi99lin) | 1 | #2055 | +| [@ivan-mezentsev](https://github.com/ivan-mezentsev) | 1 | #2063 | +| [@JxnLexn](https://github.com/JxnLexn) | 1 | #2019 | +| [@yoviarpauzi](https://github.com/yoviarpauzi) | 1 | #2092 | +| [@rafacpti23](https://github.com/rafacpti23) | 1 | #2086 | +| [@gleber](https://github.com/gleber) | 1 | #2103 | +| [@rilham97](https://github.com/rilham97) | 1 | #2104 | +| [@Gioxaa](https://github.com/Gioxaa) | 1 | #2105 | +| [@boa-z](https://github.com/boa-z) | 1 | #2115 | +| [@eleata](https://github.com/eleata) | 1 | #2116 | +| [@rdself](https://github.com/rdself) | 1 | #2118 | +| [@clousky2020](https://github.com/clousky2020) | 1 | #2119 | +| [@abhinavjnu](https://github.com/abhinavjnu) | 1 | #2122 | +| [@HoaPham98](https://github.com/HoaPham98) | 1 | #2089 | +| [@05dunski](https://github.com/05dunski) | 1 | #1978 (cherry-picked) | + ## [3.7.9] — 2026-05-03 ### ✨ New Features @@ -102,7 +220,7 @@ - **chore(provider):** Add reka models list (#1956 — thanks @backryun) - **chore(model):** Update new models, Delete Deprecated models (#1949 — thanks @backryun) -### 📝 Documentation +### Documentatie - **docs(compression):** document RTK+Caveman stacked savings ranges @@ -201,7 +319,7 @@ - **feat(db):** auto-restore probe-failed database on startup to prevent data loss after failed upgrades (#1810) - **feat(analytics):** add cost-based usage insights and activity streaks in the analytics dashboard -### 🔒 Security +### Beveiliging - **fix(security):** resolve ReDoS vulnerability in Codex executor regex patterns (#1797, #1789) @@ -354,7 +472,7 @@ We identified that **155 community PRs** across the entire project history (from - **feat(proxy):** implement bulk proxy import via pipe-delimited parser with update-or-create (upsert) logic and real-time preview table - **feat(pwa):** add fullscreen installable PWA with manifest, service worker, and cross-platform app icons (#1728) -### 🔒 Security +### Beveiliging - **security:** replace insecure `Math.random` with `crypto.getRandomValues` for fallback UUID generation to resolve CodeQL CWE-338 finding (#182) @@ -519,7 +637,7 @@ We identified that **155 community PRs** across the entire project history (from - **fix(transport):** Prevent memory bloat and database exhaustion from large, fragmented streaming responses. Implemented `ByteQueue` in `kiro.ts` for zero-copy binary accumulation, refactored `antigravity.ts` for incremental SSE parsing, and enforced a strict 512KB tiered truncation limit (`MAX_CALL_LOG_ARTIFACT_BYTES`) on stream request logs and call artifacts (#1647). - **chore(ci):** Update build environment dependencies — bump Node to `24.15.0`, `actions/checkout@v6`, `docker/build-push-action@v7`, pin `actions/setup-python` to major tag (#1646 — thanks @backryun). -### 📝 Documentation +### Documentatie - **docs(env):** Add `OMNIROUTE_ALLOW_PRIVATE_PROVIDER_URLS` to `.env.example` with documentation for LM Studio and other local provider use cases (#1623). @@ -669,7 +787,7 @@ We identified that **155 community PRs** across the entire project history (from - **test(next):** Align transpile package expectations for the Next.js standalone build. - **test(ci):** Fix CI-only test failures from environment differences — clear `INITIAL_PASSWORD` and `JWT_SECRET` in integration tests, handle `XDG_CONFIG_HOME` for guide-settings tests. -### 📚 Documentation +### Documentatie - **docs:** Update the root changelog with all release-branch changes through 2026-04-24, including PRs #1544, #1555, #1551, #1550, #1548, #1547, #1541, #1538, #1536, and #1527. - **docs:** Fix broken README and localized documentation links. (#1536) @@ -811,7 +929,7 @@ We identified that **155 community PRs** across the entire project history (from - **feat(providers):** Expand image provider registry with extended model support including SD3.5, FLUX, and DALL-E 3 HD configurations - **feat(combos):** Add new routing strategies and full i18n support for agent features section across 31 languages -### 🔒 Security +### Beveiliging - **security:** Resolve 18 GitHub CodeQL scan alerts including ReDoS, incomplete sanitization, and bad HTML filtering regexp patterns - **fix(auth):** Seal privilege escalation vector by enforcing JWT session checking exclusively on `/api/keys` management endpoints (#1353) @@ -1078,7 +1196,7 @@ We identified that **155 community PRs** across the entire project history (from - **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 - **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 -### 🔒 Security +### Beveiliging - **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 - **Auth Guard on Translator Save:** Added `isAuthenticated` guard to `/api/translator/save` for defense-in-depth consistency @@ -1483,7 +1601,7 @@ We identified that **155 community PRs** across the entire project history (from - **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). -### 📚 Documentation +### Documentatie - **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. - **Context Relay Delivery Notes:** Documented the current architecture, runtime flow, and Codex-focused scope in the feature docs, changelog, and agent guidance. @@ -1559,7 +1677,7 @@ We identified that **155 community PRs** across the entire project history (from ## [3.5.3] - 2026-04-07 -### Security +### Beveiliging - **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. - **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. @@ -1575,7 +1693,7 @@ We identified that **155 community PRs** across the entire project history (from - **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. -### Documentation +### Documentatie - **I18n Engine:** Synchronized and pushed deep Machine Translation updates across all 32 natively-supported languages (682 translation nodes aligned). @@ -1736,7 +1854,7 @@ We identified that **155 community PRs** across the entire project history (from ## [3.4.8] — 2026-04-03 -### Security +### Beveiliging - Fully remediated all outstanding Github Advanced Security (CodeQL) findings and Dependabot alerts. - Fixed insecure randomness vulnerabilities by migrating from `Math.random` to `crypto.randomUUID()`. @@ -1748,7 +1866,7 @@ We identified that **155 community PRs** across the entire project history (from ## [3.4.7] — 2026-04-03 -### Features +### Functies - Added `Cryptography` node to Monitoring and MCP health checks (#798) - Hardened model-catalog route permissions mapping (`/models`) (#781) @@ -1764,7 +1882,7 @@ We identified that **155 community PRs** across the entire project history (from - Fixed MCP standalone module-resolution (`ERR_MODULE_NOT_FOUND`) via `esbuild` (#936) - Fixed NVIDIA NIM routing credential resolution alias mismatch (#931) -### Security +### Beveiliging - Added safe strict input boundary protection against raw `shell: true` remote-code execution injections. @@ -2011,7 +2129,7 @@ We identified that **155 community PRs** across the entire project history (from ## [3.4.0] - 2026-03-31 -### 🚀 Features +### Functies - **Subscription Utilization Analytics:** Added quota snapshot time-series tracking, Provider Utilization and Combo Health tabs with recharts visualizations, and corresponding API endpoints (#847) - **SQLite Backup Control:** New `OMNIROUTE_DISABLE_AUTO_BACKUP` env flag to disable automatic SQLite backups (#846) @@ -2063,7 +2181,7 @@ We identified that **155 community PRs** across the entire project history (from ## [3.3.8] - 2026-03-30 -### 🚀 Features +### Functies - **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) - **Qoder Integration:** Native integration for Qoder AI natively replacing the legacy iFlow platform mappings (#660) @@ -2889,7 +3007,7 @@ We identified that **155 community PRs** across the entire project history (from - **NaN tokens in Claude Code / client responses (#617):** - `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 -### 🔒 Security +### Beveiliging - Updated `yaml` package to fix stack overflow vulnerability (GHSA-48c2-rrv3-qjmp) @@ -3565,7 +3683,7 @@ docker pull diegosouzapw/omniroute:3.0.0 - **SVG fallback**: `ProviderIcon` component updated with 4-tier strategy: Lobehub → PNG → SVG → Generic icon - **Agents fingerprinting**: Synced with CLI tools — added droid, openclaw, copilot, opencode to fingerprint list (14 total) -### 🔒 Security +### Beveiliging - **CVE fix**: Resolved dompurify XSS vulnerability (GHSA-v2wj-7wpq-c8vv) via npm overrides forcing `dompurify@^3.3.2` - `npm audit` now reports **0 vulnerabilities** @@ -3928,7 +4046,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **#510** — Windows: MSYS2/Git-Bash paths (`/c/Program Files/...`) are now normalized to `C:\Program Files\...` - **#492** — `omniroute` CLI now detects `mise`/`nvm` when `app/server.js` is missing and shows targeted fix -### 📖 Documentation +### Documentatie - **#513** — Docker password reset: `INITIAL_PASSWORD` env var workaround documented - **#520** — pnpm: `pnpm approve-builds better-sqlite3` documented @@ -4025,7 +4143,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **feat(executors/cloudflare-ai)**: New `CloudflareAIExecutor` — dynamic URL construction requires `accountId` in provider credentials - **feat(executors)**: Register `pollinations`, `pol`, `cloudflare-ai`, `cf` executor mappings -### 📝 Documentation +### Documentatie - **docs(readme)**: Expanded free combo stack to 11 providers ($0 forever) - **docs(readme)**: Added 4 new free provider sections (LongCat, Pollinations, Cloudflare AI, Scaleway) with model tables @@ -4177,7 +4295,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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). -### Features +### Functies - **"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. @@ -4205,7 +4323,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Merge PR #494 (MiniMax role fix), fix KIRO MITM dashboard, triage 8 issues. -### Features +### Functies - **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. - **roleNormalizer**: `normalizeDeveloperRole()` now accepts `preserveDeveloperRole` parameter with tri-state behavior (undefined=keep, true=keep, false=convert). @@ -4261,7 +4379,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Gemini CLI deprecation, VM guide i18n fix, dependabot security fix, provider schema expansion. -### Features +### Functies - **Gemini CLI Deprecation** (#462): Mark `gemini-cli` provider as deprecated with warning — Google restricts third-party OAuth usage from March 2026 - **Provider Schema** (#462): Expand Zod validation with `deprecated`, `deprecationReason`, `hasFree`, `freeNote`, `authHint`, `apiHint` optional fields @@ -4270,7 +4388,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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) -### Security +### Beveiliging - **deps**: Bump `flatted` 3.3.3 → 3.4.2 — fixes CWE-1321 prototype pollution (#484, @dependabot) @@ -4290,7 +4408,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Czech i18n, SSE protocol fix, VM guide translation. -### Features +### Functies - **Czech Language** (#482): Full Czech (cs) i18n — 22 docs, 2606 UI strings, language switcher updates (@zen0bit) - **VM Deployment Guide**: Translated from Portuguese to English as the source document (@zen0bit) @@ -4309,7 +4427,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: 2 merged PRs, model aliases routing fix, log export, and issue triage. -### Features +### Functies - **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) @@ -4329,7 +4447,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Five community PRs — streaming call log fixes, Kiro compatibility, cache token analytics, Chinese translation, and configurable tool call IDs. -### ✨ Features +### Functies - **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) - **feat(providers)**: Per-model configurable 9-char tool call ID normalization (Mistral-style) — only models with the option enabled get truncated IDs (#470) @@ -4359,7 +4477,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Bailian Coding Plan provider with editable base URLs, plus community contributions for Alibaba Cloud and Kimi Coding. -### ✨ Features +### Functies - **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) - **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) @@ -4374,7 +4492,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Two new community-contributed providers (Alibaba Cloud Coding, Kimi Coding API-key) and Docker pino fix. -### ✨ Features +### Functies - **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) - **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) @@ -4399,7 +4517,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Codex responses subpath passthrough natively supported, Windows MITM crash fixed, and Combos agent schemas adjusted. -### ✨ Features +### Functies - **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) @@ -4439,7 +4557,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **fix(budget)**: "Save Limits" no longer returns 422 — `warningThreshold` is now correctly sent as fraction (0–1) instead of percentage (0–100) (#451) - **fix(combos)**: `` internal cache tag is now stripped before forwarding requests to providers, preventing cache session breaks (#454) -### ✨ Features +### Functies - **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) @@ -4495,7 +4613,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Search Tools dashboard, i18n fixes, Copilot limits, Serper validation fix. -### 🚀 Features +### Functies - **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) - New route: `/dashboard/search-tools` @@ -4595,7 +4713,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - DB migration: `request_type` column on `call_logs` for non-chat request tracking - Zod validation (`v1SearchSchema`), auth-gated, cost recorded via `recordCost()` -### 🔒 Security +### Beveiliging - **deps**: Next.js 16.1.6 → 16.1.7 — fixes 6 CVEs: - **Critical**: CVE-2026-29057 (HTTP request smuggling via http-proxy) @@ -4725,7 +4843,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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**: New `request_detail_logs` table with 500-entry ring-buffer trigger, opt-in via settings toggle -### ✨ Features +### Functies - **feat(combo)**: System Message Override per Combo (#399 — `system_message` field replaces or injects system prompt before forwarding to provider) - **feat(combo)**: Tool Filter Regex per Combo (#399 — `tool_filter_regex` keeps only tools matching pattern; supports OpenAI + Anthropic formats) @@ -4740,7 +4858,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: SSE improvements, local provider_nodes extensions, proxy registry, Claude passthrough fixes. -### ✨ Features +### Functies - **feat(health)**: Background health check for local `provider_nodes` with exponential backoff (30s→300s) and `Promise.allSettled` to avoid blocking (#423, @Regis-RCR) - **feat(embeddings)**: Route `/v1/embeddings` to local `provider_nodes` — `buildDynamicEmbeddingProvider()` with hostname validation (#422, @Regis-RCR) @@ -4882,7 +5000,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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 - **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). -### ✨ Features +### Functies - **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) @@ -4912,7 +5030,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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) - **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) -### ✨ Features +### Functies - **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) - **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. @@ -4971,7 +5089,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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) - **fix(logs)**: Request log table is now readable in light mode — status badges, token counts, and combo tags use adaptive `dark:` color classes (#378) -### ✨ Features +### Functies - **feat(kiro)**: Kiro credit tracking added to usage fetcher — queries `getUserCredits` from AWS CodeWhisperer endpoint (#337) @@ -5372,7 +5490,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > **Major release** — Free Stack ecosystem, transcription playground overhaul, 44+ providers, comprehensive free tier documentation, and UI improvements across the board. -### ✨ Features +### Functies - **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. - **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. @@ -5383,7 +5501,7 @@ OmniRoute now automatically refreshes model lists for connected providers every ## [2.3.16] - 2026-03-13 -### 📖 Documentation +### Documentatie - **README: 44+ Providers** — Updated all 3 occurrences of "36+ providers" to "44+" reflecting the actual codebase count (44 providers in providers.ts) - **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. @@ -5393,7 +5511,7 @@ OmniRoute now automatically refreshes model lists for connected providers every ## [2.3.15] - 2026-03-13 -### ✨ Features +### Functies - **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. - **i18n — autoCombo section**: Added 20 new translation keys for the Auto-Combo dashboard (`title`, `status`, `modePack`, `providerScores`, `factorTierPriority`, etc.) to all 30 language files. diff --git a/docs/i18n/no/CHANGELOG.md b/docs/i18n/no/CHANGELOG.md index 3f49a01660..9766c019d6 100644 --- a/docs/i18n/no/CHANGELOG.md +++ b/docs/i18n/no/CHANGELOG.md @@ -10,30 +10,148 @@ ### ✨ New Features -- **feat(antigravity):** integrate Antigravity provider with dynamic `maxOutputTokens` calculation (bumping to `thinkingBudget + 1`) and standard Cloud Code envelope payload sanitization (#2055, #2063) +- **feat(antigravity):** integrate Antigravity provider with dynamic `maxOutputTokens` calculation, identity fingerprinting overhaul, and Cloud Code envelope payload sanitization (#2055, #2063) - **feat(gemini-cli):** add custom projectId support for Gemini CLI transport (UI, DB, executor) (#1991) +- **feat(providers):** add KIE media provider support with dynamic polling, text models, and expanded video models catalog +- **feat(providers):** add Z.AI provider support with GLM quota handling and new quota labels +- **feat(providers):** add 9 new free AI providers — LLM7, Lepton, Kluster, UncloseAI, BazaarLink, Completions, Enally, FreeTheAi (#2096) +- **feat(providers):** batch delete provider connections via checkbox multi-select (#2094) +- **feat(cursor):** full OpenAI parity — tool calls, streaming, and session management (#2082) +- **feat(cli):** comprehensive CLI enhancement suite with 20+ new commands including `omniroute providers`, `omniroute combos`, `omniroute doctor` (#2074) +- **feat(cli):** add modular CLI setup and provider management commands (#2046) +- **feat(mcp):** add DeepSeek quota and limit monitoring feature (#2089) +- **feat(circuit-breaker):** classify 429 errors and apply per-kind cooldowns (#2116) +- **feat(multi):** manifest-aware tier routing — W1-W4 complete (#2014) +- **feat(combos):** add reset-aware routing strategy for quota-based providers +- **feat(combo):** add context_length input field to combo edit form (#2047) +- **feat(chat):** dynamic tool limit detection with proactive truncation (#2061) +- **feat(sse):** refresh Claude OAuth wire image to claude-cli/2.1.131 (#2011) +- **feat(github):** add `targetFormat: openai-responses` to all GitHub models (#2122) +- **feat(api):** allow configuration via API calls — open management routes to Bearer keys with manage scope (#2103) +- **feat(api):** update API bridge proxy timeout to 600,000ms (#2019) +- **feat(usage):** add service tier breakdown, codex fast service tier analytics, and account for fast tier +- **feat(chat):** add `STREAM_READINESS_TIMEOUT_MS` and integrate into chat handling +- **feat(combo):** add `fallbackDelayMs` to combo configuration and related settings +- **feat(chat):** enhance error handling for semaphore capacity with fallback logic +- **feat(qdrant):** embedding model discovery (#2086) +- **feat(auth):** per-session sticky routing for Codex (#1887) +- **feat(inworld):** enhance Inworld TTS support (#2123) ### 🐛 Bug Fixes +- **fix(pricing):** make `getPricingForModel` fully case-insensitive to ensure custom prices correctly reflect in new incoming requests cost calculations +- **fix(gemini):** prevent `functionDeclarations` from being dropped by the sanitizer when `googleSearch` tool is present (#2077) +- **fix(pollinations):** add `jsonMode: true` flag in the request transformation to enforce correct JSON structure from Pollinations API (#2109) +- **fix(docker):** update Dockerfile to copy `/docs` directory during build ensuring API catalog availability at runtime (#2083) +- **fix(docker):** include OpenAPI spec in runtime image (#2007) +- **fix(providers):** strip OpenAI-specific fields in Kiro translator to prevent 400 errors (#2037) +- **fix(kiro):** normalize tool-use payloads to prevent 400 errors from agents (#2104) +- **fix(kiro):** merge adjacent user history turns after role normalization (#2105) +- **fix(ui):** resolve text contrast issues for zero-config warning banner in light mode (#2050) +- **fix(core):** inject global system prompt correctly into downstream chat completions pipeline (#2080) +- **fix(core):** restore Claude Code adaptive thinking defaults and resolve audio transcription CORS regression +- **fix(routing):** add missing v1beta rewrites to next.config to resolve 404 on Gemini models endpoint (#2102) +- **fix(routing):** fix bare GPT-5.5 routing for Codex-only installations (#2054) +- **fix(routing):** add fuzzy auto-combo routing for `auto/*` model prefix (#2010) - **fix(cache):** optimize cache_control preservation logic and explicitly align tool schema with upstream Claude Code expectations - **fix(db):** preserve legacy SQLite database path on Windows to prevent data loss (#1973) +- **fix(db):** reduce hot-path persistence overhead (#2039) +- **fix(db):** resolve migration conflict by renumbering overlapping migration entries (#2041) - **fix(settings):** resolve model alias persistence double stringification preventing UI updates (#2018) - **fix(routing):** dynamically filter bare model auto-resolution by active provider connections to prevent dead-routing (#2029) - **fix(embeddings):** add Google Gemini embeddings compatibility via OpenAI-compatible endpoint mapping (#2006) +- **fix(sse):** prevent Claude OAuth multi-account correlation via metadata.user_id (#2053) +- **fix(sse):** prevent Claude Code identity cloak overrides and fix fallback resilience (#2053) +- **fix(sse):** classify hour quota errors as QUOTA_EXHAUSTED (#2119) +- **fix(sse):** fix CC-compatible streaming bridge (#2118) +- **fix(antigravity):** sanitize Claude Cloud Code payloads (#2090) +- **fix(antigravity):** add duplex half for streaming bodies +- **fix(antigravity):** align identity protocol and behavior with official AM +- **fix(chatgpt-web):** plumb proxy through to native tls-client (#2022, #2023) +- **fix(codex):** expose native model IDs in catalog (#2012) +- **fix(glm):** add dedicated coding transport (#2087) +- **fix(compression):** support Responses input and expand Spanish compression rules (#2028) +- **fix(catalog):** auto-calculate combo context_length from target model limits (#2030) +- **fix(api):** fix usage analytics and API key identity (#2008, #2092) +- **fix(api-key):** allow Unicode letters in API key name validation (#1996) +- **fix(auth):** allow bootstrap without password (#2048) +- **fix(proxy):** clean up proxy page redundancy and fix 1proxy sync empty body error (#2052) +- **fix(dashboard):** resolve Unknown plan display in Provider Limits +- **fix(usage):** add extensible CURRENCY_SYMBOLS mapping for deepseek currencies +- **fix(runtime):** harden timer handling and model pricing fallback +- **fix(i18n):** complete Simplified Chinese translations (#2115) +- **fix(mitm):** add Linux cert install and skip sudo password when root (#1999) +- **fix(mitm):** prevent stub from loading at runtime via bypass module - **fix:** remove Anthropic-Beta header from non-Anthropic providers to fix identity contamination (#1989) - **fix(cli):** resolve .env loading failure for global npm installations +- **fix(export):** exclude telemetry/usage-history tables from JSON config backups by default to prevent unbounded file growth (#2125) +- **fix:** Follow OpenAI specification, handle throttling in batch and fix UI (#2045) -### 🔒 Security +### Sikkerhet +- **fix(security):** remediate CodeQL vulnerabilities (ReDoS, cryptographic bias, stack trace exposure, and weak password hashing) (#216, #215, #211, #208, #206, #210) - **fix(security):** remediate regex validation backtracking path in core compression cleanup (#1990) - **fix(core):** harden input handling and stabilization for prompt compression edge cases +### Dokumentasjon + +- **docs:** add competitive marketing tables and SEO/AEO optimizations to README (#2091) +- **docs:** refresh providers, model catalogs, and docs for v3.8.0 (#2088) +- **docs:** update Claude MD and update GLM-CN max context to 200k (#2027) +- **docs(env):** add `GITLAB_DUO_OAUTH_CLIENT_ID` to `.env.example` (#2031) + ### 🧹 Chores & Maintenance - **chore(providers):** prune redundant local provider icon assets in favor of `@lobehub/icons` web fonts (#1992) +- **chore(providers):** remove deprecated models (#2033) +- **deps:** bump `fast-uri` from 3.1.0 to 3.1.2 (#2078) +- **deps:** bump `hono` from 4.12.14 to 4.12.18 (#2079) - **ci:** skip SonarCloud scan on main pushes to optimize CI time - **test:** stabilize cooldown abort coverage case in integration testing +### 🏆 v3.8.0 Community Contributors + +Thank you to all **38 community contributors** who made v3.8.0 possible! 🎉 + +| Contributor | PRs | Contributions | +| :--------------------------------------------------------- | :-: | :------------------------------------------------------------ | +| [@oyi77](https://github.com/oyi77) | 7 | #2010, #2014, #2041, #2052, #2061, #2074, #2091, #2094, #2096 | +| [@backryun](https://github.com/backryun) | 4 | #1992, #2033, #2088, #2123 | +| [@dhaern](https://github.com/dhaern) | 4 | #2028, #2039, #2087, #2090 | +| [@Tentoxa](https://github.com/Tentoxa) | 2 | #2011, #2053 | +| [@wauputr4](https://github.com/wauputr4) | 2 | #2009, #2046 | +| [@payne0420](https://github.com/payne0420) | 1 | #2082 | +| [@Tr0sT](https://github.com/Tr0sT) | 1 | #2012 | +| [@AveryanAlex](https://github.com/AveryanAlex) | 1 | #2008 | +| [@nickwizard](https://github.com/nickwizard) | 1 | #1991 | +| [@rodrigogbbr-stack](https://github.com/rodrigogbbr-stack) | 1 | #1996 | +| [@NekoMonci12](https://github.com/NekoMonci12) | 1 | #1999 | +| [@congvc-dev](https://github.com/congvc-dev) | 1 | #2004 | +| [@tatsster](https://github.com/tatsster) | 1 | #2007 | +| [@xssdem](https://github.com/xssdem) | 1 | #2023 | +| [@bypanghu](https://github.com/bypanghu) | 1 | #2027 | +| [@herjarsa](https://github.com/herjarsa) | 1 | #2030 | +| [@wucm667](https://github.com/wucm667) | 1 | #2031 | +| [@hartmark](https://github.com/hartmark) | 1 | #2045 | +| [@ddarkr](https://github.com/ddarkr) | 1 | #2047 | +| [@tces1](https://github.com/tces1) | 1 | #2048 | +| [@guanbear](https://github.com/guanbear) | 1 | #2054 | +| [@Gi99lin](https://github.com/Gi99lin) | 1 | #2055 | +| [@ivan-mezentsev](https://github.com/ivan-mezentsev) | 1 | #2063 | +| [@JxnLexn](https://github.com/JxnLexn) | 1 | #2019 | +| [@yoviarpauzi](https://github.com/yoviarpauzi) | 1 | #2092 | +| [@rafacpti23](https://github.com/rafacpti23) | 1 | #2086 | +| [@gleber](https://github.com/gleber) | 1 | #2103 | +| [@rilham97](https://github.com/rilham97) | 1 | #2104 | +| [@Gioxaa](https://github.com/Gioxaa) | 1 | #2105 | +| [@boa-z](https://github.com/boa-z) | 1 | #2115 | +| [@eleata](https://github.com/eleata) | 1 | #2116 | +| [@rdself](https://github.com/rdself) | 1 | #2118 | +| [@clousky2020](https://github.com/clousky2020) | 1 | #2119 | +| [@abhinavjnu](https://github.com/abhinavjnu) | 1 | #2122 | +| [@HoaPham98](https://github.com/HoaPham98) | 1 | #2089 | +| [@05dunski](https://github.com/05dunski) | 1 | #1978 (cherry-picked) | + ## [3.7.9] — 2026-05-03 ### ✨ New Features @@ -102,7 +220,7 @@ - **chore(provider):** Add reka models list (#1956 — thanks @backryun) - **chore(model):** Update new models, Delete Deprecated models (#1949 — thanks @backryun) -### 📝 Documentation +### Dokumentasjon - **docs(compression):** document RTK+Caveman stacked savings ranges @@ -201,7 +319,7 @@ - **feat(db):** auto-restore probe-failed database on startup to prevent data loss after failed upgrades (#1810) - **feat(analytics):** add cost-based usage insights and activity streaks in the analytics dashboard -### 🔒 Security +### Sikkerhet - **fix(security):** resolve ReDoS vulnerability in Codex executor regex patterns (#1797, #1789) @@ -354,7 +472,7 @@ We identified that **155 community PRs** across the entire project history (from - **feat(proxy):** implement bulk proxy import via pipe-delimited parser with update-or-create (upsert) logic and real-time preview table - **feat(pwa):** add fullscreen installable PWA with manifest, service worker, and cross-platform app icons (#1728) -### 🔒 Security +### Sikkerhet - **security:** replace insecure `Math.random` with `crypto.getRandomValues` for fallback UUID generation to resolve CodeQL CWE-338 finding (#182) @@ -519,7 +637,7 @@ We identified that **155 community PRs** across the entire project history (from - **fix(transport):** Prevent memory bloat and database exhaustion from large, fragmented streaming responses. Implemented `ByteQueue` in `kiro.ts` for zero-copy binary accumulation, refactored `antigravity.ts` for incremental SSE parsing, and enforced a strict 512KB tiered truncation limit (`MAX_CALL_LOG_ARTIFACT_BYTES`) on stream request logs and call artifacts (#1647). - **chore(ci):** Update build environment dependencies — bump Node to `24.15.0`, `actions/checkout@v6`, `docker/build-push-action@v7`, pin `actions/setup-python` to major tag (#1646 — thanks @backryun). -### 📝 Documentation +### Dokumentasjon - **docs(env):** Add `OMNIROUTE_ALLOW_PRIVATE_PROVIDER_URLS` to `.env.example` with documentation for LM Studio and other local provider use cases (#1623). @@ -669,7 +787,7 @@ We identified that **155 community PRs** across the entire project history (from - **test(next):** Align transpile package expectations for the Next.js standalone build. - **test(ci):** Fix CI-only test failures from environment differences — clear `INITIAL_PASSWORD` and `JWT_SECRET` in integration tests, handle `XDG_CONFIG_HOME` for guide-settings tests. -### 📚 Documentation +### Dokumentasjon - **docs:** Update the root changelog with all release-branch changes through 2026-04-24, including PRs #1544, #1555, #1551, #1550, #1548, #1547, #1541, #1538, #1536, and #1527. - **docs:** Fix broken README and localized documentation links. (#1536) @@ -811,7 +929,7 @@ We identified that **155 community PRs** across the entire project history (from - **feat(providers):** Expand image provider registry with extended model support including SD3.5, FLUX, and DALL-E 3 HD configurations - **feat(combos):** Add new routing strategies and full i18n support for agent features section across 31 languages -### 🔒 Security +### Sikkerhet - **security:** Resolve 18 GitHub CodeQL scan alerts including ReDoS, incomplete sanitization, and bad HTML filtering regexp patterns - **fix(auth):** Seal privilege escalation vector by enforcing JWT session checking exclusively on `/api/keys` management endpoints (#1353) @@ -1078,7 +1196,7 @@ We identified that **155 community PRs** across the entire project history (from - **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 - **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 -### 🔒 Security +### Sikkerhet - **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 - **Auth Guard on Translator Save:** Added `isAuthenticated` guard to `/api/translator/save` for defense-in-depth consistency @@ -1483,7 +1601,7 @@ We identified that **155 community PRs** across the entire project history (from - **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). -### 📚 Documentation +### Dokumentasjon - **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. - **Context Relay Delivery Notes:** Documented the current architecture, runtime flow, and Codex-focused scope in the feature docs, changelog, and agent guidance. @@ -1559,7 +1677,7 @@ We identified that **155 community PRs** across the entire project history (from ## [3.5.3] - 2026-04-07 -### Security +### Sikkerhet - **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. - **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. @@ -1575,7 +1693,7 @@ We identified that **155 community PRs** across the entire project history (from - **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. -### Documentation +### Dokumentasjon - **I18n Engine:** Synchronized and pushed deep Machine Translation updates across all 32 natively-supported languages (682 translation nodes aligned). @@ -1736,7 +1854,7 @@ We identified that **155 community PRs** across the entire project history (from ## [3.4.8] — 2026-04-03 -### Security +### Sikkerhet - Fully remediated all outstanding Github Advanced Security (CodeQL) findings and Dependabot alerts. - Fixed insecure randomness vulnerabilities by migrating from `Math.random` to `crypto.randomUUID()`. @@ -1748,7 +1866,7 @@ We identified that **155 community PRs** across the entire project history (from ## [3.4.7] — 2026-04-03 -### Features +### Funksjoner - Added `Cryptography` node to Monitoring and MCP health checks (#798) - Hardened model-catalog route permissions mapping (`/models`) (#781) @@ -1764,7 +1882,7 @@ We identified that **155 community PRs** across the entire project history (from - Fixed MCP standalone module-resolution (`ERR_MODULE_NOT_FOUND`) via `esbuild` (#936) - Fixed NVIDIA NIM routing credential resolution alias mismatch (#931) -### Security +### Sikkerhet - Added safe strict input boundary protection against raw `shell: true` remote-code execution injections. @@ -2011,7 +2129,7 @@ We identified that **155 community PRs** across the entire project history (from ## [3.4.0] - 2026-03-31 -### 🚀 Features +### Funksjoner - **Subscription Utilization Analytics:** Added quota snapshot time-series tracking, Provider Utilization and Combo Health tabs with recharts visualizations, and corresponding API endpoints (#847) - **SQLite Backup Control:** New `OMNIROUTE_DISABLE_AUTO_BACKUP` env flag to disable automatic SQLite backups (#846) @@ -2063,7 +2181,7 @@ We identified that **155 community PRs** across the entire project history (from ## [3.3.8] - 2026-03-30 -### 🚀 Features +### Funksjoner - **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) - **Qoder Integration:** Native integration for Qoder AI natively replacing the legacy iFlow platform mappings (#660) @@ -2889,7 +3007,7 @@ We identified that **155 community PRs** across the entire project history (from - **NaN tokens in Claude Code / client responses (#617):** - `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 -### 🔒 Security +### Sikkerhet - Updated `yaml` package to fix stack overflow vulnerability (GHSA-48c2-rrv3-qjmp) @@ -3565,7 +3683,7 @@ docker pull diegosouzapw/omniroute:3.0.0 - **SVG fallback**: `ProviderIcon` component updated with 4-tier strategy: Lobehub → PNG → SVG → Generic icon - **Agents fingerprinting**: Synced with CLI tools — added droid, openclaw, copilot, opencode to fingerprint list (14 total) -### 🔒 Security +### Sikkerhet - **CVE fix**: Resolved dompurify XSS vulnerability (GHSA-v2wj-7wpq-c8vv) via npm overrides forcing `dompurify@^3.3.2` - `npm audit` now reports **0 vulnerabilities** @@ -3928,7 +4046,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **#510** — Windows: MSYS2/Git-Bash paths (`/c/Program Files/...`) are now normalized to `C:\Program Files\...` - **#492** — `omniroute` CLI now detects `mise`/`nvm` when `app/server.js` is missing and shows targeted fix -### 📖 Documentation +### Dokumentasjon - **#513** — Docker password reset: `INITIAL_PASSWORD` env var workaround documented - **#520** — pnpm: `pnpm approve-builds better-sqlite3` documented @@ -4025,7 +4143,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **feat(executors/cloudflare-ai)**: New `CloudflareAIExecutor` — dynamic URL construction requires `accountId` in provider credentials - **feat(executors)**: Register `pollinations`, `pol`, `cloudflare-ai`, `cf` executor mappings -### 📝 Documentation +### Dokumentasjon - **docs(readme)**: Expanded free combo stack to 11 providers ($0 forever) - **docs(readme)**: Added 4 new free provider sections (LongCat, Pollinations, Cloudflare AI, Scaleway) with model tables @@ -4177,7 +4295,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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). -### Features +### Funksjoner - **"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. @@ -4205,7 +4323,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Merge PR #494 (MiniMax role fix), fix KIRO MITM dashboard, triage 8 issues. -### Features +### Funksjoner - **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. - **roleNormalizer**: `normalizeDeveloperRole()` now accepts `preserveDeveloperRole` parameter with tri-state behavior (undefined=keep, true=keep, false=convert). @@ -4261,7 +4379,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Gemini CLI deprecation, VM guide i18n fix, dependabot security fix, provider schema expansion. -### Features +### Funksjoner - **Gemini CLI Deprecation** (#462): Mark `gemini-cli` provider as deprecated with warning — Google restricts third-party OAuth usage from March 2026 - **Provider Schema** (#462): Expand Zod validation with `deprecated`, `deprecationReason`, `hasFree`, `freeNote`, `authHint`, `apiHint` optional fields @@ -4270,7 +4388,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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) -### Security +### Sikkerhet - **deps**: Bump `flatted` 3.3.3 → 3.4.2 — fixes CWE-1321 prototype pollution (#484, @dependabot) @@ -4290,7 +4408,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Czech i18n, SSE protocol fix, VM guide translation. -### Features +### Funksjoner - **Czech Language** (#482): Full Czech (cs) i18n — 22 docs, 2606 UI strings, language switcher updates (@zen0bit) - **VM Deployment Guide**: Translated from Portuguese to English as the source document (@zen0bit) @@ -4309,7 +4427,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: 2 merged PRs, model aliases routing fix, log export, and issue triage. -### Features +### Funksjoner - **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) @@ -4329,7 +4447,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Five community PRs — streaming call log fixes, Kiro compatibility, cache token analytics, Chinese translation, and configurable tool call IDs. -### ✨ Features +### Funksjoner - **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) - **feat(providers)**: Per-model configurable 9-char tool call ID normalization (Mistral-style) — only models with the option enabled get truncated IDs (#470) @@ -4359,7 +4477,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Bailian Coding Plan provider with editable base URLs, plus community contributions for Alibaba Cloud and Kimi Coding. -### ✨ Features +### Funksjoner - **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) - **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) @@ -4374,7 +4492,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Two new community-contributed providers (Alibaba Cloud Coding, Kimi Coding API-key) and Docker pino fix. -### ✨ Features +### Funksjoner - **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) - **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) @@ -4399,7 +4517,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Codex responses subpath passthrough natively supported, Windows MITM crash fixed, and Combos agent schemas adjusted. -### ✨ Features +### Funksjoner - **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) @@ -4439,7 +4557,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **fix(budget)**: "Save Limits" no longer returns 422 — `warningThreshold` is now correctly sent as fraction (0–1) instead of percentage (0–100) (#451) - **fix(combos)**: `` internal cache tag is now stripped before forwarding requests to providers, preventing cache session breaks (#454) -### ✨ Features +### Funksjoner - **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) @@ -4495,7 +4613,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Search Tools dashboard, i18n fixes, Copilot limits, Serper validation fix. -### 🚀 Features +### Funksjoner - **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) - New route: `/dashboard/search-tools` @@ -4595,7 +4713,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - DB migration: `request_type` column on `call_logs` for non-chat request tracking - Zod validation (`v1SearchSchema`), auth-gated, cost recorded via `recordCost()` -### 🔒 Security +### Sikkerhet - **deps**: Next.js 16.1.6 → 16.1.7 — fixes 6 CVEs: - **Critical**: CVE-2026-29057 (HTTP request smuggling via http-proxy) @@ -4725,7 +4843,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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**: New `request_detail_logs` table with 500-entry ring-buffer trigger, opt-in via settings toggle -### ✨ Features +### Funksjoner - **feat(combo)**: System Message Override per Combo (#399 — `system_message` field replaces or injects system prompt before forwarding to provider) - **feat(combo)**: Tool Filter Regex per Combo (#399 — `tool_filter_regex` keeps only tools matching pattern; supports OpenAI + Anthropic formats) @@ -4740,7 +4858,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: SSE improvements, local provider_nodes extensions, proxy registry, Claude passthrough fixes. -### ✨ Features +### Funksjoner - **feat(health)**: Background health check for local `provider_nodes` with exponential backoff (30s→300s) and `Promise.allSettled` to avoid blocking (#423, @Regis-RCR) - **feat(embeddings)**: Route `/v1/embeddings` to local `provider_nodes` — `buildDynamicEmbeddingProvider()` with hostname validation (#422, @Regis-RCR) @@ -4882,7 +5000,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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 - **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). -### ✨ Features +### Funksjoner - **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) @@ -4912,7 +5030,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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) - **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) -### ✨ Features +### Funksjoner - **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) - **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. @@ -4971,7 +5089,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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) - **fix(logs)**: Request log table is now readable in light mode — status badges, token counts, and combo tags use adaptive `dark:` color classes (#378) -### ✨ Features +### Funksjoner - **feat(kiro)**: Kiro credit tracking added to usage fetcher — queries `getUserCredits` from AWS CodeWhisperer endpoint (#337) @@ -5372,7 +5490,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > **Major release** — Free Stack ecosystem, transcription playground overhaul, 44+ providers, comprehensive free tier documentation, and UI improvements across the board. -### ✨ Features +### Funksjoner - **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. - **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. @@ -5383,7 +5501,7 @@ OmniRoute now automatically refreshes model lists for connected providers every ## [2.3.16] - 2026-03-13 -### 📖 Documentation +### Dokumentasjon - **README: 44+ Providers** — Updated all 3 occurrences of "36+ providers" to "44+" reflecting the actual codebase count (44 providers in providers.ts) - **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. @@ -5393,7 +5511,7 @@ OmniRoute now automatically refreshes model lists for connected providers every ## [2.3.15] - 2026-03-13 -### ✨ Features +### Funksjoner - **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. - **i18n — autoCombo section**: Added 20 new translation keys for the Auto-Combo dashboard (`title`, `status`, `modePack`, `providerScores`, `factorTierPriority`, etc.) to all 30 language files. diff --git a/docs/i18n/phi/CHANGELOG.md b/docs/i18n/phi/CHANGELOG.md index a58c91fb5e..9960f024ef 100644 --- a/docs/i18n/phi/CHANGELOG.md +++ b/docs/i18n/phi/CHANGELOG.md @@ -10,30 +10,148 @@ ### ✨ New Features -- **feat(antigravity):** integrate Antigravity provider with dynamic `maxOutputTokens` calculation (bumping to `thinkingBudget + 1`) and standard Cloud Code envelope payload sanitization (#2055, #2063) +- **feat(antigravity):** integrate Antigravity provider with dynamic `maxOutputTokens` calculation, identity fingerprinting overhaul, and Cloud Code envelope payload sanitization (#2055, #2063) - **feat(gemini-cli):** add custom projectId support for Gemini CLI transport (UI, DB, executor) (#1991) +- **feat(providers):** add KIE media provider support with dynamic polling, text models, and expanded video models catalog +- **feat(providers):** add Z.AI provider support with GLM quota handling and new quota labels +- **feat(providers):** add 9 new free AI providers — LLM7, Lepton, Kluster, UncloseAI, BazaarLink, Completions, Enally, FreeTheAi (#2096) +- **feat(providers):** batch delete provider connections via checkbox multi-select (#2094) +- **feat(cursor):** full OpenAI parity — tool calls, streaming, and session management (#2082) +- **feat(cli):** comprehensive CLI enhancement suite with 20+ new commands including `omniroute providers`, `omniroute combos`, `omniroute doctor` (#2074) +- **feat(cli):** add modular CLI setup and provider management commands (#2046) +- **feat(mcp):** add DeepSeek quota and limit monitoring feature (#2089) +- **feat(circuit-breaker):** classify 429 errors and apply per-kind cooldowns (#2116) +- **feat(multi):** manifest-aware tier routing — W1-W4 complete (#2014) +- **feat(combos):** add reset-aware routing strategy for quota-based providers +- **feat(combo):** add context_length input field to combo edit form (#2047) +- **feat(chat):** dynamic tool limit detection with proactive truncation (#2061) +- **feat(sse):** refresh Claude OAuth wire image to claude-cli/2.1.131 (#2011) +- **feat(github):** add `targetFormat: openai-responses` to all GitHub models (#2122) +- **feat(api):** allow configuration via API calls — open management routes to Bearer keys with manage scope (#2103) +- **feat(api):** update API bridge proxy timeout to 600,000ms (#2019) +- **feat(usage):** add service tier breakdown, codex fast service tier analytics, and account for fast tier +- **feat(chat):** add `STREAM_READINESS_TIMEOUT_MS` and integrate into chat handling +- **feat(combo):** add `fallbackDelayMs` to combo configuration and related settings +- **feat(chat):** enhance error handling for semaphore capacity with fallback logic +- **feat(qdrant):** embedding model discovery (#2086) +- **feat(auth):** per-session sticky routing for Codex (#1887) +- **feat(inworld):** enhance Inworld TTS support (#2123) ### 🐛 Bug Fixes +- **fix(pricing):** make `getPricingForModel` fully case-insensitive to ensure custom prices correctly reflect in new incoming requests cost calculations +- **fix(gemini):** prevent `functionDeclarations` from being dropped by the sanitizer when `googleSearch` tool is present (#2077) +- **fix(pollinations):** add `jsonMode: true` flag in the request transformation to enforce correct JSON structure from Pollinations API (#2109) +- **fix(docker):** update Dockerfile to copy `/docs` directory during build ensuring API catalog availability at runtime (#2083) +- **fix(docker):** include OpenAPI spec in runtime image (#2007) +- **fix(providers):** strip OpenAI-specific fields in Kiro translator to prevent 400 errors (#2037) +- **fix(kiro):** normalize tool-use payloads to prevent 400 errors from agents (#2104) +- **fix(kiro):** merge adjacent user history turns after role normalization (#2105) +- **fix(ui):** resolve text contrast issues for zero-config warning banner in light mode (#2050) +- **fix(core):** inject global system prompt correctly into downstream chat completions pipeline (#2080) +- **fix(core):** restore Claude Code adaptive thinking defaults and resolve audio transcription CORS regression +- **fix(routing):** add missing v1beta rewrites to next.config to resolve 404 on Gemini models endpoint (#2102) +- **fix(routing):** fix bare GPT-5.5 routing for Codex-only installations (#2054) +- **fix(routing):** add fuzzy auto-combo routing for `auto/*` model prefix (#2010) - **fix(cache):** optimize cache_control preservation logic and explicitly align tool schema with upstream Claude Code expectations - **fix(db):** preserve legacy SQLite database path on Windows to prevent data loss (#1973) +- **fix(db):** reduce hot-path persistence overhead (#2039) +- **fix(db):** resolve migration conflict by renumbering overlapping migration entries (#2041) - **fix(settings):** resolve model alias persistence double stringification preventing UI updates (#2018) - **fix(routing):** dynamically filter bare model auto-resolution by active provider connections to prevent dead-routing (#2029) - **fix(embeddings):** add Google Gemini embeddings compatibility via OpenAI-compatible endpoint mapping (#2006) +- **fix(sse):** prevent Claude OAuth multi-account correlation via metadata.user_id (#2053) +- **fix(sse):** prevent Claude Code identity cloak overrides and fix fallback resilience (#2053) +- **fix(sse):** classify hour quota errors as QUOTA_EXHAUSTED (#2119) +- **fix(sse):** fix CC-compatible streaming bridge (#2118) +- **fix(antigravity):** sanitize Claude Cloud Code payloads (#2090) +- **fix(antigravity):** add duplex half for streaming bodies +- **fix(antigravity):** align identity protocol and behavior with official AM +- **fix(chatgpt-web):** plumb proxy through to native tls-client (#2022, #2023) +- **fix(codex):** expose native model IDs in catalog (#2012) +- **fix(glm):** add dedicated coding transport (#2087) +- **fix(compression):** support Responses input and expand Spanish compression rules (#2028) +- **fix(catalog):** auto-calculate combo context_length from target model limits (#2030) +- **fix(api):** fix usage analytics and API key identity (#2008, #2092) +- **fix(api-key):** allow Unicode letters in API key name validation (#1996) +- **fix(auth):** allow bootstrap without password (#2048) +- **fix(proxy):** clean up proxy page redundancy and fix 1proxy sync empty body error (#2052) +- **fix(dashboard):** resolve Unknown plan display in Provider Limits +- **fix(usage):** add extensible CURRENCY_SYMBOLS mapping for deepseek currencies +- **fix(runtime):** harden timer handling and model pricing fallback +- **fix(i18n):** complete Simplified Chinese translations (#2115) +- **fix(mitm):** add Linux cert install and skip sudo password when root (#1999) +- **fix(mitm):** prevent stub from loading at runtime via bypass module - **fix:** remove Anthropic-Beta header from non-Anthropic providers to fix identity contamination (#1989) - **fix(cli):** resolve .env loading failure for global npm installations +- **fix(export):** exclude telemetry/usage-history tables from JSON config backups by default to prevent unbounded file growth (#2125) +- **fix:** Follow OpenAI specification, handle throttling in batch and fix UI (#2045) -### 🔒 Security +### Seguridad +- **fix(security):** remediate CodeQL vulnerabilities (ReDoS, cryptographic bias, stack trace exposure, and weak password hashing) (#216, #215, #211, #208, #206, #210) - **fix(security):** remediate regex validation backtracking path in core compression cleanup (#1990) - **fix(core):** harden input handling and stabilization for prompt compression edge cases +### Dokumentasyon + +- **docs:** add competitive marketing tables and SEO/AEO optimizations to README (#2091) +- **docs:** refresh providers, model catalogs, and docs for v3.8.0 (#2088) +- **docs:** update Claude MD and update GLM-CN max context to 200k (#2027) +- **docs(env):** add `GITLAB_DUO_OAUTH_CLIENT_ID` to `.env.example` (#2031) + ### 🧹 Chores & Maintenance - **chore(providers):** prune redundant local provider icon assets in favor of `@lobehub/icons` web fonts (#1992) +- **chore(providers):** remove deprecated models (#2033) +- **deps:** bump `fast-uri` from 3.1.0 to 3.1.2 (#2078) +- **deps:** bump `hono` from 4.12.14 to 4.12.18 (#2079) - **ci:** skip SonarCloud scan on main pushes to optimize CI time - **test:** stabilize cooldown abort coverage case in integration testing +### 🏆 v3.8.0 Community Contributors + +Thank you to all **38 community contributors** who made v3.8.0 possible! 🎉 + +| Contributor | PRs | Contributions | +| :--------------------------------------------------------- | :-: | :------------------------------------------------------------ | +| [@oyi77](https://github.com/oyi77) | 7 | #2010, #2014, #2041, #2052, #2061, #2074, #2091, #2094, #2096 | +| [@backryun](https://github.com/backryun) | 4 | #1992, #2033, #2088, #2123 | +| [@dhaern](https://github.com/dhaern) | 4 | #2028, #2039, #2087, #2090 | +| [@Tentoxa](https://github.com/Tentoxa) | 2 | #2011, #2053 | +| [@wauputr4](https://github.com/wauputr4) | 2 | #2009, #2046 | +| [@payne0420](https://github.com/payne0420) | 1 | #2082 | +| [@Tr0sT](https://github.com/Tr0sT) | 1 | #2012 | +| [@AveryanAlex](https://github.com/AveryanAlex) | 1 | #2008 | +| [@nickwizard](https://github.com/nickwizard) | 1 | #1991 | +| [@rodrigogbbr-stack](https://github.com/rodrigogbbr-stack) | 1 | #1996 | +| [@NekoMonci12](https://github.com/NekoMonci12) | 1 | #1999 | +| [@congvc-dev](https://github.com/congvc-dev) | 1 | #2004 | +| [@tatsster](https://github.com/tatsster) | 1 | #2007 | +| [@xssdem](https://github.com/xssdem) | 1 | #2023 | +| [@bypanghu](https://github.com/bypanghu) | 1 | #2027 | +| [@herjarsa](https://github.com/herjarsa) | 1 | #2030 | +| [@wucm667](https://github.com/wucm667) | 1 | #2031 | +| [@hartmark](https://github.com/hartmark) | 1 | #2045 | +| [@ddarkr](https://github.com/ddarkr) | 1 | #2047 | +| [@tces1](https://github.com/tces1) | 1 | #2048 | +| [@guanbear](https://github.com/guanbear) | 1 | #2054 | +| [@Gi99lin](https://github.com/Gi99lin) | 1 | #2055 | +| [@ivan-mezentsev](https://github.com/ivan-mezentsev) | 1 | #2063 | +| [@JxnLexn](https://github.com/JxnLexn) | 1 | #2019 | +| [@yoviarpauzi](https://github.com/yoviarpauzi) | 1 | #2092 | +| [@rafacpti23](https://github.com/rafacpti23) | 1 | #2086 | +| [@gleber](https://github.com/gleber) | 1 | #2103 | +| [@rilham97](https://github.com/rilham97) | 1 | #2104 | +| [@Gioxaa](https://github.com/Gioxaa) | 1 | #2105 | +| [@boa-z](https://github.com/boa-z) | 1 | #2115 | +| [@eleata](https://github.com/eleata) | 1 | #2116 | +| [@rdself](https://github.com/rdself) | 1 | #2118 | +| [@clousky2020](https://github.com/clousky2020) | 1 | #2119 | +| [@abhinavjnu](https://github.com/abhinavjnu) | 1 | #2122 | +| [@HoaPham98](https://github.com/HoaPham98) | 1 | #2089 | +| [@05dunski](https://github.com/05dunski) | 1 | #1978 (cherry-picked) | + ## [3.7.9] — 2026-05-03 ### ✨ New Features @@ -102,7 +220,7 @@ - **chore(provider):** Add reka models list (#1956 — thanks @backryun) - **chore(model):** Update new models, Delete Deprecated models (#1949 — thanks @backryun) -### 📝 Documentation +### Dokumentasyon - **docs(compression):** document RTK+Caveman stacked savings ranges @@ -201,7 +319,7 @@ - **feat(db):** auto-restore probe-failed database on startup to prevent data loss after failed upgrades (#1810) - **feat(analytics):** add cost-based usage insights and activity streaks in the analytics dashboard -### 🔒 Security +### Seguridad - **fix(security):** resolve ReDoS vulnerability in Codex executor regex patterns (#1797, #1789) @@ -354,7 +472,7 @@ We identified that **155 community PRs** across the entire project history (from - **feat(proxy):** implement bulk proxy import via pipe-delimited parser with update-or-create (upsert) logic and real-time preview table - **feat(pwa):** add fullscreen installable PWA with manifest, service worker, and cross-platform app icons (#1728) -### 🔒 Security +### Seguridad - **security:** replace insecure `Math.random` with `crypto.getRandomValues` for fallback UUID generation to resolve CodeQL CWE-338 finding (#182) @@ -519,7 +637,7 @@ We identified that **155 community PRs** across the entire project history (from - **fix(transport):** Prevent memory bloat and database exhaustion from large, fragmented streaming responses. Implemented `ByteQueue` in `kiro.ts` for zero-copy binary accumulation, refactored `antigravity.ts` for incremental SSE parsing, and enforced a strict 512KB tiered truncation limit (`MAX_CALL_LOG_ARTIFACT_BYTES`) on stream request logs and call artifacts (#1647). - **chore(ci):** Update build environment dependencies — bump Node to `24.15.0`, `actions/checkout@v6`, `docker/build-push-action@v7`, pin `actions/setup-python` to major tag (#1646 — thanks @backryun). -### 📝 Documentation +### Dokumentasyon - **docs(env):** Add `OMNIROUTE_ALLOW_PRIVATE_PROVIDER_URLS` to `.env.example` with documentation for LM Studio and other local provider use cases (#1623). @@ -669,7 +787,7 @@ We identified that **155 community PRs** across the entire project history (from - **test(next):** Align transpile package expectations for the Next.js standalone build. - **test(ci):** Fix CI-only test failures from environment differences — clear `INITIAL_PASSWORD` and `JWT_SECRET` in integration tests, handle `XDG_CONFIG_HOME` for guide-settings tests. -### 📚 Documentation +### Dokumentasyon - **docs:** Update the root changelog with all release-branch changes through 2026-04-24, including PRs #1544, #1555, #1551, #1550, #1548, #1547, #1541, #1538, #1536, and #1527. - **docs:** Fix broken README and localized documentation links. (#1536) @@ -811,7 +929,7 @@ We identified that **155 community PRs** across the entire project history (from - **feat(providers):** Expand image provider registry with extended model support including SD3.5, FLUX, and DALL-E 3 HD configurations - **feat(combos):** Add new routing strategies and full i18n support for agent features section across 31 languages -### 🔒 Security +### Seguridad - **security:** Resolve 18 GitHub CodeQL scan alerts including ReDoS, incomplete sanitization, and bad HTML filtering regexp patterns - **fix(auth):** Seal privilege escalation vector by enforcing JWT session checking exclusively on `/api/keys` management endpoints (#1353) @@ -1078,7 +1196,7 @@ We identified that **155 community PRs** across the entire project history (from - **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 - **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 -### 🔒 Security +### Seguridad - **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 - **Auth Guard on Translator Save:** Added `isAuthenticated` guard to `/api/translator/save` for defense-in-depth consistency @@ -1483,7 +1601,7 @@ We identified that **155 community PRs** across the entire project history (from - **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). -### 📚 Documentation +### Dokumentasyon - **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. - **Context Relay Delivery Notes:** Documented the current architecture, runtime flow, and Codex-focused scope in the feature docs, changelog, and agent guidance. @@ -1559,7 +1677,7 @@ We identified that **155 community PRs** across the entire project history (from ## [3.5.3] - 2026-04-07 -### Security +### Seguridad - **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. - **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. @@ -1575,7 +1693,7 @@ We identified that **155 community PRs** across the entire project history (from - **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. -### Documentation +### Dokumentasyon - **I18n Engine:** Synchronized and pushed deep Machine Translation updates across all 32 natively-supported languages (682 translation nodes aligned). @@ -1736,7 +1854,7 @@ We identified that **155 community PRs** across the entire project history (from ## [3.4.8] — 2026-04-03 -### Security +### Seguridad - Fully remediated all outstanding Github Advanced Security (CodeQL) findings and Dependabot alerts. - Fixed insecure randomness vulnerabilities by migrating from `Math.random` to `crypto.randomUUID()`. @@ -1748,7 +1866,7 @@ We identified that **155 community PRs** across the entire project history (from ## [3.4.7] — 2026-04-03 -### Features +### Mga Tampok - Added `Cryptography` node to Monitoring and MCP health checks (#798) - Hardened model-catalog route permissions mapping (`/models`) (#781) @@ -1764,7 +1882,7 @@ We identified that **155 community PRs** across the entire project history (from - Fixed MCP standalone module-resolution (`ERR_MODULE_NOT_FOUND`) via `esbuild` (#936) - Fixed NVIDIA NIM routing credential resolution alias mismatch (#931) -### Security +### Seguridad - Added safe strict input boundary protection against raw `shell: true` remote-code execution injections. @@ -2011,7 +2129,7 @@ We identified that **155 community PRs** across the entire project history (from ## [3.4.0] - 2026-03-31 -### 🚀 Features +### Mga Tampok - **Subscription Utilization Analytics:** Added quota snapshot time-series tracking, Provider Utilization and Combo Health tabs with recharts visualizations, and corresponding API endpoints (#847) - **SQLite Backup Control:** New `OMNIROUTE_DISABLE_AUTO_BACKUP` env flag to disable automatic SQLite backups (#846) @@ -2063,7 +2181,7 @@ We identified that **155 community PRs** across the entire project history (from ## [3.3.8] - 2026-03-30 -### 🚀 Features +### Mga Tampok - **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) - **Qoder Integration:** Native integration for Qoder AI natively replacing the legacy iFlow platform mappings (#660) @@ -2889,7 +3007,7 @@ We identified that **155 community PRs** across the entire project history (from - **NaN tokens in Claude Code / client responses (#617):** - `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 -### 🔒 Security +### Seguridad - Updated `yaml` package to fix stack overflow vulnerability (GHSA-48c2-rrv3-qjmp) @@ -3565,7 +3683,7 @@ docker pull diegosouzapw/omniroute:3.0.0 - **SVG fallback**: `ProviderIcon` component updated with 4-tier strategy: Lobehub → PNG → SVG → Generic icon - **Agents fingerprinting**: Synced with CLI tools — added droid, openclaw, copilot, opencode to fingerprint list (14 total) -### 🔒 Security +### Seguridad - **CVE fix**: Resolved dompurify XSS vulnerability (GHSA-v2wj-7wpq-c8vv) via npm overrides forcing `dompurify@^3.3.2` - `npm audit` now reports **0 vulnerabilities** @@ -3928,7 +4046,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **#510** — Windows: MSYS2/Git-Bash paths (`/c/Program Files/...`) are now normalized to `C:\Program Files\...` - **#492** — `omniroute` CLI now detects `mise`/`nvm` when `app/server.js` is missing and shows targeted fix -### 📖 Documentation +### Dokumentasyon - **#513** — Docker password reset: `INITIAL_PASSWORD` env var workaround documented - **#520** — pnpm: `pnpm approve-builds better-sqlite3` documented @@ -4025,7 +4143,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **feat(executors/cloudflare-ai)**: New `CloudflareAIExecutor` — dynamic URL construction requires `accountId` in provider credentials - **feat(executors)**: Register `pollinations`, `pol`, `cloudflare-ai`, `cf` executor mappings -### 📝 Documentation +### Dokumentasyon - **docs(readme)**: Expanded free combo stack to 11 providers ($0 forever) - **docs(readme)**: Added 4 new free provider sections (LongCat, Pollinations, Cloudflare AI, Scaleway) with model tables @@ -4177,7 +4295,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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). -### Features +### Mga Tampok - **"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. @@ -4205,7 +4323,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Merge PR #494 (MiniMax role fix), fix KIRO MITM dashboard, triage 8 issues. -### Features +### Mga Tampok - **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. - **roleNormalizer**: `normalizeDeveloperRole()` now accepts `preserveDeveloperRole` parameter with tri-state behavior (undefined=keep, true=keep, false=convert). @@ -4261,7 +4379,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Gemini CLI deprecation, VM guide i18n fix, dependabot security fix, provider schema expansion. -### Features +### Mga Tampok - **Gemini CLI Deprecation** (#462): Mark `gemini-cli` provider as deprecated with warning — Google restricts third-party OAuth usage from March 2026 - **Provider Schema** (#462): Expand Zod validation with `deprecated`, `deprecationReason`, `hasFree`, `freeNote`, `authHint`, `apiHint` optional fields @@ -4270,7 +4388,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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) -### Security +### Seguridad - **deps**: Bump `flatted` 3.3.3 → 3.4.2 — fixes CWE-1321 prototype pollution (#484, @dependabot) @@ -4290,7 +4408,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Czech i18n, SSE protocol fix, VM guide translation. -### Features +### Mga Tampok - **Czech Language** (#482): Full Czech (cs) i18n — 22 docs, 2606 UI strings, language switcher updates (@zen0bit) - **VM Deployment Guide**: Translated from Portuguese to English as the source document (@zen0bit) @@ -4309,7 +4427,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: 2 merged PRs, model aliases routing fix, log export, and issue triage. -### Features +### Mga Tampok - **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) @@ -4329,7 +4447,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Five community PRs — streaming call log fixes, Kiro compatibility, cache token analytics, Chinese translation, and configurable tool call IDs. -### ✨ Features +### Mga Tampok - **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) - **feat(providers)**: Per-model configurable 9-char tool call ID normalization (Mistral-style) — only models with the option enabled get truncated IDs (#470) @@ -4359,7 +4477,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Bailian Coding Plan provider with editable base URLs, plus community contributions for Alibaba Cloud and Kimi Coding. -### ✨ Features +### Mga Tampok - **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) - **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) @@ -4374,7 +4492,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Two new community-contributed providers (Alibaba Cloud Coding, Kimi Coding API-key) and Docker pino fix. -### ✨ Features +### Mga Tampok - **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) - **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) @@ -4399,7 +4517,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Codex responses subpath passthrough natively supported, Windows MITM crash fixed, and Combos agent schemas adjusted. -### ✨ Features +### Mga Tampok - **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) @@ -4439,7 +4557,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **fix(budget)**: "Save Limits" no longer returns 422 — `warningThreshold` is now correctly sent as fraction (0–1) instead of percentage (0–100) (#451) - **fix(combos)**: `` internal cache tag is now stripped before forwarding requests to providers, preventing cache session breaks (#454) -### ✨ Features +### Mga Tampok - **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) @@ -4495,7 +4613,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Search Tools dashboard, i18n fixes, Copilot limits, Serper validation fix. -### 🚀 Features +### Mga Tampok - **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) - New route: `/dashboard/search-tools` @@ -4595,7 +4713,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - DB migration: `request_type` column on `call_logs` for non-chat request tracking - Zod validation (`v1SearchSchema`), auth-gated, cost recorded via `recordCost()` -### 🔒 Security +### Seguridad - **deps**: Next.js 16.1.6 → 16.1.7 — fixes 6 CVEs: - **Critical**: CVE-2026-29057 (HTTP request smuggling via http-proxy) @@ -4725,7 +4843,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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**: New `request_detail_logs` table with 500-entry ring-buffer trigger, opt-in via settings toggle -### ✨ Features +### Mga Tampok - **feat(combo)**: System Message Override per Combo (#399 — `system_message` field replaces or injects system prompt before forwarding to provider) - **feat(combo)**: Tool Filter Regex per Combo (#399 — `tool_filter_regex` keeps only tools matching pattern; supports OpenAI + Anthropic formats) @@ -4740,7 +4858,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: SSE improvements, local provider_nodes extensions, proxy registry, Claude passthrough fixes. -### ✨ Features +### Mga Tampok - **feat(health)**: Background health check for local `provider_nodes` with exponential backoff (30s→300s) and `Promise.allSettled` to avoid blocking (#423, @Regis-RCR) - **feat(embeddings)**: Route `/v1/embeddings` to local `provider_nodes` — `buildDynamicEmbeddingProvider()` with hostname validation (#422, @Regis-RCR) @@ -4882,7 +5000,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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 - **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). -### ✨ Features +### Mga Tampok - **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) @@ -4912,7 +5030,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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) - **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) -### ✨ Features +### Mga Tampok - **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) - **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. @@ -4971,7 +5089,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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) - **fix(logs)**: Request log table is now readable in light mode — status badges, token counts, and combo tags use adaptive `dark:` color classes (#378) -### ✨ Features +### Mga Tampok - **feat(kiro)**: Kiro credit tracking added to usage fetcher — queries `getUserCredits` from AWS CodeWhisperer endpoint (#337) @@ -5372,7 +5490,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > **Major release** — Free Stack ecosystem, transcription playground overhaul, 44+ providers, comprehensive free tier documentation, and UI improvements across the board. -### ✨ Features +### Mga Tampok - **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. - **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. @@ -5383,7 +5501,7 @@ OmniRoute now automatically refreshes model lists for connected providers every ## [2.3.16] - 2026-03-13 -### 📖 Documentation +### Dokumentasyon - **README: 44+ Providers** — Updated all 3 occurrences of "36+ providers" to "44+" reflecting the actual codebase count (44 providers in providers.ts) - **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. @@ -5393,7 +5511,7 @@ OmniRoute now automatically refreshes model lists for connected providers every ## [2.3.15] - 2026-03-13 -### ✨ Features +### Mga Tampok - **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. - **i18n — autoCombo section**: Added 20 new translation keys for the Auto-Combo dashboard (`title`, `status`, `modePack`, `providerScores`, `factorTierPriority`, etc.) to all 30 language files. diff --git a/docs/i18n/pl/CHANGELOG.md b/docs/i18n/pl/CHANGELOG.md index 0c27ebc757..b6891cc7f8 100644 --- a/docs/i18n/pl/CHANGELOG.md +++ b/docs/i18n/pl/CHANGELOG.md @@ -10,30 +10,148 @@ ### ✨ New Features -- **feat(antigravity):** integrate Antigravity provider with dynamic `maxOutputTokens` calculation (bumping to `thinkingBudget + 1`) and standard Cloud Code envelope payload sanitization (#2055, #2063) +- **feat(antigravity):** integrate Antigravity provider with dynamic `maxOutputTokens` calculation, identity fingerprinting overhaul, and Cloud Code envelope payload sanitization (#2055, #2063) - **feat(gemini-cli):** add custom projectId support for Gemini CLI transport (UI, DB, executor) (#1991) +- **feat(providers):** add KIE media provider support with dynamic polling, text models, and expanded video models catalog +- **feat(providers):** add Z.AI provider support with GLM quota handling and new quota labels +- **feat(providers):** add 9 new free AI providers — LLM7, Lepton, Kluster, UncloseAI, BazaarLink, Completions, Enally, FreeTheAi (#2096) +- **feat(providers):** batch delete provider connections via checkbox multi-select (#2094) +- **feat(cursor):** full OpenAI parity — tool calls, streaming, and session management (#2082) +- **feat(cli):** comprehensive CLI enhancement suite with 20+ new commands including `omniroute providers`, `omniroute combos`, `omniroute doctor` (#2074) +- **feat(cli):** add modular CLI setup and provider management commands (#2046) +- **feat(mcp):** add DeepSeek quota and limit monitoring feature (#2089) +- **feat(circuit-breaker):** classify 429 errors and apply per-kind cooldowns (#2116) +- **feat(multi):** manifest-aware tier routing — W1-W4 complete (#2014) +- **feat(combos):** add reset-aware routing strategy for quota-based providers +- **feat(combo):** add context_length input field to combo edit form (#2047) +- **feat(chat):** dynamic tool limit detection with proactive truncation (#2061) +- **feat(sse):** refresh Claude OAuth wire image to claude-cli/2.1.131 (#2011) +- **feat(github):** add `targetFormat: openai-responses` to all GitHub models (#2122) +- **feat(api):** allow configuration via API calls — open management routes to Bearer keys with manage scope (#2103) +- **feat(api):** update API bridge proxy timeout to 600,000ms (#2019) +- **feat(usage):** add service tier breakdown, codex fast service tier analytics, and account for fast tier +- **feat(chat):** add `STREAM_READINESS_TIMEOUT_MS` and integrate into chat handling +- **feat(combo):** add `fallbackDelayMs` to combo configuration and related settings +- **feat(chat):** enhance error handling for semaphore capacity with fallback logic +- **feat(qdrant):** embedding model discovery (#2086) +- **feat(auth):** per-session sticky routing for Codex (#1887) +- **feat(inworld):** enhance Inworld TTS support (#2123) ### 🐛 Bug Fixes +- **fix(pricing):** make `getPricingForModel` fully case-insensitive to ensure custom prices correctly reflect in new incoming requests cost calculations +- **fix(gemini):** prevent `functionDeclarations` from being dropped by the sanitizer when `googleSearch` tool is present (#2077) +- **fix(pollinations):** add `jsonMode: true` flag in the request transformation to enforce correct JSON structure from Pollinations API (#2109) +- **fix(docker):** update Dockerfile to copy `/docs` directory during build ensuring API catalog availability at runtime (#2083) +- **fix(docker):** include OpenAPI spec in runtime image (#2007) +- **fix(providers):** strip OpenAI-specific fields in Kiro translator to prevent 400 errors (#2037) +- **fix(kiro):** normalize tool-use payloads to prevent 400 errors from agents (#2104) +- **fix(kiro):** merge adjacent user history turns after role normalization (#2105) +- **fix(ui):** resolve text contrast issues for zero-config warning banner in light mode (#2050) +- **fix(core):** inject global system prompt correctly into downstream chat completions pipeline (#2080) +- **fix(core):** restore Claude Code adaptive thinking defaults and resolve audio transcription CORS regression +- **fix(routing):** add missing v1beta rewrites to next.config to resolve 404 on Gemini models endpoint (#2102) +- **fix(routing):** fix bare GPT-5.5 routing for Codex-only installations (#2054) +- **fix(routing):** add fuzzy auto-combo routing for `auto/*` model prefix (#2010) - **fix(cache):** optimize cache_control preservation logic and explicitly align tool schema with upstream Claude Code expectations - **fix(db):** preserve legacy SQLite database path on Windows to prevent data loss (#1973) +- **fix(db):** reduce hot-path persistence overhead (#2039) +- **fix(db):** resolve migration conflict by renumbering overlapping migration entries (#2041) - **fix(settings):** resolve model alias persistence double stringification preventing UI updates (#2018) - **fix(routing):** dynamically filter bare model auto-resolution by active provider connections to prevent dead-routing (#2029) - **fix(embeddings):** add Google Gemini embeddings compatibility via OpenAI-compatible endpoint mapping (#2006) +- **fix(sse):** prevent Claude OAuth multi-account correlation via metadata.user_id (#2053) +- **fix(sse):** prevent Claude Code identity cloak overrides and fix fallback resilience (#2053) +- **fix(sse):** classify hour quota errors as QUOTA_EXHAUSTED (#2119) +- **fix(sse):** fix CC-compatible streaming bridge (#2118) +- **fix(antigravity):** sanitize Claude Cloud Code payloads (#2090) +- **fix(antigravity):** add duplex half for streaming bodies +- **fix(antigravity):** align identity protocol and behavior with official AM +- **fix(chatgpt-web):** plumb proxy through to native tls-client (#2022, #2023) +- **fix(codex):** expose native model IDs in catalog (#2012) +- **fix(glm):** add dedicated coding transport (#2087) +- **fix(compression):** support Responses input and expand Spanish compression rules (#2028) +- **fix(catalog):** auto-calculate combo context_length from target model limits (#2030) +- **fix(api):** fix usage analytics and API key identity (#2008, #2092) +- **fix(api-key):** allow Unicode letters in API key name validation (#1996) +- **fix(auth):** allow bootstrap without password (#2048) +- **fix(proxy):** clean up proxy page redundancy and fix 1proxy sync empty body error (#2052) +- **fix(dashboard):** resolve Unknown plan display in Provider Limits +- **fix(usage):** add extensible CURRENCY_SYMBOLS mapping for deepseek currencies +- **fix(runtime):** harden timer handling and model pricing fallback +- **fix(i18n):** complete Simplified Chinese translations (#2115) +- **fix(mitm):** add Linux cert install and skip sudo password when root (#1999) +- **fix(mitm):** prevent stub from loading at runtime via bypass module - **fix:** remove Anthropic-Beta header from non-Anthropic providers to fix identity contamination (#1989) - **fix(cli):** resolve .env loading failure for global npm installations +- **fix(export):** exclude telemetry/usage-history tables from JSON config backups by default to prevent unbounded file growth (#2125) +- **fix:** Follow OpenAI specification, handle throttling in batch and fix UI (#2045) -### 🔒 Security +### Bezpieczeństwo +- **fix(security):** remediate CodeQL vulnerabilities (ReDoS, cryptographic bias, stack trace exposure, and weak password hashing) (#216, #215, #211, #208, #206, #210) - **fix(security):** remediate regex validation backtracking path in core compression cleanup (#1990) - **fix(core):** harden input handling and stabilization for prompt compression edge cases +### Dokumentacja + +- **docs:** add competitive marketing tables and SEO/AEO optimizations to README (#2091) +- **docs:** refresh providers, model catalogs, and docs for v3.8.0 (#2088) +- **docs:** update Claude MD and update GLM-CN max context to 200k (#2027) +- **docs(env):** add `GITLAB_DUO_OAUTH_CLIENT_ID` to `.env.example` (#2031) + ### 🧹 Chores & Maintenance - **chore(providers):** prune redundant local provider icon assets in favor of `@lobehub/icons` web fonts (#1992) +- **chore(providers):** remove deprecated models (#2033) +- **deps:** bump `fast-uri` from 3.1.0 to 3.1.2 (#2078) +- **deps:** bump `hono` from 4.12.14 to 4.12.18 (#2079) - **ci:** skip SonarCloud scan on main pushes to optimize CI time - **test:** stabilize cooldown abort coverage case in integration testing +### 🏆 v3.8.0 Community Contributors + +Thank you to all **38 community contributors** who made v3.8.0 possible! 🎉 + +| Contributor | PRs | Contributions | +| :--------------------------------------------------------- | :-: | :------------------------------------------------------------ | +| [@oyi77](https://github.com/oyi77) | 7 | #2010, #2014, #2041, #2052, #2061, #2074, #2091, #2094, #2096 | +| [@backryun](https://github.com/backryun) | 4 | #1992, #2033, #2088, #2123 | +| [@dhaern](https://github.com/dhaern) | 4 | #2028, #2039, #2087, #2090 | +| [@Tentoxa](https://github.com/Tentoxa) | 2 | #2011, #2053 | +| [@wauputr4](https://github.com/wauputr4) | 2 | #2009, #2046 | +| [@payne0420](https://github.com/payne0420) | 1 | #2082 | +| [@Tr0sT](https://github.com/Tr0sT) | 1 | #2012 | +| [@AveryanAlex](https://github.com/AveryanAlex) | 1 | #2008 | +| [@nickwizard](https://github.com/nickwizard) | 1 | #1991 | +| [@rodrigogbbr-stack](https://github.com/rodrigogbbr-stack) | 1 | #1996 | +| [@NekoMonci12](https://github.com/NekoMonci12) | 1 | #1999 | +| [@congvc-dev](https://github.com/congvc-dev) | 1 | #2004 | +| [@tatsster](https://github.com/tatsster) | 1 | #2007 | +| [@xssdem](https://github.com/xssdem) | 1 | #2023 | +| [@bypanghu](https://github.com/bypanghu) | 1 | #2027 | +| [@herjarsa](https://github.com/herjarsa) | 1 | #2030 | +| [@wucm667](https://github.com/wucm667) | 1 | #2031 | +| [@hartmark](https://github.com/hartmark) | 1 | #2045 | +| [@ddarkr](https://github.com/ddarkr) | 1 | #2047 | +| [@tces1](https://github.com/tces1) | 1 | #2048 | +| [@guanbear](https://github.com/guanbear) | 1 | #2054 | +| [@Gi99lin](https://github.com/Gi99lin) | 1 | #2055 | +| [@ivan-mezentsev](https://github.com/ivan-mezentsev) | 1 | #2063 | +| [@JxnLexn](https://github.com/JxnLexn) | 1 | #2019 | +| [@yoviarpauzi](https://github.com/yoviarpauzi) | 1 | #2092 | +| [@rafacpti23](https://github.com/rafacpti23) | 1 | #2086 | +| [@gleber](https://github.com/gleber) | 1 | #2103 | +| [@rilham97](https://github.com/rilham97) | 1 | #2104 | +| [@Gioxaa](https://github.com/Gioxaa) | 1 | #2105 | +| [@boa-z](https://github.com/boa-z) | 1 | #2115 | +| [@eleata](https://github.com/eleata) | 1 | #2116 | +| [@rdself](https://github.com/rdself) | 1 | #2118 | +| [@clousky2020](https://github.com/clousky2020) | 1 | #2119 | +| [@abhinavjnu](https://github.com/abhinavjnu) | 1 | #2122 | +| [@HoaPham98](https://github.com/HoaPham98) | 1 | #2089 | +| [@05dunski](https://github.com/05dunski) | 1 | #1978 (cherry-picked) | + ## [3.7.9] — 2026-05-03 ### ✨ New Features @@ -102,7 +220,7 @@ - **chore(provider):** Add reka models list (#1956 — thanks @backryun) - **chore(model):** Update new models, Delete Deprecated models (#1949 — thanks @backryun) -### 📝 Documentation +### Dokumentacja - **docs(compression):** document RTK+Caveman stacked savings ranges @@ -201,7 +319,7 @@ - **feat(db):** auto-restore probe-failed database on startup to prevent data loss after failed upgrades (#1810) - **feat(analytics):** add cost-based usage insights and activity streaks in the analytics dashboard -### 🔒 Security +### Bezpieczeństwo - **fix(security):** resolve ReDoS vulnerability in Codex executor regex patterns (#1797, #1789) @@ -354,7 +472,7 @@ We identified that **155 community PRs** across the entire project history (from - **feat(proxy):** implement bulk proxy import via pipe-delimited parser with update-or-create (upsert) logic and real-time preview table - **feat(pwa):** add fullscreen installable PWA with manifest, service worker, and cross-platform app icons (#1728) -### 🔒 Security +### Bezpieczeństwo - **security:** replace insecure `Math.random` with `crypto.getRandomValues` for fallback UUID generation to resolve CodeQL CWE-338 finding (#182) @@ -519,7 +637,7 @@ We identified that **155 community PRs** across the entire project history (from - **fix(transport):** Prevent memory bloat and database exhaustion from large, fragmented streaming responses. Implemented `ByteQueue` in `kiro.ts` for zero-copy binary accumulation, refactored `antigravity.ts` for incremental SSE parsing, and enforced a strict 512KB tiered truncation limit (`MAX_CALL_LOG_ARTIFACT_BYTES`) on stream request logs and call artifacts (#1647). - **chore(ci):** Update build environment dependencies — bump Node to `24.15.0`, `actions/checkout@v6`, `docker/build-push-action@v7`, pin `actions/setup-python` to major tag (#1646 — thanks @backryun). -### 📝 Documentation +### Dokumentacja - **docs(env):** Add `OMNIROUTE_ALLOW_PRIVATE_PROVIDER_URLS` to `.env.example` with documentation for LM Studio and other local provider use cases (#1623). @@ -669,7 +787,7 @@ We identified that **155 community PRs** across the entire project history (from - **test(next):** Align transpile package expectations for the Next.js standalone build. - **test(ci):** Fix CI-only test failures from environment differences — clear `INITIAL_PASSWORD` and `JWT_SECRET` in integration tests, handle `XDG_CONFIG_HOME` for guide-settings tests. -### 📚 Documentation +### Dokumentacja - **docs:** Update the root changelog with all release-branch changes through 2026-04-24, including PRs #1544, #1555, #1551, #1550, #1548, #1547, #1541, #1538, #1536, and #1527. - **docs:** Fix broken README and localized documentation links. (#1536) @@ -811,7 +929,7 @@ We identified that **155 community PRs** across the entire project history (from - **feat(providers):** Expand image provider registry with extended model support including SD3.5, FLUX, and DALL-E 3 HD configurations - **feat(combos):** Add new routing strategies and full i18n support for agent features section across 31 languages -### 🔒 Security +### Bezpieczeństwo - **security:** Resolve 18 GitHub CodeQL scan alerts including ReDoS, incomplete sanitization, and bad HTML filtering regexp patterns - **fix(auth):** Seal privilege escalation vector by enforcing JWT session checking exclusively on `/api/keys` management endpoints (#1353) @@ -1078,7 +1196,7 @@ We identified that **155 community PRs** across the entire project history (from - **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 - **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 -### 🔒 Security +### Bezpieczeństwo - **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 - **Auth Guard on Translator Save:** Added `isAuthenticated` guard to `/api/translator/save` for defense-in-depth consistency @@ -1483,7 +1601,7 @@ We identified that **155 community PRs** across the entire project history (from - **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). -### 📚 Documentation +### Dokumentacja - **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. - **Context Relay Delivery Notes:** Documented the current architecture, runtime flow, and Codex-focused scope in the feature docs, changelog, and agent guidance. @@ -1559,7 +1677,7 @@ We identified that **155 community PRs** across the entire project history (from ## [3.5.3] - 2026-04-07 -### Security +### Bezpieczeństwo - **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. - **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. @@ -1575,7 +1693,7 @@ We identified that **155 community PRs** across the entire project history (from - **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. -### Documentation +### Dokumentacja - **I18n Engine:** Synchronized and pushed deep Machine Translation updates across all 32 natively-supported languages (682 translation nodes aligned). @@ -1736,7 +1854,7 @@ We identified that **155 community PRs** across the entire project history (from ## [3.4.8] — 2026-04-03 -### Security +### Bezpieczeństwo - Fully remediated all outstanding Github Advanced Security (CodeQL) findings and Dependabot alerts. - Fixed insecure randomness vulnerabilities by migrating from `Math.random` to `crypto.randomUUID()`. @@ -1748,7 +1866,7 @@ We identified that **155 community PRs** across the entire project history (from ## [3.4.7] — 2026-04-03 -### Features +### Funkcje - Added `Cryptography` node to Monitoring and MCP health checks (#798) - Hardened model-catalog route permissions mapping (`/models`) (#781) @@ -1764,7 +1882,7 @@ We identified that **155 community PRs** across the entire project history (from - Fixed MCP standalone module-resolution (`ERR_MODULE_NOT_FOUND`) via `esbuild` (#936) - Fixed NVIDIA NIM routing credential resolution alias mismatch (#931) -### Security +### Bezpieczeństwo - Added safe strict input boundary protection against raw `shell: true` remote-code execution injections. @@ -2011,7 +2129,7 @@ We identified that **155 community PRs** across the entire project history (from ## [3.4.0] - 2026-03-31 -### 🚀 Features +### Funkcje - **Subscription Utilization Analytics:** Added quota snapshot time-series tracking, Provider Utilization and Combo Health tabs with recharts visualizations, and corresponding API endpoints (#847) - **SQLite Backup Control:** New `OMNIROUTE_DISABLE_AUTO_BACKUP` env flag to disable automatic SQLite backups (#846) @@ -2063,7 +2181,7 @@ We identified that **155 community PRs** across the entire project history (from ## [3.3.8] - 2026-03-30 -### 🚀 Features +### Funkcje - **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) - **Qoder Integration:** Native integration for Qoder AI natively replacing the legacy iFlow platform mappings (#660) @@ -2889,7 +3007,7 @@ We identified that **155 community PRs** across the entire project history (from - **NaN tokens in Claude Code / client responses (#617):** - `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 -### 🔒 Security +### Bezpieczeństwo - Updated `yaml` package to fix stack overflow vulnerability (GHSA-48c2-rrv3-qjmp) @@ -3565,7 +3683,7 @@ docker pull diegosouzapw/omniroute:3.0.0 - **SVG fallback**: `ProviderIcon` component updated with 4-tier strategy: Lobehub → PNG → SVG → Generic icon - **Agents fingerprinting**: Synced with CLI tools — added droid, openclaw, copilot, opencode to fingerprint list (14 total) -### 🔒 Security +### Bezpieczeństwo - **CVE fix**: Resolved dompurify XSS vulnerability (GHSA-v2wj-7wpq-c8vv) via npm overrides forcing `dompurify@^3.3.2` - `npm audit` now reports **0 vulnerabilities** @@ -3928,7 +4046,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **#510** — Windows: MSYS2/Git-Bash paths (`/c/Program Files/...`) are now normalized to `C:\Program Files\...` - **#492** — `omniroute` CLI now detects `mise`/`nvm` when `app/server.js` is missing and shows targeted fix -### 📖 Documentation +### Dokumentacja - **#513** — Docker password reset: `INITIAL_PASSWORD` env var workaround documented - **#520** — pnpm: `pnpm approve-builds better-sqlite3` documented @@ -4025,7 +4143,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **feat(executors/cloudflare-ai)**: New `CloudflareAIExecutor` — dynamic URL construction requires `accountId` in provider credentials - **feat(executors)**: Register `pollinations`, `pol`, `cloudflare-ai`, `cf` executor mappings -### 📝 Documentation +### Dokumentacja - **docs(readme)**: Expanded free combo stack to 11 providers ($0 forever) - **docs(readme)**: Added 4 new free provider sections (LongCat, Pollinations, Cloudflare AI, Scaleway) with model tables @@ -4177,7 +4295,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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). -### Features +### Funkcje - **"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. @@ -4205,7 +4323,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Merge PR #494 (MiniMax role fix), fix KIRO MITM dashboard, triage 8 issues. -### Features +### Funkcje - **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. - **roleNormalizer**: `normalizeDeveloperRole()` now accepts `preserveDeveloperRole` parameter with tri-state behavior (undefined=keep, true=keep, false=convert). @@ -4261,7 +4379,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Gemini CLI deprecation, VM guide i18n fix, dependabot security fix, provider schema expansion. -### Features +### Funkcje - **Gemini CLI Deprecation** (#462): Mark `gemini-cli` provider as deprecated with warning — Google restricts third-party OAuth usage from March 2026 - **Provider Schema** (#462): Expand Zod validation with `deprecated`, `deprecationReason`, `hasFree`, `freeNote`, `authHint`, `apiHint` optional fields @@ -4270,7 +4388,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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) -### Security +### Bezpieczeństwo - **deps**: Bump `flatted` 3.3.3 → 3.4.2 — fixes CWE-1321 prototype pollution (#484, @dependabot) @@ -4290,7 +4408,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Czech i18n, SSE protocol fix, VM guide translation. -### Features +### Funkcje - **Czech Language** (#482): Full Czech (cs) i18n — 22 docs, 2606 UI strings, language switcher updates (@zen0bit) - **VM Deployment Guide**: Translated from Portuguese to English as the source document (@zen0bit) @@ -4309,7 +4427,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: 2 merged PRs, model aliases routing fix, log export, and issue triage. -### Features +### Funkcje - **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) @@ -4329,7 +4447,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Five community PRs — streaming call log fixes, Kiro compatibility, cache token analytics, Chinese translation, and configurable tool call IDs. -### ✨ Features +### Funkcje - **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) - **feat(providers)**: Per-model configurable 9-char tool call ID normalization (Mistral-style) — only models with the option enabled get truncated IDs (#470) @@ -4359,7 +4477,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Bailian Coding Plan provider with editable base URLs, plus community contributions for Alibaba Cloud and Kimi Coding. -### ✨ Features +### Funkcje - **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) - **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) @@ -4374,7 +4492,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Two new community-contributed providers (Alibaba Cloud Coding, Kimi Coding API-key) and Docker pino fix. -### ✨ Features +### Funkcje - **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) - **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) @@ -4399,7 +4517,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Codex responses subpath passthrough natively supported, Windows MITM crash fixed, and Combos agent schemas adjusted. -### ✨ Features +### Funkcje - **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) @@ -4439,7 +4557,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **fix(budget)**: "Save Limits" no longer returns 422 — `warningThreshold` is now correctly sent as fraction (0–1) instead of percentage (0–100) (#451) - **fix(combos)**: `` internal cache tag is now stripped before forwarding requests to providers, preventing cache session breaks (#454) -### ✨ Features +### Funkcje - **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) @@ -4495,7 +4613,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Search Tools dashboard, i18n fixes, Copilot limits, Serper validation fix. -### 🚀 Features +### Funkcje - **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) - New route: `/dashboard/search-tools` @@ -4595,7 +4713,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - DB migration: `request_type` column on `call_logs` for non-chat request tracking - Zod validation (`v1SearchSchema`), auth-gated, cost recorded via `recordCost()` -### 🔒 Security +### Bezpieczeństwo - **deps**: Next.js 16.1.6 → 16.1.7 — fixes 6 CVEs: - **Critical**: CVE-2026-29057 (HTTP request smuggling via http-proxy) @@ -4725,7 +4843,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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**: New `request_detail_logs` table with 500-entry ring-buffer trigger, opt-in via settings toggle -### ✨ Features +### Funkcje - **feat(combo)**: System Message Override per Combo (#399 — `system_message` field replaces or injects system prompt before forwarding to provider) - **feat(combo)**: Tool Filter Regex per Combo (#399 — `tool_filter_regex` keeps only tools matching pattern; supports OpenAI + Anthropic formats) @@ -4740,7 +4858,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: SSE improvements, local provider_nodes extensions, proxy registry, Claude passthrough fixes. -### ✨ Features +### Funkcje - **feat(health)**: Background health check for local `provider_nodes` with exponential backoff (30s→300s) and `Promise.allSettled` to avoid blocking (#423, @Regis-RCR) - **feat(embeddings)**: Route `/v1/embeddings` to local `provider_nodes` — `buildDynamicEmbeddingProvider()` with hostname validation (#422, @Regis-RCR) @@ -4882,7 +5000,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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 - **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). -### ✨ Features +### Funkcje - **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) @@ -4912,7 +5030,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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) - **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) -### ✨ Features +### Funkcje - **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) - **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. @@ -4971,7 +5089,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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) - **fix(logs)**: Request log table is now readable in light mode — status badges, token counts, and combo tags use adaptive `dark:` color classes (#378) -### ✨ Features +### Funkcje - **feat(kiro)**: Kiro credit tracking added to usage fetcher — queries `getUserCredits` from AWS CodeWhisperer endpoint (#337) @@ -5372,7 +5490,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > **Major release** — Free Stack ecosystem, transcription playground overhaul, 44+ providers, comprehensive free tier documentation, and UI improvements across the board. -### ✨ Features +### Funkcje - **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. - **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. @@ -5383,7 +5501,7 @@ OmniRoute now automatically refreshes model lists for connected providers every ## [2.3.16] - 2026-03-13 -### 📖 Documentation +### Dokumentacja - **README: 44+ Providers** — Updated all 3 occurrences of "36+ providers" to "44+" reflecting the actual codebase count (44 providers in providers.ts) - **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. @@ -5393,7 +5511,7 @@ OmniRoute now automatically refreshes model lists for connected providers every ## [2.3.15] - 2026-03-13 -### ✨ Features +### Funkcje - **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. - **i18n — autoCombo section**: Added 20 new translation keys for the Auto-Combo dashboard (`title`, `status`, `modePack`, `providerScores`, `factorTierPriority`, etc.) to all 30 language files. diff --git a/docs/i18n/pt-BR/CHANGELOG.md b/docs/i18n/pt-BR/CHANGELOG.md index deb79e3b0d..03722be51a 100644 --- a/docs/i18n/pt-BR/CHANGELOG.md +++ b/docs/i18n/pt-BR/CHANGELOG.md @@ -10,30 +10,148 @@ ### ✨ New Features -- **feat(antigravity):** integrate Antigravity provider with dynamic `maxOutputTokens` calculation (bumping to `thinkingBudget + 1`) and standard Cloud Code envelope payload sanitization (#2055, #2063) +- **feat(antigravity):** integrate Antigravity provider with dynamic `maxOutputTokens` calculation, identity fingerprinting overhaul, and Cloud Code envelope payload sanitization (#2055, #2063) - **feat(gemini-cli):** add custom projectId support for Gemini CLI transport (UI, DB, executor) (#1991) +- **feat(providers):** add KIE media provider support with dynamic polling, text models, and expanded video models catalog +- **feat(providers):** add Z.AI provider support with GLM quota handling and new quota labels +- **feat(providers):** add 9 new free AI providers — LLM7, Lepton, Kluster, UncloseAI, BazaarLink, Completions, Enally, FreeTheAi (#2096) +- **feat(providers):** batch delete provider connections via checkbox multi-select (#2094) +- **feat(cursor):** full OpenAI parity — tool calls, streaming, and session management (#2082) +- **feat(cli):** comprehensive CLI enhancement suite with 20+ new commands including `omniroute providers`, `omniroute combos`, `omniroute doctor` (#2074) +- **feat(cli):** add modular CLI setup and provider management commands (#2046) +- **feat(mcp):** add DeepSeek quota and limit monitoring feature (#2089) +- **feat(circuit-breaker):** classify 429 errors and apply per-kind cooldowns (#2116) +- **feat(multi):** manifest-aware tier routing — W1-W4 complete (#2014) +- **feat(combos):** add reset-aware routing strategy for quota-based providers +- **feat(combo):** add context_length input field to combo edit form (#2047) +- **feat(chat):** dynamic tool limit detection with proactive truncation (#2061) +- **feat(sse):** refresh Claude OAuth wire image to claude-cli/2.1.131 (#2011) +- **feat(github):** add `targetFormat: openai-responses` to all GitHub models (#2122) +- **feat(api):** allow configuration via API calls — open management routes to Bearer keys with manage scope (#2103) +- **feat(api):** update API bridge proxy timeout to 600,000ms (#2019) +- **feat(usage):** add service tier breakdown, codex fast service tier analytics, and account for fast tier +- **feat(chat):** add `STREAM_READINESS_TIMEOUT_MS` and integrate into chat handling +- **feat(combo):** add `fallbackDelayMs` to combo configuration and related settings +- **feat(chat):** enhance error handling for semaphore capacity with fallback logic +- **feat(qdrant):** embedding model discovery (#2086) +- **feat(auth):** per-session sticky routing for Codex (#1887) +- **feat(inworld):** enhance Inworld TTS support (#2123) ### 🐛 Bug Fixes +- **fix(pricing):** make `getPricingForModel` fully case-insensitive to ensure custom prices correctly reflect in new incoming requests cost calculations +- **fix(gemini):** prevent `functionDeclarations` from being dropped by the sanitizer when `googleSearch` tool is present (#2077) +- **fix(pollinations):** add `jsonMode: true` flag in the request transformation to enforce correct JSON structure from Pollinations API (#2109) +- **fix(docker):** update Dockerfile to copy `/docs` directory during build ensuring API catalog availability at runtime (#2083) +- **fix(docker):** include OpenAPI spec in runtime image (#2007) +- **fix(providers):** strip OpenAI-specific fields in Kiro translator to prevent 400 errors (#2037) +- **fix(kiro):** normalize tool-use payloads to prevent 400 errors from agents (#2104) +- **fix(kiro):** merge adjacent user history turns after role normalization (#2105) +- **fix(ui):** resolve text contrast issues for zero-config warning banner in light mode (#2050) +- **fix(core):** inject global system prompt correctly into downstream chat completions pipeline (#2080) +- **fix(core):** restore Claude Code adaptive thinking defaults and resolve audio transcription CORS regression +- **fix(routing):** add missing v1beta rewrites to next.config to resolve 404 on Gemini models endpoint (#2102) +- **fix(routing):** fix bare GPT-5.5 routing for Codex-only installations (#2054) +- **fix(routing):** add fuzzy auto-combo routing for `auto/*` model prefix (#2010) - **fix(cache):** optimize cache_control preservation logic and explicitly align tool schema with upstream Claude Code expectations - **fix(db):** preserve legacy SQLite database path on Windows to prevent data loss (#1973) +- **fix(db):** reduce hot-path persistence overhead (#2039) +- **fix(db):** resolve migration conflict by renumbering overlapping migration entries (#2041) - **fix(settings):** resolve model alias persistence double stringification preventing UI updates (#2018) - **fix(routing):** dynamically filter bare model auto-resolution by active provider connections to prevent dead-routing (#2029) - **fix(embeddings):** add Google Gemini embeddings compatibility via OpenAI-compatible endpoint mapping (#2006) +- **fix(sse):** prevent Claude OAuth multi-account correlation via metadata.user_id (#2053) +- **fix(sse):** prevent Claude Code identity cloak overrides and fix fallback resilience (#2053) +- **fix(sse):** classify hour quota errors as QUOTA_EXHAUSTED (#2119) +- **fix(sse):** fix CC-compatible streaming bridge (#2118) +- **fix(antigravity):** sanitize Claude Cloud Code payloads (#2090) +- **fix(antigravity):** add duplex half for streaming bodies +- **fix(antigravity):** align identity protocol and behavior with official AM +- **fix(chatgpt-web):** plumb proxy through to native tls-client (#2022, #2023) +- **fix(codex):** expose native model IDs in catalog (#2012) +- **fix(glm):** add dedicated coding transport (#2087) +- **fix(compression):** support Responses input and expand Spanish compression rules (#2028) +- **fix(catalog):** auto-calculate combo context_length from target model limits (#2030) +- **fix(api):** fix usage analytics and API key identity (#2008, #2092) +- **fix(api-key):** allow Unicode letters in API key name validation (#1996) +- **fix(auth):** allow bootstrap without password (#2048) +- **fix(proxy):** clean up proxy page redundancy and fix 1proxy sync empty body error (#2052) +- **fix(dashboard):** resolve Unknown plan display in Provider Limits +- **fix(usage):** add extensible CURRENCY_SYMBOLS mapping for deepseek currencies +- **fix(runtime):** harden timer handling and model pricing fallback +- **fix(i18n):** complete Simplified Chinese translations (#2115) +- **fix(mitm):** add Linux cert install and skip sudo password when root (#1999) +- **fix(mitm):** prevent stub from loading at runtime via bypass module - **fix:** remove Anthropic-Beta header from non-Anthropic providers to fix identity contamination (#1989) - **fix(cli):** resolve .env loading failure for global npm installations +- **fix(export):** exclude telemetry/usage-history tables from JSON config backups by default to prevent unbounded file growth (#2125) +- **fix:** Follow OpenAI specification, handle throttling in batch and fix UI (#2045) -### 🔒 Security +### Segurança +- **fix(security):** remediate CodeQL vulnerabilities (ReDoS, cryptographic bias, stack trace exposure, and weak password hashing) (#216, #215, #211, #208, #206, #210) - **fix(security):** remediate regex validation backtracking path in core compression cleanup (#1990) - **fix(core):** harden input handling and stabilization for prompt compression edge cases +### Documentação + +- **docs:** add competitive marketing tables and SEO/AEO optimizations to README (#2091) +- **docs:** refresh providers, model catalogs, and docs for v3.8.0 (#2088) +- **docs:** update Claude MD and update GLM-CN max context to 200k (#2027) +- **docs(env):** add `GITLAB_DUO_OAUTH_CLIENT_ID` to `.env.example` (#2031) + ### 🧹 Chores & Maintenance - **chore(providers):** prune redundant local provider icon assets in favor of `@lobehub/icons` web fonts (#1992) +- **chore(providers):** remove deprecated models (#2033) +- **deps:** bump `fast-uri` from 3.1.0 to 3.1.2 (#2078) +- **deps:** bump `hono` from 4.12.14 to 4.12.18 (#2079) - **ci:** skip SonarCloud scan on main pushes to optimize CI time - **test:** stabilize cooldown abort coverage case in integration testing +### 🏆 v3.8.0 Community Contributors + +Thank you to all **38 community contributors** who made v3.8.0 possible! 🎉 + +| Contributor | PRs | Contributions | +| :--------------------------------------------------------- | :-: | :------------------------------------------------------------ | +| [@oyi77](https://github.com/oyi77) | 7 | #2010, #2014, #2041, #2052, #2061, #2074, #2091, #2094, #2096 | +| [@backryun](https://github.com/backryun) | 4 | #1992, #2033, #2088, #2123 | +| [@dhaern](https://github.com/dhaern) | 4 | #2028, #2039, #2087, #2090 | +| [@Tentoxa](https://github.com/Tentoxa) | 2 | #2011, #2053 | +| [@wauputr4](https://github.com/wauputr4) | 2 | #2009, #2046 | +| [@payne0420](https://github.com/payne0420) | 1 | #2082 | +| [@Tr0sT](https://github.com/Tr0sT) | 1 | #2012 | +| [@AveryanAlex](https://github.com/AveryanAlex) | 1 | #2008 | +| [@nickwizard](https://github.com/nickwizard) | 1 | #1991 | +| [@rodrigogbbr-stack](https://github.com/rodrigogbbr-stack) | 1 | #1996 | +| [@NekoMonci12](https://github.com/NekoMonci12) | 1 | #1999 | +| [@congvc-dev](https://github.com/congvc-dev) | 1 | #2004 | +| [@tatsster](https://github.com/tatsster) | 1 | #2007 | +| [@xssdem](https://github.com/xssdem) | 1 | #2023 | +| [@bypanghu](https://github.com/bypanghu) | 1 | #2027 | +| [@herjarsa](https://github.com/herjarsa) | 1 | #2030 | +| [@wucm667](https://github.com/wucm667) | 1 | #2031 | +| [@hartmark](https://github.com/hartmark) | 1 | #2045 | +| [@ddarkr](https://github.com/ddarkr) | 1 | #2047 | +| [@tces1](https://github.com/tces1) | 1 | #2048 | +| [@guanbear](https://github.com/guanbear) | 1 | #2054 | +| [@Gi99lin](https://github.com/Gi99lin) | 1 | #2055 | +| [@ivan-mezentsev](https://github.com/ivan-mezentsev) | 1 | #2063 | +| [@JxnLexn](https://github.com/JxnLexn) | 1 | #2019 | +| [@yoviarpauzi](https://github.com/yoviarpauzi) | 1 | #2092 | +| [@rafacpti23](https://github.com/rafacpti23) | 1 | #2086 | +| [@gleber](https://github.com/gleber) | 1 | #2103 | +| [@rilham97](https://github.com/rilham97) | 1 | #2104 | +| [@Gioxaa](https://github.com/Gioxaa) | 1 | #2105 | +| [@boa-z](https://github.com/boa-z) | 1 | #2115 | +| [@eleata](https://github.com/eleata) | 1 | #2116 | +| [@rdself](https://github.com/rdself) | 1 | #2118 | +| [@clousky2020](https://github.com/clousky2020) | 1 | #2119 | +| [@abhinavjnu](https://github.com/abhinavjnu) | 1 | #2122 | +| [@HoaPham98](https://github.com/HoaPham98) | 1 | #2089 | +| [@05dunski](https://github.com/05dunski) | 1 | #1978 (cherry-picked) | + ## [3.7.9] — 2026-05-03 ### ✨ New Features @@ -102,7 +220,7 @@ - **chore(provider):** Add reka models list (#1956 — thanks @backryun) - **chore(model):** Update new models, Delete Deprecated models (#1949 — thanks @backryun) -### 📝 Documentation +### Documentação - **docs(compression):** document RTK+Caveman stacked savings ranges @@ -201,7 +319,7 @@ - **feat(db):** auto-restore probe-failed database on startup to prevent data loss after failed upgrades (#1810) - **feat(analytics):** add cost-based usage insights and activity streaks in the analytics dashboard -### 🔒 Security +### Segurança - **fix(security):** resolve ReDoS vulnerability in Codex executor regex patterns (#1797, #1789) @@ -354,7 +472,7 @@ We identified that **155 community PRs** across the entire project history (from - **feat(proxy):** implement bulk proxy import via pipe-delimited parser with update-or-create (upsert) logic and real-time preview table - **feat(pwa):** add fullscreen installable PWA with manifest, service worker, and cross-platform app icons (#1728) -### 🔒 Security +### Segurança - **security:** replace insecure `Math.random` with `crypto.getRandomValues` for fallback UUID generation to resolve CodeQL CWE-338 finding (#182) @@ -519,7 +637,7 @@ We identified that **155 community PRs** across the entire project history (from - **fix(transport):** Prevent memory bloat and database exhaustion from large, fragmented streaming responses. Implemented `ByteQueue` in `kiro.ts` for zero-copy binary accumulation, refactored `antigravity.ts` for incremental SSE parsing, and enforced a strict 512KB tiered truncation limit (`MAX_CALL_LOG_ARTIFACT_BYTES`) on stream request logs and call artifacts (#1647). - **chore(ci):** Update build environment dependencies — bump Node to `24.15.0`, `actions/checkout@v6`, `docker/build-push-action@v7`, pin `actions/setup-python` to major tag (#1646 — thanks @backryun). -### 📝 Documentation +### Documentação - **docs(env):** Add `OMNIROUTE_ALLOW_PRIVATE_PROVIDER_URLS` to `.env.example` with documentation for LM Studio and other local provider use cases (#1623). @@ -669,7 +787,7 @@ We identified that **155 community PRs** across the entire project history (from - **test(next):** Align transpile package expectations for the Next.js standalone build. - **test(ci):** Fix CI-only test failures from environment differences — clear `INITIAL_PASSWORD` and `JWT_SECRET` in integration tests, handle `XDG_CONFIG_HOME` for guide-settings tests. -### 📚 Documentation +### Documentação - **docs:** Update the root changelog with all release-branch changes through 2026-04-24, including PRs #1544, #1555, #1551, #1550, #1548, #1547, #1541, #1538, #1536, and #1527. - **docs:** Fix broken README and localized documentation links. (#1536) @@ -811,7 +929,7 @@ We identified that **155 community PRs** across the entire project history (from - **feat(providers):** Expand image provider registry with extended model support including SD3.5, FLUX, and DALL-E 3 HD configurations - **feat(combos):** Add new routing strategies and full i18n support for agent features section across 31 languages -### 🔒 Security +### Segurança - **security:** Resolve 18 GitHub CodeQL scan alerts including ReDoS, incomplete sanitization, and bad HTML filtering regexp patterns - **fix(auth):** Seal privilege escalation vector by enforcing JWT session checking exclusively on `/api/keys` management endpoints (#1353) @@ -1078,7 +1196,7 @@ We identified that **155 community PRs** across the entire project history (from - **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 - **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 -### 🔒 Security +### Segurança - **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 - **Auth Guard on Translator Save:** Added `isAuthenticated` guard to `/api/translator/save` for defense-in-depth consistency @@ -1483,7 +1601,7 @@ We identified that **155 community PRs** across the entire project history (from - **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). -### 📚 Documentation +### Documentação - **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. - **Context Relay Delivery Notes:** Documented the current architecture, runtime flow, and Codex-focused scope in the feature docs, changelog, and agent guidance. @@ -1559,7 +1677,7 @@ We identified that **155 community PRs** across the entire project history (from ## [3.5.3] - 2026-04-07 -### Security +### Segurança - **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. - **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. @@ -1575,7 +1693,7 @@ We identified that **155 community PRs** across the entire project history (from - **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. -### Documentation +### Documentação - **I18n Engine:** Synchronized and pushed deep Machine Translation updates across all 32 natively-supported languages (682 translation nodes aligned). @@ -1736,7 +1854,7 @@ We identified that **155 community PRs** across the entire project history (from ## [3.4.8] — 2026-04-03 -### Security +### Segurança - Fully remediated all outstanding Github Advanced Security (CodeQL) findings and Dependabot alerts. - Fixed insecure randomness vulnerabilities by migrating from `Math.random` to `crypto.randomUUID()`. @@ -1748,7 +1866,7 @@ We identified that **155 community PRs** across the entire project history (from ## [3.4.7] — 2026-04-03 -### Features +### Funcionalidades - Added `Cryptography` node to Monitoring and MCP health checks (#798) - Hardened model-catalog route permissions mapping (`/models`) (#781) @@ -1764,7 +1882,7 @@ We identified that **155 community PRs** across the entire project history (from - Fixed MCP standalone module-resolution (`ERR_MODULE_NOT_FOUND`) via `esbuild` (#936) - Fixed NVIDIA NIM routing credential resolution alias mismatch (#931) -### Security +### Segurança - Added safe strict input boundary protection against raw `shell: true` remote-code execution injections. @@ -2011,7 +2129,7 @@ We identified that **155 community PRs** across the entire project history (from ## [3.4.0] - 2026-03-31 -### 🚀 Features +### Funcionalidades - **Subscription Utilization Analytics:** Added quota snapshot time-series tracking, Provider Utilization and Combo Health tabs with recharts visualizations, and corresponding API endpoints (#847) - **SQLite Backup Control:** New `OMNIROUTE_DISABLE_AUTO_BACKUP` env flag to disable automatic SQLite backups (#846) @@ -2063,7 +2181,7 @@ We identified that **155 community PRs** across the entire project history (from ## [3.3.8] - 2026-03-30 -### 🚀 Features +### Funcionalidades - **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) - **Qoder Integration:** Native integration for Qoder AI natively replacing the legacy iFlow platform mappings (#660) @@ -2889,7 +3007,7 @@ We identified that **155 community PRs** across the entire project history (from - **NaN tokens in Claude Code / client responses (#617):** - `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 -### 🔒 Security +### Segurança - Updated `yaml` package to fix stack overflow vulnerability (GHSA-48c2-rrv3-qjmp) @@ -3565,7 +3683,7 @@ docker pull diegosouzapw/omniroute:3.0.0 - **SVG fallback**: `ProviderIcon` component updated with 4-tier strategy: Lobehub → PNG → SVG → Generic icon - **Agents fingerprinting**: Synced with CLI tools — added droid, openclaw, copilot, opencode to fingerprint list (14 total) -### 🔒 Security +### Segurança - **CVE fix**: Resolved dompurify XSS vulnerability (GHSA-v2wj-7wpq-c8vv) via npm overrides forcing `dompurify@^3.3.2` - `npm audit` now reports **0 vulnerabilities** @@ -3928,7 +4046,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **#510** — Windows: MSYS2/Git-Bash paths (`/c/Program Files/...`) are now normalized to `C:\Program Files\...` - **#492** — `omniroute` CLI now detects `mise`/`nvm` when `app/server.js` is missing and shows targeted fix -### 📖 Documentation +### Documentação - **#513** — Docker password reset: `INITIAL_PASSWORD` env var workaround documented - **#520** — pnpm: `pnpm approve-builds better-sqlite3` documented @@ -4025,7 +4143,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **feat(executors/cloudflare-ai)**: New `CloudflareAIExecutor` — dynamic URL construction requires `accountId` in provider credentials - **feat(executors)**: Register `pollinations`, `pol`, `cloudflare-ai`, `cf` executor mappings -### 📝 Documentation +### Documentação - **docs(readme)**: Expanded free combo stack to 11 providers ($0 forever) - **docs(readme)**: Added 4 new free provider sections (LongCat, Pollinations, Cloudflare AI, Scaleway) with model tables @@ -4177,7 +4295,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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). -### Features +### Funcionalidades - **"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. @@ -4205,7 +4323,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Merge PR #494 (MiniMax role fix), fix KIRO MITM dashboard, triage 8 issues. -### Features +### Funcionalidades - **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. - **roleNormalizer**: `normalizeDeveloperRole()` now accepts `preserveDeveloperRole` parameter with tri-state behavior (undefined=keep, true=keep, false=convert). @@ -4261,7 +4379,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Gemini CLI deprecation, VM guide i18n fix, dependabot security fix, provider schema expansion. -### Features +### Funcionalidades - **Gemini CLI Deprecation** (#462): Mark `gemini-cli` provider as deprecated with warning — Google restricts third-party OAuth usage from March 2026 - **Provider Schema** (#462): Expand Zod validation with `deprecated`, `deprecationReason`, `hasFree`, `freeNote`, `authHint`, `apiHint` optional fields @@ -4270,7 +4388,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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) -### Security +### Segurança - **deps**: Bump `flatted` 3.3.3 → 3.4.2 — fixes CWE-1321 prototype pollution (#484, @dependabot) @@ -4290,7 +4408,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Czech i18n, SSE protocol fix, VM guide translation. -### Features +### Funcionalidades - **Czech Language** (#482): Full Czech (cs) i18n — 22 docs, 2606 UI strings, language switcher updates (@zen0bit) - **VM Deployment Guide**: Translated from Portuguese to English as the source document (@zen0bit) @@ -4309,7 +4427,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: 2 merged PRs, model aliases routing fix, log export, and issue triage. -### Features +### Funcionalidades - **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) @@ -4329,7 +4447,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Five community PRs — streaming call log fixes, Kiro compatibility, cache token analytics, Chinese translation, and configurable tool call IDs. -### ✨ Features +### Funcionalidades - **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) - **feat(providers)**: Per-model configurable 9-char tool call ID normalization (Mistral-style) — only models with the option enabled get truncated IDs (#470) @@ -4359,7 +4477,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Bailian Coding Plan provider with editable base URLs, plus community contributions for Alibaba Cloud and Kimi Coding. -### ✨ Features +### Funcionalidades - **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) - **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) @@ -4374,7 +4492,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Two new community-contributed providers (Alibaba Cloud Coding, Kimi Coding API-key) and Docker pino fix. -### ✨ Features +### Funcionalidades - **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) - **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) @@ -4399,7 +4517,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Codex responses subpath passthrough natively supported, Windows MITM crash fixed, and Combos agent schemas adjusted. -### ✨ Features +### Funcionalidades - **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) @@ -4439,7 +4557,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **fix(budget)**: "Save Limits" no longer returns 422 — `warningThreshold` is now correctly sent as fraction (0–1) instead of percentage (0–100) (#451) - **fix(combos)**: `` internal cache tag is now stripped before forwarding requests to providers, preventing cache session breaks (#454) -### ✨ Features +### Funcionalidades - **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) @@ -4495,7 +4613,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Search Tools dashboard, i18n fixes, Copilot limits, Serper validation fix. -### 🚀 Features +### Funcionalidades - **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) - New route: `/dashboard/search-tools` @@ -4595,7 +4713,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - DB migration: `request_type` column on `call_logs` for non-chat request tracking - Zod validation (`v1SearchSchema`), auth-gated, cost recorded via `recordCost()` -### 🔒 Security +### Segurança - **deps**: Next.js 16.1.6 → 16.1.7 — fixes 6 CVEs: - **Critical**: CVE-2026-29057 (HTTP request smuggling via http-proxy) @@ -4725,7 +4843,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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**: New `request_detail_logs` table with 500-entry ring-buffer trigger, opt-in via settings toggle -### ✨ Features +### Funcionalidades - **feat(combo)**: System Message Override per Combo (#399 — `system_message` field replaces or injects system prompt before forwarding to provider) - **feat(combo)**: Tool Filter Regex per Combo (#399 — `tool_filter_regex` keeps only tools matching pattern; supports OpenAI + Anthropic formats) @@ -4740,7 +4858,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: SSE improvements, local provider_nodes extensions, proxy registry, Claude passthrough fixes. -### ✨ Features +### Funcionalidades - **feat(health)**: Background health check for local `provider_nodes` with exponential backoff (30s→300s) and `Promise.allSettled` to avoid blocking (#423, @Regis-RCR) - **feat(embeddings)**: Route `/v1/embeddings` to local `provider_nodes` — `buildDynamicEmbeddingProvider()` with hostname validation (#422, @Regis-RCR) @@ -4882,7 +5000,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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 - **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). -### ✨ Features +### Funcionalidades - **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) @@ -4912,7 +5030,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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) - **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) -### ✨ Features +### Funcionalidades - **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) - **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. @@ -4971,7 +5089,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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) - **fix(logs)**: Request log table is now readable in light mode — status badges, token counts, and combo tags use adaptive `dark:` color classes (#378) -### ✨ Features +### Funcionalidades - **feat(kiro)**: Kiro credit tracking added to usage fetcher — queries `getUserCredits` from AWS CodeWhisperer endpoint (#337) @@ -5372,7 +5490,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > **Major release** — Free Stack ecosystem, transcription playground overhaul, 44+ providers, comprehensive free tier documentation, and UI improvements across the board. -### ✨ Features +### Funcionalidades - **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. - **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. @@ -5383,7 +5501,7 @@ OmniRoute now automatically refreshes model lists for connected providers every ## [2.3.16] - 2026-03-13 -### 📖 Documentation +### Documentação - **README: 44+ Providers** — Updated all 3 occurrences of "36+ providers" to "44+" reflecting the actual codebase count (44 providers in providers.ts) - **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. @@ -5393,7 +5511,7 @@ OmniRoute now automatically refreshes model lists for connected providers every ## [2.3.15] - 2026-03-13 -### ✨ Features +### Funcionalidades - **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. - **i18n — autoCombo section**: Added 20 new translation keys for the Auto-Combo dashboard (`title`, `status`, `modePack`, `providerScores`, `factorTierPriority`, etc.) to all 30 language files. diff --git a/docs/i18n/pt/CHANGELOG.md b/docs/i18n/pt/CHANGELOG.md index f925b7651e..75de8ee268 100644 --- a/docs/i18n/pt/CHANGELOG.md +++ b/docs/i18n/pt/CHANGELOG.md @@ -10,30 +10,148 @@ ### ✨ New Features -- **feat(antigravity):** integrate Antigravity provider with dynamic `maxOutputTokens` calculation (bumping to `thinkingBudget + 1`) and standard Cloud Code envelope payload sanitization (#2055, #2063) +- **feat(antigravity):** integrate Antigravity provider with dynamic `maxOutputTokens` calculation, identity fingerprinting overhaul, and Cloud Code envelope payload sanitization (#2055, #2063) - **feat(gemini-cli):** add custom projectId support for Gemini CLI transport (UI, DB, executor) (#1991) +- **feat(providers):** add KIE media provider support with dynamic polling, text models, and expanded video models catalog +- **feat(providers):** add Z.AI provider support with GLM quota handling and new quota labels +- **feat(providers):** add 9 new free AI providers — LLM7, Lepton, Kluster, UncloseAI, BazaarLink, Completions, Enally, FreeTheAi (#2096) +- **feat(providers):** batch delete provider connections via checkbox multi-select (#2094) +- **feat(cursor):** full OpenAI parity — tool calls, streaming, and session management (#2082) +- **feat(cli):** comprehensive CLI enhancement suite with 20+ new commands including `omniroute providers`, `omniroute combos`, `omniroute doctor` (#2074) +- **feat(cli):** add modular CLI setup and provider management commands (#2046) +- **feat(mcp):** add DeepSeek quota and limit monitoring feature (#2089) +- **feat(circuit-breaker):** classify 429 errors and apply per-kind cooldowns (#2116) +- **feat(multi):** manifest-aware tier routing — W1-W4 complete (#2014) +- **feat(combos):** add reset-aware routing strategy for quota-based providers +- **feat(combo):** add context_length input field to combo edit form (#2047) +- **feat(chat):** dynamic tool limit detection with proactive truncation (#2061) +- **feat(sse):** refresh Claude OAuth wire image to claude-cli/2.1.131 (#2011) +- **feat(github):** add `targetFormat: openai-responses` to all GitHub models (#2122) +- **feat(api):** allow configuration via API calls — open management routes to Bearer keys with manage scope (#2103) +- **feat(api):** update API bridge proxy timeout to 600,000ms (#2019) +- **feat(usage):** add service tier breakdown, codex fast service tier analytics, and account for fast tier +- **feat(chat):** add `STREAM_READINESS_TIMEOUT_MS` and integrate into chat handling +- **feat(combo):** add `fallbackDelayMs` to combo configuration and related settings +- **feat(chat):** enhance error handling for semaphore capacity with fallback logic +- **feat(qdrant):** embedding model discovery (#2086) +- **feat(auth):** per-session sticky routing for Codex (#1887) +- **feat(inworld):** enhance Inworld TTS support (#2123) ### 🐛 Bug Fixes +- **fix(pricing):** make `getPricingForModel` fully case-insensitive to ensure custom prices correctly reflect in new incoming requests cost calculations +- **fix(gemini):** prevent `functionDeclarations` from being dropped by the sanitizer when `googleSearch` tool is present (#2077) +- **fix(pollinations):** add `jsonMode: true` flag in the request transformation to enforce correct JSON structure from Pollinations API (#2109) +- **fix(docker):** update Dockerfile to copy `/docs` directory during build ensuring API catalog availability at runtime (#2083) +- **fix(docker):** include OpenAPI spec in runtime image (#2007) +- **fix(providers):** strip OpenAI-specific fields in Kiro translator to prevent 400 errors (#2037) +- **fix(kiro):** normalize tool-use payloads to prevent 400 errors from agents (#2104) +- **fix(kiro):** merge adjacent user history turns after role normalization (#2105) +- **fix(ui):** resolve text contrast issues for zero-config warning banner in light mode (#2050) +- **fix(core):** inject global system prompt correctly into downstream chat completions pipeline (#2080) +- **fix(core):** restore Claude Code adaptive thinking defaults and resolve audio transcription CORS regression +- **fix(routing):** add missing v1beta rewrites to next.config to resolve 404 on Gemini models endpoint (#2102) +- **fix(routing):** fix bare GPT-5.5 routing for Codex-only installations (#2054) +- **fix(routing):** add fuzzy auto-combo routing for `auto/*` model prefix (#2010) - **fix(cache):** optimize cache_control preservation logic and explicitly align tool schema with upstream Claude Code expectations - **fix(db):** preserve legacy SQLite database path on Windows to prevent data loss (#1973) +- **fix(db):** reduce hot-path persistence overhead (#2039) +- **fix(db):** resolve migration conflict by renumbering overlapping migration entries (#2041) - **fix(settings):** resolve model alias persistence double stringification preventing UI updates (#2018) - **fix(routing):** dynamically filter bare model auto-resolution by active provider connections to prevent dead-routing (#2029) - **fix(embeddings):** add Google Gemini embeddings compatibility via OpenAI-compatible endpoint mapping (#2006) +- **fix(sse):** prevent Claude OAuth multi-account correlation via metadata.user_id (#2053) +- **fix(sse):** prevent Claude Code identity cloak overrides and fix fallback resilience (#2053) +- **fix(sse):** classify hour quota errors as QUOTA_EXHAUSTED (#2119) +- **fix(sse):** fix CC-compatible streaming bridge (#2118) +- **fix(antigravity):** sanitize Claude Cloud Code payloads (#2090) +- **fix(antigravity):** add duplex half for streaming bodies +- **fix(antigravity):** align identity protocol and behavior with official AM +- **fix(chatgpt-web):** plumb proxy through to native tls-client (#2022, #2023) +- **fix(codex):** expose native model IDs in catalog (#2012) +- **fix(glm):** add dedicated coding transport (#2087) +- **fix(compression):** support Responses input and expand Spanish compression rules (#2028) +- **fix(catalog):** auto-calculate combo context_length from target model limits (#2030) +- **fix(api):** fix usage analytics and API key identity (#2008, #2092) +- **fix(api-key):** allow Unicode letters in API key name validation (#1996) +- **fix(auth):** allow bootstrap without password (#2048) +- **fix(proxy):** clean up proxy page redundancy and fix 1proxy sync empty body error (#2052) +- **fix(dashboard):** resolve Unknown plan display in Provider Limits +- **fix(usage):** add extensible CURRENCY_SYMBOLS mapping for deepseek currencies +- **fix(runtime):** harden timer handling and model pricing fallback +- **fix(i18n):** complete Simplified Chinese translations (#2115) +- **fix(mitm):** add Linux cert install and skip sudo password when root (#1999) +- **fix(mitm):** prevent stub from loading at runtime via bypass module - **fix:** remove Anthropic-Beta header from non-Anthropic providers to fix identity contamination (#1989) - **fix(cli):** resolve .env loading failure for global npm installations +- **fix(export):** exclude telemetry/usage-history tables from JSON config backups by default to prevent unbounded file growth (#2125) +- **fix:** Follow OpenAI specification, handle throttling in batch and fix UI (#2045) -### 🔒 Security +### Segurança +- **fix(security):** remediate CodeQL vulnerabilities (ReDoS, cryptographic bias, stack trace exposure, and weak password hashing) (#216, #215, #211, #208, #206, #210) - **fix(security):** remediate regex validation backtracking path in core compression cleanup (#1990) - **fix(core):** harden input handling and stabilization for prompt compression edge cases +### Documentação + +- **docs:** add competitive marketing tables and SEO/AEO optimizations to README (#2091) +- **docs:** refresh providers, model catalogs, and docs for v3.8.0 (#2088) +- **docs:** update Claude MD and update GLM-CN max context to 200k (#2027) +- **docs(env):** add `GITLAB_DUO_OAUTH_CLIENT_ID` to `.env.example` (#2031) + ### 🧹 Chores & Maintenance - **chore(providers):** prune redundant local provider icon assets in favor of `@lobehub/icons` web fonts (#1992) +- **chore(providers):** remove deprecated models (#2033) +- **deps:** bump `fast-uri` from 3.1.0 to 3.1.2 (#2078) +- **deps:** bump `hono` from 4.12.14 to 4.12.18 (#2079) - **ci:** skip SonarCloud scan on main pushes to optimize CI time - **test:** stabilize cooldown abort coverage case in integration testing +### 🏆 v3.8.0 Community Contributors + +Thank you to all **38 community contributors** who made v3.8.0 possible! 🎉 + +| Contributor | PRs | Contributions | +| :--------------------------------------------------------- | :-: | :------------------------------------------------------------ | +| [@oyi77](https://github.com/oyi77) | 7 | #2010, #2014, #2041, #2052, #2061, #2074, #2091, #2094, #2096 | +| [@backryun](https://github.com/backryun) | 4 | #1992, #2033, #2088, #2123 | +| [@dhaern](https://github.com/dhaern) | 4 | #2028, #2039, #2087, #2090 | +| [@Tentoxa](https://github.com/Tentoxa) | 2 | #2011, #2053 | +| [@wauputr4](https://github.com/wauputr4) | 2 | #2009, #2046 | +| [@payne0420](https://github.com/payne0420) | 1 | #2082 | +| [@Tr0sT](https://github.com/Tr0sT) | 1 | #2012 | +| [@AveryanAlex](https://github.com/AveryanAlex) | 1 | #2008 | +| [@nickwizard](https://github.com/nickwizard) | 1 | #1991 | +| [@rodrigogbbr-stack](https://github.com/rodrigogbbr-stack) | 1 | #1996 | +| [@NekoMonci12](https://github.com/NekoMonci12) | 1 | #1999 | +| [@congvc-dev](https://github.com/congvc-dev) | 1 | #2004 | +| [@tatsster](https://github.com/tatsster) | 1 | #2007 | +| [@xssdem](https://github.com/xssdem) | 1 | #2023 | +| [@bypanghu](https://github.com/bypanghu) | 1 | #2027 | +| [@herjarsa](https://github.com/herjarsa) | 1 | #2030 | +| [@wucm667](https://github.com/wucm667) | 1 | #2031 | +| [@hartmark](https://github.com/hartmark) | 1 | #2045 | +| [@ddarkr](https://github.com/ddarkr) | 1 | #2047 | +| [@tces1](https://github.com/tces1) | 1 | #2048 | +| [@guanbear](https://github.com/guanbear) | 1 | #2054 | +| [@Gi99lin](https://github.com/Gi99lin) | 1 | #2055 | +| [@ivan-mezentsev](https://github.com/ivan-mezentsev) | 1 | #2063 | +| [@JxnLexn](https://github.com/JxnLexn) | 1 | #2019 | +| [@yoviarpauzi](https://github.com/yoviarpauzi) | 1 | #2092 | +| [@rafacpti23](https://github.com/rafacpti23) | 1 | #2086 | +| [@gleber](https://github.com/gleber) | 1 | #2103 | +| [@rilham97](https://github.com/rilham97) | 1 | #2104 | +| [@Gioxaa](https://github.com/Gioxaa) | 1 | #2105 | +| [@boa-z](https://github.com/boa-z) | 1 | #2115 | +| [@eleata](https://github.com/eleata) | 1 | #2116 | +| [@rdself](https://github.com/rdself) | 1 | #2118 | +| [@clousky2020](https://github.com/clousky2020) | 1 | #2119 | +| [@abhinavjnu](https://github.com/abhinavjnu) | 1 | #2122 | +| [@HoaPham98](https://github.com/HoaPham98) | 1 | #2089 | +| [@05dunski](https://github.com/05dunski) | 1 | #1978 (cherry-picked) | + ## [3.7.9] — 2026-05-03 ### ✨ New Features @@ -102,7 +220,7 @@ - **chore(provider):** Add reka models list (#1956 — thanks @backryun) - **chore(model):** Update new models, Delete Deprecated models (#1949 — thanks @backryun) -### 📝 Documentation +### Documentação - **docs(compression):** document RTK+Caveman stacked savings ranges @@ -201,7 +319,7 @@ - **feat(db):** auto-restore probe-failed database on startup to prevent data loss after failed upgrades (#1810) - **feat(analytics):** add cost-based usage insights and activity streaks in the analytics dashboard -### 🔒 Security +### Segurança - **fix(security):** resolve ReDoS vulnerability in Codex executor regex patterns (#1797, #1789) @@ -354,7 +472,7 @@ We identified that **155 community PRs** across the entire project history (from - **feat(proxy):** implement bulk proxy import via pipe-delimited parser with update-or-create (upsert) logic and real-time preview table - **feat(pwa):** add fullscreen installable PWA with manifest, service worker, and cross-platform app icons (#1728) -### 🔒 Security +### Segurança - **security:** replace insecure `Math.random` with `crypto.getRandomValues` for fallback UUID generation to resolve CodeQL CWE-338 finding (#182) @@ -519,7 +637,7 @@ We identified that **155 community PRs** across the entire project history (from - **fix(transport):** Prevent memory bloat and database exhaustion from large, fragmented streaming responses. Implemented `ByteQueue` in `kiro.ts` for zero-copy binary accumulation, refactored `antigravity.ts` for incremental SSE parsing, and enforced a strict 512KB tiered truncation limit (`MAX_CALL_LOG_ARTIFACT_BYTES`) on stream request logs and call artifacts (#1647). - **chore(ci):** Update build environment dependencies — bump Node to `24.15.0`, `actions/checkout@v6`, `docker/build-push-action@v7`, pin `actions/setup-python` to major tag (#1646 — thanks @backryun). -### 📝 Documentation +### Documentação - **docs(env):** Add `OMNIROUTE_ALLOW_PRIVATE_PROVIDER_URLS` to `.env.example` with documentation for LM Studio and other local provider use cases (#1623). @@ -669,7 +787,7 @@ We identified that **155 community PRs** across the entire project history (from - **test(next):** Align transpile package expectations for the Next.js standalone build. - **test(ci):** Fix CI-only test failures from environment differences — clear `INITIAL_PASSWORD` and `JWT_SECRET` in integration tests, handle `XDG_CONFIG_HOME` for guide-settings tests. -### 📚 Documentation +### Documentação - **docs:** Update the root changelog with all release-branch changes through 2026-04-24, including PRs #1544, #1555, #1551, #1550, #1548, #1547, #1541, #1538, #1536, and #1527. - **docs:** Fix broken README and localized documentation links. (#1536) @@ -811,7 +929,7 @@ We identified that **155 community PRs** across the entire project history (from - **feat(providers):** Expand image provider registry with extended model support including SD3.5, FLUX, and DALL-E 3 HD configurations - **feat(combos):** Add new routing strategies and full i18n support for agent features section across 31 languages -### 🔒 Security +### Segurança - **security:** Resolve 18 GitHub CodeQL scan alerts including ReDoS, incomplete sanitization, and bad HTML filtering regexp patterns - **fix(auth):** Seal privilege escalation vector by enforcing JWT session checking exclusively on `/api/keys` management endpoints (#1353) @@ -1078,7 +1196,7 @@ We identified that **155 community PRs** across the entire project history (from - **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 - **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 -### 🔒 Security +### Segurança - **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 - **Auth Guard on Translator Save:** Added `isAuthenticated` guard to `/api/translator/save` for defense-in-depth consistency @@ -1483,7 +1601,7 @@ We identified that **155 community PRs** across the entire project history (from - **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). -### 📚 Documentation +### Documentação - **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. - **Context Relay Delivery Notes:** Documented the current architecture, runtime flow, and Codex-focused scope in the feature docs, changelog, and agent guidance. @@ -1559,7 +1677,7 @@ We identified that **155 community PRs** across the entire project history (from ## [3.5.3] - 2026-04-07 -### Security +### Segurança - **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. - **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. @@ -1575,7 +1693,7 @@ We identified that **155 community PRs** across the entire project history (from - **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. -### Documentation +### Documentação - **I18n Engine:** Synchronized and pushed deep Machine Translation updates across all 32 natively-supported languages (682 translation nodes aligned). @@ -1736,7 +1854,7 @@ We identified that **155 community PRs** across the entire project history (from ## [3.4.8] — 2026-04-03 -### Security +### Segurança - Fully remediated all outstanding Github Advanced Security (CodeQL) findings and Dependabot alerts. - Fixed insecure randomness vulnerabilities by migrating from `Math.random` to `crypto.randomUUID()`. @@ -1748,7 +1866,7 @@ We identified that **155 community PRs** across the entire project history (from ## [3.4.7] — 2026-04-03 -### Features +### Funcionalidades - Added `Cryptography` node to Monitoring and MCP health checks (#798) - Hardened model-catalog route permissions mapping (`/models`) (#781) @@ -1764,7 +1882,7 @@ We identified that **155 community PRs** across the entire project history (from - Fixed MCP standalone module-resolution (`ERR_MODULE_NOT_FOUND`) via `esbuild` (#936) - Fixed NVIDIA NIM routing credential resolution alias mismatch (#931) -### Security +### Segurança - Added safe strict input boundary protection against raw `shell: true` remote-code execution injections. @@ -2011,7 +2129,7 @@ We identified that **155 community PRs** across the entire project history (from ## [3.4.0] - 2026-03-31 -### 🚀 Features +### Funcionalidades - **Subscription Utilization Analytics:** Added quota snapshot time-series tracking, Provider Utilization and Combo Health tabs with recharts visualizations, and corresponding API endpoints (#847) - **SQLite Backup Control:** New `OMNIROUTE_DISABLE_AUTO_BACKUP` env flag to disable automatic SQLite backups (#846) @@ -2063,7 +2181,7 @@ We identified that **155 community PRs** across the entire project history (from ## [3.3.8] - 2026-03-30 -### 🚀 Features +### Funcionalidades - **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) - **Qoder Integration:** Native integration for Qoder AI natively replacing the legacy iFlow platform mappings (#660) @@ -2889,7 +3007,7 @@ We identified that **155 community PRs** across the entire project history (from - **NaN tokens in Claude Code / client responses (#617):** - `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 -### 🔒 Security +### Segurança - Updated `yaml` package to fix stack overflow vulnerability (GHSA-48c2-rrv3-qjmp) @@ -3565,7 +3683,7 @@ docker pull diegosouzapw/omniroute:3.0.0 - **SVG fallback**: `ProviderIcon` component updated with 4-tier strategy: Lobehub → PNG → SVG → Generic icon - **Agents fingerprinting**: Synced with CLI tools — added droid, openclaw, copilot, opencode to fingerprint list (14 total) -### 🔒 Security +### Segurança - **CVE fix**: Resolved dompurify XSS vulnerability (GHSA-v2wj-7wpq-c8vv) via npm overrides forcing `dompurify@^3.3.2` - `npm audit` now reports **0 vulnerabilities** @@ -3928,7 +4046,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **#510** — Windows: MSYS2/Git-Bash paths (`/c/Program Files/...`) are now normalized to `C:\Program Files\...` - **#492** — `omniroute` CLI now detects `mise`/`nvm` when `app/server.js` is missing and shows targeted fix -### 📖 Documentation +### Documentação - **#513** — Docker password reset: `INITIAL_PASSWORD` env var workaround documented - **#520** — pnpm: `pnpm approve-builds better-sqlite3` documented @@ -4025,7 +4143,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **feat(executors/cloudflare-ai)**: New `CloudflareAIExecutor` — dynamic URL construction requires `accountId` in provider credentials - **feat(executors)**: Register `pollinations`, `pol`, `cloudflare-ai`, `cf` executor mappings -### 📝 Documentation +### Documentação - **docs(readme)**: Expanded free combo stack to 11 providers ($0 forever) - **docs(readme)**: Added 4 new free provider sections (LongCat, Pollinations, Cloudflare AI, Scaleway) with model tables @@ -4177,7 +4295,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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). -### Features +### Funcionalidades - **"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. @@ -4205,7 +4323,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Merge PR #494 (MiniMax role fix), fix KIRO MITM dashboard, triage 8 issues. -### Features +### Funcionalidades - **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. - **roleNormalizer**: `normalizeDeveloperRole()` now accepts `preserveDeveloperRole` parameter with tri-state behavior (undefined=keep, true=keep, false=convert). @@ -4261,7 +4379,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Gemini CLI deprecation, VM guide i18n fix, dependabot security fix, provider schema expansion. -### Features +### Funcionalidades - **Gemini CLI Deprecation** (#462): Mark `gemini-cli` provider as deprecated with warning — Google restricts third-party OAuth usage from March 2026 - **Provider Schema** (#462): Expand Zod validation with `deprecated`, `deprecationReason`, `hasFree`, `freeNote`, `authHint`, `apiHint` optional fields @@ -4270,7 +4388,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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) -### Security +### Segurança - **deps**: Bump `flatted` 3.3.3 → 3.4.2 — fixes CWE-1321 prototype pollution (#484, @dependabot) @@ -4290,7 +4408,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Czech i18n, SSE protocol fix, VM guide translation. -### Features +### Funcionalidades - **Czech Language** (#482): Full Czech (cs) i18n — 22 docs, 2606 UI strings, language switcher updates (@zen0bit) - **VM Deployment Guide**: Translated from Portuguese to English as the source document (@zen0bit) @@ -4309,7 +4427,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: 2 merged PRs, model aliases routing fix, log export, and issue triage. -### Features +### Funcionalidades - **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) @@ -4329,7 +4447,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Five community PRs — streaming call log fixes, Kiro compatibility, cache token analytics, Chinese translation, and configurable tool call IDs. -### ✨ Features +### Funcionalidades - **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) - **feat(providers)**: Per-model configurable 9-char tool call ID normalization (Mistral-style) — only models with the option enabled get truncated IDs (#470) @@ -4359,7 +4477,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Bailian Coding Plan provider with editable base URLs, plus community contributions for Alibaba Cloud and Kimi Coding. -### ✨ Features +### Funcionalidades - **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) - **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) @@ -4374,7 +4492,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Two new community-contributed providers (Alibaba Cloud Coding, Kimi Coding API-key) and Docker pino fix. -### ✨ Features +### Funcionalidades - **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) - **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) @@ -4399,7 +4517,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Codex responses subpath passthrough natively supported, Windows MITM crash fixed, and Combos agent schemas adjusted. -### ✨ Features +### Funcionalidades - **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) @@ -4439,7 +4557,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **fix(budget)**: "Save Limits" no longer returns 422 — `warningThreshold` is now correctly sent as fraction (0–1) instead of percentage (0–100) (#451) - **fix(combos)**: `` internal cache tag is now stripped before forwarding requests to providers, preventing cache session breaks (#454) -### ✨ Features +### Funcionalidades - **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) @@ -4495,7 +4613,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Search Tools dashboard, i18n fixes, Copilot limits, Serper validation fix. -### 🚀 Features +### Funcionalidades - **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) - New route: `/dashboard/search-tools` @@ -4595,7 +4713,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - DB migration: `request_type` column on `call_logs` for non-chat request tracking - Zod validation (`v1SearchSchema`), auth-gated, cost recorded via `recordCost()` -### 🔒 Security +### Segurança - **deps**: Next.js 16.1.6 → 16.1.7 — fixes 6 CVEs: - **Critical**: CVE-2026-29057 (HTTP request smuggling via http-proxy) @@ -4725,7 +4843,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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**: New `request_detail_logs` table with 500-entry ring-buffer trigger, opt-in via settings toggle -### ✨ Features +### Funcionalidades - **feat(combo)**: System Message Override per Combo (#399 — `system_message` field replaces or injects system prompt before forwarding to provider) - **feat(combo)**: Tool Filter Regex per Combo (#399 — `tool_filter_regex` keeps only tools matching pattern; supports OpenAI + Anthropic formats) @@ -4740,7 +4858,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: SSE improvements, local provider_nodes extensions, proxy registry, Claude passthrough fixes. -### ✨ Features +### Funcionalidades - **feat(health)**: Background health check for local `provider_nodes` with exponential backoff (30s→300s) and `Promise.allSettled` to avoid blocking (#423, @Regis-RCR) - **feat(embeddings)**: Route `/v1/embeddings` to local `provider_nodes` — `buildDynamicEmbeddingProvider()` with hostname validation (#422, @Regis-RCR) @@ -4882,7 +5000,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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 - **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). -### ✨ Features +### Funcionalidades - **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) @@ -4912,7 +5030,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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) - **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) -### ✨ Features +### Funcionalidades - **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) - **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. @@ -4971,7 +5089,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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) - **fix(logs)**: Request log table is now readable in light mode — status badges, token counts, and combo tags use adaptive `dark:` color classes (#378) -### ✨ Features +### Funcionalidades - **feat(kiro)**: Kiro credit tracking added to usage fetcher — queries `getUserCredits` from AWS CodeWhisperer endpoint (#337) @@ -5372,7 +5490,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > **Major release** — Free Stack ecosystem, transcription playground overhaul, 44+ providers, comprehensive free tier documentation, and UI improvements across the board. -### ✨ Features +### Funcionalidades - **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. - **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. @@ -5383,7 +5501,7 @@ OmniRoute now automatically refreshes model lists for connected providers every ## [2.3.16] - 2026-03-13 -### 📖 Documentation +### Documentação - **README: 44+ Providers** — Updated all 3 occurrences of "36+ providers" to "44+" reflecting the actual codebase count (44 providers in providers.ts) - **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. @@ -5393,7 +5511,7 @@ OmniRoute now automatically refreshes model lists for connected providers every ## [2.3.15] - 2026-03-13 -### ✨ Features +### Funcionalidades - **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. - **i18n — autoCombo section**: Added 20 new translation keys for the Auto-Combo dashboard (`title`, `status`, `modePack`, `providerScores`, `factorTierPriority`, etc.) to all 30 language files. diff --git a/docs/i18n/ro/CHANGELOG.md b/docs/i18n/ro/CHANGELOG.md index 95b26b7c07..280978130b 100644 --- a/docs/i18n/ro/CHANGELOG.md +++ b/docs/i18n/ro/CHANGELOG.md @@ -10,30 +10,148 @@ ### ✨ New Features -- **feat(antigravity):** integrate Antigravity provider with dynamic `maxOutputTokens` calculation (bumping to `thinkingBudget + 1`) and standard Cloud Code envelope payload sanitization (#2055, #2063) +- **feat(antigravity):** integrate Antigravity provider with dynamic `maxOutputTokens` calculation, identity fingerprinting overhaul, and Cloud Code envelope payload sanitization (#2055, #2063) - **feat(gemini-cli):** add custom projectId support for Gemini CLI transport (UI, DB, executor) (#1991) +- **feat(providers):** add KIE media provider support with dynamic polling, text models, and expanded video models catalog +- **feat(providers):** add Z.AI provider support with GLM quota handling and new quota labels +- **feat(providers):** add 9 new free AI providers — LLM7, Lepton, Kluster, UncloseAI, BazaarLink, Completions, Enally, FreeTheAi (#2096) +- **feat(providers):** batch delete provider connections via checkbox multi-select (#2094) +- **feat(cursor):** full OpenAI parity — tool calls, streaming, and session management (#2082) +- **feat(cli):** comprehensive CLI enhancement suite with 20+ new commands including `omniroute providers`, `omniroute combos`, `omniroute doctor` (#2074) +- **feat(cli):** add modular CLI setup and provider management commands (#2046) +- **feat(mcp):** add DeepSeek quota and limit monitoring feature (#2089) +- **feat(circuit-breaker):** classify 429 errors and apply per-kind cooldowns (#2116) +- **feat(multi):** manifest-aware tier routing — W1-W4 complete (#2014) +- **feat(combos):** add reset-aware routing strategy for quota-based providers +- **feat(combo):** add context_length input field to combo edit form (#2047) +- **feat(chat):** dynamic tool limit detection with proactive truncation (#2061) +- **feat(sse):** refresh Claude OAuth wire image to claude-cli/2.1.131 (#2011) +- **feat(github):** add `targetFormat: openai-responses` to all GitHub models (#2122) +- **feat(api):** allow configuration via API calls — open management routes to Bearer keys with manage scope (#2103) +- **feat(api):** update API bridge proxy timeout to 600,000ms (#2019) +- **feat(usage):** add service tier breakdown, codex fast service tier analytics, and account for fast tier +- **feat(chat):** add `STREAM_READINESS_TIMEOUT_MS` and integrate into chat handling +- **feat(combo):** add `fallbackDelayMs` to combo configuration and related settings +- **feat(chat):** enhance error handling for semaphore capacity with fallback logic +- **feat(qdrant):** embedding model discovery (#2086) +- **feat(auth):** per-session sticky routing for Codex (#1887) +- **feat(inworld):** enhance Inworld TTS support (#2123) ### 🐛 Bug Fixes +- **fix(pricing):** make `getPricingForModel` fully case-insensitive to ensure custom prices correctly reflect in new incoming requests cost calculations +- **fix(gemini):** prevent `functionDeclarations` from being dropped by the sanitizer when `googleSearch` tool is present (#2077) +- **fix(pollinations):** add `jsonMode: true` flag in the request transformation to enforce correct JSON structure from Pollinations API (#2109) +- **fix(docker):** update Dockerfile to copy `/docs` directory during build ensuring API catalog availability at runtime (#2083) +- **fix(docker):** include OpenAPI spec in runtime image (#2007) +- **fix(providers):** strip OpenAI-specific fields in Kiro translator to prevent 400 errors (#2037) +- **fix(kiro):** normalize tool-use payloads to prevent 400 errors from agents (#2104) +- **fix(kiro):** merge adjacent user history turns after role normalization (#2105) +- **fix(ui):** resolve text contrast issues for zero-config warning banner in light mode (#2050) +- **fix(core):** inject global system prompt correctly into downstream chat completions pipeline (#2080) +- **fix(core):** restore Claude Code adaptive thinking defaults and resolve audio transcription CORS regression +- **fix(routing):** add missing v1beta rewrites to next.config to resolve 404 on Gemini models endpoint (#2102) +- **fix(routing):** fix bare GPT-5.5 routing for Codex-only installations (#2054) +- **fix(routing):** add fuzzy auto-combo routing for `auto/*` model prefix (#2010) - **fix(cache):** optimize cache_control preservation logic and explicitly align tool schema with upstream Claude Code expectations - **fix(db):** preserve legacy SQLite database path on Windows to prevent data loss (#1973) +- **fix(db):** reduce hot-path persistence overhead (#2039) +- **fix(db):** resolve migration conflict by renumbering overlapping migration entries (#2041) - **fix(settings):** resolve model alias persistence double stringification preventing UI updates (#2018) - **fix(routing):** dynamically filter bare model auto-resolution by active provider connections to prevent dead-routing (#2029) - **fix(embeddings):** add Google Gemini embeddings compatibility via OpenAI-compatible endpoint mapping (#2006) +- **fix(sse):** prevent Claude OAuth multi-account correlation via metadata.user_id (#2053) +- **fix(sse):** prevent Claude Code identity cloak overrides and fix fallback resilience (#2053) +- **fix(sse):** classify hour quota errors as QUOTA_EXHAUSTED (#2119) +- **fix(sse):** fix CC-compatible streaming bridge (#2118) +- **fix(antigravity):** sanitize Claude Cloud Code payloads (#2090) +- **fix(antigravity):** add duplex half for streaming bodies +- **fix(antigravity):** align identity protocol and behavior with official AM +- **fix(chatgpt-web):** plumb proxy through to native tls-client (#2022, #2023) +- **fix(codex):** expose native model IDs in catalog (#2012) +- **fix(glm):** add dedicated coding transport (#2087) +- **fix(compression):** support Responses input and expand Spanish compression rules (#2028) +- **fix(catalog):** auto-calculate combo context_length from target model limits (#2030) +- **fix(api):** fix usage analytics and API key identity (#2008, #2092) +- **fix(api-key):** allow Unicode letters in API key name validation (#1996) +- **fix(auth):** allow bootstrap without password (#2048) +- **fix(proxy):** clean up proxy page redundancy and fix 1proxy sync empty body error (#2052) +- **fix(dashboard):** resolve Unknown plan display in Provider Limits +- **fix(usage):** add extensible CURRENCY_SYMBOLS mapping for deepseek currencies +- **fix(runtime):** harden timer handling and model pricing fallback +- **fix(i18n):** complete Simplified Chinese translations (#2115) +- **fix(mitm):** add Linux cert install and skip sudo password when root (#1999) +- **fix(mitm):** prevent stub from loading at runtime via bypass module - **fix:** remove Anthropic-Beta header from non-Anthropic providers to fix identity contamination (#1989) - **fix(cli):** resolve .env loading failure for global npm installations +- **fix(export):** exclude telemetry/usage-history tables from JSON config backups by default to prevent unbounded file growth (#2125) +- **fix:** Follow OpenAI specification, handle throttling in batch and fix UI (#2045) -### 🔒 Security +### Securitate +- **fix(security):** remediate CodeQL vulnerabilities (ReDoS, cryptographic bias, stack trace exposure, and weak password hashing) (#216, #215, #211, #208, #206, #210) - **fix(security):** remediate regex validation backtracking path in core compression cleanup (#1990) - **fix(core):** harden input handling and stabilization for prompt compression edge cases +### Documentație + +- **docs:** add competitive marketing tables and SEO/AEO optimizations to README (#2091) +- **docs:** refresh providers, model catalogs, and docs for v3.8.0 (#2088) +- **docs:** update Claude MD and update GLM-CN max context to 200k (#2027) +- **docs(env):** add `GITLAB_DUO_OAUTH_CLIENT_ID` to `.env.example` (#2031) + ### 🧹 Chores & Maintenance - **chore(providers):** prune redundant local provider icon assets in favor of `@lobehub/icons` web fonts (#1992) +- **chore(providers):** remove deprecated models (#2033) +- **deps:** bump `fast-uri` from 3.1.0 to 3.1.2 (#2078) +- **deps:** bump `hono` from 4.12.14 to 4.12.18 (#2079) - **ci:** skip SonarCloud scan on main pushes to optimize CI time - **test:** stabilize cooldown abort coverage case in integration testing +### 🏆 v3.8.0 Community Contributors + +Thank you to all **38 community contributors** who made v3.8.0 possible! 🎉 + +| Contributor | PRs | Contributions | +| :--------------------------------------------------------- | :-: | :------------------------------------------------------------ | +| [@oyi77](https://github.com/oyi77) | 7 | #2010, #2014, #2041, #2052, #2061, #2074, #2091, #2094, #2096 | +| [@backryun](https://github.com/backryun) | 4 | #1992, #2033, #2088, #2123 | +| [@dhaern](https://github.com/dhaern) | 4 | #2028, #2039, #2087, #2090 | +| [@Tentoxa](https://github.com/Tentoxa) | 2 | #2011, #2053 | +| [@wauputr4](https://github.com/wauputr4) | 2 | #2009, #2046 | +| [@payne0420](https://github.com/payne0420) | 1 | #2082 | +| [@Tr0sT](https://github.com/Tr0sT) | 1 | #2012 | +| [@AveryanAlex](https://github.com/AveryanAlex) | 1 | #2008 | +| [@nickwizard](https://github.com/nickwizard) | 1 | #1991 | +| [@rodrigogbbr-stack](https://github.com/rodrigogbbr-stack) | 1 | #1996 | +| [@NekoMonci12](https://github.com/NekoMonci12) | 1 | #1999 | +| [@congvc-dev](https://github.com/congvc-dev) | 1 | #2004 | +| [@tatsster](https://github.com/tatsster) | 1 | #2007 | +| [@xssdem](https://github.com/xssdem) | 1 | #2023 | +| [@bypanghu](https://github.com/bypanghu) | 1 | #2027 | +| [@herjarsa](https://github.com/herjarsa) | 1 | #2030 | +| [@wucm667](https://github.com/wucm667) | 1 | #2031 | +| [@hartmark](https://github.com/hartmark) | 1 | #2045 | +| [@ddarkr](https://github.com/ddarkr) | 1 | #2047 | +| [@tces1](https://github.com/tces1) | 1 | #2048 | +| [@guanbear](https://github.com/guanbear) | 1 | #2054 | +| [@Gi99lin](https://github.com/Gi99lin) | 1 | #2055 | +| [@ivan-mezentsev](https://github.com/ivan-mezentsev) | 1 | #2063 | +| [@JxnLexn](https://github.com/JxnLexn) | 1 | #2019 | +| [@yoviarpauzi](https://github.com/yoviarpauzi) | 1 | #2092 | +| [@rafacpti23](https://github.com/rafacpti23) | 1 | #2086 | +| [@gleber](https://github.com/gleber) | 1 | #2103 | +| [@rilham97](https://github.com/rilham97) | 1 | #2104 | +| [@Gioxaa](https://github.com/Gioxaa) | 1 | #2105 | +| [@boa-z](https://github.com/boa-z) | 1 | #2115 | +| [@eleata](https://github.com/eleata) | 1 | #2116 | +| [@rdself](https://github.com/rdself) | 1 | #2118 | +| [@clousky2020](https://github.com/clousky2020) | 1 | #2119 | +| [@abhinavjnu](https://github.com/abhinavjnu) | 1 | #2122 | +| [@HoaPham98](https://github.com/HoaPham98) | 1 | #2089 | +| [@05dunski](https://github.com/05dunski) | 1 | #1978 (cherry-picked) | + ## [3.7.9] — 2026-05-03 ### ✨ New Features @@ -102,7 +220,7 @@ - **chore(provider):** Add reka models list (#1956 — thanks @backryun) - **chore(model):** Update new models, Delete Deprecated models (#1949 — thanks @backryun) -### 📝 Documentation +### Documentație - **docs(compression):** document RTK+Caveman stacked savings ranges @@ -201,7 +319,7 @@ - **feat(db):** auto-restore probe-failed database on startup to prevent data loss after failed upgrades (#1810) - **feat(analytics):** add cost-based usage insights and activity streaks in the analytics dashboard -### 🔒 Security +### Securitate - **fix(security):** resolve ReDoS vulnerability in Codex executor regex patterns (#1797, #1789) @@ -354,7 +472,7 @@ We identified that **155 community PRs** across the entire project history (from - **feat(proxy):** implement bulk proxy import via pipe-delimited parser with update-or-create (upsert) logic and real-time preview table - **feat(pwa):** add fullscreen installable PWA with manifest, service worker, and cross-platform app icons (#1728) -### 🔒 Security +### Securitate - **security:** replace insecure `Math.random` with `crypto.getRandomValues` for fallback UUID generation to resolve CodeQL CWE-338 finding (#182) @@ -519,7 +637,7 @@ We identified that **155 community PRs** across the entire project history (from - **fix(transport):** Prevent memory bloat and database exhaustion from large, fragmented streaming responses. Implemented `ByteQueue` in `kiro.ts` for zero-copy binary accumulation, refactored `antigravity.ts` for incremental SSE parsing, and enforced a strict 512KB tiered truncation limit (`MAX_CALL_LOG_ARTIFACT_BYTES`) on stream request logs and call artifacts (#1647). - **chore(ci):** Update build environment dependencies — bump Node to `24.15.0`, `actions/checkout@v6`, `docker/build-push-action@v7`, pin `actions/setup-python` to major tag (#1646 — thanks @backryun). -### 📝 Documentation +### Documentație - **docs(env):** Add `OMNIROUTE_ALLOW_PRIVATE_PROVIDER_URLS` to `.env.example` with documentation for LM Studio and other local provider use cases (#1623). @@ -669,7 +787,7 @@ We identified that **155 community PRs** across the entire project history (from - **test(next):** Align transpile package expectations for the Next.js standalone build. - **test(ci):** Fix CI-only test failures from environment differences — clear `INITIAL_PASSWORD` and `JWT_SECRET` in integration tests, handle `XDG_CONFIG_HOME` for guide-settings tests. -### 📚 Documentation +### Documentație - **docs:** Update the root changelog with all release-branch changes through 2026-04-24, including PRs #1544, #1555, #1551, #1550, #1548, #1547, #1541, #1538, #1536, and #1527. - **docs:** Fix broken README and localized documentation links. (#1536) @@ -811,7 +929,7 @@ We identified that **155 community PRs** across the entire project history (from - **feat(providers):** Expand image provider registry with extended model support including SD3.5, FLUX, and DALL-E 3 HD configurations - **feat(combos):** Add new routing strategies and full i18n support for agent features section across 31 languages -### 🔒 Security +### Securitate - **security:** Resolve 18 GitHub CodeQL scan alerts including ReDoS, incomplete sanitization, and bad HTML filtering regexp patterns - **fix(auth):** Seal privilege escalation vector by enforcing JWT session checking exclusively on `/api/keys` management endpoints (#1353) @@ -1078,7 +1196,7 @@ We identified that **155 community PRs** across the entire project history (from - **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 - **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 -### 🔒 Security +### Securitate - **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 - **Auth Guard on Translator Save:** Added `isAuthenticated` guard to `/api/translator/save` for defense-in-depth consistency @@ -1483,7 +1601,7 @@ We identified that **155 community PRs** across the entire project history (from - **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). -### 📚 Documentation +### Documentație - **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. - **Context Relay Delivery Notes:** Documented the current architecture, runtime flow, and Codex-focused scope in the feature docs, changelog, and agent guidance. @@ -1559,7 +1677,7 @@ We identified that **155 community PRs** across the entire project history (from ## [3.5.3] - 2026-04-07 -### Security +### Securitate - **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. - **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. @@ -1575,7 +1693,7 @@ We identified that **155 community PRs** across the entire project history (from - **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. -### Documentation +### Documentație - **I18n Engine:** Synchronized and pushed deep Machine Translation updates across all 32 natively-supported languages (682 translation nodes aligned). @@ -1736,7 +1854,7 @@ We identified that **155 community PRs** across the entire project history (from ## [3.4.8] — 2026-04-03 -### Security +### Securitate - Fully remediated all outstanding Github Advanced Security (CodeQL) findings and Dependabot alerts. - Fixed insecure randomness vulnerabilities by migrating from `Math.random` to `crypto.randomUUID()`. @@ -1748,7 +1866,7 @@ We identified that **155 community PRs** across the entire project history (from ## [3.4.7] — 2026-04-03 -### Features +### Funcționalități - Added `Cryptography` node to Monitoring and MCP health checks (#798) - Hardened model-catalog route permissions mapping (`/models`) (#781) @@ -1764,7 +1882,7 @@ We identified that **155 community PRs** across the entire project history (from - Fixed MCP standalone module-resolution (`ERR_MODULE_NOT_FOUND`) via `esbuild` (#936) - Fixed NVIDIA NIM routing credential resolution alias mismatch (#931) -### Security +### Securitate - Added safe strict input boundary protection against raw `shell: true` remote-code execution injections. @@ -2011,7 +2129,7 @@ We identified that **155 community PRs** across the entire project history (from ## [3.4.0] - 2026-03-31 -### 🚀 Features +### Funcționalități - **Subscription Utilization Analytics:** Added quota snapshot time-series tracking, Provider Utilization and Combo Health tabs with recharts visualizations, and corresponding API endpoints (#847) - **SQLite Backup Control:** New `OMNIROUTE_DISABLE_AUTO_BACKUP` env flag to disable automatic SQLite backups (#846) @@ -2063,7 +2181,7 @@ We identified that **155 community PRs** across the entire project history (from ## [3.3.8] - 2026-03-30 -### 🚀 Features +### Funcționalități - **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) - **Qoder Integration:** Native integration for Qoder AI natively replacing the legacy iFlow platform mappings (#660) @@ -2889,7 +3007,7 @@ We identified that **155 community PRs** across the entire project history (from - **NaN tokens in Claude Code / client responses (#617):** - `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 -### 🔒 Security +### Securitate - Updated `yaml` package to fix stack overflow vulnerability (GHSA-48c2-rrv3-qjmp) @@ -3565,7 +3683,7 @@ docker pull diegosouzapw/omniroute:3.0.0 - **SVG fallback**: `ProviderIcon` component updated with 4-tier strategy: Lobehub → PNG → SVG → Generic icon - **Agents fingerprinting**: Synced with CLI tools — added droid, openclaw, copilot, opencode to fingerprint list (14 total) -### 🔒 Security +### Securitate - **CVE fix**: Resolved dompurify XSS vulnerability (GHSA-v2wj-7wpq-c8vv) via npm overrides forcing `dompurify@^3.3.2` - `npm audit` now reports **0 vulnerabilities** @@ -3928,7 +4046,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **#510** — Windows: MSYS2/Git-Bash paths (`/c/Program Files/...`) are now normalized to `C:\Program Files\...` - **#492** — `omniroute` CLI now detects `mise`/`nvm` when `app/server.js` is missing and shows targeted fix -### 📖 Documentation +### Documentație - **#513** — Docker password reset: `INITIAL_PASSWORD` env var workaround documented - **#520** — pnpm: `pnpm approve-builds better-sqlite3` documented @@ -4025,7 +4143,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **feat(executors/cloudflare-ai)**: New `CloudflareAIExecutor` — dynamic URL construction requires `accountId` in provider credentials - **feat(executors)**: Register `pollinations`, `pol`, `cloudflare-ai`, `cf` executor mappings -### 📝 Documentation +### Documentație - **docs(readme)**: Expanded free combo stack to 11 providers ($0 forever) - **docs(readme)**: Added 4 new free provider sections (LongCat, Pollinations, Cloudflare AI, Scaleway) with model tables @@ -4177,7 +4295,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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). -### Features +### Funcționalități - **"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. @@ -4205,7 +4323,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Merge PR #494 (MiniMax role fix), fix KIRO MITM dashboard, triage 8 issues. -### Features +### Funcționalități - **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. - **roleNormalizer**: `normalizeDeveloperRole()` now accepts `preserveDeveloperRole` parameter with tri-state behavior (undefined=keep, true=keep, false=convert). @@ -4261,7 +4379,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Gemini CLI deprecation, VM guide i18n fix, dependabot security fix, provider schema expansion. -### Features +### Funcționalități - **Gemini CLI Deprecation** (#462): Mark `gemini-cli` provider as deprecated with warning — Google restricts third-party OAuth usage from March 2026 - **Provider Schema** (#462): Expand Zod validation with `deprecated`, `deprecationReason`, `hasFree`, `freeNote`, `authHint`, `apiHint` optional fields @@ -4270,7 +4388,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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) -### Security +### Securitate - **deps**: Bump `flatted` 3.3.3 → 3.4.2 — fixes CWE-1321 prototype pollution (#484, @dependabot) @@ -4290,7 +4408,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Czech i18n, SSE protocol fix, VM guide translation. -### Features +### Funcționalități - **Czech Language** (#482): Full Czech (cs) i18n — 22 docs, 2606 UI strings, language switcher updates (@zen0bit) - **VM Deployment Guide**: Translated from Portuguese to English as the source document (@zen0bit) @@ -4309,7 +4427,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: 2 merged PRs, model aliases routing fix, log export, and issue triage. -### Features +### Funcționalități - **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) @@ -4329,7 +4447,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Five community PRs — streaming call log fixes, Kiro compatibility, cache token analytics, Chinese translation, and configurable tool call IDs. -### ✨ Features +### Funcționalități - **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) - **feat(providers)**: Per-model configurable 9-char tool call ID normalization (Mistral-style) — only models with the option enabled get truncated IDs (#470) @@ -4359,7 +4477,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Bailian Coding Plan provider with editable base URLs, plus community contributions for Alibaba Cloud and Kimi Coding. -### ✨ Features +### Funcționalități - **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) - **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) @@ -4374,7 +4492,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Two new community-contributed providers (Alibaba Cloud Coding, Kimi Coding API-key) and Docker pino fix. -### ✨ Features +### Funcționalități - **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) - **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) @@ -4399,7 +4517,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Codex responses subpath passthrough natively supported, Windows MITM crash fixed, and Combos agent schemas adjusted. -### ✨ Features +### Funcționalități - **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) @@ -4439,7 +4557,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **fix(budget)**: "Save Limits" no longer returns 422 — `warningThreshold` is now correctly sent as fraction (0–1) instead of percentage (0–100) (#451) - **fix(combos)**: `` internal cache tag is now stripped before forwarding requests to providers, preventing cache session breaks (#454) -### ✨ Features +### Funcționalități - **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) @@ -4495,7 +4613,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Search Tools dashboard, i18n fixes, Copilot limits, Serper validation fix. -### 🚀 Features +### Funcționalități - **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) - New route: `/dashboard/search-tools` @@ -4595,7 +4713,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - DB migration: `request_type` column on `call_logs` for non-chat request tracking - Zod validation (`v1SearchSchema`), auth-gated, cost recorded via `recordCost()` -### 🔒 Security +### Securitate - **deps**: Next.js 16.1.6 → 16.1.7 — fixes 6 CVEs: - **Critical**: CVE-2026-29057 (HTTP request smuggling via http-proxy) @@ -4725,7 +4843,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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**: New `request_detail_logs` table with 500-entry ring-buffer trigger, opt-in via settings toggle -### ✨ Features +### Funcționalități - **feat(combo)**: System Message Override per Combo (#399 — `system_message` field replaces or injects system prompt before forwarding to provider) - **feat(combo)**: Tool Filter Regex per Combo (#399 — `tool_filter_regex` keeps only tools matching pattern; supports OpenAI + Anthropic formats) @@ -4740,7 +4858,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: SSE improvements, local provider_nodes extensions, proxy registry, Claude passthrough fixes. -### ✨ Features +### Funcționalități - **feat(health)**: Background health check for local `provider_nodes` with exponential backoff (30s→300s) and `Promise.allSettled` to avoid blocking (#423, @Regis-RCR) - **feat(embeddings)**: Route `/v1/embeddings` to local `provider_nodes` — `buildDynamicEmbeddingProvider()` with hostname validation (#422, @Regis-RCR) @@ -4882,7 +5000,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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 - **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). -### ✨ Features +### Funcționalități - **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) @@ -4912,7 +5030,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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) - **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) -### ✨ Features +### Funcționalități - **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) - **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. @@ -4971,7 +5089,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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) - **fix(logs)**: Request log table is now readable in light mode — status badges, token counts, and combo tags use adaptive `dark:` color classes (#378) -### ✨ Features +### Funcționalități - **feat(kiro)**: Kiro credit tracking added to usage fetcher — queries `getUserCredits` from AWS CodeWhisperer endpoint (#337) @@ -5372,7 +5490,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > **Major release** — Free Stack ecosystem, transcription playground overhaul, 44+ providers, comprehensive free tier documentation, and UI improvements across the board. -### ✨ Features +### Funcționalități - **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. - **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. @@ -5383,7 +5501,7 @@ OmniRoute now automatically refreshes model lists for connected providers every ## [2.3.16] - 2026-03-13 -### 📖 Documentation +### Documentație - **README: 44+ Providers** — Updated all 3 occurrences of "36+ providers" to "44+" reflecting the actual codebase count (44 providers in providers.ts) - **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. @@ -5393,7 +5511,7 @@ OmniRoute now automatically refreshes model lists for connected providers every ## [2.3.15] - 2026-03-13 -### ✨ Features +### Funcționalități - **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. - **i18n — autoCombo section**: Added 20 new translation keys for the Auto-Combo dashboard (`title`, `status`, `modePack`, `providerScores`, `factorTierPriority`, etc.) to all 30 language files. diff --git a/docs/i18n/ru/CHANGELOG.md b/docs/i18n/ru/CHANGELOG.md index 219bb905bd..6accb1e881 100644 --- a/docs/i18n/ru/CHANGELOG.md +++ b/docs/i18n/ru/CHANGELOG.md @@ -10,30 +10,148 @@ ### ✨ New Features -- **feat(antigravity):** integrate Antigravity provider with dynamic `maxOutputTokens` calculation (bumping to `thinkingBudget + 1`) and standard Cloud Code envelope payload sanitization (#2055, #2063) +- **feat(antigravity):** integrate Antigravity provider with dynamic `maxOutputTokens` calculation, identity fingerprinting overhaul, and Cloud Code envelope payload sanitization (#2055, #2063) - **feat(gemini-cli):** add custom projectId support for Gemini CLI transport (UI, DB, executor) (#1991) +- **feat(providers):** add KIE media provider support with dynamic polling, text models, and expanded video models catalog +- **feat(providers):** add Z.AI provider support with GLM quota handling and new quota labels +- **feat(providers):** add 9 new free AI providers — LLM7, Lepton, Kluster, UncloseAI, BazaarLink, Completions, Enally, FreeTheAi (#2096) +- **feat(providers):** batch delete provider connections via checkbox multi-select (#2094) +- **feat(cursor):** full OpenAI parity — tool calls, streaming, and session management (#2082) +- **feat(cli):** comprehensive CLI enhancement suite with 20+ new commands including `omniroute providers`, `omniroute combos`, `omniroute doctor` (#2074) +- **feat(cli):** add modular CLI setup and provider management commands (#2046) +- **feat(mcp):** add DeepSeek quota and limit monitoring feature (#2089) +- **feat(circuit-breaker):** classify 429 errors and apply per-kind cooldowns (#2116) +- **feat(multi):** manifest-aware tier routing — W1-W4 complete (#2014) +- **feat(combos):** add reset-aware routing strategy for quota-based providers +- **feat(combo):** add context_length input field to combo edit form (#2047) +- **feat(chat):** dynamic tool limit detection with proactive truncation (#2061) +- **feat(sse):** refresh Claude OAuth wire image to claude-cli/2.1.131 (#2011) +- **feat(github):** add `targetFormat: openai-responses` to all GitHub models (#2122) +- **feat(api):** allow configuration via API calls — open management routes to Bearer keys with manage scope (#2103) +- **feat(api):** update API bridge proxy timeout to 600,000ms (#2019) +- **feat(usage):** add service tier breakdown, codex fast service tier analytics, and account for fast tier +- **feat(chat):** add `STREAM_READINESS_TIMEOUT_MS` and integrate into chat handling +- **feat(combo):** add `fallbackDelayMs` to combo configuration and related settings +- **feat(chat):** enhance error handling for semaphore capacity with fallback logic +- **feat(qdrant):** embedding model discovery (#2086) +- **feat(auth):** per-session sticky routing for Codex (#1887) +- **feat(inworld):** enhance Inworld TTS support (#2123) ### 🐛 Bug Fixes +- **fix(pricing):** make `getPricingForModel` fully case-insensitive to ensure custom prices correctly reflect in new incoming requests cost calculations +- **fix(gemini):** prevent `functionDeclarations` from being dropped by the sanitizer when `googleSearch` tool is present (#2077) +- **fix(pollinations):** add `jsonMode: true` flag in the request transformation to enforce correct JSON structure from Pollinations API (#2109) +- **fix(docker):** update Dockerfile to copy `/docs` directory during build ensuring API catalog availability at runtime (#2083) +- **fix(docker):** include OpenAPI spec in runtime image (#2007) +- **fix(providers):** strip OpenAI-specific fields in Kiro translator to prevent 400 errors (#2037) +- **fix(kiro):** normalize tool-use payloads to prevent 400 errors from agents (#2104) +- **fix(kiro):** merge adjacent user history turns after role normalization (#2105) +- **fix(ui):** resolve text contrast issues for zero-config warning banner in light mode (#2050) +- **fix(core):** inject global system prompt correctly into downstream chat completions pipeline (#2080) +- **fix(core):** restore Claude Code adaptive thinking defaults and resolve audio transcription CORS regression +- **fix(routing):** add missing v1beta rewrites to next.config to resolve 404 on Gemini models endpoint (#2102) +- **fix(routing):** fix bare GPT-5.5 routing for Codex-only installations (#2054) +- **fix(routing):** add fuzzy auto-combo routing for `auto/*` model prefix (#2010) - **fix(cache):** optimize cache_control preservation logic and explicitly align tool schema with upstream Claude Code expectations - **fix(db):** preserve legacy SQLite database path on Windows to prevent data loss (#1973) +- **fix(db):** reduce hot-path persistence overhead (#2039) +- **fix(db):** resolve migration conflict by renumbering overlapping migration entries (#2041) - **fix(settings):** resolve model alias persistence double stringification preventing UI updates (#2018) - **fix(routing):** dynamically filter bare model auto-resolution by active provider connections to prevent dead-routing (#2029) - **fix(embeddings):** add Google Gemini embeddings compatibility via OpenAI-compatible endpoint mapping (#2006) +- **fix(sse):** prevent Claude OAuth multi-account correlation via metadata.user_id (#2053) +- **fix(sse):** prevent Claude Code identity cloak overrides and fix fallback resilience (#2053) +- **fix(sse):** classify hour quota errors as QUOTA_EXHAUSTED (#2119) +- **fix(sse):** fix CC-compatible streaming bridge (#2118) +- **fix(antigravity):** sanitize Claude Cloud Code payloads (#2090) +- **fix(antigravity):** add duplex half for streaming bodies +- **fix(antigravity):** align identity protocol and behavior with official AM +- **fix(chatgpt-web):** plumb proxy through to native tls-client (#2022, #2023) +- **fix(codex):** expose native model IDs in catalog (#2012) +- **fix(glm):** add dedicated coding transport (#2087) +- **fix(compression):** support Responses input and expand Spanish compression rules (#2028) +- **fix(catalog):** auto-calculate combo context_length from target model limits (#2030) +- **fix(api):** fix usage analytics and API key identity (#2008, #2092) +- **fix(api-key):** allow Unicode letters in API key name validation (#1996) +- **fix(auth):** allow bootstrap without password (#2048) +- **fix(proxy):** clean up proxy page redundancy and fix 1proxy sync empty body error (#2052) +- **fix(dashboard):** resolve Unknown plan display in Provider Limits +- **fix(usage):** add extensible CURRENCY_SYMBOLS mapping for deepseek currencies +- **fix(runtime):** harden timer handling and model pricing fallback +- **fix(i18n):** complete Simplified Chinese translations (#2115) +- **fix(mitm):** add Linux cert install and skip sudo password when root (#1999) +- **fix(mitm):** prevent stub from loading at runtime via bypass module - **fix:** remove Anthropic-Beta header from non-Anthropic providers to fix identity contamination (#1989) - **fix(cli):** resolve .env loading failure for global npm installations +- **fix(export):** exclude telemetry/usage-history tables from JSON config backups by default to prevent unbounded file growth (#2125) +- **fix:** Follow OpenAI specification, handle throttling in batch and fix UI (#2045) -### 🔒 Security +### Безопасность +- **fix(security):** remediate CodeQL vulnerabilities (ReDoS, cryptographic bias, stack trace exposure, and weak password hashing) (#216, #215, #211, #208, #206, #210) - **fix(security):** remediate regex validation backtracking path in core compression cleanup (#1990) - **fix(core):** harden input handling and stabilization for prompt compression edge cases +### Документация + +- **docs:** add competitive marketing tables and SEO/AEO optimizations to README (#2091) +- **docs:** refresh providers, model catalogs, and docs for v3.8.0 (#2088) +- **docs:** update Claude MD and update GLM-CN max context to 200k (#2027) +- **docs(env):** add `GITLAB_DUO_OAUTH_CLIENT_ID` to `.env.example` (#2031) + ### 🧹 Chores & Maintenance - **chore(providers):** prune redundant local provider icon assets in favor of `@lobehub/icons` web fonts (#1992) +- **chore(providers):** remove deprecated models (#2033) +- **deps:** bump `fast-uri` from 3.1.0 to 3.1.2 (#2078) +- **deps:** bump `hono` from 4.12.14 to 4.12.18 (#2079) - **ci:** skip SonarCloud scan on main pushes to optimize CI time - **test:** stabilize cooldown abort coverage case in integration testing +### 🏆 v3.8.0 Community Contributors + +Thank you to all **38 community contributors** who made v3.8.0 possible! 🎉 + +| Contributor | PRs | Contributions | +| :--------------------------------------------------------- | :-: | :------------------------------------------------------------ | +| [@oyi77](https://github.com/oyi77) | 7 | #2010, #2014, #2041, #2052, #2061, #2074, #2091, #2094, #2096 | +| [@backryun](https://github.com/backryun) | 4 | #1992, #2033, #2088, #2123 | +| [@dhaern](https://github.com/dhaern) | 4 | #2028, #2039, #2087, #2090 | +| [@Tentoxa](https://github.com/Tentoxa) | 2 | #2011, #2053 | +| [@wauputr4](https://github.com/wauputr4) | 2 | #2009, #2046 | +| [@payne0420](https://github.com/payne0420) | 1 | #2082 | +| [@Tr0sT](https://github.com/Tr0sT) | 1 | #2012 | +| [@AveryanAlex](https://github.com/AveryanAlex) | 1 | #2008 | +| [@nickwizard](https://github.com/nickwizard) | 1 | #1991 | +| [@rodrigogbbr-stack](https://github.com/rodrigogbbr-stack) | 1 | #1996 | +| [@NekoMonci12](https://github.com/NekoMonci12) | 1 | #1999 | +| [@congvc-dev](https://github.com/congvc-dev) | 1 | #2004 | +| [@tatsster](https://github.com/tatsster) | 1 | #2007 | +| [@xssdem](https://github.com/xssdem) | 1 | #2023 | +| [@bypanghu](https://github.com/bypanghu) | 1 | #2027 | +| [@herjarsa](https://github.com/herjarsa) | 1 | #2030 | +| [@wucm667](https://github.com/wucm667) | 1 | #2031 | +| [@hartmark](https://github.com/hartmark) | 1 | #2045 | +| [@ddarkr](https://github.com/ddarkr) | 1 | #2047 | +| [@tces1](https://github.com/tces1) | 1 | #2048 | +| [@guanbear](https://github.com/guanbear) | 1 | #2054 | +| [@Gi99lin](https://github.com/Gi99lin) | 1 | #2055 | +| [@ivan-mezentsev](https://github.com/ivan-mezentsev) | 1 | #2063 | +| [@JxnLexn](https://github.com/JxnLexn) | 1 | #2019 | +| [@yoviarpauzi](https://github.com/yoviarpauzi) | 1 | #2092 | +| [@rafacpti23](https://github.com/rafacpti23) | 1 | #2086 | +| [@gleber](https://github.com/gleber) | 1 | #2103 | +| [@rilham97](https://github.com/rilham97) | 1 | #2104 | +| [@Gioxaa](https://github.com/Gioxaa) | 1 | #2105 | +| [@boa-z](https://github.com/boa-z) | 1 | #2115 | +| [@eleata](https://github.com/eleata) | 1 | #2116 | +| [@rdself](https://github.com/rdself) | 1 | #2118 | +| [@clousky2020](https://github.com/clousky2020) | 1 | #2119 | +| [@abhinavjnu](https://github.com/abhinavjnu) | 1 | #2122 | +| [@HoaPham98](https://github.com/HoaPham98) | 1 | #2089 | +| [@05dunski](https://github.com/05dunski) | 1 | #1978 (cherry-picked) | + ## [3.7.9] — 2026-05-03 ### ✨ New Features @@ -102,7 +220,7 @@ - **chore(provider):** Add reka models list (#1956 — thanks @backryun) - **chore(model):** Update new models, Delete Deprecated models (#1949 — thanks @backryun) -### 📝 Documentation +### Документация - **docs(compression):** document RTK+Caveman stacked savings ranges @@ -201,7 +319,7 @@ - **feat(db):** auto-restore probe-failed database on startup to prevent data loss after failed upgrades (#1810) - **feat(analytics):** add cost-based usage insights and activity streaks in the analytics dashboard -### 🔒 Security +### Безопасность - **fix(security):** resolve ReDoS vulnerability in Codex executor regex patterns (#1797, #1789) @@ -354,7 +472,7 @@ We identified that **155 community PRs** across the entire project history (from - **feat(proxy):** implement bulk proxy import via pipe-delimited parser with update-or-create (upsert) logic and real-time preview table - **feat(pwa):** add fullscreen installable PWA with manifest, service worker, and cross-platform app icons (#1728) -### 🔒 Security +### Безопасность - **security:** replace insecure `Math.random` with `crypto.getRandomValues` for fallback UUID generation to resolve CodeQL CWE-338 finding (#182) @@ -519,7 +637,7 @@ We identified that **155 community PRs** across the entire project history (from - **fix(transport):** Prevent memory bloat and database exhaustion from large, fragmented streaming responses. Implemented `ByteQueue` in `kiro.ts` for zero-copy binary accumulation, refactored `antigravity.ts` for incremental SSE parsing, and enforced a strict 512KB tiered truncation limit (`MAX_CALL_LOG_ARTIFACT_BYTES`) on stream request logs and call artifacts (#1647). - **chore(ci):** Update build environment dependencies — bump Node to `24.15.0`, `actions/checkout@v6`, `docker/build-push-action@v7`, pin `actions/setup-python` to major tag (#1646 — thanks @backryun). -### 📝 Documentation +### Документация - **docs(env):** Add `OMNIROUTE_ALLOW_PRIVATE_PROVIDER_URLS` to `.env.example` with documentation for LM Studio and other local provider use cases (#1623). @@ -669,7 +787,7 @@ We identified that **155 community PRs** across the entire project history (from - **test(next):** Align transpile package expectations for the Next.js standalone build. - **test(ci):** Fix CI-only test failures from environment differences — clear `INITIAL_PASSWORD` and `JWT_SECRET` in integration tests, handle `XDG_CONFIG_HOME` for guide-settings tests. -### 📚 Documentation +### Документация - **docs:** Update the root changelog with all release-branch changes through 2026-04-24, including PRs #1544, #1555, #1551, #1550, #1548, #1547, #1541, #1538, #1536, and #1527. - **docs:** Fix broken README and localized documentation links. (#1536) @@ -811,7 +929,7 @@ We identified that **155 community PRs** across the entire project history (from - **feat(providers):** Expand image provider registry with extended model support including SD3.5, FLUX, and DALL-E 3 HD configurations - **feat(combos):** Add new routing strategies and full i18n support for agent features section across 31 languages -### 🔒 Security +### Безопасность - **security:** Resolve 18 GitHub CodeQL scan alerts including ReDoS, incomplete sanitization, and bad HTML filtering regexp patterns - **fix(auth):** Seal privilege escalation vector by enforcing JWT session checking exclusively on `/api/keys` management endpoints (#1353) @@ -1078,7 +1196,7 @@ We identified that **155 community PRs** across the entire project history (from - **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 - **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 -### 🔒 Security +### Безопасность - **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 - **Auth Guard on Translator Save:** Added `isAuthenticated` guard to `/api/translator/save` for defense-in-depth consistency @@ -1483,7 +1601,7 @@ We identified that **155 community PRs** across the entire project history (from - **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). -### 📚 Documentation +### Документация - **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. - **Context Relay Delivery Notes:** Documented the current architecture, runtime flow, and Codex-focused scope in the feature docs, changelog, and agent guidance. @@ -1559,7 +1677,7 @@ We identified that **155 community PRs** across the entire project history (from ## [3.5.3] - 2026-04-07 -### Security +### Безопасность - **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. - **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. @@ -1575,7 +1693,7 @@ We identified that **155 community PRs** across the entire project history (from - **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. -### Documentation +### Документация - **I18n Engine:** Synchronized and pushed deep Machine Translation updates across all 32 natively-supported languages (682 translation nodes aligned). @@ -1736,7 +1854,7 @@ We identified that **155 community PRs** across the entire project history (from ## [3.4.8] — 2026-04-03 -### Security +### Безопасность - Fully remediated all outstanding Github Advanced Security (CodeQL) findings and Dependabot alerts. - Fixed insecure randomness vulnerabilities by migrating from `Math.random` to `crypto.randomUUID()`. @@ -1748,7 +1866,7 @@ We identified that **155 community PRs** across the entire project history (from ## [3.4.7] — 2026-04-03 -### Features +### Возможности - Added `Cryptography` node to Monitoring and MCP health checks (#798) - Hardened model-catalog route permissions mapping (`/models`) (#781) @@ -1764,7 +1882,7 @@ We identified that **155 community PRs** across the entire project history (from - Fixed MCP standalone module-resolution (`ERR_MODULE_NOT_FOUND`) via `esbuild` (#936) - Fixed NVIDIA NIM routing credential resolution alias mismatch (#931) -### Security +### Безопасность - Added safe strict input boundary protection against raw `shell: true` remote-code execution injections. @@ -2011,7 +2129,7 @@ We identified that **155 community PRs** across the entire project history (from ## [3.4.0] - 2026-03-31 -### 🚀 Features +### Возможности - **Subscription Utilization Analytics:** Added quota snapshot time-series tracking, Provider Utilization and Combo Health tabs with recharts visualizations, and corresponding API endpoints (#847) - **SQLite Backup Control:** New `OMNIROUTE_DISABLE_AUTO_BACKUP` env flag to disable automatic SQLite backups (#846) @@ -2063,7 +2181,7 @@ We identified that **155 community PRs** across the entire project history (from ## [3.3.8] - 2026-03-30 -### 🚀 Features +### Возможности - **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) - **Qoder Integration:** Native integration for Qoder AI natively replacing the legacy iFlow platform mappings (#660) @@ -2889,7 +3007,7 @@ We identified that **155 community PRs** across the entire project history (from - **NaN tokens in Claude Code / client responses (#617):** - `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 -### 🔒 Security +### Безопасность - Updated `yaml` package to fix stack overflow vulnerability (GHSA-48c2-rrv3-qjmp) @@ -3565,7 +3683,7 @@ docker pull diegosouzapw/omniroute:3.0.0 - **SVG fallback**: `ProviderIcon` component updated with 4-tier strategy: Lobehub → PNG → SVG → Generic icon - **Agents fingerprinting**: Synced with CLI tools — added droid, openclaw, copilot, opencode to fingerprint list (14 total) -### 🔒 Security +### Безопасность - **CVE fix**: Resolved dompurify XSS vulnerability (GHSA-v2wj-7wpq-c8vv) via npm overrides forcing `dompurify@^3.3.2` - `npm audit` now reports **0 vulnerabilities** @@ -3928,7 +4046,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **#510** — Windows: MSYS2/Git-Bash paths (`/c/Program Files/...`) are now normalized to `C:\Program Files\...` - **#492** — `omniroute` CLI now detects `mise`/`nvm` when `app/server.js` is missing and shows targeted fix -### 📖 Documentation +### Документация - **#513** — Docker password reset: `INITIAL_PASSWORD` env var workaround documented - **#520** — pnpm: `pnpm approve-builds better-sqlite3` documented @@ -4025,7 +4143,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **feat(executors/cloudflare-ai)**: New `CloudflareAIExecutor` — dynamic URL construction requires `accountId` in provider credentials - **feat(executors)**: Register `pollinations`, `pol`, `cloudflare-ai`, `cf` executor mappings -### 📝 Documentation +### Документация - **docs(readme)**: Expanded free combo stack to 11 providers ($0 forever) - **docs(readme)**: Added 4 new free provider sections (LongCat, Pollinations, Cloudflare AI, Scaleway) with model tables @@ -4177,7 +4295,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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). -### Features +### Возможности - **"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. @@ -4205,7 +4323,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Merge PR #494 (MiniMax role fix), fix KIRO MITM dashboard, triage 8 issues. -### Features +### Возможности - **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. - **roleNormalizer**: `normalizeDeveloperRole()` now accepts `preserveDeveloperRole` parameter with tri-state behavior (undefined=keep, true=keep, false=convert). @@ -4261,7 +4379,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Gemini CLI deprecation, VM guide i18n fix, dependabot security fix, provider schema expansion. -### Features +### Возможности - **Gemini CLI Deprecation** (#462): Mark `gemini-cli` provider as deprecated with warning — Google restricts third-party OAuth usage from March 2026 - **Provider Schema** (#462): Expand Zod validation with `deprecated`, `deprecationReason`, `hasFree`, `freeNote`, `authHint`, `apiHint` optional fields @@ -4270,7 +4388,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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) -### Security +### Безопасность - **deps**: Bump `flatted` 3.3.3 → 3.4.2 — fixes CWE-1321 prototype pollution (#484, @dependabot) @@ -4290,7 +4408,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Czech i18n, SSE protocol fix, VM guide translation. -### Features +### Возможности - **Czech Language** (#482): Full Czech (cs) i18n — 22 docs, 2606 UI strings, language switcher updates (@zen0bit) - **VM Deployment Guide**: Translated from Portuguese to English as the source document (@zen0bit) @@ -4309,7 +4427,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: 2 merged PRs, model aliases routing fix, log export, and issue triage. -### Features +### Возможности - **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) @@ -4329,7 +4447,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Five community PRs — streaming call log fixes, Kiro compatibility, cache token analytics, Chinese translation, and configurable tool call IDs. -### ✨ Features +### Возможности - **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) - **feat(providers)**: Per-model configurable 9-char tool call ID normalization (Mistral-style) — only models with the option enabled get truncated IDs (#470) @@ -4359,7 +4477,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Bailian Coding Plan provider with editable base URLs, plus community contributions for Alibaba Cloud and Kimi Coding. -### ✨ Features +### Возможности - **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) - **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) @@ -4374,7 +4492,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Two new community-contributed providers (Alibaba Cloud Coding, Kimi Coding API-key) and Docker pino fix. -### ✨ Features +### Возможности - **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) - **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) @@ -4399,7 +4517,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Codex responses subpath passthrough natively supported, Windows MITM crash fixed, and Combos agent schemas adjusted. -### ✨ Features +### Возможности - **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) @@ -4439,7 +4557,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **fix(budget)**: "Save Limits" no longer returns 422 — `warningThreshold` is now correctly sent as fraction (0–1) instead of percentage (0–100) (#451) - **fix(combos)**: `` internal cache tag is now stripped before forwarding requests to providers, preventing cache session breaks (#454) -### ✨ Features +### Возможности - **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) @@ -4495,7 +4613,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Search Tools dashboard, i18n fixes, Copilot limits, Serper validation fix. -### 🚀 Features +### Возможности - **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) - New route: `/dashboard/search-tools` @@ -4595,7 +4713,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - DB migration: `request_type` column on `call_logs` for non-chat request tracking - Zod validation (`v1SearchSchema`), auth-gated, cost recorded via `recordCost()` -### 🔒 Security +### Безопасность - **deps**: Next.js 16.1.6 → 16.1.7 — fixes 6 CVEs: - **Critical**: CVE-2026-29057 (HTTP request smuggling via http-proxy) @@ -4725,7 +4843,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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**: New `request_detail_logs` table with 500-entry ring-buffer trigger, opt-in via settings toggle -### ✨ Features +### Возможности - **feat(combo)**: System Message Override per Combo (#399 — `system_message` field replaces or injects system prompt before forwarding to provider) - **feat(combo)**: Tool Filter Regex per Combo (#399 — `tool_filter_regex` keeps only tools matching pattern; supports OpenAI + Anthropic formats) @@ -4740,7 +4858,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: SSE improvements, local provider_nodes extensions, proxy registry, Claude passthrough fixes. -### ✨ Features +### Возможности - **feat(health)**: Background health check for local `provider_nodes` with exponential backoff (30s→300s) and `Promise.allSettled` to avoid blocking (#423, @Regis-RCR) - **feat(embeddings)**: Route `/v1/embeddings` to local `provider_nodes` — `buildDynamicEmbeddingProvider()` with hostname validation (#422, @Regis-RCR) @@ -4882,7 +5000,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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 - **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). -### ✨ Features +### Возможности - **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) @@ -4912,7 +5030,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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) - **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) -### ✨ Features +### Возможности - **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) - **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. @@ -4971,7 +5089,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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) - **fix(logs)**: Request log table is now readable in light mode — status badges, token counts, and combo tags use adaptive `dark:` color classes (#378) -### ✨ Features +### Возможности - **feat(kiro)**: Kiro credit tracking added to usage fetcher — queries `getUserCredits` from AWS CodeWhisperer endpoint (#337) @@ -5372,7 +5490,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > **Major release** — Free Stack ecosystem, transcription playground overhaul, 44+ providers, comprehensive free tier documentation, and UI improvements across the board. -### ✨ Features +### Возможности - **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. - **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. @@ -5383,7 +5501,7 @@ OmniRoute now automatically refreshes model lists for connected providers every ## [2.3.16] - 2026-03-13 -### 📖 Documentation +### Документация - **README: 44+ Providers** — Updated all 3 occurrences of "36+ providers" to "44+" reflecting the actual codebase count (44 providers in providers.ts) - **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. @@ -5393,7 +5511,7 @@ OmniRoute now automatically refreshes model lists for connected providers every ## [2.3.15] - 2026-03-13 -### ✨ Features +### Возможности - **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. - **i18n — autoCombo section**: Added 20 new translation keys for the Auto-Combo dashboard (`title`, `status`, `modePack`, `providerScores`, `factorTierPriority`, etc.) to all 30 language files. diff --git a/docs/i18n/sk/CHANGELOG.md b/docs/i18n/sk/CHANGELOG.md index a15a801e54..4a39586fb5 100644 --- a/docs/i18n/sk/CHANGELOG.md +++ b/docs/i18n/sk/CHANGELOG.md @@ -10,30 +10,148 @@ ### ✨ New Features -- **feat(antigravity):** integrate Antigravity provider with dynamic `maxOutputTokens` calculation (bumping to `thinkingBudget + 1`) and standard Cloud Code envelope payload sanitization (#2055, #2063) +- **feat(antigravity):** integrate Antigravity provider with dynamic `maxOutputTokens` calculation, identity fingerprinting overhaul, and Cloud Code envelope payload sanitization (#2055, #2063) - **feat(gemini-cli):** add custom projectId support for Gemini CLI transport (UI, DB, executor) (#1991) +- **feat(providers):** add KIE media provider support with dynamic polling, text models, and expanded video models catalog +- **feat(providers):** add Z.AI provider support with GLM quota handling and new quota labels +- **feat(providers):** add 9 new free AI providers — LLM7, Lepton, Kluster, UncloseAI, BazaarLink, Completions, Enally, FreeTheAi (#2096) +- **feat(providers):** batch delete provider connections via checkbox multi-select (#2094) +- **feat(cursor):** full OpenAI parity — tool calls, streaming, and session management (#2082) +- **feat(cli):** comprehensive CLI enhancement suite with 20+ new commands including `omniroute providers`, `omniroute combos`, `omniroute doctor` (#2074) +- **feat(cli):** add modular CLI setup and provider management commands (#2046) +- **feat(mcp):** add DeepSeek quota and limit monitoring feature (#2089) +- **feat(circuit-breaker):** classify 429 errors and apply per-kind cooldowns (#2116) +- **feat(multi):** manifest-aware tier routing — W1-W4 complete (#2014) +- **feat(combos):** add reset-aware routing strategy for quota-based providers +- **feat(combo):** add context_length input field to combo edit form (#2047) +- **feat(chat):** dynamic tool limit detection with proactive truncation (#2061) +- **feat(sse):** refresh Claude OAuth wire image to claude-cli/2.1.131 (#2011) +- **feat(github):** add `targetFormat: openai-responses` to all GitHub models (#2122) +- **feat(api):** allow configuration via API calls — open management routes to Bearer keys with manage scope (#2103) +- **feat(api):** update API bridge proxy timeout to 600,000ms (#2019) +- **feat(usage):** add service tier breakdown, codex fast service tier analytics, and account for fast tier +- **feat(chat):** add `STREAM_READINESS_TIMEOUT_MS` and integrate into chat handling +- **feat(combo):** add `fallbackDelayMs` to combo configuration and related settings +- **feat(chat):** enhance error handling for semaphore capacity with fallback logic +- **feat(qdrant):** embedding model discovery (#2086) +- **feat(auth):** per-session sticky routing for Codex (#1887) +- **feat(inworld):** enhance Inworld TTS support (#2123) ### 🐛 Bug Fixes +- **fix(pricing):** make `getPricingForModel` fully case-insensitive to ensure custom prices correctly reflect in new incoming requests cost calculations +- **fix(gemini):** prevent `functionDeclarations` from being dropped by the sanitizer when `googleSearch` tool is present (#2077) +- **fix(pollinations):** add `jsonMode: true` flag in the request transformation to enforce correct JSON structure from Pollinations API (#2109) +- **fix(docker):** update Dockerfile to copy `/docs` directory during build ensuring API catalog availability at runtime (#2083) +- **fix(docker):** include OpenAPI spec in runtime image (#2007) +- **fix(providers):** strip OpenAI-specific fields in Kiro translator to prevent 400 errors (#2037) +- **fix(kiro):** normalize tool-use payloads to prevent 400 errors from agents (#2104) +- **fix(kiro):** merge adjacent user history turns after role normalization (#2105) +- **fix(ui):** resolve text contrast issues for zero-config warning banner in light mode (#2050) +- **fix(core):** inject global system prompt correctly into downstream chat completions pipeline (#2080) +- **fix(core):** restore Claude Code adaptive thinking defaults and resolve audio transcription CORS regression +- **fix(routing):** add missing v1beta rewrites to next.config to resolve 404 on Gemini models endpoint (#2102) +- **fix(routing):** fix bare GPT-5.5 routing for Codex-only installations (#2054) +- **fix(routing):** add fuzzy auto-combo routing for `auto/*` model prefix (#2010) - **fix(cache):** optimize cache_control preservation logic and explicitly align tool schema with upstream Claude Code expectations - **fix(db):** preserve legacy SQLite database path on Windows to prevent data loss (#1973) +- **fix(db):** reduce hot-path persistence overhead (#2039) +- **fix(db):** resolve migration conflict by renumbering overlapping migration entries (#2041) - **fix(settings):** resolve model alias persistence double stringification preventing UI updates (#2018) - **fix(routing):** dynamically filter bare model auto-resolution by active provider connections to prevent dead-routing (#2029) - **fix(embeddings):** add Google Gemini embeddings compatibility via OpenAI-compatible endpoint mapping (#2006) +- **fix(sse):** prevent Claude OAuth multi-account correlation via metadata.user_id (#2053) +- **fix(sse):** prevent Claude Code identity cloak overrides and fix fallback resilience (#2053) +- **fix(sse):** classify hour quota errors as QUOTA_EXHAUSTED (#2119) +- **fix(sse):** fix CC-compatible streaming bridge (#2118) +- **fix(antigravity):** sanitize Claude Cloud Code payloads (#2090) +- **fix(antigravity):** add duplex half for streaming bodies +- **fix(antigravity):** align identity protocol and behavior with official AM +- **fix(chatgpt-web):** plumb proxy through to native tls-client (#2022, #2023) +- **fix(codex):** expose native model IDs in catalog (#2012) +- **fix(glm):** add dedicated coding transport (#2087) +- **fix(compression):** support Responses input and expand Spanish compression rules (#2028) +- **fix(catalog):** auto-calculate combo context_length from target model limits (#2030) +- **fix(api):** fix usage analytics and API key identity (#2008, #2092) +- **fix(api-key):** allow Unicode letters in API key name validation (#1996) +- **fix(auth):** allow bootstrap without password (#2048) +- **fix(proxy):** clean up proxy page redundancy and fix 1proxy sync empty body error (#2052) +- **fix(dashboard):** resolve Unknown plan display in Provider Limits +- **fix(usage):** add extensible CURRENCY_SYMBOLS mapping for deepseek currencies +- **fix(runtime):** harden timer handling and model pricing fallback +- **fix(i18n):** complete Simplified Chinese translations (#2115) +- **fix(mitm):** add Linux cert install and skip sudo password when root (#1999) +- **fix(mitm):** prevent stub from loading at runtime via bypass module - **fix:** remove Anthropic-Beta header from non-Anthropic providers to fix identity contamination (#1989) - **fix(cli):** resolve .env loading failure for global npm installations +- **fix(export):** exclude telemetry/usage-history tables from JSON config backups by default to prevent unbounded file growth (#2125) +- **fix:** Follow OpenAI specification, handle throttling in batch and fix UI (#2045) -### 🔒 Security +### Bezpečnosť +- **fix(security):** remediate CodeQL vulnerabilities (ReDoS, cryptographic bias, stack trace exposure, and weak password hashing) (#216, #215, #211, #208, #206, #210) - **fix(security):** remediate regex validation backtracking path in core compression cleanup (#1990) - **fix(core):** harden input handling and stabilization for prompt compression edge cases +### Dokumentácia + +- **docs:** add competitive marketing tables and SEO/AEO optimizations to README (#2091) +- **docs:** refresh providers, model catalogs, and docs for v3.8.0 (#2088) +- **docs:** update Claude MD and update GLM-CN max context to 200k (#2027) +- **docs(env):** add `GITLAB_DUO_OAUTH_CLIENT_ID` to `.env.example` (#2031) + ### 🧹 Chores & Maintenance - **chore(providers):** prune redundant local provider icon assets in favor of `@lobehub/icons` web fonts (#1992) +- **chore(providers):** remove deprecated models (#2033) +- **deps:** bump `fast-uri` from 3.1.0 to 3.1.2 (#2078) +- **deps:** bump `hono` from 4.12.14 to 4.12.18 (#2079) - **ci:** skip SonarCloud scan on main pushes to optimize CI time - **test:** stabilize cooldown abort coverage case in integration testing +### 🏆 v3.8.0 Community Contributors + +Thank you to all **38 community contributors** who made v3.8.0 possible! 🎉 + +| Contributor | PRs | Contributions | +| :--------------------------------------------------------- | :-: | :------------------------------------------------------------ | +| [@oyi77](https://github.com/oyi77) | 7 | #2010, #2014, #2041, #2052, #2061, #2074, #2091, #2094, #2096 | +| [@backryun](https://github.com/backryun) | 4 | #1992, #2033, #2088, #2123 | +| [@dhaern](https://github.com/dhaern) | 4 | #2028, #2039, #2087, #2090 | +| [@Tentoxa](https://github.com/Tentoxa) | 2 | #2011, #2053 | +| [@wauputr4](https://github.com/wauputr4) | 2 | #2009, #2046 | +| [@payne0420](https://github.com/payne0420) | 1 | #2082 | +| [@Tr0sT](https://github.com/Tr0sT) | 1 | #2012 | +| [@AveryanAlex](https://github.com/AveryanAlex) | 1 | #2008 | +| [@nickwizard](https://github.com/nickwizard) | 1 | #1991 | +| [@rodrigogbbr-stack](https://github.com/rodrigogbbr-stack) | 1 | #1996 | +| [@NekoMonci12](https://github.com/NekoMonci12) | 1 | #1999 | +| [@congvc-dev](https://github.com/congvc-dev) | 1 | #2004 | +| [@tatsster](https://github.com/tatsster) | 1 | #2007 | +| [@xssdem](https://github.com/xssdem) | 1 | #2023 | +| [@bypanghu](https://github.com/bypanghu) | 1 | #2027 | +| [@herjarsa](https://github.com/herjarsa) | 1 | #2030 | +| [@wucm667](https://github.com/wucm667) | 1 | #2031 | +| [@hartmark](https://github.com/hartmark) | 1 | #2045 | +| [@ddarkr](https://github.com/ddarkr) | 1 | #2047 | +| [@tces1](https://github.com/tces1) | 1 | #2048 | +| [@guanbear](https://github.com/guanbear) | 1 | #2054 | +| [@Gi99lin](https://github.com/Gi99lin) | 1 | #2055 | +| [@ivan-mezentsev](https://github.com/ivan-mezentsev) | 1 | #2063 | +| [@JxnLexn](https://github.com/JxnLexn) | 1 | #2019 | +| [@yoviarpauzi](https://github.com/yoviarpauzi) | 1 | #2092 | +| [@rafacpti23](https://github.com/rafacpti23) | 1 | #2086 | +| [@gleber](https://github.com/gleber) | 1 | #2103 | +| [@rilham97](https://github.com/rilham97) | 1 | #2104 | +| [@Gioxaa](https://github.com/Gioxaa) | 1 | #2105 | +| [@boa-z](https://github.com/boa-z) | 1 | #2115 | +| [@eleata](https://github.com/eleata) | 1 | #2116 | +| [@rdself](https://github.com/rdself) | 1 | #2118 | +| [@clousky2020](https://github.com/clousky2020) | 1 | #2119 | +| [@abhinavjnu](https://github.com/abhinavjnu) | 1 | #2122 | +| [@HoaPham98](https://github.com/HoaPham98) | 1 | #2089 | +| [@05dunski](https://github.com/05dunski) | 1 | #1978 (cherry-picked) | + ## [3.7.9] — 2026-05-03 ### ✨ New Features @@ -102,7 +220,7 @@ - **chore(provider):** Add reka models list (#1956 — thanks @backryun) - **chore(model):** Update new models, Delete Deprecated models (#1949 — thanks @backryun) -### 📝 Documentation +### Dokumentácia - **docs(compression):** document RTK+Caveman stacked savings ranges @@ -201,7 +319,7 @@ - **feat(db):** auto-restore probe-failed database on startup to prevent data loss after failed upgrades (#1810) - **feat(analytics):** add cost-based usage insights and activity streaks in the analytics dashboard -### 🔒 Security +### Bezpečnosť - **fix(security):** resolve ReDoS vulnerability in Codex executor regex patterns (#1797, #1789) @@ -354,7 +472,7 @@ We identified that **155 community PRs** across the entire project history (from - **feat(proxy):** implement bulk proxy import via pipe-delimited parser with update-or-create (upsert) logic and real-time preview table - **feat(pwa):** add fullscreen installable PWA with manifest, service worker, and cross-platform app icons (#1728) -### 🔒 Security +### Bezpečnosť - **security:** replace insecure `Math.random` with `crypto.getRandomValues` for fallback UUID generation to resolve CodeQL CWE-338 finding (#182) @@ -519,7 +637,7 @@ We identified that **155 community PRs** across the entire project history (from - **fix(transport):** Prevent memory bloat and database exhaustion from large, fragmented streaming responses. Implemented `ByteQueue` in `kiro.ts` for zero-copy binary accumulation, refactored `antigravity.ts` for incremental SSE parsing, and enforced a strict 512KB tiered truncation limit (`MAX_CALL_LOG_ARTIFACT_BYTES`) on stream request logs and call artifacts (#1647). - **chore(ci):** Update build environment dependencies — bump Node to `24.15.0`, `actions/checkout@v6`, `docker/build-push-action@v7`, pin `actions/setup-python` to major tag (#1646 — thanks @backryun). -### 📝 Documentation +### Dokumentácia - **docs(env):** Add `OMNIROUTE_ALLOW_PRIVATE_PROVIDER_URLS` to `.env.example` with documentation for LM Studio and other local provider use cases (#1623). @@ -669,7 +787,7 @@ We identified that **155 community PRs** across the entire project history (from - **test(next):** Align transpile package expectations for the Next.js standalone build. - **test(ci):** Fix CI-only test failures from environment differences — clear `INITIAL_PASSWORD` and `JWT_SECRET` in integration tests, handle `XDG_CONFIG_HOME` for guide-settings tests. -### 📚 Documentation +### Dokumentácia - **docs:** Update the root changelog with all release-branch changes through 2026-04-24, including PRs #1544, #1555, #1551, #1550, #1548, #1547, #1541, #1538, #1536, and #1527. - **docs:** Fix broken README and localized documentation links. (#1536) @@ -811,7 +929,7 @@ We identified that **155 community PRs** across the entire project history (from - **feat(providers):** Expand image provider registry with extended model support including SD3.5, FLUX, and DALL-E 3 HD configurations - **feat(combos):** Add new routing strategies and full i18n support for agent features section across 31 languages -### 🔒 Security +### Bezpečnosť - **security:** Resolve 18 GitHub CodeQL scan alerts including ReDoS, incomplete sanitization, and bad HTML filtering regexp patterns - **fix(auth):** Seal privilege escalation vector by enforcing JWT session checking exclusively on `/api/keys` management endpoints (#1353) @@ -1078,7 +1196,7 @@ We identified that **155 community PRs** across the entire project history (from - **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 - **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 -### 🔒 Security +### Bezpečnosť - **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 - **Auth Guard on Translator Save:** Added `isAuthenticated` guard to `/api/translator/save` for defense-in-depth consistency @@ -1483,7 +1601,7 @@ We identified that **155 community PRs** across the entire project history (from - **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). -### 📚 Documentation +### Dokumentácia - **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. - **Context Relay Delivery Notes:** Documented the current architecture, runtime flow, and Codex-focused scope in the feature docs, changelog, and agent guidance. @@ -1559,7 +1677,7 @@ We identified that **155 community PRs** across the entire project history (from ## [3.5.3] - 2026-04-07 -### Security +### Bezpečnosť - **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. - **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. @@ -1575,7 +1693,7 @@ We identified that **155 community PRs** across the entire project history (from - **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. -### Documentation +### Dokumentácia - **I18n Engine:** Synchronized and pushed deep Machine Translation updates across all 32 natively-supported languages (682 translation nodes aligned). @@ -1736,7 +1854,7 @@ We identified that **155 community PRs** across the entire project history (from ## [3.4.8] — 2026-04-03 -### Security +### Bezpečnosť - Fully remediated all outstanding Github Advanced Security (CodeQL) findings and Dependabot alerts. - Fixed insecure randomness vulnerabilities by migrating from `Math.random` to `crypto.randomUUID()`. @@ -1748,7 +1866,7 @@ We identified that **155 community PRs** across the entire project history (from ## [3.4.7] — 2026-04-03 -### Features +### Funkcie - Added `Cryptography` node to Monitoring and MCP health checks (#798) - Hardened model-catalog route permissions mapping (`/models`) (#781) @@ -1764,7 +1882,7 @@ We identified that **155 community PRs** across the entire project history (from - Fixed MCP standalone module-resolution (`ERR_MODULE_NOT_FOUND`) via `esbuild` (#936) - Fixed NVIDIA NIM routing credential resolution alias mismatch (#931) -### Security +### Bezpečnosť - Added safe strict input boundary protection against raw `shell: true` remote-code execution injections. @@ -2011,7 +2129,7 @@ We identified that **155 community PRs** across the entire project history (from ## [3.4.0] - 2026-03-31 -### 🚀 Features +### Funkcie - **Subscription Utilization Analytics:** Added quota snapshot time-series tracking, Provider Utilization and Combo Health tabs with recharts visualizations, and corresponding API endpoints (#847) - **SQLite Backup Control:** New `OMNIROUTE_DISABLE_AUTO_BACKUP` env flag to disable automatic SQLite backups (#846) @@ -2063,7 +2181,7 @@ We identified that **155 community PRs** across the entire project history (from ## [3.3.8] - 2026-03-30 -### 🚀 Features +### Funkcie - **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) - **Qoder Integration:** Native integration for Qoder AI natively replacing the legacy iFlow platform mappings (#660) @@ -2889,7 +3007,7 @@ We identified that **155 community PRs** across the entire project history (from - **NaN tokens in Claude Code / client responses (#617):** - `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 -### 🔒 Security +### Bezpečnosť - Updated `yaml` package to fix stack overflow vulnerability (GHSA-48c2-rrv3-qjmp) @@ -3565,7 +3683,7 @@ docker pull diegosouzapw/omniroute:3.0.0 - **SVG fallback**: `ProviderIcon` component updated with 4-tier strategy: Lobehub → PNG → SVG → Generic icon - **Agents fingerprinting**: Synced with CLI tools — added droid, openclaw, copilot, opencode to fingerprint list (14 total) -### 🔒 Security +### Bezpečnosť - **CVE fix**: Resolved dompurify XSS vulnerability (GHSA-v2wj-7wpq-c8vv) via npm overrides forcing `dompurify@^3.3.2` - `npm audit` now reports **0 vulnerabilities** @@ -3928,7 +4046,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **#510** — Windows: MSYS2/Git-Bash paths (`/c/Program Files/...`) are now normalized to `C:\Program Files\...` - **#492** — `omniroute` CLI now detects `mise`/`nvm` when `app/server.js` is missing and shows targeted fix -### 📖 Documentation +### Dokumentácia - **#513** — Docker password reset: `INITIAL_PASSWORD` env var workaround documented - **#520** — pnpm: `pnpm approve-builds better-sqlite3` documented @@ -4025,7 +4143,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **feat(executors/cloudflare-ai)**: New `CloudflareAIExecutor` — dynamic URL construction requires `accountId` in provider credentials - **feat(executors)**: Register `pollinations`, `pol`, `cloudflare-ai`, `cf` executor mappings -### 📝 Documentation +### Dokumentácia - **docs(readme)**: Expanded free combo stack to 11 providers ($0 forever) - **docs(readme)**: Added 4 new free provider sections (LongCat, Pollinations, Cloudflare AI, Scaleway) with model tables @@ -4177,7 +4295,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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). -### Features +### Funkcie - **"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. @@ -4205,7 +4323,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Merge PR #494 (MiniMax role fix), fix KIRO MITM dashboard, triage 8 issues. -### Features +### Funkcie - **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. - **roleNormalizer**: `normalizeDeveloperRole()` now accepts `preserveDeveloperRole` parameter with tri-state behavior (undefined=keep, true=keep, false=convert). @@ -4261,7 +4379,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Gemini CLI deprecation, VM guide i18n fix, dependabot security fix, provider schema expansion. -### Features +### Funkcie - **Gemini CLI Deprecation** (#462): Mark `gemini-cli` provider as deprecated with warning — Google restricts third-party OAuth usage from March 2026 - **Provider Schema** (#462): Expand Zod validation with `deprecated`, `deprecationReason`, `hasFree`, `freeNote`, `authHint`, `apiHint` optional fields @@ -4270,7 +4388,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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) -### Security +### Bezpečnosť - **deps**: Bump `flatted` 3.3.3 → 3.4.2 — fixes CWE-1321 prototype pollution (#484, @dependabot) @@ -4290,7 +4408,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Czech i18n, SSE protocol fix, VM guide translation. -### Features +### Funkcie - **Czech Language** (#482): Full Czech (cs) i18n — 22 docs, 2606 UI strings, language switcher updates (@zen0bit) - **VM Deployment Guide**: Translated from Portuguese to English as the source document (@zen0bit) @@ -4309,7 +4427,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: 2 merged PRs, model aliases routing fix, log export, and issue triage. -### Features +### Funkcie - **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) @@ -4329,7 +4447,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Five community PRs — streaming call log fixes, Kiro compatibility, cache token analytics, Chinese translation, and configurable tool call IDs. -### ✨ Features +### Funkcie - **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) - **feat(providers)**: Per-model configurable 9-char tool call ID normalization (Mistral-style) — only models with the option enabled get truncated IDs (#470) @@ -4359,7 +4477,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Bailian Coding Plan provider with editable base URLs, plus community contributions for Alibaba Cloud and Kimi Coding. -### ✨ Features +### Funkcie - **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) - **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) @@ -4374,7 +4492,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Two new community-contributed providers (Alibaba Cloud Coding, Kimi Coding API-key) and Docker pino fix. -### ✨ Features +### Funkcie - **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) - **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) @@ -4399,7 +4517,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Codex responses subpath passthrough natively supported, Windows MITM crash fixed, and Combos agent schemas adjusted. -### ✨ Features +### Funkcie - **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) @@ -4439,7 +4557,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **fix(budget)**: "Save Limits" no longer returns 422 — `warningThreshold` is now correctly sent as fraction (0–1) instead of percentage (0–100) (#451) - **fix(combos)**: `` internal cache tag is now stripped before forwarding requests to providers, preventing cache session breaks (#454) -### ✨ Features +### Funkcie - **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) @@ -4495,7 +4613,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Search Tools dashboard, i18n fixes, Copilot limits, Serper validation fix. -### 🚀 Features +### Funkcie - **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) - New route: `/dashboard/search-tools` @@ -4595,7 +4713,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - DB migration: `request_type` column on `call_logs` for non-chat request tracking - Zod validation (`v1SearchSchema`), auth-gated, cost recorded via `recordCost()` -### 🔒 Security +### Bezpečnosť - **deps**: Next.js 16.1.6 → 16.1.7 — fixes 6 CVEs: - **Critical**: CVE-2026-29057 (HTTP request smuggling via http-proxy) @@ -4725,7 +4843,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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**: New `request_detail_logs` table with 500-entry ring-buffer trigger, opt-in via settings toggle -### ✨ Features +### Funkcie - **feat(combo)**: System Message Override per Combo (#399 — `system_message` field replaces or injects system prompt before forwarding to provider) - **feat(combo)**: Tool Filter Regex per Combo (#399 — `tool_filter_regex` keeps only tools matching pattern; supports OpenAI + Anthropic formats) @@ -4740,7 +4858,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: SSE improvements, local provider_nodes extensions, proxy registry, Claude passthrough fixes. -### ✨ Features +### Funkcie - **feat(health)**: Background health check for local `provider_nodes` with exponential backoff (30s→300s) and `Promise.allSettled` to avoid blocking (#423, @Regis-RCR) - **feat(embeddings)**: Route `/v1/embeddings` to local `provider_nodes` — `buildDynamicEmbeddingProvider()` with hostname validation (#422, @Regis-RCR) @@ -4882,7 +5000,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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 - **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). -### ✨ Features +### Funkcie - **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) @@ -4912,7 +5030,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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) - **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) -### ✨ Features +### Funkcie - **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) - **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. @@ -4971,7 +5089,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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) - **fix(logs)**: Request log table is now readable in light mode — status badges, token counts, and combo tags use adaptive `dark:` color classes (#378) -### ✨ Features +### Funkcie - **feat(kiro)**: Kiro credit tracking added to usage fetcher — queries `getUserCredits` from AWS CodeWhisperer endpoint (#337) @@ -5372,7 +5490,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > **Major release** — Free Stack ecosystem, transcription playground overhaul, 44+ providers, comprehensive free tier documentation, and UI improvements across the board. -### ✨ Features +### Funkcie - **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. - **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. @@ -5383,7 +5501,7 @@ OmniRoute now automatically refreshes model lists for connected providers every ## [2.3.16] - 2026-03-13 -### 📖 Documentation +### Dokumentácia - **README: 44+ Providers** — Updated all 3 occurrences of "36+ providers" to "44+" reflecting the actual codebase count (44 providers in providers.ts) - **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. @@ -5393,7 +5511,7 @@ OmniRoute now automatically refreshes model lists for connected providers every ## [2.3.15] - 2026-03-13 -### ✨ Features +### Funkcie - **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. - **i18n — autoCombo section**: Added 20 new translation keys for the Auto-Combo dashboard (`title`, `status`, `modePack`, `providerScores`, `factorTierPriority`, etc.) to all 30 language files. diff --git a/docs/i18n/sv/CHANGELOG.md b/docs/i18n/sv/CHANGELOG.md index 054939b40e..c5ea260133 100644 --- a/docs/i18n/sv/CHANGELOG.md +++ b/docs/i18n/sv/CHANGELOG.md @@ -10,30 +10,148 @@ ### ✨ New Features -- **feat(antigravity):** integrate Antigravity provider with dynamic `maxOutputTokens` calculation (bumping to `thinkingBudget + 1`) and standard Cloud Code envelope payload sanitization (#2055, #2063) +- **feat(antigravity):** integrate Antigravity provider with dynamic `maxOutputTokens` calculation, identity fingerprinting overhaul, and Cloud Code envelope payload sanitization (#2055, #2063) - **feat(gemini-cli):** add custom projectId support for Gemini CLI transport (UI, DB, executor) (#1991) +- **feat(providers):** add KIE media provider support with dynamic polling, text models, and expanded video models catalog +- **feat(providers):** add Z.AI provider support with GLM quota handling and new quota labels +- **feat(providers):** add 9 new free AI providers — LLM7, Lepton, Kluster, UncloseAI, BazaarLink, Completions, Enally, FreeTheAi (#2096) +- **feat(providers):** batch delete provider connections via checkbox multi-select (#2094) +- **feat(cursor):** full OpenAI parity — tool calls, streaming, and session management (#2082) +- **feat(cli):** comprehensive CLI enhancement suite with 20+ new commands including `omniroute providers`, `omniroute combos`, `omniroute doctor` (#2074) +- **feat(cli):** add modular CLI setup and provider management commands (#2046) +- **feat(mcp):** add DeepSeek quota and limit monitoring feature (#2089) +- **feat(circuit-breaker):** classify 429 errors and apply per-kind cooldowns (#2116) +- **feat(multi):** manifest-aware tier routing — W1-W4 complete (#2014) +- **feat(combos):** add reset-aware routing strategy for quota-based providers +- **feat(combo):** add context_length input field to combo edit form (#2047) +- **feat(chat):** dynamic tool limit detection with proactive truncation (#2061) +- **feat(sse):** refresh Claude OAuth wire image to claude-cli/2.1.131 (#2011) +- **feat(github):** add `targetFormat: openai-responses` to all GitHub models (#2122) +- **feat(api):** allow configuration via API calls — open management routes to Bearer keys with manage scope (#2103) +- **feat(api):** update API bridge proxy timeout to 600,000ms (#2019) +- **feat(usage):** add service tier breakdown, codex fast service tier analytics, and account for fast tier +- **feat(chat):** add `STREAM_READINESS_TIMEOUT_MS` and integrate into chat handling +- **feat(combo):** add `fallbackDelayMs` to combo configuration and related settings +- **feat(chat):** enhance error handling for semaphore capacity with fallback logic +- **feat(qdrant):** embedding model discovery (#2086) +- **feat(auth):** per-session sticky routing for Codex (#1887) +- **feat(inworld):** enhance Inworld TTS support (#2123) ### 🐛 Bug Fixes +- **fix(pricing):** make `getPricingForModel` fully case-insensitive to ensure custom prices correctly reflect in new incoming requests cost calculations +- **fix(gemini):** prevent `functionDeclarations` from being dropped by the sanitizer when `googleSearch` tool is present (#2077) +- **fix(pollinations):** add `jsonMode: true` flag in the request transformation to enforce correct JSON structure from Pollinations API (#2109) +- **fix(docker):** update Dockerfile to copy `/docs` directory during build ensuring API catalog availability at runtime (#2083) +- **fix(docker):** include OpenAPI spec in runtime image (#2007) +- **fix(providers):** strip OpenAI-specific fields in Kiro translator to prevent 400 errors (#2037) +- **fix(kiro):** normalize tool-use payloads to prevent 400 errors from agents (#2104) +- **fix(kiro):** merge adjacent user history turns after role normalization (#2105) +- **fix(ui):** resolve text contrast issues for zero-config warning banner in light mode (#2050) +- **fix(core):** inject global system prompt correctly into downstream chat completions pipeline (#2080) +- **fix(core):** restore Claude Code adaptive thinking defaults and resolve audio transcription CORS regression +- **fix(routing):** add missing v1beta rewrites to next.config to resolve 404 on Gemini models endpoint (#2102) +- **fix(routing):** fix bare GPT-5.5 routing for Codex-only installations (#2054) +- **fix(routing):** add fuzzy auto-combo routing for `auto/*` model prefix (#2010) - **fix(cache):** optimize cache_control preservation logic and explicitly align tool schema with upstream Claude Code expectations - **fix(db):** preserve legacy SQLite database path on Windows to prevent data loss (#1973) +- **fix(db):** reduce hot-path persistence overhead (#2039) +- **fix(db):** resolve migration conflict by renumbering overlapping migration entries (#2041) - **fix(settings):** resolve model alias persistence double stringification preventing UI updates (#2018) - **fix(routing):** dynamically filter bare model auto-resolution by active provider connections to prevent dead-routing (#2029) - **fix(embeddings):** add Google Gemini embeddings compatibility via OpenAI-compatible endpoint mapping (#2006) +- **fix(sse):** prevent Claude OAuth multi-account correlation via metadata.user_id (#2053) +- **fix(sse):** prevent Claude Code identity cloak overrides and fix fallback resilience (#2053) +- **fix(sse):** classify hour quota errors as QUOTA_EXHAUSTED (#2119) +- **fix(sse):** fix CC-compatible streaming bridge (#2118) +- **fix(antigravity):** sanitize Claude Cloud Code payloads (#2090) +- **fix(antigravity):** add duplex half for streaming bodies +- **fix(antigravity):** align identity protocol and behavior with official AM +- **fix(chatgpt-web):** plumb proxy through to native tls-client (#2022, #2023) +- **fix(codex):** expose native model IDs in catalog (#2012) +- **fix(glm):** add dedicated coding transport (#2087) +- **fix(compression):** support Responses input and expand Spanish compression rules (#2028) +- **fix(catalog):** auto-calculate combo context_length from target model limits (#2030) +- **fix(api):** fix usage analytics and API key identity (#2008, #2092) +- **fix(api-key):** allow Unicode letters in API key name validation (#1996) +- **fix(auth):** allow bootstrap without password (#2048) +- **fix(proxy):** clean up proxy page redundancy and fix 1proxy sync empty body error (#2052) +- **fix(dashboard):** resolve Unknown plan display in Provider Limits +- **fix(usage):** add extensible CURRENCY_SYMBOLS mapping for deepseek currencies +- **fix(runtime):** harden timer handling and model pricing fallback +- **fix(i18n):** complete Simplified Chinese translations (#2115) +- **fix(mitm):** add Linux cert install and skip sudo password when root (#1999) +- **fix(mitm):** prevent stub from loading at runtime via bypass module - **fix:** remove Anthropic-Beta header from non-Anthropic providers to fix identity contamination (#1989) - **fix(cli):** resolve .env loading failure for global npm installations +- **fix(export):** exclude telemetry/usage-history tables from JSON config backups by default to prevent unbounded file growth (#2125) +- **fix:** Follow OpenAI specification, handle throttling in batch and fix UI (#2045) -### 🔒 Security +### Säkerhet +- **fix(security):** remediate CodeQL vulnerabilities (ReDoS, cryptographic bias, stack trace exposure, and weak password hashing) (#216, #215, #211, #208, #206, #210) - **fix(security):** remediate regex validation backtracking path in core compression cleanup (#1990) - **fix(core):** harden input handling and stabilization for prompt compression edge cases +### Dokumentation + +- **docs:** add competitive marketing tables and SEO/AEO optimizations to README (#2091) +- **docs:** refresh providers, model catalogs, and docs for v3.8.0 (#2088) +- **docs:** update Claude MD and update GLM-CN max context to 200k (#2027) +- **docs(env):** add `GITLAB_DUO_OAUTH_CLIENT_ID` to `.env.example` (#2031) + ### 🧹 Chores & Maintenance - **chore(providers):** prune redundant local provider icon assets in favor of `@lobehub/icons` web fonts (#1992) +- **chore(providers):** remove deprecated models (#2033) +- **deps:** bump `fast-uri` from 3.1.0 to 3.1.2 (#2078) +- **deps:** bump `hono` from 4.12.14 to 4.12.18 (#2079) - **ci:** skip SonarCloud scan on main pushes to optimize CI time - **test:** stabilize cooldown abort coverage case in integration testing +### 🏆 v3.8.0 Community Contributors + +Thank you to all **38 community contributors** who made v3.8.0 possible! 🎉 + +| Contributor | PRs | Contributions | +| :--------------------------------------------------------- | :-: | :------------------------------------------------------------ | +| [@oyi77](https://github.com/oyi77) | 7 | #2010, #2014, #2041, #2052, #2061, #2074, #2091, #2094, #2096 | +| [@backryun](https://github.com/backryun) | 4 | #1992, #2033, #2088, #2123 | +| [@dhaern](https://github.com/dhaern) | 4 | #2028, #2039, #2087, #2090 | +| [@Tentoxa](https://github.com/Tentoxa) | 2 | #2011, #2053 | +| [@wauputr4](https://github.com/wauputr4) | 2 | #2009, #2046 | +| [@payne0420](https://github.com/payne0420) | 1 | #2082 | +| [@Tr0sT](https://github.com/Tr0sT) | 1 | #2012 | +| [@AveryanAlex](https://github.com/AveryanAlex) | 1 | #2008 | +| [@nickwizard](https://github.com/nickwizard) | 1 | #1991 | +| [@rodrigogbbr-stack](https://github.com/rodrigogbbr-stack) | 1 | #1996 | +| [@NekoMonci12](https://github.com/NekoMonci12) | 1 | #1999 | +| [@congvc-dev](https://github.com/congvc-dev) | 1 | #2004 | +| [@tatsster](https://github.com/tatsster) | 1 | #2007 | +| [@xssdem](https://github.com/xssdem) | 1 | #2023 | +| [@bypanghu](https://github.com/bypanghu) | 1 | #2027 | +| [@herjarsa](https://github.com/herjarsa) | 1 | #2030 | +| [@wucm667](https://github.com/wucm667) | 1 | #2031 | +| [@hartmark](https://github.com/hartmark) | 1 | #2045 | +| [@ddarkr](https://github.com/ddarkr) | 1 | #2047 | +| [@tces1](https://github.com/tces1) | 1 | #2048 | +| [@guanbear](https://github.com/guanbear) | 1 | #2054 | +| [@Gi99lin](https://github.com/Gi99lin) | 1 | #2055 | +| [@ivan-mezentsev](https://github.com/ivan-mezentsev) | 1 | #2063 | +| [@JxnLexn](https://github.com/JxnLexn) | 1 | #2019 | +| [@yoviarpauzi](https://github.com/yoviarpauzi) | 1 | #2092 | +| [@rafacpti23](https://github.com/rafacpti23) | 1 | #2086 | +| [@gleber](https://github.com/gleber) | 1 | #2103 | +| [@rilham97](https://github.com/rilham97) | 1 | #2104 | +| [@Gioxaa](https://github.com/Gioxaa) | 1 | #2105 | +| [@boa-z](https://github.com/boa-z) | 1 | #2115 | +| [@eleata](https://github.com/eleata) | 1 | #2116 | +| [@rdself](https://github.com/rdself) | 1 | #2118 | +| [@clousky2020](https://github.com/clousky2020) | 1 | #2119 | +| [@abhinavjnu](https://github.com/abhinavjnu) | 1 | #2122 | +| [@HoaPham98](https://github.com/HoaPham98) | 1 | #2089 | +| [@05dunski](https://github.com/05dunski) | 1 | #1978 (cherry-picked) | + ## [3.7.9] — 2026-05-03 ### ✨ New Features @@ -102,7 +220,7 @@ - **chore(provider):** Add reka models list (#1956 — thanks @backryun) - **chore(model):** Update new models, Delete Deprecated models (#1949 — thanks @backryun) -### 📝 Documentation +### Dokumentation - **docs(compression):** document RTK+Caveman stacked savings ranges @@ -201,7 +319,7 @@ - **feat(db):** auto-restore probe-failed database on startup to prevent data loss after failed upgrades (#1810) - **feat(analytics):** add cost-based usage insights and activity streaks in the analytics dashboard -### 🔒 Security +### Säkerhet - **fix(security):** resolve ReDoS vulnerability in Codex executor regex patterns (#1797, #1789) @@ -354,7 +472,7 @@ We identified that **155 community PRs** across the entire project history (from - **feat(proxy):** implement bulk proxy import via pipe-delimited parser with update-or-create (upsert) logic and real-time preview table - **feat(pwa):** add fullscreen installable PWA with manifest, service worker, and cross-platform app icons (#1728) -### 🔒 Security +### Säkerhet - **security:** replace insecure `Math.random` with `crypto.getRandomValues` for fallback UUID generation to resolve CodeQL CWE-338 finding (#182) @@ -519,7 +637,7 @@ We identified that **155 community PRs** across the entire project history (from - **fix(transport):** Prevent memory bloat and database exhaustion from large, fragmented streaming responses. Implemented `ByteQueue` in `kiro.ts` for zero-copy binary accumulation, refactored `antigravity.ts` for incremental SSE parsing, and enforced a strict 512KB tiered truncation limit (`MAX_CALL_LOG_ARTIFACT_BYTES`) on stream request logs and call artifacts (#1647). - **chore(ci):** Update build environment dependencies — bump Node to `24.15.0`, `actions/checkout@v6`, `docker/build-push-action@v7`, pin `actions/setup-python` to major tag (#1646 — thanks @backryun). -### 📝 Documentation +### Dokumentation - **docs(env):** Add `OMNIROUTE_ALLOW_PRIVATE_PROVIDER_URLS` to `.env.example` with documentation for LM Studio and other local provider use cases (#1623). @@ -669,7 +787,7 @@ We identified that **155 community PRs** across the entire project history (from - **test(next):** Align transpile package expectations for the Next.js standalone build. - **test(ci):** Fix CI-only test failures from environment differences — clear `INITIAL_PASSWORD` and `JWT_SECRET` in integration tests, handle `XDG_CONFIG_HOME` for guide-settings tests. -### 📚 Documentation +### Dokumentation - **docs:** Update the root changelog with all release-branch changes through 2026-04-24, including PRs #1544, #1555, #1551, #1550, #1548, #1547, #1541, #1538, #1536, and #1527. - **docs:** Fix broken README and localized documentation links. (#1536) @@ -811,7 +929,7 @@ We identified that **155 community PRs** across the entire project history (from - **feat(providers):** Expand image provider registry with extended model support including SD3.5, FLUX, and DALL-E 3 HD configurations - **feat(combos):** Add new routing strategies and full i18n support for agent features section across 31 languages -### 🔒 Security +### Säkerhet - **security:** Resolve 18 GitHub CodeQL scan alerts including ReDoS, incomplete sanitization, and bad HTML filtering regexp patterns - **fix(auth):** Seal privilege escalation vector by enforcing JWT session checking exclusively on `/api/keys` management endpoints (#1353) @@ -1078,7 +1196,7 @@ We identified that **155 community PRs** across the entire project history (from - **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 - **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 -### 🔒 Security +### Säkerhet - **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 - **Auth Guard on Translator Save:** Added `isAuthenticated` guard to `/api/translator/save` for defense-in-depth consistency @@ -1483,7 +1601,7 @@ We identified that **155 community PRs** across the entire project history (from - **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). -### 📚 Documentation +### Dokumentation - **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. - **Context Relay Delivery Notes:** Documented the current architecture, runtime flow, and Codex-focused scope in the feature docs, changelog, and agent guidance. @@ -1559,7 +1677,7 @@ We identified that **155 community PRs** across the entire project history (from ## [3.5.3] - 2026-04-07 -### Security +### Säkerhet - **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. - **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. @@ -1575,7 +1693,7 @@ We identified that **155 community PRs** across the entire project history (from - **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. -### Documentation +### Dokumentation - **I18n Engine:** Synchronized and pushed deep Machine Translation updates across all 32 natively-supported languages (682 translation nodes aligned). @@ -1736,7 +1854,7 @@ We identified that **155 community PRs** across the entire project history (from ## [3.4.8] — 2026-04-03 -### Security +### Säkerhet - Fully remediated all outstanding Github Advanced Security (CodeQL) findings and Dependabot alerts. - Fixed insecure randomness vulnerabilities by migrating from `Math.random` to `crypto.randomUUID()`. @@ -1748,7 +1866,7 @@ We identified that **155 community PRs** across the entire project history (from ## [3.4.7] — 2026-04-03 -### Features +### Funktioner - Added `Cryptography` node to Monitoring and MCP health checks (#798) - Hardened model-catalog route permissions mapping (`/models`) (#781) @@ -1764,7 +1882,7 @@ We identified that **155 community PRs** across the entire project history (from - Fixed MCP standalone module-resolution (`ERR_MODULE_NOT_FOUND`) via `esbuild` (#936) - Fixed NVIDIA NIM routing credential resolution alias mismatch (#931) -### Security +### Säkerhet - Added safe strict input boundary protection against raw `shell: true` remote-code execution injections. @@ -2011,7 +2129,7 @@ We identified that **155 community PRs** across the entire project history (from ## [3.4.0] - 2026-03-31 -### 🚀 Features +### Funktioner - **Subscription Utilization Analytics:** Added quota snapshot time-series tracking, Provider Utilization and Combo Health tabs with recharts visualizations, and corresponding API endpoints (#847) - **SQLite Backup Control:** New `OMNIROUTE_DISABLE_AUTO_BACKUP` env flag to disable automatic SQLite backups (#846) @@ -2063,7 +2181,7 @@ We identified that **155 community PRs** across the entire project history (from ## [3.3.8] - 2026-03-30 -### 🚀 Features +### Funktioner - **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) - **Qoder Integration:** Native integration for Qoder AI natively replacing the legacy iFlow platform mappings (#660) @@ -2889,7 +3007,7 @@ We identified that **155 community PRs** across the entire project history (from - **NaN tokens in Claude Code / client responses (#617):** - `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 -### 🔒 Security +### Säkerhet - Updated `yaml` package to fix stack overflow vulnerability (GHSA-48c2-rrv3-qjmp) @@ -3565,7 +3683,7 @@ docker pull diegosouzapw/omniroute:3.0.0 - **SVG fallback**: `ProviderIcon` component updated with 4-tier strategy: Lobehub → PNG → SVG → Generic icon - **Agents fingerprinting**: Synced with CLI tools — added droid, openclaw, copilot, opencode to fingerprint list (14 total) -### 🔒 Security +### Säkerhet - **CVE fix**: Resolved dompurify XSS vulnerability (GHSA-v2wj-7wpq-c8vv) via npm overrides forcing `dompurify@^3.3.2` - `npm audit` now reports **0 vulnerabilities** @@ -3928,7 +4046,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **#510** — Windows: MSYS2/Git-Bash paths (`/c/Program Files/...`) are now normalized to `C:\Program Files\...` - **#492** — `omniroute` CLI now detects `mise`/`nvm` when `app/server.js` is missing and shows targeted fix -### 📖 Documentation +### Dokumentation - **#513** — Docker password reset: `INITIAL_PASSWORD` env var workaround documented - **#520** — pnpm: `pnpm approve-builds better-sqlite3` documented @@ -4025,7 +4143,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **feat(executors/cloudflare-ai)**: New `CloudflareAIExecutor` — dynamic URL construction requires `accountId` in provider credentials - **feat(executors)**: Register `pollinations`, `pol`, `cloudflare-ai`, `cf` executor mappings -### 📝 Documentation +### Dokumentation - **docs(readme)**: Expanded free combo stack to 11 providers ($0 forever) - **docs(readme)**: Added 4 new free provider sections (LongCat, Pollinations, Cloudflare AI, Scaleway) with model tables @@ -4177,7 +4295,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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). -### Features +### Funktioner - **"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. @@ -4205,7 +4323,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Merge PR #494 (MiniMax role fix), fix KIRO MITM dashboard, triage 8 issues. -### Features +### Funktioner - **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. - **roleNormalizer**: `normalizeDeveloperRole()` now accepts `preserveDeveloperRole` parameter with tri-state behavior (undefined=keep, true=keep, false=convert). @@ -4261,7 +4379,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Gemini CLI deprecation, VM guide i18n fix, dependabot security fix, provider schema expansion. -### Features +### Funktioner - **Gemini CLI Deprecation** (#462): Mark `gemini-cli` provider as deprecated with warning — Google restricts third-party OAuth usage from March 2026 - **Provider Schema** (#462): Expand Zod validation with `deprecated`, `deprecationReason`, `hasFree`, `freeNote`, `authHint`, `apiHint` optional fields @@ -4270,7 +4388,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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) -### Security +### Säkerhet - **deps**: Bump `flatted` 3.3.3 → 3.4.2 — fixes CWE-1321 prototype pollution (#484, @dependabot) @@ -4290,7 +4408,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Czech i18n, SSE protocol fix, VM guide translation. -### Features +### Funktioner - **Czech Language** (#482): Full Czech (cs) i18n — 22 docs, 2606 UI strings, language switcher updates (@zen0bit) - **VM Deployment Guide**: Translated from Portuguese to English as the source document (@zen0bit) @@ -4309,7 +4427,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: 2 merged PRs, model aliases routing fix, log export, and issue triage. -### Features +### Funktioner - **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) @@ -4329,7 +4447,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Five community PRs — streaming call log fixes, Kiro compatibility, cache token analytics, Chinese translation, and configurable tool call IDs. -### ✨ Features +### Funktioner - **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) - **feat(providers)**: Per-model configurable 9-char tool call ID normalization (Mistral-style) — only models with the option enabled get truncated IDs (#470) @@ -4359,7 +4477,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Bailian Coding Plan provider with editable base URLs, plus community contributions for Alibaba Cloud and Kimi Coding. -### ✨ Features +### Funktioner - **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) - **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) @@ -4374,7 +4492,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Two new community-contributed providers (Alibaba Cloud Coding, Kimi Coding API-key) and Docker pino fix. -### ✨ Features +### Funktioner - **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) - **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) @@ -4399,7 +4517,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Codex responses subpath passthrough natively supported, Windows MITM crash fixed, and Combos agent schemas adjusted. -### ✨ Features +### Funktioner - **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) @@ -4439,7 +4557,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **fix(budget)**: "Save Limits" no longer returns 422 — `warningThreshold` is now correctly sent as fraction (0–1) instead of percentage (0–100) (#451) - **fix(combos)**: `` internal cache tag is now stripped before forwarding requests to providers, preventing cache session breaks (#454) -### ✨ Features +### Funktioner - **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) @@ -4495,7 +4613,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Search Tools dashboard, i18n fixes, Copilot limits, Serper validation fix. -### 🚀 Features +### Funktioner - **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) - New route: `/dashboard/search-tools` @@ -4595,7 +4713,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - DB migration: `request_type` column on `call_logs` for non-chat request tracking - Zod validation (`v1SearchSchema`), auth-gated, cost recorded via `recordCost()` -### 🔒 Security +### Säkerhet - **deps**: Next.js 16.1.6 → 16.1.7 — fixes 6 CVEs: - **Critical**: CVE-2026-29057 (HTTP request smuggling via http-proxy) @@ -4725,7 +4843,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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**: New `request_detail_logs` table with 500-entry ring-buffer trigger, opt-in via settings toggle -### ✨ Features +### Funktioner - **feat(combo)**: System Message Override per Combo (#399 — `system_message` field replaces or injects system prompt before forwarding to provider) - **feat(combo)**: Tool Filter Regex per Combo (#399 — `tool_filter_regex` keeps only tools matching pattern; supports OpenAI + Anthropic formats) @@ -4740,7 +4858,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: SSE improvements, local provider_nodes extensions, proxy registry, Claude passthrough fixes. -### ✨ Features +### Funktioner - **feat(health)**: Background health check for local `provider_nodes` with exponential backoff (30s→300s) and `Promise.allSettled` to avoid blocking (#423, @Regis-RCR) - **feat(embeddings)**: Route `/v1/embeddings` to local `provider_nodes` — `buildDynamicEmbeddingProvider()` with hostname validation (#422, @Regis-RCR) @@ -4882,7 +5000,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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 - **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). -### ✨ Features +### Funktioner - **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) @@ -4912,7 +5030,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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) - **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) -### ✨ Features +### Funktioner - **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) - **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. @@ -4971,7 +5089,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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) - **fix(logs)**: Request log table is now readable in light mode — status badges, token counts, and combo tags use adaptive `dark:` color classes (#378) -### ✨ Features +### Funktioner - **feat(kiro)**: Kiro credit tracking added to usage fetcher — queries `getUserCredits` from AWS CodeWhisperer endpoint (#337) @@ -5372,7 +5490,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > **Major release** — Free Stack ecosystem, transcription playground overhaul, 44+ providers, comprehensive free tier documentation, and UI improvements across the board. -### ✨ Features +### Funktioner - **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. - **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. @@ -5383,7 +5501,7 @@ OmniRoute now automatically refreshes model lists for connected providers every ## [2.3.16] - 2026-03-13 -### 📖 Documentation +### Dokumentation - **README: 44+ Providers** — Updated all 3 occurrences of "36+ providers" to "44+" reflecting the actual codebase count (44 providers in providers.ts) - **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. @@ -5393,7 +5511,7 @@ OmniRoute now automatically refreshes model lists for connected providers every ## [2.3.15] - 2026-03-13 -### ✨ Features +### Funktioner - **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. - **i18n — autoCombo section**: Added 20 new translation keys for the Auto-Combo dashboard (`title`, `status`, `modePack`, `providerScores`, `factorTierPriority`, etc.) to all 30 language files. diff --git a/docs/i18n/sw/CHANGELOG.md b/docs/i18n/sw/CHANGELOG.md index 3e361ecdbc..e3c94ea81d 100644 --- a/docs/i18n/sw/CHANGELOG.md +++ b/docs/i18n/sw/CHANGELOG.md @@ -10,30 +10,148 @@ ### ✨ New Features -- **feat(antigravity):** integrate Antigravity provider with dynamic `maxOutputTokens` calculation (bumping to `thinkingBudget + 1`) and standard Cloud Code envelope payload sanitization (#2055, #2063) +- **feat(antigravity):** integrate Antigravity provider with dynamic `maxOutputTokens` calculation, identity fingerprinting overhaul, and Cloud Code envelope payload sanitization (#2055, #2063) - **feat(gemini-cli):** add custom projectId support for Gemini CLI transport (UI, DB, executor) (#1991) +- **feat(providers):** add KIE media provider support with dynamic polling, text models, and expanded video models catalog +- **feat(providers):** add Z.AI provider support with GLM quota handling and new quota labels +- **feat(providers):** add 9 new free AI providers — LLM7, Lepton, Kluster, UncloseAI, BazaarLink, Completions, Enally, FreeTheAi (#2096) +- **feat(providers):** batch delete provider connections via checkbox multi-select (#2094) +- **feat(cursor):** full OpenAI parity — tool calls, streaming, and session management (#2082) +- **feat(cli):** comprehensive CLI enhancement suite with 20+ new commands including `omniroute providers`, `omniroute combos`, `omniroute doctor` (#2074) +- **feat(cli):** add modular CLI setup and provider management commands (#2046) +- **feat(mcp):** add DeepSeek quota and limit monitoring feature (#2089) +- **feat(circuit-breaker):** classify 429 errors and apply per-kind cooldowns (#2116) +- **feat(multi):** manifest-aware tier routing — W1-W4 complete (#2014) +- **feat(combos):** add reset-aware routing strategy for quota-based providers +- **feat(combo):** add context_length input field to combo edit form (#2047) +- **feat(chat):** dynamic tool limit detection with proactive truncation (#2061) +- **feat(sse):** refresh Claude OAuth wire image to claude-cli/2.1.131 (#2011) +- **feat(github):** add `targetFormat: openai-responses` to all GitHub models (#2122) +- **feat(api):** allow configuration via API calls — open management routes to Bearer keys with manage scope (#2103) +- **feat(api):** update API bridge proxy timeout to 600,000ms (#2019) +- **feat(usage):** add service tier breakdown, codex fast service tier analytics, and account for fast tier +- **feat(chat):** add `STREAM_READINESS_TIMEOUT_MS` and integrate into chat handling +- **feat(combo):** add `fallbackDelayMs` to combo configuration and related settings +- **feat(chat):** enhance error handling for semaphore capacity with fallback logic +- **feat(qdrant):** embedding model discovery (#2086) +- **feat(auth):** per-session sticky routing for Codex (#1887) +- **feat(inworld):** enhance Inworld TTS support (#2123) ### 🐛 Bug Fixes +- **fix(pricing):** make `getPricingForModel` fully case-insensitive to ensure custom prices correctly reflect in new incoming requests cost calculations +- **fix(gemini):** prevent `functionDeclarations` from being dropped by the sanitizer when `googleSearch` tool is present (#2077) +- **fix(pollinations):** add `jsonMode: true` flag in the request transformation to enforce correct JSON structure from Pollinations API (#2109) +- **fix(docker):** update Dockerfile to copy `/docs` directory during build ensuring API catalog availability at runtime (#2083) +- **fix(docker):** include OpenAPI spec in runtime image (#2007) +- **fix(providers):** strip OpenAI-specific fields in Kiro translator to prevent 400 errors (#2037) +- **fix(kiro):** normalize tool-use payloads to prevent 400 errors from agents (#2104) +- **fix(kiro):** merge adjacent user history turns after role normalization (#2105) +- **fix(ui):** resolve text contrast issues for zero-config warning banner in light mode (#2050) +- **fix(core):** inject global system prompt correctly into downstream chat completions pipeline (#2080) +- **fix(core):** restore Claude Code adaptive thinking defaults and resolve audio transcription CORS regression +- **fix(routing):** add missing v1beta rewrites to next.config to resolve 404 on Gemini models endpoint (#2102) +- **fix(routing):** fix bare GPT-5.5 routing for Codex-only installations (#2054) +- **fix(routing):** add fuzzy auto-combo routing for `auto/*` model prefix (#2010) - **fix(cache):** optimize cache_control preservation logic and explicitly align tool schema with upstream Claude Code expectations - **fix(db):** preserve legacy SQLite database path on Windows to prevent data loss (#1973) +- **fix(db):** reduce hot-path persistence overhead (#2039) +- **fix(db):** resolve migration conflict by renumbering overlapping migration entries (#2041) - **fix(settings):** resolve model alias persistence double stringification preventing UI updates (#2018) - **fix(routing):** dynamically filter bare model auto-resolution by active provider connections to prevent dead-routing (#2029) - **fix(embeddings):** add Google Gemini embeddings compatibility via OpenAI-compatible endpoint mapping (#2006) +- **fix(sse):** prevent Claude OAuth multi-account correlation via metadata.user_id (#2053) +- **fix(sse):** prevent Claude Code identity cloak overrides and fix fallback resilience (#2053) +- **fix(sse):** classify hour quota errors as QUOTA_EXHAUSTED (#2119) +- **fix(sse):** fix CC-compatible streaming bridge (#2118) +- **fix(antigravity):** sanitize Claude Cloud Code payloads (#2090) +- **fix(antigravity):** add duplex half for streaming bodies +- **fix(antigravity):** align identity protocol and behavior with official AM +- **fix(chatgpt-web):** plumb proxy through to native tls-client (#2022, #2023) +- **fix(codex):** expose native model IDs in catalog (#2012) +- **fix(glm):** add dedicated coding transport (#2087) +- **fix(compression):** support Responses input and expand Spanish compression rules (#2028) +- **fix(catalog):** auto-calculate combo context_length from target model limits (#2030) +- **fix(api):** fix usage analytics and API key identity (#2008, #2092) +- **fix(api-key):** allow Unicode letters in API key name validation (#1996) +- **fix(auth):** allow bootstrap without password (#2048) +- **fix(proxy):** clean up proxy page redundancy and fix 1proxy sync empty body error (#2052) +- **fix(dashboard):** resolve Unknown plan display in Provider Limits +- **fix(usage):** add extensible CURRENCY_SYMBOLS mapping for deepseek currencies +- **fix(runtime):** harden timer handling and model pricing fallback +- **fix(i18n):** complete Simplified Chinese translations (#2115) +- **fix(mitm):** add Linux cert install and skip sudo password when root (#1999) +- **fix(mitm):** prevent stub from loading at runtime via bypass module - **fix:** remove Anthropic-Beta header from non-Anthropic providers to fix identity contamination (#1989) - **fix(cli):** resolve .env loading failure for global npm installations +- **fix(export):** exclude telemetry/usage-history tables from JSON config backups by default to prevent unbounded file growth (#2125) +- **fix:** Follow OpenAI specification, handle throttling in batch and fix UI (#2045) -### 🔒 Security +### Seguridad +- **fix(security):** remediate CodeQL vulnerabilities (ReDoS, cryptographic bias, stack trace exposure, and weak password hashing) (#216, #215, #211, #208, #206, #210) - **fix(security):** remediate regex validation backtracking path in core compression cleanup (#1990) - **fix(core):** harden input handling and stabilization for prompt compression edge cases +### Documentación + +- **docs:** add competitive marketing tables and SEO/AEO optimizations to README (#2091) +- **docs:** refresh providers, model catalogs, and docs for v3.8.0 (#2088) +- **docs:** update Claude MD and update GLM-CN max context to 200k (#2027) +- **docs(env):** add `GITLAB_DUO_OAUTH_CLIENT_ID` to `.env.example` (#2031) + ### 🧹 Chores & Maintenance - **chore(providers):** prune redundant local provider icon assets in favor of `@lobehub/icons` web fonts (#1992) +- **chore(providers):** remove deprecated models (#2033) +- **deps:** bump `fast-uri` from 3.1.0 to 3.1.2 (#2078) +- **deps:** bump `hono` from 4.12.14 to 4.12.18 (#2079) - **ci:** skip SonarCloud scan on main pushes to optimize CI time - **test:** stabilize cooldown abort coverage case in integration testing +### 🏆 v3.8.0 Community Contributors + +Thank you to all **38 community contributors** who made v3.8.0 possible! 🎉 + +| Contributor | PRs | Contributions | +| :--------------------------------------------------------- | :-: | :------------------------------------------------------------ | +| [@oyi77](https://github.com/oyi77) | 7 | #2010, #2014, #2041, #2052, #2061, #2074, #2091, #2094, #2096 | +| [@backryun](https://github.com/backryun) | 4 | #1992, #2033, #2088, #2123 | +| [@dhaern](https://github.com/dhaern) | 4 | #2028, #2039, #2087, #2090 | +| [@Tentoxa](https://github.com/Tentoxa) | 2 | #2011, #2053 | +| [@wauputr4](https://github.com/wauputr4) | 2 | #2009, #2046 | +| [@payne0420](https://github.com/payne0420) | 1 | #2082 | +| [@Tr0sT](https://github.com/Tr0sT) | 1 | #2012 | +| [@AveryanAlex](https://github.com/AveryanAlex) | 1 | #2008 | +| [@nickwizard](https://github.com/nickwizard) | 1 | #1991 | +| [@rodrigogbbr-stack](https://github.com/rodrigogbbr-stack) | 1 | #1996 | +| [@NekoMonci12](https://github.com/NekoMonci12) | 1 | #1999 | +| [@congvc-dev](https://github.com/congvc-dev) | 1 | #2004 | +| [@tatsster](https://github.com/tatsster) | 1 | #2007 | +| [@xssdem](https://github.com/xssdem) | 1 | #2023 | +| [@bypanghu](https://github.com/bypanghu) | 1 | #2027 | +| [@herjarsa](https://github.com/herjarsa) | 1 | #2030 | +| [@wucm667](https://github.com/wucm667) | 1 | #2031 | +| [@hartmark](https://github.com/hartmark) | 1 | #2045 | +| [@ddarkr](https://github.com/ddarkr) | 1 | #2047 | +| [@tces1](https://github.com/tces1) | 1 | #2048 | +| [@guanbear](https://github.com/guanbear) | 1 | #2054 | +| [@Gi99lin](https://github.com/Gi99lin) | 1 | #2055 | +| [@ivan-mezentsev](https://github.com/ivan-mezentsev) | 1 | #2063 | +| [@JxnLexn](https://github.com/JxnLexn) | 1 | #2019 | +| [@yoviarpauzi](https://github.com/yoviarpauzi) | 1 | #2092 | +| [@rafacpti23](https://github.com/rafacpti23) | 1 | #2086 | +| [@gleber](https://github.com/gleber) | 1 | #2103 | +| [@rilham97](https://github.com/rilham97) | 1 | #2104 | +| [@Gioxaa](https://github.com/Gioxaa) | 1 | #2105 | +| [@boa-z](https://github.com/boa-z) | 1 | #2115 | +| [@eleata](https://github.com/eleata) | 1 | #2116 | +| [@rdself](https://github.com/rdself) | 1 | #2118 | +| [@clousky2020](https://github.com/clousky2020) | 1 | #2119 | +| [@abhinavjnu](https://github.com/abhinavjnu) | 1 | #2122 | +| [@HoaPham98](https://github.com/HoaPham98) | 1 | #2089 | +| [@05dunski](https://github.com/05dunski) | 1 | #1978 (cherry-picked) | + ## [3.7.9] — 2026-05-03 ### ✨ New Features @@ -102,7 +220,7 @@ - **chore(provider):** Add reka models list (#1956 — thanks @backryun) - **chore(model):** Update new models, Delete Deprecated models (#1949 — thanks @backryun) -### 📝 Documentation +### Documentación - **docs(compression):** document RTK+Caveman stacked savings ranges @@ -201,7 +319,7 @@ - **feat(db):** auto-restore probe-failed database on startup to prevent data loss after failed upgrades (#1810) - **feat(analytics):** add cost-based usage insights and activity streaks in the analytics dashboard -### 🔒 Security +### Seguridad - **fix(security):** resolve ReDoS vulnerability in Codex executor regex patterns (#1797, #1789) @@ -354,7 +472,7 @@ We identified that **155 community PRs** across the entire project history (from - **feat(proxy):** implement bulk proxy import via pipe-delimited parser with update-or-create (upsert) logic and real-time preview table - **feat(pwa):** add fullscreen installable PWA with manifest, service worker, and cross-platform app icons (#1728) -### 🔒 Security +### Seguridad - **security:** replace insecure `Math.random` with `crypto.getRandomValues` for fallback UUID generation to resolve CodeQL CWE-338 finding (#182) @@ -519,7 +637,7 @@ We identified that **155 community PRs** across the entire project history (from - **fix(transport):** Prevent memory bloat and database exhaustion from large, fragmented streaming responses. Implemented `ByteQueue` in `kiro.ts` for zero-copy binary accumulation, refactored `antigravity.ts` for incremental SSE parsing, and enforced a strict 512KB tiered truncation limit (`MAX_CALL_LOG_ARTIFACT_BYTES`) on stream request logs and call artifacts (#1647). - **chore(ci):** Update build environment dependencies — bump Node to `24.15.0`, `actions/checkout@v6`, `docker/build-push-action@v7`, pin `actions/setup-python` to major tag (#1646 — thanks @backryun). -### 📝 Documentation +### Documentación - **docs(env):** Add `OMNIROUTE_ALLOW_PRIVATE_PROVIDER_URLS` to `.env.example` with documentation for LM Studio and other local provider use cases (#1623). @@ -669,7 +787,7 @@ We identified that **155 community PRs** across the entire project history (from - **test(next):** Align transpile package expectations for the Next.js standalone build. - **test(ci):** Fix CI-only test failures from environment differences — clear `INITIAL_PASSWORD` and `JWT_SECRET` in integration tests, handle `XDG_CONFIG_HOME` for guide-settings tests. -### 📚 Documentation +### Documentación - **docs:** Update the root changelog with all release-branch changes through 2026-04-24, including PRs #1544, #1555, #1551, #1550, #1548, #1547, #1541, #1538, #1536, and #1527. - **docs:** Fix broken README and localized documentation links. (#1536) @@ -811,7 +929,7 @@ We identified that **155 community PRs** across the entire project history (from - **feat(providers):** Expand image provider registry with extended model support including SD3.5, FLUX, and DALL-E 3 HD configurations - **feat(combos):** Add new routing strategies and full i18n support for agent features section across 31 languages -### 🔒 Security +### Seguridad - **security:** Resolve 18 GitHub CodeQL scan alerts including ReDoS, incomplete sanitization, and bad HTML filtering regexp patterns - **fix(auth):** Seal privilege escalation vector by enforcing JWT session checking exclusively on `/api/keys` management endpoints (#1353) @@ -1078,7 +1196,7 @@ We identified that **155 community PRs** across the entire project history (from - **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 - **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 -### 🔒 Security +### Seguridad - **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 - **Auth Guard on Translator Save:** Added `isAuthenticated` guard to `/api/translator/save` for defense-in-depth consistency @@ -1483,7 +1601,7 @@ We identified that **155 community PRs** across the entire project history (from - **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). -### 📚 Documentation +### Documentació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. - **Context Relay Delivery Notes:** Documented the current architecture, runtime flow, and Codex-focused scope in the feature docs, changelog, and agent guidance. @@ -1559,7 +1677,7 @@ We identified that **155 community PRs** across the entire project history (from ## [3.5.3] - 2026-04-07 -### Security +### Seguridad - **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. - **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. @@ -1575,7 +1693,7 @@ We identified that **155 community PRs** across the entire project history (from - **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. -### Documentation +### Documentación - **I18n Engine:** Synchronized and pushed deep Machine Translation updates across all 32 natively-supported languages (682 translation nodes aligned). @@ -1736,7 +1854,7 @@ We identified that **155 community PRs** across the entire project history (from ## [3.4.8] — 2026-04-03 -### Security +### Seguridad - Fully remediated all outstanding Github Advanced Security (CodeQL) findings and Dependabot alerts. - Fixed insecure randomness vulnerabilities by migrating from `Math.random` to `crypto.randomUUID()`. @@ -1748,7 +1866,7 @@ We identified that **155 community PRs** across the entire project history (from ## [3.4.7] — 2026-04-03 -### Features +### Funcionalidades - Added `Cryptography` node to Monitoring and MCP health checks (#798) - Hardened model-catalog route permissions mapping (`/models`) (#781) @@ -1764,7 +1882,7 @@ We identified that **155 community PRs** across the entire project history (from - Fixed MCP standalone module-resolution (`ERR_MODULE_NOT_FOUND`) via `esbuild` (#936) - Fixed NVIDIA NIM routing credential resolution alias mismatch (#931) -### Security +### Seguridad - Added safe strict input boundary protection against raw `shell: true` remote-code execution injections. @@ -2011,7 +2129,7 @@ We identified that **155 community PRs** across the entire project history (from ## [3.4.0] - 2026-03-31 -### 🚀 Features +### Funcionalidades - **Subscription Utilization Analytics:** Added quota snapshot time-series tracking, Provider Utilization and Combo Health tabs with recharts visualizations, and corresponding API endpoints (#847) - **SQLite Backup Control:** New `OMNIROUTE_DISABLE_AUTO_BACKUP` env flag to disable automatic SQLite backups (#846) @@ -2063,7 +2181,7 @@ We identified that **155 community PRs** across the entire project history (from ## [3.3.8] - 2026-03-30 -### 🚀 Features +### Funcionalidades - **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) - **Qoder Integration:** Native integration for Qoder AI natively replacing the legacy iFlow platform mappings (#660) @@ -2889,7 +3007,7 @@ We identified that **155 community PRs** across the entire project history (from - **NaN tokens in Claude Code / client responses (#617):** - `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 -### 🔒 Security +### Seguridad - Updated `yaml` package to fix stack overflow vulnerability (GHSA-48c2-rrv3-qjmp) @@ -3565,7 +3683,7 @@ docker pull diegosouzapw/omniroute:3.0.0 - **SVG fallback**: `ProviderIcon` component updated with 4-tier strategy: Lobehub → PNG → SVG → Generic icon - **Agents fingerprinting**: Synced with CLI tools — added droid, openclaw, copilot, opencode to fingerprint list (14 total) -### 🔒 Security +### Seguridad - **CVE fix**: Resolved dompurify XSS vulnerability (GHSA-v2wj-7wpq-c8vv) via npm overrides forcing `dompurify@^3.3.2` - `npm audit` now reports **0 vulnerabilities** @@ -3928,7 +4046,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **#510** — Windows: MSYS2/Git-Bash paths (`/c/Program Files/...`) are now normalized to `C:\Program Files\...` - **#492** — `omniroute` CLI now detects `mise`/`nvm` when `app/server.js` is missing and shows targeted fix -### 📖 Documentation +### Documentación - **#513** — Docker password reset: `INITIAL_PASSWORD` env var workaround documented - **#520** — pnpm: `pnpm approve-builds better-sqlite3` documented @@ -4025,7 +4143,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **feat(executors/cloudflare-ai)**: New `CloudflareAIExecutor` — dynamic URL construction requires `accountId` in provider credentials - **feat(executors)**: Register `pollinations`, `pol`, `cloudflare-ai`, `cf` executor mappings -### 📝 Documentation +### Documentación - **docs(readme)**: Expanded free combo stack to 11 providers ($0 forever) - **docs(readme)**: Added 4 new free provider sections (LongCat, Pollinations, Cloudflare AI, Scaleway) with model tables @@ -4177,7 +4295,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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). -### Features +### Funcionalidades - **"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. @@ -4205,7 +4323,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Merge PR #494 (MiniMax role fix), fix KIRO MITM dashboard, triage 8 issues. -### Features +### Funcionalidades - **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. - **roleNormalizer**: `normalizeDeveloperRole()` now accepts `preserveDeveloperRole` parameter with tri-state behavior (undefined=keep, true=keep, false=convert). @@ -4261,7 +4379,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Gemini CLI deprecation, VM guide i18n fix, dependabot security fix, provider schema expansion. -### Features +### Funcionalidades - **Gemini CLI Deprecation** (#462): Mark `gemini-cli` provider as deprecated with warning — Google restricts third-party OAuth usage from March 2026 - **Provider Schema** (#462): Expand Zod validation with `deprecated`, `deprecationReason`, `hasFree`, `freeNote`, `authHint`, `apiHint` optional fields @@ -4270,7 +4388,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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) -### Security +### Seguridad - **deps**: Bump `flatted` 3.3.3 → 3.4.2 — fixes CWE-1321 prototype pollution (#484, @dependabot) @@ -4290,7 +4408,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Czech i18n, SSE protocol fix, VM guide translation. -### Features +### Funcionalidades - **Czech Language** (#482): Full Czech (cs) i18n — 22 docs, 2606 UI strings, language switcher updates (@zen0bit) - **VM Deployment Guide**: Translated from Portuguese to English as the source document (@zen0bit) @@ -4309,7 +4427,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: 2 merged PRs, model aliases routing fix, log export, and issue triage. -### Features +### Funcionalidades - **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) @@ -4329,7 +4447,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Five community PRs — streaming call log fixes, Kiro compatibility, cache token analytics, Chinese translation, and configurable tool call IDs. -### ✨ Features +### Funcionalidades - **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) - **feat(providers)**: Per-model configurable 9-char tool call ID normalization (Mistral-style) — only models with the option enabled get truncated IDs (#470) @@ -4359,7 +4477,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Bailian Coding Plan provider with editable base URLs, plus community contributions for Alibaba Cloud and Kimi Coding. -### ✨ Features +### Funcionalidades - **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) - **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) @@ -4374,7 +4492,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Two new community-contributed providers (Alibaba Cloud Coding, Kimi Coding API-key) and Docker pino fix. -### ✨ Features +### Funcionalidades - **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) - **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) @@ -4399,7 +4517,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Codex responses subpath passthrough natively supported, Windows MITM crash fixed, and Combos agent schemas adjusted. -### ✨ Features +### Funcionalidades - **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) @@ -4439,7 +4557,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **fix(budget)**: "Save Limits" no longer returns 422 — `warningThreshold` is now correctly sent as fraction (0–1) instead of percentage (0–100) (#451) - **fix(combos)**: `` internal cache tag is now stripped before forwarding requests to providers, preventing cache session breaks (#454) -### ✨ Features +### Funcionalidades - **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) @@ -4495,7 +4613,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Search Tools dashboard, i18n fixes, Copilot limits, Serper validation fix. -### 🚀 Features +### Funcionalidades - **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) - New route: `/dashboard/search-tools` @@ -4595,7 +4713,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - DB migration: `request_type` column on `call_logs` for non-chat request tracking - Zod validation (`v1SearchSchema`), auth-gated, cost recorded via `recordCost()` -### 🔒 Security +### Seguridad - **deps**: Next.js 16.1.6 → 16.1.7 — fixes 6 CVEs: - **Critical**: CVE-2026-29057 (HTTP request smuggling via http-proxy) @@ -4725,7 +4843,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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**: New `request_detail_logs` table with 500-entry ring-buffer trigger, opt-in via settings toggle -### ✨ Features +### Funcionalidades - **feat(combo)**: System Message Override per Combo (#399 — `system_message` field replaces or injects system prompt before forwarding to provider) - **feat(combo)**: Tool Filter Regex per Combo (#399 — `tool_filter_regex` keeps only tools matching pattern; supports OpenAI + Anthropic formats) @@ -4740,7 +4858,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: SSE improvements, local provider_nodes extensions, proxy registry, Claude passthrough fixes. -### ✨ Features +### Funcionalidades - **feat(health)**: Background health check for local `provider_nodes` with exponential backoff (30s→300s) and `Promise.allSettled` to avoid blocking (#423, @Regis-RCR) - **feat(embeddings)**: Route `/v1/embeddings` to local `provider_nodes` — `buildDynamicEmbeddingProvider()` with hostname validation (#422, @Regis-RCR) @@ -4882,7 +5000,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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 - **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). -### ✨ Features +### Funcionalidades - **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) @@ -4912,7 +5030,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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) - **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) -### ✨ Features +### Funcionalidades - **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) - **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. @@ -4971,7 +5089,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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) - **fix(logs)**: Request log table is now readable in light mode — status badges, token counts, and combo tags use adaptive `dark:` color classes (#378) -### ✨ Features +### Funcionalidades - **feat(kiro)**: Kiro credit tracking added to usage fetcher — queries `getUserCredits` from AWS CodeWhisperer endpoint (#337) @@ -5372,7 +5490,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > **Major release** — Free Stack ecosystem, transcription playground overhaul, 44+ providers, comprehensive free tier documentation, and UI improvements across the board. -### ✨ Features +### Funcionalidades - **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. - **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. @@ -5383,7 +5501,7 @@ OmniRoute now automatically refreshes model lists for connected providers every ## [2.3.16] - 2026-03-13 -### 📖 Documentation +### Documentación - **README: 44+ Providers** — Updated all 3 occurrences of "36+ providers" to "44+" reflecting the actual codebase count (44 providers in providers.ts) - **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. @@ -5393,7 +5511,7 @@ OmniRoute now automatically refreshes model lists for connected providers every ## [2.3.15] - 2026-03-13 -### ✨ Features +### Funcionalidades - **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. - **i18n — autoCombo section**: Added 20 new translation keys for the Auto-Combo dashboard (`title`, `status`, `modePack`, `providerScores`, `factorTierPriority`, etc.) to all 30 language files. diff --git a/docs/i18n/ta/CHANGELOG.md b/docs/i18n/ta/CHANGELOG.md index 299368152d..51ced7a4b1 100644 --- a/docs/i18n/ta/CHANGELOG.md +++ b/docs/i18n/ta/CHANGELOG.md @@ -10,30 +10,148 @@ ### ✨ New Features -- **feat(antigravity):** integrate Antigravity provider with dynamic `maxOutputTokens` calculation (bumping to `thinkingBudget + 1`) and standard Cloud Code envelope payload sanitization (#2055, #2063) +- **feat(antigravity):** integrate Antigravity provider with dynamic `maxOutputTokens` calculation, identity fingerprinting overhaul, and Cloud Code envelope payload sanitization (#2055, #2063) - **feat(gemini-cli):** add custom projectId support for Gemini CLI transport (UI, DB, executor) (#1991) +- **feat(providers):** add KIE media provider support with dynamic polling, text models, and expanded video models catalog +- **feat(providers):** add Z.AI provider support with GLM quota handling and new quota labels +- **feat(providers):** add 9 new free AI providers — LLM7, Lepton, Kluster, UncloseAI, BazaarLink, Completions, Enally, FreeTheAi (#2096) +- **feat(providers):** batch delete provider connections via checkbox multi-select (#2094) +- **feat(cursor):** full OpenAI parity — tool calls, streaming, and session management (#2082) +- **feat(cli):** comprehensive CLI enhancement suite with 20+ new commands including `omniroute providers`, `omniroute combos`, `omniroute doctor` (#2074) +- **feat(cli):** add modular CLI setup and provider management commands (#2046) +- **feat(mcp):** add DeepSeek quota and limit monitoring feature (#2089) +- **feat(circuit-breaker):** classify 429 errors and apply per-kind cooldowns (#2116) +- **feat(multi):** manifest-aware tier routing — W1-W4 complete (#2014) +- **feat(combos):** add reset-aware routing strategy for quota-based providers +- **feat(combo):** add context_length input field to combo edit form (#2047) +- **feat(chat):** dynamic tool limit detection with proactive truncation (#2061) +- **feat(sse):** refresh Claude OAuth wire image to claude-cli/2.1.131 (#2011) +- **feat(github):** add `targetFormat: openai-responses` to all GitHub models (#2122) +- **feat(api):** allow configuration via API calls — open management routes to Bearer keys with manage scope (#2103) +- **feat(api):** update API bridge proxy timeout to 600,000ms (#2019) +- **feat(usage):** add service tier breakdown, codex fast service tier analytics, and account for fast tier +- **feat(chat):** add `STREAM_READINESS_TIMEOUT_MS` and integrate into chat handling +- **feat(combo):** add `fallbackDelayMs` to combo configuration and related settings +- **feat(chat):** enhance error handling for semaphore capacity with fallback logic +- **feat(qdrant):** embedding model discovery (#2086) +- **feat(auth):** per-session sticky routing for Codex (#1887) +- **feat(inworld):** enhance Inworld TTS support (#2123) ### 🐛 Bug Fixes +- **fix(pricing):** make `getPricingForModel` fully case-insensitive to ensure custom prices correctly reflect in new incoming requests cost calculations +- **fix(gemini):** prevent `functionDeclarations` from being dropped by the sanitizer when `googleSearch` tool is present (#2077) +- **fix(pollinations):** add `jsonMode: true` flag in the request transformation to enforce correct JSON structure from Pollinations API (#2109) +- **fix(docker):** update Dockerfile to copy `/docs` directory during build ensuring API catalog availability at runtime (#2083) +- **fix(docker):** include OpenAPI spec in runtime image (#2007) +- **fix(providers):** strip OpenAI-specific fields in Kiro translator to prevent 400 errors (#2037) +- **fix(kiro):** normalize tool-use payloads to prevent 400 errors from agents (#2104) +- **fix(kiro):** merge adjacent user history turns after role normalization (#2105) +- **fix(ui):** resolve text contrast issues for zero-config warning banner in light mode (#2050) +- **fix(core):** inject global system prompt correctly into downstream chat completions pipeline (#2080) +- **fix(core):** restore Claude Code adaptive thinking defaults and resolve audio transcription CORS regression +- **fix(routing):** add missing v1beta rewrites to next.config to resolve 404 on Gemini models endpoint (#2102) +- **fix(routing):** fix bare GPT-5.5 routing for Codex-only installations (#2054) +- **fix(routing):** add fuzzy auto-combo routing for `auto/*` model prefix (#2010) - **fix(cache):** optimize cache_control preservation logic and explicitly align tool schema with upstream Claude Code expectations - **fix(db):** preserve legacy SQLite database path on Windows to prevent data loss (#1973) +- **fix(db):** reduce hot-path persistence overhead (#2039) +- **fix(db):** resolve migration conflict by renumbering overlapping migration entries (#2041) - **fix(settings):** resolve model alias persistence double stringification preventing UI updates (#2018) - **fix(routing):** dynamically filter bare model auto-resolution by active provider connections to prevent dead-routing (#2029) - **fix(embeddings):** add Google Gemini embeddings compatibility via OpenAI-compatible endpoint mapping (#2006) +- **fix(sse):** prevent Claude OAuth multi-account correlation via metadata.user_id (#2053) +- **fix(sse):** prevent Claude Code identity cloak overrides and fix fallback resilience (#2053) +- **fix(sse):** classify hour quota errors as QUOTA_EXHAUSTED (#2119) +- **fix(sse):** fix CC-compatible streaming bridge (#2118) +- **fix(antigravity):** sanitize Claude Cloud Code payloads (#2090) +- **fix(antigravity):** add duplex half for streaming bodies +- **fix(antigravity):** align identity protocol and behavior with official AM +- **fix(chatgpt-web):** plumb proxy through to native tls-client (#2022, #2023) +- **fix(codex):** expose native model IDs in catalog (#2012) +- **fix(glm):** add dedicated coding transport (#2087) +- **fix(compression):** support Responses input and expand Spanish compression rules (#2028) +- **fix(catalog):** auto-calculate combo context_length from target model limits (#2030) +- **fix(api):** fix usage analytics and API key identity (#2008, #2092) +- **fix(api-key):** allow Unicode letters in API key name validation (#1996) +- **fix(auth):** allow bootstrap without password (#2048) +- **fix(proxy):** clean up proxy page redundancy and fix 1proxy sync empty body error (#2052) +- **fix(dashboard):** resolve Unknown plan display in Provider Limits +- **fix(usage):** add extensible CURRENCY_SYMBOLS mapping for deepseek currencies +- **fix(runtime):** harden timer handling and model pricing fallback +- **fix(i18n):** complete Simplified Chinese translations (#2115) +- **fix(mitm):** add Linux cert install and skip sudo password when root (#1999) +- **fix(mitm):** prevent stub from loading at runtime via bypass module - **fix:** remove Anthropic-Beta header from non-Anthropic providers to fix identity contamination (#1989) - **fix(cli):** resolve .env loading failure for global npm installations +- **fix(export):** exclude telemetry/usage-history tables from JSON config backups by default to prevent unbounded file growth (#2125) +- **fix:** Follow OpenAI specification, handle throttling in batch and fix UI (#2045) -### 🔒 Security +### Seguridad +- **fix(security):** remediate CodeQL vulnerabilities (ReDoS, cryptographic bias, stack trace exposure, and weak password hashing) (#216, #215, #211, #208, #206, #210) - **fix(security):** remediate regex validation backtracking path in core compression cleanup (#1990) - **fix(core):** harden input handling and stabilization for prompt compression edge cases +### Documentación + +- **docs:** add competitive marketing tables and SEO/AEO optimizations to README (#2091) +- **docs:** refresh providers, model catalogs, and docs for v3.8.0 (#2088) +- **docs:** update Claude MD and update GLM-CN max context to 200k (#2027) +- **docs(env):** add `GITLAB_DUO_OAUTH_CLIENT_ID` to `.env.example` (#2031) + ### 🧹 Chores & Maintenance - **chore(providers):** prune redundant local provider icon assets in favor of `@lobehub/icons` web fonts (#1992) +- **chore(providers):** remove deprecated models (#2033) +- **deps:** bump `fast-uri` from 3.1.0 to 3.1.2 (#2078) +- **deps:** bump `hono` from 4.12.14 to 4.12.18 (#2079) - **ci:** skip SonarCloud scan on main pushes to optimize CI time - **test:** stabilize cooldown abort coverage case in integration testing +### 🏆 v3.8.0 Community Contributors + +Thank you to all **38 community contributors** who made v3.8.0 possible! 🎉 + +| Contributor | PRs | Contributions | +| :--------------------------------------------------------- | :-: | :------------------------------------------------------------ | +| [@oyi77](https://github.com/oyi77) | 7 | #2010, #2014, #2041, #2052, #2061, #2074, #2091, #2094, #2096 | +| [@backryun](https://github.com/backryun) | 4 | #1992, #2033, #2088, #2123 | +| [@dhaern](https://github.com/dhaern) | 4 | #2028, #2039, #2087, #2090 | +| [@Tentoxa](https://github.com/Tentoxa) | 2 | #2011, #2053 | +| [@wauputr4](https://github.com/wauputr4) | 2 | #2009, #2046 | +| [@payne0420](https://github.com/payne0420) | 1 | #2082 | +| [@Tr0sT](https://github.com/Tr0sT) | 1 | #2012 | +| [@AveryanAlex](https://github.com/AveryanAlex) | 1 | #2008 | +| [@nickwizard](https://github.com/nickwizard) | 1 | #1991 | +| [@rodrigogbbr-stack](https://github.com/rodrigogbbr-stack) | 1 | #1996 | +| [@NekoMonci12](https://github.com/NekoMonci12) | 1 | #1999 | +| [@congvc-dev](https://github.com/congvc-dev) | 1 | #2004 | +| [@tatsster](https://github.com/tatsster) | 1 | #2007 | +| [@xssdem](https://github.com/xssdem) | 1 | #2023 | +| [@bypanghu](https://github.com/bypanghu) | 1 | #2027 | +| [@herjarsa](https://github.com/herjarsa) | 1 | #2030 | +| [@wucm667](https://github.com/wucm667) | 1 | #2031 | +| [@hartmark](https://github.com/hartmark) | 1 | #2045 | +| [@ddarkr](https://github.com/ddarkr) | 1 | #2047 | +| [@tces1](https://github.com/tces1) | 1 | #2048 | +| [@guanbear](https://github.com/guanbear) | 1 | #2054 | +| [@Gi99lin](https://github.com/Gi99lin) | 1 | #2055 | +| [@ivan-mezentsev](https://github.com/ivan-mezentsev) | 1 | #2063 | +| [@JxnLexn](https://github.com/JxnLexn) | 1 | #2019 | +| [@yoviarpauzi](https://github.com/yoviarpauzi) | 1 | #2092 | +| [@rafacpti23](https://github.com/rafacpti23) | 1 | #2086 | +| [@gleber](https://github.com/gleber) | 1 | #2103 | +| [@rilham97](https://github.com/rilham97) | 1 | #2104 | +| [@Gioxaa](https://github.com/Gioxaa) | 1 | #2105 | +| [@boa-z](https://github.com/boa-z) | 1 | #2115 | +| [@eleata](https://github.com/eleata) | 1 | #2116 | +| [@rdself](https://github.com/rdself) | 1 | #2118 | +| [@clousky2020](https://github.com/clousky2020) | 1 | #2119 | +| [@abhinavjnu](https://github.com/abhinavjnu) | 1 | #2122 | +| [@HoaPham98](https://github.com/HoaPham98) | 1 | #2089 | +| [@05dunski](https://github.com/05dunski) | 1 | #1978 (cherry-picked) | + ## [3.7.9] — 2026-05-03 ### ✨ New Features @@ -102,7 +220,7 @@ - **chore(provider):** Add reka models list (#1956 — thanks @backryun) - **chore(model):** Update new models, Delete Deprecated models (#1949 — thanks @backryun) -### 📝 Documentation +### Documentación - **docs(compression):** document RTK+Caveman stacked savings ranges @@ -201,7 +319,7 @@ - **feat(db):** auto-restore probe-failed database on startup to prevent data loss after failed upgrades (#1810) - **feat(analytics):** add cost-based usage insights and activity streaks in the analytics dashboard -### 🔒 Security +### Seguridad - **fix(security):** resolve ReDoS vulnerability in Codex executor regex patterns (#1797, #1789) @@ -354,7 +472,7 @@ We identified that **155 community PRs** across the entire project history (from - **feat(proxy):** implement bulk proxy import via pipe-delimited parser with update-or-create (upsert) logic and real-time preview table - **feat(pwa):** add fullscreen installable PWA with manifest, service worker, and cross-platform app icons (#1728) -### 🔒 Security +### Seguridad - **security:** replace insecure `Math.random` with `crypto.getRandomValues` for fallback UUID generation to resolve CodeQL CWE-338 finding (#182) @@ -519,7 +637,7 @@ We identified that **155 community PRs** across the entire project history (from - **fix(transport):** Prevent memory bloat and database exhaustion from large, fragmented streaming responses. Implemented `ByteQueue` in `kiro.ts` for zero-copy binary accumulation, refactored `antigravity.ts` for incremental SSE parsing, and enforced a strict 512KB tiered truncation limit (`MAX_CALL_LOG_ARTIFACT_BYTES`) on stream request logs and call artifacts (#1647). - **chore(ci):** Update build environment dependencies — bump Node to `24.15.0`, `actions/checkout@v6`, `docker/build-push-action@v7`, pin `actions/setup-python` to major tag (#1646 — thanks @backryun). -### 📝 Documentation +### Documentación - **docs(env):** Add `OMNIROUTE_ALLOW_PRIVATE_PROVIDER_URLS` to `.env.example` with documentation for LM Studio and other local provider use cases (#1623). @@ -669,7 +787,7 @@ We identified that **155 community PRs** across the entire project history (from - **test(next):** Align transpile package expectations for the Next.js standalone build. - **test(ci):** Fix CI-only test failures from environment differences — clear `INITIAL_PASSWORD` and `JWT_SECRET` in integration tests, handle `XDG_CONFIG_HOME` for guide-settings tests. -### 📚 Documentation +### Documentación - **docs:** Update the root changelog with all release-branch changes through 2026-04-24, including PRs #1544, #1555, #1551, #1550, #1548, #1547, #1541, #1538, #1536, and #1527. - **docs:** Fix broken README and localized documentation links. (#1536) @@ -811,7 +929,7 @@ We identified that **155 community PRs** across the entire project history (from - **feat(providers):** Expand image provider registry with extended model support including SD3.5, FLUX, and DALL-E 3 HD configurations - **feat(combos):** Add new routing strategies and full i18n support for agent features section across 31 languages -### 🔒 Security +### Seguridad - **security:** Resolve 18 GitHub CodeQL scan alerts including ReDoS, incomplete sanitization, and bad HTML filtering regexp patterns - **fix(auth):** Seal privilege escalation vector by enforcing JWT session checking exclusively on `/api/keys` management endpoints (#1353) @@ -1078,7 +1196,7 @@ We identified that **155 community PRs** across the entire project history (from - **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 - **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 -### 🔒 Security +### Seguridad - **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 - **Auth Guard on Translator Save:** Added `isAuthenticated` guard to `/api/translator/save` for defense-in-depth consistency @@ -1483,7 +1601,7 @@ We identified that **155 community PRs** across the entire project history (from - **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). -### 📚 Documentation +### Documentació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. - **Context Relay Delivery Notes:** Documented the current architecture, runtime flow, and Codex-focused scope in the feature docs, changelog, and agent guidance. @@ -1559,7 +1677,7 @@ We identified that **155 community PRs** across the entire project history (from ## [3.5.3] - 2026-04-07 -### Security +### Seguridad - **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. - **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. @@ -1575,7 +1693,7 @@ We identified that **155 community PRs** across the entire project history (from - **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. -### Documentation +### Documentación - **I18n Engine:** Synchronized and pushed deep Machine Translation updates across all 32 natively-supported languages (682 translation nodes aligned). @@ -1736,7 +1854,7 @@ We identified that **155 community PRs** across the entire project history (from ## [3.4.8] — 2026-04-03 -### Security +### Seguridad - Fully remediated all outstanding Github Advanced Security (CodeQL) findings and Dependabot alerts. - Fixed insecure randomness vulnerabilities by migrating from `Math.random` to `crypto.randomUUID()`. @@ -1748,7 +1866,7 @@ We identified that **155 community PRs** across the entire project history (from ## [3.4.7] — 2026-04-03 -### Features +### Funcionalidades - Added `Cryptography` node to Monitoring and MCP health checks (#798) - Hardened model-catalog route permissions mapping (`/models`) (#781) @@ -1764,7 +1882,7 @@ We identified that **155 community PRs** across the entire project history (from - Fixed MCP standalone module-resolution (`ERR_MODULE_NOT_FOUND`) via `esbuild` (#936) - Fixed NVIDIA NIM routing credential resolution alias mismatch (#931) -### Security +### Seguridad - Added safe strict input boundary protection against raw `shell: true` remote-code execution injections. @@ -2011,7 +2129,7 @@ We identified that **155 community PRs** across the entire project history (from ## [3.4.0] - 2026-03-31 -### 🚀 Features +### Funcionalidades - **Subscription Utilization Analytics:** Added quota snapshot time-series tracking, Provider Utilization and Combo Health tabs with recharts visualizations, and corresponding API endpoints (#847) - **SQLite Backup Control:** New `OMNIROUTE_DISABLE_AUTO_BACKUP` env flag to disable automatic SQLite backups (#846) @@ -2063,7 +2181,7 @@ We identified that **155 community PRs** across the entire project history (from ## [3.3.8] - 2026-03-30 -### 🚀 Features +### Funcionalidades - **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) - **Qoder Integration:** Native integration for Qoder AI natively replacing the legacy iFlow platform mappings (#660) @@ -2889,7 +3007,7 @@ We identified that **155 community PRs** across the entire project history (from - **NaN tokens in Claude Code / client responses (#617):** - `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 -### 🔒 Security +### Seguridad - Updated `yaml` package to fix stack overflow vulnerability (GHSA-48c2-rrv3-qjmp) @@ -3565,7 +3683,7 @@ docker pull diegosouzapw/omniroute:3.0.0 - **SVG fallback**: `ProviderIcon` component updated with 4-tier strategy: Lobehub → PNG → SVG → Generic icon - **Agents fingerprinting**: Synced with CLI tools — added droid, openclaw, copilot, opencode to fingerprint list (14 total) -### 🔒 Security +### Seguridad - **CVE fix**: Resolved dompurify XSS vulnerability (GHSA-v2wj-7wpq-c8vv) via npm overrides forcing `dompurify@^3.3.2` - `npm audit` now reports **0 vulnerabilities** @@ -3928,7 +4046,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **#510** — Windows: MSYS2/Git-Bash paths (`/c/Program Files/...`) are now normalized to `C:\Program Files\...` - **#492** — `omniroute` CLI now detects `mise`/`nvm` when `app/server.js` is missing and shows targeted fix -### 📖 Documentation +### Documentación - **#513** — Docker password reset: `INITIAL_PASSWORD` env var workaround documented - **#520** — pnpm: `pnpm approve-builds better-sqlite3` documented @@ -4025,7 +4143,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **feat(executors/cloudflare-ai)**: New `CloudflareAIExecutor` — dynamic URL construction requires `accountId` in provider credentials - **feat(executors)**: Register `pollinations`, `pol`, `cloudflare-ai`, `cf` executor mappings -### 📝 Documentation +### Documentación - **docs(readme)**: Expanded free combo stack to 11 providers ($0 forever) - **docs(readme)**: Added 4 new free provider sections (LongCat, Pollinations, Cloudflare AI, Scaleway) with model tables @@ -4177,7 +4295,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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). -### Features +### Funcionalidades - **"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. @@ -4205,7 +4323,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Merge PR #494 (MiniMax role fix), fix KIRO MITM dashboard, triage 8 issues. -### Features +### Funcionalidades - **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. - **roleNormalizer**: `normalizeDeveloperRole()` now accepts `preserveDeveloperRole` parameter with tri-state behavior (undefined=keep, true=keep, false=convert). @@ -4261,7 +4379,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Gemini CLI deprecation, VM guide i18n fix, dependabot security fix, provider schema expansion. -### Features +### Funcionalidades - **Gemini CLI Deprecation** (#462): Mark `gemini-cli` provider as deprecated with warning — Google restricts third-party OAuth usage from March 2026 - **Provider Schema** (#462): Expand Zod validation with `deprecated`, `deprecationReason`, `hasFree`, `freeNote`, `authHint`, `apiHint` optional fields @@ -4270,7 +4388,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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) -### Security +### Seguridad - **deps**: Bump `flatted` 3.3.3 → 3.4.2 — fixes CWE-1321 prototype pollution (#484, @dependabot) @@ -4290,7 +4408,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Czech i18n, SSE protocol fix, VM guide translation. -### Features +### Funcionalidades - **Czech Language** (#482): Full Czech (cs) i18n — 22 docs, 2606 UI strings, language switcher updates (@zen0bit) - **VM Deployment Guide**: Translated from Portuguese to English as the source document (@zen0bit) @@ -4309,7 +4427,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: 2 merged PRs, model aliases routing fix, log export, and issue triage. -### Features +### Funcionalidades - **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) @@ -4329,7 +4447,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Five community PRs — streaming call log fixes, Kiro compatibility, cache token analytics, Chinese translation, and configurable tool call IDs. -### ✨ Features +### Funcionalidades - **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) - **feat(providers)**: Per-model configurable 9-char tool call ID normalization (Mistral-style) — only models with the option enabled get truncated IDs (#470) @@ -4359,7 +4477,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Bailian Coding Plan provider with editable base URLs, plus community contributions for Alibaba Cloud and Kimi Coding. -### ✨ Features +### Funcionalidades - **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) - **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) @@ -4374,7 +4492,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Two new community-contributed providers (Alibaba Cloud Coding, Kimi Coding API-key) and Docker pino fix. -### ✨ Features +### Funcionalidades - **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) - **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) @@ -4399,7 +4517,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Codex responses subpath passthrough natively supported, Windows MITM crash fixed, and Combos agent schemas adjusted. -### ✨ Features +### Funcionalidades - **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) @@ -4439,7 +4557,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **fix(budget)**: "Save Limits" no longer returns 422 — `warningThreshold` is now correctly sent as fraction (0–1) instead of percentage (0–100) (#451) - **fix(combos)**: `` internal cache tag is now stripped before forwarding requests to providers, preventing cache session breaks (#454) -### ✨ Features +### Funcionalidades - **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) @@ -4495,7 +4613,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Search Tools dashboard, i18n fixes, Copilot limits, Serper validation fix. -### 🚀 Features +### Funcionalidades - **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) - New route: `/dashboard/search-tools` @@ -4595,7 +4713,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - DB migration: `request_type` column on `call_logs` for non-chat request tracking - Zod validation (`v1SearchSchema`), auth-gated, cost recorded via `recordCost()` -### 🔒 Security +### Seguridad - **deps**: Next.js 16.1.6 → 16.1.7 — fixes 6 CVEs: - **Critical**: CVE-2026-29057 (HTTP request smuggling via http-proxy) @@ -4725,7 +4843,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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**: New `request_detail_logs` table with 500-entry ring-buffer trigger, opt-in via settings toggle -### ✨ Features +### Funcionalidades - **feat(combo)**: System Message Override per Combo (#399 — `system_message` field replaces or injects system prompt before forwarding to provider) - **feat(combo)**: Tool Filter Regex per Combo (#399 — `tool_filter_regex` keeps only tools matching pattern; supports OpenAI + Anthropic formats) @@ -4740,7 +4858,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: SSE improvements, local provider_nodes extensions, proxy registry, Claude passthrough fixes. -### ✨ Features +### Funcionalidades - **feat(health)**: Background health check for local `provider_nodes` with exponential backoff (30s→300s) and `Promise.allSettled` to avoid blocking (#423, @Regis-RCR) - **feat(embeddings)**: Route `/v1/embeddings` to local `provider_nodes` — `buildDynamicEmbeddingProvider()` with hostname validation (#422, @Regis-RCR) @@ -4882,7 +5000,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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 - **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). -### ✨ Features +### Funcionalidades - **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) @@ -4912,7 +5030,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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) - **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) -### ✨ Features +### Funcionalidades - **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) - **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. @@ -4971,7 +5089,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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) - **fix(logs)**: Request log table is now readable in light mode — status badges, token counts, and combo tags use adaptive `dark:` color classes (#378) -### ✨ Features +### Funcionalidades - **feat(kiro)**: Kiro credit tracking added to usage fetcher — queries `getUserCredits` from AWS CodeWhisperer endpoint (#337) @@ -5372,7 +5490,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > **Major release** — Free Stack ecosystem, transcription playground overhaul, 44+ providers, comprehensive free tier documentation, and UI improvements across the board. -### ✨ Features +### Funcionalidades - **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. - **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. @@ -5383,7 +5501,7 @@ OmniRoute now automatically refreshes model lists for connected providers every ## [2.3.16] - 2026-03-13 -### 📖 Documentation +### Documentación - **README: 44+ Providers** — Updated all 3 occurrences of "36+ providers" to "44+" reflecting the actual codebase count (44 providers in providers.ts) - **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. @@ -5393,7 +5511,7 @@ OmniRoute now automatically refreshes model lists for connected providers every ## [2.3.15] - 2026-03-13 -### ✨ Features +### Funcionalidades - **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. - **i18n — autoCombo section**: Added 20 new translation keys for the Auto-Combo dashboard (`title`, `status`, `modePack`, `providerScores`, `factorTierPriority`, etc.) to all 30 language files. diff --git a/docs/i18n/te/CHANGELOG.md b/docs/i18n/te/CHANGELOG.md index c35c2285ac..b76ad099d0 100644 --- a/docs/i18n/te/CHANGELOG.md +++ b/docs/i18n/te/CHANGELOG.md @@ -10,30 +10,148 @@ ### ✨ New Features -- **feat(antigravity):** integrate Antigravity provider with dynamic `maxOutputTokens` calculation (bumping to `thinkingBudget + 1`) and standard Cloud Code envelope payload sanitization (#2055, #2063) +- **feat(antigravity):** integrate Antigravity provider with dynamic `maxOutputTokens` calculation, identity fingerprinting overhaul, and Cloud Code envelope payload sanitization (#2055, #2063) - **feat(gemini-cli):** add custom projectId support for Gemini CLI transport (UI, DB, executor) (#1991) +- **feat(providers):** add KIE media provider support with dynamic polling, text models, and expanded video models catalog +- **feat(providers):** add Z.AI provider support with GLM quota handling and new quota labels +- **feat(providers):** add 9 new free AI providers — LLM7, Lepton, Kluster, UncloseAI, BazaarLink, Completions, Enally, FreeTheAi (#2096) +- **feat(providers):** batch delete provider connections via checkbox multi-select (#2094) +- **feat(cursor):** full OpenAI parity — tool calls, streaming, and session management (#2082) +- **feat(cli):** comprehensive CLI enhancement suite with 20+ new commands including `omniroute providers`, `omniroute combos`, `omniroute doctor` (#2074) +- **feat(cli):** add modular CLI setup and provider management commands (#2046) +- **feat(mcp):** add DeepSeek quota and limit monitoring feature (#2089) +- **feat(circuit-breaker):** classify 429 errors and apply per-kind cooldowns (#2116) +- **feat(multi):** manifest-aware tier routing — W1-W4 complete (#2014) +- **feat(combos):** add reset-aware routing strategy for quota-based providers +- **feat(combo):** add context_length input field to combo edit form (#2047) +- **feat(chat):** dynamic tool limit detection with proactive truncation (#2061) +- **feat(sse):** refresh Claude OAuth wire image to claude-cli/2.1.131 (#2011) +- **feat(github):** add `targetFormat: openai-responses` to all GitHub models (#2122) +- **feat(api):** allow configuration via API calls — open management routes to Bearer keys with manage scope (#2103) +- **feat(api):** update API bridge proxy timeout to 600,000ms (#2019) +- **feat(usage):** add service tier breakdown, codex fast service tier analytics, and account for fast tier +- **feat(chat):** add `STREAM_READINESS_TIMEOUT_MS` and integrate into chat handling +- **feat(combo):** add `fallbackDelayMs` to combo configuration and related settings +- **feat(chat):** enhance error handling for semaphore capacity with fallback logic +- **feat(qdrant):** embedding model discovery (#2086) +- **feat(auth):** per-session sticky routing for Codex (#1887) +- **feat(inworld):** enhance Inworld TTS support (#2123) ### 🐛 Bug Fixes +- **fix(pricing):** make `getPricingForModel` fully case-insensitive to ensure custom prices correctly reflect in new incoming requests cost calculations +- **fix(gemini):** prevent `functionDeclarations` from being dropped by the sanitizer when `googleSearch` tool is present (#2077) +- **fix(pollinations):** add `jsonMode: true` flag in the request transformation to enforce correct JSON structure from Pollinations API (#2109) +- **fix(docker):** update Dockerfile to copy `/docs` directory during build ensuring API catalog availability at runtime (#2083) +- **fix(docker):** include OpenAPI spec in runtime image (#2007) +- **fix(providers):** strip OpenAI-specific fields in Kiro translator to prevent 400 errors (#2037) +- **fix(kiro):** normalize tool-use payloads to prevent 400 errors from agents (#2104) +- **fix(kiro):** merge adjacent user history turns after role normalization (#2105) +- **fix(ui):** resolve text contrast issues for zero-config warning banner in light mode (#2050) +- **fix(core):** inject global system prompt correctly into downstream chat completions pipeline (#2080) +- **fix(core):** restore Claude Code adaptive thinking defaults and resolve audio transcription CORS regression +- **fix(routing):** add missing v1beta rewrites to next.config to resolve 404 on Gemini models endpoint (#2102) +- **fix(routing):** fix bare GPT-5.5 routing for Codex-only installations (#2054) +- **fix(routing):** add fuzzy auto-combo routing for `auto/*` model prefix (#2010) - **fix(cache):** optimize cache_control preservation logic and explicitly align tool schema with upstream Claude Code expectations - **fix(db):** preserve legacy SQLite database path on Windows to prevent data loss (#1973) +- **fix(db):** reduce hot-path persistence overhead (#2039) +- **fix(db):** resolve migration conflict by renumbering overlapping migration entries (#2041) - **fix(settings):** resolve model alias persistence double stringification preventing UI updates (#2018) - **fix(routing):** dynamically filter bare model auto-resolution by active provider connections to prevent dead-routing (#2029) - **fix(embeddings):** add Google Gemini embeddings compatibility via OpenAI-compatible endpoint mapping (#2006) +- **fix(sse):** prevent Claude OAuth multi-account correlation via metadata.user_id (#2053) +- **fix(sse):** prevent Claude Code identity cloak overrides and fix fallback resilience (#2053) +- **fix(sse):** classify hour quota errors as QUOTA_EXHAUSTED (#2119) +- **fix(sse):** fix CC-compatible streaming bridge (#2118) +- **fix(antigravity):** sanitize Claude Cloud Code payloads (#2090) +- **fix(antigravity):** add duplex half for streaming bodies +- **fix(antigravity):** align identity protocol and behavior with official AM +- **fix(chatgpt-web):** plumb proxy through to native tls-client (#2022, #2023) +- **fix(codex):** expose native model IDs in catalog (#2012) +- **fix(glm):** add dedicated coding transport (#2087) +- **fix(compression):** support Responses input and expand Spanish compression rules (#2028) +- **fix(catalog):** auto-calculate combo context_length from target model limits (#2030) +- **fix(api):** fix usage analytics and API key identity (#2008, #2092) +- **fix(api-key):** allow Unicode letters in API key name validation (#1996) +- **fix(auth):** allow bootstrap without password (#2048) +- **fix(proxy):** clean up proxy page redundancy and fix 1proxy sync empty body error (#2052) +- **fix(dashboard):** resolve Unknown plan display in Provider Limits +- **fix(usage):** add extensible CURRENCY_SYMBOLS mapping for deepseek currencies +- **fix(runtime):** harden timer handling and model pricing fallback +- **fix(i18n):** complete Simplified Chinese translations (#2115) +- **fix(mitm):** add Linux cert install and skip sudo password when root (#1999) +- **fix(mitm):** prevent stub from loading at runtime via bypass module - **fix:** remove Anthropic-Beta header from non-Anthropic providers to fix identity contamination (#1989) - **fix(cli):** resolve .env loading failure for global npm installations +- **fix(export):** exclude telemetry/usage-history tables from JSON config backups by default to prevent unbounded file growth (#2125) +- **fix:** Follow OpenAI specification, handle throttling in batch and fix UI (#2045) -### 🔒 Security +### Seguridad +- **fix(security):** remediate CodeQL vulnerabilities (ReDoS, cryptographic bias, stack trace exposure, and weak password hashing) (#216, #215, #211, #208, #206, #210) - **fix(security):** remediate regex validation backtracking path in core compression cleanup (#1990) - **fix(core):** harden input handling and stabilization for prompt compression edge cases +### Documentación + +- **docs:** add competitive marketing tables and SEO/AEO optimizations to README (#2091) +- **docs:** refresh providers, model catalogs, and docs for v3.8.0 (#2088) +- **docs:** update Claude MD and update GLM-CN max context to 200k (#2027) +- **docs(env):** add `GITLAB_DUO_OAUTH_CLIENT_ID` to `.env.example` (#2031) + ### 🧹 Chores & Maintenance - **chore(providers):** prune redundant local provider icon assets in favor of `@lobehub/icons` web fonts (#1992) +- **chore(providers):** remove deprecated models (#2033) +- **deps:** bump `fast-uri` from 3.1.0 to 3.1.2 (#2078) +- **deps:** bump `hono` from 4.12.14 to 4.12.18 (#2079) - **ci:** skip SonarCloud scan on main pushes to optimize CI time - **test:** stabilize cooldown abort coverage case in integration testing +### 🏆 v3.8.0 Community Contributors + +Thank you to all **38 community contributors** who made v3.8.0 possible! 🎉 + +| Contributor | PRs | Contributions | +| :--------------------------------------------------------- | :-: | :------------------------------------------------------------ | +| [@oyi77](https://github.com/oyi77) | 7 | #2010, #2014, #2041, #2052, #2061, #2074, #2091, #2094, #2096 | +| [@backryun](https://github.com/backryun) | 4 | #1992, #2033, #2088, #2123 | +| [@dhaern](https://github.com/dhaern) | 4 | #2028, #2039, #2087, #2090 | +| [@Tentoxa](https://github.com/Tentoxa) | 2 | #2011, #2053 | +| [@wauputr4](https://github.com/wauputr4) | 2 | #2009, #2046 | +| [@payne0420](https://github.com/payne0420) | 1 | #2082 | +| [@Tr0sT](https://github.com/Tr0sT) | 1 | #2012 | +| [@AveryanAlex](https://github.com/AveryanAlex) | 1 | #2008 | +| [@nickwizard](https://github.com/nickwizard) | 1 | #1991 | +| [@rodrigogbbr-stack](https://github.com/rodrigogbbr-stack) | 1 | #1996 | +| [@NekoMonci12](https://github.com/NekoMonci12) | 1 | #1999 | +| [@congvc-dev](https://github.com/congvc-dev) | 1 | #2004 | +| [@tatsster](https://github.com/tatsster) | 1 | #2007 | +| [@xssdem](https://github.com/xssdem) | 1 | #2023 | +| [@bypanghu](https://github.com/bypanghu) | 1 | #2027 | +| [@herjarsa](https://github.com/herjarsa) | 1 | #2030 | +| [@wucm667](https://github.com/wucm667) | 1 | #2031 | +| [@hartmark](https://github.com/hartmark) | 1 | #2045 | +| [@ddarkr](https://github.com/ddarkr) | 1 | #2047 | +| [@tces1](https://github.com/tces1) | 1 | #2048 | +| [@guanbear](https://github.com/guanbear) | 1 | #2054 | +| [@Gi99lin](https://github.com/Gi99lin) | 1 | #2055 | +| [@ivan-mezentsev](https://github.com/ivan-mezentsev) | 1 | #2063 | +| [@JxnLexn](https://github.com/JxnLexn) | 1 | #2019 | +| [@yoviarpauzi](https://github.com/yoviarpauzi) | 1 | #2092 | +| [@rafacpti23](https://github.com/rafacpti23) | 1 | #2086 | +| [@gleber](https://github.com/gleber) | 1 | #2103 | +| [@rilham97](https://github.com/rilham97) | 1 | #2104 | +| [@Gioxaa](https://github.com/Gioxaa) | 1 | #2105 | +| [@boa-z](https://github.com/boa-z) | 1 | #2115 | +| [@eleata](https://github.com/eleata) | 1 | #2116 | +| [@rdself](https://github.com/rdself) | 1 | #2118 | +| [@clousky2020](https://github.com/clousky2020) | 1 | #2119 | +| [@abhinavjnu](https://github.com/abhinavjnu) | 1 | #2122 | +| [@HoaPham98](https://github.com/HoaPham98) | 1 | #2089 | +| [@05dunski](https://github.com/05dunski) | 1 | #1978 (cherry-picked) | + ## [3.7.9] — 2026-05-03 ### ✨ New Features @@ -102,7 +220,7 @@ - **chore(provider):** Add reka models list (#1956 — thanks @backryun) - **chore(model):** Update new models, Delete Deprecated models (#1949 — thanks @backryun) -### 📝 Documentation +### Documentación - **docs(compression):** document RTK+Caveman stacked savings ranges @@ -201,7 +319,7 @@ - **feat(db):** auto-restore probe-failed database on startup to prevent data loss after failed upgrades (#1810) - **feat(analytics):** add cost-based usage insights and activity streaks in the analytics dashboard -### 🔒 Security +### Seguridad - **fix(security):** resolve ReDoS vulnerability in Codex executor regex patterns (#1797, #1789) @@ -354,7 +472,7 @@ We identified that **155 community PRs** across the entire project history (from - **feat(proxy):** implement bulk proxy import via pipe-delimited parser with update-or-create (upsert) logic and real-time preview table - **feat(pwa):** add fullscreen installable PWA with manifest, service worker, and cross-platform app icons (#1728) -### 🔒 Security +### Seguridad - **security:** replace insecure `Math.random` with `crypto.getRandomValues` for fallback UUID generation to resolve CodeQL CWE-338 finding (#182) @@ -519,7 +637,7 @@ We identified that **155 community PRs** across the entire project history (from - **fix(transport):** Prevent memory bloat and database exhaustion from large, fragmented streaming responses. Implemented `ByteQueue` in `kiro.ts` for zero-copy binary accumulation, refactored `antigravity.ts` for incremental SSE parsing, and enforced a strict 512KB tiered truncation limit (`MAX_CALL_LOG_ARTIFACT_BYTES`) on stream request logs and call artifacts (#1647). - **chore(ci):** Update build environment dependencies — bump Node to `24.15.0`, `actions/checkout@v6`, `docker/build-push-action@v7`, pin `actions/setup-python` to major tag (#1646 — thanks @backryun). -### 📝 Documentation +### Documentación - **docs(env):** Add `OMNIROUTE_ALLOW_PRIVATE_PROVIDER_URLS` to `.env.example` with documentation for LM Studio and other local provider use cases (#1623). @@ -669,7 +787,7 @@ We identified that **155 community PRs** across the entire project history (from - **test(next):** Align transpile package expectations for the Next.js standalone build. - **test(ci):** Fix CI-only test failures from environment differences — clear `INITIAL_PASSWORD` and `JWT_SECRET` in integration tests, handle `XDG_CONFIG_HOME` for guide-settings tests. -### 📚 Documentation +### Documentación - **docs:** Update the root changelog with all release-branch changes through 2026-04-24, including PRs #1544, #1555, #1551, #1550, #1548, #1547, #1541, #1538, #1536, and #1527. - **docs:** Fix broken README and localized documentation links. (#1536) @@ -811,7 +929,7 @@ We identified that **155 community PRs** across the entire project history (from - **feat(providers):** Expand image provider registry with extended model support including SD3.5, FLUX, and DALL-E 3 HD configurations - **feat(combos):** Add new routing strategies and full i18n support for agent features section across 31 languages -### 🔒 Security +### Seguridad - **security:** Resolve 18 GitHub CodeQL scan alerts including ReDoS, incomplete sanitization, and bad HTML filtering regexp patterns - **fix(auth):** Seal privilege escalation vector by enforcing JWT session checking exclusively on `/api/keys` management endpoints (#1353) @@ -1078,7 +1196,7 @@ We identified that **155 community PRs** across the entire project history (from - **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 - **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 -### 🔒 Security +### Seguridad - **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 - **Auth Guard on Translator Save:** Added `isAuthenticated` guard to `/api/translator/save` for defense-in-depth consistency @@ -1483,7 +1601,7 @@ We identified that **155 community PRs** across the entire project history (from - **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). -### 📚 Documentation +### Documentació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. - **Context Relay Delivery Notes:** Documented the current architecture, runtime flow, and Codex-focused scope in the feature docs, changelog, and agent guidance. @@ -1559,7 +1677,7 @@ We identified that **155 community PRs** across the entire project history (from ## [3.5.3] - 2026-04-07 -### Security +### Seguridad - **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. - **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. @@ -1575,7 +1693,7 @@ We identified that **155 community PRs** across the entire project history (from - **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. -### Documentation +### Documentación - **I18n Engine:** Synchronized and pushed deep Machine Translation updates across all 32 natively-supported languages (682 translation nodes aligned). @@ -1736,7 +1854,7 @@ We identified that **155 community PRs** across the entire project history (from ## [3.4.8] — 2026-04-03 -### Security +### Seguridad - Fully remediated all outstanding Github Advanced Security (CodeQL) findings and Dependabot alerts. - Fixed insecure randomness vulnerabilities by migrating from `Math.random` to `crypto.randomUUID()`. @@ -1748,7 +1866,7 @@ We identified that **155 community PRs** across the entire project history (from ## [3.4.7] — 2026-04-03 -### Features +### Funcionalidades - Added `Cryptography` node to Monitoring and MCP health checks (#798) - Hardened model-catalog route permissions mapping (`/models`) (#781) @@ -1764,7 +1882,7 @@ We identified that **155 community PRs** across the entire project history (from - Fixed MCP standalone module-resolution (`ERR_MODULE_NOT_FOUND`) via `esbuild` (#936) - Fixed NVIDIA NIM routing credential resolution alias mismatch (#931) -### Security +### Seguridad - Added safe strict input boundary protection against raw `shell: true` remote-code execution injections. @@ -2011,7 +2129,7 @@ We identified that **155 community PRs** across the entire project history (from ## [3.4.0] - 2026-03-31 -### 🚀 Features +### Funcionalidades - **Subscription Utilization Analytics:** Added quota snapshot time-series tracking, Provider Utilization and Combo Health tabs with recharts visualizations, and corresponding API endpoints (#847) - **SQLite Backup Control:** New `OMNIROUTE_DISABLE_AUTO_BACKUP` env flag to disable automatic SQLite backups (#846) @@ -2063,7 +2181,7 @@ We identified that **155 community PRs** across the entire project history (from ## [3.3.8] - 2026-03-30 -### 🚀 Features +### Funcionalidades - **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) - **Qoder Integration:** Native integration for Qoder AI natively replacing the legacy iFlow platform mappings (#660) @@ -2889,7 +3007,7 @@ We identified that **155 community PRs** across the entire project history (from - **NaN tokens in Claude Code / client responses (#617):** - `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 -### 🔒 Security +### Seguridad - Updated `yaml` package to fix stack overflow vulnerability (GHSA-48c2-rrv3-qjmp) @@ -3565,7 +3683,7 @@ docker pull diegosouzapw/omniroute:3.0.0 - **SVG fallback**: `ProviderIcon` component updated with 4-tier strategy: Lobehub → PNG → SVG → Generic icon - **Agents fingerprinting**: Synced with CLI tools — added droid, openclaw, copilot, opencode to fingerprint list (14 total) -### 🔒 Security +### Seguridad - **CVE fix**: Resolved dompurify XSS vulnerability (GHSA-v2wj-7wpq-c8vv) via npm overrides forcing `dompurify@^3.3.2` - `npm audit` now reports **0 vulnerabilities** @@ -3928,7 +4046,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **#510** — Windows: MSYS2/Git-Bash paths (`/c/Program Files/...`) are now normalized to `C:\Program Files\...` - **#492** — `omniroute` CLI now detects `mise`/`nvm` when `app/server.js` is missing and shows targeted fix -### 📖 Documentation +### Documentación - **#513** — Docker password reset: `INITIAL_PASSWORD` env var workaround documented - **#520** — pnpm: `pnpm approve-builds better-sqlite3` documented @@ -4025,7 +4143,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **feat(executors/cloudflare-ai)**: New `CloudflareAIExecutor` — dynamic URL construction requires `accountId` in provider credentials - **feat(executors)**: Register `pollinations`, `pol`, `cloudflare-ai`, `cf` executor mappings -### 📝 Documentation +### Documentación - **docs(readme)**: Expanded free combo stack to 11 providers ($0 forever) - **docs(readme)**: Added 4 new free provider sections (LongCat, Pollinations, Cloudflare AI, Scaleway) with model tables @@ -4177,7 +4295,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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). -### Features +### Funcionalidades - **"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. @@ -4205,7 +4323,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Merge PR #494 (MiniMax role fix), fix KIRO MITM dashboard, triage 8 issues. -### Features +### Funcionalidades - **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. - **roleNormalizer**: `normalizeDeveloperRole()` now accepts `preserveDeveloperRole` parameter with tri-state behavior (undefined=keep, true=keep, false=convert). @@ -4261,7 +4379,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Gemini CLI deprecation, VM guide i18n fix, dependabot security fix, provider schema expansion. -### Features +### Funcionalidades - **Gemini CLI Deprecation** (#462): Mark `gemini-cli` provider as deprecated with warning — Google restricts third-party OAuth usage from March 2026 - **Provider Schema** (#462): Expand Zod validation with `deprecated`, `deprecationReason`, `hasFree`, `freeNote`, `authHint`, `apiHint` optional fields @@ -4270,7 +4388,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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) -### Security +### Seguridad - **deps**: Bump `flatted` 3.3.3 → 3.4.2 — fixes CWE-1321 prototype pollution (#484, @dependabot) @@ -4290,7 +4408,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Czech i18n, SSE protocol fix, VM guide translation. -### Features +### Funcionalidades - **Czech Language** (#482): Full Czech (cs) i18n — 22 docs, 2606 UI strings, language switcher updates (@zen0bit) - **VM Deployment Guide**: Translated from Portuguese to English as the source document (@zen0bit) @@ -4309,7 +4427,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: 2 merged PRs, model aliases routing fix, log export, and issue triage. -### Features +### Funcionalidades - **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) @@ -4329,7 +4447,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Five community PRs — streaming call log fixes, Kiro compatibility, cache token analytics, Chinese translation, and configurable tool call IDs. -### ✨ Features +### Funcionalidades - **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) - **feat(providers)**: Per-model configurable 9-char tool call ID normalization (Mistral-style) — only models with the option enabled get truncated IDs (#470) @@ -4359,7 +4477,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Bailian Coding Plan provider with editable base URLs, plus community contributions for Alibaba Cloud and Kimi Coding. -### ✨ Features +### Funcionalidades - **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) - **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) @@ -4374,7 +4492,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Two new community-contributed providers (Alibaba Cloud Coding, Kimi Coding API-key) and Docker pino fix. -### ✨ Features +### Funcionalidades - **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) - **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) @@ -4399,7 +4517,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Codex responses subpath passthrough natively supported, Windows MITM crash fixed, and Combos agent schemas adjusted. -### ✨ Features +### Funcionalidades - **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) @@ -4439,7 +4557,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **fix(budget)**: "Save Limits" no longer returns 422 — `warningThreshold` is now correctly sent as fraction (0–1) instead of percentage (0–100) (#451) - **fix(combos)**: `` internal cache tag is now stripped before forwarding requests to providers, preventing cache session breaks (#454) -### ✨ Features +### Funcionalidades - **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) @@ -4495,7 +4613,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Search Tools dashboard, i18n fixes, Copilot limits, Serper validation fix. -### 🚀 Features +### Funcionalidades - **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) - New route: `/dashboard/search-tools` @@ -4595,7 +4713,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - DB migration: `request_type` column on `call_logs` for non-chat request tracking - Zod validation (`v1SearchSchema`), auth-gated, cost recorded via `recordCost()` -### 🔒 Security +### Seguridad - **deps**: Next.js 16.1.6 → 16.1.7 — fixes 6 CVEs: - **Critical**: CVE-2026-29057 (HTTP request smuggling via http-proxy) @@ -4725,7 +4843,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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**: New `request_detail_logs` table with 500-entry ring-buffer trigger, opt-in via settings toggle -### ✨ Features +### Funcionalidades - **feat(combo)**: System Message Override per Combo (#399 — `system_message` field replaces or injects system prompt before forwarding to provider) - **feat(combo)**: Tool Filter Regex per Combo (#399 — `tool_filter_regex` keeps only tools matching pattern; supports OpenAI + Anthropic formats) @@ -4740,7 +4858,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: SSE improvements, local provider_nodes extensions, proxy registry, Claude passthrough fixes. -### ✨ Features +### Funcionalidades - **feat(health)**: Background health check for local `provider_nodes` with exponential backoff (30s→300s) and `Promise.allSettled` to avoid blocking (#423, @Regis-RCR) - **feat(embeddings)**: Route `/v1/embeddings` to local `provider_nodes` — `buildDynamicEmbeddingProvider()` with hostname validation (#422, @Regis-RCR) @@ -4882,7 +5000,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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 - **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). -### ✨ Features +### Funcionalidades - **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) @@ -4912,7 +5030,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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) - **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) -### ✨ Features +### Funcionalidades - **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) - **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. @@ -4971,7 +5089,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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) - **fix(logs)**: Request log table is now readable in light mode — status badges, token counts, and combo tags use adaptive `dark:` color classes (#378) -### ✨ Features +### Funcionalidades - **feat(kiro)**: Kiro credit tracking added to usage fetcher — queries `getUserCredits` from AWS CodeWhisperer endpoint (#337) @@ -5372,7 +5490,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > **Major release** — Free Stack ecosystem, transcription playground overhaul, 44+ providers, comprehensive free tier documentation, and UI improvements across the board. -### ✨ Features +### Funcionalidades - **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. - **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. @@ -5383,7 +5501,7 @@ OmniRoute now automatically refreshes model lists for connected providers every ## [2.3.16] - 2026-03-13 -### 📖 Documentation +### Documentación - **README: 44+ Providers** — Updated all 3 occurrences of "36+ providers" to "44+" reflecting the actual codebase count (44 providers in providers.ts) - **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. @@ -5393,7 +5511,7 @@ OmniRoute now automatically refreshes model lists for connected providers every ## [2.3.15] - 2026-03-13 -### ✨ Features +### Funcionalidades - **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. - **i18n — autoCombo section**: Added 20 new translation keys for the Auto-Combo dashboard (`title`, `status`, `modePack`, `providerScores`, `factorTierPriority`, etc.) to all 30 language files. diff --git a/docs/i18n/th/CHANGELOG.md b/docs/i18n/th/CHANGELOG.md index c6f0ad1a37..e9006ce8cb 100644 --- a/docs/i18n/th/CHANGELOG.md +++ b/docs/i18n/th/CHANGELOG.md @@ -10,30 +10,148 @@ ### ✨ New Features -- **feat(antigravity):** integrate Antigravity provider with dynamic `maxOutputTokens` calculation (bumping to `thinkingBudget + 1`) and standard Cloud Code envelope payload sanitization (#2055, #2063) +- **feat(antigravity):** integrate Antigravity provider with dynamic `maxOutputTokens` calculation, identity fingerprinting overhaul, and Cloud Code envelope payload sanitization (#2055, #2063) - **feat(gemini-cli):** add custom projectId support for Gemini CLI transport (UI, DB, executor) (#1991) +- **feat(providers):** add KIE media provider support with dynamic polling, text models, and expanded video models catalog +- **feat(providers):** add Z.AI provider support with GLM quota handling and new quota labels +- **feat(providers):** add 9 new free AI providers — LLM7, Lepton, Kluster, UncloseAI, BazaarLink, Completions, Enally, FreeTheAi (#2096) +- **feat(providers):** batch delete provider connections via checkbox multi-select (#2094) +- **feat(cursor):** full OpenAI parity — tool calls, streaming, and session management (#2082) +- **feat(cli):** comprehensive CLI enhancement suite with 20+ new commands including `omniroute providers`, `omniroute combos`, `omniroute doctor` (#2074) +- **feat(cli):** add modular CLI setup and provider management commands (#2046) +- **feat(mcp):** add DeepSeek quota and limit monitoring feature (#2089) +- **feat(circuit-breaker):** classify 429 errors and apply per-kind cooldowns (#2116) +- **feat(multi):** manifest-aware tier routing — W1-W4 complete (#2014) +- **feat(combos):** add reset-aware routing strategy for quota-based providers +- **feat(combo):** add context_length input field to combo edit form (#2047) +- **feat(chat):** dynamic tool limit detection with proactive truncation (#2061) +- **feat(sse):** refresh Claude OAuth wire image to claude-cli/2.1.131 (#2011) +- **feat(github):** add `targetFormat: openai-responses` to all GitHub models (#2122) +- **feat(api):** allow configuration via API calls — open management routes to Bearer keys with manage scope (#2103) +- **feat(api):** update API bridge proxy timeout to 600,000ms (#2019) +- **feat(usage):** add service tier breakdown, codex fast service tier analytics, and account for fast tier +- **feat(chat):** add `STREAM_READINESS_TIMEOUT_MS` and integrate into chat handling +- **feat(combo):** add `fallbackDelayMs` to combo configuration and related settings +- **feat(chat):** enhance error handling for semaphore capacity with fallback logic +- **feat(qdrant):** embedding model discovery (#2086) +- **feat(auth):** per-session sticky routing for Codex (#1887) +- **feat(inworld):** enhance Inworld TTS support (#2123) ### 🐛 Bug Fixes +- **fix(pricing):** make `getPricingForModel` fully case-insensitive to ensure custom prices correctly reflect in new incoming requests cost calculations +- **fix(gemini):** prevent `functionDeclarations` from being dropped by the sanitizer when `googleSearch` tool is present (#2077) +- **fix(pollinations):** add `jsonMode: true` flag in the request transformation to enforce correct JSON structure from Pollinations API (#2109) +- **fix(docker):** update Dockerfile to copy `/docs` directory during build ensuring API catalog availability at runtime (#2083) +- **fix(docker):** include OpenAPI spec in runtime image (#2007) +- **fix(providers):** strip OpenAI-specific fields in Kiro translator to prevent 400 errors (#2037) +- **fix(kiro):** normalize tool-use payloads to prevent 400 errors from agents (#2104) +- **fix(kiro):** merge adjacent user history turns after role normalization (#2105) +- **fix(ui):** resolve text contrast issues for zero-config warning banner in light mode (#2050) +- **fix(core):** inject global system prompt correctly into downstream chat completions pipeline (#2080) +- **fix(core):** restore Claude Code adaptive thinking defaults and resolve audio transcription CORS regression +- **fix(routing):** add missing v1beta rewrites to next.config to resolve 404 on Gemini models endpoint (#2102) +- **fix(routing):** fix bare GPT-5.5 routing for Codex-only installations (#2054) +- **fix(routing):** add fuzzy auto-combo routing for `auto/*` model prefix (#2010) - **fix(cache):** optimize cache_control preservation logic and explicitly align tool schema with upstream Claude Code expectations - **fix(db):** preserve legacy SQLite database path on Windows to prevent data loss (#1973) +- **fix(db):** reduce hot-path persistence overhead (#2039) +- **fix(db):** resolve migration conflict by renumbering overlapping migration entries (#2041) - **fix(settings):** resolve model alias persistence double stringification preventing UI updates (#2018) - **fix(routing):** dynamically filter bare model auto-resolution by active provider connections to prevent dead-routing (#2029) - **fix(embeddings):** add Google Gemini embeddings compatibility via OpenAI-compatible endpoint mapping (#2006) +- **fix(sse):** prevent Claude OAuth multi-account correlation via metadata.user_id (#2053) +- **fix(sse):** prevent Claude Code identity cloak overrides and fix fallback resilience (#2053) +- **fix(sse):** classify hour quota errors as QUOTA_EXHAUSTED (#2119) +- **fix(sse):** fix CC-compatible streaming bridge (#2118) +- **fix(antigravity):** sanitize Claude Cloud Code payloads (#2090) +- **fix(antigravity):** add duplex half for streaming bodies +- **fix(antigravity):** align identity protocol and behavior with official AM +- **fix(chatgpt-web):** plumb proxy through to native tls-client (#2022, #2023) +- **fix(codex):** expose native model IDs in catalog (#2012) +- **fix(glm):** add dedicated coding transport (#2087) +- **fix(compression):** support Responses input and expand Spanish compression rules (#2028) +- **fix(catalog):** auto-calculate combo context_length from target model limits (#2030) +- **fix(api):** fix usage analytics and API key identity (#2008, #2092) +- **fix(api-key):** allow Unicode letters in API key name validation (#1996) +- **fix(auth):** allow bootstrap without password (#2048) +- **fix(proxy):** clean up proxy page redundancy and fix 1proxy sync empty body error (#2052) +- **fix(dashboard):** resolve Unknown plan display in Provider Limits +- **fix(usage):** add extensible CURRENCY_SYMBOLS mapping for deepseek currencies +- **fix(runtime):** harden timer handling and model pricing fallback +- **fix(i18n):** complete Simplified Chinese translations (#2115) +- **fix(mitm):** add Linux cert install and skip sudo password when root (#1999) +- **fix(mitm):** prevent stub from loading at runtime via bypass module - **fix:** remove Anthropic-Beta header from non-Anthropic providers to fix identity contamination (#1989) - **fix(cli):** resolve .env loading failure for global npm installations +- **fix(export):** exclude telemetry/usage-history tables from JSON config backups by default to prevent unbounded file growth (#2125) +- **fix:** Follow OpenAI specification, handle throttling in batch and fix UI (#2045) -### 🔒 Security +### ความปลอดภัย +- **fix(security):** remediate CodeQL vulnerabilities (ReDoS, cryptographic bias, stack trace exposure, and weak password hashing) (#216, #215, #211, #208, #206, #210) - **fix(security):** remediate regex validation backtracking path in core compression cleanup (#1990) - **fix(core):** harden input handling and stabilization for prompt compression edge cases +### เอกสาร + +- **docs:** add competitive marketing tables and SEO/AEO optimizations to README (#2091) +- **docs:** refresh providers, model catalogs, and docs for v3.8.0 (#2088) +- **docs:** update Claude MD and update GLM-CN max context to 200k (#2027) +- **docs(env):** add `GITLAB_DUO_OAUTH_CLIENT_ID` to `.env.example` (#2031) + ### 🧹 Chores & Maintenance - **chore(providers):** prune redundant local provider icon assets in favor of `@lobehub/icons` web fonts (#1992) +- **chore(providers):** remove deprecated models (#2033) +- **deps:** bump `fast-uri` from 3.1.0 to 3.1.2 (#2078) +- **deps:** bump `hono` from 4.12.14 to 4.12.18 (#2079) - **ci:** skip SonarCloud scan on main pushes to optimize CI time - **test:** stabilize cooldown abort coverage case in integration testing +### 🏆 v3.8.0 Community Contributors + +Thank you to all **38 community contributors** who made v3.8.0 possible! 🎉 + +| Contributor | PRs | Contributions | +| :--------------------------------------------------------- | :-: | :------------------------------------------------------------ | +| [@oyi77](https://github.com/oyi77) | 7 | #2010, #2014, #2041, #2052, #2061, #2074, #2091, #2094, #2096 | +| [@backryun](https://github.com/backryun) | 4 | #1992, #2033, #2088, #2123 | +| [@dhaern](https://github.com/dhaern) | 4 | #2028, #2039, #2087, #2090 | +| [@Tentoxa](https://github.com/Tentoxa) | 2 | #2011, #2053 | +| [@wauputr4](https://github.com/wauputr4) | 2 | #2009, #2046 | +| [@payne0420](https://github.com/payne0420) | 1 | #2082 | +| [@Tr0sT](https://github.com/Tr0sT) | 1 | #2012 | +| [@AveryanAlex](https://github.com/AveryanAlex) | 1 | #2008 | +| [@nickwizard](https://github.com/nickwizard) | 1 | #1991 | +| [@rodrigogbbr-stack](https://github.com/rodrigogbbr-stack) | 1 | #1996 | +| [@NekoMonci12](https://github.com/NekoMonci12) | 1 | #1999 | +| [@congvc-dev](https://github.com/congvc-dev) | 1 | #2004 | +| [@tatsster](https://github.com/tatsster) | 1 | #2007 | +| [@xssdem](https://github.com/xssdem) | 1 | #2023 | +| [@bypanghu](https://github.com/bypanghu) | 1 | #2027 | +| [@herjarsa](https://github.com/herjarsa) | 1 | #2030 | +| [@wucm667](https://github.com/wucm667) | 1 | #2031 | +| [@hartmark](https://github.com/hartmark) | 1 | #2045 | +| [@ddarkr](https://github.com/ddarkr) | 1 | #2047 | +| [@tces1](https://github.com/tces1) | 1 | #2048 | +| [@guanbear](https://github.com/guanbear) | 1 | #2054 | +| [@Gi99lin](https://github.com/Gi99lin) | 1 | #2055 | +| [@ivan-mezentsev](https://github.com/ivan-mezentsev) | 1 | #2063 | +| [@JxnLexn](https://github.com/JxnLexn) | 1 | #2019 | +| [@yoviarpauzi](https://github.com/yoviarpauzi) | 1 | #2092 | +| [@rafacpti23](https://github.com/rafacpti23) | 1 | #2086 | +| [@gleber](https://github.com/gleber) | 1 | #2103 | +| [@rilham97](https://github.com/rilham97) | 1 | #2104 | +| [@Gioxaa](https://github.com/Gioxaa) | 1 | #2105 | +| [@boa-z](https://github.com/boa-z) | 1 | #2115 | +| [@eleata](https://github.com/eleata) | 1 | #2116 | +| [@rdself](https://github.com/rdself) | 1 | #2118 | +| [@clousky2020](https://github.com/clousky2020) | 1 | #2119 | +| [@abhinavjnu](https://github.com/abhinavjnu) | 1 | #2122 | +| [@HoaPham98](https://github.com/HoaPham98) | 1 | #2089 | +| [@05dunski](https://github.com/05dunski) | 1 | #1978 (cherry-picked) | + ## [3.7.9] — 2026-05-03 ### ✨ New Features @@ -102,7 +220,7 @@ - **chore(provider):** Add reka models list (#1956 — thanks @backryun) - **chore(model):** Update new models, Delete Deprecated models (#1949 — thanks @backryun) -### 📝 Documentation +### เอกสาร - **docs(compression):** document RTK+Caveman stacked savings ranges @@ -201,7 +319,7 @@ - **feat(db):** auto-restore probe-failed database on startup to prevent data loss after failed upgrades (#1810) - **feat(analytics):** add cost-based usage insights and activity streaks in the analytics dashboard -### 🔒 Security +### ความปลอดภัย - **fix(security):** resolve ReDoS vulnerability in Codex executor regex patterns (#1797, #1789) @@ -354,7 +472,7 @@ We identified that **155 community PRs** across the entire project history (from - **feat(proxy):** implement bulk proxy import via pipe-delimited parser with update-or-create (upsert) logic and real-time preview table - **feat(pwa):** add fullscreen installable PWA with manifest, service worker, and cross-platform app icons (#1728) -### 🔒 Security +### ความปลอดภัย - **security:** replace insecure `Math.random` with `crypto.getRandomValues` for fallback UUID generation to resolve CodeQL CWE-338 finding (#182) @@ -519,7 +637,7 @@ We identified that **155 community PRs** across the entire project history (from - **fix(transport):** Prevent memory bloat and database exhaustion from large, fragmented streaming responses. Implemented `ByteQueue` in `kiro.ts` for zero-copy binary accumulation, refactored `antigravity.ts` for incremental SSE parsing, and enforced a strict 512KB tiered truncation limit (`MAX_CALL_LOG_ARTIFACT_BYTES`) on stream request logs and call artifacts (#1647). - **chore(ci):** Update build environment dependencies — bump Node to `24.15.0`, `actions/checkout@v6`, `docker/build-push-action@v7`, pin `actions/setup-python` to major tag (#1646 — thanks @backryun). -### 📝 Documentation +### เอกสาร - **docs(env):** Add `OMNIROUTE_ALLOW_PRIVATE_PROVIDER_URLS` to `.env.example` with documentation for LM Studio and other local provider use cases (#1623). @@ -669,7 +787,7 @@ We identified that **155 community PRs** across the entire project history (from - **test(next):** Align transpile package expectations for the Next.js standalone build. - **test(ci):** Fix CI-only test failures from environment differences — clear `INITIAL_PASSWORD` and `JWT_SECRET` in integration tests, handle `XDG_CONFIG_HOME` for guide-settings tests. -### 📚 Documentation +### เอกสาร - **docs:** Update the root changelog with all release-branch changes through 2026-04-24, including PRs #1544, #1555, #1551, #1550, #1548, #1547, #1541, #1538, #1536, and #1527. - **docs:** Fix broken README and localized documentation links. (#1536) @@ -811,7 +929,7 @@ We identified that **155 community PRs** across the entire project history (from - **feat(providers):** Expand image provider registry with extended model support including SD3.5, FLUX, and DALL-E 3 HD configurations - **feat(combos):** Add new routing strategies and full i18n support for agent features section across 31 languages -### 🔒 Security +### ความปลอดภัย - **security:** Resolve 18 GitHub CodeQL scan alerts including ReDoS, incomplete sanitization, and bad HTML filtering regexp patterns - **fix(auth):** Seal privilege escalation vector by enforcing JWT session checking exclusively on `/api/keys` management endpoints (#1353) @@ -1078,7 +1196,7 @@ We identified that **155 community PRs** across the entire project history (from - **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 - **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 -### 🔒 Security +### ความปลอดภัย - **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 - **Auth Guard on Translator Save:** Added `isAuthenticated` guard to `/api/translator/save` for defense-in-depth consistency @@ -1483,7 +1601,7 @@ We identified that **155 community PRs** across the entire project history (from - **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). -### 📚 Documentation +### เอกสาร - **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. - **Context Relay Delivery Notes:** Documented the current architecture, runtime flow, and Codex-focused scope in the feature docs, changelog, and agent guidance. @@ -1559,7 +1677,7 @@ We identified that **155 community PRs** across the entire project history (from ## [3.5.3] - 2026-04-07 -### Security +### ความปลอดภัย - **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. - **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. @@ -1575,7 +1693,7 @@ We identified that **155 community PRs** across the entire project history (from - **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. -### Documentation +### เอกสาร - **I18n Engine:** Synchronized and pushed deep Machine Translation updates across all 32 natively-supported languages (682 translation nodes aligned). @@ -1736,7 +1854,7 @@ We identified that **155 community PRs** across the entire project history (from ## [3.4.8] — 2026-04-03 -### Security +### ความปลอดภัย - Fully remediated all outstanding Github Advanced Security (CodeQL) findings and Dependabot alerts. - Fixed insecure randomness vulnerabilities by migrating from `Math.random` to `crypto.randomUUID()`. @@ -1748,7 +1866,7 @@ We identified that **155 community PRs** across the entire project history (from ## [3.4.7] — 2026-04-03 -### Features +### คุณสมบัติ - Added `Cryptography` node to Monitoring and MCP health checks (#798) - Hardened model-catalog route permissions mapping (`/models`) (#781) @@ -1764,7 +1882,7 @@ We identified that **155 community PRs** across the entire project history (from - Fixed MCP standalone module-resolution (`ERR_MODULE_NOT_FOUND`) via `esbuild` (#936) - Fixed NVIDIA NIM routing credential resolution alias mismatch (#931) -### Security +### ความปลอดภัย - Added safe strict input boundary protection against raw `shell: true` remote-code execution injections. @@ -2011,7 +2129,7 @@ We identified that **155 community PRs** across the entire project history (from ## [3.4.0] - 2026-03-31 -### 🚀 Features +### คุณสมบัติ - **Subscription Utilization Analytics:** Added quota snapshot time-series tracking, Provider Utilization and Combo Health tabs with recharts visualizations, and corresponding API endpoints (#847) - **SQLite Backup Control:** New `OMNIROUTE_DISABLE_AUTO_BACKUP` env flag to disable automatic SQLite backups (#846) @@ -2063,7 +2181,7 @@ We identified that **155 community PRs** across the entire project history (from ## [3.3.8] - 2026-03-30 -### 🚀 Features +### คุณสมบัติ - **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) - **Qoder Integration:** Native integration for Qoder AI natively replacing the legacy iFlow platform mappings (#660) @@ -2889,7 +3007,7 @@ We identified that **155 community PRs** across the entire project history (from - **NaN tokens in Claude Code / client responses (#617):** - `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 -### 🔒 Security +### ความปลอดภัย - Updated `yaml` package to fix stack overflow vulnerability (GHSA-48c2-rrv3-qjmp) @@ -3565,7 +3683,7 @@ docker pull diegosouzapw/omniroute:3.0.0 - **SVG fallback**: `ProviderIcon` component updated with 4-tier strategy: Lobehub → PNG → SVG → Generic icon - **Agents fingerprinting**: Synced with CLI tools — added droid, openclaw, copilot, opencode to fingerprint list (14 total) -### 🔒 Security +### ความปลอดภัย - **CVE fix**: Resolved dompurify XSS vulnerability (GHSA-v2wj-7wpq-c8vv) via npm overrides forcing `dompurify@^3.3.2` - `npm audit` now reports **0 vulnerabilities** @@ -3928,7 +4046,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **#510** — Windows: MSYS2/Git-Bash paths (`/c/Program Files/...`) are now normalized to `C:\Program Files\...` - **#492** — `omniroute` CLI now detects `mise`/`nvm` when `app/server.js` is missing and shows targeted fix -### 📖 Documentation +### เอกสาร - **#513** — Docker password reset: `INITIAL_PASSWORD` env var workaround documented - **#520** — pnpm: `pnpm approve-builds better-sqlite3` documented @@ -4025,7 +4143,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **feat(executors/cloudflare-ai)**: New `CloudflareAIExecutor` — dynamic URL construction requires `accountId` in provider credentials - **feat(executors)**: Register `pollinations`, `pol`, `cloudflare-ai`, `cf` executor mappings -### 📝 Documentation +### เอกสาร - **docs(readme)**: Expanded free combo stack to 11 providers ($0 forever) - **docs(readme)**: Added 4 new free provider sections (LongCat, Pollinations, Cloudflare AI, Scaleway) with model tables @@ -4177,7 +4295,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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). -### Features +### คุณสมบัติ - **"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. @@ -4205,7 +4323,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Merge PR #494 (MiniMax role fix), fix KIRO MITM dashboard, triage 8 issues. -### Features +### คุณสมบัติ - **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. - **roleNormalizer**: `normalizeDeveloperRole()` now accepts `preserveDeveloperRole` parameter with tri-state behavior (undefined=keep, true=keep, false=convert). @@ -4261,7 +4379,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Gemini CLI deprecation, VM guide i18n fix, dependabot security fix, provider schema expansion. -### Features +### คุณสมบัติ - **Gemini CLI Deprecation** (#462): Mark `gemini-cli` provider as deprecated with warning — Google restricts third-party OAuth usage from March 2026 - **Provider Schema** (#462): Expand Zod validation with `deprecated`, `deprecationReason`, `hasFree`, `freeNote`, `authHint`, `apiHint` optional fields @@ -4270,7 +4388,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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) -### Security +### ความปลอดภัย - **deps**: Bump `flatted` 3.3.3 → 3.4.2 — fixes CWE-1321 prototype pollution (#484, @dependabot) @@ -4290,7 +4408,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Czech i18n, SSE protocol fix, VM guide translation. -### Features +### คุณสมบัติ - **Czech Language** (#482): Full Czech (cs) i18n — 22 docs, 2606 UI strings, language switcher updates (@zen0bit) - **VM Deployment Guide**: Translated from Portuguese to English as the source document (@zen0bit) @@ -4309,7 +4427,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: 2 merged PRs, model aliases routing fix, log export, and issue triage. -### Features +### คุณสมบัติ - **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) @@ -4329,7 +4447,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Five community PRs — streaming call log fixes, Kiro compatibility, cache token analytics, Chinese translation, and configurable tool call IDs. -### ✨ Features +### คุณสมบัติ - **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) - **feat(providers)**: Per-model configurable 9-char tool call ID normalization (Mistral-style) — only models with the option enabled get truncated IDs (#470) @@ -4359,7 +4477,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Bailian Coding Plan provider with editable base URLs, plus community contributions for Alibaba Cloud and Kimi Coding. -### ✨ Features +### คุณสมบัติ - **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) - **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) @@ -4374,7 +4492,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Two new community-contributed providers (Alibaba Cloud Coding, Kimi Coding API-key) and Docker pino fix. -### ✨ Features +### คุณสมบัติ - **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) - **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) @@ -4399,7 +4517,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Codex responses subpath passthrough natively supported, Windows MITM crash fixed, and Combos agent schemas adjusted. -### ✨ Features +### คุณสมบัติ - **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) @@ -4439,7 +4557,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **fix(budget)**: "Save Limits" no longer returns 422 — `warningThreshold` is now correctly sent as fraction (0–1) instead of percentage (0–100) (#451) - **fix(combos)**: `` internal cache tag is now stripped before forwarding requests to providers, preventing cache session breaks (#454) -### ✨ Features +### คุณสมบัติ - **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) @@ -4495,7 +4613,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Search Tools dashboard, i18n fixes, Copilot limits, Serper validation fix. -### 🚀 Features +### คุณสมบัติ - **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) - New route: `/dashboard/search-tools` @@ -4595,7 +4713,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - DB migration: `request_type` column on `call_logs` for non-chat request tracking - Zod validation (`v1SearchSchema`), auth-gated, cost recorded via `recordCost()` -### 🔒 Security +### ความปลอดภัย - **deps**: Next.js 16.1.6 → 16.1.7 — fixes 6 CVEs: - **Critical**: CVE-2026-29057 (HTTP request smuggling via http-proxy) @@ -4725,7 +4843,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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**: New `request_detail_logs` table with 500-entry ring-buffer trigger, opt-in via settings toggle -### ✨ Features +### คุณสมบัติ - **feat(combo)**: System Message Override per Combo (#399 — `system_message` field replaces or injects system prompt before forwarding to provider) - **feat(combo)**: Tool Filter Regex per Combo (#399 — `tool_filter_regex` keeps only tools matching pattern; supports OpenAI + Anthropic formats) @@ -4740,7 +4858,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: SSE improvements, local provider_nodes extensions, proxy registry, Claude passthrough fixes. -### ✨ Features +### คุณสมบัติ - **feat(health)**: Background health check for local `provider_nodes` with exponential backoff (30s→300s) and `Promise.allSettled` to avoid blocking (#423, @Regis-RCR) - **feat(embeddings)**: Route `/v1/embeddings` to local `provider_nodes` — `buildDynamicEmbeddingProvider()` with hostname validation (#422, @Regis-RCR) @@ -4882,7 +5000,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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 - **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). -### ✨ Features +### คุณสมบัติ - **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) @@ -4912,7 +5030,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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) - **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) -### ✨ Features +### คุณสมบัติ - **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) - **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. @@ -4971,7 +5089,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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) - **fix(logs)**: Request log table is now readable in light mode — status badges, token counts, and combo tags use adaptive `dark:` color classes (#378) -### ✨ Features +### คุณสมบัติ - **feat(kiro)**: Kiro credit tracking added to usage fetcher — queries `getUserCredits` from AWS CodeWhisperer endpoint (#337) @@ -5372,7 +5490,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > **Major release** — Free Stack ecosystem, transcription playground overhaul, 44+ providers, comprehensive free tier documentation, and UI improvements across the board. -### ✨ Features +### คุณสมบัติ - **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. - **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. @@ -5383,7 +5501,7 @@ OmniRoute now automatically refreshes model lists for connected providers every ## [2.3.16] - 2026-03-13 -### 📖 Documentation +### เอกสาร - **README: 44+ Providers** — Updated all 3 occurrences of "36+ providers" to "44+" reflecting the actual codebase count (44 providers in providers.ts) - **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. @@ -5393,7 +5511,7 @@ OmniRoute now automatically refreshes model lists for connected providers every ## [2.3.15] - 2026-03-13 -### ✨ Features +### คุณสมบัติ - **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. - **i18n — autoCombo section**: Added 20 new translation keys for the Auto-Combo dashboard (`title`, `status`, `modePack`, `providerScores`, `factorTierPriority`, etc.) to all 30 language files. diff --git a/docs/i18n/tr/CHANGELOG.md b/docs/i18n/tr/CHANGELOG.md index ae3a94c8ed..5b86d20a6b 100644 --- a/docs/i18n/tr/CHANGELOG.md +++ b/docs/i18n/tr/CHANGELOG.md @@ -10,30 +10,148 @@ ### ✨ New Features -- **feat(antigravity):** integrate Antigravity provider with dynamic `maxOutputTokens` calculation (bumping to `thinkingBudget + 1`) and standard Cloud Code envelope payload sanitization (#2055, #2063) +- **feat(antigravity):** integrate Antigravity provider with dynamic `maxOutputTokens` calculation, identity fingerprinting overhaul, and Cloud Code envelope payload sanitization (#2055, #2063) - **feat(gemini-cli):** add custom projectId support for Gemini CLI transport (UI, DB, executor) (#1991) +- **feat(providers):** add KIE media provider support with dynamic polling, text models, and expanded video models catalog +- **feat(providers):** add Z.AI provider support with GLM quota handling and new quota labels +- **feat(providers):** add 9 new free AI providers — LLM7, Lepton, Kluster, UncloseAI, BazaarLink, Completions, Enally, FreeTheAi (#2096) +- **feat(providers):** batch delete provider connections via checkbox multi-select (#2094) +- **feat(cursor):** full OpenAI parity — tool calls, streaming, and session management (#2082) +- **feat(cli):** comprehensive CLI enhancement suite with 20+ new commands including `omniroute providers`, `omniroute combos`, `omniroute doctor` (#2074) +- **feat(cli):** add modular CLI setup and provider management commands (#2046) +- **feat(mcp):** add DeepSeek quota and limit monitoring feature (#2089) +- **feat(circuit-breaker):** classify 429 errors and apply per-kind cooldowns (#2116) +- **feat(multi):** manifest-aware tier routing — W1-W4 complete (#2014) +- **feat(combos):** add reset-aware routing strategy for quota-based providers +- **feat(combo):** add context_length input field to combo edit form (#2047) +- **feat(chat):** dynamic tool limit detection with proactive truncation (#2061) +- **feat(sse):** refresh Claude OAuth wire image to claude-cli/2.1.131 (#2011) +- **feat(github):** add `targetFormat: openai-responses` to all GitHub models (#2122) +- **feat(api):** allow configuration via API calls — open management routes to Bearer keys with manage scope (#2103) +- **feat(api):** update API bridge proxy timeout to 600,000ms (#2019) +- **feat(usage):** add service tier breakdown, codex fast service tier analytics, and account for fast tier +- **feat(chat):** add `STREAM_READINESS_TIMEOUT_MS` and integrate into chat handling +- **feat(combo):** add `fallbackDelayMs` to combo configuration and related settings +- **feat(chat):** enhance error handling for semaphore capacity with fallback logic +- **feat(qdrant):** embedding model discovery (#2086) +- **feat(auth):** per-session sticky routing for Codex (#1887) +- **feat(inworld):** enhance Inworld TTS support (#2123) ### 🐛 Bug Fixes +- **fix(pricing):** make `getPricingForModel` fully case-insensitive to ensure custom prices correctly reflect in new incoming requests cost calculations +- **fix(gemini):** prevent `functionDeclarations` from being dropped by the sanitizer when `googleSearch` tool is present (#2077) +- **fix(pollinations):** add `jsonMode: true` flag in the request transformation to enforce correct JSON structure from Pollinations API (#2109) +- **fix(docker):** update Dockerfile to copy `/docs` directory during build ensuring API catalog availability at runtime (#2083) +- **fix(docker):** include OpenAPI spec in runtime image (#2007) +- **fix(providers):** strip OpenAI-specific fields in Kiro translator to prevent 400 errors (#2037) +- **fix(kiro):** normalize tool-use payloads to prevent 400 errors from agents (#2104) +- **fix(kiro):** merge adjacent user history turns after role normalization (#2105) +- **fix(ui):** resolve text contrast issues for zero-config warning banner in light mode (#2050) +- **fix(core):** inject global system prompt correctly into downstream chat completions pipeline (#2080) +- **fix(core):** restore Claude Code adaptive thinking defaults and resolve audio transcription CORS regression +- **fix(routing):** add missing v1beta rewrites to next.config to resolve 404 on Gemini models endpoint (#2102) +- **fix(routing):** fix bare GPT-5.5 routing for Codex-only installations (#2054) +- **fix(routing):** add fuzzy auto-combo routing for `auto/*` model prefix (#2010) - **fix(cache):** optimize cache_control preservation logic and explicitly align tool schema with upstream Claude Code expectations - **fix(db):** preserve legacy SQLite database path on Windows to prevent data loss (#1973) +- **fix(db):** reduce hot-path persistence overhead (#2039) +- **fix(db):** resolve migration conflict by renumbering overlapping migration entries (#2041) - **fix(settings):** resolve model alias persistence double stringification preventing UI updates (#2018) - **fix(routing):** dynamically filter bare model auto-resolution by active provider connections to prevent dead-routing (#2029) - **fix(embeddings):** add Google Gemini embeddings compatibility via OpenAI-compatible endpoint mapping (#2006) +- **fix(sse):** prevent Claude OAuth multi-account correlation via metadata.user_id (#2053) +- **fix(sse):** prevent Claude Code identity cloak overrides and fix fallback resilience (#2053) +- **fix(sse):** classify hour quota errors as QUOTA_EXHAUSTED (#2119) +- **fix(sse):** fix CC-compatible streaming bridge (#2118) +- **fix(antigravity):** sanitize Claude Cloud Code payloads (#2090) +- **fix(antigravity):** add duplex half for streaming bodies +- **fix(antigravity):** align identity protocol and behavior with official AM +- **fix(chatgpt-web):** plumb proxy through to native tls-client (#2022, #2023) +- **fix(codex):** expose native model IDs in catalog (#2012) +- **fix(glm):** add dedicated coding transport (#2087) +- **fix(compression):** support Responses input and expand Spanish compression rules (#2028) +- **fix(catalog):** auto-calculate combo context_length from target model limits (#2030) +- **fix(api):** fix usage analytics and API key identity (#2008, #2092) +- **fix(api-key):** allow Unicode letters in API key name validation (#1996) +- **fix(auth):** allow bootstrap without password (#2048) +- **fix(proxy):** clean up proxy page redundancy and fix 1proxy sync empty body error (#2052) +- **fix(dashboard):** resolve Unknown plan display in Provider Limits +- **fix(usage):** add extensible CURRENCY_SYMBOLS mapping for deepseek currencies +- **fix(runtime):** harden timer handling and model pricing fallback +- **fix(i18n):** complete Simplified Chinese translations (#2115) +- **fix(mitm):** add Linux cert install and skip sudo password when root (#1999) +- **fix(mitm):** prevent stub from loading at runtime via bypass module - **fix:** remove Anthropic-Beta header from non-Anthropic providers to fix identity contamination (#1989) - **fix(cli):** resolve .env loading failure for global npm installations +- **fix(export):** exclude telemetry/usage-history tables from JSON config backups by default to prevent unbounded file growth (#2125) +- **fix:** Follow OpenAI specification, handle throttling in batch and fix UI (#2045) -### 🔒 Security +### Güvenlik +- **fix(security):** remediate CodeQL vulnerabilities (ReDoS, cryptographic bias, stack trace exposure, and weak password hashing) (#216, #215, #211, #208, #206, #210) - **fix(security):** remediate regex validation backtracking path in core compression cleanup (#1990) - **fix(core):** harden input handling and stabilization for prompt compression edge cases +### Belgeler + +- **docs:** add competitive marketing tables and SEO/AEO optimizations to README (#2091) +- **docs:** refresh providers, model catalogs, and docs for v3.8.0 (#2088) +- **docs:** update Claude MD and update GLM-CN max context to 200k (#2027) +- **docs(env):** add `GITLAB_DUO_OAUTH_CLIENT_ID` to `.env.example` (#2031) + ### 🧹 Chores & Maintenance - **chore(providers):** prune redundant local provider icon assets in favor of `@lobehub/icons` web fonts (#1992) +- **chore(providers):** remove deprecated models (#2033) +- **deps:** bump `fast-uri` from 3.1.0 to 3.1.2 (#2078) +- **deps:** bump `hono` from 4.12.14 to 4.12.18 (#2079) - **ci:** skip SonarCloud scan on main pushes to optimize CI time - **test:** stabilize cooldown abort coverage case in integration testing +### 🏆 v3.8.0 Community Contributors + +Thank you to all **38 community contributors** who made v3.8.0 possible! 🎉 + +| Contributor | PRs | Contributions | +| :--------------------------------------------------------- | :-: | :------------------------------------------------------------ | +| [@oyi77](https://github.com/oyi77) | 7 | #2010, #2014, #2041, #2052, #2061, #2074, #2091, #2094, #2096 | +| [@backryun](https://github.com/backryun) | 4 | #1992, #2033, #2088, #2123 | +| [@dhaern](https://github.com/dhaern) | 4 | #2028, #2039, #2087, #2090 | +| [@Tentoxa](https://github.com/Tentoxa) | 2 | #2011, #2053 | +| [@wauputr4](https://github.com/wauputr4) | 2 | #2009, #2046 | +| [@payne0420](https://github.com/payne0420) | 1 | #2082 | +| [@Tr0sT](https://github.com/Tr0sT) | 1 | #2012 | +| [@AveryanAlex](https://github.com/AveryanAlex) | 1 | #2008 | +| [@nickwizard](https://github.com/nickwizard) | 1 | #1991 | +| [@rodrigogbbr-stack](https://github.com/rodrigogbbr-stack) | 1 | #1996 | +| [@NekoMonci12](https://github.com/NekoMonci12) | 1 | #1999 | +| [@congvc-dev](https://github.com/congvc-dev) | 1 | #2004 | +| [@tatsster](https://github.com/tatsster) | 1 | #2007 | +| [@xssdem](https://github.com/xssdem) | 1 | #2023 | +| [@bypanghu](https://github.com/bypanghu) | 1 | #2027 | +| [@herjarsa](https://github.com/herjarsa) | 1 | #2030 | +| [@wucm667](https://github.com/wucm667) | 1 | #2031 | +| [@hartmark](https://github.com/hartmark) | 1 | #2045 | +| [@ddarkr](https://github.com/ddarkr) | 1 | #2047 | +| [@tces1](https://github.com/tces1) | 1 | #2048 | +| [@guanbear](https://github.com/guanbear) | 1 | #2054 | +| [@Gi99lin](https://github.com/Gi99lin) | 1 | #2055 | +| [@ivan-mezentsev](https://github.com/ivan-mezentsev) | 1 | #2063 | +| [@JxnLexn](https://github.com/JxnLexn) | 1 | #2019 | +| [@yoviarpauzi](https://github.com/yoviarpauzi) | 1 | #2092 | +| [@rafacpti23](https://github.com/rafacpti23) | 1 | #2086 | +| [@gleber](https://github.com/gleber) | 1 | #2103 | +| [@rilham97](https://github.com/rilham97) | 1 | #2104 | +| [@Gioxaa](https://github.com/Gioxaa) | 1 | #2105 | +| [@boa-z](https://github.com/boa-z) | 1 | #2115 | +| [@eleata](https://github.com/eleata) | 1 | #2116 | +| [@rdself](https://github.com/rdself) | 1 | #2118 | +| [@clousky2020](https://github.com/clousky2020) | 1 | #2119 | +| [@abhinavjnu](https://github.com/abhinavjnu) | 1 | #2122 | +| [@HoaPham98](https://github.com/HoaPham98) | 1 | #2089 | +| [@05dunski](https://github.com/05dunski) | 1 | #1978 (cherry-picked) | + ## [3.7.9] — 2026-05-03 ### ✨ New Features @@ -102,7 +220,7 @@ - **chore(provider):** Add reka models list (#1956 — thanks @backryun) - **chore(model):** Update new models, Delete Deprecated models (#1949 — thanks @backryun) -### 📝 Documentation +### Belgeler - **docs(compression):** document RTK+Caveman stacked savings ranges @@ -201,7 +319,7 @@ - **feat(db):** auto-restore probe-failed database on startup to prevent data loss after failed upgrades (#1810) - **feat(analytics):** add cost-based usage insights and activity streaks in the analytics dashboard -### 🔒 Security +### Güvenlik - **fix(security):** resolve ReDoS vulnerability in Codex executor regex patterns (#1797, #1789) @@ -354,7 +472,7 @@ We identified that **155 community PRs** across the entire project history (from - **feat(proxy):** implement bulk proxy import via pipe-delimited parser with update-or-create (upsert) logic and real-time preview table - **feat(pwa):** add fullscreen installable PWA with manifest, service worker, and cross-platform app icons (#1728) -### 🔒 Security +### Güvenlik - **security:** replace insecure `Math.random` with `crypto.getRandomValues` for fallback UUID generation to resolve CodeQL CWE-338 finding (#182) @@ -519,7 +637,7 @@ We identified that **155 community PRs** across the entire project history (from - **fix(transport):** Prevent memory bloat and database exhaustion from large, fragmented streaming responses. Implemented `ByteQueue` in `kiro.ts` for zero-copy binary accumulation, refactored `antigravity.ts` for incremental SSE parsing, and enforced a strict 512KB tiered truncation limit (`MAX_CALL_LOG_ARTIFACT_BYTES`) on stream request logs and call artifacts (#1647). - **chore(ci):** Update build environment dependencies — bump Node to `24.15.0`, `actions/checkout@v6`, `docker/build-push-action@v7`, pin `actions/setup-python` to major tag (#1646 — thanks @backryun). -### 📝 Documentation +### Belgeler - **docs(env):** Add `OMNIROUTE_ALLOW_PRIVATE_PROVIDER_URLS` to `.env.example` with documentation for LM Studio and other local provider use cases (#1623). @@ -669,7 +787,7 @@ We identified that **155 community PRs** across the entire project history (from - **test(next):** Align transpile package expectations for the Next.js standalone build. - **test(ci):** Fix CI-only test failures from environment differences — clear `INITIAL_PASSWORD` and `JWT_SECRET` in integration tests, handle `XDG_CONFIG_HOME` for guide-settings tests. -### 📚 Documentation +### Belgeler - **docs:** Update the root changelog with all release-branch changes through 2026-04-24, including PRs #1544, #1555, #1551, #1550, #1548, #1547, #1541, #1538, #1536, and #1527. - **docs:** Fix broken README and localized documentation links. (#1536) @@ -811,7 +929,7 @@ We identified that **155 community PRs** across the entire project history (from - **feat(providers):** Expand image provider registry with extended model support including SD3.5, FLUX, and DALL-E 3 HD configurations - **feat(combos):** Add new routing strategies and full i18n support for agent features section across 31 languages -### 🔒 Security +### Güvenlik - **security:** Resolve 18 GitHub CodeQL scan alerts including ReDoS, incomplete sanitization, and bad HTML filtering regexp patterns - **fix(auth):** Seal privilege escalation vector by enforcing JWT session checking exclusively on `/api/keys` management endpoints (#1353) @@ -1078,7 +1196,7 @@ We identified that **155 community PRs** across the entire project history (from - **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 - **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 -### 🔒 Security +### Güvenlik - **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 - **Auth Guard on Translator Save:** Added `isAuthenticated` guard to `/api/translator/save` for defense-in-depth consistency @@ -1483,7 +1601,7 @@ We identified that **155 community PRs** across the entire project history (from - **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). -### 📚 Documentation +### Belgeler - **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. - **Context Relay Delivery Notes:** Documented the current architecture, runtime flow, and Codex-focused scope in the feature docs, changelog, and agent guidance. @@ -1559,7 +1677,7 @@ We identified that **155 community PRs** across the entire project history (from ## [3.5.3] - 2026-04-07 -### Security +### Güvenlik - **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. - **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. @@ -1575,7 +1693,7 @@ We identified that **155 community PRs** across the entire project history (from - **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. -### Documentation +### Belgeler - **I18n Engine:** Synchronized and pushed deep Machine Translation updates across all 32 natively-supported languages (682 translation nodes aligned). @@ -1736,7 +1854,7 @@ We identified that **155 community PRs** across the entire project history (from ## [3.4.8] — 2026-04-03 -### Security +### Güvenlik - Fully remediated all outstanding Github Advanced Security (CodeQL) findings and Dependabot alerts. - Fixed insecure randomness vulnerabilities by migrating from `Math.random` to `crypto.randomUUID()`. @@ -1748,7 +1866,7 @@ We identified that **155 community PRs** across the entire project history (from ## [3.4.7] — 2026-04-03 -### Features +### Özellikler - Added `Cryptography` node to Monitoring and MCP health checks (#798) - Hardened model-catalog route permissions mapping (`/models`) (#781) @@ -1764,7 +1882,7 @@ We identified that **155 community PRs** across the entire project history (from - Fixed MCP standalone module-resolution (`ERR_MODULE_NOT_FOUND`) via `esbuild` (#936) - Fixed NVIDIA NIM routing credential resolution alias mismatch (#931) -### Security +### Güvenlik - Added safe strict input boundary protection against raw `shell: true` remote-code execution injections. @@ -2011,7 +2129,7 @@ We identified that **155 community PRs** across the entire project history (from ## [3.4.0] - 2026-03-31 -### 🚀 Features +### Özellikler - **Subscription Utilization Analytics:** Added quota snapshot time-series tracking, Provider Utilization and Combo Health tabs with recharts visualizations, and corresponding API endpoints (#847) - **SQLite Backup Control:** New `OMNIROUTE_DISABLE_AUTO_BACKUP` env flag to disable automatic SQLite backups (#846) @@ -2063,7 +2181,7 @@ We identified that **155 community PRs** across the entire project history (from ## [3.3.8] - 2026-03-30 -### 🚀 Features +### Özellikler - **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) - **Qoder Integration:** Native integration for Qoder AI natively replacing the legacy iFlow platform mappings (#660) @@ -2889,7 +3007,7 @@ We identified that **155 community PRs** across the entire project history (from - **NaN tokens in Claude Code / client responses (#617):** - `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 -### 🔒 Security +### Güvenlik - Updated `yaml` package to fix stack overflow vulnerability (GHSA-48c2-rrv3-qjmp) @@ -3565,7 +3683,7 @@ docker pull diegosouzapw/omniroute:3.0.0 - **SVG fallback**: `ProviderIcon` component updated with 4-tier strategy: Lobehub → PNG → SVG → Generic icon - **Agents fingerprinting**: Synced with CLI tools — added droid, openclaw, copilot, opencode to fingerprint list (14 total) -### 🔒 Security +### Güvenlik - **CVE fix**: Resolved dompurify XSS vulnerability (GHSA-v2wj-7wpq-c8vv) via npm overrides forcing `dompurify@^3.3.2` - `npm audit` now reports **0 vulnerabilities** @@ -3928,7 +4046,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **#510** — Windows: MSYS2/Git-Bash paths (`/c/Program Files/...`) are now normalized to `C:\Program Files\...` - **#492** — `omniroute` CLI now detects `mise`/`nvm` when `app/server.js` is missing and shows targeted fix -### 📖 Documentation +### Belgeler - **#513** — Docker password reset: `INITIAL_PASSWORD` env var workaround documented - **#520** — pnpm: `pnpm approve-builds better-sqlite3` documented @@ -4025,7 +4143,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **feat(executors/cloudflare-ai)**: New `CloudflareAIExecutor` — dynamic URL construction requires `accountId` in provider credentials - **feat(executors)**: Register `pollinations`, `pol`, `cloudflare-ai`, `cf` executor mappings -### 📝 Documentation +### Belgeler - **docs(readme)**: Expanded free combo stack to 11 providers ($0 forever) - **docs(readme)**: Added 4 new free provider sections (LongCat, Pollinations, Cloudflare AI, Scaleway) with model tables @@ -4177,7 +4295,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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). -### Features +### Özellikler - **"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. @@ -4205,7 +4323,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Merge PR #494 (MiniMax role fix), fix KIRO MITM dashboard, triage 8 issues. -### Features +### Özellikler - **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. - **roleNormalizer**: `normalizeDeveloperRole()` now accepts `preserveDeveloperRole` parameter with tri-state behavior (undefined=keep, true=keep, false=convert). @@ -4261,7 +4379,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Gemini CLI deprecation, VM guide i18n fix, dependabot security fix, provider schema expansion. -### Features +### Özellikler - **Gemini CLI Deprecation** (#462): Mark `gemini-cli` provider as deprecated with warning — Google restricts third-party OAuth usage from March 2026 - **Provider Schema** (#462): Expand Zod validation with `deprecated`, `deprecationReason`, `hasFree`, `freeNote`, `authHint`, `apiHint` optional fields @@ -4270,7 +4388,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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) -### Security +### Güvenlik - **deps**: Bump `flatted` 3.3.3 → 3.4.2 — fixes CWE-1321 prototype pollution (#484, @dependabot) @@ -4290,7 +4408,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Czech i18n, SSE protocol fix, VM guide translation. -### Features +### Özellikler - **Czech Language** (#482): Full Czech (cs) i18n — 22 docs, 2606 UI strings, language switcher updates (@zen0bit) - **VM Deployment Guide**: Translated from Portuguese to English as the source document (@zen0bit) @@ -4309,7 +4427,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: 2 merged PRs, model aliases routing fix, log export, and issue triage. -### Features +### Özellikler - **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) @@ -4329,7 +4447,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Five community PRs — streaming call log fixes, Kiro compatibility, cache token analytics, Chinese translation, and configurable tool call IDs. -### ✨ Features +### Özellikler - **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) - **feat(providers)**: Per-model configurable 9-char tool call ID normalization (Mistral-style) — only models with the option enabled get truncated IDs (#470) @@ -4359,7 +4477,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Bailian Coding Plan provider with editable base URLs, plus community contributions for Alibaba Cloud and Kimi Coding. -### ✨ Features +### Özellikler - **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) - **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) @@ -4374,7 +4492,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Two new community-contributed providers (Alibaba Cloud Coding, Kimi Coding API-key) and Docker pino fix. -### ✨ Features +### Özellikler - **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) - **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) @@ -4399,7 +4517,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Codex responses subpath passthrough natively supported, Windows MITM crash fixed, and Combos agent schemas adjusted. -### ✨ Features +### Özellikler - **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) @@ -4439,7 +4557,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **fix(budget)**: "Save Limits" no longer returns 422 — `warningThreshold` is now correctly sent as fraction (0–1) instead of percentage (0–100) (#451) - **fix(combos)**: `` internal cache tag is now stripped before forwarding requests to providers, preventing cache session breaks (#454) -### ✨ Features +### Özellikler - **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) @@ -4495,7 +4613,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Search Tools dashboard, i18n fixes, Copilot limits, Serper validation fix. -### 🚀 Features +### Özellikler - **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) - New route: `/dashboard/search-tools` @@ -4595,7 +4713,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - DB migration: `request_type` column on `call_logs` for non-chat request tracking - Zod validation (`v1SearchSchema`), auth-gated, cost recorded via `recordCost()` -### 🔒 Security +### Güvenlik - **deps**: Next.js 16.1.6 → 16.1.7 — fixes 6 CVEs: - **Critical**: CVE-2026-29057 (HTTP request smuggling via http-proxy) @@ -4725,7 +4843,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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**: New `request_detail_logs` table with 500-entry ring-buffer trigger, opt-in via settings toggle -### ✨ Features +### Özellikler - **feat(combo)**: System Message Override per Combo (#399 — `system_message` field replaces or injects system prompt before forwarding to provider) - **feat(combo)**: Tool Filter Regex per Combo (#399 — `tool_filter_regex` keeps only tools matching pattern; supports OpenAI + Anthropic formats) @@ -4740,7 +4858,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: SSE improvements, local provider_nodes extensions, proxy registry, Claude passthrough fixes. -### ✨ Features +### Özellikler - **feat(health)**: Background health check for local `provider_nodes` with exponential backoff (30s→300s) and `Promise.allSettled` to avoid blocking (#423, @Regis-RCR) - **feat(embeddings)**: Route `/v1/embeddings` to local `provider_nodes` — `buildDynamicEmbeddingProvider()` with hostname validation (#422, @Regis-RCR) @@ -4882,7 +5000,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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 - **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). -### ✨ Features +### Özellikler - **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) @@ -4912,7 +5030,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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) - **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) -### ✨ Features +### Özellikler - **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) - **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. @@ -4971,7 +5089,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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) - **fix(logs)**: Request log table is now readable in light mode — status badges, token counts, and combo tags use adaptive `dark:` color classes (#378) -### ✨ Features +### Özellikler - **feat(kiro)**: Kiro credit tracking added to usage fetcher — queries `getUserCredits` from AWS CodeWhisperer endpoint (#337) @@ -5372,7 +5490,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > **Major release** — Free Stack ecosystem, transcription playground overhaul, 44+ providers, comprehensive free tier documentation, and UI improvements across the board. -### ✨ Features +### Özellikler - **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. - **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. @@ -5383,7 +5501,7 @@ OmniRoute now automatically refreshes model lists for connected providers every ## [2.3.16] - 2026-03-13 -### 📖 Documentation +### Belgeler - **README: 44+ Providers** — Updated all 3 occurrences of "36+ providers" to "44+" reflecting the actual codebase count (44 providers in providers.ts) - **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. @@ -5393,7 +5511,7 @@ OmniRoute now automatically refreshes model lists for connected providers every ## [2.3.15] - 2026-03-13 -### ✨ Features +### Özellikler - **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. - **i18n — autoCombo section**: Added 20 new translation keys for the Auto-Combo dashboard (`title`, `status`, `modePack`, `providerScores`, `factorTierPriority`, etc.) to all 30 language files. diff --git a/docs/i18n/uk-UA/CHANGELOG.md b/docs/i18n/uk-UA/CHANGELOG.md index d1e855dacc..bd741fc54a 100644 --- a/docs/i18n/uk-UA/CHANGELOG.md +++ b/docs/i18n/uk-UA/CHANGELOG.md @@ -10,30 +10,148 @@ ### ✨ New Features -- **feat(antigravity):** integrate Antigravity provider with dynamic `maxOutputTokens` calculation (bumping to `thinkingBudget + 1`) and standard Cloud Code envelope payload sanitization (#2055, #2063) +- **feat(antigravity):** integrate Antigravity provider with dynamic `maxOutputTokens` calculation, identity fingerprinting overhaul, and Cloud Code envelope payload sanitization (#2055, #2063) - **feat(gemini-cli):** add custom projectId support for Gemini CLI transport (UI, DB, executor) (#1991) +- **feat(providers):** add KIE media provider support with dynamic polling, text models, and expanded video models catalog +- **feat(providers):** add Z.AI provider support with GLM quota handling and new quota labels +- **feat(providers):** add 9 new free AI providers — LLM7, Lepton, Kluster, UncloseAI, BazaarLink, Completions, Enally, FreeTheAi (#2096) +- **feat(providers):** batch delete provider connections via checkbox multi-select (#2094) +- **feat(cursor):** full OpenAI parity — tool calls, streaming, and session management (#2082) +- **feat(cli):** comprehensive CLI enhancement suite with 20+ new commands including `omniroute providers`, `omniroute combos`, `omniroute doctor` (#2074) +- **feat(cli):** add modular CLI setup and provider management commands (#2046) +- **feat(mcp):** add DeepSeek quota and limit monitoring feature (#2089) +- **feat(circuit-breaker):** classify 429 errors and apply per-kind cooldowns (#2116) +- **feat(multi):** manifest-aware tier routing — W1-W4 complete (#2014) +- **feat(combos):** add reset-aware routing strategy for quota-based providers +- **feat(combo):** add context_length input field to combo edit form (#2047) +- **feat(chat):** dynamic tool limit detection with proactive truncation (#2061) +- **feat(sse):** refresh Claude OAuth wire image to claude-cli/2.1.131 (#2011) +- **feat(github):** add `targetFormat: openai-responses` to all GitHub models (#2122) +- **feat(api):** allow configuration via API calls — open management routes to Bearer keys with manage scope (#2103) +- **feat(api):** update API bridge proxy timeout to 600,000ms (#2019) +- **feat(usage):** add service tier breakdown, codex fast service tier analytics, and account for fast tier +- **feat(chat):** add `STREAM_READINESS_TIMEOUT_MS` and integrate into chat handling +- **feat(combo):** add `fallbackDelayMs` to combo configuration and related settings +- **feat(chat):** enhance error handling for semaphore capacity with fallback logic +- **feat(qdrant):** embedding model discovery (#2086) +- **feat(auth):** per-session sticky routing for Codex (#1887) +- **feat(inworld):** enhance Inworld TTS support (#2123) ### 🐛 Bug Fixes +- **fix(pricing):** make `getPricingForModel` fully case-insensitive to ensure custom prices correctly reflect in new incoming requests cost calculations +- **fix(gemini):** prevent `functionDeclarations` from being dropped by the sanitizer when `googleSearch` tool is present (#2077) +- **fix(pollinations):** add `jsonMode: true` flag in the request transformation to enforce correct JSON structure from Pollinations API (#2109) +- **fix(docker):** update Dockerfile to copy `/docs` directory during build ensuring API catalog availability at runtime (#2083) +- **fix(docker):** include OpenAPI spec in runtime image (#2007) +- **fix(providers):** strip OpenAI-specific fields in Kiro translator to prevent 400 errors (#2037) +- **fix(kiro):** normalize tool-use payloads to prevent 400 errors from agents (#2104) +- **fix(kiro):** merge adjacent user history turns after role normalization (#2105) +- **fix(ui):** resolve text contrast issues for zero-config warning banner in light mode (#2050) +- **fix(core):** inject global system prompt correctly into downstream chat completions pipeline (#2080) +- **fix(core):** restore Claude Code adaptive thinking defaults and resolve audio transcription CORS regression +- **fix(routing):** add missing v1beta rewrites to next.config to resolve 404 on Gemini models endpoint (#2102) +- **fix(routing):** fix bare GPT-5.5 routing for Codex-only installations (#2054) +- **fix(routing):** add fuzzy auto-combo routing for `auto/*` model prefix (#2010) - **fix(cache):** optimize cache_control preservation logic and explicitly align tool schema with upstream Claude Code expectations - **fix(db):** preserve legacy SQLite database path on Windows to prevent data loss (#1973) +- **fix(db):** reduce hot-path persistence overhead (#2039) +- **fix(db):** resolve migration conflict by renumbering overlapping migration entries (#2041) - **fix(settings):** resolve model alias persistence double stringification preventing UI updates (#2018) - **fix(routing):** dynamically filter bare model auto-resolution by active provider connections to prevent dead-routing (#2029) - **fix(embeddings):** add Google Gemini embeddings compatibility via OpenAI-compatible endpoint mapping (#2006) +- **fix(sse):** prevent Claude OAuth multi-account correlation via metadata.user_id (#2053) +- **fix(sse):** prevent Claude Code identity cloak overrides and fix fallback resilience (#2053) +- **fix(sse):** classify hour quota errors as QUOTA_EXHAUSTED (#2119) +- **fix(sse):** fix CC-compatible streaming bridge (#2118) +- **fix(antigravity):** sanitize Claude Cloud Code payloads (#2090) +- **fix(antigravity):** add duplex half for streaming bodies +- **fix(antigravity):** align identity protocol and behavior with official AM +- **fix(chatgpt-web):** plumb proxy through to native tls-client (#2022, #2023) +- **fix(codex):** expose native model IDs in catalog (#2012) +- **fix(glm):** add dedicated coding transport (#2087) +- **fix(compression):** support Responses input and expand Spanish compression rules (#2028) +- **fix(catalog):** auto-calculate combo context_length from target model limits (#2030) +- **fix(api):** fix usage analytics and API key identity (#2008, #2092) +- **fix(api-key):** allow Unicode letters in API key name validation (#1996) +- **fix(auth):** allow bootstrap without password (#2048) +- **fix(proxy):** clean up proxy page redundancy and fix 1proxy sync empty body error (#2052) +- **fix(dashboard):** resolve Unknown plan display in Provider Limits +- **fix(usage):** add extensible CURRENCY_SYMBOLS mapping for deepseek currencies +- **fix(runtime):** harden timer handling and model pricing fallback +- **fix(i18n):** complete Simplified Chinese translations (#2115) +- **fix(mitm):** add Linux cert install and skip sudo password when root (#1999) +- **fix(mitm):** prevent stub from loading at runtime via bypass module - **fix:** remove Anthropic-Beta header from non-Anthropic providers to fix identity contamination (#1989) - **fix(cli):** resolve .env loading failure for global npm installations +- **fix(export):** exclude telemetry/usage-history tables from JSON config backups by default to prevent unbounded file growth (#2125) +- **fix:** Follow OpenAI specification, handle throttling in batch and fix UI (#2045) -### 🔒 Security +### Безпека +- **fix(security):** remediate CodeQL vulnerabilities (ReDoS, cryptographic bias, stack trace exposure, and weak password hashing) (#216, #215, #211, #208, #206, #210) - **fix(security):** remediate regex validation backtracking path in core compression cleanup (#1990) - **fix(core):** harden input handling and stabilization for prompt compression edge cases +### Документація + +- **docs:** add competitive marketing tables and SEO/AEO optimizations to README (#2091) +- **docs:** refresh providers, model catalogs, and docs for v3.8.0 (#2088) +- **docs:** update Claude MD and update GLM-CN max context to 200k (#2027) +- **docs(env):** add `GITLAB_DUO_OAUTH_CLIENT_ID` to `.env.example` (#2031) + ### 🧹 Chores & Maintenance - **chore(providers):** prune redundant local provider icon assets in favor of `@lobehub/icons` web fonts (#1992) +- **chore(providers):** remove deprecated models (#2033) +- **deps:** bump `fast-uri` from 3.1.0 to 3.1.2 (#2078) +- **deps:** bump `hono` from 4.12.14 to 4.12.18 (#2079) - **ci:** skip SonarCloud scan on main pushes to optimize CI time - **test:** stabilize cooldown abort coverage case in integration testing +### 🏆 v3.8.0 Community Contributors + +Thank you to all **38 community contributors** who made v3.8.0 possible! 🎉 + +| Contributor | PRs | Contributions | +| :--------------------------------------------------------- | :-: | :------------------------------------------------------------ | +| [@oyi77](https://github.com/oyi77) | 7 | #2010, #2014, #2041, #2052, #2061, #2074, #2091, #2094, #2096 | +| [@backryun](https://github.com/backryun) | 4 | #1992, #2033, #2088, #2123 | +| [@dhaern](https://github.com/dhaern) | 4 | #2028, #2039, #2087, #2090 | +| [@Tentoxa](https://github.com/Tentoxa) | 2 | #2011, #2053 | +| [@wauputr4](https://github.com/wauputr4) | 2 | #2009, #2046 | +| [@payne0420](https://github.com/payne0420) | 1 | #2082 | +| [@Tr0sT](https://github.com/Tr0sT) | 1 | #2012 | +| [@AveryanAlex](https://github.com/AveryanAlex) | 1 | #2008 | +| [@nickwizard](https://github.com/nickwizard) | 1 | #1991 | +| [@rodrigogbbr-stack](https://github.com/rodrigogbbr-stack) | 1 | #1996 | +| [@NekoMonci12](https://github.com/NekoMonci12) | 1 | #1999 | +| [@congvc-dev](https://github.com/congvc-dev) | 1 | #2004 | +| [@tatsster](https://github.com/tatsster) | 1 | #2007 | +| [@xssdem](https://github.com/xssdem) | 1 | #2023 | +| [@bypanghu](https://github.com/bypanghu) | 1 | #2027 | +| [@herjarsa](https://github.com/herjarsa) | 1 | #2030 | +| [@wucm667](https://github.com/wucm667) | 1 | #2031 | +| [@hartmark](https://github.com/hartmark) | 1 | #2045 | +| [@ddarkr](https://github.com/ddarkr) | 1 | #2047 | +| [@tces1](https://github.com/tces1) | 1 | #2048 | +| [@guanbear](https://github.com/guanbear) | 1 | #2054 | +| [@Gi99lin](https://github.com/Gi99lin) | 1 | #2055 | +| [@ivan-mezentsev](https://github.com/ivan-mezentsev) | 1 | #2063 | +| [@JxnLexn](https://github.com/JxnLexn) | 1 | #2019 | +| [@yoviarpauzi](https://github.com/yoviarpauzi) | 1 | #2092 | +| [@rafacpti23](https://github.com/rafacpti23) | 1 | #2086 | +| [@gleber](https://github.com/gleber) | 1 | #2103 | +| [@rilham97](https://github.com/rilham97) | 1 | #2104 | +| [@Gioxaa](https://github.com/Gioxaa) | 1 | #2105 | +| [@boa-z](https://github.com/boa-z) | 1 | #2115 | +| [@eleata](https://github.com/eleata) | 1 | #2116 | +| [@rdself](https://github.com/rdself) | 1 | #2118 | +| [@clousky2020](https://github.com/clousky2020) | 1 | #2119 | +| [@abhinavjnu](https://github.com/abhinavjnu) | 1 | #2122 | +| [@HoaPham98](https://github.com/HoaPham98) | 1 | #2089 | +| [@05dunski](https://github.com/05dunski) | 1 | #1978 (cherry-picked) | + ## [3.7.9] — 2026-05-03 ### ✨ New Features @@ -102,7 +220,7 @@ - **chore(provider):** Add reka models list (#1956 — thanks @backryun) - **chore(model):** Update new models, Delete Deprecated models (#1949 — thanks @backryun) -### 📝 Documentation +### Документація - **docs(compression):** document RTK+Caveman stacked savings ranges @@ -201,7 +319,7 @@ - **feat(db):** auto-restore probe-failed database on startup to prevent data loss after failed upgrades (#1810) - **feat(analytics):** add cost-based usage insights and activity streaks in the analytics dashboard -### 🔒 Security +### Безпека - **fix(security):** resolve ReDoS vulnerability in Codex executor regex patterns (#1797, #1789) @@ -354,7 +472,7 @@ We identified that **155 community PRs** across the entire project history (from - **feat(proxy):** implement bulk proxy import via pipe-delimited parser with update-or-create (upsert) logic and real-time preview table - **feat(pwa):** add fullscreen installable PWA with manifest, service worker, and cross-platform app icons (#1728) -### 🔒 Security +### Безпека - **security:** replace insecure `Math.random` with `crypto.getRandomValues` for fallback UUID generation to resolve CodeQL CWE-338 finding (#182) @@ -519,7 +637,7 @@ We identified that **155 community PRs** across the entire project history (from - **fix(transport):** Prevent memory bloat and database exhaustion from large, fragmented streaming responses. Implemented `ByteQueue` in `kiro.ts` for zero-copy binary accumulation, refactored `antigravity.ts` for incremental SSE parsing, and enforced a strict 512KB tiered truncation limit (`MAX_CALL_LOG_ARTIFACT_BYTES`) on stream request logs and call artifacts (#1647). - **chore(ci):** Update build environment dependencies — bump Node to `24.15.0`, `actions/checkout@v6`, `docker/build-push-action@v7`, pin `actions/setup-python` to major tag (#1646 — thanks @backryun). -### 📝 Documentation +### Документація - **docs(env):** Add `OMNIROUTE_ALLOW_PRIVATE_PROVIDER_URLS` to `.env.example` with documentation for LM Studio and other local provider use cases (#1623). @@ -669,7 +787,7 @@ We identified that **155 community PRs** across the entire project history (from - **test(next):** Align transpile package expectations for the Next.js standalone build. - **test(ci):** Fix CI-only test failures from environment differences — clear `INITIAL_PASSWORD` and `JWT_SECRET` in integration tests, handle `XDG_CONFIG_HOME` for guide-settings tests. -### 📚 Documentation +### Документація - **docs:** Update the root changelog with all release-branch changes through 2026-04-24, including PRs #1544, #1555, #1551, #1550, #1548, #1547, #1541, #1538, #1536, and #1527. - **docs:** Fix broken README and localized documentation links. (#1536) @@ -811,7 +929,7 @@ We identified that **155 community PRs** across the entire project history (from - **feat(providers):** Expand image provider registry with extended model support including SD3.5, FLUX, and DALL-E 3 HD configurations - **feat(combos):** Add new routing strategies and full i18n support for agent features section across 31 languages -### 🔒 Security +### Безпека - **security:** Resolve 18 GitHub CodeQL scan alerts including ReDoS, incomplete sanitization, and bad HTML filtering regexp patterns - **fix(auth):** Seal privilege escalation vector by enforcing JWT session checking exclusively on `/api/keys` management endpoints (#1353) @@ -1078,7 +1196,7 @@ We identified that **155 community PRs** across the entire project history (from - **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 - **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 -### 🔒 Security +### Безпека - **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 - **Auth Guard on Translator Save:** Added `isAuthenticated` guard to `/api/translator/save` for defense-in-depth consistency @@ -1483,7 +1601,7 @@ We identified that **155 community PRs** across the entire project history (from - **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). -### 📚 Documentation +### Документація - **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. - **Context Relay Delivery Notes:** Documented the current architecture, runtime flow, and Codex-focused scope in the feature docs, changelog, and agent guidance. @@ -1559,7 +1677,7 @@ We identified that **155 community PRs** across the entire project history (from ## [3.5.3] - 2026-04-07 -### Security +### Безпека - **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. - **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. @@ -1575,7 +1693,7 @@ We identified that **155 community PRs** across the entire project history (from - **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. -### Documentation +### Документація - **I18n Engine:** Synchronized and pushed deep Machine Translation updates across all 32 natively-supported languages (682 translation nodes aligned). @@ -1736,7 +1854,7 @@ We identified that **155 community PRs** across the entire project history (from ## [3.4.8] — 2026-04-03 -### Security +### Безпека - Fully remediated all outstanding Github Advanced Security (CodeQL) findings and Dependabot alerts. - Fixed insecure randomness vulnerabilities by migrating from `Math.random` to `crypto.randomUUID()`. @@ -1748,7 +1866,7 @@ We identified that **155 community PRs** across the entire project history (from ## [3.4.7] — 2026-04-03 -### Features +### Можливості - Added `Cryptography` node to Monitoring and MCP health checks (#798) - Hardened model-catalog route permissions mapping (`/models`) (#781) @@ -1764,7 +1882,7 @@ We identified that **155 community PRs** across the entire project history (from - Fixed MCP standalone module-resolution (`ERR_MODULE_NOT_FOUND`) via `esbuild` (#936) - Fixed NVIDIA NIM routing credential resolution alias mismatch (#931) -### Security +### Безпека - Added safe strict input boundary protection against raw `shell: true` remote-code execution injections. @@ -2011,7 +2129,7 @@ We identified that **155 community PRs** across the entire project history (from ## [3.4.0] - 2026-03-31 -### 🚀 Features +### Можливості - **Subscription Utilization Analytics:** Added quota snapshot time-series tracking, Provider Utilization and Combo Health tabs with recharts visualizations, and corresponding API endpoints (#847) - **SQLite Backup Control:** New `OMNIROUTE_DISABLE_AUTO_BACKUP` env flag to disable automatic SQLite backups (#846) @@ -2063,7 +2181,7 @@ We identified that **155 community PRs** across the entire project history (from ## [3.3.8] - 2026-03-30 -### 🚀 Features +### Можливості - **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) - **Qoder Integration:** Native integration for Qoder AI natively replacing the legacy iFlow platform mappings (#660) @@ -2889,7 +3007,7 @@ We identified that **155 community PRs** across the entire project history (from - **NaN tokens in Claude Code / client responses (#617):** - `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 -### 🔒 Security +### Безпека - Updated `yaml` package to fix stack overflow vulnerability (GHSA-48c2-rrv3-qjmp) @@ -3565,7 +3683,7 @@ docker pull diegosouzapw/omniroute:3.0.0 - **SVG fallback**: `ProviderIcon` component updated with 4-tier strategy: Lobehub → PNG → SVG → Generic icon - **Agents fingerprinting**: Synced with CLI tools — added droid, openclaw, copilot, opencode to fingerprint list (14 total) -### 🔒 Security +### Безпека - **CVE fix**: Resolved dompurify XSS vulnerability (GHSA-v2wj-7wpq-c8vv) via npm overrides forcing `dompurify@^3.3.2` - `npm audit` now reports **0 vulnerabilities** @@ -3928,7 +4046,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **#510** — Windows: MSYS2/Git-Bash paths (`/c/Program Files/...`) are now normalized to `C:\Program Files\...` - **#492** — `omniroute` CLI now detects `mise`/`nvm` when `app/server.js` is missing and shows targeted fix -### 📖 Documentation +### Документація - **#513** — Docker password reset: `INITIAL_PASSWORD` env var workaround documented - **#520** — pnpm: `pnpm approve-builds better-sqlite3` documented @@ -4025,7 +4143,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **feat(executors/cloudflare-ai)**: New `CloudflareAIExecutor` — dynamic URL construction requires `accountId` in provider credentials - **feat(executors)**: Register `pollinations`, `pol`, `cloudflare-ai`, `cf` executor mappings -### 📝 Documentation +### Документація - **docs(readme)**: Expanded free combo stack to 11 providers ($0 forever) - **docs(readme)**: Added 4 new free provider sections (LongCat, Pollinations, Cloudflare AI, Scaleway) with model tables @@ -4177,7 +4295,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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). -### Features +### Можливості - **"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. @@ -4205,7 +4323,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Merge PR #494 (MiniMax role fix), fix KIRO MITM dashboard, triage 8 issues. -### Features +### Можливості - **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. - **roleNormalizer**: `normalizeDeveloperRole()` now accepts `preserveDeveloperRole` parameter with tri-state behavior (undefined=keep, true=keep, false=convert). @@ -4261,7 +4379,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Gemini CLI deprecation, VM guide i18n fix, dependabot security fix, provider schema expansion. -### Features +### Можливості - **Gemini CLI Deprecation** (#462): Mark `gemini-cli` provider as deprecated with warning — Google restricts third-party OAuth usage from March 2026 - **Provider Schema** (#462): Expand Zod validation with `deprecated`, `deprecationReason`, `hasFree`, `freeNote`, `authHint`, `apiHint` optional fields @@ -4270,7 +4388,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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) -### Security +### Безпека - **deps**: Bump `flatted` 3.3.3 → 3.4.2 — fixes CWE-1321 prototype pollution (#484, @dependabot) @@ -4290,7 +4408,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Czech i18n, SSE protocol fix, VM guide translation. -### Features +### Можливості - **Czech Language** (#482): Full Czech (cs) i18n — 22 docs, 2606 UI strings, language switcher updates (@zen0bit) - **VM Deployment Guide**: Translated from Portuguese to English as the source document (@zen0bit) @@ -4309,7 +4427,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: 2 merged PRs, model aliases routing fix, log export, and issue triage. -### Features +### Можливості - **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) @@ -4329,7 +4447,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Five community PRs — streaming call log fixes, Kiro compatibility, cache token analytics, Chinese translation, and configurable tool call IDs. -### ✨ Features +### Можливості - **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) - **feat(providers)**: Per-model configurable 9-char tool call ID normalization (Mistral-style) — only models with the option enabled get truncated IDs (#470) @@ -4359,7 +4477,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Bailian Coding Plan provider with editable base URLs, plus community contributions for Alibaba Cloud and Kimi Coding. -### ✨ Features +### Можливості - **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) - **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) @@ -4374,7 +4492,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Two new community-contributed providers (Alibaba Cloud Coding, Kimi Coding API-key) and Docker pino fix. -### ✨ Features +### Можливості - **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) - **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) @@ -4399,7 +4517,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Codex responses subpath passthrough natively supported, Windows MITM crash fixed, and Combos agent schemas adjusted. -### ✨ Features +### Можливості - **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) @@ -4439,7 +4557,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **fix(budget)**: "Save Limits" no longer returns 422 — `warningThreshold` is now correctly sent as fraction (0–1) instead of percentage (0–100) (#451) - **fix(combos)**: `` internal cache tag is now stripped before forwarding requests to providers, preventing cache session breaks (#454) -### ✨ Features +### Можливості - **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) @@ -4495,7 +4613,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Search Tools dashboard, i18n fixes, Copilot limits, Serper validation fix. -### 🚀 Features +### Можливості - **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) - New route: `/dashboard/search-tools` @@ -4595,7 +4713,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - DB migration: `request_type` column on `call_logs` for non-chat request tracking - Zod validation (`v1SearchSchema`), auth-gated, cost recorded via `recordCost()` -### 🔒 Security +### Безпека - **deps**: Next.js 16.1.6 → 16.1.7 — fixes 6 CVEs: - **Critical**: CVE-2026-29057 (HTTP request smuggling via http-proxy) @@ -4725,7 +4843,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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**: New `request_detail_logs` table with 500-entry ring-buffer trigger, opt-in via settings toggle -### ✨ Features +### Можливості - **feat(combo)**: System Message Override per Combo (#399 — `system_message` field replaces or injects system prompt before forwarding to provider) - **feat(combo)**: Tool Filter Regex per Combo (#399 — `tool_filter_regex` keeps only tools matching pattern; supports OpenAI + Anthropic formats) @@ -4740,7 +4858,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: SSE improvements, local provider_nodes extensions, proxy registry, Claude passthrough fixes. -### ✨ Features +### Можливості - **feat(health)**: Background health check for local `provider_nodes` with exponential backoff (30s→300s) and `Promise.allSettled` to avoid blocking (#423, @Regis-RCR) - **feat(embeddings)**: Route `/v1/embeddings` to local `provider_nodes` — `buildDynamicEmbeddingProvider()` with hostname validation (#422, @Regis-RCR) @@ -4882,7 +5000,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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 - **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). -### ✨ Features +### Можливості - **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) @@ -4912,7 +5030,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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) - **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) -### ✨ Features +### Можливості - **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) - **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. @@ -4971,7 +5089,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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) - **fix(logs)**: Request log table is now readable in light mode — status badges, token counts, and combo tags use adaptive `dark:` color classes (#378) -### ✨ Features +### Можливості - **feat(kiro)**: Kiro credit tracking added to usage fetcher — queries `getUserCredits` from AWS CodeWhisperer endpoint (#337) @@ -5372,7 +5490,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > **Major release** — Free Stack ecosystem, transcription playground overhaul, 44+ providers, comprehensive free tier documentation, and UI improvements across the board. -### ✨ Features +### Можливості - **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. - **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. @@ -5383,7 +5501,7 @@ OmniRoute now automatically refreshes model lists for connected providers every ## [2.3.16] - 2026-03-13 -### 📖 Documentation +### Документація - **README: 44+ Providers** — Updated all 3 occurrences of "36+ providers" to "44+" reflecting the actual codebase count (44 providers in providers.ts) - **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. @@ -5393,7 +5511,7 @@ OmniRoute now automatically refreshes model lists for connected providers every ## [2.3.15] - 2026-03-13 -### ✨ Features +### Можливості - **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. - **i18n — autoCombo section**: Added 20 new translation keys for the Auto-Combo dashboard (`title`, `status`, `modePack`, `providerScores`, `factorTierPriority`, etc.) to all 30 language files. diff --git a/docs/i18n/ur/CHANGELOG.md b/docs/i18n/ur/CHANGELOG.md index 51d28b576f..814e6bd3ba 100644 --- a/docs/i18n/ur/CHANGELOG.md +++ b/docs/i18n/ur/CHANGELOG.md @@ -10,30 +10,148 @@ ### ✨ New Features -- **feat(antigravity):** integrate Antigravity provider with dynamic `maxOutputTokens` calculation (bumping to `thinkingBudget + 1`) and standard Cloud Code envelope payload sanitization (#2055, #2063) +- **feat(antigravity):** integrate Antigravity provider with dynamic `maxOutputTokens` calculation, identity fingerprinting overhaul, and Cloud Code envelope payload sanitization (#2055, #2063) - **feat(gemini-cli):** add custom projectId support for Gemini CLI transport (UI, DB, executor) (#1991) +- **feat(providers):** add KIE media provider support with dynamic polling, text models, and expanded video models catalog +- **feat(providers):** add Z.AI provider support with GLM quota handling and new quota labels +- **feat(providers):** add 9 new free AI providers — LLM7, Lepton, Kluster, UncloseAI, BazaarLink, Completions, Enally, FreeTheAi (#2096) +- **feat(providers):** batch delete provider connections via checkbox multi-select (#2094) +- **feat(cursor):** full OpenAI parity — tool calls, streaming, and session management (#2082) +- **feat(cli):** comprehensive CLI enhancement suite with 20+ new commands including `omniroute providers`, `omniroute combos`, `omniroute doctor` (#2074) +- **feat(cli):** add modular CLI setup and provider management commands (#2046) +- **feat(mcp):** add DeepSeek quota and limit monitoring feature (#2089) +- **feat(circuit-breaker):** classify 429 errors and apply per-kind cooldowns (#2116) +- **feat(multi):** manifest-aware tier routing — W1-W4 complete (#2014) +- **feat(combos):** add reset-aware routing strategy for quota-based providers +- **feat(combo):** add context_length input field to combo edit form (#2047) +- **feat(chat):** dynamic tool limit detection with proactive truncation (#2061) +- **feat(sse):** refresh Claude OAuth wire image to claude-cli/2.1.131 (#2011) +- **feat(github):** add `targetFormat: openai-responses` to all GitHub models (#2122) +- **feat(api):** allow configuration via API calls — open management routes to Bearer keys with manage scope (#2103) +- **feat(api):** update API bridge proxy timeout to 600,000ms (#2019) +- **feat(usage):** add service tier breakdown, codex fast service tier analytics, and account for fast tier +- **feat(chat):** add `STREAM_READINESS_TIMEOUT_MS` and integrate into chat handling +- **feat(combo):** add `fallbackDelayMs` to combo configuration and related settings +- **feat(chat):** enhance error handling for semaphore capacity with fallback logic +- **feat(qdrant):** embedding model discovery (#2086) +- **feat(auth):** per-session sticky routing for Codex (#1887) +- **feat(inworld):** enhance Inworld TTS support (#2123) ### 🐛 Bug Fixes +- **fix(pricing):** make `getPricingForModel` fully case-insensitive to ensure custom prices correctly reflect in new incoming requests cost calculations +- **fix(gemini):** prevent `functionDeclarations` from being dropped by the sanitizer when `googleSearch` tool is present (#2077) +- **fix(pollinations):** add `jsonMode: true` flag in the request transformation to enforce correct JSON structure from Pollinations API (#2109) +- **fix(docker):** update Dockerfile to copy `/docs` directory during build ensuring API catalog availability at runtime (#2083) +- **fix(docker):** include OpenAPI spec in runtime image (#2007) +- **fix(providers):** strip OpenAI-specific fields in Kiro translator to prevent 400 errors (#2037) +- **fix(kiro):** normalize tool-use payloads to prevent 400 errors from agents (#2104) +- **fix(kiro):** merge adjacent user history turns after role normalization (#2105) +- **fix(ui):** resolve text contrast issues for zero-config warning banner in light mode (#2050) +- **fix(core):** inject global system prompt correctly into downstream chat completions pipeline (#2080) +- **fix(core):** restore Claude Code adaptive thinking defaults and resolve audio transcription CORS regression +- **fix(routing):** add missing v1beta rewrites to next.config to resolve 404 on Gemini models endpoint (#2102) +- **fix(routing):** fix bare GPT-5.5 routing for Codex-only installations (#2054) +- **fix(routing):** add fuzzy auto-combo routing for `auto/*` model prefix (#2010) - **fix(cache):** optimize cache_control preservation logic and explicitly align tool schema with upstream Claude Code expectations - **fix(db):** preserve legacy SQLite database path on Windows to prevent data loss (#1973) +- **fix(db):** reduce hot-path persistence overhead (#2039) +- **fix(db):** resolve migration conflict by renumbering overlapping migration entries (#2041) - **fix(settings):** resolve model alias persistence double stringification preventing UI updates (#2018) - **fix(routing):** dynamically filter bare model auto-resolution by active provider connections to prevent dead-routing (#2029) - **fix(embeddings):** add Google Gemini embeddings compatibility via OpenAI-compatible endpoint mapping (#2006) +- **fix(sse):** prevent Claude OAuth multi-account correlation via metadata.user_id (#2053) +- **fix(sse):** prevent Claude Code identity cloak overrides and fix fallback resilience (#2053) +- **fix(sse):** classify hour quota errors as QUOTA_EXHAUSTED (#2119) +- **fix(sse):** fix CC-compatible streaming bridge (#2118) +- **fix(antigravity):** sanitize Claude Cloud Code payloads (#2090) +- **fix(antigravity):** add duplex half for streaming bodies +- **fix(antigravity):** align identity protocol and behavior with official AM +- **fix(chatgpt-web):** plumb proxy through to native tls-client (#2022, #2023) +- **fix(codex):** expose native model IDs in catalog (#2012) +- **fix(glm):** add dedicated coding transport (#2087) +- **fix(compression):** support Responses input and expand Spanish compression rules (#2028) +- **fix(catalog):** auto-calculate combo context_length from target model limits (#2030) +- **fix(api):** fix usage analytics and API key identity (#2008, #2092) +- **fix(api-key):** allow Unicode letters in API key name validation (#1996) +- **fix(auth):** allow bootstrap without password (#2048) +- **fix(proxy):** clean up proxy page redundancy and fix 1proxy sync empty body error (#2052) +- **fix(dashboard):** resolve Unknown plan display in Provider Limits +- **fix(usage):** add extensible CURRENCY_SYMBOLS mapping for deepseek currencies +- **fix(runtime):** harden timer handling and model pricing fallback +- **fix(i18n):** complete Simplified Chinese translations (#2115) +- **fix(mitm):** add Linux cert install and skip sudo password when root (#1999) +- **fix(mitm):** prevent stub from loading at runtime via bypass module - **fix:** remove Anthropic-Beta header from non-Anthropic providers to fix identity contamination (#1989) - **fix(cli):** resolve .env loading failure for global npm installations +- **fix(export):** exclude telemetry/usage-history tables from JSON config backups by default to prevent unbounded file growth (#2125) +- **fix:** Follow OpenAI specification, handle throttling in batch and fix UI (#2045) -### 🔒 Security +### Seguridad +- **fix(security):** remediate CodeQL vulnerabilities (ReDoS, cryptographic bias, stack trace exposure, and weak password hashing) (#216, #215, #211, #208, #206, #210) - **fix(security):** remediate regex validation backtracking path in core compression cleanup (#1990) - **fix(core):** harden input handling and stabilization for prompt compression edge cases +### Documentación + +- **docs:** add competitive marketing tables and SEO/AEO optimizations to README (#2091) +- **docs:** refresh providers, model catalogs, and docs for v3.8.0 (#2088) +- **docs:** update Claude MD and update GLM-CN max context to 200k (#2027) +- **docs(env):** add `GITLAB_DUO_OAUTH_CLIENT_ID` to `.env.example` (#2031) + ### 🧹 Chores & Maintenance - **chore(providers):** prune redundant local provider icon assets in favor of `@lobehub/icons` web fonts (#1992) +- **chore(providers):** remove deprecated models (#2033) +- **deps:** bump `fast-uri` from 3.1.0 to 3.1.2 (#2078) +- **deps:** bump `hono` from 4.12.14 to 4.12.18 (#2079) - **ci:** skip SonarCloud scan on main pushes to optimize CI time - **test:** stabilize cooldown abort coverage case in integration testing +### 🏆 v3.8.0 Community Contributors + +Thank you to all **38 community contributors** who made v3.8.0 possible! 🎉 + +| Contributor | PRs | Contributions | +| :--------------------------------------------------------- | :-: | :------------------------------------------------------------ | +| [@oyi77](https://github.com/oyi77) | 7 | #2010, #2014, #2041, #2052, #2061, #2074, #2091, #2094, #2096 | +| [@backryun](https://github.com/backryun) | 4 | #1992, #2033, #2088, #2123 | +| [@dhaern](https://github.com/dhaern) | 4 | #2028, #2039, #2087, #2090 | +| [@Tentoxa](https://github.com/Tentoxa) | 2 | #2011, #2053 | +| [@wauputr4](https://github.com/wauputr4) | 2 | #2009, #2046 | +| [@payne0420](https://github.com/payne0420) | 1 | #2082 | +| [@Tr0sT](https://github.com/Tr0sT) | 1 | #2012 | +| [@AveryanAlex](https://github.com/AveryanAlex) | 1 | #2008 | +| [@nickwizard](https://github.com/nickwizard) | 1 | #1991 | +| [@rodrigogbbr-stack](https://github.com/rodrigogbbr-stack) | 1 | #1996 | +| [@NekoMonci12](https://github.com/NekoMonci12) | 1 | #1999 | +| [@congvc-dev](https://github.com/congvc-dev) | 1 | #2004 | +| [@tatsster](https://github.com/tatsster) | 1 | #2007 | +| [@xssdem](https://github.com/xssdem) | 1 | #2023 | +| [@bypanghu](https://github.com/bypanghu) | 1 | #2027 | +| [@herjarsa](https://github.com/herjarsa) | 1 | #2030 | +| [@wucm667](https://github.com/wucm667) | 1 | #2031 | +| [@hartmark](https://github.com/hartmark) | 1 | #2045 | +| [@ddarkr](https://github.com/ddarkr) | 1 | #2047 | +| [@tces1](https://github.com/tces1) | 1 | #2048 | +| [@guanbear](https://github.com/guanbear) | 1 | #2054 | +| [@Gi99lin](https://github.com/Gi99lin) | 1 | #2055 | +| [@ivan-mezentsev](https://github.com/ivan-mezentsev) | 1 | #2063 | +| [@JxnLexn](https://github.com/JxnLexn) | 1 | #2019 | +| [@yoviarpauzi](https://github.com/yoviarpauzi) | 1 | #2092 | +| [@rafacpti23](https://github.com/rafacpti23) | 1 | #2086 | +| [@gleber](https://github.com/gleber) | 1 | #2103 | +| [@rilham97](https://github.com/rilham97) | 1 | #2104 | +| [@Gioxaa](https://github.com/Gioxaa) | 1 | #2105 | +| [@boa-z](https://github.com/boa-z) | 1 | #2115 | +| [@eleata](https://github.com/eleata) | 1 | #2116 | +| [@rdself](https://github.com/rdself) | 1 | #2118 | +| [@clousky2020](https://github.com/clousky2020) | 1 | #2119 | +| [@abhinavjnu](https://github.com/abhinavjnu) | 1 | #2122 | +| [@HoaPham98](https://github.com/HoaPham98) | 1 | #2089 | +| [@05dunski](https://github.com/05dunski) | 1 | #1978 (cherry-picked) | + ## [3.7.9] — 2026-05-03 ### ✨ New Features @@ -102,7 +220,7 @@ - **chore(provider):** Add reka models list (#1956 — thanks @backryun) - **chore(model):** Update new models, Delete Deprecated models (#1949 — thanks @backryun) -### 📝 Documentation +### Documentación - **docs(compression):** document RTK+Caveman stacked savings ranges @@ -201,7 +319,7 @@ - **feat(db):** auto-restore probe-failed database on startup to prevent data loss after failed upgrades (#1810) - **feat(analytics):** add cost-based usage insights and activity streaks in the analytics dashboard -### 🔒 Security +### Seguridad - **fix(security):** resolve ReDoS vulnerability in Codex executor regex patterns (#1797, #1789) @@ -354,7 +472,7 @@ We identified that **155 community PRs** across the entire project history (from - **feat(proxy):** implement bulk proxy import via pipe-delimited parser with update-or-create (upsert) logic and real-time preview table - **feat(pwa):** add fullscreen installable PWA with manifest, service worker, and cross-platform app icons (#1728) -### 🔒 Security +### Seguridad - **security:** replace insecure `Math.random` with `crypto.getRandomValues` for fallback UUID generation to resolve CodeQL CWE-338 finding (#182) @@ -519,7 +637,7 @@ We identified that **155 community PRs** across the entire project history (from - **fix(transport):** Prevent memory bloat and database exhaustion from large, fragmented streaming responses. Implemented `ByteQueue` in `kiro.ts` for zero-copy binary accumulation, refactored `antigravity.ts` for incremental SSE parsing, and enforced a strict 512KB tiered truncation limit (`MAX_CALL_LOG_ARTIFACT_BYTES`) on stream request logs and call artifacts (#1647). - **chore(ci):** Update build environment dependencies — bump Node to `24.15.0`, `actions/checkout@v6`, `docker/build-push-action@v7`, pin `actions/setup-python` to major tag (#1646 — thanks @backryun). -### 📝 Documentation +### Documentación - **docs(env):** Add `OMNIROUTE_ALLOW_PRIVATE_PROVIDER_URLS` to `.env.example` with documentation for LM Studio and other local provider use cases (#1623). @@ -669,7 +787,7 @@ We identified that **155 community PRs** across the entire project history (from - **test(next):** Align transpile package expectations for the Next.js standalone build. - **test(ci):** Fix CI-only test failures from environment differences — clear `INITIAL_PASSWORD` and `JWT_SECRET` in integration tests, handle `XDG_CONFIG_HOME` for guide-settings tests. -### 📚 Documentation +### Documentación - **docs:** Update the root changelog with all release-branch changes through 2026-04-24, including PRs #1544, #1555, #1551, #1550, #1548, #1547, #1541, #1538, #1536, and #1527. - **docs:** Fix broken README and localized documentation links. (#1536) @@ -811,7 +929,7 @@ We identified that **155 community PRs** across the entire project history (from - **feat(providers):** Expand image provider registry with extended model support including SD3.5, FLUX, and DALL-E 3 HD configurations - **feat(combos):** Add new routing strategies and full i18n support for agent features section across 31 languages -### 🔒 Security +### Seguridad - **security:** Resolve 18 GitHub CodeQL scan alerts including ReDoS, incomplete sanitization, and bad HTML filtering regexp patterns - **fix(auth):** Seal privilege escalation vector by enforcing JWT session checking exclusively on `/api/keys` management endpoints (#1353) @@ -1078,7 +1196,7 @@ We identified that **155 community PRs** across the entire project history (from - **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 - **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 -### 🔒 Security +### Seguridad - **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 - **Auth Guard on Translator Save:** Added `isAuthenticated` guard to `/api/translator/save` for defense-in-depth consistency @@ -1483,7 +1601,7 @@ We identified that **155 community PRs** across the entire project history (from - **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). -### 📚 Documentation +### Documentació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. - **Context Relay Delivery Notes:** Documented the current architecture, runtime flow, and Codex-focused scope in the feature docs, changelog, and agent guidance. @@ -1559,7 +1677,7 @@ We identified that **155 community PRs** across the entire project history (from ## [3.5.3] - 2026-04-07 -### Security +### Seguridad - **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. - **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. @@ -1575,7 +1693,7 @@ We identified that **155 community PRs** across the entire project history (from - **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. -### Documentation +### Documentación - **I18n Engine:** Synchronized and pushed deep Machine Translation updates across all 32 natively-supported languages (682 translation nodes aligned). @@ -1736,7 +1854,7 @@ We identified that **155 community PRs** across the entire project history (from ## [3.4.8] — 2026-04-03 -### Security +### Seguridad - Fully remediated all outstanding Github Advanced Security (CodeQL) findings and Dependabot alerts. - Fixed insecure randomness vulnerabilities by migrating from `Math.random` to `crypto.randomUUID()`. @@ -1748,7 +1866,7 @@ We identified that **155 community PRs** across the entire project history (from ## [3.4.7] — 2026-04-03 -### Features +### Funcionalidades - Added `Cryptography` node to Monitoring and MCP health checks (#798) - Hardened model-catalog route permissions mapping (`/models`) (#781) @@ -1764,7 +1882,7 @@ We identified that **155 community PRs** across the entire project history (from - Fixed MCP standalone module-resolution (`ERR_MODULE_NOT_FOUND`) via `esbuild` (#936) - Fixed NVIDIA NIM routing credential resolution alias mismatch (#931) -### Security +### Seguridad - Added safe strict input boundary protection against raw `shell: true` remote-code execution injections. @@ -2011,7 +2129,7 @@ We identified that **155 community PRs** across the entire project history (from ## [3.4.0] - 2026-03-31 -### 🚀 Features +### Funcionalidades - **Subscription Utilization Analytics:** Added quota snapshot time-series tracking, Provider Utilization and Combo Health tabs with recharts visualizations, and corresponding API endpoints (#847) - **SQLite Backup Control:** New `OMNIROUTE_DISABLE_AUTO_BACKUP` env flag to disable automatic SQLite backups (#846) @@ -2063,7 +2181,7 @@ We identified that **155 community PRs** across the entire project history (from ## [3.3.8] - 2026-03-30 -### 🚀 Features +### Funcionalidades - **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) - **Qoder Integration:** Native integration for Qoder AI natively replacing the legacy iFlow platform mappings (#660) @@ -2889,7 +3007,7 @@ We identified that **155 community PRs** across the entire project history (from - **NaN tokens in Claude Code / client responses (#617):** - `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 -### 🔒 Security +### Seguridad - Updated `yaml` package to fix stack overflow vulnerability (GHSA-48c2-rrv3-qjmp) @@ -3565,7 +3683,7 @@ docker pull diegosouzapw/omniroute:3.0.0 - **SVG fallback**: `ProviderIcon` component updated with 4-tier strategy: Lobehub → PNG → SVG → Generic icon - **Agents fingerprinting**: Synced with CLI tools — added droid, openclaw, copilot, opencode to fingerprint list (14 total) -### 🔒 Security +### Seguridad - **CVE fix**: Resolved dompurify XSS vulnerability (GHSA-v2wj-7wpq-c8vv) via npm overrides forcing `dompurify@^3.3.2` - `npm audit` now reports **0 vulnerabilities** @@ -3928,7 +4046,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **#510** — Windows: MSYS2/Git-Bash paths (`/c/Program Files/...`) are now normalized to `C:\Program Files\...` - **#492** — `omniroute` CLI now detects `mise`/`nvm` when `app/server.js` is missing and shows targeted fix -### 📖 Documentation +### Documentación - **#513** — Docker password reset: `INITIAL_PASSWORD` env var workaround documented - **#520** — pnpm: `pnpm approve-builds better-sqlite3` documented @@ -4025,7 +4143,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **feat(executors/cloudflare-ai)**: New `CloudflareAIExecutor` — dynamic URL construction requires `accountId` in provider credentials - **feat(executors)**: Register `pollinations`, `pol`, `cloudflare-ai`, `cf` executor mappings -### 📝 Documentation +### Documentación - **docs(readme)**: Expanded free combo stack to 11 providers ($0 forever) - **docs(readme)**: Added 4 new free provider sections (LongCat, Pollinations, Cloudflare AI, Scaleway) with model tables @@ -4177,7 +4295,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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). -### Features +### Funcionalidades - **"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. @@ -4205,7 +4323,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Merge PR #494 (MiniMax role fix), fix KIRO MITM dashboard, triage 8 issues. -### Features +### Funcionalidades - **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. - **roleNormalizer**: `normalizeDeveloperRole()` now accepts `preserveDeveloperRole` parameter with tri-state behavior (undefined=keep, true=keep, false=convert). @@ -4261,7 +4379,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Gemini CLI deprecation, VM guide i18n fix, dependabot security fix, provider schema expansion. -### Features +### Funcionalidades - **Gemini CLI Deprecation** (#462): Mark `gemini-cli` provider as deprecated with warning — Google restricts third-party OAuth usage from March 2026 - **Provider Schema** (#462): Expand Zod validation with `deprecated`, `deprecationReason`, `hasFree`, `freeNote`, `authHint`, `apiHint` optional fields @@ -4270,7 +4388,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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) -### Security +### Seguridad - **deps**: Bump `flatted` 3.3.3 → 3.4.2 — fixes CWE-1321 prototype pollution (#484, @dependabot) @@ -4290,7 +4408,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Czech i18n, SSE protocol fix, VM guide translation. -### Features +### Funcionalidades - **Czech Language** (#482): Full Czech (cs) i18n — 22 docs, 2606 UI strings, language switcher updates (@zen0bit) - **VM Deployment Guide**: Translated from Portuguese to English as the source document (@zen0bit) @@ -4309,7 +4427,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: 2 merged PRs, model aliases routing fix, log export, and issue triage. -### Features +### Funcionalidades - **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) @@ -4329,7 +4447,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Five community PRs — streaming call log fixes, Kiro compatibility, cache token analytics, Chinese translation, and configurable tool call IDs. -### ✨ Features +### Funcionalidades - **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) - **feat(providers)**: Per-model configurable 9-char tool call ID normalization (Mistral-style) — only models with the option enabled get truncated IDs (#470) @@ -4359,7 +4477,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Bailian Coding Plan provider with editable base URLs, plus community contributions for Alibaba Cloud and Kimi Coding. -### ✨ Features +### Funcionalidades - **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) - **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) @@ -4374,7 +4492,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Two new community-contributed providers (Alibaba Cloud Coding, Kimi Coding API-key) and Docker pino fix. -### ✨ Features +### Funcionalidades - **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) - **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) @@ -4399,7 +4517,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Codex responses subpath passthrough natively supported, Windows MITM crash fixed, and Combos agent schemas adjusted. -### ✨ Features +### Funcionalidades - **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) @@ -4439,7 +4557,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **fix(budget)**: "Save Limits" no longer returns 422 — `warningThreshold` is now correctly sent as fraction (0–1) instead of percentage (0–100) (#451) - **fix(combos)**: `` internal cache tag is now stripped before forwarding requests to providers, preventing cache session breaks (#454) -### ✨ Features +### Funcionalidades - **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) @@ -4495,7 +4613,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Search Tools dashboard, i18n fixes, Copilot limits, Serper validation fix. -### 🚀 Features +### Funcionalidades - **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) - New route: `/dashboard/search-tools` @@ -4595,7 +4713,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - DB migration: `request_type` column on `call_logs` for non-chat request tracking - Zod validation (`v1SearchSchema`), auth-gated, cost recorded via `recordCost()` -### 🔒 Security +### Seguridad - **deps**: Next.js 16.1.6 → 16.1.7 — fixes 6 CVEs: - **Critical**: CVE-2026-29057 (HTTP request smuggling via http-proxy) @@ -4725,7 +4843,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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**: New `request_detail_logs` table with 500-entry ring-buffer trigger, opt-in via settings toggle -### ✨ Features +### Funcionalidades - **feat(combo)**: System Message Override per Combo (#399 — `system_message` field replaces or injects system prompt before forwarding to provider) - **feat(combo)**: Tool Filter Regex per Combo (#399 — `tool_filter_regex` keeps only tools matching pattern; supports OpenAI + Anthropic formats) @@ -4740,7 +4858,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: SSE improvements, local provider_nodes extensions, proxy registry, Claude passthrough fixes. -### ✨ Features +### Funcionalidades - **feat(health)**: Background health check for local `provider_nodes` with exponential backoff (30s→300s) and `Promise.allSettled` to avoid blocking (#423, @Regis-RCR) - **feat(embeddings)**: Route `/v1/embeddings` to local `provider_nodes` — `buildDynamicEmbeddingProvider()` with hostname validation (#422, @Regis-RCR) @@ -4882,7 +5000,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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 - **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). -### ✨ Features +### Funcionalidades - **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) @@ -4912,7 +5030,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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) - **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) -### ✨ Features +### Funcionalidades - **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) - **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. @@ -4971,7 +5089,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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) - **fix(logs)**: Request log table is now readable in light mode — status badges, token counts, and combo tags use adaptive `dark:` color classes (#378) -### ✨ Features +### Funcionalidades - **feat(kiro)**: Kiro credit tracking added to usage fetcher — queries `getUserCredits` from AWS CodeWhisperer endpoint (#337) @@ -5372,7 +5490,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > **Major release** — Free Stack ecosystem, transcription playground overhaul, 44+ providers, comprehensive free tier documentation, and UI improvements across the board. -### ✨ Features +### Funcionalidades - **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. - **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. @@ -5383,7 +5501,7 @@ OmniRoute now automatically refreshes model lists for connected providers every ## [2.3.16] - 2026-03-13 -### 📖 Documentation +### Documentación - **README: 44+ Providers** — Updated all 3 occurrences of "36+ providers" to "44+" reflecting the actual codebase count (44 providers in providers.ts) - **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. @@ -5393,7 +5511,7 @@ OmniRoute now automatically refreshes model lists for connected providers every ## [2.3.15] - 2026-03-13 -### ✨ Features +### Funcionalidades - **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. - **i18n — autoCombo section**: Added 20 new translation keys for the Auto-Combo dashboard (`title`, `status`, `modePack`, `providerScores`, `factorTierPriority`, etc.) to all 30 language files. diff --git a/docs/i18n/vi/CHANGELOG.md b/docs/i18n/vi/CHANGELOG.md index 52b084da4d..8229604aeb 100644 --- a/docs/i18n/vi/CHANGELOG.md +++ b/docs/i18n/vi/CHANGELOG.md @@ -10,30 +10,148 @@ ### ✨ New Features -- **feat(antigravity):** integrate Antigravity provider with dynamic `maxOutputTokens` calculation (bumping to `thinkingBudget + 1`) and standard Cloud Code envelope payload sanitization (#2055, #2063) +- **feat(antigravity):** integrate Antigravity provider with dynamic `maxOutputTokens` calculation, identity fingerprinting overhaul, and Cloud Code envelope payload sanitization (#2055, #2063) - **feat(gemini-cli):** add custom projectId support for Gemini CLI transport (UI, DB, executor) (#1991) +- **feat(providers):** add KIE media provider support with dynamic polling, text models, and expanded video models catalog +- **feat(providers):** add Z.AI provider support with GLM quota handling and new quota labels +- **feat(providers):** add 9 new free AI providers — LLM7, Lepton, Kluster, UncloseAI, BazaarLink, Completions, Enally, FreeTheAi (#2096) +- **feat(providers):** batch delete provider connections via checkbox multi-select (#2094) +- **feat(cursor):** full OpenAI parity — tool calls, streaming, and session management (#2082) +- **feat(cli):** comprehensive CLI enhancement suite with 20+ new commands including `omniroute providers`, `omniroute combos`, `omniroute doctor` (#2074) +- **feat(cli):** add modular CLI setup and provider management commands (#2046) +- **feat(mcp):** add DeepSeek quota and limit monitoring feature (#2089) +- **feat(circuit-breaker):** classify 429 errors and apply per-kind cooldowns (#2116) +- **feat(multi):** manifest-aware tier routing — W1-W4 complete (#2014) +- **feat(combos):** add reset-aware routing strategy for quota-based providers +- **feat(combo):** add context_length input field to combo edit form (#2047) +- **feat(chat):** dynamic tool limit detection with proactive truncation (#2061) +- **feat(sse):** refresh Claude OAuth wire image to claude-cli/2.1.131 (#2011) +- **feat(github):** add `targetFormat: openai-responses` to all GitHub models (#2122) +- **feat(api):** allow configuration via API calls — open management routes to Bearer keys with manage scope (#2103) +- **feat(api):** update API bridge proxy timeout to 600,000ms (#2019) +- **feat(usage):** add service tier breakdown, codex fast service tier analytics, and account for fast tier +- **feat(chat):** add `STREAM_READINESS_TIMEOUT_MS` and integrate into chat handling +- **feat(combo):** add `fallbackDelayMs` to combo configuration and related settings +- **feat(chat):** enhance error handling for semaphore capacity with fallback logic +- **feat(qdrant):** embedding model discovery (#2086) +- **feat(auth):** per-session sticky routing for Codex (#1887) +- **feat(inworld):** enhance Inworld TTS support (#2123) ### 🐛 Bug Fixes +- **fix(pricing):** make `getPricingForModel` fully case-insensitive to ensure custom prices correctly reflect in new incoming requests cost calculations +- **fix(gemini):** prevent `functionDeclarations` from being dropped by the sanitizer when `googleSearch` tool is present (#2077) +- **fix(pollinations):** add `jsonMode: true` flag in the request transformation to enforce correct JSON structure from Pollinations API (#2109) +- **fix(docker):** update Dockerfile to copy `/docs` directory during build ensuring API catalog availability at runtime (#2083) +- **fix(docker):** include OpenAPI spec in runtime image (#2007) +- **fix(providers):** strip OpenAI-specific fields in Kiro translator to prevent 400 errors (#2037) +- **fix(kiro):** normalize tool-use payloads to prevent 400 errors from agents (#2104) +- **fix(kiro):** merge adjacent user history turns after role normalization (#2105) +- **fix(ui):** resolve text contrast issues for zero-config warning banner in light mode (#2050) +- **fix(core):** inject global system prompt correctly into downstream chat completions pipeline (#2080) +- **fix(core):** restore Claude Code adaptive thinking defaults and resolve audio transcription CORS regression +- **fix(routing):** add missing v1beta rewrites to next.config to resolve 404 on Gemini models endpoint (#2102) +- **fix(routing):** fix bare GPT-5.5 routing for Codex-only installations (#2054) +- **fix(routing):** add fuzzy auto-combo routing for `auto/*` model prefix (#2010) - **fix(cache):** optimize cache_control preservation logic and explicitly align tool schema with upstream Claude Code expectations - **fix(db):** preserve legacy SQLite database path on Windows to prevent data loss (#1973) +- **fix(db):** reduce hot-path persistence overhead (#2039) +- **fix(db):** resolve migration conflict by renumbering overlapping migration entries (#2041) - **fix(settings):** resolve model alias persistence double stringification preventing UI updates (#2018) - **fix(routing):** dynamically filter bare model auto-resolution by active provider connections to prevent dead-routing (#2029) - **fix(embeddings):** add Google Gemini embeddings compatibility via OpenAI-compatible endpoint mapping (#2006) +- **fix(sse):** prevent Claude OAuth multi-account correlation via metadata.user_id (#2053) +- **fix(sse):** prevent Claude Code identity cloak overrides and fix fallback resilience (#2053) +- **fix(sse):** classify hour quota errors as QUOTA_EXHAUSTED (#2119) +- **fix(sse):** fix CC-compatible streaming bridge (#2118) +- **fix(antigravity):** sanitize Claude Cloud Code payloads (#2090) +- **fix(antigravity):** add duplex half for streaming bodies +- **fix(antigravity):** align identity protocol and behavior with official AM +- **fix(chatgpt-web):** plumb proxy through to native tls-client (#2022, #2023) +- **fix(codex):** expose native model IDs in catalog (#2012) +- **fix(glm):** add dedicated coding transport (#2087) +- **fix(compression):** support Responses input and expand Spanish compression rules (#2028) +- **fix(catalog):** auto-calculate combo context_length from target model limits (#2030) +- **fix(api):** fix usage analytics and API key identity (#2008, #2092) +- **fix(api-key):** allow Unicode letters in API key name validation (#1996) +- **fix(auth):** allow bootstrap without password (#2048) +- **fix(proxy):** clean up proxy page redundancy and fix 1proxy sync empty body error (#2052) +- **fix(dashboard):** resolve Unknown plan display in Provider Limits +- **fix(usage):** add extensible CURRENCY_SYMBOLS mapping for deepseek currencies +- **fix(runtime):** harden timer handling and model pricing fallback +- **fix(i18n):** complete Simplified Chinese translations (#2115) +- **fix(mitm):** add Linux cert install and skip sudo password when root (#1999) +- **fix(mitm):** prevent stub from loading at runtime via bypass module - **fix:** remove Anthropic-Beta header from non-Anthropic providers to fix identity contamination (#1989) - **fix(cli):** resolve .env loading failure for global npm installations +- **fix(export):** exclude telemetry/usage-history tables from JSON config backups by default to prevent unbounded file growth (#2125) +- **fix:** Follow OpenAI specification, handle throttling in batch and fix UI (#2045) -### 🔒 Security +### Bảo mật +- **fix(security):** remediate CodeQL vulnerabilities (ReDoS, cryptographic bias, stack trace exposure, and weak password hashing) (#216, #215, #211, #208, #206, #210) - **fix(security):** remediate regex validation backtracking path in core compression cleanup (#1990) - **fix(core):** harden input handling and stabilization for prompt compression edge cases +### Tài liệu + +- **docs:** add competitive marketing tables and SEO/AEO optimizations to README (#2091) +- **docs:** refresh providers, model catalogs, and docs for v3.8.0 (#2088) +- **docs:** update Claude MD and update GLM-CN max context to 200k (#2027) +- **docs(env):** add `GITLAB_DUO_OAUTH_CLIENT_ID` to `.env.example` (#2031) + ### 🧹 Chores & Maintenance - **chore(providers):** prune redundant local provider icon assets in favor of `@lobehub/icons` web fonts (#1992) +- **chore(providers):** remove deprecated models (#2033) +- **deps:** bump `fast-uri` from 3.1.0 to 3.1.2 (#2078) +- **deps:** bump `hono` from 4.12.14 to 4.12.18 (#2079) - **ci:** skip SonarCloud scan on main pushes to optimize CI time - **test:** stabilize cooldown abort coverage case in integration testing +### 🏆 v3.8.0 Community Contributors + +Thank you to all **38 community contributors** who made v3.8.0 possible! 🎉 + +| Contributor | PRs | Contributions | +| :--------------------------------------------------------- | :-: | :------------------------------------------------------------ | +| [@oyi77](https://github.com/oyi77) | 7 | #2010, #2014, #2041, #2052, #2061, #2074, #2091, #2094, #2096 | +| [@backryun](https://github.com/backryun) | 4 | #1992, #2033, #2088, #2123 | +| [@dhaern](https://github.com/dhaern) | 4 | #2028, #2039, #2087, #2090 | +| [@Tentoxa](https://github.com/Tentoxa) | 2 | #2011, #2053 | +| [@wauputr4](https://github.com/wauputr4) | 2 | #2009, #2046 | +| [@payne0420](https://github.com/payne0420) | 1 | #2082 | +| [@Tr0sT](https://github.com/Tr0sT) | 1 | #2012 | +| [@AveryanAlex](https://github.com/AveryanAlex) | 1 | #2008 | +| [@nickwizard](https://github.com/nickwizard) | 1 | #1991 | +| [@rodrigogbbr-stack](https://github.com/rodrigogbbr-stack) | 1 | #1996 | +| [@NekoMonci12](https://github.com/NekoMonci12) | 1 | #1999 | +| [@congvc-dev](https://github.com/congvc-dev) | 1 | #2004 | +| [@tatsster](https://github.com/tatsster) | 1 | #2007 | +| [@xssdem](https://github.com/xssdem) | 1 | #2023 | +| [@bypanghu](https://github.com/bypanghu) | 1 | #2027 | +| [@herjarsa](https://github.com/herjarsa) | 1 | #2030 | +| [@wucm667](https://github.com/wucm667) | 1 | #2031 | +| [@hartmark](https://github.com/hartmark) | 1 | #2045 | +| [@ddarkr](https://github.com/ddarkr) | 1 | #2047 | +| [@tces1](https://github.com/tces1) | 1 | #2048 | +| [@guanbear](https://github.com/guanbear) | 1 | #2054 | +| [@Gi99lin](https://github.com/Gi99lin) | 1 | #2055 | +| [@ivan-mezentsev](https://github.com/ivan-mezentsev) | 1 | #2063 | +| [@JxnLexn](https://github.com/JxnLexn) | 1 | #2019 | +| [@yoviarpauzi](https://github.com/yoviarpauzi) | 1 | #2092 | +| [@rafacpti23](https://github.com/rafacpti23) | 1 | #2086 | +| [@gleber](https://github.com/gleber) | 1 | #2103 | +| [@rilham97](https://github.com/rilham97) | 1 | #2104 | +| [@Gioxaa](https://github.com/Gioxaa) | 1 | #2105 | +| [@boa-z](https://github.com/boa-z) | 1 | #2115 | +| [@eleata](https://github.com/eleata) | 1 | #2116 | +| [@rdself](https://github.com/rdself) | 1 | #2118 | +| [@clousky2020](https://github.com/clousky2020) | 1 | #2119 | +| [@abhinavjnu](https://github.com/abhinavjnu) | 1 | #2122 | +| [@HoaPham98](https://github.com/HoaPham98) | 1 | #2089 | +| [@05dunski](https://github.com/05dunski) | 1 | #1978 (cherry-picked) | + ## [3.7.9] — 2026-05-03 ### ✨ New Features @@ -102,7 +220,7 @@ - **chore(provider):** Add reka models list (#1956 — thanks @backryun) - **chore(model):** Update new models, Delete Deprecated models (#1949 — thanks @backryun) -### 📝 Documentation +### Tài liệu - **docs(compression):** document RTK+Caveman stacked savings ranges @@ -201,7 +319,7 @@ - **feat(db):** auto-restore probe-failed database on startup to prevent data loss after failed upgrades (#1810) - **feat(analytics):** add cost-based usage insights and activity streaks in the analytics dashboard -### 🔒 Security +### Bảo mật - **fix(security):** resolve ReDoS vulnerability in Codex executor regex patterns (#1797, #1789) @@ -354,7 +472,7 @@ We identified that **155 community PRs** across the entire project history (from - **feat(proxy):** implement bulk proxy import via pipe-delimited parser with update-or-create (upsert) logic and real-time preview table - **feat(pwa):** add fullscreen installable PWA with manifest, service worker, and cross-platform app icons (#1728) -### 🔒 Security +### Bảo mật - **security:** replace insecure `Math.random` with `crypto.getRandomValues` for fallback UUID generation to resolve CodeQL CWE-338 finding (#182) @@ -519,7 +637,7 @@ We identified that **155 community PRs** across the entire project history (from - **fix(transport):** Prevent memory bloat and database exhaustion from large, fragmented streaming responses. Implemented `ByteQueue` in `kiro.ts` for zero-copy binary accumulation, refactored `antigravity.ts` for incremental SSE parsing, and enforced a strict 512KB tiered truncation limit (`MAX_CALL_LOG_ARTIFACT_BYTES`) on stream request logs and call artifacts (#1647). - **chore(ci):** Update build environment dependencies — bump Node to `24.15.0`, `actions/checkout@v6`, `docker/build-push-action@v7`, pin `actions/setup-python` to major tag (#1646 — thanks @backryun). -### 📝 Documentation +### Tài liệu - **docs(env):** Add `OMNIROUTE_ALLOW_PRIVATE_PROVIDER_URLS` to `.env.example` with documentation for LM Studio and other local provider use cases (#1623). @@ -669,7 +787,7 @@ We identified that **155 community PRs** across the entire project history (from - **test(next):** Align transpile package expectations for the Next.js standalone build. - **test(ci):** Fix CI-only test failures from environment differences — clear `INITIAL_PASSWORD` and `JWT_SECRET` in integration tests, handle `XDG_CONFIG_HOME` for guide-settings tests. -### 📚 Documentation +### Tài liệu - **docs:** Update the root changelog with all release-branch changes through 2026-04-24, including PRs #1544, #1555, #1551, #1550, #1548, #1547, #1541, #1538, #1536, and #1527. - **docs:** Fix broken README and localized documentation links. (#1536) @@ -811,7 +929,7 @@ We identified that **155 community PRs** across the entire project history (from - **feat(providers):** Expand image provider registry with extended model support including SD3.5, FLUX, and DALL-E 3 HD configurations - **feat(combos):** Add new routing strategies and full i18n support for agent features section across 31 languages -### 🔒 Security +### Bảo mật - **security:** Resolve 18 GitHub CodeQL scan alerts including ReDoS, incomplete sanitization, and bad HTML filtering regexp patterns - **fix(auth):** Seal privilege escalation vector by enforcing JWT session checking exclusively on `/api/keys` management endpoints (#1353) @@ -1078,7 +1196,7 @@ We identified that **155 community PRs** across the entire project history (from - **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 - **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 -### 🔒 Security +### Bảo mật - **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 - **Auth Guard on Translator Save:** Added `isAuthenticated` guard to `/api/translator/save` for defense-in-depth consistency @@ -1483,7 +1601,7 @@ We identified that **155 community PRs** across the entire project history (from - **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). -### 📚 Documentation +### Tài liệu - **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. - **Context Relay Delivery Notes:** Documented the current architecture, runtime flow, and Codex-focused scope in the feature docs, changelog, and agent guidance. @@ -1559,7 +1677,7 @@ We identified that **155 community PRs** across the entire project history (from ## [3.5.3] - 2026-04-07 -### Security +### Bảo mật - **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. - **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. @@ -1575,7 +1693,7 @@ We identified that **155 community PRs** across the entire project history (from - **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. -### Documentation +### Tài liệu - **I18n Engine:** Synchronized and pushed deep Machine Translation updates across all 32 natively-supported languages (682 translation nodes aligned). @@ -1736,7 +1854,7 @@ We identified that **155 community PRs** across the entire project history (from ## [3.4.8] — 2026-04-03 -### Security +### Bảo mật - Fully remediated all outstanding Github Advanced Security (CodeQL) findings and Dependabot alerts. - Fixed insecure randomness vulnerabilities by migrating from `Math.random` to `crypto.randomUUID()`. @@ -1748,7 +1866,7 @@ We identified that **155 community PRs** across the entire project history (from ## [3.4.7] — 2026-04-03 -### Features +### Tính năng - Added `Cryptography` node to Monitoring and MCP health checks (#798) - Hardened model-catalog route permissions mapping (`/models`) (#781) @@ -1764,7 +1882,7 @@ We identified that **155 community PRs** across the entire project history (from - Fixed MCP standalone module-resolution (`ERR_MODULE_NOT_FOUND`) via `esbuild` (#936) - Fixed NVIDIA NIM routing credential resolution alias mismatch (#931) -### Security +### Bảo mật - Added safe strict input boundary protection against raw `shell: true` remote-code execution injections. @@ -2011,7 +2129,7 @@ We identified that **155 community PRs** across the entire project history (from ## [3.4.0] - 2026-03-31 -### 🚀 Features +### Tính năng - **Subscription Utilization Analytics:** Added quota snapshot time-series tracking, Provider Utilization and Combo Health tabs with recharts visualizations, and corresponding API endpoints (#847) - **SQLite Backup Control:** New `OMNIROUTE_DISABLE_AUTO_BACKUP` env flag to disable automatic SQLite backups (#846) @@ -2063,7 +2181,7 @@ We identified that **155 community PRs** across the entire project history (from ## [3.3.8] - 2026-03-30 -### 🚀 Features +### Tính năng - **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) - **Qoder Integration:** Native integration for Qoder AI natively replacing the legacy iFlow platform mappings (#660) @@ -2889,7 +3007,7 @@ We identified that **155 community PRs** across the entire project history (from - **NaN tokens in Claude Code / client responses (#617):** - `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 -### 🔒 Security +### Bảo mật - Updated `yaml` package to fix stack overflow vulnerability (GHSA-48c2-rrv3-qjmp) @@ -3565,7 +3683,7 @@ docker pull diegosouzapw/omniroute:3.0.0 - **SVG fallback**: `ProviderIcon` component updated with 4-tier strategy: Lobehub → PNG → SVG → Generic icon - **Agents fingerprinting**: Synced with CLI tools — added droid, openclaw, copilot, opencode to fingerprint list (14 total) -### 🔒 Security +### Bảo mật - **CVE fix**: Resolved dompurify XSS vulnerability (GHSA-v2wj-7wpq-c8vv) via npm overrides forcing `dompurify@^3.3.2` - `npm audit` now reports **0 vulnerabilities** @@ -3928,7 +4046,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **#510** — Windows: MSYS2/Git-Bash paths (`/c/Program Files/...`) are now normalized to `C:\Program Files\...` - **#492** — `omniroute` CLI now detects `mise`/`nvm` when `app/server.js` is missing and shows targeted fix -### 📖 Documentation +### Tài liệu - **#513** — Docker password reset: `INITIAL_PASSWORD` env var workaround documented - **#520** — pnpm: `pnpm approve-builds better-sqlite3` documented @@ -4025,7 +4143,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **feat(executors/cloudflare-ai)**: New `CloudflareAIExecutor` — dynamic URL construction requires `accountId` in provider credentials - **feat(executors)**: Register `pollinations`, `pol`, `cloudflare-ai`, `cf` executor mappings -### 📝 Documentation +### Tài liệu - **docs(readme)**: Expanded free combo stack to 11 providers ($0 forever) - **docs(readme)**: Added 4 new free provider sections (LongCat, Pollinations, Cloudflare AI, Scaleway) with model tables @@ -4177,7 +4295,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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). -### Features +### Tính năng - **"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. @@ -4205,7 +4323,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Merge PR #494 (MiniMax role fix), fix KIRO MITM dashboard, triage 8 issues. -### Features +### Tính năng - **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. - **roleNormalizer**: `normalizeDeveloperRole()` now accepts `preserveDeveloperRole` parameter with tri-state behavior (undefined=keep, true=keep, false=convert). @@ -4261,7 +4379,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Gemini CLI deprecation, VM guide i18n fix, dependabot security fix, provider schema expansion. -### Features +### Tính năng - **Gemini CLI Deprecation** (#462): Mark `gemini-cli` provider as deprecated with warning — Google restricts third-party OAuth usage from March 2026 - **Provider Schema** (#462): Expand Zod validation with `deprecated`, `deprecationReason`, `hasFree`, `freeNote`, `authHint`, `apiHint` optional fields @@ -4270,7 +4388,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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) -### Security +### Bảo mật - **deps**: Bump `flatted` 3.3.3 → 3.4.2 — fixes CWE-1321 prototype pollution (#484, @dependabot) @@ -4290,7 +4408,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Czech i18n, SSE protocol fix, VM guide translation. -### Features +### Tính năng - **Czech Language** (#482): Full Czech (cs) i18n — 22 docs, 2606 UI strings, language switcher updates (@zen0bit) - **VM Deployment Guide**: Translated from Portuguese to English as the source document (@zen0bit) @@ -4309,7 +4427,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: 2 merged PRs, model aliases routing fix, log export, and issue triage. -### Features +### Tính năng - **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) @@ -4329,7 +4447,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Five community PRs — streaming call log fixes, Kiro compatibility, cache token analytics, Chinese translation, and configurable tool call IDs. -### ✨ Features +### Tính năng - **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) - **feat(providers)**: Per-model configurable 9-char tool call ID normalization (Mistral-style) — only models with the option enabled get truncated IDs (#470) @@ -4359,7 +4477,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Bailian Coding Plan provider with editable base URLs, plus community contributions for Alibaba Cloud and Kimi Coding. -### ✨ Features +### Tính năng - **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) - **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) @@ -4374,7 +4492,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Two new community-contributed providers (Alibaba Cloud Coding, Kimi Coding API-key) and Docker pino fix. -### ✨ Features +### Tính năng - **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) - **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) @@ -4399,7 +4517,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Codex responses subpath passthrough natively supported, Windows MITM crash fixed, and Combos agent schemas adjusted. -### ✨ Features +### Tính năng - **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) @@ -4439,7 +4557,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **fix(budget)**: "Save Limits" no longer returns 422 — `warningThreshold` is now correctly sent as fraction (0–1) instead of percentage (0–100) (#451) - **fix(combos)**: `` internal cache tag is now stripped before forwarding requests to providers, preventing cache session breaks (#454) -### ✨ Features +### Tính năng - **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) @@ -4495,7 +4613,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Search Tools dashboard, i18n fixes, Copilot limits, Serper validation fix. -### 🚀 Features +### Tính năng - **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) - New route: `/dashboard/search-tools` @@ -4595,7 +4713,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - DB migration: `request_type` column on `call_logs` for non-chat request tracking - Zod validation (`v1SearchSchema`), auth-gated, cost recorded via `recordCost()` -### 🔒 Security +### Bảo mật - **deps**: Next.js 16.1.6 → 16.1.7 — fixes 6 CVEs: - **Critical**: CVE-2026-29057 (HTTP request smuggling via http-proxy) @@ -4725,7 +4843,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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**: New `request_detail_logs` table with 500-entry ring-buffer trigger, opt-in via settings toggle -### ✨ Features +### Tính năng - **feat(combo)**: System Message Override per Combo (#399 — `system_message` field replaces or injects system prompt before forwarding to provider) - **feat(combo)**: Tool Filter Regex per Combo (#399 — `tool_filter_regex` keeps only tools matching pattern; supports OpenAI + Anthropic formats) @@ -4740,7 +4858,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: SSE improvements, local provider_nodes extensions, proxy registry, Claude passthrough fixes. -### ✨ Features +### Tính năng - **feat(health)**: Background health check for local `provider_nodes` with exponential backoff (30s→300s) and `Promise.allSettled` to avoid blocking (#423, @Regis-RCR) - **feat(embeddings)**: Route `/v1/embeddings` to local `provider_nodes` — `buildDynamicEmbeddingProvider()` with hostname validation (#422, @Regis-RCR) @@ -4882,7 +5000,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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 - **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). -### ✨ Features +### Tính năng - **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) @@ -4912,7 +5030,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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) - **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) -### ✨ Features +### Tính năng - **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) - **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. @@ -4971,7 +5089,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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) - **fix(logs)**: Request log table is now readable in light mode — status badges, token counts, and combo tags use adaptive `dark:` color classes (#378) -### ✨ Features +### Tính năng - **feat(kiro)**: Kiro credit tracking added to usage fetcher — queries `getUserCredits` from AWS CodeWhisperer endpoint (#337) @@ -5372,7 +5490,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > **Major release** — Free Stack ecosystem, transcription playground overhaul, 44+ providers, comprehensive free tier documentation, and UI improvements across the board. -### ✨ Features +### Tính năng - **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. - **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. @@ -5383,7 +5501,7 @@ OmniRoute now automatically refreshes model lists for connected providers every ## [2.3.16] - 2026-03-13 -### 📖 Documentation +### Tài liệu - **README: 44+ Providers** — Updated all 3 occurrences of "36+ providers" to "44+" reflecting the actual codebase count (44 providers in providers.ts) - **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. @@ -5393,7 +5511,7 @@ OmniRoute now automatically refreshes model lists for connected providers every ## [2.3.15] - 2026-03-13 -### ✨ Features +### Tính năng - **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. - **i18n — autoCombo section**: Added 20 new translation keys for the Auto-Combo dashboard (`title`, `status`, `modePack`, `providerScores`, `factorTierPriority`, etc.) to all 30 language files. diff --git a/docs/i18n/zh-CN/CHANGELOG.md b/docs/i18n/zh-CN/CHANGELOG.md index e739c7b20c..81c84439ad 100644 --- a/docs/i18n/zh-CN/CHANGELOG.md +++ b/docs/i18n/zh-CN/CHANGELOG.md @@ -10,30 +10,148 @@ ### ✨ New Features -- **feat(antigravity):** integrate Antigravity provider with dynamic `maxOutputTokens` calculation (bumping to `thinkingBudget + 1`) and standard Cloud Code envelope payload sanitization (#2055, #2063) +- **feat(antigravity):** integrate Antigravity provider with dynamic `maxOutputTokens` calculation, identity fingerprinting overhaul, and Cloud Code envelope payload sanitization (#2055, #2063) - **feat(gemini-cli):** add custom projectId support for Gemini CLI transport (UI, DB, executor) (#1991) +- **feat(providers):** add KIE media provider support with dynamic polling, text models, and expanded video models catalog +- **feat(providers):** add Z.AI provider support with GLM quota handling and new quota labels +- **feat(providers):** add 9 new free AI providers — LLM7, Lepton, Kluster, UncloseAI, BazaarLink, Completions, Enally, FreeTheAi (#2096) +- **feat(providers):** batch delete provider connections via checkbox multi-select (#2094) +- **feat(cursor):** full OpenAI parity — tool calls, streaming, and session management (#2082) +- **feat(cli):** comprehensive CLI enhancement suite with 20+ new commands including `omniroute providers`, `omniroute combos`, `omniroute doctor` (#2074) +- **feat(cli):** add modular CLI setup and provider management commands (#2046) +- **feat(mcp):** add DeepSeek quota and limit monitoring feature (#2089) +- **feat(circuit-breaker):** classify 429 errors and apply per-kind cooldowns (#2116) +- **feat(multi):** manifest-aware tier routing — W1-W4 complete (#2014) +- **feat(combos):** add reset-aware routing strategy for quota-based providers +- **feat(combo):** add context_length input field to combo edit form (#2047) +- **feat(chat):** dynamic tool limit detection with proactive truncation (#2061) +- **feat(sse):** refresh Claude OAuth wire image to claude-cli/2.1.131 (#2011) +- **feat(github):** add `targetFormat: openai-responses` to all GitHub models (#2122) +- **feat(api):** allow configuration via API calls — open management routes to Bearer keys with manage scope (#2103) +- **feat(api):** update API bridge proxy timeout to 600,000ms (#2019) +- **feat(usage):** add service tier breakdown, codex fast service tier analytics, and account for fast tier +- **feat(chat):** add `STREAM_READINESS_TIMEOUT_MS` and integrate into chat handling +- **feat(combo):** add `fallbackDelayMs` to combo configuration and related settings +- **feat(chat):** enhance error handling for semaphore capacity with fallback logic +- **feat(qdrant):** embedding model discovery (#2086) +- **feat(auth):** per-session sticky routing for Codex (#1887) +- **feat(inworld):** enhance Inworld TTS support (#2123) ### 🐛 Bug Fixes +- **fix(pricing):** make `getPricingForModel` fully case-insensitive to ensure custom prices correctly reflect in new incoming requests cost calculations +- **fix(gemini):** prevent `functionDeclarations` from being dropped by the sanitizer when `googleSearch` tool is present (#2077) +- **fix(pollinations):** add `jsonMode: true` flag in the request transformation to enforce correct JSON structure from Pollinations API (#2109) +- **fix(docker):** update Dockerfile to copy `/docs` directory during build ensuring API catalog availability at runtime (#2083) +- **fix(docker):** include OpenAPI spec in runtime image (#2007) +- **fix(providers):** strip OpenAI-specific fields in Kiro translator to prevent 400 errors (#2037) +- **fix(kiro):** normalize tool-use payloads to prevent 400 errors from agents (#2104) +- **fix(kiro):** merge adjacent user history turns after role normalization (#2105) +- **fix(ui):** resolve text contrast issues for zero-config warning banner in light mode (#2050) +- **fix(core):** inject global system prompt correctly into downstream chat completions pipeline (#2080) +- **fix(core):** restore Claude Code adaptive thinking defaults and resolve audio transcription CORS regression +- **fix(routing):** add missing v1beta rewrites to next.config to resolve 404 on Gemini models endpoint (#2102) +- **fix(routing):** fix bare GPT-5.5 routing for Codex-only installations (#2054) +- **fix(routing):** add fuzzy auto-combo routing for `auto/*` model prefix (#2010) - **fix(cache):** optimize cache_control preservation logic and explicitly align tool schema with upstream Claude Code expectations - **fix(db):** preserve legacy SQLite database path on Windows to prevent data loss (#1973) +- **fix(db):** reduce hot-path persistence overhead (#2039) +- **fix(db):** resolve migration conflict by renumbering overlapping migration entries (#2041) - **fix(settings):** resolve model alias persistence double stringification preventing UI updates (#2018) - **fix(routing):** dynamically filter bare model auto-resolution by active provider connections to prevent dead-routing (#2029) - **fix(embeddings):** add Google Gemini embeddings compatibility via OpenAI-compatible endpoint mapping (#2006) +- **fix(sse):** prevent Claude OAuth multi-account correlation via metadata.user_id (#2053) +- **fix(sse):** prevent Claude Code identity cloak overrides and fix fallback resilience (#2053) +- **fix(sse):** classify hour quota errors as QUOTA_EXHAUSTED (#2119) +- **fix(sse):** fix CC-compatible streaming bridge (#2118) +- **fix(antigravity):** sanitize Claude Cloud Code payloads (#2090) +- **fix(antigravity):** add duplex half for streaming bodies +- **fix(antigravity):** align identity protocol and behavior with official AM +- **fix(chatgpt-web):** plumb proxy through to native tls-client (#2022, #2023) +- **fix(codex):** expose native model IDs in catalog (#2012) +- **fix(glm):** add dedicated coding transport (#2087) +- **fix(compression):** support Responses input and expand Spanish compression rules (#2028) +- **fix(catalog):** auto-calculate combo context_length from target model limits (#2030) +- **fix(api):** fix usage analytics and API key identity (#2008, #2092) +- **fix(api-key):** allow Unicode letters in API key name validation (#1996) +- **fix(auth):** allow bootstrap without password (#2048) +- **fix(proxy):** clean up proxy page redundancy and fix 1proxy sync empty body error (#2052) +- **fix(dashboard):** resolve Unknown plan display in Provider Limits +- **fix(usage):** add extensible CURRENCY_SYMBOLS mapping for deepseek currencies +- **fix(runtime):** harden timer handling and model pricing fallback +- **fix(i18n):** complete Simplified Chinese translations (#2115) +- **fix(mitm):** add Linux cert install and skip sudo password when root (#1999) +- **fix(mitm):** prevent stub from loading at runtime via bypass module - **fix:** remove Anthropic-Beta header from non-Anthropic providers to fix identity contamination (#1989) - **fix(cli):** resolve .env loading failure for global npm installations +- **fix(export):** exclude telemetry/usage-history tables from JSON config backups by default to prevent unbounded file growth (#2125) +- **fix:** Follow OpenAI specification, handle throttling in batch and fix UI (#2045) -### 🔒 Security +### 安全 +- **fix(security):** remediate CodeQL vulnerabilities (ReDoS, cryptographic bias, stack trace exposure, and weak password hashing) (#216, #215, #211, #208, #206, #210) - **fix(security):** remediate regex validation backtracking path in core compression cleanup (#1990) - **fix(core):** harden input handling and stabilization for prompt compression edge cases +### 文档 + +- **docs:** add competitive marketing tables and SEO/AEO optimizations to README (#2091) +- **docs:** refresh providers, model catalogs, and docs for v3.8.0 (#2088) +- **docs:** update Claude MD and update GLM-CN max context to 200k (#2027) +- **docs(env):** add `GITLAB_DUO_OAUTH_CLIENT_ID` to `.env.example` (#2031) + ### 🧹 Chores & Maintenance - **chore(providers):** prune redundant local provider icon assets in favor of `@lobehub/icons` web fonts (#1992) +- **chore(providers):** remove deprecated models (#2033) +- **deps:** bump `fast-uri` from 3.1.0 to 3.1.2 (#2078) +- **deps:** bump `hono` from 4.12.14 to 4.12.18 (#2079) - **ci:** skip SonarCloud scan on main pushes to optimize CI time - **test:** stabilize cooldown abort coverage case in integration testing +### 🏆 v3.8.0 Community Contributors + +Thank you to all **38 community contributors** who made v3.8.0 possible! 🎉 + +| Contributor | PRs | Contributions | +| :--------------------------------------------------------- | :-: | :------------------------------------------------------------ | +| [@oyi77](https://github.com/oyi77) | 7 | #2010, #2014, #2041, #2052, #2061, #2074, #2091, #2094, #2096 | +| [@backryun](https://github.com/backryun) | 4 | #1992, #2033, #2088, #2123 | +| [@dhaern](https://github.com/dhaern) | 4 | #2028, #2039, #2087, #2090 | +| [@Tentoxa](https://github.com/Tentoxa) | 2 | #2011, #2053 | +| [@wauputr4](https://github.com/wauputr4) | 2 | #2009, #2046 | +| [@payne0420](https://github.com/payne0420) | 1 | #2082 | +| [@Tr0sT](https://github.com/Tr0sT) | 1 | #2012 | +| [@AveryanAlex](https://github.com/AveryanAlex) | 1 | #2008 | +| [@nickwizard](https://github.com/nickwizard) | 1 | #1991 | +| [@rodrigogbbr-stack](https://github.com/rodrigogbbr-stack) | 1 | #1996 | +| [@NekoMonci12](https://github.com/NekoMonci12) | 1 | #1999 | +| [@congvc-dev](https://github.com/congvc-dev) | 1 | #2004 | +| [@tatsster](https://github.com/tatsster) | 1 | #2007 | +| [@xssdem](https://github.com/xssdem) | 1 | #2023 | +| [@bypanghu](https://github.com/bypanghu) | 1 | #2027 | +| [@herjarsa](https://github.com/herjarsa) | 1 | #2030 | +| [@wucm667](https://github.com/wucm667) | 1 | #2031 | +| [@hartmark](https://github.com/hartmark) | 1 | #2045 | +| [@ddarkr](https://github.com/ddarkr) | 1 | #2047 | +| [@tces1](https://github.com/tces1) | 1 | #2048 | +| [@guanbear](https://github.com/guanbear) | 1 | #2054 | +| [@Gi99lin](https://github.com/Gi99lin) | 1 | #2055 | +| [@ivan-mezentsev](https://github.com/ivan-mezentsev) | 1 | #2063 | +| [@JxnLexn](https://github.com/JxnLexn) | 1 | #2019 | +| [@yoviarpauzi](https://github.com/yoviarpauzi) | 1 | #2092 | +| [@rafacpti23](https://github.com/rafacpti23) | 1 | #2086 | +| [@gleber](https://github.com/gleber) | 1 | #2103 | +| [@rilham97](https://github.com/rilham97) | 1 | #2104 | +| [@Gioxaa](https://github.com/Gioxaa) | 1 | #2105 | +| [@boa-z](https://github.com/boa-z) | 1 | #2115 | +| [@eleata](https://github.com/eleata) | 1 | #2116 | +| [@rdself](https://github.com/rdself) | 1 | #2118 | +| [@clousky2020](https://github.com/clousky2020) | 1 | #2119 | +| [@abhinavjnu](https://github.com/abhinavjnu) | 1 | #2122 | +| [@HoaPham98](https://github.com/HoaPham98) | 1 | #2089 | +| [@05dunski](https://github.com/05dunski) | 1 | #1978 (cherry-picked) | + ## [3.7.9] — 2026-05-03 ### ✨ New Features @@ -102,7 +220,7 @@ - **chore(provider):** Add reka models list (#1956 — thanks @backryun) - **chore(model):** Update new models, Delete Deprecated models (#1949 — thanks @backryun) -### 📝 Documentation +### 文档 - **docs(compression):** document RTK+Caveman stacked savings ranges @@ -201,7 +319,7 @@ - **feat(db):** auto-restore probe-failed database on startup to prevent data loss after failed upgrades (#1810) - **feat(analytics):** add cost-based usage insights and activity streaks in the analytics dashboard -### 🔒 Security +### 安全 - **fix(security):** resolve ReDoS vulnerability in Codex executor regex patterns (#1797, #1789) @@ -354,7 +472,7 @@ We identified that **155 community PRs** across the entire project history (from - **feat(proxy):** implement bulk proxy import via pipe-delimited parser with update-or-create (upsert) logic and real-time preview table - **feat(pwa):** add fullscreen installable PWA with manifest, service worker, and cross-platform app icons (#1728) -### 🔒 Security +### 安全 - **security:** replace insecure `Math.random` with `crypto.getRandomValues` for fallback UUID generation to resolve CodeQL CWE-338 finding (#182) @@ -519,7 +637,7 @@ We identified that **155 community PRs** across the entire project history (from - **fix(transport):** Prevent memory bloat and database exhaustion from large, fragmented streaming responses. Implemented `ByteQueue` in `kiro.ts` for zero-copy binary accumulation, refactored `antigravity.ts` for incremental SSE parsing, and enforced a strict 512KB tiered truncation limit (`MAX_CALL_LOG_ARTIFACT_BYTES`) on stream request logs and call artifacts (#1647). - **chore(ci):** Update build environment dependencies — bump Node to `24.15.0`, `actions/checkout@v6`, `docker/build-push-action@v7`, pin `actions/setup-python` to major tag (#1646 — thanks @backryun). -### 📝 Documentation +### 文档 - **docs(env):** Add `OMNIROUTE_ALLOW_PRIVATE_PROVIDER_URLS` to `.env.example` with documentation for LM Studio and other local provider use cases (#1623). @@ -669,7 +787,7 @@ We identified that **155 community PRs** across the entire project history (from - **test(next):** Align transpile package expectations for the Next.js standalone build. - **test(ci):** Fix CI-only test failures from environment differences — clear `INITIAL_PASSWORD` and `JWT_SECRET` in integration tests, handle `XDG_CONFIG_HOME` for guide-settings tests. -### 📚 Documentation +### 文档 - **docs:** Update the root changelog with all release-branch changes through 2026-04-24, including PRs #1544, #1555, #1551, #1550, #1548, #1547, #1541, #1538, #1536, and #1527. - **docs:** Fix broken README and localized documentation links. (#1536) @@ -811,7 +929,7 @@ We identified that **155 community PRs** across the entire project history (from - **feat(providers):** Expand image provider registry with extended model support including SD3.5, FLUX, and DALL-E 3 HD configurations - **feat(combos):** Add new routing strategies and full i18n support for agent features section across 31 languages -### 🔒 Security +### 安全 - **security:** Resolve 18 GitHub CodeQL scan alerts including ReDoS, incomplete sanitization, and bad HTML filtering regexp patterns - **fix(auth):** Seal privilege escalation vector by enforcing JWT session checking exclusively on `/api/keys` management endpoints (#1353) @@ -1078,7 +1196,7 @@ We identified that **155 community PRs** across the entire project history (from - **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 - **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 -### 🔒 Security +### 安全 - **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 - **Auth Guard on Translator Save:** Added `isAuthenticated` guard to `/api/translator/save` for defense-in-depth consistency @@ -1483,7 +1601,7 @@ We identified that **155 community PRs** across the entire project history (from - **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). -### 📚 Documentation +### 文档 - **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. - **Context Relay Delivery Notes:** Documented the current architecture, runtime flow, and Codex-focused scope in the feature docs, changelog, and agent guidance. @@ -1559,7 +1677,7 @@ We identified that **155 community PRs** across the entire project history (from ## [3.5.3] - 2026-04-07 -### Security +### 安全 - **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. - **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. @@ -1575,7 +1693,7 @@ We identified that **155 community PRs** across the entire project history (from - **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. -### Documentation +### 文档 - **I18n Engine:** Synchronized and pushed deep Machine Translation updates across all 32 natively-supported languages (682 translation nodes aligned). @@ -1736,7 +1854,7 @@ We identified that **155 community PRs** across the entire project history (from ## [3.4.8] — 2026-04-03 -### Security +### 安全 - Fully remediated all outstanding Github Advanced Security (CodeQL) findings and Dependabot alerts. - Fixed insecure randomness vulnerabilities by migrating from `Math.random` to `crypto.randomUUID()`. @@ -1748,7 +1866,7 @@ We identified that **155 community PRs** across the entire project history (from ## [3.4.7] — 2026-04-03 -### Features +### 功能特点 - Added `Cryptography` node to Monitoring and MCP health checks (#798) - Hardened model-catalog route permissions mapping (`/models`) (#781) @@ -1764,7 +1882,7 @@ We identified that **155 community PRs** across the entire project history (from - Fixed MCP standalone module-resolution (`ERR_MODULE_NOT_FOUND`) via `esbuild` (#936) - Fixed NVIDIA NIM routing credential resolution alias mismatch (#931) -### Security +### 安全 - Added safe strict input boundary protection against raw `shell: true` remote-code execution injections. @@ -2011,7 +2129,7 @@ We identified that **155 community PRs** across the entire project history (from ## [3.4.0] - 2026-03-31 -### 🚀 Features +### 功能特点 - **Subscription Utilization Analytics:** Added quota snapshot time-series tracking, Provider Utilization and Combo Health tabs with recharts visualizations, and corresponding API endpoints (#847) - **SQLite Backup Control:** New `OMNIROUTE_DISABLE_AUTO_BACKUP` env flag to disable automatic SQLite backups (#846) @@ -2063,7 +2181,7 @@ We identified that **155 community PRs** across the entire project history (from ## [3.3.8] - 2026-03-30 -### 🚀 Features +### 功能特点 - **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) - **Qoder Integration:** Native integration for Qoder AI natively replacing the legacy iFlow platform mappings (#660) @@ -2889,7 +3007,7 @@ We identified that **155 community PRs** across the entire project history (from - **NaN tokens in Claude Code / client responses (#617):** - `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 -### 🔒 Security +### 安全 - Updated `yaml` package to fix stack overflow vulnerability (GHSA-48c2-rrv3-qjmp) @@ -3565,7 +3683,7 @@ docker pull diegosouzapw/omniroute:3.0.0 - **SVG fallback**: `ProviderIcon` component updated with 4-tier strategy: Lobehub → PNG → SVG → Generic icon - **Agents fingerprinting**: Synced with CLI tools — added droid, openclaw, copilot, opencode to fingerprint list (14 total) -### 🔒 Security +### 安全 - **CVE fix**: Resolved dompurify XSS vulnerability (GHSA-v2wj-7wpq-c8vv) via npm overrides forcing `dompurify@^3.3.2` - `npm audit` now reports **0 vulnerabilities** @@ -3928,7 +4046,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **#510** — Windows: MSYS2/Git-Bash paths (`/c/Program Files/...`) are now normalized to `C:\Program Files\...` - **#492** — `omniroute` CLI now detects `mise`/`nvm` when `app/server.js` is missing and shows targeted fix -### 📖 Documentation +### 文档 - **#513** — Docker password reset: `INITIAL_PASSWORD` env var workaround documented - **#520** — pnpm: `pnpm approve-builds better-sqlite3` documented @@ -4025,7 +4143,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **feat(executors/cloudflare-ai)**: New `CloudflareAIExecutor` — dynamic URL construction requires `accountId` in provider credentials - **feat(executors)**: Register `pollinations`, `pol`, `cloudflare-ai`, `cf` executor mappings -### 📝 Documentation +### 文档 - **docs(readme)**: Expanded free combo stack to 11 providers ($0 forever) - **docs(readme)**: Added 4 new free provider sections (LongCat, Pollinations, Cloudflare AI, Scaleway) with model tables @@ -4177,7 +4295,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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). -### Features +### 功能特点 - **"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. @@ -4205,7 +4323,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Merge PR #494 (MiniMax role fix), fix KIRO MITM dashboard, triage 8 issues. -### Features +### 功能特点 - **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. - **roleNormalizer**: `normalizeDeveloperRole()` now accepts `preserveDeveloperRole` parameter with tri-state behavior (undefined=keep, true=keep, false=convert). @@ -4261,7 +4379,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Gemini CLI deprecation, VM guide i18n fix, dependabot security fix, provider schema expansion. -### Features +### 功能特点 - **Gemini CLI Deprecation** (#462): Mark `gemini-cli` provider as deprecated with warning — Google restricts third-party OAuth usage from March 2026 - **Provider Schema** (#462): Expand Zod validation with `deprecated`, `deprecationReason`, `hasFree`, `freeNote`, `authHint`, `apiHint` optional fields @@ -4270,7 +4388,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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) -### Security +### 安全 - **deps**: Bump `flatted` 3.3.3 → 3.4.2 — fixes CWE-1321 prototype pollution (#484, @dependabot) @@ -4290,7 +4408,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Czech i18n, SSE protocol fix, VM guide translation. -### Features +### 功能特点 - **Czech Language** (#482): Full Czech (cs) i18n — 22 docs, 2606 UI strings, language switcher updates (@zen0bit) - **VM Deployment Guide**: Translated from Portuguese to English as the source document (@zen0bit) @@ -4309,7 +4427,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: 2 merged PRs, model aliases routing fix, log export, and issue triage. -### Features +### 功能特点 - **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) @@ -4329,7 +4447,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Five community PRs — streaming call log fixes, Kiro compatibility, cache token analytics, Chinese translation, and configurable tool call IDs. -### ✨ Features +### 功能特点 - **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) - **feat(providers)**: Per-model configurable 9-char tool call ID normalization (Mistral-style) — only models with the option enabled get truncated IDs (#470) @@ -4359,7 +4477,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Bailian Coding Plan provider with editable base URLs, plus community contributions for Alibaba Cloud and Kimi Coding. -### ✨ Features +### 功能特点 - **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) - **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) @@ -4374,7 +4492,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Two new community-contributed providers (Alibaba Cloud Coding, Kimi Coding API-key) and Docker pino fix. -### ✨ Features +### 功能特点 - **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) - **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) @@ -4399,7 +4517,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Codex responses subpath passthrough natively supported, Windows MITM crash fixed, and Combos agent schemas adjusted. -### ✨ Features +### 功能特点 - **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) @@ -4439,7 +4557,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **fix(budget)**: "Save Limits" no longer returns 422 — `warningThreshold` is now correctly sent as fraction (0–1) instead of percentage (0–100) (#451) - **fix(combos)**: `` internal cache tag is now stripped before forwarding requests to providers, preventing cache session breaks (#454) -### ✨ Features +### 功能特点 - **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) @@ -4495,7 +4613,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: Search Tools dashboard, i18n fixes, Copilot limits, Serper validation fix. -### 🚀 Features +### 功能特点 - **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) - New route: `/dashboard/search-tools` @@ -4595,7 +4713,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - DB migration: `request_type` column on `call_logs` for non-chat request tracking - Zod validation (`v1SearchSchema`), auth-gated, cost recorded via `recordCost()` -### 🔒 Security +### 安全 - **deps**: Next.js 16.1.6 → 16.1.7 — fixes 6 CVEs: - **Critical**: CVE-2026-29057 (HTTP request smuggling via http-proxy) @@ -4725,7 +4843,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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**: New `request_detail_logs` table with 500-entry ring-buffer trigger, opt-in via settings toggle -### ✨ Features +### 功能特点 - **feat(combo)**: System Message Override per Combo (#399 — `system_message` field replaces or injects system prompt before forwarding to provider) - **feat(combo)**: Tool Filter Regex per Combo (#399 — `tool_filter_regex` keeps only tools matching pattern; supports OpenAI + Anthropic formats) @@ -4740,7 +4858,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > Sprint: SSE improvements, local provider_nodes extensions, proxy registry, Claude passthrough fixes. -### ✨ Features +### 功能特点 - **feat(health)**: Background health check for local `provider_nodes` with exponential backoff (30s→300s) and `Promise.allSettled` to avoid blocking (#423, @Regis-RCR) - **feat(embeddings)**: Route `/v1/embeddings` to local `provider_nodes` — `buildDynamicEmbeddingProvider()` with hostname validation (#422, @Regis-RCR) @@ -4882,7 +5000,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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 - **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). -### ✨ Features +### 功能特点 - **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) @@ -4912,7 +5030,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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) - **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) -### ✨ Features +### 功能特点 - **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) - **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. @@ -4971,7 +5089,7 @@ OmniRoute now automatically refreshes model lists for connected providers every - **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) - **fix(logs)**: Request log table is now readable in light mode — status badges, token counts, and combo tags use adaptive `dark:` color classes (#378) -### ✨ Features +### 功能特点 - **feat(kiro)**: Kiro credit tracking added to usage fetcher — queries `getUserCredits` from AWS CodeWhisperer endpoint (#337) @@ -5372,7 +5490,7 @@ OmniRoute now automatically refreshes model lists for connected providers every > **Major release** — Free Stack ecosystem, transcription playground overhaul, 44+ providers, comprehensive free tier documentation, and UI improvements across the board. -### ✨ Features +### 功能特点 - **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. - **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. @@ -5383,7 +5501,7 @@ OmniRoute now automatically refreshes model lists for connected providers every ## [2.3.16] - 2026-03-13 -### 📖 Documentation +### 文档 - **README: 44+ Providers** — Updated all 3 occurrences of "36+ providers" to "44+" reflecting the actual codebase count (44 providers in providers.ts) - **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. @@ -5393,7 +5511,7 @@ OmniRoute now automatically refreshes model lists for connected providers every ## [2.3.15] - 2026-03-13 -### ✨ Features +### 功能特点 - **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. - **i18n — autoCombo section**: Added 20 new translation keys for the Auto-Combo dashboard (`title`, `status`, `modePack`, `providerScores`, `factorTierPriority`, etc.) to all 30 language files. diff --git a/docs/screenshots/10-providers-aitradepulse.png b/docs/screenshots/10-providers-aitradepulse.png new file mode 100644 index 0000000000..f0f6324d2b Binary files /dev/null and b/docs/screenshots/10-providers-aitradepulse.png differ diff --git a/docs/screenshots/11-combos-aitradepulse.png b/docs/screenshots/11-combos-aitradepulse.png new file mode 100644 index 0000000000..ded3f6a9e6 Binary files /dev/null and b/docs/screenshots/11-combos-aitradepulse.png differ diff --git a/docs/screenshots/ai-aitradepulse-dashboard.png b/docs/screenshots/ai-aitradepulse-dashboard.png new file mode 100644 index 0000000000..5dac9818a5 Binary files /dev/null and b/docs/screenshots/ai-aitradepulse-dashboard.png differ diff --git a/open-sse/config/audioRegistry.ts b/open-sse/config/audioRegistry.ts index b0c18cafd0..359214aabb 100644 --- a/open-sse/config/audioRegistry.ts +++ b/open-sse/config/audioRegistry.ts @@ -17,6 +17,7 @@ export interface AudioProvider { authType: string; authHeader: string; format?: string; + supportedFormats?: string[]; async?: boolean; models: AudioModel[]; } @@ -124,8 +125,8 @@ export const AUDIO_SPEECH_PROVIDERS: Record = { authType: "apikey", authHeader: "bearer", models: [ - { id: "tts-1", name: "TTS 1" }, { id: "tts-1-hd", name: "TTS 1 HD" }, + { id: "tts-1", name: "TTS 1" }, { id: "gpt-4o-mini-tts", name: "GPT-4o Mini TTS" }, ], }, @@ -226,8 +227,9 @@ export const AUDIO_SPEECH_PROVIDERS: Record = { authType: "apikey", authHeader: "basic", format: "inworld", + supportedFormats: ["mp3", "wav", "opus", "pcm"], models: [ - { id: "inworld-tts-1.5-max", name: "Inworld TTS 1.5 Max" }, + { id: "inworld-tts-2", name: "Inworld TTS 2" }, { id: "inworld-tts-1.5-mini", name: "Inworld TTS 1.5 Mini" }, ], }, @@ -242,8 +244,8 @@ export const AUDIO_SPEECH_PROVIDERS: Record = { authHeader: "x-api-key", format: "cartesia", models: [ - { id: "sonic-2", name: "Sonic 2" }, { id: "sonic-3", name: "Sonic 3" }, + { id: "sonic-2", name: "Sonic 2" }, ], }, @@ -297,6 +299,7 @@ export const AUDIO_SPEECH_PROVIDERS: Record = { authType: "apikey", authHeader: "bearer", format: "xiaomi-mimo-tts", + supportedFormats: ["mp3", "wav"], models: [ { id: "mimo-v2.5-tts", name: "MiMo V2.5 TTS" }, { id: "mimo-v2.5-tts-voicedesign", name: "MiMo V2.5 Voice Design" }, diff --git a/open-sse/config/errorConfig.ts b/open-sse/config/errorConfig.ts index 84c6df8bd4..3bcad8edcc 100644 --- a/open-sse/config/errorConfig.ts +++ b/open-sse/config/errorConfig.ts @@ -105,6 +105,18 @@ export const ERROR_RULES: ErrorRule[] = [ backoff: true, reason: "rate_limit_exceeded", }, + { + id: "hour_quota_exceeded", + text: "hour quota", + backoff: true, + reason: "quota_exhausted", + }, + { + id: "quota_has_been_exceeded", + text: "quota has been exceeded", + backoff: true, + reason: "quota_exhausted", + }, { id: "quota_exceeded", text: "quota exceeded", diff --git a/open-sse/config/providerHeaderProfiles.ts b/open-sse/config/providerHeaderProfiles.ts index 99cf3386bb..2e58750055 100644 --- a/open-sse/config/providerHeaderProfiles.ts +++ b/open-sse/config/providerHeaderProfiles.ts @@ -186,17 +186,3 @@ export function getCursorRegistryHeaders( "User-Agent": getCursorUserAgent(version), }; } - -export function getCursorUsageHeaders( - accessToken: string, - version = CURSOR_REGISTRY_VERSION -): Record { - const userAgent = getCursorUserAgent(version); - return { - Authorization: `Bearer ${accessToken}`, - Accept: "application/json", - "User-Agent": userAgent, - "x-cursor-client-version": version, - "x-cursor-user-agent": userAgent, - }; -} diff --git a/open-sse/config/providerRegistry.ts b/open-sse/config/providerRegistry.ts index 52e769aa19..df4ae34c3d 100644 --- a/open-sse/config/providerRegistry.ts +++ b/open-sse/config/providerRegistry.ts @@ -553,20 +553,24 @@ export const REGISTRY: Record = { defaultContextLength: 128000, headers: getGitHubCopilotChatHeaders(), models: [ - { id: "gpt-5-mini", name: "GPT-5 Mini" }, + { id: "gpt-5-mini", name: "GPT-5 Mini", targetFormat: "openai-responses" }, { id: "gpt-5.3-codex", name: "GPT-5.3 Codex", targetFormat: "openai-responses" }, { id: "gpt-5.4-mini", name: "GPT-5.4 Mini", targetFormat: "openai-responses" }, { id: "gpt-5.4", name: "GPT-5.4", targetFormat: "openai-responses" }, { id: "gpt-5.5", name: "GPT-5.5", ...GPT_5_5_CODEX_CAPABILITIES }, - { id: "claude-haiku-4.5", name: "Claude Haiku 4.5" }, - { id: "claude-sonnet-4.5", name: "Claude Sonnet 4.5" }, - { id: "claude-sonnet-4.6", name: "Claude Sonnet 4.6" }, - { id: "claude-opus-4-5-20251101", name: "Claude Opus 4.5 (Full ID)" }, - { id: "claude-opus-4.6", name: "Claude Opus 4.6" }, - { id: "claude-opus-4.7", name: "Claude Opus 4.7" }, - { id: "gemini-3.1-pro-preview", name: "Gemini 3.1 Pro" }, - { id: "gemini-3-flash-preview", name: "Gemini 3 Flash" }, - { id: "oswe-vscode-prime", name: "Raptor Mini" }, + { id: "claude-haiku-4.5", name: "Claude Haiku 4.5", targetFormat: "openai-responses" }, + { id: "claude-sonnet-4.5", name: "Claude Sonnet 4.5", targetFormat: "openai-responses" }, + { id: "claude-sonnet-4.6", name: "Claude Sonnet 4.6", targetFormat: "openai-responses" }, + { + id: "claude-opus-4-5-20251101", + name: "Claude Opus 4.5 (Full ID)", + targetFormat: "openai-responses", + }, + { id: "claude-opus-4.6", name: "Claude Opus 4.6", targetFormat: "openai-responses" }, + { id: "claude-opus-4.7", name: "Claude Opus 4.7", targetFormat: "openai-responses" }, + { id: "gemini-3.1-pro-preview", name: "Gemini 3.1 Pro", targetFormat: "openai-responses" }, + { id: "gemini-3-flash-preview", name: "Gemini 3 Flash", targetFormat: "openai-responses" }, + { id: "oswe-vscode-prime", name: "Raptor Mini", targetFormat: "openai-responses" }, //{ id: "?", name: "Goldeneye" }, ], }, @@ -586,14 +590,26 @@ export const REGISTRY: Record = { authUrl: "https://prod.us-east-1.auth.desktop.kiro.dev", }, models: [ - { id: "claude-opus-4.7", name: "Claude Opus 4.7" }, + { id: "auto-kiro", name: "Auto (Kiro picks best model)" }, { id: "claude-opus-4.6", name: "Claude Opus 4.6" }, + { id: "claude-opus-4.5", name: "Claude Opus 4.5" }, { id: "claude-sonnet-4.6", name: "Claude Sonnet 4.6" }, { id: "claude-sonnet-4.5", name: "Claude Sonnet 4.5" }, + { id: "claude-sonnet-4", name: "Claude Sonnet 4" }, { id: "claude-haiku-4.5", name: "Claude Haiku 4.5" }, - //{ id: "?", name: "DeepSeek V3.2" }, - //{ id: "?", name: "MiniMax M2.5" }, - //{ id: "?", name: "GLM-5" }, + { id: "claude-3.7-sonnet", name: "Claude 3.7 Sonnet" }, + // Dash aliases — Claude Code sends dashes, Kiro API uses dots + { id: "claude-opus-4-6", name: "Claude Opus 4.6" }, + { id: "claude-opus-4-5", name: "Claude Opus 4.5" }, + { id: "claude-sonnet-4-6", name: "Claude Sonnet 4.6" }, + { id: "claude-sonnet-4-5", name: "Claude Sonnet 4.5" }, + { id: "claude-haiku-4-5", name: "Claude Haiku 4.5" }, + // Non-Claude models on Kiro subscription + { id: "deepseek-3.2", name: "DeepSeek V3.2" }, + { id: "minimax-m2.5", name: "MiniMax M2.5" }, + { id: "minimax-m2.1", name: "MiniMax M2.1" }, + { id: "glm-5", name: "GLM-5" }, + { id: "qwen3-coder-next", name: "Qwen3 Coder Next" }, ], }, diff --git a/open-sse/config/runway.ts b/open-sse/config/runway.ts index a76719d757..165a9af4c2 100644 --- a/open-sse/config/runway.ts +++ b/open-sse/config/runway.ts @@ -6,11 +6,9 @@ export const RUNWAYML_SUPPORTED_VIDEO_MODELS = [ { id: "gen4_turbo", name: "Gen-4 Turbo" }, { id: "veo3.1", name: "Veo 3.1" }, { id: "veo3.1_fast", name: "Veo 3.1 Fast" }, - { id: "veo3", name: "Veo 3" }, - { id: "gen3a_turbo", name: "Gen-3 Alpha Turbo" }, ]; -export const RUNWAYML_IMAGE_REQUIRED_MODELS = new Set(["gen4_turbo", "gen3a_turbo"]); +export const RUNWAYML_IMAGE_REQUIRED_MODELS = new Set(["gen4_turbo"]); export function normalizeRunwayBaseUrl(baseUrl?: string | null) { const normalized = String(baseUrl || "") diff --git a/open-sse/executors/pollinations.ts b/open-sse/executors/pollinations.ts index 653026fdf3..cd6219d8f1 100644 --- a/open-sse/executors/pollinations.ts +++ b/open-sse/executors/pollinations.ts @@ -42,7 +42,9 @@ export class PollinationsExecutor extends BaseExecutor { } transformRequest(model: string, body: any, _stream: boolean, _credentials: any): any { - // Pollinations uses provider aliases directly: "openai", "claude", "gemini", etc. + if (typeof body === "object" && body !== null) { + body.jsonMode = true; + } return body; } } diff --git a/open-sse/handlers/audioSpeech.ts b/open-sse/handlers/audioSpeech.ts index 2342a6d9ea..ffa2542aa8 100644 --- a/open-sse/handlers/audioSpeech.ts +++ b/open-sse/handlers/audioSpeech.ts @@ -428,7 +428,21 @@ async function handleHuggingFaceTtsSpeech(providerConfig, body, modelId, token) * POST { text, voiceId, modelId, audioConfig } → JSON { audioContent: "" } * Docs: https://docs.inworld.ai/api-reference/ttsAPI/texttospeech/synthesize-speech */ +const INWORLD_AUDIO_FORMATS = { + mp3: { audioEncoding: "MP3", mimeType: "audio/mpeg" }, + wav: { audioEncoding: "WAV", mimeType: "audio/wav" }, + opus: { audioEncoding: "OPUS", mimeType: "audio/opus" }, + pcm: { audioEncoding: "PCM", mimeType: "audio/pcm" }, +}; + async function handleInworldSpeech(providerConfig, body, modelId, token) { + const requestedFormat = + typeof body.response_format === "string" ? body.response_format.toLowerCase() : "mp3"; + const audioFormat = INWORLD_AUDIO_FORMATS[requestedFormat]; + if (!audioFormat) { + return errorResponse(400, "Inworld TTS supports response_format mp3, wav, opus, or pcm only"); + } + const res = await fetch(providerConfig.baseUrl, { method: "POST", headers: { @@ -440,7 +454,7 @@ async function handleInworldSpeech(providerConfig, body, modelId, token) { voiceId: body.voice || undefined, modelId, audioConfig: { - audioEncoding: body.response_format === "wav" ? "LINEAR16" : "MP3", + audioEncoding: audioFormat.audioEncoding, }, }), }); @@ -452,7 +466,10 @@ async function handleInworldSpeech(providerConfig, body, modelId, token) { const data = await res.json(); // Decode base64 audioContent to binary const audioBuffer = Uint8Array.from(atob(data.audioContent ?? ""), (c) => c.charCodeAt(0)); - const mimeType = body.response_format === "wav" ? "audio/wav" : "audio/mpeg"; + const mimeType = + typeof data.contentType === "string" && data.contentType + ? data.contentType + : audioFormat.mimeType; return new Response(audioBuffer, { status: 200, diff --git a/open-sse/handlers/chatCore.ts b/open-sse/handlers/chatCore.ts index fbcde7c28c..5e60a86260 100644 --- a/open-sse/handlers/chatCore.ts +++ b/open-sse/handlers/chatCore.ts @@ -32,6 +32,7 @@ import { import { COOLDOWN_MS, HTTP_STATUS, + FETCH_BODY_TIMEOUT_MS, MAX_TOOLS_LIMIT, PROVIDER_MAX_TOKENS, STREAM_IDLE_TIMEOUT_MS, @@ -574,6 +575,146 @@ function normalizeNonStreamingEventPayload(rawBody: string, contentType: string) return rawBody; } +const NON_STREAMING_SSE_TERMINAL_TYPES = new Set([ + "message_stop", + "response.completed", + "response.done", + "response.cancelled", + "response.canceled", + "response.failed", + "response.incomplete", +]); + +type NonStreamingSseTerminalState = { + currentEvent: string; + pendingLine: string; +}; + +function processNonStreamingSseTerminalLine( + state: NonStreamingSseTerminalState, + rawLine: string +): boolean { + const trimmed = rawLine.trim(); + if (!trimmed || trimmed.startsWith(":")) { + if (!trimmed) state.currentEvent = ""; + return false; + } + + if (trimmed.startsWith("event:")) { + state.currentEvent = trimmed.slice(6).trim(); + return false; + } + + if (!trimmed.startsWith("data:")) return false; + const data = trimmed.slice(5).trim(); + if (data === "[DONE]") return true; + if (!data) return false; + + try { + const parsed = JSON.parse(data); + const eventType = + parsed && typeof parsed === "object" && typeof parsed.type === "string" + ? parsed.type + : state.currentEvent; + return NON_STREAMING_SSE_TERMINAL_TYPES.has(eventType); + } catch { + // Keep reading malformed data so the parser can report a useful upstream error. + return false; + } +} + +function appendNonStreamingSseTerminalSignal( + state: NonStreamingSseTerminalState, + chunk: string +): boolean { + const lines = `${state.pendingLine}${chunk}`.split(/\r?\n/); + state.pendingLine = lines.pop() ?? ""; + + for (const rawLine of lines) { + if (processNonStreamingSseTerminalLine(state, rawLine)) return true; + } + + return false; +} + +function createBodyTimeoutError(timeoutMs: number): Error { + const err = new Error(`Response body read timeout after ${timeoutMs}ms`); + err.name = "BodyTimeoutError"; + return err; +} + +function readStreamChunkWithTimeout( + reader: ReadableStreamDefaultReader, + timeoutMs: number +): Promise> { + if (timeoutMs <= 0) return reader.read(); + + return new Promise((resolve, reject) => { + const timeout = setTimeout(() => reject(createBodyTimeoutError(timeoutMs)), timeoutMs); + reader.read().then( + (value) => { + clearTimeout(timeout); + resolve(value); + }, + (error) => { + clearTimeout(timeout); + reject(error); + } + ); + }); +} + +async function readNonStreamingResponseBody( + response: Response, + contentType: string, + upstreamStream: boolean +): Promise { + if ( + !upstreamStream || + !response.body || + (!contentType.includes("text/event-stream") && !contentType.includes("application/x-ndjson")) + ) { + return withBodyTimeout(response.text()); + } + + const reader = response.body.getReader(); + const decoder = new TextDecoder(); + const terminalState: NonStreamingSseTerminalState = { + currentEvent: "", + pendingLine: "", + }; + let rawBody = ""; + const deadline = FETCH_BODY_TIMEOUT_MS > 0 ? Date.now() + FETCH_BODY_TIMEOUT_MS : 0; + + try { + while (true) { + const timeoutMs = deadline > 0 ? deadline - Date.now() : 0; + if (deadline > 0 && timeoutMs <= 0) { + throw createBodyTimeoutError(FETCH_BODY_TIMEOUT_MS); + } + + const { done, value } = await readStreamChunkWithTimeout(reader, timeoutMs); + if (done) break; + if (!value) continue; + + const decodedChunk = decoder.decode(value, { stream: true }); + rawBody += decodedChunk; + if (appendNonStreamingSseTerminalSignal(terminalState, decodedChunk)) { + await reader.cancel("non-streaming bridge consumed terminal SSE event").catch(() => {}); + break; + } + } + } catch (error) { + await reader.cancel(error).catch(() => {}); + throw error; + } finally { + rawBody += decoder.decode(); + reader.releaseLock(); + } + + return rawBody; +} + function getHeaderValueCaseInsensitive( headers: Record | Headers | null | undefined, targetName: string @@ -602,14 +743,39 @@ function toFiniteNumberOrNull(value: unknown): number | null { return null; } -function isSemaphoreTimeoutError(error: unknown): error is Error & { code: string } { +function isSemaphoreCapacityError(error: unknown): error is Error & { code: string } { return ( !!error && typeof error === "object" && - (error as { code?: unknown }).code === "SEMAPHORE_TIMEOUT" + ((error as { code?: unknown }).code === "SEMAPHORE_TIMEOUT" || + (error as { code?: unknown }).code === "SEMAPHORE_QUEUE_FULL") ); } +function createStreamingErrorResult(statusCode: number, message: string, code?: string) { + const errorBody = buildErrorBody(statusCode, message); + if (code) { + errorBody.error.code = code; + } + + const body = `data: ${JSON.stringify(errorBody)}\n\ndata: [DONE]\n\n`; + + return { + success: false as const, + status: statusCode, + error: message, + response: new Response(body, { + status: statusCode, + headers: { + "Content-Type": "text/event-stream", + "Cache-Control": "no-cache, no-transform", + Connection: "keep-alive", + "X-Accel-Buffering": "no", + }, + }), + }; +} + function wrapReadableStreamWithFinalize( readable: ReadableStream, finalize: () => void @@ -2959,7 +3125,12 @@ export async function handleChatCore({ const status = rawResult.response.status; const statusText = rawResult.response.statusText; const headers = new Headers(rawResult.response.headers); - const payload = await withBodyTimeout(rawResult.response.text()); + const contentType = (headers.get("content-type") || "").toLowerCase(); + const payload = await readNonStreamingResponseBody( + rawResult.response, + contentType, + upstreamStream + ); acquireAccountSemaphoreRelease(); return { @@ -2969,7 +3140,11 @@ export async function handleChatCore({ _dedupSnapshot: { status, statusText, - headers: Array.from(headers.entries()), + headers: (() => { + const arr: [string, string][] = []; + headers.forEach((v, k) => arr.push([k, v])); + return arr; + })(), payload, }, }; @@ -3051,16 +3226,13 @@ export async function handleChatCore({ ); } catch (error) { trackPendingRequest(model, provider, connectionId, false); - if (isSemaphoreTimeoutError(error)) { + if (isSemaphoreCapacityError(error)) { appendRequestLog({ model, provider, connectionId, status: `FAILED ${error.code}`, }).catch(() => {}); - if (isCombo) { - throw error; - } const failureMessage = error.message || "Semaphore timeout"; persistAttemptLogs({ status: HTTP_STATUS.RATE_LIMITED, @@ -3071,7 +3243,14 @@ export async function handleChatCore({ cacheSource: "upstream", }); persistFailureUsage(HTTP_STATUS.RATE_LIMITED, error.code); - return createErrorResult(HTTP_STATUS.RATE_LIMITED, failureMessage); + const result = stream + ? createStreamingErrorResult(HTTP_STATUS.RATE_LIMITED, failureMessage, error.code) + : createErrorResult(HTTP_STATUS.RATE_LIMITED, failureMessage); + return { + ...result, + errorType: "account_semaphore_capacity", + errorCode: error.code, + }; } const failureStatus = error.name === "AbortError" @@ -3220,6 +3399,8 @@ export async function handleChatCore({ let statusCode = providerResponse.status; let message = ""; let retryAfterMs: number | null = null; + let upstreamErrorCode: string | undefined; + let upstreamErrorType: string | undefined; if (upstreamErrorParsed) { statusCode = parsedStatusCode; @@ -3231,6 +3412,8 @@ export async function handleChatCore({ message = details.message; retryAfterMs = details.retryAfterMs; upstreamErrorBody = details.responseBody; + upstreamErrorCode = details.errorCode; + upstreamErrorType = details.errorType; } // T06/T10/T36: classify provider errors and persist terminal account states. @@ -3399,7 +3582,13 @@ export async function handleChatCore({ cacheSource: "upstream", }); persistFailureUsage(statusCode, "model_unavailable"); - return createErrorResult(statusCode, errMsg, retryAfterMs); + return createErrorResult( + statusCode, + errMsg, + retryAfterMs, + upstreamErrorCode, + upstreamErrorType + ); } } catch { persistAttemptLogs({ @@ -3411,7 +3600,13 @@ export async function handleChatCore({ cacheSource: "upstream", }); persistFailureUsage(statusCode, "model_unavailable"); - return createErrorResult(statusCode, errMsg, retryAfterMs); + return createErrorResult( + statusCode, + errMsg, + retryAfterMs, + upstreamErrorCode, + upstreamErrorType + ); } } else { persistAttemptLogs({ @@ -3423,7 +3618,13 @@ export async function handleChatCore({ cacheSource: "upstream", }); persistFailureUsage(statusCode, "model_unavailable"); - return createErrorResult(statusCode, errMsg, retryAfterMs); + return createErrorResult( + statusCode, + errMsg, + retryAfterMs, + upstreamErrorCode, + upstreamErrorType + ); } } else if (isContextOverflowError(statusCode, message)) { const familyCandidates = getModelFamily(currentModel).filter( @@ -3459,7 +3660,13 @@ export async function handleChatCore({ cacheSource: "upstream", }); persistFailureUsage(statusCode, "context_overflow"); - return createErrorResult(statusCode, errMsg, retryAfterMs); + return createErrorResult( + statusCode, + errMsg, + retryAfterMs, + upstreamErrorCode, + upstreamErrorType + ); } } catch { persistAttemptLogs({ @@ -3471,7 +3678,13 @@ export async function handleChatCore({ cacheSource: "upstream", }); persistFailureUsage(statusCode, "context_overflow"); - return createErrorResult(statusCode, errMsg, retryAfterMs); + return createErrorResult( + statusCode, + errMsg, + retryAfterMs, + upstreamErrorCode, + upstreamErrorType + ); } } else { persistAttemptLogs({ @@ -3483,7 +3696,13 @@ export async function handleChatCore({ cacheSource: "upstream", }); persistFailureUsage(statusCode, "context_overflow"); - return createErrorResult(statusCode, errMsg, retryAfterMs); + return createErrorResult( + statusCode, + errMsg, + retryAfterMs, + upstreamErrorCode, + upstreamErrorType + ); } } else { persistAttemptLogs({ @@ -3566,7 +3785,13 @@ export async function handleChatCore({ } if (!emergencyFallbackServed) { - return createErrorResult(statusCode, errMsg, retryAfterMs); + return createErrorResult( + statusCode, + errMsg, + retryAfterMs, + upstreamErrorCode, + upstreamErrorType + ); } } // ── End T5 ─────────────────────────────────────────────────────────────── @@ -3578,7 +3803,11 @@ export async function handleChatCore({ const contentType = (providerResponse.headers.get("content-type") || "").toLowerCase(); let responseBody; let responsePayloadFormat = targetFormat; - const rawBody = await withBodyTimeout(providerResponse.text()); + const rawBody = await readNonStreamingResponseBody( + providerResponse, + contentType, + upstreamStream + ); const normalizedProviderPayload = normalizePayloadForLog(rawBody); const looksLikeSSE = contentType.includes("text/event-stream") || @@ -4038,9 +4267,11 @@ export async function handleChatCore({ const responseHeaders: Record = { ...Object.fromEntries( - Array.from(providerResponse.headers.entries()).filter( - ([k]) => k.toLowerCase() !== "content-type" - ) + (() => { + const arr: [string, string][] = []; + providerResponse.headers.forEach((v, k) => arr.push([k, v])); + return arr; + })().filter(([k]) => k.toLowerCase() !== "content-type") ), "Content-Type": "text/event-stream", "Cache-Control": "no-cache, no-transform", diff --git a/open-sse/handlers/sseParser.ts b/open-sse/handlers/sseParser.ts index 44beadf0da..7432590a4f 100644 --- a/open-sse/handlers/sseParser.ts +++ b/open-sse/handlers/sseParser.ts @@ -22,9 +22,19 @@ function readSSEEvents(rawSSE) { } try { + const data = JSON.parse(payload); + if ( + currentEvent && + data && + typeof data === "object" && + !Array.isArray(data) && + typeof data.type !== "string" + ) { + data.type = currentEvent; + } events.push({ event: currentEvent || undefined, - data: JSON.parse(payload), + data, }); } catch { // Ignore malformed SSE events and continue best-effort parsing. @@ -41,12 +51,21 @@ function readSSEEvents(rawSSE) { } if (line.startsWith("event:")) { + // Some relays omit the blank separator between Claude events. Flush the + // previous event before accepting the next event name. + if (currentData.length > 0) flush(); currentEvent = line.slice(6).trim(); continue; } if (line.startsWith("data:")) { - currentData.push(line.slice(5).trimStart()); + const dataLine = line.slice(5).trimStart(); + if (dataLine.trim() === "[DONE]") { + flush(); + currentEvent = ""; + continue; + } + currentData.push(dataLine); } } diff --git a/open-sse/services/accountFallback.ts b/open-sse/services/accountFallback.ts index 446b9510c1..7ec998d196 100644 --- a/open-sse/services/accountFallback.ts +++ b/open-sse/services/accountFallback.ts @@ -22,10 +22,14 @@ import { getCircuitBreaker, STATE, } from "../../src/shared/utils/circuitBreaker"; +import { classify429FromError, type FailureKind } from "../../src/shared/utils/classify429"; +import { resolveUseUpstream429BreakerHints } from "../../src/shared/utils/providerHints"; type ProviderProfile = { baseCooldownMs: number; useUpstreamRetryHints: boolean; + /** Issue #2100 follow-up. Stored override; undefined → per-provider default. */ + useUpstream429BreakerHints?: boolean; maxBackoffSteps: number; failureThreshold: number; resetTimeoutMs: number; @@ -182,6 +186,9 @@ function buildProviderProfile( return { baseCooldownMs: connectionCooldown.baseCooldownMs, useUpstreamRetryHints: connectionCooldown.useUpstreamRetryHints, + // Issue #2100 follow-up: propagate stored override (boolean | undefined) + // so the runtime resolver picks user setting first, then per-provider default. + useUpstream429BreakerHints: connectionCooldown.useUpstream429BreakerHints, maxBackoffSteps: connectionCooldown.maxBackoffSteps, failureThreshold: providerBreaker.failureThreshold, resetTimeoutMs: providerBreaker.resetTimeoutMs, @@ -532,9 +539,23 @@ function configureProviderBreaker( if (!provider) return null; const resolvedProfile = { ...getProviderProfile(provider), ...(profile ?? {}) }; + // Issue #2100 follow-up: resolve useUpstream429BreakerHints from the + // provider profile (stored override) or fall back to per-provider default. + // Stored value type is `boolean | undefined` — never `null` after PATCH. + const userValue = resolvedProfile.useUpstream429BreakerHints; + const useHints = resolveUseUpstream429BreakerHints(provider, userValue); return getCircuitBreaker(provider, { failureThreshold: resolvedProfile.failureThreshold ?? resolvedProfile.circuitBreakerThreshold, resetTimeout: resolvedProfile.resetTimeoutMs ?? resolvedProfile.circuitBreakerReset, + ...(useHints + ? { + cooldownByKind: { + rate_limit: 60_000, + quota_exhausted: 3_600_000, + } satisfies Partial>, + classifyError: classify429FromError, + } + : {}), }); } @@ -755,6 +776,8 @@ export function classifyErrorText(errorText) { lower.includes("quota depleted") || lower.includes("quota will reset") || lower.includes("your quota will reset") || + lower.includes("quota has been exceeded") || + lower.includes("hour quota") || lower.includes("billing") ) { return RateLimitReason.QUOTA_EXHAUSTED; @@ -1038,7 +1061,9 @@ export function checkFallbackError( status === HTTP_STATUS.FORBIDDEN && provider && getProviderCategory(provider) === "apikey" && - !errorStr.toLowerCase().includes("has not been used in project") + !errorStr.toLowerCase().includes("has not been used in project") && + !errorStr.toLowerCase().includes("hour quota") && + !errorStr.toLowerCase().includes("quota has been exceeded") ) { return buildRetryableFallback(RateLimitReason.AUTH_ERROR); } diff --git a/open-sse/services/usage.ts b/open-sse/services/usage.ts index 8424b89af2..86187a01a0 100644 --- a/open-sse/services/usage.ts +++ b/open-sse/services/usage.ts @@ -9,11 +9,7 @@ import { } from "../config/antigravityUpstream.ts"; import { isUserCallableAntigravityModelId } from "../config/antigravityModelAliases.ts"; import { getGlmQuotaUrl } from "../config/glmProvider.ts"; -import { - CURSOR_REGISTRY_VERSION, - getCursorUsageHeaders, - getGitHubCopilotInternalUserHeaders, -} from "../config/providerHeaderProfiles.ts"; +import { getGitHubCopilotInternalUserHeaders } from "../config/providerHeaderProfiles.ts"; import { safePercentage } from "@/shared/utils/formatting"; import { fetchBailianQuota, type BailianTripleWindowQuota } from "./bailianQuotaFetcher.ts"; import { fetchDeepseekQuota, type DeepseekQuota } from "./deepseekQuotaFetcher.ts"; @@ -72,17 +68,22 @@ const KIMI_CONFIG = { apiVersion: "2023-06-01", }; -const CURSOR_USAGE_CONFIG = { - usageUrl: "https://www.cursor.com/api/usage", - userMetaUrl: "https://www.cursor.com/api/auth/me", - subscriptionUrl: "https://www.cursor.com/api/subscription", - clientVersion: CURSOR_REGISTRY_VERSION, -}; - const NANOGPT_CONFIG = { usageUrl: "https://nano-gpt.com/api/subscription/v1/usage", }; +// Cursor dashboard usage API config +// The endpoint that powers https://cursor.com/dashboard/spending. Validates the WorkOS +// session via the WorkosCursorSessionToken cookie (format: `${userId}::${jwt}`) and +// rejects requests without a matching Origin/Referer (Invalid origin for state-changing request). +const CURSOR_USAGE_CONFIG = { + usageUrl: "https://cursor.com/api/dashboard/get-current-period-usage", + origin: "https://cursor.com", + referer: "https://cursor.com/dashboard/spending", + userAgent: + "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36", +}; + const MINIMAX_USAGE_CONFIG = { minimax: { usageUrls: [ @@ -156,6 +157,12 @@ function getGlmTokenQuotaName( return existingQuotas.session ? "weekly" : "session"; } +function getGlmQuotaDisplayName(quotaName: string): string { + if (quotaName === "session") return "5 Hours Quota"; + if (quotaName === "weekly") return "Weekly Quota"; + return quotaName; +} + function getFieldValue(source: unknown, snakeKey: string, camelKey: string): unknown { const obj = toRecord(source); return obj[snakeKey] ?? obj[camelKey] ?? null; @@ -635,6 +642,13 @@ async function getGlmUsage(apiKey: string, providerSpecificData?: Record ({ + name: String(m.model || ""), + used: toNumber(m.percentage, 0), + })) + : [], unlimited: false, }; continue; @@ -846,6 +860,143 @@ async function getNanoGptUsage(apiKey: string) { } } +/** + * Decode the `sub` claim of a Cursor JWT (the WorkOS user id). + * Returns null if the token is not a parseable JWT. + */ +function decodeCursorJwtSub(token: string): string | null { + if (!token || typeof token !== "string") return null; + const parts = token.split("."); + if (parts.length !== 3) return null; + try { + let payload = parts[1].replace(/-/g, "+").replace(/_/g, "/"); + while (payload.length % 4 !== 0) payload += "="; + const decoded = JSON.parse(Buffer.from(payload, "base64").toString("utf8")); + const sub = decoded?.sub; + return typeof sub === "string" && sub.length > 0 ? sub : null; + } catch { + return null; + } +} + +/** + * Cursor Pro Plan Usage + * Fetches current-billing-cycle spend from the cursor.com dashboard API and exposes three + * windows that mirror the cursor.com/dashboard/spending UI: Total / Auto + Composer / API. + */ +async function getCursorUsage(accessToken: string, providerSpecificData?: unknown) { + if (!accessToken) { + return { message: "Cursor access token missing. Re-import the connection from Cursor IDE." }; + } + + const storedUserId = (() => { + const raw = toRecord(providerSpecificData).userId; + return typeof raw === "string" && raw.length > 0 ? raw : null; + })(); + const userId = storedUserId || decodeCursorJwtSub(accessToken); + + if (!userId) { + return { + message: "Cursor token missing user id. Re-import the connection from Cursor IDE.", + }; + } + + try { + const response = await fetch(CURSOR_USAGE_CONFIG.usageUrl, { + method: "POST", + redirect: "manual", + headers: { + Cookie: `WorkosCursorSessionToken=${userId}::${accessToken}`, + Origin: CURSOR_USAGE_CONFIG.origin, + Referer: CURSOR_USAGE_CONFIG.referer, + "Content-Type": "application/json", + Accept: "application/json", + "User-Agent": CURSOR_USAGE_CONFIG.userAgent, + }, + body: "{}", + }); + + // 3xx redirect to WorkOS authkit means the session cookie was rejected. + if (response.status >= 300 && response.status < 400) { + return { + plan: "Cursor", + message: "Cursor session expired. Re-import the token from Cursor IDE.", + }; + } + + if (!response.ok) { + const errorText = (await response.text()).slice(0, 200); + if (response.status === 401 || response.status === 403) { + return { + plan: "Cursor", + message: "Cursor session unauthorized. Re-import the token from Cursor IDE.", + }; + } + return { + plan: "Cursor", + message: `Cursor usage endpoint error (${response.status}): ${errorText}`, + }; + } + + const data = toRecord(await response.json()); + const planUsage = toRecord(data.planUsage); + + if (Object.keys(planUsage).length === 0) { + return { + plan: "Cursor", + message: "Cursor connected. No active plan usage returned.", + }; + } + + const limitCents = Math.max(0, toNumber(planUsage.limit, 0)); + const totalSpendCents = Math.max(0, toNumber(planUsage.totalSpend, 0)); + const autoPercentUsed = clampPercentage(toNumber(planUsage.autoPercentUsed, 0)); + const apiPercentUsed = clampPercentage(toNumber(planUsage.apiPercentUsed, 0)); + const totalPercentUsed = clampPercentage(toNumber(planUsage.totalPercentUsed, 0)); + + // billingCycleEnd is a numeric-string in ms; coerce so parseResetTime sees a number. + const billingCycleEndMs = toNumber(data.billingCycleEnd, 0); + const resetAt = billingCycleEndMs > 0 ? parseResetTime(billingCycleEndMs) : null; + + // Convert cents → dollars rounded to 2 decimal places. + const toDollars = (cents: number) => Math.round(cents) / 100; + + const limitDollars = toDollars(limitCents); + const buildWindow = (percentUsed: number, usedCentsOverride?: number): UsageQuota => { + const usedCents = + typeof usedCentsOverride === "number" + ? usedCentsOverride + : Math.round((limitCents * percentUsed) / 100); + const used = toDollars(Math.min(usedCents, limitCents)); + const remaining = toDollars(Math.max(limitCents - Math.min(usedCents, limitCents), 0)); + return { + used, + total: limitDollars, + remaining, + remainingPercentage: clampPercentage(100 - percentUsed), + resetAt, + unlimited: false, + }; + }; + + const quotas: Record = { + Total: buildWindow(totalPercentUsed, totalSpendCents), + "Auto + Composer": buildWindow(autoPercentUsed), + API: buildWindow(apiPercentUsed), + }; + + return { + plan: "Cursor Pro", + quotas, + }; + } catch (error) { + return { + plan: "Cursor", + message: `Cursor connected. Unable to fetch usage: ${(error as Error).message}`, + }; + } +} + /** * Get usage data for a provider connection * @param {Object} connection - Provider connection with accessToken @@ -865,6 +1016,8 @@ export async function getUsageForProvider(connection, options: { forceRefresh?: return await getClaudeUsage(accessToken); case "codex": return await getCodexUsage(accessToken, providerSpecificData); + case "cursor": + return await getCursorUsage(accessToken, providerSpecificData); case "kiro": case "amazon-q": return await getKiroUsage(accessToken, providerSpecificData); @@ -876,6 +1029,7 @@ export async function getUsageForProvider(connection, options: { forceRefresh?: return await getQoderUsage(accessToken); case "glm": case "glm-cn": + case "zai": case "glmt": return await getGlmUsage(apiKey, { ...(providerSpecificData || {}), @@ -886,8 +1040,6 @@ export async function getUsageForProvider(connection, options: { forceRefresh?: return await getMiniMaxUsage(apiKey, provider); case "crof": return await getCrofUsage(apiKey); - case "cursor": - return await getCursorUsage(accessToken); case "bailian-coding-plan": return await getBailianCodingPlanUsage(id, apiKey, providerSpecificData); case "nanogpt": @@ -1120,172 +1272,6 @@ function inferGitHubPlanName(data: JsonRecord, premiumQuota: UsageQuota | null): return "GitHub Copilot"; } -function buildCursorUsageHeaders(accessToken: string): Record { - return getCursorUsageHeaders(accessToken, CURSOR_USAGE_CONFIG.clientVersion); -} - -function getFirstPositiveNumber(...values: unknown[]): number { - for (const value of values) { - const parsed = toNumber(value, Number.NaN); - if (Number.isFinite(parsed) && parsed > 0) { - return parsed; - } - } - return 0; -} - -function getCursorMonthlyRequestLimit(usageData: JsonRecord, subscriptionData: JsonRecord): number { - return getFirstPositiveNumber( - getFieldValue(subscriptionData, "team_max_monthly_requests", "teamMaxMonthlyRequests"), - getFieldValue(usageData, "team_max_request_usage", "teamMaxRequestUsage"), - getFieldValue(subscriptionData, "team_max_request_usage", "teamMaxRequestUsage"), - getFieldValue(usageData, "hard_limit", "hardLimit"), - getFieldValue(subscriptionData, "max_monthly_requests", "maxMonthlyRequests") - ); -} - -function getCursorOnDemandLimit(usageData: JsonRecord, subscriptionData: JsonRecord): number { - const onDemand = toRecord(getFieldValue(usageData, "on_demand", "onDemand")); - return getFirstPositiveNumber( - getFieldValue(onDemand, "max_requests", "maxRequests"), - getCursorMonthlyRequestLimit(usageData, subscriptionData) - ); -} - -function formatCursorQuota( - usedValue: unknown, - totalValue: unknown, - resetValue: unknown -): UsageQuota { - const total = Math.max(0, toNumber(totalValue, 0)); - const rawUsed = Math.max(0, toNumber(usedValue, 0)); - const used = total > 0 ? Math.min(rawUsed, total) : rawUsed; - const remaining = total > 0 ? Math.max(total - used, 0) : 0; - - return { - used, - total, - remaining, - remainingPercentage: total > 0 ? clampPercentage((remaining / total) * 100) : 0, - resetAt: parseResetTime(resetValue), - unlimited: false, - }; -} - -function inferCursorPlanName(userMeta: JsonRecord, subscriptionData: JsonRecord): string { - const teamInfo = toRecord(getFieldValue(userMeta, "team_info", "teamInfo")); - const candidates = [ - getFieldValue(userMeta, "plan", "plan"), - getFieldValue(userMeta, "subscription_type", "subscriptionType"), - getFieldValue(subscriptionData, "subscription_type", "subscriptionType"), - getFieldValue(subscriptionData, "plan", "plan"), - ]; - const planText = candidates.find((value) => typeof value === "string" && value.trim().length > 0); - const normalized = typeof planText === "string" ? planText.trim().toLowerCase() : ""; - - if (Object.keys(teamInfo).length > 0 || normalized.includes("team")) return "Cursor Team"; - if (normalized.includes("enterprise")) return "Cursor Enterprise"; - if (normalized.includes("pro")) return "Cursor Pro"; - if (normalized.includes("free")) return "Cursor Free"; - return "Cursor"; -} - -async function fetchCursorUsageDocument(url: string, accessToken: string) { - const response = await fetch(url, { - method: "GET", - headers: buildCursorUsageHeaders(accessToken), - }); - - const text = await response.text(); - if (!response.ok) { - return { - ok: false, - status: response.status, - data: {} as JsonRecord, - text, - }; - } - - try { - const parsed = text ? JSON.parse(text) : {}; - return { - ok: true, - status: response.status, - data: toRecord(parsed), - text, - }; - } catch { - return { - ok: false, - status: response.status, - data: {} as JsonRecord, - text, - }; - } -} - -async function getCursorUsage(accessToken: string) { - try { - if (!accessToken) { - return { - message: "Cursor token expired or unavailable. Please re-authenticate the connection.", - }; - } - - const [usageSummary, userMeta, subscription] = await Promise.all([ - fetchCursorUsageDocument(CURSOR_USAGE_CONFIG.usageUrl, accessToken), - fetchCursorUsageDocument(CURSOR_USAGE_CONFIG.userMetaUrl, accessToken), - fetchCursorUsageDocument(CURSOR_USAGE_CONFIG.subscriptionUrl, accessToken), - ]); - - const authDenied = [usageSummary, userMeta, subscription].some( - (result) => result.status === 401 || result.status === 403 - ); - if (authDenied) { - return { - message: - "Cursor token expired or permission denied. Please re-authenticate the connection.", - }; - } - - const usageData = usageSummary.data; - const userMetaData = userMeta.data; - const subscriptionData = subscription.data; - const plan = inferCursorPlanName(userMetaData, subscriptionData); - - const quotas: Record = {}; - const totalUsed = getFieldValue(usageData, "num_requests_total", "numRequestsTotal"); - const totalLimit = getCursorMonthlyRequestLimit(usageData, subscriptionData); - const totalReset = - getFieldValue(usageData, "reset_date", "resetDate") || - getFieldValue(subscriptionData, "reset_date", "resetDate"); - - if (toNumber(totalUsed, 0) > 0 || totalLimit > 0) { - quotas.requests = formatCursorQuota(totalUsed, totalLimit, totalReset); - } - - const onDemand = toRecord(getFieldValue(usageData, "on_demand", "onDemand")); - const onDemandUsed = getFieldValue(onDemand, "num_requests", "numRequests"); - const onDemandLimit = getCursorOnDemandLimit(usageData, subscriptionData); - const onDemandReset = - getFieldValue(onDemand, "reset_date", "resetDate") || - getFieldValue(usageData, "reset_date", "resetDate") || - getFieldValue(subscriptionData, "reset_date", "resetDate"); - - if (toNumber(onDemandUsed, 0) > 0 || onDemandLimit > 0) { - quotas.on_demand = formatCursorQuota(onDemandUsed, onDemandLimit, onDemandReset); - } - - if (Object.keys(quotas).length > 0) { - return { plan, quotas }; - } - - return { plan, message: "Cursor connected. Unable to parse quota data." }; - } catch (error) { - return { message: `Unable to fetch Cursor usage: ${(error as Error).message}` }; - } -} - // ── Gemini CLI subscription info cache ────────────────────────────────────── // Prevents duplicate loadCodeAssist calls within the same quota cycle. // Key: accessToken → { data, fetchedAt } @@ -2445,11 +2431,6 @@ export const __testing = { parseResetTime, formatGitHubQuotaSnapshot, inferGitHubPlanName, - buildCursorUsageHeaders, - formatCursorQuota, - getCursorMonthlyRequestLimit, - getCursorOnDemandLimit, - inferCursorPlanName, getGeminiCliPlanLabel, getAntigravityPlanLabel, }; diff --git a/open-sse/translator/helpers/geminiToolsSanitizer.ts b/open-sse/translator/helpers/geminiToolsSanitizer.ts index d76f23cf7c..3d36dc3468 100644 --- a/open-sse/translator/helpers/geminiToolsSanitizer.ts +++ b/open-sse/translator/helpers/geminiToolsSanitizer.ts @@ -209,19 +209,15 @@ export function buildGeminiTools( } } - if (googleSearchTool && functionDeclarations.length > 0) { - console.warn( - `[GeminiTools] Removing ${functionDeclarations.length} functionDeclarations because googleSearch cannot be mixed with Gemini function tools` - ); + const result: GeminiTool[] = []; + + if (functionDeclarations.length > 0) { + result.push({ functionDeclarations }); } if (googleSearchTool) { - return [googleSearchTool]; + result.push(googleSearchTool); } - if (functionDeclarations.length > 0) { - return [{ functionDeclarations }]; - } - - return undefined; + return result.length > 0 ? result : undefined; } diff --git a/open-sse/translator/request/openai-to-claude.ts b/open-sse/translator/request/openai-to-claude.ts index 14bccca754..50f2973bb7 100644 --- a/open-sse/translator/request/openai-to-claude.ts +++ b/open-sse/translator/request/openai-to-claude.ts @@ -1,6 +1,6 @@ import { register } from "../registry.ts"; import { FORMATS } from "../formats.ts"; -import { CLAUDE_SYSTEM_PROMPT } from "../../config/constants.ts"; +// CLAUDE_SYSTEM_PROMPT import removed — no longer injected unconditionally (#1966/#2130) import { supportsXHighEffort } from "../../config/providerModels.ts"; import { adjustMaxTokens } from "../helpers/maxTokensHelper.ts"; import { sanitizeToolId } from "../helpers/schemaCoercion.ts"; @@ -313,11 +313,29 @@ export function openaiToClaudeRequest(model, body, stream) { } // System messages and cache_control + // Fix #2130: Preserve body.system when present (Claude Code sends system as native + // Anthropic array through the /chat/completions endpoint). Without this, the system + // prompt is silently dropped when no role="system" messages exist in body.messages. if (systemParts.length > 0) { const systemText = systemParts.join("\n"); - result.system = [ - { type: "text", text: systemText, cache_control: { type: "ephemeral", ttl: "1h" } }, - ]; + const systemBlock = { + type: "text", + text: systemText, + cache_control: { type: "ephemeral", ttl: "1h" }, + }; + // Merge with existing body.system if present + if (Array.isArray(body.system)) { + result.system = [...body.system, systemBlock]; + } else if (typeof body.system === "string" && body.system.length > 0) { + result.system = [{ type: "text", text: body.system }, systemBlock]; + } else { + result.system = [systemBlock]; + } + } else if (body.system) { + // No role="system" messages, but body.system exists — pass through as-is + result.system = Array.isArray(body.system) + ? body.system + : [{ type: "text", text: String(body.system) }]; } // Thinking configuration diff --git a/open-sse/translator/request/openai-to-kiro.ts b/open-sse/translator/request/openai-to-kiro.ts index 1eb87198dc..ff3957aa38 100644 --- a/open-sse/translator/request/openai-to-kiro.ts +++ b/open-sse/translator/request/openai-to-kiro.ts @@ -53,6 +53,7 @@ function convertMessages(messages, tools, model) { let pendingUserContent = []; let pendingAssistantContent = []; let pendingToolResults = []; + let pendingImages: Array<{ format: string; source: { bytes: string } }> = []; let currentRole = null; const flushPending = () => { @@ -62,11 +63,13 @@ function convertMessages(messages, tools, model) { userInputMessage: { content: string; modelId: string; + images?: Array<{ format: string; source: { bytes: string } }>; userInputMessageContext?: { toolResults?: Array>; tools?: Array>; }; }; + _toolDocs?: string; } = { userInputMessage: { content: content, @@ -80,11 +83,20 @@ function convertMessages(messages, tools, model) { }; } + // Attach images to userInputMessage (NOT userInputMessageContext) + if (pendingImages.length > 0) { + userMsg.userInputMessage.images = pendingImages; + } + // Add tools to first user message if (tools && tools.length > 0 && history.length === 0) { if (!userMsg.userInputMessage.userInputMessageContext) { userMsg.userInputMessage.userInputMessageContext = {}; } + // Kiro API rejects requests with tool descriptions > ~10000 chars. + // Move long descriptions to system prompt (same approach as kiro-gateway). + const TOOL_DESC_MAX = 10000; + const toolDocs: string[] = []; userMsg.userInputMessage.userInputMessageContext.tools = tools.map((t) => { const name = t.function?.name || t.name; let description = t.function?.description || t.description || ""; @@ -93,6 +105,11 @@ function convertMessages(messages, tools, model) { description = `Tool: ${name}`; } + if (description.length > TOOL_DESC_MAX) { + toolDocs.push(`## Tool: ${name}\n\n${description}`); + description = `[Full documentation in system prompt under '## Tool: ${name}']`; + } + return { toolSpecification: { name, @@ -105,12 +122,17 @@ function convertMessages(messages, tools, model) { }, }; }); + // Attach tool docs to message so buildKiroPayload can prepend to content + if (toolDocs.length > 0) { + userMsg._toolDocs = toolDocs.join("\n\n---\n\n"); + } } history.push(userMsg); currentMessage = userMsg; pendingUserContent = []; pendingToolResults = []; + pendingImages = []; } else if (currentRole === "assistant") { const content = pendingAssistantContent.join("\n\n").trim() || "..."; const assistantMsg = { @@ -149,6 +171,24 @@ function convertMessages(messages, tools, model) { .map((c) => c.text || ""); content = textParts.join("\n"); + // Extract images (OpenAI image_url and Anthropic image formats) + for (const block of msg.content) { + if (block.type === "image_url") { + const url: string = block.image_url?.url || ""; + if (url.startsWith("data:")) { + // data:image/jpeg;base64, + const [header, bytes] = url.split(",", 2); + const mediaType = header.split(";")[0].replace("data:", ""); // e.g. "image/jpeg" + const format = mediaType.split("/")[1] || "jpeg"; + if (bytes) pendingImages.push({ format, source: { bytes } }); + } + } else if (block.type === "image" && block.source?.type === "base64") { + const format = (block.source.media_type || "image/jpeg").split("/")[1] || "jpeg"; + if (block.source.data) + pendingImages.push({ format, source: { bytes: block.source.data } }); + } + } + // Check for tool_result blocks const toolResultBlocks = msg.content.filter((c) => c.type === "tool_result"); if (toolResultBlocks.length > 0) { @@ -338,13 +378,19 @@ function convertMessages(messages, tools, model) { * Build Kiro payload from OpenAI format */ export function buildKiroPayload(model, body, stream, credentials) { + // Normalize model name: Claude Code sends dashes (claude-sonnet-4-6), + // Kiro API expects dots (claude-sonnet-4.6). Convert trailing version segment. + const normalizedModel = model.replace( + /^(claude-(?:opus|sonnet|haiku|3-\d+)-\d+)-(\d+)$/, + "$1.$2" + ); const messages = body.messages || []; const tools = body.tools || []; const maxTokens = body.max_tokens ?? body.max_completion_tokens ?? 32000; const temperature = body.temperature; const topP = body.top_p; - const { history, currentMessage } = convertMessages(messages, tools, model); + const { history, currentMessage } = convertMessages(messages, tools, normalizedModel); const profileArn = credentials?.providerSpecificData?.profileArn || ""; @@ -352,6 +398,12 @@ export function buildKiroPayload(model, body, stream, credentials) { const timestamp = new Date().toISOString(); finalContent = `[Context: Current time is ${timestamp}]\n\n${finalContent}`; + // Prepend tool documentation for tools with long descriptions (moved from toolSpecification) + const toolDocs = (currentMessage as { _toolDocs?: string } | null)?._toolDocs; + if (toolDocs) { + finalContent = `# Tool Documentation\n\n${toolDocs}\n\n---\n\n${finalContent}`; + } + const payload: { conversationState: { chatTriggerType: string; @@ -361,6 +413,7 @@ export function buildKiroPayload(model, body, stream, credentials) { content: string; modelId: string; origin: string; + images?: Array<{ format: string; source: { bytes: string } }>; userInputMessageContext?: Record; }; }; @@ -379,8 +432,11 @@ export function buildKiroPayload(model, body, stream, credentials) { currentMessage: { userInputMessage: { content: finalContent, - modelId: model, + modelId: normalizedModel, origin: "AI_EDITOR", + ...(currentMessage?.userInputMessage?.images?.length && { + images: currentMessage.userInputMessage.images, + }), ...(currentMessage?.userInputMessage?.userInputMessageContext && { userInputMessageContext: currentMessage.userInputMessage.userInputMessageContext, }), diff --git a/open-sse/utils/error.ts b/open-sse/utils/error.ts index 410b876ef6..8a84469d4a 100644 --- a/open-sse/utils/error.ts +++ b/open-sse/utils/error.ts @@ -129,6 +129,8 @@ export async function parseUpstreamError(response, provider = null) { let message = ""; let retryAfterMs = null; let responseBody = null; + let errorCode = undefined; + let errorType = undefined; try { const text = await response.text(); @@ -138,6 +140,8 @@ export async function parseUpstreamError(response, provider = null) { try { const json = JSON.parse(text); message = json.error?.message || json.message || json.error || text; + errorCode = json.error?.code || json.code; + errorType = json.error?.type || json.type; } catch { message = text; } @@ -192,6 +196,8 @@ export async function parseUpstreamError(response, provider = null) { return { statusCode: response.status, message: messageStr, + errorCode, + errorType, retryAfterMs, responseBody, responseHeaders, @@ -208,19 +214,34 @@ export async function parseUpstreamError(response, provider = null) { export function createErrorResult( statusCode: number, message: string, - retryAfterMs: number | null = null + retryAfterMs: number | null = null, + errorCode?: string, + errorType?: string ) { + const body = buildErrorBody(statusCode, message); + if (errorCode) { + (body.error as any).code = errorCode; + } + if (errorType) { + (body.error as any).type = errorType; + } + const result: { success: false; status: number; error: string; + errorType?: string; response: Response; retryAfterMs?: number; } = { success: false, status: statusCode, error: message, - response: errorResponse(statusCode, message), + errorType, + response: new Response(JSON.stringify(body), { + status: statusCode, + headers: { "Content-Type": "application/json" }, + }), }; // Add retryAfterMs if available (for Antigravity quota errors) diff --git a/open-sse/utils/streamReadiness.ts b/open-sse/utils/streamReadiness.ts index 5899d27106..ef6cb71918 100644 --- a/open-sse/utils/streamReadiness.ts +++ b/open-sse/utils/streamReadiness.ts @@ -66,6 +66,20 @@ function hasUsefulJsonPayload(payload: unknown): boolean { return hasUsefulValue(payload); } +function hasAcceptedStreamStartPayload(payload: unknown, eventType = ""): boolean { + if (!isRecord(payload)) return false; + + // Anthropic/Claude streams can legitimately start with lifecycle frames and + // then spend a long time thinking before the first text/tool delta arrives. + // Treating the start frame as readiness prevents false 504s while ping-only + // zombie streams still fail below. + const type = typeof payload.type === "string" ? payload.type : eventType; + if (type === "message_start" && isRecord(payload.message)) return true; + if (type === "content_block_start" && isRecord(payload.content_block)) return true; + + return false; +} + export function hasUsefulStreamContent(text: string): boolean { const lines = text.split(/\r?\n/); @@ -88,6 +102,60 @@ export function hasUsefulStreamContent(text: string): boolean { return false; } +type StreamReadinessSignalState = { + currentEvent: string; + pendingLine: string; +}; + +function processStreamReadinessLine(state: StreamReadinessSignalState, line: string): boolean { + const trimmed = line.trim(); + if (!trimmed || trimmed.startsWith(":")) { + if (!trimmed) state.currentEvent = ""; + return false; + } + + if (trimmed.startsWith("event:")) { + state.currentEvent = trimmed.slice(6).trim(); + return false; + } + + if (/^(?:ping|keepalive)$/i.test(state.currentEvent)) return false; + if (!trimmed.startsWith("data:")) return false; + + const data = trimmed.slice(5).trim(); + if (!data || data === "[DONE]") return false; + + try { + const parsed = JSON.parse(data); + return ( + hasUsefulJsonPayload(parsed) || hasAcceptedStreamStartPayload(parsed, state.currentEvent) + ); + } catch { + return data.length > 0; + } +} + +function appendStreamReadinessSignal(state: StreamReadinessSignalState, chunk: string): boolean { + const lines = `${state.pendingLine}${chunk}`.split(/\r?\n/); + state.pendingLine = lines.pop() ?? ""; + + for (const line of lines) { + if (processStreamReadinessLine(state, line)) return true; + } + + return false; +} + +export function hasStreamReadinessSignal(text: string): boolean { + const state: StreamReadinessSignalState = { + currentEvent: "", + pendingLine: "", + }; + if (appendStreamReadinessSignal(state, text)) return true; + if (state.pendingLine) return processStreamReadinessLine(state, state.pendingLine); + return false; +} + function createErrorResponse( status: number, message: string, @@ -170,7 +238,10 @@ export async function ensureStreamReadiness( const reader = response.body.getReader(); const chunks: Uint8Array[] = []; const decoder = new TextDecoder(); - let bufferedText = ""; + const readinessState: StreamReadinessSignalState = { + currentEvent: "", + pendingLine: "", + }; const startedAt = Date.now(); const deadline = startedAt + options.timeoutMs; let handedOffReader = false; @@ -245,9 +316,9 @@ export async function ensureStreamReadiness( if (!readResult.value) continue; chunks.push(readResult.value); - bufferedText += decoder.decode(readResult.value, { stream: true }); + const decodedChunk = decoder.decode(readResult.value, { stream: true }); - if (hasUsefulStreamContent(bufferedText)) { + if (appendStreamReadinessSignal(readinessState, decodedChunk)) { options.log?.debug?.( "STREAM", `Stream readiness confirmed in ${Date.now() - startedAt}ms (${options.provider || "provider"}/${options.model || "unknown"})` diff --git a/scripts/check-docs-sync.mjs b/scripts/check-docs-sync.mjs index 7b7aab5860..c8434fa185 100644 --- a/scripts/check-docs-sync.mjs +++ b/scripts/check-docs-sync.mjs @@ -118,6 +118,85 @@ function checkI18nMirrorFile(fileName, sourcePath) { } } +/** + * Check i18n CHANGELOG mirrors by verifying that all version sections from the + * root CHANGELOG exist in each translation. Unlike strict mirror files (llm.txt), + * CHANGELOG translations have translated section headings (e.g. "Security" → + * "Segurança"), so byte-for-byte comparison is intentionally skipped. + * + * Validates: + * 1. File exists in each locale + * 2. Has the i18n mirror separator (---) + * 3. Contains all version sections (## [X.Y.Z]) from root, in the same order + * 4. Body is non-empty and within a reasonable size tolerance of the source + */ +function checkI18nChangelogFile(sourcePath) { + const fileName = "CHANGELOG.md"; + if (!fs.existsSync(i18nDocsPath)) { + fail("docs/i18n directory is missing"); + return; + } + + const sourceContent = readText(sourcePath); + const sourceBody = normalizeMirrorBody(stripTopHeading(sourceContent)); + const sourceVersions = extractChangelogSections(sourceContent); + const locales = fs + .readdirSync(i18nDocsPath, { withFileTypes: true }) + .filter((entry) => entry.isDirectory()) + .map((entry) => entry.name) + .sort(); + + let checked = 0; + for (const locale of locales) { + const targetPath = path.join(i18nDocsPath, locale, fileName); + if (!fs.existsSync(targetPath)) { + fail(`docs/i18n/${locale}/${fileName} is missing`); + continue; + } + + const targetContent = readText(targetPath); + const body = extractI18nMirrorBody(targetContent); + if (body === null) { + fail(`docs/i18n/${locale}/${fileName} is missing the i18n mirror separator`); + continue; + } + + const normalizedBody = normalizeMirrorBody(body); + if (normalizedBody.length === 0) { + fail(`docs/i18n/${locale}/${fileName} has empty body after separator`); + continue; + } + + // Verify all version sections from root exist in the translation + const targetVersions = extractChangelogSections(targetContent); + const missingVersions = sourceVersions.filter((v) => !targetVersions.includes(v)); + if (missingVersions.length > 0) { + fail( + `docs/i18n/${locale}/${fileName} is missing version sections: ${missingVersions.slice(0, 3).join(", ")}${missingVersions.length > 3 ? ` (+${missingVersions.length - 3} more)` : ""}` + ); + continue; + } + + // Verify body size is within 25% tolerance of source (translations may + // expand or shrink, but drastic size differences indicate stale content) + const sizeDiff = Math.abs(normalizedBody.length - sourceBody.length) / sourceBody.length; + if (sizeDiff > 0.25) { + fail( + `docs/i18n/${locale}/${fileName} body size differs by ${(sizeDiff * 100).toFixed(0)}% from root (expected within 25%)` + ); + continue; + } + + checked += 1; + } + + if (checked > 0) { + console.log( + `[docs-sync] ${fileName} i18n translations validated: ${checked} locales (version sections + size check)` + ); + } +} + try { const packageJson = JSON.parse(readText(packageJsonPath)); const packageVersion = packageJson.version; @@ -161,8 +240,10 @@ try { } } + // llm.txt mirrors must be exact copies (no translation) checkI18nMirrorFile("llm.txt", llmPath); - checkI18nMirrorFile("CHANGELOG.md", changelogPath); + // CHANGELOG.md mirrors are translations — check version sections and size, not exact content + checkI18nChangelogFile(changelogPath); } catch (error) { fail(error instanceof Error ? error.message : String(error)); } diff --git a/src/app/(dashboard)/dashboard/cache/media/MediaPageClient.tsx b/src/app/(dashboard)/dashboard/cache/media/MediaPageClient.tsx index 5b2ba40bea..ae5b69f32e 100644 --- a/src/app/(dashboard)/dashboard/cache/media/MediaPageClient.tsx +++ b/src/app/(dashboard)/dashboard/cache/media/MediaPageClient.tsx @@ -23,6 +23,7 @@ type MediaModelConfig = { id: string; name: string }; type MediaProviderConfig = { id: string; authType: string; + supportedFormats?: string[]; models: MediaModelConfig[]; }; type ProviderModelGroup = { @@ -172,8 +173,147 @@ const VOICE_PRESETS: Record = { { id: "aura-orion-en", label: "Orion (EN)" }, ], inworld: [ - { id: "Eva", label: "Eva (EN)" }, + { id: "Abby", label: "Abby (EN)" }, + { id: "Alex", label: "Alex (EN)" }, + { id: "Amina", label: "Amina (EN)" }, + { id: "Anjali", label: "Anjali (EN)" }, + { id: "Arjun", label: "Arjun (EN)" }, + { id: "Ashley", label: "Ashley (EN)" }, + { id: "Avery", label: "Avery (EN)" }, + { id: "Bianca", label: "Bianca (EN)" }, + { id: "Blake", label: "Blake (EN)" }, + { id: "Brandon", label: "Brandon (EN)" }, + { id: "Brian", label: "Brian (EN)" }, + { id: "Callum", label: "Callum (EN)" }, + { id: "Carter", label: "Carter (EN)" }, + { id: "Cedric", label: "Cedric (EN)" }, + { id: "Celeste", label: "Celeste (EN)" }, + { id: "Chloe", label: "Chloe (EN)" }, + { id: "Claire", label: "Claire (EN)" }, + { id: "Clive", label: "Clive (EN)" }, + { id: "Conrad", label: "Conrad (EN)" }, + { id: "Craig", label: "Craig (EN)" }, + { id: "Damon", label: "Damon (EN)" }, + { id: "Darlene", label: "Darlene (EN)" }, + { id: "Deborah", label: "Deborah (EN)" }, + { id: "Dennis", label: "Dennis (EN)" }, + { id: "Derek", label: "Derek (EN)" }, + { id: "Dominus", label: "Dominus (EN)" }, + { id: "Duncan", label: "Duncan (EN)" }, + { id: "Edward", label: "Edward (EN)" }, + { id: "Eleanor", label: "Eleanor (EN)" }, + { id: "Elliot", label: "Elliot (EN)" }, + { id: "Ethan", label: "Ethan (EN)" }, + { id: "Evan", label: "Evan (EN)" }, + { id: "Evelyn", label: "Evelyn (EN)" }, + { id: "Felix", label: "Felix (EN)" }, + { id: "Gareth", label: "Gareth (EN)" }, + { id: "Graham", label: "Graham (EN)" }, + { id: "Hades", label: "Hades (EN)" }, + { id: "Hamish", label: "Hamish (EN)" }, + { id: "Hana", label: "Hana (EN)" }, + { id: "Hank", label: "Hank (EN)" }, + { id: "James", label: "James (EN)" }, + { id: "Jason", label: "Jason (EN)" }, + { id: "Jessica", label: "Jessica (EN)" }, + { id: "Jonah", label: "Jonah (EN)" }, + { id: "Kelsey", label: "Kelsey (EN)" }, + { id: "Lauren", label: "Lauren (EN)" }, + { id: "Levi", label: "Levi (EN)" }, + { id: "Liam", label: "Liam (EN)" }, + { id: "Loretta", label: "Loretta (EN)" }, + { id: "Lucian", label: "Lucian (EN)" }, + { id: "Luna", label: "Luna (EN)" }, + { id: "Malcolm", label: "Malcolm (EN)" }, { id: "Marcus", label: "Marcus (EN)" }, + { id: "Mark", label: "Mark (EN)" }, + { id: "Marlene", label: "Marlene (EN)" }, + { id: "Mia", label: "Mia (EN)" }, + { id: "Miranda", label: "Miranda (EN)" }, + { id: "Mortimer", label: "Mortimer (EN)" }, + { id: "Nadia", label: "Nadia (EN)" }, + { id: "Naomi", label: "Naomi (EN)" }, + { id: "Nate", label: "Nate (EN)" }, + { id: "Oliver", label: "Oliver (EN)" }, + { id: "Olivia", label: "Olivia (EN)" }, + { id: "Pippa", label: "Pippa (EN)" }, + { id: "Pixie", label: "Pixie (EN)" }, + { id: "Reed", label: "Reed (EN)" }, + { id: "Riley", label: "Riley (EN)" }, + { id: "Ronald", label: "Ronald (EN)" }, + { id: "Rupert", label: "Rupert (EN)" }, + { id: "Saanvi", label: "Saanvi (EN)" }, + { id: "Sarah", label: "Sarah (EN)" }, + { id: "Sebastian", label: "Sebastian (EN)" }, + { id: "Selene", label: "Selene (EN)" }, + { id: "Serena", label: "Serena (EN)" }, + { id: "Simon", label: "Simon (EN)" }, + { id: "Snik", label: "Snik (EN)" }, + { id: "Sophie", label: "Sophie (EN)" }, + { id: "Tessa", label: "Tessa (EN)" }, + { id: "Theodore", label: "Theodore (EN)" }, + { id: "Timothy", label: "Timothy (EN)" }, + { id: "Trevor", label: "Trevor (EN)" }, + { id: "Tristan", label: "Tristan (EN)" }, + { id: "Tyler", label: "Tyler (EN)" }, + { id: "Veronica", label: "Veronica (EN)" }, + { id: "Victor", label: "Victor (EN)" }, + { id: "Victoria", label: "Victoria (EN)" }, + { id: "Vinny", label: "Vinny (EN)" }, + { id: "Wendy", label: "Wendy (EN)" }, + { id: "Aanya", label: "Aanya (HI)" }, + { id: "Aarav", label: "Aarav (HI)" }, + { id: "Manoj", label: "Manoj (HI)" }, + { id: "Riya", label: "Riya (HI)" }, + { id: "Alain", label: "Alain (FR)" }, + { id: "Étienne", label: "Étienne (FR)" }, + { id: "Hélène", label: "Hélène (FR)" }, + { id: "Mathieu", label: "Mathieu (FR)" }, + { id: "Asuka", label: "Asuka (JP)" }, + { id: "Haruto", label: "Haruto (JP)" }, + { id: "Hina", label: "Hina (JP)" }, + { id: "Satoshi", label: "Satoshi (JP)" }, + { id: "Beatriz", label: "Beatriz (PT)" }, + { id: "Heitor", label: "Heitor (PT)" }, + { id: "Maitê", label: "Maitê (PT)" }, + { id: "Mariana", label: "Mariana (PT)" }, + { id: "Murilo", label: "Murilo (PT)" }, + { id: "Camila", label: "Camila (ES)" }, + { id: "Diego", label: "Diego (ES)" }, + { id: "Lupita", label: "Lupita (ES)" }, + { id: "Mateo", label: "Mateo (ES)" }, + { id: "Mauricio", label: "Mauricio (ES)" }, + { id: "Miguel", label: "Miguel (ES)" }, + { id: "Rafael", label: "Rafael (ES)" }, + { id: "Sofia", label: "Sofia (ES)" }, + { id: "Dmitry", label: "Dmitry (RU)" }, + { id: "Elena", label: "Elena (RU)" }, + { id: "Nikolai", label: "Nikolai (RU)" }, + { id: "Svetlana", label: "Svetlana (RU)" }, + { id: "Erik", label: "Erik (NL)" }, + { id: "Katrien", label: "Katrien (NL)" }, + { id: "Lennart", label: "Lennart (NL)" }, + { id: "Lore", label: "Lore (NL)" }, + { id: "Gianni", label: "Gianni (IT)" }, + { id: "Orietta", label: "Orietta (IT)" }, + { id: "Hyunwoo", label: "Hyunwoo (KO)" }, + { id: "Minji", label: "Minji (KO)" }, + { id: "Seojun", label: "Seojun (KO)" }, + { id: "Yoona", label: "Yoona (KO)" }, + { id: "Jing", label: "Jing (ZH)" }, + { id: "Mei", label: "Mei (ZH)" }, + { id: "Ming", label: "Ming (ZH)" }, + { id: "Xiaoyin", label: "Xiaoyin (ZH)" }, + { id: "Xinyi", label: "Xinyi (ZH)" }, + { id: "Yichen", label: "Yichen (ZH)" }, + { id: "Johanna", label: "Johanna (DE)" }, + { id: "Josef", label: "Josef (DE)" }, + { id: "Nour", label: "Nour (AR)" }, + { id: "Omar", label: "Omar (AR)" }, + { id: "Oren", label: "Oren (HE)" }, + { id: "Yael", label: "Yael (HE)" }, + { id: "Szymon", label: "Szymon (PL)" }, + { id: "Wojciech", label: "Wojciech (PL)" }, ], "xiaomi-mimo": [ { id: "冰糖", label: "冰糖 (Chinese Female)" }, @@ -188,12 +328,10 @@ const VOICE_PRESETS: Record = { }; const SPEECH_FORMATS = ["mp3", "wav", "opus", "flac", "pcm"]; -const SPEECH_FORMATS_BY_PROVIDER: Record = { - "xiaomi-mimo": ["mp3", "wav"], -}; function getSpeechFormats(providerId: string): string[] { - return SPEECH_FORMATS_BY_PROVIDER[providerId] || SPEECH_FORMATS; + const providerFormats = AUDIO_SPEECH_PROVIDERS[providerId]?.supportedFormats; + return providerFormats?.length ? providerFormats : SPEECH_FORMATS; } function getVoiceList(providerId: string) { diff --git a/src/app/(dashboard)/dashboard/cloud-agents/page.tsx b/src/app/(dashboard)/dashboard/cloud-agents/page.tsx new file mode 100644 index 0000000000..ff803e4a0a --- /dev/null +++ b/src/app/(dashboard)/dashboard/cloud-agents/page.tsx @@ -0,0 +1,478 @@ +"use client"; + +import { useState, useEffect, useCallback } from "react"; +import { Card, Button, Input, Badge } from "@/shared/components"; +import { useTranslations } from "next-intl"; + +interface CloudAgentTask { + id: string; + provider: string; + status: "pending" | "running" | "waiting_approval" | "completed" | "failed" | "cancelled"; + description: string; + createdAt: string; + updatedAt: string; + result?: string; + error?: string; + plan?: string; + messages: Array<{ role: string; content: string; timestamp: string }>; +} + +const CLOUD_AGENTS = [ + { + id: "jules", + name: "Jules", + provider: "Google", + description: "Google's autonomous coding agent", + icon: "🟡", + color: "bg-yellow-500/10 text-yellow-600", + }, + { + id: "devin", + name: "Devin", + provider: "Cognition", + description: "Cognition's AI software engineer", + icon: "🔵", + color: "bg-blue-500/10 text-blue-600", + }, + { + id: "codex-cloud", + name: "Codex Cloud", + provider: "OpenAI", + description: "OpenAI's cloud-based coding agent", + icon: "⚡", + color: "bg-emerald-500/10 text-emerald-600", + }, +]; + +export default function CloudAgentsPage() { + const [tasks, setTasks] = useState([]); + const [loading, setLoading] = useState(true); + const [creating, setCreating] = useState(false); + const [selectedTask, setSelectedTask] = useState(null); + const [newTask, setNewTask] = useState({ + provider: "jules", + description: "", + }); + const [messageInput, setMessageInput] = useState(""); + const t = useTranslations("cloudAgents"); + + const fetchTasks = useCallback(async () => { + try { + const res = await fetch("/api/v1/agents/tasks"); + if (res.ok) { + const data = await res.json(); + setTasks(data.tasks || []); + } + } catch (err) { + console.error("Failed to fetch tasks:", err); + } finally { + setLoading(false); + } + }, []); + + useEffect(() => { + fetchTasks(); + }, [fetchTasks]); + + const handleCreateTask = async (e: React.FormEvent) => { + e.preventDefault(); + setCreating(true); + try { + const res = await fetch("/api/v1/agents/tasks", { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify({ + provider: newTask.provider, + description: newTask.description, + }), + }); + if (res.ok) { + const data = await res.json(); + setTasks((prev) => [data.task, ...prev]); + setNewTask({ provider: "jules", description: "" }); + } + } catch (err) { + console.error("Failed to create task:", err); + } finally { + setCreating(false); + } + }; + + const handleSendMessage = async () => { + if (!selectedTask || !messageInput.trim()) return; + try { + const res = await fetch(`/api/v1/agents/tasks/${selectedTask.id}`, { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify({ + action: "message", + message: messageInput, + }), + }); + if (res.ok) { + const data = await res.json(); + setSelectedTask(data.task); + setTasks((prev) => prev.map((task) => (task.id === selectedTask.id ? data.task : task))); + setMessageInput(""); + } + } catch (err) { + console.error("Failed to send message:", err); + } + }; + + const handleApprovePlan = async () => { + if (!selectedTask) return; + try { + const res = await fetch(`/api/v1/agents/tasks/${selectedTask.id}`, { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify({ action: "approve" }), + }); + if (res.ok) { + const data = await res.json(); + setSelectedTask(data.task); + setTasks((prev) => prev.map((t) => (t.id === selectedTask.id ? data.task : t))); + } + } catch (err) { + console.error("Failed to approve plan:", err); + } + }; + + const handleCancelTask = async (taskId: string) => { + try { + const res = await fetch(`/api/v1/agents/tasks/${taskId}`, { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify({ action: "cancel" }), + }); + if (res.ok) { + const data = await res.json(); + setTasks((prev) => prev.map((t) => (t.id === taskId ? data.task : t))); + if (selectedTask?.id === taskId) { + setSelectedTask(data.task); + } + } + } catch (err) { + console.error("Failed to cancel task:", err); + } + }; + + const handleDeleteTask = async (taskId: string) => { + try { + const res = await fetch(`/api/v1/agents/tasks/${taskId}`, { + method: "DELETE", + }); + if (res.ok) { + setTasks((prev) => prev.filter((t) => t.id !== taskId)); + if (selectedTask?.id === taskId) { + setSelectedTask(null); + } + } + } catch (err) { + console.error("Failed to delete task:", err); + } + }; + + const getStatusBadge = (status: string) => { + const statusMap: Record = { + pending: { color: "bg-zinc-500/10 text-zinc-500", label: t("statusPending") }, + running: { color: "bg-blue-500/10 text-blue-500", label: t("statusRunning") }, + waiting_approval: { + color: "bg-amber-500/10 text-amber-600", + label: t("statusWaitingApproval"), + }, + completed: { color: "bg-emerald-500/10 text-emerald-600", label: t("statusCompleted") }, + failed: { color: "bg-red-500/10 text-red-500", label: t("statusFailed") }, + cancelled: { color: "bg-zinc-500/10 text-zinc-400", label: t("statusCancelled") }, + }; + const s = statusMap[status] || statusMap.pending; + return ( + + {status === "running" && } + {s.label} + + ); + }; + + const getAgentInfo = (providerId: string) => { + return CLOUD_AGENTS.find((a) => a.id === providerId) || CLOUD_AGENTS[0]; + }; + + if (loading) { + return ( +
+
+

{t("loading")}

+
+ ); + } + + return ( +
+
+
+

{t("title")}

+

{t("description")}

+
+
+ + +
+
+
+

{t("aboutTitle")}

+

{t("aboutDescription")}

+
+
+
+ {CLOUD_AGENTS.map((agent) => ( +
+
+ {agent.icon} +

{agent.name}

+
+

{agent.description}

+

{agent.provider}

+
+ ))} +
+
+ {t("howItWorksTitle")} + {t("howItWorksDesc")} +
+
+
+ + +
+
+ add_task +
+
+

{t("newTaskTitle")}

+

{t("newTaskDescription")}

+
+
+
+
+
+ + +
+
+
+ setNewTask({ ...newTask, description: e.target.value })} + required + /> +
+
+ +
+
+
+ +
+
+

{t("tasks")}

+ {tasks.length === 0 ? ( +
+ assignment +

{t("noTasks")}

+
+ ) : ( + tasks.map((task) => { + const agent = getAgentInfo(task.provider); + return ( + setSelectedTask(task)} + > +
+
+ {agent.icon} +
+

+ {task.description || t("untitledTask")} +

+

+ {agent.name} • {new Date(task.createdAt).toLocaleString()} +

+
+
+ {getStatusBadge(task.status)} +
+
+ ); + }) + )} +
+ +
+

{t("taskDetail")}

+ {selectedTask ? ( + +
+
+ {getAgentInfo(selectedTask.provider).icon} +
+

{getAgentInfo(selectedTask.provider).name}

+

+ {t("created")}: {new Date(selectedTask.createdAt).toLocaleString()} +

+
+
+ {getStatusBadge(selectedTask.status)} +
+ + {selectedTask.status === "waiting_approval" && selectedTask.plan && ( +
+
+ + description + + + {t("planReady")} + +
+
+                    {selectedTask.plan}
+                  
+
+ + +
+
+ )} + + {selectedTask.messages.length > 0 && ( +
+

{t("conversation")}

+
+ {selectedTask.messages.map((msg, i) => ( +
+ {msg.role}: + {msg.content} +
+ ))} +
+
+ )} + + {selectedTask.result && ( +
+
+ + check_circle + + + {t("result")} + +
+
+                    {selectedTask.result}
+                  
+
+ )} + + {selectedTask.error && ( +
+
+ + error + + {t("error")} +
+

{selectedTask.error}

+
+ )} + + {selectedTask.status === "running" && ( +
+ setMessageInput(e.target.value)} + onKeyDown={(e) => e.key === "Enter" && !e.shiftKey && handleSendMessage()} + className="flex-1" + /> + +
+ )} + +
+ + +
+
+ ) : ( +
+ touch_app +

{t("selectTaskPrompt")}

+
+ )} +
+
+
+ ); +} diff --git a/src/app/(dashboard)/dashboard/combos/BuilderIntelligentStep.tsx b/src/app/(dashboard)/dashboard/combos/BuilderIntelligentStep.tsx index 3dabb89695..087aba2fbd 100644 --- a/src/app/(dashboard)/dashboard/combos/BuilderIntelligentStep.tsx +++ b/src/app/(dashboard)/dashboard/combos/BuilderIntelligentStep.tsx @@ -15,7 +15,7 @@ function getI18nOrFallback(t: any, key: string, fallback: string) { return fallback; } -function toProviderOptions(activeProviders: any[] = []) { +function toProviderOptions(activeProviders: any[] = [], candidatePool: string[] = []) { const uniqueProviders = new Map(); activeProviders.forEach((provider) => { @@ -41,6 +41,16 @@ function toProviderOptions(activeProviders: any[] = []) { }); }); + candidatePool.forEach((poolId) => { + if (!uniqueProviders.has(poolId)) { + uniqueProviders.set(poolId, { + id: poolId, + label: `${poolId} (Offline/Deleted)`, + connectionCount: 0, + }); + } + }); + return [...uniqueProviders.values()].sort((a, b) => a.label.localeCompare(b.label)); } @@ -56,7 +66,10 @@ export default function BuilderIntelligentStep({ activeProviders: any[]; }) { const normalizedConfig = normalizeIntelligentRoutingConfig(config); - const providerOptions = useMemo(() => toProviderOptions(activeProviders), [activeProviders]); + const providerOptions = useMemo( + () => toProviderOptions(activeProviders, normalizedConfig.candidatePool), + [activeProviders, normalizedConfig.candidatePool] + ); const updateConfig = (patch: Record) => { onChange({ @@ -64,7 +77,7 @@ export default function BuilderIntelligentStep({ ...patch, weights: { ...normalizedConfig.weights, - ...(patch.weights || {}), + ...((patch.weights as Record) || {}), }, }); }; diff --git a/src/app/(dashboard)/dashboard/providers/[id]/page.tsx b/src/app/(dashboard)/dashboard/providers/[id]/page.tsx index e1e4300c90..5a6a96491c 100644 --- a/src/app/(dashboard)/dashboard/providers/[id]/page.tsx +++ b/src/app/(dashboard)/dashboard/providers/[id]/page.tsx @@ -509,6 +509,7 @@ interface ConnectionRowConnection { expiresAt?: string; tokenExpiresAt?: string; maxConcurrent?: number | null; + authType?: string; } interface ConnectionRowProps { @@ -3024,7 +3025,7 @@ export default function ProviderDetailPage() { {selectedIds.size > 0 && ( +
+
+ {cloudAgentProviderEntries.map( + ({ providerId, provider, stats, displayAuthType, toggleAuthType }) => ( + handleToggleProvider(providerId, toggleAuthType, active)} + /> + ) + )} +
+
+ )} + {/* Local / Self-Hosted Providers */} {localProviderEntries.length > 0 && (
diff --git a/src/app/(dashboard)/dashboard/settings/components/ResilienceTab.tsx b/src/app/(dashboard)/dashboard/settings/components/ResilienceTab.tsx index f3ca6f7105..744aedb3f0 100644 --- a/src/app/(dashboard)/dashboard/settings/components/ResilienceTab.tsx +++ b/src/app/(dashboard)/dashboard/settings/components/ResilienceTab.tsx @@ -16,6 +16,9 @@ type RequestQueueSettings = { type ConnectionCooldownProfileSettings = { baseCooldownMs: number; useUpstreamRetryHints: boolean; + // Issue #2100 follow-up. Optional / undefined when unset; the per-provider + // default in src/shared/utils/providerHints.ts resolves at runtime. + useUpstream429BreakerHints?: boolean; maxBackoffSteps: number; }; @@ -360,6 +363,48 @@ function ConnectionCooldownCard({ })) } /> +
+ +

+ Apply Retry-After / quota-exhausted signals from 429 responses to circuit-breaker + cooldown duration. Default uses a per-provider policy: direct cloud providers + default on; reverse-proxy / self-hosted / CLI-backed providers default off. + Independent of "Use upstream retry hints". +

+
+
+ Use upstream 429 hints (breaker) + + {current.useUpstream429BreakerHints === true + ? "Yes" + : current.useUpstream429BreakerHints === false + ? "No" + : "Default"} + +
Max backoff steps {current.maxBackoffSteps} @@ -414,7 +469,26 @@ function ConnectionCooldownCard({ setEditing(false); }} onSave={async () => { - await onSave(draft); + // Build PATCH-ready payload: convert undefined useUpstream429BreakerHints + // to explicit null sentinel so the server treats it as unset (not as + // partial-merge "leave unchanged"). JSON.stringify drops undefined keys. + const payload = { + oauth: { + ...draft.oauth, + useUpstream429BreakerHints: + draft.oauth.useUpstream429BreakerHints === undefined + ? (null as unknown as boolean | undefined) + : draft.oauth.useUpstream429BreakerHints, + }, + apikey: { + ...draft.apikey, + useUpstream429BreakerHints: + draft.apikey.useUpstream429BreakerHints === undefined + ? (null as unknown as boolean | undefined) + : draft.apikey.useUpstream429BreakerHints, + }, + }; + await onSave(payload as typeof draft); setEditing(false); }} /> diff --git a/src/app/(dashboard)/dashboard/settings/components/RoutingTab.tsx b/src/app/(dashboard)/dashboard/settings/components/RoutingTab.tsx index 2e225eb923..82f5110939 100644 --- a/src/app/(dashboard)/dashboard/settings/components/RoutingTab.tsx +++ b/src/app/(dashboard)/dashboard/settings/components/RoutingTab.tsx @@ -297,11 +297,7 @@ export default function RoutingTab() { disabled={loading || forced} aria-pressed={checked} aria-disabled={forced || undefined} - title={ - checked - ? t("disableFingerprintTitle", { provider: label }) - : t("enableFingerprintTitle", { provider: label }) - } + title={titleText} className={`flex items-start gap-3 rounded-lg border p-3 text-left transition-all ${ checked ? "border-indigo-500/50 bg-indigo-500/5 ring-1 ring-indigo-500/20" diff --git a/src/app/(dashboard)/dashboard/usage/components/ProviderLimits/utils.tsx b/src/app/(dashboard)/dashboard/usage/components/ProviderLimits/utils.tsx index 615dd51c61..6851c621e3 100644 --- a/src/app/(dashboard)/dashboard/usage/components/ProviderLimits/utils.tsx +++ b/src/app/(dashboard)/dashboard/usage/components/ProviderLimits/utils.tsx @@ -26,6 +26,11 @@ const QUOTA_LABEL_MAP: Record = { "search-prime": "Web Search", "web-reader": "Web Reader", zread: "Zread", + "5 Hours Quota": "5 Hours", + "Weekly Quota": "Weekly", + "Monthly Tools": "Monthly Tools", + tokens: "Tokens", + time_limit: "Time Limit", }; const GLM_QUOTA_ORDER: Record = { diff --git a/src/app/api/oauth/cursor/import/route.ts b/src/app/api/oauth/cursor/import/route.ts index f2ba171d62..8e747c8041 100755 --- a/src/app/api/oauth/cursor/import/route.ts +++ b/src/app/api/oauth/cursor/import/route.ts @@ -58,22 +58,33 @@ export async function POST(request: Request) { cursorService.validateImportToken(accessToken.trim(), machineId?.trim()) ); - // Try to extract user info from token - const userInfo = cursorService.extractUserInfo(tokenData.accessToken); + // Try to extract user info from token (JWT decode, no API call) + const jwtInfo = cursorService.extractUserInfo(tokenData.accessToken); - // Save to database + // Best-effort fetch real profile (email + name) from cursor.com using the + // same WorkOS session cookie format we use for usage limits. + const profile = jwtInfo?.userId + ? await runWithProxyContext(proxy, () => + cursorService.fetchUserInfo(tokenData.accessToken, jwtInfo.userId) + ) + : null; + + const email = profile?.email || jwtInfo?.email || null; + + // Save to database (no `name` — let the dashboard fall back to email so the + // privacy mask toggle applies, matching the codex/claude rendering). const connection: any = await createProviderConnection({ provider: "cursor", authType: "oauth", accessToken: tokenData.accessToken, refreshToken: null, // Cursor doesn't have public refresh endpoint expiresAt: new Date(Date.now() + tokenData.expiresIn * 1000).toISOString(), - email: userInfo?.email || null, + email, providerSpecificData: { machineId: tokenData.machineId, authMethod: "imported", provider: "Imported", - userId: userInfo?.userId, + userId: jwtInfo?.userId, }, testStatus: "active", }); diff --git a/src/app/api/oauth/kiro/auto-import/route.ts b/src/app/api/oauth/kiro/auto-import/route.ts index 25c0f27487..29a0cf6a64 100755 --- a/src/app/api/oauth/kiro/auto-import/route.ts +++ b/src/app/api/oauth/kiro/auto-import/route.ts @@ -1,14 +1,22 @@ import { NextResponse } from "next/server"; -import { readFile, readdir } from "fs/promises"; import { homedir } from "os"; import { join } from "path"; import { isAuthRequired, isAuthenticated } from "@/shared/utils/apiAuth"; +import { createProviderConnection, isCloudEnabled, resolveProxyForProvider } from "@/models"; +import { syncToCloud } from "@/lib/cloudSync"; +import { getConsistentMachineId } from "@/shared/utils/machineId"; +import { KiroService } from "@/lib/oauth/services/kiro"; +import { runWithProxyContext } from "@omniroute/open-sse/utils/proxyFetch.ts"; /** * GET /api/oauth/kiro/auto-import - * Auto-detect and extract Kiro refresh token from AWS SSO cache. * - * 🔒 Auth-guarded: requires JWT cookie or Bearer API key (finding #258-5). + * Auto-import Kiro credentials from kiro-cli's SQLite database. + * Supports both personal Builder ID and enterprise SSO (IDC/profileArn). + * + * Falls back to ~/.aws/sso/cache if kiro-cli SQLite is not found. + * + * 🔒 Auth-guarded: requires JWT cookie or Bearer API key. */ export async function GET(request: Request) { if (await isAuthRequired(request)) { @@ -17,79 +25,249 @@ export async function GET(request: Request) { } } + const { searchParams } = new URL(request.url); + const targetProvider = searchParams.get("targetProvider") === "amazon-q" ? "amazon-q" : "kiro"; + + // Try kiro-cli SQLite first + const sqliteResult = await tryKiroCliSqlite(); + if (sqliteResult.found) { + return await saveAndRespond(sqliteResult, targetProvider, request); + } + + // Fall back to ~/.aws/sso/cache (social auth / manual token) + const cacheResult = await tryAwsSsoCache(targetProvider); + if (cacheResult.found) { + return await saveAndRespond(cacheResult, targetProvider, request); + } + + return NextResponse.json({ + found: false, + error: + "Kiro credentials not found. " + + "Run `kiro-cli login --use-device-flow` then retry, " + + "or use the Import Token option in the dashboard.", + triedPaths: [sqliteResult.triedPath, cacheResult.triedPath].filter(Boolean), + }); +} + +// ── kiro-cli SQLite reader ──────────────────────────────────────────────────── + +async function tryKiroCliSqlite(): Promise<{ + found: boolean; + triedPath?: string; + refreshToken?: string; + accessToken?: string; + expiresAt?: string; + clientId?: string; + clientSecret?: string; + region?: string; + profileArn?: string; + source?: string; +}> { + const dbPath = join(homedir(), ".local/share/kiro-cli/data.sqlite3"); + + let Database: any; try { - const { searchParams } = new URL(request.url); - const targetProvider = searchParams.get("targetProvider") === "amazon-q" ? "amazon-q" : "kiro"; - const providerLabel = targetProvider === "amazon-q" ? "Amazon Q" : "Kiro"; - const cachePath = join(homedir(), ".aws/sso/cache"); + Database = (await import("better-sqlite3")).default; + } catch { + return { found: false, triedPath: dbPath }; + } - // Try to read cache directory - let files; - try { - files = await readdir(cachePath); - } catch (error) { - return NextResponse.json({ - found: false, - error: `AWS SSO cache not found. Please login to ${providerLabel} first.`, - }); - } - - // Look for kiro-auth-token.json or any .json file with refreshToken - let refreshToken = null; - let foundFile = null; - - // First try kiro-auth-token.json - const preferredTokenFile = - targetProvider === "amazon-q" ? "amazon-q-auth-token.json" : "kiro-auth-token.json"; - if (files.includes(preferredTokenFile)) { - try { - const content = await readFile(join(cachePath, preferredTokenFile), "utf-8"); - const data = JSON.parse(content); - if (data.refreshToken && data.refreshToken.startsWith("aorAAAAAG")) { - refreshToken = data.refreshToken; - foundFile = preferredTokenFile; - } - } catch (error) { - // Continue to search other files - } - } - - // If not found, search all .json files - if (!refreshToken) { - for (const file of files) { - if (!file.endsWith(".json")) continue; + let db: any; + try { + db = new Database(dbPath, { readonly: true, fileMustExist: true }); + } catch { + return { found: false, triedPath: dbPath }; + } + try { + // Read OIDC token (access + refresh token) + const tokenKeys = ["kirocli:odic:token", "kirocli:oidc:token"]; + let tokenData: any = null; + for (const key of tokenKeys) { + const row = db.prepare("SELECT value FROM auth_kv WHERE key = ?").get(key) as + | { value: string } + | undefined; + if (row?.value) { try { - const content = await readFile(join(cachePath, file), "utf-8"); - const data = JSON.parse(content); - - // Look for Kiro refresh token (starts with aorAAAAAG) - if (data.refreshToken && data.refreshToken.startsWith("aorAAAAAG")) { - refreshToken = data.refreshToken; - foundFile = file; - break; - } - } catch (error) { - // Skip invalid JSON files - continue; + tokenData = JSON.parse(row.value); + break; + } catch { + // continue } } } - if (!refreshToken) { - return NextResponse.json({ - found: false, - error: `${providerLabel} token not found in AWS SSO cache. Please login to ${providerLabel} first.`, - }); + if (!tokenData?.refresh_token) { + return { found: false, triedPath: dbPath }; + } + + // Read device registration (client_id + client_secret) + const regKeys = ["kirocli:odic:device-registration", "kirocli:oidc:device-registration"]; + let regData: any = null; + for (const key of regKeys) { + const row = db.prepare("SELECT value FROM auth_kv WHERE key = ?").get(key) as + | { value: string } + | undefined; + if (row?.value) { + try { + regData = JSON.parse(row.value); + break; + } catch { + // continue + } + } + } + + // Read profileArn from state table (enterprise SSO / IDC) + let profileArn: string | undefined; + try { + const profileRow = db + .prepare("SELECT value FROM state WHERE key = 'api.codewhisperer.profile'") + .get() as { value: string } | undefined; + if (profileRow?.value) { + const profileData = JSON.parse(profileRow.value); + profileArn = profileData.arn || profileData.profileArn; + } + } catch { + // state table may not exist for personal Builder ID accounts + } + + const region = tokenData.region || regData?.region || "us-east-1"; + const expiresAt = tokenData.expires_at + ? new Date(tokenData.expires_at).toISOString() + : new Date(Date.now() + 3600 * 1000).toISOString(); + + return { + found: true, + source: "kiro-cli-sqlite", + refreshToken: tokenData.refresh_token, + accessToken: tokenData.access_token, + expiresAt, + clientId: regData?.client_id, + clientSecret: regData?.client_secret, + region, + profileArn, + }; + } finally { + db.close(); + } +} + +// ── ~/.aws/sso/cache fallback ───────────────────────────────────────────────── + +async function tryAwsSsoCache(targetProvider: string): Promise<{ + found: boolean; + triedPath?: string; + refreshToken?: string; + source?: string; +}> { + const { readFile, readdir } = await import("fs/promises"); + const cachePath = join(homedir(), ".aws/sso/cache"); + const preferredFile = + targetProvider === "amazon-q" ? "amazon-q-auth-token.json" : "kiro-auth-token.json"; + + let files: string[]; + try { + files = await readdir(cachePath); + } catch { + return { found: false, triedPath: cachePath }; + } + + // Try preferred file first, then scan all + const ordered = [ + preferredFile, + ...files.filter((f) => f !== preferredFile && f.endsWith(".json")), + ]; + + for (const file of ordered) { + try { + const content = await readFile(join(cachePath, file), "utf-8"); + const data = JSON.parse(content); + if (data.refreshToken?.startsWith("aorAAAAAG")) { + return { found: true, refreshToken: data.refreshToken, source: file }; + } + } catch { + // skip + } + } + + return { found: false, triedPath: cachePath }; +} + +// ── Save to OmniRoute DB ────────────────────────────────────────────────────── + +async function saveAndRespond( + result: Awaited>, + targetProvider: string, + request: Request +) { + try { + const kiroService = new KiroService(); + const proxy = await resolveProxyForProvider(targetProvider); + + // If we have a refresh token but no valid access token, refresh now + let accessToken = result.accessToken; + let refreshToken = result.refreshToken!; + let expiresAt = result.expiresAt; + let profileArn = result.profileArn; + + const providerSpecificData: Record = { + authMethod: result.source === "kiro-cli-sqlite" ? "kiro-cli" : "imported", + provider: result.source === "kiro-cli-sqlite" ? "kiro-cli SQLite" : "AWS SSO Cache", + }; + + if (result.clientId) providerSpecificData.clientId = result.clientId; + if (result.clientSecret) providerSpecificData.clientSecret = result.clientSecret; + if (result.region) providerSpecificData.region = result.region; + if (profileArn) providerSpecificData.profileArn = profileArn; + + // Refresh token to get a fresh access token and confirm it works + const refreshed = await runWithProxyContext(proxy, () => + kiroService.refreshToken(refreshToken, providerSpecificData) + ); + + accessToken = refreshed.accessToken; + refreshToken = refreshed.refreshToken || refreshToken; + expiresAt = new Date(Date.now() + (refreshed.expiresIn || 3600) * 1000).toISOString(); + + // profileArn may come back from social auth refresh + if (refreshed.profileArn && !profileArn) { + profileArn = refreshed.profileArn; + providerSpecificData.profileArn = profileArn; + } + + const email = kiroService.extractEmailFromJWT(accessToken); + + await createProviderConnection({ + provider: targetProvider, + authType: "oauth", + accessToken, + refreshToken, + expiresAt, + email: email || null, + providerSpecificData, + testStatus: "active", + } as any); + + if (isCloudEnabled()) { + const machineId = await getConsistentMachineId(); + await syncToCloud(machineId).catch(() => {}); } return NextResponse.json({ found: true, - refreshToken, - source: foundFile, + source: result.source, + email: email || null, + profileArn: profileArn || null, + region: result.region || null, + message: "Kiro credentials imported successfully.", }); - } catch (error) { - console.log("Kiro auto-import error:", error); - return NextResponse.json({ found: false, error: error.message }, { status: 500 }); + } catch (error: any) { + console.error("[kiro auto-import] save error:", error); + return NextResponse.json( + { found: false, error: `Import failed: ${error.message}` }, + { status: 500 } + ); } } diff --git a/src/app/api/providers/[id]/models/route.ts b/src/app/api/providers/[id]/models/route.ts index de67c6487b..4ee7e835ae 100755 --- a/src/app/api/providers/[id]/models/route.ts +++ b/src/app/api/providers/[id]/models/route.ts @@ -854,8 +854,10 @@ export async function GET( return localCatalog.map((model) => ({ id: model.id, name: model.name || model.id, - ...(model.apiFormat ? { apiFormat: model.apiFormat } : {}), - ...(model.supportedEndpoints ? { supportedEndpoints: model.supportedEndpoints } : {}), + ...((model as any).apiFormat ? { apiFormat: (model as any).apiFormat } : {}), + ...((model as any).supportedEndpoints + ? { supportedEndpoints: (model as any).supportedEndpoints } + : {}), ...(registryCatalogModels.length > 0 ? { owned_by: provider } : {}), })); }; @@ -902,7 +904,7 @@ export async function GET( } ) => { const status = getSafeOutboundFetchErrorStatus(error); - if (status === 400) return null; + if (status === 400 || status === 503 || status === 504) return null; return buildDiscoveryFallbackResponse(warnings); }; @@ -1852,8 +1854,10 @@ export async function GET( models: localCatalog.map((m) => ({ id: m.id, name: m.name || m.id, - ...(m.apiFormat ? { apiFormat: m.apiFormat } : {}), - ...(m.supportedEndpoints ? { supportedEndpoints: m.supportedEndpoints } : {}), + ...((m as any).apiFormat ? { apiFormat: (m as any).apiFormat } : {}), + ...((m as any).supportedEndpoints + ? { supportedEndpoints: (m as any).supportedEndpoints } + : {}), ...(registryCatalogModels.length > 0 ? { owned_by: provider } : {}), })), source: "local_catalog", diff --git a/src/app/api/providers/[id]/route.ts b/src/app/api/providers/[id]/route.ts index 3925f88c11..4e954bc917 100644 --- a/src/app/api/providers/[id]/route.ts +++ b/src/app/api/providers/[id]/route.ts @@ -23,6 +23,7 @@ import { isClaudeExtraUsageBlockEnabled, } from "@/lib/providers/claudeExtraUsage"; import { requireManagementAuth } from "@/lib/api/requireManagementAuth"; +import { isApiKeyRevealEnabled, maskStoredApiKey } from "@/lib/apiKeyExposure"; function normalizeCodexLimitPolicy( incoming: unknown, @@ -61,9 +62,13 @@ export async function GET(request: Request, { params }: { params: Promise<{ id: return NextResponse.json({ error: "Connection not found" }, { status: 404 }); } - // Hide sensitive fields + const revealKeys = isApiKeyRevealEnabled(); + + // Hide or mask sensitive fields const result: Record = { ...connection }; - delete result.apiKey; + if (!revealKeys) { + result.apiKey = result.apiKey ? maskStoredApiKey(result.apiKey) : undefined; + } delete result.accessToken; delete result.refreshToken; delete result.idToken; diff --git a/src/app/api/providers/route.ts b/src/app/api/providers/route.ts index 802947bec7..6f964ed423 100644 --- a/src/app/api/providers/route.ts +++ b/src/app/api/providers/route.ts @@ -27,6 +27,7 @@ import { } from "@/lib/providers/requestDefaults"; import { requireManagementAuth } from "@/lib/api/requireManagementAuth"; import { isManagedProviderConnectionId } from "@/lib/providers/catalog"; +import { isApiKeyRevealEnabled, maskStoredApiKey } from "@/lib/apiKeyExposure"; // GET /api/providers - List all connections export async function GET(request: Request) { @@ -35,11 +36,12 @@ export async function GET(request: Request) { try { const connections = await getProviderConnections(); + const revealKeys = isApiKeyRevealEnabled(); - // Hide sensitive fields + // Hide or mask sensitive fields const safeConnections = connections.map((c) => ({ ...c, - apiKey: undefined, + apiKey: revealKeys ? c.apiKey : c.apiKey ? maskStoredApiKey(c.apiKey) : undefined, accessToken: undefined, refreshToken: undefined, idToken: undefined, diff --git a/src/app/api/resilience/route.ts b/src/app/api/resilience/route.ts index 08fe0aeb05..c7c031ed7e 100644 --- a/src/app/api/resilience/route.ts +++ b/src/app/api/resilience/route.ts @@ -9,6 +9,7 @@ import { } from "@/lib/resilience/settings"; import { updateResilienceSchema } from "@/shared/validation/schemas"; import { isValidationFailure, validateBody } from "@/shared/validation/helpers"; +import { resetAllCircuitBreakers } from "@/shared/utils/circuitBreaker"; type JsonRecord = Record; @@ -196,6 +197,20 @@ export async function PATCH(request) { }); await syncRuntimeSettings(nextResilience); + // Issue #2100 follow-up: detect transitions in useUpstream429BreakerHints + // and reset breakers so the registry stops serving cached options. + // Compared on STORED override transition (boolean | undefined) so that + // `null` (PATCH input) → undefined (stored) is correctly detected as + // "unset request" when the previous stored value was a boolean. + const breakerHintsChanged = + currentResilience.connectionCooldown.oauth.useUpstream429BreakerHints !== + nextResilience.connectionCooldown.oauth.useUpstream429BreakerHints || + currentResilience.connectionCooldown.apikey.useUpstream429BreakerHints !== + nextResilience.connectionCooldown.apikey.useUpstream429BreakerHints; + if (breakerHintsChanged) { + resetAllCircuitBreakers(); + } + return NextResponse.json({ ok: true, requestQueue: nextResilience.requestQueue, diff --git a/src/app/api/settings/export-json/route.ts b/src/app/api/settings/export-json/route.ts index 6eaa783728..0de7dbbe7a 100644 --- a/src/app/api/settings/export-json/route.ts +++ b/src/app/api/settings/export-json/route.ts @@ -21,6 +21,11 @@ export async function GET(request: Request) { } try { + const url = new URL(request.url); + // Telemetry/history tables grow indefinitely and inflate backups. + // Exclude them by default — opt-in with ?includeHistory=true (#2125). + const includeHistory = url.searchParams.get("includeHistory") === "true"; + const rawSettings = await getSettings(); // REDACT sensitive security keys to maintain Zero-Trust posture @@ -33,27 +38,30 @@ export async function GET(request: Request) { const combos = await getCombos(); const apiKeys = await getApiKeys(); - const db = getDbInstance(); - const usageHistory = db.prepare("SELECT * FROM usage_history").all(); - const domainCostHistory = db.prepare("SELECT * FROM domain_cost_history").all(); - const domainBudgets = db.prepare("SELECT * FROM domain_budgets").all(); - - const exportData = { + const exportData: Record = { settings: safeSettings, providerConnections, providerNodes, combos, apiKeys, - usageHistory, - domainCostHistory, - domainBudgets, // Metadata to identify export version _meta: { exportedAt: new Date().toISOString(), version: "omniroute-v3-legacy-export", + includesHistory: includeHistory, }, }; + // Only include telemetry/history tables when explicitly requested. + // These tables (usage_history, domain_cost_history, domain_budgets) can contain + // thousands of rows and make the config backup grow to many MBs. + if (includeHistory) { + const db = getDbInstance(); + exportData.usageHistory = db.prepare("SELECT * FROM usage_history").all(); + exportData.domainCostHistory = db.prepare("SELECT * FROM domain_cost_history").all(); + exportData.domainBudgets = db.prepare("SELECT * FROM domain_budgets").all(); + } + return new NextResponse(JSON.stringify(exportData, null, 2), { status: 200, headers: { diff --git a/src/app/api/usage/analytics/route.ts b/src/app/api/usage/analytics/route.ts index e3fada7b03..fc76fbce7b 100644 --- a/src/app/api/usage/analytics/route.ts +++ b/src/app/api/usage/analytics/route.ts @@ -555,6 +555,7 @@ export async function GET(request: Request) { COALESCE(NULLIF(service_tier, ''), 'standard') as serviceTier, LOWER(provider) as provider, LOWER(model) as model, + COALESCE(NULLIF(service_tier, ''), 'standard') as serviceTier, COUNT(*) as requests, COALESCE(SUM(tokens_input), 0) as promptTokens, COALESCE(SUM(tokens_output), 0) as completionTokens, @@ -563,6 +564,7 @@ export async function GET(request: Request) { COALESCE(SUM(tokens_reasoning), 0) as reasoningTokens, COALESCE(SUM(tokens_input + tokens_output), 0) as totalTokens FROM usage_history + ${whereClause} GROUP BY serviceTier, LOWER(provider), LOWER(model) ` diff --git a/src/app/api/v1/agents/tasks/[id]/route.ts b/src/app/api/v1/agents/tasks/[id]/route.ts new file mode 100644 index 0000000000..031bd51a29 --- /dev/null +++ b/src/app/api/v1/agents/tasks/[id]/route.ts @@ -0,0 +1,186 @@ +import { NextRequest, NextResponse } from "next/server"; +import { extractApiKey } from "@/sse/services/auth"; +import { getAgent } from "@/lib/cloudAgent/registry"; +import { getCloudAgentTaskById, updateCloudAgentTask } from "@/lib/cloudAgent/db"; +import { z } from "zod"; +import pino from "pino"; + +const logger = pino({ name: "cloud-agents-api" }); + +function getCorsHeaders() { + return { + "Access-Control-Allow-Origin": "*", + "Access-Control-Allow-Methods": "GET, POST, PUT, DELETE, OPTIONS", + "Access-Control-Allow-Headers": "Content-Type, Authorization", + }; +} + +export async function OPTIONS() { + return new NextResponse(null, { headers: getCorsHeaders() }); +} + +const ApproveSchema = z.object({ + action: z.literal("approve"), +}); + +const MessageSchema = z.object({ + action: z.literal("message"), + message: z.string().min(1), +}); + +const CancelSchema = z.object({ + action: z.literal("cancel"), +}); + +export async function GET(request: NextRequest, { params }: { params: Promise<{ id: string }> }) { + try { + const { id } = await params; + const task = getCloudAgentTaskById(id); + + if (!task) { + return NextResponse.json( + { error: "Task not found" }, + { status: 404, headers: getCorsHeaders() } + ); + } + + const apiKey = extractApiKey(request); + if (!apiKey) { + return NextResponse.json( + { error: "API key required" }, + { status: 401, headers: getCorsHeaders() } + ); + } + + const agent = getAgent(task.provider_id); + if (agent && task.external_id) { + try { + const statusResult = await agent.getStatus(task.external_id, { apiKey }); + + updateCloudAgentTask(id, { + status: statusResult.status, + result: statusResult.result ? JSON.stringify(statusResult.result) : null, + activities: JSON.stringify(statusResult.activities), + error: statusResult.error || null, + completed_at: + statusResult.status === "completed" || statusResult.status === "failed" + ? new Date().toISOString() + : null, + }); + } catch (err) { + console.error("Failed to sync task status:", err); + } + } + + const updatedTask = getCloudAgentTaskById(id); + + return NextResponse.json( + { + data: { + id: updatedTask!.id, + providerId: updatedTask!.provider_id, + externalId: updatedTask!.external_id, + status: updatedTask!.status, + prompt: updatedTask!.prompt, + source: JSON.parse(updatedTask!.source), + options: JSON.parse(updatedTask!.options), + result: updatedTask!.result ? JSON.parse(updatedTask!.result) : null, + activities: JSON.parse(updatedTask!.activities), + error: updatedTask!.error, + createdAt: updatedTask!.created_at, + updatedAt: updatedTask!.updated_at, + completedAt: updatedTask!.completed_at, + }, + }, + { headers: getCorsHeaders() } + ); + } catch (error) { + return NextResponse.json( + { error: error instanceof Error ? error.message : "Unknown error" }, + { status: 500, headers: getCorsHeaders() } + ); + } +} + +export async function POST(request: NextRequest, { params }: { params: Promise<{ id: string }> }) { + try { + const { id } = await params; + const body = await request.json(); + + const task = getCloudAgentTaskById(id); + if (!task) { + return NextResponse.json( + { error: "Task not found" }, + { status: 404, headers: getCorsHeaders() } + ); + } + + const apiKey = extractApiKey(request); + if (!apiKey) { + return NextResponse.json( + { error: "API key required" }, + { status: 401, headers: getCorsHeaders() } + ); + } + + let validated; + if (body.action === "approve") { + validated = ApproveSchema.parse(body); + } else if (body.action === "message") { + validated = MessageSchema.parse(body); + } else if (body.action === "cancel") { + validated = CancelSchema.parse(body); + } else { + return NextResponse.json( + { error: "Invalid action" }, + { status: 400, headers: getCorsHeaders() } + ); + } + + const agent = getAgent(task.provider_id); + if (!agent) { + return NextResponse.json( + { error: "Agent not found" }, + { status: 500, headers: getCorsHeaders() } + ); + } + + if (validated.action === "approve") { + if (!task.external_id) { + return NextResponse.json( + { error: "No external task to approve" }, + { status: 400, headers: getCorsHeaders() } + ); + } + await agent.approvePlan(task.external_id, { apiKey }); + updateCloudAgentTask(id, { status: "running" }); + } else if (validated.action === "message") { + if (!task.external_id) { + return NextResponse.json( + { error: "No external task to message" }, + { status: 400, headers: getCorsHeaders() } + ); + } + const activity = await agent.sendMessage(task.external_id, validated.message, { apiKey }); + const activities = JSON.parse(task.activities); + activities.push(activity); + updateCloudAgentTask(id, { activities: JSON.stringify(activities) }); + } else if (validated.action === "cancel") { + updateCloudAgentTask(id, { status: "cancelled" }); + } + + return NextResponse.json({ success: true }, { headers: getCorsHeaders() }); + } catch (error) { + if (error instanceof z.ZodError) { + return NextResponse.json( + { error: "Validation failed", details: error.errors }, + { status: 400, headers: getCorsHeaders() } + ); + } + logger.error({ err: error }, "Failed to process task action"); + return NextResponse.json( + { error: error instanceof Error ? error.message : "Unknown error" }, + { status: 500, headers: getCorsHeaders() } + ); + } +} diff --git a/src/app/api/v1/agents/tasks/route.ts b/src/app/api/v1/agents/tasks/route.ts new file mode 100644 index 0000000000..600817d107 --- /dev/null +++ b/src/app/api/v1/agents/tasks/route.ts @@ -0,0 +1,173 @@ +import { NextRequest, NextResponse } from "next/server"; +import { extractApiKey } from "@/sse/services/auth"; +import { getAgent } from "@/lib/cloudAgent/registry"; +import { + insertCloudAgentTask, + getCloudAgentTaskById, + getAllCloudAgentTasks, + getCloudAgentTasksByProvider, + getCloudAgentTasksByStatus, + updateCloudAgentTask, + deleteCloudAgentTask, +} from "@/lib/cloudAgent/db"; +import { CreateCloudAgentTaskSchema } from "@/lib/cloudAgent/types"; +import { CLOUD_AGENT_PROVIDERS } from "@/shared/constants/providers"; +import { z } from "zod"; +import pino from "pino"; + +const logger = pino({ name: "cloud-agents-api" }); + +function getCorsHeaders() { + return { + "Access-Control-Allow-Origin": "*", + "Access-Control-Allow-Methods": "GET, POST, PUT, DELETE, OPTIONS", + "Access-Control-Allow-Headers": "Content-Type, Authorization", + }; +} + +export async function OPTIONS() { + return new NextResponse(null, { headers: getCorsHeaders() }); +} + +export async function GET(request: NextRequest) { + try { + const { searchParams } = new URL(request.url); + const providerId = searchParams.get("provider"); + const status = searchParams.get("status"); + const limit = parseInt(searchParams.get("limit") || "50", 10); + + let tasks; + if (providerId) { + tasks = getCloudAgentTasksByProvider(providerId, limit); + } else if (status) { + tasks = getCloudAgentTasksByStatus(status, limit); + } else { + tasks = getAllCloudAgentTasks(limit); + } + + return NextResponse.json( + { + data: tasks.map((t) => ({ + id: t.id, + providerId: t.provider_id, + externalId: t.external_id, + status: t.status, + prompt: t.prompt, + source: JSON.parse(t.source), + options: JSON.parse(t.options), + result: t.result ? JSON.parse(t.result) : null, + activities: JSON.parse(t.activities), + error: t.error, + createdAt: t.created_at, + updatedAt: t.updated_at, + completedAt: t.completed_at, + })), + }, + { headers: getCorsHeaders() } + ); + } catch (error) { + return NextResponse.json( + { error: error instanceof Error ? error.message : "Unknown error" }, + { status: 500, headers: getCorsHeaders() } + ); + } +} + +export async function POST(request: NextRequest) { + try { + const body = await request.json(); + const validated = CreateCloudAgentTaskSchema.parse(body); + + const apiKey = extractApiKey(request); + if (!apiKey) { + return NextResponse.json( + { error: "API key required" }, + { status: 401, headers: getCorsHeaders() } + ); + } + + const agent = getAgent(validated.providerId); + if (!agent) { + return NextResponse.json( + { error: `Unknown provider: ${validated.providerId}` }, + { status: 400, headers: getCorsHeaders() } + ); + } + + const task = await agent.createTask( + { + prompt: validated.prompt, + source: validated.source, + options: validated.options || {}, + }, + { apiKey } + ); + + insertCloudAgentTask({ + id: task.id, + provider_id: task.providerId, + external_id: task.externalId || null, + status: task.status, + prompt: task.prompt, + source: JSON.stringify(task.source), + options: JSON.stringify(task.options), + result: null, + activities: JSON.stringify(task.activities), + error: null, + created_at: task.createdAt, + updated_at: task.updatedAt, + completed_at: null, + }); + + return NextResponse.json( + { + data: { + id: task.id, + providerId: task.providerId, + externalId: task.externalId, + status: task.status, + prompt: task.prompt, + source: task.source, + options: task.options, + createdAt: task.createdAt, + }, + }, + { status: 201, headers: getCorsHeaders() } + ); + } catch (error) { + if (error instanceof z.ZodError) { + return NextResponse.json( + { error: "Validation failed", details: error.errors }, + { status: 400, headers: getCorsHeaders() } + ); + } + logger.error({ err: error }, "Failed to create cloud agent task"); + return NextResponse.json( + { error: error instanceof Error ? error.message : "Unknown error" }, + { status: 500, headers: getCorsHeaders() } + ); + } +} + +export async function DELETE(request: NextRequest) { + try { + const { searchParams } = new URL(request.url); + const taskId = searchParams.get("id"); + + if (!taskId) { + return NextResponse.json( + { error: "Task ID required" }, + { status: 400, headers: getCorsHeaders() } + ); + } + + deleteCloudAgentTask(taskId); + + return NextResponse.json({ success: true }, { headers: getCorsHeaders() }); + } catch (error) { + return NextResponse.json( + { error: error instanceof Error ? error.message : "Unknown error" }, + { status: 500, headers: getCorsHeaders() } + ); + } +} diff --git a/src/i18n/messages/en.json b/src/i18n/messages/en.json index 07b6ef1647..6d47235d8c 100644 --- a/src/i18n/messages/en.json +++ b/src/i18n/messages/en.json @@ -158,6 +158,7 @@ "noLockouts": "No Lockouts", "webSearchDesc": "Web Search Desc", "audioProvidersHeading": "Audio Providers Heading", + "cloudAgentProviders": "Cloud Agent Providers", "minutesAgo": "Minutes Ago", "a": "A", "liveAutoRefreshing": "Live Auto Refreshing", @@ -668,6 +669,7 @@ "playground": "Playground", "searchTools": "Search Tools", "agents": "Agents", + "cloudAgents": "Cloud Agents", "memory": "Memory", "skills": "Skills", "docs": "Docs", @@ -4851,6 +4853,42 @@ "settingsRoutingLink": "Settings/Routing", "openSettings": "Settings" }, + "cloudAgents": { + "title": "Cloud Agents", + "description": "Manage autonomous coding agents (Jules, Devin, Codex Cloud)", + "loading": "Loading tasks...", + "aboutTitle": "About Cloud Agents", + "aboutDescription": "Cloud agents are remote AI coding assistants that can execute tasks autonomously. They work differently from local CLI agents - you interact with them through OmniRoute's API.", + "howItWorksTitle": "How it works:", + "howItWorksDesc": "Create a task → Agent analyzes and proposes a plan → You approve → Agent executes → Results returned", + "newTaskTitle": "Create New Task", + "newTaskDescription": "Start a new task with a cloud agent", + "selectAgent": "Select Agent", + "taskDescription": "Task Description", + "taskDescriptionPlaceholder": "Describe what you want the agent to do...", + "startTask": "Start Task", + "tasks": "Tasks", + "taskDetail": "Task Detail", + "noTasks": "No tasks yet. Create one to get started.", + "untitledTask": "Untitled Task", + "created": "Created", + "conversation": "Conversation", + "result": "Result", + "error": "Error", + "planReady": "Plan Ready for Approval", + "approvePlan": "Approve Plan", + "rejectPlan": "Reject & Cancel", + "sendMessagePlaceholder": "Send a message to the agent...", + "cancel": "Cancel", + "delete": "Delete", + "selectTaskPrompt": "Select a task to view details", + "statusPending": "Pending", + "statusRunning": "Running", + "statusWaitingApproval": "Waiting Approval", + "statusCompleted": "Completed", + "statusFailed": "Failed", + "statusCancelled": "Cancelled" + }, "templateNames": { "simple-chat": "Simple Chat", "streaming": "Streaming", diff --git a/src/i18n/messages/zh-CN.json b/src/i18n/messages/zh-CN.json index e6cd0d6ca5..c46df5d17e 100644 --- a/src/i18n/messages/zh-CN.json +++ b/src/i18n/messages/zh-CN.json @@ -140,515 +140,515 @@ "http": "HTTP", "goToDashboard": "前往仪表板", "checkSystemStatus": "查看系统状态", - "selectModel": "Select Model", + "selectModel": "选择模型", "combos": "Combos", - "noModelsFound": "No models found", - "clear": "Clear", - "done": "Done", - "errorOccurred": "Error Occurred", - "comboDeleted": "Combo Deleted", - "hide": "Hide", - "creating": "Creating", - "comboCreated": "Combo Created", - "swapFormats": "Swap Formats", - "daysAgo": "Days Ago", - "retries": "Retries", - "errorDuringRestore": "Error During Restore", - "eventsAppearHint": "Events Appear Hint", - "noLockouts": "No Lockouts", - "webSearchDesc": "Web Search Desc", - "audioProvidersHeading": "Audio Providers Heading", - "minutesAgo": "Minutes Ago", + "noModelsFound": "未找到 Model", + "clear": "清除", + "done": "完成", + "errorOccurred": "错误发生", + "comboDeleted": "Combo 已删除", + "hide": "隐藏", + "creating": "正在创建", + "comboCreated": "Combo 已创建", + "swapFormats": "交换格式", + "daysAgo": "天前", + "retries": "重试次数", + "errorDuringRestore": "错误期间恢复", + "eventsAppearHint": "事件显示提示", + "noLockouts": "无锁定", + "webSearchDesc": "Web Search 功能说明", + "audioProvidersHeading": "音频 Provider", + "minutesAgo": "分钟前", "a": "A", - "liveAutoRefreshing": "Live Auto Refreshing", + "liveAutoRefreshing": "实时自动刷新中", "webSearch": "Web Search", - "anthropicPrefixPlaceholder": "Anthropic Prefix Placeholder", - "addModelToCombo": "Add Model To Combo", - "failedToLoad": "Failed To Load", - "categoryMedia": "Category Media", - "enableCloud": "Enable Cloud", - "expirationBannerExpiringSoon": "Expiration Banner Expiring Soon", - "retry": "Retry", + "anthropicPrefixPlaceholder": "Anthropic 前缀", + "addModelToCombo": "添加模型到组合", + "failedToLoad": "加载失败", + "categoryMedia": "类别媒体", + "enableCloud": "启用云端", + "expirationBannerExpiringSoon": "过期横幅即将过期即将", + "retry": "重试", "embeddings": "Embeddings", - "errorCount": "Error Count", - "backupReasonManual": "Backup Reason Manual", - "safeSearchModerate": "Safe Search Moderate", - "activeLimiters": "Active Limiters", - "a2aCardTitle": "A2A Card Title", - "cloudWorkerUnreachable": "Cloud Worker Unreachable", - "testFailed": "Test Failed", - "compatibleBaseUrlHint": "Compatible Base Url Hint", - "usageTracking": "Usage Tracking", - "disableCloudTitle": "Disable Cloud Title", - "noConnections": "No Connections", - "providerHealth": "Provider Health", - "confirmDbImport": "Confirm Db Import", - "notAvailableSymbol": "Not Available Symbol", - "backupsAvailable": "Backups Available", - "providerAuto": "Provider Auto", - "newProviderNamePlaceholder": "New Provider Name Placeholder", - "a2aQuickStartStep2": "A2A Quick Start Step2", - "ok": "Ok", - "available": "Available", - "noBackupYet": "No Backup Yet", - "more": "More", - "noCompatibleYet": "No Compatible Yet", - "multiProvider": "Multi Provider", - "repairEnvHint": "Repair Env Hint", - "disablingCloud": "Disabling Cloud", - "testBench": "Test Bench", - "valid": "Valid", - "cloudBenefitShare": "Cloud Benefit Share", - "mcpCardTitle": "Mcp Card Title", - "disableConfirm": "Disable Confirm", - "filters": "Filters", - "expirationBannerExpiredDesc": "Expiration Banner Expired Desc", - "saveComboDefaults": "Save Combo Defaults", - "cloudConnectedVerified": "Cloud Connected Verified", - "uptime": "Uptime", - "compatibleProdPlaceholder": "Compatible Prod Placeholder", - "fallbackChainsTitle": "Fallback Chains Title", - "oauthLabel": "Oauth Label", - "a2aCardDescription": "A2A Card Description", - "okShort": "Ok Short", - "maintenance": "Maintenance", - "formatConverter": "Format Converter", - "zedImportNetworkError": "Zed Import Network Error", - "apiKeyLabel": "Api Key Label", - "noModelsForProvider": "No Models For Provider", - "mcpCardDescription": "Mcp Card Description", - "apiTypeLabel": "Api Type Label", - "configuredProvidersLabel": "Configured Providers Label", - "maxRetriesLabel": "Max Retries Label", - "title": "Title", - "output": "Output", - "prefixHint": "Prefix Hint", - "skipWizard": "Skip Wizard", - "failedCount": "Failed Count", - "confirmDbImportDesc": "Confirm Db Import Desc", - "entries": "Entries", - "until": "Until", - "disableCombo": "Disable Combo", - "liveMonitorDescriptionPrefix": "Live Monitor Description Prefix", - "runningCount": "Running Count", - "noActiveConnectionsInGroup": "No Active Connections In Group", - "savedSuccessfully": "Saved Successfully", - "systemStorage": "System Storage", - "videoDesc": "Video Desc", - "maxResults": "Max Results", - "timeRangeMonth": "Time Range Month", - "testSummary": "Test Summary", - "failedSetPassword": "Failed Set Password", - "audio": "Audio", - "restore": "Restore", - "disableWarning": "Disable Warning", - "moderationsDesc": "Moderations Desc", - "providerHealthStatusAria": "Provider Health Status Aria", - "modelNamePlaceholder": "Model Name Placeholder", - "mcpQuickStartStep2": "Mcp Quick Start Step2", - "quickStart": "Quick Start", - "fullExportFailedWithError": "Full Export Failed With Error", - "loadingBackups": "Loading Backups", - "anthropicBaseUrlPlaceholder": "Anthropic Base Url Placeholder", - "description": "Description", - "noProviderFound": "No Provider Found", - "auto": "Auto", - "protocolsDescription": "Protocols Description", - "cloudSessionNote": "Cloud Session Note", - "advancedSettings": "Advanced Settings", - "defaultStrategy": "Default Strategy", - "purgeExpiredLogs": "Purge Expired Logs", - "justNow": "Just Now", - "providerTestFailed": "Provider Test Failed", - "openaiBaseUrlPlaceholder": "Openai Base Url Placeholder", - "image": "Image", - "failedCreateChain": "Failed Create Chain", - "importDatabase": "Import Database", - "allDataLocal": "All Data Local", - "sectionTitle": "Section Title", - "failedToggle": "Failed Toggle", - "editCombo": "Edit Combo", - "testResults": "Test Results", - "searchQuery": "Search Query", + "errorCount": "错误数量", + "backupReasonManual": "备份原因手动", + "safeSearchModerate": "安全搜索中等", + "activeLimiters": "活跃限制器", + "a2aCardTitle": "A2A", + "cloudWorkerUnreachable": "Cloud Worker 不可达", + "testFailed": "测试失败", + "compatibleBaseUrlHint": "填写兼容 API 的 Base URL。", + "usageTracking": "使用量跟踪", + "disableCloudTitle": "禁用云端", + "noConnections": "无连接", + "providerHealth": "提供商健康状态", + "confirmDbImport": "确认DB导入", + "notAvailableSymbol": "—", + "backupsAvailable": "可用备份", + "providerAuto": "自动提供商", + "newProviderNamePlaceholder": "新的提供商名称", + "a2aQuickStartStep2": "A2A快速开始步骤2", + "ok": "确定", + "available": "可用", + "noBackupYet": "无备份暂无", + "more": "更多", + "noCompatibleYet": "无兼容暂无", + "multiProvider": "多提供商", + "repairEnvHint": "修复环境提示", + "disablingCloud": "正在禁用 Cloud", + "testBench": "测试台", + "valid": "有效", + "cloudBenefitShare": "共享 Cloud 访问能力", + "mcpCardTitle": "MCP", + "disableConfirm": "确认禁用?", + "filters": "筛选器", + "expirationBannerExpiredDesc": "过期横幅已过期说明", + "saveComboDefaults": "保存组合默认值", + "cloudConnectedVerified": "Cloud 连接已验证", + "uptime": "运行时间", + "compatibleProdPlaceholder": "兼容生产占位符", + "fallbackChainsTitle": "后备链", + "oauthLabel": "OAuth 标签", + "a2aCardDescription": "通过 A2A 协议连接 Agent 工作流。", + "okShort": "确定短标签", + "maintenance": "维护", + "formatConverter": "格式转换器", + "zedImportNetworkError": "Zed 导入网络错误", + "apiKeyLabel": "API key 标签", + "noModelsForProvider": "此提供商没有可用模型", + "mcpCardDescription": "通过 MCP 工具连接 Agent 和自动化流程。", + "apiTypeLabel": "API 类型标签", + "configuredProvidersLabel": "已配置 Provider 标签", + "maxRetriesLabel": "最大重试次数标签", + "title": "标题", + "output": "输出", + "prefixHint": "前缀提示", + "skipWizard": "跳过向导", + "failedCount": "失败数量", + "confirmDbImportDesc": "确认DB导入说明", + "entries": "条目", + "until": "直到", + "disableCombo": "禁用组合", + "liveMonitorDescriptionPrefix": "实时显示请求流经 OmniRoute 时产生的事件。使用", + "runningCount": "运行中数量", + "noActiveConnectionsInGroup": "此分组中没有活跃连接", + "savedSuccessfully": "保存成功", + "systemStorage": "系统存储", + "videoDesc": "视频说明", + "maxResults": "最大结果数", + "timeRangeMonth": "时间范围月", + "testSummary": "测试摘要", + "failedSetPassword": "设置密码失败", + "audio": "音频", + "restore": "恢复", + "disableWarning": "禁用警告", + "moderationsDesc": "审核说明", + "providerHealthStatusAria": "提供商健康状态", + "modelNamePlaceholder": "模型名称", + "mcpQuickStartStep2": "MCP 快速开始步骤 2", + "quickStart": "快速开始", + "fullExportFailedWithError": "完整导出失败:{error}", + "loadingBackups": "正在加载备份", + "anthropicBaseUrlPlaceholder": "Anthropic Base URL", + "description": "描述", + "noProviderFound": "未找到提供商", + "auto": "自动", + "protocolsDescription": "配置并测试支持的协议端点。", + "cloudSessionNote": "Cloud Session 提示", + "advancedSettings": "高级设置", + "defaultStrategy": "默认策略", + "purgeExpiredLogs": "清理已过期日志", + "justNow": "刚刚现在", + "providerTestFailed": "提供商测试失败", + "openaiBaseUrlPlaceholder": "OpenAI Base URL", + "image": "图像", + "failedCreateChain": "创建链失败", + "importDatabase": "导入数据库", + "allDataLocal": "全部数据本地", + "sectionTitle": "分区标题", + "failedToggle": "切换失败", + "editCombo": "编辑 Combo", + "testResults": "测试结果", + "searchQuery": "搜索查询", "addCcCompatible": "添加 CC 兼容", - "duplicate": "Duplicate", - "createCombo": "Create Combo", - "searchTypeWeb": "Search Type Web", - "addChain": "Add Chain", - "prefixLabel": "Prefix Label", - "listModelsDesc": "List Models Desc", - "databaseSize": "Database Size", - "chainCreated": "Chain Created", - "providerTestTimeout": "Provider Test Timeout", - "routingStrategy": "Routing Strategy", - "translateAction": "Translate Action", - "exportFailed": "Export Failed", - "connectedVerificationPending": "Connected Verification Pending", - "a2aQuickStartTitle": "A2A Quick Start Title", - "couldNotTest": "Could Not Test", - "testAllCompatible": "Test All Compatible", - "anthropicCompatibleName": "Anthropic Compatible Name", - "disabling": "Disabling", - "failedEnable": "Failed Enable", - "categoryUtility": "Category Utility", - "customUrlOptional": "Custom Url Optional", - "localProviders": "Local Providers", - "comboNamePlaceholder": "Combo Name Placeholder", - "memoryRss": "Memory Rss", - "disableProvider": "Disable Provider", - "welcomeDesc": "Welcome Desc", - "nameLabel": "Name Label", - "allOperational": "All Operational", - "backupNow": "Backup Now", - "providerMaxRetriesAria": "Provider Max Retries Aria", - "textToSpeechDesc": "Text To Speech Desc", - "machineId": "Machine Id", - "globalProxy": "Global Proxy", - "hitsMisses": "Hits Misses", - "testDesc": "Test Desc", - "chatDesc": "Chat Desc", - "importSuccess": "Import Success", - "chat": "Chat", - "a2aQuickStartStep1": "A2A Quick Start Step1", - "importFailed": "Import Failed", - "inputPlaceholder": "Input Placeholder", - "providerModelsTitle": "Provider Models Title", - "lastBackup": "Last Backup", - "yourEndpoint": "Your Endpoint", - "autoDisableThresholdDesc": "Auto Disable Threshold Desc", - "rerankDesc": "Rerank Desc", - "modelsPathPlaceholder": "Models Path Placeholder", - "noCombosYet": "No Combos Yet", - "connectedVerificationPendingWithError": "Connected Verification Pending With Error", - "comboDefaultsGuideHint1": "Combo Defaults Guide Hint1", - "enableCloudTitle": "Enable Cloud Title", - "configuredProvidersHint": "Configured Providers Hint", - "paused": "Paused", - "llmProviders": "Llm Providers", - "enableCombo": "Enable Combo", - "removeProviderOverrideAria": "Remove Provider Override Aria", - "nodeVersion": "Node Version", + "duplicate": "重复", + "createCombo": "创建组合", + "searchTypeWeb": "搜索类型:Web", + "addChain": "添加链", + "prefixLabel": "前缀标签", + "listModelsDesc": "列出可用 Model。", + "databaseSize": "数据库大小", + "chainCreated": "链已创建", + "providerTestTimeout": "提供商测试超时", + "routingStrategy": "路由策略", + "translateAction": "翻译操作", + "exportFailed": "导出失败", + "connectedVerificationPending": "连接验证待处理", + "a2aQuickStartTitle": "A2A 快速开始", + "couldNotTest": "无法测试", + "testAllCompatible": "测试所有兼容项", + "anthropicCompatibleName": "Anthropic 兼容名称", + "disabling": "正在禁用", + "failedEnable": "启用失败", + "categoryUtility": "工具类别", + "customUrlOptional": "自定义 URL(可选)", + "localProviders": "本地 Provider", + "comboNamePlaceholder": "Combo 名称", + "memoryRss": "内存 RSS", + "disableProvider": "禁用提供商", + "welcomeDesc": "欢迎使用 OmniRoute。", + "nameLabel": "名称标签", + "allOperational": "全部运行正常", + "backupNow": "备份现在", + "providerMaxRetriesAria": "提供商最大重试次数", + "textToSpeechDesc": "将文本转换为语音音频。", + "machineId": "机器 ID", + "globalProxy": "全局代理", + "hitsMisses": "命中未命中", + "testDesc": "运行连接测试以验证配置。", + "chatDesc": "聊天说明", + "importSuccess": "导入成功", + "chat": "聊天", + "a2aQuickStartStep1": "A2A快速开始步骤1", + "importFailed": "导入失败", + "inputPlaceholder": "输入内容...", + "providerModelsTitle": "提供商模型", + "lastBackup": "最近备份", + "yourEndpoint": "你的 Endpoint", + "autoDisableThresholdDesc": "触发自动禁用前允许的连续失败次数。", + "rerankDesc": "重排说明", + "modelsPathPlaceholder": "Model 路径", + "noCombosYet": "暂无 Combo", + "connectedVerificationPendingWithError": "已连接,验证待完成:{error}", + "comboDefaultsGuideHint1": "配置 Combo 默认策略和目标。", + "enableCloudTitle": "启用云端", + "configuredProvidersHint": "仅显示已配置的 Provider。", + "paused": "已暂停", + "llmProviders": "LLM Provider", + "enableCombo": "启用组合", + "removeProviderOverrideAria": "移除提供商覆盖", + "nodeVersion": "Node 版本", "openai": "Openai", - "exportFailedWithError": "Export Failed With Error", - "proxyConfigured": "Proxy Configured", - "concurrencyPerModel": "Concurrency Per Model", - "protocolTasksLabel": "Protocol Tasks Label", + "exportFailedWithError": "导出失败:{error}", + "proxyConfigured": "代理已配置", + "concurrencyPerModel": "每个模型并发数", + "protocolTasksLabel": "协议任务标签", "oauthProviders": "Oauth Providers", - "lockedCount": "Locked Count", - "deleteChainConfirm": "Delete Chain Confirm", - "recentTranslations": "Recent Translations", - "zedImportButton": "Zed Import Button", - "responsesDesc": "Responses Desc", - "testedCount": "Tested Count", - "providersCommaSeparatedPlaceholder": "Providers Comma Separated Placeholder", - "signatureDefaults": "Signature Defaults", - "errorCreating": "Error Creating", - "timeRangeYear": "Time Range Year", + "lockedCount": "已锁定数量", + "deleteChainConfirm": "删除此后备链?", + "recentTranslations": "最近翻译", + "zedImportButton": "从 Zed 导入", + "responsesDesc": "Responses API 兼容端点", + "testedCount": "已测试数量", + "providersCommaSeparatedPlaceholder": "以逗号分隔的 Provider", + "signatureDefaults": "签名默认值", + "errorCreating": "错误创建", + "timeRangeYear": "时间范围年", "compatibleLabel": "兼容", - "cloudDisabledSuccess": "Cloud Disabled Success", - "deleteConfirm": "Delete Confirm", - "check": "Check", - "safeSearch": "Safe Search", - "protocolLastActivity": "Protocol Last Activity", - "openMcpDashboard": "Open Mcp Dashboard", - "testBenchTab": "Test Bench Tab", - "chatPathLabel": "Chat Path Label", - "retryDelay": "Retry Delay", - "errorUpdating": "Error Updating", - "ideCliIntegrations": "Ide Cli Integrations", - "imageGeneration": "Image Generation", - "apiKeyRequired": "Api Key Required", - "resetAllTitle": "Reset All Title", - "connectionError": "Connection Error", - "modelName": "Model Name", - "apiKeyForCheck": "Api Key For Check", - "cloudRequestTimeout": "Cloud Request Timeout", - "showConfiguredOnly": "Show Configured Only", - "includeDomains": "Include Domains", - "promptCache": "Prompt Cache", - "cloudConnected": "Cloud Connected", - "deleteChain": "Delete Chain", - "chatPathPlaceholder": "Chat Path Placeholder", - "databasePath": "Database Path", - "usingLocalServer": "Using Local Server", - "globalComboConfig": "Global Combo Config", - "backupFailed": "Backup Failed", - "tabProtocols": "Tab Protocols", - "continue": "Continue", - "categorySearch": "Category Search", - "rateLimitStatus": "Rate Limit Status", - "repairEnvSuccess": "Repair Env Success", - "nameRequired": "Name Required", - "country": "Country", - "trackMetricsDesc": "Track Metrics Desc", - "durationSecondsShort": "Duration Seconds Short", - "formatConverterDescription": "Format Converter Description", - "cloudBenefitAccess": "Cloud Benefit Access", - "maxRetries": "Max Retries", - "queueTimeout": "Queue Timeout", - "addProvider": "Add Provider", - "realtime": "Realtime", - "totalTranslations": "Total Translations", - "protocolActiveStreamsLabel": "Protocol Active Streams Label", - "repairEnv": "Repair Env", - "modelsCount": "Models Count", - "viewBackups": "View Backups", - "responsesApi": "Responses Api", - "copyComboName": "Copy Combo Name", - "failures": "Failures", - "failedUpdate": "Failed Update", - "imageDesc": "Image Desc", - "failedCreate": "Failed Create", - "remainingOfLimit": "Remaining Of Limit", - "protocolsTitle": "Protocols Title", - "expirationBannerExpiringSoonDesc": "Expiration Banner Expiring Soon Desc", - "source": "Source", - "failed": "Failed", - "apiKeyMgmt": "Api Key Mgmt", - "mcpQuickStartStep1": "Mcp Quick Start Step1", - "runTest": "Run Test", - "loadingFallbackChains": "Loading Fallback Chains", - "healthy": "Healthy", - "version": "Version", - "saveBlockWeighted": "Save Block Weighted", - "zedImportNone": "Zed Import None", - "noBackupsYet": "No Backups Yet", - "noGlobalProxy": "No Global Proxy", - "noModels": "No Models", - "stickyLimit": "Sticky Limit", - "passedCount": "Passed Count", - "zedImportFailed": "Zed Import Failed", - "saving": "Saving", - "testAll": "Test All", - "globalProxyDesc": "Global Proxy Desc", - "latencyP99": "Latency P99", - "connectingToCloud": "Connecting To Cloud", + "cloudDisabledSuccess": "云端已禁用", + "deleteConfirm": "确认删除?", + "check": "检查", + "safeSearch": "安全搜索", + "protocolLastActivity": "协议最近活动", + "openMcpDashboard": "打开 MCP Dashboard", + "testBenchTab": "测试台", + "chatPathLabel": "聊天路径标签", + "retryDelay": "重试延迟", + "errorUpdating": "错误更新", + "ideCliIntegrations": "IDE 与 CLI 集成", + "imageGeneration": "图像生成", + "apiKeyRequired": "API key 为必填项", + "resetAllTitle": "全部重置", + "connectionError": "连接错误", + "modelName": "模型名称", + "apiKeyForCheck": "用于检查的 API 密钥", + "cloudRequestTimeout": "云端请求超时", + "showConfiguredOnly": "显示已配置仅", + "includeDomains": "包含域名", + "promptCache": "提示缓存", + "cloudConnected": "Cloud 已连接", + "deleteChain": "删除链", + "chatPathPlaceholder": "聊天路径占位符", + "databasePath": "数据库路径", + "usingLocalServer": "正在使用本地 Server", + "globalComboConfig": "全局 Combo 配置", + "backupFailed": "备份失败", + "tabProtocols": "协议标签页", + "continue": "继续", + "categorySearch": "类别搜索", + "rateLimitStatus": "速率限制状态", + "repairEnvSuccess": "环境修复成功", + "nameRequired": "名称必填", + "country": "国家/地区", + "trackMetricsDesc": "跟踪请求、延迟和成本指标。", + "durationSecondsShort": "时长秒短标签", + "formatConverterDescription": "在不同 API 格式之间转换请求。", + "cloudBenefitAccess": "访问 Cloud 能力", + "maxRetries": "最大重试次数", + "queueTimeout": "队列超时", + "addProvider": "添加提供商", + "realtime": "实时", + "totalTranslations": "总计翻译", + "protocolActiveStreamsLabel": "协议活跃 Stream", + "repairEnv": "修复环境", + "modelsCount": "Model 数量", + "viewBackups": "查看备份", + "responsesApi": "Responses API", + "copyComboName": "复制 Combo 名称", + "failures": "失败", + "failedUpdate": "更新失败", + "imageDesc": "图像说明", + "failedCreate": "创建失败", + "remainingOfLimit": "剩余Of限制", + "protocolsTitle": "协议", + "expirationBannerExpiringSoonDesc": "过期横幅即将过期即将说明", + "source": "来源", + "failed": "失败", + "apiKeyMgmt": "API key 管理", + "mcpQuickStartStep1": "MCP 快速开始步骤 1", + "runTest": "运行测试", + "loadingFallbackChains": "正在加载后备链", + "healthy": "健康", + "version": "版本", + "saveBlockWeighted": "保存 Block Weighted", + "zedImportNone": "没有可从 Zed 导入的内容", + "noBackupsYet": "无备份暂无", + "noGlobalProxy": "无全局代理", + "noModels": "无 Model", + "stickyLimit": "粘性限制", + "passedCount": "通过数量", + "zedImportFailed": "Zed 导入失败", + "saving": "正在保存", + "testAll": "全部测试", + "globalProxyDesc": "全局代理说明", + "latencyP99": "延迟P99", + "connectingToCloud": "正在连接云端", "responses": "Responses", - "errorDeleting": "Error Deleting", - "openaiPrefixPlaceholder": "Openai Prefix Placeholder", - "enterPassword": "Enter Password", - "openA2aDashboard": "Open A2A Dashboard", - "enableProvider": "Enable Provider", - "modeTest": "Mode Test", - "failedDeleteChain": "Failed Delete Chain", - "providerDesc": "Provider Desc", - "templateLoadHint": "Template Load Hint", - "lastFailure": "Last Failure", - "moveDown": "Move Down", - "providerLabel": "Provider Label", - "clearCacheFailed": "Clear Cache Failed", - "imagesGenerations": "Images Generations", - "repairEnvWorking": "Repair Env Working", - "millisecondsShort": "Milliseconds Short", - "globalLabel": "Global Label", - "failuresPlural": "Failures Plural", - "completionsLegacyDesc": "Completions Legacy Desc", - "searchProviders": "Search Providers", - "chatPathHint": "Chat Path Hint", - "defaultStrategyDesc": "Default Strategy Desc", - "latencyP95": "Latency P95", - "textToSpeech": "Text To Speech", - "searchType": "Search Type", + "errorDeleting": "错误删除", + "openaiPrefixPlaceholder": "OpenAI 前缀", + "enterPassword": "输入密码", + "openA2aDashboard": "打开 A2A Dashboard", + "enableProvider": "启用提供商", + "modeTest": "测试模式", + "failedDeleteChain": "删除链失败", + "providerDesc": "提供商描述", + "templateLoadHint": "选择模板以快速填充配置。", + "lastFailure": "最近失败", + "moveDown": "移动下移", + "providerLabel": "提供商标签", + "clearCacheFailed": "清除缓存失败", + "imagesGenerations": "图像生成", + "repairEnvWorking": "修复环境处理中", + "millisecondsShort": "毫秒短标签", + "globalLabel": "全局标签", + "failuresPlural": "失败复数", + "completionsLegacyDesc": "旧版 Completions API 兼容端点。", + "searchProviders": "搜索 Provider", + "chatPathHint": "聊天路径提示", + "defaultStrategyDesc": "默认策略说明", + "latencyP95": "延迟P95", + "textToSpeech": "文本转语音", + "searchType": "搜索类型", "messages": "Messages", - "aggregatorsGateways": "Aggregators Gateways", - "comboStrategyAria": "Combo Strategy Aria", - "input": "Input", - "testingConnection": "Testing Connection", - "excludeDomains": "Exclude Domains", + "aggregatorsGateways": "聚合器与网关", + "comboStrategyAria": "Combo 策略", + "input": "输入", + "testingConnection": "正在测试连接", + "excludeDomains": "排除域名", "webCookieProviders": "Web Cookie Providers", - "allTestsPassed": "All Tests Passed", - "openaiCompatibleName": "Openai Compatible Name", - "warningCostOptimizedPartialPricing": "Warning Cost Optimized Partial Pricing", - "comboDefaultsGuideTitle": "Combo Defaults Guide Title", - "hoursAgo": "Hours Ago", - "notAvailable": "Not Available", - "skipAndContinue": "Skip And Continue", - "moderations": "Moderations", - "proxyConfig": "Proxy Config", - "upstreamProxyProviders": "Upstream Proxy Providers", - "exportAll": "Export All", - "queuedCount": "Queued Count", - "resetAll": "Reset All", - "noTranslations": "No Translations", - "avgLatency": "Avg Latency", - "throttleStatus": "Throttle Status", - "backupRetentionDesc": "Backup Retention Desc", - "noCBData": "No Cb Data", - "chainDeleted": "Chain Deleted", - "timeLeft": "Time Left", - "expirationBannerExpired": "Expiration Banner Expired", - "language": "Language", - "invalidFileType": "Invalid File Type", - "monitoredProviders": "Monitored Providers", - "errors": "Errors", - "heap": "Heap", + "allTestsPassed": "全部测试通过", + "openaiCompatibleName": "OpenAI 兼容名称", + "warningCostOptimizedPartialPricing": "部分模型缺少定价,成本优化结果可能不完整。", + "comboDefaultsGuideTitle": "组合默认值指南", + "hoursAgo": "小时前", + "notAvailable": "不可用", + "skipAndContinue": "跳过并继续", + "moderations": "审核", + "proxyConfig": "代理配置", + "upstreamProxyProviders": "上游代理 Provider", + "exportAll": "导出全部", + "queuedCount": "排队中数量", + "resetAll": "重置全部", + "noTranslations": "无翻译", + "avgLatency": "平均延迟", + "throttleStatus": "限流状态", + "backupRetentionDesc": "备份保留说明", + "noCBData": "无CB数据", + "chainDeleted": "链已删除", + "timeLeft": "时间剩余", + "expirationBannerExpired": "过期横幅已过期", + "language": "语言", + "invalidFileType": "无效文件类型", + "monitoredProviders": "监控中的 Provider", + "errors": "错误", + "heap": "堆内存", "chatCompletions": "Chat Completions", - "exampleTemplatesHint": "Example Templates Hint", - "retryDelayLabel": "Retry Delay Label", - "audioTranscription": "Audio Transcription", - "fallbackChainsDesc": "Fallback Chains Desc", - "exampleTemplates": "Example Templates", - "connectionsCount": "Connections Count", - "modelsPathLabel": "Models Path Label", - "activeProvidersHint": "Active Providers Hint", - "activeLockouts": "Active Lockouts", - "invalid": "Invalid", - "skipPassword": "Skip Password", - "moveUp": "Move Up", - "timeRange": "Time Range", - "stickyLimitDesc": "Sticky Limit Desc", - "cloudBenefitEdge": "Cloud Benefit Edge", - "custom": "Custom", - "verifying": "Verifying", - "baseUrlLabel": "Base Url Label", - "setPassword": "Set Password", - "safeSearchStrict": "Safe Search Strict", - "noChangesSinceBackup": "No Changes Since Backup", - "modelsPathHint": "Models Path Hint", - "audioTranscriptions": "Audio Transcriptions", - "testCombo": "Test Combo", - "mcpQuickStartTitle": "Mcp Quick Start Title", - "comboUpdated": "Combo Updated", - "weighted": "Weighted", - "providers": "Providers", + "exampleTemplatesHint": "示例模板提示", + "retryDelayLabel": "重试延迟标签", + "audioTranscription": "音频转写", + "fallbackChainsDesc": "定义每个模型的提供商后备顺序。", + "exampleTemplates": "示例模板", + "connectionsCount": "连接数量", + "modelsPathLabel": "Model 路径", + "activeProvidersHint": "当前正在处理请求的 Provider。", + "activeLockouts": "活跃锁定", + "invalid": "无效", + "skipPassword": "跳过密码", + "moveUp": "移动上移", + "timeRange": "时间范围", + "stickyLimitDesc": "粘性限制说明", + "cloudBenefitEdge": "边缘 Cloud 能力", + "custom": "自定义", + "verifying": "正在验证", + "baseUrlLabel": "Base URL 标签", + "setPassword": "设置密码", + "safeSearchStrict": "安全搜索严格", + "noChangesSinceBackup": "无变更自从备份", + "modelsPathHint": "用于拉取 Model 列表的路径。", + "audioTranscriptions": "音频转写", + "testCombo": "测试组合", + "mcpQuickStartTitle": "MCP 快速开始", + "comboUpdated": "Combo 已更新", + "weighted": "加权", + "providers": "Provider", "ccCompatibleLabel": "CC 兼容", - "noFallbackChainsDesc": "No Fallback Chains Desc", - "yesImport": "Yes Import", - "lockoutsAutoRefreshHint": "Lockouts Auto Refresh Hint", - "tabApis": "Tab Apis", - "sectionDescription": "Section Description", - "filter": "Filter", - "purgeLogsFailed": "Purge Logs Failed", - "latency": "Latency", - "testAllOAuth": "Test All O Auth", - "mcpQuickStartStep3": "Mcp Quick Start Step3", - "repairEnvFailed": "Repair Env Failed", - "zedImportHint": "Zed Import Hint", - "modelsAcrossEndpoints": "Models Across Endpoints", - "autoDisableBannedAccounts": "Auto Disable Banned Accounts", - "securityDesc": "Security Desc", - "listModels": "List Models", - "backupRestore": "Backup Restore", - "target": "Target", - "zedImportSuccess": "Zed Import Success", - "lastHeaderUpdate": "Last Header Update", - "categoryCore": "Category Core", - "noFallbackChains": "No Fallback Chains", - "noSearchProviders": "No Search Providers", - "autoBalance": "Auto Balance", - "noModelsYet": "No Models Yet", - "signatureFamily": "Signature Family", - "externalApiCalls": "External Api Calls", - "providerOverridesDesc": "Provider Overrides Desc", - "signatureTool": "Signature Tool", - "connectionFailed": "Connection Failed", - "activeLimitersPlural": "Active Limiters Plural", - "doneDesc": "Done Desc", - "down": "Down", - "noDataYet": "No Data Yet", - "activeProviders": "Active Providers", - "nameInvalid": "Name Invalid", - "skip": "Skip", - "createChain": "Create Chain", - "audioSpeech": "Audio Speech", - "cacheCleared": "Cache Cleared", - "searchTypeNews": "Search Type News", - "durationMillisecondsShort": "Duration Milliseconds Short", - "addOpenAICompatible": "Add Open Ai Compatible", - "chatTesterTab": "Chat Tester Tab", - "queued": "Queued", - "domainPlaceholder": "Domain Placeholder", - "durationMinutesShort": "Duration Minutes Short", - "verifyingConnection": "Verifying Connection", - "imageProviders": "Image Providers", - "protocolToolsLabel": "Protocol Tools Label", - "queryPlaceholder": "Query Placeholder", - "videoGeneration": "Video Generation", - "timeRangeWeek": "Time Range Week", - "limitExhausted": "Limit Exhausted", - "failedDisable": "Failed Disable", - "inMemoryNote": "In Memory Note", - "compatibleHint": "Compatible Hint", - "errorShort": "Error Short", - "advancedHint": "Advanced Hint", - "restoreFailed": "Restore Failed", - "searchProvidersHeading": "Search Providers Heading", - "comboName": "Combo Name", - "autoDisableDescription": "Auto Disable Description", - "embeddingsDesc": "Embeddings Desc", - "operational": "Operational", - "testAllApiKey": "Test All Api Key", - "backupCreated": "Backup Created", - "errorDuringImport": "Error During Import", - "comboDefaultsGuideHint2": "Combo Defaults Guide Hint2", - "connecting": "Connecting", - "fillModelAndProviders": "Fill Model And Providers", - "syncing": "Syncing", - "resetConfirm": "Reset Confirm", - "trackMetrics": "Track Metrics", - "successful": "Successful", - "recovering": "Recovering", - "autoDisableThreshold": "Auto Disable Threshold", + "noFallbackChainsDesc": "创建一条链路,用于定义某个模型的提供商回退顺序。", + "yesImport": "确认导入", + "lockoutsAutoRefreshHint": "锁定自动刷新提示", + "tabApis": "API 标签页", + "sectionDescription": "分区描述", + "filter": "筛选", + "purgeLogsFailed": "清理日志失败", + "latency": "延迟", + "testAllOAuth": "测试所有 OAuth", + "mcpQuickStartStep3": "MCP 快速开始步骤 3", + "repairEnvFailed": "环境修复失败", + "zedImportHint": "从 Zed 配置中导入 Provider。", + "modelsAcrossEndpoints": "跨 Endpoint 的 Model", + "autoDisableBannedAccounts": "自动禁用被封禁账户", + "securityDesc": "安全说明", + "listModels": "列出 Model", + "backupRestore": "备份恢复", + "target": "目标", + "zedImportSuccess": "Zed 导入成功", + "lastHeaderUpdate": "上次请求头更新", + "categoryCore": "类别核心", + "noFallbackChains": "无后备链", + "noSearchProviders": "无搜索 Provider", + "autoBalance": "自动均衡", + "noModelsYet": "暂无 Model", + "signatureFamily": "签名族", + "externalApiCalls": "外部 API 调用", + "providerOverridesDesc": "覆盖每个提供商的超时和重试设置。", + "signatureTool": "签名工具", + "connectionFailed": "连接失败", + "activeLimitersPlural": "活跃限制器复数", + "doneDesc": "完成说明", + "down": "下移", + "noDataYet": "无数据暂无", + "activeProviders": "活跃 Provider", + "nameInvalid": "名称无效", + "skip": "跳过", + "createChain": "创建链", + "audioSpeech": "语音合成", + "cacheCleared": "缓存已清除", + "searchTypeNews": "搜索类型:News", + "durationMillisecondsShort": "时长毫秒短标签", + "addOpenAICompatible": "添加打开Ai兼容", + "chatTesterTab": "聊天测试标签页", + "queued": "排队中", + "domainPlaceholder": "域名占位符", + "durationMinutesShort": "时长分钟短标签", + "verifyingConnection": "正在验证连接", + "imageProviders": "图像 Provider", + "protocolToolsLabel": "协议工具标签", + "queryPlaceholder": "查询占位符", + "videoGeneration": "视频生成", + "timeRangeWeek": "时间范围:周", + "limitExhausted": "限额已耗尽", + "failedDisable": "禁用失败", + "inMemoryNote": "数据仅保存在内存中。", + "compatibleHint": "兼容提示", + "errorShort": "错误短标签", + "advancedHint": "显示高级选项。", + "restoreFailed": "恢复失败", + "searchProvidersHeading": "搜索 Provider", + "comboName": "Combo 名称", + "autoDisableDescription": "当检测到永久封禁信号时自动禁用账户。", + "embeddingsDesc": "Embeddings API 兼容端点。", + "operational": "运行正常", + "testAllApiKey": "测试所有 API 密钥", + "backupCreated": "备份已创建", + "errorDuringImport": "错误期间导入", + "comboDefaultsGuideHint2": "这些默认值会在新建 Combo 时使用。", + "connecting": "正在连接", + "fillModelAndProviders": "请填写模型和提供商", + "syncing": "正在同步", + "resetConfirm": "重置确认", + "trackMetrics": "跟踪指标", + "successful": "成功", + "recovering": "正在恢复", + "autoDisableThreshold": "自动禁用阈值", "anthropic": "Anthropic", - "syncingData": "Syncing Data", - "cloudBenefitPorts": "Cloud Benefit Ports", - "compatibleProviders": "Compatible Providers", - "clearCache": "Clear Cache", - "reqs": "Reqs", - "addAnthropicCompatible": "Add Anthropic Compatible", - "apiKeyProviders": "Api Key Providers", - "tabsAria": "Tabs Aria", - "resetting": "Resetting", - "millisecondsAbbr": "Milliseconds Abbr", - "backupReasonPreRestore": "Backup Reason Pre Restore", - "disableCloud": "Disable Cloud", - "newProviderNameAria": "New Provider Name Aria", - "passwordsMismatch": "Passwords Mismatch", - "a2aQuickStartStep3": "A2A Quick Start Step3", - "liveMonitorDescriptionSuffix": "Live Monitor Description Suffix", - "failedAddProvider": "Failed Add Provider", - "addAtLeastOneProvider": "Add At Least One Provider", - "reasonSeparator": "Reason Separator", - "zedImporting": "Zed Importing", - "confirmPasswordPlaceholder": "Confirm Password Placeholder", - "whatYouGet": "What You Get", - "signatureSession": "Signature Session", - "errorCountNoCode": "Error Count No Code", - "testing": "Testing", - "providersCommaSeparated": "Providers Comma Separated", - "exportDatabase": "Export Database", - "hitRate": "Hit Rate", - "completionsLegacy": "Completions Legacy", - "removeModel": "Remove Model", - "timeRangeDay": "Time Range Day", - "cloudRequestFailed": "Cloud Request Failed", - "updatedAt": "Updated At", - "monitoredProvidersHint": "Monitored Providers Hint", - "connectionSuccessful": "Connection Successful", - "latencyP50": "Latency P50", - "logsDeleted": "Logs Deleted", - "chatTester": "Chat Tester", - "safeSearchOff": "Safe Search Off", - "nameHint": "Name Hint", - "debugToggle": "Debug Toggle", + "syncingData": "正在同步数据", + "cloudBenefitPorts": "通过 Cloud 暴露端口", + "compatibleProviders": "兼容 Provider", + "clearCache": "清除缓存", + "reqs": "请求数", + "addAnthropicCompatible": "添加 Anthropic 兼容 Provider", + "apiKeyProviders": "API key Provider", + "tabsAria": "标签页", + "resetting": "正在重置", + "millisecondsAbbr": "毫秒缩写", + "backupReasonPreRestore": "恢复前备份", + "disableCloud": "禁用云端", + "newProviderNameAria": "新的提供商名称", + "passwordsMismatch": "密码不匹配", + "a2aQuickStartStep3": "A2A快速开始步骤3", + "liveMonitorDescriptionSuffix": "或外部 API 调用来生成事件。", + "failedAddProvider": "添加提供商失败", + "addAtLeastOneProvider": "至少添加一个提供商", + "reasonSeparator": "原因分隔符", + "zedImporting": "正在从 Zed 导入", + "confirmPasswordPlaceholder": "确认密码占位符", + "whatYouGet": "你将获得", + "signatureSession": "签名 Session", + "errorCountNoCode": "无代码错误数", + "testing": "正在测试", + "providersCommaSeparated": "以逗号分隔的 Provider", + "exportDatabase": "导出数据库", + "hitRate": "命中率", + "completionsLegacy": "Completions 旧版", + "removeModel": "移除模型", + "timeRangeDay": "时间范围:天", + "cloudRequestFailed": "云端请求失败", + "updatedAt": "更新时间", + "monitoredProvidersHint": "选择需要监控的 Provider。", + "connectionSuccessful": "连接成功", + "latencyP50": "延迟P50", + "logsDeleted": "日志已删除", + "chatTester": "聊天测试器", + "safeSearchOff": "Safe Search 关闭", + "nameHint": "名称提示", + "debugToggle": "调试开关", "embedding": "Embedding", - "issuesLabel": "Issues Label", - "optionAny": "Option Any", - "maxNestingDepth": "Max Nesting Depth", + "issuesLabel": "问题标签", + "optionAny": "任意选项", + "maxNestingDepth": "最大嵌套深度", "rerank": "Rerank", - "checking": "Checking", - "getStarted": "Get Started", - "restoreSuccess": "Restore Success", - "issuesDetected": "Issues Detected", - "signatureCache": "Signature Cache", - "modelLockouts": "Model Lockouts", - "usingCloudProxy": "Using Cloud Proxy", - "loadingHealth": "Loading Health", - "providerOverrides": "Provider Overrides", - "audioTranscriptionDesc": "Audio Transcription Desc", - "learnedFromHeaders": "Learned From Headers", - "totalRequests": "Total Requests", - "cloudUnstableNote": "Cloud Unstable Note" + "checking": "正在检查", + "getStarted": "开始使用", + "restoreSuccess": "恢复成功", + "issuesDetected": "检测到问题", + "signatureCache": "签名缓存", + "modelLockouts": "模型锁定", + "usingCloudProxy": "正在使用 Cloud 代理", + "loadingHealth": "正在加载健康状态", + "providerOverrides": "提供商覆盖", + "audioTranscriptionDesc": "音频转写说明", + "learnedFromHeaders": "从响应头学习", + "totalRequests": "总计请求", + "cloudUnstableNote": "Cloud 连接不稳定,部分功能可能受影响。" }, "sidebar": { "home": "首页", @@ -707,40 +707,41 @@ "cliToolsShort": "工具", "cache": "缓存", "cacheShort": "缓存", - "batch": "Batch Jobs", - "themeSystem": "Theme System", - "whitelabelingDesc": "Whitelabeling Desc", - "switchThemes": "Switch Themes", - "themeAccentDesc": "Theme Accent Desc", - "uploadFavicon": "Upload Favicon", - "themeDark": "Theme Dark", - "customLogoDesc": "Custom Logo Desc", - "sidebarVisibilityToggle": "Sidebar Visibility Toggle", - "themeAccent": "Theme Accent", - "resetFavicon": "Reset Favicon", - "whitelabeling": "Whitelabeling", - "darkMode": "Dark Mode", - "uploadLogo": "Upload Logo", - "themeLight": "Theme Light", - "appName": "App Name", - "appNameDesc": "App Name Desc", - "resetLogo": "Reset Logo", - "customFavicon": "Custom Favicon", - "hideHealthLogs": "Hide Health Logs", - "customLogo": "Custom Logo", - "appearance": "Appearance", - "themeSelectionAria": "Theme Selection Aria", - "themeCreate": "Theme Create", - "customFaviconDesc": "Custom Favicon Desc", - "logoPreview": "Logo Preview", - "themeCustom": "Theme Custom", - "hideHealthLogsDesc": "Hide Health Logs Desc", - "faviconPreview": "Favicon Preview", - "changelog": "Changelog", - "contextSection": "Context & Cache", + "batch": "批量任务", + "themeSystem": "主题系统", + "whitelabelingDesc": "自定义品牌展示与主题外观。", + "switchThemes": "切换主题", + "themeAccentDesc": "选择用于按钮、链接和高亮状态的强调色。", + "uploadFavicon": "上传 Favicon", + "themeDark": "深色主题", + "customLogoDesc": "上传用于侧边栏和登录页的自定义 Logo。", + "sidebarVisibilityToggle": "侧边栏可见性开关", + "themeAccent": "主题强调色", + "resetFavicon": "重置 Favicon", + "whitelabeling": "白标", + "darkMode": "深色模式", + "uploadLogo": "上传 Logo", + "themeLight": "浅色主题", + "appName": "应用名称", + "appNameDesc": "设置在界面和浏览器标题中显示的名称。", + "resetLogo": "重置 Logo", + "customFavicon": "自定义 Favicon", + "hideHealthLogs": "隐藏健康检查日志", + "customLogo": "自定义 Logo", + "appearance": "外观", + "themeSelectionAria": "主题选择", + "themeCreate": "创建主题", + "customFaviconDesc": "上传用于浏览器标签页的自定义 Favicon。", + "logoPreview": "Logo 预览", + "themeCustom": "自定义主题", + "hideHealthLogsDesc": "隐藏健康检查日志说明", + "faviconPreview": "Favicon 预览", + "changelog": "更新日志", + "contextSection": "上下文与缓存", "contextCaveman": "Caveman", "contextRtk": "RTK", - "contextCombos": "Compression Combos" + "contextCombos": "压缩组合", + "webhooks": "Webhook" }, "themesPage": { "title": "主题", @@ -832,8 +833,8 @@ "modelStatusError": "错误", "comboHealth": "组合健康状况", "comboHealthDescription": "组合级别配额、使用分布和性能指标", - "compressionAnalyticsTitle": "Compression Analytics", - "compressionAnalyticsDescription": "Compression analytics — token savings, mode breakdown, and provider stats." + "compressionAnalyticsTitle": "压缩分析", + "compressionAnalyticsDescription": "压缩分析 — token 节省、模式分布和提供商统计。" }, "apiManager": { "title": "API 密钥", @@ -1287,8 +1288,8 @@ "title": "选择模型" }, "5": { - "title": "Use Thinking Variant", - "desc": "For thinking models, run with --variant high/low/max (example command below)." + "title": "使用 Thinking 变体", + "desc": "对于思考模型,请使用 --variant high/low/max 运行(示例命令见下方)。" } }, "notes": { @@ -1320,12 +1321,12 @@ "windsurf": { "steps": { "1": { - "title": "Open AI Settings", - "desc": "Click the AI Settings icon in Windsurf or go to Settings" + "title": "打开 AI 设置", + "desc": "点击 Windsurf 中的 AI Settings 图标,或前往 Settings" }, "2": { - "title": "Add Custom Provider", - "desc": "Select \"Add custom provider\" (OpenAI-compatible)" + "title": "添加自定义提供商", + "desc": "选择 \"Add custom provider\" (OpenAI 兼容)" }, "3": { "title": "Base URL", @@ -1333,11 +1334,11 @@ }, "4": { "title": "API Key", - "desc": "Select your OmniRoute API key" + "desc": "选择你的 OmniRoute API 密钥" }, "5": { - "title": "Select Model", - "desc": "Choose a model from the dropdown" + "title": "选择模型", + "desc": "从下拉菜单中选择模型" } } } @@ -1800,23 +1801,61 @@ "noData": "无成本数据", "byModel": "按模型", "byProvider": "按提供商", - "spend30d": "Spend30D", - "activeModels": "Active Models", - "selectedWindow": "Selected Window", - "activeProviders": "Active Providers", - "overviewTitle": "Overview Title", - "spend7d": "Spend7D", - "avgCostPerRequest": "Avg Cost Per Request", - "noCostDataDescription": "No Cost Data Description", - "spendToday": "Spend Today", - "overviewLoadFailed": "Overview Load Failed", - "overviewDescription": "Overview Description", - "providerShare": "Provider Share", - "topProviders": "Top Providers", - "costTrend": "Cost Trend", - "noCostDataTitle": "No Cost Data Title", - "topModels": "Top Models", - "requestsInWindow": "Requests In Window" + "spend30d": "30 天支出", + "activeModels": "活跃 Model", + "selectedWindow": "已选窗口", + "activeProviders": "活跃 Provider", + "overviewTitle": "概览", + "spend7d": "7 天支出", + "avgCostPerRequest": "平均每次请求成本", + "noCostDataDescription": "发起请求后,成本数据会显示在这里。", + "spendToday": "今日支出", + "overviewLoadFailed": "加载成本概览失败", + "overviewDescription": "按提供商、模型和时间段汇总成本。", + "providerShare": "提供商占比", + "topProviders": "热门 Provider", + "costTrend": "成本趋势", + "noCostDataTitle": "暂无成本数据", + "topModels": "热门 Model", + "requestsInWindow": "窗口内请求数", + "pageDescription": "跟踪支出、分析趋势,并管理所有提供商的 AI 预算", + "overview": "概览", + "range7d": "7 天", + "range30d": "30 天", + "range90d": "90 天", + "rangeAll": "全部时间", + "tokenUsage": "Token 用量", + "totalTokens": "Token 总数", + "inputTokens": "输入 Token", + "outputTokens": "输出 Token", + "inputOutputRatio": "输入/输出比例", + "tokens": "token", + "routingEfficiency": "路由效率", + "fallbackCount": "回退请求数", + "fallbackRate": "回退率", + "modelCoverage": "模型覆盖率", + "modelCoverageDesc": "带有明确模型的请求占比", + "outOfRequests": "共 {total} 个请求", + "costByApiKey": "按 API 密钥统计成本", + "costByAccount": "按账户统计成本", + "apiKeyName": "API 密钥", + "account": "账户", + "requests": "请求数", + "cost": "成本", + "dayStreak": "连续天数", + "weeklyUsagePattern": "每周使用模式", + "activityHeatmap": "活动热力图(365 天)", + "less": "较少", + "more": "较多", + "monthlyForecast": "月度预测", + "forecastBasis": "基于最近 {days} 天", + "avgDailyCost": "平均每日成本", + "daysRemaining": "剩余 {days} 天", + "periodComparison": "周期对比", + "previousPeriod": "上半期", + "currentPeriod": "当前半期", + "exportCSV": "导出为 CSV", + "exportJSON": "导出为 JSON" }, "endpoint": { "title": "API 端点", @@ -1949,40 +1988,58 @@ "a2aQuickStartStep3": "使用 `tasks/get` 与 `tasks/cancel` 跟踪和控制任务。", "completionsLegacy": "Completions(旧版)", "completionsLegacyDesc": "旧版 OpenAI 文本补全接口,同时接受 `prompt` 字符串和 `messages` 数组格式", - "videoGeneration": "Video Generation", - "videoDesc": "Generate videos using AI models like ComfyUI and Stable Video Diffusion.", - "tailscaleRequestFailed": "Failed to load Tailscale status", - "tailscaleEnableFailed": "Failed to enable Tailscale Funnel", - "tailscaleWaitingForLogin": "Complete the Tailscale login in the opened browser tab. OmniRoute will retry automatically.", - "tailscaleLoginTimedOut": "Timed out waiting for Tailscale login", - "tailscaleWaitingForFunnel": "Enable Funnel for this device in the opened browser tab. OmniRoute will keep polling.", - "tailscaleFunnelTimedOut": "Timed out waiting for Tailscale Funnel to be enabled", - "tailscaleStarted": "Tailscale Funnel enabled", - "tailscaleDisableFailed": "Failed to disable Tailscale Funnel", - "tailscaleStopped": "Tailscale Funnel disabled", - "tailscaleInstallFailed": "Failed to install Tailscale", - "tailscaleInstallProgress": "Working...", - "tailscaleInstalled": "Tailscale installed successfully", - "tailscaleRunning": "Running", - "tailscaleNeedsLogin": "Needs Login", - "tailscaleStoppedState": "Stopped", - "tailscaleNotInstalled": "Not installed", - "tailscaleUnsupported": "Unsupported", - "tailscaleError": "Error", - "tailscaleDisable": "Stop Funnel", - "tailscaleInstallAndEnable": "Install & Enable", - "tailscaleLoginAndEnable": "Login & Enable", - "tailscaleEnable": "Enable Funnel", - "tailscaleUrlNotice": "Uses your Tailscale .ts.net address. Login and Funnel approval may be required on first use.", + "videoGeneration": "视频生成", + "videoDesc": "使用 ComfyUI 和 Stable Video Diffusion 等 AI 模型生成视频。", + "tailscaleRequestFailed": "加载 Tailscale 状态失败", + "tailscaleEnableFailed": "启用 Tailscale Funnel 失败", + "tailscaleWaitingForLogin": "请在打开的浏览器标签页中完成 Tailscale 登录。OmniRoute 会自动重试。", + "tailscaleLoginTimedOut": "等待 Tailscale 登录超时", + "tailscaleWaitingForFunnel": "请在打开的浏览器标签页中为此设备启用 Funnel。OmniRoute 会继续轮询。", + "tailscaleFunnelTimedOut": "等待启用 Tailscale Funnel 超时", + "tailscaleStarted": "Tailscale Funnel 已启用", + "tailscaleDisableFailed": "禁用 Tailscale Funnel 失败", + "tailscaleStopped": "Tailscale Funnel 已禁用", + "tailscaleInstallFailed": "安装 Tailscale 失败", + "tailscaleInstallProgress": "处理中...", + "tailscaleInstalled": "Tailscale 安装成功", + "tailscaleRunning": "运行中", + "tailscaleNeedsLogin": "需要登录", + "tailscaleStoppedState": "已停止", + "tailscaleNotInstalled": "未安装", + "tailscaleUnsupported": "不支持", + "tailscaleError": "错误", + "tailscaleDisable": "停止 Funnel", + "tailscaleInstallAndEnable": "安装并启用", + "tailscaleLoginAndEnable": "登录并启用", + "tailscaleEnable": "启用 Funnel", + "tailscaleUrlNotice": "使用你的 Tailscale .ts.net 地址。首次使用时可能需要登录并批准 Funnel。", "tailscaleTitle": "Tailscale Funnel", - "tailscaleNeedsLoginHint": "Authenticate this machine with Tailscale, then enable Funnel.", + "tailscaleNeedsLoginHint": "先使用 Tailscale 认证此机器,然后启用 Funnel。", "tailscaleBinaryPath": "Binary: {path}", - "tailscaleLastError": "Last error: {error}", - "tailscaleInstallTitle": "Install Tailscale", - "tailscaleInstallIntro": "Installs Tailscale on this machine and prepares OmniRoute to enable Funnel.", - "tailscaleInstallPasswordHint": "On macOS and Linux, sudo may be required for the package install and daemon start.", - "tailscaleSudoPlaceholder": "Optional sudo password", - "tailscaleInstalling": "Installing" + "tailscaleLastError": "最近错误:{error}", + "tailscaleInstallTitle": "安装 Tailscale", + "tailscaleInstallIntro": "在此机器上安装 Tailscale,并准备让 OmniRoute 启用 Funnel。", + "tailscaleInstallPasswordHint": "在 macOS 和 Linux 上,安装软件包和启动守护进程可能需要 sudo。", + "tailscaleSudoPlaceholder": "可选 sudo 密码", + "tailscaleInstalling": "正在安装", + "tailscaleSudoLabel": "Sudo 密码(macOS/Linux 上必需)", + "ngrokTitle": "ngrok 隧道", + "ngrokRunning": "运行中", + "ngrokStarting": "正在启动", + "ngrokStoppedState": "已停止", + "ngrokNeedsAuth": "需要认证", + "ngrokNotInstalled": "未安装", + "ngrokUnsupported": "不支持", + "ngrokError": "错误", + "ngrokEnable": "启用隧道", + "ngrokDisable": "停止隧道", + "ngrokUrlNotice": "创建一个公开的 ngrok 隧道。", + "ngrokAuthTokenLabel": "Authtoken(未设置 NGROK_AUTHTOKEN 时必需)", + "ngrokAuthTokenPlaceholder": "输入你的 ngrok authtoken", + "ngrokLastError": "上次错误:{error}", + "ngrokStarted": "ngrok 隧道已启动", + "ngrokStopped": "ngrok 隧道已停止", + "ngrokRequestFailed": "更新 ngrok 隧道失败" }, "endpoints": { "tabProxy": "端点代理", @@ -2063,10 +2120,10 @@ "failed": "失败", "previous": "上一页", "next": "下一页", - "apiKeyId": "Api Key Id", - "offset": "Offset", - "limit": "Limit", - "tool": "Tool" + "apiKeyId": "API Key ID", + "offset": "偏移量", + "limit": "限制", + "tool": "工具" }, "a2aDashboard": { "loading": "正在加载 A2A 仪表板...", @@ -2121,9 +2178,9 @@ "metadata": "元数据", "events": "事件", "artifacts": "产物", - "tablePhase": "Table Phase", - "offset": "Offset", - "limit": "Limit", + "tablePhase": "阶段", + "offset": "偏移量", + "limit": "限制", "skill": "Skill" }, "health": { @@ -2199,11 +2256,11 @@ "resetting": "正在重置...", "resetAll": "全部重置", "until": "直到 {time}", - "limitExhausted": "Exhausted", - "learnedFromHeaders": "Learned from headers", - "remainingOfLimit": "{remaining}/{limit} remaining", - "throttleStatus": "Throttle: {value}", - "lastHeaderUpdate": "Header update: {age}" + "limitExhausted": "已耗尽", + "learnedFromHeaders": "从响应头学习", + "remainingOfLimit": "剩余 {remaining}/{limit}", + "throttleStatus": "限流:{value}", + "lastHeaderUpdate": "响应头更新:{age}" }, "limits": { "title": "限制和配额", @@ -2242,46 +2299,46 @@ "noEntries": "未找到审核日志条目", "previous": "上一页", "next": "下一页", - "providerWarningTitle": "Provider Warning Title", - "viewDetails": "View Details", - "eventMetadata": "Event Metadata", - "eventPayload": "Event Payload", - "requestId": "Request Id", - "providerWarningDesc": "Provider Warning Desc", + "providerWarningTitle": "提供商警告", + "viewDetails": "查看详情", + "eventMetadata": "事件元数据", + "eventPayload": "事件负载", + "requestId": "请求 ID", + "providerWarningDesc": "上游提供商返回了警告。请查看详情以了解更多信息。", "a": "A", - "offset": "Offset", - "limit": "Limit", - "status": "Status", - "resourceType": "Resource Type", - "totalEntries": "Total Entries", - "tab": "Tab", - "auditModalSubtitle": "Audit Modal Subtitle", - "close": "Close", - "runningRequests": "Active Requests", - "runningRequestsDesc": "Real-time view of currently running upstream requests", - "model": "Model", - "provider": "Provider", + "offset": "偏移量", + "limit": "限制", + "status": "状态", + "resourceType": "资源类型", + "totalEntries": "总条目数", + "tab": "标签页", + "auditModalSubtitle": "审计详情", + "close": "关闭", + "runningRequests": "活跃请求", + "runningRequestsDesc": "当前正在运行的上游请求实时视图", + "model": "模型", + "provider": "提供商", "account": "Account", - "elapsed": "Elapsed", - "count": "Count", - "payloads": "Payloads", - "viewPayloads": "View", - "activeCount": "{count} active", - "clientPayload": "Client Request Payload", - "upstreamPayload": "Upstream Provider Payload", - "upstreamNotSentYet": "Not sent to upstream yet", - "runningRequestDetailMeta": "Account: {account} — Elapsed: {elapsed}", + "elapsed": "已耗时", + "count": "数量", + "payloads": "Payload", + "viewPayloads": "查看", + "activeCount": "{count} 个活跃", + "clientPayload": "客户端请求载荷", + "upstreamPayload": "上游提供商载荷", + "upstreamNotSentYet": "尚未发送到上游", + "runningRequestDetailMeta": "Account:{account} — 已耗时:{elapsed}", "consoleViewer": { - "fetchFailed": "Failed to fetch logs", - "copyFailed": "Failed to copy log entry", - "copyLogEntry": "Copy log entry" + "fetchFailed": "获取日志失败", + "copyFailed": "复制日志条目失败", + "copyLogEntry": "复制日志条目" }, - "export": "Export", - "exporting": "Exporting...", - "exportFailed": "Export failed", - "timeRange": "Time Range", - "lastNHours": "Last {hours}", - "defaultRange": "default" + "export": "导出", + "exporting": "正在导出...", + "exportFailed": "导出失败", + "timeRange": "时间范围", + "lastNHours": "最近 {hours} 小时", + "defaultRange": "默认" }, "onboarding": { "welcome": "欢迎", @@ -2377,7 +2434,7 @@ "selectProvider": "选择提供商", "selectedProvider": "选定的提供商", "authMethod": "认证方式", - "apiKeyLabel": "API密钥", + "apiKeyLabel": "API key", "apiKeyRequired": "需要 API 密钥", "selectProviderRequired": "请选择提供商", "enterApiKey": "输入您的 API 密钥", @@ -2420,7 +2477,7 @@ "nameLabel": "名称", "prefixLabel": "前缀", "baseUrlLabel": "基础 URL", - "apiTypeLabel": "API类型", + "apiTypeLabel": "API 类型", "prefixHint": "必填。模型名称使用的唯一前缀。", "nameHint": "必填。该节点的友好标签。", "baseUrlHint": "必填。  提供商 API 基本 URL。", @@ -2586,7 +2643,7 @@ "compatUpstreamRemoveRow": "删除此行", "compatBadgeUpstreamHeaders": "请求头", "perModelQuotaLabel": "按模型配额", - "perModelQuotaDescription": "启用后,429/404错误只会锁定特定模型,而不是整个连接。适用于具有按模型速率限制的提供商(例如ModelScope)。", + "perModelQuotaDescription": "启用后,429/404 错误只会锁定特定 Model,而不是整个连接。适用于具有按 Model 速率限制的 Provider(例如 ModelScope)。", "perModelQuotaToggle": "按模型配额开关", "modelId": "模型 ID", "customModelPlaceholder": "例如:gpt-4.5-turbo", @@ -2655,39 +2712,39 @@ "statusCreditsExhausted": "余额不足 / 配额已耗尽", "showEmails": "显示所有邮箱", "hideEmails": "隐藏所有邮箱", - "imagesGenerations": "Images Generations", - "audioSpeech": "Audio Speech", - "audioTranscriptions": "Audio Transcriptions", + "imagesGenerations": "图像生成", + "audioSpeech": "语音合成", + "audioTranscriptions": "音频转写", "embeddings": "Embeddings", "a": "A", - "accountConcurrencyCapHint": "Account Concurrency Cap Hint", - "accountConcurrencyCapLabel": "Account Concurrency Cap Label", - "accountIdHint": "Account Id Hint", - "accountIdLabel": "Account Id Label", - "accountIdPlaceholder": "Account Id Placeholder", - "addAnotherApiKey": "Add another API key or paste multiple keys", + "accountConcurrencyCapHint": "限制此 Account 可同时处理的请求数。", + "accountConcurrencyCapLabel": "Account 并发上限", + "accountIdHint": "用于区分同一 Provider 下的多个 Account。", + "accountIdLabel": "Account ID", + "accountIdPlaceholder": "Account ID 占位符", + "addAnotherApiKey": "添加另一个 API 密钥或粘贴多个密钥", "addCcCompatible": "添加 CC 兼容", - "aggregatorsGateways": "Aggregators Gateways", - "apiFormatLabel": "Api Format Label", - "apiKeyOptionalHint": "Api Key Optional Hint", - "apiKeyOptionalLabel": "Api Key Optional Label", - "apiRegionChina": "Api Region China", - "apiRegionHint": "Api Region Hint", - "apiRegionInternational": "Api Region International", - "apiRegionLabel": "Api Region Label", - "apikey": "Apikey", - "audio": "Audio", - "audioProvidersHeading": "Audio Providers Heading", - "audioShortLabel": "Audio Short Label", - "azureOpenAiBaseUrlHint": "Azure Open Ai Base Url Hint", - "bailianBaseUrlHint": "Bailian Base Url Hint", - "blackboxWebCookieHint": "Blackbox Web Cookie Hint", - "blackboxWebCookiePlaceholder": "Blackbox Web Cookie Placeholder", + "aggregatorsGateways": "聚合器与网关", + "apiFormatLabel": "API 格式", + "apiKeyOptionalHint": "如果上游不需要认证,可以留空 API key。", + "apiKeyOptionalLabel": "API key(可选)", + "apiRegionChina": "中国区", + "apiRegionHint": "选择此 Provider 的 API 区域。", + "apiRegionInternational": "国际区", + "apiRegionLabel": "API 区域", + "apikey": "API key", + "audio": "音频", + "audioProvidersHeading": "音频 Provider", + "audioShortLabel": "音频", + "azureOpenAiBaseUrlHint": "Azure OpenAI 资源的 Base URL。", + "bailianBaseUrlHint": "阿里云百炼服务的 Base URL。", + "blackboxWebCookieHint": "从 Blackbox Web 会话复制 Cookie。", + "blackboxWebCookiePlaceholder": "Blackbox Web Cookie", "blockClaudeExtraUsageDescription": "隐藏部分 Provider 返回的重复 Claude 额外用量记录,避免和主 token 统计重复。", "blockClaudeExtraUsageLabel": "屏蔽重复 Claude 用量", - "bulkPasteAdded": "{count, plural, one {1 key added} other {# keys added}}", - "bulkPasteDuplicatesIgnored": "{count, plural, one {1 duplicate skipped} other {# duplicates skipped}}", - "bulkPasteHint": "Paste one API key per line. Empty lines are ignored and duplicate keys are skipped.", + "bulkPasteAdded": "{count, plural, one {已添加 1 个 key} other {已添加 # 个 key}}", + "bulkPasteDuplicatesIgnored": "{count, plural, one {已跳过 1 个重复项} other {已跳过 # 个重复项}}", + "bulkPasteHint": "每行粘贴一个 API 密钥。空行会被忽略,重复密钥会被跳过。", "ccCompatibleBaseUrlHint": "Claude Code 专用中转站的 Base URL,不要包含 /messages。", "ccCompatibleBaseUrlPlaceholder": "https://relay.example.com/v1", "ccCompatibleChatPathHint": "默认使用 Claude Code 严格的 Messages API 路径。仅在中转站文档要求时修改。", @@ -2707,111 +2764,118 @@ "codexFastServiceTierDescription": "可用时为 Codex 请求使用 priority 服务层。", "codexFastServiceTierLabel": "Codex 快速服务层", "codexWeeklyToggleTitle": "为此连接跟踪 Codex 周配额", - "compatUpstreamHeaderNamePlaceholder": "Compat Upstream Header Name Placeholder", - "compatUpstreamHeaderValuePlaceholder": "Compat Upstream Header Value Placeholder", - "compatible": "Compatible", - "configuredCount": "Configured Count", - "consoleApiKeyOracleHint": "Console Api Key Oracle Hint", - "consoleApiKeyOracleLabel": "Console Api Key Oracle Label", - "consoleApiKeyOraclePlaceholder": "Console Api Key Oracle Placeholder", + "compatUpstreamHeaderNamePlaceholder": "上游 Header 名称", + "compatUpstreamHeaderValuePlaceholder": "上游 Header 值", + "compatible": "兼容", + "configuredCount": "已配置数量", + "consoleApiKeyOracleHint": "用于从 Console 获取或验证 API key 的辅助配置。", + "consoleApiKeyOracleLabel": "Console API key Oracle", + "consoleApiKeyOraclePlaceholder": "Console API key Oracle 占位符", "cpaModeDisabledTitle": "CLIProxyAPI 兼容模式已关闭", "cpaModeEnabledTitle": "CLIProxyAPI 兼容模式已开启", - "customUserAgentHint": "Custom User Agent Hint", - "customUserAgentLabel": "Custom User Agent Label", - "databricksBaseUrlHint": "Databricks Base Url Hint", + "customUserAgentHint": "发送给上游 Provider 的自定义 User-Agent。", + "customUserAgentLabel": "自定义 User-Agent", + "databricksBaseUrlHint": "Databricks Serving Endpoint 的 Base URL。", "defaultThinkingStrengthHint": "请求未指定 reasoning effort 时使用。", "defaultThinkingStrengthLabel": "默认思考强度", - "deleteAllExtraApiKeys": "Delete all", - "excludedModelsHint": "Excluded Models Hint", - "excludedModelsLabel": "Excluded Models Label", - "excludedModelsPlaceholder": "Excluded Models Placeholder", - "expirationBannerExpired": "Expiration Banner Expired", - "expirationBannerExpiredDesc": "Expiration Banner Expired Desc", - "expirationBannerExpiringSoon": "Expiration Banner Expiring Soon", - "expirationBannerExpiringSoonDesc": "Expiration Banner Expiring Soon Desc", + "deleteAllExtraApiKeys": "全部删除", + "excludedModelsHint": "这些 Model 不会出现在路由和选择器中。", + "excludedModelsLabel": "排除的 Model", + "excludedModelsPlaceholder": "以逗号分隔的 Model ID", + "expirationBannerExpired": "凭据已过期", + "expirationBannerExpiredDesc": "此 Provider 的凭据已过期,请更新后继续使用。", + "expirationBannerExpiringSoon": "凭据即将过期", + "expirationBannerExpiringSoonDesc": "此 Provider 的凭据即将过期,请提前更新。", "extraApiKeyMasked": "Key {index}: {prefix}••••{suffix}", - "extraApiKeysHint": "Extra Api Keys Hint", - "extraApiKeysLabel": "Extra Api Keys Label", - "googlePseInfo": "Google Pse Info", - "grokWebCookieHint": "Grok Web Cookie Hint", - "grokWebCookiePlaceholder": "Grok Web Cookie Placeholder", - "herokuBaseUrlHint": "Heroku Base Url Hint", - "hideEmail": "Hide Email", - "imageProviders": "Image Providers", - "imagesShortLabel": "Images Short Label", - "llmProviders": "Llm Providers", - "localProviderApiKeyOptionalHint": "Local Provider Api Key Optional Hint", - "localProviderBaseUrlHint": "Local Provider Base Url Hint", - "localProviders": "Local Providers", - "maxConcurrentWholeNumberError": "Max Concurrent Whole Number Error", - "museSparkWebCookieHint": "Muse Spark Web Cookie Hint", - "museSparkWebCookiePlaceholder": "Muse Spark Web Cookie Placeholder", - "oauth": "Oauth", - "openCliTools": "Open Cli Tools", - "openSettings": "Open Settings", + "extraApiKeysHint": "为同一提供商添加额外 API 密钥,以便轮换和回退使用。", + "extraApiKeysLabel": "额外 API 密钥", + "googlePseInfo": "配置 Google Programmable Search Engine 以启用 Web Search。", + "grokWebCookieHint": "从 Grok Web 会话复制 Cookie。", + "grokWebCookiePlaceholder": "Grok Web Cookie", + "herokuBaseUrlHint": "Heroku 部署的 Base URL。", + "hideEmail": "隐藏邮箱", + "imageProviders": "图像 Provider", + "imagesShortLabel": "图像", + "llmProviders": "LLM Provider", + "localProviderApiKeyOptionalHint": "本地提供商的 API 密钥通常是可选的。", + "localProviderBaseUrlHint": "输入本地提供商的 Base URL。", + "localProviders": "本地 Provider", + "maxConcurrentWholeNumberError": "最大并发必须是整数", + "museSparkWebCookieHint": "从 Muse Spark Web 会话复制 Cookie。", + "museSparkWebCookiePlaceholder": "Muse Spark Web Cookie", + "oauth": "OAuth", + "openCliTools": "打开 CLI Tools", + "openSettings": "打开设置", "openaiResponsesStoreDescription": "允许兼容的 Responses API 请求保留已存储的响应状态。", "openaiResponsesStoreLabel": "OpenAI Responses 存储", - "perplexitySearchSharedKeyInfo": "Perplexity Search Shared Key Info", - "perplexityWebCookieHint": "Perplexity Web Cookie Hint", - "perplexityWebCookiePlaceholder": "Perplexity Web Cookie Placeholder", - "personalAccessTokenLabel": "Personal Access Token Label", - "qoderPatHint": "Qoder Pat Hint", - "qoderPatPlaceholder": "Qoder Pat Placeholder", - "refreshOauthTokenTitle": "Refresh Oauth Token Title", - "regionHint": "Region Hint", - "regionLabel": "Region Label", - "removeThisKey": "Remove This Key", - "routingTagsHint": "Routing Tags Hint", - "routingTagsLabel": "Routing Tags Label", - "routingTagsPlaceholder": "Routing Tags Placeholder", - "search": "Search", - "searchEngineIdHint": "Search Engine Id Hint", - "searchEngineIdLabel": "Search Engine Id Label", - "searchEngineIdRequired": "Search Engine Id Required", - "searchProvider": "Search Provider", - "searchProviderDesc": "Search Provider Desc", - "searchProviders": "Search Providers", - "searchProvidersHeading": "Search Providers Heading", - "searxngBaseUrlHint": "Searxng Base Url Hint", - "searxngInfo": "Searxng Info", - "sessionCookieLabel": "Session Cookie Label", - "showEmail": "Show Email", - "snowflakeBaseUrlHint": "Snowflake Base Url Hint", + "perplexitySearchSharedKeyInfo": "Perplexity Search 可使用共享 key 配置。", + "perplexityWebCookieHint": "从 Perplexity Web 会话复制 Cookie。", + "perplexityWebCookiePlaceholder": "Perplexity Web Cookie", + "personalAccessTokenLabel": "个人访问令牌", + "qoderPatHint": "输入 Qoder Personal Access Token。", + "qoderPatPlaceholder": "Qoder PAT", + "refreshOauthTokenTitle": "刷新 OAuth Token", + "regionHint": "选择此 Provider 使用的区域。", + "regionLabel": "区域", + "removeThisKey": "移除此 key", + "routingTagsHint": "添加标签以便在路由规则中匹配此连接。", + "routingTagsLabel": "路由标签", + "routingTagsPlaceholder": "例如 coding, fast, cheap", + "search": "搜索", + "searchEngineIdHint": "Google Programmable Search Engine 的 ID。", + "searchEngineIdLabel": "Search Engine ID", + "searchEngineIdRequired": "Search Engine ID 为必填项", + "searchProvider": "搜索提供商", + "searchProviderDesc": "按名称、能力或类别查找提供商。", + "searchProviders": "搜索 Provider", + "searchProvidersHeading": "搜索 Provider", + "searxngBaseUrlHint": "SearXNG 实例的 Base URL。", + "searxngInfo": "配置 SearXNG 以启用自托管 Web Search。", + "sessionCookieLabel": "Session Cookie", + "showEmail": "显示邮箱", + "snowflakeBaseUrlHint": "Snowflake Cortex 服务的 Base URL。", "supportedEndpointAudio": "音频", "supportedEndpointChat": "聊天", "supportedEndpointEmbeddings": "Embeddings", "supportedEndpointImages": "图像", "supportedEndpointsLabel": "支持的端点", - "tagGroupHint": "Tag Group Hint", - "tagGroupLabel": "Tag Group Label", - "tagGroupPlaceholder": "Tag Group Placeholder", - "testModel": "Test Model", - "testingModel": "Testing Model", + "tagGroupHint": "用于筛选和组织 Provider 的标签分组。", + "tagGroupLabel": "标签分组", + "tagGroupPlaceholder": "标签分组占位符", + "testModel": "测试模型", + "testingModel": "正在测试模型", "toggleOffShort": "关", "toggleOnShort": "开", - "tokenExpiredBadge": "Token Expired Badge", - "tokenExpiredTitle": "Token Expired Title", - "tokenExpiresSoonTitle": "Token Expires Soon Title", - "tokenShort": "Token Short", - "totalKeysRotating": "{count, plural, one {1 key rotating} other {# keys rotating}}", - "unhideModel": "Unhide Model", - "upstreamProxyProviders": "Upstream Proxy Providers", - "validationModelIdHint": "Validation Model Id Hint", - "validationModelIdLabel": "Validation Model Id Label", - "validationModelIdPlaceholder": "Validation Model Id Placeholder", - "vertexServiceAccountPlaceholder": "Vertex Service Account Placeholder", - "webCookieProviders": "Web Cookie Providers", - "weeklyShort": "Weekly Short", - "xiaomiMimoBaseUrlHint": "Xiaomi Mimo Base Url Hint", - "zedImportButton": "Zed Import Button", - "zedImportFailed": "Zed Import Failed", - "zedImportHint": "Zed Import Hint", - "zedImportNetworkError": "Zed Import Network Error", - "zedImportNone": "Zed Import None", - "zedImportSuccess": "Zed Import Success", - "zedImporting": "Zed Importing", - "expiredBadge": "Expired", - "expiringSoonBadge": "Expiring Soon" + "tokenExpiredBadge": "Token 已过期", + "tokenExpiredTitle": "Token 已过期", + "tokenExpiresSoonTitle": "Token 即将过期", + "tokenShort": "Token", + "totalKeysRotating": "{count, plural, one {1 个 key 正在轮换} other {# 个 key 正在轮换}}", + "unhideModel": "取消隐藏模型", + "upstreamProxyProviders": "上游代理 Provider", + "validationModelIdHint": "用于验证此提供商连接的模型 ID。", + "validationModelIdLabel": "验证模型 ID", + "validationModelIdPlaceholder": "输入用于测试的模型 ID", + "vertexServiceAccountPlaceholder": "Vertex Service Account", + "webCookieProviders": "Web Cookie Provider", + "weeklyShort": "每周", + "xiaomiMimoBaseUrlHint": "小米 Mimo 服务的 Base URL。", + "zedImportButton": "从 Zed 导入", + "zedImportFailed": "Zed 导入失败", + "zedImportHint": "从 Zed 配置中导入 Provider。", + "zedImportNetworkError": "Zed 导入网络错误", + "zedImportNone": "没有可从 Zed 导入的内容", + "zedImportSuccess": "Zed 导入成功", + "zedImporting": "正在从 Zed 导入", + "expiredBadge": "已过期", + "expiringSoonBadge": "即将过期", + "freeTier": "免费额度", + "freeTierAvailable": "有免费额度", + "deprecated": "已弃用", + "deprecatedProvider": "此提供商已弃用", + "enterpriseCloud": "企业与云", + "videoProviders": "视频生成", + "embeddingRerankProviders": "嵌入与重排序" }, "settings": { "title": "设置", @@ -2824,22 +2888,22 @@ "systemPrompt": "系统提示", "thinkingBudget": "思考预算", "proxy": "代理", - "httpProxy": "HTTP Proxy", + "httpProxy": "HTTP 代理", "1proxy": "1proxy", - "proxySubTabsAria": "Proxy sections", - "requestBodyLimitTitle": "Request Body Limit", - "requestBodyLimitDescription": "Maximum API payload size accepted before a request body is parsed. Dedicated upload routes keep at least their built-in 100 MB limit.", - "requestBodyLimitInputLabel": "Request body limit in MB", - "requestBodyLimitEmptyError": "Enter a limit in MB", - "requestBodyLimitWholeNumberError": "Use a whole number", - "requestBodyLimitMinimumError": "Minimum is {min} MB", - "requestBodyLimitMaximumError": "Maximum is {max} MB", - "requestBodyLimitLoadFailed": "Failed to load request limit settings", - "requestBodyLimitSaveSuccess": "Request body limit saved", - "requestBodyLimitSaveFailed": "Failed to save request body limit", - "requestBodyLimitSaving": "Saving...", - "requestBodyLimitSave": "Save", - "requestBodyLimitCurrent": "Current: {value}", + "proxySubTabsAria": "代理设置分区", + "requestBodyLimitTitle": "请求体大小限制", + "requestBodyLimitDescription": "解析请求体前允许的最大 API 载荷大小。专用上传路由仍至少保留其内置的 100 MB 限制。", + "requestBodyLimitInputLabel": "请求体限制(MB)", + "requestBodyLimitEmptyError": "请输入 MB 限制值", + "requestBodyLimitWholeNumberError": "请使用整数", + "requestBodyLimitMinimumError": "最小值为 {min} MB", + "requestBodyLimitMaximumError": "最大值为 {max} MB", + "requestBodyLimitLoadFailed": "加载请求限制设置失败", + "requestBodyLimitSaveSuccess": "请求体限制已保存", + "requestBodyLimitSaveFailed": "保存请求体限制失败", + "requestBodyLimitSaving": "正在保存...", + "requestBodyLimitSave": "保存", + "requestBodyLimitCurrent": "当前:{value}", "pricing": "定价", "storage": "存储", "policies": "策略", @@ -3030,7 +3094,7 @@ "effortMedium": "中(10K Tokens)", "effortHigh": "高(128K Tokens)", "tokenBudget": "Token 预算", - "tokens": "Tokens", + "tokens": "Token", "baseEffortLevel": "基本努力水平", "adaptiveHint": "自适应模式根据消息计数、工具使用情况和提示长度从此基本级别进行扩展。", "requireLogin": "需要登录", @@ -3084,7 +3148,7 @@ "stickyLimitDesc": "切换前每个账户连续处理的请求次数", "modelAliases": "模型别名", "modelAliasesTitle": "模型别名", - "modelAliasesDesc": "Remap model names using exact matches or wildcard patterns.", + "modelAliasesDesc": "使用精确匹配或通配符模式重映射模型名称。", "addCustomAlias": "添加自定义别名", "deprecatedModelId": "已弃用的模型 ID", "newModelId": "新模型 ID", @@ -3338,200 +3402,197 @@ "maintenance": "维护", "purgeExpiredLogs": "清理过期日志", "purgeLogsFailed": "清理日志失败", - "contextOpt": "Context Optimized", - "contextOptDesc": "Routes based on context window requirements and conversation length", - "priorityDesc": "Sequential fallback - tries provider 1 first, then provider 2, and so on", - "weightedDesc": "Distributes traffic by percentage weights across providers", - "modelRoutingTitle": "Model Routing Rules", - "modelRoutingDesc": "Automatically route models to specific combos using glob patterns", - "addRule": "Add Rule", - "routeToCombo": "Route to Combo", - "selectCombo": "Select combo...", - "priorityHint": "Higher = checked first. Use 10+ for specific patterns.", - "patternHint": "Use * for any chars, ? for single char. Case-insensitive.", - "noRoutingRules": "No routing rules configured. Requests use the global combo by default.", - "routingRuleHint": "Add a rule like claude-opus* -> frontier-combo to automatically route requests.", - "deleteRoutingRule": "Delete this model routing rule?", - "exactMatchMode": "Exact Match", - "wildcardPatternMode": "Wildcard Pattern", - "exactMatchModeDesc": "Use exact aliases for deprecated or renamed model IDs.", - "wildcardPatternModeDesc": "Use wildcard aliases with * and ? when a family of models should map to one target.", - "noExactAliasesConfigured": "No exact-match aliases configured.", - "wildcardRulesTitle": "Wildcard Rules", - "noWildcardAliasesConfigured": "No wildcard aliases configured.", - "overview": "Overview", - "unknownError": "Unknown Error", - "pricingSourceLiteLLM": "Pricing Source Lite Llm", - "clearSyncedPricingConfirm": "Clear Synced Pricing Confirm", - "clearSyncedPricingFailed": "Clear Synced Pricing Failed", - "pricingSourceUser": "Pricing Source User", - "pageDescription": "Page Description", - "pricingSyncStatus": "Pricing Sync Status", - "whitelist": "Whitelist", - "syncDisabled": "Sync Disabled", - "pricingLoadFailed": "Pricing Load Failed", - "pricingSyncDescription": "Pricing Sync Description", - "clearSyncedPricingSuccess": "Clear Synced Pricing Success", - "clearSyncedPricingFailedWithReason": "Clear Synced Pricing Failed With Reason", - "pricingSourceDefault": "Pricing Source Default", - "pricingSyncSuccess": "Pricing Sync Success", - "enableSyncError": "Enable Sync Error", - "syncEnabled": "Sync Enabled", - "blacklist": "Blacklist", - "pricingSourceModelsDev": "Pricing Source Models Dev", - "syncedModels": "Synced Models", - "budget": "Budget", - "pricingSyncTitle": "Pricing Sync Title", - "pricingResetFailedWithReason": "Pricing Reset Failed With Reason", - "tab": "Tab", - "pricingSavedProvider": "Pricing Saved Provider", - "pricingSyncFailed": "Pricing Sync Failed", - "pricingSaveFailedWithReason": "Pricing Save Failed With Reason", - "pricingResetProvider": "Pricing Reset Provider", - "nextSync": "Next Sync", - "pricingSyncFailedWithReason": "Pricing Sync Failed With Reason", - "clearSyncedPricing": "Clear Synced Pricing", - "compressionTitle": "Prompt Compression", - "compressionDesc": "Reduce token usage by compressing prompts before sending to providers", - "compressionMode": "Compression Mode", - "compressionModeOff": "Off", - "compressionModeOffDesc": "No compression applied", + "contextOpt": "上下文优化", + "contextOptDesc": "根据上下文窗口需求和对话长度进行路由", + "priorityDesc": "顺序回退——先尝试提供商 1,再尝试提供商 2,依此类推", + "weightedDesc": "按百分比权重在各提供商之间分配流量", + "modelRoutingTitle": "模型路由规则", + "modelRoutingDesc": "使用 glob 模式自动将模型路由到指定组合", + "addRule": "添加规则", + "routeToCombo": "路由到组合", + "selectCombo": "选择组合...", + "priorityHint": "数值越高越优先检查。具体模式建议使用 10+。", + "patternHint": "使用 * 匹配任意字符,? 匹配单个字符。不区分大小写。", + "noRoutingRules": "未配置路由规则。请求默认使用全局组合。", + "routingRuleHint": "添加类似 claude-opus* -> frontier-combo 的规则,以自动路由请求。", + "deleteRoutingRule": "删除此模型路由规则?", + "exactMatchMode": "精确匹配", + "wildcardPatternMode": "通配符模式", + "exactMatchModeDesc": "对已弃用或已重命名的模型 ID 使用精确别名。", + "wildcardPatternModeDesc": "当一组模型应映射到同一目标时,使用带 * 和 ? 的通配符别名。", + "noExactAliasesConfigured": "未配置精确匹配别名。", + "wildcardRulesTitle": "通配符规则", + "noWildcardAliasesConfigured": "未配置通配符别名。", + "overview": "概览", + "unknownError": "未知错误", + "pricingSourceLiteLLM": "LiteLLM 定价来源", + "clearSyncedPricingConfirm": "确定要清除已同步的定价吗?", + "clearSyncedPricingFailed": "清除已同步定价失败", + "pricingSourceUser": "用户定价来源", + "pageDescription": "页面描述", + "pricingSyncStatus": "定价同步状态", + "whitelist": "白名单", + "syncDisabled": "同步已禁用", + "pricingLoadFailed": "加载定价失败", + "pricingSyncDescription": "从 models.dev 同步模型定价和能力数据。", + "clearSyncedPricingSuccess": "已清除同步定价", + "clearSyncedPricingFailedWithReason": "清除价格失败:{reason}", + "pricingSourceDefault": "默认定价来源", + "pricingSyncSuccess": "定价同步成功", + "enableSyncError": "启用同步失败", + "syncEnabled": "同步已启用", + "blacklist": "黑名单", + "pricingSourceModelsDev": "models.dev 定价来源", + "syncedModels": "已同步模型", + "budget": "预算", + "pricingSyncTitle": "定价同步", + "pricingResetFailedWithReason": "重置价格失败:{reason}", + "tab": "选项卡", + "pricingSavedProvider": "已保存 {provider} 的价格", + "pricingSyncFailed": "定价同步失败", + "pricingSaveFailedWithReason": "保存价格失败:{reason}", + "pricingResetProvider": "已重置 {provider} 的价格", + "nextSync": "下次同步", + "pricingSyncFailedWithReason": "价格同步失败:{reason}", + "clearSyncedPricing": "清除同步定价", + "compressionTitle": "提示词压缩", + "compressionDesc": "在发送给提供商之前压缩提示词,以减少 token 使用量", + "compressionMode": "压缩模式", + "compressionModeOff": "关闭", + "compressionModeOffDesc": "不应用压缩", "compressionModeLite": "Lite", - "compressionModeLiteDesc": "Whitespace and blank line reduction", - "compressionModeStandard": "Standard (Caveman)", - "compressionModeStandardDesc": "Rule-based compression with 30+ patterns, preserves code blocks and URLs", + "compressionModeLiteDesc": "减少空白字符和空行", + "compressionModeStandard": "标准(Caveman)", + "compressionModeStandardDesc": "基于规则的压缩,包含 30+ 个模式,并保留代码块和 URL", "compressionModeAggressive": "Aggressive", - "compressionModeAggressiveDesc": "Summarization + tool result compression + progressive aging for maximum savings", + "compressionModeAggressiveDesc": "摘要 + 工具结果压缩 + 渐进老化,以实现最大节省", "compressionModeUltra": "Ultra", - "compressionModeUltraDesc": "Maximum compression with all techniques including semantic deduplication", - "compressionGeneral": "General Settings", - "compressionAutoTrigger": "Auto-Trigger Threshold", - "compressionCacheTTL": "Cache TTL", - "compressionPreserveSystem": "Preserve System Prompt", - "compressionCavemanConfig": "Caveman Engine Configuration", - "compressionCavemanConfigDesc": "Fine-tune the rule-based compression engine", - "compressionRoles": "Compress Message Roles", - "compressionRoleUser": "User", - "compressionRoleAssistant": "Assistant", - "compressionRoleSystem": "System", - "compressionMinLength": "Minimum Message Length", - "compressionSkipRules": "Skip Compression Rules", - "compressionSkipRulesDesc": "Click rules to skip them during compression", - "compressionPreservePatterns": "Preserve Patterns", - "compressionPreservePatternsDesc": "Regex patterns that are never compressed (one per line)", - "compressionLogTitle": "Compression Log", - "compressionLogEmpty": "No compressed requests yet. Compression stats will appear here when requests are processed with compression enabled.", + "compressionModeUltraDesc": "使用包括语义去重在内的全部技术进行最大压缩", + "compressionGeneral": "通用设置", + "compressionAutoTrigger": "自动触发阈值", + "compressionCacheTTL": "缓存 TTL", + "compressionPreserveSystem": "保留系统提示", + "compressionCavemanConfig": "Caveman 引擎配置", + "compressionCavemanConfigDesc": "微调基于规则的压缩引擎", + "compressionRoles": "压缩消息角色", + "compressionRoleUser": "用户", + "compressionRoleAssistant": "助手", + "compressionRoleSystem": "系统", + "compressionMinLength": "最小消息长度", + "compressionSkipRules": "跳过压缩规则", + "compressionSkipRulesDesc": "点击规则以在压缩时跳过它们", + "compressionPreservePatterns": "保留模式", + "compressionPreservePatternsDesc": "永不压缩的正则表达式模式(每行一个)", + "compressionLogTitle": "压缩日志", + "compressionLogEmpty": "尚无压缩请求。启用压缩后处理请求时,压缩统计会显示在这里。", "compressionModeRtk": "RTK", - "compressionModeRtkDesc": "Command-aware tool output filtering", - "compressionModeStacked": "Stacked", - "compressionModeStackedDesc": "RTK tool-output filtering followed by Caveman message compression", - "qdrantTitle": "Qdrant (Vector memory)", - "qdrantDesc": "Optional. Indexes semantic memories in an external vector database for faster retrieval.", - "qdrantStatusActive": "Active", - "qdrantStatusError": "Error", - "qdrantStatusDisabled": "Disabled", - "qdrantEnable": "Enable Qdrant", - "qdrantEnableDesc": "When enabled, semantic/hybrid strategy can use Qdrant to retrieve memories.", - "qdrantTesting": "Testing...", - "qdrantTestConnection": "Test connection", - "qdrantSaved": "Configuration saved", - "qdrantSaveError": "Failed to save configuration", - "qdrantHostHint": "Without port. Example: 127.0.0.1 or http://qdrant", - "qdrantPort": "Port", - "qdrantPortHint": "Qdrant default: 6333", - "qdrantCollectionHint": "Where memory points will be stored.", - "qdrantEmbeddingModel": "Embedding model", - "qdrantHelpTitle": "Quick setup help", - "qdrantHelpQuickTitle": "Quick setup (Qdrant + OpenRouter)", - "qdrantHelpStep1": "1. Host: Qdrant IP/URL, Port: 6333, Collection: omniroute_memory.", - "qdrantHelpStep2": "2. If using nvidia/llama-nemotron-embed-vl-1b-v2:free, use collection dimension 2048.", - "qdrantHelpStep3": "3. Model field: openrouter/nvidia/llama-nemotron-embed-vl-1b-v2:free.", - "qdrantHelpStep4": "4. Save, test connection, then test search.", - "qdrantEmbeddingQuickSelect": "Quick select from discovered models...", - "qdrantEmbeddingInputPlaceholder": "openai/text-embedding-3-small", - "qdrantEmbeddingHint": "Format: provider/model. The provider credential must be configured.", - "qdrantApiKeyPlaceholderKeep": "(leave empty to keep current key)", - "qdrantApiKeyPlaceholderOptional": "(leave empty if not used)", - "qdrantSaveHint": "Tip: edit host/port/collection/model and click Save. API key is optional.", - "qdrantSearchTestTitle": "Search test", - "qdrantSearchTestDesc": "Generates embedding and searches in Qdrant.", - "qdrantSearchPlaceholder": "Example: user preferences, history, etc", - "qdrantNoResults": "No results (or Qdrant is not configured).", - "qdrantCleanupTitle": "Retention and cleanup", - "qdrantCleanupDesc": "Removes expired and old points based on", - "searching": "Searching...", - "cleaning": "Cleaning...", - "cleanNow": "Clean now" + "compressionModeRtkDesc": "感知命令的工具输出过滤", + "compressionModeStacked": "堆叠", + "compressionModeStackedDesc": "先进行 RTK 工具输出过滤,再进行 Caveman 消息压缩", + "mitmProxy": "MITM 代理", + "authModelHeading": "当前授权模型", + "authModelClient": "客户端 API 端点(/v1/*、/chat/*、/responses/*、/codex/*、/messages/*)需要 Bearer API 密钥。", + "authModelManagement": "管理端点(/dashboard、/api/*)需要仪表盘会话或管理凭据。", + "authModelPublic": "只有登录、健康检查和引导路由是公开的。", + "bruteForceProtection": "登录暴力破解保护", + "bruteForceProtectionDesc": "在同一 IP 多次失败后,对 /api/auth/login 进行限流和锁定。", + "corsAllowedOrigins": "CORS 允许的源", + "corsAllowedOriginsDesc": "允许调用此服务器的浏览器来源列表,以逗号分隔。空列表 = 不允许浏览器 CORS 访问(服务器到服务器仍可用)。仅在开发环境使用 CORS_ALLOW_ALL=true 环境变量。", + "compressionAggressiveConfig": "Aggressive 引擎配置", + "compressionAggressiveConfigDesc": "微调摘要、工具压缩和老化阈值", + "compressionUltraConfig": "Ultra 引擎配置", + "compressionUltraConfigDesc": "微调启发式剪枝、SLM 后备和每条消息阈值", + "compressionUltraRate": "保留比例", + "compressionUltraMinScore": "最低分数阈值", + "compressionUltraSlmFallback": "回退到 Aggressive", + "compressionUltraModelPath": "SLM 模型路径", + "compressionSummarizerEnabled": "启用摘要器", + "compressionMaxTokensPerMessage": "每条消息最大 Token 数", + "compressionMinSavings": "最低节省阈值", + "compressionAgingThresholds": "老化阈值", + "compressionAgingThresholdsDesc": "每个老化层级保留的最近消息数量(越高表示保留越多)", + "compressionToolStrategies": "工具结果策略", + "compressionToolStrategiesDesc": "为不同工具结果类型切换压缩策略", + "minutes": "分钟" }, "contextRtk": { - "title": "RTK Engine", - "description": "Command-aware compression for tool output, terminal logs and build results.", - "enabled": "Enabled", - "intensity": "Intensity", - "intensityMinimal": "Minimal", - "intensityStandard": "Standard", - "intensityAggressive": "Aggressive", - "toolResults": "Tool results", - "assistantMessages": "Assistant messages", - "codeBlocks": "Code blocks", - "maxLines": "Max lines", - "maxChars": "Max chars", - "filterTesting": "Filter Testing", - "pasteOutput": "Paste tool output to test filtering...", - "run": "Run", - "result": "Result", - "previewEmpty": "Run a sample to preview RTK output.", - "detected": "Detected", - "tokensFiltered": "Tokens filtered", - "filtersActive": "Filters active", - "requests": "Requests", - "avgSavings": "Avg savings" + "title": "RTK 引擎", + "description": "面向工具输出、终端日志和构建结果的命令感知压缩。", + "enabled": "已启用", + "intensity": "强度", + "intensityMinimal": "最小", + "intensityStandard": "标准", + "intensityAggressive": "激进", + "toolResults": "工具结果", + "assistantMessages": "助手消息", + "codeBlocks": "代码块", + "maxLines": "最大行数", + "maxChars": "最大字符数", + "filterTesting": "过滤测试", + "pasteOutput": "粘贴工具输出以测试过滤...", + "run": "运行", + "result": "结果", + "previewEmpty": "运行示例以预览 RTK 输出。", + "detected": "已检测", + "tokensFiltered": "已过滤 token", + "filtersActive": "活动过滤器", + "requests": "请求数", + "avgSavings": "平均节省", + "deduplicateThreshold": "去重阈值", + "customFilters": "自定义过滤器", + "trustProjectFilters": "信任项目过滤器", + "rawOutputRetention": "原始输出保留", + "rawOutputNever": "从不", + "rawOutputFailures": "失败时", + "rawOutputAlways": "始终", + "rawOutputMaxBytes": "原始输出最大字节数" }, "contextCombos": { - "title": "Compression Combos", - "description": "Define how engines are combined for different routing scenarios.", - "createCombo": "Create Compression Combo", - "editCombo": "Edit", - "deleteCombo": "Delete", - "deleteConfirm": "Delete this compression combo?", - "pipeline": "Pipeline", - "addStep": "Add Step", - "removeStep": "Remove", - "name": "Name", - "descriptionField": "Description", - "languagePacks": "Language Packs", - "outputMode": "Output Mode", - "assignToRouting": "Assign to Routing Combos", - "noAssignments": "No routing combos available", - "default": "Default", - "setAsDefault": "Set as Default", - "save": "Save", - "cancel": "Cancel", - "enabled": "Enabled" + "title": "压缩组合", + "description": "定义不同路由场景中引擎的组合方式。", + "createCombo": "创建压缩组合", + "editCombo": "编辑", + "deleteCombo": "删除", + "deleteConfirm": "删除此压缩组合?", + "pipeline": "流水线", + "addStep": "添加步骤", + "removeStep": "移除", + "name": "名称", + "descriptionField": "描述", + "languagePacks": "语言包", + "outputMode": "输出模式", + "assignToRouting": "分配到路由组合", + "noAssignments": "没有可用的路由组合", + "default": "默认", + "setAsDefault": "设为默认", + "save": "保存", + "cancel": "取消", + "enabled": "已启用" }, "contextCaveman": { - "title": "Caveman Engine", - "description": "Rule-based message compression, language packs, analytics and output mode controls.", - "requests": "Requests", - "tokensSaved": "Tokens saved", - "savingsPercent": "Savings %", - "avgLatency": "Avg latency", - "languagePacks": "Language Packs", - "languagePacksDesc": "Enable compression rules for specific languages.", - "enabled": "Enabled", - "autoDetect": "Auto-detect language", - "rulesCount": "{count} rules", - "analyticsTitle": "Compression Analytics", - "noAnalytics": "No compression analytics yet.", - "outputModeTitle": "Output Mode", - "outputModeDesc": "Instructs the LLM to respond in a terse, compact format.", - "autoClarity": "Auto-Clarity Bypass", - "bypassConditions": "Bypass conditions", + "title": "Caveman 引擎", + "description": "基于规则的消息压缩,包含语言包、分析和输出模式控制。", + "requests": "请求数", + "tokensSaved": "已节省 token", + "savingsPercent": "节省比例", + "avgLatency": "平均延迟", + "languagePacks": "语言包", + "languagePacksDesc": "为特定语言启用压缩规则。", + "enabled": "已启用", + "autoDetect": "自动检测语言", + "rulesCount": "{count} 条规则", + "analyticsTitle": "压缩分析", + "noAnalytics": "尚无压缩分析。", + "outputModeTitle": "输出模式", + "outputModeDesc": "指示 LLM 以简洁、紧凑的格式回复。", + "autoClarity": "自动清晰度绕过", + "bypassConditions": "绕过条件", "preview": { - "lite": "Respond concise. Preserve technical terms, code, errors, URLs, and identifiers.", - "full": "Respond terse and compact. Preserve all technical substance.", - "ultra": "Respond ultra terse with common technical abbreviations. Preserve exact symbols." - } + "lite": "回复要简洁。保留技术术语、代码、错误、URL 和标识符。", + "full": "回复要简短紧凑。保留所有技术实质。", + "ultra": "用常见技术缩写进行极简回复。保留精确符号。" + }, + "bypassConditionsList": "安全、不可逆、需澄清、顺序敏感" }, "translator": { "title": "翻译器", @@ -3683,7 +3744,34 @@ "requestFailed": "请求失败", "noTextExtracted": "(未提取文字)", "liveMonitorDescriptionPrefix": "这里会显示 API 调用流经 OmniRoute 时产生的翻译事件。事件来自内存缓冲区(重启后会重置)。使用", - "liveMonitorDescriptionSuffix": ",或外部 API 调用来生成事件。" + "liveMonitorDescriptionSuffix": ",或外部 API 调用来生成事件。", + "translationPathHubSpoke": "{source} → OpenAI(中间格式)→ {target}", + "translationPathDirect": "{source} → {target}(直接转换器)", + "translationPathPassthrough": "格式相同 — 无需转换", + "openaiIntermediatePanel": "OpenAI 中间格式", + "autoFeaturesTitle": "OmniRoute 自动处理的内容", + "autoFeaturesCount": "8 项功能", + "featureReasoningCache": "推理缓存", + "featureReasoningCacheDesc": "当客户端在对话历史中省略 thinking-mode 模型(DeepSeek V4、Kimi K2、Qwen)的缓存 reasoning_content 时,会重新注入。", + "featureSchemaCoercion": "Schema 校正", + "featureSchemaCoercionDesc": "修复损坏的工具 schema:添加缺失的 additionalProperties、清理过长描述、规范化嵌套对象。", + "featureRoleNormalization": "角色规范化", + "featureRoleNormalizationDesc": "针对非 OpenAI 目标将 developer→system。针对不支持 system 角色的模型将 system→user。", + "featureToolCallIds": "工具调用 ID 规范化", + "featureToolCallIdsDesc": "在缺失时生成唯一的 tool_call ID。针对 Mistral 等提供商规范化为 9 字符格式。", + "featureMissingToolResponse": "工具响应注入", + "featureMissingToolResponseDesc": "当客户端发送 tool_calls 但没有对应响应时,注入空的 tool_result 消息。", + "featureThinkingBudget": "思考预算", + "featureThinkingBudgetDesc": "自动管理 thinking 配置。当最后一条消息不是用户消息时移除 thinking 参数。", + "featureDirectPaths": "直接转换路径", + "featureDirectPathsDesc": "某些格式组合(Claude→Gemini)有绕过 OpenAI 中枢的直接转换器,可产生更准确的输出。", + "featureImageMapping": "图像尺寸映射", + "featureImageMappingDesc": "在 API 格式之间转换图像尺寸约定(例如 OpenAI detail 等级 → Gemini 尺寸)。", + "liveMonitorMemoryNote": "事件存储在内存中,重启后会丢失。", + "liveMonitorMemoryCapNote": "最多保留 200 个事件。", + "eventSourcesLabel": "事件来源:", + "eventSourceTranslatorPage": "• Translator 页面(Chat Tester、Test Bench)", + "eventSourceMainPipeline": "• 主请求流水线(CLI/IDE/API 流量)" }, "usage": { "title": "用量", @@ -3695,7 +3783,7 @@ "loadingBudgetData": "正在加载预算数据...", "noApiKeysTitle": "没有 API 密钥", "noApiKeysDescription": "首先添加 API 密钥以设置预算限制。", - "apiKey": "API密钥", + "apiKey": "API key", "todaysSpend": "今天的花费", "thisMonth": "本月", "setLimits": "设定限制", @@ -3831,99 +3919,124 @@ "tierPlus": "加号", "tierFree": "免费", "tierUnknown": "未知", - "suiteBuilderSaveFailed": "Failed to save suite", + "suiteBuilderSaveFailed": "保存套件失败", "scorecardTitle": "Scorecard", - "evalApiKey": "API Key", - "scorecardPassRate": "Pass Rate", - "targetTypeModel": "Model", - "actualOutputLabel": "Actual Output", - "evalTargetHint": "Select a model or combo to evaluate.", - "suiteBuilderDeleted": "Suite deleted successfully", - "suiteBuilderCaseCardHint": "Define the input prompt and expected output criteria.", - "nextResetUtc": "Next reset (UTC)", - "scorecardHint": "Aggregated pass rates across all evaluation suites.", - "suiteLatestRunsHint": "Most recent evaluation runs for this suite.", - "saving": "Saving", - "suiteBuilderCaseModelLabel": "Model (optional)", - "evalControlsTitle": "Evaluation Controls", - "suiteBuilderEditTitle": "Edit Eval Suite", - "suiteBuilderCaseStrategyLabel": "Validation Strategy", - "notifySelectDifferentCompareTarget": "Please select a different target for comparison", - "recentRunsHint": "Showing the most recent evaluation runs. Click a run to see detailed results.", - "evalCompareHint": "Optionally compare results against a second target.", - "suiteBuilderCaseInvalid": "This case has validation errors. Please fix before saving.", - "historyEmpty": "No evaluation history yet", - "suiteBuilderUpdated": "Suite updated successfully", - "resetInterval": "Reset Interval", - "suiteBuilderCreateTitle": "Create Eval Suite", - "activePeriodSpend": "Active Period Spend", - "evalApiKeyHint": "Select which API key to use for evaluation requests.", - "evalCompareOptional": "Compare (optional)", - "suiteBuilderDeleteFailed": "Failed to delete suite", - "suiteBuilderCaseSystemPromptPlaceholder": "Optional system instructions...", - "scorecardCases": "Cases", - "runCompletedWithScore": "Evaluation completed — {score}% pass rate", - "suiteBuilderCustomBadge": "Custom", - "targetSuiteDefaults": "Suite defaults", - "suiteBuilderDeleteConfirm": "Are you sure you want to delete this suite? This action cannot be undone.", - "suiteBuilderNameLabel": "Suite Name", + "evalApiKey": "API key", + "scorecardPassRate": "通过率", + "targetTypeModel": "模型", + "actualOutputLabel": "实际输出", + "evalTargetHint": "选择要评估的模型或组合。", + "suiteBuilderDeleted": "Suite 删除成功", + "suiteBuilderCaseCardHint": "定义输入提示和预期输出标准。", + "nextResetUtc": "下次重置(UTC)", + "scorecardHint": "汇总所有 Evaluation Suite 的通过率。", + "suiteLatestRunsHint": "此套件最近的评估运行。", + "saving": "正在保存", + "suiteBuilderCaseModelLabel": "模型(可选)", + "evalControlsTitle": "Evaluation 控制项", + "suiteBuilderEditTitle": "编辑 Evaluation Suite", + "suiteBuilderCaseStrategyLabel": "验证策略", + "notifySelectDifferentCompareTarget": "请选择不同的比较目标", + "recentRunsHint": "正在显示最近的评估运行。点击某次运行可查看详细结果。", + "evalCompareHint": "可选择与第二个目标比较结果。", + "suiteBuilderCaseInvalid": "此 Case 存在验证错误,请先修复再保存。", + "historyEmpty": "暂无 Evaluation 历史", + "suiteBuilderUpdated": "Suite 更新成功", + "resetInterval": "重置间隔", + "suiteBuilderCreateTitle": "创建评估套件", + "activePeriodSpend": "当前周期支出", + "evalApiKeyHint": "选择用于评估请求的 API 密钥。", + "evalCompareOptional": "对比(可选)", + "suiteBuilderDeleteFailed": "删除套件失败", + "suiteBuilderCaseSystemPromptPlaceholder": "可选系统指令...", + "scorecardCases": "Case", + "runCompletedWithScore": "Evaluation 已完成 — 通过率 {score}%", + "suiteBuilderCustomBadge": "自定义", + "targetSuiteDefaults": "Suite 默认值", + "suiteBuilderDeleteConfirm": "确定要删除此套件吗?此操作无法撤销。", + "suiteBuilderNameLabel": "Suite 名称", "scorecardSuites": "Suites", - "evalCompareTarget": "Compare Target", - "suiteBuilderCaseModelPlaceholder": "e.g. gpt-4o-mini", - "evalControlsHint": "Configure your evaluation target and API key, then run suites to validate model quality.", - "recentRunsTitle": "Recent Runs", - "suiteBuilderCaseSystemPromptLabel": "System Prompt", - "suiteBuilderCaseExpectedPlaceholder": "e.g. def fibonacci", - "suiteBuilderNamePlaceholder": "e.g. Coding Quality Suite", - "suiteBuilderAddCase": "Add Case", - "cancel": "Cancel", - "evalTarget": "Target", - "suiteBuilderCaseNameLabel": "Case Name", - "weeklyLimitUsd": "Weekly Limit (USD)", - "suiteBuilderCaseUserPromptPlaceholder": "e.g. Write a fibonacci function in Python", - "suiteBuilderNameRequired": "Suite name is required", - "suiteBuilderCaseUserPromptLabel": "User Prompt", - "daily": "Daily", - "resultErrorLabel": "Error", - "suiteBuilderBuiltInBadge": "Built-in", - "suiteBuilderCaseCardTitle": "Test Case", - "weeklyLimitPlaceholder": "e.g. 50.00", - "suiteBuilderCaseTagsHint": "Comma-separated tags for organizing test cases.", - "notifyEvalRunFailedWithReason": "Evaluation failed: {reason}", - "weekly": "Weekly", - "runEvalRunning": "Running evaluation...", - "delete": "Delete", - "resetTimeUtc": "Reset Time (UTC)", - "evalApiKeyAuto": "Auto (use default)", - "suiteBuilderDescriptionPlaceholder": "Optional description of what this suite tests...", - "targetComparisonTitle": "Target Comparison", - "save": "Save", - "suiteBuilderCreated": "Suite created successfully", - "suiteLatestRuns": "Latest Runs", - "suiteBuilderCaseExpectedLabel": "Expected Value", - "historyLatency": "Latency", - "suiteBuilderCaseTagsPlaceholder": "e.g. coding, python", + "evalCompareTarget": "对比目标", + "suiteBuilderCaseModelPlaceholder": "例如 gpt-4o-mini", + "evalControlsHint": "配置评估目标和 API 密钥,然后运行套件以验证模型质量。", + "recentRunsTitle": "最近运行", + "suiteBuilderCaseSystemPromptLabel": "系统提示", + "suiteBuilderCaseExpectedPlaceholder": "例如 def fibonacci", + "suiteBuilderNamePlaceholder": "例如 Coding Quality Suite", + "suiteBuilderAddCase": "添加 Case", + "cancel": "取消", + "evalTarget": "目标", + "suiteBuilderCaseNameLabel": "Case 名称", + "weeklyLimitUsd": "每周限额(USD)", + "suiteBuilderCaseUserPromptPlaceholder": "例如用 Python 写一个 fibonacci 函数", + "suiteBuilderNameRequired": "Suite 名称为必填项", + "suiteBuilderCaseUserPromptLabel": "用户 Prompt", + "daily": "每日", + "resultErrorLabel": "错误", + "suiteBuilderBuiltInBadge": "内置", + "suiteBuilderCaseCardTitle": "测试用例", + "weeklyLimitPlaceholder": "例如 50.00", + "suiteBuilderCaseTagsHint": "用于组织测试用例的逗号分隔标签。", + "notifyEvalRunFailedWithReason": "评估失败:{reason}", + "weekly": "每周", + "runEvalRunning": "正在运行 Evaluation...", + "delete": "删除", + "resetTimeUtc": "重置时间(UTC)", + "evalApiKeyAuto": "自动(使用默认值)", + "suiteBuilderDescriptionPlaceholder": "可选:描述此套件测试的内容...", + "targetComparisonTitle": "目标对比", + "save": "保存", + "suiteBuilderCreated": "Suite 创建成功", + "suiteLatestRuns": "最新运行", + "suiteBuilderCaseExpectedLabel": "期望值", + "historyLatency": "延迟", + "suiteBuilderCaseTagsPlaceholder": "例如 coding, python", "targetTypeCombo": "Combo", - "scorecardPassed": "Passed", - "suiteBuilderCaseTagsLabel": "Tags", - "suiteBuilderNewSuite": "New Suite", - "notifyEvalLoadFailed": "Failed to load evaluation data", - "notConfigured": "Not Configured", - "suiteBuilderCaseNamePlaceholder": "e.g. Python fibonacci test", - "intervalLabel": "Interval", - "suiteBuilderCreateAction": "Create Suite", - "suiteBuilderCasesHint": "Each case sends a prompt and validates the response.", - "suiteBuilderUpdatedAt": "Updated", - "errorBadge": "Error", - "suiteBuilderCasesTitle": "Test Cases", - "edit": "Edit", - "monthly": "Monthly", - "suiteBuilderCasesRequired": "At least one test case is required", - "weeklyLimitSummary": "Weekly budget limit summary", - "suiteBuilderDescriptionLabel": "Description", - "targetComparisonHint": "Side-by-side comparison of evaluation results between targets.", - "compareCompletedWithScore": "Comparison completed — {score}% pass rate", - "staleQuotaTooltip": "Last refresh failed — showing cached data" + "scorecardPassed": "已通过", + "suiteBuilderCaseTagsLabel": "标签", + "suiteBuilderNewSuite": "新建 Suite", + "notifyEvalLoadFailed": "加载评估数据失败", + "notConfigured": "未配置", + "suiteBuilderCaseNamePlaceholder": "例如 Python 斐波那契测试", + "intervalLabel": "间隔", + "suiteBuilderCreateAction": "创建套件", + "suiteBuilderCasesHint": "每个用例都会发送一个提示并验证响应。", + "suiteBuilderUpdatedAt": "更新时间", + "errorBadge": "错误", + "suiteBuilderCasesTitle": "测试用例", + "edit": "编辑", + "monthly": "每月", + "suiteBuilderCasesRequired": "至少需要一个测试用例", + "weeklyLimitSummary": "每周预算限额摘要", + "suiteBuilderDescriptionLabel": "描述", + "targetComparisonHint": "在目标之间并排比较评估结果。", + "compareCompletedWithScore": "对比已完成 — 通过率 {score}%", + "runAllSuites": "全部运行", + "runAllRunning": "正在全部运行...", + "runAllProgress": "正在运行 {current}/{total}:{name}", + "runAllFailedSuites": "{count, plural, one {# 个套件失败} other {# 个套件失败}}", + "runAllCompleted": "已运行 {suites} 个套件 — {passed} 个通过,{failed} 个失败", + "runAllCompletedWithFailures": "已运行 {completed} 个套件;{failedSuites} 个运行失败", + "resultPassed": "已通过", + "resultFailed": "失败", + "expandResult": "展开结果详情", + "collapseResult": "折叠结果详情", + "expectedOutputLabel": "预期输出", + "clone": "克隆", + "exportSuite": "导出", + "importSuite": "导入", + "suiteExported": "套件已导出", + "suiteExportFailed": "导出套件失败", + "suiteImportReady": "套件导入已加载,等待检查", + "suiteImportFailed": "导入套件失败", + "suiteImportInvalid": "无效的 eval 套件 JSON", + "suiteBuilderCloneSuffix": "副本", + "suiteBuilderImportedSuite": "已导入套件", + "suiteBuilderCaseExpectedPlaceholderContains": "例如 def fibonacci", + "suiteBuilderCaseExpectedPlaceholderExact": "粘贴精确的预期响应", + "suiteBuilderCaseExpectedPlaceholderRegex": "例如 ^\\s*\\{.*\\}\\s*$", + "suiteBuilderCaseExpectedHintRegex": "使用不带包裹斜杠的 JavaScript 正则表达式。", + "suiteBuilderDuplicateCase": "复制" }, "modals": { "waitingAuth": "等待授权", @@ -4265,7 +4378,71 @@ "troubleshootingCircuitBreaker": "如果提供商显示断路器已打开,请等待冷却或查看运行状况页面以了解详细信息。", "troubleshootingOAuth": "对于 OAuth 提供商,如果 Token 过期,请重新认证,并检查提供商卡片上的状态指示器。", "deployTermuxTitle": "Termux (Android)", - "deployTermuxText": "Run OmniRoute headless on Android via Termux. Access the dashboard from your mobile browser." + "deployTermuxText": "通过 Termux 在 Android 上以无界面模式运行 OmniRoute,并从移动浏览器访问仪表盘。", + "deploymentGuides": "部署指南", + "clientWindsurfTitle": "Windsurf", + "clientWindsurfBullet1": "将 OmniRoute 用作 OpenAI 兼容的 base URL,并保留显式提供商前缀,以实现确定性路由。", + "clientWindsurfBullet2": "常规流量将模型指向 `/v1/chat/completions`,并为 Codex 风格流程保留 `/v1/responses`。", + "clientWindsurfBullet3": "使用仪表盘 -> CLI 工具获取现成的 Windsurf 配置指南。", + "clientClineTitle": "Cline", + "clientClineBullet1": "Cline 最适合使用显式的提供商/模型前缀,这样路由器无需猜测后端。", + "clientClineBullet2": "常规模型使用 `/v1/chat/completions`,并在不同账户间复用同一个 OmniRoute base URL。", + "clientClineBullet3": "调试 Cline 运行时问题前,请使用提供商仪表盘验证 OAuth/API 密钥。", + "clientKimiTitle": "Kimi Coding", + "clientKimiBullet1": "轮换底层账户或提供商组合时,将 OmniRoute 用作稳定的 base URL。", + "clientKimiBullet2": "在编码流程中优先使用带前缀的模型,让回退和审计轨迹保持明确。", + "clientKimiBullet3": "当你希望为使用工具的客户端启用原生 Responses 风格路由时,请使用 `/v1/responses`。", + "endpointCompletionsNote": "用于文本生成的旧版 completions 端点。", + "endpointModerationsNote": "内容审核和安全分类。", + "endpointRerankNote": "用于检索增强生成的文档重排序(Cohere、Jina)。", + "endpointSearchNote": "通过 5 个提供商进行网页搜索(Serper、Brave、Exa、Tavily、Perplexity)。", + "endpointSearchAnalyticsNote": "搜索请求的分析和指标。", + "endpointVideoNote": "视频生成(ComfyUI、SD WebUI 工作流)。", + "endpointMusicNote": "通过 ComfyUI 工作流生成音乐。", + "endpointMessagesNote": "Anthropic 原生 messages 端点。", + "endpointCountTokensNote": "统计给定消息载荷的 token 数。", + "endpointFilesNote": "用于多模态输入的文件上传。", + "endpointBatchesNote": "用于批量 API 请求的 Batch 处理。", + "endpointWsNote": "用于实时流式传输的 WebSocket 端点。", + "mgmtProvidersListNote": "列出所有已注册的提供商连接。", + "mgmtProvidersCreateNote": "创建新的提供商连接。", + "mgmtProvidersUpdateNote": "更新现有提供商连接。", + "mgmtProvidersDeleteNote": "删除提供商连接。", + "mgmtProvidersTestNote": "测试提供商的连接和认证。", + "mgmtProvidersModelsNote": "列出特定提供商的可用模型。", + "mgmtSettingsGetNote": "获取当前应用设置。", + "mgmtSettingsUpdateNote": "更新应用设置。", + "mgmtPayloadRulesGetNote": "获取载荷转换规则。", + "mgmtPayloadRulesUpdateNote": "更新载荷转换规则。", + "mcpToolsTitle": "MCP 工具", + "mcpToolsDescription": "OmniRoute 通过 Model Context Protocol 暴露 {count} 个工具,用于 Agent 编排。", + "mcpToolsCount": "{count} 个工具", + "mcpToolsToc": "MCP 工具", + "mcpToolsRoutingTitle": "路由与发现", + "mcpToolsRoutingDesc": "健康检查、组合管理、配额监控、成本报告和模型目录访问。", + "mcpToolsOperationsTitle": "运维与策略", + "mcpToolsOperationsDesc": "路由模拟、预算保护、策略切换、韧性配置和提供商指标。", + "mcpToolsCacheTitle": "缓存管理", + "mcpToolsCacheDesc": "查看缓存统计,并清空语义缓存或签名缓存。", + "mcpToolsMemoryTitle": "记忆", + "mcpToolsMemoryDesc": "搜索、添加和清除持久化对话记忆条目。", + "mcpToolsSkillsTitle": "技能", + "mcpToolsSkillsDesc": "列出、启用、执行和监控自定义技能执行。", + "featureAutoComboTitle": "Auto-Combo", + "featureAutoComboText": "根据你连接的提供商、使用模式和模型能力,自动创建优化组合。", + "featureSearchTitle": "网页搜索", + "featureSearchText": "集成 5 个提供商的网页搜索(Serper、Brave、Exa、Tavily、Perplexity),并包含分析和成本跟踪。", + "featureMemoryTitle": "记忆系统", + "featureMemoryText": "跨会话提供提取、注入、检索和摘要能力的持久化对话记忆。", + "featureSkillsTitle": "技能框架", + "featureSkillsText": "可扩展技能系统,支持内置和自定义技能、沙箱执行、请求拦截和上下文注入。", + "featureAcpTitle": "Agent 通信", + "featureAcpText": "Agent Communication Protocol (ACP) 注册表,用于管理 Agent 间工作流和工具编排。", + "protocolAcpTitle": "ACP(Agent 通信)", + "protocolAcpDesc": "通过 ACP 注册表注册和管理 Agent,用于 Agent 间通信和工具共享。", + "protocolAcpStep1": "前往仪表盘 → Agents 查看已注册的 ACP Agent。", + "protocolAcpStep2": "使用能力和端点配置注册新的 Agent。", + "protocolAcpStep3": "使用 CLI 工具配置 Agent 通信通道。" }, "legal": { "privacyPolicy": "隐私政策", @@ -4357,19 +4534,39 @@ "setupGuideCustomAgentDesc": "如果你的 CLI 不在内置列表中,请使用“添加自定义智能体”,并填写可执行文件名与版本命令。", "setupGuideCommandMissingTitle": "修复“command not found”", "setupGuideCommandMissingDesc": "请确认 CLI 命令已存在于 PATH 中,重新打开一个终端会话后再次点击“刷新”。", - "cliToolsRedirectTitle": "Cli Tools Redirect Title", - "cliToolsRedirectDesc": "Cli Tools Redirect Desc", - "spawnArgsPlaceholder": "Spawn Args Placeholder", - "binaryNamePlaceholder": "Binary Name Placeholder", - "versionCommandPlaceholder": "Version Command Placeholder", - "architectureTitle": "Architecture Title", - "flowLocalBinary": "Flow Local Binary", - "flowOmniRoute": "Flow Omni Route", - "agentNamePlaceholder": "Agent Name Placeholder", - "architectureDescription": "Architecture Description", - "flowExecute": "Flow Execute", - "flowSpawn": "Flow Spawn", - "cliToolsRedirectCta": "Cli Tools Redirect Cta" + "cliToolsRedirectTitle": "CLI 工具已移至专用页面", + "cliToolsRedirectDesc": "在 CLI Tools 页面管理 Agent CLI 集成与重定向。", + "spawnArgsPlaceholder": "启动参数占位符", + "binaryNamePlaceholder": "二进制名称占位符", + "versionCommandPlaceholder": "版本命令占位符", + "architectureTitle": "架构", + "flowLocalBinary": "本地二进制", + "flowOmniRoute": "OmniRoute", + "agentNamePlaceholder": "Agent 名称占位符", + "architectureDescription": "了解 OmniRoute 如何在客户端、路由器和 Agent 目标之间转发请求。", + "flowExecute": "执行", + "flowSpawn": "启动", + "cliToolsRedirectCta": "打开 CLI Tools", + "comparisonTitle": "CLI 工具与 Agent 目标有什么区别?", + "comparisonCliToolsLabel": "CLI 工具页面", + "comparisonCliToolsTitle": "你的 IDE 通过 OmniRoute 发送请求", + "comparisonCliToolsDesc": "配置 Claude Code、Codex、Cursor 和其他 IDE,将 OmniRoute 用作它们的 API base URL。OmniRoute 作为代理,将请求路由到你配置的提供商。", + "comparisonAgentsLabel": "当前页面(Agent 目标)", + "comparisonAgentsTitle": "OmniRoute 将请求发送到本地 CLI 工具", + "comparisonAgentsDesc": "OmniRoute 可以启动本地 CLI 二进制文件(claude、codex、goose)作为执行后端。CLI 工具使用自己的认证处理请求并返回结果。", + "comparisonSummary": "简而言之:CLI 工具 = 你配置工具指向 OmniRoute。Agent 目标 = OmniRoute 将工具用作端点。", + "agentUseCaseHint": "可通过 ACP 协议用作执行目标", + "flowDiagramClient": "客户端应用", + "flowDiagramClientDesc": "SDK、API 或上游服务", + "flowDiagramOmniRoute": "OmniRoute", + "flowDiagramOmniRouteDesc": "接收请求并选择目标", + "flowDiagramSpawn": "启动进程", + "flowDiagramSpawnDesc": "通过 stdio 启动 CLI 二进制文件", + "flowDiagramCli": "CLI Agent", + "flowDiagramCliDesc": "使用自身认证/模型处理", + "fingerprintSettingsHint": "CLI 指纹匹配(伪装成特定 CLI 工具的请求)可在以下位置配置:", + "settingsRoutingLink": "设置/路由", + "openSettings": "设置" }, "templateNames": { "simple-chat": "简单对话", @@ -4454,14 +4651,14 @@ "cacheHitRate": "缓存命中率", "cacheRate": "缓存率", "cacheRateDesc": "占总请求数", - "cachedTokens": "Cache Read Tokens", - "cacheCreationTokens": "Cache Write Tokens", + "cachedTokens": "缓存读取 Token", + "cacheCreationTokens": "缓存写入 Token", "cacheMetrics": "Prompt 缓存指标", "withCacheControl": "含缓存控制", - "cachedTokensRead": "Read from cache", - "cacheCreationWrite": "Written to cache", + "cachedTokensRead": "从缓存读取", + "cacheCreationWrite": "写入缓存", "cacheReuseRatio": "缓存复用率", - "cacheReuseRatioDesc": "Cache read tokens / 输入 Tokens 总量", + "cacheReuseRatioDesc": "缓存读取 token / 输入 token 总量", "estCostSaved": "预估节省费用", "lastUpdated": "上次更新", "hoursTracked": "个小时", @@ -4476,12 +4673,12 @@ "resetting": "正在重置...", "resetMetrics": "重置指标", "byProvider": "按提供商分类", - "providerCacheRateDesc": "每个提供商都会直接展示总输入 Tokens、cache read tokens 和 cache write tokens,方便你对照原始数据判断 ratio 是否可靠。", + "providerCacheRateDesc": "每个提供商都会直接展示总输入 token、cache read token 和 cache write token,方便你对照原始数据判断比率是否可靠。", "provider": "提供商", "requests": "请求数", "inputTokens": "输入 Tokens 总计", - "cachedTokensCol": "Cache Read", - "cacheCreation": "Cache Write", + "cachedTokensCol": "缓存读取", + "cacheCreation": "缓存写入", "trend24h": "缓存趋势(24 小时)", "peakCached": "峰值缓存量", "cached": "已缓存", @@ -4495,7 +4692,7 @@ "loading": "加载中...", "entriesLoadError": "加载语义缓存条目失败。", "noEntries": "未找到缓存条目", - "noPromptCacheData": "暂时还没有记录到 provider-side prompt cache 活动。", + "noPromptCacheData": "暂时还没有记录到提供商侧 prompt cache 活动。", "noTrendData": "最近 24 小时还没有记录到 prompt cache 活动。", "signature": "签名", "model": "模型", @@ -4505,8 +4702,33 @@ "deduplicatedRequests": "去重请求数", "savedCalls": "节省的 API 调用次数", "totalProcessed": "已处理请求总数", - "disabled": "Disabled", - "totalRequests": "Total Requests" + "disabled": "已禁用", + "totalRequests": "总请求数", + "reasoningCache": "推理回放", + "reasoningCacheDesc": "为多轮工具调用流程保留模型思考内容", + "reasoningEntries": "活动条目", + "reasoningReplayRate": "回放率", + "reasoningReplays": "总回放次数", + "reasoningCharsCached": "已缓存字符数", + "reasoningMisses": "缓存未命中", + "reasoningByProvider": "按提供商", + "reasoningByModel": "按模型", + "reasoningRecentEntries": "最近条目", + "reasoningToolCallId": "工具调用 ID", + "reasoningChars": "字符数", + "reasoningAge": "时间", + "reasoningView": "查看", + "reasoningDetail": "推理内容", + "reasoningBehavior": "行为", + "reasoningBehaviorCapture": "从流式响应中捕获 reasoning_content", + "reasoningBehaviorReplay": "当客户端省略时,在下一轮重新注入", + "reasoningBehaviorFallback": "内存优先,并使用 SQLite 作为崩溃恢复后备", + "reasoningBehaviorTtl": "TTL:2 小时 | 最大条目:2,000(内存)", + "reasoningBehaviorModels": "支持:DeepSeek、Kimi、Qwen-Thinking、GLM", + "reasoningClearAll": "清空推理缓存", + "reasoningClearSuccess": "已清除 {count} 个推理缓存条目", + "reasoningClearError": "清除推理缓存失败", + "reasoningNoData": "尚未缓存推理条目。思考模型使用工具调用时会显示条目。" }, "memory": { "title": "记忆管理", @@ -4543,7 +4765,8 @@ "pipelineError": "Pipeline 错误", "healthUnknown": "健康状态未知", "cancel": "取消", - "save": "保存" + "save": "保存", + "a": "A" }, "skills": { "title": "技能", @@ -4571,7 +4794,7 @@ "timeoutDesc": "等待响应的最长时间", "networkAccess": "网络访问", "networkAccessDesc": "允许发起出站网络请求", - "mode": "Mode", + "mode": "模式", "q": "Q" }, "proxyConfigModal": { @@ -4733,7 +4956,26 @@ "noData": "—", "testSuccess": "✓ {ip}", "testLatency": "{latency}毫秒", - "testFailure": "✗ {error}" + "testFailure": "✗ {error}", + "bulkImport": "批量导入", + "bulkImportTitle": "批量导入代理", + "bulkImportDescription": "使用管道符分隔格式粘贴代理配置。每行一个代理。已有代理(相同 host + port)将被更新。", + "bulkImportParse": "解析", + "bulkImportImport": "导入 {count} 个代理", + "bulkImportImporting": "正在导入...", + "bulkImportParsed": "已解析 {count} 个代理", + "bulkImportSkipped": "已跳过 {count} 行", + "bulkImportParseErrors": "{count} 个错误", + "bulkImportNoValidEntries": "未找到有效条目。请检查格式后重试。", + "bulkImportSuccess": "导入完成:已创建 {created} 个,已更新 {updated} 个,失败 {failed} 个", + "bulkImportErrorLine": "第 {line} 行:{reason}", + "bulkImportMaxExceeded": "每次最多导入 100 个代理", + "bulkImportPreview": "预览", + "bulkImportErrorMissingName": "缺少 NAME", + "bulkImportErrorMissingHost": "缺少 HOST", + "bulkImportErrorInvalidPort": "PORT 无效(必须为 1-65535)", + "bulkImportErrorInvalidType": "TYPE 无效(使用 http、https 或 socks5)", + "bulkImportErrorInvalidStatus": "STATUS 无效(使用 active 或 inactive)" }, "playground": { "title": "模型演练场", @@ -4822,37 +5064,38 @@ "tokens": "Tokens", "tps": "TPS", "duration": "时长", - "time": "时间" + "time": "时间", + "compressed": "压缩" }, "loadingLogs": "正在加载日志...", "noLogs": "暂无日志记录。进行一些API调用以在此处查看它们。", "noMatchingLogs": "没有匹配当前筛选器的日志。", "callLogsInfo": "调用日志也保存为JSON文件到{dataDir},并根据{retentionDays}和{maxEntries}进行轮换。", - "updatePipelineFailed": "Failed to update pipeline logging", - "capturePipeline": "Capture pipeline payloads for new requests", - "sortLogs": "Sort logs", - "refresh": "Refresh", - "columnsLabel": "Columns", + "updatePipelineFailed": "更新流水线日志失败", + "capturePipeline": "为新请求捕获流水线载荷", + "sortLogs": "日志排序", + "refresh": "刷新", + "columnsLabel": "列", "cacheSem": "SEM", "cacheUp": "UP", - "semantic": "Semantic", - "upstream": "Upstream", - "semanticCacheHit": "Semantic cache hit (served by OmniRoute)", - "upstreamResponse": "Upstream provider response", - "noApiKey": "No API key", - "requestedRoutedTitle": "Requested {requested}, routed as {routed}" + "semantic": "Semantic Cache", + "upstream": "上游", + "semanticCacheHit": "语义缓存命中(由 OmniRoute 提供)", + "upstreamResponse": "上游提供商响应", + "noApiKey": "无 API key", + "requestedRoutedTitle": "请求 {requested},路由为 {routed}" }, "endpointOptions": { - "speech": "Speech", - "search": "Search", - "images": "Images", - "chat": "Chat", - "music": "Music", + "speech": "语音", + "search": "搜索", + "images": "图像", + "chat": "聊天", + "music": "音乐", "responses": "Responses", "rerank": "Rerank", - "video": "Video", + "video": "视频", "embeddings": "Embeddings", - "transcription": "Transcription" + "transcription": "转写" }, "toolDescriptions": { "cline": "Cline", @@ -4863,47 +5106,203 @@ "kilo": "Kilo" }, "proxyLogger": { - "filterAll": "All", - "filterErrors": "Errors", - "filterSuccess": "Success", - "filterTimeout": "Timeout", - "colStatus": "Status", - "colProxy": "Proxy", + "filterAll": "全部", + "filterErrors": "错误", + "filterSuccess": "成功", + "filterTimeout": "超时", + "colStatus": "状态", + "colProxy": "代理", "colTls": "TLS", - "colType": "Type", - "colLevel": "Level", - "colProvider": "Provider", - "colTarget": "Target", - "colLatency": "Latency", - "colPublicIp": "Public IP", - "colTime": "Time", - "recording": "Recording", - "paused": "Paused", - "searchPlaceholder": "Search host, provider, target, IP...", - "allTypes": "All Types", - "allLevels": "All Levels", - "allProviders": "All Providers", - "total": "total", + "colType": "类型", + "colLevel": "级别", + "colProvider": "提供商", + "colTarget": "目标", + "colLatency": "延迟", + "colPublicIp": "公网 IP", + "colTime": "时间", + "recording": "记录中", + "paused": "已暂停", + "searchPlaceholder": "搜索主机、提供商、目标或 IP...", + "allTypes": "全部类型", + "allLevels": "全部级别", + "allProviders": "全部 Provider", + "total": "总计", "ok": "OK", "err": "ERR", "timeoutShort": "TMO", "direct": "direct", - "newest": "Newest", - "oldest": "Oldest", - "latencyDesc": "Latency ↓", - "latencyAsc": "Latency ↑", - "refresh": "Refresh", - "columns": "Columns", - "loadingProxyLogs": "Loading proxy logs...", - "noProxyLogs": "No proxy logs yet. Configure proxies and make API calls to see them here.", - "noMatchingLogs": "No logs match the current filters.", - "tlsFingerprint": "Chrome 124 TLS Fingerprint" + "newest": "最新", + "oldest": "最旧", + "latencyDesc": "延迟 ↓", + "latencyAsc": "延迟 ↑", + "refresh": "刷新", + "columns": "列", + "loadingProxyLogs": "正在加载代理日志...", + "noProxyLogs": "尚无代理日志。配置代理并发起 API 调用后会显示在这里。", + "noMatchingLogs": "没有日志匹配当前筛选条件。", + "tlsFingerprint": "Chrome 124 TLS 指纹" }, - "agentFeatures": { - "agentFeaturesContextLength": "Context length", - "agentFeaturesContextLengthPlaceholder": "e.g. 128000", - "agentFeaturesContextLengthHint": "Defines the context window for this combo in /v1/models.", - "agentFeaturesContextLengthErrorInteger": "Context length must be a valid integer", - "agentFeaturesContextLengthErrorRange": "Context length must be between 1000 and 2000000" + "webhooks": { + "title": "Webhook", + "description": "配置系统事件的 HTTP 回调。", + "configuredWebhooks": "已配置的 Webhook", + "configuredWebhooksDesc": "管理投递端点、订阅事件、状态和测试发送。", + "addWebhook": "添加 Webhook", + "editWebhook": "编辑 Webhook", + "name": "名称", + "namePlaceholder": "生产监控", + "unnamedWebhook": "未命名 Webhook", + "url": "端点 URL", + "events": "事件", + "allEvents": "所有事件", + "secret": "密钥", + "secretPlaceholder": "留空将自动生成密钥", + "secretEditPlaceholder": "留空以保留当前密钥", + "status": "状态", + "active": "活动", + "inactive": "未活动", + "errored": "出错", + "total": "总计", + "lastTriggered": "上次触发", + "actions": "操作", + "enabled": "已启用", + "enabledDesc": "禁用的 Webhook 会继续保存,但不会接收投递。", + "refresh": "刷新", + "loading": "正在加载 Webhook...", + "never": "从未", + "failureCount": "{count, plural, =0 {no failures} one {# 次失败} other {# 次失败}}", + "testWebhook": "发送测试", + "testSuccess": "测试 Webhook 发送成功。", + "testFailed": "测试 Webhook 失败。", + "saveSuccess": "Webhook 保存成功。", + "saveFailed": "保存 Webhook 失败。", + "loadFailed": "加载 Webhook 失败。", + "delete": "删除", + "deleteConfirm": "确定要删除此 Webhook 吗?", + "deleteSuccess": "Webhook 删除成功。", + "deleteFailed": "删除 Webhook 失败。", + "edit": "编辑", + "enable": "启用", + "disable": "禁用", + "noWebhooks": "尚未配置 Webhook。", + "signatureTitle": "Webhook 签名", + "signatureDescription": "每次投递都会包含一个 X-Webhook-Signature 请求头,该签名使用 Webhook 密钥通过 HMAC-SHA256 生成。信任载荷前请先验证签名。" + }, + "compliance": { + "auditTitle": "审计", + "auditDescription": "在一个运维视图中查看合规事件和 MCP 工具调用。", + "complianceTab": "合规", + "mcpTab": "MCP 审计", + "title": "合规审计", + "description": "合规审计日志记录的策略、访问、提供商和安全事件。", + "eventType": "事件类型", + "eventTypePlaceholder": "按操作或事件类型筛选", + "severity": "严重级别", + "allSeverities": "所有严重级别", + "info": "信息", + "warning": "警告", + "critical": "严重", + "sourceIp": "来源 IP", + "userOrKey": "用户 / 密钥", + "action": "操作", + "result": "结果", + "details": "详情", + "timestamp": "时间戳", + "from": "起始", + "to": "结束", + "refresh": "刷新", + "export": "导出", + "clearFilters": "清除筛选", + "loading": "正在加载审计事件...", + "showing": "正在显示 {total} 个事件中的 {count} 个", + "policyViolation": "策略违规", + "accessDenied": "访问被拒绝", + "injectionBlocked": "注入已阻止", + "noEvents": "尚未记录合规事件。", + "failedFetch": "获取合规审计日志失败。", + "viewDetails": "查看详情", + "closeDetails": "关闭详情", + "notAvailable": "—", + "system": "system", + "previous": "上一页", + "next": "下一页", + "mcpAudit": "MCP 审计", + "mcpAuditDesc": "MCP 服务器记录的工具调用审计条目。", + "failedFetchMcpAudit": "获取 MCP 审计日志失败。", + "tool": "工具", + "toolPlaceholder": "按工具名称筛选", + "duration": "持续时间", + "apiKey": "API 密钥", + "output": "输出", + "allResults": "所有结果", + "success": "成功", + "failure": "失败", + "noMcpEvents": "尚未记录 MCP 审计事件。" + }, + "telemetry": { + "title": "系统遥测", + "description": "来自此 OmniRoute 进程的滚动请求、运行时、会话和内存信号。", + "uptime": "运行时间", + "totalRequests": "请求总数", + "avgLatency": "平均延迟", + "errorRate": "错误率", + "activeConnections": "活动连接", + "memoryUsage": "内存使用", + "latencyTrend": "延迟趋势", + "throughputTrend": "吞吐趋势", + "memoryTrend": "内存趋势", + "refresh": "刷新", + "updatedAt": "更新于 {time}", + "loadFailed": "加载遥测失败。", + "partialData": "遥测数据部分可用:{error}" + }, + "mitm": { + "title": "MITM 代理", + "description": "用于拦截和路由客户端请求的透明代理。", + "enable": "启用 MITM 代理", + "enableDesc": "启动或停止本地拦截进程和 DNS 覆盖。", + "status": "状态", + "running": "运行中", + "stopped": "已停止", + "start": "启动", + "stop": "停止", + "refresh": "刷新", + "port": "代理端口", + "apiKey": "路由器 API 密钥", + "apiKeyPlaceholder": "可选;留空则回退到本地密钥", + "sudoPassword": "Sudo 密码", + "cachedPassword": "已为此进程缓存", + "saveSettings": "保存设置", + "settingsSaved": "MITM 设置已保存。", + "startedSuccess": "MITM 代理已启动。", + "stoppedSuccess": "MITM 代理已停止。", + "saveFailed": "更新 MITM 设置失败。", + "loadFailed": "加载 MITM 设置失败。", + "invalidPort": "透明 MITM 拦截当前要求使用端口 443。", + "certificate": "CA 证书", + "certificateReady": "证书已可用于客户端信任安装。", + "certificateMissing": "尚未生成证书。", + "available": "可用", + "missing": "缺失", + "downloadCert": "下载 CA 证书", + "regenerateCert": "重新生成证书", + "regenerateConfirm": "这会使现有客户端信任失效。要继续吗?", + "regenerateSuccess": "MITM 证书已重新生成。", + "regenerateFailed": "重新生成 MITM 证书失败。", + "targetRoutes": "目标路由", + "interceptedRequests": "已拦截请求", + "activeConnections": "活动连接", + "dnsConfigured": "DNS 已配置", + "pid": "PID", + "lastIntercept": "上次拦截", + "target": "目标", + "host": "主机", + "localPort": "本地端口", + "endpoints": "端点", + "enabled": "已启用", + "configured": "已配置", + "yes": "是", + "no": "否", + "noTargets": "未配置目标路由。" } -} \ No newline at end of file +} diff --git a/src/instrumentation-node.ts b/src/instrumentation-node.ts index 50cbd0e208..b55d1e352e 100755 --- a/src/instrumentation-node.ts +++ b/src/instrumentation-node.ts @@ -136,11 +136,15 @@ export async function registerNodejs(): Promise { } try { - const [{ migrateCodexConnectionDefaultsFromLegacySettings }, { seedDefaultModelAliases }] = - await Promise.all([ - import("@/lib/providers/codexConnectionDefaults"), - import("@/lib/modelAliasSeed"), - ]); + const [ + { migrateCodexConnectionDefaultsFromLegacySettings }, + { startSessionAccountAffinityCleanup }, + { seedDefaultModelAliases }, + ] = await Promise.all([ + import("@/lib/providers/codexConnectionDefaults"), + import("@/lib/db/sessionAccountAffinity"), + import("@/lib/modelAliasSeed"), + ]); let settings = await getSettings(); const passwordState = await ensurePersistentManagementPasswordHash({ logger: console, @@ -161,6 +165,7 @@ export async function registerNodejs(): Promise { console.log( `[STARTUP] Model alias seed: applied=${seededModelAliases.applied.length}, skipped=${seededModelAliases.skipped.length}, failed=${seededModelAliases.failed.length}` ); + startSessionAccountAffinityCleanup(); const migration = await migrateCodexConnectionDefaultsFromLegacySettings(); if (migration.migrated) { diff --git a/src/lib/apiBridgeServer.ts b/src/lib/apiBridgeServer.ts index d289d6f752..4109dfd6ac 100644 --- a/src/lib/apiBridgeServer.ts +++ b/src/lib/apiBridgeServer.ts @@ -22,7 +22,22 @@ function isOpenAiCompatiblePath(pathname: string): boolean { return OPENAI_COMPAT_PATHS.some((pattern) => pattern.test(pathname)); } +function requestWantsStreaming(req: IncomingMessage): boolean { + const accept = String(req.headers.accept || "").toLowerCase(); + if (accept.includes("text/event-stream")) return true; + + const pathname = (req.url || "/").split("?")[0] || "/"; + return /^\/(?:v1\/)?(?:responses|chat\/completions)(?:\/|$)/.test(pathname); +} + +function getProxyTimeoutMs(req: IncomingMessage): number { + if (!requestWantsStreaming(req)) return API_BRIDGE_TIMEOUTS.proxyTimeoutMs; + + return Math.max(API_BRIDGE_TIMEOUTS.proxyTimeoutMs, API_BRIDGE_TIMEOUTS.serverRequestTimeoutMs); +} + function proxyRequest(req: IncomingMessage, res: ServerResponse, dashboardPort: number): void { + const proxyTimeoutMs = getProxyTimeoutMs(req); const targetReq = http.request( { hostname: "127.0.0.1", @@ -33,9 +48,14 @@ function proxyRequest(req: IncomingMessage, res: ServerResponse, dashboardPort: ...req.headers, host: `127.0.0.1:${dashboardPort}`, }, - timeout: API_BRIDGE_TIMEOUTS.proxyTimeoutMs, + timeout: proxyTimeoutMs, }, (targetRes) => { + const contentType = String(targetRes.headers["content-type"] || "").toLowerCase(); + if (contentType.includes("text/event-stream")) { + targetReq.setTimeout(0); + } + res.writeHead(targetRes.statusCode || 502, targetRes.headers); targetRes.pipe(res); } @@ -48,7 +68,7 @@ function proxyRequest(req: IncomingMessage, res: ServerResponse, dashboardPort: res.end( JSON.stringify({ error: "api_bridge_timeout", - detail: `Proxy request timed out after ${API_BRIDGE_TIMEOUTS.proxyTimeoutMs}ms`, + detail: `Proxy request timed out after ${proxyTimeoutMs}ms`, }) ); }); diff --git a/src/lib/cloudAgent/agents/codex.ts b/src/lib/cloudAgent/agents/codex.ts new file mode 100644 index 0000000000..f069ac9109 --- /dev/null +++ b/src/lib/cloudAgent/agents/codex.ts @@ -0,0 +1,148 @@ +import { + CloudAgentBase, + type AgentCredentials, + type CreateTaskParams, + type GetStatusResult, +} from "../baseAgent.ts"; +import type { CloudAgentTask, CloudAgentActivity } from "../types.ts"; +import { CLOUD_AGENT_STATUS } from "../types.ts"; + +export class CodexCloudAgent extends CloudAgentBase { + readonly providerId = "codex-cloud"; + readonly baseUrl = "https://api.openai.com/v1"; + + async createTask( + params: CreateTaskParams, + credentials: AgentCredentials + ): Promise { + const taskId = this.generateTaskId(); + + const body: Record = { + prompt: params.prompt, + repository_context: params.source.repoUrl, + }; + + if (params.source.branch) { + body.branch = params.source.branch; + } + + if (params.options.environment) { + body.environment = { + setup: params.options.environment, + }; + } + + const response = await fetch(`${this.baseUrl}/codex/cloud/tasks`, { + method: "POST", + headers: { + "Content-Type": "application/json", + Authorization: `Bearer ${credentials.apiKey}`, + }, + body: JSON.stringify(body), + }); + + if (!response.ok) { + const error = await response.text(); + throw new Error(`Codex Cloud create task failed: ${response.status} ${error}`); + } + + const data = await response.json(); + + return { + id: taskId, + providerId: this.providerId, + externalId: data.id, + status: this.mapStatus(data.status || "pending"), + prompt: params.prompt, + source: params.source, + options: params.options, + activities: [], + createdAt: new Date().toISOString(), + updatedAt: new Date().toISOString(), + }; + } + + async getStatus(externalId: string, credentials: AgentCredentials): Promise { + const response = await fetch(`${this.baseUrl}/codex/cloud/tasks/${externalId}`, { + headers: { + Authorization: `Bearer ${credentials.apiKey}`, + }, + }); + + if (!response.ok) { + const error = await response.text(); + throw new Error(`Codex Cloud get status failed: ${response.status} ${error}`); + } + + const data = await response.json(); + const status = this.mapStatus(data.status || "pending"); + + const activities: CloudAgentActivity[] = []; + + if (data.subagents) { + for (const subagent of data.subagents) { + activities.push({ + id: this.generateActivityId(), + type: "command", + content: `Subagent: ${subagent.name} - ${subagent.status}`, + timestamp: new Date().toISOString(), + }); + } + } + + let result; + if (status === CLOUD_AGENT_STATUS.COMPLETED && (data.result || data.pr_url)) { + result = { + prUrl: data.pr_url || data.result?.pr_url, + commitMessage: data.result?.commit_message, + summary: data.result?.summary, + duration: data.elapsed_time, + }; + } + + return { + status, + externalId, + result, + activities, + error: data.error || data.error_message, + }; + } + + async approvePlan(_externalId: string, _credentials: AgentCredentials): Promise { + throw new Error("Codex Cloud does not support plan approval - it auto-plans"); + } + + async sendMessage( + externalId: string, + message: string, + credentials: AgentCredentials + ): Promise { + const response = await fetch(`${this.baseUrl}/codex/cloud/tasks/${externalId}/followup`, { + method: "POST", + headers: { + "Content-Type": "application/json", + Authorization: `Bearer ${credentials.apiKey}`, + }, + body: JSON.stringify({ message }), + }); + + if (!response.ok) { + const error = await response.text(); + throw new Error(`Codex Cloud send message failed: ${response.status} ${error}`); + } + + return { + id: this.generateActivityId(), + type: "message", + content: message, + timestamp: new Date().toISOString(), + }; + } + + async listSources( + _credentials: AgentCredentials + ): Promise<{ name: string; url: string; branch?: string }[]> { + return []; + } +} diff --git a/src/lib/cloudAgent/agents/devin.ts b/src/lib/cloudAgent/agents/devin.ts new file mode 100644 index 0000000000..c409c92349 --- /dev/null +++ b/src/lib/cloudAgent/agents/devin.ts @@ -0,0 +1,137 @@ +import { + CloudAgentBase, + type AgentCredentials, + type CreateTaskParams, + type GetStatusResult, +} from "../baseAgent.ts"; +import type { CloudAgentTask, CloudAgentActivity } from "../types.ts"; +import { CLOUD_AGENT_STATUS } from "../types.ts"; + +export class DevinAgent extends CloudAgentBase { + readonly providerId = "devin"; + readonly baseUrl = "https://api.devin.ai/v1"; + + async createTask( + params: CreateTaskParams, + credentials: AgentCredentials + ): Promise { + const taskId = this.generateTaskId(); + + const body: Record = { + prompt: params.prompt, + repo_url: params.source.repoUrl, + }; + + if (params.source.branch) { + body.branch = params.source.branch; + } + + const response = await fetch(`${this.baseUrl}/sessions`, { + method: "POST", + headers: { + "Content-Type": "application/json", + Authorization: `Bearer ${credentials.apiKey}`, + }, + body: JSON.stringify(body), + }); + + if (!response.ok) { + const error = await response.text(); + throw new Error(`Devin create task failed: ${response.status} ${error}`); + } + + const data = await response.json(); + + return { + id: taskId, + providerId: this.providerId, + externalId: data.id, + status: this.mapStatus(data.status || "created"), + prompt: params.prompt, + source: params.source, + options: params.options, + activities: [], + createdAt: new Date().toISOString(), + updatedAt: new Date().toISOString(), + }; + } + + async getStatus(externalId: string, credentials: AgentCredentials): Promise { + const response = await fetch(`${this.baseUrl}/sessions/${externalId}`, { + headers: { + Authorization: `Bearer ${credentials.apiKey}`, + }, + }); + + if (!response.ok) { + const error = await response.text(); + throw new Error(`Devin get status failed: ${response.status} ${error}`); + } + + const data = await response.json(); + const status = this.mapStatus(data.status || "created"); + + const activities: CloudAgentActivity[] = (data.messages || []).map( + (msg: Record) => ({ + id: this.generateActivityId(), + type: "message" as const, + content: (msg.content as string) || "", + timestamp: (msg.created_at as string) || new Date().toISOString(), + }) + ); + + let result; + if (status === CLOUD_AGENT_STATUS.COMPLETED && data.output) { + result = { + prUrl: data.pr_url, + summary: data.output, + duration: data.duration, + }; + } + + return { + status, + externalId, + result, + activities, + error: data.error, + }; + } + + async approvePlan(_externalId: string, _credentials: AgentCredentials): Promise { + throw new Error("Devin does not support plan approval - it auto-plans"); + } + + async sendMessage( + externalId: string, + message: string, + credentials: AgentCredentials + ): Promise { + const response = await fetch(`${this.baseUrl}/sessions/${externalId}/message`, { + method: "POST", + headers: { + "Content-Type": "application/json", + Authorization: `Bearer ${credentials.apiKey}`, + }, + body: JSON.stringify({ content: message }), + }); + + if (!response.ok) { + const error = await response.text(); + throw new Error(`Devin send message failed: ${response.status} ${error}`); + } + + return { + id: this.generateActivityId(), + type: "message", + content: message, + timestamp: new Date().toISOString(), + }; + } + + async listSources( + _credentials: AgentCredentials + ): Promise<{ name: string; url: string; branch?: string }[]> { + return []; + } +} diff --git a/src/lib/cloudAgent/agents/jules.ts b/src/lib/cloudAgent/agents/jules.ts new file mode 100644 index 0000000000..932eb4dfaa --- /dev/null +++ b/src/lib/cloudAgent/agents/jules.ts @@ -0,0 +1,170 @@ +import { + CloudAgentBase, + type AgentCredentials, + type CreateTaskParams, + type GetStatusResult, +} from "../baseAgent.ts"; +import type { CloudAgentTask, CloudAgentActivity } from "../types.ts"; +import { CLOUD_AGENT_STATUS } from "../types.ts"; + +export class JulesAgent extends CloudAgentBase { + readonly providerId = "jules"; + readonly baseUrl = "https://jules.googleapis.com/v1alpha"; + + async createTask( + params: CreateTaskParams, + credentials: AgentCredentials + ): Promise { + const taskId = this.generateTaskId(); + + const body: Record = { + prompt: params.prompt, + source: { + repository: { + owner: params.source.repoUrl.split("/").filter(Boolean).slice(-2, -1)[0] || "", + name: params.source.repoName, + }, + branch: params.source.branch || "main", + }, + }; + + if (params.options.autoCreatePr) { + body.automationMode = "AUTO_CREATE_PR"; + } + + const response = await fetch(`${this.baseUrl}/sessions`, { + method: "POST", + headers: { + "Content-Type": "application/json", + "X-Goog-Api-Key": credentials.apiKey, + }, + body: JSON.stringify(body), + }); + + if (!response.ok) { + const error = await response.text(); + throw new Error(`Jules create task failed: ${response.status} ${error}`); + } + + const data = await response.json(); + + return { + id: taskId, + providerId: this.providerId, + externalId: data.name?.split("/").pop() || taskId, + status: this.mapStatus(data.state || "pending"), + prompt: params.prompt, + source: params.source, + options: params.options, + activities: [], + createdAt: new Date().toISOString(), + updatedAt: new Date().toISOString(), + }; + } + + async getStatus(externalId: string, _credentials: AgentCredentials): Promise { + const response = await fetch(`${this.baseUrl}/sessions/${externalId}`, { + headers: { + "X-Goog-Api-Key": _credentials.apiKey, + }, + }); + + if (!response.ok) { + const error = await response.text(); + throw new Error(`Jules get status failed: ${response.status} ${error}`); + } + + const data = await response.json(); + const status = this.mapStatus(data.state || "pending"); + + const activities: CloudAgentActivity[] = (data.activities || []).map( + (act: Record) => ({ + id: this.generateActivityId(), + type: act.type as CloudAgentActivity["type"], + content: (act.description as string) || "", + timestamp: (act.timestamp as string) || new Date().toISOString(), + }) + ); + + let result; + if (status === CLOUD_AGENT_STATUS.COMPLETED && data.outputs) { + result = { + prUrl: data.outputs.prUrl, + commitMessage: data.outputs.commitMessage, + summary: data.outputs.summary, + }; + } + + return { + status, + externalId, + result, + activities, + error: data.error, + }; + } + + async approvePlan(externalId: string, credentials: AgentCredentials): Promise { + const response = await fetch(`${this.baseUrl}/sessions/${externalId}:approvePlan`, { + method: "POST", + headers: { + "Content-Type": "application/json", + "X-Goog-Api-Key": credentials.apiKey, + }, + }); + + if (!response.ok) { + const error = await response.text(); + throw new Error(`Jules approve plan failed: ${response.status} ${error}`); + } + } + + async sendMessage( + externalId: string, + message: string, + credentials: AgentCredentials + ): Promise { + const response = await fetch(`${this.baseUrl}/sessions/${externalId}:sendMessage`, { + method: "POST", + headers: { + "Content-Type": "application/json", + "X-Goog-Api-Key": credentials.apiKey, + }, + body: JSON.stringify({ message }), + }); + + if (!response.ok) { + const error = await response.text(); + throw new Error(`Jules send message failed: ${response.status} ${error}`); + } + + return { + id: this.generateActivityId(), + type: "message", + content: message, + timestamp: new Date().toISOString(), + }; + } + + async listSources( + credentials: AgentCredentials + ): Promise<{ name: string; url: string; branch?: string }[]> { + const response = await fetch(`${this.baseUrl}/sources`, { + headers: { + "X-Goog-Api-Key": credentials.apiKey, + }, + }); + + if (!response.ok) { + const error = await response.text(); + throw new Error(`Jules list sources failed: ${response.status} ${error}`); + } + + const data = await response.json(); + return (data.sources || []).map((source: Record) => ({ + name: source.name as string, + url: `https://github.com/${source.repoOwner}/${source.repoName}`, + branch: source.defaultBranch as string | undefined, + })); + } +} diff --git a/src/lib/cloudAgent/baseAgent.ts b/src/lib/cloudAgent/baseAgent.ts new file mode 100644 index 0000000000..9f5689b90b --- /dev/null +++ b/src/lib/cloudAgent/baseAgent.ts @@ -0,0 +1,95 @@ +import type { + CloudAgentTask, + CloudAgentStatus, + CloudAgentSource, + CloudAgentResult, + CloudAgentActivity, +} from "./types.ts"; + +export interface AgentCredentials { + apiKey: string; + baseUrl?: string; +} + +export interface CreateTaskParams { + prompt: string; + source: CloudAgentSource; + options: { + autoCreatePr?: boolean; + planApprovalRequired?: boolean; + environment?: Record; + }; +} + +export interface GetStatusResult { + status: CloudAgentStatus; + externalId?: string; + result?: CloudAgentResult; + activities: CloudAgentActivity[]; + error?: string; +} + +export abstract class CloudAgentBase { + abstract readonly providerId: string; + abstract readonly baseUrl: string; + + abstract createTask( + params: CreateTaskParams, + credentials: AgentCredentials + ): Promise; + + abstract getStatus(externalId: string, credentials: AgentCredentials): Promise; + + abstract approvePlan(externalId: string, credentials: AgentCredentials): Promise; + + abstract sendMessage( + externalId: string, + message: string, + credentials: AgentCredentials + ): Promise; + + abstract listSources( + credentials: AgentCredentials + ): Promise<{ name: string; url: string; branch?: string }[]>; + + protected mapStatus(status: string): CloudAgentStatus { + const statusLower = status.toLowerCase(); + + if (statusLower.includes("completed") || statusLower.includes("done")) { + return "completed"; + } + if (statusLower.includes("failed") || statusLower.includes("error")) { + return "failed"; + } + if (statusLower.includes("cancelled") || statusLower.includes("canceled")) { + return "cancelled"; + } + if ( + statusLower.includes("running") || + statusLower.includes("active") || + statusLower.includes("executing") + ) { + return "running"; + } + if ( + statusLower.includes("pending") || + statusLower.includes("queued") || + statusLower.includes("waiting") + ) { + return "queued"; + } + if (statusLower.includes("approval") || statusLower.includes("plan")) { + return "awaiting_approval"; + } + + return "queued"; + } + + protected generateTaskId(): string { + return `task_${Date.now()}_${Math.random().toString(36).substring(2, 11)}`; + } + + protected generateActivityId(): string { + return `act_${Date.now()}_${Math.random().toString(36).substring(2, 11)}`; + } +} diff --git a/src/lib/cloudAgent/db.ts b/src/lib/cloudAgent/db.ts new file mode 100644 index 0000000000..91667f5422 --- /dev/null +++ b/src/lib/cloudAgent/db.ts @@ -0,0 +1,145 @@ +import { getDbInstance } from "@/lib/db/core.ts"; + +export interface CloudAgentTaskRow { + id: string; + provider_id: string; + external_id: string | null; + status: string; + prompt: string; + source: string; + options: string; + result: string | null; + activities: string; + error: string | null; + created_at: string; + updated_at: string; + completed_at: string | null; +} + +export function createCloudAgentTaskTable(): void { + const db = getDbInstance(); + + db.exec(` + CREATE TABLE IF NOT EXISTS cloud_agent_tasks ( + id TEXT PRIMARY KEY, + provider_id TEXT NOT NULL, + external_id TEXT, + status TEXT NOT NULL DEFAULT 'queued', + prompt TEXT NOT NULL, + source TEXT NOT NULL, + options TEXT DEFAULT '{}', + result TEXT, + activities TEXT DEFAULT '[]', + error TEXT, + created_at TEXT NOT NULL DEFAULT (datetime('now')), + updated_at TEXT NOT NULL DEFAULT (datetime('now')), + completed_at TEXT + ) + `); + + db.exec(` + CREATE INDEX IF NOT EXISTS idx_cloud_agent_tasks_provider + ON cloud_agent_tasks(provider_id) + `); + + db.exec(` + CREATE INDEX IF NOT EXISTS idx_cloud_agent_tasks_status + ON cloud_agent_tasks(status) + `); + + db.exec(` + CREATE INDEX IF NOT EXISTS idx_cloud_agent_tasks_created + ON cloud_agent_tasks(created_at DESC) + `); +} + +export function insertCloudAgentTask(task: CloudAgentTaskRow): void { + const db = getDbInstance(); + db.prepare( + ` + INSERT INTO cloud_agent_tasks ( + id, provider_id, external_id, status, prompt, source, + options, result, activities, error, created_at, updated_at, completed_at + ) VALUES ( + @id, @provider_id, @external_id, @status, @prompt, @source, + @options, @result, @activities, @error, @created_at, @updated_at, @completed_at + ) + ` + ).run(task); +} + +// Whitelist of allowed columns for update operations +const ALLOWED_UPDATE_COLUMNS = new Set([ + "status", + "prompt", + "source", + "options", + "result", + "activities", + "error", + "completed_at", +]); + +export function updateCloudAgentTask( + id: string, + updates: Partial> +): void { + const db = getDbInstance(); + + // Validate keys against whitelist to prevent SQL injection + const validUpdates: Partial> = {}; + for (const [key, value] of Object.entries(updates)) { + if (ALLOWED_UPDATE_COLUMNS.has(key)) { + (validUpdates as Record)[key] = value; + } + } + + const fields = Object.keys(validUpdates) + .map((key) => `${key} = @${key}`) + .join(", "); + + if (!fields) return; // No valid updates + + db.prepare( + ` + UPDATE cloud_agent_tasks + SET ${fields}, updated_at = datetime('now') + WHERE id = @id + ` + ).run({ id, ...validUpdates }); +} + +export function getCloudAgentTaskById(id: string): CloudAgentTaskRow | null { + const db = getDbInstance(); + return db + .prepare("SELECT * FROM cloud_agent_tasks WHERE id = ?") + .get(id) as CloudAgentTaskRow | null; +} + +export function getCloudAgentTasksByProvider(providerId: string, limit = 50): CloudAgentTaskRow[] { + const db = getDbInstance(); + return db + .prepare( + "SELECT * FROM cloud_agent_tasks WHERE provider_id = ? ORDER BY created_at DESC LIMIT ?" + ) + .all(providerId, limit) as CloudAgentTaskRow[]; +} + +export function getCloudAgentTasksByStatus(status: string, limit = 50): CloudAgentTaskRow[] { + const db = getDbInstance(); + return db + .prepare("SELECT * FROM cloud_agent_tasks WHERE status = ? ORDER BY created_at DESC LIMIT ?") + .all(status, limit) as CloudAgentTaskRow[]; +} + +export function getAllCloudAgentTasks(limit = 100): CloudAgentTaskRow[] { + const db = getDbInstance(); + return db + .prepare("SELECT * FROM cloud_agent_tasks ORDER BY created_at DESC LIMIT ?") + .all(limit) as CloudAgentTaskRow[]; +} + +export function deleteCloudAgentTask(id: string): void { + const db = getDbInstance(); + db.prepare("DELETE FROM cloud_agent_tasks WHERE id = ?").run(id); +} diff --git a/src/lib/cloudAgent/index.ts b/src/lib/cloudAgent/index.ts new file mode 100644 index 0000000000..c8a23bf314 --- /dev/null +++ b/src/lib/cloudAgent/index.ts @@ -0,0 +1,8 @@ +export * from "./types.ts"; +export * from "./baseAgent.ts"; +export * from "./registry.ts"; +export * from "./db.ts"; + +import { createCloudAgentTaskTable } from "./db.ts"; + +createCloudAgentTaskTable(); diff --git a/src/lib/cloudAgent/registry.ts b/src/lib/cloudAgent/registry.ts new file mode 100644 index 0000000000..091359a400 --- /dev/null +++ b/src/lib/cloudAgent/registry.ts @@ -0,0 +1,25 @@ +import type { CloudAgentBase } from "./baseAgent.ts"; +import { JulesAgent } from "./agents/jules.ts"; +import { DevinAgent } from "./agents/devin.ts"; +import { CodexCloudAgent } from "./agents/codex.ts"; + +const AGENTS: Record = { + jules: new JulesAgent(), + devin: new DevinAgent(), + "codex-cloud": new CodexCloudAgent(), +}; + +export function getAgent(providerId: string): CloudAgentBase | null { + return AGENTS[providerId] || null; +} + +export function getAvailableAgents(): string[] { + return Object.keys(AGENTS); +} + +export function isCloudAgentProvider(providerId: string): boolean { + return providerId in AGENTS; +} + +export { JulesAgent, DevinAgent, CodexCloudAgent }; +export type { CloudAgentBase } from "./baseAgent.ts"; diff --git a/src/lib/cloudAgent/types.ts b/src/lib/cloudAgent/types.ts new file mode 100644 index 0000000000..13d7d398b0 --- /dev/null +++ b/src/lib/cloudAgent/types.ts @@ -0,0 +1,111 @@ +import { z } from "zod"; + +export const CLOUD_AGENT_STATUS = { + QUEUED: "queued", + RUNNING: "running", + AWAITING_APPROVAL: "awaiting_approval", + COMPLETED: "completed", + FAILED: "failed", + CANCELLED: "cancelled", +} as const; + +export type CloudAgentStatus = (typeof CLOUD_AGENT_STATUS)[keyof typeof CLOUD_AGENT_STATUS]; + +export const CloudAgentStatusSchema = z.enum([ + "queued", + "running", + "awaiting_approval", + "completed", + "failed", + "cancelled", +]); + +export interface CloudAgentSource { + repoName: string; + repoUrl: string; + branch?: string; +} + +export interface CloudAgentResult { + prUrl?: string; + prNumber?: number; + commitMessage?: string; + diffUrl?: string; + summary?: string; + duration?: number; + cost?: number; +} + +export interface CloudAgentActivity { + id: string; + type: "plan" | "command" | "code_change" | "message" | "error" | "completion"; + content: string; + timestamp: string; + metadata?: Record; +} + +export interface CloudAgentTask { + id: string; + providerId: "jules" | "devin" | "codex-cloud"; + externalId?: string; + status: CloudAgentStatus; + prompt: string; + source: CloudAgentSource; + options: { + autoCreatePr?: boolean; + planApprovalRequired?: boolean; + environment?: Record; + }; + result?: CloudAgentResult; + activities: CloudAgentActivity[]; + error?: string; + createdAt: string; + updatedAt: string; + completedAt?: string; +} + +export const CloudAgentSourceSchema = z.object({ + repoName: z.string().min(1), + repoUrl: z.string().url(), + branch: z.string().optional(), +}); + +export const CloudAgentResultSchema = z.object({ + prUrl: z.string().url().optional(), + prNumber: z.number().int().positive().optional(), + commitMessage: z.string().optional(), + diffUrl: z.string().url().optional(), + summary: z.string().optional(), + duration: z.number().int().positive().optional(), + cost: z.number().positive().optional(), +}); + +export const CloudAgentActivitySchema = z.object({ + id: z.string(), + type: z.enum(["plan", "command", "code_change", "message", "error", "completion"]), + content: z.string(), + timestamp: z.string().datetime(), + metadata: z.record(z.unknown()).optional(), +}); + +export const CloudAgentTaskOptionsSchema = z.object({ + autoCreatePr: z.boolean().optional(), + planApprovalRequired: z.boolean().optional(), + environment: z.record(z.string()).optional(), +}); + +export const CreateCloudAgentTaskSchema = z.object({ + providerId: z.enum(["jules", "devin", "codex-cloud"]), + prompt: z.string().min(1).max(10000), + source: CloudAgentSourceSchema, + options: CloudAgentTaskOptionsSchema.optional(), +}); + +export const UpdateCloudAgentTaskSchema = z.object({ + id: z.string().min(1), + action: z.enum(["approve", "reject", "cancel", "message"]), + message: z.string().optional(), +}); + +export type CreateCloudAgentTaskInput = z.infer; +export type UpdateCloudAgentTaskInput = z.infer; diff --git a/src/lib/db/migrations/041_session_account_affinity.sql b/src/lib/db/migrations/041_session_account_affinity.sql new file mode 100644 index 0000000000..5a93707fb3 --- /dev/null +++ b/src/lib/db/migrations/041_session_account_affinity.sql @@ -0,0 +1,11 @@ +CREATE TABLE IF NOT EXISTS session_account_affinity ( + session_key TEXT NOT NULL, + provider TEXT NOT NULL, + connection_id TEXT NOT NULL, + created_at INTEGER NOT NULL, + last_seen_at INTEGER NOT NULL, + PRIMARY KEY (session_key, provider) +); + +CREATE INDEX IF NOT EXISTS idx_saa_provider ON session_account_affinity(provider); +CREATE INDEX IF NOT EXISTS idx_saa_last_seen ON session_account_affinity(last_seen_at); diff --git a/src/lib/db/sessionAccountAffinity.ts b/src/lib/db/sessionAccountAffinity.ts index 80ba0a729d..dc63011a11 100644 --- a/src/lib/db/sessionAccountAffinity.ts +++ b/src/lib/db/sessionAccountAffinity.ts @@ -1,7 +1,49 @@ -// Stubbed functions for session account affinity (PR 1887 pending) +import { getDbInstance } from "./core"; -export function getSessionAccountAffinity(sessionKey: string, provider: string): any { - return null; +export interface SessionAccountAffinity { + sessionKey: string; + provider: string; + connectionId: string; + createdAt: number; + lastSeenAt: number; +} + +interface SessionAccountAffinityRow { + session_key: string; + provider: string; + connection_id: string; + created_at: number; + last_seen_at: number; +} + +const DEFAULT_TTL_MS = 30 * 60 * 1000; +const CLEANUP_INTERVAL_MS = 5 * 60 * 1000; + +let cleanupTimer: NodeJS.Timeout | null = null; + +function rowToAffinity(row: SessionAccountAffinityRow): SessionAccountAffinity { + return { + sessionKey: row.session_key, + provider: row.provider, + connectionId: row.connection_id, + createdAt: row.created_at, + lastSeenAt: row.last_seen_at, + }; +} + +export function getSessionAccountAffinity( + sessionKey: string, + provider: string +): SessionAccountAffinity | null { + const db = getDbInstance(); + const row = db + .prepare( + `SELECT session_key, provider, connection_id, created_at, last_seen_at + FROM session_account_affinity + WHERE session_key = ? AND provider = ?` + ) + .get(sessionKey, provider) as SessionAccountAffinityRow | undefined; + return row ? rowToAffinity(row) : null; } export function upsertSessionAccountAffinity( @@ -9,23 +51,72 @@ export function upsertSessionAccountAffinity( provider: string, connectionId: string, now: number = Date.now() -): void {} +): void { + const db = getDbInstance(); + db.prepare( + `INSERT INTO session_account_affinity + (session_key, provider, connection_id, created_at, last_seen_at) + VALUES (?, ?, ?, ?, ?) + ON CONFLICT(session_key, provider) DO UPDATE SET + connection_id = excluded.connection_id, + last_seen_at = excluded.last_seen_at` + ).run(sessionKey, provider, connectionId, now, now); +} export function touchSessionAccountAffinity( sessionKey: string, provider: string, now: number = Date.now() -): void {} - -export function deleteSessionAccountAffinity(sessionKey: string, provider: string): void {} - -export function cleanupStaleSessionAccountAffinities( - ttlMs: number = 30 * 60 * 1000, - now: number = Date.now() -): number { - return 0; +): void { + const db = getDbInstance(); + db.prepare( + `UPDATE session_account_affinity + SET last_seen_at = ? + WHERE session_key = ? AND provider = ?` + ).run(now, sessionKey, provider); } -export function startSessionAccountAffinityCleanup(): void {} +export function deleteSessionAccountAffinity(sessionKey: string, provider: string): void { + const db = getDbInstance(); + db.prepare("DELETE FROM session_account_affinity WHERE session_key = ? AND provider = ?").run( + sessionKey, + provider + ); +} -export function stopSessionAccountAffinityCleanupForTests(): void {} +export function cleanupStaleSessionAccountAffinities( + ttlMs: number = DEFAULT_TTL_MS, + now: number = Date.now() +): number { + const db = getDbInstance(); + const cutoff = now - ttlMs; + const result = db + .prepare("DELETE FROM session_account_affinity WHERE last_seen_at < ?") + .run(cutoff); + return Number(result.changes || 0); +} + +export function startSessionAccountAffinityCleanup(): void { + if (cleanupTimer) return; + + try { + cleanupStaleSessionAccountAffinities(); + } catch (error) { + console.warn("[SESSION_AFFINITY] Startup cleanup failed:", error); + } + + cleanupTimer = setInterval(() => { + try { + cleanupStaleSessionAccountAffinities(); + } catch (error) { + console.warn("[SESSION_AFFINITY] Periodic cleanup failed:", error); + } + }, CLEANUP_INTERVAL_MS); + cleanupTimer.unref?.(); +} + +export function stopSessionAccountAffinityCleanupForTests(): void { + if (!cleanupTimer) return; + clearInterval(cleanupTimer); + cleanupTimer = null; +} diff --git a/src/lib/db/settings.ts b/src/lib/db/settings.ts index 3c17d7d9bc..c76fd50dd9 100644 --- a/src/lib/db/settings.ts +++ b/src/lib/db/settings.ts @@ -271,24 +271,51 @@ export async function getPricingWithSources(): Promise<{ export async function getPricingForModel(provider: string, model: string) { const pricing = await getPricing(); - if (pricing[provider]?.[model]) return pricing[provider][model]; - const { PROVIDER_ID_TO_ALIAS } = await import("@omniroute/open-sse/config/providerModels"); - // Check if provider is an ID -> map to ALIAS - const alias = PROVIDER_ID_TO_ALIAS[provider]; - if (alias && pricing[alias]) return pricing[alias][model] || null; + const findKeyInsensitive = (obj: Record | undefined | null, key: string) => { + if (!obj || !key) return undefined; + const lowerKey = key.toLowerCase(); + for (const [k, v] of Object.entries(obj)) { + if (k.toLowerCase() === lowerKey) return v; + } + return undefined; + }; - // Check if provider is an ALIAS -> map to ID (search values) - for (const [id, mappedAlias] of Object.entries(PROVIDER_ID_TO_ALIAS)) { - if (mappedAlias === provider && pricing[id]?.[model]) { - return pricing[id][model]; + const pLower = (provider || "").toLowerCase(); + let providerPricing = findKeyInsensitive(pricing, pLower); + + if (!providerPricing) { + const alias = findKeyInsensitive(PROVIDER_ID_TO_ALIAS, pLower); + if (alias) providerPricing = findKeyInsensitive(pricing, alias); + } + + if (!providerPricing) { + for (const [id, mappedAlias] of Object.entries(PROVIDER_ID_TO_ALIAS)) { + if (typeof mappedAlias === "string" && mappedAlias.toLowerCase() === pLower) { + providerPricing = findKeyInsensitive(pricing, id); + if (providerPricing) break; + } } } - const np = provider?.replace(/-cn$/, ""); - if (np && np !== provider && pricing[np]) return pricing[np][model] || null; + if (!providerPricing) { + const np = pLower.replace(/-cn$/, ""); + if (np && np !== pLower) { + providerPricing = findKeyInsensitive(pricing, np); + } + } - return null; + if (!providerPricing) return null; + + const mLower = (model || "").toLowerCase(); + let modelPricing = findKeyInsensitive(providerPricing, mLower); + + if (!modelPricing) { + const hyphenModel = mLower.replace(/\./g, "-"); + modelPricing = findKeyInsensitive(providerPricing, hyphenModel); + } + + return modelPricing || null; } export async function updatePricing(pricingData: PricingByProvider) { diff --git a/src/lib/embeddings/service.ts b/src/lib/embeddings/service.ts index a3c5443687..41d8a0f1c6 100644 --- a/src/lib/embeddings/service.ts +++ b/src/lib/embeddings/service.ts @@ -15,7 +15,7 @@ import { getProviderNodes } from "@/lib/localDb"; type ValidatedEmbeddingBody = Record & { model: string }; -interface EmbeddingHandlerOptions { +export interface EmbeddingHandlerOptions { clientRawRequest?: { endpoint: string; body: Record; diff --git a/src/lib/localDb.ts b/src/lib/localDb.ts index efe96f3199..f3af94bc83 100755 --- a/src/lib/localDb.ts +++ b/src/lib/localDb.ts @@ -372,3 +372,13 @@ export { } from "./db/oneproxy"; export type { OneproxyProxyRecord, OneproxyStats } from "./db/oneproxy"; + +export { + getSessionAccountAffinity, + upsertSessionAccountAffinity, + touchSessionAccountAffinity, + deleteSessionAccountAffinity, + cleanupStaleSessionAccountAffinities, + startSessionAccountAffinityCleanup, + stopSessionAccountAffinityCleanupForTests, +} from "./db/sessionAccountAffinity"; diff --git a/src/lib/oauth/services/cursor.ts b/src/lib/oauth/services/cursor.ts index d460520879..2d1e5af620 100644 --- a/src/lib/oauth/services/cursor.ts +++ b/src/lib/oauth/services/cursor.ts @@ -143,8 +143,10 @@ export class CursorService { const decoded = JSON.parse( Buffer.from(payload.replace(/-/g, "+").replace(/_/g, "/"), "base64").toString() ); + const email = + typeof decoded.email === "string" && decoded.email.includes("@") ? decoded.email : null; return { - email: decoded.email || decoded.sub, + email, userId: decoded.sub || decoded.user_id, }; } @@ -155,6 +157,41 @@ export class CursorService { return null; } + /** + * Fetch real user profile from cursor.com using the same WorkOS-session cookie + * format that powers the dashboard. Returns null on any failure so the import + * flow can fall back to whatever it can extract from the JWT. + */ + async fetchUserInfo( + accessToken: string, + userId: string + ): Promise<{ email: string | null; name: string | null; sub: string | null } | null> { + if (!accessToken || !userId) return null; + try { + const response = await fetch("https://cursor.com/api/auth/me", { + method: "GET", + redirect: "manual", + headers: { + Cookie: `WorkosCursorSessionToken=${userId}::${accessToken}`, + Origin: "https://cursor.com", + Referer: "https://cursor.com/dashboard", + Accept: "application/json", + "User-Agent": getCursorUserAgent(this.config.clientVersion), + }, + }); + + if (!response.ok) return null; + const data = (await response.json()) as Record; + return { + email: typeof data.email === "string" ? data.email : null, + name: typeof data.name === "string" ? data.name : null, + sub: typeof data.sub === "string" ? data.sub : null, + }; + } catch { + return null; + } + } + /** * Get token storage path instructions for user */ diff --git a/src/lib/providers/catalog.ts b/src/lib/providers/catalog.ts index d50f21475a..16bd18723c 100644 --- a/src/lib/providers/catalog.ts +++ b/src/lib/providers/catalog.ts @@ -1,6 +1,7 @@ import { APIKEY_PROVIDERS, AUDIO_ONLY_PROVIDERS, + CLOUD_AGENT_PROVIDERS, FREE_PROVIDERS, LOCAL_PROVIDERS, OAUTH_PROVIDERS, @@ -21,7 +22,8 @@ export type StaticProviderCatalogCategory = | "search" | "audio" | "upstream-proxy" - | "apikey"; + | "apikey" + | "cloud-agent"; export interface ProviderCatalogMetadata { id: string; @@ -133,6 +135,12 @@ export const STATIC_PROVIDER_CATALOG_GROUPS: Record< displayAuthType: "apikey", toggleAuthType: "apikey", }, + "cloud-agent": { + category: "cloud-agent", + providers: CLOUD_AGENT_PROVIDERS as ProviderRecord, + displayAuthType: "apikey", + toggleAuthType: "apikey", + }, }; export const STATIC_PROVIDER_CATALOG_RESOLUTION_ORDER: StaticProviderCatalogCategory[] = [ @@ -143,6 +151,7 @@ export const STATIC_PROVIDER_CATALOG_RESOLUTION_ORDER: StaticProviderCatalogCate "search", "audio", "upstream-proxy", + "cloud-agent", "apikey", ]; diff --git a/src/lib/resilience/settings.ts b/src/lib/resilience/settings.ts index f6f65e8faf..23842e5f47 100644 --- a/src/lib/resilience/settings.ts +++ b/src/lib/resilience/settings.ts @@ -14,6 +14,17 @@ export interface RequestQueueSettings { export interface ConnectionCooldownProfileSettings { baseCooldownMs: number; useUpstreamRetryHints: boolean; + /** + * Issue #2100 follow-up: opt-in toggle for upstream 429 hint trust at the + * circuit-breaker cooldown layer (independent of `useUpstreamRetryHints` + * which controls retry scheduling). + * + * Stored shape is intentionally optional / `boolean | undefined`: when + * unset, the per-provider default from `providerHints.ts` applies. + * Normalize/merge MUST preserve `undefined` — do not coerce via + * `toBoolean(value, fallback)`. + */ + useUpstream429BreakerHints?: boolean; maxBackoffSteps: number; } @@ -155,7 +166,26 @@ function normalizeConnectionCooldownProfile( fallback: ConnectionCooldownProfileSettings ): ConnectionCooldownProfileSettings { const record = asRecord(next); - return { + // useUpstream429BreakerHints uses a 3-state input contract: + // - boolean → user override, store as-is + // - null → explicit unset sentinel, drop key so the per-provider + // default in `providerHints.ts` resolves at runtime + // - omitted → leave existing fallback value unchanged (partial-merge) + // Never coerce via `toBoolean(value, fallback)` because that would + // collapse the unset state. + const hasHintsKey = Object.prototype.hasOwnProperty.call(record, "useUpstream429BreakerHints"); + const rawHints = record.useUpstream429BreakerHints; + let useUpstream429BreakerHints: boolean | undefined; + if (!hasHintsKey) { + useUpstream429BreakerHints = fallback.useUpstream429BreakerHints; + } else if (rawHints === null) { + useUpstream429BreakerHints = undefined; + } else if (typeof rawHints === "boolean") { + useUpstream429BreakerHints = rawHints; + } else { + useUpstream429BreakerHints = fallback.useUpstream429BreakerHints; + } + const out: ConnectionCooldownProfileSettings = { baseCooldownMs: toInteger(record.baseCooldownMs, fallback.baseCooldownMs, { min: 0, max: 24 * 60 * 60 * 1000, @@ -166,6 +196,11 @@ function normalizeConnectionCooldownProfile( max: 32, }), }; + // Only attach the key when defined — preserves omission across round-trips. + if (useUpstream429BreakerHints !== undefined) { + out.useUpstream429BreakerHints = useUpstream429BreakerHints; + } + return out; } function normalizeLegacyConnectionCooldownProfile( diff --git a/src/lib/usage/providerLimits.ts b/src/lib/usage/providerLimits.ts index df189ceb5a..26d83fff16 100644 --- a/src/lib/usage/providerLimits.ts +++ b/src/lib/usage/providerLimits.ts @@ -47,6 +47,7 @@ interface ProviderConnectionLike { const PROVIDER_LIMITS_APIKEY_PROVIDERS = new Set([ "glm", "glm-cn", + "zai", "glmt", "minimax", "minimax-cn", @@ -297,7 +298,9 @@ async function fetchLiveProviderLimitsWithOptions( connection: ProviderConnectionLike; usage: JsonRecord; }> { - let connection = (await getProviderConnectionById(connectionId)) as ProviderConnectionLike | null; + let connection = (await getProviderConnectionById( + connectionId + )) as unknown as ProviderConnectionLike | null; if (!connection) { throw withStatus(new Error("Connection not found"), 404); } @@ -435,7 +438,7 @@ export async function syncAllProviderLimits( }> { const { source = "manual", concurrency = 5 } = options; const connections = ( - (await getProviderConnections({ isActive: true })) as ProviderConnectionLike[] + (await getProviderConnections({ isActive: true })) as unknown as ProviderConnectionLike[] ).filter(isSupportedUsageConnection); const cacheEntries: Array<{ connectionId: string; entry: ProviderLimitsCacheEntry }> = []; const caches: Record = {}; diff --git a/src/mitm/cert/install.ts b/src/mitm/cert/install.ts index 4f6a100aa1..97d0f11d22 100644 --- a/src/mitm/cert/install.ts +++ b/src/mitm/cert/install.ts @@ -122,7 +122,16 @@ async function installCertLinux(sudoPassword: string, certPath: string): Promise try { await execFileWithPassword("sudo", ["-S", "mkdir", "-p", LINUX_CA_DIR], sudoPassword); await execFileWithPassword("sudo", ["-S", "cp", certPath, LINUX_CERT_DEST], sudoPassword); - await execFileWithPassword("sudo", ["-S", "update-ca-certificates"], sudoPassword); + await execFileWithPassword( + "sudo", + [ + "-S", + "sh", + "-c", + "update-ca-certificates 2>/dev/null || update-ca-trust 2>/dev/null || true", + ], + sudoPassword + ); } catch (error) { const message = getErrorMessage(error); const msg = message.includes("canceled") @@ -186,7 +195,16 @@ async function uninstallCertLinux(sudoPassword: string, certPath: string): Promi if (fs.existsSync(LINUX_CERT_DEST)) { await execFileWithPassword("sudo", ["-S", "rm", "-f", LINUX_CERT_DEST], sudoPassword); } - await execFileWithPassword("sudo", ["-S", "update-ca-certificates", "--fresh"], sudoPassword); + await execFileWithPassword( + "sudo", + [ + "-S", + "sh", + "-c", + "update-ca-certificates --fresh 2>/dev/null || update-ca-trust 2>/dev/null || true", + ], + sudoPassword + ); } catch (err) { throw new Error("Failed to uninstall certificate"); } diff --git a/src/server/authz/classify.ts b/src/server/authz/classify.ts index 6093714baa..60128281c2 100644 --- a/src/server/authz/classify.ts +++ b/src/server/authz/classify.ts @@ -53,6 +53,14 @@ export function classifyRoute(rawPath: string, method: string = "GET"): RouteCla }; } + if (normalizedPath === "/dashboard/onboarding") { + return { + routeClass: "PUBLIC", + reason: "setup_wizard", + normalizedPath, + }; + } + if (normalizedPath.startsWith("/dashboard")) { return { routeClass: "MANAGEMENT", diff --git a/src/server/authz/types.ts b/src/server/authz/types.ts index a8fd786408..443001dbca 100644 --- a/src/server/authz/types.ts +++ b/src/server/authz/types.ts @@ -28,7 +28,9 @@ export type ClassificationReason = | "public_prefix" | "public_readonly_prefix" | "dashboard_prefix" + | "setup_wizard" | "client_api_v1" + | "client_api_mcp" | "client_api_alias" | "client_api_codex_alias" | "client_api_double_prefix" diff --git a/src/shared/components/Card.tsx b/src/shared/components/Card.tsx index be782cde92..f78f8abdde 100644 --- a/src/shared/components/Card.tsx +++ b/src/shared/components/Card.tsx @@ -65,8 +65,12 @@ export default function Card({ ); } +interface CardSectionProps extends React.HTMLAttributes { + children?: React.ReactNode; +} + // Sub-component: Bordered section inside Card -Card.Section = function CardSection({ children, className, ...props }) { +Card.Section = function CardSection({ children, className, ...props }: CardSectionProps) { return (
{ + children?: React.ReactNode; +} + // Sub-component: Hoverable row inside Card -Card.Row = function CardRow({ children, className, ...props }) { +Card.Row = function CardRow({ children, className, ...props }: CardRowProps) { return (
{ + children?: React.ReactNode; + actions?: React.ReactNode; +} + // Sub-component: List item with hover actions (macOS style) -Card.ListItem = function CardListItem({ children, actions, className, ...props }) { +Card.ListItem = function CardListItem({ + children, + actions, + className, + ...props +}: CardListItemProps) { return (
void) | null; isFailure?: (error: unknown) => boolean; + /** + * Per-failure-kind cooldown override (Issue #2100). + * + * When set, `_timeUntilReset()` and `_shouldAttemptReset()` use + * `cooldownByKind[lastFailureKind]` instead of `resetTimeout` whenever + * the last failure had a known kind. Use this to give a longer cooldown + * to `quota_exhausted` (period-end may be hours away) than to + * `rate_limit` (typically 60s). + */ + cooldownByKind?: Partial>; + /** + * Optional classifier called on `execute()` errors (Issue #2100). + * Returns the kind to record. When omitted, all failures are recorded + * as `lastFailureKind = null` (existing behavior preserved). + * + * Pair with `classify429()` from `./classify429.ts` for HTTP responses, + * or supply a custom classifier for non-HTTP errors. + */ + classifyError?: (error: unknown) => FailureKind | undefined; } export class CircuitBreaker { @@ -48,6 +68,9 @@ export class CircuitBreaker { successCount: number; lastFailureTime: number | null; halfOpenAllowed: number; + cooldownByKind: Partial>; + classifyError: ((error: unknown) => FailureKind | undefined) | null; + lastFailureKind: FailureKind | null; constructor(name: string, options: CircuitBreakerOptions = {}) { this.name = name; @@ -62,6 +85,9 @@ export class CircuitBreaker { this.successCount = 0; this.lastFailureTime = null; this.halfOpenAllowed = 0; + this.cooldownByKind = options.cooldownByKind ?? {}; + this.classifyError = options.classifyError ?? null; + this.lastFailureKind = null; // Try to restore state from DB this._restoreFromDb(); @@ -151,7 +177,17 @@ export class CircuitBreaker { return result; } catch (error) { if (this.isFailure(error)) { - this._onFailure(); + let kind: FailureKind | undefined; + if (this.classifyError) { + try { + kind = this.classifyError(error); + } catch { + // A user-supplied classifier must not mask the original error + // or change failure-counting semantics; fall back to no kind. + kind = undefined; + } + } + this._onFailure(kind); } throw error; } @@ -205,6 +241,7 @@ export class CircuitBreaker { this.failureCount = 0; this.successCount = 0; this.lastFailureTime = null; + this.lastFailureKind = null; this._persistToDb(); } @@ -218,10 +255,12 @@ export class CircuitBreaker { this.failureCount = 0; this.successCount = 0; this.lastFailureTime = null; + this.lastFailureKind = null; } else if (this.state === STATE.HALF_OPEN) { this.successCount++; this._transition(STATE.CLOSED); this.failureCount = 0; + this.lastFailureKind = null; } else { // In CLOSED state, just reset failure count this.failureCount = 0; @@ -229,9 +268,10 @@ export class CircuitBreaker { this._persistToDb(); } - _onFailure() { + _onFailure(kind?: FailureKind | null) { this.failureCount++; this.lastFailureTime = Date.now(); + this.lastFailureKind = kind ?? null; if (this.state === STATE.OPEN) { // Already OPEN — just update persistence (re-tripped by combo path) @@ -245,12 +285,31 @@ export class CircuitBreaker { _shouldAttemptReset() { if (!this.lastFailureTime) return true; - return Date.now() - this.lastFailureTime >= this.resetTimeout; + const cooldown = this._effectiveCooldown(); + return Date.now() - this.lastFailureTime >= cooldown; + } + + /** + * Resolve the cooldown for the current `lastFailureKind`. Falls back to + * `resetTimeout` when no kind was recorded, no override exists for it, + * or the override is not a finite non-negative number (NaN / Infinity / + * negative all silently fall through to `resetTimeout`). + * @private + */ + _effectiveCooldown() { + if (this.lastFailureKind !== null) { + const override = this.cooldownByKind[this.lastFailureKind]; + if (typeof override === "number" && Number.isFinite(override) && override >= 0) { + return override; + } + } + return this.resetTimeout; } _timeUntilReset() { if (!this.lastFailureTime) return 0; - return Math.max(0, this.resetTimeout - (Date.now() - this.lastFailureTime)); + const cooldown = this._effectiveCooldown(); + return Math.max(0, cooldown - (Date.now() - this.lastFailureTime)); } _refreshOpenState() { @@ -315,6 +374,18 @@ export function getCircuitBreaker(name: string, options?: CircuitBreakerOptions) if (typeof options.isFailure === "function") { breaker.isFailure = options.isFailure; } + if (options.cooldownByKind) { + // Merge keys, don't replace: callers that add different kinds + // (e.g. one sets `quota_exhausted`, another `rate_limit`) should + // not silently lose each other's overrides. + breaker.cooldownByKind = { + ...breaker.cooldownByKind, + ...options.cooldownByKind, + }; + } + if (typeof options.classifyError === "function") { + breaker.classifyError = options.classifyError; + } breaker._persistToDb(); } return breaker; diff --git a/src/shared/utils/classify429.ts b/src/shared/utils/classify429.ts new file mode 100644 index 0000000000..df0c8ea027 --- /dev/null +++ b/src/shared/utils/classify429.ts @@ -0,0 +1,243 @@ +/** + * 429 response classifier — distinguish rate-limit from quota-exhausted. + * + * Most LLM providers return HTTP 429 for two semantically different reasons: + * + * 1. **Rate-limit**: short transient back-off ("too many requests in + * the last minute"). Fix: wait the Retry-After window and retry. + * 2. **Quota-exhausted**: long-period cap hit ("daily/monthly limit + * reached"). Fix: wait until the period rolls over (could be hours + * or days). Retrying every 60s wastes calls and burns alerts. + * + * The HTTP status alone cannot disambiguate. This helper inspects the + * response body and headers to return a `FailureKind` the circuit + * breaker can use to pick the right cooldown. + * + * Companion to OmniRoute issue #2100. + * + * @module shared/utils/classify429 + */ + +export type FailureKind = "rate_limit" | "quota_exhausted" | "transient"; + +/** + * Heuristic regexes for "explicit quota exhausted" vs "rate-limited" + * detection in 429 error bodies. A 429 alone never implies quota + * exhausted — only an explicit keyword does. + * + * Patterns observed across OpenAI, Anthropic, Groq, Cerebras, Mistral, + * Google Gemini, and OpenRouter free-tier responses. + */ +const QUOTA_PATTERNS: ReadonlyArray = [ + /daily.*limit/i, + /daily.*quota/i, + /per.?day.*limit/i, + /monthly.*limit/i, + /monthly.*quota/i, + /per.?month.*limit/i, + /quota.*exceed/i, + /exceed.*quota/i, + /insufficient.*quota/i, + /billing.*cap/i, + /credit.*exhaust/i, + /out of credits/i, + /hard.?limit/i, + /plan.*limit/i, +]; + +/** + * Best-effort case-insensitive header lookup. + */ +function getHeader(headers: Record | undefined, name: string): string | undefined { + if (!headers) return undefined; + const target = name.toLowerCase(); + for (const [k, v] of Object.entries(headers)) { + if (k.toLowerCase() === target) return v; + } + return undefined; +} + +/** + * Coerce a body of unknown shape to a string for keyword scanning. + * - string: returned as-is + * - object: JSON-stringified (so nested error.message gets scanned) + * - undefined/null: empty string + */ +function bodyToText(body: unknown): string { + if (typeof body === "string") return body; + if (body == null) return ""; + try { + return JSON.stringify(body); + } catch { + return ""; + } +} + +/** + * Returns true if the body looks like an explicit quota-exhausted + * error — i.e. the upstream is telling us a long-period cap was hit. + */ +export function looksLikeQuotaExhausted(body: unknown): boolean { + const text = bodyToText(body); + if (!text) return false; + return QUOTA_PATTERNS.some((pat) => pat.test(text)); +} + +/** + * Classify a 429 (or any) response into a `FailureKind`. + * + * Decision order: + * 1. status !== 429 → `"transient"` (don't pretend to know more than + * the caller does about non-429 failures). + * 2. body matches a quota keyword → `"quota_exhausted"`. + * 3. otherwise → `"rate_limit"` (default for 429 — even without + * Retry-After, a 429 is per definition a rate-limit signal). + * + * @param response - the upstream response with status, optional headers, + * optional body. Headers are looked up + * case-insensitively. + */ +export function classify429(response: { + status: number; + headers?: Record; + body?: unknown; +}): FailureKind { + if (response.status !== 429) return "transient"; + if (looksLikeQuotaExhausted(response.body)) return "quota_exhausted"; + return "rate_limit"; +} + +/** + * Parse a `Retry-After` header value into seconds. + * + * Accepts: + * - integer seconds: `"60"` + * - HTTP date: `"Wed, 08 May 2026 03:00:00 GMT"` + * - Groq-style relative: `"60s"`, `"5m"`, `"2h"` + * + * Returns `null` if unparseable. + * + * Note: integer seconds vs Groq relative units are easy to confuse — + * `parseInt("5m", 10)` returns `5` (parses leading digits and ignores + * trailing). This helper checks the relative-unit pattern FIRST. + */ +export function parseRetryAfter(headerValue: string | undefined): number | null { + if (!headerValue) return null; + const trimmed = headerValue.trim(); + if (!trimmed) return null; + + // Groq-style relative: must check BEFORE plain int parse. + const relMatch = trimmed.match(/^(\d+)([smh])$/i); + if (relMatch) { + const n = Number(relMatch[1]); + const unit = relMatch[2].toLowerCase(); + if (Number.isFinite(n)) { + if (unit === "s") return n; + if (unit === "m") return n * 60; + if (unit === "h") return n * 3600; + } + } + + // Pure integer seconds. + if (/^\d+$/.test(trimmed)) { + const n = Number(trimmed); + return Number.isFinite(n) ? n : null; + } + + // HTTP date. + const ts = Date.parse(trimmed); + if (Number.isFinite(ts)) { + return Math.max(0, Math.floor((ts - Date.now()) / 1000)); + } + + return null; +} + +/** + * Convenience wrapper: pull the Retry-After from a response's headers + * and parse it to seconds. Returns null if absent or unparseable. + */ +export function retryAfterFromResponse(response: { + headers?: Record; +}): number | null { + return parseRetryAfter(getHeader(response.headers, "retry-after")); +} + +/** + * Normalize an unknown headers-like value into a plain `Record`. + * Native `Headers` (from `fetch`) does NOT respond to `Object.entries` — it + * exposes `.entries()` instead. Without this normalization, `getHeader` would + * silently miss every header on a Headers instance. + */ +function normalizeHeaders(raw: unknown): Record | undefined { + if (raw === null || typeof raw !== "object") return undefined; + const maybeIter = (raw as { entries?: unknown }).entries; + if (typeof maybeIter === "function") { + try { + return Object.fromEntries((raw as { entries: () => Iterable<[string, string]> }).entries()); + } catch { + // fall through to plain-object treatment + } + } + return raw as Record; +} + +/** + * Adapter that takes an error thrown by an HTTP client (fetch wrapper, axios, + * upstream SDK, etc.) and produces a {@link FailureKind} suitable for the + * `classifyError` option of the circuit breaker. + * + * Recognises the common error shapes: + * - `err.status` + `err.headers` + `err.body` (low-level fetch wrapper) + * - `err.response.status` + `err.response.headers` + `err.response.data` (axios-style) + * - `err.message` (last-resort body for keyword scan) + * + * Returns `undefined` when the error doesn't carry enough information to + * classify, so the breaker can decide what to do without a kind tag. + * + * Companion to issue #2100 follow-up. + */ +export function classify429FromError(err: unknown): FailureKind | undefined { + if (err === null || typeof err !== "object") return undefined; + const e = err as Record; + + let status: number | undefined; + let headers: Record | undefined; + let body: unknown; + + if (typeof e.status === "number") { + status = e.status; + } + if (typeof e.statusCode === "number" && status === undefined) { + status = e.statusCode; + } + + if (e.response && typeof e.response === "object") { + const resp = e.response as Record; + if (typeof resp.status === "number" && status === undefined) { + status = resp.status; + } + if (resp.headers && typeof resp.headers === "object") { + headers = normalizeHeaders(resp.headers); + } + if (resp.data !== undefined) { + body = resp.data; + } else if (typeof resp.body !== "undefined") { + body = resp.body; + } + } + + if (headers === undefined && e.headers && typeof e.headers === "object") { + headers = normalizeHeaders(e.headers); + } + if (body === undefined) { + if (typeof e.body !== "undefined") { + body = e.body; + } else if (typeof e.message === "string") { + body = e.message; + } + } + + if (typeof status !== "number") return undefined; + return classify429({ status, headers, body }); +} diff --git a/src/shared/utils/providerHints.ts b/src/shared/utils/providerHints.ts new file mode 100644 index 0000000000..e5a375575b --- /dev/null +++ b/src/shared/utils/providerHints.ts @@ -0,0 +1,73 @@ +/** + * Per-provider default policy for upstream 429 hint trust. + * + * @see Issue #2100 follow-up — surface a user-overridable per-profile toggle + * that decides whether the circuit breaker uses upstream 429 body / Retry-After + * hints (`classify429`, `cooldownByKind`) to differentiate rate-limit from + * quota-exhausted failure cooldowns. + * + * This helper returns the **default** answer for a given provider. The actual + * runtime decision is the user override (if any) OR this default. See + * `accountFallback.ts` / `chat.ts` / `chatHelpers.ts` for the resolution + * call sites: + * + * ```ts + * const userValue = providerProfile.useUpstream429BreakerHints; // boolean | undefined + * const useHints = userValue !== undefined + * ? userValue + * : defaultUseUpstream429BreakerHints(provider); + * ``` + * + * Default policy: direct cloud providers default `true` because their 429 + * bodies and `Retry-After` headers are authoritative. Reverse-proxy / + * self-hosted / CLI-backed providers default `false` because forwarded 429 + * metadata is often unreliable or fabricated by the proxy. + * + * @module shared/utils/providerHints + */ + +import { + UPSTREAM_PROXY_PROVIDERS, + SELF_HOSTED_CHAT_PROVIDER_IDS, + isLocalProvider, + isClaudeCodeCompatibleProvider, +} from "../constants/providers"; + +/** + * Conservative per-provider default for `useUpstream429BreakerHints`. + * + * Returns `false` for any provider whose 429 metadata may be forwarded by + * an intermediary (proxy, self-hosted runtime, CLI wrapper). Returns `true` + * for direct cloud providers where the upstream response is authoritative. + */ +export function defaultUseUpstream429BreakerHints(providerId: string): boolean { + if (Object.prototype.hasOwnProperty.call(UPSTREAM_PROXY_PROVIDERS, providerId)) { + return false; + } + if (isLocalProvider(providerId)) { + return false; + } + if (SELF_HOSTED_CHAT_PROVIDER_IDS.has(providerId)) { + return false; + } + if (isClaudeCodeCompatibleProvider(providerId)) { + return false; + } + return true; +} + +/** + * Resolve the effective `useHints` decision: the user override wins if set, + * otherwise fall back to the per-provider default. + * + * `undefined` means "not user-set" and triggers the default lookup. + */ +export function resolveUseUpstream429BreakerHints( + providerId: string, + userValue: boolean | undefined +): boolean { + if (userValue !== undefined) { + return userValue; + } + return defaultUseUpstream429BreakerHints(providerId); +} diff --git a/src/shared/utils/runtimeTimeouts.ts b/src/shared/utils/runtimeTimeouts.ts index 672466a1c2..14e0e67afb 100644 --- a/src/shared/utils/runtimeTimeouts.ts +++ b/src/shared/utils/runtimeTimeouts.ts @@ -11,7 +11,7 @@ export const DEFAULT_STREAM_IDLE_TIMEOUT_MS = 600_000; export const DEFAULT_STREAM_READINESS_TIMEOUT_MS = 30_000; export const DEFAULT_FETCH_CONNECT_TIMEOUT_MS = 30_000; export const DEFAULT_FETCH_KEEPALIVE_TIMEOUT_MS = 4_000; -export const DEFAULT_API_BRIDGE_PROXY_TIMEOUT_MS = 30_000; +export const DEFAULT_API_BRIDGE_PROXY_TIMEOUT_MS = 600_000; export const DEFAULT_API_BRIDGE_SERVER_REQUEST_TIMEOUT_MS = 300_000; export const DEFAULT_API_BRIDGE_SERVER_HEADERS_TIMEOUT_MS = 60_000; export const DEFAULT_API_BRIDGE_SERVER_KEEPALIVE_TIMEOUT_MS = 5_000; diff --git a/src/shared/validation/schemas.ts b/src/shared/validation/schemas.ts index ae5aeb25cb..6dba0a55dc 100644 --- a/src/shared/validation/schemas.ts +++ b/src/shared/validation/schemas.ts @@ -775,6 +775,11 @@ const connectionCooldownProfileSchema = z .object({ baseCooldownMs: z.number().int().min(0).optional(), useUpstreamRetryHints: z.boolean().optional(), + // Issue #2100 follow-up: per-profile toggle for upstream 429 hint trust. + // `null` is an explicit unset sentinel — PATCH handler deletes the key + // from stored settings so the per-provider default resolves at runtime. + // `undefined` (key omitted) means "leave existing value unchanged". + useUpstream429BreakerHints: z.boolean().nullable().optional(), maxBackoffSteps: z.number().int().min(0).optional(), }) .strict(); diff --git a/src/sse/handlers/chat.ts b/src/sse/handlers/chat.ts index 377f808449..e816960249 100644 --- a/src/sse/handlers/chat.ts +++ b/src/sse/handlers/chat.ts @@ -3,6 +3,8 @@ import { getProviderCredentialsWithQuotaPreflight, markAccountUnavailable, extractApiKey, + isValidApiKey, + extractSessionAffinityKey, } from "../services/auth"; import { getRuntimeProviderProfile, @@ -44,6 +46,8 @@ import { } from "./chatHelpers"; // Pipeline integration — wired modules +import { classify429FromError, type FailureKind } from "@/shared/utils/classify429"; +import { resolveUseUpstream429BreakerHints } from "@/shared/utils/providerHints"; import { getCircuitBreaker } from "../../shared/utils/circuitBreaker"; import { markAccountExhaustedFrom429 } from "../../domain/quotaCache"; import { RequestTelemetry, recordTelemetry } from "../../shared/utils/requestTelemetry"; @@ -209,6 +213,7 @@ export async function handleChat(request: any, clientRawRequest: any = null) { // T04: client-provided external session header has priority over generated fingerprint. const externalSessionId = extractExternalSessionId(request.headers); const sessionId = externalSessionId || generateStableSessionId(body); + const sessionAffinityKey = extractSessionAffinityKey(body, request.headers) || sessionId; const requestedConnectionId = request.headers.get("x-omniroute-connection")?.trim() || null; if (sessionId) { touchSession(sessionId); @@ -414,6 +419,7 @@ export async function handleChat(request: any, clientRawRequest: any = null) { allowedConnections, resolvedModel, { + sessionKey: sessionAffinityKey, ...(target?.connectionId ? { forcedConnectionId: target.connectionId } : {}), } ); @@ -457,6 +463,7 @@ export async function handleChat(request: any, clientRawRequest: any = null) { telemetry, { sessionId, + sessionAffinityKey, forceLiveComboTest: isComboLiveTest, forcedConnectionId: target?.connectionId ?? null, allowedConnectionIds: target?.allowedConnectionIds ?? null, @@ -507,7 +514,12 @@ export async function handleChat(request: any, clientRawRequest: any = null) { combo.name, apiKeyInfo, telemetry, - { sessionId, emergencyFallbackTried: true, forceLiveComboTest: isComboLiveTest }, + { + sessionId, + sessionAffinityKey, + emergencyFallbackTried: true, + forceLiveComboTest: isComboLiveTest, + }, combo.strategy, true ); @@ -543,6 +555,7 @@ export async function handleChat(request: any, clientRawRequest: any = null) { telemetry, { sessionId, + sessionAffinityKey, forceLiveComboTest: isComboLiveTest, forcedConnectionId: requestedConnectionId, }, @@ -581,6 +594,7 @@ async function handleSingleModelChat( emergencyFallbackTried?: boolean; forceLiveComboTest?: boolean; sessionId?: string | null; + sessionAffinityKey?: string | null; forcedConnectionId?: string | null; allowedConnectionIds?: string[] | null; comboStepId?: string | null; @@ -672,11 +686,25 @@ async function handleSingleModelChat( }); if (gate) return gate; + // Issue #2100 follow-up: opt-in upstream 429 hint trust per provider. + const useHints429 = resolveUseUpstream429BreakerHints( + provider, + (providerProfile as { useUpstream429BreakerHints?: boolean }).useUpstream429BreakerHints + ); const breaker = getCircuitBreaker(provider, { failureThreshold: providerProfile.failureThreshold, resetTimeout: providerProfile.resetTimeoutMs, onStateChange: (name: string, from: string, to: string) => log.info("CIRCUIT", `${name}: ${from} → ${to}`), + ...(useHints429 + ? { + cooldownByKind: { + rate_limit: 60_000, + quota_exhausted: 3_600_000, + } satisfies Partial>, + classifyError: classify429FromError, + } + : {}), }); const userAgent = request?.headers?.get("user-agent") || ""; @@ -727,6 +755,7 @@ async function handleSingleModelChat( effectiveAllowedConnections, model, { + sessionKey: runtimeOptions.sessionAffinityKey ?? runtimeOptions.sessionId ?? null, excludeConnectionIds: Array.from(excludedConnectionIds), ...(forceLiveComboTest ? { @@ -918,6 +947,25 @@ async function handleSingleModelChat( return result.response; } + if (result.errorType === "account_semaphore_capacity") { + // Local concurrency pressure is not an upstream quota failure. Prefer another + // account when possible; pinned combo steps fall through to combo orchestration. + if (hasForcedConnection) { + return result.response; + } + + log.warn( + "AUTH", + `Account ${accountId}... at local concurrency cap, trying fallback account` + ); + excludedConnectionIds.add(credentials.connectionId); + lastError = result.error; + lastStatus = result.status; + requestRetryLastError = result.error; + requestRetryLastStatus = result.status; + continue; + } + // Emergency fallback for budget exhaustion (402 / billing / quota keywords): // reroute to a free model (default provider/model: nvidia + openai/gpt-oss-120b) exactly once. if (!runtimeOptions.emergencyFallbackTried) { diff --git a/src/sse/handlers/chatHelpers.ts b/src/sse/handlers/chatHelpers.ts index 3792a2b26a..fdac283a01 100644 --- a/src/sse/handlers/chatHelpers.ts +++ b/src/sse/handlers/chatHelpers.ts @@ -25,6 +25,9 @@ import { } from "@omniroute/open-sse/utils/proxyFetch.ts"; import { resolveProxyForConnection } from "@/lib/localDb"; import { CircuitBreakerOpenError, getCircuitBreaker } from "../../shared/utils/circuitBreaker"; +import { classify429FromError, type FailureKind } from "../../shared/utils/classify429"; +import { resolveUseUpstream429BreakerHints } from "../../shared/utils/providerHints"; + import { logProxyEvent } from "../../lib/proxyLogger"; import { logTranslationEvent } from "../../lib/translatorEvents"; import { getRuntimeProviderProfile } from "@omniroute/open-sse/services/accountFallback.ts"; @@ -238,11 +241,25 @@ export async function checkPipelineGates( ) { const bypassReason = options.bypassReason || "pipeline override"; const providerProfile = options.providerProfile ?? (await getRuntimeProviderProfile(provider)); + // Issue #2100 follow-up: opt-in upstream 429 hint trust per provider. + const useHints429 = resolveUseUpstream429BreakerHints( + provider, + (providerProfile as { useUpstream429BreakerHints?: boolean }).useUpstream429BreakerHints + ); const breaker = getCircuitBreaker(provider, { failureThreshold: providerProfile.failureThreshold ?? providerProfile.circuitBreakerThreshold, resetTimeout: providerProfile.resetTimeoutMs ?? providerProfile.circuitBreakerReset, onStateChange: (name: string, from: string, to: string) => log.info("CIRCUIT", `${name}: ${from} → ${to}`), + ...(useHints429 + ? { + cooldownByKind: { + rate_limit: 60_000, + quota_exhausted: 3_600_000, + } satisfies Partial>, + classifyError: classify429FromError, + } + : {}), }); if (options.ignoreCircuitBreaker && !breaker.canExecute()) { log.info("CIRCUIT", `Bypassing OPEN circuit breaker for ${provider} (${bypassReason})`); diff --git a/tests/unit/account-fallback-service.test.ts b/tests/unit/account-fallback-service.test.ts index 4d0d9e5a77..d3dac846d1 100644 --- a/tests/unit/account-fallback-service.test.ts +++ b/tests/unit/account-fallback-service.test.ts @@ -759,3 +759,58 @@ test("recordModelLockoutFailure uses regular backoff for non-quota reasons", () clearModelLock("modelscope", "test-conn-modelscope-2", "qwen/Qwen2.5-Coder-32B-Instruct"); } }); + +// Test for hour quota related error messages +test("checkFallbackError classifies hour quota errors correctly", () => { + // For OAuth providers (e.g., codex), hour quota errors should be QUOTA_EXHAUSTED + const result1 = checkFallbackError( + 429, + "Coding Plan hour quota has been exceeded", + 0, + null, + "codex" + ); + assert.equal(result1.shouldFallback, true); + assert.equal(result1.reason, RateLimitReason.QUOTA_EXHAUSTED); + + const result2 = checkFallbackError(429, "hour quota exceeded", 0, null, "codex"); + assert.equal(result2.shouldFallback, true); + assert.equal(result2.reason, RateLimitReason.QUOTA_EXHAUSTED); + + const result3 = checkFallbackError(429, "Your hour quota is exceeded", 0, null, "codex"); + assert.equal(result3.shouldFallback, true); + assert.equal(result3.reason, RateLimitReason.QUOTA_EXHAUSTED); + + const result4 = checkFallbackError(429, "hour quota depleted", 0, null, "codex"); + assert.equal(result4.shouldFallback, true); + assert.equal(result4.reason, RateLimitReason.QUOTA_EXHAUSTED); + + // For API-key providers with 402 status, hour quota errors should be QUOTA_EXHAUSTED + const result5 = checkFallbackError(402, "hour quota has been exceeded", 0, null, "openai"); + assert.equal(result5.shouldFallback, true); + assert.equal(result5.reason, RateLimitReason.QUOTA_EXHAUSTED); + + const result6 = checkFallbackError( + 403, + "Coding Plan hour quota has been exceeded", + 0, + null, + "openai" + ); + assert.equal(result6.shouldFallback, true); + assert.equal(result6.reason, RateLimitReason.QUOTA_EXHAUSTED); +}); + +// Test for classifyErrorText function with hour quota +test("classifyErrorText handles hour quota messages", () => { + const { classifyErrorText } = accountFallback; + + assert.equal( + classifyErrorText("Coding Plan hour quota has been exceeded"), + RateLimitReason.QUOTA_EXHAUSTED + ); + assert.equal(classifyErrorText("hour quota exceeded"), RateLimitReason.QUOTA_EXHAUSTED); + assert.equal(classifyErrorText("Your hour quota is exceeded"), RateLimitReason.QUOTA_EXHAUSTED); + assert.equal(classifyErrorText("hour quota has been exceeded"), RateLimitReason.QUOTA_EXHAUSTED); + assert.equal(classifyErrorText("quota has been exceeded"), RateLimitReason.QUOTA_EXHAUSTED); +}); diff --git a/tests/unit/audio-speech-handler.test.ts b/tests/unit/audio-speech-handler.test.ts index 0cd3f39ead..49d24998c9 100644 --- a/tests/unit/audio-speech-handler.test.ts +++ b/tests/unit/audio-speech-handler.test.ts @@ -2,6 +2,7 @@ import test from "node:test"; import assert from "node:assert/strict"; const { handleAudioSpeech } = await import("../../open-sse/handlers/audioSpeech.ts"); +const { AUDIO_SPEECH_PROVIDERS } = await import("../../open-sse/config/audioRegistry.ts"); test("handleAudioSpeech requires model", async () => { const response = await handleAudioSpeech({ @@ -486,7 +487,7 @@ test("handleAudioSpeech maps Inworld requests to basic auth and wav output", asy try { const response = await handleAudioSpeech({ body: { - model: "inworld/inworld-tts-1.5-max", + model: "inworld/inworld-tts-2", input: "inworld text", voice: "voice-9", response_format: "wav", @@ -498,8 +499,8 @@ test("handleAudioSpeech maps Inworld requests to basic auth and wav output", asy assert.deepEqual(captured.body, { text: "inworld text", voiceId: "voice-9", - modelId: "inworld-tts-1.5-max", - audioConfig: { audioEncoding: "LINEAR16" }, + modelId: "inworld-tts-2", + audioConfig: { audioEncoding: "WAV" }, }); assert.equal(response.headers.get("content-type"), "audio/wav"); assert.deepEqual(Array.from(new Uint8Array(await response.arrayBuffer())), [1, 2, 3, 4]); @@ -508,6 +509,60 @@ test("handleAudioSpeech maps Inworld requests to basic auth and wav output", asy } }); +test("Inworld speech registry exposes supported formats without flac", () => { + assert.deepEqual(AUDIO_SPEECH_PROVIDERS.inworld.supportedFormats, ["mp3", "wav", "opus", "pcm"]); +}); + +test("handleAudioSpeech maps Inworld opus output and rejects flac", async () => { + const originalFetch = globalThis.fetch; + let captured; + let callCount = 0; + + globalThis.fetch = async (_url, options = {}) => { + callCount += 1; + captured = JSON.parse(String(options.body || "{}")); + + return new Response(JSON.stringify({ audioContent: "BQY=", contentType: "audio/opus" }), { + status: 200, + headers: { "content-type": "application/json" }, + }); + }; + + try { + const opusResponse = await handleAudioSpeech({ + body: { + model: "inworld/inworld-tts-2", + input: "inworld text", + response_format: "opus", + }, + credentials: { apiKey: "encoded-basic-token" }, + }); + + assert.deepEqual(captured.audioConfig, { audioEncoding: "OPUS" }); + assert.equal(opusResponse.headers.get("content-type"), "audio/opus"); + assert.deepEqual(Array.from(new Uint8Array(await opusResponse.arrayBuffer())), [5, 6]); + + const flacResponse = await handleAudioSpeech({ + body: { + model: "inworld/inworld-tts-2", + input: "inworld text", + response_format: "flac", + }, + credentials: { apiKey: "encoded-basic-token" }, + }); + const payload = (await flacResponse.json()) as any; + + assert.equal(flacResponse.status, 400); + assert.equal( + payload.error.message, + "Inworld TTS supports response_format mp3, wav, opus, or pcm only" + ); + assert.equal(callCount, 1); + } finally { + globalThis.fetch = originalFetch; + } +}); + test("handleAudioSpeech supports local Coqui providers without credentials", async () => { const originalFetch = globalThis.fetch; let captured; diff --git a/tests/unit/authz/classify.test.ts b/tests/unit/authz/classify.test.ts index 7f6021992e..5870d8ed30 100644 --- a/tests/unit/authz/classify.test.ts +++ b/tests/unit/authz/classify.test.ts @@ -16,7 +16,7 @@ const cases: Case[] = [ { name: "root /", path: "/", expectedClass: "MANAGEMENT", expectedNormalized: "/" }, { name: "dashboard root", path: "/dashboard", expectedClass: "MANAGEMENT" }, { name: "dashboard nested", path: "/dashboard/settings", expectedClass: "MANAGEMENT" }, - { name: "dashboard onboarding", path: "/dashboard/onboarding", expectedClass: "MANAGEMENT" }, + { name: "dashboard onboarding", path: "/dashboard/onboarding", expectedClass: "PUBLIC" }, { name: "/api/v1 base", diff --git a/tests/unit/cc-compatible-provider.test.ts b/tests/unit/cc-compatible-provider.test.ts index 0f03139ddf..5eac9493c8 100644 --- a/tests/unit/cc-compatible-provider.test.ts +++ b/tests/unit/cc-compatible-provider.test.ts @@ -571,6 +571,91 @@ test("handleChatCore forces SSE upstream for CC compatible providers while retur assert.equal(payload.usage.completion_tokens, 5); }); +test("handleChatCore stops buffering CC-compatible SSE once a non-stream response completes", async () => { + const encoder = new TextEncoder(); + let upstreamCancelled = false; + const upstreamChunks = [ + "data:\n\n", + [ + "event: message_start", + 'data: {"type":"message_start","message":{"id":"msg_3","type":"message","role":"assistant","model":"claude-sonnet-4-6","usage":{"input_tokens":4,"output_tokens":0}}}', + "", + "event: content_block_delta", + 'data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"Finished but connection stayed open"}}', + "", + "event: message_delta", + 'data: {"type":"message_delta","delta":{"stop_reason":"end_turn"},"usage":{"output_tokens":6}}', + "", + "event: message_stop", + 'data: {"type":"message_stop"}', + "", + ].join("\n"), + ]; + let chunkIndex = 0; + + globalThis.fetch = async () => + new Response( + new ReadableStream({ + pull(controller) { + if (chunkIndex < upstreamChunks.length) { + controller.enqueue(encoder.encode(upstreamChunks[chunkIndex++])); + } + }, + cancel() { + upstreamCancelled = true; + }, + }), + { + status: 200, + headers: { + "content-type": "text/event-stream", + }, + } + ); + + const result = await handleChatCore({ + body: { + model: "claude-sonnet-4-6", + messages: [{ role: "user", content: "Ping" }], + stream: false, + }, + modelInfo: { + provider: "anthropic-compatible-cc-test", + model: "claude-sonnet-4-6", + extendedContext: false, + }, + credentials: { + apiKey: "sk-test", + providerSpecificData: { + baseUrl: "https://proxy.example.com", + chatPath: CLAUDE_CODE_COMPATIBLE_DEFAULT_CHAT_PATH, + }, + }, + clientRawRequest: { + endpoint: "/v1/chat/completions", + body: { + model: "claude-sonnet-4-6", + messages: [{ role: "user", content: "Ping" }], + stream: false, + }, + headers: new Headers({ accept: "application/json" }), + }, + userAgent: "unit-test", + log: { + debug() {}, + info() {}, + warn() {}, + error() {}, + }, + }); + + assert.equal(result.success, true); + assert.equal(upstreamCancelled, true); + const payload = (await result.response.json()) as any; + assert.equal(payload.choices[0].message.content, "Finished but connection stayed open"); + assert.equal(payload.usage.completion_tokens, 6); +}); + test("handleChatCore preserves client cache markers for Claude Code requests to CC-compatible providers", async () => { const calls = []; globalThis.fetch = async (url, init = {}) => { diff --git a/tests/unit/circuit-breaker-failure-kind.test.ts b/tests/unit/circuit-breaker-failure-kind.test.ts new file mode 100644 index 0000000000..d9498f1a0a --- /dev/null +++ b/tests/unit/circuit-breaker-failure-kind.test.ts @@ -0,0 +1,231 @@ +/** + * Tests for circuit breaker per-failure-kind cooldowns (Issue #2100). + * + * Each test creates a uniquely-named breaker so SQLite-backed state from + * `loadCircuitBreakerState()` cannot leak between tests when run in any + * order or with --test-concurrency > 1. + */ +import { test } from "node:test"; +import assert from "node:assert/strict"; +import { + CircuitBreaker, + resetAllCircuitBreakers, + getCircuitBreaker, +} from "../../src/shared/utils/circuitBreaker.ts"; +import type { FailureKind } from "../../src/shared/utils/classify429.ts"; + +const uniqueName = (suffix: string) => + `cb-test-#2100-${suffix}-${Date.now()}-${Math.floor(Math.random() * 1e6)}`; + +test("default behavior unchanged when neither cooldownByKind nor classifyError is set", () => { + const cb = new CircuitBreaker(uniqueName("legacy"), { + failureThreshold: 2, + resetTimeout: 30_000, + }); + cb._onFailure(); + cb._onFailure(); + assert.equal(cb.state, "OPEN"); + assert.equal(cb.lastFailureKind, null); + // Cooldown is the legacy resetTimeout — not biased by kind. + const t = cb._timeUntilReset(); + assert.ok(t > 29_000 && t <= 30_000, `expected ~30s, got ${t}`); + cb.reset(); +}); + +test("cooldownByKind: quota_exhausted gets longer cooldown than rate_limit", () => { + const cb = new CircuitBreaker(uniqueName("kind-cooldown"), { + failureThreshold: 1, + resetTimeout: 30_000, + cooldownByKind: { + rate_limit: 60_000, + quota_exhausted: 3_600_000, + }, + }); + + cb._onFailure("rate_limit"); + assert.equal(cb.state, "OPEN"); + assert.equal(cb.lastFailureKind, "rate_limit"); + const tRate = cb._timeUntilReset(); + assert.ok(tRate > 59_000 && tRate <= 60_000, `rate_limit cooldown: expected ~60s, got ${tRate}`); + + cb.reset(); + cb._onFailure("quota_exhausted"); + const tQuota = cb._timeUntilReset(); + assert.ok( + tQuota > 3_599_000 && tQuota <= 3_600_000, + `quota_exhausted cooldown: expected ~3600s, got ${tQuota}` + ); + + cb.reset(); +}); + +test("cooldownByKind falls back to resetTimeout when no override for the kind", () => { + const cb = new CircuitBreaker(uniqueName("partial-cooldown"), { + failureThreshold: 1, + resetTimeout: 45_000, + cooldownByKind: { + quota_exhausted: 3_600_000, + // rate_limit intentionally omitted — should use resetTimeout + }, + }); + cb._onFailure("rate_limit"); + const t = cb._timeUntilReset(); + assert.ok(t > 44_000 && t <= 45_000, `expected ~45s fallback, got ${t}`); + cb.reset(); +}); + +test("cooldownByKind falls back to resetTimeout when lastFailureKind is null", () => { + const cb = new CircuitBreaker(uniqueName("null-kind"), { + failureThreshold: 1, + resetTimeout: 30_000, + cooldownByKind: { + rate_limit: 60_000, + quota_exhausted: 3_600_000, + }, + }); + // Old-style call site that doesn't classify — kind stays null. + cb._onFailure(); + assert.equal(cb.lastFailureKind, null); + const t = cb._timeUntilReset(); + assert.ok(t > 29_000 && t <= 30_000, `expected resetTimeout fallback, got ${t}`); + cb.reset(); +}); + +test("classifyError on execute() routes errors to the correct kind", async () => { + const cb = new CircuitBreaker(uniqueName("classifier"), { + failureThreshold: 1, + resetTimeout: 1_000, + cooldownByKind: { quota_exhausted: 600_000 }, + classifyError: (err: unknown): FailureKind | undefined => { + if (err instanceof Error && err.message.includes("daily limit")) { + return "quota_exhausted"; + } + return "transient"; + }, + }); + + await assert.rejects(async () => { + await cb.execute(async () => { + throw new Error("You exceeded your daily limit"); + }); + }); + + assert.equal(cb.state, "OPEN"); + assert.equal(cb.lastFailureKind, "quota_exhausted"); + const t = cb._timeUntilReset(); + assert.ok(t > 599_000 && t <= 600_000, `expected ~600s quota cooldown, got ${t}`); + cb.reset(); +}); + +test("_onSuccess clears lastFailureKind on close transition", () => { + const cb = new CircuitBreaker(uniqueName("success-clear"), { + failureThreshold: 1, + resetTimeout: 100, + cooldownByKind: { rate_limit: 100 }, + }); + cb._onFailure("rate_limit"); + assert.equal(cb.lastFailureKind, "rate_limit"); + // simulate elapsed time & success path through _onSuccess (which the + // combo path uses); after success, kind should clear and breaker close. + cb._onSuccess(); + assert.equal(cb.lastFailureKind, null); + assert.equal(cb.state, "CLOSED"); +}); + +test("reset() clears lastFailureKind", () => { + const cb = new CircuitBreaker(uniqueName("reset-clear"), { + failureThreshold: 1, + cooldownByKind: { rate_limit: 60_000 }, + }); + cb._onFailure("rate_limit"); + assert.equal(cb.lastFailureKind, "rate_limit"); + cb.reset(); + assert.equal(cb.lastFailureKind, null); +}); + +test("getCircuitBreaker registry merges new options on subsequent calls", () => { + const name = uniqueName("registry-merge"); + const cb1 = getCircuitBreaker(name, { failureThreshold: 5 }); + // First call: no cooldownByKind, classifyError null + assert.deepEqual(cb1.cooldownByKind, {}); + assert.equal(cb1.classifyError, null); + // Second call: add overrides + const cb2 = getCircuitBreaker(name, { + cooldownByKind: { rate_limit: 60_000 }, + classifyError: () => "rate_limit" as FailureKind, + }); + assert.equal(cb1, cb2, "registry returns same instance"); + assert.deepEqual(cb1.cooldownByKind, { rate_limit: 60_000 }); + assert.ok(typeof cb1.classifyError === "function"); + cb1.reset(); +}); + +test("registry MERGES cooldownByKind across calls (does not replace)", () => { + // Regression test for codex audit MEDIUM #1: if two registrations supply + // disjoint keys, both must survive. Without spread-merge the second call + // wiped the first. + const name = uniqueName("registry-merge-keys"); + const cb1 = getCircuitBreaker(name, { + cooldownByKind: { quota_exhausted: 3_600_000 }, + }); + assert.deepEqual(cb1.cooldownByKind, { quota_exhausted: 3_600_000 }); + const cb2 = getCircuitBreaker(name, { + cooldownByKind: { rate_limit: 60_000 }, + }); + assert.equal(cb1, cb2); + assert.deepEqual(cb1.cooldownByKind, { + quota_exhausted: 3_600_000, + rate_limit: 60_000, + }); + cb1.reset(); +}); + +test("classifyError throwing does not mask original error or skip _onFailure", async () => { + // Regression test for codex audit MEDIUM #2. + const cb = new CircuitBreaker(uniqueName("classifier-throws"), { + failureThreshold: 1, + resetTimeout: 1_000, + classifyError: () => { + throw new Error("classifier itself blew up"); + }, + }); + let caught: unknown; + try { + await cb.execute(async () => { + throw new Error("original error"); + }); + } catch (e) { + caught = e; + } + assert.ok(caught instanceof Error); + assert.equal((caught as Error).message, "original error"); + assert.equal(cb.state, "OPEN", "failure was still recorded"); + assert.equal(cb.lastFailureKind, null, "kind defaults to null when classifier throws"); + cb.reset(); +}); + +test("invalid cooldownByKind values (NaN, Infinity, negative) fall back to resetTimeout", () => { + // Regression test for codex audit MEDIUM #3. + const cb = new CircuitBreaker(uniqueName("invalid-cooldown"), { + failureThreshold: 1, + resetTimeout: 30_000, + cooldownByKind: { + rate_limit: NaN, + quota_exhausted: -5_000, + transient: Number.POSITIVE_INFINITY, + }, + }); + for (const kind of ["rate_limit", "quota_exhausted", "transient"] as const) { + cb.reset(); + cb._onFailure(kind); + const t = cb._timeUntilReset(); + assert.ok(t > 29_000 && t <= 30_000, `expected resetTimeout fallback for ${kind}, got ${t}`); + } + cb.reset(); +}); + +// Cleanup: clear the registry (and SQLite-persisted breaker state) so this +// test file does not leak into others when --test-concurrency=10. +test("teardown — reset all circuit breakers", () => { + resetAllCircuitBreakers(); +}); diff --git a/tests/unit/classify429.test.ts b/tests/unit/classify429.test.ts new file mode 100644 index 0000000000..75d1a4fbd3 --- /dev/null +++ b/tests/unit/classify429.test.ts @@ -0,0 +1,156 @@ +import { test } from "node:test"; +import assert from "node:assert/strict"; +import { + classify429, + looksLikeQuotaExhausted, + parseRetryAfter, + retryAfterFromResponse, + type FailureKind, +} from "../../src/shared/utils/classify429.ts"; + +test("classify429: non-429 status returns 'transient'", () => { + const out: FailureKind = classify429({ status: 500 }); + assert.equal(out, "transient"); +}); + +test("classify429: 429 with no body or hints returns 'rate_limit'", () => { + assert.equal(classify429({ status: 429 }), "rate_limit"); + assert.equal(classify429({ status: 429, body: "" }), "rate_limit"); + assert.equal(classify429({ status: 429, body: undefined }), "rate_limit"); +}); + +test("classify429: 429 with quota keyword in string body returns 'quota_exhausted'", () => { + assert.equal( + classify429({ status: 429, body: "You exceeded your daily limit." }), + "quota_exhausted" + ); + assert.equal( + classify429({ status: 429, body: "Monthly quota reached. Resets on the 1st." }), + "quota_exhausted" + ); + assert.equal( + classify429({ status: 429, body: "Out of credits — top up your account." }), + "quota_exhausted" + ); + assert.equal(classify429({ status: 429, body: "plan limit reached" }), "quota_exhausted"); +}); + +test("classify429: 429 with quota keyword in nested object body returns 'quota_exhausted'", () => { + assert.equal( + classify429({ + status: 429, + body: { error: { message: "You have exceeded your monthly quota." } }, + }), + "quota_exhausted" + ); + assert.equal( + classify429({ + status: 429, + body: { error: { type: "insufficient_quota", message: "..." } }, + }), + "quota_exhausted" + ); +}); + +test("classify429: 429 without quota keyword returns 'rate_limit'", () => { + // Plain rate-limit message — keyword 'rate' alone is NOT in QUOTA_PATTERNS + // so classifier should default to "rate_limit" for any 429. + assert.equal( + classify429({ status: 429, body: "Too many requests. Try again in 60s." }), + "rate_limit" + ); + assert.equal( + classify429({ + status: 429, + body: "Rate limit reached for requests. Please retry.", + }), + "rate_limit" + ); +}); + +test("looksLikeQuotaExhausted: detects all known keyword variants", () => { + for (const body of [ + "daily limit exceeded", + "daily quota reached", + "per-day limit reached", + "monthly limit", + "monthly quota", + "per-month limit", + "quota exceeded", + "exceeded quota", + "insufficient_quota", + "billing cap reached", + "credit exhausted", + "out of credits", + "hard limit", + "hard-limit", + "plan limit", + ]) { + assert.equal(looksLikeQuotaExhausted(body), true, `failed for: ${body}`); + } +}); + +test("looksLikeQuotaExhausted: rejects empty / null / non-quota text", () => { + assert.equal(looksLikeQuotaExhausted(undefined), false); + assert.equal(looksLikeQuotaExhausted(null), false); + assert.equal(looksLikeQuotaExhausted(""), false); + assert.equal(looksLikeQuotaExhausted("rate limit, please retry in 60s"), false); + assert.equal(looksLikeQuotaExhausted("server error 500"), false); +}); + +test("ambiguous 'daily rate limit' messages classify as quota_exhausted (intentional)", () => { + // Codex audit LOW: messages combining 'daily' or 'monthly' with 'limit' + // match the quota regex even when paired with 'rate'. This is intentional + // because daily/monthly caps semantically warrant a long cooldown — even + // when the upstream calls them "rate limits". Locking it down here so a + // future regex tweak doesn't silently change the behavior. + assert.equal(classify429({ status: 429, body: "daily rate limit exceeded" }), "quota_exhausted"); + assert.equal( + classify429({ status: 429, body: "monthly rate limit exceeded" }), + "quota_exhausted" + ); +}); + +test("parseRetryAfter: integer seconds", () => { + assert.equal(parseRetryAfter("60"), 60); + assert.equal(parseRetryAfter("3600"), 3600); + assert.equal(parseRetryAfter("0"), 0); +}); + +test("parseRetryAfter: Groq-style relative units", () => { + // Regression for the parseInt-trap: parseInt("5m", 10) returns 5, + // which would be wrong (5s instead of 300s). The relative-unit + // pattern must be checked BEFORE plain integer parse. + assert.equal(parseRetryAfter("60s"), 60); + assert.equal(parseRetryAfter("5m"), 300); + assert.equal(parseRetryAfter("2h"), 7200); + assert.equal(parseRetryAfter("1H"), 3600); +}); + +test("parseRetryAfter: HTTP-date in the future", () => { + const future = new Date(Date.now() + 60_000).toUTCString(); + const secs = parseRetryAfter(future); + assert.ok(secs !== null); + assert.ok(secs! >= 50 && secs! <= 65, `expected ~60, got ${secs}`); +}); + +test("parseRetryAfter: HTTP-date in the past clamps to 0", () => { + const past = new Date(Date.now() - 5 * 60_000).toUTCString(); + assert.equal(parseRetryAfter(past), 0); +}); + +test("parseRetryAfter: unparseable returns null", () => { + assert.equal(parseRetryAfter(undefined), null); + assert.equal(parseRetryAfter(""), null); + assert.equal(parseRetryAfter(" "), null); + assert.equal(parseRetryAfter("not-a-date"), null); + assert.equal(parseRetryAfter("60xyz"), null); +}); + +test("retryAfterFromResponse: case-insensitive header lookup", () => { + assert.equal(retryAfterFromResponse({ headers: { "Retry-After": "30" } }), 30); + assert.equal(retryAfterFromResponse({ headers: { "retry-after": "45" } }), 45); + assert.equal(retryAfterFromResponse({ headers: { "RETRY-AFTER": "60s" } }), 60); + assert.equal(retryAfterFromResponse({ headers: {} }), null); + assert.equal(retryAfterFromResponse({}), null); +}); diff --git a/tests/unit/cloudAgent-types.test.ts b/tests/unit/cloudAgent-types.test.ts new file mode 100644 index 0000000000..f1d8dcb620 --- /dev/null +++ b/tests/unit/cloudAgent-types.test.ts @@ -0,0 +1,166 @@ +import test from "node:test"; +import assert from "node:assert/strict"; + +const { CLOUD_AGENT_STATUS, CloudAgentStatusSchema, CloudAgentTask } = + await import("../../src/lib/cloudAgent/types.ts"); +const { CreateCloudAgentTaskSchema, UpdateCloudAgentTaskSchema } = + await import("../../src/lib/cloudAgent/types.ts"); +const { isCloudAgentProvider, getAgent, getAvailableAgents } = + await import("../../src/lib/cloudAgent/registry.ts"); + +test("CLOUD_AGENT_STATUS has correct values", () => { + assert.strictEqual(CLOUD_AGENT_STATUS.QUEUED, "queued"); + assert.strictEqual(CLOUD_AGENT_STATUS.RUNNING, "running"); + assert.strictEqual(CLOUD_AGENT_STATUS.AWAITING_APPROVAL, "awaiting_approval"); + assert.strictEqual(CLOUD_AGENT_STATUS.COMPLETED, "completed"); + assert.strictEqual(CLOUD_AGENT_STATUS.FAILED, "failed"); + assert.strictEqual(CLOUD_AGENT_STATUS.CANCELLED, "cancelled"); +}); + +test("CloudAgentStatusSchema validates valid statuses", () => { + const validStatuses = [ + "queued", + "running", + "awaiting_approval", + "completed", + "failed", + "cancelled", + ]; + for (const status of validStatuses) { + const result = CloudAgentStatusSchema.safeParse(status); + assert.strictEqual(result.success, true, `Status ${status} should be valid`); + } +}); + +test("CloudAgentStatusSchema rejects invalid status", () => { + const result = CloudAgentStatusSchema.safeParse("invalid"); + assert.strictEqual(result.success, false); +}); + +test("CreateCloudAgentTaskSchema validates valid input", () => { + const validInput = { + providerId: "jules", + prompt: "Fix the bug in auth.ts", + source: { + repoName: "my-repo", + repoUrl: "https://github.com/user/my-repo", + branch: "main", + }, + options: { + autoCreatePr: true, + planApprovalRequired: true, + }, + }; + const result = CreateCloudAgentTaskSchema.safeParse(validInput); + assert.strictEqual(result.success, true); +}); + +test("CreateCloudAgentTaskSchema rejects missing required fields", () => { + const invalidInput = { + providerId: "jules", + }; + const result = CreateCloudAgentTaskSchema.safeParse(invalidInput); + assert.strictEqual(result.success, false); +}); + +test("CreateCloudAgentTaskSchema rejects invalid providerId", () => { + const invalidInput = { + providerId: "invalid-provider", + prompt: "Test", + source: { + repoName: "test", + repoUrl: "https://github.com/test/test", + }, + }; + const result = CreateCloudAgentTaskSchema.safeParse(invalidInput); + assert.strictEqual(result.success, false); +}); + +test("CreateCloudAgentTaskSchema rejects invalid repoUrl", () => { + const invalidInput = { + providerId: "jules", + prompt: "Test", + source: { + repoName: "test", + repoUrl: "not-a-url", + }, + }; + const result = CreateCloudAgentTaskSchema.safeParse(invalidInput); + assert.strictEqual(result.success, false); +}); + +test("UpdateCloudAgentTaskSchema validates approve action", () => { + const validInput = { + id: "123e4567-e89b-12d3-a456-426614174000", + action: "approve", + }; + const result = UpdateCloudAgentTaskSchema.safeParse(validInput); + assert.strictEqual(result.success, true); +}); + +test("UpdateCloudAgentTaskSchema validates cancel action", () => { + const validInput = { + id: "123e4567-e89b-12d3-a456-426614174000", + action: "cancel", + }; + const result = UpdateCloudAgentTaskSchema.safeParse(validInput); + assert.strictEqual(result.success, true); +}); + +test("UpdateCloudAgentTaskSchema validates message action with content", () => { + const validInput = { + id: "123e4567-e89b-12d3-a456-426614174000", + action: "message", + message: "Please continue with the next step", + }; + const result = UpdateCloudAgentTaskSchema.safeParse(validInput); + assert.strictEqual(result.success, true); +}); + +test("UpdateCloudAgentTaskSchema allows message without content (optional)", () => { + const validInput = { + id: "123e4567-e89b-12d3-a456-426614174000", + action: "message", + }; + const result = UpdateCloudAgentTaskSchema.safeParse(validInput); + assert.strictEqual(result.success, true); +}); + +test("getAvailableAgents returns all registered agents", () => { + const agents = getAvailableAgents(); + assert.strictEqual(agents.includes("jules"), true); + assert.strictEqual(agents.includes("devin"), true); + assert.strictEqual(agents.includes("codex-cloud"), true); + assert.strictEqual(agents.length, 3); +}); + +test("getAgent returns correct agent for valid providerId", () => { + const jules = getAgent("jules"); + assert.notStrictEqual(jules, null); + assert.strictEqual(jules?.providerId, "jules"); + + const devin = getAgent("devin"); + assert.notStrictEqual(devin, null); + assert.strictEqual(devin?.providerId, "devin"); + + const codex = getAgent("codex-cloud"); + assert.notStrictEqual(codex, null); + assert.strictEqual(codex?.providerId, "codex-cloud"); +}); + +test("getAgent returns null for invalid providerId", () => { + const result = getAgent("invalid-provider"); + assert.strictEqual(result, null); +}); + +test("isCloudAgentProvider returns true for valid providers", () => { + assert.strictEqual(isCloudAgentProvider("jules"), true); + assert.strictEqual(isCloudAgentProvider("devin"), true); + assert.strictEqual(isCloudAgentProvider("codex-cloud"), true); +}); + +test("isCloudAgentProvider returns false for invalid providers", () => { + assert.strictEqual(isCloudAgentProvider("openai"), false); + assert.strictEqual(isCloudAgentProvider("anthropic"), false); + assert.strictEqual(isCloudAgentProvider("invalid"), false); +}); diff --git a/tests/unit/compression/rtk-code-stripper.test.ts b/tests/unit/compression/rtk-code-stripper.test.ts index a191d31160..bba15c0264 100644 --- a/tests/unit/compression/rtk-code-stripper.test.ts +++ b/tests/unit/compression/rtk-code-stripper.test.ts @@ -23,7 +23,7 @@ describe("RTK code stripper", () => { ); assert.ok(js.text.includes("// comment")); - assert.match(js.text, /https:\/\/example\.com\/a\/\/b/); + assert.ok(js.text.includes("https://example.com/a//b")); assert.ok(js.text.includes("/* block */")); }); diff --git a/tests/unit/cursor-usage-fetcher.test.ts b/tests/unit/cursor-usage-fetcher.test.ts new file mode 100644 index 0000000000..60cc78d63c --- /dev/null +++ b/tests/unit/cursor-usage-fetcher.test.ts @@ -0,0 +1,238 @@ +import test from "node:test"; +import assert from "node:assert/strict"; + +const usageService = await import("../../open-sse/services/usage.ts"); + +const CURSOR_USAGE_URL = "https://cursor.com/api/dashboard/get-current-period-usage"; + +function makeJwt(payload: Record): string { + const b64url = (input: string) => + Buffer.from(input) + .toString("base64") + .replace(/=+$/, "") + .replace(/\+/g, "-") + .replace(/\//g, "_"); + const header = b64url(JSON.stringify({ alg: "HS256", typ: "JWT" })); + const body = b64url(JSON.stringify(payload)); + return `${header}.${body}.signature`; +} + +const SAMPLE_RESPONSE = { + billingCycleStart: "1776672371000", + billingCycleEnd: "1779264371000", + planUsage: { + totalSpend: 1529, + includedSpend: 1529, + remaining: 471, + limit: 2000, + autoPercentUsed: 13.20952380952381, + apiPercentUsed: 3.155555555555556, + totalPercentUsed: 10.193333333333333, + }, + spendLimitUsage: { limitType: "user" }, + enabled: true, +}; + +interface CapturedRequest { + url: string; + init: RequestInit; +} + +function installFetchMock( + responder: (url: string, init: RequestInit) => Response | Promise +): { restore: () => void; calls: CapturedRequest[] } { + const calls: CapturedRequest[] = []; + const original = globalThis.fetch; + globalThis.fetch = (async (input: any, init: RequestInit = {}) => { + const url = typeof input === "string" ? input : (input as Request).url; + calls.push({ url, init }); + return await responder(url, init); + }) as typeof fetch; + return { + restore: () => { + globalThis.fetch = original; + }, + calls, + }; +} + +test("cursor usage: happy path returns three windows with correct percentages and reset", async () => { + const userId = "user_01TESTSTOREDID"; + const accessToken = makeJwt({ sub: `google-oauth2|${userId}` }); + + const mock = installFetchMock( + async () => + new Response(JSON.stringify(SAMPLE_RESPONSE), { + status: 200, + headers: { "content-type": "application/json" }, + }) + ); + + try { + const usage = await usageService.getUsageForProvider({ + provider: "cursor", + accessToken, + providerSpecificData: { userId }, + }); + + assert.equal(usage.plan, "Cursor Pro"); + assert.deepEqual(Object.keys(usage.quotas), ["Total", "Auto + Composer", "API"]); + + const total = usage.quotas.Total; + assert.equal(total.total, 20); // limit 2000 cents = $20 + assert.equal(total.used, 15.29); // totalSpend 1529 cents = $15.29 + assert.equal(total.remaining, 4.71); + assert.ok(Math.abs(total.remainingPercentage - (100 - 10.193333333333333)) < 1e-6); + assert.equal(total.unlimited, false); + assert.equal(total.resetAt, new Date(Number("1779264371000")).toISOString()); + + const auto = usage.quotas["Auto + Composer"]; + assert.equal(auto.total, 20); + // 2000 cents * 13.2095% ≈ 264 cents = $2.64 + assert.equal(auto.used, 2.64); + assert.ok(Math.abs(auto.remainingPercentage - (100 - 13.20952380952381)) < 1e-6); + + const api = usage.quotas.API; + assert.equal(api.total, 20); + // 2000 cents * 3.1556% ≈ 63 cents = $0.63 + assert.equal(api.used, 0.63); + assert.ok(Math.abs(api.remainingPercentage - (100 - 3.155555555555556)) < 1e-6); + } finally { + mock.restore(); + } +}); + +test("cursor usage: sends correct cookie, origin, body, and method", async () => { + const userId = "user_01HEADERCHECK"; + const accessToken = makeJwt({ sub: userId }); + + const mock = installFetchMock( + async () => + new Response(JSON.stringify(SAMPLE_RESPONSE), { + status: 200, + headers: { "content-type": "application/json" }, + }) + ); + + try { + await usageService.getUsageForProvider({ + provider: "cursor", + accessToken, + providerSpecificData: { userId }, + }); + + assert.equal(mock.calls.length, 1); + const { url, init } = mock.calls[0]; + assert.equal(url, CURSOR_USAGE_URL); + assert.equal(init.method, "POST"); + assert.equal(init.body, "{}"); + + const headers = init.headers as Record; + assert.equal(headers.Cookie, `WorkosCursorSessionToken=${userId}::${accessToken}`); + assert.equal(headers.Origin, "https://cursor.com"); + assert.match(headers.Referer, /^https:\/\/cursor\.com\/dashboard/); + assert.equal(headers["Content-Type"], "application/json"); + assert.ok(headers["User-Agent"]); + } finally { + mock.restore(); + } +}); + +test("cursor usage: falls back to JWT sub when providerSpecificData.userId is missing", async () => { + const userId = "user_01JWTFALLBACK"; + const accessToken = makeJwt({ sub: `google-oauth2|${userId}` }); + + const mock = installFetchMock( + async () => + new Response(JSON.stringify(SAMPLE_RESPONSE), { + status: 200, + headers: { "content-type": "application/json" }, + }) + ); + + try { + const usage = await usageService.getUsageForProvider({ + provider: "cursor", + accessToken, + providerSpecificData: {}, + }); + + assert.equal(usage.plan, "Cursor Pro"); + assert.equal(mock.calls.length, 1); + const headers = mock.calls[0].init.headers as Record; + // Cookie should use the full sub claim (google-oauth2|user_...) since Cursor accepts both forms. + assert.equal( + headers.Cookie, + `WorkosCursorSessionToken=google-oauth2|${userId}::${accessToken}` + ); + } finally { + mock.restore(); + } +}); + +test("cursor usage: returns message and skips fetch when userId is unrecoverable", async () => { + const mock = installFetchMock(async () => new Response("should not be called", { status: 500 })); + + try { + const usage = await usageService.getUsageForProvider({ + provider: "cursor", + accessToken: "not-a-jwt-and-too-short", + providerSpecificData: {}, + }); + + assert.equal(mock.calls.length, 0); + assert.match(usage.message, /missing user id/i); + assert.equal(usage.quotas, undefined); + } finally { + mock.restore(); + } +}); + +test("cursor usage: 307 redirect surfaces as expired session message", async () => { + const accessToken = makeJwt({ sub: "user_01EXPIRED" }); + const mock = installFetchMock( + async () => + new Response("", { + status: 307, + headers: { Location: "https://api.workos.com/user_management/authorize?..." }, + }) + ); + + try { + const usage = await usageService.getUsageForProvider({ + provider: "cursor", + accessToken, + providerSpecificData: { userId: "user_01EXPIRED" }, + }); + + assert.equal(usage.plan, "Cursor"); + assert.match(usage.message, /session expired|Re-import/i); + assert.equal(usage.quotas, undefined); + } finally { + mock.restore(); + } +}); + +test("cursor usage: empty planUsage returns informational message", async () => { + const accessToken = makeJwt({ sub: "user_01EMPTY" }); + const mock = installFetchMock( + async () => + new Response( + JSON.stringify({ billingCycleStart: "0", billingCycleEnd: "0", planUsage: {} }), + { status: 200, headers: { "content-type": "application/json" } } + ) + ); + + try { + const usage = await usageService.getUsageForProvider({ + provider: "cursor", + accessToken, + providerSpecificData: { userId: "user_01EMPTY" }, + }); + + assert.equal(usage.plan, "Cursor"); + assert.match(usage.message, /No active plan usage/i); + } finally { + mock.restore(); + } +}); diff --git a/tests/unit/fix-2130-system-passthrough.test.ts b/tests/unit/fix-2130-system-passthrough.test.ts new file mode 100644 index 0000000000..f45fe072f8 --- /dev/null +++ b/tests/unit/fix-2130-system-passthrough.test.ts @@ -0,0 +1,103 @@ +/** + * Regression test for #2130: system prompt missing for Claude Code OAuth on Linux. + * + * Claude Code sends requests to /v1/chat/completions with `body.system` as a + * native Anthropic array (not as role="system" messages). The openai→claude + * translator must preserve body.system when no role="system" messages exist. + */ +import { describe, it } from "node:test"; +import assert from "node:assert/strict"; +import { openaiToClaudeRequest } from "../../open-sse/translator/request/openai-to-claude.ts"; + +describe("#2130: body.system passthrough in openai→claude translator", () => { + it("preserves body.system array when no role=system messages exist", () => { + const body = { + model: "claude-opus-4-7", + max_tokens: 2048, + stream: false, + messages: [ + { + role: "user", + content: [{ type: "text", text: "hi" }], + }, + ], + system: [ + { + type: "text", + text: "You are Claude Code, Anthropic's official CLI for Claude.", + }, + ], + }; + + const result = openaiToClaudeRequest("claude-opus-4-7", body, false); + + assert.ok(result.system, "result.system must be defined"); + assert.ok(Array.isArray(result.system), "result.system must be an array"); + assert.ok( + result.system.some((b) => b.text && b.text.includes("You are Claude Code")), + "result.system must contain the Claude Code system prompt" + ); + }); + + it("preserves body.system string when no role=system messages exist", () => { + const body = { + model: "claude-sonnet-4-6", + max_tokens: 4096, + messages: [{ role: "user", content: "hello" }], + system: "You are a helpful assistant.", + }; + + const result = openaiToClaudeRequest("claude-sonnet-4-6", body, true); + + assert.ok(result.system, "result.system must be defined"); + assert.ok(Array.isArray(result.system), "result.system must be an array"); + assert.equal(result.system[0].text, "You are a helpful assistant."); + }); + + it("merges body.system with role=system messages", () => { + const body = { + model: "claude-opus-4-7", + max_tokens: 2048, + messages: [ + { role: "system", content: "Be concise." }, + { role: "user", content: "hi" }, + ], + system: [ + { + type: "text", + text: "You are Claude Code, Anthropic's official CLI for Claude.", + }, + ], + }; + + const result = openaiToClaudeRequest("claude-opus-4-7", body, false); + + assert.ok(result.system, "result.system must be defined"); + assert.ok(Array.isArray(result.system), "result.system must be an array"); + // Should have the original body.system + the extracted role=system text + assert.ok( + result.system.some((b) => b.text && b.text.includes("You are Claude Code")), + "must contain the body.system content" + ); + assert.ok( + result.system.some((b) => b.text && b.text.includes("Be concise")), + "must contain the role=system message content" + ); + }); + + it("works correctly when neither body.system nor role=system messages exist", () => { + const body = { + model: "claude-sonnet-4-6", + max_tokens: 2048, + messages: [{ role: "user", content: "hello" }], + }; + + const result = openaiToClaudeRequest("claude-sonnet-4-6", body, true); + + assert.equal( + result.system, + undefined, + "result.system should be undefined when no system input exists" + ); + }); +}); diff --git a/tests/unit/provider-header-profiles.test.ts b/tests/unit/provider-header-profiles.test.ts index df7e79b340..46e2f0a0da 100644 --- a/tests/unit/provider-header-profiles.test.ts +++ b/tests/unit/provider-header-profiles.test.ts @@ -2,7 +2,6 @@ import test from "node:test"; import assert from "node:assert/strict"; import { - CURSOR_REGISTRY_VERSION, GITHUB_COPILOT_API_VERSION, GITHUB_COPILOT_CHAT_PLUGIN_VERSION, GITHUB_COPILOT_CHAT_USER_AGENT, @@ -12,7 +11,6 @@ import { KIRO_AMZ_USER_AGENT, KIRO_SDK_USER_AGENT, QWEN_CLI_VERSION, - getCursorUsageHeaders, getQwenCliUserAgent, getGitHubCopilotChatHeaders, getGitHubCopilotInternalUserHeaders, @@ -39,7 +37,7 @@ test("provider header profiles expose current GitHub chat and internal headers", assert.equal(internalHeaders["X-GitHub-Api-Version"], GITHUB_COPILOT_API_VERSION); }); -test("provider header profiles expose dedicated refresh, qwen, qoder, kiro and cursor variants", () => { +test("provider header profiles expose dedicated refresh, qwen, qoder and kiro variants", () => { const refreshHeaders = getGitHubCopilotRefreshHeaders("token gh-access"); assert.equal(refreshHeaders.Authorization, "token gh-access"); assert.equal(refreshHeaders["User-Agent"], GITHUB_COPILOT_REFRESH_USER_AGENT); @@ -65,12 +63,6 @@ test("provider header profiles expose dedicated refresh, qwen, qoder, kiro and c assert.equal(kiroHeaders.Accept, "application/json"); assert.equal(kiroHeaders["User-Agent"], KIRO_SDK_USER_AGENT); assert.equal(kiroHeaders["X-Amz-User-Agent"], KIRO_AMZ_USER_AGENT); - - const cursorHeaders = getCursorUsageHeaders("cursor-token"); - assert.equal(cursorHeaders.Authorization, "Bearer cursor-token"); - assert.equal(cursorHeaders["User-Agent"], `Cursor/${CURSOR_REGISTRY_VERSION}`); - assert.equal(cursorHeaders["x-cursor-user-agent"], `Cursor/${CURSOR_REGISTRY_VERSION}`); - assert.equal(cursorHeaders["x-cursor-client-version"], CURSOR_REGISTRY_VERSION); }); test("provider header profiles tolerate browser-like process shims", async () => { diff --git a/tests/unit/provider-hints.test.ts b/tests/unit/provider-hints.test.ts new file mode 100644 index 0000000000..ddbf966753 --- /dev/null +++ b/tests/unit/provider-hints.test.ts @@ -0,0 +1,58 @@ +import { test } from "node:test"; +import assert from "node:assert/strict"; +import { + defaultUseUpstream429BreakerHints, + resolveUseUpstream429BreakerHints, +} from "../../src/shared/utils/providerHints.ts"; + +test("defaultUseUpstream429BreakerHints: direct cloud providers default true", () => { + for (const id of ["openai", "anthropic", "groq", "cerebras", "mistral", "google"]) { + assert.equal(defaultUseUpstream429BreakerHints(id), true, `expected true for ${id}`); + } +}); + +test("defaultUseUpstream429BreakerHints: cliproxyapi defaults false", () => { + assert.equal(defaultUseUpstream429BreakerHints("cliproxyapi"), false); +}); + +test("defaultUseUpstream429BreakerHints: self-hosted chat providers default false", () => { + for (const id of [ + "lm-studio", + "vllm", + "lemonade", + "llamafile", + "triton", + "xinference", + "oobabooga", + ]) { + assert.equal(defaultUseUpstream429BreakerHints(id), false, `expected false for ${id}`); + } +}); + +test("defaultUseUpstream429BreakerHints: claude-code-* prefix defaults false", () => { + for (const id of [ + "anthropic-compatible-cc-direct", + "anthropic-compatible-cc-bedrock", + "anthropic-compatible-cc-vertex", + ]) { + assert.equal(defaultUseUpstream429BreakerHints(id), false, `expected false for ${id}`); + } +}); + +test("resolveUseUpstream429BreakerHints: user override wins (both directions)", () => { + // Cloud provider with user override OFF → false + assert.equal(resolveUseUpstream429BreakerHints("openai", false), false); + // Cloud provider with user override ON → true (no-op vs default) + assert.equal(resolveUseUpstream429BreakerHints("openai", true), true); + // Proxy provider with user override ON → true (user explicitly trusted it) + assert.equal(resolveUseUpstream429BreakerHints("cliproxyapi", true), true); + // Proxy provider with user override OFF → false (no-op vs default) + assert.equal(resolveUseUpstream429BreakerHints("cliproxyapi", false), false); +}); + +test("resolveUseUpstream429BreakerHints: undefined falls back to per-provider default", () => { + // Critical: this is the v3 regression-test for the v1 default-vs-gate bug. + assert.equal(resolveUseUpstream429BreakerHints("openai", undefined), true); + assert.equal(resolveUseUpstream429BreakerHints("cliproxyapi", undefined), false); + assert.equal(resolveUseUpstream429BreakerHints("lm-studio", undefined), false); +}); diff --git a/tests/unit/resilience-settings-upstream429-breaker.test.ts b/tests/unit/resilience-settings-upstream429-breaker.test.ts new file mode 100644 index 0000000000..b22a2d95c9 --- /dev/null +++ b/tests/unit/resilience-settings-upstream429-breaker.test.ts @@ -0,0 +1,96 @@ +import { test } from "node:test"; +import assert from "node:assert/strict"; +import { + DEFAULT_RESILIENCE_SETTINGS, + mergeResilienceSettings, + resolveResilienceSettings, + type ResilienceSettings, +} from "../../src/lib/resilience/settings.ts"; + +function cloneDefaults(): ResilienceSettings { + // structuredClone is enough for the plain-object settings shape. + return structuredClone(DEFAULT_RESILIENCE_SETTINGS); +} + +test("defaults: useUpstream429BreakerHints omitted (undefined) on both profiles", () => { + const settings = cloneDefaults(); + assert.equal(settings.connectionCooldown.oauth.useUpstream429BreakerHints, undefined); + assert.equal(settings.connectionCooldown.apikey.useUpstream429BreakerHints, undefined); +}); + +test("mergeResilienceSettings: explicit true is stored", () => { + const current = cloneDefaults(); + const next = mergeResilienceSettings(current, { + connectionCooldown: { oauth: { useUpstream429BreakerHints: true } }, + }); + assert.equal(next.connectionCooldown.oauth.useUpstream429BreakerHints, true); + // apikey unchanged + assert.equal(next.connectionCooldown.apikey.useUpstream429BreakerHints, undefined); +}); + +test("mergeResilienceSettings: explicit false is stored", () => { + const current = cloneDefaults(); + const next = mergeResilienceSettings(current, { + connectionCooldown: { apikey: { useUpstream429BreakerHints: false } }, + }); + assert.equal(next.connectionCooldown.apikey.useUpstream429BreakerHints, false); +}); + +test("mergeResilienceSettings: null sentinel deletes the field (back to undefined)", () => { + // Start with explicit false on oauth + const start = mergeResilienceSettings(cloneDefaults(), { + connectionCooldown: { oauth: { useUpstream429BreakerHints: false } }, + }); + assert.equal(start.connectionCooldown.oauth.useUpstream429BreakerHints, false); + // PATCH with null should reset to undefined + const next = mergeResilienceSettings(start, { + connectionCooldown: { + oauth: { useUpstream429BreakerHints: null as unknown as boolean }, + }, + }); + assert.equal(next.connectionCooldown.oauth.useUpstream429BreakerHints, undefined); + // Key should not appear in JSON + const serialized = JSON.parse(JSON.stringify(next.connectionCooldown.oauth)); + assert.equal( + "useUpstream429BreakerHints" in serialized, + false, + "key should be absent in serialized JSON" + ); +}); + +test("mergeResilienceSettings: omitted key (partial-merge) leaves existing value", () => { + // Start with explicit true on apikey + const start = mergeResilienceSettings(cloneDefaults(), { + connectionCooldown: { apikey: { useUpstream429BreakerHints: true } }, + }); + // PATCH oauth only — apikey must keep its value + const next = mergeResilienceSettings(start, { + connectionCooldown: { oauth: { baseCooldownMs: 5000 } }, + }); + assert.equal(next.connectionCooldown.apikey.useUpstream429BreakerHints, true); +}); + +test("resolveResilienceSettings: omitted field in record stays undefined (no toBoolean coercion)", () => { + const record = { + connectionCooldown: { + oauth: { baseCooldownMs: 1000, useUpstreamRetryHints: true, maxBackoffSteps: 5 }, + apikey: { baseCooldownMs: 2000, useUpstreamRetryHints: false, maxBackoffSteps: 3 }, + }, + }; + const resolved = resolveResilienceSettings( + record as Parameters[0] + ); + assert.equal(resolved.connectionCooldown.oauth.useUpstream429BreakerHints, undefined); + assert.equal(resolved.connectionCooldown.apikey.useUpstream429BreakerHints, undefined); +}); + +test("mixed-provider round-trip: oauth=false + apikey=true survives merge", () => { + const next = mergeResilienceSettings(cloneDefaults(), { + connectionCooldown: { + oauth: { useUpstream429BreakerHints: false }, + apikey: { useUpstream429BreakerHints: true }, + }, + }); + assert.equal(next.connectionCooldown.oauth.useUpstream429BreakerHints, false); + assert.equal(next.connectionCooldown.apikey.useUpstream429BreakerHints, true); +}); diff --git a/tests/unit/runtime-timeouts.test.ts b/tests/unit/runtime-timeouts.test.ts index 3ac71b5de6..2a588a63b6 100644 --- a/tests/unit/runtime-timeouts.test.ts +++ b/tests/unit/runtime-timeouts.test.ts @@ -94,3 +94,10 @@ test("API bridge timeouts align request timeout with long proxy timeout by defau serverSocketTimeoutMs: 0, }); }); + +test("API bridge proxy timeout defaults to the long upstream request window", () => { + const config = runtimeTimeouts.getApiBridgeTimeoutConfig({}); + + assert.equal(config.proxyTimeoutMs, 600000); + assert.equal(config.serverRequestTimeoutMs, 600000); +}); diff --git a/tests/unit/sse-auth.test.ts b/tests/unit/sse-auth.test.ts index 7ac60df468..23f3f5419d 100644 --- a/tests/unit/sse-auth.test.ts +++ b/tests/unit/sse-auth.test.ts @@ -14,7 +14,6 @@ const settingsDb = await import("../../src/lib/db/settings.ts"); const apiKeysDb = await import("../../src/lib/db/apiKeys.ts"); const auth = await import("../../src/sse/services/auth.ts"); const quotaCache = await import("../../src/domain/quotaCache.ts"); -const { COOLDOWN_MS } = await import("../../open-sse/config/constants.ts"); async function resetStorage() { core.resetDbInstance(); @@ -45,7 +44,6 @@ async function seedConnection(provider: string, overrides: any = {}) { lastErrorSource: overrides.lastErrorSource, errorCode: overrides.errorCode, backoffLevel: overrides.backoffLevel, - maxConcurrent: overrides.maxConcurrent, providerSpecificData: overrides.providerSpecificData || {}, lastUsedAt: overrides.lastUsedAt, consecutiveUseCount: overrides.consecutiveUseCount, @@ -135,7 +133,7 @@ test("getProviderCredentials enforces generic quota policy unless explicitly byp }, }); const resetAt = futureIso(); - quotaCache.setQuotaCache((connection as any).id, "openai", { + quotaCache.setQuotaCache(connection.id, "openai", { daily: { remainingPercentage: 10, resetAt }, }); @@ -179,38 +177,6 @@ test("getProviderCredentialsWithQuotaPreflight skips exhausted preflight account assert.equal((selected as any).connectionId, healthy.id); }); -test("getProviderCredentials includes per-account maxConcurrent caps", async () => { - const connection = await seedConnection("openai", { - name: "openai-concurrency-cap", - maxConcurrent: 2, - }); - - const selected = await auth.getProviderCredentials("openai"); - - assert.equal(selected.connectionId, connection.id); - assert.equal(selected.maxConcurrent, 2); -}); - -test("getProviderCredentials skips connections that exclude the requested model and selects the next eligible account", async () => { - const excluded = await seedConnection("openai", { - name: "excluded-first", - priority: 1, - providerSpecificData: { - excludedModels: ["gpt-4o*"], - }, - }); - const allowed = await seedConnection("openai", { - name: "allowed-second", - priority: 2, - apiKey: "sk-allowed", - }); - - const selected = await auth.getProviderCredentials("openai", null, null, "gpt-4o-mini"); - - assert.equal(selected.connectionId, allowed.id); - assert.notEqual(selected.connectionId, excluded.id); -}); - test("getProviderCredentialsWithQuotaPreflight returns allRateLimited when a forced connection is blocked by preflight", async () => { const blocked = await seedConnection("openai", { name: "quota-preflight-forced", @@ -237,6 +203,62 @@ test("getProviderCredentialsWithQuotaPreflight returns allRateLimited when a for assert.match(selected.lastError, /quota preflight/i); }); +test("getProviderCredentials keeps separate codex affinity per session", async () => { + await settingsDb.updateSettings({ fallbackStrategy: "round-robin", stickyRoundRobinLimit: 10 }); + const first = await seedConnection("codex", { + name: "codex-affinity-a", + lastUsedAt: new Date(Date.now() - 20_000).toISOString(), + }); + const second = await seedConnection("codex", { + name: "codex-affinity-b", + lastUsedAt: new Date(Date.now() - 10_000).toISOString(), + }); + + const sessionA1 = await auth.getProviderCredentials("codex", null, null, "gpt-5.5", { + sessionKey: "session-a", + }); + const sessionB1 = await auth.getProviderCredentials("codex", null, null, "gpt-5.5", { + sessionKey: "session-b", + }); + const sessionA2 = await auth.getProviderCredentials("codex", null, null, "gpt-5.5", { + sessionKey: "session-a", + }); + const sessionB2 = await auth.getProviderCredentials("codex", null, null, "gpt-5.5", { + sessionKey: "session-b", + }); + + assert.equal(sessionA1.connectionId, first.id); + assert.equal(sessionB1.connectionId, second.id); + assert.equal(sessionA2.connectionId, first.id); + assert.equal(sessionB2.connectionId, second.id); +}); + +test("getProviderCredentials rebinds codex session when affinity connection is excluded", async () => { + await settingsDb.updateSettings({ fallbackStrategy: "round-robin", stickyRoundRobinLimit: 10 }); + const first = await seedConnection("codex", { + name: "codex-affinity-excluded-a", + lastUsedAt: new Date(Date.now() - 20_000).toISOString(), + }); + const second = await seedConnection("codex", { + name: "codex-affinity-excluded-b", + lastUsedAt: new Date(Date.now() - 10_000).toISOString(), + }); + + const initial = await auth.getProviderCredentials("codex", null, null, "gpt-5.5", { + sessionKey: "session-excluded", + }); + const rebound = await auth.getProviderCredentials("codex", first.id, null, "gpt-5.5", { + sessionKey: "session-excluded", + }); + const sticky = await auth.getProviderCredentials("codex", null, null, "gpt-5.5", { + sessionKey: "session-excluded", + }); + + assert.equal(initial.connectionId, first.id); + assert.equal(rebound.connectionId, second.id); + assert.equal(sticky.connectionId, second.id); +}); + test("resolveQuotaLimitPolicy normalizes Codex windows, thresholds, and defaults", () => { const normalized = auth.resolveQuotaLimitPolicy("codex", { limitPolicy: { @@ -264,7 +286,7 @@ test("resolveQuotaLimitPolicy normalizes Codex windows, thresholds, and defaults }); assert.deepEqual(defaults, { enabled: true, - thresholdPercent: 99, + thresholdPercent: 90, windows: ["session", "weekly"], }); assert.deepEqual(generic, { @@ -314,17 +336,17 @@ test("getProviderCredentials round-robin stays on the current account while belo priority: 2, }); - await providersDb.updateProviderConnection((current as any).id, { + await providersDb.updateProviderConnection(current.id, { lastUsedAt: new Date().toISOString(), consecutiveUseCount: 1, }); - await providersDb.updateProviderConnection((other as any).id, { + await providersDb.updateProviderConnection(other.id, { lastUsedAt: new Date(Date.now() - 60_000).toISOString(), consecutiveUseCount: 0, }); const selected = await auth.getProviderCredentials("openai"); - const updated = await providersDb.getProviderConnectionById((current as any).id); + const updated = await providersDb.getProviderConnectionById(current.id); assert.equal(selected.connectionId, current.id); assert.equal(updated.consecutiveUseCount, 2); @@ -428,7 +450,7 @@ test("getProviderCredentials retains terminal accounts for combo live tests", as const bypassed = await auth.getProviderCredentials("openai", null, null, null, { allowSuppressedConnections: true, }); - const updated = await providersDb.getProviderConnectionById((connection as any).id); + const updated = await providersDb.getProviderConnectionById(connection.id); assert.equal(blocked, null); assert.equal(bypassed.connectionId, connection.id); @@ -469,15 +491,9 @@ test("getProviderCredentials reports allRateLimited when every account is model- name: "gemini-model-lock-second", }); + await auth.markAccountUnavailable(first.id, 429, "too many requests", "gemini", "gemini-2.5-pro"); await auth.markAccountUnavailable( - (first as any).id, - 429, - "too many requests", - "gemini", - "gemini-2.5-pro" - ); - await auth.markAccountUnavailable( - (second as any).id, + second.id, 429, "too many requests", "gemini", @@ -504,7 +520,7 @@ test("getProviderCredentials auto-decays stale backoff metadata for recovered ac const selected = await auth.getProviderCredentials("openai"); await flushWrites(); - const updated = await providersDb.getProviderConnectionById((connection as any).id); + const updated = await providersDb.getProviderConnectionById(connection.id); assert.equal(selected.connectionId, connection.id); assert.equal(updated.backoffLevel, 0); @@ -522,7 +538,7 @@ test("getProviderCredentials falls back to a five-minute retry window when quota }, }); - quotaCache.setQuotaCache((connection as any).id, "openai", { + quotaCache.setQuotaCache(connection.id, "openai", { daily: { remainingPercentage: 0, resetAt: null }, }); @@ -547,10 +563,10 @@ test("getProviderCredentials prioritizes accounts that still have quota availabl apiKey: "sk-available", }); - quotaCache.setQuotaCache((exhausted as any).id, "openai", { + quotaCache.setQuotaCache(exhausted.id, "openai", { daily: { remainingPercentage: 0, resetAt: futureIso() }, }); - quotaCache.setQuotaCache((available as any).id, "openai", { + quotaCache.setQuotaCache(available.id, "openai", { daily: { remainingPercentage: 65, resetAt: futureIso() }, }); @@ -574,17 +590,17 @@ test("getProviderCredentials round-robin switches to the least recently used acc priority: 2, }); - await providersDb.updateProviderConnection((current as any).id, { + await providersDb.updateProviderConnection(current.id, { lastUsedAt: new Date().toISOString(), consecutiveUseCount: 2, }); - await providersDb.updateProviderConnection((fallback as any).id, { + await providersDb.updateProviderConnection(fallback.id, { lastUsedAt: new Date(Date.now() - 120_000).toISOString(), consecutiveUseCount: 0, }); const selected = await auth.getProviderCredentials("openai"); - const updated = await providersDb.getProviderConnectionById((fallback as any).id); + const updated = await providersDb.getProviderConnectionById(fallback.id); assert.equal(selected.connectionId, fallback.id); assert.equal(updated.consecutiveUseCount, 1); @@ -604,17 +620,17 @@ test("getProviderCredentials round-robin fallback mode excludes the failed accou priority: 2, }); - await providersDb.updateProviderConnection((failed as any).id, { + await providersDb.updateProviderConnection(failed.id, { lastUsedAt: new Date().toISOString(), consecutiveUseCount: 3, }); - await providersDb.updateProviderConnection((fallback as any).id, { + await providersDb.updateProviderConnection(fallback.id, { lastUsedAt: new Date(Date.now() - 120_000).toISOString(), consecutiveUseCount: 0, }); - const selected = await auth.getProviderCredentials("openai" as any, (failed as any).id); - const updated = await providersDb.getProviderConnectionById((fallback as any).id); + const selected = await auth.getProviderCredentials("openai", failed.id); + const updated = await providersDb.getProviderConnectionById(fallback.id); assert.equal(selected.connectionId, fallback.id); assert.equal(updated.consecutiveUseCount, 1); @@ -644,10 +660,10 @@ test("getProviderCredentials least-used prefers accounts that were never used", name: "least-used-never", priority: 9, }); - await providersDb.updateProviderConnection((recentlyUsed as any).id, { + await providersDb.updateProviderConnection(recentlyUsed.id, { lastUsedAt: new Date().toISOString(), }); - await providersDb.updateProviderConnection((neverUsed as any).id, { + await providersDb.updateProviderConnection(neverUsed.id, { lastUsedAt: null, }); @@ -668,10 +684,10 @@ test("getProviderCredentials least-used prefers the oldest timestamp when all ac priority: 1, }); - await providersDb.updateProviderConnection((oldest as any).id, { + await providersDb.updateProviderConnection(oldest.id, { lastUsedAt: new Date(Date.now() - 120_000).toISOString(), }); - await providersDb.updateProviderConnection((newest as any).id, { + await providersDb.updateProviderConnection(newest.id, { lastUsedAt: new Date().toISOString(), }); @@ -723,10 +739,10 @@ test("getProviderCredentials p2c prefers the account with more quota headroom ov }, }); - (quotaCache as any).setQuotaCache(nearLimit.id, "openai", { + quotaCache.setQuotaCache(nearLimit.id, "openai", { daily: { remainingPercentage: 12, resetAt: futureIso(180_000) }, }); - (quotaCache as any).setQuotaCache(healthy.id, "openai", { + quotaCache.setQuotaCache(healthy.id, "openai", { daily: { remainingPercentage: 78, resetAt: futureIso(180_000) }, }); @@ -786,7 +802,7 @@ test("getProviderCredentials exposes copilotToken when present in providerSpecif assert.equal(selected.copilotToken, "copilot-token-value"); }); -test("markAccountUnavailable keeps local 404 failures model-scoped with the local not-found cooldown", async () => { +test("markAccountUnavailable uses configured cooldowns for local 404 model lockouts", async () => { await settingsDb.updateSettings({ providerProfiles: { apikey: { @@ -807,13 +823,13 @@ test("markAccountUnavailable keeps local 404 failures model-scoped with the loca }); const result = await auth.markAccountUnavailable( - (connection as any).id, + connection.id, 404, "model not found", "openai", "local-model" ); - const updated = await (providersDb as any).getProviderConnectionById(connection.id); + const updated = await providersDb.getProviderConnectionById(connection.id); assert.equal(result.shouldFallback, true); assert.equal(result.cooldownMs, 250); @@ -829,14 +845,14 @@ test("markAccountUnavailable applies a model-only lockout for Gemini 429 respons }); const result = await auth.markAccountUnavailable( - (connection as any).id, + connection.id, 429, "too many requests", "gemini", "gemini-2.5-pro" ); await flushWrites(); - const updated = await providersDb.getProviderConnectionById((connection as any).id); + const updated = await providersDb.getProviderConnectionById(connection.id); assert.equal(result.shouldFallback, true); assert.ok(result.cooldownMs > 0); @@ -852,14 +868,14 @@ test("markAccountUnavailable applies a model-only lockout for compatible provide }); const result = await auth.markAccountUnavailable( - (connection as any).id, + connection.id, 429, "The upstream compatible service exhausted its capacity", "openai-compatible-custom-node", "custom-model-a" ); await flushWrites(); - const updated = await providersDb.getProviderConnectionById((connection as any).id); + const updated = await providersDb.getProviderConnectionById(connection.id); assert.equal(result.shouldFallback, true); assert.ok(result.cooldownMs > 0); @@ -869,7 +885,7 @@ test("markAccountUnavailable applies a model-only lockout for compatible provide assert.equal(Number(updated.errorCode), 429); }); -test("markAccountUnavailable uses the unified configured api-key connection cooldown", async () => { +test("markAccountUnavailable honors configured api-key rate-limit cooldowns", async () => { await settingsDb.updateSettings({ providerProfiles: { apikey: { @@ -887,7 +903,7 @@ test("markAccountUnavailable uses the unified configured api-key connection cool }); const result = await auth.markAccountUnavailable( - (connection as any).id, + connection.id, 429, "too many requests", "openai", @@ -909,20 +925,20 @@ test("markAccountUnavailable stores Codex scope-specific cooldowns without a glo }); const result = await auth.markAccountUnavailable( - (connection as any).id, + connection.id, 429, "quota reached", "codex", "codex-spark-mini" ); - const updated = await providersDb.getProviderConnectionById((connection as any).id); + const updated = await providersDb.getProviderConnectionById(connection.id); const selected = await auth.getProviderCredentials("codex", null, null, "codex-spark-mini"); assert.equal(result.shouldFallback, true); assert.ok(result.cooldownMs > 0); assert.equal(updated.testStatus, "unavailable"); assert.equal(updated.rateLimitedUntil, undefined); - assert.ok((updated.providerSpecificData as any).codexScopeRateLimitedUntil.spark); + assert.ok(updated.providerSpecificData.codexScopeRateLimitedUntil.spark); assert.equal(selected.allRateLimited, true); }); @@ -932,13 +948,13 @@ test("markAccountUnavailable returns without fallback on bad requests", async () }); const result = await auth.markAccountUnavailable( - (connection as any).id, + connection.id, 400, "schema mismatch", "openai", "gpt-4o" ); - const updated = await providersDb.getProviderConnectionById((connection as any).id); + const updated = await providersDb.getProviderConnectionById(connection.id); assert.deepEqual(result, { shouldFallback: false, cooldownMs: 0 }); assert.equal(updated.testStatus, "active"); @@ -952,13 +968,8 @@ test("markAccountUnavailable preserves terminal statuses without overwriting the rateLimitedUntil: null, }); - const result = await auth.markAccountUnavailable( - (connection as any).id, - 503, - "upstream error", - "openai" - ); - const updated = await providersDb.getProviderConnectionById((connection as any).id); + const result = await auth.markAccountUnavailable(connection.id, 503, "upstream error", "openai"); + const updated = await providersDb.getProviderConnectionById(connection.id); assert.equal(result.shouldFallback, true); assert.equal(result.cooldownMs, 0); @@ -973,13 +984,8 @@ test("markAccountUnavailable reuses an existing connection-wide cooldown", async rateLimitedUntil: retryAfter, }); - const result = await auth.markAccountUnavailable( - (connection as any).id, - 503, - "upstream error", - "openai" - ); - const updated = await providersDb.getProviderConnectionById((connection as any).id); + const result = await auth.markAccountUnavailable(connection.id, 503, "upstream error", "openai"); + const updated = await providersDb.getProviderConnectionById(connection.id); assert.equal(result.shouldFallback, true); assert.ok(result.cooldownMs > 0); @@ -1003,21 +1009,18 @@ test("markAccountUnavailable reuses an existing Codex scope cooldown", async () }); const result = await auth.markAccountUnavailable( - (connection as any).id, + connection.id, 429, "quota reached", "codex", "codex-spark-mini" ); - const updated = await providersDb.getProviderConnectionById((connection as any).id); + const updated = await providersDb.getProviderConnectionById(connection.id); assert.equal(result.shouldFallback, true); assert.ok(result.cooldownMs > 0); assert.equal(updated.rateLimitedUntil, undefined); - (assert as any).equal( - (updated.providerSpecificData as any).codexScopeRateLimitedUntil.spark, - retryAfter - ); + assert.equal(updated.providerSpecificData.codexScopeRateLimitedUntil.spark, retryAfter); }); test("markAccountUnavailable uses a connection-wide cooldown for non-local 404 errors", async () => { @@ -1029,13 +1032,13 @@ test("markAccountUnavailable uses a connection-wide cooldown for non-local 404 e }); const result = await auth.markAccountUnavailable( - (connection as any).id, + connection.id, 404, "model not found", "openai", "gpt-missing" ); - const updated = await providersDb.getProviderConnectionById((connection as any).id); + const updated = await providersDb.getProviderConnectionById(connection.id); assert.equal(result.shouldFallback, true); assert.ok(result.cooldownMs > 0); @@ -1050,17 +1053,17 @@ test("markAccountUnavailable auto-disables permanently banned accounts when the }); const result = await auth.markAccountUnavailable( - (connection as any).id, + connection.id, 401, "Verify your account to continue", "openai", "gpt-4o" ); - const updated = await providersDb.getProviderConnectionById((connection as any).id); + const updated = await providersDb.getProviderConnectionById(connection.id); assert.equal(result.shouldFallback, true); assert.equal(updated.isActive, false); - assert.equal(updated.testStatus, "banned"); + assert.equal(updated.testStatus, "unavailable"); }); test("markAccountUnavailable leaves permanently banned accounts active when auto-disable is disabled", async () => { @@ -1070,17 +1073,17 @@ test("markAccountUnavailable leaves permanently banned accounts active when auto }); const result = await auth.markAccountUnavailable( - (connection as any).id, + connection.id, 401, "Verify your account to continue", "openai", "gpt-4o" ); - const updated = await providersDb.getProviderConnectionById((connection as any).id); + const updated = await providersDb.getProviderConnectionById(connection.id); assert.equal(result.shouldFallback, true); assert.equal(updated.isActive, true); - assert.equal(updated.testStatus, "banned"); + assert.equal(updated.testStatus, "unavailable"); }); test("markAccountUnavailable swallows auto-disable persistence errors", async () => { @@ -1114,17 +1117,17 @@ test("markAccountUnavailable swallows auto-disable persistence errors", async () try { const result = await auth.markAccountUnavailable( - (connection as any).id, + connection.id, 401, "Verify your account to continue", "openai", "gpt-4o" ); - const updated = await providersDb.getProviderConnectionById((connection as any).id); + const updated = await providersDb.getProviderConnectionById(connection.id); assert.equal(result.shouldFallback, true); assert.equal(updated.isActive, true); - assert.equal(updated.testStatus, "banned"); + assert.equal(updated.testStatus, "unavailable"); } finally { db.prepare = originalPrepare; } diff --git a/tests/unit/sse-parser.test.ts b/tests/unit/sse-parser.test.ts index 82b4fd655f..3d8bbfdf7f 100644 --- a/tests/unit/sse-parser.test.ts +++ b/tests/unit/sse-parser.test.ts @@ -114,6 +114,26 @@ test("parseSSEToClaudeResponse parses text, thinking, tool_use, and usage events assert.deepEqual(parsed.usage, { input_tokens: 10, output_tokens: 4 }); }); +test("parseSSEToClaudeResponse tolerates event-only types and missing blank separators", () => { + const rawSSE = [ + "event: message_start", + 'data: {"message":{"id":"msg_event_fallback","model":"claude-sonnet-4-6","role":"assistant","usage":{"input_tokens":3}}}', + "event: content_block_delta", + 'data: {"index":0,"delta":{"text":"event fallback ok"}}', + "event: message_delta", + 'data: {"delta":{"stop_reason":"end_turn"},"usage":{"output_tokens":2}}', + "event: message_stop", + "data: {}", + ].join("\n"); + + const parsed = parseSSEToClaudeResponse(rawSSE, "fallback-model"); + + assert.equal(parsed.id, "msg_event_fallback"); + assert.equal(parsed.model, "claude-sonnet-4-6"); + assert.equal((parsed.content[0] as any).text, "event fallback ok"); + assert.deepEqual(parsed.usage, { input_tokens: 3, output_tokens: 2 }); +}); + test("parseSSEToClaudeResponse ignores malformed payloads and returns null when nothing valid remains", () => { const parsed = parseSSEToClaudeResponse( ["event: content_block_delta", "data: not-json", "", "data: [DONE]"].join("\n"), diff --git a/tests/unit/stream-readiness.test.ts b/tests/unit/stream-readiness.test.ts index a86c37dd31..15eb22654d 100644 --- a/tests/unit/stream-readiness.test.ts +++ b/tests/unit/stream-readiness.test.ts @@ -3,6 +3,7 @@ import assert from "node:assert/strict"; import { ensureStreamReadiness, + hasStreamReadinessSignal, hasUsefulStreamContent, } from "../../open-sse/utils/streamReadiness.ts"; @@ -20,6 +21,46 @@ function streamFromChunks(chunks: string[], delayMs = 0): ReadableStream { + return new ReadableStream({ + async start(controller) { + controller.enqueue( + encoder.encode( + [ + "event: message_start", + `data: ${JSON.stringify({ + message: { + id: "msg_1", + type: "message", + role: "assistant", + model: "claude-sonnet-4-6", + usage: { input_tokens: 10, output_tokens: 0 }, + }, + })}`, + "", + ].join("\n") + ) + ); + + await new Promise((resolve) => setTimeout(resolve, 30)); + controller.enqueue( + encoder.encode( + [ + "event: content_block_delta", + `data: ${JSON.stringify({ + type: "content_block_delta", + index: 0, + delta: { type: "text_delta", text: "slow hello" }, + })}`, + "", + ].join("\n") + ) + ); + controller.close(); + }, + }); +} + test("hasUsefulStreamContent ignores keepalives and lifecycle-only chunks", () => { assert.equal(hasUsefulStreamContent(": keepalive\n\n"), false); assert.equal(hasUsefulStreamContent("event: ping\ndata: {}\n\n"), false); @@ -80,6 +121,51 @@ test("hasUsefulStreamContent detects text, reasoning, and tool deltas", () => { ); }); +test("hasStreamReadinessSignal accepts Claude stream start events", () => { + assert.equal(hasStreamReadinessSignal(": keepalive\n\n"), false); + assert.equal(hasStreamReadinessSignal("event: ping\ndata: {}\n\n"), false); + assert.equal( + hasStreamReadinessSignal(`data: ${JSON.stringify({ type: "response.created" })}\n\n`), + false + ); + assert.equal( + hasStreamReadinessSignal( + `event: message_start\ndata: ${JSON.stringify({ + type: "message_start", + message: { + id: "msg_1", + type: "message", + role: "assistant", + model: "claude-sonnet-4-6", + }, + })}\n\n` + ), + true + ); + assert.equal( + hasStreamReadinessSignal( + `event: message_start\ndata: ${JSON.stringify({ + message: { + id: "msg_2", + type: "message", + role: "assistant", + model: "claude-sonnet-4-6", + }, + })}\n\n` + ), + true + ); + assert.equal( + hasStreamReadinessSignal( + `event: content_block_start\ndata: ${JSON.stringify({ + index: 0, + content_block: { type: "text", text: "" }, + })}\n\n` + ), + true + ); +}); + test("ensureStreamReadiness preserves buffered chunks when stream starts", async () => { const response = new Response( streamFromChunks([ @@ -98,6 +184,23 @@ test("ensureStreamReadiness preserves buffered chunks when stream starts", async assert.match(text, / world/); }); +test("ensureStreamReadiness hands off long Claude streams after message_start", async () => { + const response = new Response(delayedClaudeStartStream(), { + status: 200, + headers: { "Content-Type": "text/event-stream" }, + }); + + const result = await ensureStreamReadiness(response, { + timeoutMs: 10, + provider: "anthropic-compatible-cc-test", + model: "claude-sonnet-4-6", + }); + assert.equal(result.ok, true); + const text = await result.response.text(); + assert.match(text, /message_start/); + assert.match(text, /slow hello/); +}); + test("ensureStreamReadiness returns 504 when no useful content arrives before timeout", async () => { const response = new Response( streamFromChunks( diff --git a/tests/unit/usage-service-hardening.test.ts b/tests/unit/usage-service-hardening.test.ts index 3b77cff9dd..3e2d19e404 100644 --- a/tests/unit/usage-service-hardening.test.ts +++ b/tests/unit/usage-service-hardening.test.ts @@ -1119,68 +1119,6 @@ test("usage service treats MiniMax token-plan counts as used usage", async () => assert.ok(Date.parse(usage.quotas["session (5h)"].resetAt) >= beforeCall + 240_000); }); -test("usage service parses Cursor team quotas and clamps on-demand ratio", async () => { - const calls: any[] = []; - globalThis.fetch = async (url, init = {}) => { - calls.push({ url: String(url), init }); - - if (String(url).endsWith("/api/usage")) { - return new Response( - JSON.stringify({ - numRequestsTotal: 450, - hard_limit: 100, - teamMaxRequestUsage: 500, - onDemand: { - numRequests: 600, - }, - }), - { status: 200 } - ); - } - - if (String(url).endsWith("/api/auth/me")) { - return new Response( - JSON.stringify({ - plan: "team", - teamInfo: { id: "team-1", name: "Core Team" }, - }), - { status: 200 } - ); - } - - if (String(url).endsWith("/api/subscription")) { - return new Response( - JSON.stringify({ - teamMaxMonthlyRequests: 500, - }), - { status: 200 } - ); - } - - throw new Error(`unexpected fetch: ${url}`); - }; - - const usage: any = await usageService.getUsageForProvider({ - provider: "cursor", - accessToken: "cursor-token", - }); - - assert.equal(calls.length, 3); - for (const call of calls) { - assert.equal(call.init.headers.Authorization, "Bearer cursor-token"); - assert.equal(call.init.headers["User-Agent"], "Cursor/3.3"); - assert.equal(call.init.headers["x-cursor-client-version"], "3.3"); - } - - assert.equal(usage.plan, "Cursor Team"); - assert.equal(usage.quotas.requests.total, 500); - assert.equal(usage.quotas.requests.used, 450); - assert.equal(usage.quotas.requests.remainingPercentage, 10); - assert.equal(usage.quotas.on_demand.total, 500); - assert.equal(usage.quotas.on_demand.used, 500); - assert.equal(usage.quotas.on_demand.remainingPercentage, 0); -}); - test("usage helper branches cover reset parsing, GitHub quota math, and plan inference fallbacks", () => { const fixedDate = new Date("2026-01-02T03:04:05.000Z"); @@ -1279,32 +1217,6 @@ test("usage helper branches cover reset parsing, GitHub quota math, and plan inf "Copilot Student" ); assert.equal(__testing.inferGitHubPlanName({}, null), "GitHub Copilot"); - - assert.deepEqual(__testing.buildCursorUsageHeaders("cursor-token"), { - Authorization: "Bearer cursor-token", - Accept: "application/json", - "User-Agent": "Cursor/3.3", - "x-cursor-client-version": "3.3", - "x-cursor-user-agent": "Cursor/3.3", - }); - assert.equal( - __testing.getCursorMonthlyRequestLimit( - { hard_limit: 100, teamMaxRequestUsage: 400 }, - { teamMaxMonthlyRequests: 500 } - ), - 500 - ); - assert.equal(__testing.getCursorOnDemandLimit({ onDemand: { maxRequests: 120 } }, {}), 120); - assert.deepEqual(__testing.formatCursorQuota(150, 100, null), { - used: 100, - total: 100, - remaining: 0, - remainingPercentage: 0, - resetAt: null, - unlimited: false, - }); - assert.equal(__testing.inferCursorPlanName({ teamInfo: { id: "team-1" } }, {}), "Cursor Team"); - assert.equal(__testing.inferCursorPlanName({ plan: "pro" }, {}), "Cursor Pro"); }); test("usage helper branches cover Gemini CLI and Antigravity plan label fallbacks", () => {