diff --git a/.agents/workflows/update-docs.md b/.agents/workflows/update-docs.md
deleted file mode 100644
index ab3bd26a2d..0000000000
--- a/.agents/workflows/update-docs.md
+++ /dev/null
@@ -1,105 +0,0 @@
----
-description: How to automatically summarize recent changes and update README and CHANGELOG
----
-
-# Update Documentation Workflow
-
-Update CHANGELOG.md, README.md, docs/ files, and all multi-language translations whenever features are added or changed.
-
-## Steps
-
-### 1. Summarize recent changes
-
-Review git log and identify new features, fixes, or changes since the last release tag:
-
-```bash
-git log $(git describe --tags --abbrev=0)..HEAD --oneline
-```
-
-### 2. Update English CHANGELOG.md
-
-Add an `[Unreleased]` section (or version header if releasing) with:
-
-- `### ✨ New Features` — each feature as a bullet point
-- `### 🐛 Bug Fixes` — if applicable
-- `### 🧪 Tests` — test count changes
-- `### 📁 New Files` — table of new files with purpose
-
-### 3. Update English README.md
-
-Update the feature tables in these sections:
-
-- **🧠 Routing & Intelligence** — for routing/model features
-- **🛡️ Resilience & Security** — for security/resilience features
-- **📊 Observability & Analytics** — for monitoring features
-- **☁️ Deploy & Sync** — for deployment features
-
-### 4. Update docs/ files
-
-- `docs/FEATURES.md` — update the Settings section description
-- `docs/API_REFERENCE.md` — add new API routes if any
-- `docs/ARCHITECTURE.md` — update architecture if structural changes
-
-### 5. 🌐 Sync Multi-Language Documentation (CRITICAL)
-
-// turbo-all
-
-**This step MUST be run after every README or docs update.**
-
-The project has **30 language versions** of documentation:
-
-**README files (root directory):**
-
-```
-README.md (English - source of truth)
-README.pt-BR.md README.pt.md README.es.md README.fr.md README.it.md
-README.de.md README.nl.md README.sv.md README.no.md README.da.md README.fi.md
-README.ru.md README.uk-UA.md README.bg.md README.sk.md README.pl.md README.ro.md README.hu.md
-README.ar.md README.he.md README.th.md README.in.md README.id.md README.ms.md README.vi.md
-README.ja.md README.ko.md README.zh-CN.md README.phi.md README.cs.md
-```
-
-**docs/i18n/ directories (29 languages):**
-
-```
-docs/i18n/{ar,bg,cs,da,de,es,fi,fr,he,hu,id,in,it,ja,ko,ms,nl,no,phi,pl,pt,pt-BR,ro,ru,sk,sv,th,uk-UA,vi,zh-CN}/
-Each contains: API_REFERENCE.md, ARCHITECTURE.md, CODEBASE_DOCUMENTATION.md, FEATURES.md, TROUBLESHOOTING.md, USER_GUIDE.md
-```
-
-**Sync approach for feature table updates:**
-
-a. Identify which feature table rows were added to English README.md
-b. For each translated README, find the corresponding anchor lines:
-
-- **Routing section:** Find the `💬` (System Prompt) table row — the line before it is always the last routing feature. Insert new routing features before System Prompt.
-- **Resilience section:** Find the `📊` Rate Limits table row (the one in lines 590-600, NOT the quota tracking one in lines 560-570). Insert new resilience features after it.
- c. The new feature entries can stay in English for technical features, matching the pattern used in the existing translations.
- d. Use `sed` or similar tool to batch-insert across all 29 translated READMEs.
-
-**Verification:**
-
-```bash
-# Verify all READMEs have the new features
-grep -l "NEW_FEATURE_NAME" README.*.md | wc -l
-# Should return 30 (all language versions)
-```
-
-**FEATURES.md sync:**
-
-```bash
-# Update Settings description in all docs/i18n/*/FEATURES.md
-for dir in docs/i18n/*/; do
- # Update the Settings section description to mention new features
- # Check FEATURES.md in each directory
-done
-```
-
-### 6. Verify documentation changes
-
-```bash
-# Check all modified files
-git status --short
-
-# Verify no broken markdown
-# Optional: run markdownlint if available
-```
diff --git a/.agents/workflows/version-bump.md b/.agents/workflows/version-bump.md
new file mode 100644
index 0000000000..4b3b77a921
--- /dev/null
+++ b/.agents/workflows/version-bump.md
@@ -0,0 +1,327 @@
+---
+description: Bump version, auto-generate CHANGELOG from git commits, update all versioned files, and refresh root + docs/ documentation to reflect the current project state
+---
+
+# Version Bump Workflow
+
+Automatically bump the project version, generate CHANGELOG entries from git history since the last tag, update every file that references the version, and refresh project documentation to reflect the current state.
+
+> **VERSION RULE: Always use PATCH bumps (3.x.y → 3.x.y+1)**
+> NEVER use `npm version minor` or `npm version major`.
+> Always use: `npm version patch --no-git-tag-version`
+> The threshold rule: when `y` reaches 10, bump to `3.(x+1).0` — e.g. `3.4.10` → `3.5.0`.
+
+---
+
+## Phase 1: Determine Version
+
+### 1. Read current version and last tag
+
+// turbo
+
+```bash
+cd /home/diegosouzapw/dev/proxys/9router
+CURRENT_VERSION=$(node -p "require('./package.json').version")
+LAST_TAG=$(git describe --tags --abbrev=0 2>/dev/null || echo "")
+CURRENT_BRANCH=$(git branch --show-current)
+echo "Current version: $CURRENT_VERSION"
+echo "Last tag: $LAST_TAG"
+echo "Current branch: $CURRENT_BRANCH"
+```
+
+### 2. Calculate new version
+
+Apply the patch bump rule:
+
+- If the current patch number is `9`, the new version is `3.(minor+1).0`
+- Otherwise, increment patch: `3.x.y` → `3.x.(y+1)`
+
+If the version was ALREADY bumped (e.g. you are on a release branch and package.json already has the new version), **skip the npm version bump** and use the existing version.
+
+### 3. Bump package.json (if needed)
+
+// turbo
+
+```bash
+# Only if version hasn't been bumped yet
+npm version patch --no-git-tag-version
+```
+
+Or for threshold (y=10):
+
+```bash
+# Manual threshold bump
+VERSION="3.X.0" # compute manually
+npm version "$VERSION" --no-git-tag-version
+```
+
+---
+
+## Phase 2: Generate CHANGELOG from Git History
+
+### 4. Collect commits since last tag
+
+// turbo
+
+```bash
+cd /home/diegosouzapw/dev/proxys/9router
+LAST_TAG=$(git describe --tags --abbrev=0 2>/dev/null)
+echo "=== Commits since $LAST_TAG ==="
+git log "$LAST_TAG"..HEAD --pretty=format:"%h %s" --no-merges | head -100
+echo ""
+echo "=== Merge commits ==="
+git log "$LAST_TAG"..HEAD --merges --pretty=format:"%h %s" | head -50
+```
+
+### 5. Classify commits and generate CHANGELOG section
+
+Analyze each commit message and classify into categories based on the conventional-commit prefix and content:
+
+| Category | Patterns |
+| ------------------- | ------------------------------------------------ |
+| ✨ New Features | `feat:`, `feat(*):` |
+| 🐛 Bug Fixes | `fix:`, `fix(*):` |
+| ⚠️ Breaking Changes | `BREAKING CHANGE`, `!:` suffix |
+| 🛠️ Maintenance | `chore:`, `refactor:`, `perf:`, `build:` |
+| 🧪 Tests | `test:`, `tests:` |
+| 📝 Documentation | `docs:` |
+| 🔒 Security | `security:`, CVE references, vulnerability fixes |
+| 🌍 i18n | translation updates, locale changes |
+
+For each category with entries, create a markdown section with descriptive bullet points. Use the commit messages but rewrite them to be human-readable and descriptive (not raw commit messages).
+
+**If a commit references a PR number** (e.g. `#880`, `PR #885`), include it in the description.
+
+### 6. Update CHANGELOG.md
+
+Replace the `## [Unreleased]` section content with the generated entries, then add the new versioned section:
+
+```markdown
+## [Unreleased]
+
+---
+
+## [NEW_VERSION] — YYYY-MM-DD
+
+### ✨ New Features
+
+- **Feature name:** Description (#PR)
+
+### 🐛 Bug Fixes
+
+- **Fix name:** Description (#PR)
+
+### 🛠️ Maintenance
+
+- **Item:** Description
+
+---
+
+## [PREVIOUS_VERSION] — YYYY-MM-DD
+
+...
+```
+
+The date must be today's date in `YYYY-MM-DD` format.
+
+---
+
+## Phase 3: Sync Version Across All Files
+
+### 7. Update workspace package.json files and openapi.yaml
+
+// turbo
+
+```bash
+cd /home/diegosouzapw/dev/proxys/9router
+VERSION=$(node -p "require('./package.json').version")
+
+# Update docs/openapi.yaml version
+sed -i "s/ version: .*/ version: $VERSION/" docs/openapi.yaml
+echo "✓ docs/openapi.yaml → $VERSION"
+
+# Update workspace packages (open-sse, electron)
+for dir in electron open-sse; do
+ if [ -d "$dir" ] && [ -f "$dir/package.json" ]; then
+ (cd "$dir" && npm version "$VERSION" --no-git-tag-version --allow-same-version > /dev/null)
+ echo "✓ $dir/package.json → $VERSION"
+ fi
+done
+
+echo "✓ All workspace packages synced to $VERSION"
+```
+
+### 8. Update llm.txt version references
+
+// turbo
+
+```bash
+cd /home/diegosouzapw/dev/proxys/9router
+VERSION=$(node -p "require('./package.json').version")
+OLD_VERSION_PATTERN='[0-9]\+\.[0-9]\+\.[0-9]\+'
+
+# Update "Current version:" line
+sed -i "s/\*\*Current version:\*\* $OLD_VERSION_PATTERN/**Current version:** $VERSION/" llm.txt
+
+# Update "Key Features (vX.Y.Z)" header
+sed -i "s/## Key Features (v$OLD_VERSION_PATTERN)/## Key Features (v$VERSION)/" llm.txt
+
+echo "✓ llm.txt → $VERSION"
+```
+
+### 9. Regenerate lock file
+
+// turbo
+
+```bash
+cd /home/diegosouzapw/dev/proxys/9router
+npm install
+echo "✓ Lock file regenerated"
+```
+
+---
+
+## Phase 4: Update Root Documentation
+
+Based on the CHANGELOG entries generated in Phase 2, review and update these root-level files if relevant changes warrant updates:
+
+### 10. Review and update root documentation files
+
+For each file below, read the current content and determine if the CHANGELOG entries require any updates. Only modify files where substantive changes have occurred:
+
+| File | When to update |
+| ----------------- | --------------------------------------------------------------------------------------------------------------------------- |
+| `README.md` | New providers, major features, stats changes (test count, provider count), badges, installation instructions, feature table |
+| `AGENTS.md` | Architecture changes, new modules, new commands, new providers, new services/handlers/executors |
+| `CONTRIBUTING.md` | Dev workflow changes, new tooling, test infrastructure changes |
+| `SECURITY.md` | Security fixes, new auth mechanisms, vulnerability disclosures |
+| `llm.txt` | Provider count changes, new features, architecture changes |
+
+**Update rules:**
+
+- **README.md**: Update provider count, test count, feature highlights table, badges if any numbers changed. If a new provider was added, add it to the provider table. If a major feature was added, add it to the features section.
+- **AGENTS.md**: If new architecture components (handlers, executors, services, DB modules) were added, update the Architecture section. If new commands were added, update the Build/Test table.
+- **SECURITY.md**: Add new vulnerability fixes or security improvements to the relevant section.
+- **llm.txt**: Update provider count, feature list, version references.
+
+### 11. Review and update docs/ files (excluding i18n/)
+
+For each file in `docs/` (excluding `docs/i18n/`), review if CHANGELOG changes affect it:
+
+| File | When to update |
+| -------------------------------- | --------------------------------------------------- |
+| `docs/API_REFERENCE.md` | New API endpoints, changed request/response formats |
+| `docs/ARCHITECTURE.md` | New modules, new services, changed data flow |
+| `docs/CLI-TOOLS.md` | New CLI tool integrations, config format changes |
+| `docs/FEATURES.md` | New features, removed features, changed settings |
+| `docs/MCP-SERVER.md` | New MCP tools, changed tool signatures |
+| `docs/A2A-SERVER.md` | New A2A skills, protocol changes |
+| `docs/USER_GUIDE.md` | UX changes, new dashboard pages, settings changes |
+| `docs/VM_DEPLOYMENT_GUIDE.md` | Deployment changes, new env vars |
+| `docs/TROUBLESHOOTING.md` | New known issues, resolved problems |
+| `docs/AUTO-COMBO.md` | Routing changes, new strategies |
+| `docs/CODEBASE_DOCUMENTATION.md` | New files, architectural changes |
+| `docs/RELEASE_CHECKLIST.md` | Process changes |
+| `docs/COVERAGE_PLAN.md` | Test changes |
+| `docs/openapi.yaml` | Already updated in step 7 |
+
+**Only update files where the CHANGELOG entries directly affect the documented content.** Do NOT update files just to bump a version number — only when the documented behavior, features, or architecture has actually changed.
+
+---
+
+## Phase 5: Verify
+
+### 12. Run lint check
+
+// turbo
+
+```bash
+cd /home/diegosouzapw/dev/proxys/9router
+npm run lint
+```
+
+### 13. Run tests
+
+// turbo
+
+```bash
+cd /home/diegosouzapw/dev/proxys/9router
+npm test
+```
+
+### 14. Verify version sync across all files
+
+// turbo
+
+```bash
+cd /home/diegosouzapw/dev/proxys/9router
+VERSION=$(node -p "require('./package.json').version")
+echo "Expected version: $VERSION"
+echo ""
+
+echo "--- package.json ---"
+grep '"version"' package.json | head -1
+
+echo "--- open-sse/package.json ---"
+grep '"version"' open-sse/package.json | head -1
+
+echo "--- electron/package.json ---"
+[ -f electron/package.json ] && grep '"version"' electron/package.json | head -1
+
+echo "--- docs/openapi.yaml ---"
+grep " version:" docs/openapi.yaml | head -1
+
+echo "--- llm.txt ---"
+grep "Current version:" llm.txt
+
+echo "--- CHANGELOG.md (first versioned entry) ---"
+grep "^## \[" CHANGELOG.md | head -2
+```
+
+### 15. 🛑 STOP — Present Summary to User
+
+**STOP** and present a summary to the user including:
+
+- Old version → New version
+- CHANGELOG entries generated
+- Files modified
+- Test results
+- Any documentation updates made
+
+**Wait for the user to confirm before committing.**
+
+---
+
+## Phase 6: Commit (only after user approval)
+
+### 16. Stage and commit
+
+// turbo-all
+
+```bash
+cd /home/diegosouzapw/dev/proxys/9router
+git add -A
+VERSION=$(node -p "require('./package.json').version")
+git commit -m "chore(release): bump to v$VERSION — changelog, docs, version sync"
+```
+
+---
+
+## Notes
+
+- This workflow does **NOT** create tags, releases, or deploy. Use `/generate-release` for the full release cycle after this.
+- This workflow does **NOT** update `docs/i18n/` translations. Use `/update-i18n` separately after committing.
+- The CHANGELOG generation is based on git commits since the last tag. If there are no new commits, the workflow should inform the user and stop.
+- Always verify the generated CHANGELOG entries make sense — raw commit messages may need rewriting for clarity.
+- If the version was already bumped (e.g. you're on a `release/vX.Y.Z` branch), skip the `npm version` step and use the existing version.
+
+## Version Touchpoints Checklist
+
+| File | Field/Pattern |
+| ----------------------- | ----------------------------------------------------------- |
+| `package.json` | `"version": "X.Y.Z"` |
+| `open-sse/package.json` | `"version": "X.Y.Z"` |
+| `electron/package.json` | `"version": "X.Y.Z"` |
+| `docs/openapi.yaml` | `version: X.Y.Z` |
+| `llm.txt` | `**Current version:** X.Y.Z` and `## Key Features (vX.Y.Z)` |
+| `CHANGELOG.md` | `## [X.Y.Z] — YYYY-MM-DD` |
diff --git a/.dockerignore b/.dockerignore
index 5b921cd983..9f7dea5a31 100644
--- a/.dockerignore
+++ b/.dockerignore
@@ -30,3 +30,40 @@ npm-debug.log*
yarn-debug.log*
yarn-error.log*
.pnpm-debug.log*
+
+# Test suites
+tests
+test-results
+playwright-report
+blob-report
+
+# Documentation (not needed in container)
+docs
+*.md
+!README.md
+
+# Electron (separate build)
+electron
+
+# VS Code extension (separate project)
+vscode-extension
+
+# Build artifacts
+*.tgz
+*.AppImage
+*.deb
+*.rpm
+
+# Package manager lock (bun)
+bun.lock
+
+# Agent config
+.agents
+.gemini
+
+# Misc
+llm.txt
+images
+clipr
+omnirouteCloud
+omnirouteSite
diff --git a/.env.example b/.env.example
index 00d3853846..a6c3713888 100644
--- a/.env.example
+++ b/.env.example
@@ -18,7 +18,8 @@ STORAGE_DRIVER=sqlite
# Generate with: openssl rand -hex 32
STORAGE_ENCRYPTION_KEY=
STORAGE_ENCRYPTION_KEY_VERSION=v1
-LOG_RETENTION_DAYS=90
+APP_LOG_RETENTION_DAYS=90
+CALL_LOG_RETENTION_DAYS=90
SQLITE_MAX_SIZE_MB=2048
SQLITE_CLEAN_LEGACY_FILES=true
DISABLE_SQLITE_AUTO_BACKUP=false
@@ -38,10 +39,10 @@ INSTANCE_NAME=omniroute
# Recommended security and ops variables
MACHINE_ID_SALT=endpoint-proxy-salt
-ENABLE_REQUEST_LOGS=false
AUTH_COOKIE_SECURE=false
REQUIRE_API_KEY=false
ALLOW_API_KEY_REVEAL=false
+PROVIDER_LIMITS_SYNC_INTERVAL_MINUTES=70
# Input Sanitizer (FASE-01 — prompt injection & PII protection)
# INPUT_SANITIZER_ENABLED=true
@@ -197,12 +198,15 @@ GEMINI_CLI_USER_AGENT=google-api-nodejs-client/9.15.1
# CORS_ORIGINS=*
# Logging
-# LOG_LEVEL=info
-# LOG_FORMAT=text
-LOG_TO_FILE=true
-# LOG_FILE_PATH=logs/application/app.log
-# LOG_MAX_FILE_SIZE=50M
-# LOG_RETENTION_DAYS=7
+# APP_LOG_LEVEL=info
+# APP_LOG_FORMAT=text
+APP_LOG_TO_FILE=true
+# APP_LOG_FILE_PATH=logs/application/app.log
+# APP_LOG_MAX_FILE_SIZE=50M
+# APP_LOG_RETENTION_DAYS=7
+# APP_LOG_MAX_FILES=20
+# CALL_LOG_RETENTION_DAYS=7
+# CALL_LOG_MAX_ENTRIES=10000
# ─────────────────────────────────────────────────────────────────────────────
# Memory Optimization (Low-RAM configurations)
@@ -221,6 +225,4 @@ LOG_TO_FILE=true
# SEMANTIC_CACHE_TTL_MS=1800000
# In-memory log buffers
-# PROXY_LOG_MAX_ENTRIES=200
-# CALL_LOGS_MAX=200
# STREAM_HISTORY_MAX=50
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 9d009ac268..3fbfe0d895 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -32,6 +32,46 @@ jobs:
- run: npm run typecheck:core
- run: npm run typecheck:noimplicit:core
+ i18n:
+ name: i18n Validation
+ runs-on: ubuntu-latest
+ continue-on-error: true
+ strategy:
+ fail-fast: false
+ matrix:
+ lang: ${{ fromJson(needs.i18n-matrix.outputs.langs) }}
+ needs: i18n-matrix
+ steps:
+ - uses: actions/checkout@v4
+ - uses: actions/setup-python@v6.2.0
+ with:
+ python-version: '3.12'
+ - name: Validate ${{ matrix.lang }}
+ run: |
+ echo "Validating language: ${{ matrix.lang }}"
+ python3 scripts/validate_translation.py quick -l '${{ matrix.lang }}'
+ - name: Report to summary
+ if: always()
+ run: |
+ echo "### ${{ matrix.lang }} Translation Report" >> $GITHUB_STEP_SUMMARY
+ echo '```' >> $GITHUB_STEP_SUMMARY
+ python3 scripts/validate_translation.py quick -l '${{ matrix.lang }}' >> $GITHUB_STEP_SUMMARY 2>&1
+ echo '```' >> $GITHUB_STEP_SUMMARY
+
+ i18n-matrix:
+ name: Build language matrix
+ runs-on: ubuntu-latest
+ outputs:
+ langs: ${{ steps.langs.outputs.langs }}
+ steps:
+ - uses: actions/checkout@v4
+ - name: Generate language list
+ id: langs
+ run: |
+ LANG_DIR="src/i18n/messages"
+ LANGS=$(ls "$LANG_DIR"/*.json | xargs -n1 basename | sed 's/.json$//' | grep -v '^en$' | jq -R . | jq -s . | jq -c .)
+ echo "langs=${LANGS}" >> $GITHUB_OUTPUT
+
security:
name: Security Audit
runs-on: ubuntu-latest
diff --git a/.gitignore b/.gitignore
index df550b50c9..f32c82f9a5 100644
--- a/.gitignore
+++ b/.gitignore
@@ -5,6 +5,12 @@
omnirouteCloud/
omnirouteSite/
+# Root-level underscore-prefixed directories (private/draft — never commit)
+/_*/
+
+# Draft features documentation (internal only)
+docs/new-features/
+
# dependencies
node_modules/
/.pnp
@@ -88,6 +94,7 @@ docs/*
!docs/AUTO-COMBO.md
!docs/MCP-SERVER.md
!docs/CLI-TOOLS.md
+!docs/COVERAGE_PLAN.md
# open-sse tests
@@ -137,4 +144,13 @@ vscode-extension/
/app
# IDEA
-.idea/
\ No newline at end of file
+.idea/
+
+# Local OpenCode agent config
+.config/
+
+# Empty/dangling files
+typescript
+
+# Gemini Antigravity agent data
+.gemini/
\ No newline at end of file
diff --git a/.npmignore b/.npmignore
index c11b218d07..bc60215011 100644
--- a/.npmignore
+++ b/.npmignore
@@ -26,14 +26,19 @@ scripts/
.github/
.husky/
.vscode/
+.agents/
.env*
eslint.config.mjs
prettier.config.mjs
postcss.config.mjs
next.config.mjs
tsconfig.json
+tsconfig.typecheck-core.json
+tsconfig.typecheck-noimplicit-core.json
playwright.config.ts
+vitest.config.ts
next-env.d.ts
+llm.txt
# Docker
docker-compose*.yml
@@ -41,8 +46,8 @@ Dockerfile
.dockerignore
# Misc
-restart.sh
AGENTS.md
+bun.lock
# Build artifacts (pre-built goes inside app/)
.next/
@@ -56,3 +61,9 @@ node_modules/
electron/
app/electron/
app/vscode-extension/
+
+# Subprojects
+clipr/
+omnirouteCloud/
+omnirouteSite/
+vscode-extension/
diff --git a/AGENTS.md b/AGENTS.md
index 52a5fcb6a5..62d4261222 100644
--- a/AGENTS.md
+++ b/AGENTS.md
@@ -3,162 +3,256 @@
## Project
Unified AI proxy/router — route any LLM through one endpoint. Multi-provider support
-(OpenAI, Anthropic, Gemini, DeepSeek, Groq, xAI, Mistral, Fireworks, Cohere, etc.)
-with **MCP Server** (16 tools for agent control) and **A2A v0.3 Protocol** (Agent-to-Agent orchestration).
+with **60+ providers** (OpenAI, Anthropic, Gemini, DeepSeek, Groq, xAI, Mistral, Fireworks,
+Cohere, NVIDIA, Cerebras, Pollinations, Puter, Cloudflare AI, HuggingFace, and many more)
+with **MCP Server** (25 tools), **A2A v0.3 Protocol**, and **Electron desktop app**.
## Stack
-- **Runtime**: Next.js 16 (App Router), Node.js, ES Modules
-- **Language**: TypeScript 5.9 (`src/`) + JavaScript (`open-sse/`)
+- **Runtime**: Next.js 16 (App Router), Node.js ≥18 <24, ES Modules (`"type": "module"`)
+- **Language**: TypeScript 5.9 (`src/`) + JavaScript (`open-sse/`, `electron/`)
- **Database**: better-sqlite3 (SQLite) — `DATA_DIR` configurable, default `~/.omniroute/`
-- **Streaming**: SSE via `open-sse` internal package
+- **Streaming**: SSE via `open-sse` internal workspace package
- **Styling**: Tailwind CSS v4
-- **Docker**: Multi-stage Dockerfile, 3 profiles (base / cli / host)
-- **i18n**: next-intl with 30 languages (`src/i18n/messages/`)
+- **i18n**: next-intl with 30 languages
+- **Desktop**: Electron (cross-platform: Windows, macOS, Linux)
+- **Schemas**: Zod v4 for all API / MCP input validation
+
+---
+
+## Build, Lint, and Test Commands
+
+| Command | Description |
+| ----------------------------------- | --------------------------------- |
+| `npm run dev` | Start Next.js dev server |
+| `npm run build` | Production build (isolated) |
+| `npm run start` | Run production build |
+| `npm run build:cli` | Build CLI package |
+| `npm run lint` | ESLint on all source files |
+| `npm run typecheck:core` | TypeScript core type checking |
+| `npm run typecheck:noimplicit:core` | Strict checking (no implicit any) |
+| `npm run check` | Run lint + test |
+| `npm run check:cycles` | Check for circular dependencies |
+| `npm run electron:dev` | Run Electron app in dev mode |
+| `npm run electron:build` | Build Electron app for current OS |
+
+### Running Tests
+
+```bash
+# All tests (unit + vitest + ecosystem + e2e)
+npm run test:all
+
+# Single test file (Node.js native test runner — most tests use this)
+node --import tsx/esm --test tests/unit/your-file.test.mjs
+node --import tsx/esm --test tests/unit/plan3-p0.test.mjs
+node --import tsx/esm --test tests/unit/fixes-p1.test.mjs
+node --import tsx/esm --test tests/unit/security-fase01.test.mjs
+
+# Integration tests
+node --import tsx/esm --test tests/integration/*.test.mjs
+
+# Vitest (MCP server, autoCombo)
+npm run test:vitest
+
+# E2E with Playwright
+npm run test:e2e
+
+# Protocol clients E2E (MCP transports, A2A)
+npm run test:protocols:e2e
+
+# Ecosystem compatibility tests
+npm run test:ecosystem
+
+# Coverage (55% min thresholds — statements, lines, functions; 60% branches)
+npm run test:coverage
+```
+
+---
+
+## Code Style Guidelines
+
+### Formatting (Prettier — enforced via lint-staged)
+
+2 spaces · semicolons required · double quotes (`"`) · 100 char width · es5 trailing commas.
+Always run `prettier --write` on changed files.
+
+### TypeScript
+
+- **Target**: ES2022 · **Module**: `esnext` · **Resolution**: `bundler`
+- `strict: false` — prefer explicit types, don't rely on inference
+- Path aliases: `@/*` → `src/`, `@omniroute/open-sse` → `open-sse/`, `@omniroute/open-sse/*` → `open-sse/*`
+
+### ESLint Rules
+
+- **Security (error, everywhere)**: `no-eval`, `no-implied-eval`, `no-new-func`
+- **Relaxed in `open-sse/` and `tests/`**: `@typescript-eslint/no-explicit-any` = warn
+- React hooks rules and `@next/next/no-assign-module-variable` disabled in `open-sse/` and `tests/`
+
+### Naming
+
+| Element | Convention | Example |
+| ------------------- | -------------------------------- | ------------------------------------ |
+| Files | camelCase / kebab-case | `chatCore.ts`, `tokenHealthCheck.ts` |
+| React components | PascalCase | `Dashboard.tsx`, `ProviderCard.tsx` |
+| Functions/variables | camelCase | `getHealth()`, `switchCombo()` |
+| Constants | UPPER_SNAKE | `MAX_RETRIES`, `DEFAULT_TIMEOUT` |
+| Interfaces | PascalCase (`I` prefix optional) | `ProviderConfig` |
+| Enums | PascalCase (members too) | `LogLevel.Error` |
+
+### Imports
+
+- **Order**: external → internal (`@/`, `@omniroute/open-sse`) → relative (`./`, `../`)
+- **No barrel imports** from `localDb.ts` — import from the specific `db/` module instead
+
+### Error Handling
+
+- try/catch with specific error types; always log with context (pino logger)
+- Never silently swallow errors in SSE streams — use abort signals for cleanup
+- Return proper HTTP status codes (4xx client, 5xx server)
+
+### Security
+
+- **NEVER** commit API keys, secrets, or credentials
+- Validate all user inputs with Zod schemas
+- Auth middleware required on all API routes
+- Never log SQLite encryption keys
+- Sanitize user content (dompurify for HTML)
+
+---
## Architecture
### Data Layer (`src/lib/db/`)
All persistence uses SQLite through domain-specific modules:
-
-| Module | Responsibility |
-| -------------- | ------------------------------------------ |
-| `core.ts` | SQLite engine, migrations, WAL, encryption |
-| `providers.ts` | Provider connections & nodes |
-| `models.ts` | Model aliases, MITM aliases, custom models |
-| `combos.ts` | Combo configurations |
-| `apiKeys.ts` | API key management & validation |
-| `settings.ts` | Settings, pricing, proxy config |
-| `backup.ts` | Backup / restore operations |
-
-`src/lib/localDb.ts` is a **re-export layer only** — all 27+ consumers import from it,
-but the real logic lives in `src/lib/db/`.
+`core.ts`, `providers.ts`, `models.ts`, `combos.ts`, `apiKeys.ts`, `settings.ts`,
+`backup.ts`, `proxies.ts`, `prompts.ts`, `webhooks.ts`, `detailedLogs.ts`,
+`domainState.ts`, `registeredKeys.ts`, `quotaSnapshots.ts`, `modelComboMappings.ts`,
+`cliToolState.ts`, `encryption.ts`, `readCache.ts`, `secrets.ts`, `stateReset.ts`.
+Schema migrations live in `db/migrations/` and run via `migrationRunner.ts`.
+`src/lib/localDb.ts` is a **re-export layer only** — never add logic there.
### Request Pipeline (`open-sse/`)
-| Handler | Role |
-| ----------------------- | ------------------------------------------- |
-| `chatCore.js` | Main chat completions proxy (SSE / non-SSE) |
-| `responsesHandler.js` | OpenAI Responses API compat |
-| `responseTranslator.js` | Format translation for Responses API |
-| `embeddings.js` | Embedding proxy |
-| `imageGeneration.js` | Image generation proxy |
-| `sseParser.js` | SSE stream parser |
-| `usageExtractor.js` | Token usage extraction from responses |
+`chatCore.ts` → executor → upstream provider. Translations in `open-sse/translator/`.
-Translation between provider formats: `open-sse/translator/`
+**Handlers** (`open-sse/handlers/`): `chatCore.ts`, `responsesHandler.ts`, `embeddings.ts`,
+`imageGeneration.ts`, `videoGeneration.ts`, `musicGeneration.ts`, `audioSpeech.ts`,
+`audioTranscription.ts`, `moderations.ts`, `rerank.ts`, `search.ts`.
-**Upstream model extra headers** (`compatByProtocol` / custom models): merged in executors after default auth; **same header name replaces** the executor value (e.g. custom `Authorization` overrides Bearer). In `open-sse/handlers/chatCore.ts`, the primary request merges headers for **both** the client model id and `resolveModelAlias(clientModel)` (resolved id wins on key conflicts). **T5 intra-family fallback** recomputes headers using only the fallback model id and `resolveModelAlias(fallback)` so sibling models do not inherit another model’s headers. Forbidden header names live in `src/shared/constants/upstreamHeaders.ts` — keep sanitize (`models.ts`), Zod (`schemas.ts`), and unit tests aligned when editing that list.
+**Upstream headers**: merged after default auth; same header name replaces executor value.
+**T5 intra-family fallback** recomputes headers using only the fallback model id.
+Forbidden header names: `src/shared/constants/upstreamHeaders.ts` — keep sanitize,
+Zod schemas, and unit tests aligned when editing.
+
+### Provider Categories
+
+- **Free** (4): Qoder AI, Qwen Code, Gemini CLI (deprecated), Kiro AI
+- **OAuth** (8): Claude Code, Antigravity, Codex, GitHub Copilot, Cursor, Kimi Coding, Kilo Code, Cline
+- **API Key** (48+): OpenAI, Anthropic, Gemini, DeepSeek, Groq, xAI, Mistral, Perplexity,
+ Together, Fireworks, Cerebras, Cohere, NVIDIA, Nebius, SiliconFlow, Hyperbolic,
+ HuggingFace, OpenRouter, Vertex AI, Cloudflare AI, Scaleway, AI/ML API, Pollinations,
+ Puter, Longcat, Alibaba, Kimi, Minimax, Blackbox, Synthetic, Kilo Gateway,
+ Z.AI, GLM, Deepgram, AssemblyAI, ElevenLabs, Cartesia, PlayHT, Inworld,
+ NanoBanana, SD WebUI, ComfyUI, Ollama Cloud, Perplexity Search, Serper, Brave, Exa,
+ Tavily, OpenCode Zen/Go, Bailian Coding Plan, and more.
+- **Custom**: OpenAI-compatible (`openai-compatible-*`) and Anthropic-compatible (`anthropic-compatible-*`) prefixes
+
+Providers are registered in `src/shared/constants/providers.ts` with Zod validation at module load.
+
+### Executors (`open-sse/executors/`)
+
+Provider-specific request executors: `base.ts`, `default.ts`, `cursor.ts`, `codex.ts`,
+`antigravity.ts`, `github.ts`, `gemini-cli.ts`, `kiro.ts`, `qoder.ts`, `vertex.ts`,
+`cloudflare-ai.ts`, `opencode.ts`, `pollinations.ts`, `puter.ts`.
+
+### Translator (`open-sse/translator/`)
+
+Translates between API formats (OpenAI-format ↔ Anthropic, Gemini, etc.).
+Includes request/response translators with helpers for image handling.
+
+### Transformer (`open-sse/transformer/`)
+
+`responsesTransformer.ts` — transforms Responses API format to/from Chat Completions format.
+
+### Services (`open-sse/services/`)
+
+36+ service modules including: `combo.ts` (routing engine), `usage.ts`, `tokenRefresh.ts`,
+`rateLimitManager.ts`, `accountFallback.ts`, `sessionManager.ts`, `wildcardRouter.ts`,
+`autoCombo/`, `intentClassifier.ts`, `taskAwareRouter.ts`, `thinkingBudget.ts`,
+`contextManager.ts`, `modelDeprecation.ts`, `modelFamilyFallback.ts`,
+`emergencyFallback.ts`, `workflowFSM.ts`, `backgroundTaskDetector.ts`, `ipFilter.ts`,
+`signatureCache.ts`, `volumeDetector.ts`, and more.
+
+### Domain Layer (`src/domain/`)
+
+Policy engine modules: `policyEngine.ts`, `comboResolver.ts`, `costRules.ts`,
+`degradation.ts`, `fallbackPolicy.ts`, `lockoutPolicy.ts`, `modelAvailability.ts`,
+`providerExpiration.ts`, `quotaCache.ts`, `responses.ts`, `configAudit.ts`.
### MCP Server (`open-sse/mcp-server/`)
-16 tools for AI agent control via **3 transport modes**:
+25 tools, 3 transports (stdio / SSE / Streamable HTTP). Scoped auth (10 scopes), Zod schemas.
-- **stdio** — Local IDE integration (Claude Desktop, Cursor, VS Code)
-- **SSE** — Remote Server-Sent Events at `/api/mcp/sse`
-- **Streamable HTTP** — Modern bidirectional HTTP at `/api/mcp/stream`
+**Core tools** (18): get_health, list_combos, get_combo_metrics, switch_combo, check_quota,
+route_request, cost_report, list_models_catalog, simulate_route, set_budget_guard,
+set_routing_strategy, set_resilience_profile, test_combo, get_provider_metrics,
+best_combo_for_task, explain_route, get_session_snapshot, sync_pricing.
-HTTP transports run in-process via `httpTransport.ts` singleton using `WebStandardStreamableHTTPServerTransport`.
+**Memory tools** (3): memory_search, memory_add, memory_clear.
-| Category | Tools |
-| --------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| Essential | `get_health`, `list_combos`, `get_combo_metrics`, `switch_combo`, `check_quota`, `route_request`, `cost_report`, `list_models_catalog` |
-| Advanced | `simulate_route`, `set_budget_guard`, `set_resilience_profile`, `test_combo`, `get_provider_metrics`, `best_combo_for_task`, `explain_route`, `get_session_snapshot` |
-
-- Scoped authorization (9 scopes), audit logging, Zod schemas
-- IDE configs for Claude Desktop, Cursor, VS Code Copilot
+**Skill tools** (4): skills_list, skills_enable, skills_execute, skills_executions.
### A2A Server (`src/lib/a2a/`)
-Agent-to-Agent v0.3 protocol:
+JSON-RPC 2.0, SSE streaming, Task Manager with TTL cleanup(
+Agent Card at `/.well-known/agent.json`.
+Skills: `quotaManagement.ts`, `smartRouting.ts`.
-- JSON-RPC 2.0: `message/send`, `message/stream`, `tasks/get`, `tasks/cancel`
-- Agent Card at `/.well-known/agent.json`
-- Skills: `smart-routing`, `quota-management`
-- SSE streaming with 15s heartbeat
-- Task Manager with state machine and TTL-based cleanup
+### ACP Module (`src/lib/acp/`)
-### Auto-Combo Engine (`open-sse/services/autoCombo/`)
+Agent Communication Protocol registry and manager.
-Self-healing routing optimization:
+### Memory System (`src/lib/memory/`)
-- 6-factor scoring, 4 mode packs, bandit exploration
-- Progressive cooldown, probe-based re-admission
+Extraction, injection, retrieval, summarization, and store modules for persistent
+conversational memory across sessions.
-### Dashboard (`src/app/(dashboard)/`)
+### Skills System (`src/lib/skills/`)
-| Page | Description |
-| ------------------------ | --------------------------------------------------------------- |
-| `/dashboard` | Home with quick start, provider overview |
-| `/dashboard/endpoint` | **Endpoints** (tabbed): Endpoint Proxy, MCP, A2A, API Endpoints |
-| `/dashboard/providers` | Provider management and connections |
-| `/dashboard/combos` | Combo configurations with routing strategies |
-| `/dashboard/logs` | Request, Proxy, Audit, Console logs (tabbed) |
-| `/dashboard/analytics` | Usage analytics and evaluations |
-| `/dashboard/costs` | Cost tracking and breakdown |
-| `/dashboard/health` | Uptime, circuit breakers, latency |
-| `/dashboard/cli-tools` | CLI tool integrations (Claude, Codex, Antigravity, etc.) |
-| `/dashboard/media` | Image, Video, Music generation playground |
-| `/dashboard/settings` | System settings with multiple tabs |
-| `/dashboard/api-manager` | API key management with model permissions |
+Extensible skill framework: registry, executor, sandbox, built-in skills,
+custom skill support, interception, and injection.
-### OAuth & Tokens (`src/lib/oauth/`)
+### Compliance (`src/lib/compliance/`)
-18 modules handling OAuth flows, token refresh, and provider credentials.
-Default credentials are hardcoded in `src/lib/oauth/constants/oauth.ts`,
-overridable via env vars or `data/provider-credentials.json`.
+Policy index for compliance enforcement.
-### Supporting Systems
+### MITM Proxy (`src/mitm/`)
-| System | Location |
-| -------------------------- | ------------------------------------------------- |
-| Usage tracking & analytics | `src/lib/usageDb.ts`, `src/lib/usageAnalytics.ts` |
-| Token health checks | `src/lib/tokenHealthCheck.ts` |
-| Cloud sync | `src/lib/cloudSync.ts` |
-| Proxy logging | `src/lib/proxyLogger.ts` |
-| Data paths resolution | `src/lib/dataPaths.ts` |
+MITM proxy capability with certificate management, DNS handling, and target routing.
+
+### Middleware (`src/middleware/`)
+
+Request middleware including `promptInjectionGuard.ts`.
### Adding a New Provider
1. Register in `src/shared/constants/providers.ts`
-2. Add executor in `open-sse/executors/`
-3. Add translator rules in `open-sse/translator/` (if non-OpenAI format)
+2. Add executor in `open-sse/executors/` (if custom logic needed)
+3. Add translator in `open-sse/translator/` (if non-OpenAI format)
4. Add OAuth config in `src/lib/oauth/constants/oauth.ts` (if OAuth-based)
+5. Add models in `open-sse/config/providerRegistry.ts`
+
+---
## Review Focus
-### Security
-
-- No hardcoded API keys or secrets in commits
-- Auth middleware on all API routes
-- Input validation on user-facing endpoints (Zod schemas)
-- SQLite encryption key must not be logged
-
-### Architecture
-
-- DB operations go through `src/lib/db/` modules, never raw SQL in routes
-- Provider requests flow through `open-sse/handlers/`
-- Translations use `open-sse/translator/` modules
-- `localDb.ts` is re-exports only — add new functions to the proper `db/*.ts` module
-- MCP and A2A pages are embedded as tabs inside `/dashboard/endpoint`, not standalone routes
-
-### Code Quality
-
-- Consistent error handling with try/catch
-- Proper HTTP status codes
-- No memory leaks in SSE streams (abort signals, cleanup)
-- Rate limit headers must be parsed correctly
-- All API inputs validated with Zod schemas
-
-### Docker
-
-- Dockerfile has two targets: `runner-base` and `runner-cli`
-- `docker-compose.yml` — development (3 profiles)
-- `docker-compose.prod.yml` — isolated production instance (port 20130)
-- Data persists in named volumes (`omniroute-data` / `omniroute-prod-data`)
-
-### Review Mode
-
-- Provide analysis and suggestions only
-- Focus on bugs, security, performance, and best practices
+- **DB ops** go through `src/lib/db/` modules, never raw SQL in routes
+- **Provider requests** flow through `open-sse/handlers/`
+- **MCP/A2A pages** are tabs inside `/dashboard/endpoint`, not standalone routes
+- **No memory leaks** in SSE streams (abort signals, cleanup)
+- **Rate limit headers** must be parsed correctly
+- All API inputs validated with **Zod schemas**
+- **Provider constants** validated at module load via Zod (`src/shared/validation/providerSchema.ts`)
+- **Pricing data** syncs from LiteLLM via `src/lib/pricingSync.ts`
+- **Memory/Skills** are cross-cutting: affect MCP tools, request pipeline, and A2A skills
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 6d1a354407..a6400e3eb6 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,6 +2,43 @@
## [Unreleased]
+### 🛠️ Maintenance
+
+- **AGENTS.md rewrite:** Condensed from 297→153 lines. Added build/lint/test commands (including single-test execution), code style guidelines (Prettier, TypeScript, ESLint, naming, imports, error handling, security), and trimmed verbose architecture tables for AI agent consumption.
+
+## [3.4.2] - 2026-04-01
+
+### ✨ New Features
+
+- **Antigravity Memory & Skills:** Completed remote memory and skills injection for the Antigravity provider at the proxy network level.
+- **Claude Code Compatibility:** Built a natively hidden compatibility bridge for Claude Code, passing tools and formatting through cleanly.
+- **Web Search MCP:** Added the `omniroute_web_search` tool with the `execute:search` scope.
+- **Cache Components:** Implemented dynamic cache components utilizing TDD.
+- **UI & Customization:** Added custom favicon support, appearance tabs, wired whitelabeling to the sidebar, and added Windsurf guide steps across all 33 languages.
+- **Log Retention:** Unified request log retention and artifacts natively.
+- **Model Enhancements:** Added explicit `contextLength` for all opencode-zen models.
+
+### 🐛 Bug Fixes
+
+- **Claude Image Passthrough:** Fixed Claude models missing image block passthroughs (#898).
+- **Gemini CLI Routing:** Resolved 403 authorization lockouts and content accumulation issues by refreshing the project ID via `loadCodeAssist` (#868).
+- **Antigravity Stability:** Corrected model access lists, enforced 404 lockouts, fixed 429 cascades locking out standard connections, and capped `gemini-3.1-pro` output tokens (#885).
+- **Provider Sync Cadence:** Repaired the provider limits synchronization cadence via the internal scheduler (#888).
+- **Dashboard Optimization:** Resolved `/dashboard/limits` UI freezing when processing 70+ accounts via chunk parallelization (#784).
+- **SSRF Hardening:** Enforced strict SSRF IP range filtering and blocked the `::1` loopback interface.
+- **MIME Types:** Standardized `mime_type` to snake_case to match Gemini API specifications.
+- **CI Stabilization:** Fixed failing analytics/settings Playwright selectors and request assertions so GitHub Actions E2E runs pass reliably across localized UIs and switch-based controls.
+- **Deterministic Tests:** Removed date-sensitive quota fixtures from Copilot usage tests and aligned idempotency/model catalog tests with the merged runtime behavior.
+- **MCP Type Hardening:** Removed zero-budget explicit `any` regressions from the MCP server tool registration path.
+
+### 🛠️ Maintenance
+
+- **Pipeline Logging:** Refined pipeline logging artifacts and enforce retention caps (#880).
+- **AGENTS.md Overhaul:** Condensed from 297→153 lines. Added build/test/style guidelines, code workflows (Prettier, TypeScript, ESLint), and trimmed verbose tables (#882).
+- **Release Branch Integration:** Consolidated the active feature branches into `release/v3.4.2` on top of current `main` and validated the branch with lint, unit, coverage, build, and CI-mode E2E runs.
+- **Testing:** Added vitest configuration for component testing and Playwright specs for settings toggles.
+- **Doc Updates:** Expanded root readmes, translated chinese documents natively, and cleaned up obsolete files.
+
## [3.4.1] - 2026-03-31
> [!WARNING]
@@ -41,10 +78,11 @@
- **Legacy Request Log Upgrade Backup:** Upgrades now archive old `data/logs/`, legacy `data/call_logs/`, and `data/log.txt` layouts into `DATA_DIR/log_archives/*.zip` before removing the deprecated structure.
- **Streaming Usage Persistence:** Streaming requests now write a single `usage_history` row on completion instead of emitting a duplicate in-progress usage row with empty status metadata.
+- **Logging Follow-up Cleanup:** Pipeline logs no longer capture `SOURCE REQUEST`, request artifact entries now honor `CALL_LOG_MAX_ENTRIES`, and application log archives now honor `APP_LOG_MAX_FILES`.
---
-## [3.3.11] - 2026-03-31
+## [3.4.0] - 2026-03-31
### 🚀 Features
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index c306f5894f..4ccd03bb42 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -8,7 +8,7 @@ Thank you for your interest in contributing! This guide covers everything you ne
### Prerequisites
-- **Node.js** 20+ (recommended: 22 LTS)
+- **Node.js** >= 18 < 24 (recommended: 22 LTS)
- **npm** 10+
- **Git**
@@ -33,13 +33,13 @@ echo "API_KEY_SECRET=$(openssl rand -hex 32)" >> .env
Key variables for development:
-| Variable | Development Default | Description |
-| ---------------------- | ----------------------- | ------------------------- |
-| `PORT` | `3000` | Server port |
-| `NEXT_PUBLIC_BASE_URL` | `http://localhost:3000` | Base URL for frontend |
-| `JWT_SECRET` | (generate above) | JWT signing secret |
-| `INITIAL_PASSWORD` | `123456` | First login password |
-| `ENABLE_REQUEST_LOGS` | `false` | Enable debug request logs |
+| Variable | Development Default | Description |
+| ---------------------- | ------------------------ | --------------------- |
+| `PORT` | `20128` | Server port |
+| `NEXT_PUBLIC_BASE_URL` | `http://localhost:20128` | Base URL for frontend |
+| `JWT_SECRET` | (generate above) | JWT signing secret |
+| `INITIAL_PASSWORD` | `CHANGEME` | First login password |
+| `APP_LOG_LEVEL` | `info` | Log verbosity level |
### Dashboard Settings
@@ -68,8 +68,8 @@ PORT=20128 NEXT_PUBLIC_BASE_URL=http://localhost:20128 npm run dev
Default URLs:
-- **Dashboard**: `http://localhost:3000/dashboard`
-- **API**: `http://localhost:3000/v1`
+- **Dashboard**: `http://localhost:20128/dashboard`
+- **API**: `http://localhost:20128/v1`
---
@@ -108,28 +108,35 @@ test: add observability unit tests
refactor(db): consolidate rate limit tables
```
-Scopes: `db`, `sse`, `oauth`, `dashboard`, `api`, `cli`, `docker`, `ci`.
+Scopes: `db`, `sse`, `oauth`, `dashboard`, `api`, `cli`, `docker`, `ci`, `mcp`, `a2a`, `memory`, `skills`.
---
## Running Tests
```bash
-# All unit tests
-npm test
-npm run test:unit
+# All tests (unit + vitest + ecosystem + e2e)
+npm run test:all
-# Specific test suites
-npm run test:security # Security tests
-npm run test:fixes # Fix verification tests
+# Single test file (Node.js native test runner — most tests use this)
+node --import tsx/esm --test tests/unit/your-file.test.mjs
-# With coverage
-npm run test:coverage
-npm run coverage:report
+# Vitest (MCP server, autoCombo, cache)
+npm run test:vitest
# E2E tests (requires Playwright)
npm run test:e2e
+# Protocol clients E2E (MCP transports, A2A)
+npm run test:protocols:e2e
+
+# Ecosystem compatibility tests
+npm run test:ecosystem
+
+# Coverage (55% min statements/lines/functions; 60% branches)
+npm run test:coverage
+npm run coverage:report
+
# Lint + format check
npm run lint
npm run check
@@ -140,25 +147,29 @@ Coverage notes:
- `npm run test:coverage` measures source coverage for the main unit test suite, excludes `tests/**`, and includes `open-sse/**`
- `npm run coverage:report` prints the detailed file-by-file report from the latest coverage run
- `npm run test:coverage:legacy` preserves the older metric for historical comparison
+- See `docs/COVERAGE_PLAN.md` for the phased coverage improvement roadmap
-Current test status: **968+ unit tests** covering:
+Current test status: **122 unit test files** covering:
- Provider translators and format conversion
- Rate limiting, circuit breaker, and resilience
- Semantic cache, idempotency, progress tracking
-- Database operations and schema
+- Database operations and schema (21 DB modules)
- OAuth flows and authentication
-- API endpoint validation
+- API endpoint validation (Zod v4)
+- MCP server tools and scope enforcement
+- Memory and Skills systems
---
## Code Style
- **ESLint** — Run `npm run lint` before committing
-- **Prettier** — Auto-formatted via `lint-staged` on commit
-- **TypeScript** — All `src/` code uses `.ts`/`.tsx`; document with TSDoc (`@param`, `@returns`, `@throws`)
+- **Prettier** — Auto-formatted via `lint-staged` on commit (2 spaces, semicolons, double quotes, 100 char width, es5 trailing commas)
+- **TypeScript** — All `src/` code uses `.ts`/`.tsx`; `open-sse/` uses `.ts`/`.js`; document with TSDoc (`@param`, `@returns`, `@throws`)
- **No `eval()`** — ESLint enforces `no-eval`, `no-implied-eval`, `no-new-func`
-- **Zod validation** — Use Zod schemas for API input validation
+- **Zod validation** — Use Zod v4 schemas for all API input validation
+- **Naming**: Files = camelCase/kebab-case, components = PascalCase, constants = UPPER_SNAKE
---
@@ -166,40 +177,60 @@ Current test status: **968+ unit tests** covering:
```
src/ # TypeScript (.ts / .tsx)
-├── app/ # Next.js App Router
-│ ├── (dashboard)/ # Dashboard pages (.tsx)
-│ ├── api/ # API routes (.ts)
+├── app/ # Next.js 16 App Router
+│ ├── (dashboard)/ # Dashboard pages (23 sections)
+│ ├── api/ # API routes (51 directories)
│ └── login/ # Auth pages (.tsx)
-├── domain/ # Domain types and response helpers (.ts)
+├── domain/ # Policy engine (policyEngine, comboResolver, costRules, etc.)
├── lib/ # Core business logic (.ts)
-│ ├── db/ # SQLite database layer
-│ ├── oauth/ # OAuth services per provider
-│ ├── cacheLayer.ts # LRU cache
-│ ├── semanticCache.ts # Semantic response cache
-│ ├── idempotencyLayer.ts # Request deduplication
-│ └── localDb.ts # Settings facade (LowDB for config, SQLite for domain data)
+│ ├── a2a/ # Agent-to-Agent v0.3 protocol server
+│ ├── acp/ # Agent Communication Protocol registry
+│ ├── compliance/ # Compliance policy engine
+│ ├── db/ # SQLite database layer (21 modules + 16 migrations)
+│ ├── memory/ # Persistent conversational memory
+│ ├── oauth/ # OAuth providers, services, and utilities
+│ ├── skills/ # Extensible skill framework
+│ ├── usage/ # Usage tracking and cost calculation
+│ └── localDb.ts # Re-export layer only — never add logic here
+├── middleware/ # Request middleware (promptInjectionGuard)
+├── mitm/ # MITM proxy (cert, DNS, target routing)
├── shared/
│ ├── components/ # React components (.tsx)
-│ ├── middleware/ # Correlation IDs, etc.
-│ ├── utils/ # Circuit breaker, sanitizer, etc.
-│ └── validation/ # Zod schemas
-└── sse/ # SSE chat handlers (.ts)
+│ ├── constants/ # Provider definitions (60+), MCP scopes, routing strategies
+│ ├── utils/ # Circuit breaker, sanitizer, auth helpers
+│ └── validation/ # Zod v4 schemas
+└── sse/ # SSE proxy pipeline
-open-sse/ # @omniroute/open-sse workspace (JavaScript)
-├── handlers/ # chatCore.js — main request handler
-├── services/ # Rate limit, fallback
-├── translators/ # Format converters (OpenAI ↔ Claude ↔ Gemini)
-└── utils/ # Progress tracker, stream helpers
+open-sse/ # @omniroute/open-sse workspace
+├── executors/ # 14 provider-specific request executors
+├── handlers/ # 11 request handlers (chat, responses, embeddings, images, etc.)
+├── mcp-server/ # MCP server (25 tools, 3 transports, 10 scopes)
+├── services/ # 36+ services (combo, autoCombo, rateLimitManager, etc.)
+├── translator/ # Format translators (OpenAI ↔ Claude ↔ Gemini ↔ Responses ↔ Ollama)
+├── transformer/ # Responses API transformer
+└── utils/ # 22 utility modules (stream, TLS, proxy, logging)
+
+electron/ # Electron desktop app (cross-platform)
tests/
-├── unit/ # Node.js test runner (.test.mjs)
-└── e2e/ # Playwright tests
+├── unit/ # Node.js test runner (122 test files)
+├── integration/ # Integration tests
+├── e2e/ # Playwright tests
+├── security/ # Security tests
+├── translator/ # Translator-specific tests
+└── load/ # Load tests
docs/ # Documentation
-├── USER_GUIDE.md # Provider setup, CLI integration
-├── API_REFERENCE.md # All endpoints
-├── TROUBLESHOOTING.md # Common issues
├── ARCHITECTURE.md # System architecture
+├── API_REFERENCE.md # All endpoints
+├── USER_GUIDE.md # Provider setup, CLI integration
+├── TROUBLESHOOTING.md # Common issues
+├── MCP-SERVER.md # MCP server (25 tools)
+├── A2A-SERVER.md # A2A agent protocol
+├── AUTO-COMBO.md # Auto-combo engine
+├── CLI-TOOLS.md # CLI tools integration
+├── COVERAGE_PLAN.md # Test coverage improvement plan
+├── openapi.yaml # OpenAPI specification
└── adr/ # Architecture Decision Records
```
@@ -207,50 +238,25 @@ docs/ # Documentation
## Adding a New Provider
-### Step 1: OAuth Service (if using OAuth)
+### Step 1: Register Provider Constants
-Create `src/lib/oauth/services/your-provider.ts` extending `OAuthService`:
+Add to `src/shared/constants/providers.ts` — Zod-validated at module load.
-```typescript
-import { OAuthService } from "../OAuthService";
+### Step 2: Add Executor (if custom logic needed)
-export class YourProviderService extends OAuthService {
- constructor() {
- super({
- name: "your-provider",
- authUrl: "https://provider.com/oauth/authorize",
- tokenUrl: "https://provider.com/oauth/token",
- clientId: "...",
- scopes: ["..."],
- });
- }
-}
-```
+Create executor in `open-sse/executors/your-provider.ts` extending the base executor.
-### Step 2: Register Provider
+### Step 3: Add Translator (if non-OpenAI format)
-Add to `src/lib/oauth/providers.ts`:
+Create request/response translators in `open-sse/translator/`.
-```typescript
-import { YourProviderService } from "./services/your-provider";
-// Add to the providers map
-```
+### Step 4: Add OAuth Config (if OAuth-based)
-### Step 3: Add Constants
+Add OAuth credentials in `src/lib/oauth/constants/oauth.ts` and service in `src/lib/oauth/services/`.
-Add provider constants in `src/lib/providerConstants.ts`:
+### Step 5: Register Models
-- Provider prefix (e.g., `yp/`)
-- Default models
-- Pricing info
-
-### Step 4: Add Translator (if non-OpenAI format)
-
-Create translator in `open-sse/translators/` if the provider uses a custom API format.
-
-### Step 5: Add Timeout
-
-Add request timeout configuration in `src/shared/utils/requestTimeout.ts`.
+Add model definitions in `open-sse/config/providerRegistry.ts`.
### Step 6: Add Tests
@@ -269,6 +275,7 @@ Write unit tests in `tests/unit/` covering at minimum:
- [ ] Build succeeds (`npm run build`)
- [ ] TypeScript types added for new public functions and interfaces
- [ ] No hardcoded secrets or fallback values
+- [ ] All inputs validated with Zod schemas
- [ ] CHANGELOG updated (if user-facing change)
- [ ] Documentation updated (if applicable)
@@ -276,16 +283,13 @@ Write unit tests in `tests/unit/` covering at minimum:
## Releasing
-When a new GitHub Release is created (e.g. `v0.4.0`), the package is **automatically published to npm** via GitHub Actions:
-
-```bash
-gh release create v0.4.0 --title "v0.4.0" --generate-notes
-```
+Releases are managed via the `/generate-release` workflow. When a new GitHub Release is created, the package is **automatically published to npm** via GitHub Actions.
---
## Getting Help
- **Architecture**: See [`docs/ARCHITECTURE.md`](docs/ARCHITECTURE.md)
+- **API Reference**: See [`docs/API_REFERENCE.md`](docs/API_REFERENCE.md)
- **Issues**: [github.com/diegosouzapw/OmniRoute/issues](https://github.com/diegosouzapw/OmniRoute/issues)
- **ADRs**: See `docs/adr/` for architectural decision records
diff --git a/README.ar.md b/README.ar.md
deleted file mode 100644
index 7543673d2a..0000000000
--- a/README.ar.md
+++ /dev/null
@@ -1,5 +0,0 @@
-# 🌐 OmniRoute (ar)
-
-The documentation has been formalized and moved to our centralized i18n structure.
-
-👉 **[Read the Documentation here](docs/i18n/ar/README.md)**
diff --git a/README.bg.md b/README.bg.md
deleted file mode 100644
index ace55dd961..0000000000
--- a/README.bg.md
+++ /dev/null
@@ -1,5 +0,0 @@
-# 🌐 OmniRoute (bg)
-
-The documentation has been formalized and moved to our centralized i18n structure.
-
-👉 **[Read the Documentation here](docs/i18n/bg/README.md)**
diff --git a/README.cs.md b/README.cs.md
deleted file mode 100644
index 2ea24f0434..0000000000
--- a/README.cs.md
+++ /dev/null
@@ -1,5 +0,0 @@
-# 🌐 OmniRoute (cs)
-
-The documentation has been formalized and moved to our centralized i18n structure.
-
-👉 **[Read the Documentation here](docs/i18n/cs/README.md)**
diff --git a/README.da.md b/README.da.md
deleted file mode 100644
index 5004128080..0000000000
--- a/README.da.md
+++ /dev/null
@@ -1,5 +0,0 @@
-# 🌐 OmniRoute (da)
-
-The documentation has been formalized and moved to our centralized i18n structure.
-
-👉 **[Read the Documentation here](docs/i18n/da/README.md)**
diff --git a/README.fi.md b/README.fi.md
deleted file mode 100644
index 72c81e0cb8..0000000000
--- a/README.fi.md
+++ /dev/null
@@ -1,5 +0,0 @@
-# 🌐 OmniRoute (fi)
-
-The documentation has been formalized and moved to our centralized i18n structure.
-
-👉 **[Read the Documentation here](docs/i18n/fi/README.md)**
diff --git a/README.he.md b/README.he.md
deleted file mode 100644
index 66366a95e7..0000000000
--- a/README.he.md
+++ /dev/null
@@ -1,5 +0,0 @@
-# 🌐 OmniRoute (he)
-
-The documentation has been formalized and moved to our centralized i18n structure.
-
-👉 **[Read the Documentation here](docs/i18n/he/README.md)**
diff --git a/README.hu.md b/README.hu.md
deleted file mode 100644
index 0d1bfec7ab..0000000000
--- a/README.hu.md
+++ /dev/null
@@ -1,5 +0,0 @@
-# 🌐 OmniRoute (hu)
-
-The documentation has been formalized and moved to our centralized i18n structure.
-
-👉 **[Read the Documentation here](docs/i18n/hu/README.md)**
diff --git a/README.id.md b/README.id.md
deleted file mode 100644
index 1a2a5e9ac0..0000000000
--- a/README.id.md
+++ /dev/null
@@ -1,5 +0,0 @@
-# 🌐 OmniRoute (id)
-
-The documentation has been formalized and moved to our centralized i18n structure.
-
-👉 **[Read the Documentation here](docs/i18n/id/README.md)**
diff --git a/README.in.md b/README.in.md
deleted file mode 100644
index 885c53aa12..0000000000
--- a/README.in.md
+++ /dev/null
@@ -1,5 +0,0 @@
-# 🌐 OmniRoute (in)
-
-The documentation has been formalized and moved to our centralized i18n structure.
-
-👉 **[Read the Documentation here](docs/i18n/in/README.md)**
diff --git a/README.ja.md b/README.ja.md
deleted file mode 100644
index 271a24496d..0000000000
--- a/README.ja.md
+++ /dev/null
@@ -1,5 +0,0 @@
-# 🌐 OmniRoute (ja)
-
-The documentation has been formalized and moved to our centralized i18n structure.
-
-👉 **[Read the Documentation here](docs/i18n/ja/README.md)**
diff --git a/README.ko.md b/README.ko.md
deleted file mode 100644
index dd32fb014e..0000000000
--- a/README.ko.md
+++ /dev/null
@@ -1,5 +0,0 @@
-# 🌐 OmniRoute (ko)
-
-The documentation has been formalized and moved to our centralized i18n structure.
-
-👉 **[Read the Documentation here](docs/i18n/ko/README.md)**
diff --git a/README.md b/README.md
index 0aba453e72..016444ee97 100644
--- a/README.md
+++ b/README.md
@@ -2,7 +2,7 @@
### Never stop coding. Smart routing to **FREE & low-cost AI models** with automatic fallback.
-_Your universal API proxy — one endpoint, 67+ providers, zero downtime. Now with **MCP & A2A** agent orchestration._
+_Your universal API proxy — one endpoint, 60+ providers, zero downtime. Now with **MCP Server (25 tools)**, **A2A Protocol**, **Memory/Skills Systems** & **Electron Desktop App**._
**Chat Completions • Embeddings • Image Generation • Video • Music • Audio • Reranking • **Web Search** • MCP Server • A2A Protocol • 100% TypeScript**
@@ -42,15 +42,17 @@ _Your universal API proxy — one endpoint, 67+ providers, zero downtime. Now wi
> - `APP_LOG_FILE_PATH`
> - `APP_LOG_MAX_FILE_SIZE`
> - `APP_LOG_RETENTION_DAYS`
+> - `APP_LOG_MAX_FILES`
> - `APP_LOG_LEVEL`
> - `APP_LOG_FORMAT`
> - `CALL_LOG_RETENTION_DAYS`
+> - `CALL_LOG_MAX_ENTRIES`
>
> For release details and upgrade notes, see the [CHANGELOG](CHANGELOG.md).
---
-## 🆕 What's New in v3.0.0
+## 🆕 What's New
> **Upgrading from v2.9.5?** — See the [full CHANGELOG](CHANGELOG.md#300--2026-03-22-release-candidate--not-yet-merged-to-main) for all changes.
@@ -268,9 +270,9 @@ Developers pay $20–200/month for Claude Pro, Codex Pro, or GitHub Copilot. Eve
**How OmniRoute solves it:**
- **Smart 4-Tier Fallback** — If subscription quota runs out, automatically redirects to API Key → Cheap → Free with zero manual intervention
-- **Real-Time Quota Tracking** — Shows token consumption in real-time with reset countdown (5h, daily, weekly)
+- **Provider Limits Tracking** — Cached quota snapshots refresh on a server-side schedule (default `PROVIDER_LIMITS_SYNC_INTERVAL_MINUTES=70`) with manual refresh available in the UI
- **Multi-Account Support** — Multiple accounts per provider with auto round-robin — when one runs out, switches to the next
-- **Custom Combos** — Customizable fallback chains with 6 balancing strategies (fill-first, round-robin, P2C, random, least-used, cost-optimized)
+- **Custom Combos** — Customizable fallback chains with 9 balancing strategies (priority, weighted, fill-first, round-robin, P2C, random, least-used, cost-optimized, strict-random)
- **Codex Business Quotas** — Business/Team workspace quota monitoring directly in the dashboard
@@ -282,7 +284,7 @@ OpenAI uses one format, Claude (Anthropic) uses another, Gemini yet another. If
**How OmniRoute solves it:**
-- **Unified Endpoint** — A single `http://localhost:20128/v1` serves as proxy for all 67+ providers
+- **Unified Endpoint** — A single `http://localhost:20128/v1` serves as proxy for all 60+ providers
- **Format Translation** — Automatic and transparent: OpenAI ↔ Claude ↔ Gemini ↔ Responses API
- **Response Sanitization** — Strips non-standard fields (`x_groq`, `usage_breakdown`, `service_tier`) that break OpenAI SDK v1.83+
- **Role Normalization** — Converts `developer` → `system` for non-OpenAI providers; `system` → `user` for GLM/ERNIE
@@ -368,7 +370,7 @@ Developers use Cursor, Claude Code, Codex CLI, OpenClaw, Gemini CLI, Kilo Code..
- **CLI Tools Dashboard** — Dedicated page with one-click setup for Claude Code, Codex CLI, OpenClaw, Kilo Code, Antigravity, Cline
- **GitHub Copilot Config Generator** — Generates `chatLanguageModels.json` for VS Code with bulk model selection
- **Onboarding Wizard** — Guided 4-step setup for first-time users
-- **One endpoint, all models** — Configure `http://localhost:20128/v1` once, access 67+ providers
+- **One endpoint, all models** — Configure `http://localhost:20128/v1` once, access 60+ providers
@@ -415,7 +417,7 @@ When a call fails, the dev doesn't know if it was a rate limit, expired token, w
- **SQLite Proxy Logs** — Persistent logs that survive server restarts
- **Translator Playground** — 4 debugging modes: Playground (format translation), Chat Tester (round-trip), Test Bench (batch), Live Monitor (real-time)
- **Request Telemetry** — p50/p95/p99 latency + X-Request-Id tracing
-- **File-Based Logging with Rotation** — Console interceptor captures everything to JSON log with size-based rotation
+- **File-Based Logging with Rotation** — App logs rotate by size, retention days, and archive count; call log artifacts rotate by retention days and file count
- **System Info Report** — `npm run system-info` generates `system-info.txt` with your full environment (Node version, OmniRoute version, OS, CLI tools, Docker/PM2 status). Attach it when reporting issues for instant triage.
@@ -510,7 +512,7 @@ Developers who want all responses in a specific language, with a specific tone,
- **System Prompt Injection** — Global prompt applied to all requests
- **Thinking Budget Validation** — Reasoning token allocation control per request (passthrough, auto, custom, adaptive)
-- **6 Routing Strategies** — Global strategies that determine how requests are distributed
+- **9 Routing Strategies** — Global strategies that determine how requests are distributed
- **Wildcard Router** — `provider/*` patterns route dynamically to any provider
- **Combo Enable/Disable Toggle** — Toggle combos directly from the dashboard
- **Provider Toggle** — Enable/disable all connections for a provider with one click
@@ -577,7 +579,7 @@ Different clients should have least-privilege access to tool categories.
**How OmniRoute solves it:**
-- 9 granular MCP scopes for controlled tool access
+- 10 granular MCP scopes for controlled tool access
- Scope enforcement and visibility in MCP management UI
- Safe default posture for operational tooling
@@ -1321,19 +1323,19 @@ OmniRoute v2.0 is built as an operational platform, not just a relay proxy.
### 🤖 Agent & Protocol Operations (v2.0)
-| Feature | What It Does |
-| ------------------------------------- | -------------------------------------------------------------------------------------------------- |
-| 🔧 **MCP Server (16 tools)** | IDE/agent tools via 3 transports: stdio, SSE (`/api/mcp/sse`), Streamable HTTP (`/api/mcp/stream`) |
-| 🤝 **A2A Server (JSON-RPC + SSE)** | Agent-to-agent task execution with sync and streaming flows |
-| 🧭 **Consolidated Endpoints Page** | Tabbed management page with Endpoint Proxy, MCP, A2A, and API Endpoints tabs |
-| 🎚️ **Service Enable/Disable Toggles** | ON/OFF switches for MCP and A2A with settings persistence (default: OFF) |
-| 🛰️ **MCP Runtime Heartbeat** | Real process status (pid, uptime, heartbeat age, transport, scope mode) |
-| 📋 **MCP Audit Trail** | Filterable audit logs with success/failure and key attribution |
-| 🔐 **MCP Scope Enforcement** | 9 granular scope permissions for controlled tool access |
-| 📡 **A2A Task Lifecycle Management** | List/filter tasks, inspect events/artifacts, cancel running tasks |
-| 📋 **Agent Card Discovery** | `/.well-known/agent.json` for client auto-discovery |
-| 🧪 **Protocol E2E Test Harness** | Real MCP SDK + A2A client flows in `test:protocols:e2e` |
-| ⚙️ **Operational Controls** | Switch combo, apply resilience profiles, reset breakers from one control surface |
+| Feature | What It Does |
+| ------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------- |
+| 🔧 **MCP Server (25 tools)** | IDE/agent tools via 3 transports: stdio, SSE (`/api/mcp/sse`), Streamable HTTP (`/api/mcp/stream`). 18 core + 3 memory + 4 skill tools |
+| 🤝 **A2A Server (JSON-RPC + SSE)** | Agent-to-agent task execution with sync and streaming flows |
+| 🧭 **Consolidated Endpoints Page** | Tabbed management page with Endpoint Proxy, MCP, A2A, and API Endpoints tabs |
+| 🎚️ **Service Enable/Disable Toggles** | ON/OFF switches for MCP and A2A with settings persistence (default: OFF) |
+| 🛰️ **MCP Runtime Heartbeat** | Real process status (pid, uptime, heartbeat age, transport, scope mode) |
+| 📋 **MCP Audit Trail** | Filterable audit logs with success/failure and key attribution |
+| 🔐 **MCP Scope Enforcement** | 10 granular scope permissions for controlled tool access |
+| 📡 **A2A Task Lifecycle Management** | List/filter tasks, inspect events/artifacts, cancel running tasks |
+| 📋 **Agent Card Discovery** | `/.well-known/agent.json` for client auto-discovery |
+| 🧪 **Protocol E2E Test Harness** | Real MCP SDK + A2A client flows in `test:protocols:e2e` |
+| ⚙️ **Operational Controls** | Switch combo, apply resilience profiles, reset breakers from one control surface |
### 🧠 Routing & Intelligence
@@ -1344,7 +1346,7 @@ OmniRoute v2.0 is built as an operational platform, not just a relay proxy.
| 🔄 **Format Translation** | OpenAI ↔ Claude ↔ Gemini ↔ Responses with schema-safe conversions |
| 👥 **Multi-Account Support** | Multiple accounts per provider with intelligent selection |
| 🔄 **Auto Token Refresh** | OAuth tokens refresh automatically with retry |
-| 🎨 **Custom Combos** | 6 balancing strategies + fallback chain control |
+| 🎨 **Custom Combos** | 9 balancing strategies + fallback chain control |
| 🌐 **Wildcard Router** | `provider/*` dynamic routing |
| 🧠 **Thinking Budget Controls** | Passthrough, auto, custom, and adaptive reasoning limits |
| 🔀 **Model Aliases** | Built-in + custom model aliasing and migration safety |
@@ -1945,6 +1947,7 @@ opencode
- Request artifacts are written to `DATA_DIR/call_logs/` as one JSON file per request
- Enable pipeline capture from Dashboard → Logs → Request Logs if you need detailed per-stage payloads
- Set `APP_LOG_TO_FILE=true` if you also want application console logs in `logs/application/app.log`
+- Adjust `APP_LOG_MAX_FILE_SIZE`, `APP_LOG_RETENTION_DAYS`, `APP_LOG_MAX_FILES`, and `CALL_LOG_MAX_ENTRIES` as needed
**Connection test shows "Invalid" for OpenAI-compatible providers**
diff --git a/README.ms.md b/README.ms.md
deleted file mode 100644
index c621bd73e0..0000000000
--- a/README.ms.md
+++ /dev/null
@@ -1,5 +0,0 @@
-# 🌐 OmniRoute (ms)
-
-The documentation has been formalized and moved to our centralized i18n structure.
-
-👉 **[Read the Documentation here](docs/i18n/ms/README.md)**
diff --git a/README.nl.md b/README.nl.md
deleted file mode 100644
index f7a878e69e..0000000000
--- a/README.nl.md
+++ /dev/null
@@ -1,5 +0,0 @@
-# 🌐 OmniRoute (nl)
-
-The documentation has been formalized and moved to our centralized i18n structure.
-
-👉 **[Read the Documentation here](docs/i18n/nl/README.md)**
diff --git a/README.no.md b/README.no.md
deleted file mode 100644
index 1db4066200..0000000000
--- a/README.no.md
+++ /dev/null
@@ -1,5 +0,0 @@
-# 🌐 OmniRoute (no)
-
-The documentation has been formalized and moved to our centralized i18n structure.
-
-👉 **[Read the Documentation here](docs/i18n/no/README.md)**
diff --git a/README.phi.md b/README.phi.md
deleted file mode 100644
index 57baa57a4f..0000000000
--- a/README.phi.md
+++ /dev/null
@@ -1,5 +0,0 @@
-# 🌐 OmniRoute (phi)
-
-The documentation has been formalized and moved to our centralized i18n structure.
-
-👉 **[Read the Documentation here](docs/i18n/phi/README.md)**
diff --git a/README.pl.md b/README.pl.md
deleted file mode 100644
index 7a2f9c9c70..0000000000
--- a/README.pl.md
+++ /dev/null
@@ -1,5 +0,0 @@
-# 🌐 OmniRoute (pl)
-
-The documentation has been formalized and moved to our centralized i18n structure.
-
-👉 **[Read the Documentation here](docs/i18n/pl/README.md)**
diff --git a/README.pt.md b/README.pt.md
deleted file mode 100644
index 8828324fa1..0000000000
--- a/README.pt.md
+++ /dev/null
@@ -1,2077 +0,0 @@
-# 🚀 OmniRoute — O gateway de IA gratuito
-
-### Nunca pare de codificar. Roteamento inteligente para **modelos de IA GRATUITOS e de baixo custo** com fallback automático.
-
-_Seu proxy de API universal — um endpoint, mais de 67 provedores, zero tempo de inatividade. Agora com orquestração de agentes **MCP e A2A**._
-
-**Conclusões de bate-papo • Incorporações • Geração de imagens • Vídeo • Música • Áudio • Reclassificação • **Pesquisa na Web** • Servidor MCP • Protocolo A2A • 100% TypeScript**
-
----
-
-
-
-[](https://www.npmjs.com/package/omniroute)
-[](https://www.npmjs.com/package/omniroute)
-[](https://hub.docker.com/r/diegosouzapw/omniroute)
-[](https://hub.docker.com/r/diegosouzapw/omniroute)
-[](https://github.com/diegosouzapw/OmniRoute/blob/main/LICENSE)
-[](https://omniroute.online)
-[](https://chat.whatsapp.com/JI7cDQ1GyaiDHhVBpLxf8b?mode=gi_t)
-
-[🌐 Website](https://omniroute.online) • [🚀 Quick Start](#-quick-start) • [💡 Features](#-key-features) • [📖 Docs](#-documentation) • [💰 Pricing](#-pricing-at-a-glance) • [💬 WhatsApp](https://chat.whatsapp.com/JI7cDQ1GyaiDHhVBpLxf8b?mode=gi_t)
-
-
-
-🌐 **Disponível em:** 🇺🇸 [English](README.md) | 🇧🇷 [Português (Brasil)](docs/i18n/pt-BR/README.md) | 🇪🇸 [Español](docs/i18n/es/README.md) | 🇫🇷 [Français](docs/i18n/fr/README.md) | 🇮🇹 [Italiano](docs/i18n/it/README.md) | 🇷🇺 [Русский](docs/i18n/ru/README.md) | 🇨🇳 [中文 (简体)](docs/i18n/zh-CN/README.md) | 🇩🇪 [Deutsch](docs/i18n/de/README.md) | 🇮🇳 [हिन्दी](docs/i18n/in/README.md) | 🇹🇭 [ไทย](docs/i18n/th/README.md) | 🇺🇦 [Українська](docs/i18n/uk-UA/README.md) | 🇸🇦 [العربية](docs/i18n/ar/README.md) | 🇯🇵 [日本語](docs/i18n/ja/README.md) | 🇻🇳 [Tiếng Việt](docs/i18n/vi/README.md) | 🇧🇬 [Български](docs/i18n/bg/README.md) | 🇩🇰 [Dansk](docs/i18n/da/README.md) | 🇫🇮 [Suomi](docs/i18n/fi/README.md) | 🇮🇱 [עברית](docs/i18n/he/README.md) | 🇭🇺 [Magyar](docs/i18n/hu/README.md) | 🇮🇩 [Bahasa Indonesia](docs/i18n/id/README.md) | 🇰🇷 [한국어](docs/i18n/ko/README.md) | 🇲🇾 [Bahasa Melayu](docs/i18n/ms/README.md) | 🇳🇱 [Nederlands](docs/i18n/nl/README.md) | 🇳🇴 [Norsk](docs/i18n/no/README.md) | 🇵🇹 [Português (Portugal)](docs/i18n/pt/README.md) | 🇷🇴 [Română](docs/i18n/ro/README.md) | 🇵🇱 [Polski](docs/i18n/pl/README.md) | 🇸🇰 [Slovenčina](docs/i18n/sk/README.md) | 🇸🇪 [Svenska](docs/i18n/sv/README.md) | 🇵🇭 [Filipino](docs/i18n/phi/README.md) | 🇨🇿 [Čeština](docs/i18n/cs/README.md)
-
----
-
-## 🆕 O que há de novo na v3.0.0
-
-> **Atualizando da v2.9.5?** — Consulte [full CHANGELOG](CHANGELOG.md#300--2026-03-22-release-candidate--not-yet-merged-to-main) para todas as alterações.
-
-| Área | Alterar |
-| ----------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| 🔒 **Segurança CodeQL** | Corrigidos mais de 10 alertas CodeQL: redos polinomiais, aleatoriedade insegura, remediação de injeção de shell |
-| ✅ **Validação de Rota** | Todas as 176 rotas de API agora validadas com esquemas Zod + `validateBody()` — CI `check:route-validation:t06` passa |
-| 🐛 ** Vazamento de tag omniModel ** | Tags internas `` não vazam mais para clientes em respostas de streaming SSE (#585) |
-| 🔑 **API de chaves registradas** | Provisionamento automático de chaves de API via `POST /api/v1/registered-keys` com aplicação de cota por provedor/conta, idempotência, armazenamento SHA-256 e relatório opcional de problemas do GitHub |
-| 👁️ **Scoped API Key Reveal** 🆕 | Opt-in recovery of API keys via `ALLOW_API_KEY_REVEAL` |
-| 🎨 **Ícones de provedor** | Mais de 130 logotipos de provedores via `@lobehub/icons` (SVG) com PNG → cadeia de fallback genérica |
-| 🔄 **Sincronização automática do modelo** | Agendador 24h e alternância manual da interface do usuário para sincronizar listas de modelos para provedores integrados e personalizados compatíveis com OpenAI |
-| 🌐 **OpenCode Zen/Go** | Dois novos provedores de @kang-heewon via PR #530: nível gratuito + nível de assinatura via `OpencodeExecutor` |
-| 🐛 **Gemini CLI OAuth** | Erro acionável quando `GEMINI_OAUTH_CLIENT_SECRET` está faltando no Docker (foi um erro enigmático do Google) |
-| 🐛 **Configuração OpenCode** | `saveOpenCodeConfig()` agora grava TOML corretamente em `XDG_CONFIG_HOME` |
-| 🐛 **Substituição de modelo fixado** | `body.model` definido corretamente como `pinnedModel` na proteção de cache de contexto |
-| 🐛 **Loop Codex/Claude** | `tool_result` blocos agora convertidos em texto para interromper loops infinitos |
-| 🐛 **Redirecionamento de login** | O login não congela mais após pular a configuração da senha |
-| 🐛 **Caminhos do Windows** | Caminhos MSYS2/Git-Bash (`/c/...`) normalizados para `C:\...` automaticamente |
-
----
-
-## 🖼️ Painel principal
-
-
-

-
-
----
-
-## 📸 Visualização do painel
-
-
-Clique para ver as capturas de tela do painel
-
-| Página | Captura de tela |
-| -------------------- | ------------------------------------------------- |
-| **Fornecedores** |  |
-| **Combos** |  |
-| **Análise** |  |
-| **Saúde** |  |
-| **Tradutor** |  |
-| **Configurações** |  |
-| **Ferramentas CLI** |  |
-| **Registros de uso** |  |
-| **Pontos finais** |  |
-
-
-
----
-
-### 🤖 Provedor de IA gratuito para seus agentes de codificação favoritos
-
-_Conecte qualquer ferramenta IDE ou CLI com tecnologia de IA por meio do OmniRoute - gateway de API gratuito para codificação ilimitada._
-
-
-
-📡 Todos os agentes se conectam via http://localhost:20128/v1 ou http://cloud.omniroute.online/v1 — uma configuração, modelos ilimitados e cota
-
----
-
-## 🤔 Por que OmniRoute?
-
-**Pare de desperdiçar dinheiro e atingir limites:**
-
--
A cota de assinatura expira sem ser utilizada todos os meses
--
Os limites de taxa impedem você de codificar no meio
--
APIs caras (US$ 20-50/mês por provedor)
--
Troca manual entre provedores
-
-**OmniRoute resolve isso:**
-
-- ✅ **Maximize as assinaturas** - Rastreie a cota, use cada bit antes de redefinir
-- ✅ **Fullback automático** - Assinatura → Chave de API → Barato → Gratuito, tempo de inatividade zero
-- ✅ **Múltiplas contas** - Round-robin entre contas por provedor
-- ✅ **Universal** - Funciona com Claude Code, Codex, Gemini CLI, Cursor, Cline, OpenClaw, qualquer ferramenta CLI
-
----
-
-## 📧 Suporte
-
-> 💬 **Junte-se à nossa comunidade!** [WhatsApp Group](https://chat.whatsapp.com/JI7cDQ1GyaiDHhVBpLxf8b?mode=gi_t) — Obtenha ajuda, compartilhe dicas e fique atualizado.
-
-- **Site**: [omniroute.online](https://omniroute.online)
-- **GitHub**: [github.com/diegosouzapw/OmniRoute](https://github.com/diegosouzapw/OmniRoute)
-- **Problemas**: [github.com/diegosouzapw/OmniRoute/issues](https://github.com/diegosouzapw/OmniRoute/issues)
-- **WhatsApp**: [Community Group](https://chat.whatsapp.com/JI7cDQ1GyaiDHhVBpLxf8b?mode=gi_t)
-- **Contribuindo**: Consulte [CONTRIBUTING.md](CONTRIBUTING.md), abra um PR ou escolha um `good first issue`
-- **Projeto Original**: [9router by decolua](https://github.com/decolua/9router)
-
-### 🐛 Relatando um bug?
-
-Ao abrir um problema, execute o comando system-info e anexe o arquivo gerado:
-
-```bash
-npm run system-info
-```
-
-Isso gera um `system-info.txt` com sua versão do Node.js, versão do OmniRoute, detalhes do sistema operacional, ferramentas CLI instaladas (qoder, gemini, claude, codex, antigravity, droid, etc.), status do Docker/PM2 e pacotes do sistema — tudo o que precisamos para reproduzir seu problema rapidamente. Anexe o arquivo diretamente ao seu problema do GitHub.
-
----
-
-## 🔄 Como funciona
-
-```
-┌─────────────┐
-│ Your CLI │ (Claude Code, Codex, Gemini CLI, OpenClaw, Cursor, Cline...)
-│ Tool │
-└──────┬──────┘
- │ http://localhost:20128/v1
- ↓
-┌─────────────────────────────────────────┐
-│ OmniRoute (Smart Router) │
-│ • Format translation (OpenAI ↔ Claude) │
-│ • Quota tracking + Embeddings + Images │
-│ • Auto token refresh │
-└──────┬──────────────────────────────────┘
- │
- ├─→ [Tier 1: SUBSCRIPTION] Claude Code, Codex, Gemini CLI
- │ ↓ quota exhausted
- ├─→ [Tier 2: API KEY] DeepSeek, Groq, xAI, Mistral, NVIDIA NIM, etc.
- │ ↓ budget limit
- ├─→ [Tier 3: CHEAP] GLM ($0.6/1M), MiniMax ($0.2/1M)
- │ ↓ budget limit
- └─→ [Tier 4: FREE] Qoder, Qwen, Kiro (unlimited)
-
-Result: Never stop coding, minimal cost
-```
-
----
-
-## 🎯 O que o OmniRoute resolve — 30 pontos reais de dor e casos de uso
-
-> **Todo desenvolvedor que usa ferramentas de IA enfrenta esses problemas diariamente.** O OmniRoute foi criado para resolver todos eles, desde custos excessivos até bloqueios regionais, desde fluxos quebrados de OAuth até operações de protocolo e observabilidade empresarial.
-
-
-💸 1. "Eu pago por uma assinatura cara, mas ainda sou interrompido pelos limites"
-
-Os desenvolvedores pagam US$ 20–200/mês pelo Claude Pro, Codex Pro ou GitHub Copilot. Mesmo pagando, a cota tem um limite máximo – 5h de uso, limites semanais ou limites de taxa por minuto. No meio da sessão de codificação, o provedor para de responder e o desenvolvedor perde fluxo e produtividade.
-
-**Como o OmniRoute resolve isso:**
-
-- **Smart 4-Tier Fallback** — Se a cota de assinatura acabar, redireciona automaticamente para API Key → Barato → Gratuito sem intervenção manual
-- **Rastreamento de cota em tempo real** — Mostra o consumo de tokens em tempo real com contagem regressiva redefinida (5h, diariamente, semanalmente)
-- **Suporte para múltiplas contas** — Várias contas por provedor com round-robin automático — quando uma acabar, muda para a próxima
-- **Combos personalizados** — Cadeias alternativas personalizáveis com 6 estratégias de balanceamento (preencher primeiro, round-robin, P2C, aleatório, menos usado, com custo otimizado)
-- **Codex Business Quotas** — Monitoramento de cotas de espaço de trabalho de negócios/equipe diretamente no painel
-
-
-
-
-🔌 2. "Preciso usar vários provedores, mas cada um tem uma API diferente"
-
-OpenAI usa um formato, Claude (Anthropic) usa outro, Gemini ainda outro. Se um desenvolvedor quiser testar modelos de diferentes provedores ou fazer fallback entre eles, ele precisará reconfigurar SDKs, alterar endpoints e lidar com formatos incompatíveis. Provedores personalizados (FriendLI, NIM) possuem endpoints de modelo não padrão.
-
-**Como o OmniRoute resolve isso:**
-
-- **Endpoint unificado** — Um único `http://localhost:20128/v1` serve como proxy para todos os mais de 67 provedores
-- **Tradução de formato** — Automática e transparente: OpenAI ↔ Claude ↔ Gemini ↔ API de respostas
-- **Response Sanitization** — Remove campos não padrão (`x_groq`, `usage_breakdown`, `service_tier`) que quebram o OpenAI SDK v1.83+
-- **Normalização de funções** — Converte `developer` → `system` para provedores não-OpenAI; `system` → `user` para GLM/ERNIE
-- **Think Tag Extraction** — Extrai blocos `` de modelos como DeepSeek R1 para `reasoning_content` padronizado
-- **Saída estruturada para Gemini** — `json_schema` → `responseMimeType`/`responseSchema` conversão automática
-- **`stream` o padrão é `false`** — Alinha-se com a especificação OpenAI, evitando SSE inesperado em SDKs Python/Rust/Go
-
-
-
-
-🌐 3. "Meu provedor de IA bloqueia minha região/país"
-
-Provedores como OpenAI/Codex bloqueiam o acesso de determinadas regiões geográficas. Os usuários recebem erros como `unsupported_country_region_territory` durante conexões OAuth e API. Isto é especialmente frustrante para desenvolvedores de países em desenvolvimento.
-
-**Como o OmniRoute resolve isso:**
-
-- **Configuração de proxy de 3 níveis** — Proxy configurável em 3 níveis: global (todo o tráfego), por provedor (apenas um provedor) e por conexão/chave
-- **Selos de proxy codificados por cores** — Indicadores visuais: 🟢 proxy global, 🟡 proxy do provedor, 🔵 proxy de conexão, sempre mostrando o IP
-- **Troca de token OAuth por meio de proxy** — O fluxo OAuth também passa pelo proxy, resolvendo `unsupported_country_region_territory`
-- **Testes de conexão via proxy** — Os testes de conexão usam o proxy configurado (não há mais bypass direto)
-- **Suporte SOCKS5** — Suporte completo ao proxy SOCKS5 para roteamento de saída
-- **TLS Fingerprint Spoofing** — Impressão digital TLS semelhante a um navegador via `wreq-js` para ignorar a detecção de bot
-- **🔏 CLI Fingerprint Matching** — Reordena cabeçalhos e campos de corpo para corresponder às assinaturas binárias CLI nativas, reduzindo drasticamente o risco de sinalização de conta. O IP do proxy é preservado – você obtém mascaramento de IP furtivo ** e ** simultaneamente
-
-
-
-
-🆓 4. "Quero usar IA para codificação, mas não tenho dinheiro"
-
-Nem todos podem pagar US$ 20–200/mês por assinaturas de IA. Estudantes, desenvolvedores de países emergentes, amadores e freelancers precisam de acesso a modelos de qualidade a custo zero.
-
-**Como o OmniRoute resolve isso:**
-
-- **Provedores de nível gratuito integrados** — Suporte nativo para provedores 100% gratuitos: Qoder (5 modelos ilimitados via OAuth: kimi-k2-thinking, qwen3-coder-plus, deepseek-r1, minimax-m2, kimi-k2), Qwen (4 modelos ilimitados: qwen3-coder-plus, qwen3-coder-flash, qwen3-coder-next, vision-model), Kiro (Claude + AWS Builder ID gratuitamente), Gemini CLI (180 mil tokens/mês grátis)
-- **Ollama Cloud** — Modelos Ollama hospedados na nuvem em `api.ollama.com` com nível gratuito de "uso leve"; use o prefixo `ollamacloud/`
-- **Combos somente gratuitos** — Cadeia `gc/gemini-3-flash → if/kimi-k2-thinking → qw/qwen3-coder-plus` = US$ 0/mês com tempo de inatividade zero
-- **NVIDIA NIM Free Access** — ~40 RPM de acesso gratuito para desenvolvedores para sempre a mais de 70 modelos em build.nvidia.com (transição de créditos para limites de taxa pura)
-- **Estratégia de Custo Otimizado** — Estratégia de roteamento que escolhe automaticamente o provedor mais barato disponível
-
-
-
-
-🔒 5. "Preciso proteger meu gateway de IA contra acesso não autorizado"
-
-Ao expor um gateway de IA à rede (LAN, VPS, Docker), qualquer pessoa com o endereço pode consumir os tokens/cota do desenvolvedor. Sem proteção, as APIs ficam vulneráveis ao uso indevido, injeção imediata e abuso.
-
-**Como o OmniRoute resolve isso:**
-
-- **Gerenciamento de chaves de API** — Geração, rotação e escopo por provedor com uma página `/dashboard/api-manager` dedicada
-- **Permissões em nível de modelo** — Restringir chaves de API a modelos específicos (`openai/*`, padrões curinga), com alternância Permitir tudo/Restringir
-- **API Endpoint Protection** — Exija uma chave para `/v1/models` e bloqueie provedores específicos da listagem
-- **Auth Guard + Proteção CSRF** — Todas as rotas do painel protegidas com middleware `withAuth` + tokens CSRF
-- **Rate Limiter** — Limitação de taxa por IP com janelas configuráveis
-- **Filtragem de IP** — Lista de permissões/lista de bloqueio para controle de acesso
-- **Prompt Injection Guard** — Sanitização contra padrões de prompt maliciosos
-- **Criptografia AES-256-GCM** — Credenciais criptografadas em repouso
-
-
-
-
-🛑 6. "Meu provedor caiu e perdi meu fluxo de codificação"
-
-Os provedores de IA podem ficar instáveis, retornar erros 5xx ou atingir limites de taxa temporários. Se um desenvolvedor depender de um único provedor, ele será interrompido. Sem disjuntores, tentativas repetidas podem travar o aplicativo.
-
-**Como o OmniRoute resolve isso:**
-
-- **Disjuntor por modelo** — Abertura/fechamento automático com limites configuráveis e resfriamento (Fechado/Aberto/Meio-aberto), com escopo definido por modelo para evitar bloqueios em cascata
-- **Retirada exponencial** — Atrasos progressivos em novas tentativas
-- **Rebanho Anti-Trovão** — Proteção Mutex + semáforo contra tempestades de novas tentativas simultâneas
-- **Combo Fallback Chains** — Se o provedor primário falhar, ele cairá automaticamente na cadeia sem intervenção
-- **Combo Circuit Breaker** — Desativa automaticamente provedores com falha em uma cadeia de combinação
-- **Health Dashboard** — Monitoramento de tempo de atividade, estados de disjuntores, bloqueios, estatísticas de cache, latência p50/p95/p99
-
-
-
-
-🔧 7. "Configurar cada ferramenta de IA é tedioso e repetitivo"
-
-Os desenvolvedores usam Cursor, Claude Code, Codex CLI, OpenClaw, Gemini CLI, Kilo Code... Cada ferramenta precisa de uma configuração diferente (endpoint da API, chave, modelo). Reconfigurar ao trocar de provedor ou modelo é uma perda de tempo.
-
-**Como o OmniRoute resolve isso:**
-
-- **CLI Tools Dashboard** — Página dedicada com configuração de um clique para Claude Code, Codex CLI, OpenClaw, Kilo Code, Antigravity, Cline
-- **GitHub Copilot Config Generator** — Gera `chatLanguageModels.json` para código VS com seleção de modelo em massa
-- **Assistente de integração** — Configuração guiada em 4 etapas para usuários iniciantes
-- **Um endpoint, todos os modelos** — Configure `http://localhost:20128/v1` uma vez, acesse mais de 67 provedores
-
-
-
-
-🔑 8. "Gerenciar tokens OAuth de vários provedores é um inferno"
-
-Claude Code, Codex, Gemini CLI, Copilot — todos usam OAuth 2.0 com tokens expirados. Os desenvolvedores precisam se autenticar novamente constantemente, lidar com `client_secret is missing`, `redirect_uri_mismatch` e falhas em servidores remotos. OAuth em LAN/VPS é particularmente problemático.
-
-**Como o OmniRoute resolve isso:**
-
-- **Atualização automática de token** — Os tokens OAuth são atualizados em segundo plano antes da expiração
-- **OAuth 2.0 (PKCE) integrado ** — Fluxo automático para Claude Code, Codex, Gemini CLI, Copilot, Kiro, Qwen, Qoder
-- **OAuth de várias contas** — Várias contas por provedor por meio de extração de token JWT/ID
-- **OAuth LAN/Remote Fix** — Detecção de IP privado para `redirect_uri` + modo URL manual para servidores remotos
-- **OAuth por trás do Nginx** — Usa `window.location.origin` para compatibilidade de proxy reverso
-- **Guia OAuth remoto** — Guia passo a passo para credenciais do Google Cloud em VPS/Docker
-
-
-
-
-📊 9. "Não sei quanto estou gastando ou onde"
-
-Os desenvolvedores usam vários provedores pagos, mas não têm uma visão unificada dos gastos. Cada provedor possui seu próprio painel de faturamento, mas não há visão consolidada. Custos inesperados podem se acumular.
-
-**Como o OmniRoute resolve isso:**
-
-- **Painel de análise de custos** — Acompanhamento de custos por token e gerenciamento de orçamento por provedor
-- **Limites de orçamento por nível** — Teto de gastos por nível que aciona substituto automático
-- **Configuração de preços por modelo** — Preços configuráveis por modelo
-- **Estatísticas de uso por chave de API** — Contagem de solicitações e carimbo de data/hora do último uso por chave
-- **Painel de análise** — Cartões de estatísticas, gráfico de uso do modelo, tabela de provedores com taxas de sucesso e latência
-
-
-
-
-🐛 10. "Não consigo diagnosticar erros e problemas em chamadas de IA"
-
-Quando uma chamada falha, o desenvolvedor não sabe se foi um limite de taxa, um token expirado, um formato errado ou um erro do provedor. Logs fragmentados em diferentes terminais. Sem observabilidade, a depuração é uma tentativa e erro.
-
-**Como o OmniRoute resolve isso:**
-
-- **Painel de registros unificados** — 4 guias: registros de solicitação, registros de proxy, registros de auditoria, console
-- **Console Log Viewer** — Visualizador em estilo terminal em tempo real com níveis codificados por cores, rolagem automática, pesquisa, filtro
-- **SQLite Proxy Logs** — Logs persistentes que sobrevivem às reinicializações do servidor
-- **Translator Playground** — 4 modos de depuração: Playground (tradução de formato), Chat Tester (ida e volta), Test Bench (lote), Live Monitor (tempo real)
-- **Solicitar telemetria** — latência p50/p95/p99 + rastreamento X-Request-Id
-- **Registro baseado em arquivo com rotação** — O interceptador do console captura tudo no log JSON com rotação baseada em tamanho
-- **Relatório de informações do sistema** — `npm run system-info` gera `system-info.txt` com seu ambiente completo (versão do nó, versão do OmniRoute, sistema operacional, ferramentas CLI, status do Docker/PM2). Anexe-o ao relatar problemas para triagem instantânea.
-
-
-
-
-🏗️ 11. "Implantar e manter o gateway é complexo"
-
-Instalar, configurar e manter um proxy de IA em diferentes ambientes (local, VPS, Docker, nuvem) exige muito trabalho. Problemas como caminhos codificados, `EACCES` em diretórios, conflitos de porta e compilações de plataforma cruzada adicionam atrito.
-
-**Como o OmniRoute resolve isso:**
-
-- **instalação global npm** — `npm install -g omniroute && omniroute` — concluído
-- **Docker Multiplataforma** — AMD64 + ARM64 nativo (Apple Silicon, AWS Graviton, Raspberry Pi)
-- **Perfis Docker Compose** — `base` (sem ferramentas CLI) e `cli` (com Claude Code, Codex, OpenClaw)
-- **Aplicativo Electron Desktop** — Aplicativo nativo para Windows/macOS/Linux com bandeja do sistema, inicialização automática e modo offline
-- **Modo Split-Port** — API e Dashboard em portas separadas para cenários avançados (proxy reverso, rede de contêineres)
-- **Cloud Sync** — Sincronização de configuração entre dispositivos via Cloudflare Workers
-- **Backups de banco de dados** — Backup, restauração, exportação e importação automática de todas as configurações
-
-
-
-
-🌍 12. "A interface é somente em inglês e minha equipe não fala inglês"
-
-Equipes em países que não falam inglês, especialmente na América Latina, Ásia e Europa, enfrentam dificuldades com interfaces somente em inglês. As barreiras linguísticas reduzem a adoção e aumentam os erros de configuração.
-
-**Como o OmniRoute resolve isso:**
-
-- **Painel i18n — 30 idiomas** — Todas as mais de 500 teclas traduzidas, incluindo árabe, búlgaro, dinamarquês, alemão, espanhol, finlandês, francês, hebraico, hindi, húngaro, indonésio, italiano, japonês, coreano, malaio, holandês, norueguês, polonês, português (PT/BR), romeno, russo, eslovaco, sueco, tailandês, ucraniano, vietnamita, chinês, filipino, inglês
-- **Suporte RTL** — Suporte da direita para a esquerda para árabe e hebraico
-- **READMEs multilíngues** — 30 traduções completas de documentação
-- **Seletor de idioma** — Ícone de globo no cabeçalho para troca em tempo real
-
-
-
-
-🔄 13. "Preciso de mais do que bate-papo - preciso de incorporações, imagens, áudio"
-
-IA não é apenas conclusão de bate-papo. Os desenvolvedores precisam gerar imagens, transcrever áudio, criar embeddings para RAG, reclassificar documentos e moderar conteúdo. Cada API possui um endpoint e formato diferente.
-
-**Como o OmniRoute resolve isso:**
-
-- **Embeddings** — `/v1/embeddings` com 6 provedores e mais de 9 modelos
-- **Geração de imagens** — `/v1/images/generations` com 10 provedores e mais de 20 modelos (OpenAI, xAI, Together, Fireworks, Nebius, Hyperbolic, NanoBanana, Antigravity, SD WebUI, ComfyUI)
-- **Texto para vídeo** — `/v1/videos/generations` — ComfyUI (AnimateDiff, SVD) e SD WebUI
-- **Texto para música** — `/v1/music/generations` — ComfyUI (áudio estável aberto, MusicGen)
-- **Transcrição de áudio** — `/v1/audio/transcriptions` — Whisper + Nvidia NIM, HuggingFace, Qwen3
-- **Conversão de texto em fala** — `/v1/audio/speech` — ElevenLabs, Nvidia NIM, HuggingFace, Coqui, Tortoise, Qwen3, **Inworld**, **Cartesia**, **PlayHT**, + provedores existentes
-- **Moderações** — `/v1/moderations` — Verificações de segurança de conteúdo
-- **Reclassificação** — `/v1/rerank` — Reclassificação da relevância do documento
-- **API de respostas** — Suporte completo a `/v1/responses` para Codex
-
-
-
-
-🧪 14. "Não tenho como testar e comparar a qualidade entre modelos"
-
-Os desenvolvedores querem saber qual modelo é melhor para seu caso de uso – código, tradução, raciocínio – mas comparar manualmente é lento. Não existem ferramentas de avaliação integradas.
-
-**Como o OmniRoute resolve isso:**
-
-- **Avaliações LLM** — Teste Golden Set com 10 casos pré-carregados cobrindo saudações, matemática, geografia, geração de código, conformidade com JSON, tradução, remarcação, recusa de segurança
-- **4 estratégias de correspondência** — `exact`, `contains`, `regex`, `custom` (função JS)
-- **Translator Playground Test Bench** — Teste em lote com múltiplas entradas e saídas esperadas, comparação entre fornecedores
-- **Testador de bate-papo** — Ida e volta completa com renderização de resposta visual
-- **Monitoramento ao vivo** — Transmissão em tempo real de todas as solicitações que passam pelo proxy
-
-
-
-
-📈 15. "Preciso escalar sem perder desempenho"
-
-À medida que o volume de solicitações aumenta, sem armazenar em cache as mesmas perguntas geram custos duplicados. Sem idempotência, solicitações duplicadas desperdiçam processamento. Os limites de tarifas por provedor devem ser respeitados.
-
-**Como o OmniRoute resolve isso:**
-
-- **Cache Semântico** — Cache de duas camadas (assinatura + semântica) reduz custo e latência
-- **Idempotência de solicitação** — janela de desduplicação de 5s para solicitações idênticas
-- **Detecção de limite de taxa** — RPM por provedor, intervalo mínimo e rastreamento simultâneo máximo
-- **Limites de taxa editáveis** — Padrões configuráveis em Configurações → Resiliência com persistência
-- **Cache de validação de chave de API** — cache de três camadas para desempenho de produção
-- **Health Dashboard com telemetria** — latência p50/p95/p99, estatísticas de cache, tempo de atividade
-
-
-
-
-🤖 16. "Quero controlar o comportamento do modelo globalmente"
-
-Desenvolvedores que desejam todas as respostas em um idioma específico, com um tom específico ou que desejam limitar os tokens de raciocínio. Configurar isso em cada ferramenta/solicitação é impraticável.
-
-**Como o OmniRoute resolve isso:**
-
-- **Injeção de Prompt do Sistema** — Prompt global aplicado a todas as solicitações
-- **Thinking Budget Validation** — Controle de alocação de token de raciocínio por solicitação (passthrough, automático, personalizado, adaptativo)
-- **6 Estratégias de Roteamento** — Estratégias globais que determinam como as solicitações são distribuídas
-- **Wildcard Router** — `provider/*` padrões roteiam dinamicamente para qualquer provedor
-- **Combo Habilitar/Desabilitar Alternar** — Alternar combos diretamente do painel
-- **Alternância de provedor** — Habilite/desabilite todas as conexões de um provedor com um clique
-- **Provedores bloqueados** — Excluir provedores específicos da listagem `/v1/models`
-
-
-
-
-🧰 17. "Preciso de ferramentas MCP como recursos de produto de primeira classe"
-
-Muitos gateways de IA expõem o MCP apenas como um detalhe de implementação oculto. As equipes precisam de uma camada operacional visível e gerenciável.
-
-**Como o OmniRoute resolve isso:**
-
-- MCP aparece na navegação do painel e na guia protocolo de endpoint
-- Página dedicada de gerenciamento de MCP com processos, ferramentas, escopos e auditoria
-- Início rápido integrado para `omniroute --mcp` e integração de cliente
-
-
-
-
-🧠 18. "Preciso de orquestração A2A com caminhos de tarefa de sincronização + fluxo"
-
-Os fluxos de trabalho do agente precisam de respostas diretas e execução em streaming de longa duração com controle do ciclo de vida.
-
-**Como o OmniRoute resolve isso:**
-
-- Endpoint A2A JSON-RPC (`POST /a2a`) com `message/send` e `message/stream`
-- Streaming SSE com propagação de estado terminal
-- APIs de ciclo de vida de tarefas para `tasks/get` e `tasks/cancel`
-
-
-
-
-🛰️ 19. "Preciso de integridade real do processo MCP, não de status adivinhado"
-
-As equipes operacionais precisam saber se o MCP está realmente ativo, e não apenas se uma API está acessível.
-
-**Como o OmniRoute resolve isso:**
-
-- Arquivo de pulsação em tempo de execução com PID, carimbos de data/hora, transporte, contagem de ferramentas e modo de escopo
-- API de status MCP combinando pulsação + atividade recente
-- Cartões de status da interface do usuário para atualização de processo/tempo de atividade/pulsação
-
-
-
-
-📋 20. "Preciso de execução auditável da ferramenta MCP"
-
-Quando as ferramentas alteram a configuração ou acionam ações operacionais, as equipes precisam de rastreabilidade forense.
-
-**Como o OmniRoute resolve isso:**
-
-- Registro de auditoria apoiado por SQLite para chamadas de ferramentas MCP
-- Filtros por ferramenta, sucesso/falha, chave de API e paginação
-- Tabela de auditoria do painel + endpoints de estatísticas para automação
-
-
-
-
-🔐 21. "Preciso de permissões MCP com escopo definido por integração"
-
-Clientes diferentes devem ter acesso com privilégios mínimos às categorias de ferramentas.
-
-**Como o OmniRoute resolve isso:**
-
-- 9 escopos MCP granulares para acesso controlado à ferramenta
-- Aplicação do escopo e visibilidade na UI de gerenciamento do MCP
-- Postura padrão segura para ferramentas operacionais
-
-
-
-
-⚙️ 22. "Preciso de controles operacionais sem reimplantar"
-
-As equipes precisam de mudanças rápidas no tempo de execução durante incidentes ou eventos de custo.
-
-**Como o OmniRoute resolve isso:**
-
-- Alternar ativação combinada diretamente do painel MCP
-- Aplicar perfis de resiliência de pacotes de políticas predefinidos
-- Redefinir o estado do disjuntor no mesmo painel de operações
-
-
-
-
-🔄 23. "Preciso de visibilidade e cancelamento do ciclo de vida da tarefa A2A ao vivo"
-
-Sem visibilidade do ciclo de vida, os incidentes de tarefas tornam-se difíceis de triagem.
-
-**Como o OmniRoute resolve isso:**
-
-- Listagem/filtragem de tarefas por estado/habilidade com paginação
-- Detalhamento de metadados de tarefas, eventos e artefatos
-- Terminal de cancelamento de tarefa e ação de UI com confirmação
-
-
-
-
-🌊 24. "Preciso de métricas de fluxo ativo para carga A2A"
-
-Os fluxos de trabalho de streaming exigem insights operacionais sobre simultaneidade e conexões em tempo real.
-
-**Como o OmniRoute resolve isso:**
-
-- Contadores de fluxo ativos integrados ao status A2A
-- Carimbo de data/hora da última tarefa e contagens por estado
-- Cartões de painel A2A para monitoramento de operações em tempo real
-
-
-
-
-🪪 25. "Preciso de descoberta de agente padrão para clientes"
-
-Clientes e orquestradores externos precisam de metadados legíveis por máquina para integração.
-
-**Como o OmniRoute resolve isso:**
-
-- Cartão do Agente exposto em `/.well-known/agent.json`
-- Capacidades e habilidades mostradas na UI de gerenciamento
-- A API de status A2A inclui metadados de descoberta para automação
-
-
-
-
-🧭 26. "Preciso de descoberta de protocolo na UX do produto"
-
-Se os usuários não conseguirem descobrir superfícies de protocolo, a adoção e a qualidade do suporte cairão.
-
-**Como o OmniRoute resolve isso:**
-
-- Página **Endpoints** consolidada com guias para Proxy, MCP, A2A e API Endpoints
-- Alterna o status do serviço inline (Online/Offline) para MCP e A2A
-- Links da visão geral para guias de gerenciamento dedicadas
-
-
-
-
-🧪 27. "Preciso de validação de protocolo ponta a ponta com clientes reais"
-
-Os testes simulados não são suficientes para validar a compatibilidade do protocolo antes do lançamento.
-
-**Como o OmniRoute resolve isso:**
-
-- Suíte E2E que inicializa o aplicativo e usa transporte de cliente SDK MCP real
-- Testes de cliente A2A para fluxos de descoberta, envio, streaming, obtenção e cancelamento
-- Verificação cruzada de afirmações com APIs de auditoria MCP e tarefas A2A
-
-
-
-
-📡 28. "Preciso de observabilidade unificada em todas as interfaces"
-
-A divisão da observabilidade por protocolo cria pontos cegos e MTTR mais longo.
-
-**Como o OmniRoute resolve isso:**
-
-- Painéis/logs/análises unificados em um produto
-- Saúde + auditoria + solicitação de telemetria nas camadas OpenAI, MCP e A2A
-- APIs operacionais para status e automação
-
-
-
-
-💼 29. "Preciso de um tempo de execução para proxy + ferramentas + orquestração de agente"
-
-A execução de muitos serviços separados aumenta o custo operacional e os modos de falha.
-
-**Como o OmniRoute resolve isso:**
-
-- Proxy compatível com OpenAI, servidor MCP e servidor A2A em uma pilha
-- Autenticação compartilhada, resiliência, armazenamento de dados e observabilidade
-- Modelo de política consistente em todas as superfícies de interação
-
-
-
-
-🚀 30. "Preciso enviar fluxos de trabalho de agente sem expansão de código cola"
-
-As equipes perdem velocidade ao unir vários serviços e scripts ad-hoc.
-
-**Como o OmniRoute resolve isso:**
-
-- Estratégia unificada de endpoint para clientes e agentes
-- UIs de gerenciamento de protocolo integradas e caminhos de validação de fumaça
-- Fundações prontas para produção (segurança, registro, resiliência, backup)
-
-
-
-### Exemplos de manuais (casos de uso integrados)
-
-**Manual A: Maximize a assinatura paga + backup barato**
-
-```txt
-Combo: "maximize-claude"
- 1. cc/claude-opus-4-6
- 2. glm/glm-4.7
- 3. if/kimi-k2-thinking
-
-Monthly cost: $20 + small backup spend
-Outcome: higher quality, near-zero interruption
-```
-
-**Manual B: Pilha de codificação de custo zero**
-
-```txt
-Combo: "free-forever"
- 1. gc/gemini-3-flash
- 2. if/kimi-k2-thinking
- 3. qw/qwen3-coder-plus
-
-Monthly cost: $0
-Outcome: stable free coding workflow
-```
-
-**Manual C: cadeia de fallback sempre ativa 24 horas por dia, 7 dias por semana**
-
-```txt
-Combo: "always-on"
- 1. cc/claude-opus-4-6
- 2. cx/gpt-5.2-codex
- 3. glm/glm-4.7
- 4. minimax/MiniMax-M2.1
- 5. if/kimi-k2-thinking
-
-Outcome: deep fallback depth for deadline-critical workloads
-```
-
-**Manual D: Operações de agente com MCP + A2A**
-
-```txt
-1) Start MCP transport (`omniroute --mcp`) for tool-driven operations
-2) Run A2A tasks via `message/send` and `message/stream`
-3) Observe via /dashboard/endpoint (MCP and A2A tabs)
-4) Toggle services via inline status controls
-```
-
----
-
-## 🆓 Comece de Graça — Custo Zero de Configuração
-
-> Configure a codificação de IA em minutos por **$0/mês**. Conecte essas contas gratuitas e use o combo **Free Stack** integrado.
-
-| Etapa | Ação | Provedores desbloqueados |
-| ----- | -------------------------------------------------- | ------------------------------------------------------------------ |
-| 1 | Conectar **Kiro** (ID do AWS Builder OAuth) | Claude Soneto 4.5, Haiku 4.5 — **ilimitado** |
-| 2 | Conecte **Qoder** (Google OAuth) | kimi-k2-thinking, qwen3-coder-plus, deepseek-r1... — **ilimitado** |
-| 3 | Conecte **Qwen** (código do dispositivo) | qwen3-coder-plus, qwen3-coder-flash... — **ilimitado** |
-| 4 | Conecte **Gemini CLI** (Google OAuth) | gemini-3-flash, gemini-2.5-pro — **180K/mês grátis** |
-| 5 | `/dashboard/combos` → **Pilha grátis ($0)** modelo | Round-robin todos os provedores gratuitos automaticamente |
-
-**Aponte qualquer IDE/CLI para:** `http://localhost:20128/v1` · Chave API: `any-string` · Concluído.
-
-> **Cobertura extra opcional (também gratuita):** Chave de API Groq (30 RPM grátis), NVIDIA NIM (40 RPM grátis, modelos com mais de 70), Cerebras (1 milhão de tok/dia), chave de API LongCat (50 milhões de tokens/dia!), Cloudflare Workers AI (10 mil neurônios/dia, mais de 50 modelos).
-
-## ⚡ Início rápido
-
-### 1) Instale e execute
-
-```bash
-npm install -g omniroute
-omniroute
-```
-
-> **usuários pnpm:** Execute `pnpm approve-builds -g` após a instalação para ativar scripts de construção nativos exigidos por `better-sqlite3` e `@swc/core`:
->
-> ```bash
-> pnpm install -g omniroute
-> pnpm approve-builds -g # Select all packages → approve
-> omniroute
-> ```
-
-O painel abre em `http://localhost:20128` e o URL base da API é `http://localhost:20128/v1`.
-
-| Comando | Descrição |
-| ----------------------- | --------------------------------------------------------------- |
-| `omniroute` | Iniciar servidor (`PORT=20128`, API e dashboard na mesma porta) |
-| `omniroute --port 3000` | Defina a porta canônica/API como 3000 |
-| `omniroute --mcp` | Inicie o servidor MCP (transporte stdio) |
-| `omniroute --no-open` | Não abra o navegador automaticamente |
-| `omniroute --help` | Mostrar ajuda |
-
-Modo de porta dividida opcional:
-
-```bash
-PORT=20128 DASHBOARD_PORT=20129 omniroute
-# API: http://localhost:20128/v1
-# Dashboard: http://localhost:20129
-```
-
-### 2) Conecte provedores e crie sua chave API
-
-1. Abra Dashboard → `Providers` e conecte pelo menos um provedor (OAuth ou chave API).
-2. Abra Dashboard → `Endpoints` e crie uma chave API.
-3. (Opcional) Abra Dashboard → `Combos` e defina sua cadeia de fallback.
-
-### 3) Aponte sua ferramenta de codificação para OmniRoute
-
-```txt
-Base URL: http://localhost:20128/v1
-API Key: [copy from Endpoint page]
-Model: if/kimi-k2-thinking (or any provider/model prefix)
-```
-
-Funciona com Claude Code, Codex CLI, Gemini CLI, Cursor, Cline, OpenClaw, OpenCode e SDKs compatíveis com OpenAI.
-
-### 4) Habilitar e validar protocolos (v2.0)
-
-**MCP (para operações orientadas por ferramentas):**
-
-```bash
-omniroute --mcp
-```
-
-Em seguida, conecte seu cliente MCP em `stdio` e teste ferramentas como:
-
-- `omniroute_get_health`
-- `omniroute_list_combos`
-
-**A2A (para fluxos de trabalho entre agentes):**
-
-```bash
-curl http://localhost:20128/.well-known/agent.json
-```
-
-```bash
-curl -X POST http://localhost:20128/a2a \
- -H 'content-type: application/json' \
- -d '{"jsonrpc":"2.0","id":"quickstart","method":"message/send","params":{"skill":"quota-management","messages":[{"role":"user","content":"Give me a short quota summary."}]}}'
-```
-
-### 5) Valide tudo de ponta a ponta (recomendado)
-
-```bash
-npm run test:protocols:e2e
-```
-
-Este conjunto valida fluxos reais de clientes MCP e A2A em um aplicativo em execução.
-
-### Alternativa: executar a partir da fonte
-
-```bash
-cp .env.example .env
-npm install
-PORT=20128 DASHBOARD_PORT=20129 NEXT_PUBLIC_BASE_URL=http://localhost:20129 npm run dev
-```
-
----
-
-## 🐳 Docker
-
-OmniRoute está disponível como uma imagem pública do Docker em [Docker Hub](https://hub.docker.com/r/diegosouzapw/omniroute).
-
-**Execução rápida:**
-
-```bash
-docker run -d \
- --name omniroute \
- --restart unless-stopped \
- -p 20128:20128 \
- -v omniroute-data:/app/data \
- diegosouzapw/omniroute:latest
-```
-
-**Com arquivo de ambiente:**
-
-```bash
-# Copy and edit .env first
-cp .env.example .env
-
-docker run -d \
- --name omniroute \
- --restart unless-stopped \
- --env-file .env \
- -p 20128:20128 \
- -v omniroute-data:/app/data \
- diegosouzapw/omniroute:latest
-```
-
-**Usando Docker Compose:**
-
-```bash
-# Base profile (no CLI tools)
-docker compose --profile base up -d
-
-# CLI profile (Claude Code, Codex, OpenClaw built-in)
-docker compose --profile cli up -d
-```
-
-| Imagem | Etiqueta | Tamanho | Descrição |
-| ------------------------ | -------- | ------- | --------------------- |
-| `diegosouzapw/omniroute` | `latest` | ~250 MB | Última versão estável |
-| `diegosouzapw/omniroute` | `1.0.3` | ~250 MB | Versão atual |
-
----
-
-## 🖥️ Aplicativo de desktop – off-line e sempre ativo
-
-> 🆕 **NOVO!** OmniRoute agora está disponível como um **aplicativo de desktop nativo** para Windows, macOS e Linux.
-
-Execute o OmniRoute como um aplicativo de desktop independente — sem terminal, sem navegador, sem necessidade de internet para modelos locais. O aplicativo baseado em Electron inclui:
-
-- 🖥️ **Janela Nativa** — Janela de aplicativo dedicada com integração na bandeja do sistema
-- 🔄 **Início automático** — Inicie o OmniRoute no login do sistema
-- 🔔 **Notificações nativas** — Receba alertas sobre esgotamento de cota ou problemas com o provedor
-- ⚡ **Instalação com um clique** — NSIS (Windows), DMG (macOS), AppImage (Linux)
-- 🌐 **Modo offline** — Funciona totalmente offline com servidor incluído
-
-### Início rápido
-
-```bash
-# Development mode
-npm run electron:dev
-
-# Build for your platform
-npm run electron:build # Current platform
-npm run electron:build:win # Windows (.exe)
-npm run electron:build:mac # macOS (.dmg) — x64 & arm64
-npm run electron:build:linux # Linux (.AppImage)
-```
-
-### Bandeja do sistema
-
-Quando minimizado, o OmniRoute fica na bandeja do sistema com ações rápidas:
-
-- Abra o painel
-- Alterar porta do servidor
-- Sair do aplicativo
-
-📖 Documentação completa: [**OMNI_TOKEN_153**](electron/README.md)
-
----
-
-## 💰 Visão geral dos preços
-
-| Nível | Provedor | Custo | Redefinição de cota | Melhor para |
-| ------------------- | ------------------------------------- | -------------------------------------- | ------------------------ | ----------------------------------------------- |
-| **💳 ASSINATURA** | Código Claude (Pro) | $ 20/mês | 5h + semanalmente | Já inscrito |
-| | Códice (Plus/Pro) | US$ 20-200/mês | 5h + semanalmente | Usuários OpenAI |
-| | Gêmeos CLI | **GRÁTIS** | 180 mil/mês + 1 mil/dia | Todos! |
-| | Copiloto GitHub | US$ 10-19/mês | Mensalmente | Usuários do GitHub |
-| **🔑 CHAVE DE API** | NVIDIA NIM | **GRÁTIS** (desenvolvedor para sempre) | ~40RPM | Mais de 70 modelos abertos |
-| | Cérebros | **GRÁTIS** (1 milhão de tok/dia) | 60KTPM/30RPM | O mais rápido do mundo |
-| | Groq | **GRÁTIS** (30 RPM) | RPD de 14,4K | Lhama/Gemma ultrarrápida |
-| | DeepSeek V3.2 | US$ 0,27/US$ 1,10 por 1 milhão | Nenhum | Melhor raciocínio preço/qualidade |
-| | xAI Grok-4 Rápido | **$0,20/$0,50 por 1 milhão** 🆕 | Nenhum | Chamada de ferramenta mais rápida +, ultrabaixa |
-| | xAI Grok-4 (padrão) | US$ 0,20/US$ 1,50 por 1 milhão 🆕 | Nenhum | Carro-chefe do raciocínio da xAI |
-| | Mistral | Teste grátis + pago | Taxa limitada | IA Europeia |
-| | OpenRouter | Pagamento conforme uso | Nenhum | Mais de 100 modelos no total. |
-| **💰 BARATO** | GLM-5 (via Z.AI) 🆕 | US$ 0,5/1 milhão | Diariamente 10h | Saída de 128K, o mais novo carro-chefe |
-| | GLM-4.7 | US$ 0,6/1 milhão | Diariamente 10h | Backup de orçamento |
-| | MiniMax M2.5 🆕 | Entrada de US$ 0,3/1 milhão | Rolamento de 5 horas | Raciocínio + tarefas de agência |
-| | MiniMax M2.1 | US$ 0,2/1 milhão | Rolamento de 5 horas | Opção mais barata |
-| | Kimi K2.5 (API Moonshot) 🆕 | Pagamento conforme uso | Nenhum | Acesso direto à API Moonshot |
-| | Kimi K2 | $ 9 / mês fixo | 10 milhões de tokens/mês | Custo previsível |
-| **🆓 GRÁTIS** | Qoder | **$0** | Ilimitado | 5 modelos ilimitados |
-| | Qwen | **$0** | Ilimitado | 4 modelos ilimitados |
-| | Kiro | **$0** | Ilimitado | Claude Sonnet/Haiku (Construtor AWS) |
-| | LongCat Flash Lite 🆕 | **$0** (50 milhões de dólares/dia 🔥) | 1RPS | Maior cota gratuita do planeta |
-| | Polinizações AI 🆕 | **$0** (sem necessidade de chave) | 1 necessidade/15s | GPT-5, Claude, DeepSeek, Lhama 4 |
-| | IA dos trabalhadores da Cloudflare 🆕 | **$0** (10 mil neurônios/dia) | ~150 resp/dia | Mais de 50 modelos, vantagem global |
-| | IA Scaleway 🆕 | **$0** (total de 1 milhão de tokens) | Taxa limitada | UE/GDPR, Qwen3 235B, Llama 70B |
-
-> 🆕 **Novos modelos adicionados (março de 2026):** Família Grok-4 Fast a US$ 0,20/US$ 0,50/M (comparado em 1143ms — 30% mais rápido que Gemini 2.5 Flash), GLM-5 via Z.AI com saída de 128K, raciocínio MiniMax M2.5, preço atualizado DeepSeek V3.2, Kimi K2.5 via API direta Moonshot.
-
-**💡 Pilha Combo de $0 — A configuração gratuita completa:**
-
-```
-# 🆓 Ultimate Free Stack 2026 — 11 Providers, $0 Forever
-Kiro (kr/) → Claude Sonnet/Haiku UNLIMITED
-Qoder (if/) → kimi-k2-thinking, qwen3-coder-plus, deepseek-r1 UNLIMITED
-LongCat Lite (lc/) → LongCat-Flash-Lite — 50M tokens/day 🔥
-Pollinations (pol/) → GPT-5, Claude, DeepSeek, Llama 4 — no key needed
-Qwen (qw/) → qwen3-coder-plus, qwen3-coder-flash, qwen3-coder-next UNLIMITED
-Gemini (gemini/) → Gemini 2.5 Flash — 1,500 req/day free API key
-Cloudflare AI (cf/) → Llama 70B, Gemma 3, Mistral — 10K Neurons/day
-Scaleway (scw/) → Qwen3 235B, Llama 70B — 1M free tokens (EU)
-Groq (groq/) → Llama/Gemma ultra-fast — 14.4K req/day
-NVIDIA NIM (nvidia/) → 70+ open models — 40 RPM forever
-Cerebras (cerebras/) → Llama/Qwen world-fastest — 1M tok/day
-```
-
-**Custo zero. Nunca para de codificar.** Configure isso como um combo OmniRoute e todos os fallbacks acontecem automaticamente - nunca há troca manual.
-
----
-
----
-
-## 🆓 Modelos gratuitos – O que você realmente obtém
-
-> Todos os modelos abaixo são **100% gratuitos, sem necessidade de cartão de crédito**. OmniRoute roteia automaticamente entre eles quando uma cota acaba – combine todos eles para um combo inquebrável de $ 0.
-
-### 🔵 MODELOS CLAUDE (via Kiro — AWS Builder ID)
-
-| Modelo | Prefixo | Limite | Limite de taxa |
-| ------------------- | ------- | ------------- | ------------------------------- |
-| `claude-sonnet-4.5` | `kr/` | **Ilimitado** | Nenhum limite diário comunicado |
-| `claude-haiku-4.5` | `kr/` | **Ilimitado** | Nenhum limite diário comunicado |
-| `claude-opus-4.6` | `kr/` | **Ilimitado** | Último Opus via Kiro |
-
-### 🟢 MODELOS QODER (OAuth grátis — sem cartão de crédito)
-
-| Modelo | Prefixo | Limite | Limite de taxa |
-| ------------------ | ------- | ------------- | ------------------------------- |
-| `kimi-k2-thinking` | `if/` | **Ilimitado** | Nenhum limite máximo comunicado |
-| `qwen3-coder-plus` | `if/` | **Ilimitado** | Nenhum limite máximo comunicado |
-| `deepseek-r1` | `if/` | **Ilimitado** | Nenhum limite máximo comunicado |
-| `minimax-m2.1` | `if/` | **Ilimitado** | Nenhum limite máximo comunicado |
-| `kimi-k2` | `if/` | **Ilimitado** | Nenhum limite máximo comunicado |
-
-### 🟡 MODELOS QWEN (autenticação do código do dispositivo)
-
-| Modelo | Prefixo | Limite | Limite de taxa |
-| ------------------- | ------- | ------------- | ------------------------------- |
-| `qwen3-coder-plus` | `qw/` | **Ilimitado** | Nenhum limite máximo comunicado |
-| `qwen3-coder-flash` | `qw/` | **Ilimitado** | Nenhum limite máximo comunicado |
-| `qwen3-coder-next` | `qw/` | **Ilimitado** | Nenhum limite máximo comunicado |
-| `vision-model` | `qw/` | **Ilimitado** | Multimodal (imagens) |
-
-### 🟣 CLI GEMINI (Google OAuth)
-
-| Modelo | Prefixo | Limite | Limite de taxa |
-| ------------------------ | ------- | -------------------------------- | ------------------ |
-| `gemini-3-flash-preview` | `gc/` | **180 mil tok/mês** + 1 mil/dia | Redefinição mensal |
-| `gemini-2.5-pro` | `gc/` | 180 mil/mês (pool compartilhado) | Alta qualidade |
-
-### ⚫ NVIDIA NIM (chave de API gratuita — build.nvidia.com)
-
-| Nível | Limite Diário | Limite de taxa | Notas |
-| ---------------------- | ------------------- | -------------- | --------------------------------------------------------------------------- |
-| Grátis (Desenvolvedor) | Sem limite de token | **~40RPM** | Mais de 70 modelos; transição para limites de taxas puras em meados de 2025 |
-
-Modelos gratuitos populares: `moonshotai/kimi-k2.5` (Kimi K2.5), `z-ai/glm4.7` (GLM 4.7), `deepseek-ai/deepseek-v3.2` (DeepSeek V3.2), `nvidia/llama-3.3-70b-instruct`, `deepseek/deepseek-r1`
-
-### ⚪ CEREBRAS (chave de API gratuita — inference.cerebras.ai)
-
-| Nível | Limite Diário | Limite de taxa | Notas |
-| ------ | -------------------------- | -------------- | ----------------------------------------------------------- |
-| Grátis | **1 milhão de tokens/dia** | 60KTPM/30RPM | A inferência LLM mais rápida do mundo; reinicia diariamente |
-
-Disponível gratuitamente: `llama-3.3-70b`, `llama-3.1-8b`, `deepseek-r1-distill-llama-70b`
-
-### 🔴 GROQ (chave de API gratuita — console.groq.com)
-
-| Nível | Limite Diário | Limite de taxa | Notas |
-| ------ | ---------------- | ----------------- | -------------------------------------------------- |
-| Grátis | **RPD de 14,4K** | 30 RPM por modelo | Sem cartão de crédito; 429 no limite, sem cobrança |
-
-Disponível gratuitamente: `llama-3.3-70b-versatile`, `gemma2-9b-it`, `mixtral-8x7b`, `whisper-large-v3`
-
-### 🔴 LONGCAT AI (chave de API gratuita — longcat.chat) 🆕
-
-| Modelo | Prefixo | Cota diária gratuita | Notas |
-| ----------------------------- | ------- | --------------------------- | -------------------------------------- |
-| `LongCat-Flash-Lite` | `lc/` | **50 milhões de tokens** 💥 | Maior cota gratuita de todos os tempos |
-| `LongCat-Flash-Chat` | `lc/` | 500 mil tokens | Bate-papo multiturno |
-| `LongCat-Flash-Thinking` | `lc/` | 500 mil tokens | Raciocínio / CoT |
-| `LongCat-Flash-Thinking-2601` | `lc/` | 500 mil tokens | Versão de janeiro de 2026 |
-| `LongCat-Flash-Omni-2603` | `lc/` | 500 mil tokens | Multimodal |
-
-> 100% gratuito durante a versão beta pública. Inscreva-se em [longcat.chat](https://longcat.chat) com e-mail ou telefone. Reinicia diariamente às 00:00 UTC.
-
-### 🟢 POLINIZAÇÕES AI (nenhuma chave de API necessária) 🆕
-
-| Modelo | Prefixo | Limite de taxa | Provedor por trás |
-| ---------- | ------- | ----------------- | -------------------- |
-| `openai` | `pol/` | 1 necessidade/15s | GPT-5 |
-| `claude` | `pol/` | 1 necessidade/15s | Claude Antrópico |
-| `gemini` | `pol/` | 1 necessidade/15s | Google Gêmeos |
-| `deepseek` | `pol/` | 1 necessidade/15s | DeepSeek V3 |
-| `llama` | `pol/` | 1 necessidade/15s | Batedor Meta Lhama 4 |
-| `mistral` | `pol/` | 1 necessidade/15s | IA Mistral |
-
-> ✨ **Atrito zero:** Sem inscrição, sem chave de API. Adicione o provedor Polinizações com um campo-chave vazio e ele funcionará imediatamente.
-
-### 🟠 CLOUDFLARE WORKERS AI (chave de API gratuita — cloudflare.com) 🆕
-
-| Nível | Neurônios Diários | Uso equivalente | Notas |
-| ------ | ----------------- | ------------------------------------------------- | ----------------------------------- |
-| Grátis | **10.000** | ~150 LLM resp / áudio 500s / incorporações de 15K | Vantagem global, mais de 50 modelos |
-
-Modelos gratuitos populares: `@cf/meta/llama-3.3-70b-instruct`, `@cf/google/gemma-3-12b-it`, `@cf/openai/whisper-large-v3-turbo` (áudio grátis!), `@cf/qwen/qwen2.5-coder-15b-instruct`
-
-> Requer token de API + ID da conta de [dash.cloudflare.com](https://dash.cloudflare.com). Armazene o ID da conta nas configurações do provedor.
-
-### 🟣 SCALEWAY AI (1 milhão de tokens grátis — scaleway.com) 🆕
-
-| Nível | Cota Grátis | Localização | Notas |
-| ------ | ---------------------- | ------------ | ----------------------------------------------------- |
-| Grátis | **1 milhão de tokens** | 🇫🇷 Paris, UE | Não é necessário cartão de crédito dentro dos limites |
-
-Disponível gratuitamente: `qwen3-235b-a22b-instruct-2507` (Qwen3 235B!), `llama-3.1-70b-instruct`, `mistral-small-3.2-24b-instruct-2506`, `deepseek-v3-0324`
-
-> Compatível com UE/GDPR. Obtenha a chave API em [console.scaleway.com](https://console.scaleway.com).
-
-> **💡 The Ultimate Free Stack (11 provedores, $ 0 para sempre): **
->
-> ```
-> Kiro (kr/) → Claude Sonnet/Haiku UNLIMITED
-> Qoder (if/) → kimi-k2-thinking, qwen3-coder-plus, deepseek-r1 UNLIMITED
-> LongCat Lite (lc/) → LongCat-Flash-Lite — 50M tokens/day 🔥
-> Pollinations (pol/) → GPT-5, Claude, DeepSeek, Llama 4 — no key needed
-> Qwen (qw/) → qwen3-coder models UNLIMITED
-> Gemini (gemini/) → Gemini 2.5 Flash — 1,500 req/day free
-> Cloudflare AI (cf/) → 50+ models — 10K Neurons/day
-> Scaleway (scw/) → Qwen3 235B, Llama 70B — 1M free tokens (EU)
-> Groq (groq/) → Llama/Gemma — 14.4K req/day ultra-fast
-> NVIDIA NIM (nvidia/) → 70+ open models — 40 RPM forever
-> Cerebras (cerebras/) → Llama/Qwen world-fastest — 1M tok/day
-> ```
-
-## 🎙️ Combo de transcrição grátis
-
-> Transcreva qualquer áudio/vídeo por **$0** — Deepgram lidera com $200 grátis, AssemblyAI $50 substituto, Groq Whisper como backup de emergência ilimitado.
-
-| Provedor | Créditos Grátis | Melhor Modelo | Limite de taxa |
-| ----------------- | --------------------------- | ---------------------------------------------- | --------------------------------------- |
-| 🟢 **Deepgram** | **$200 grátis** (inscrição) | `nova-3` — melhor precisão, mais de 30 idiomas | Sem limite de RPM em créditos gratuitos |
-| 🔵 **AssemblyAI** | **$50 grátis** (inscrição) | `universal-3-pro` — capítulos, sentimento, PII | Sem limite de RPM em créditos gratuitos |
-| 🔴 **Groque** | **Grátis para sempre** | `whisper-large-v3` — Sussurro OpenAI | 30 RPM (taxa limitada) |
-
-**Combo sugerido em `/dashboard/combos`:**
-
-```
-Name: free-transcription
-Strategy: Priority
-Nodes:
- [1] deepgram/nova-3 → uses $200 free first
- [2] assemblyai/universal-3-pro → fallback when Deepgram credits run out
- [3] groq/whisper-large-v3 → free forever, emergency fallback
-```
-
-Em seguida, em `/dashboard/media` → guia **Transcrição**: carregue qualquer arquivo de áudio ou vídeo → selecione seu endpoint de combinação → obtenha a transcrição em formatos suportados.
-
-## 💡 Principais recursos
-
-OmniRoute v2.0 é construído como uma plataforma operacional, não apenas um proxy de retransmissão.
-
-### 🆕 Novo — Melhorias inspiradas no ClawRouter (março de 2026)
-
-| Recurso | O que faz |
-| ---------------------------------------- | --------------------------------------------------------------------------------------------------------------- |
-| ⚡ **Grok-4 Família Rápida** | Modelos xAI por US$ 0,20/US$ 0,50/M – benchmark de 1143 ms (30% mais rápido que Gemini 2.5 Flash) |
-| 🧠 **GLM-5 via Z.AI** | Contexto de saída de 128K, US$ 0,5/1 milhão – o mais novo carro-chefe da família GLM |
-| 🔮 **MiniMax M2.5** | Raciocínio + tarefas de agência por US$ 0,30/1 milhão — atualização significativa do M2.1 |
-| 🎯 **toolCalling Flag por modelo** | Por modelo `toolCalling: true/false` no registro - AutoCombo ignora modelos sem capacidade de ferramenta |
-| 🌍 **Detecção de intenção multilíngue** | Palavras-chave PT/ZH/ES/AR na pontuação AutoCombo — melhor seleção de modelos para conteúdo diferente do inglês |
-| 📊 **Recursos baseados em benchmarks** | Latência p95 real de solicitações ao vivo alimenta pontuação combinada – AutoCombo aprende com dados reais |
-| 🔁 **Solicitar desduplicação** | Janela de desduplicação baseada em hash de conteúdo — segura para vários agentes, evita cobranças duplicadas |
-| 🔌 **Estratégia de roteador conectável** | Interface `RouterStrategy` extensível — adicione lógica de roteamento personalizada como plug-ins |
-
-### 🚀 Anterior v2.0.9+ — Playground, impressões digitais CLI e ACP
-
-| Recurso | O que faz |
-| ----------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| 🎮 **Parque Modelo** | Página do painel para testar qualquer modelo diretamente - seletores de provedor/modelo/endpoint, Monaco Editor, streaming, aborto, tempo |
-| 🔏 **Correspondência de impressão digital CLI** | Ordenação de cabeçalho/corpo por provedor para corresponder às assinaturas CLI nativas — alterne por provedor em Configurações > Segurança. **Seu IP proxy é preservado** |
-| 🤝 **Suporte ACP (Protocolo Agente Cliente)** | Descoberta de agente CLI (Codex, Claude, Goose, Gemini CLI, OpenClaw + mais 9), gerador de processo, endpoint `/api/acp/agents` |
-| 🤖 **Painel de Agentes ACP** | Depurar › Página Agentes — grade de 14 agentes com status de instalação, versão, formulário de agente personalizado para qualquer ferramenta CLI. Os usuários do **OpenCode** recebem um botão "Baixar opencode.json" que gera automaticamente uma configuração pronta para uso com todos os modelos disponíveis. |
-| 🔧 **Roteamento de modelo personalizado `apiFormat`** | Modelos personalizados com `apiFormat: "responses"` agora roteiam corretamente para o tradutor da API de respostas |
-| 🏢 **Isolamento do espaço de trabalho do Codex** | Vários espaços de trabalho do Codex por e-mail — OAuth separa corretamente as conexões por ID do espaço de trabalho |
-| 🔄 **Atualização automática eletrônica** | O aplicativo de desktop verifica atualizações + instalação automática ao reiniciar |
-
-### 🤖 Operações de agente e protocolo (v2.0)
-
-| Recurso | O que faz |
-| ------------------------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------- |
-| 🔧 **Servidor MCP (16 ferramentas)** | Ferramentas IDE/agente por meio de 3 transportes: stdio, SSE (`/api/mcp/sse`), HTTP Streamable (`/api/mcp/stream`) |
-| 🤝 **Servidor A2A (JSON-RPC + SSE)** | Execução de tarefas entre agentes com fluxos de sincronização e streaming |
-| 🧭 **Página de endpoints consolidados** | Página de gerenciamento com guias com guias Endpoint Proxy, MCP, A2A e API Endpoints |
-| 🎚️ **Alternativas de ativação/desativação de serviço** | Chaves ON/OFF para MCP e A2A com persistência de configurações (padrão: OFF) |
-| 🛰️ **Pulsação de tempo de execução do MCP** | Status real do processo (pid, tempo de atividade, idade da pulsação, transporte, modo de escopo) |
-| 📋 **Trilha de auditoria MCP** | Logs de auditoria filtráveis com sucesso/falha e atribuição de chave |
-| 🔐 **Aplicação do escopo do MCP** | 9 permissões de escopo granular para acesso controlado a ferramentas |
-| 📡 **Gerenciamento do ciclo de vida de tarefas A2A** | Listar/filtrar tarefas, inspecionar eventos/artefatos, cancelar tarefas em execução |
-| 📋 **Descoberta de cartão de agente** | `/.well-known/agent.json` para descoberta automática de cliente |
-| 🧪 **Arnês de teste do protocolo E2E** | Fluxos reais de cliente MCP SDK + A2A em `test:protocols:e2e` |
-| ⚙️ **Controles operacionais** | Combinação de interruptores, aplicação de perfis de resiliência, reinicialização de disjuntores a partir de uma superfície de controle |
-
-### 🧠 Roteamento e Inteligência
-
-| Recurso | O que faz |
-| ----------------------------------------------------------- | ------------------------------------------------------------------------------------- |
-| 🎯 **Fullback inteligente de 4 camadas** | Roteamento automático: Assinatura → Chave de API → Barato → Grátis |
-| 📊 **Acompanhamento de cotas em tempo real** | Contagem de tokens ativos + contagem regressiva redefinida por provedor |
-| 🔄 **Tradução de formato** | OpenAI ↔ Claude ↔ Gemini ↔ Respostas com conversões seguras de esquema |
-| 👥 **Suporte para múltiplas contas** | Múltiplas contas por provedor com seleção inteligente |
-| 🔄 **Atualização automática de token** | Os tokens OAuth são atualizados automaticamente com nova tentativa |
-| 🎨 **Combos Personalizados** | 6 estratégias de balanceamento + controle da cadeia de fallback |
-| 🌐 **Roteador curinga** | `provider/*` roteamento dinâmico |
-| 🧠 **Pensando em controles de orçamento** | Limites de raciocínio de passagem, automático, personalizado e adaptativo |
-| 🔀 **Alases de modelo** | Aliasing de modelo integrado + personalizado e segurança de migração |
-| ⚡ **Degradação de fundo** | Encaminhar tarefas em segundo plano de baixa prioridade para modelos mais baratos |
-| 🧪 **Roteamento inteligente com reconhecimento de tarefas** | Seleção automática de modelo por tipo de conteúdo (codificação/visão/análise/resumo) |
-| 💬 **Injeção imediata do sistema** | Controles de comportamento globais aplicados de forma consistente |
-| 📄 **Compatibilidade da API de respostas** | Suporte completo `/v1/responses` para Codex e fluxos de trabalho de agência avançados |
-
-### 🎵 APIs multimodais
-
-| Recurso | O que faz |
-| --------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| 🖼️ **Geração de imagens** | `/v1/images/generations` com nuvem e back-ends locais |
-| 📐 **Incorporações** | `/v1/embeddings` para pipelines de pesquisa e RAG |
-| 🎤 **Transcrição de áudio** | `/v1/audio/transcriptions` — 7 provedores (Deepgram Nova 3, AssemblyAI, Groq Whisper, HuggingFace, ElevenLabs, OpenAI, Azure), detecção automática de idioma, suporte a MP4/MP3/WAV |
-| 🔊 **Conversão de texto em fala** | `/v1/audio/speech` — 10 provedores (ElevenLabs, OpenAI, Deepgram, Cartesia, PlayHT, HuggingFace, Nvidia NIM, Inworld, Coqui, Tortoise) com mensagens de erro corretas |
-| 🎬 **Geração de Vídeo** | `/v1/videos/generations` (fluxos de trabalho ComfyUI + SD WebUI) |
-| 🎵 **Geração Musical** | `/v1/music/generations` (fluxos de trabalho ComfyUI) |
-| 🛡️ **Moderações** | `/v1/moderations` verificações de segurança |
-| 🔀 **Reclassificação** | `/v1/rerank` para pontuação de relevância |
-| 🔍 **Pesquisa na Web** 🆕 | `/v1/search` — 5 provedores (Serper, Brave, Perplexity, Exa, Tavily), mais de 6.500 grátis/mês, failover automático, cache |
-
-### 🛡️ Resiliência, Segurança e Governança
-
-| Recurso | O que faz |
-| ----------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------- |
-| 🔌 **Disjuntores** | Acionamento/recuperação por modelo com controles de limite |
-| 🎯 **Modelos com reconhecimento de endpoint** | Modelos personalizados declaram endpoints suportados + formato API |
-| 🛡️ **Rebanho Anti-Trovão** | Proteções Mutex + semáforo em eventos de nova tentativa/taxa |
-| 🧠 **Semântica + Cache de Assinatura** | Redução de custo/latência com duas camadas de cache |
-| ⚡ **Solicitar Idempotência** | Janela de proteção duplicada |
-| 🔒 **Falsificação de impressão digital TLS** | Impressão digital TLS semelhante a navegador — **reduz a detecção de bots e a sinalização de contas** |
-| 🔏 **Correspondência de impressão digital CLI** | Corresponde às assinaturas de solicitação CLI nativas — **reduz o risco de banimento enquanto preserva o IP do proxy** |
-| 🌐 **Filtragem de IP** | Controle de lista de permissões/lista de bloqueio para implantações expostas |
-| 📊 **Limites de taxas editáveis** | Limites configuráveis em nível global/de provedor com persistência |
-| 🔑 **Gerenciamento de chaves de API + escopo** | Emissão/rotação segura de chaves e controles de modelo/provedor |
-| 🛡️ **Protegido `/models`** | Autenticação opcional e ocultação de provedor para catálogo de modelos |
-
-### 📊 Observabilidade e análise
-
-| Recurso | O que faz |
-| -------------------------------------- | ---------------------------------------------------------------------------- |
-| 📝 **Solicitação + Registro de Proxy** | Solicitação/resposta completa e registro de proxy |
-| 📉 **Streamed Detailed Logs** 🆕 | Reconstructs SSE payload streams cleanly into the UI |
-| 📋 **Painel de registros unificado** | Visualizações de solicitação, proxy, auditoria e console em uma página |
-| 🔍 **Solicitar Telemetria** | Latência p50/p95/p99 e rastreamento de solicitação |
-| 🏥 **Painel de saúde** | Tempo de atividade, estados de disjuntores, bloqueios, estatísticas de cache |
-| 💰 **Acompanhamento de custos** | Controles de orçamento e visibilidade de preços por modelo |
-| 📈 **Visualizações analíticas** | Insights de uso de modelo/provedor e visualizações de tendências |
-| 🧪 **Estrutura de Avaliação** | Teste de Golden Set com estratégias de jogo configuráveis |
-
-### ☁️ Implantação e plataforma
-
-| Recurso | O que faz |
-| --------------------------------------- | ------------------------------------------------------------------------------ |
-| 🌐 **Implante em qualquer lugar** | Ambientes Localhost, VPS, Docker, Cloud |
-| 💾 **Sincronização na nuvem** | Sincronização de configuração via Cloud Worker |
-| 🔄 **Backup/Restauração** | Fluxos de exportação/importação e recuperação de desastres |
-| 🧙 **Assistente de integração** | Configuração guiada na primeira execução |
-| 🔧 **Painel de Ferramentas CLI** | Configuração com um clique para ferramentas de codificação populares |
-| 🎮 **Parque Modelo** | Teste qualquer provedor/modelo/endpoint no painel |
-| 🔏 **Alternar impressão digital CLI** | Correspondência de impressão digital por provedor em Configurações > Segurança |
-| 🌐 **i18n (30 idiomas)** | Painel completo + suporte a idiomas de documentos com cobertura RTL |
-| 🧹 **Limpar todos os modelos** | Limpeza da lista de modelos com um clique nos detalhes do provedor |
-| 👁️ **Sidebar Controls** 🆕 | Hide components and integrations from Appearance Settings |
-| 📋 **Modelos de problemas** | Modelos padronizados do GitHub para bugs e recursos |
-| 📂 **Diretório de dados personalizado** | Substituição de `DATA_DIR` para local de armazenamento |
-
-### Aprofundamento do recurso
-
-#### Fallback inteligente com controle prático de custos
-
-```txt
-Combo: "my-coding-stack"
- 1. cc/claude-opus-4-6
- 2. nvidia/llama-3.3-70b
- 3. glm/glm-4.7
- 4. if/kimi-k2-thinking
-```
-
-Quando a cota, a taxa ou a integridade falham, o OmniRoute passa automaticamente para o próximo candidato sem alternância manual.
-
-#### Gerenciamento de protocolo visível e operável
-
-- MCP + A2A podem ser descobertos na interface do usuário e nos documentos (não ocultos)
-- APIs de status de protocolo expõem dados operacionais em tempo real (`/api/mcp/*`, `/api/a2a/*`)
-- Os painéis incluem ações para operações do dia 2 (alternâncias de combinação, reinicializações de disjuntores, cancelamento de tarefas)
-
-#### Tradutor + fluxo de trabalho de validação
-
-A área do Tradutor inclui:
-
-- **Playground**: solicita verificações de transformação
-- **Testador de bate-papo**: solicitação/resposta completa, ida e volta
-- **Banco de testes**: vários casos em uma execução
-- **Monitoramento ao vivo**: visualização do tráfego em tempo real
-
-Além de validação de protocolo com clientes reais via `npm run test:protocols:e2e`.
-
-> 📖 **[MCP Server README](open-sse/mcp-server/README.md)** — Referência de ferramentas, configurações de IDE e exemplos de clientes
->
-> 📖 **[A2A Server README](src/lib/a2a/README.md)** — Habilidades, métodos JSON-RPC, streaming e ciclo de vida de tarefas
-
-## 🧪 Avaliações (Evals)
-
-OmniRoute inclui uma estrutura de avaliação integrada para testar a qualidade da resposta do LLM em relação a um conjunto dourado. Acesse-o em **Analytics → Evals** no painel.
-
-### Conjunto Dourado Integrado
-
-O "OmniRoute Golden Set" pré-carregado contém casos de teste para:
-
-- Saudações, matemática, geografia, geração de código
-- Conformidade com o formato JSON, tradução, geração de descontos
-- Recusa de segurança (conteúdo prejudicial), contagem, lógica booleana
-
-### Estratégias de Avaliação
-
-| Estratégia | Descrição | Exemplo |
-| ---------- | --------------------------------------------------------------------------- | -------------------------------- |
-| `exact` | A saída deve corresponder exatamente | `"4"` |
-| `contains` | A saída deve conter substring (sem distinção entre maiúsculas e minúsculas) | `"Paris"` |
-| `regex` | A saída deve corresponder ao padrão regex | `"1.*2.*3"` |
-| `custom` | Função JS personalizada retorna verdadeiro/falso | `(output) => output.length > 10` |
-
----
-
-## 📖 Guia de configuração
-
-### Configuração do protocolo (MCP + A2A)
-
-
-🧩 Configuração MCP (protocolo de contexto do modelo)
-
-Inicie o transporte MCP no modo stdio:
-
-```bash
-omniroute --mcp
-```
-
-Fluxo de validação recomendado:
-
-1. Conecte seu cliente MCP por stdio.
-2. Execute `omniroute_get_health`.
-3. Execute `omniroute_list_combos`.
-4. Abra `/dashboard/mcp` para confirmar pulsação, atividade e auditoria.
-
-APIs úteis para automação:
-
-- `GET /api/mcp/status`
-- `GET /api/mcp/tools`
-- `GET /api/mcp/audit`
-- `GET /api/mcp/audit/stats`
-
-
-
-
-🤝 Configuração A2A (Agente2Agente)
-
-Conheça o agente:
-
-```bash
-curl http://localhost:20128/.well-known/agent.json
-```
-
-Envie uma tarefa:
-
-```bash
-curl -X POST http://localhost:20128/a2a \
- -H 'content-type: application/json' \
- -d '{"jsonrpc":"2.0","id":"setup-a2a","method":"message/send","params":{"skill":"quota-management","messages":[{"role":"user","content":"Summarize quota status."}]}}'
-```
-
-Gerenciar ciclo de vida:
-
-- `GET /api/a2a/status`
-- `GET /api/a2a/tasks`
-- `GET /api/a2a/tasks/:id`
-- `POST /api/a2a/tasks/:id/cancel`
-
-IU operacional:
-
-- `/dashboard/a2a` para observabilidade de tarefa/estado/fluxo e ações de fumaça
-
-
-
-
-🧪 Validação de protocolo ponta a ponta
-
-Valide ambos os protocolos com clientes reais:
-
-```bash
-npm run test:protocols:e2e
-```
-
-Isso verifica:
-
-- Conexão/lista/chamada do cliente MCP SDK
-- Descoberta A2A/enviar/transmitir/obter/cancelar
-- Verificação cruzada de dados em APIs de auditoria MCP e gerenciamento de tarefas A2A
-
-
-
-
-💳 Provedores de assinatura
-
-### Código Claude (Pro/Max)
-
-```bash
-Dashboard → Providers → Connect Claude Code
-→ OAuth login → Auto token refresh
-→ 5-hour + weekly quota tracking
-
-Models:
- cc/claude-opus-4-6
- cc/claude-sonnet-4-5-20250929
- cc/claude-haiku-4-5-20251001
-```
-
-**Dica profissional:** Use o Opus para tarefas complexas e o Sonnet para velocidade. OmniRoute rastreia cota por modelo!
-
-### Codex OpenAI (Plus/Pro)
-
-```bash
-Dashboard → Providers → Connect Codex
-→ OAuth login (port 1455)
-→ 5-hour + weekly reset
-
-Models:
- cx/gpt-5.2-codex
- cx/gpt-5.1-codex-max
-```
-
-#### Gerenciamento de limite de conta Codex (5h + semanalmente)
-
-Cada conta do Codex agora possui opções de política em `Dashboard -> Providers`:
-
-- `5h` (ON/OFF): impõe a política de limite de janela de 5 horas.
-- `Weekly` (ON/OFF): impõe a política de limite de janela semanal.
-- Comportamento do limite: quando uma janela habilitada atinge >=90% de uso, essa conta é ignorada.
-- Comportamento de rotação: OmniRoute roteia automaticamente para a próxima conta Codex qualificada.
-- Comportamento de redefinição: quando o tempo `resetAt` do provedor passar, a conta se tornará elegível novamente automaticamente.
-
-Cenários:
-
-- `5h ON` + `Weekly ON`: a conta é ignorada quando uma das janelas atinge o limite.
-- `5h OFF` + `Weekly ON`: somente o uso semanal pode bloquear a conta.
-- `5h ON` + `Weekly OFF`: apenas o uso de 5 horas pode bloquear a conta.
-- `resetAt` aprovado: a conta entra novamente na rotação automaticamente (sem reativação manual).
-
-### Gemini CLI (GRÁTIS 180K/mês!)
-
-```bash
-Dashboard → Providers → Connect Gemini CLI
-→ Google OAuth
-→ 180K completions/month + 1K/day
-
-Models:
- gc/gemini-3-flash-preview
- gc/gemini-2.5-pro
-```
-
-**Melhor valor:** Grande nível gratuito! Use isso antes dos níveis pagos.
-
-### GitHub Copiloto
-
-```bash
-Dashboard → Providers → Connect GitHub
-→ OAuth via GitHub
-→ Monthly reset (1st of month)
-
-Models:
- gh/gpt-5
- gh/claude-4.5-sonnet
- gh/gemini-3-pro
-```
-
-
-
-
-🔑 Provedores de chave de API
-
-### NVIDIA NIM (acesso GRATUITO para desenvolvedores – mais de 70 modelos)
-
-1. Inscreva-se: [build.nvidia.com](https://build.nvidia.com)
-2. Obtenha uma chave de API gratuita (1.000 créditos de inferência incluídos)
-3. Painel → Adicionar Provedor → NVIDIA NIM:
- - Chave API: `nvapi-your-key`
-
-**Modelos:** `nvidia/llama-3.3-70b-instruct`, `nvidia/mistral-7b-instruct` e mais de 50
-
-**Dica profissional:** API compatível com OpenAI — funciona perfeitamente com a tradução de formato do OmniRoute!
-
-### DeepSeek
-
-1. Inscreva-se: [platform.deepseek.com](https://platform.deepseek.com)
-2. Obtenha a chave API
-3. Painel → Adicionar provedor → DeepSeek
-
-**Modelos:** `deepseek/deepseek-chat`, `deepseek/deepseek-coder`
-
-### Groq (nível gratuito disponível!)
-
-1. Inscreva-se: [console.groq.com](https://console.groq.com)
-2. Obtenha a chave API (nível gratuito incluído)
-3. Painel → Adicionar Provedor → Groq
-
-**Modelos:** `groq/llama-3.3-70b`, `groq/mixtral-8x7b`
-
-**Dica profissional:** Inferência ultrarrápida — melhor para codificação em tempo real!
-
-### OpenRouter (mais de 100 modelos)
-
-1. Inscreva-se: [openrouter.ai](https://openrouter.ai)
-2. Obtenha a chave API
-3. Painel → Adicionar Provedor → OpenRouter
-
-**Modelos:** acesse mais de 100 modelos de todos os principais fornecedores por meio de uma única chave de API.
-
-
-
-
-💰 Provedores baratos (backup)
-
-### GLM-4.7 (redefinição diária, US$ 0,6/1 milhão)
-
-1. Inscreva-se: [Zhipu AI](https://open.bigmodel.cn/)
-2. Obtenha a chave API do plano de codificação
-3. Painel → Adicionar chave API:
- - Provedor: `glm`
- - Chave API: `your-key`
-
-**Usar:** `glm/glm-4.7`
-
-**Dica profissional:** O plano de codificação oferece cota 3× com custo de 1/7! Redefinir diariamente às 10h.
-
-### MiniMax M2.1 (redefinição de 5h, US$ 0,20/1 milhão)
-
-1. Inscreva-se: [MiniMax](https://www.minimax.io/)
-2. Obtenha a chave API
-3. Painel → Adicionar chave API
-
-**Usar:** `minimax/MiniMax-M2.1`
-
-**Dica profissional:** Opção mais barata para contexto longo (1 milhão de tokens)!
-
-### Kimi K2 (US$ 9/mês fixo)
-
-1. Inscreva-se: [Moonshot AI](https://platform.moonshot.ai/)
-2. Obtenha a chave API
-3. Painel → Adicionar chave API
-
-**Usar:** `kimi/kimi-latest`
-
-**Dica profissional:** $9 fixos/mês para 10 milhões de tokens = $0,90/custo efetivo de 1 milhão!
-
-
-
-
-🆓 Provedores GRATUITOS (backup de emergência)
-
-### Qoder (5 modelos GRATUITOS via OAuth)
-
-```bash
-Dashboard → Connect Qoder
-→ Qoder OAuth login
-→ Unlimited usage
-
-Models:
- if/kimi-k2-thinking
- if/qwen3-coder-plus
- if/glm-4.7
- if/minimax-m2
- if/deepseek-r1
-```
-
-### Qwen (4 modelos GRATUITOS via código do dispositivo)
-
-```bash
-Dashboard → Connect Qwen
-→ Device code authorization
-→ Unlimited usage
-
-Models:
- qw/qwen3-coder-plus
- qw/qwen3-coder-flash
-```
-
-### Kiro (Claude GRÁTIS)
-
-```bash
-Dashboard → Connect Kiro
-→ AWS Builder ID or Google/GitHub
-→ Unlimited usage
-
-Models:
- kr/claude-sonnet-4.5
- kr/claude-haiku-4.5
-```
-
-
-
-
-🎨 Criar Combos
-
-### Exemplo 1: Maximize a assinatura → Backup barato
-
-```
-Dashboard → Combos → Create New
-
-Name: premium-coding
-Models:
- 1. cc/claude-opus-4-6 (Subscription primary)
- 2. glm/glm-4.7 (Cheap backup, $0.6/1M)
- 3. minimax/MiniMax-M2.1 (Cheapest fallback, $0.20/1M)
-
-Use in CLI: premium-coding
-```
-
-### Exemplo 2: somente gratuito (custo zero)
-
-```
-Name: free-combo
-Models:
- 1. gc/gemini-3-flash-preview (180K free/month)
- 2. if/kimi-k2-thinking (unlimited)
- 3. qw/qwen3-coder-plus (unlimited)
-
-Cost: $0 forever!
-```
-
-
-
-
-🔧 Integração CLI
-
-### Cursor IDE
-
-```
-Settings → Models → Advanced:
- OpenAI API Base URL: http://localhost:20128/v1
- OpenAI API Key: [from OmniRoute dashboard]
- Model: cc/claude-opus-4-6
-```
-
-### Código Cláudio
-
-Use a página **Ferramentas CLI** no painel para configuração com um clique ou edite `~/.claude/settings.json` manualmente.
-
-### CLI do Codex
-
-```bash
-export OPENAI_BASE_URL="http://localhost:20128"
-export OPENAI_API_KEY="your-omniroute-api-key"
-
-codex "your prompt"
-```
-
-###OpenClaw
-
-**Opção 1 — Painel (recomendado):**
-
-```
-Dashboard → CLI Tools → OpenClaw → Select Model → Apply
-```
-
-**Opção 2 — Manual:** Editar `~/.openclaw/openclaw.json`:
-
-```json
-{
- "models": {
- "providers": {
- "omniroute": {
- "baseUrl": "http://127.0.0.1:20128/v1",
- "apiKey": "sk_omniroute",
- "api": "openai-completions"
- }
- }
- }
-}
-```
-
-> **Observação:** OpenClaw só funciona com OmniRoute local. Use `127.0.0.1` em vez de `localhost` para evitar problemas de resolução de IPv6.
-
-### Cline / Continuar / RooCode
-
-```
-Settings → API Configuration:
- Provider: OpenAI Compatible
- Base URL: http://localhost:20128/v1
- API Key: [from OmniRoute dashboard]
- Model: if/kimi-k2-thinking
-```
-
-### OpenCode
-
-**Etapa 1:** Adicione OmniRoute como um provedor personalizado:
-
-```bash
-opencode
-/connect
-# Select "Other" → Enter ID: "omniroute" → Enter your OmniRoute API key
-```
-
-**Etapa 2:** Crie/edite `opencode.json` na raiz do seu projeto:
-
-```json
-{
- "$schema": "https://opencode.ai/config.json",
- "provider": {
- "omniroute": {
- "npm": "@ai-sdk/openai-compatible",
- "name": "OmniRoute",
- "options": {
- "baseURL": "http://localhost:20128/v1"
- },
- "models": {
- "cc/claude-sonnet-4-20250514": { "name": "Claude Sonnet 4" },
- "gg/gemini-2.5-pro": { "name": "Gemini 2.5 Pro" },
- "if/kimi-k2-thinking": { "name": "Kimi K2 (Free)" }
- }
- }
- }
-}
-```
-
-**Etapa 3:** Selecione o modelo no OpenCode:
-
-```bash
-/models
-# Select any OmniRoute model from the list
-```
-
-> **Dica:** Adicione qualquer modelo disponível no endpoint `/v1/models` do OmniRoute à seção `models`. Use o formato `provider/model-id` do painel do OmniRoute.
-
-
-
----
-
-## 🐛 Solução de problemas
-
-
-Clique para expandir o guia de solução de problemas
-
-**"O modelo de linguagem não forneceu mensagens"**
-
-- Cota do provedor esgotada → Verifique o rastreador de cota do painel
-- Solução: use o combo substituto ou mude para um nível mais barato
-
-** Limitação de taxa **
-
-- Cota de assinatura esgotada → Fallback para GLM/MiniMax
-- Adicionar combinação: `cc/claude-opus-4-6 → glm/glm-4.7 → if/kimi-k2-thinking`
-
-**O token OAuth expirou**
-
-- Atualizado automaticamente pelo OmniRoute
-- Se os problemas persistirem: Painel → Provedor → Reconectar
-
-**Custos elevados**
-
-- Verifique as estatísticas de uso em Painel → Custos
-- Mude o modelo primário para GLM/MiniMax
-- Use o nível gratuito (Gemini CLI, Qoder) para tarefas não críticas
-
-**As portas do painel/API estão erradas**
-
-- `PORT` é a porta base canônica (e porta API por padrão)
-- `API_PORT` substitui apenas o ouvinte de API compatível com OpenAI
-- `DASHBOARD_PORT` substitui apenas o ouvinte dashboard/Next.js
-- Defina `NEXT_PUBLIC_BASE_URL` para seu painel/URL público (para retornos de chamada OAuth)
-
-**Erros de sincronização na nuvem**
-
-- Verifique `BASE_URL` pontos para sua instância em execução
-- Verifique os pontos `CLOUD_URL` para o endpoint de nuvem esperado
-- Mantenha os valores `NEXT_PUBLIC_*` alinhados com os valores do lado do servidor
-
-**Primeiro login não funciona**
-
-- Verifique `INITIAL_PASSWORD` em `.env`
-- Se não definida, a senha substituta é `123456`
-
-**Sem registros de solicitação**
-
-- Definir `ENABLE_REQUEST_LOGS=true` em `.env`
-
-**O teste de conexão mostra "Inválido" para provedores compatíveis com OpenAI**
-
-- Muitos provedores não expõem um endpoint `/models`
-- OmniRoute v1.0.6+ inclui validação de fallback por meio de conclusões de chat
-- Certifique-se de que o URL base inclua o sufixo `/v1`
-
-### 🔐 OAuth em um servidor remoto
-
-
-
-
-> **⚠️ Importante para usuários executando OmniRoute em um VPS, Docker ou qualquer servidor remoto**
-
-#### Por que o Antigravity / Gemini CLI OAuth falha em servidores remotos?
-
-Os provedores **Antigravity** e **Gemini CLI** usam o **Google OAuth 2.0**. O Google exige que `redirect_uri` no fluxo OAuth corresponda exatamente a um dos URIs pré-registrados no Console do Google Cloud do aplicativo.
-
-As credenciais OAuth incluídas no OmniRoute são registradas **somente para `localhost`**. Quando você acessa o OmniRoute em um servidor remoto (por exemplo, `https://omniroute.myserver.com`), o Google rejeita a autenticação com:
-
-```
-Error 400: redirect_uri_mismatch
-```
-
-#### Solução: Configure suas próprias credenciais OAuth
-
-Você precisa criar um **ID do cliente OAuth 2.0** no Console do Google Cloud com o URI do seu servidor.
-
-#### Passo a passo
-
-**1. Abra o Console do Google Cloud**
-
-Vá para: [https://console.cloud.google.com/apis/credentials](https://console.cloud.google.com/apis/credentials)
-
-**2. Crie um novo ID de cliente OAuth 2.0**
-
-- Clique em **"+ Criar credenciais"** → **"ID do cliente OAuth"**
-- Tipo de aplicativo: **"Aplicativo Web"**
-- Nome: o que você quiser (por exemplo, `OmniRoute Remote`)
-
-**3. Adicionar URIs de redirecionamento autorizados**
-
-No campo **"URIs de redirecionamento autorizados"**, adicione:
-
-```
-https://your-server.com/callback
-```
-
-> Substitua `your-server.com` pelo domínio ou IP do seu servidor (inclua a porta se necessário, por exemplo, `http://45.33.32.156:20128/callback`).
-
-**4. Salve e copie as credenciais**
-
-Após a criação, o Google mostrará o **ID do cliente** e o **Segredo do cliente**.
-
-**5. Definir variáveis de ambiente**
-
-Em seu `.env` (ou variáveis de ambiente Docker):
-
-```bash
-# For Antigravity:
-ANTIGRAVITY_OAUTH_CLIENT_ID=your-client-id.apps.googleusercontent.com
-ANTIGRAVITY_OAUTH_CLIENT_SECRET=GOCSPX-your-secret
-
-# For Gemini CLI:
-GEMINI_OAUTH_CLIENT_ID=your-client-id.apps.googleusercontent.com
-GEMINI_OAUTH_CLIENT_SECRET=GOCSPX-your-secret
-GEMINI_CLI_OAUTH_CLIENT_SECRET=GOCSPX-your-secret
-```
-
-**6. Reinicie o OmniRoute**
-
-```bash
-# npm:
-npm run dev
-
-# Docker:
-docker restart omniroute
-```
-
-**7. Tente conectar novamente**
-
-Painel → Provedores → Antigravidade (ou Gemini CLI) → OAuth
-
-O Google agora redirecionará corretamente para `https://your-server.com/callback`.
-
----
-
-#### Solução temporária (sem credenciais personalizadas)
-
-Se não quiser configurar suas próprias credenciais agora, você ainda pode usar o **fluxo manual de URL**:
-
-1. OmniRoute abre o URL de autorização do Google
-2. Após autorização, o Google tenta redirecionar para `localhost` (que falha no servidor remoto)
-3. **Copie o URL completo** da barra de endereço do seu navegador (mesmo que a página não carregue)
-4. Cole esse URL no campo mostrado no modal de conexão OmniRoute
-5. Clique em **"Conectar"**
-
-> Isso funciona porque o código de autorização no URL é válido independentemente de a página de redirecionamento ter sido carregada.
-
----
-
-
-🇧🇷 Versão em Português
-
-#### Por que o OAuth do Antigravity / Gemini CLI falha em servidores remotos?
-
-Os provedores **Antigravity** e **Gemini CLI** usam **Google OAuth 2.0** para autenticação. O Google exige que um `redirect_uri` usado no fluxo OAuth seja **exatamente** uma das URIs pré-cadastradas no Google Cloud Console do aplicativo.
-
-As credenciais OAuth incorporadas no OmniRoute estão cadastradas **apenas para `localhost`**. Quando você acessa o OmniRoute em um servidor remoto (ex: `https://omniroute.meuservidor.com`), o Google rejeita a autenticação com:
-
-```
-Error 400: redirect_uri_mismatch
-```
-
-#### Solução: Configure suas próprias credenciais OAuth
-
-Você precisa criar um **OAuth 2.0 Client ID** no Google Cloud Console com o URI do seu servidor.
-
-####Passo a passo
-
-**1. Acesse o Console do Google Cloud**
-
-Abra: [https://console.cloud.google.com/apis/credentials](https://console.cloud.google.com/apis/credentials)
-
-**2. Crie um novo ID de cliente OAuth 2.0**
-
-- Clique em **"+ Criar credenciais"** → **"ID do cliente OAuth"**
-- Tipo de aplicativo: **"Aplicativo Web"**
-- Nome: escolha qualquer nome (ex: `OmniRoute Remote`)
-
-**3. Adicionar como URIs de redirecionamento autorizados**
-
-No campo **"URIs de redirecionamento autorizados"**, adicionado:
-
-```
-https://seu-servidor.com/callback
-```
-
-> Substitua `seu-servidor.com` pelo domínio ou IP do seu servidor (inclua a porta se necessário, ex: `http://45.33.32.156:20128/callback`).
-
-**4. Salve e copie as credenciais**
-
-Após criar, o Google mostrará o **Client ID** e o **Client Secret**.
-
-**5. Configurar como variáveis de ambiente**
-
-No seu `.env` (ou nas variáveis de ambiente do Docker):
-
-```bash
-# Para Antigravity:
-ANTIGRAVITY_OAUTH_CLIENT_ID=seu-client-id.apps.googleusercontent.com
-ANTIGRAVITY_OAUTH_CLIENT_SECRET=GOCSPX-seu-secret
-
-# Para Gemini CLI:
-GEMINI_OAUTH_CLIENT_ID=seu-client-id.apps.googleusercontent.com
-GEMINI_OAUTH_CLIENT_SECRET=GOCSPX-seu-secret
-GEMINI_CLI_OAUTH_CLIENT_SECRET=GOCSPX-seu-secret
-```
-
-**6. Reinicie o OmniRoute**
-
-```bash
-# Se usando npm:
-npm run dev
-
-# Se usando Docker:
-docker restart omniroute
-```
-
-**7. Tente conectar novamente**
-
-Painel → Provedores → Antigravidade (ou Gemini CLI) → OAuth
-
-Agora o Google redirecionará corretamente para `https://seu-servidor.com/callback` e a autenticação funcionará.
-
----
-
-#### Solução alternativa temporária (sem configurar credenciais próprias)
-
-Se não quiser criar credenciais próprias agora, ainda é possível usar o fluxo **manual de URL**:
-
-1. O OmniRoute abrirá uma URL de autorização do Google
-2. Após você autorizar, o Google tentará redirecionar para `localhost` (que falha no servidor remoto)
-3. **Copie a URL completa** da barra de endereço do seu navegador (mesmo que a página não carregue)
-4. Cole essa URL no campo que aparece no modal de conexão do OmniRoute
-5. Clique em **"Conectar"**
-
-> Esta solução alternativa funciona porque o código de autorização na URL é válido, independentemente do redirecionamento ter sido carregado ou não.
-
-
-
----
-
-
-
-## 🛠️ Pilha de tecnologia
-
-
-Clique para expandir os detalhes da pilha de tecnologia
-
-- **Tempo de execução**: Node.js 18–22 LTS (⚠️ Node.js 24+ **não é compatível** — `better-sqlite3` binários nativos são incompatíveis)
-- **Idioma**: TypeScript 5.9 — **100% TypeScript** em `src/` e `open-sse/` (zero `any` em módulos principais desde v2.0)
-- **Estrutura**: Next.js 16 + React 19 + Tailwind CSS 4
-- **Banco de dados**: LowDB (JSON) + SQLite (estado do domínio + logs de proxy + auditoria MCP + decisões de roteamento)
-- **Esquemas**: Zod (validação de E/S da ferramenta MCP, contratos de API)
-- **Protocolos**: MCP (stdio/HTTP) + A2A v0.3 (JSON-RPC 2.0 + SSE)
-- **Streaming**: eventos enviados pelo servidor (SSE)
-- **Auth**: OAuth 2.0 (PKCE) + JWT + Chaves de API + Autorização com escopo MCP
-- **Testes**: executor de testes Node.js + Vitest (mais de 900 testes incluindo unidade, integração, E2E)
-- **CI/CD**: GitHub Actions (publicação automática de npm + Docker Hub no lançamento)
-- **Site**: [omniroute.online](https://omniroute.online)
-- **Pacote**: [npmjs.com/package/omniroute](https://www.npmjs.com/package/omniroute)
-- **Docker**: [hub.docker.com/r/diegosouzapw/omniroute](https://hub.docker.com/r/diegosouzapw/omniroute)
-- **Resiliência**: Disjuntor, espera exponencial, rebanho anti-trovão, falsificação de TLS, autocura de combinação automática
-
-
-
----
-
-## 📖 Documentação
-
-| Documento | Descrição |
-| ---------------------------------------------- | ------------------------------------------------------------------------ |
-| [User Guide](docs/USER_GUIDE.md) | Provedores, combos, integração CLI, implantação |
-| [API Reference](docs/API_REFERENCE.md) | Todos os endpoints com exemplos |
-| [MCP Server](open-sse/mcp-server/README.md) | 16 ferramentas MCP, configurações IDE, clientes Python/TS/Go |
-| [A2A Server](src/lib/a2a/README.md) | Protocolo JSON-RPC 2.0, habilidades, streaming, gerenciamento de tarefas |
-| [Auto-Combo Engine](docs/auto-combo.md) | Pontuação de 6 fatores, pacotes de modos, autocura |
-| [Troubleshooting](docs/TROUBLESHOOTING.md) | Problemas e soluções comuns |
-| [Architecture](docs/ARCHITECTURE.md) | Arquitetura do sistema e componentes internos |
-| [Contributing](CONTRIBUTING.md) | Configuração e diretrizes de desenvolvimento |
-| [OpenAPI Spec](docs/openapi.yaml) | Especificação OpenAPI 3.0 |
-| [Security Policy](SECURITY.md) | Relatórios de vulnerabilidades e práticas de segurança |
-| [VM Deployment](docs/VM_DEPLOYMENT_GUIDE.md) | Guia completo: configuração de VM + nginx + Cloudflare |
-| [Features Gallery](docs/FEATURES.md) | Tour visual do painel com capturas de tela |
-| [Release Checklist](docs/RELEASE_CHECKLIST.md) | Etapas de validação de pré-lançamento |
-
----
-
-## 🗺️ Roteiro
-
-OmniRoute tem **210+ recursos planejados** em diversas fases de desenvolvimento. Aqui estão as principais áreas:
-
-| Categoria | Recursos planejados | Destaques |
-| --------------------------------- | ------------------- | ------------------------------------------------------------------------------------------------------------ |
-| 🧠 **Roteamento e Inteligência** | 25+ | Roteamento de menor latência, roteamento baseado em tags, simulação de cota, seleção de conta P2C |
-| 🔒 **Segurança e Conformidade** | 20+ | Proteção SSRF, camuflagem de credenciais, limite de taxa por endpoint, escopo de chave de gerenciamento |
-| 📊 **Observabilidade** | 15+ | Integração OpenTelemetry, monitoramento de cotas em tempo real, rastreamento de custos por modelo |
-| 🔄 **Integrações com Provedores** | 20+ | Registro de modelo dinâmico, resfriamento de provedor, Codex multicontas, análise de cotas do Copilot |
-| ⚡ **Desempenho** | 15+ | Camada de cache dupla, cache de prompt, cache de resposta, manutenção de atividade de streaming, API em lote |
-| 🌐 **Ecossistema** | 10+ | API WebSocket, configuração hot-reload, armazenamento de configuração distribuído, modo comercial |
-
-### 🔜 Em breve
-
-- 🔗 **Integração OpenCode** — Suporte de provedor nativo para o IDE de codificação OpenCode AI
-- 🔗 **Integração TRAE** — Suporte total para a estrutura de desenvolvimento TRAE AI
-- 📦 **API Batch** — Processamento assíncrono em lote para solicitações em massa
-- 🎯 **Roteamento baseado em tags** — Roteie solicitações com base em tags personalizadas e metadados
-- 💰 **Estratégia de custo mais baixo** — Selecione automaticamente o provedor mais barato disponível
-
-> 📝 Especificações completas de recursos disponíveis em [**OMNI_TOKEN_342**](docs/new-features/) (217 especificações detalhadas)
-
----
-
-## 👥 Colaboradores
-
-[](https://github.com/diegosouzapw/OmniRoute/graphs/contributors)
-
-### Como contribuir
-
-1. Bifurque o repositório
-2. Crie sua ramificação de recursos (`git checkout -b feature/amazing-feature`)
-3. Confirme suas alterações (`git commit -m 'Add amazing feature'`)
-4. Envie para a ramificação (`git push origin feature/amazing-feature`)
-5. Abra uma solicitação pull
-
-Consulte [CONTRIBUTING.md](CONTRIBUTING.md) para obter diretrizes detalhadas.
-
-### Lançando uma nova versão
-
-```bash
-# Create a release — npm publish happens automatically
-gh release create v2.0.0 --title "v2.0.0" --generate-notes
-```
-
----
-
-## 📊 História das Estrelas
-
-## Observadores das estrelas ao longo do tempo
-
-## [](https://starchart.cc/diegosouzapw/OmniRoute)
-
-## 🙏 Agradecimentos
-
-Agradecimentos especiais a **[9router](https://github.com/decolua/9router)** de **[decolua](https://github.com/decolua)** — o projeto original que inspirou este fork. OmniRoute se baseia nessa base incrível com recursos adicionais, APIs multimodais e uma reescrita completa do TypeScript.
-
-Agradecimentos especiais a **[CLIProxyAPI](https://github.com/router-for-me/CLIProxyAPI)** — a implementação Go original que inspirou esta versão JavaScript.
-
----
-
-## 📄 Licença
-
-Licença MIT - consulte [LICENSE](LICENSE) para obter detalhes.
-
----
-
-
-
Construído com ❤️ para desenvolvedores que codificam 24 horas por dia, 7 dias por semana
-
-
omniroute.online
-
-
diff --git a/README.ro.md b/README.ro.md
deleted file mode 100644
index 01ff4f4db8..0000000000
--- a/README.ro.md
+++ /dev/null
@@ -1,5 +0,0 @@
-# 🌐 OmniRoute (ro)
-
-The documentation has been formalized and moved to our centralized i18n structure.
-
-👉 **[Read the Documentation here](docs/i18n/ro/README.md)**
diff --git a/README.sk.md b/README.sk.md
deleted file mode 100644
index 9345729ed7..0000000000
--- a/README.sk.md
+++ /dev/null
@@ -1,5 +0,0 @@
-# 🌐 OmniRoute (sk)
-
-The documentation has been formalized and moved to our centralized i18n structure.
-
-👉 **[Read the Documentation here](docs/i18n/sk/README.md)**
diff --git a/README.sv.md b/README.sv.md
deleted file mode 100644
index 2194e80227..0000000000
--- a/README.sv.md
+++ /dev/null
@@ -1,5 +0,0 @@
-# 🌐 OmniRoute (sv)
-
-The documentation has been formalized and moved to our centralized i18n structure.
-
-👉 **[Read the Documentation here](docs/i18n/sv/README.md)**
diff --git a/README.th.md b/README.th.md
deleted file mode 100644
index 488ef8db4f..0000000000
--- a/README.th.md
+++ /dev/null
@@ -1,5 +0,0 @@
-# 🌐 OmniRoute (th)
-
-The documentation has been formalized and moved to our centralized i18n structure.
-
-👉 **[Read the Documentation here](docs/i18n/th/README.md)**
diff --git a/README.uk-UA.md b/README.uk-UA.md
deleted file mode 100644
index 39fec3b55c..0000000000
--- a/README.uk-UA.md
+++ /dev/null
@@ -1,5 +0,0 @@
-# 🌐 OmniRoute (uk-UA)
-
-The documentation has been formalized and moved to our centralized i18n structure.
-
-👉 **[Read the Documentation here](docs/i18n/uk-UA/README.md)**
diff --git a/README.vi.md b/README.vi.md
deleted file mode 100644
index 0931b18347..0000000000
--- a/README.vi.md
+++ /dev/null
@@ -1,5 +0,0 @@
-# 🌐 OmniRoute (vi)
-
-The documentation has been formalized and moved to our centralized i18n structure.
-
-👉 **[Read the Documentation here](docs/i18n/vi/README.md)**
diff --git a/SECURITY.md b/SECURITY.md
index b620051d82..c575dd78fa 100644
--- a/SECURITY.md
+++ b/SECURITY.md
@@ -20,9 +20,9 @@ If you discover a security vulnerability in OmniRoute, please report it responsi
| Version | Support Status |
| ------- | -------------- |
-| 1.0.x | ✅ Active |
-| 0.8.x | ✅ Security |
-| < 0.8.0 | ❌ Unsupported |
+| 3.4.x | ✅ Active |
+| 3.0.x | ✅ Security |
+| < 3.0.0 | ❌ Unsupported |
---
@@ -43,6 +43,7 @@ Request → CORS → API Key Auth → Prompt Injection Guard → Input Sanitizer
| **OAuth 2.0 + PKCE** | Secure provider auth (Claude, Codex, Gemini, Cursor, etc.) |
| **Token Refresh** | Automatic OAuth token refresh before expiry |
| **Secure Cookies** | `AUTH_COOKIE_SECURE=true` for HTTPS environments |
+| **MCP Scopes** | 10 granular scopes for MCP tool access control |
### 🛡️ Encryption at Rest
@@ -98,9 +99,11 @@ PII_REDACTION_ENABLED=true
| Feature | Description |
| ------------------------ | ---------------------------------------------------------------- |
| **CORS** | Configurable origin control (`CORS_ORIGIN` env var, default `*`) |
-| **IP Filtering** | Whitelist/blacklist IP ranges in dashboard |
+| **IP Filtering** | Allowlist/blocklist IP ranges in dashboard |
| **Rate Limiting** | Per-provider rate limits with automatic backoff |
| **Anti-Thundering Herd** | Mutex + per-connection locking prevents cascading 502s |
+| **TLS Fingerprint** | Browser-like TLS fingerprint spoofing to reduce bot detection |
+| **CLI Fingerprint** | Per-provider header/body ordering to match native CLI signatures |
### 🔌 Resilience & Availability
@@ -113,11 +116,13 @@ PII_REDACTION_ENABLED=true
### 📋 Compliance
-| Feature | Description |
-| ------------------ | --------------------------------------------------- |
-| **Log Retention** | Automatic cleanup after `LOG_RETENTION_DAYS` |
-| **No-Log Opt-out** | Per API key `noLog` flag disables request logging |
-| **Audit Log** | Administrative actions tracked in `audit_log` table |
+| Feature | Description |
+| ------------------ | ----------------------------------------------------------- |
+| **Log Retention** | Automatic cleanup after `CALL_LOG_RETENTION_DAYS` |
+| **No-Log Opt-out** | Per API key `noLog` flag disables request logging |
+| **Audit Log** | Administrative actions tracked in `audit_log` table |
+| **MCP Audit** | SQLite-backed audit logging for all MCP tool calls |
+| **Zod Validation** | All API inputs validated with Zod v4 schemas at module load |
---
@@ -167,3 +172,4 @@ docker run -d \
- Keep dependencies updated
- The project uses `husky` + `lint-staged` for pre-commit checks
- CI pipeline runs ESLint security rules on every push
+- Provider constants validated at module load via Zod (`src/shared/validation/providerSchema.ts`)
diff --git a/bun.lock b/bun.lock
new file mode 100644
index 0000000000..507b88d19a
--- /dev/null
+++ b/bun.lock
@@ -0,0 +1,2995 @@
+{
+ "lockfileVersion": 1,
+ "configVersion": 0,
+ "workspaces": {
+ "": {
+ "name": "omniroute",
+ "dependencies": {
+ "@lobehub/icons": "^5.0.1",
+ "@modelcontextprotocol/sdk": "^1.27.1",
+ "@monaco-editor/react": "^4.7.0",
+ "@swc/helpers": "0.5.19",
+ "bcryptjs": "^3.0.3",
+ "better-sqlite3": "^12.6.2",
+ "bottleneck": "^2.19.5",
+ "dompurify": "^3.3.2",
+ "express": "^5.2.1",
+ "fetch-socks": "^1.3.2",
+ "http-proxy-middleware": "^3.0.5",
+ "https-proxy-agent": "^8.0.0",
+ "jose": "^6.1.3",
+ "keytar": "^7.9.0",
+ "lowdb": "^7.0.1",
+ "monaco-editor": "^0.55.1",
+ "next": "^16.0.10",
+ "next-intl": "^4.8.3",
+ "node-machine-id": "^1.1.12",
+ "open": "^11.0.0",
+ "ora": "^9.1.0",
+ "pino": "^10.3.1",
+ "pino-pretty": "^13.1.3",
+ "react": "19.2.4",
+ "react-dom": "19.2.4",
+ "recharts": "^3.7.0",
+ "selfsigned": "^5.5.0",
+ "tsx": "^4.21.0",
+ "undici": "^7.19.2",
+ "uuid": "^13.0.0",
+ "wreq-js": "^2.0.1",
+ "yazl": "^3.3.1",
+ "zod": "^4.3.6",
+ "zustand": "^5.0.10",
+ },
+ "devDependencies": {
+ "@playwright/test": "^1.58.2",
+ "@tailwindcss/postcss": "^4.1.18",
+ "@testing-library/jest-dom": "^6.9.1",
+ "@testing-library/react": "^16.3.2",
+ "@types/bcryptjs": "^3.0.0",
+ "@types/better-sqlite3": "^7.6.13",
+ "@types/keytar": "^4.4.0",
+ "@types/node": "^25.2.3",
+ "@types/react": "^19.2.14",
+ "@types/react-dom": "^19.2.3",
+ "@vitejs/plugin-react": "^6.0.1",
+ "c8": "^11.0.0",
+ "concurrently": "^9.2.1",
+ "cross-env": "^10.1.0",
+ "eslint": "^9.39.2",
+ "eslint-config-next": "^16.0.10",
+ "husky": "^9.1.7",
+ "jsdom": "^29.0.1",
+ "lint-staged": "^16.2.7",
+ "prettier": "^3.8.1",
+ "tailwindcss": "^4",
+ "typescript": "^5.9.3",
+ "typescript-eslint": "^8.56.0",
+ "vitest": "^4.0.18",
+ "wait-on": "^9.0.4",
+ },
+ },
+ "open-sse": {
+ "name": "@omniroute/open-sse",
+ "version": "3.3.11",
+ },
+ },
+ "overrides": {
+ "dompurify": "^3.3.2",
+ "path-to-regexp": "^8.4.0",
+ "react": "19.2.4",
+ "react-dom": "19.2.4",
+ },
+ "packages": {
+ "@adobe/css-tools": ["@adobe/css-tools@4.4.4", "", {}, "sha512-Elp+iwUx5rN5+Y8xLt5/GRoG20WGoDCQ/1Fb+1LiGtvwbDavuSk0jhD/eZdckHAuzcDzccnkv+rEjyWfRx18gg=="],
+
+ "@alloc/quick-lru": ["@alloc/quick-lru@5.2.0", "", {}, "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw=="],
+
+ "@ant-design/colors": ["@ant-design/colors@8.0.1", "", { "dependencies": { "@ant-design/fast-color": "^3.0.0" } }, "sha512-foPVl0+SWIslGUtD/xBr1p9U4AKzPhNYEseXYRRo5QSzGACYZrQbe11AYJbYfAWnWSpGBx6JjBmSeugUsD9vqQ=="],
+
+ "@ant-design/cssinjs": ["@ant-design/cssinjs@2.1.2", "", { "dependencies": { "@babel/runtime": "^7.11.1", "@emotion/hash": "^0.8.0", "@emotion/unitless": "^0.7.5", "@rc-component/util": "^1.4.0", "clsx": "^2.1.1", "csstype": "^3.1.3", "stylis": "^4.3.4" }, "peerDependencies": { "react": ">=16.0.0", "react-dom": ">=16.0.0" } }, "sha512-2Hy8BnCEH31xPeSLbhhB2ctCPXE2ZnASdi+KbSeS79BNbUhL9hAEe20SkUk+BR8aKTmqb6+FKFruk7w8z0VoRQ=="],
+
+ "@ant-design/cssinjs-utils": ["@ant-design/cssinjs-utils@2.1.2", "", { "dependencies": { "@ant-design/cssinjs": "^2.1.2", "@babel/runtime": "^7.23.2", "@rc-component/util": "^1.4.0" }, "peerDependencies": { "react": ">=18", "react-dom": ">=18" } }, "sha512-5fTHQ158jJJ5dC/ECeyIdZUzKxE/mpEMRZxthyG1sw/AKRHKgJBg00Yi6ACVXgycdje7KahRNvNET/uBccwCnA=="],
+
+ "@ant-design/fast-color": ["@ant-design/fast-color@3.0.1", "", {}, "sha512-esKJegpW4nckh0o6kV3Tkb7NPIZYbPnnFxmQDUmL08ukXZAvV85TZBr70eGuke/CIArLaP6aw8lt9KILjnWuOw=="],
+
+ "@ant-design/icons": ["@ant-design/icons@6.1.0", "", { "dependencies": { "@ant-design/colors": "^8.0.0", "@ant-design/icons-svg": "^4.4.0", "@rc-component/util": "^1.3.0", "clsx": "^2.1.1" }, "peerDependencies": { "react": ">=16.0.0", "react-dom": ">=16.0.0" } }, "sha512-KrWMu1fIg3w/1F2zfn+JlfNDU8dDqILfA5Tg85iqs1lf8ooyGlbkA+TkwfOKKgqpUmAiRY1PTFpuOU2DAIgSUg=="],
+
+ "@ant-design/icons-svg": ["@ant-design/icons-svg@4.4.2", "", {}, "sha512-vHbT+zJEVzllwP+CM+ul7reTEfBR0vgxFe7+lREAsAA7YGsYpboiq2sQNeQeRvh09GfQgs/GyFEvZpJ9cLXpXA=="],
+
+ "@ant-design/react-slick": ["@ant-design/react-slick@2.0.0", "", { "dependencies": { "@babel/runtime": "^7.28.4", "clsx": "^2.1.1", "json2mq": "^0.2.0", "throttle-debounce": "^5.0.0" }, "peerDependencies": { "react": "^0.14.0 || ^15.0.1 || ^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", "react-dom": "^0.14.0 || ^15.0.1 || ^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, "sha512-HMS9sRoEmZey8LsE/Yo6+klhlzU12PisjrVcydW3So7RdklyEd2qehyU6a7Yp+OYN72mgsYs3NFCyP2lCPFVqg=="],
+
+ "@antfu/install-pkg": ["@antfu/install-pkg@1.1.0", "", { "dependencies": { "package-manager-detector": "^1.3.0", "tinyexec": "^1.0.1" } }, "sha512-MGQsmw10ZyI+EJo45CdSER4zEb+p31LpDAFp2Z3gkSd1yqVZGi0Ebx++YTEMonJy4oChEMLsxZ64j8FH6sSqtQ=="],
+
+ "@asamuzakjp/css-color": ["@asamuzakjp/css-color@5.1.1", "", { "dependencies": { "@csstools/css-calc": "^3.1.1", "@csstools/css-color-parser": "^4.0.2", "@csstools/css-parser-algorithms": "^4.0.0", "@csstools/css-tokenizer": "^4.0.0", "lru-cache": "^11.2.7" } }, "sha512-iGWN8E45Ws0XWx3D44Q1t6vX2LqhCKcwfmwBYCDsFrYFS6m4q/Ks61L2veETaLv+ckDC6+dTETJoaAAb7VjLiw=="],
+
+ "@asamuzakjp/dom-selector": ["@asamuzakjp/dom-selector@7.0.4", "", { "dependencies": { "@asamuzakjp/nwsapi": "^2.3.9", "bidi-js": "^1.0.3", "css-tree": "^3.2.1", "is-potential-custom-element-name": "^1.0.1", "lru-cache": "^11.2.7" } }, "sha512-jXR6x4AcT3eIrS2fSNAwJpwirOkGcd+E7F7CP3zjdTqz9B/2huHOL8YJZBgekKwLML+u7qB/6P1LXQuMScsx0w=="],
+
+ "@asamuzakjp/nwsapi": ["@asamuzakjp/nwsapi@2.3.9", "", {}, "sha512-n8GuYSrI9bF7FFZ/SjhwevlHc8xaVlb/7HmHelnc/PZXBD2ZR49NnN9sMMuDdEGPeeRQ5d0hqlSlEpgCX3Wl0Q=="],
+
+ "@babel/code-frame": ["@babel/code-frame@7.29.0", "", { "dependencies": { "@babel/helper-validator-identifier": "^7.28.5", "js-tokens": "^4.0.0", "picocolors": "^1.1.1" } }, "sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw=="],
+
+ "@babel/compat-data": ["@babel/compat-data@7.29.0", "", {}, "sha512-T1NCJqT/j9+cn8fvkt7jtwbLBfLC/1y1c7NtCeXFRgzGTsafi68MRv8yzkYSapBnFA6L3U2VSc02ciDzoAJhJg=="],
+
+ "@babel/core": ["@babel/core@7.29.0", "", { "dependencies": { "@babel/code-frame": "^7.29.0", "@babel/generator": "^7.29.0", "@babel/helper-compilation-targets": "^7.28.6", "@babel/helper-module-transforms": "^7.28.6", "@babel/helpers": "^7.28.6", "@babel/parser": "^7.29.0", "@babel/template": "^7.28.6", "@babel/traverse": "^7.29.0", "@babel/types": "^7.29.0", "@jridgewell/remapping": "^2.3.5", "convert-source-map": "^2.0.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", "json5": "^2.2.3", "semver": "^6.3.1" } }, "sha512-CGOfOJqWjg2qW/Mb6zNsDm+u5vFQ8DxXfbM09z69p5Z6+mE1ikP2jUXw+j42Pf1XTYED2Rni5f95npYeuwMDQA=="],
+
+ "@babel/generator": ["@babel/generator@7.29.1", "", { "dependencies": { "@babel/parser": "^7.29.0", "@babel/types": "^7.29.0", "@jridgewell/gen-mapping": "^0.3.12", "@jridgewell/trace-mapping": "^0.3.28", "jsesc": "^3.0.2" } }, "sha512-qsaF+9Qcm2Qv8SRIMMscAvG4O3lJ0F1GuMo5HR/Bp02LopNgnZBC/EkbevHFeGs4ls/oPz9v+Bsmzbkbe+0dUw=="],
+
+ "@babel/helper-compilation-targets": ["@babel/helper-compilation-targets@7.28.6", "", { "dependencies": { "@babel/compat-data": "^7.28.6", "@babel/helper-validator-option": "^7.27.1", "browserslist": "^4.24.0", "lru-cache": "^5.1.1", "semver": "^6.3.1" } }, "sha512-JYtls3hqi15fcx5GaSNL7SCTJ2MNmjrkHXg4FSpOA/grxK8KwyZ5bubHsCq8FXCkua6xhuaaBit+3b7+VZRfcA=="],
+
+ "@babel/helper-globals": ["@babel/helper-globals@7.28.0", "", {}, "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw=="],
+
+ "@babel/helper-module-imports": ["@babel/helper-module-imports@7.28.6", "", { "dependencies": { "@babel/traverse": "^7.28.6", "@babel/types": "^7.28.6" } }, "sha512-l5XkZK7r7wa9LucGw9LwZyyCUscb4x37JWTPz7swwFE/0FMQAGpiWUZn8u9DzkSBWEcK25jmvubfpw2dnAMdbw=="],
+
+ "@babel/helper-module-transforms": ["@babel/helper-module-transforms@7.28.6", "", { "dependencies": { "@babel/helper-module-imports": "^7.28.6", "@babel/helper-validator-identifier": "^7.28.5", "@babel/traverse": "^7.28.6" }, "peerDependencies": { "@babel/core": "^7.0.0" } }, "sha512-67oXFAYr2cDLDVGLXTEABjdBJZ6drElUSI7WKp70NrpyISso3plG9SAGEF6y7zbha/wOzUByWWTJvEDVNIUGcA=="],
+
+ "@babel/helper-string-parser": ["@babel/helper-string-parser@7.27.1", "", {}, "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA=="],
+
+ "@babel/helper-validator-identifier": ["@babel/helper-validator-identifier@7.28.5", "", {}, "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q=="],
+
+ "@babel/helper-validator-option": ["@babel/helper-validator-option@7.27.1", "", {}, "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg=="],
+
+ "@babel/helpers": ["@babel/helpers@7.28.6", "", { "dependencies": { "@babel/template": "^7.28.6", "@babel/types": "^7.28.6" } }, "sha512-xOBvwq86HHdB7WUDTfKfT/Vuxh7gElQ+Sfti2Cy6yIWNW05P8iUslOVcZ4/sKbE+/jQaukQAdz/gf3724kYdqw=="],
+
+ "@babel/parser": ["@babel/parser@7.29.0", "", { "dependencies": { "@babel/types": "^7.29.0" }, "bin": { "parser": "bin/babel-parser.js" } }, "sha512-IyDgFV5GeDUVX4YdF/3CPULtVGSXXMLh1xVIgdCgxApktqnQV0r7/8Nqthg+8YLGaAtdyIlo2qIdZrbCv4+7ww=="],
+
+ "@babel/runtime": ["@babel/runtime@7.29.2", "", {}, "sha512-JiDShH45zKHWyGe4ZNVRrCjBz8Nh9TMmZG1kh4QTK8hCBTWBi8Da+i7s1fJw7/lYpM4ccepSNfqzZ/QvABBi5g=="],
+
+ "@babel/template": ["@babel/template@7.28.6", "", { "dependencies": { "@babel/code-frame": "^7.28.6", "@babel/parser": "^7.28.6", "@babel/types": "^7.28.6" } }, "sha512-YA6Ma2KsCdGb+WC6UpBVFJGXL58MDA6oyONbjyF/+5sBgxY/dwkhLogbMT2GXXyU84/IhRw/2D1Os1B/giz+BQ=="],
+
+ "@babel/traverse": ["@babel/traverse@7.29.0", "", { "dependencies": { "@babel/code-frame": "^7.29.0", "@babel/generator": "^7.29.0", "@babel/helper-globals": "^7.28.0", "@babel/parser": "^7.29.0", "@babel/template": "^7.28.6", "@babel/types": "^7.29.0", "debug": "^4.3.1" } }, "sha512-4HPiQr0X7+waHfyXPZpWPfWL/J7dcN1mx9gL6WdQVMbPnF3+ZhSMs8tCxN7oHddJE9fhNE7+lxdnlyemKfJRuA=="],
+
+ "@babel/types": ["@babel/types@7.29.0", "", { "dependencies": { "@babel/helper-string-parser": "^7.27.1", "@babel/helper-validator-identifier": "^7.28.5" } }, "sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A=="],
+
+ "@base-ui/react": ["@base-ui/react@1.0.0", "", { "dependencies": { "@babel/runtime": "^7.28.4", "@base-ui/utils": "0.2.3", "@floating-ui/react-dom": "^2.1.6", "@floating-ui/utils": "^0.2.10", "reselect": "^5.1.1", "tabbable": "^6.3.0", "use-sync-external-store": "^1.6.0" }, "peerDependencies": { "@types/react": "^17 || ^18 || ^19", "react": "^17 || ^18 || ^19", "react-dom": "^17 || ^18 || ^19" } }, "sha512-4USBWz++DUSLTuIYpbYkSgy1F9ZmNG9S/lXvlUN6qMK0P0RlW+6eQmDUB4DgZ7HVvtXl4pvi4z5J2fv6Z3+9hg=="],
+
+ "@base-ui/utils": ["@base-ui/utils@0.2.3", "", { "dependencies": { "@babel/runtime": "^7.28.4", "@floating-ui/utils": "^0.2.10", "reselect": "^5.1.1", "use-sync-external-store": "^1.6.0" }, "peerDependencies": { "@types/react": "^17 || ^18 || ^19", "react": "^17 || ^18 || ^19", "react-dom": "^17 || ^18 || ^19" } }, "sha512-/CguQ2PDaOzeVOkllQR8nocJ0FFIDqsWIcURsVmm53QGo8NhFNpePjNlyPIB41luxfOqnG7PU0xicMEw3ls7XQ=="],
+
+ "@bcoe/v8-coverage": ["@bcoe/v8-coverage@1.0.2", "", {}, "sha512-6zABk/ECA/QYSCQ1NGiVwwbQerUCZ+TQbp64Q3AgmfNvurHH0j8TtXa1qbShXA6qqkpAj4V5W8pP6mLe1mcMqA=="],
+
+ "@braintree/sanitize-url": ["@braintree/sanitize-url@7.1.2", "", {}, "sha512-jigsZK+sMF/cuiB7sERuo9V7N9jx+dhmHHnQyDSVdpZwVutaBu7WvNYqMDLSgFgfB30n452TP3vjDAvFC973mA=="],
+
+ "@bramus/specificity": ["@bramus/specificity@2.4.2", "", { "dependencies": { "css-tree": "^3.0.0" }, "bin": { "specificity": "bin/cli.js" } }, "sha512-ctxtJ/eA+t+6q2++vj5j7FYX3nRu311q1wfYH3xjlLOsczhlhxAg2FWNUXhpGvAw3BWo1xBcvOV6/YLc2r5FJw=="],
+
+ "@chevrotain/cst-dts-gen": ["@chevrotain/cst-dts-gen@11.1.2", "", { "dependencies": { "@chevrotain/gast": "11.1.2", "@chevrotain/types": "11.1.2", "lodash-es": "4.17.23" } }, "sha512-XTsjvDVB5nDZBQB8o0o/0ozNelQtn2KrUVteIHSlPd2VAV2utEb6JzyCJaJ8tGxACR4RiBNWy5uYUHX2eji88Q=="],
+
+ "@chevrotain/gast": ["@chevrotain/gast@11.1.2", "", { "dependencies": { "@chevrotain/types": "11.1.2", "lodash-es": "4.17.23" } }, "sha512-Z9zfXR5jNZb1Hlsd/p+4XWeUFugrHirq36bKzPWDSIacV+GPSVXdk+ahVWZTwjhNwofAWg/sZg58fyucKSQx5g=="],
+
+ "@chevrotain/regexp-to-ast": ["@chevrotain/regexp-to-ast@11.1.2", "", {}, "sha512-nMU3Uj8naWer7xpZTYJdxbAs6RIv/dxYzkYU8GSwgUtcAAlzjcPfX1w+RKRcYG8POlzMeayOQ/znfwxEGo5ulw=="],
+
+ "@chevrotain/types": ["@chevrotain/types@11.1.2", "", {}, "sha512-U+HFai5+zmJCkK86QsaJtoITlboZHBqrVketcO2ROv865xfCMSFpELQoz1GkX5GzME8pTa+3kbKrZHQtI0gdbw=="],
+
+ "@chevrotain/utils": ["@chevrotain/utils@11.1.2", "", {}, "sha512-4mudFAQ6H+MqBTfqLmU7G1ZwRzCLfJEooL/fsF6rCX5eePMbGhoy5n4g+G4vlh2muDcsCTJtL+uKbOzWxs5LHA=="],
+
+ "@csstools/color-helpers": ["@csstools/color-helpers@6.0.2", "", {}, "sha512-LMGQLS9EuADloEFkcTBR3BwV/CGHV7zyDxVRtVDTwdI2Ca4it0CCVTT9wCkxSgokjE5Ho41hEPgb8OEUwoXr6Q=="],
+
+ "@csstools/css-calc": ["@csstools/css-calc@3.1.1", "", { "peerDependencies": { "@csstools/css-parser-algorithms": "^4.0.0", "@csstools/css-tokenizer": "^4.0.0" } }, "sha512-HJ26Z/vmsZQqs/o3a6bgKslXGFAungXGbinULZO3eMsOyNJHeBBZfup5FiZInOghgoM4Hwnmw+OgbJCNg1wwUQ=="],
+
+ "@csstools/css-color-parser": ["@csstools/css-color-parser@4.0.2", "", { "dependencies": { "@csstools/color-helpers": "^6.0.2", "@csstools/css-calc": "^3.1.1" }, "peerDependencies": { "@csstools/css-parser-algorithms": "^4.0.0", "@csstools/css-tokenizer": "^4.0.0" } }, "sha512-0GEfbBLmTFf0dJlpsNU7zwxRIH0/BGEMuXLTCvFYxuL1tNhqzTbtnFICyJLTNK4a+RechKP75e7w42ClXSnJQw=="],
+
+ "@csstools/css-parser-algorithms": ["@csstools/css-parser-algorithms@4.0.0", "", { "peerDependencies": { "@csstools/css-tokenizer": "^4.0.0" } }, "sha512-+B87qS7fIG3L5h3qwJ/IFbjoVoOe/bpOdh9hAjXbvx0o8ImEmUsGXN0inFOnk2ChCFgqkkGFQ+TpM5rbhkKe4w=="],
+
+ "@csstools/css-syntax-patches-for-csstree": ["@csstools/css-syntax-patches-for-csstree@1.1.2", "", { "peerDependencies": { "css-tree": "^3.2.1" }, "optionalPeers": ["css-tree"] }, "sha512-5GkLzz4prTIpoyeUiIu3iV6CSG3Plo7xRVOFPKI7FVEJ3mZ0A8SwK0XU3Gl7xAkiQ+mDyam+NNp875/C5y+jSA=="],
+
+ "@csstools/css-tokenizer": ["@csstools/css-tokenizer@4.0.0", "", {}, "sha512-QxULHAm7cNu72w97JUNCBFODFaXpbDg+dP8b/oWFAZ2MTRppA3U00Y2L1HqaS4J6yBqxwa/Y3nMBaxVKbB/NsA=="],
+
+ "@dnd-kit/accessibility": ["@dnd-kit/accessibility@3.1.1", "", { "dependencies": { "tslib": "^2.0.0" }, "peerDependencies": { "react": ">=16.8.0" } }, "sha512-2P+YgaXF+gRsIihwwY1gCsQSYnu9Zyj2py8kY5fFvUM1qm2WA2u639R6YNVfU4GWr+ZM5mqEsfHZZLoRONbemw=="],
+
+ "@dnd-kit/core": ["@dnd-kit/core@6.3.1", "", { "dependencies": { "@dnd-kit/accessibility": "^3.1.1", "@dnd-kit/utilities": "^3.2.2", "tslib": "^2.0.0" }, "peerDependencies": { "react": ">=16.8.0", "react-dom": ">=16.8.0" } }, "sha512-xkGBRQQab4RLwgXxoqETICr6S5JlogafbhNsidmrkVv2YRs5MLwpjoF2qpiGjQt8S9AoxtIV603s0GIUpY5eYQ=="],
+
+ "@dnd-kit/modifiers": ["@dnd-kit/modifiers@9.0.0", "", { "dependencies": { "@dnd-kit/utilities": "^3.2.2", "tslib": "^2.0.0" }, "peerDependencies": { "@dnd-kit/core": "^6.3.0", "react": ">=16.8.0" } }, "sha512-ybiLc66qRGuZoC20wdSSG6pDXFikui/dCNGthxv4Ndy8ylErY0N3KVxY2bgo7AWwIbxDmXDg3ylAFmnrjcbVvw=="],
+
+ "@dnd-kit/sortable": ["@dnd-kit/sortable@10.0.0", "", { "dependencies": { "@dnd-kit/utilities": "^3.2.2", "tslib": "^2.0.0" }, "peerDependencies": { "@dnd-kit/core": "^6.3.0", "react": ">=16.8.0" } }, "sha512-+xqhmIIzvAYMGfBYYnbKuNicfSsk4RksY2XdmJhT+HAC01nix6fHCztU68jooFiMUB01Ky3F0FyOvhG/BZrWkg=="],
+
+ "@dnd-kit/utilities": ["@dnd-kit/utilities@3.2.2", "", { "dependencies": { "tslib": "^2.0.0" }, "peerDependencies": { "react": ">=16.8.0" } }, "sha512-+MKAJEOfaBe5SmV6t34p80MMKhjvUz0vRrvVJbPT0WElzaOJ/1xs+D+KDv+tD/NE5ujfrChEcshd4fLn0wpiqg=="],
+
+ "@emnapi/core": ["@emnapi/core@1.8.1", "", { "dependencies": { "@emnapi/wasi-threads": "1.1.0", "tslib": "^2.4.0" } }, "sha512-AvT9QFpxK0Zd8J0jopedNm+w/2fIzvtPKPjqyw9jwvBaReTTqPBk9Hixaz7KbjimP+QNz605/XnjFcDAL2pqBg=="],
+
+ "@emnapi/runtime": ["@emnapi/runtime@1.8.1", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-mehfKSMWjjNol8659Z8KxEMrdSJDDot5SXMq00dM8BN4o+CLNXQ0xH2V7EchNHV4RmbZLmmPdEaXZc5H2FXmDg=="],
+
+ "@emnapi/wasi-threads": ["@emnapi/wasi-threads@1.1.0", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-WI0DdZ8xFSbgMjR1sFsKABJ/C5OnRrjT06JXbZKexJGrDuPTzZdDYfFlsgcCXCyf+suG5QU2e/y1Wo2V/OapLQ=="],
+
+ "@emoji-mart/data": ["@emoji-mart/data@1.2.1", "", {}, "sha512-no2pQMWiBy6gpBEiqGeU77/bFejDqUTRY7KX+0+iur13op3bqUsXdnwoZs6Xb1zbv0gAj5VvS1PWoUUckSr5Dw=="],
+
+ "@emoji-mart/react": ["@emoji-mart/react@1.1.1", "", { "peerDependencies": { "emoji-mart": "^5.2", "react": "^16.8 || ^17 || ^18" } }, "sha512-NMlFNeWgv1//uPsvLxvGQoIerPuVdXwK/EUek8OOkJ6wVOWPUizRBJU0hDqWZCOROVpfBgCemaC3m6jDOXi03g=="],
+
+ "@emotion/babel-plugin": ["@emotion/babel-plugin@11.13.5", "", { "dependencies": { "@babel/helper-module-imports": "^7.16.7", "@babel/runtime": "^7.18.3", "@emotion/hash": "^0.9.2", "@emotion/memoize": "^0.9.0", "@emotion/serialize": "^1.3.3", "babel-plugin-macros": "^3.1.0", "convert-source-map": "^1.5.0", "escape-string-regexp": "^4.0.0", "find-root": "^1.1.0", "source-map": "^0.5.7", "stylis": "4.2.0" } }, "sha512-pxHCpT2ex+0q+HH91/zsdHkw/lXd468DIN2zvfvLtPKLLMo6gQj7oLObq8PhkrxOZb/gGCq03S3Z7PDhS8pduQ=="],
+
+ "@emotion/cache": ["@emotion/cache@11.14.0", "", { "dependencies": { "@emotion/memoize": "^0.9.0", "@emotion/sheet": "^1.4.0", "@emotion/utils": "^1.4.2", "@emotion/weak-memoize": "^0.4.0", "stylis": "4.2.0" } }, "sha512-L/B1lc/TViYk4DcpGxtAVbx0ZyiKM5ktoIyafGkH6zg/tj+mA+NE//aPYKG0k8kCHSHVJrpLpcAlOBEXQ3SavA=="],
+
+ "@emotion/css": ["@emotion/css@11.13.5", "", { "dependencies": { "@emotion/babel-plugin": "^11.13.5", "@emotion/cache": "^11.13.5", "@emotion/serialize": "^1.3.3", "@emotion/sheet": "^1.4.0", "@emotion/utils": "^1.4.2" } }, "sha512-wQdD0Xhkn3Qy2VNcIzbLP9MR8TafI0MJb7BEAXKp+w4+XqErksWR4OXomuDzPsN4InLdGhVe6EYcn2ZIUCpB8w=="],
+
+ "@emotion/hash": ["@emotion/hash@0.8.0", "", {}, "sha512-kBJtf7PH6aWwZ6fka3zQ0p6SBYzx4fl1LoZXE2RrnYST9Xljm7WfKJrU4g/Xr3Beg72MLrp1AWNUmuYJTL7Cow=="],
+
+ "@emotion/is-prop-valid": ["@emotion/is-prop-valid@1.4.0", "", { "dependencies": { "@emotion/memoize": "^0.9.0" } }, "sha512-QgD4fyscGcbbKwJmqNvUMSE02OsHUa+lAWKdEUIJKgqe5IwRSKd7+KhibEWdaKwgjLj0DRSHA9biAIqGBk05lw=="],
+
+ "@emotion/memoize": ["@emotion/memoize@0.9.0", "", {}, "sha512-30FAj7/EoJ5mwVPOWhAyCX+FPfMDrVecJAM+Iw9NRoSl4BBAQeqj4cApHHUXOVvIPgLVDsCFoz/hGD+5QQD1GQ=="],
+
+ "@emotion/react": ["@emotion/react@11.14.0", "", { "dependencies": { "@babel/runtime": "^7.18.3", "@emotion/babel-plugin": "^11.13.5", "@emotion/cache": "^11.14.0", "@emotion/serialize": "^1.3.3", "@emotion/use-insertion-effect-with-fallbacks": "^1.2.0", "@emotion/utils": "^1.4.2", "@emotion/weak-memoize": "^0.4.0", "hoist-non-react-statics": "^3.3.1" }, "peerDependencies": { "react": ">=16.8.0" } }, "sha512-O000MLDBDdk/EohJPFUqvnp4qnHeYkVP5B0xEG0D/L7cOKP9kefu2DXn8dj74cQfsEzUqh+sr1RzFqiL1o+PpA=="],
+
+ "@emotion/serialize": ["@emotion/serialize@1.3.3", "", { "dependencies": { "@emotion/hash": "^0.9.2", "@emotion/memoize": "^0.9.0", "@emotion/unitless": "^0.10.0", "@emotion/utils": "^1.4.2", "csstype": "^3.0.2" } }, "sha512-EISGqt7sSNWHGI76hC7x1CksiXPahbxEOrC5RjmFRJTqLyEK9/9hZvBbiYn70dw4wuwMKiEMCUlR6ZXTSWQqxA=="],
+
+ "@emotion/sheet": ["@emotion/sheet@1.4.0", "", {}, "sha512-fTBW9/8r2w3dXWYM4HCB1Rdp8NLibOw2+XELH5m5+AkWiL/KqYX6dc0kKYlaYyKjrQ6ds33MCdMPEwgs2z1rqg=="],
+
+ "@emotion/unitless": ["@emotion/unitless@0.7.5", "", {}, "sha512-OWORNpfjMsSSUBVrRBVGECkhWcULOAJz9ZW8uK9qgxD+87M7jHRcvh/A96XXNhXTLmKcoYSQtBEX7lHMO7YRwg=="],
+
+ "@emotion/use-insertion-effect-with-fallbacks": ["@emotion/use-insertion-effect-with-fallbacks@1.2.0", "", { "peerDependencies": { "react": ">=16.8.0" } }, "sha512-yJMtVdH59sxi/aVJBpk9FQq+OR8ll5GT8oWd57UpeaKEVGab41JWaCFA7FRLoMLloOZF/c/wsPoe+bfGmRKgDg=="],
+
+ "@emotion/utils": ["@emotion/utils@1.4.2", "", {}, "sha512-3vLclRofFziIa3J2wDh9jjbkUz9qk5Vi3IZ/FSTKViB0k+ef0fPV7dYrUIugbgupYDx7v9ud/SjrtEP8Y4xLoA=="],
+
+ "@emotion/weak-memoize": ["@emotion/weak-memoize@0.4.0", "", {}, "sha512-snKqtPW01tN0ui7yu9rGv69aJXr/a/Ywvl11sUjNtEcRc+ng/mQriFL0wLXMef74iHa/EkftbDzU9F8iFbH+zg=="],
+
+ "@epic-web/invariant": ["@epic-web/invariant@1.0.0", "", {}, "sha512-lrTPqgvfFQtR/eY/qkIzp98OGdNJu0m5ji3q/nJI8v3SXkRKEnWiOxMmbvcSoAIzv/cGiuvRy57k4suKQSAdwA=="],
+
+ "@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.27.3", "", { "os": "aix", "cpu": "ppc64" }, "sha512-9fJMTNFTWZMh5qwrBItuziu834eOCUcEqymSH7pY+zoMVEZg3gcPuBNxH1EvfVYe9h0x/Ptw8KBzv7qxb7l8dg=="],
+
+ "@esbuild/android-arm": ["@esbuild/android-arm@0.27.3", "", { "os": "android", "cpu": "arm" }, "sha512-i5D1hPY7GIQmXlXhs2w8AWHhenb00+GxjxRncS2ZM7YNVGNfaMxgzSGuO8o8SJzRc/oZwU2bcScvVERk03QhzA=="],
+
+ "@esbuild/android-arm64": ["@esbuild/android-arm64@0.27.3", "", { "os": "android", "cpu": "arm64" }, "sha512-YdghPYUmj/FX2SYKJ0OZxf+iaKgMsKHVPF1MAq/P8WirnSpCStzKJFjOjzsW0QQ7oIAiccHdcqjbHmJxRb/dmg=="],
+
+ "@esbuild/android-x64": ["@esbuild/android-x64@0.27.3", "", { "os": "android", "cpu": "x64" }, "sha512-IN/0BNTkHtk8lkOM8JWAYFg4ORxBkZQf9zXiEOfERX/CzxW3Vg1ewAhU7QSWQpVIzTW+b8Xy+lGzdYXV6UZObQ=="],
+
+ "@esbuild/darwin-arm64": ["@esbuild/darwin-arm64@0.27.3", "", { "os": "darwin", "cpu": "arm64" }, "sha512-Re491k7ByTVRy0t3EKWajdLIr0gz2kKKfzafkth4Q8A5n1xTHrkqZgLLjFEHVD+AXdUGgQMq+Godfq45mGpCKg=="],
+
+ "@esbuild/darwin-x64": ["@esbuild/darwin-x64@0.27.3", "", { "os": "darwin", "cpu": "x64" }, "sha512-vHk/hA7/1AckjGzRqi6wbo+jaShzRowYip6rt6q7VYEDX4LEy1pZfDpdxCBnGtl+A5zq8iXDcyuxwtv3hNtHFg=="],
+
+ "@esbuild/freebsd-arm64": ["@esbuild/freebsd-arm64@0.27.3", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-ipTYM2fjt3kQAYOvo6vcxJx3nBYAzPjgTCk7QEgZG8AUO3ydUhvelmhrbOheMnGOlaSFUoHXB6un+A7q4ygY9w=="],
+
+ "@esbuild/freebsd-x64": ["@esbuild/freebsd-x64@0.27.3", "", { "os": "freebsd", "cpu": "x64" }, "sha512-dDk0X87T7mI6U3K9VjWtHOXqwAMJBNN2r7bejDsc+j03SEjtD9HrOl8gVFByeM0aJksoUuUVU9TBaZa2rgj0oA=="],
+
+ "@esbuild/linux-arm": ["@esbuild/linux-arm@0.27.3", "", { "os": "linux", "cpu": "arm" }, "sha512-s6nPv2QkSupJwLYyfS+gwdirm0ukyTFNl3KTgZEAiJDd+iHZcbTPPcWCcRYH+WlNbwChgH2QkE9NSlNrMT8Gfw=="],
+
+ "@esbuild/linux-arm64": ["@esbuild/linux-arm64@0.27.3", "", { "os": "linux", "cpu": "arm64" }, "sha512-sZOuFz/xWnZ4KH3YfFrKCf1WyPZHakVzTiqji3WDc0BCl2kBwiJLCXpzLzUBLgmp4veFZdvN5ChW4Eq/8Fc2Fg=="],
+
+ "@esbuild/linux-ia32": ["@esbuild/linux-ia32@0.27.3", "", { "os": "linux", "cpu": "ia32" }, "sha512-yGlQYjdxtLdh0a3jHjuwOrxQjOZYD/C9PfdbgJJF3TIZWnm/tMd/RcNiLngiu4iwcBAOezdnSLAwQDPqTmtTYg=="],
+
+ "@esbuild/linux-loong64": ["@esbuild/linux-loong64@0.27.3", "", { "os": "linux", "cpu": "none" }, "sha512-WO60Sn8ly3gtzhyjATDgieJNet/KqsDlX5nRC5Y3oTFcS1l0KWba+SEa9Ja1GfDqSF1z6hif/SkpQJbL63cgOA=="],
+
+ "@esbuild/linux-mips64el": ["@esbuild/linux-mips64el@0.27.3", "", { "os": "linux", "cpu": "none" }, "sha512-APsymYA6sGcZ4pD6k+UxbDjOFSvPWyZhjaiPyl/f79xKxwTnrn5QUnXR5prvetuaSMsb4jgeHewIDCIWljrSxw=="],
+
+ "@esbuild/linux-ppc64": ["@esbuild/linux-ppc64@0.27.3", "", { "os": "linux", "cpu": "ppc64" }, "sha512-eizBnTeBefojtDb9nSh4vvVQ3V9Qf9Df01PfawPcRzJH4gFSgrObw+LveUyDoKU3kxi5+9RJTCWlj4FjYXVPEA=="],
+
+ "@esbuild/linux-riscv64": ["@esbuild/linux-riscv64@0.27.3", "", { "os": "linux", "cpu": "none" }, "sha512-3Emwh0r5wmfm3ssTWRQSyVhbOHvqegUDRd0WhmXKX2mkHJe1SFCMJhagUleMq+Uci34wLSipf8Lagt4LlpRFWQ=="],
+
+ "@esbuild/linux-s390x": ["@esbuild/linux-s390x@0.27.3", "", { "os": "linux", "cpu": "s390x" }, "sha512-pBHUx9LzXWBc7MFIEEL0yD/ZVtNgLytvx60gES28GcWMqil8ElCYR4kvbV2BDqsHOvVDRrOxGySBM9Fcv744hw=="],
+
+ "@esbuild/linux-x64": ["@esbuild/linux-x64@0.27.3", "", { "os": "linux", "cpu": "x64" }, "sha512-Czi8yzXUWIQYAtL/2y6vogER8pvcsOsk5cpwL4Gk5nJqH5UZiVByIY8Eorm5R13gq+DQKYg0+JyQoytLQas4dA=="],
+
+ "@esbuild/netbsd-arm64": ["@esbuild/netbsd-arm64@0.27.3", "", { "os": "none", "cpu": "arm64" }, "sha512-sDpk0RgmTCR/5HguIZa9n9u+HVKf40fbEUt+iTzSnCaGvY9kFP0YKBWZtJaraonFnqef5SlJ8/TiPAxzyS+UoA=="],
+
+ "@esbuild/netbsd-x64": ["@esbuild/netbsd-x64@0.27.3", "", { "os": "none", "cpu": "x64" }, "sha512-P14lFKJl/DdaE00LItAukUdZO5iqNH7+PjoBm+fLQjtxfcfFE20Xf5CrLsmZdq5LFFZzb5JMZ9grUwvtVYzjiA=="],
+
+ "@esbuild/openbsd-arm64": ["@esbuild/openbsd-arm64@0.27.3", "", { "os": "openbsd", "cpu": "arm64" }, "sha512-AIcMP77AvirGbRl/UZFTq5hjXK+2wC7qFRGoHSDrZ5v5b8DK/GYpXW3CPRL53NkvDqb9D+alBiC/dV0Fb7eJcw=="],
+
+ "@esbuild/openbsd-x64": ["@esbuild/openbsd-x64@0.27.3", "", { "os": "openbsd", "cpu": "x64" }, "sha512-DnW2sRrBzA+YnE70LKqnM3P+z8vehfJWHXECbwBmH/CU51z6FiqTQTHFenPlHmo3a8UgpLyH3PT+87OViOh1AQ=="],
+
+ "@esbuild/openharmony-arm64": ["@esbuild/openharmony-arm64@0.27.3", "", { "os": "none", "cpu": "arm64" }, "sha512-NinAEgr/etERPTsZJ7aEZQvvg/A6IsZG/LgZy+81wON2huV7SrK3e63dU0XhyZP4RKGyTm7aOgmQk0bGp0fy2g=="],
+
+ "@esbuild/sunos-x64": ["@esbuild/sunos-x64@0.27.3", "", { "os": "sunos", "cpu": "x64" }, "sha512-PanZ+nEz+eWoBJ8/f8HKxTTD172SKwdXebZ0ndd953gt1HRBbhMsaNqjTyYLGLPdoWHy4zLU7bDVJztF5f3BHA=="],
+
+ "@esbuild/win32-arm64": ["@esbuild/win32-arm64@0.27.3", "", { "os": "win32", "cpu": "arm64" }, "sha512-B2t59lWWYrbRDw/tjiWOuzSsFh1Y/E95ofKz7rIVYSQkUYBjfSgf6oeYPNWHToFRr2zx52JKApIcAS/D5TUBnA=="],
+
+ "@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.27.3", "", { "os": "win32", "cpu": "ia32" }, "sha512-QLKSFeXNS8+tHW7tZpMtjlNb7HKau0QDpwm49u0vUp9y1WOF+PEzkU84y9GqYaAVW8aH8f3GcBck26jh54cX4Q=="],
+
+ "@esbuild/win32-x64": ["@esbuild/win32-x64@0.27.3", "", { "os": "win32", "cpu": "x64" }, "sha512-4uJGhsxuptu3OcpVAzli+/gWusVGwZZHTlS63hh++ehExkVT8SgiEf7/uC/PclrPPkLhZqGgCTjd0VWLo6xMqA=="],
+
+ "@eslint-community/eslint-utils": ["@eslint-community/eslint-utils@4.9.1", "", { "dependencies": { "eslint-visitor-keys": "^3.4.3" }, "peerDependencies": { "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" } }, "sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ=="],
+
+ "@eslint-community/regexpp": ["@eslint-community/regexpp@4.12.2", "", {}, "sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew=="],
+
+ "@eslint/config-array": ["@eslint/config-array@0.21.2", "", { "dependencies": { "@eslint/object-schema": "^2.1.7", "debug": "^4.3.1", "minimatch": "^3.1.5" } }, "sha512-nJl2KGTlrf9GjLimgIru+V/mzgSK0ABCDQRvxw5BjURL7WfH5uoWmizbH7QB6MmnMBd8cIC9uceWnezL1VZWWw=="],
+
+ "@eslint/config-helpers": ["@eslint/config-helpers@0.4.2", "", { "dependencies": { "@eslint/core": "^0.17.0" } }, "sha512-gBrxN88gOIf3R7ja5K9slwNayVcZgK6SOUORm2uBzTeIEfeVaIhOpCtTox3P6R7o2jLFwLFTLnC7kU/RGcYEgw=="],
+
+ "@eslint/core": ["@eslint/core@0.17.0", "", { "dependencies": { "@types/json-schema": "^7.0.15" } }, "sha512-yL/sLrpmtDaFEiUj1osRP4TI2MDz1AddJL+jZ7KSqvBuliN4xqYY54IfdN8qD8Toa6g1iloph1fxQNkjOxrrpQ=="],
+
+ "@eslint/eslintrc": ["@eslint/eslintrc@3.3.5", "", { "dependencies": { "ajv": "^6.14.0", "debug": "^4.3.2", "espree": "^10.0.1", "globals": "^14.0.0", "ignore": "^5.2.0", "import-fresh": "^3.2.1", "js-yaml": "^4.1.1", "minimatch": "^3.1.5", "strip-json-comments": "^3.1.1" } }, "sha512-4IlJx0X0qftVsN5E+/vGujTRIFtwuLbNsVUe7TO6zYPDR1O6nFwvwhIKEKSrl6dZchmYBITazxKoUYOjdtjlRg=="],
+
+ "@eslint/js": ["@eslint/js@9.39.4", "", {}, "sha512-nE7DEIchvtiFTwBw4Lfbu59PG+kCofhjsKaCWzxTpt4lfRjRMqG6uMBzKXuEcyXhOHoUp9riAm7/aWYGhXZ9cw=="],
+
+ "@eslint/object-schema": ["@eslint/object-schema@2.1.7", "", {}, "sha512-VtAOaymWVfZcmZbp6E2mympDIHvyjXs/12LqWYjVw6qjrfF+VK+fyG33kChz3nnK+SU5/NeHOqrTEHS8sXO3OA=="],
+
+ "@eslint/plugin-kit": ["@eslint/plugin-kit@0.4.1", "", { "dependencies": { "@eslint/core": "^0.17.0", "levn": "^0.4.1" } }, "sha512-43/qtrDUokr7LJqoF2c3+RInu/t4zfrpYdoSDfYyhg52rwLV6TnOvdG4fXm7IkSB3wErkcmJS9iEhjVtOSEjjA=="],
+
+ "@exodus/bytes": ["@exodus/bytes@1.15.0", "", { "peerDependencies": { "@noble/hashes": "^1.8.0 || ^2.0.0" }, "optionalPeers": ["@noble/hashes"] }, "sha512-UY0nlA+feH81UGSHv92sLEPLCeZFjXOuHhrIo0HQydScuQc8s0A7kL/UdgwgDq8g8ilksmuoF35YVTNphV2aBQ=="],
+
+ "@floating-ui/core": ["@floating-ui/core@1.7.5", "", { "dependencies": { "@floating-ui/utils": "^0.2.11" } }, "sha512-1Ih4WTWyw0+lKyFMcBHGbb5U5FtuHJuujoyyr5zTaWS5EYMeT6Jb2AuDeftsCsEuchO+mM2ij5+q9crhydzLhQ=="],
+
+ "@floating-ui/dom": ["@floating-ui/dom@1.7.6", "", { "dependencies": { "@floating-ui/core": "^1.7.5", "@floating-ui/utils": "^0.2.11" } }, "sha512-9gZSAI5XM36880PPMm//9dfiEngYoC6Am2izES1FF406YFsjvyBMmeJ2g4SAju3xWwtuynNRFL2s9hgxpLI5SQ=="],
+
+ "@floating-ui/react": ["@floating-ui/react@0.27.19", "", { "dependencies": { "@floating-ui/react-dom": "^2.1.8", "@floating-ui/utils": "^0.2.11", "tabbable": "^6.0.0" }, "peerDependencies": { "react": ">=17.0.0", "react-dom": ">=17.0.0" } }, "sha512-31B8h5mm8YxotlE7/AU/PhNAl8eWxAmjL/v2QOxroDNkTFLk3Uu82u63N3b6TXa4EGJeeZLVcd/9AlNlVqzeog=="],
+
+ "@floating-ui/react-dom": ["@floating-ui/react-dom@2.1.8", "", { "dependencies": { "@floating-ui/dom": "^1.7.6" }, "peerDependencies": { "react": ">=16.8.0", "react-dom": ">=16.8.0" } }, "sha512-cC52bHwM/n/CxS87FH0yWdngEZrjdtLW/qVruo68qg+prK7ZQ4YGdut2GyDVpoGeAYe/h899rVeOVm6Oi40k2A=="],
+
+ "@floating-ui/utils": ["@floating-ui/utils@0.2.11", "", {}, "sha512-RiB/yIh78pcIxl6lLMG0CgBXAZ2Y0eVHqMPYugu+9U0AeT6YBeiJpf7lbdJNIugFP5SIjwNRgo4DhR1Qxi26Gg=="],
+
+ "@formatjs/ecma402-abstract": ["@formatjs/ecma402-abstract@3.1.1", "", { "dependencies": { "@formatjs/fast-memoize": "3.1.0", "@formatjs/intl-localematcher": "0.8.1", "decimal.js": "^10.6.0", "tslib": "^2.8.1" } }, "sha512-jhZbTwda+2tcNrs4kKvxrPLPjx8QsBCLCUgrrJ/S+G9YrGHWLhAyFMMBHJBnBoOwuLHd7L14FgYudviKaxkO2Q=="],
+
+ "@formatjs/fast-memoize": ["@formatjs/fast-memoize@3.1.0", "", { "dependencies": { "tslib": "^2.8.1" } }, "sha512-b5mvSWCI+XVKiz5WhnBCY3RJ4ZwfjAidU0yVlKa3d3MSgKmH1hC3tBGEAtYyN5mqL7N0G5x0BOUYyO8CEupWgg=="],
+
+ "@formatjs/icu-messageformat-parser": ["@formatjs/icu-messageformat-parser@3.5.1", "", { "dependencies": { "@formatjs/ecma402-abstract": "3.1.1", "@formatjs/icu-skeleton-parser": "2.1.1", "tslib": "^2.8.1" } }, "sha512-sSDmSvmmoVQ92XqWb499KrIhv/vLisJU8ITFrx7T7NZHUmMY7EL9xgRowAosaljhqnj/5iufG24QrdzB6X3ItA=="],
+
+ "@formatjs/icu-skeleton-parser": ["@formatjs/icu-skeleton-parser@2.1.1", "", { "dependencies": { "@formatjs/ecma402-abstract": "3.1.1", "tslib": "^2.8.1" } }, "sha512-PSFABlcNefjI6yyk8f7nyX1DC7NHmq6WaCHZLySEXBrXuLOB2f935YsnzuPjlz+ibhb9yWTdPeVX1OVcj24w2Q=="],
+
+ "@formatjs/intl-localematcher": ["@formatjs/intl-localematcher@0.8.1", "", { "dependencies": { "@formatjs/fast-memoize": "3.1.0", "tslib": "^2.8.1" } }, "sha512-xwEuwQFdtSq1UKtQnyTZWC+eHdv7Uygoa+H2k/9uzBVQjDyp9r20LNDNKedWXll7FssT3GRHvqsdJGYSUWqYFA=="],
+
+ "@giscus/react": ["@giscus/react@3.1.0", "", { "dependencies": { "giscus": "^1.6.0" }, "peerDependencies": { "react": "^16 || ^17 || ^18 || ^19", "react-dom": "^16 || ^17 || ^18 || ^19" } }, "sha512-0TCO2TvL43+oOdyVVGHDItwxD1UMKP2ZYpT6gXmhFOqfAJtZxTzJ9hkn34iAF/b6YzyJ4Um89QIt9z/ajmAEeg=="],
+
+ "@hapi/address": ["@hapi/address@5.1.1", "", { "dependencies": { "@hapi/hoek": "^11.0.2" } }, "sha512-A+po2d/dVoY7cYajycYI43ZbYMXukuopIsqCjh5QzsBCipDtdofHntljDlpccMjIfTy6UOkg+5KPriwYch2bXA=="],
+
+ "@hapi/formula": ["@hapi/formula@3.0.2", "", {}, "sha512-hY5YPNXzw1He7s0iqkRQi+uMGh383CGdyyIGYtB+W5N3KHPXoqychklvHhKCC9M3Xtv0OCs/IHw+r4dcHtBYWw=="],
+
+ "@hapi/hoek": ["@hapi/hoek@11.0.7", "", {}, "sha512-HV5undWkKzcB4RZUusqOpcgxOaq6VOAH7zhhIr2g3G8NF/MlFO75SjOr2NfuSx0Mh40+1FqCkagKLJRykUWoFQ=="],
+
+ "@hapi/pinpoint": ["@hapi/pinpoint@2.0.1", "", {}, "sha512-EKQmr16tM8s16vTT3cA5L0kZZcTMU5DUOZTuvpnY738m+jyP3JIUj+Mm1xc1rsLkGBQ/gVnfKYPwOmPg1tUR4Q=="],
+
+ "@hapi/tlds": ["@hapi/tlds@1.1.6", "", {}, "sha512-xdi7A/4NZokvV0ewovme3aUO5kQhW9pQ2YD1hRqZGhhSi5rBv4usHYidVocXSi9eihYsznZxLtAiEYYUL6VBGw=="],
+
+ "@hapi/topo": ["@hapi/topo@6.0.2", "", { "dependencies": { "@hapi/hoek": "^11.0.2" } }, "sha512-KR3rD5inZbGMrHmgPxsJ9dbi6zEK+C3ZwUwTa+eMwWLz7oijWUTWD2pMSNNYJAU6Qq+65NkxXjqHr/7LM2Xkqg=="],
+
+ "@hono/node-server": ["@hono/node-server@1.19.10", "", { "peerDependencies": { "hono": "^4" } }, "sha512-hZ7nOssGqRgyV3FVVQdfi+U4q02uB23bpnYpdvNXkYTRRyWx84b7yf1ans+dnJ/7h41sGL3CeQTfO+ZGxuO+Iw=="],
+
+ "@humanfs/core": ["@humanfs/core@0.19.1", "", {}, "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA=="],
+
+ "@humanfs/node": ["@humanfs/node@0.16.7", "", { "dependencies": { "@humanfs/core": "^0.19.1", "@humanwhocodes/retry": "^0.4.0" } }, "sha512-/zUx+yOsIrG4Y43Eh2peDeKCxlRt/gET6aHfaKpuq267qXdYDFViVHfMaLyygZOnl0kGWxFIgsBy8QFuTLUXEQ=="],
+
+ "@humanwhocodes/module-importer": ["@humanwhocodes/module-importer@1.0.1", "", {}, "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA=="],
+
+ "@humanwhocodes/retry": ["@humanwhocodes/retry@0.4.3", "", {}, "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ=="],
+
+ "@iconify/types": ["@iconify/types@2.0.0", "", {}, "sha512-+wluvCrRhXrhyOmRDJ3q8mux9JkKy5SJ/v8ol2tu4FVjyYvtEzkc/3pK15ET6RKg4b4w4BmTk1+gsCUhf21Ykg=="],
+
+ "@iconify/utils": ["@iconify/utils@3.1.0", "", { "dependencies": { "@antfu/install-pkg": "^1.1.0", "@iconify/types": "^2.0.0", "mlly": "^1.8.0" } }, "sha512-Zlzem1ZXhI1iHeeERabLNzBHdOa4VhQbqAcOQaMKuTuyZCpwKbC2R4Dd0Zo3g9EAc+Y4fiarO8HIHRAth7+skw=="],
+
+ "@img/colour": ["@img/colour@1.0.0", "", {}, "sha512-A5P/LfWGFSl6nsckYtjw9da+19jB8hkJ6ACTGcDfEJ0aE+l2n2El7dsVM7UVHZQ9s2lmYMWlrS21YLy2IR1LUw=="],
+
+ "@img/sharp-darwin-arm64": ["@img/sharp-darwin-arm64@0.34.5", "", { "optionalDependencies": { "@img/sharp-libvips-darwin-arm64": "1.2.4" }, "os": "darwin", "cpu": "arm64" }, "sha512-imtQ3WMJXbMY4fxb/Ndp6HBTNVtWCUI0WdobyheGf5+ad6xX8VIDO8u2xE4qc/fr08CKG/7dDseFtn6M6g/r3w=="],
+
+ "@img/sharp-darwin-x64": ["@img/sharp-darwin-x64@0.34.5", "", { "optionalDependencies": { "@img/sharp-libvips-darwin-x64": "1.2.4" }, "os": "darwin", "cpu": "x64" }, "sha512-YNEFAF/4KQ/PeW0N+r+aVVsoIY0/qxxikF2SWdp+NRkmMB7y9LBZAVqQ4yhGCm/H3H270OSykqmQMKLBhBJDEw=="],
+
+ "@img/sharp-libvips-darwin-arm64": ["@img/sharp-libvips-darwin-arm64@1.2.4", "", { "os": "darwin", "cpu": "arm64" }, "sha512-zqjjo7RatFfFoP0MkQ51jfuFZBnVE2pRiaydKJ1G/rHZvnsrHAOcQALIi9sA5co5xenQdTugCvtb1cuf78Vf4g=="],
+
+ "@img/sharp-libvips-darwin-x64": ["@img/sharp-libvips-darwin-x64@1.2.4", "", { "os": "darwin", "cpu": "x64" }, "sha512-1IOd5xfVhlGwX+zXv2N93k0yMONvUlANylbJw1eTah8K/Jtpi15KC+WSiaX/nBmbm2HxRM1gZ0nSdjSsrZbGKg=="],
+
+ "@img/sharp-libvips-linux-arm": ["@img/sharp-libvips-linux-arm@1.2.4", "", { "os": "linux", "cpu": "arm" }, "sha512-bFI7xcKFELdiNCVov8e44Ia4u2byA+l3XtsAj+Q8tfCwO6BQ8iDojYdvoPMqsKDkuoOo+X6HZA0s0q11ANMQ8A=="],
+
+ "@img/sharp-libvips-linux-arm64": ["@img/sharp-libvips-linux-arm64@1.2.4", "", { "os": "linux", "cpu": "arm64" }, "sha512-excjX8DfsIcJ10x1Kzr4RcWe1edC9PquDRRPx3YVCvQv+U5p7Yin2s32ftzikXojb1PIFc/9Mt28/y+iRklkrw=="],
+
+ "@img/sharp-libvips-linux-ppc64": ["@img/sharp-libvips-linux-ppc64@1.2.4", "", { "os": "linux", "cpu": "ppc64" }, "sha512-FMuvGijLDYG6lW+b/UvyilUWu5Ayu+3r2d1S8notiGCIyYU/76eig1UfMmkZ7vwgOrzKzlQbFSuQfgm7GYUPpA=="],
+
+ "@img/sharp-libvips-linux-riscv64": ["@img/sharp-libvips-linux-riscv64@1.2.4", "", { "os": "linux", "cpu": "none" }, "sha512-oVDbcR4zUC0ce82teubSm+x6ETixtKZBh/qbREIOcI3cULzDyb18Sr/Wcyx7NRQeQzOiHTNbZFF1UwPS2scyGA=="],
+
+ "@img/sharp-libvips-linux-s390x": ["@img/sharp-libvips-linux-s390x@1.2.4", "", { "os": "linux", "cpu": "s390x" }, "sha512-qmp9VrzgPgMoGZyPvrQHqk02uyjA0/QrTO26Tqk6l4ZV0MPWIW6LTkqOIov+J1yEu7MbFQaDpwdwJKhbJvuRxQ=="],
+
+ "@img/sharp-libvips-linux-x64": ["@img/sharp-libvips-linux-x64@1.2.4", "", { "os": "linux", "cpu": "x64" }, "sha512-tJxiiLsmHc9Ax1bz3oaOYBURTXGIRDODBqhveVHonrHJ9/+k89qbLl0bcJns+e4t4rvaNBxaEZsFtSfAdquPrw=="],
+
+ "@img/sharp-libvips-linuxmusl-arm64": ["@img/sharp-libvips-linuxmusl-arm64@1.2.4", "", { "os": "linux", "cpu": "arm64" }, "sha512-FVQHuwx1IIuNow9QAbYUzJ+En8KcVm9Lk5+uGUQJHaZmMECZmOlix9HnH7n1TRkXMS0pGxIJokIVB9SuqZGGXw=="],
+
+ "@img/sharp-libvips-linuxmusl-x64": ["@img/sharp-libvips-linuxmusl-x64@1.2.4", "", { "os": "linux", "cpu": "x64" }, "sha512-+LpyBk7L44ZIXwz/VYfglaX/okxezESc6UxDSoyo2Ks6Jxc4Y7sGjpgU9s4PMgqgjj1gZCylTieNamqA1MF7Dg=="],
+
+ "@img/sharp-linux-arm": ["@img/sharp-linux-arm@0.34.5", "", { "optionalDependencies": { "@img/sharp-libvips-linux-arm": "1.2.4" }, "os": "linux", "cpu": "arm" }, "sha512-9dLqsvwtg1uuXBGZKsxem9595+ujv0sJ6Vi8wcTANSFpwV/GONat5eCkzQo/1O6zRIkh0m/8+5BjrRr7jDUSZw=="],
+
+ "@img/sharp-linux-arm64": ["@img/sharp-linux-arm64@0.34.5", "", { "optionalDependencies": { "@img/sharp-libvips-linux-arm64": "1.2.4" }, "os": "linux", "cpu": "arm64" }, "sha512-bKQzaJRY/bkPOXyKx5EVup7qkaojECG6NLYswgktOZjaXecSAeCWiZwwiFf3/Y+O1HrauiE3FVsGxFg8c24rZg=="],
+
+ "@img/sharp-linux-ppc64": ["@img/sharp-linux-ppc64@0.34.5", "", { "optionalDependencies": { "@img/sharp-libvips-linux-ppc64": "1.2.4" }, "os": "linux", "cpu": "ppc64" }, "sha512-7zznwNaqW6YtsfrGGDA6BRkISKAAE1Jo0QdpNYXNMHu2+0dTrPflTLNkpc8l7MUP5M16ZJcUvysVWWrMefZquA=="],
+
+ "@img/sharp-linux-riscv64": ["@img/sharp-linux-riscv64@0.34.5", "", { "optionalDependencies": { "@img/sharp-libvips-linux-riscv64": "1.2.4" }, "os": "linux", "cpu": "none" }, "sha512-51gJuLPTKa7piYPaVs8GmByo7/U7/7TZOq+cnXJIHZKavIRHAP77e3N2HEl3dgiqdD/w0yUfiJnII77PuDDFdw=="],
+
+ "@img/sharp-linux-s390x": ["@img/sharp-linux-s390x@0.34.5", "", { "optionalDependencies": { "@img/sharp-libvips-linux-s390x": "1.2.4" }, "os": "linux", "cpu": "s390x" }, "sha512-nQtCk0PdKfho3eC5MrbQoigJ2gd1CgddUMkabUj+rBevs8tZ2cULOx46E7oyX+04WGfABgIwmMC0VqieTiR4jg=="],
+
+ "@img/sharp-linux-x64": ["@img/sharp-linux-x64@0.34.5", "", { "optionalDependencies": { "@img/sharp-libvips-linux-x64": "1.2.4" }, "os": "linux", "cpu": "x64" }, "sha512-MEzd8HPKxVxVenwAa+JRPwEC7QFjoPWuS5NZnBt6B3pu7EG2Ge0id1oLHZpPJdn3OQK+BQDiw9zStiHBTJQQQQ=="],
+
+ "@img/sharp-linuxmusl-arm64": ["@img/sharp-linuxmusl-arm64@0.34.5", "", { "optionalDependencies": { "@img/sharp-libvips-linuxmusl-arm64": "1.2.4" }, "os": "linux", "cpu": "arm64" }, "sha512-fprJR6GtRsMt6Kyfq44IsChVZeGN97gTD331weR1ex1c1rypDEABN6Tm2xa1wE6lYb5DdEnk03NZPqA7Id21yg=="],
+
+ "@img/sharp-linuxmusl-x64": ["@img/sharp-linuxmusl-x64@0.34.5", "", { "optionalDependencies": { "@img/sharp-libvips-linuxmusl-x64": "1.2.4" }, "os": "linux", "cpu": "x64" }, "sha512-Jg8wNT1MUzIvhBFxViqrEhWDGzqymo3sV7z7ZsaWbZNDLXRJZoRGrjulp60YYtV4wfY8VIKcWidjojlLcWrd8Q=="],
+
+ "@img/sharp-wasm32": ["@img/sharp-wasm32@0.34.5", "", { "dependencies": { "@emnapi/runtime": "^1.7.0" }, "cpu": "none" }, "sha512-OdWTEiVkY2PHwqkbBI8frFxQQFekHaSSkUIJkwzclWZe64O1X4UlUjqqqLaPbUpMOQk6FBu/HtlGXNblIs0huw=="],
+
+ "@img/sharp-win32-arm64": ["@img/sharp-win32-arm64@0.34.5", "", { "os": "win32", "cpu": "arm64" }, "sha512-WQ3AgWCWYSb2yt+IG8mnC6Jdk9Whs7O0gxphblsLvdhSpSTtmu69ZG1Gkb6NuvxsNACwiPV6cNSZNzt0KPsw7g=="],
+
+ "@img/sharp-win32-ia32": ["@img/sharp-win32-ia32@0.34.5", "", { "os": "win32", "cpu": "ia32" }, "sha512-FV9m/7NmeCmSHDD5j4+4pNI8Cp3aW+JvLoXcTUo0IqyjSfAZJ8dIUmijx1qaJsIiU+Hosw6xM5KijAWRJCSgNg=="],
+
+ "@img/sharp-win32-x64": ["@img/sharp-win32-x64@0.34.5", "", { "os": "win32", "cpu": "x64" }, "sha512-+29YMsqY2/9eFEiW93eqWnuLcWcufowXewwSNIT6UwZdUUCrM3oFjMWH/Z6/TMmb4hlFenmfAVbpWeup2jryCw=="],
+
+ "@istanbuljs/schema": ["@istanbuljs/schema@0.1.3", "", {}, "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA=="],
+
+ "@jridgewell/gen-mapping": ["@jridgewell/gen-mapping@0.3.13", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.0", "@jridgewell/trace-mapping": "^0.3.24" } }, "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA=="],
+
+ "@jridgewell/remapping": ["@jridgewell/remapping@2.3.5", "", { "dependencies": { "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.24" } }, "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ=="],
+
+ "@jridgewell/resolve-uri": ["@jridgewell/resolve-uri@3.1.2", "", {}, "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw=="],
+
+ "@jridgewell/sourcemap-codec": ["@jridgewell/sourcemap-codec@1.5.5", "", {}, "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og=="],
+
+ "@jridgewell/trace-mapping": ["@jridgewell/trace-mapping@0.3.31", "", { "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" } }, "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw=="],
+
+ "@lit-labs/ssr-dom-shim": ["@lit-labs/ssr-dom-shim@1.5.1", "", {}, "sha512-Aou5UdlSpr5whQe8AA/bZG0jMj96CoJIWbGfZ91qieWu5AWUMKw8VR/pAkQkJYvBNhmCcWnZlyyk5oze8JIqYA=="],
+
+ "@lit/reactive-element": ["@lit/reactive-element@2.1.2", "", { "dependencies": { "@lit-labs/ssr-dom-shim": "^1.5.0" } }, "sha512-pbCDiVMnne1lYUIaYNN5wrwQXDtHaYtg7YEFPeW+hws6U47WeFvISGUWekPGKWOP1ygrs0ef0o1VJMk1exos5A=="],
+
+ "@lobehub/emojilib": ["@lobehub/emojilib@1.0.0", "", {}, "sha512-s9KnjaPjsEefaNv150G3aifvB+J3P4eEKG+epY9zDPS2BeB6+V2jELWqAZll+nkogMaVovjEE813z3V751QwGw=="],
+
+ "@lobehub/fluent-emoji": ["@lobehub/fluent-emoji@4.1.0", "", { "dependencies": { "@lobehub/emojilib": "^1.0.0", "antd-style": "^4.1.0", "emoji-regex": "^10.6.0", "es-toolkit": "^1.43.0", "lucide-react": "^0.562.0", "url-join": "^5.0.0" }, "peerDependencies": { "react": "^19.0.0", "react-dom": "^19.0.0" } }, "sha512-R1MB2lfUkDvB7XAQdRzY75c1dx/tB7gEvBPaEEMarzKfCJWmXm7rheS6caVzmgwAlq5sfmTbxPL+un99sp//Yw=="],
+
+ "@lobehub/icons": ["@lobehub/icons@5.0.1", "", { "dependencies": { "antd-style": "^4.1.0", "lucide-react": "^0.469.0", "polished": "^4.3.1" }, "peerDependencies": { "@lobehub/ui": "^5.0.0", "antd": "^6.1.1", "react": "^19.0.0", "react-dom": "^19.0.0" } }, "sha512-Wp9KINavihoWtTOHqHFj80GaKOrIRnOT0S7q5JxMRjijv4CEzbyEkJ2ILJlTz8zstRUfx+HvCVAKUv/Mbdp00Q=="],
+
+ "@lobehub/ui": ["@lobehub/ui@5.5.2", "", { "dependencies": { "@ant-design/cssinjs": "^2.0.3", "@base-ui/react": "1.0.0", "@dnd-kit/core": "^6.3.1", "@dnd-kit/modifiers": "^9.0.0", "@dnd-kit/sortable": "^10.0.0", "@dnd-kit/utilities": "^3.2.2", "@emoji-mart/data": "^1.2.1", "@emoji-mart/react": "^1.1.1", "@emotion/is-prop-valid": "^1.4.0", "@floating-ui/react": "^0.27.17", "@giscus/react": "^3.1.0", "@mdx-js/mdx": "^3.1.1", "@mdx-js/react": "^3.1.1", "@pierre/diffs": "^1.0.10", "@radix-ui/react-slot": "^1.2.4", "@shikijs/core": "^3.22.0", "@shikijs/transformers": "^3.22.0", "@splinetool/runtime": "0.9.526", "ahooks": "^3.9.6", "antd-style": "^4.1.0", "chroma-js": "^3.2.0", "class-variance-authority": "^0.7.1", "clsx": "^2.1.1", "dayjs": "^1.11.19", "emoji-mart": "^5.6.0", "es-toolkit": "^1.44.0", "fast-deep-equal": "^3.1.3", "immer": "^11.1.3", "katex": "^0.16.28", "leva": "^0.10.1", "lucide-react": "^0.563.0", "marked": "^17.0.1", "mermaid": "^11.12.2", "motion": "^12.30.0", "numeral": "^2.0.6", "polished": "^4.3.1", "query-string": "^9.3.1", "rc-collapse": "^4.0.0", "rc-footer": "^0.6.8", "rc-image": "^7.12.0", "rc-input-number": "^9.5.0", "rc-menu": "^9.16.1", "re-resizable": "^6.11.2", "react-avatar-editor": "^14.0.0", "react-error-boundary": "^6.1.0", "react-hotkeys-hook": "^5.2.4", "react-markdown": "^10.1.0", "react-merge-refs": "^3.0.2", "react-rnd": "^10.5.2", "react-zoom-pan-pinch": "^3.7.0", "rehype-github-alerts": "^4.2.0", "rehype-katex": "^7.0.1", "rehype-raw": "^7.0.0", "remark-breaks": "^4.0.0", "remark-cjk-friendly": "^1.2.3", "remark-gfm": "^4.0.1", "remark-github": "^12.0.0", "remark-math": "^6.0.0", "remend": "^1.2.0", "shiki": "^3.22.0", "shiki-stream": "^0.1.4", "swr": "^2.4.0", "ts-md5": "^2.0.1", "unified": "^11.0.5", "url-join": "^5.0.0", "use-merge-value": "^1.2.0", "uuid": "^13.0.0", "virtua": "^0.48.5" }, "peerDependencies": { "@lobehub/fluent-emoji": "^4.0.0", "@lobehub/icons": "^5.0.0", "antd": "^6.1.1", "motion": "^12.0.0", "react": "^19.0.0", "react-dom": "^19.0.0" } }, "sha512-bcC075ELclUd2ydAzwhmWUhHbcIFU6zKldnSLUuDIaPdfc5UF5Gr1YBqdZe77wB3ItInTMzaozWvSWK1LQNeJQ=="],
+
+ "@mdx-js/mdx": ["@mdx-js/mdx@3.1.1", "", { "dependencies": { "@types/estree": "^1.0.0", "@types/estree-jsx": "^1.0.0", "@types/hast": "^3.0.0", "@types/mdx": "^2.0.0", "acorn": "^8.0.0", "collapse-white-space": "^2.0.0", "devlop": "^1.0.0", "estree-util-is-identifier-name": "^3.0.0", "estree-util-scope": "^1.0.0", "estree-walker": "^3.0.0", "hast-util-to-jsx-runtime": "^2.0.0", "markdown-extensions": "^2.0.0", "recma-build-jsx": "^1.0.0", "recma-jsx": "^1.0.0", "recma-stringify": "^1.0.0", "rehype-recma": "^1.0.0", "remark-mdx": "^3.0.0", "remark-parse": "^11.0.0", "remark-rehype": "^11.0.0", "source-map": "^0.7.0", "unified": "^11.0.0", "unist-util-position-from-estree": "^2.0.0", "unist-util-stringify-position": "^4.0.0", "unist-util-visit": "^5.0.0", "vfile": "^6.0.0" } }, "sha512-f6ZO2ifpwAQIpzGWaBQT2TXxPv6z3RBzQKpVftEWN78Vl/YweF1uwussDx8ECAXVtr3Rs89fKyG9YlzUs9DyGQ=="],
+
+ "@mdx-js/react": ["@mdx-js/react@3.1.1", "", { "dependencies": { "@types/mdx": "^2.0.0" }, "peerDependencies": { "@types/react": ">=16", "react": ">=16" } }, "sha512-f++rKLQgUVYDAtECQ6fn/is15GkEH9+nZPM3MS0RcxVqoTfawHvDlSCH7JbMhAM6uJ32v3eXLvLmLvjGu7PTQw=="],
+
+ "@mermaid-js/parser": ["@mermaid-js/parser@1.0.1", "", { "dependencies": { "langium": "^4.0.0" } }, "sha512-opmV19kN1JsK0T6HhhokHpcVkqKpF+x2pPDKKM2ThHtZAB5F4PROopk0amuVYK5qMrIA4erzpNm8gmPNJgMDxQ=="],
+
+ "@modelcontextprotocol/sdk": ["@modelcontextprotocol/sdk@1.27.1", "", { "dependencies": { "@hono/node-server": "^1.19.9", "ajv": "^8.17.1", "ajv-formats": "^3.0.1", "content-type": "^1.0.5", "cors": "^2.8.5", "cross-spawn": "^7.0.5", "eventsource": "^3.0.2", "eventsource-parser": "^3.0.0", "express": "^5.2.1", "express-rate-limit": "^8.2.1", "hono": "^4.11.4", "jose": "^6.1.3", "json-schema-typed": "^8.0.2", "pkce-challenge": "^5.0.0", "raw-body": "^3.0.0", "zod": "^3.25 || ^4.0", "zod-to-json-schema": "^3.25.1" }, "peerDependencies": { "@cfworker/json-schema": "^4.1.1", "zod": "^3.25 || ^4.0" }, "optionalPeers": ["@cfworker/json-schema"] }, "sha512-sr6GbP+4edBwFndLbM60gf07z0FQ79gaExpnsjMGePXqFcSSb7t6iscpjk9DhFhwd+mTEQrzNafGP8/iGGFYaA=="],
+
+ "@monaco-editor/loader": ["@monaco-editor/loader@1.7.0", "", { "dependencies": { "state-local": "^1.0.6" } }, "sha512-gIwR1HrJrrx+vfyOhYmCZ0/JcWqG5kbfG7+d3f/C1LXk2EvzAbHSg3MQ5lO2sMlo9izoAZ04shohfKLVT6crVA=="],
+
+ "@monaco-editor/react": ["@monaco-editor/react@4.7.0", "", { "dependencies": { "@monaco-editor/loader": "^1.5.0" }, "peerDependencies": { "monaco-editor": ">= 0.25.0 < 1", "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, "sha512-cyzXQCtO47ydzxpQtCGSQGOC8Gk3ZUeBXFAxD+CWXYFo5OqZyZUonFl0DwUlTyAfRHntBfw2p3w4s9R6oe1eCA=="],
+
+ "@napi-rs/wasm-runtime": ["@napi-rs/wasm-runtime@1.1.1", "", { "dependencies": { "@emnapi/core": "^1.7.1", "@emnapi/runtime": "^1.7.1", "@tybys/wasm-util": "^0.10.1" } }, "sha512-p64ah1M1ld8xjWv3qbvFwHiFVWrq1yFvV4f7w+mzaqiR4IlSgkqhcRdHwsGgomwzBH51sRY4NEowLxnaBjcW/A=="],
+
+ "@next/env": ["@next/env@16.1.7", "", {}, "sha512-rJJbIdJB/RQr2F1nylZr/PJzamvNNhfr3brdKP6s/GW850jbtR70QlSfFselvIBbcPUOlQwBakexjFzqLzF6pg=="],
+
+ "@next/eslint-plugin-next": ["@next/eslint-plugin-next@16.1.6", "", { "dependencies": { "fast-glob": "3.3.1" } }, "sha512-/Qq3PTagA6+nYVfryAtQ7/9FEr/6YVyvOtl6rZnGsbReGLf0jZU6gkpr1FuChAQpvV46a78p4cmHOVP8mbfSMQ=="],
+
+ "@next/swc-darwin-arm64": ["@next/swc-darwin-arm64@16.1.7", "", { "os": "darwin", "cpu": "arm64" }, "sha512-b2wWIE8sABdyafc4IM8r5Y/dS6kD80JRtOGrUiKTsACFQfWWgUQ2NwoUX1yjFMXVsAwcQeNpnucF2ZrujsBBPg=="],
+
+ "@next/swc-darwin-x64": ["@next/swc-darwin-x64@16.1.7", "", { "os": "darwin", "cpu": "x64" }, "sha512-zcnVaaZulS1WL0Ss38R5Q6D2gz7MtBu8GZLPfK+73D/hp4GFMrC2sudLky1QibfV7h6RJBJs/gOFvYP0X7UVlQ=="],
+
+ "@next/swc-linux-arm64-gnu": ["@next/swc-linux-arm64-gnu@16.1.7", "", { "os": "linux", "cpu": "arm64" }, "sha512-2ant89Lux/Q3VyC8vNVg7uBaFVP9SwoK2jJOOR0L8TQnX8CAYnh4uctAScy2Hwj2dgjVHqHLORQZJ2wH6VxhSQ=="],
+
+ "@next/swc-linux-arm64-musl": ["@next/swc-linux-arm64-musl@16.1.7", "", { "os": "linux", "cpu": "arm64" }, "sha512-uufcze7LYv0FQg9GnNeZ3/whYfo+1Q3HnQpm16o6Uyi0OVzLlk2ZWoY7j07KADZFY8qwDbsmFnMQP3p3+Ftprw=="],
+
+ "@next/swc-linux-x64-gnu": ["@next/swc-linux-x64-gnu@16.1.7", "", { "os": "linux", "cpu": "x64" }, "sha512-KWVf2gxYvHtvuT+c4MBOGxuse5TD7DsMFYSxVxRBnOzok/xryNeQSjXgxSv9QpIVlaGzEn/pIuI6Koosx8CGWA=="],
+
+ "@next/swc-linux-x64-musl": ["@next/swc-linux-x64-musl@16.1.7", "", { "os": "linux", "cpu": "x64" }, "sha512-HguhaGwsGr1YAGs68uRKc4aGWxLET+NevJskOcCAwXbwj0fYX0RgZW2gsOCzr9S11CSQPIkxmoSbuVaBp4Z3dA=="],
+
+ "@next/swc-win32-arm64-msvc": ["@next/swc-win32-arm64-msvc@16.1.7", "", { "os": "win32", "cpu": "arm64" }, "sha512-S0n3KrDJokKTeFyM/vGGGR8+pCmXYrjNTk2ZozOL1C/JFdfUIL9O1ATaJOl5r2POe56iRChbsszrjMAdWSv7kQ=="],
+
+ "@next/swc-win32-x64-msvc": ["@next/swc-win32-x64-msvc@16.1.7", "", { "os": "win32", "cpu": "x64" }, "sha512-mwgtg8CNZGYm06LeEd+bNnOUfwOyNem/rOiP14Lsz+AnUY92Zq/LXwtebtUiaeVkhbroRCQ0c8GlR4UT1U+0yg=="],
+
+ "@noble/hashes": ["@noble/hashes@1.4.0", "", {}, "sha512-V1JJ1WTRUqHHrOSh597hURcMqVKVGL/ea3kv0gSnEdsEZ0/+VyPghM1lMNGc00z7CIQorSvbKpuJkxvuHbvdbg=="],
+
+ "@nodelib/fs.scandir": ["@nodelib/fs.scandir@2.1.5", "", { "dependencies": { "@nodelib/fs.stat": "2.0.5", "run-parallel": "^1.1.9" } }, "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g=="],
+
+ "@nodelib/fs.stat": ["@nodelib/fs.stat@2.0.5", "", {}, "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A=="],
+
+ "@nodelib/fs.walk": ["@nodelib/fs.walk@1.2.8", "", { "dependencies": { "@nodelib/fs.scandir": "2.1.5", "fastq": "^1.6.0" } }, "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg=="],
+
+ "@nolyfill/is-core-module": ["@nolyfill/is-core-module@1.0.39", "", {}, "sha512-nn5ozdjYQpUCZlWGuxcJY/KpxkWQs4DcbMCmKojjyrYDEAGy4Ce19NN4v5MduafTwJlbKc99UA8YhSVqq9yPZA=="],
+
+ "@omniroute/open-sse": ["@omniroute/open-sse@workspace:open-sse"],
+
+ "@oxc-project/runtime": ["@oxc-project/runtime@0.115.0", "", {}, "sha512-Rg8Wlt5dCbXhQnsXPrkOjL1DTSvXLgb2R/KYfnf1/K+R0k6UMLEmbQXPM+kwrWqSmWA2t0B1EtHy2/3zikQpvQ=="],
+
+ "@oxc-project/types": ["@oxc-project/types@0.115.0", "", {}, "sha512-4n91DKnebUS4yjUHl2g3/b2T+IUdCfmoZGhmwsovZCDaJSs+QkVAM+0AqqTxHSsHfeiMuueT75cZaZcT/m0pSw=="],
+
+ "@parcel/watcher": ["@parcel/watcher@2.5.6", "", { "dependencies": { "detect-libc": "^2.0.3", "is-glob": "^4.0.3", "node-addon-api": "^7.0.0", "picomatch": "^4.0.3" }, "optionalDependencies": { "@parcel/watcher-android-arm64": "2.5.6", "@parcel/watcher-darwin-arm64": "2.5.6", "@parcel/watcher-darwin-x64": "2.5.6", "@parcel/watcher-freebsd-x64": "2.5.6", "@parcel/watcher-linux-arm-glibc": "2.5.6", "@parcel/watcher-linux-arm-musl": "2.5.6", "@parcel/watcher-linux-arm64-glibc": "2.5.6", "@parcel/watcher-linux-arm64-musl": "2.5.6", "@parcel/watcher-linux-x64-glibc": "2.5.6", "@parcel/watcher-linux-x64-musl": "2.5.6", "@parcel/watcher-win32-arm64": "2.5.6", "@parcel/watcher-win32-ia32": "2.5.6", "@parcel/watcher-win32-x64": "2.5.6" } }, "sha512-tmmZ3lQxAe/k/+rNnXQRawJ4NjxO2hqiOLTHvWchtGZULp4RyFeh6aU4XdOYBFe2KE1oShQTv4AblOs2iOrNnQ=="],
+
+ "@parcel/watcher-android-arm64": ["@parcel/watcher-android-arm64@2.5.6", "", { "os": "android", "cpu": "arm64" }, "sha512-YQxSS34tPF/6ZG7r/Ih9xy+kP/WwediEUsqmtf0cuCV5TPPKw/PQHRhueUo6JdeFJaqV3pyjm0GdYjZotbRt/A=="],
+
+ "@parcel/watcher-darwin-arm64": ["@parcel/watcher-darwin-arm64@2.5.6", "", { "os": "darwin", "cpu": "arm64" }, "sha512-Z2ZdrnwyXvvvdtRHLmM4knydIdU9adO3D4n/0cVipF3rRiwP+3/sfzpAwA/qKFL6i1ModaabkU7IbpeMBgiVEA=="],
+
+ "@parcel/watcher-darwin-x64": ["@parcel/watcher-darwin-x64@2.5.6", "", { "os": "darwin", "cpu": "x64" }, "sha512-HgvOf3W9dhithcwOWX9uDZyn1lW9R+7tPZ4sug+NGrGIo4Rk1hAXLEbcH1TQSqxts0NYXXlOWqVpvS1SFS4fRg=="],
+
+ "@parcel/watcher-freebsd-x64": ["@parcel/watcher-freebsd-x64@2.5.6", "", { "os": "freebsd", "cpu": "x64" }, "sha512-vJVi8yd/qzJxEKHkeemh7w3YAn6RJCtYlE4HPMoVnCpIXEzSrxErBW5SJBgKLbXU3WdIpkjBTeUNtyBVn8TRng=="],
+
+ "@parcel/watcher-linux-arm-glibc": ["@parcel/watcher-linux-arm-glibc@2.5.6", "", { "os": "linux", "cpu": "arm" }, "sha512-9JiYfB6h6BgV50CCfasfLf/uvOcJskMSwcdH1PHH9rvS1IrNy8zad6IUVPVUfmXr+u+Km9IxcfMLzgdOudz9EQ=="],
+
+ "@parcel/watcher-linux-arm-musl": ["@parcel/watcher-linux-arm-musl@2.5.6", "", { "os": "linux", "cpu": "arm" }, "sha512-Ve3gUCG57nuUUSyjBq/MAM0CzArtuIOxsBdQ+ftz6ho8n7s1i9E1Nmk/xmP323r2YL0SONs1EuwqBp2u1k5fxg=="],
+
+ "@parcel/watcher-linux-arm64-glibc": ["@parcel/watcher-linux-arm64-glibc@2.5.6", "", { "os": "linux", "cpu": "arm64" }, "sha512-f2g/DT3NhGPdBmMWYoxixqYr3v/UXcmLOYy16Bx0TM20Tchduwr4EaCbmxh1321TABqPGDpS8D/ggOTaljijOA=="],
+
+ "@parcel/watcher-linux-arm64-musl": ["@parcel/watcher-linux-arm64-musl@2.5.6", "", { "os": "linux", "cpu": "arm64" }, "sha512-qb6naMDGlbCwdhLj6hgoVKJl2odL34z2sqkC7Z6kzir8b5W65WYDpLB6R06KabvZdgoHI/zxke4b3zR0wAbDTA=="],
+
+ "@parcel/watcher-linux-x64-glibc": ["@parcel/watcher-linux-x64-glibc@2.5.6", "", { "os": "linux", "cpu": "x64" }, "sha512-kbT5wvNQlx7NaGjzPFu8nVIW1rWqV780O7ZtkjuWaPUgpv2NMFpjYERVi0UYj1msZNyCzGlaCWEtzc+exjMGbQ=="],
+
+ "@parcel/watcher-linux-x64-musl": ["@parcel/watcher-linux-x64-musl@2.5.6", "", { "os": "linux", "cpu": "x64" }, "sha512-1JRFeC+h7RdXwldHzTsmdtYR/Ku8SylLgTU/reMuqdVD7CtLwf0VR1FqeprZ0eHQkO0vqsbvFLXUmYm/uNKJBg=="],
+
+ "@parcel/watcher-win32-arm64": ["@parcel/watcher-win32-arm64@2.5.6", "", { "os": "win32", "cpu": "arm64" }, "sha512-3ukyebjc6eGlw9yRt678DxVF7rjXatWiHvTXqphZLvo7aC5NdEgFufVwjFfY51ijYEWpXbqF5jtrK275z52D4Q=="],
+
+ "@parcel/watcher-win32-ia32": ["@parcel/watcher-win32-ia32@2.5.6", "", { "os": "win32", "cpu": "ia32" }, "sha512-k35yLp1ZMwwee3Ez/pxBi5cf4AoBKYXj00CZ80jUz5h8prpiaQsiRPKQMxoLstNuqe2vR4RNPEAEcjEFzhEz/g=="],
+
+ "@parcel/watcher-win32-x64": ["@parcel/watcher-win32-x64@2.5.6", "", { "os": "win32", "cpu": "x64" }, "sha512-hbQlYcCq5dlAX9Qx+kFb0FHue6vbjlf0FrNzSKdYK2APUf7tGfGxQCk2ihEREmbR6ZMc0MVAD5RIX/41gpUzTw=="],
+
+ "@peculiar/asn1-cms": ["@peculiar/asn1-cms@2.6.0", "", { "dependencies": { "@peculiar/asn1-schema": "^2.6.0", "@peculiar/asn1-x509": "^2.6.0", "@peculiar/asn1-x509-attr": "^2.6.0", "asn1js": "^3.0.6", "tslib": "^2.8.1" } }, "sha512-2uZqP+ggSncESeUF/9Su8rWqGclEfEiz1SyU02WX5fUONFfkjzS2Z/F1Li0ofSmf4JqYXIOdCAZqIXAIBAT1OA=="],
+
+ "@peculiar/asn1-csr": ["@peculiar/asn1-csr@2.6.0", "", { "dependencies": { "@peculiar/asn1-schema": "^2.6.0", "@peculiar/asn1-x509": "^2.6.0", "asn1js": "^3.0.6", "tslib": "^2.8.1" } }, "sha512-BeWIu5VpTIhfRysfEp73SGbwjjoLL/JWXhJ/9mo4vXnz3tRGm+NGm3KNcRzQ9VMVqwYS2RHlolz21svzRXIHPQ=="],
+
+ "@peculiar/asn1-ecc": ["@peculiar/asn1-ecc@2.6.0", "", { "dependencies": { "@peculiar/asn1-schema": "^2.6.0", "@peculiar/asn1-x509": "^2.6.0", "asn1js": "^3.0.6", "tslib": "^2.8.1" } }, "sha512-FF3LMGq6SfAOwUG2sKpPXblibn6XnEIKa+SryvUl5Pik+WR9rmRA3OCiwz8R3lVXnYnyRkSZsSLdml8H3UiOcw=="],
+
+ "@peculiar/asn1-pfx": ["@peculiar/asn1-pfx@2.6.0", "", { "dependencies": { "@peculiar/asn1-cms": "^2.6.0", "@peculiar/asn1-pkcs8": "^2.6.0", "@peculiar/asn1-rsa": "^2.6.0", "@peculiar/asn1-schema": "^2.6.0", "asn1js": "^3.0.6", "tslib": "^2.8.1" } }, "sha512-rtUvtf+tyKGgokHHmZzeUojRZJYPxoD/jaN1+VAB4kKR7tXrnDCA/RAWXAIhMJJC+7W27IIRGe9djvxKgsldCQ=="],
+
+ "@peculiar/asn1-pkcs8": ["@peculiar/asn1-pkcs8@2.6.0", "", { "dependencies": { "@peculiar/asn1-schema": "^2.6.0", "@peculiar/asn1-x509": "^2.6.0", "asn1js": "^3.0.6", "tslib": "^2.8.1" } }, "sha512-KyQ4D8G/NrS7Fw3XCJrngxmjwO/3htnA0lL9gDICvEQ+GJ+EPFqldcJQTwPIdvx98Tua+WjkdKHSC0/Km7T+lA=="],
+
+ "@peculiar/asn1-pkcs9": ["@peculiar/asn1-pkcs9@2.6.0", "", { "dependencies": { "@peculiar/asn1-cms": "^2.6.0", "@peculiar/asn1-pfx": "^2.6.0", "@peculiar/asn1-pkcs8": "^2.6.0", "@peculiar/asn1-schema": "^2.6.0", "@peculiar/asn1-x509": "^2.6.0", "@peculiar/asn1-x509-attr": "^2.6.0", "asn1js": "^3.0.6", "tslib": "^2.8.1" } }, "sha512-b78OQ6OciW0aqZxdzliXGYHASeCvvw5caqidbpQRYW2mBtXIX2WhofNXTEe7NyxTb0P6J62kAAWLwn0HuMF1Fw=="],
+
+ "@peculiar/asn1-rsa": ["@peculiar/asn1-rsa@2.6.0", "", { "dependencies": { "@peculiar/asn1-schema": "^2.6.0", "@peculiar/asn1-x509": "^2.6.0", "asn1js": "^3.0.6", "tslib": "^2.8.1" } }, "sha512-Nu4C19tsrTsCp9fDrH+sdcOKoVfdfoQQ7S3VqjJU6vedR7tY3RLkQ5oguOIB3zFW33USDUuYZnPEQYySlgha4w=="],
+
+ "@peculiar/asn1-schema": ["@peculiar/asn1-schema@2.6.0", "", { "dependencies": { "asn1js": "^3.0.6", "pvtsutils": "^1.3.6", "tslib": "^2.8.1" } }, "sha512-xNLYLBFTBKkCzEZIw842BxytQQATQv+lDTCEMZ8C196iJcJJMBUZxrhSTxLaohMyKK8QlzRNTRkUmanucnDSqg=="],
+
+ "@peculiar/asn1-x509": ["@peculiar/asn1-x509@2.6.0", "", { "dependencies": { "@peculiar/asn1-schema": "^2.6.0", "asn1js": "^3.0.6", "pvtsutils": "^1.3.6", "tslib": "^2.8.1" } }, "sha512-uzYbPEpoQiBoTq0/+jZtpM6Gq6zADBx+JNFP3yqRgziWBxQ/Dt/HcuvRfm9zJTPdRcBqPNdaRHTVwpyiq6iNMA=="],
+
+ "@peculiar/asn1-x509-attr": ["@peculiar/asn1-x509-attr@2.6.0", "", { "dependencies": { "@peculiar/asn1-schema": "^2.6.0", "@peculiar/asn1-x509": "^2.6.0", "asn1js": "^3.0.6", "tslib": "^2.8.1" } }, "sha512-MuIAXFX3/dc8gmoZBkwJWxUWOSvG4MMDntXhrOZpJVMkYX+MYc/rUAU2uJOved9iJEoiUx7//3D8oG83a78UJA=="],
+
+ "@peculiar/x509": ["@peculiar/x509@1.14.3", "", { "dependencies": { "@peculiar/asn1-cms": "^2.6.0", "@peculiar/asn1-csr": "^2.6.0", "@peculiar/asn1-ecc": "^2.6.0", "@peculiar/asn1-pkcs9": "^2.6.0", "@peculiar/asn1-rsa": "^2.6.0", "@peculiar/asn1-schema": "^2.6.0", "@peculiar/asn1-x509": "^2.6.0", "pvtsutils": "^1.3.6", "reflect-metadata": "^0.2.2", "tslib": "^2.8.1", "tsyringe": "^4.10.0" } }, "sha512-C2Xj8FZ0uHWeCXXqX5B4/gVFQmtSkiuOolzAgutjTfseNOHT3pUjljDZsTSxXFGgio54bCzVFqmEOUrIVk8RDA=="],
+
+ "@pierre/diffs": ["@pierre/diffs@1.1.3", "", { "dependencies": { "@pierre/theme": "0.0.22", "@shikijs/transformers": "^3.0.0", "diff": "8.0.3", "hast-util-to-html": "9.0.5", "lru_map": "0.4.1", "shiki": "^3.0.0" }, "peerDependencies": { "react": "^18.3.1 || ^19.0.0", "react-dom": "^18.3.1 || ^19.0.0" } }, "sha512-sV6G1FL0L4UtequXi+50Uge4QVsouo5vgJx7pCawQ4+ctFglh03zIsB81W8PNheh3coIlVzLzFgB9kI7X4eyjw=="],
+
+ "@pierre/theme": ["@pierre/theme@0.0.22", "", {}, "sha512-ePUIdQRNGjrveELTU7fY89Xa7YGHHEy5Po5jQy/18lm32eRn96+tnYJEtFooGdffrx55KBUtOXfvVy/7LDFFhA=="],
+
+ "@pinojs/redact": ["@pinojs/redact@0.4.0", "", {}, "sha512-k2ENnmBugE/rzQfEcdWHcCY+/FM3VLzH9cYEsbdsoqrvzAKRhUZeRNhAZvB8OitQJ1TBed3yqWtdjzS6wJKBwg=="],
+
+ "@playwright/test": ["@playwright/test@1.58.2", "", { "dependencies": { "playwright": "1.58.2" }, "bin": { "playwright": "cli.js" } }, "sha512-akea+6bHYBBfA9uQqSYmlJXn61cTa+jbO87xVLCWbTqbWadRVmhxlXATaOjOgcBaWU4ePo0wB41KMFv3o35IXA=="],
+
+ "@primer/octicons": ["@primer/octicons@19.23.1", "", { "dependencies": { "object-assign": "^4.1.1" } }, "sha512-CzjGmxkmNhyst6EekrS3SJPdtzgIkUMP/LSJch65y99/kmiFXbO1a+q7zoYe3hnI9NaOM0IN+ydDIbOmd8YqcA=="],
+
+ "@radix-ui/primitive": ["@radix-ui/primitive@1.1.3", "", {}, "sha512-JTF99U/6XIjCBo0wqkU5sK10glYe27MRRsfwoiq5zzOEZLHU3A3KCMa5X/azekYRCJ0HlwI0crAXS/5dEHTzDg=="],
+
+ "@radix-ui/react-arrow": ["@radix-ui/react-arrow@1.1.7", "", { "dependencies": { "@radix-ui/react-primitive": "2.1.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" } }, "sha512-F+M1tLhO+mlQaOWspE8Wstg+z6PwxwRd8oQ8IXceWz92kfAmalTRf0EjrouQeo7QssEPfCn05B4Ihs1K9WQ/7w=="],
+
+ "@radix-ui/react-compose-refs": ["@radix-ui/react-compose-refs@1.1.2", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" } }, "sha512-z4eqJvfiNnFMHIIvXP3CY57y2WJs5g2v3X0zm9mEJkrkNv4rDxu+sg9Jh8EkXyeqBkB7SOcboo9dMVqhyrACIg=="],
+
+ "@radix-ui/react-context": ["@radix-ui/react-context@1.1.2", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" } }, "sha512-jCi/QKUM2r1Ju5a3J64TH2A5SpKAgh0LpknyqdQ4m6DCV0xJ2HG1xARRwNGPQfi1SLdLWZ1OJz6F4OMBBNiGJA=="],
+
+ "@radix-ui/react-dismissable-layer": ["@radix-ui/react-dismissable-layer@1.1.11", "", { "dependencies": { "@radix-ui/primitive": "1.1.3", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-use-callback-ref": "1.1.1", "@radix-ui/react-use-escape-keydown": "1.1.1" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" } }, "sha512-Nqcp+t5cTB8BinFkZgXiMJniQH0PsUt2k51FUhbdfeKvc4ACcG2uQniY/8+h1Yv6Kza4Q7lD7PQV0z0oicE0Mg=="],
+
+ "@radix-ui/react-id": ["@radix-ui/react-id@1.1.1", "", { "dependencies": { "@radix-ui/react-use-layout-effect": "1.1.1" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" } }, "sha512-kGkGegYIdQsOb4XjsfM97rXsiHaBwco+hFI66oO4s9LU+PLAC5oJ7khdOVFxkhsmlbpUqDAvXw11CluXP+jkHg=="],
+
+ "@radix-ui/react-popper": ["@radix-ui/react-popper@1.2.8", "", { "dependencies": { "@floating-ui/react-dom": "^2.0.0", "@radix-ui/react-arrow": "1.1.7", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-use-callback-ref": "1.1.1", "@radix-ui/react-use-layout-effect": "1.1.1", "@radix-ui/react-use-rect": "1.1.1", "@radix-ui/react-use-size": "1.1.1", "@radix-ui/rect": "1.1.1" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" } }, "sha512-0NJQ4LFFUuWkE7Oxf0htBKS6zLkkjBH+hM1uk7Ng705ReR8m/uelduy1DBo0PyBXPKVnBA6YBlU94MBGXrSBCw=="],
+
+ "@radix-ui/react-portal": ["@radix-ui/react-portal@1.1.10", "", { "dependencies": { "@radix-ui/react-primitive": "2.1.4", "@radix-ui/react-use-layout-effect": "1.1.1" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" } }, "sha512-4kY9IVa6+9nJPsYmngK5Uk2kUmZnv7ChhHAFeQ5oaj8jrR1bIi3xww8nH71pz1/Ve4d/cXO3YxT8eikt1B0a8w=="],
+
+ "@radix-ui/react-presence": ["@radix-ui/react-presence@1.1.5", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-use-layout-effect": "1.1.1" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" } }, "sha512-/jfEwNDdQVBCNvjkGit4h6pMOzq8bHkopq458dPt2lMjx+eBQUohZNG9A7DtO/O5ukSbxuaNGXMjHicgwy6rQQ=="],
+
+ "@radix-ui/react-primitive": ["@radix-ui/react-primitive@2.1.4", "", { "dependencies": { "@radix-ui/react-slot": "1.2.4" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" } }, "sha512-9hQc4+GNVtJAIEPEqlYqW5RiYdrr8ea5XQ0ZOnD6fgru+83kqT15mq2OCcbe8KnjRZl5vF3ks69AKz3kh1jrhg=="],
+
+ "@radix-ui/react-slot": ["@radix-ui/react-slot@1.2.4", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.2" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" } }, "sha512-Jl+bCv8HxKnlTLVrcDE8zTMJ09R9/ukw4qBs/oZClOfoQk/cOTbDn+NceXfV7j09YPVQUryJPHurafcSg6EVKA=="],
+
+ "@radix-ui/react-tooltip": ["@radix-ui/react-tooltip@1.2.8", "", { "dependencies": { "@radix-ui/primitive": "1.1.3", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-dismissable-layer": "1.1.11", "@radix-ui/react-id": "1.1.1", "@radix-ui/react-popper": "1.2.8", "@radix-ui/react-portal": "1.1.9", "@radix-ui/react-presence": "1.1.5", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-slot": "1.2.3", "@radix-ui/react-use-controllable-state": "1.2.2", "@radix-ui/react-visually-hidden": "1.2.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" } }, "sha512-tY7sVt1yL9ozIxvmbtN5qtmH2krXcBCfjEiCgKGLqunJHvgvZG2Pcl2oQ3kbcZARb1BGEHdkLzcYGO8ynVlieg=="],
+
+ "@radix-ui/react-use-callback-ref": ["@radix-ui/react-use-callback-ref@1.1.1", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" } }, "sha512-FkBMwD+qbGQeMu1cOHnuGB6x4yzPjho8ap5WtbEJ26umhgqVXbhekKUQO+hZEL1vU92a3wHwdp0HAcqAUF5iDg=="],
+
+ "@radix-ui/react-use-controllable-state": ["@radix-ui/react-use-controllable-state@1.2.2", "", { "dependencies": { "@radix-ui/react-use-effect-event": "0.0.2", "@radix-ui/react-use-layout-effect": "1.1.1" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" } }, "sha512-BjasUjixPFdS+NKkypcyyN5Pmg83Olst0+c6vGov0diwTEo6mgdqVR6hxcEgFuh4QrAs7Rc+9KuGJ9TVCj0Zzg=="],
+
+ "@radix-ui/react-use-effect-event": ["@radix-ui/react-use-effect-event@0.0.2", "", { "dependencies": { "@radix-ui/react-use-layout-effect": "1.1.1" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" } }, "sha512-Qp8WbZOBe+blgpuUT+lw2xheLP8q0oatc9UpmiemEICxGvFLYmHm9QowVZGHtJlGbS6A6yJ3iViad/2cVjnOiA=="],
+
+ "@radix-ui/react-use-escape-keydown": ["@radix-ui/react-use-escape-keydown@1.1.1", "", { "dependencies": { "@radix-ui/react-use-callback-ref": "1.1.1" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" } }, "sha512-Il0+boE7w/XebUHyBjroE+DbByORGR9KKmITzbR7MyQ4akpORYP/ZmbhAr0DG7RmmBqoOnZdy2QlvajJ2QA59g=="],
+
+ "@radix-ui/react-use-layout-effect": ["@radix-ui/react-use-layout-effect@1.1.1", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" } }, "sha512-RbJRS4UWQFkzHTTwVymMTUv8EqYhOp8dOOviLj2ugtTiXRaRQS7GLGxZTLL1jWhMeoSCf5zmcZkqTl9IiYfXcQ=="],
+
+ "@radix-ui/react-use-rect": ["@radix-ui/react-use-rect@1.1.1", "", { "dependencies": { "@radix-ui/rect": "1.1.1" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" } }, "sha512-QTYuDesS0VtuHNNvMh+CjlKJ4LJickCMUAqjlE3+j8w+RlRpwyX3apEQKGFzbZGdo7XNG1tXa+bQqIE7HIXT2w=="],
+
+ "@radix-ui/react-use-size": ["@radix-ui/react-use-size@1.1.1", "", { "dependencies": { "@radix-ui/react-use-layout-effect": "1.1.1" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" } }, "sha512-ewrXRDTAqAXlkl6t/fkXWNAhFX9I+CkKlw6zjEwk86RSPKwZr3xpBRso655aqYafwtnbpHLj6toFzmd6xdVptQ=="],
+
+ "@radix-ui/react-visually-hidden": ["@radix-ui/react-visually-hidden@1.2.3", "", { "dependencies": { "@radix-ui/react-primitive": "2.1.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" } }, "sha512-pzJq12tEaaIhqjbzpCuv/OypJY/BPavOofm+dbab+MHLajy277+1lLm6JFcGgF5eskJ6mquGirhXY2GD/8u8Ug=="],
+
+ "@radix-ui/rect": ["@radix-ui/rect@1.1.1", "", {}, "sha512-HPwpGIzkl28mWyZqG52jiqDJ12waP11Pa1lGoiyUkIEuMLBP0oeK/C89esbXrxsky5we7dfd8U58nm0SgAWpVw=="],
+
+ "@rc-component/async-validator": ["@rc-component/async-validator@5.1.0", "", { "dependencies": { "@babel/runtime": "^7.24.4" } }, "sha512-n4HcR5siNUXRX23nDizbZBQPO0ZM/5oTtmKZ6/eqL0L2bo747cklFdZGRN2f+c9qWGICwDzrhW0H7tE9PptdcA=="],
+
+ "@rc-component/cascader": ["@rc-component/cascader@1.14.0", "", { "dependencies": { "@rc-component/select": "~1.6.0", "@rc-component/tree": "~1.2.0", "@rc-component/util": "^1.4.0", "clsx": "^2.1.1" }, "peerDependencies": { "react": ">=18.0.0", "react-dom": ">=18.0.0" } }, "sha512-Ip9356xwZUR2nbW5PRVGif4B/bDve4pLa/N+PGbvBaTnjbvmN4PFMBGQSmlDlzKP1ovxaYMvwF/dI9lXNLT4iQ=="],
+
+ "@rc-component/checkbox": ["@rc-component/checkbox@2.0.0", "", { "dependencies": { "@rc-component/util": "^1.3.0", "clsx": "^2.1.1" }, "peerDependencies": { "react": ">=16.9.0", "react-dom": ">=16.9.0" } }, "sha512-3CXGPpAR9gsPKeO2N78HAPOzU30UdemD6HGJoWVJOpa6WleaGB5kzZj3v6bdTZab31YuWgY/RxV3VKPctn0DwQ=="],
+
+ "@rc-component/collapse": ["@rc-component/collapse@1.2.0", "", { "dependencies": { "@babel/runtime": "^7.10.1", "@rc-component/motion": "^1.1.4", "@rc-component/util": "^1.3.0", "clsx": "^2.1.1" }, "peerDependencies": { "react": ">=18.0.0", "react-dom": ">=18.0.0" } }, "sha512-ZRYSKSS39qsFx93p26bde7JUZJshsUBEQRlRXPuJYlAiNX0vyYlF5TsAm8JZN3LcF8XvKikdzPbgAtXSbkLUkw=="],
+
+ "@rc-component/color-picker": ["@rc-component/color-picker@3.1.1", "", { "dependencies": { "@ant-design/fast-color": "^3.0.1", "@rc-component/util": "^1.3.0", "clsx": "^2.1.1" }, "peerDependencies": { "react": ">=16.9.0", "react-dom": ">=16.9.0" } }, "sha512-OHaCHLHszCegdXmIq2ZRIZBN/EtpT6Wm8SG/gpzLATHbVKc/avvuKi+zlOuk05FTWvgaMmpxAko44uRJ3M+2pg=="],
+
+ "@rc-component/context": ["@rc-component/context@2.0.1", "", { "dependencies": { "@rc-component/util": "^1.3.0" }, "peerDependencies": { "react": ">=16.9.0", "react-dom": ">=16.9.0" } }, "sha512-HyZbYm47s/YqtP6pKXNMjPEMaukyg7P0qVfgMLzr7YiFNMHbK2fKTAGzms9ykfGHSfyf75nBbgWw+hHkp+VImw=="],
+
+ "@rc-component/dialog": ["@rc-component/dialog@1.8.4", "", { "dependencies": { "@rc-component/motion": "^1.1.3", "@rc-component/portal": "^2.1.0", "@rc-component/util": "^1.9.0", "clsx": "^2.1.1" }, "peerDependencies": { "react": ">=18.0.0", "react-dom": ">=18.0.0" } }, "sha512-Ay6PM7phkTkquplG8fWfUGFZ2GTLx9diTl4f0d8Eqxd7W1u1KjE9AQooFQHOHnhZf0Ya3z51+5EKCWHmt/dNEw=="],
+
+ "@rc-component/drawer": ["@rc-component/drawer@1.4.2", "", { "dependencies": { "@rc-component/motion": "^1.1.4", "@rc-component/portal": "^2.1.3", "@rc-component/util": "^1.9.0", "clsx": "^2.1.1" }, "peerDependencies": { "react": ">=18.0.0", "react-dom": ">=18.0.0" } }, "sha512-1ib+fZEp6FBu+YvcIktm+nCQ+Q+qIpwpoaJH6opGr4ofh2QMq+qdr5DLC4oCf5qf3pcWX9lUWPYX652k4ini8Q=="],
+
+ "@rc-component/dropdown": ["@rc-component/dropdown@1.0.2", "", { "dependencies": { "@rc-component/trigger": "^3.0.0", "@rc-component/util": "^1.2.1", "clsx": "^2.1.1" }, "peerDependencies": { "react": ">=16.11.0", "react-dom": ">=16.11.0" } }, "sha512-6PY2ecUSYhDPhkNHHb4wfeAya04WhpmUSKzdR60G+kMNVUCX2vjT/AgTS0Lz0I/K6xrPMJ3enQbwVpeN3sHCgg=="],
+
+ "@rc-component/form": ["@rc-component/form@1.7.2", "", { "dependencies": { "@rc-component/async-validator": "^5.1.0", "@rc-component/util": "^1.6.2", "clsx": "^2.1.1" }, "peerDependencies": { "react": ">=16.9.0", "react-dom": ">=16.9.0" } }, "sha512-5C90rXH7aZvvvxB4M5ew+QxROvimdL/lqhSshR8NsyiR7HKOoGQYSitxdfENnH6/0KNFxEy2ranVe2LrTnHZIw=="],
+
+ "@rc-component/image": ["@rc-component/image@1.6.0", "", { "dependencies": { "@rc-component/motion": "^1.0.0", "@rc-component/portal": "^2.1.2", "@rc-component/util": "^1.3.0", "clsx": "^2.1.1" }, "peerDependencies": { "react": ">=16.9.0", "react-dom": ">=16.9.0" } }, "sha512-tSfn2ZE/oP082g4QIOxeehkmgnXB7R+5AFj/lIFr4k7pEuxHBdyGIq9axoCY9qea8NN0DY6p4IB/F07tLqaT5A=="],
+
+ "@rc-component/input": ["@rc-component/input@1.1.2", "", { "dependencies": { "@rc-component/util": "^1.4.0", "clsx": "^2.1.1" }, "peerDependencies": { "react": ">=16.0.0", "react-dom": ">=16.0.0" } }, "sha512-Q61IMR47piUBudgixJ30CciKIy9b1H95qe7GgEKOmSJVJXvFRWJllJfQry9tif+MX2cWFXWJf/RXz4kaCeq/Fg=="],
+
+ "@rc-component/input-number": ["@rc-component/input-number@1.6.2", "", { "dependencies": { "@rc-component/mini-decimal": "^1.0.1", "@rc-component/util": "^1.4.0", "clsx": "^2.1.1" }, "peerDependencies": { "react": ">=16.9.0", "react-dom": ">=16.9.0" } }, "sha512-Gjcq7meZlCOiWN1t1xCC+7/s85humHVokTBI7PJgTfoyw5OWF74y3e6P8PHX104g9+b54jsodFIzyaj6p8LI9w=="],
+
+ "@rc-component/mentions": ["@rc-component/mentions@1.6.0", "", { "dependencies": { "@rc-component/input": "~1.1.0", "@rc-component/menu": "~1.2.0", "@rc-component/textarea": "~1.1.0", "@rc-component/trigger": "^3.0.0", "@rc-component/util": "^1.3.0", "clsx": "^2.1.1" }, "peerDependencies": { "react": ">=16.9.0", "react-dom": ">=16.9.0" } }, "sha512-KIkQNP6habNuTsLhUv0UGEOwG67tlmE7KNIJoQZZNggEZl5lQJTytFDb69sl5CK3TDdISCTjKP3nGEBKgT61CQ=="],
+
+ "@rc-component/menu": ["@rc-component/menu@1.2.0", "", { "dependencies": { "@rc-component/motion": "^1.1.4", "@rc-component/overflow": "^1.0.0", "@rc-component/trigger": "^3.0.0", "@rc-component/util": "^1.3.0", "clsx": "^2.1.1" }, "peerDependencies": { "react": ">=16.9.0", "react-dom": ">=16.9.0" } }, "sha512-VWwDuhvYHSnTGj4n6bV3ISrLACcPAzdPOq3d0BzkeiM5cve8BEYfvkEhNoM0PLzv51jpcejeyrLXeMVIJ+QJlg=="],
+
+ "@rc-component/mini-decimal": ["@rc-component/mini-decimal@1.1.3", "", { "dependencies": { "@babel/runtime": "^7.18.0" } }, "sha512-bk/FJ09fLf+NLODMAFll6CfYrHPBioTedhW6lxDBuuWucJEqFUd4l/D/5JgIi3dina6sYahB8iuPAZTNz2pMxw=="],
+
+ "@rc-component/motion": ["@rc-component/motion@1.3.1", "", { "dependencies": { "@rc-component/util": "^1.2.0", "clsx": "^2.1.1" }, "peerDependencies": { "react": ">=16.9.0", "react-dom": ">=16.9.0" } }, "sha512-Wo1mkd0tCcHtvYvpPOmlYJz546z16qlsiwaygmW7NPJpOZOF9GBjhGzdzZSsC2lEJ1IUkWLF4gMHlRA1aSA+Yw=="],
+
+ "@rc-component/mutate-observer": ["@rc-component/mutate-observer@2.0.1", "", { "dependencies": { "@rc-component/util": "^1.2.0" }, "peerDependencies": { "react": ">=16.9.0", "react-dom": ">=16.9.0" } }, "sha512-AyarjoLU5YlxuValRi+w8JRH2Z84TBbFO2RoGWz9d8bSu0FqT8DtugH3xC3BV7mUwlmROFauyWuXFuq4IFbH+w=="],
+
+ "@rc-component/notification": ["@rc-component/notification@1.2.0", "", { "dependencies": { "@rc-component/motion": "^1.1.4", "@rc-component/util": "^1.2.1", "clsx": "^2.1.1" }, "peerDependencies": { "react": ">=16.9.0", "react-dom": ">=16.9.0" } }, "sha512-OX3J+zVU7rvoJCikjrfW7qOUp7zlDeFBK2eA3SFbGSkDqo63Sl4Ss8A04kFP+fxHSxMDIS9jYVEZtU1FNCFuBA=="],
+
+ "@rc-component/overflow": ["@rc-component/overflow@1.0.0", "", { "dependencies": { "@babel/runtime": "^7.11.1", "@rc-component/resize-observer": "^1.0.1", "@rc-component/util": "^1.4.0", "clsx": "^2.1.1" }, "peerDependencies": { "react": ">=16.9.0", "react-dom": ">=16.9.0" } }, "sha512-GSlBeoE0XTBi5cf3zl8Qh7Uqhn7v8RrlJ8ajeVpEkNe94HWy5l5BQ0Mwn2TVUq9gdgbfEMUmTX7tJFAg7mz0Rw=="],
+
+ "@rc-component/pagination": ["@rc-component/pagination@1.2.0", "", { "dependencies": { "@rc-component/util": "^1.3.0", "clsx": "^2.1.1" }, "peerDependencies": { "react": ">=16.9.0", "react-dom": ">=16.9.0" } }, "sha512-YcpUFE8dMLfSo6OARJlK6DbHHvrxz7pMGPGmC/caZSJJz6HRKHC1RPP001PRHCvG9Z/veD039uOQmazVuLJzlw=="],
+
+ "@rc-component/picker": ["@rc-component/picker@1.9.1", "", { "dependencies": { "@rc-component/overflow": "^1.0.0", "@rc-component/resize-observer": "^1.0.0", "@rc-component/trigger": "^3.6.15", "@rc-component/util": "^1.3.0", "clsx": "^2.1.1" }, "peerDependencies": { "date-fns": ">= 2.x", "dayjs": ">= 1.x", "luxon": ">= 3.x", "moment": ">= 2.x", "react": ">=16.9.0", "react-dom": ">=16.9.0" }, "optionalPeers": ["date-fns", "luxon", "moment"] }, "sha512-9FBYYsvH3HMLICaPDA/1Th5FLaDkFa7qAtangIdlhKb3ZALaR745e9PsOhheJb6asS4QXc12ffiAcjdkZ4C5/g=="],
+
+ "@rc-component/portal": ["@rc-component/portal@1.1.2", "", { "dependencies": { "@babel/runtime": "^7.18.0", "classnames": "^2.3.2", "rc-util": "^5.24.4" }, "peerDependencies": { "react": ">=16.9.0", "react-dom": ">=16.9.0" } }, "sha512-6f813C0IsasTZms08kfA8kPAGxbbkYToa8ALaiDIGGECU4i9hj8Plgbx0sNJDrey3EtHO30hmdaxtT0138xZcg=="],
+
+ "@rc-component/progress": ["@rc-component/progress@1.0.2", "", { "dependencies": { "@rc-component/util": "^1.2.1", "clsx": "^2.1.1" }, "peerDependencies": { "react": ">=16.9.0", "react-dom": ">=16.9.0" } }, "sha512-WZUnH9eGxH1+xodZKqdrHke59uyGZSWgj5HBM5Kwk5BrTMuAORO7VJ2IP5Qbm9aH3n9x3IcesqHHR0NWPBC7fQ=="],
+
+ "@rc-component/qrcode": ["@rc-component/qrcode@1.1.1", "", { "dependencies": { "@babel/runtime": "^7.24.7" }, "peerDependencies": { "react": ">=16.9.0", "react-dom": ">=16.9.0" } }, "sha512-LfLGNymzKdUPjXUbRP+xOhIWY4jQ+YMj5MmWAcgcAq1Ij8XP7tRmAXqyuv96XvLUBE/5cA8hLFl9eO1JQMujrA=="],
+
+ "@rc-component/rate": ["@rc-component/rate@1.0.1", "", { "dependencies": { "@rc-component/util": "^1.3.0", "clsx": "^2.1.1" }, "peerDependencies": { "react": ">=16.9.0", "react-dom": ">=16.9.0" } }, "sha512-bkXxeBqDpl5IOC7yL7GcSYjQx9G8H+6kLYQnNZWeBYq2OYIv1MONd6mqKTjnnJYpV0cQIU2z3atdW0j1kttpTw=="],
+
+ "@rc-component/resize-observer": ["@rc-component/resize-observer@1.1.1", "", { "dependencies": { "@rc-component/util": "^1.2.0" }, "peerDependencies": { "react": ">=16.9.0", "react-dom": ">=16.9.0" } }, "sha512-NfXXMmiR+SmUuKE1NwJESzEUYUFWIDUn2uXpxCTOLwiRUUakd62DRNFjRJArgzyFW8S5rsL4aX5XlyIXyC/vRA=="],
+
+ "@rc-component/segmented": ["@rc-component/segmented@1.3.0", "", { "dependencies": { "@babel/runtime": "^7.11.1", "@rc-component/motion": "^1.1.4", "@rc-component/util": "^1.3.0", "clsx": "^2.1.1" }, "peerDependencies": { "react": ">=16.0.0", "react-dom": ">=16.0.0" } }, "sha512-5J/bJ01mbDnoA6P/FW8SxUvKn+OgUSTZJPzCNnTBntG50tzoP7DydGhqxp7ggZXZls7me3mc2EQDXakU3iTVFg=="],
+
+ "@rc-component/select": ["@rc-component/select@1.6.15", "", { "dependencies": { "@rc-component/overflow": "^1.0.0", "@rc-component/trigger": "^3.0.0", "@rc-component/util": "^1.3.0", "@rc-component/virtual-list": "^1.0.1", "clsx": "^2.1.1" }, "peerDependencies": { "react": "*", "react-dom": "*" } }, "sha512-SyVCWnqxCQZZcQvQJ/CxSjx2bGma6ds/HtnpkIfZVnt6RoEgbqUmHgD6vrzNarNXwbLXerwVzWwq8F3d1sst7g=="],
+
+ "@rc-component/slider": ["@rc-component/slider@1.0.1", "", { "dependencies": { "@rc-component/util": "^1.3.0", "clsx": "^2.1.1" }, "peerDependencies": { "react": ">=16.9.0", "react-dom": ">=16.9.0" } }, "sha512-uDhEPU1z3WDfCJhaL9jfd2ha/Eqpdfxsn0Zb0Xcq1NGQAman0TWaR37OWp2vVXEOdV2y0njSILTMpTfPV1454g=="],
+
+ "@rc-component/steps": ["@rc-component/steps@1.2.2", "", { "dependencies": { "@rc-component/util": "^1.2.1", "clsx": "^2.1.1" }, "peerDependencies": { "react": ">=16.9.0", "react-dom": ">=16.9.0" } }, "sha512-/yVIZ00gDYYPHSY0JP+M+s3ZvuXLu2f9rEjQqiUDs7EcYsUYrpJ/1bLj9aI9R7MBR3fu/NGh6RM9u2qGfqp+Nw=="],
+
+ "@rc-component/switch": ["@rc-component/switch@1.0.3", "", { "dependencies": { "@rc-component/util": "^1.3.0", "clsx": "^2.1.1" }, "peerDependencies": { "react": ">=16.9.0", "react-dom": ">=16.9.0" } }, "sha512-Jgi+EbOBquje/XNdofr7xbJQZPYJP+BlPfR0h+WN4zFkdtB2EWqEfvkXJWeipflwjWip0/17rNbxEAqs8hVHfw=="],
+
+ "@rc-component/table": ["@rc-component/table@1.9.1", "", { "dependencies": { "@rc-component/context": "^2.0.1", "@rc-component/resize-observer": "^1.0.0", "@rc-component/util": "^1.1.0", "@rc-component/virtual-list": "^1.0.1", "clsx": "^2.1.1" }, "peerDependencies": { "react": ">=18.0.0", "react-dom": ">=18.0.0" } }, "sha512-FVI5ZS/GdB3BcgexfCYKi3iHhZS3Fr59EtsxORszYGrfpH1eWr33eDNSYkVfLI6tfJ7vftJDd9D5apfFWqkdJg=="],
+
+ "@rc-component/tabs": ["@rc-component/tabs@1.7.0", "", { "dependencies": { "@rc-component/dropdown": "~1.0.0", "@rc-component/menu": "~1.2.0", "@rc-component/motion": "^1.1.3", "@rc-component/resize-observer": "^1.0.0", "@rc-component/util": "^1.3.0", "clsx": "^2.1.1" }, "peerDependencies": { "react": ">=16.9.0", "react-dom": ">=16.9.0" } }, "sha512-J48cs2iBi7Ho3nptBxxIqizEliUC+ExE23faspUQKGQ550vaBlv3aGF8Epv/UB1vFWeoJDTW/dNzgIU0Qj5i/w=="],
+
+ "@rc-component/textarea": ["@rc-component/textarea@1.1.2", "", { "dependencies": { "@rc-component/input": "~1.1.0", "@rc-component/resize-observer": "^1.0.0", "@rc-component/util": "^1.3.0", "clsx": "^2.1.1" }, "peerDependencies": { "react": ">=16.9.0", "react-dom": ">=16.9.0" } }, "sha512-9rMUEODWZDMovfScIEHXWlVZuPljZ2pd1LKNjslJVitn4SldEzq5vO1CL3yy3Dnib6zZal2r2DPtjy84VVpF6A=="],
+
+ "@rc-component/tooltip": ["@rc-component/tooltip@1.4.0", "", { "dependencies": { "@rc-component/trigger": "^3.7.1", "@rc-component/util": "^1.3.0", "clsx": "^2.1.1" }, "peerDependencies": { "react": ">=18.0.0", "react-dom": ">=18.0.0" } }, "sha512-8Rx5DCctIlLI4raR0I0xHjVTf1aF48+gKCNeAAo5bmF5VoR5YED+A/XEqzXv9KKqrJDRcd3Wndpxh2hyzrTtSg=="],
+
+ "@rc-component/tour": ["@rc-component/tour@2.3.0", "", { "dependencies": { "@rc-component/portal": "^2.2.0", "@rc-component/trigger": "^3.0.0", "@rc-component/util": "^1.7.0", "clsx": "^2.1.1" }, "peerDependencies": { "react": ">=16.9.0", "react-dom": ">=16.9.0" } }, "sha512-K04K9r32kUC+auBSQfr+Fss4SpSIS9JGe56oq/ALAX0p+i2ylYOI1MgR83yBY7v96eO6ZFXcM/igCQmubps0Ow=="],
+
+ "@rc-component/tree": ["@rc-component/tree@1.2.4", "", { "dependencies": { "@rc-component/motion": "^1.0.0", "@rc-component/util": "^1.8.1", "@rc-component/virtual-list": "^1.0.1", "clsx": "^2.1.1" }, "peerDependencies": { "react": "*", "react-dom": "*" } }, "sha512-5Gli43+m4R7NhpYYz3Z61I6LOw9yI6CNChxgVtvrO6xB1qML7iE6QMLVMB3+FTjo2yF6uFdAHtqWPECz/zbX5w=="],
+
+ "@rc-component/tree-select": ["@rc-component/tree-select@1.8.0", "", { "dependencies": { "@rc-component/select": "~1.6.0", "@rc-component/tree": "~1.2.0", "@rc-component/util": "^1.4.0", "clsx": "^2.1.1" }, "peerDependencies": { "react": "*", "react-dom": "*" } }, "sha512-iYsPq3nuLYvGqdvFAW+l+I9ASRIOVbMXyA8FGZg2lGym/GwkaWeJGzI4eJ7c9IOEhRj0oyfIN4S92Fl3J05mjQ=="],
+
+ "@rc-component/trigger": ["@rc-component/trigger@3.9.0", "", { "dependencies": { "@rc-component/motion": "^1.1.4", "@rc-component/portal": "^2.2.0", "@rc-component/resize-observer": "^1.1.1", "@rc-component/util": "^1.2.1", "clsx": "^2.1.1" }, "peerDependencies": { "react": ">=18.0.0", "react-dom": ">=18.0.0" } }, "sha512-X8btpwfrT27AgrZVOz4swclhEHTZcqaHeQMXXBgveagOiakTa36uObXbdwerXffgV8G9dH1fAAE0DHtVQs8EHg=="],
+
+ "@rc-component/upload": ["@rc-component/upload@1.1.0", "", { "dependencies": { "@rc-component/util": "^1.3.0", "clsx": "^2.1.1" }, "peerDependencies": { "react": ">=16.9.0", "react-dom": ">=16.9.0" } }, "sha512-LIBV90mAnUE6VK5N4QvForoxZc4XqEYZimcp7fk+lkE4XwHHyJWxpIXQQwMU8hJM+YwBbsoZkGksL1sISWHQxw=="],
+
+ "@rc-component/util": ["@rc-component/util@1.10.0", "", { "dependencies": { "is-mobile": "^5.0.0", "react-is": "^18.2.0" }, "peerDependencies": { "react": ">=18.0.0", "react-dom": ">=18.0.0" } }, "sha512-aY9GLBuiUdpyfIUpAWSYer4Tu3mVaZCo5A0q9NtXcazT3MRiI3/WNHCR+DUn5VAtR6iRRf0ynCqQUcHli5UdYw=="],
+
+ "@rc-component/virtual-list": ["@rc-component/virtual-list@1.0.2", "", { "dependencies": { "@babel/runtime": "^7.20.0", "@rc-component/resize-observer": "^1.0.1", "@rc-component/util": "^1.4.0", "clsx": "^2.1.1" }, "peerDependencies": { "react": ">=16.9.0", "react-dom": ">=16.9.0" } }, "sha512-uvTol/mH74FYsn5loDGJxo+7kjkO4i+y4j87Re1pxJBs0FaeuMuLRzQRGaXwnMcV1CxpZLi2Z56Rerj2M00fjQ=="],
+
+ "@reduxjs/toolkit": ["@reduxjs/toolkit@2.11.2", "", { "dependencies": { "@standard-schema/spec": "^1.0.0", "@standard-schema/utils": "^0.3.0", "immer": "^11.0.0", "redux": "^5.0.1", "redux-thunk": "^3.1.0", "reselect": "^5.1.0" }, "peerDependencies": { "react": "^16.9.0 || ^17.0.0 || ^18 || ^19", "react-redux": "^7.2.1 || ^8.1.3 || ^9.0.0" } }, "sha512-Kd6kAHTA6/nUpp8mySPqj3en3dm0tdMIgbttnQ1xFMVpufoj+ADi8pXLBsd4xzTRHQa7t/Jv8W5UnCuW4kuWMQ=="],
+
+ "@rolldown/binding-android-arm64": ["@rolldown/binding-android-arm64@1.0.0-rc.9", "", { "os": "android", "cpu": "arm64" }, "sha512-lcJL0bN5hpgJfSIz/8PIf02irmyL43P+j1pTCfbD1DbLkmGRuFIA4DD3B3ZOvGqG0XiVvRznbKtN0COQVaKUTg=="],
+
+ "@rolldown/binding-darwin-arm64": ["@rolldown/binding-darwin-arm64@1.0.0-rc.9", "", { "os": "darwin", "cpu": "arm64" }, "sha512-J7Zk3kLYFsLtuH6U+F4pS2sYVzac0qkjcO5QxHS7OS7yZu2LRs+IXo+uvJ/mvpyUljDJ3LROZPoQfgBIpCMhdQ=="],
+
+ "@rolldown/binding-darwin-x64": ["@rolldown/binding-darwin-x64@1.0.0-rc.9", "", { "os": "darwin", "cpu": "x64" }, "sha512-iwtmmghy8nhfRGeNAIltcNXzD0QMNaaA5U/NyZc1Ia4bxrzFByNMDoppoC+hl7cDiUq5/1CnFthpT9n+UtfFyg=="],
+
+ "@rolldown/binding-freebsd-x64": ["@rolldown/binding-freebsd-x64@1.0.0-rc.9", "", { "os": "freebsd", "cpu": "x64" }, "sha512-DLFYI78SCiZr5VvdEplsVC2Vx53lnA4/Ga5C65iyldMVaErr86aiqCoNBLl92PXPfDtUYjUh+xFFor40ueNs4Q=="],
+
+ "@rolldown/binding-linux-arm-gnueabihf": ["@rolldown/binding-linux-arm-gnueabihf@1.0.0-rc.9", "", { "os": "linux", "cpu": "arm" }, "sha512-CsjTmTwd0Hri6iTw/DRMK7kOZ7FwAkrO4h8YWKoX/kcj833e4coqo2wzIFywtch/8Eb5enQ/lwLM7w6JX1W5RQ=="],
+
+ "@rolldown/binding-linux-arm64-gnu": ["@rolldown/binding-linux-arm64-gnu@1.0.0-rc.9", "", { "os": "linux", "cpu": "arm64" }, "sha512-2x9O2JbSPxpxMDhP9Z74mahAStibTlrBMW0520+epJH5sac7/LwZW5Bmg/E6CXuEF53JJFW509uP+lSedaUNxg=="],
+
+ "@rolldown/binding-linux-arm64-musl": ["@rolldown/binding-linux-arm64-musl@1.0.0-rc.9", "", { "os": "linux", "cpu": "arm64" }, "sha512-JA1QRW31ogheAIRhIg9tjMfsYbglXXYGNPLdPEYrwFxdbkQCAzvpSCSHCDWNl4hTtrol8WeboCSEpjdZK8qrCg=="],
+
+ "@rolldown/binding-linux-ppc64-gnu": ["@rolldown/binding-linux-ppc64-gnu@1.0.0-rc.9", "", { "os": "linux", "cpu": "ppc64" }, "sha512-aOKU9dJheda8Kj8Y3w9gnt9QFOO+qKPAl8SWd7JPHP+Cu0EuDAE5wokQubLzIDQWg2myXq2XhTpOVS07qqvT+w=="],
+
+ "@rolldown/binding-linux-s390x-gnu": ["@rolldown/binding-linux-s390x-gnu@1.0.0-rc.9", "", { "os": "linux", "cpu": "s390x" }, "sha512-OalO94fqj7IWRn3VdXWty75jC5dk4C197AWEuMhIpvVv2lw9fiPhud0+bW2ctCxb3YoBZor71QHbY+9/WToadA=="],
+
+ "@rolldown/binding-linux-x64-gnu": ["@rolldown/binding-linux-x64-gnu@1.0.0-rc.9", "", { "os": "linux", "cpu": "x64" }, "sha512-cVEl1vZtBsBZna3YMjGXNvnYYrOJ7RzuWvZU0ffvJUexWkukMaDuGhUXn0rjnV0ptzGVkvc+vW9Yqy6h8YX4pg=="],
+
+ "@rolldown/binding-linux-x64-musl": ["@rolldown/binding-linux-x64-musl@1.0.0-rc.9", "", { "os": "linux", "cpu": "x64" }, "sha512-UzYnKCIIc4heAKgI4PZ3dfBGUZefGCJ1TPDuLHoCzgrMYPb5Rv6TLFuYtyM4rWyHM7hymNdsg5ik2C+UD9VDbA=="],
+
+ "@rolldown/binding-openharmony-arm64": ["@rolldown/binding-openharmony-arm64@1.0.0-rc.9", "", { "os": "none", "cpu": "arm64" }, "sha512-+6zoiF+RRyf5cdlFQP7nm58mq7+/2PFaY2DNQeD4B87N36JzfF/l9mdBkkmTvSYcYPE8tMh/o3cRlsx1ldLfog=="],
+
+ "@rolldown/binding-wasm32-wasi": ["@rolldown/binding-wasm32-wasi@1.0.0-rc.9", "", { "dependencies": { "@napi-rs/wasm-runtime": "^1.1.1" }, "cpu": "none" }, "sha512-rgFN6sA/dyebil3YTlL2evvi/M+ivhfnyxec7AccTpRPccno/rPoNlqybEZQBkcbZu8Hy+eqNJCqfBR8P7Pg8g=="],
+
+ "@rolldown/binding-win32-arm64-msvc": ["@rolldown/binding-win32-arm64-msvc@1.0.0-rc.9", "", { "os": "win32", "cpu": "arm64" }, "sha512-lHVNUG/8nlF1IQk1C0Ci574qKYyty2goMiPlRqkC5R+3LkXDkL5Dhx8ytbxq35m+pkHVIvIxviD+TWLdfeuadA=="],
+
+ "@rolldown/binding-win32-x64-msvc": ["@rolldown/binding-win32-x64-msvc@1.0.0-rc.9", "", { "os": "win32", "cpu": "x64" }, "sha512-G0oA4+w1iY5AGi5HcDTxWsoxF509hrFIPB2rduV5aDqS9FtDg1CAfa7V34qImbjfhIcA8C+RekocJZA96EarwQ=="],
+
+ "@rolldown/pluginutils": ["@rolldown/pluginutils@1.0.0-rc.7", "", {}, "sha512-qujRfC8sFVInYSPPMLQByRh7zhwkGFS4+tyMQ83srV1qrxL4g8E2tyxVVyxd0+8QeBM1mIk9KbWxkegRr76XzA=="],
+
+ "@rtsao/scc": ["@rtsao/scc@1.1.0", "", {}, "sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g=="],
+
+ "@schummar/icu-type-parser": ["@schummar/icu-type-parser@1.21.5", "", {}, "sha512-bXHSaW5jRTmke9Vd0h5P7BtWZG9Znqb8gSDxZnxaGSJnGwPLDPfS+3g0BKzeWqzgZPsIVZkM7m2tbo18cm5HBw=="],
+
+ "@shikijs/core": ["@shikijs/core@3.23.0", "", { "dependencies": { "@shikijs/types": "3.23.0", "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4", "hast-util-to-html": "^9.0.5" } }, "sha512-NSWQz0riNb67xthdm5br6lAkvpDJRTgB36fxlo37ZzM2yq0PQFFzbd8psqC2XMPgCzo1fW6cVi18+ArJ44wqgA=="],
+
+ "@shikijs/engine-javascript": ["@shikijs/engine-javascript@3.23.0", "", { "dependencies": { "@shikijs/types": "3.23.0", "@shikijs/vscode-textmate": "^10.0.2", "oniguruma-to-es": "^4.3.4" } }, "sha512-aHt9eiGFobmWR5uqJUViySI1bHMqrAgamWE1TYSUoftkAeCCAiGawPMwM+VCadylQtF4V3VNOZ5LmfItH5f3yA=="],
+
+ "@shikijs/engine-oniguruma": ["@shikijs/engine-oniguruma@3.23.0", "", { "dependencies": { "@shikijs/types": "3.23.0", "@shikijs/vscode-textmate": "^10.0.2" } }, "sha512-1nWINwKXxKKLqPibT5f4pAFLej9oZzQTsby8942OTlsJzOBZ0MWKiwzMsd+jhzu8YPCHAswGnnN1YtQfirL35g=="],
+
+ "@shikijs/langs": ["@shikijs/langs@3.23.0", "", { "dependencies": { "@shikijs/types": "3.23.0" } }, "sha512-2Ep4W3Re5aB1/62RSYQInK9mM3HsLeB91cHqznAJMuylqjzNVAVCMnNWRHFtcNHXsoNRayP9z1qj4Sq3nMqYXg=="],
+
+ "@shikijs/themes": ["@shikijs/themes@3.23.0", "", { "dependencies": { "@shikijs/types": "3.23.0" } }, "sha512-5qySYa1ZgAT18HR/ypENL9cUSGOeI2x+4IvYJu4JgVJdizn6kG4ia5Q1jDEOi7gTbN4RbuYtmHh0W3eccOrjMA=="],
+
+ "@shikijs/transformers": ["@shikijs/transformers@3.23.0", "", { "dependencies": { "@shikijs/core": "3.23.0", "@shikijs/types": "3.23.0" } }, "sha512-F9msZVxdF+krQNSdQ4V+Ja5QemeAoTQ2jxt7nJCwhDsdF1JWS3KxIQXA3lQbyKwS3J61oHRUSv4jYWv3CkaKTQ=="],
+
+ "@shikijs/types": ["@shikijs/types@3.23.0", "", { "dependencies": { "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4" } }, "sha512-3JZ5HXOZfYjsYSk0yPwBrkupyYSLpAE26Qc0HLghhZNGTZg/SKxXIIgoxOpmmeQP0RRSDJTk1/vPfw9tbw+jSQ=="],
+
+ "@shikijs/vscode-textmate": ["@shikijs/vscode-textmate@10.0.2", "", {}, "sha512-83yeghZ2xxin3Nj8z1NMd/NCuca+gsYXswywDy5bHvwlWL8tpTQmzGeUuHd9FC3E/SBEMvzJRwWEOz5gGes9Qg=="],
+
+ "@splinetool/runtime": ["@splinetool/runtime@0.9.526", "", { "dependencies": { "on-change": "^4.0.0", "semver-compare": "^1.0.0" } }, "sha512-qznHbXA5aKwDbCgESAothCNm1IeEZcmNWG145p5aXj4w5uoqR1TZ9qkTHTKLTsUbHeitCwdhzmRqan1kxboLgQ=="],
+
+ "@standard-schema/spec": ["@standard-schema/spec@1.1.0", "", {}, "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w=="],
+
+ "@standard-schema/utils": ["@standard-schema/utils@0.3.0", "", {}, "sha512-e7Mew686owMaPJVNNLs55PUvgz371nKgwsc4vxE49zsODpJEnxgxRo2y/OKrqueavXgZNMDVj3DdHFlaSAeU8g=="],
+
+ "@stitches/react": ["@stitches/react@1.2.8", "", { "peerDependencies": { "react": ">= 16.3.0" } }, "sha512-9g9dWI4gsSVe8bNLlb+lMkBYsnIKCZTmvqvDG+Avnn69XfmHZKiaMrx7cgTaddq7aTPPmXiTsbFcUy0xgI4+wA=="],
+
+ "@swc/core": ["@swc/core@1.15.13", "", { "dependencies": { "@swc/counter": "^0.1.3", "@swc/types": "^0.1.25" }, "optionalDependencies": { "@swc/core-darwin-arm64": "1.15.13", "@swc/core-darwin-x64": "1.15.13", "@swc/core-linux-arm-gnueabihf": "1.15.13", "@swc/core-linux-arm64-gnu": "1.15.13", "@swc/core-linux-arm64-musl": "1.15.13", "@swc/core-linux-x64-gnu": "1.15.13", "@swc/core-linux-x64-musl": "1.15.13", "@swc/core-win32-arm64-msvc": "1.15.13", "@swc/core-win32-ia32-msvc": "1.15.13", "@swc/core-win32-x64-msvc": "1.15.13" }, "peerDependencies": { "@swc/helpers": ">=0.5.17" } }, "sha512-0l1gl/72PErwUZuavcRpRAQN9uSst+Nk++niC5IX6lmMWpXoScYx3oq/narT64/sKv/eRiPTaAjBFGDEQiWJIw=="],
+
+ "@swc/core-darwin-arm64": ["@swc/core-darwin-arm64@1.15.13", "", { "os": "darwin", "cpu": "arm64" }, "sha512-ztXusRuC5NV2w+a6pDhX13CGioMLq8CjX5P4XgVJ21ocqz9t19288Do0y8LklplDtwcEhYGTNdMbkmUT7+lDTg=="],
+
+ "@swc/core-darwin-x64": ["@swc/core-darwin-x64@1.15.13", "", { "os": "darwin", "cpu": "x64" }, "sha512-cVifxQUKhaE7qcO/y9Mq6PEhoyvN9tSLzCnnFZ4EIabFHBuLtDDO6a+vLveOy98hAs5Qu1+bb5Nv0oa1Pihe3Q=="],
+
+ "@swc/core-linux-arm-gnueabihf": ["@swc/core-linux-arm-gnueabihf@1.15.13", "", { "os": "linux", "cpu": "arm" }, "sha512-t+xxEzZ48enl/wGGy7SRYd7kImWQ/+wvVFD7g5JZo234g6/QnIgZ+YdfIyjHB+ZJI3F7a2IQHS7RNjxF29UkWw=="],
+
+ "@swc/core-linux-arm64-gnu": ["@swc/core-linux-arm64-gnu@1.15.13", "", { "os": "linux", "cpu": "arm64" }, "sha512-VndeGvKmTXFn6AGwjy0Kg8i7HccOCE7Jt/vmZwRxGtOfNZM1RLYRQ7MfDLo6T0h1Bq6eYzps3L5Ma4zBmjOnOg=="],
+
+ "@swc/core-linux-arm64-musl": ["@swc/core-linux-arm64-musl@1.15.13", "", { "os": "linux", "cpu": "arm64" }, "sha512-SmZ9m+XqCB35NddHCctvHFLqPZDAs5j8IgD36GoutufDJmeq2VNfgk5rQoqNqKmAK3Y7iFdEmI76QoHIWiCLyw=="],
+
+ "@swc/core-linux-x64-gnu": ["@swc/core-linux-x64-gnu@1.15.13", "", { "os": "linux", "cpu": "x64" }, "sha512-5rij+vB9a29aNkHq72EXI2ihDZPszJb4zlApJY4aCC/q6utgqFA6CkrfTfIb+O8hxtG3zP5KERETz8mfFK6A0A=="],
+
+ "@swc/core-linux-x64-musl": ["@swc/core-linux-x64-musl@1.15.13", "", { "os": "linux", "cpu": "x64" }, "sha512-OlSlaOK9JplQ5qn07WiBLibkOw7iml2++ojEXhhR3rbWrNEKCD7sd8+6wSavsInyFdw4PhLA+Hy6YyDBIE23Yw=="],
+
+ "@swc/core-win32-arm64-msvc": ["@swc/core-win32-arm64-msvc@1.15.13", "", { "os": "win32", "cpu": "arm64" }, "sha512-zwQii5YVdsfG8Ti9gIKgBKZg8qMkRZxl+OlYWUT5D93Jl4NuNBRausP20tfEkQdAPSRrMCSUZBM6FhW7izAZRg=="],
+
+ "@swc/core-win32-ia32-msvc": ["@swc/core-win32-ia32-msvc@1.15.13", "", { "os": "win32", "cpu": "ia32" }, "sha512-hYXvyVVntqRlYoAIDwNzkS3tL2ijP3rxyWQMNKaxcCxxkCDto/w3meOK/OB6rbQSkNw0qTUcBfU9k+T0ptYdfQ=="],
+
+ "@swc/core-win32-x64-msvc": ["@swc/core-win32-x64-msvc@1.15.13", "", { "os": "win32", "cpu": "x64" }, "sha512-XTzKs7c/vYCcjmcwawnQvlHHNS1naJEAzcBckMI5OJlnrcgW8UtcX9NHFYvNjGtXuKv0/9KvqL4fuahdvlNGKw=="],
+
+ "@swc/counter": ["@swc/counter@0.1.3", "", {}, "sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ=="],
+
+ "@swc/helpers": ["@swc/helpers@0.5.19", "", { "dependencies": { "tslib": "^2.8.0" } }, "sha512-QamiFeIK3txNjgUTNppE6MiG3p7TdninpZu0E0PbqVh1a9FNLT2FRhisaa4NcaX52XVhA5l7Pk58Ft7Sqi/2sA=="],
+
+ "@swc/types": ["@swc/types@0.1.25", "", { "dependencies": { "@swc/counter": "^0.1.3" } }, "sha512-iAoY/qRhNH8a/hBvm3zKj9qQ4oc2+3w1unPJa2XvTK3XjeLXtzcCingVPw/9e5mn1+0yPqxcBGp9Jf0pkfMb1g=="],
+
+ "@tailwindcss/node": ["@tailwindcss/node@4.2.1", "", { "dependencies": { "@jridgewell/remapping": "^2.3.5", "enhanced-resolve": "^5.19.0", "jiti": "^2.6.1", "lightningcss": "1.31.1", "magic-string": "^0.30.21", "source-map-js": "^1.2.1", "tailwindcss": "4.2.1" } }, "sha512-jlx6sLk4EOwO6hHe1oCGm1Q4AN/s0rSrTTPBGPM0/RQ6Uylwq17FuU8IeJJKEjtc6K6O07zsvP+gDO6MMWo7pg=="],
+
+ "@tailwindcss/oxide": ["@tailwindcss/oxide@4.2.1", "", { "optionalDependencies": { "@tailwindcss/oxide-android-arm64": "4.2.1", "@tailwindcss/oxide-darwin-arm64": "4.2.1", "@tailwindcss/oxide-darwin-x64": "4.2.1", "@tailwindcss/oxide-freebsd-x64": "4.2.1", "@tailwindcss/oxide-linux-arm-gnueabihf": "4.2.1", "@tailwindcss/oxide-linux-arm64-gnu": "4.2.1", "@tailwindcss/oxide-linux-arm64-musl": "4.2.1", "@tailwindcss/oxide-linux-x64-gnu": "4.2.1", "@tailwindcss/oxide-linux-x64-musl": "4.2.1", "@tailwindcss/oxide-wasm32-wasi": "4.2.1", "@tailwindcss/oxide-win32-arm64-msvc": "4.2.1", "@tailwindcss/oxide-win32-x64-msvc": "4.2.1" } }, "sha512-yv9jeEFWnjKCI6/T3Oq50yQEOqmpmpfzG1hcZsAOaXFQPfzWprWrlHSdGPEF3WQTi8zu8ohC9Mh9J470nT5pUw=="],
+
+ "@tailwindcss/oxide-android-arm64": ["@tailwindcss/oxide-android-arm64@4.2.1", "", { "os": "android", "cpu": "arm64" }, "sha512-eZ7G1Zm5EC8OOKaesIKuw77jw++QJ2lL9N+dDpdQiAB/c/B2wDh0QPFHbkBVrXnwNugvrbJFk1gK2SsVjwWReg=="],
+
+ "@tailwindcss/oxide-darwin-arm64": ["@tailwindcss/oxide-darwin-arm64@4.2.1", "", { "os": "darwin", "cpu": "arm64" }, "sha512-q/LHkOstoJ7pI1J0q6djesLzRvQSIfEto148ppAd+BVQK0JYjQIFSK3JgYZJa+Yzi0DDa52ZsQx2rqytBnf8Hw=="],
+
+ "@tailwindcss/oxide-darwin-x64": ["@tailwindcss/oxide-darwin-x64@4.2.1", "", { "os": "darwin", "cpu": "x64" }, "sha512-/f/ozlaXGY6QLbpvd/kFTro2l18f7dHKpB+ieXz+Cijl4Mt9AI2rTrpq7V+t04nK+j9XBQHnSMdeQRhbGyt6fw=="],
+
+ "@tailwindcss/oxide-freebsd-x64": ["@tailwindcss/oxide-freebsd-x64@4.2.1", "", { "os": "freebsd", "cpu": "x64" }, "sha512-5e/AkgYJT/cpbkys/OU2Ei2jdETCLlifwm7ogMC7/hksI2fC3iiq6OcXwjibcIjPung0kRtR3TxEITkqgn0TcA=="],
+
+ "@tailwindcss/oxide-linux-arm-gnueabihf": ["@tailwindcss/oxide-linux-arm-gnueabihf@4.2.1", "", { "os": "linux", "cpu": "arm" }, "sha512-Uny1EcVTTmerCKt/1ZuKTkb0x8ZaiuYucg2/kImO5A5Y/kBz41/+j0gxUZl+hTF3xkWpDmHX+TaWhOtba2Fyuw=="],
+
+ "@tailwindcss/oxide-linux-arm64-gnu": ["@tailwindcss/oxide-linux-arm64-gnu@4.2.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-CTrwomI+c7n6aSSQlsPL0roRiNMDQ/YzMD9EjcR+H4f0I1SQ8QqIuPnsVp7QgMkC1Qi8rtkekLkOFjo7OlEFRQ=="],
+
+ "@tailwindcss/oxide-linux-arm64-musl": ["@tailwindcss/oxide-linux-arm64-musl@4.2.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-WZA0CHRL/SP1TRbA5mp9htsppSEkWuQ4KsSUumYQnyl8ZdT39ntwqmz4IUHGN6p4XdSlYfJwM4rRzZLShHsGAQ=="],
+
+ "@tailwindcss/oxide-linux-x64-gnu": ["@tailwindcss/oxide-linux-x64-gnu@4.2.1", "", { "os": "linux", "cpu": "x64" }, "sha512-qMFzxI2YlBOLW5PhblzuSWlWfwLHaneBE0xHzLrBgNtqN6mWfs+qYbhryGSXQjFYB1Dzf5w+LN5qbUTPhW7Y5g=="],
+
+ "@tailwindcss/oxide-linux-x64-musl": ["@tailwindcss/oxide-linux-x64-musl@4.2.1", "", { "os": "linux", "cpu": "x64" }, "sha512-5r1X2FKnCMUPlXTWRYpHdPYUY6a1Ar/t7P24OuiEdEOmms5lyqjDRvVY1yy9Rmioh+AunQ0rWiOTPE8F9A3v5g=="],
+
+ "@tailwindcss/oxide-wasm32-wasi": ["@tailwindcss/oxide-wasm32-wasi@4.2.1", "", { "cpu": "none" }, "sha512-MGFB5cVPvshR85MTJkEvqDUnuNoysrsRxd6vnk1Lf2tbiqNlXpHYZqkqOQalydienEWOHHFyyuTSYRsLfxFJ2Q=="],
+
+ "@tailwindcss/oxide-win32-arm64-msvc": ["@tailwindcss/oxide-win32-arm64-msvc@4.2.1", "", { "os": "win32", "cpu": "arm64" }, "sha512-YlUEHRHBGnCMh4Nj4GnqQyBtsshUPdiNroZj8VPkvTZSoHsilRCwXcVKnG9kyi0ZFAS/3u+qKHBdDc81SADTRA=="],
+
+ "@tailwindcss/oxide-win32-x64-msvc": ["@tailwindcss/oxide-win32-x64-msvc@4.2.1", "", { "os": "win32", "cpu": "x64" }, "sha512-rbO34G5sMWWyrN/idLeVxAZgAKWrn5LiR3/I90Q9MkA67s6T1oB0xtTe+0heoBvHSpbU9Mk7i6uwJnpo4u21XQ=="],
+
+ "@tailwindcss/postcss": ["@tailwindcss/postcss@4.2.1", "", { "dependencies": { "@alloc/quick-lru": "^5.2.0", "@tailwindcss/node": "4.2.1", "@tailwindcss/oxide": "4.2.1", "postcss": "^8.5.6", "tailwindcss": "4.2.1" } }, "sha512-OEwGIBnXnj7zJeonOh6ZG9woofIjGrd2BORfvE5p9USYKDCZoQmfqLcfNiRWoJlRWLdNPn2IgVZuWAOM4iTYMw=="],
+
+ "@testing-library/dom": ["@testing-library/dom@10.4.1", "", { "dependencies": { "@babel/code-frame": "^7.10.4", "@babel/runtime": "^7.12.5", "@types/aria-query": "^5.0.1", "aria-query": "5.3.0", "dom-accessibility-api": "^0.5.9", "lz-string": "^1.5.0", "picocolors": "1.1.1", "pretty-format": "^27.0.2" } }, "sha512-o4PXJQidqJl82ckFaXUeoAW+XysPLauYI43Abki5hABd853iMhitooc6znOnczgbTYmEP6U6/y1ZyKAIsvMKGg=="],
+
+ "@testing-library/jest-dom": ["@testing-library/jest-dom@6.9.1", "", { "dependencies": { "@adobe/css-tools": "^4.4.0", "aria-query": "^5.0.0", "css.escape": "^1.5.1", "dom-accessibility-api": "^0.6.3", "picocolors": "^1.1.1", "redent": "^3.0.0" } }, "sha512-zIcONa+hVtVSSep9UT3jZ5rizo2BsxgyDYU7WFD5eICBE7no3881HGeb/QkGfsJs6JTkY1aQhT7rIPC7e+0nnA=="],
+
+ "@testing-library/react": ["@testing-library/react@16.3.2", "", { "dependencies": { "@babel/runtime": "^7.12.5" }, "peerDependencies": { "@testing-library/dom": "^10.0.0", "@types/react": "^18.0.0 || ^19.0.0", "@types/react-dom": "^18.0.0 || ^19.0.0", "react": "^18.0.0 || ^19.0.0", "react-dom": "^18.0.0 || ^19.0.0" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-XU5/SytQM+ykqMnAnvB2umaJNIOsLF3PVv//1Ew4CTcpz0/BRyy/af40qqrt7SjKpDdT1saBMc42CUok5gaw+g=="],
+
+ "@tybys/wasm-util": ["@tybys/wasm-util@0.10.1", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg=="],
+
+ "@types/aria-query": ["@types/aria-query@5.0.4", "", {}, "sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw=="],
+
+ "@types/bcryptjs": ["@types/bcryptjs@3.0.0", "", { "dependencies": { "bcryptjs": "*" } }, "sha512-WRZOuCuaz8UcZZE4R5HXTco2goQSI2XxjGY3hbM/xDvwmqFWd4ivooImsMx65OKM6CtNKbnZ5YL+YwAwK7c1dg=="],
+
+ "@types/better-sqlite3": ["@types/better-sqlite3@7.6.13", "", { "dependencies": { "@types/node": "*" } }, "sha512-NMv9ASNARoKksWtsq/SHakpYAYnhBrQgGD8zkLYk/jaK8jUGn08CfEdTRgYhMypUQAfzSP8W6gNLe0q19/t4VA=="],
+
+ "@types/chai": ["@types/chai@5.2.3", "", { "dependencies": { "@types/deep-eql": "*", "assertion-error": "^2.0.1" } }, "sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA=="],
+
+ "@types/d3": ["@types/d3@7.4.3", "", { "dependencies": { "@types/d3-array": "*", "@types/d3-axis": "*", "@types/d3-brush": "*", "@types/d3-chord": "*", "@types/d3-color": "*", "@types/d3-contour": "*", "@types/d3-delaunay": "*", "@types/d3-dispatch": "*", "@types/d3-drag": "*", "@types/d3-dsv": "*", "@types/d3-ease": "*", "@types/d3-fetch": "*", "@types/d3-force": "*", "@types/d3-format": "*", "@types/d3-geo": "*", "@types/d3-hierarchy": "*", "@types/d3-interpolate": "*", "@types/d3-path": "*", "@types/d3-polygon": "*", "@types/d3-quadtree": "*", "@types/d3-random": "*", "@types/d3-scale": "*", "@types/d3-scale-chromatic": "*", "@types/d3-selection": "*", "@types/d3-shape": "*", "@types/d3-time": "*", "@types/d3-time-format": "*", "@types/d3-timer": "*", "@types/d3-transition": "*", "@types/d3-zoom": "*" } }, "sha512-lZXZ9ckh5R8uiFVt8ogUNf+pIrK4EsWrx2Np75WvF/eTpJ0FMHNhjXk8CKEx/+gpHbNQyJWehbFaTvqmHWB3ww=="],
+
+ "@types/d3-array": ["@types/d3-array@3.2.2", "", {}, "sha512-hOLWVbm7uRza0BYXpIIW5pxfrKe0W+D5lrFiAEYR+pb6w3N2SwSMaJbXdUfSEv+dT4MfHBLtn5js0LAWaO6otw=="],
+
+ "@types/d3-axis": ["@types/d3-axis@3.0.6", "", { "dependencies": { "@types/d3-selection": "*" } }, "sha512-pYeijfZuBd87T0hGn0FO1vQ/cgLk6E1ALJjfkC0oJ8cbwkZl3TpgS8bVBLZN+2jjGgg38epgxb2zmoGtSfvgMw=="],
+
+ "@types/d3-brush": ["@types/d3-brush@3.0.6", "", { "dependencies": { "@types/d3-selection": "*" } }, "sha512-nH60IZNNxEcrh6L1ZSMNA28rj27ut/2ZmI3r96Zd+1jrZD++zD3LsMIjWlvg4AYrHn/Pqz4CF3veCxGjtbqt7A=="],
+
+ "@types/d3-chord": ["@types/d3-chord@3.0.6", "", {}, "sha512-LFYWWd8nwfwEmTZG9PfQxd17HbNPksHBiJHaKuY1XeqscXacsS2tyoo6OdRsjf+NQYeB6XrNL3a25E3gH69lcg=="],
+
+ "@types/d3-color": ["@types/d3-color@3.1.3", "", {}, "sha512-iO90scth9WAbmgv7ogoq57O9YpKmFBbmoEoCHDB2xMBY0+/KVrqAaCDyCE16dUspeOvIxFFRI+0sEtqDqy2b4A=="],
+
+ "@types/d3-contour": ["@types/d3-contour@3.0.6", "", { "dependencies": { "@types/d3-array": "*", "@types/geojson": "*" } }, "sha512-BjzLgXGnCWjUSYGfH1cpdo41/hgdWETu4YxpezoztawmqsvCeep+8QGfiY6YbDvfgHz/DkjeIkkZVJavB4a3rg=="],
+
+ "@types/d3-delaunay": ["@types/d3-delaunay@6.0.4", "", {}, "sha512-ZMaSKu4THYCU6sV64Lhg6qjf1orxBthaC161plr5KuPHo3CNm8DTHiLw/5Eq2b6TsNP0W0iJrUOFscY6Q450Hw=="],
+
+ "@types/d3-dispatch": ["@types/d3-dispatch@3.0.7", "", {}, "sha512-5o9OIAdKkhN1QItV2oqaE5KMIiXAvDWBDPrD85e58Qlz1c1kI/J0NcqbEG88CoTwJrYe7ntUCVfeUl2UJKbWgA=="],
+
+ "@types/d3-drag": ["@types/d3-drag@3.0.7", "", { "dependencies": { "@types/d3-selection": "*" } }, "sha512-HE3jVKlzU9AaMazNufooRJ5ZpWmLIoc90A37WU2JMmeq28w1FQqCZswHZ3xR+SuxYftzHq6WU6KJHvqxKzTxxQ=="],
+
+ "@types/d3-dsv": ["@types/d3-dsv@3.0.7", "", {}, "sha512-n6QBF9/+XASqcKK6waudgL0pf/S5XHPPI8APyMLLUHd8NqouBGLsU8MgtO7NINGtPBtk9Kko/W4ea0oAspwh9g=="],
+
+ "@types/d3-ease": ["@types/d3-ease@3.0.2", "", {}, "sha512-NcV1JjO5oDzoK26oMzbILE6HW7uVXOHLQvHshBUW4UMdZGfiY6v5BeQwh9a9tCzv+CeefZQHJt5SRgK154RtiA=="],
+
+ "@types/d3-fetch": ["@types/d3-fetch@3.0.7", "", { "dependencies": { "@types/d3-dsv": "*" } }, "sha512-fTAfNmxSb9SOWNB9IoG5c8Hg6R+AzUHDRlsXsDZsNp6sxAEOP0tkP3gKkNSO/qmHPoBFTxNrjDprVHDQDvo5aA=="],
+
+ "@types/d3-force": ["@types/d3-force@3.0.10", "", {}, "sha512-ZYeSaCF3p73RdOKcjj+swRlZfnYpK1EbaDiYICEEp5Q6sUiqFaFQ9qgoshp5CzIyyb/yD09kD9o2zEltCexlgw=="],
+
+ "@types/d3-format": ["@types/d3-format@3.0.4", "", {}, "sha512-fALi2aI6shfg7vM5KiR1wNJnZ7r6UuggVqtDA+xiEdPZQwy/trcQaHnwShLuLdta2rTymCNpxYTiMZX/e09F4g=="],
+
+ "@types/d3-geo": ["@types/d3-geo@3.1.0", "", { "dependencies": { "@types/geojson": "*" } }, "sha512-856sckF0oP/diXtS4jNsiQw/UuK5fQG8l/a9VVLeSouf1/PPbBE1i1W852zVwKwYCBkFJJB7nCFTbk6UMEXBOQ=="],
+
+ "@types/d3-hierarchy": ["@types/d3-hierarchy@3.1.7", "", {}, "sha512-tJFtNoYBtRtkNysX1Xq4sxtjK8YgoWUNpIiUee0/jHGRwqvzYxkq0hGVbbOGSz+JgFxxRu4K8nb3YpG3CMARtg=="],
+
+ "@types/d3-interpolate": ["@types/d3-interpolate@3.0.4", "", { "dependencies": { "@types/d3-color": "*" } }, "sha512-mgLPETlrpVV1YRJIglr4Ez47g7Yxjl1lj7YKsiMCb27VJH9W8NVM6Bb9d8kkpG/uAQS5AmbA48q2IAolKKo1MA=="],
+
+ "@types/d3-path": ["@types/d3-path@3.1.1", "", {}, "sha512-VMZBYyQvbGmWyWVea0EHs/BwLgxc+MKi1zLDCONksozI4YJMcTt8ZEuIR4Sb1MMTE8MMW49v0IwI5+b7RmfWlg=="],
+
+ "@types/d3-polygon": ["@types/d3-polygon@3.0.2", "", {}, "sha512-ZuWOtMaHCkN9xoeEMr1ubW2nGWsp4nIql+OPQRstu4ypeZ+zk3YKqQT0CXVe/PYqrKpZAi+J9mTs05TKwjXSRA=="],
+
+ "@types/d3-quadtree": ["@types/d3-quadtree@3.0.6", "", {}, "sha512-oUzyO1/Zm6rsxKRHA1vH0NEDG58HrT5icx/azi9MF1TWdtttWl0UIUsjEQBBh+SIkrpd21ZjEv7ptxWys1ncsg=="],
+
+ "@types/d3-random": ["@types/d3-random@3.0.3", "", {}, "sha512-Imagg1vJ3y76Y2ea0871wpabqp613+8/r0mCLEBfdtqC7xMSfj9idOnmBYyMoULfHePJyxMAw3nWhJxzc+LFwQ=="],
+
+ "@types/d3-scale": ["@types/d3-scale@4.0.9", "", { "dependencies": { "@types/d3-time": "*" } }, "sha512-dLmtwB8zkAeO/juAMfnV+sItKjlsw2lKdZVVy6LRr0cBmegxSABiLEpGVmSJJ8O08i4+sGR6qQtb6WtuwJdvVw=="],
+
+ "@types/d3-scale-chromatic": ["@types/d3-scale-chromatic@3.1.0", "", {}, "sha512-iWMJgwkK7yTRmWqRB5plb1kadXyQ5Sj8V/zYlFGMUBbIPKQScw+Dku9cAAMgJG+z5GYDoMjWGLVOvjghDEFnKQ=="],
+
+ "@types/d3-selection": ["@types/d3-selection@3.0.11", "", {}, "sha512-bhAXu23DJWsrI45xafYpkQ4NtcKMwWnAC/vKrd2l+nxMFuvOT3XMYTIj2opv8vq8AO5Yh7Qac/nSeP/3zjTK0w=="],
+
+ "@types/d3-shape": ["@types/d3-shape@3.1.8", "", { "dependencies": { "@types/d3-path": "*" } }, "sha512-lae0iWfcDeR7qt7rA88BNiqdvPS5pFVPpo5OfjElwNaT2yyekbM0C9vK+yqBqEmHr6lDkRnYNoTBYlAgJa7a4w=="],
+
+ "@types/d3-time": ["@types/d3-time@3.0.4", "", {}, "sha512-yuzZug1nkAAaBlBBikKZTgzCeA+k1uy4ZFwWANOfKw5z5LRhV0gNA7gNkKm7HoK+HRN0wX3EkxGk0fpbWhmB7g=="],
+
+ "@types/d3-time-format": ["@types/d3-time-format@4.0.3", "", {}, "sha512-5xg9rC+wWL8kdDj153qZcsJ0FWiFt0J5RB6LYUNZjwSnesfblqrI/bJ1wBdJ8OQfncgbJG5+2F+qfqnqyzYxyg=="],
+
+ "@types/d3-timer": ["@types/d3-timer@3.0.2", "", {}, "sha512-Ps3T8E8dZDam6fUyNiMkekK3XUsaUEik+idO9/YjPtfj2qruF8tFBXS7XhtE4iIXBLxhmLjP3SXpLhVf21I9Lw=="],
+
+ "@types/d3-transition": ["@types/d3-transition@3.0.9", "", { "dependencies": { "@types/d3-selection": "*" } }, "sha512-uZS5shfxzO3rGlu0cC3bjmMFKsXv+SmZZcgp0KD22ts4uGXp5EVYGzu/0YdwZeKmddhcAccYtREJKkPfXkZuCg=="],
+
+ "@types/d3-zoom": ["@types/d3-zoom@3.0.8", "", { "dependencies": { "@types/d3-interpolate": "*", "@types/d3-selection": "*" } }, "sha512-iqMC4/YlFCSlO8+2Ii1GGGliCAY4XdeG748w5vQUbevlbDu0zSjH/+jojorQVBK/se0j6DUFNPBGSqD3YWYnDw=="],
+
+ "@types/debug": ["@types/debug@4.1.13", "", { "dependencies": { "@types/ms": "*" } }, "sha512-KSVgmQmzMwPlmtljOomayoR89W4FynCAi3E8PPs7vmDVPe84hT+vGPKkJfThkmXs0x0jAaa9U8uW8bbfyS2fWw=="],
+
+ "@types/deep-eql": ["@types/deep-eql@4.0.2", "", {}, "sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw=="],
+
+ "@types/estree": ["@types/estree@1.0.8", "", {}, "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w=="],
+
+ "@types/estree-jsx": ["@types/estree-jsx@1.0.5", "", { "dependencies": { "@types/estree": "*" } }, "sha512-52CcUVNFyfb1A2ALocQw/Dd1BQFNmSdkuC3BkZ6iqhdMfQz7JWOFRuJFloOzjk+6WijU56m9oKXFAXc7o3Towg=="],
+
+ "@types/geojson": ["@types/geojson@7946.0.16", "", {}, "sha512-6C8nqWur3j98U6+lXDfTUWIfgvZU+EumvpHKcYjujKH7woYyLj2sUmff0tRhrqM7BohUw7Pz3ZB1jj2gW9Fvmg=="],
+
+ "@types/hast": ["@types/hast@3.0.4", "", { "dependencies": { "@types/unist": "*" } }, "sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ=="],
+
+ "@types/http-proxy": ["@types/http-proxy@1.17.17", "", { "dependencies": { "@types/node": "*" } }, "sha512-ED6LB+Z1AVylNTu7hdzuBqOgMnvG/ld6wGCG8wFnAzKX5uyW2K3WD52v0gnLCTK/VLpXtKckgWuyScYK6cSPaw=="],
+
+ "@types/istanbul-lib-coverage": ["@types/istanbul-lib-coverage@2.0.6", "", {}, "sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w=="],
+
+ "@types/js-cookie": ["@types/js-cookie@3.0.6", "", {}, "sha512-wkw9yd1kEXOPnvEeEV1Go1MmxtBJL0RR79aOTAApecWFVu7w0NNXNqhcWgvw2YgZDYadliXkl14pa3WXw5jlCQ=="],
+
+ "@types/json-schema": ["@types/json-schema@7.0.15", "", {}, "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA=="],
+
+ "@types/json5": ["@types/json5@0.0.29", "", {}, "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ=="],
+
+ "@types/katex": ["@types/katex@0.16.8", "", {}, "sha512-trgaNyfU+Xh2Tc+ABIb44a5AYUpicB3uwirOioeOkNPPbmgRNtcWyDeeFRzjPZENO9Vq8gvVqfhaaXWLlevVwg=="],
+
+ "@types/keytar": ["@types/keytar@4.4.0", "", {}, "sha512-cq/NkUUy6rpWD8n7PweNQQBpw2o0cf5v6fbkUVEpOB9VzzIvyPvSEId1/goIj+MciW2v1Lw5mRimKO01XgE9EA=="],
+
+ "@types/mdast": ["@types/mdast@4.0.4", "", { "dependencies": { "@types/unist": "*" } }, "sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA=="],
+
+ "@types/mdx": ["@types/mdx@2.0.13", "", {}, "sha512-+OWZQfAYyio6YkJb3HLxDrvnx6SWWDbC0zVPfBRzUk0/nqoDyf6dNxQi3eArPe8rJ473nobTMQ/8Zk+LxJ+Yuw=="],
+
+ "@types/ms": ["@types/ms@2.1.0", "", {}, "sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA=="],
+
+ "@types/node": ["@types/node@25.5.0", "", { "dependencies": { "undici-types": "~7.18.0" } }, "sha512-jp2P3tQMSxWugkCUKLRPVUpGaL5MVFwF8RDuSRztfwgN1wmqJeMSbKlnEtQqU8UrhTmzEmZdu2I6v2dpp7XIxw=="],
+
+ "@types/parse-json": ["@types/parse-json@4.0.2", "", {}, "sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw=="],
+
+ "@types/react": ["@types/react@19.2.14", "", { "dependencies": { "csstype": "^3.2.2" } }, "sha512-ilcTH/UniCkMdtexkoCN0bI7pMcJDvmQFPvuPvmEaYA/NSfFTAgdUSLAoVjaRJm7+6PvcM+q1zYOwS4wTYMF9w=="],
+
+ "@types/react-dom": ["@types/react-dom@19.2.3", "", { "peerDependencies": { "@types/react": "^19.2.0" } }, "sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ=="],
+
+ "@types/trusted-types": ["@types/trusted-types@2.0.7", "", {}, "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw=="],
+
+ "@types/unist": ["@types/unist@3.0.3", "", {}, "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q=="],
+
+ "@types/use-sync-external-store": ["@types/use-sync-external-store@0.0.6", "", {}, "sha512-zFDAD+tlpf2r4asuHEj0XH6pY6i0g5NeAHPn+15wk3BV6JA69eERFXC1gyGThDkVa1zCyKr5jox1+2LbV/AMLg=="],
+
+ "@typescript-eslint/eslint-plugin": ["@typescript-eslint/eslint-plugin@8.57.1", "", { "dependencies": { "@eslint-community/regexpp": "^4.12.2", "@typescript-eslint/scope-manager": "8.57.1", "@typescript-eslint/type-utils": "8.57.1", "@typescript-eslint/utils": "8.57.1", "@typescript-eslint/visitor-keys": "8.57.1", "ignore": "^7.0.5", "natural-compare": "^1.4.0", "ts-api-utils": "^2.4.0" }, "peerDependencies": { "@typescript-eslint/parser": "^8.57.1", "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-Gn3aqnvNl4NGc6x3/Bqk1AOn0thyTU9bqDRhiRnUWezgvr2OnhYCWCgC8zXXRVqBsIL1pSDt7T9nJUe0oM0kDQ=="],
+
+ "@typescript-eslint/parser": ["@typescript-eslint/parser@8.57.1", "", { "dependencies": { "@typescript-eslint/scope-manager": "8.57.1", "@typescript-eslint/types": "8.57.1", "@typescript-eslint/typescript-estree": "8.57.1", "@typescript-eslint/visitor-keys": "8.57.1", "debug": "^4.4.3" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-k4eNDan0EIMTT/dUKc/g+rsJ6wcHYhNPdY19VoX/EOtaAG8DLtKCykhrUnuHPYvinn5jhAPgD2Qw9hXBwrahsw=="],
+
+ "@typescript-eslint/project-service": ["@typescript-eslint/project-service@8.57.1", "", { "dependencies": { "@typescript-eslint/tsconfig-utils": "^8.57.1", "@typescript-eslint/types": "^8.57.1", "debug": "^4.4.3" }, "peerDependencies": { "typescript": ">=4.8.4 <6.0.0" } }, "sha512-vx1F37BRO1OftsYlmG9xay1TqnjNVlqALymwWVuYTdo18XuKxtBpCj1QlzNIEHlvlB27osvXFWptYiEWsVdYsg=="],
+
+ "@typescript-eslint/scope-manager": ["@typescript-eslint/scope-manager@8.57.1", "", { "dependencies": { "@typescript-eslint/types": "8.57.1", "@typescript-eslint/visitor-keys": "8.57.1" } }, "sha512-hs/QcpCwlwT2L5S+3fT6gp0PabyGk4Q0Rv2doJXA0435/OpnSR3VRgvrp8Xdoc3UAYSg9cyUjTeFXZEPg/3OKg=="],
+
+ "@typescript-eslint/tsconfig-utils": ["@typescript-eslint/tsconfig-utils@8.57.1", "", { "peerDependencies": { "typescript": ">=4.8.4 <6.0.0" } }, "sha512-0lgOZB8cl19fHO4eI46YUx2EceQqhgkPSuCGLlGi79L2jwYY1cxeYc1Nae8Aw1xjgW3PKVDLlr3YJ6Bxx8HkWg=="],
+
+ "@typescript-eslint/type-utils": ["@typescript-eslint/type-utils@8.57.1", "", { "dependencies": { "@typescript-eslint/types": "8.57.1", "@typescript-eslint/typescript-estree": "8.57.1", "@typescript-eslint/utils": "8.57.1", "debug": "^4.4.3", "ts-api-utils": "^2.4.0" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-+Bwwm0ScukFdyoJsh2u6pp4S9ktegF98pYUU0hkphOOqdMB+1sNQhIz8y5E9+4pOioZijrkfNO/HUJVAFFfPKA=="],
+
+ "@typescript-eslint/types": ["@typescript-eslint/types@8.57.1", "", {}, "sha512-S29BOBPJSFUiblEl6RzPPjJt6w25A6XsBqRVDt53tA/tlL8q7ceQNZHTjPeONt/3S7KRI4quk+yP9jK2WjBiPQ=="],
+
+ "@typescript-eslint/typescript-estree": ["@typescript-eslint/typescript-estree@8.57.1", "", { "dependencies": { "@typescript-eslint/project-service": "8.57.1", "@typescript-eslint/tsconfig-utils": "8.57.1", "@typescript-eslint/types": "8.57.1", "@typescript-eslint/visitor-keys": "8.57.1", "debug": "^4.4.3", "minimatch": "^10.2.2", "semver": "^7.7.3", "tinyglobby": "^0.2.15", "ts-api-utils": "^2.4.0" }, "peerDependencies": { "typescript": ">=4.8.4 <6.0.0" } }, "sha512-ybe2hS9G6pXpqGtPli9Gx9quNV0TWLOmh58ADlmZe9DguLq0tiAKVjirSbtM1szG6+QH6rVXyU6GTLQbWnMY+g=="],
+
+ "@typescript-eslint/utils": ["@typescript-eslint/utils@8.57.1", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.9.1", "@typescript-eslint/scope-manager": "8.57.1", "@typescript-eslint/types": "8.57.1", "@typescript-eslint/typescript-estree": "8.57.1" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-XUNSJ/lEVFttPMMoDVA2r2bwrl8/oPx8cURtczkSEswY5T3AeLmCy+EKWQNdL4u0MmAHOjcWrqJp2cdvgjn8dQ=="],
+
+ "@typescript-eslint/visitor-keys": ["@typescript-eslint/visitor-keys@8.57.1", "", { "dependencies": { "@typescript-eslint/types": "8.57.1", "eslint-visitor-keys": "^5.0.0" } }, "sha512-YWnmJkXbofiz9KbnbbwuA2rpGkFPLbAIetcCNO6mJ8gdhdZ/v7WDXsoGFAJuM6ikUFKTlSQnjWnVO4ux+UzS6A=="],
+
+ "@ungap/structured-clone": ["@ungap/structured-clone@1.3.0", "", {}, "sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g=="],
+
+ "@unrs/resolver-binding-android-arm-eabi": ["@unrs/resolver-binding-android-arm-eabi@1.11.1", "", { "os": "android", "cpu": "arm" }, "sha512-ppLRUgHVaGRWUx0R0Ut06Mjo9gBaBkg3v/8AxusGLhsIotbBLuRk51rAzqLC8gq6NyyAojEXglNjzf6R948DNw=="],
+
+ "@unrs/resolver-binding-android-arm64": ["@unrs/resolver-binding-android-arm64@1.11.1", "", { "os": "android", "cpu": "arm64" }, "sha512-lCxkVtb4wp1v+EoN+HjIG9cIIzPkX5OtM03pQYkG+U5O/wL53LC4QbIeazgiKqluGeVEeBlZahHalCaBvU1a2g=="],
+
+ "@unrs/resolver-binding-darwin-arm64": ["@unrs/resolver-binding-darwin-arm64@1.11.1", "", { "os": "darwin", "cpu": "arm64" }, "sha512-gPVA1UjRu1Y/IsB/dQEsp2V1pm44Of6+LWvbLc9SDk1c2KhhDRDBUkQCYVWe6f26uJb3fOK8saWMgtX8IrMk3g=="],
+
+ "@unrs/resolver-binding-darwin-x64": ["@unrs/resolver-binding-darwin-x64@1.11.1", "", { "os": "darwin", "cpu": "x64" }, "sha512-cFzP7rWKd3lZaCsDze07QX1SC24lO8mPty9vdP+YVa3MGdVgPmFc59317b2ioXtgCMKGiCLxJ4HQs62oz6GfRQ=="],
+
+ "@unrs/resolver-binding-freebsd-x64": ["@unrs/resolver-binding-freebsd-x64@1.11.1", "", { "os": "freebsd", "cpu": "x64" }, "sha512-fqtGgak3zX4DCB6PFpsH5+Kmt/8CIi4Bry4rb1ho6Av2QHTREM+47y282Uqiu3ZRF5IQioJQ5qWRV6jduA+iGw=="],
+
+ "@unrs/resolver-binding-linux-arm-gnueabihf": ["@unrs/resolver-binding-linux-arm-gnueabihf@1.11.1", "", { "os": "linux", "cpu": "arm" }, "sha512-u92mvlcYtp9MRKmP+ZvMmtPN34+/3lMHlyMj7wXJDeXxuM0Vgzz0+PPJNsro1m3IZPYChIkn944wW8TYgGKFHw=="],
+
+ "@unrs/resolver-binding-linux-arm-musleabihf": ["@unrs/resolver-binding-linux-arm-musleabihf@1.11.1", "", { "os": "linux", "cpu": "arm" }, "sha512-cINaoY2z7LVCrfHkIcmvj7osTOtm6VVT16b5oQdS4beibX2SYBwgYLmqhBjA1t51CarSaBuX5YNsWLjsqfW5Cw=="],
+
+ "@unrs/resolver-binding-linux-arm64-gnu": ["@unrs/resolver-binding-linux-arm64-gnu@1.11.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-34gw7PjDGB9JgePJEmhEqBhWvCiiWCuXsL9hYphDF7crW7UgI05gyBAi6MF58uGcMOiOqSJ2ybEeCvHcq0BCmQ=="],
+
+ "@unrs/resolver-binding-linux-arm64-musl": ["@unrs/resolver-binding-linux-arm64-musl@1.11.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-RyMIx6Uf53hhOtJDIamSbTskA99sPHS96wxVE/bJtePJJtpdKGXO1wY90oRdXuYOGOTuqjT8ACccMc4K6QmT3w=="],
+
+ "@unrs/resolver-binding-linux-ppc64-gnu": ["@unrs/resolver-binding-linux-ppc64-gnu@1.11.1", "", { "os": "linux", "cpu": "ppc64" }, "sha512-D8Vae74A4/a+mZH0FbOkFJL9DSK2R6TFPC9M+jCWYia/q2einCubX10pecpDiTmkJVUH+y8K3BZClycD8nCShA=="],
+
+ "@unrs/resolver-binding-linux-riscv64-gnu": ["@unrs/resolver-binding-linux-riscv64-gnu@1.11.1", "", { "os": "linux", "cpu": "none" }, "sha512-frxL4OrzOWVVsOc96+V3aqTIQl1O2TjgExV4EKgRY09AJ9leZpEg8Ak9phadbuX0BA4k8U5qtvMSQQGGmaJqcQ=="],
+
+ "@unrs/resolver-binding-linux-riscv64-musl": ["@unrs/resolver-binding-linux-riscv64-musl@1.11.1", "", { "os": "linux", "cpu": "none" }, "sha512-mJ5vuDaIZ+l/acv01sHoXfpnyrNKOk/3aDoEdLO/Xtn9HuZlDD6jKxHlkN8ZhWyLJsRBxfv9GYM2utQ1SChKew=="],
+
+ "@unrs/resolver-binding-linux-s390x-gnu": ["@unrs/resolver-binding-linux-s390x-gnu@1.11.1", "", { "os": "linux", "cpu": "s390x" }, "sha512-kELo8ebBVtb9sA7rMe1Cph4QHreByhaZ2QEADd9NzIQsYNQpt9UkM9iqr2lhGr5afh885d/cB5QeTXSbZHTYPg=="],
+
+ "@unrs/resolver-binding-linux-x64-gnu": ["@unrs/resolver-binding-linux-x64-gnu@1.11.1", "", { "os": "linux", "cpu": "x64" }, "sha512-C3ZAHugKgovV5YvAMsxhq0gtXuwESUKc5MhEtjBpLoHPLYM+iuwSj3lflFwK3DPm68660rZ7G8BMcwSro7hD5w=="],
+
+ "@unrs/resolver-binding-linux-x64-musl": ["@unrs/resolver-binding-linux-x64-musl@1.11.1", "", { "os": "linux", "cpu": "x64" }, "sha512-rV0YSoyhK2nZ4vEswT/QwqzqQXw5I6CjoaYMOX0TqBlWhojUf8P94mvI7nuJTeaCkkds3QE4+zS8Ko+GdXuZtA=="],
+
+ "@unrs/resolver-binding-wasm32-wasi": ["@unrs/resolver-binding-wasm32-wasi@1.11.1", "", { "dependencies": { "@napi-rs/wasm-runtime": "^0.2.11" }, "cpu": "none" }, "sha512-5u4RkfxJm+Ng7IWgkzi3qrFOvLvQYnPBmjmZQ8+szTK/b31fQCnleNl1GgEt7nIsZRIf5PLhPwT0WM+q45x/UQ=="],
+
+ "@unrs/resolver-binding-win32-arm64-msvc": ["@unrs/resolver-binding-win32-arm64-msvc@1.11.1", "", { "os": "win32", "cpu": "arm64" }, "sha512-nRcz5Il4ln0kMhfL8S3hLkxI85BXs3o8EYoattsJNdsX4YUU89iOkVn7g0VHSRxFuVMdM4Q1jEpIId1Ihim/Uw=="],
+
+ "@unrs/resolver-binding-win32-ia32-msvc": ["@unrs/resolver-binding-win32-ia32-msvc@1.11.1", "", { "os": "win32", "cpu": "ia32" }, "sha512-DCEI6t5i1NmAZp6pFonpD5m7i6aFrpofcp4LA2i8IIq60Jyo28hamKBxNrZcyOwVOZkgsRp9O2sXWBWP8MnvIQ=="],
+
+ "@unrs/resolver-binding-win32-x64-msvc": ["@unrs/resolver-binding-win32-x64-msvc@1.11.1", "", { "os": "win32", "cpu": "x64" }, "sha512-lrW200hZdbfRtztbygyaq/6jP6AKE8qQN2KvPcJ+x7wiD038YtnYtZ82IMNJ69GJibV7bwL3y9FgK+5w/pYt6g=="],
+
+ "@upsetjs/venn.js": ["@upsetjs/venn.js@2.0.0", "", { "optionalDependencies": { "d3-selection": "^3.0.0", "d3-transition": "^3.0.1" } }, "sha512-WbBhLrooyePuQ1VZxrJjtLvTc4NVfpOyKx0sKqioq9bX1C1m7Jgykkn8gLrtwumBioXIqam8DLxp88Adbue6Hw=="],
+
+ "@use-gesture/core": ["@use-gesture/core@10.3.1", "", {}, "sha512-WcINiDt8WjqBdUXye25anHiNxPc0VOrlT8F6LLkU6cycrOGUDyY/yyFmsg3k8i5OLvv25llc0QC45GhR/C8llw=="],
+
+ "@use-gesture/react": ["@use-gesture/react@10.3.1", "", { "dependencies": { "@use-gesture/core": "10.3.1" }, "peerDependencies": { "react": ">= 16.8.0" } }, "sha512-Yy19y6O2GJq8f7CHf7L0nxL8bf4PZCPaVOCgJrusOeFHY1LvHgYXnmnXg6N5iwAnbgbZCDjo60SiM6IPJi9C5g=="],
+
+ "@vitejs/plugin-react": ["@vitejs/plugin-react@6.0.1", "", { "dependencies": { "@rolldown/pluginutils": "1.0.0-rc.7" }, "peerDependencies": { "@rolldown/plugin-babel": "^0.1.7 || ^0.2.0", "babel-plugin-react-compiler": "^1.0.0", "vite": "^8.0.0" }, "optionalPeers": ["@rolldown/plugin-babel", "babel-plugin-react-compiler"] }, "sha512-l9X/E3cDb+xY3SWzlG1MOGt2usfEHGMNIaegaUGFsLkb3RCn/k8/TOXBcab+OndDI4TBtktT8/9BwwW8Vi9KUQ=="],
+
+ "@vitest/expect": ["@vitest/expect@4.1.0", "", { "dependencies": { "@standard-schema/spec": "^1.1.0", "@types/chai": "^5.2.2", "@vitest/spy": "4.1.0", "@vitest/utils": "4.1.0", "chai": "^6.2.2", "tinyrainbow": "^3.0.3" } }, "sha512-EIxG7k4wlWweuCLG9Y5InKFwpMEOyrMb6ZJ1ihYu02LVj/bzUwn2VMU+13PinsjRW75XnITeFrQBMH5+dLvCDA=="],
+
+ "@vitest/mocker": ["@vitest/mocker@4.1.0", "", { "dependencies": { "@vitest/spy": "4.1.0", "estree-walker": "^3.0.3", "magic-string": "^0.30.21" }, "peerDependencies": { "msw": "^2.4.9", "vite": "^6.0.0 || ^7.0.0 || ^8.0.0-0" }, "optionalPeers": ["msw"] }, "sha512-evxREh+Hork43+Y4IOhTo+h5lGmVRyjqI739Rz4RlUPqwrkFFDF6EMvOOYjTx4E8Tl6gyCLRL8Mu7Ry12a13Tw=="],
+
+ "@vitest/pretty-format": ["@vitest/pretty-format@4.1.0", "", { "dependencies": { "tinyrainbow": "^3.0.3" } }, "sha512-3RZLZlh88Ib0J7NQTRATfc/3ZPOnSUn2uDBUoGNn5T36+bALixmzphN26OUD3LRXWkJu4H0s5vvUeqBiw+kS0A=="],
+
+ "@vitest/runner": ["@vitest/runner@4.1.0", "", { "dependencies": { "@vitest/utils": "4.1.0", "pathe": "^2.0.3" } }, "sha512-Duvx2OzQ7d6OjchL+trw+aSrb9idh7pnNfxrklo14p3zmNL4qPCDeIJAK+eBKYjkIwG96Bc6vYuxhqDXQOWpoQ=="],
+
+ "@vitest/snapshot": ["@vitest/snapshot@4.1.0", "", { "dependencies": { "@vitest/pretty-format": "4.1.0", "@vitest/utils": "4.1.0", "magic-string": "^0.30.21", "pathe": "^2.0.3" } }, "sha512-0Vy9euT1kgsnj1CHttwi9i9o+4rRLEaPRSOJ5gyv579GJkNpgJK+B4HSv/rAWixx2wdAFci1X4CEPjiu2bXIMg=="],
+
+ "@vitest/spy": ["@vitest/spy@4.1.0", "", {}, "sha512-pz77k+PgNpyMDv2FV6qmk5ZVau6c3R8HC8v342T2xlFxQKTrSeYw9waIJG8KgV9fFwAtTu4ceRzMivPTH6wSxw=="],
+
+ "@vitest/utils": ["@vitest/utils@4.1.0", "", { "dependencies": { "@vitest/pretty-format": "4.1.0", "convert-source-map": "^2.0.0", "tinyrainbow": "^3.0.3" } }, "sha512-XfPXT6a8TZY3dcGY8EdwsBulFCIw+BeeX0RZn2x/BtiY/75YGh8FeWGG8QISN/WhaqSrE2OrlDgtF8q5uhOTmw=="],
+
+ "accepts": ["accepts@2.0.0", "", { "dependencies": { "mime-types": "^3.0.0", "negotiator": "^1.0.0" } }, "sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng=="],
+
+ "acorn": ["acorn@8.16.0", "", { "bin": "bin/acorn" }, "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw=="],
+
+ "acorn-jsx": ["acorn-jsx@5.3.2", "", { "peerDependencies": { "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ=="],
+
+ "agent-base": ["agent-base@8.0.0", "", {}, "sha512-QT8i0hCz6C/KQ+KTAbSNwCHDGdmUJl2tp2ZpNlGSWCfhUNVbYG2WLE3MdZGBAgXPV4GAvjGMxo+C1hroyxmZEg=="],
+
+ "ahooks": ["ahooks@3.9.7", "", { "dependencies": { "@babel/runtime": "^7.21.0", "@types/js-cookie": "^3.0.6", "dayjs": "^1.9.1", "intersection-observer": "^0.12.0", "js-cookie": "^3.0.5", "lodash": "^4.17.21", "react-fast-compare": "^3.2.2", "resize-observer-polyfill": "^1.5.1", "screenfull": "^5.0.0", "tslib": "^2.4.1" }, "peerDependencies": { "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, "sha512-S0lvzhbdlhK36RFBkGv+RbOM/dbbweym+BIHM/bwwuWVSVN5TuVErHPMWo4w0t1NDYg5KPp2iEf7Y7E5LASYiw=="],
+
+ "ajv": ["ajv@6.14.0", "", { "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", "json-schema-traverse": "^0.4.1", "uri-js": "^4.2.2" } }, "sha512-IWrosm/yrn43eiKqkfkHis7QioDleaXQHdDVPKg0FSwwd/DuvyX79TZnFOnYpB7dcsFAMmtFztZuXPDvSePkFw=="],
+
+ "ajv-formats": ["ajv-formats@3.0.1", "", { "dependencies": { "ajv": "^8.0.0" }, "peerDependencies": { "ajv": "^8.0.0" } }, "sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ=="],
+
+ "ansi-escapes": ["ansi-escapes@7.3.0", "", { "dependencies": { "environment": "^1.0.0" } }, "sha512-BvU8nYgGQBxcmMuEeUEmNTvrMVjJNSH7RgW24vXexN4Ven6qCvy4TntnvlnwnMLTVlcRQQdbRY8NKnaIoeWDNg=="],
+
+ "ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="],
+
+ "ansi-styles": ["ansi-styles@4.3.0", "", { "dependencies": { "color-convert": "^2.0.1" } }, "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg=="],
+
+ "antd": ["antd@6.3.3", "", { "dependencies": { "@ant-design/colors": "^8.0.1", "@ant-design/cssinjs": "^2.1.2", "@ant-design/cssinjs-utils": "^2.1.2", "@ant-design/fast-color": "^3.0.1", "@ant-design/icons": "^6.1.0", "@ant-design/react-slick": "~2.0.0", "@babel/runtime": "^7.28.4", "@rc-component/cascader": "~1.14.0", "@rc-component/checkbox": "~2.0.0", "@rc-component/collapse": "~1.2.0", "@rc-component/color-picker": "~3.1.1", "@rc-component/dialog": "~1.8.4", "@rc-component/drawer": "~1.4.2", "@rc-component/dropdown": "~1.0.2", "@rc-component/form": "~1.7.2", "@rc-component/image": "~1.6.0", "@rc-component/input": "~1.1.2", "@rc-component/input-number": "~1.6.2", "@rc-component/mentions": "~1.6.0", "@rc-component/menu": "~1.2.0", "@rc-component/motion": "^1.3.1", "@rc-component/mutate-observer": "^2.0.1", "@rc-component/notification": "~1.2.0", "@rc-component/pagination": "~1.2.0", "@rc-component/picker": "~1.9.1", "@rc-component/progress": "~1.0.2", "@rc-component/qrcode": "~1.1.1", "@rc-component/rate": "~1.0.1", "@rc-component/resize-observer": "^1.1.1", "@rc-component/segmented": "~1.3.0", "@rc-component/select": "~1.6.14", "@rc-component/slider": "~1.0.1", "@rc-component/steps": "~1.2.2", "@rc-component/switch": "~1.0.3", "@rc-component/table": "~1.9.1", "@rc-component/tabs": "~1.7.0", "@rc-component/textarea": "~1.1.2", "@rc-component/tooltip": "~1.4.0", "@rc-component/tour": "~2.3.0", "@rc-component/tree": "~1.2.4", "@rc-component/tree-select": "~1.8.0", "@rc-component/trigger": "^3.9.0", "@rc-component/upload": "~1.1.0", "@rc-component/util": "^1.9.0", "clsx": "^2.1.1", "dayjs": "^1.11.11", "scroll-into-view-if-needed": "^3.1.0", "throttle-debounce": "^5.0.2" }, "peerDependencies": { "react": ">=18.0.0", "react-dom": ">=18.0.0" } }, "sha512-T8FAQelw36zS96cZw2U/qEjpYny5yFc7hg+1W7DvVr8xMoSXWvyB8WvmiDVH0nS0LPYV4y2sxetsJoGZt7rhhw=="],
+
+ "antd-style": ["antd-style@4.1.0", "", { "dependencies": { "@ant-design/cssinjs": "^2.0.0", "@babel/runtime": "^7.24.1", "@emotion/cache": "^11.11.0", "@emotion/css": "^11.11.2", "@emotion/react": "^11.11.4", "@emotion/serialize": "^1.1.3", "@emotion/utils": "^1.2.1", "use-merge-value": "^1.2.0" }, "peerDependencies": { "antd": ">=6.0.0", "react": ">=18" } }, "sha512-vnPBGg0OVlSz90KRYZhxd89aZiOImTiesF+9MQqN8jsLGZUQTjbP04X9jTdEfsztKUuMbBWg/RmB/wHTakbtMQ=="],
+
+ "argparse": ["argparse@2.0.1", "", {}, "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="],
+
+ "aria-query": ["aria-query@5.3.2", "", {}, "sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw=="],
+
+ "array-buffer-byte-length": ["array-buffer-byte-length@1.0.2", "", { "dependencies": { "call-bound": "^1.0.3", "is-array-buffer": "^3.0.5" } }, "sha512-LHE+8BuR7RYGDKvnrmcuSq3tDcKv9OFEXQt/HpbZhY7V6h0zlUXutnAD82GiFx9rdieCMjkvtcsPqBwgUl1Iiw=="],
+
+ "array-includes": ["array-includes@3.1.9", "", { "dependencies": { "call-bind": "^1.0.8", "call-bound": "^1.0.4", "define-properties": "^1.2.1", "es-abstract": "^1.24.0", "es-object-atoms": "^1.1.1", "get-intrinsic": "^1.3.0", "is-string": "^1.1.1", "math-intrinsics": "^1.1.0" } }, "sha512-FmeCCAenzH0KH381SPT5FZmiA/TmpndpcaShhfgEN9eCVjnFBqq3l1xrI42y8+PPLI6hypzou4GXw00WHmPBLQ=="],
+
+ "array.prototype.findlast": ["array.prototype.findlast@1.2.5", "", { "dependencies": { "call-bind": "^1.0.7", "define-properties": "^1.2.1", "es-abstract": "^1.23.2", "es-errors": "^1.3.0", "es-object-atoms": "^1.0.0", "es-shim-unscopables": "^1.0.2" } }, "sha512-CVvd6FHg1Z3POpBLxO6E6zr+rSKEQ9L6rZHAaY7lLfhKsWYUBBOuMs0e9o24oopj6H+geRCX0YJ+TJLBK2eHyQ=="],
+
+ "array.prototype.findlastindex": ["array.prototype.findlastindex@1.2.6", "", { "dependencies": { "call-bind": "^1.0.8", "call-bound": "^1.0.4", "define-properties": "^1.2.1", "es-abstract": "^1.23.9", "es-errors": "^1.3.0", "es-object-atoms": "^1.1.1", "es-shim-unscopables": "^1.1.0" } }, "sha512-F/TKATkzseUExPlfvmwQKGITM3DGTK+vkAsCZoDc5daVygbJBnjEUCbgkAvVFsgfXfX4YIqZ/27G3k3tdXrTxQ=="],
+
+ "array.prototype.flat": ["array.prototype.flat@1.3.3", "", { "dependencies": { "call-bind": "^1.0.8", "define-properties": "^1.2.1", "es-abstract": "^1.23.5", "es-shim-unscopables": "^1.0.2" } }, "sha512-rwG/ja1neyLqCuGZ5YYrznA62D4mZXg0i1cIskIUKSiqF3Cje9/wXAls9B9s1Wa2fomMsIv8czB8jZcPmxCXFg=="],
+
+ "array.prototype.flatmap": ["array.prototype.flatmap@1.3.3", "", { "dependencies": { "call-bind": "^1.0.8", "define-properties": "^1.2.1", "es-abstract": "^1.23.5", "es-shim-unscopables": "^1.0.2" } }, "sha512-Y7Wt51eKJSyi80hFrJCePGGNo5ktJCslFuboqJsbf57CCPcm5zztluPlc4/aD8sWsKvlwatezpV4U1efk8kpjg=="],
+
+ "array.prototype.tosorted": ["array.prototype.tosorted@1.1.4", "", { "dependencies": { "call-bind": "^1.0.7", "define-properties": "^1.2.1", "es-abstract": "^1.23.3", "es-errors": "^1.3.0", "es-shim-unscopables": "^1.0.2" } }, "sha512-p6Fx8B7b7ZhL/gmUsAy0D15WhvDccw3mnGNbZpi3pmeJdxtWsj2jEaI4Y6oo3XiHfzuSgPwKc04MYt6KgvC/wA=="],
+
+ "arraybuffer.prototype.slice": ["arraybuffer.prototype.slice@1.0.4", "", { "dependencies": { "array-buffer-byte-length": "^1.0.1", "call-bind": "^1.0.8", "define-properties": "^1.2.1", "es-abstract": "^1.23.5", "es-errors": "^1.3.0", "get-intrinsic": "^1.2.6", "is-array-buffer": "^3.0.4" } }, "sha512-BNoCY6SXXPQ7gF2opIP4GBE+Xw7U+pHMYKuzjgCN3GwiaIR09UUeKfheyIry77QtrCBlC0KK0q5/TER/tYh3PQ=="],
+
+ "asn1js": ["asn1js@3.0.7", "", { "dependencies": { "pvtsutils": "^1.3.6", "pvutils": "^1.1.3", "tslib": "^2.8.1" } }, "sha512-uLvq6KJu04qoQM6gvBfKFjlh6Gl0vOKQuR5cJMDHQkmwfMOQeN3F3SHCv9SNYSL+CRoHvOGFfllDlVz03GQjvQ=="],
+
+ "assertion-error": ["assertion-error@2.0.1", "", {}, "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA=="],
+
+ "assign-symbols": ["assign-symbols@1.0.0", "", {}, "sha512-Q+JC7Whu8HhmTdBph/Tq59IoRtoy6KAm5zzPv00WdujX82lbAL8K7WVjne7vdCsAmbF4AYaDOPyO3k0kl8qIrw=="],
+
+ "ast-types-flow": ["ast-types-flow@0.0.8", "", {}, "sha512-OH/2E5Fg20h2aPrbe+QL8JZQFko0YZaF+j4mnQ7BGhfavO7OpSLa8a0y9sBwomHdSbkhTS8TQNayBfnW5DwbvQ=="],
+
+ "astring": ["astring@1.9.0", "", { "bin": "bin/astring" }, "sha512-LElXdjswlqjWrPpJFg1Fx4wpkOCxj1TDHlSV4PlaRxHGWko024xICaa97ZkMfs6DRKlCguiAI+rbXv5GWwXIkg=="],
+
+ "async-function": ["async-function@1.0.0", "", {}, "sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA=="],
+
+ "asynckit": ["asynckit@0.4.0", "", {}, "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q=="],
+
+ "atomic-sleep": ["atomic-sleep@1.0.0", "", {}, "sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ=="],
+
+ "attr-accept": ["attr-accept@2.2.5", "", {}, "sha512-0bDNnY/u6pPwHDMoF0FieU354oBi0a8rD9FcsLwzcGWbc8KS8KPIi7y+s13OlVY+gMWc/9xEMUgNE6Qm8ZllYQ=="],
+
+ "available-typed-arrays": ["available-typed-arrays@1.0.7", "", { "dependencies": { "possible-typed-array-names": "^1.0.0" } }, "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ=="],
+
+ "axe-core": ["axe-core@4.11.1", "", {}, "sha512-BASOg+YwO2C+346x3LZOeoovTIoTrRqEsqMa6fmfAV0P+U9mFr9NsyOEpiYvFjbc64NMrSswhV50WdXzdb/Z5A=="],
+
+ "axios": ["axios@1.13.6", "", { "dependencies": { "follow-redirects": "^1.15.11", "form-data": "^4.0.5", "proxy-from-env": "^1.1.0" } }, "sha512-ChTCHMouEe2kn713WHbQGcuYrr6fXTBiu460OTwWrWob16g1bXn4vtz07Ope7ewMozJAnEquLk5lWQWtBig9DQ=="],
+
+ "axobject-query": ["axobject-query@4.1.0", "", {}, "sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ=="],
+
+ "babel-plugin-macros": ["babel-plugin-macros@3.1.0", "", { "dependencies": { "@babel/runtime": "^7.12.5", "cosmiconfig": "^7.0.0", "resolve": "^1.19.0" } }, "sha512-Cg7TFGpIr01vOQNODXOOaGz2NpCU5gl8x1qJFbb6hbZxR7XrcE2vtbAsTAbJ7/xwJtUuJEw8K8Zr/AE0LHlesg=="],
+
+ "bail": ["bail@2.0.2", "", {}, "sha512-0xO6mYd7JB2YesxDKplafRpsiOzPt9V02ddPCLbY1xYGPOX24NTyN50qnUxgCPcSoYMhKpAuBTjQoRZCAkUDRw=="],
+
+ "balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="],
+
+ "base64-js": ["base64-js@1.5.1", "", {}, "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA=="],
+
+ "baseline-browser-mapping": ["baseline-browser-mapping@2.9.19", "", { "bin": "dist/cli.js" }, "sha512-ipDqC8FrAl/76p2SSWKSI+H9tFwm7vYqXQrItCuiVPt26Km0jS+NzSsBWAaBusvSbQcfJG+JitdMm+wZAgTYqg=="],
+
+ "bcryptjs": ["bcryptjs@3.0.3", "", { "bin": { "bcrypt": "bin/bcrypt" } }, "sha512-GlF5wPWnSa/X5LKM1o0wz0suXIINz1iHRLvTS+sLyi7XPbe5ycmYI3DlZqVGZZtDgl4DmasFg7gOB3JYbphV5g=="],
+
+ "better-sqlite3": ["better-sqlite3@12.8.0", "", { "dependencies": { "bindings": "^1.5.0", "prebuild-install": "^7.1.1" } }, "sha512-RxD2Vd96sQDjQr20kdP+F+dK/1OUNiVOl200vKBZY8u0vTwysfolF6Hq+3ZK2+h8My9YvZhHsF+RSGZW2VYrPQ=="],
+
+ "bidi-js": ["bidi-js@1.0.3", "", { "dependencies": { "require-from-string": "^2.0.2" } }, "sha512-RKshQI1R3YQ+n9YJz2QQ147P66ELpa1FQEg20Dk8oW9t2KgLbpDLLp9aGZ7y8WHSshDknG0bknqGw5/tyCs5tw=="],
+
+ "bindings": ["bindings@1.5.0", "", { "dependencies": { "file-uri-to-path": "1.0.0" } }, "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ=="],
+
+ "bl": ["bl@4.1.0", "", { "dependencies": { "buffer": "^5.5.0", "inherits": "^2.0.4", "readable-stream": "^3.4.0" } }, "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w=="],
+
+ "body-parser": ["body-parser@2.2.2", "", { "dependencies": { "bytes": "^3.1.2", "content-type": "^1.0.5", "debug": "^4.4.3", "http-errors": "^2.0.0", "iconv-lite": "^0.7.0", "on-finished": "^2.4.1", "qs": "^6.14.1", "raw-body": "^3.0.1", "type-is": "^2.0.1" } }, "sha512-oP5VkATKlNwcgvxi0vM0p/D3n2C3EReYVX+DNYs5TjZFn/oQt2j+4sVJtSMr18pdRr8wjTcBl6LoV+FUwzPmNA=="],
+
+ "bottleneck": ["bottleneck@2.19.5", "", {}, "sha512-VHiNCbI1lKdl44tGrhNfU3lup0Tj/ZBMJB5/2ZbNXRCPuRCO7ed2mgcK4r17y+KB2EfuYuRaVlwNbAeaWGSpbw=="],
+
+ "brace-expansion": ["brace-expansion@1.1.13", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-9ZLprWS6EENmhEOpjCYW2c8VkmOvckIJZfkr7rBW6dObmfgJ/L1GpSYW5Hpo9lDz4D1+n0Ckz8rU7FwHDQiG/w=="],
+
+ "braces": ["braces@3.0.3", "", { "dependencies": { "fill-range": "^7.1.1" } }, "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA=="],
+
+ "browserslist": ["browserslist@4.28.1", "", { "dependencies": { "baseline-browser-mapping": "^2.9.0", "caniuse-lite": "^1.0.30001759", "electron-to-chromium": "^1.5.263", "node-releases": "^2.0.27", "update-browserslist-db": "^1.2.0" }, "bin": "cli.js" }, "sha512-ZC5Bd0LgJXgwGqUknZY/vkUQ04r8NXnJZ3yYi4vDmSiZmC/pdSN0NbNRPxZpbtO4uAfDUAFffO8IZoM3Gj8IkA=="],
+
+ "buffer": ["buffer@5.7.1", "", { "dependencies": { "base64-js": "^1.3.1", "ieee754": "^1.1.13" } }, "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ=="],
+
+ "buffer-crc32": ["buffer-crc32@1.0.0", "", {}, "sha512-Db1SbgBS/fg/392AblrMJk97KggmvYhr4pB5ZIMTWtaivCPMWLkmb7m21cJvpvgK+J3nsU2CmmixNBZx4vFj/w=="],
+
+ "bundle-name": ["bundle-name@4.1.0", "", { "dependencies": { "run-applescript": "^7.0.0" } }, "sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q=="],
+
+ "bytes": ["bytes@3.1.2", "", {}, "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg=="],
+
+ "bytestreamjs": ["bytestreamjs@2.0.1", "", {}, "sha512-U1Z/ob71V/bXfVABvNr/Kumf5VyeQRBEm6Txb0PQ6S7V5GpBM3w4Cbqz/xPDicR5tN0uvDifng8C+5qECeGwyQ=="],
+
+ "c8": ["c8@11.0.0", "", { "dependencies": { "@bcoe/v8-coverage": "^1.0.1", "@istanbuljs/schema": "^0.1.3", "find-up": "^5.0.0", "foreground-child": "^3.1.1", "istanbul-lib-coverage": "^3.2.0", "istanbul-lib-report": "^3.0.1", "istanbul-reports": "^3.1.6", "test-exclude": "^8.0.0", "v8-to-istanbul": "^9.0.0", "yargs": "^17.7.2", "yargs-parser": "^21.1.1" }, "peerDependencies": { "monocart-coverage-reports": "^2" }, "optionalPeers": ["monocart-coverage-reports"], "bin": "bin/c8.js" }, "sha512-e/uRViGHSVIJv7zsaDKM7VRn2390TgHXqUSvYwPHBQaU6L7E9L0n9JbdkwdYPvshDT0KymBmmlwSpms3yBaMNg=="],
+
+ "call-bind": ["call-bind@1.0.8", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.0", "es-define-property": "^1.0.0", "get-intrinsic": "^1.2.4", "set-function-length": "^1.2.2" } }, "sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww=="],
+
+ "call-bind-apply-helpers": ["call-bind-apply-helpers@1.0.2", "", { "dependencies": { "es-errors": "^1.3.0", "function-bind": "^1.1.2" } }, "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ=="],
+
+ "call-bound": ["call-bound@1.0.4", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.2", "get-intrinsic": "^1.3.0" } }, "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg=="],
+
+ "callsites": ["callsites@3.1.0", "", {}, "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ=="],
+
+ "caniuse-lite": ["caniuse-lite@1.0.30001769", "", {}, "sha512-BCfFL1sHijQlBGWBMuJyhZUhzo7wer5sVj9hqekB/7xn0Ypy+pER/edCYQm4exbXj4WiySGp40P8UuTh6w1srg=="],
+
+ "ccount": ["ccount@2.0.1", "", {}, "sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg=="],
+
+ "chai": ["chai@6.2.2", "", {}, "sha512-NUPRluOfOiTKBKvWPtSD4PhFvWCqOi0BGStNWs57X9js7XGTprSmFoz5F0tWhR4WPjNeR9jXqdC7/UpSJTnlRg=="],
+
+ "chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="],
+
+ "character-entities": ["character-entities@2.0.2", "", {}, "sha512-shx7oQ0Awen/BRIdkjkvz54PnEEI/EjwXDSIZp86/KKdbafHh1Df/RYGBhn4hbe2+uKC9FnT5UCEdyPz3ai9hQ=="],
+
+ "character-entities-html4": ["character-entities-html4@2.1.0", "", {}, "sha512-1v7fgQRj6hnSwFpq1Eu0ynr/CDEw0rXo2B61qXrLNdHZmPKgb7fqS1a2JwF0rISo9q77jDI8VMEHoApn8qDoZA=="],
+
+ "character-entities-legacy": ["character-entities-legacy@3.0.0", "", {}, "sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ=="],
+
+ "character-reference-invalid": ["character-reference-invalid@2.0.1", "", {}, "sha512-iBZ4F4wRbyORVsu0jPV7gXkOsGYjGHPmAyv+HiHG8gi5PtC9KI2j1+v8/tlibRvjoWX027ypmG/n0HtO5t7unw=="],
+
+ "chevrotain": ["chevrotain@11.1.2", "", { "dependencies": { "@chevrotain/cst-dts-gen": "11.1.2", "@chevrotain/gast": "11.1.2", "@chevrotain/regexp-to-ast": "11.1.2", "@chevrotain/types": "11.1.2", "@chevrotain/utils": "11.1.2", "lodash-es": "4.17.23" } }, "sha512-opLQzEVriiH1uUQ4Kctsd49bRoFDXGGSC4GUqj7pGyxM3RehRhvTlZJc1FL/Flew2p5uwxa1tUDWKzI4wNM8pg=="],
+
+ "chevrotain-allstar": ["chevrotain-allstar@0.3.1", "", { "dependencies": { "lodash-es": "^4.17.21" }, "peerDependencies": { "chevrotain": "^11.0.0" } }, "sha512-b7g+y9A0v4mxCW1qUhf3BSVPg+/NvGErk/dOkrDaHA0nQIQGAtrOjlX//9OQtRlSCy+x9rfB5N8yC71lH1nvMw=="],
+
+ "chownr": ["chownr@1.1.4", "", {}, "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg=="],
+
+ "chroma-js": ["chroma-js@3.2.0", "", {}, "sha512-os/OippSlX1RlWWr+QDPcGUZs0uoqr32urfxESG9U93lhUfbnlyckte84Q8P1UQY/qth983AS1JONKmLS4T0nw=="],
+
+ "class-variance-authority": ["class-variance-authority@0.7.1", "", { "dependencies": { "clsx": "^2.1.1" } }, "sha512-Ka+9Trutv7G8M6WT6SeiRWz792K5qEqIGEGzXKhAE6xOWAY6pPH8U+9IY3oCMv6kqTmLsv7Xh/2w2RigkePMsg=="],
+
+ "classnames": ["classnames@2.5.1", "", {}, "sha512-saHYOzhIQs6wy2sVxTM6bUDsQO4F50V9RQ22qBpEdCW+I+/Wmke2HOl6lS6dTpdxVhb88/I6+Hs+438c3lfUow=="],
+
+ "cli-cursor": ["cli-cursor@5.0.0", "", { "dependencies": { "restore-cursor": "^5.0.0" } }, "sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw=="],
+
+ "cli-spinners": ["cli-spinners@3.4.0", "", {}, "sha512-bXfOC4QcT1tKXGorxL3wbJm6XJPDqEnij2gQ2m7ESQuE+/z9YFIWnl/5RpTiKWbMq3EVKR4fRLJGn6DVfu0mpw=="],
+
+ "cli-truncate": ["cli-truncate@5.1.1", "", { "dependencies": { "slice-ansi": "^7.1.0", "string-width": "^8.0.0" } }, "sha512-SroPvNHxUnk+vIW/dOSfNqdy1sPEFkrTk6TUtqLCnBlo3N7TNYYkzzN7uSD6+jVjrdO4+p8nH7JzH6cIvUem6A=="],
+
+ "client-only": ["client-only@0.0.1", "", {}, "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA=="],
+
+ "cliui": ["cliui@8.0.1", "", { "dependencies": { "string-width": "^4.2.0", "strip-ansi": "^6.0.1", "wrap-ansi": "^7.0.0" } }, "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ=="],
+
+ "clsx": ["clsx@2.1.1", "", {}, "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA=="],
+
+ "collapse-white-space": ["collapse-white-space@2.1.0", "", {}, "sha512-loKTxY1zCOuG4j9f6EPnuyyYkf58RnhhWTvRoZEokgB+WbdXehfjFviyOVYkqzEWz1Q5kRiZdBYS5SwxbQYwzw=="],
+
+ "color-convert": ["color-convert@2.0.1", "", { "dependencies": { "color-name": "~1.1.4" } }, "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ=="],
+
+ "color-name": ["color-name@1.1.4", "", {}, "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="],
+
+ "colord": ["colord@2.9.3", "", {}, "sha512-jeC1axXpnb0/2nn/Y1LPuLdgXBLH7aDcHu4KEKfqw3CUhX7ZpfBSlPKyqXE6btIgEzfWtrX3/tyBCaCvXvMkOw=="],
+
+ "colorette": ["colorette@2.0.20", "", {}, "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w=="],
+
+ "combined-stream": ["combined-stream@1.0.8", "", { "dependencies": { "delayed-stream": "~1.0.0" } }, "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg=="],
+
+ "comma-separated-tokens": ["comma-separated-tokens@2.0.3", "", {}, "sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg=="],
+
+ "commander": ["commander@14.0.3", "", {}, "sha512-H+y0Jo/T1RZ9qPP4Eh1pkcQcLRglraJaSLoyOtHxu6AapkjWVCy2Sit1QQ4x3Dng8qDlSsZEet7g5Pq06MvTgw=="],
+
+ "compute-scroll-into-view": ["compute-scroll-into-view@3.1.1", "", {}, "sha512-VRhuHOLoKYOy4UbilLbUzbYg93XLjv2PncJC50EuTWPA3gaja1UjBsUP/D/9/juV3vQFr6XBEzn9KCAHdUvOHw=="],
+
+ "concat-map": ["concat-map@0.0.1", "", {}, "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg=="],
+
+ "concurrently": ["concurrently@9.2.1", "", { "dependencies": { "chalk": "4.1.2", "rxjs": "7.8.2", "shell-quote": "1.8.3", "supports-color": "8.1.1", "tree-kill": "1.2.2", "yargs": "17.7.2" }, "bin": { "conc": "dist/bin/concurrently.js", "concurrently": "dist/bin/concurrently.js" } }, "sha512-fsfrO0MxV64Znoy8/l1vVIjjHa29SZyyqPgQBwhiDcaW8wJc2W3XWVOGx4M3oJBnv/zdUZIIp1gDeS98GzP8Ng=="],
+
+ "confbox": ["confbox@0.1.8", "", {}, "sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w=="],
+
+ "content-disposition": ["content-disposition@1.0.1", "", {}, "sha512-oIXISMynqSqm241k6kcQ5UwttDILMK4BiurCfGEREw6+X9jkkpEe5T9FZaApyLGGOnFuyMWZpdolTXMtvEJ08Q=="],
+
+ "content-type": ["content-type@1.0.6", "", {}, "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA=="],
+
+ "convert-source-map": ["convert-source-map@2.0.0", "", {}, "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg=="],
+
+ "cookie": ["cookie@0.7.2", "", {}, "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w=="],
+
+ "cookie-signature": ["cookie-signature@1.2.2", "", {}, "sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg=="],
+
+ "cors": ["cors@2.8.6", "", { "dependencies": { "object-assign": "^4", "vary": "^1" } }, "sha512-tJtZBBHA6vjIAaF6EnIaq6laBBP9aq/Y3ouVJjEfoHbRBcHBAHYcMh/w8LDrk2PvIMMq8gmopa5D4V8RmbrxGw=="],
+
+ "cose-base": ["cose-base@1.0.3", "", { "dependencies": { "layout-base": "^1.0.0" } }, "sha512-s9whTXInMSgAp/NVXVNuVxVKzGH2qck3aQlVHxDCdAEPgtMKwc4Wq6/QKhgdEdgbLSi9rBTAcPoRa6JpiG4ksg=="],
+
+ "cosmiconfig": ["cosmiconfig@7.1.0", "", { "dependencies": { "@types/parse-json": "^4.0.0", "import-fresh": "^3.2.1", "parse-json": "^5.0.0", "path-type": "^4.0.0", "yaml": "^1.10.0" } }, "sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA=="],
+
+ "cross-env": ["cross-env@10.1.0", "", { "dependencies": { "@epic-web/invariant": "^1.0.0", "cross-spawn": "^7.0.6" }, "bin": { "cross-env": "dist/bin/cross-env.js", "cross-env-shell": "dist/bin/cross-env-shell.js" } }, "sha512-GsYosgnACZTADcmEyJctkJIoqAhHjttw7RsFrVoJNXbsWWqaq6Ym+7kZjq6mS45O0jij6vtiReppKQEtqWy6Dw=="],
+
+ "cross-spawn": ["cross-spawn@7.0.6", "", { "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", "which": "^2.0.1" } }, "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA=="],
+
+ "css-tree": ["css-tree@3.2.1", "", { "dependencies": { "mdn-data": "2.27.1", "source-map-js": "^1.2.1" } }, "sha512-X7sjQzceUhu1u7Y/ylrRZFU2FS6LRiFVp6rKLPg23y3x3c3DOKAwuXGDp+PAGjh6CSnCjYeAul8pcT8bAl+lSA=="],
+
+ "css.escape": ["css.escape@1.5.1", "", {}, "sha512-YUifsXXuknHlUsmlgyY0PKzgPOr7/FjCePfHNt0jxm83wHZi44VDMQ7/fGNkjY3/jV1MC+1CmZbaHzugyeRtpg=="],
+
+ "csstype": ["csstype@3.2.3", "", {}, "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ=="],
+
+ "cytoscape": ["cytoscape@3.33.1", "", {}, "sha512-iJc4TwyANnOGR1OmWhsS9ayRS3s+XQ185FmuHObThD+5AeJCakAAbWv8KimMTt08xCCLNgneQwFp+JRJOr9qGQ=="],
+
+ "cytoscape-cose-bilkent": ["cytoscape-cose-bilkent@4.1.0", "", { "dependencies": { "cose-base": "^1.0.0" }, "peerDependencies": { "cytoscape": "^3.2.0" } }, "sha512-wgQlVIUJF13Quxiv5e1gstZ08rnZj2XaLHGoFMYXz7SkNfCDOOteKBE6SYRfA9WxxI/iBc3ajfDoc6hb/MRAHQ=="],
+
+ "cytoscape-fcose": ["cytoscape-fcose@2.2.0", "", { "dependencies": { "cose-base": "^2.2.0" }, "peerDependencies": { "cytoscape": "^3.2.0" } }, "sha512-ki1/VuRIHFCzxWNrsshHYPs6L7TvLu3DL+TyIGEsRcvVERmxokbf5Gdk7mFxZnTdiGtnA4cfSmjZJMviqSuZrQ=="],
+
+ "d3": ["d3@7.9.0", "", { "dependencies": { "d3-array": "3", "d3-axis": "3", "d3-brush": "3", "d3-chord": "3", "d3-color": "3", "d3-contour": "4", "d3-delaunay": "6", "d3-dispatch": "3", "d3-drag": "3", "d3-dsv": "3", "d3-ease": "3", "d3-fetch": "3", "d3-force": "3", "d3-format": "3", "d3-geo": "3", "d3-hierarchy": "3", "d3-interpolate": "3", "d3-path": "3", "d3-polygon": "3", "d3-quadtree": "3", "d3-random": "3", "d3-scale": "4", "d3-scale-chromatic": "3", "d3-selection": "3", "d3-shape": "3", "d3-time": "3", "d3-time-format": "4", "d3-timer": "3", "d3-transition": "3", "d3-zoom": "3" } }, "sha512-e1U46jVP+w7Iut8Jt8ri1YsPOvFpg46k+K8TpCb0P+zjCkjkPnV7WzfDJzMHy1LnA+wj5pLT1wjO901gLXeEhA=="],
+
+ "d3-array": ["d3-array@3.2.4", "", { "dependencies": { "internmap": "1 - 2" } }, "sha512-tdQAmyA18i4J7wprpYq8ClcxZy3SC31QMeByyCFyRt7BVHdREQZ5lpzoe5mFEYZUWe+oq8HBvk9JjpibyEV4Jg=="],
+
+ "d3-axis": ["d3-axis@3.0.0", "", {}, "sha512-IH5tgjV4jE/GhHkRV0HiVYPDtvfjHQlQfJHs0usq7M30XcSBvOotpmH1IgkcXsO/5gEQZD43B//fc7SRT5S+xw=="],
+
+ "d3-brush": ["d3-brush@3.0.0", "", { "dependencies": { "d3-dispatch": "1 - 3", "d3-drag": "2 - 3", "d3-interpolate": "1 - 3", "d3-selection": "3", "d3-transition": "3" } }, "sha512-ALnjWlVYkXsVIGlOsuWH1+3udkYFI48Ljihfnh8FZPF2QS9o+PzGLBslO0PjzVoHLZ2KCVgAM8NVkXPJB2aNnQ=="],
+
+ "d3-chord": ["d3-chord@3.0.1", "", { "dependencies": { "d3-path": "1 - 3" } }, "sha512-VE5S6TNa+j8msksl7HwjxMHDM2yNK3XCkusIlpX5kwauBfXuyLAtNg9jCp/iHH61tgI4sb6R/EIMWCqEIdjT/g=="],
+
+ "d3-color": ["d3-color@3.1.0", "", {}, "sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA=="],
+
+ "d3-contour": ["d3-contour@4.0.2", "", { "dependencies": { "d3-array": "^3.2.0" } }, "sha512-4EzFTRIikzs47RGmdxbeUvLWtGedDUNkTcmzoeyg4sP/dvCexO47AaQL7VKy/gul85TOxw+IBgA8US2xwbToNA=="],
+
+ "d3-delaunay": ["d3-delaunay@6.0.4", "", { "dependencies": { "delaunator": "5" } }, "sha512-mdjtIZ1XLAM8bm/hx3WwjfHt6Sggek7qH043O8KEjDXN40xi3vx/6pYSVTwLjEgiXQTbvaouWKynLBiUZ6SK6A=="],
+
+ "d3-dispatch": ["d3-dispatch@3.0.1", "", {}, "sha512-rzUyPU/S7rwUflMyLc1ETDeBj0NRuHKKAcvukozwhshr6g6c5d8zh4c2gQjY2bZ0dXeGLWc1PF174P2tVvKhfg=="],
+
+ "d3-drag": ["d3-drag@3.0.0", "", { "dependencies": { "d3-dispatch": "1 - 3", "d3-selection": "3" } }, "sha512-pWbUJLdETVA8lQNJecMxoXfH6x+mO2UQo8rSmZ+QqxcbyA3hfeprFgIT//HW2nlHChWeIIMwS2Fq+gEARkhTkg=="],
+
+ "d3-dsv": ["d3-dsv@3.0.1", "", { "dependencies": { "commander": "7", "iconv-lite": "0.6", "rw": "1" }, "bin": { "csv2json": "bin/dsv2json.js", "csv2tsv": "bin/dsv2dsv.js", "dsv2dsv": "bin/dsv2dsv.js", "dsv2json": "bin/dsv2json.js", "json2csv": "bin/json2dsv.js", "json2dsv": "bin/json2dsv.js", "json2tsv": "bin/json2dsv.js", "tsv2csv": "bin/dsv2dsv.js", "tsv2json": "bin/dsv2json.js" } }, "sha512-UG6OvdI5afDIFP9w4G0mNq50dSOsXHJaRE8arAS5o9ApWnIElp8GZw1Dun8vP8OyHOZ/QJUKUJwxiiCCnUwm+Q=="],
+
+ "d3-ease": ["d3-ease@3.0.1", "", {}, "sha512-wR/XK3D3XcLIZwpbvQwQ5fK+8Ykds1ip7A2Txe0yxncXSdq1L9skcG7blcedkOX+ZcgxGAmLX1FrRGbADwzi0w=="],
+
+ "d3-fetch": ["d3-fetch@3.0.1", "", { "dependencies": { "d3-dsv": "1 - 3" } }, "sha512-kpkQIM20n3oLVBKGg6oHrUchHM3xODkTzjMoj7aWQFq5QEM+R6E4WkzT5+tojDY7yjez8KgCBRoj4aEr99Fdqw=="],
+
+ "d3-force": ["d3-force@3.0.0", "", { "dependencies": { "d3-dispatch": "1 - 3", "d3-quadtree": "1 - 3", "d3-timer": "1 - 3" } }, "sha512-zxV/SsA+U4yte8051P4ECydjD/S+qeYtnaIyAs9tgHCqfguma/aAQDjo85A9Z6EKhBirHRJHXIgJUlffT4wdLg=="],
+
+ "d3-format": ["d3-format@3.1.2", "", {}, "sha512-AJDdYOdnyRDV5b6ArilzCPPwc1ejkHcoyFarqlPqT7zRYjhavcT3uSrqcMvsgh2CgoPbK3RCwyHaVyxYcP2Arg=="],
+
+ "d3-geo": ["d3-geo@3.1.1", "", { "dependencies": { "d3-array": "2.5.0 - 3" } }, "sha512-637ln3gXKXOwhalDzinUgY83KzNWZRKbYubaG+fGVuc/dxO64RRljtCTnf5ecMyE1RIdtqpkVcq0IbtU2S8j2Q=="],
+
+ "d3-hierarchy": ["d3-hierarchy@3.1.2", "", {}, "sha512-FX/9frcub54beBdugHjDCdikxThEqjnR93Qt7PvQTOHxyiNCAlvMrHhclk3cD5VeAaq9fxmfRp+CnWw9rEMBuA=="],
+
+ "d3-interpolate": ["d3-interpolate@3.0.1", "", { "dependencies": { "d3-color": "1 - 3" } }, "sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g=="],
+
+ "d3-path": ["d3-path@3.1.0", "", {}, "sha512-p3KP5HCf/bvjBSSKuXid6Zqijx7wIfNW+J/maPs+iwR35at5JCbLUT0LzF1cnjbCHWhqzQTIN2Jpe8pRebIEFQ=="],
+
+ "d3-polygon": ["d3-polygon@3.0.1", "", {}, "sha512-3vbA7vXYwfe1SYhED++fPUQlWSYTTGmFmQiany/gdbiWgU/iEyQzyymwL9SkJjFFuCS4902BSzewVGsHHmHtXg=="],
+
+ "d3-quadtree": ["d3-quadtree@3.0.1", "", {}, "sha512-04xDrxQTDTCFwP5H6hRhsRcb9xxv2RzkcsygFzmkSIOJy3PeRJP7sNk3VRIbKXcog561P9oU0/rVH6vDROAgUw=="],
+
+ "d3-random": ["d3-random@3.0.1", "", {}, "sha512-FXMe9GfxTxqd5D6jFsQ+DJ8BJS4E/fT5mqqdjovykEB2oFbTMDVdg1MGFxfQW+FBOGoB++k8swBrgwSHT1cUXQ=="],
+
+ "d3-sankey": ["d3-sankey@0.12.3", "", { "dependencies": { "d3-array": "1 - 2", "d3-shape": "^1.2.0" } }, "sha512-nQhsBRmM19Ax5xEIPLMY9ZmJ/cDvd1BG3UVvt5h3WRxKg5zGRbvnteTyWAbzeSvlh3tW7ZEmq4VwR5mB3tutmQ=="],
+
+ "d3-scale": ["d3-scale@4.0.2", "", { "dependencies": { "d3-array": "2.10.0 - 3", "d3-format": "1 - 3", "d3-interpolate": "1.2.0 - 3", "d3-time": "2.1.1 - 3", "d3-time-format": "2 - 4" } }, "sha512-GZW464g1SH7ag3Y7hXjf8RoUuAFIqklOAq3MRl4OaWabTFJY9PN/E1YklhXLh+OQ3fM9yS2nOkCoS+WLZ6kvxQ=="],
+
+ "d3-scale-chromatic": ["d3-scale-chromatic@3.1.0", "", { "dependencies": { "d3-color": "1 - 3", "d3-interpolate": "1 - 3" } }, "sha512-A3s5PWiZ9YCXFye1o246KoscMWqf8BsD9eRiJ3He7C9OBaxKhAd5TFCdEx/7VbKtxxTsu//1mMJFrEt572cEyQ=="],
+
+ "d3-selection": ["d3-selection@3.0.0", "", {}, "sha512-fmTRWbNMmsmWq6xJV8D19U/gw/bwrHfNXxrIN+HfZgnzqTHp9jOmKMhsTUjXOJnZOdZY9Q28y4yebKzqDKlxlQ=="],
+
+ "d3-shape": ["d3-shape@3.2.0", "", { "dependencies": { "d3-path": "^3.1.0" } }, "sha512-SaLBuwGm3MOViRq2ABk3eLoxwZELpH6zhl3FbAoJ7Vm1gofKx6El1Ib5z23NUEhF9AsGl7y+dzLe5Cw2AArGTA=="],
+
+ "d3-time": ["d3-time@3.1.0", "", { "dependencies": { "d3-array": "2 - 3" } }, "sha512-VqKjzBLejbSMT4IgbmVgDjpkYrNWUYJnbCGo874u7MMKIWsILRX+OpX/gTk8MqjpT1A/c6HY2dCA77ZN0lkQ2Q=="],
+
+ "d3-time-format": ["d3-time-format@4.1.0", "", { "dependencies": { "d3-time": "1 - 3" } }, "sha512-dJxPBlzC7NugB2PDLwo9Q8JiTR3M3e4/XANkreKSUxF8vvXKqm1Yfq4Q5dl8budlunRVlUUaDUgFt7eA8D6NLg=="],
+
+ "d3-timer": ["d3-timer@3.0.1", "", {}, "sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA=="],
+
+ "d3-transition": ["d3-transition@3.0.1", "", { "dependencies": { "d3-color": "1 - 3", "d3-dispatch": "1 - 3", "d3-ease": "1 - 3", "d3-interpolate": "1 - 3", "d3-timer": "1 - 3" }, "peerDependencies": { "d3-selection": "2 - 3" } }, "sha512-ApKvfjsSR6tg06xrL434C0WydLr7JewBB3V+/39RMHsaXTOG0zmt/OAXeng5M5LBm0ojmxJrpomQVZ1aPvBL4w=="],
+
+ "d3-zoom": ["d3-zoom@3.0.0", "", { "dependencies": { "d3-dispatch": "1 - 3", "d3-drag": "2 - 3", "d3-interpolate": "1 - 3", "d3-selection": "2 - 3", "d3-transition": "2 - 3" } }, "sha512-b8AmV3kfQaqWAuacbPuNbL6vahnOJflOhexLzMMNLga62+/nh0JzvJ0aO/5a5MVgUFGS7Hu1P9P03o3fJkDCyw=="],
+
+ "dagre-d3-es": ["dagre-d3-es@7.0.14", "", { "dependencies": { "d3": "^7.9.0", "lodash-es": "^4.17.21" } }, "sha512-P4rFMVq9ESWqmOgK+dlXvOtLwYg0i7u0HBGJER0LZDJT2VHIPAMZ/riPxqJceWMStH5+E61QxFra9kIS3AqdMg=="],
+
+ "damerau-levenshtein": ["damerau-levenshtein@1.0.8", "", {}, "sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA=="],
+
+ "data-urls": ["data-urls@7.0.0", "", { "dependencies": { "whatwg-mimetype": "^5.0.0", "whatwg-url": "^16.0.0" } }, "sha512-23XHcCF+coGYevirZceTVD7NdJOqVn+49IHyxgszm+JIiHLoB2TkmPtsYkNWT1pvRSGkc35L6NHs0yHkN2SumA=="],
+
+ "data-view-buffer": ["data-view-buffer@1.0.2", "", { "dependencies": { "call-bound": "^1.0.3", "es-errors": "^1.3.0", "is-data-view": "^1.0.2" } }, "sha512-EmKO5V3OLXh1rtK2wgXRansaK1/mtVdTUEiEI0W8RkvgT05kfxaH29PliLnpLP73yYO6142Q72QNa8Wx/A5CqQ=="],
+
+ "data-view-byte-length": ["data-view-byte-length@1.0.2", "", { "dependencies": { "call-bound": "^1.0.3", "es-errors": "^1.3.0", "is-data-view": "^1.0.2" } }, "sha512-tuhGbE6CfTM9+5ANGf+oQb72Ky/0+s3xKUpHvShfiz2RxMFgFPjsXuRLBVMtvMs15awe45SRb83D6wH4ew6wlQ=="],
+
+ "data-view-byte-offset": ["data-view-byte-offset@1.0.1", "", { "dependencies": { "call-bound": "^1.0.2", "es-errors": "^1.3.0", "is-data-view": "^1.0.1" } }, "sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ=="],
+
+ "dateformat": ["dateformat@4.6.3", "", {}, "sha512-2P0p0pFGzHS5EMnhdxQi7aJN+iMheud0UhG4dlE1DLAlvL8JHjJJTX/CSm4JXwV0Ka5nGk3zC5mcb5bUQUxxMA=="],
+
+ "dayjs": ["dayjs@1.11.20", "", {}, "sha512-YbwwqR/uYpeoP4pu043q+LTDLFBLApUP6VxRihdfNTqu4ubqMlGDLd6ErXhEgsyvY0K6nCs7nggYumAN+9uEuQ=="],
+
+ "debug": ["debug@4.4.3", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA=="],
+
+ "decimal.js": ["decimal.js@10.6.0", "", {}, "sha512-YpgQiITW3JXGntzdUmyUR1V812Hn8T1YVXhCu+wO3OpS4eU9l4YdD3qjyiKdV6mvV29zapkMeD390UVEf2lkUg=="],
+
+ "decimal.js-light": ["decimal.js-light@2.5.1", "", {}, "sha512-qIMFpTMZmny+MMIitAB6D7iVPEorVw6YQRWkvarTkT4tBeSLLiHzcwj6q0MmYSFCiVpiqPJTJEYIrpcPzVEIvg=="],
+
+ "decode-named-character-reference": ["decode-named-character-reference@1.3.0", "", { "dependencies": { "character-entities": "^2.0.0" } }, "sha512-GtpQYB283KrPp6nRw50q3U9/VfOutZOe103qlN7BPP6Ad27xYnOIWv4lPzo8HCAL+mMZofJ9KEy30fq6MfaK6Q=="],
+
+ "decode-uri-component": ["decode-uri-component@0.4.1", "", {}, "sha512-+8VxcR21HhTy8nOt6jf20w0c9CADrw1O8d+VZ/YzzCt4bJ3uBjw+D1q2osAB8RnpwwaeYBxy0HyKQxD5JBMuuQ=="],
+
+ "decompress-response": ["decompress-response@6.0.0", "", { "dependencies": { "mimic-response": "^3.1.0" } }, "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ=="],
+
+ "deep-extend": ["deep-extend@0.6.0", "", {}, "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA=="],
+
+ "deep-is": ["deep-is@0.1.4", "", {}, "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ=="],
+
+ "default-browser": ["default-browser@5.5.0", "", { "dependencies": { "bundle-name": "^4.1.0", "default-browser-id": "^5.0.0" } }, "sha512-H9LMLr5zwIbSxrmvikGuI/5KGhZ8E2zH3stkMgM5LpOWDutGM2JZaj460Udnf1a+946zc7YBgrqEWwbk7zHvGw=="],
+
+ "default-browser-id": ["default-browser-id@5.0.1", "", {}, "sha512-x1VCxdX4t+8wVfd1so/9w+vQ4vx7lKd2Qp5tDRutErwmR85OgmfX7RlLRMWafRMY7hbEiXIbudNrjOAPa/hL8Q=="],
+
+ "define-data-property": ["define-data-property@1.1.4", "", { "dependencies": { "es-define-property": "^1.0.0", "es-errors": "^1.3.0", "gopd": "^1.0.1" } }, "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A=="],
+
+ "define-lazy-prop": ["define-lazy-prop@3.0.0", "", {}, "sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg=="],
+
+ "define-properties": ["define-properties@1.2.1", "", { "dependencies": { "define-data-property": "^1.0.1", "has-property-descriptors": "^1.0.0", "object-keys": "^1.1.1" } }, "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg=="],
+
+ "delaunator": ["delaunator@5.1.0", "", { "dependencies": { "robust-predicates": "^3.0.2" } }, "sha512-AGrQ4QSgssa1NGmWmLPqN5NY2KajF5MqxetNEO+o0n3ZwZZeTmt7bBnvzHWrmkZFxGgr4HdyFgelzgi06otLuQ=="],
+
+ "delayed-stream": ["delayed-stream@1.0.0", "", {}, "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ=="],
+
+ "depd": ["depd@2.0.0", "", {}, "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw=="],
+
+ "dequal": ["dequal@2.0.3", "", {}, "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA=="],
+
+ "detect-libc": ["detect-libc@2.1.2", "", {}, "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ=="],
+
+ "devlop": ["devlop@1.1.0", "", { "dependencies": { "dequal": "^2.0.0" } }, "sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA=="],
+
+ "diff": ["diff@8.0.3", "", {}, "sha512-qejHi7bcSD4hQAZE0tNAawRK1ZtafHDmMTMkrrIGgSLl7hTnQHmKCeB45xAcbfTqK2zowkM3j3bHt/4b/ARbYQ=="],
+
+ "doctrine": ["doctrine@2.1.0", "", { "dependencies": { "esutils": "^2.0.2" } }, "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw=="],
+
+ "dom-accessibility-api": ["dom-accessibility-api@0.6.3", "", {}, "sha512-7ZgogeTnjuHbo+ct10G9Ffp0mif17idi0IyWNVA/wcwcm7NPOD/WEHVP3n7n3MhXqxoIYm8d6MuZohYWIZ4T3w=="],
+
+ "dompurify": ["dompurify@3.3.3", "", { "optionalDependencies": { "@types/trusted-types": "^2.0.7" } }, "sha512-Oj6pzI2+RqBfFG+qOaOLbFXLQ90ARpcGG6UePL82bJLtdsa6CYJD7nmiU8MW9nQNOtCHV3lZ/Bzq1X0QYbBZCA=="],
+
+ "dunder-proto": ["dunder-proto@1.0.1", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.1", "es-errors": "^1.3.0", "gopd": "^1.2.0" } }, "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A=="],
+
+ "ee-first": ["ee-first@1.1.1", "", {}, "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow=="],
+
+ "electron-to-chromium": ["electron-to-chromium@1.5.286", "", {}, "sha512-9tfDXhJ4RKFNerfjdCcZfufu49vg620741MNs26a9+bhLThdB+plgMeou98CAaHu/WATj2iHOOHTp1hWtABj2A=="],
+
+ "emoji-mart": ["emoji-mart@5.6.0", "", {}, "sha512-eJp3QRe79pjwa+duv+n7+5YsNhRcMl812EcFVwrnRvYKoNPoQb5qxU8DG6Bgwji0akHdp6D4Ln6tYLG58MFSow=="],
+
+ "emoji-regex": ["emoji-regex@9.2.2", "", {}, "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg=="],
+
+ "encodeurl": ["encodeurl@2.0.0", "", {}, "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg=="],
+
+ "end-of-stream": ["end-of-stream@1.4.5", "", { "dependencies": { "once": "^1.4.0" } }, "sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg=="],
+
+ "enhanced-resolve": ["enhanced-resolve@5.19.0", "", { "dependencies": { "graceful-fs": "^4.2.4", "tapable": "^2.3.0" } }, "sha512-phv3E1Xl4tQOShqSte26C7Fl84EwUdZsyOuSSk9qtAGyyQs2s3jJzComh+Abf4g187lUUAvH+H26omrqia2aGg=="],
+
+ "entities": ["entities@6.0.1", "", {}, "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g=="],
+
+ "environment": ["environment@1.1.0", "", {}, "sha512-xUtoPkMggbz0MPyPiIWr1Kp4aeWJjDZ6SMvURhimjdZgsRuDplF5/s9hcgGhyXMhs+6vpnuoiZ2kFiu3FMnS8Q=="],
+
+ "error-ex": ["error-ex@1.3.4", "", { "dependencies": { "is-arrayish": "^0.2.1" } }, "sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ=="],
+
+ "es-abstract": ["es-abstract@1.24.1", "", { "dependencies": { "array-buffer-byte-length": "^1.0.2", "arraybuffer.prototype.slice": "^1.0.4", "available-typed-arrays": "^1.0.7", "call-bind": "^1.0.8", "call-bound": "^1.0.4", "data-view-buffer": "^1.0.2", "data-view-byte-length": "^1.0.2", "data-view-byte-offset": "^1.0.1", "es-define-property": "^1.0.1", "es-errors": "^1.3.0", "es-object-atoms": "^1.1.1", "es-set-tostringtag": "^2.1.0", "es-to-primitive": "^1.3.0", "function.prototype.name": "^1.1.8", "get-intrinsic": "^1.3.0", "get-proto": "^1.0.1", "get-symbol-description": "^1.1.0", "globalthis": "^1.0.4", "gopd": "^1.2.0", "has-property-descriptors": "^1.0.2", "has-proto": "^1.2.0", "has-symbols": "^1.1.0", "hasown": "^2.0.2", "internal-slot": "^1.1.0", "is-array-buffer": "^3.0.5", "is-callable": "^1.2.7", "is-data-view": "^1.0.2", "is-negative-zero": "^2.0.3", "is-regex": "^1.2.1", "is-set": "^2.0.3", "is-shared-array-buffer": "^1.0.4", "is-string": "^1.1.1", "is-typed-array": "^1.1.15", "is-weakref": "^1.1.1", "math-intrinsics": "^1.1.0", "object-inspect": "^1.13.4", "object-keys": "^1.1.1", "object.assign": "^4.1.7", "own-keys": "^1.0.1", "regexp.prototype.flags": "^1.5.4", "safe-array-concat": "^1.1.3", "safe-push-apply": "^1.0.0", "safe-regex-test": "^1.1.0", "set-proto": "^1.0.0", "stop-iteration-iterator": "^1.1.0", "string.prototype.trim": "^1.2.10", "string.prototype.trimend": "^1.0.9", "string.prototype.trimstart": "^1.0.8", "typed-array-buffer": "^1.0.3", "typed-array-byte-length": "^1.0.3", "typed-array-byte-offset": "^1.0.4", "typed-array-length": "^1.0.7", "unbox-primitive": "^1.1.0", "which-typed-array": "^1.1.19" } }, "sha512-zHXBLhP+QehSSbsS9Pt23Gg964240DPd6QCf8WpkqEXxQ7fhdZzYsocOr5u7apWonsS5EjZDmTF+/slGMyasvw=="],
+
+ "es-define-property": ["es-define-property@1.0.1", "", {}, "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g=="],
+
+ "es-errors": ["es-errors@1.3.0", "", {}, "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw=="],
+
+ "es-iterator-helpers": ["es-iterator-helpers@1.2.2", "", { "dependencies": { "call-bind": "^1.0.8", "call-bound": "^1.0.4", "define-properties": "^1.2.1", "es-abstract": "^1.24.1", "es-errors": "^1.3.0", "es-set-tostringtag": "^2.1.0", "function-bind": "^1.1.2", "get-intrinsic": "^1.3.0", "globalthis": "^1.0.4", "gopd": "^1.2.0", "has-property-descriptors": "^1.0.2", "has-proto": "^1.2.0", "has-symbols": "^1.1.0", "internal-slot": "^1.1.0", "iterator.prototype": "^1.1.5", "safe-array-concat": "^1.1.3" } }, "sha512-BrUQ0cPTB/IwXj23HtwHjS9n7O4h9FX94b4xc5zlTHxeLgTAdzYUDyy6KdExAl9lbN5rtfe44xpjpmj9grxs5w=="],
+
+ "es-module-lexer": ["es-module-lexer@2.0.0", "", {}, "sha512-5POEcUuZybH7IdmGsD8wlf0AI55wMecM9rVBTI/qEAy2c1kTOm3DjFYjrBdI2K3BaJjJYfYFeRtM0t9ssnRuxw=="],
+
+ "es-object-atoms": ["es-object-atoms@1.1.1", "", { "dependencies": { "es-errors": "^1.3.0" } }, "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA=="],
+
+ "es-set-tostringtag": ["es-set-tostringtag@2.1.0", "", { "dependencies": { "es-errors": "^1.3.0", "get-intrinsic": "^1.2.6", "has-tostringtag": "^1.0.2", "hasown": "^2.0.2" } }, "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA=="],
+
+ "es-shim-unscopables": ["es-shim-unscopables@1.1.0", "", { "dependencies": { "hasown": "^2.0.2" } }, "sha512-d9T8ucsEhh8Bi1woXCf+TIKDIROLG5WCkxg8geBCbvk22kzwC5G2OnXVMO6FUsvQlgUUXQ2itephWDLqDzbeCw=="],
+
+ "es-to-primitive": ["es-to-primitive@1.3.0", "", { "dependencies": { "is-callable": "^1.2.7", "is-date-object": "^1.0.5", "is-symbol": "^1.0.4" } }, "sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g=="],
+
+ "es-toolkit": ["es-toolkit@1.44.0", "", {}, "sha512-6penXeZalaV88MM3cGkFZZfOoLGWshWWfdy0tWw/RlVVyhvMaWSBTOvXNeiW3e5FwdS5ePW0LGEu17zT139ktg=="],
+
+ "esast-util-from-estree": ["esast-util-from-estree@2.0.0", "", { "dependencies": { "@types/estree-jsx": "^1.0.0", "devlop": "^1.0.0", "estree-util-visit": "^2.0.0", "unist-util-position-from-estree": "^2.0.0" } }, "sha512-4CyanoAudUSBAn5K13H4JhsMH6L9ZP7XbLVe/dKybkxMO7eDyLsT8UHl9TRNrU2Gr9nz+FovfSIjuXWJ81uVwQ=="],
+
+ "esast-util-from-js": ["esast-util-from-js@2.0.1", "", { "dependencies": { "@types/estree-jsx": "^1.0.0", "acorn": "^8.0.0", "esast-util-from-estree": "^2.0.0", "vfile-message": "^4.0.0" } }, "sha512-8Ja+rNJ0Lt56Pcf3TAmpBZjmx8ZcK5Ts4cAzIOjsjevg9oSXJnl6SUQ2EevU8tv3h6ZLWmoKL5H4fgWvdvfETw=="],
+
+ "esbuild": ["esbuild@0.27.3", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.27.3", "@esbuild/android-arm": "0.27.3", "@esbuild/android-arm64": "0.27.3", "@esbuild/android-x64": "0.27.3", "@esbuild/darwin-arm64": "0.27.3", "@esbuild/darwin-x64": "0.27.3", "@esbuild/freebsd-arm64": "0.27.3", "@esbuild/freebsd-x64": "0.27.3", "@esbuild/linux-arm": "0.27.3", "@esbuild/linux-arm64": "0.27.3", "@esbuild/linux-ia32": "0.27.3", "@esbuild/linux-loong64": "0.27.3", "@esbuild/linux-mips64el": "0.27.3", "@esbuild/linux-ppc64": "0.27.3", "@esbuild/linux-riscv64": "0.27.3", "@esbuild/linux-s390x": "0.27.3", "@esbuild/linux-x64": "0.27.3", "@esbuild/netbsd-arm64": "0.27.3", "@esbuild/netbsd-x64": "0.27.3", "@esbuild/openbsd-arm64": "0.27.3", "@esbuild/openbsd-x64": "0.27.3", "@esbuild/openharmony-arm64": "0.27.3", "@esbuild/sunos-x64": "0.27.3", "@esbuild/win32-arm64": "0.27.3", "@esbuild/win32-ia32": "0.27.3", "@esbuild/win32-x64": "0.27.3" }, "bin": "bin/esbuild" }, "sha512-8VwMnyGCONIs6cWue2IdpHxHnAjzxnw2Zr7MkVxB2vjmQ2ivqGFb4LEG3SMnv0Gb2F/G/2yA8zUaiL1gywDCCg=="],
+
+ "escalade": ["escalade@3.2.0", "", {}, "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA=="],
+
+ "escape-html": ["escape-html@1.0.3", "", {}, "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow=="],
+
+ "escape-string-regexp": ["escape-string-regexp@4.0.0", "", {}, "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA=="],
+
+ "eslint": ["eslint@9.39.4", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.8.0", "@eslint-community/regexpp": "^4.12.1", "@eslint/config-array": "^0.21.2", "@eslint/config-helpers": "^0.4.2", "@eslint/core": "^0.17.0", "@eslint/eslintrc": "^3.3.5", "@eslint/js": "9.39.4", "@eslint/plugin-kit": "^0.4.1", "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", "@humanwhocodes/retry": "^0.4.2", "@types/estree": "^1.0.6", "ajv": "^6.14.0", "chalk": "^4.0.0", "cross-spawn": "^7.0.6", "debug": "^4.3.2", "escape-string-regexp": "^4.0.0", "eslint-scope": "^8.4.0", "eslint-visitor-keys": "^4.2.1", "espree": "^10.4.0", "esquery": "^1.5.0", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", "file-entry-cache": "^8.0.0", "find-up": "^5.0.0", "glob-parent": "^6.0.2", "ignore": "^5.2.0", "imurmurhash": "^0.1.4", "is-glob": "^4.0.0", "json-stable-stringify-without-jsonify": "^1.0.1", "lodash.merge": "^4.6.2", "minimatch": "^3.1.5", "natural-compare": "^1.4.0", "optionator": "^0.9.3" }, "peerDependencies": { "jiti": "*" }, "bin": "bin/eslint.js" }, "sha512-XoMjdBOwe/esVgEvLmNsD3IRHkm7fbKIUGvrleloJXUZgDHig2IPWNniv+GwjyJXzuNqVjlr5+4yVUZjycJwfQ=="],
+
+ "eslint-config-next": ["eslint-config-next@16.1.6", "", { "dependencies": { "@next/eslint-plugin-next": "16.1.6", "eslint-import-resolver-node": "^0.3.6", "eslint-import-resolver-typescript": "^3.5.2", "eslint-plugin-import": "^2.32.0", "eslint-plugin-jsx-a11y": "^6.10.0", "eslint-plugin-react": "^7.37.0", "eslint-plugin-react-hooks": "^7.0.0", "globals": "16.4.0", "typescript-eslint": "^8.46.0" }, "peerDependencies": { "eslint": ">=9.0.0", "typescript": ">=3.3.1" } }, "sha512-vKq40io2B0XtkkNDYyleATwblNt8xuh3FWp8SpSz3pt7P01OkBFlKsJZ2mWt5WsCySlDQLckb1zMY9yE9Qy0LA=="],
+
+ "eslint-import-resolver-node": ["eslint-import-resolver-node@0.3.9", "", { "dependencies": { "debug": "^3.2.7", "is-core-module": "^2.13.0", "resolve": "^1.22.4" } }, "sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g=="],
+
+ "eslint-import-resolver-typescript": ["eslint-import-resolver-typescript@3.10.1", "", { "dependencies": { "@nolyfill/is-core-module": "1.0.39", "debug": "^4.4.0", "get-tsconfig": "^4.10.0", "is-bun-module": "^2.0.0", "stable-hash": "^0.0.5", "tinyglobby": "^0.2.13", "unrs-resolver": "^1.6.2" }, "peerDependencies": { "eslint": "*", "eslint-plugin-import": "*", "eslint-plugin-import-x": "*" }, "optionalPeers": ["eslint-plugin-import-x"] }, "sha512-A1rHYb06zjMGAxdLSkN2fXPBwuSaQ0iO5M/hdyS0Ajj1VBaRp0sPD3dn1FhME3c/JluGFbwSxyCfqdSbtQLAHQ=="],
+
+ "eslint-module-utils": ["eslint-module-utils@2.12.1", "", { "dependencies": { "debug": "^3.2.7" } }, "sha512-L8jSWTze7K2mTg0vos/RuLRS5soomksDPoJLXIslC7c8Wmut3bx7CPpJijDcBZtxQ5lrbUdM+s0OlNbz0DCDNw=="],
+
+ "eslint-plugin-import": ["eslint-plugin-import@2.32.0", "", { "dependencies": { "@rtsao/scc": "^1.1.0", "array-includes": "^3.1.9", "array.prototype.findlastindex": "^1.2.6", "array.prototype.flat": "^1.3.3", "array.prototype.flatmap": "^1.3.3", "debug": "^3.2.7", "doctrine": "^2.1.0", "eslint-import-resolver-node": "^0.3.9", "eslint-module-utils": "^2.12.1", "hasown": "^2.0.2", "is-core-module": "^2.16.1", "is-glob": "^4.0.3", "minimatch": "^3.1.2", "object.fromentries": "^2.0.8", "object.groupby": "^1.0.3", "object.values": "^1.2.1", "semver": "^6.3.1", "string.prototype.trimend": "^1.0.9", "tsconfig-paths": "^3.15.0" }, "peerDependencies": { "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 || ^9" } }, "sha512-whOE1HFo/qJDyX4SnXzP4N6zOWn79WhnCUY/iDR0mPfQZO8wcYE4JClzI2oZrhBnnMUCBCHZhO6VQyoBU95mZA=="],
+
+ "eslint-plugin-jsx-a11y": ["eslint-plugin-jsx-a11y@6.10.2", "", { "dependencies": { "aria-query": "^5.3.2", "array-includes": "^3.1.8", "array.prototype.flatmap": "^1.3.2", "ast-types-flow": "^0.0.8", "axe-core": "^4.10.0", "axobject-query": "^4.1.0", "damerau-levenshtein": "^1.0.8", "emoji-regex": "^9.2.2", "hasown": "^2.0.2", "jsx-ast-utils": "^3.3.5", "language-tags": "^1.0.9", "minimatch": "^3.1.2", "object.fromentries": "^2.0.8", "safe-regex-test": "^1.0.3", "string.prototype.includes": "^2.0.1" }, "peerDependencies": { "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9" } }, "sha512-scB3nz4WmG75pV8+3eRUQOHZlNSUhFNq37xnpgRkCCELU3XMvXAxLk1eqWWyE22Ki4Q01Fnsw9BA3cJHDPgn2Q=="],
+
+ "eslint-plugin-react": ["eslint-plugin-react@7.37.5", "", { "dependencies": { "array-includes": "^3.1.8", "array.prototype.findlast": "^1.2.5", "array.prototype.flatmap": "^1.3.3", "array.prototype.tosorted": "^1.1.4", "doctrine": "^2.1.0", "es-iterator-helpers": "^1.2.1", "estraverse": "^5.3.0", "hasown": "^2.0.2", "jsx-ast-utils": "^2.4.1 || ^3.0.0", "minimatch": "^3.1.2", "object.entries": "^1.1.9", "object.fromentries": "^2.0.8", "object.values": "^1.2.1", "prop-types": "^15.8.1", "resolve": "^2.0.0-next.5", "semver": "^6.3.1", "string.prototype.matchall": "^4.0.12", "string.prototype.repeat": "^1.0.0" }, "peerDependencies": { "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9.7" } }, "sha512-Qteup0SqU15kdocexFNAJMvCJEfa2xUKNV4CC1xsVMrIIqEy3SQ/rqyxCWNzfrd3/ldy6HMlD2e0JDVpDg2qIA=="],
+
+ "eslint-plugin-react-hooks": ["eslint-plugin-react-hooks@7.0.1", "", { "dependencies": { "@babel/core": "^7.24.4", "@babel/parser": "^7.24.4", "hermes-parser": "^0.25.1", "zod": "^3.25.0 || ^4.0.0", "zod-validation-error": "^3.5.0 || ^4.0.0" }, "peerDependencies": { "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0" } }, "sha512-O0d0m04evaNzEPoSW+59Mezf8Qt0InfgGIBJnpC0h3NH/WjUAR7BIKUfysC6todmtiZ/A0oUVS8Gce0WhBrHsA=="],
+
+ "eslint-scope": ["eslint-scope@8.4.0", "", { "dependencies": { "esrecurse": "^4.3.0", "estraverse": "^5.2.0" } }, "sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg=="],
+
+ "eslint-visitor-keys": ["eslint-visitor-keys@4.2.1", "", {}, "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ=="],
+
+ "espree": ["espree@10.4.0", "", { "dependencies": { "acorn": "^8.15.0", "acorn-jsx": "^5.3.2", "eslint-visitor-keys": "^4.2.1" } }, "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ=="],
+
+ "esquery": ["esquery@1.7.0", "", { "dependencies": { "estraverse": "^5.1.0" } }, "sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g=="],
+
+ "esrecurse": ["esrecurse@4.3.0", "", { "dependencies": { "estraverse": "^5.2.0" } }, "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag=="],
+
+ "estraverse": ["estraverse@5.3.0", "", {}, "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA=="],
+
+ "estree-util-attach-comments": ["estree-util-attach-comments@3.0.0", "", { "dependencies": { "@types/estree": "^1.0.0" } }, "sha512-cKUwm/HUcTDsYh/9FgnuFqpfquUbwIqwKM26BVCGDPVgvaCl/nDCCjUfiLlx6lsEZ3Z4RFxNbOQ60pkaEwFxGw=="],
+
+ "estree-util-build-jsx": ["estree-util-build-jsx@3.0.1", "", { "dependencies": { "@types/estree-jsx": "^1.0.0", "devlop": "^1.0.0", "estree-util-is-identifier-name": "^3.0.0", "estree-walker": "^3.0.0" } }, "sha512-8U5eiL6BTrPxp/CHbs2yMgP8ftMhR5ww1eIKoWRMlqvltHF8fZn5LRDvTKuxD3DUn+shRbLGqXemcP51oFCsGQ=="],
+
+ "estree-util-is-identifier-name": ["estree-util-is-identifier-name@3.0.0", "", {}, "sha512-hFtqIDZTIUZ9BXLb8y4pYGyk6+wekIivNVTcmvk8NoOh+VeRn5y6cEHzbURrWbfp1fIqdVipilzj+lfaadNZmg=="],
+
+ "estree-util-scope": ["estree-util-scope@1.0.0", "", { "dependencies": { "@types/estree": "^1.0.0", "devlop": "^1.0.0" } }, "sha512-2CAASclonf+JFWBNJPndcOpA8EMJwa0Q8LUFJEKqXLW6+qBvbFZuF5gItbQOs/umBUkjviCSDCbBwU2cXbmrhQ=="],
+
+ "estree-util-to-js": ["estree-util-to-js@2.0.0", "", { "dependencies": { "@types/estree-jsx": "^1.0.0", "astring": "^1.8.0", "source-map": "^0.7.0" } }, "sha512-WDF+xj5rRWmD5tj6bIqRi6CkLIXbbNQUcxQHzGysQzvHmdYG2G7p/Tf0J0gpxGgkeMZNTIjT/AoSvC9Xehcgdg=="],
+
+ "estree-util-visit": ["estree-util-visit@2.0.0", "", { "dependencies": { "@types/estree-jsx": "^1.0.0", "@types/unist": "^3.0.0" } }, "sha512-m5KgiH85xAhhW8Wta0vShLcUvOsh3LLPI2YVwcbio1l7E09NTLL1EyMZFM1OyWowoH0skScNbhOPl4kcBgzTww=="],
+
+ "estree-walker": ["estree-walker@3.0.3", "", { "dependencies": { "@types/estree": "^1.0.0" } }, "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g=="],
+
+ "esutils": ["esutils@2.0.3", "", {}, "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g=="],
+
+ "etag": ["etag@1.8.1", "", {}, "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg=="],
+
+ "eventemitter3": ["eventemitter3@5.0.4", "", {}, "sha512-mlsTRyGaPBjPedk6Bvw+aqbsXDtoAyAzm5MO7JgU+yVRyMQ5O8bD4Kcci7BS85f93veegeCPkL8R4GLClnjLFw=="],
+
+ "eventsource": ["eventsource@3.0.7", "", { "dependencies": { "eventsource-parser": "^3.0.1" } }, "sha512-CRT1WTyuQoD771GW56XEZFQ/ZoSfWid1alKGDYMmkt2yl8UXrVR4pspqWNEcqKvVIzg6PAltWjxcSSPrboA4iA=="],
+
+ "eventsource-parser": ["eventsource-parser@3.0.6", "", {}, "sha512-Vo1ab+QXPzZ4tCa8SwIHJFaSzy4R6SHf7BY79rFBDf0idraZWAkYrDjDj8uWaSm3S2TK+hJ7/t1CEmZ7jXw+pg=="],
+
+ "expand-template": ["expand-template@2.0.3", "", {}, "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg=="],
+
+ "expect-type": ["expect-type@1.3.0", "", {}, "sha512-knvyeauYhqjOYvQ66MznSMs83wmHrCycNEN6Ao+2AeYEfxUIkuiVxdEa1qlGEPK+We3n0THiDciYSsCcgW/DoA=="],
+
+ "express": ["express@5.2.1", "", { "dependencies": { "accepts": "^2.0.0", "body-parser": "^2.2.1", "content-disposition": "^1.0.0", "content-type": "^1.0.5", "cookie": "^0.7.1", "cookie-signature": "^1.2.1", "debug": "^4.4.0", "depd": "^2.0.0", "encodeurl": "^2.0.0", "escape-html": "^1.0.3", "etag": "^1.8.1", "finalhandler": "^2.1.0", "fresh": "^2.0.0", "http-errors": "^2.0.0", "merge-descriptors": "^2.0.0", "mime-types": "^3.0.0", "on-finished": "^2.4.1", "once": "^1.4.0", "parseurl": "^1.3.3", "proxy-addr": "^2.0.7", "qs": "^6.14.0", "range-parser": "^1.2.1", "router": "^2.2.0", "send": "^1.1.0", "serve-static": "^2.2.0", "statuses": "^2.0.1", "type-is": "^2.0.1", "vary": "^1.1.2" } }, "sha512-hIS4idWWai69NezIdRt2xFVofaF4j+6INOpJlVOLDO8zXGpUVEVzIYk12UUi2JzjEzWL3IOAxcTubgz9Po0yXw=="],
+
+ "express-rate-limit": ["express-rate-limit@8.3.0", "", { "dependencies": { "ip-address": "10.1.0" }, "peerDependencies": { "express": ">= 4.11" } }, "sha512-KJzBawY6fB9FiZGdE/0aftepZ91YlaGIrV8vgblRM3J8X+dHx/aiowJWwkx6LIGyuqGiANsjSwwrbb8mifOJ4Q=="],
+
+ "extend": ["extend@3.0.2", "", {}, "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g=="],
+
+ "extend-shallow": ["extend-shallow@2.0.1", "", { "dependencies": { "is-extendable": "^0.1.0" } }, "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug=="],
+
+ "fast-copy": ["fast-copy@4.0.2", "", {}, "sha512-ybA6PDXIXOXivLJK/z9e+Otk7ve13I4ckBvGO5I2RRmBU1gMHLVDJYEuJYhGwez7YNlYji2M2DvVU+a9mSFDlw=="],
+
+ "fast-deep-equal": ["fast-deep-equal@3.1.3", "", {}, "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="],
+
+ "fast-glob": ["fast-glob@3.3.1", "", { "dependencies": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", "glob-parent": "^5.1.2", "merge2": "^1.3.0", "micromatch": "^4.0.4" } }, "sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg=="],
+
+ "fast-json-stable-stringify": ["fast-json-stable-stringify@2.1.0", "", {}, "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw=="],
+
+ "fast-levenshtein": ["fast-levenshtein@2.0.6", "", {}, "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw=="],
+
+ "fast-safe-stringify": ["fast-safe-stringify@2.1.1", "", {}, "sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA=="],
+
+ "fast-uri": ["fast-uri@3.1.0", "", {}, "sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA=="],
+
+ "fastq": ["fastq@1.20.1", "", { "dependencies": { "reusify": "^1.0.4" } }, "sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw=="],
+
+ "fdir": ["fdir@6.5.0", "", { "peerDependencies": { "picomatch": "^3 || ^4" } }, "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg=="],
+
+ "fetch-socks": ["fetch-socks@1.3.2", "", { "dependencies": { "socks": "^2.8.2", "undici": ">=6" } }, "sha512-vkH5+Zgj2yEbU57Cei0iyLgTZ4OkEKJj56Xu3ViB5dpsl599JgEooQ3x6NVagIFRHWnWJ+7K0MO0aIV1TMgvnw=="],
+
+ "file-entry-cache": ["file-entry-cache@8.0.0", "", { "dependencies": { "flat-cache": "^4.0.0" } }, "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ=="],
+
+ "file-selector": ["file-selector@0.5.0", "", { "dependencies": { "tslib": "^2.0.3" } }, "sha512-s8KNnmIDTBoD0p9uJ9uD0XY38SCeBOtj0UMXyQSLg1Ypfrfj8+dAvwsLjYQkQ2GjhVtp2HrnF5cJzMhBjfD8HA=="],
+
+ "file-uri-to-path": ["file-uri-to-path@1.0.0", "", {}, "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw=="],
+
+ "fill-range": ["fill-range@7.1.1", "", { "dependencies": { "to-regex-range": "^5.0.1" } }, "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg=="],
+
+ "filter-obj": ["filter-obj@5.1.0", "", {}, "sha512-qWeTREPoT7I0bifpPUXtxkZJ1XJzxWtfoWWkdVGqa+eCr3SHW/Ocp89o8vLvbUuQnadybJpjOKu4V+RwO6sGng=="],
+
+ "finalhandler": ["finalhandler@2.1.1", "", { "dependencies": { "debug": "^4.4.0", "encodeurl": "^2.0.0", "escape-html": "^1.0.3", "on-finished": "^2.4.1", "parseurl": "^1.3.3", "statuses": "^2.0.1" } }, "sha512-S8KoZgRZN+a5rNwqTxlZZePjT/4cnm0ROV70LedRHZ0p8u9fRID0hJUZQpkKLzro8LfmC8sx23bY6tVNxv8pQA=="],
+
+ "find-root": ["find-root@1.1.0", "", {}, "sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng=="],
+
+ "find-up": ["find-up@5.0.0", "", { "dependencies": { "locate-path": "^6.0.0", "path-exists": "^4.0.0" } }, "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng=="],
+
+ "flat-cache": ["flat-cache@4.0.1", "", { "dependencies": { "flatted": "^3.2.9", "keyv": "^4.5.4" } }, "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw=="],
+
+ "flatted": ["flatted@3.4.2", "", {}, "sha512-PjDse7RzhcPkIJwy5t7KPWQSZ9cAbzQXcafsetQoD7sOJRQlGikNbx7yZp2OotDnJyrDcbyRq3Ttb18iYOqkxA=="],
+
+ "follow-redirects": ["follow-redirects@1.15.11", "", {}, "sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ=="],
+
+ "for-each": ["for-each@0.3.5", "", { "dependencies": { "is-callable": "^1.2.7" } }, "sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg=="],
+
+ "for-in": ["for-in@1.0.2", "", {}, "sha512-7EwmXrOjyL+ChxMhmG5lnW9MPt1aIeZEwKhQzoBUdTV0N3zuwWDZYVJatDvZ2OyzPUvdIAZDsCetk3coyMfcnQ=="],
+
+ "foreground-child": ["foreground-child@3.3.1", "", { "dependencies": { "cross-spawn": "^7.0.6", "signal-exit": "^4.0.1" } }, "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw=="],
+
+ "form-data": ["form-data@4.0.5", "", { "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", "es-set-tostringtag": "^2.1.0", "hasown": "^2.0.2", "mime-types": "^2.1.12" } }, "sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w=="],
+
+ "forwarded": ["forwarded@0.2.0", "", {}, "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow=="],
+
+ "framer-motion": ["framer-motion@12.38.0", "", { "dependencies": { "motion-dom": "^12.38.0", "motion-utils": "^12.36.0", "tslib": "^2.4.0" }, "peerDependencies": { "@emotion/is-prop-valid": "*", "react": "^18.0.0 || ^19.0.0", "react-dom": "^18.0.0 || ^19.0.0" } }, "sha512-rFYkY/pigbcswl1XQSb7q424kSTQ8q6eAC+YUsSKooHQYuLdzdHjrt6uxUC+PRAO++q5IS7+TamgIw1AphxR+g=="],
+
+ "fresh": ["fresh@2.0.0", "", {}, "sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A=="],
+
+ "fs-constants": ["fs-constants@1.0.0", "", {}, "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow=="],
+
+ "fsevents": ["fsevents@2.3.3", "", { "os": "darwin" }, "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw=="],
+
+ "function-bind": ["function-bind@1.1.2", "", {}, "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA=="],
+
+ "function.prototype.name": ["function.prototype.name@1.1.8", "", { "dependencies": { "call-bind": "^1.0.8", "call-bound": "^1.0.3", "define-properties": "^1.2.1", "functions-have-names": "^1.2.3", "hasown": "^2.0.2", "is-callable": "^1.2.7" } }, "sha512-e5iwyodOHhbMr/yNrc7fDYG4qlbIvI5gajyzPnb5TCwyhjApznQh1BMFou9b30SevY43gCJKXycoCBjMbsuW0Q=="],
+
+ "functions-have-names": ["functions-have-names@1.2.3", "", {}, "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ=="],
+
+ "generator-function": ["generator-function@2.0.1", "", {}, "sha512-SFdFmIJi+ybC0vjlHN0ZGVGHc3lgE0DxPAT0djjVg+kjOnSqclqmj0KQ7ykTOLP6YxoqOvuAODGdcHJn+43q3g=="],
+
+ "gensync": ["gensync@1.0.0-beta.2", "", {}, "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg=="],
+
+ "get-caller-file": ["get-caller-file@2.0.5", "", {}, "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg=="],
+
+ "get-east-asian-width": ["get-east-asian-width@1.4.0", "", {}, "sha512-QZjmEOC+IT1uk6Rx0sX22V6uHWVwbdbxf1faPqJ1QhLdGgsRGCZoyaQBm/piRdJy/D2um6hM1UP7ZEeQ4EkP+Q=="],
+
+ "get-intrinsic": ["get-intrinsic@1.3.0", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.2", "es-define-property": "^1.0.1", "es-errors": "^1.3.0", "es-object-atoms": "^1.1.1", "function-bind": "^1.1.2", "get-proto": "^1.0.1", "gopd": "^1.2.0", "has-symbols": "^1.1.0", "hasown": "^2.0.2", "math-intrinsics": "^1.1.0" } }, "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ=="],
+
+ "get-proto": ["get-proto@1.0.1", "", { "dependencies": { "dunder-proto": "^1.0.1", "es-object-atoms": "^1.0.0" } }, "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g=="],
+
+ "get-symbol-description": ["get-symbol-description@1.1.0", "", { "dependencies": { "call-bound": "^1.0.3", "es-errors": "^1.3.0", "get-intrinsic": "^1.2.6" } }, "sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg=="],
+
+ "get-tsconfig": ["get-tsconfig@4.13.6", "", { "dependencies": { "resolve-pkg-maps": "^1.0.0" } }, "sha512-shZT/QMiSHc/YBLxxOkMtgSid5HFoauqCE3/exfsEcwg1WkeqjG+V40yBbBrsD+jW2HDXcs28xOfcbm2jI8Ddw=="],
+
+ "get-value": ["get-value@2.0.6", "", {}, "sha512-Ln0UQDlxH1BapMu3GPtf7CuYNwRZf2gwCuPqbyG6pB8WfmFpzqcy4xtAaAMUhnNqjMKTiCPZG2oMT3YSx8U2NA=="],
+
+ "giscus": ["giscus@1.6.0", "", { "dependencies": { "lit": "^3.2.1" } }, "sha512-Zrsi8r4t1LVW950keaWcsURuZUQwUaMKjvJgTCY125vkW6OiEBkatE7ScJDbpqKHdZwb///7FVC21SE3iFK3PQ=="],
+
+ "github-from-package": ["github-from-package@0.0.0", "", {}, "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw=="],
+
+ "glob": ["glob@13.0.6", "", { "dependencies": { "minimatch": "^10.2.2", "minipass": "^7.1.3", "path-scurry": "^2.0.2" } }, "sha512-Wjlyrolmm8uDpm/ogGyXZXb1Z+Ca2B8NbJwqBVg0axK9GbBeoS7yGV6vjXnYdGm6X53iehEuxxbyiKp8QmN4Vw=="],
+
+ "glob-parent": ["glob-parent@6.0.2", "", { "dependencies": { "is-glob": "^4.0.3" } }, "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A=="],
+
+ "globals": ["globals@16.4.0", "", {}, "sha512-ob/2LcVVaVGCYN+r14cnwnoDPUufjiYgSqRhiFD0Q1iI4Odora5RE8Iv1D24hAz5oMophRGkGz+yuvQmmUMnMw=="],
+
+ "globalthis": ["globalthis@1.0.4", "", { "dependencies": { "define-properties": "^1.2.1", "gopd": "^1.0.1" } }, "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ=="],
+
+ "gopd": ["gopd@1.2.0", "", {}, "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg=="],
+
+ "graceful-fs": ["graceful-fs@4.2.11", "", {}, "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ=="],
+
+ "hachure-fill": ["hachure-fill@0.5.2", "", {}, "sha512-3GKBOn+m2LX9iq+JC1064cSFprJY4jL1jCXTcpnfER5HYE2l/4EfWSGzkPa/ZDBmYI0ZOEj5VHV/eKnPGkHuOg=="],
+
+ "has-bigints": ["has-bigints@1.1.0", "", {}, "sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg=="],
+
+ "has-flag": ["has-flag@4.0.0", "", {}, "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ=="],
+
+ "has-property-descriptors": ["has-property-descriptors@1.0.2", "", { "dependencies": { "es-define-property": "^1.0.0" } }, "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg=="],
+
+ "has-proto": ["has-proto@1.2.0", "", { "dependencies": { "dunder-proto": "^1.0.0" } }, "sha512-KIL7eQPfHQRC8+XluaIw7BHUwwqL19bQn4hzNgdr+1wXoU0KKj6rufu47lhY7KbJR2C6T6+PfyN0Ea7wkSS+qQ=="],
+
+ "has-symbols": ["has-symbols@1.1.0", "", {}, "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ=="],
+
+ "has-tostringtag": ["has-tostringtag@1.0.2", "", { "dependencies": { "has-symbols": "^1.0.3" } }, "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw=="],
+
+ "hasown": ["hasown@2.0.2", "", { "dependencies": { "function-bind": "^1.1.2" } }, "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ=="],
+
+ "hast-util-from-dom": ["hast-util-from-dom@5.0.1", "", { "dependencies": { "@types/hast": "^3.0.0", "hastscript": "^9.0.0", "web-namespaces": "^2.0.0" } }, "sha512-N+LqofjR2zuzTjCPzyDUdSshy4Ma6li7p/c3pA78uTwzFgENbgbUrm2ugwsOdcjI1muO+o6Dgzp9p8WHtn/39Q=="],
+
+ "hast-util-from-html": ["hast-util-from-html@2.0.3", "", { "dependencies": { "@types/hast": "^3.0.0", "devlop": "^1.1.0", "hast-util-from-parse5": "^8.0.0", "parse5": "^7.0.0", "vfile": "^6.0.0", "vfile-message": "^4.0.0" } }, "sha512-CUSRHXyKjzHov8yKsQjGOElXy/3EKpyX56ELnkHH34vDVw1N1XSQ1ZcAvTyAPtGqLTuKP/uxM+aLkSPqF/EtMw=="],
+
+ "hast-util-from-html-isomorphic": ["hast-util-from-html-isomorphic@2.0.0", "", { "dependencies": { "@types/hast": "^3.0.0", "hast-util-from-dom": "^5.0.0", "hast-util-from-html": "^2.0.0", "unist-util-remove-position": "^5.0.0" } }, "sha512-zJfpXq44yff2hmE0XmwEOzdWin5xwH+QIhMLOScpX91e/NSGPsAzNCvLQDIEPyO2TXi+lBmU6hjLIhV8MwP2kw=="],
+
+ "hast-util-from-parse5": ["hast-util-from-parse5@8.0.3", "", { "dependencies": { "@types/hast": "^3.0.0", "@types/unist": "^3.0.0", "devlop": "^1.0.0", "hastscript": "^9.0.0", "property-information": "^7.0.0", "vfile": "^6.0.0", "vfile-location": "^5.0.0", "web-namespaces": "^2.0.0" } }, "sha512-3kxEVkEKt0zvcZ3hCRYI8rqrgwtlIOFMWkbclACvjlDw8Li9S2hk/d51OI0nr/gIpdMHNepwgOKqZ/sy0Clpyg=="],
+
+ "hast-util-is-element": ["hast-util-is-element@3.0.0", "", { "dependencies": { "@types/hast": "^3.0.0" } }, "sha512-Val9mnv2IWpLbNPqc/pUem+a7Ipj2aHacCwgNfTiK0vJKl0LF+4Ba4+v1oPHFpf3bLYmreq0/l3Gud9S5OH42g=="],
+
+ "hast-util-parse-selector": ["hast-util-parse-selector@4.0.0", "", { "dependencies": { "@types/hast": "^3.0.0" } }, "sha512-wkQCkSYoOGCRKERFWcxMVMOcYE2K1AaNLU8DXS9arxnLOUEWbOXKXiJUNzEpqZ3JOKpnha3jkFrumEjVliDe7A=="],
+
+ "hast-util-raw": ["hast-util-raw@9.1.0", "", { "dependencies": { "@types/hast": "^3.0.0", "@types/unist": "^3.0.0", "@ungap/structured-clone": "^1.0.0", "hast-util-from-parse5": "^8.0.0", "hast-util-to-parse5": "^8.0.0", "html-void-elements": "^3.0.0", "mdast-util-to-hast": "^13.0.0", "parse5": "^7.0.0", "unist-util-position": "^5.0.0", "unist-util-visit": "^5.0.0", "vfile": "^6.0.0", "web-namespaces": "^2.0.0", "zwitch": "^2.0.0" } }, "sha512-Y8/SBAHkZGoNkpzqqfCldijcuUKh7/su31kEBp67cFY09Wy0mTRgtsLYsiIxMJxlu0f6AA5SUTbDR8K0rxnbUw=="],
+
+ "hast-util-to-estree": ["hast-util-to-estree@3.1.3", "", { "dependencies": { "@types/estree": "^1.0.0", "@types/estree-jsx": "^1.0.0", "@types/hast": "^3.0.0", "comma-separated-tokens": "^2.0.0", "devlop": "^1.0.0", "estree-util-attach-comments": "^3.0.0", "estree-util-is-identifier-name": "^3.0.0", "hast-util-whitespace": "^3.0.0", "mdast-util-mdx-expression": "^2.0.0", "mdast-util-mdx-jsx": "^3.0.0", "mdast-util-mdxjs-esm": "^2.0.0", "property-information": "^7.0.0", "space-separated-tokens": "^2.0.0", "style-to-js": "^1.0.0", "unist-util-position": "^5.0.0", "zwitch": "^2.0.0" } }, "sha512-48+B/rJWAp0jamNbAAf9M7Uf//UVqAoMmgXhBdxTDJLGKY+LRnZ99qcG+Qjl5HfMpYNzS5v4EAwVEF34LeAj7w=="],
+
+ "hast-util-to-html": ["hast-util-to-html@9.0.5", "", { "dependencies": { "@types/hast": "^3.0.0", "@types/unist": "^3.0.0", "ccount": "^2.0.0", "comma-separated-tokens": "^2.0.0", "hast-util-whitespace": "^3.0.0", "html-void-elements": "^3.0.0", "mdast-util-to-hast": "^13.0.0", "property-information": "^7.0.0", "space-separated-tokens": "^2.0.0", "stringify-entities": "^4.0.0", "zwitch": "^2.0.4" } }, "sha512-OguPdidb+fbHQSU4Q4ZiLKnzWo8Wwsf5bZfbvu7//a9oTYoqD/fWpe96NuHkoS9h0ccGOTe0C4NGXdtS0iObOw=="],
+
+ "hast-util-to-jsx-runtime": ["hast-util-to-jsx-runtime@2.3.6", "", { "dependencies": { "@types/estree": "^1.0.0", "@types/hast": "^3.0.0", "@types/unist": "^3.0.0", "comma-separated-tokens": "^2.0.0", "devlop": "^1.0.0", "estree-util-is-identifier-name": "^3.0.0", "hast-util-whitespace": "^3.0.0", "mdast-util-mdx-expression": "^2.0.0", "mdast-util-mdx-jsx": "^3.0.0", "mdast-util-mdxjs-esm": "^2.0.0", "property-information": "^7.0.0", "space-separated-tokens": "^2.0.0", "style-to-js": "^1.0.0", "unist-util-position": "^5.0.0", "vfile-message": "^4.0.0" } }, "sha512-zl6s8LwNyo1P9uw+XJGvZtdFF1GdAkOg8ujOw+4Pyb76874fLps4ueHXDhXWdk6YHQ6OgUtinliG7RsYvCbbBg=="],
+
+ "hast-util-to-parse5": ["hast-util-to-parse5@8.0.1", "", { "dependencies": { "@types/hast": "^3.0.0", "comma-separated-tokens": "^2.0.0", "devlop": "^1.0.0", "property-information": "^7.0.0", "space-separated-tokens": "^2.0.0", "web-namespaces": "^2.0.0", "zwitch": "^2.0.0" } }, "sha512-MlWT6Pjt4CG9lFCjiz4BH7l9wmrMkfkJYCxFwKQic8+RTZgWPuWxwAfjJElsXkex7DJjfSJsQIt931ilUgmwdA=="],
+
+ "hast-util-to-text": ["hast-util-to-text@4.0.2", "", { "dependencies": { "@types/hast": "^3.0.0", "@types/unist": "^3.0.0", "hast-util-is-element": "^3.0.0", "unist-util-find-after": "^5.0.0" } }, "sha512-KK6y/BN8lbaq654j7JgBydev7wuNMcID54lkRav1P0CaE1e47P72AWWPiGKXTJU271ooYzcvTAn/Zt0REnvc7A=="],
+
+ "hast-util-whitespace": ["hast-util-whitespace@3.0.0", "", { "dependencies": { "@types/hast": "^3.0.0" } }, "sha512-88JUN06ipLwsnv+dVn+OIYOvAuvBMy/Qoi6O7mQHxdPXpjy+Cd6xRkWwux7DKO+4sYILtLBRIKgsdpS2gQc7qw=="],
+
+ "hastscript": ["hastscript@9.0.1", "", { "dependencies": { "@types/hast": "^3.0.0", "comma-separated-tokens": "^2.0.0", "hast-util-parse-selector": "^4.0.0", "property-information": "^7.0.0", "space-separated-tokens": "^2.0.0" } }, "sha512-g7df9rMFX/SPi34tyGCyUBREQoKkapwdY/T04Qn9TDWfHhAYt4/I0gMVirzK5wEzeUqIjEB+LXC/ypb7Aqno5w=="],
+
+ "help-me": ["help-me@5.0.0", "", {}, "sha512-7xgomUX6ADmcYzFik0HzAxh/73YlKR9bmFzf51CZwR+b6YtzU2m0u49hQCqV6SvlqIqsaxovfwdvbnsw3b/zpg=="],
+
+ "hermes-estree": ["hermes-estree@0.25.1", "", {}, "sha512-0wUoCcLp+5Ev5pDW2OriHC2MJCbwLwuRx+gAqMTOkGKJJiBCLjtrvy4PWUGn6MIVefecRpzoOZ/UV6iGdOr+Cw=="],
+
+ "hermes-parser": ["hermes-parser@0.25.1", "", { "dependencies": { "hermes-estree": "0.25.1" } }, "sha512-6pEjquH3rqaI6cYAXYPcz9MS4rY6R4ngRgrgfDshRptUZIc3lw0MCIJIGDj9++mfySOuPTHB4nrSW99BCvOPIA=="],
+
+ "hoist-non-react-statics": ["hoist-non-react-statics@3.3.2", "", { "dependencies": { "react-is": "^16.7.0" } }, "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw=="],
+
+ "hono": ["hono@4.12.7", "", {}, "sha512-jq9l1DM0zVIvsm3lv9Nw9nlJnMNPOcAtsbsgiUhWcFzPE99Gvo6yRTlszSLLYacMeQ6quHD6hMfId8crVHvexw=="],
+
+ "html-encoding-sniffer": ["html-encoding-sniffer@6.0.0", "", { "dependencies": { "@exodus/bytes": "^1.6.0" } }, "sha512-CV9TW3Y3f8/wT0BRFc1/KAVQ3TUHiXmaAb6VW9vtiMFf7SLoMd1PdAc4W3KFOFETBJUb90KatHqlsZMWV+R9Gg=="],
+
+ "html-escaper": ["html-escaper@2.0.2", "", {}, "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg=="],
+
+ "html-url-attributes": ["html-url-attributes@3.0.1", "", {}, "sha512-ol6UPyBWqsrO6EJySPz2O7ZSr856WDrEzM5zMqp+FJJLGMW35cLYmmZnl0vztAZxRUoNZJFTCohfjuIJ8I4QBQ=="],
+
+ "html-void-elements": ["html-void-elements@3.0.0", "", {}, "sha512-bEqo66MRXsUGxWHV5IP0PUiAWwoEjba4VCzg0LjFJBpchPaTfyfCKTG6bc5F8ucKec3q5y6qOdGyYTSBEvhCrg=="],
+
+ "http-errors": ["http-errors@2.0.1", "", { "dependencies": { "depd": "~2.0.0", "inherits": "~2.0.4", "setprototypeof": "~1.2.0", "statuses": "~2.0.2", "toidentifier": "~1.0.1" } }, "sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ=="],
+
+ "http-proxy": ["http-proxy@1.18.1", "", { "dependencies": { "eventemitter3": "^4.0.0", "follow-redirects": "^1.0.0", "requires-port": "^1.0.0" } }, "sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ=="],
+
+ "http-proxy-middleware": ["http-proxy-middleware@3.0.5", "", { "dependencies": { "@types/http-proxy": "^1.17.15", "debug": "^4.3.6", "http-proxy": "^1.18.1", "is-glob": "^4.0.3", "is-plain-object": "^5.0.0", "micromatch": "^4.0.8" } }, "sha512-GLZZm1X38BPY4lkXA01jhwxvDoOkkXqjgVyUzVxiEK4iuRu03PZoYHhHRwxnfhQMDuaxi3vVri0YgSro/1oWqg=="],
+
+ "https-proxy-agent": ["https-proxy-agent@8.0.0", "", { "dependencies": { "agent-base": "8.0.0", "debug": "^4.3.4" } }, "sha512-YYeW+iCnAS3xhvj2dvVoWgsbca3RfQy/IlaNHHOtDmU0jMqPI9euIq3Y9BJETdxk16h9NHHCKqp/KB9nIMStCQ=="],
+
+ "husky": ["husky@9.1.7", "", { "bin": "bin.js" }, "sha512-5gs5ytaNjBrh5Ow3zrvdUUY+0VxIuWVL4i9irt6friV+BqdCfmV11CQTWMiBYWHbXhco+J1kHfTOUkePhCDvMA=="],
+
+ "iconv-lite": ["iconv-lite@0.7.2", "", { "dependencies": { "safer-buffer": ">= 2.1.2 < 3.0.0" } }, "sha512-im9DjEDQ55s9fL4EYzOAv0yMqmMBSZp6G0VvFyTMPKWxiSBHUj9NW/qqLmXUwXrrM7AvqSlTCfvqRb0cM8yYqw=="],
+
+ "icu-minify": ["icu-minify@4.8.3", "", { "dependencies": { "@formatjs/icu-messageformat-parser": "^3.4.0" } }, "sha512-65Av7FLosNk7bPbmQx5z5XG2Y3T2GFppcjiXh4z1idHeVgQxlDpAmkGoYI0eFzAvrOnjpWTL5FmPDhsdfRMPEA=="],
+
+ "ieee754": ["ieee754@1.2.1", "", {}, "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA=="],
+
+ "ignore": ["ignore@5.3.2", "", {}, "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g=="],
+
+ "immer": ["immer@10.2.0", "", {}, "sha512-d/+XTN3zfODyjr89gM3mPq1WNX2B8pYsu7eORitdwyA2sBubnTl3laYlBk4sXY5FUa5qTZGBDPJICVbvqzjlbw=="],
+
+ "import-fresh": ["import-fresh@3.3.1", "", { "dependencies": { "parent-module": "^1.0.0", "resolve-from": "^4.0.0" } }, "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ=="],
+
+ "imurmurhash": ["imurmurhash@0.1.4", "", {}, "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA=="],
+
+ "indent-string": ["indent-string@4.0.0", "", {}, "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg=="],
+
+ "inherits": ["inherits@2.0.4", "", {}, "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="],
+
+ "ini": ["ini@1.3.8", "", {}, "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew=="],
+
+ "inline-style-parser": ["inline-style-parser@0.2.7", "", {}, "sha512-Nb2ctOyNR8DqQoR0OwRG95uNWIC0C1lCgf5Naz5H6Ji72KZ8OcFZLz2P5sNgwlyoJ8Yif11oMuYs5pBQa86csA=="],
+
+ "internal-slot": ["internal-slot@1.1.0", "", { "dependencies": { "es-errors": "^1.3.0", "hasown": "^2.0.2", "side-channel": "^1.1.0" } }, "sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw=="],
+
+ "internmap": ["internmap@2.0.3", "", {}, "sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg=="],
+
+ "intersection-observer": ["intersection-observer@0.12.2", "", {}, "sha512-7m1vEcPCxXYI8HqnL8CKI6siDyD+eIWSwgB3DZA+ZTogxk9I4CDnj4wilt9x/+/QbHI4YG5YZNmC6458/e9Ktg=="],
+
+ "intl-messageformat": ["intl-messageformat@11.1.2", "", { "dependencies": { "@formatjs/ecma402-abstract": "3.1.1", "@formatjs/fast-memoize": "3.1.0", "@formatjs/icu-messageformat-parser": "3.5.1", "tslib": "^2.8.1" } }, "sha512-ucSrQmZGAxfiBHfBRXW/k7UC8MaGFlEj4Ry1tKiDcmgwQm1y3EDl40u+4VNHYomxJQMJi9NEI3riDRlth96jKg=="],
+
+ "ip-address": ["ip-address@10.1.0", "", {}, "sha512-XXADHxXmvT9+CRxhXg56LJovE+bmWnEWB78LB83VZTprKTmaC5QfruXocxzTZ2Kl0DNwKuBdlIhjL8LeY8Sf8Q=="],
+
+ "ipaddr.js": ["ipaddr.js@1.9.1", "", {}, "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g=="],
+
+ "is-alphabetical": ["is-alphabetical@2.0.1", "", {}, "sha512-FWyyY60MeTNyeSRpkM2Iry0G9hpr7/9kD40mD/cGQEuilcZYS4okz8SN2Q6rLCJ8gbCt6fN+rC+6tMGS99LaxQ=="],
+
+ "is-alphanumerical": ["is-alphanumerical@2.0.1", "", { "dependencies": { "is-alphabetical": "^2.0.0", "is-decimal": "^2.0.0" } }, "sha512-hmbYhX/9MUMF5uh7tOXyK/n0ZvWpad5caBA17GsC6vyuCqaWliRG5K1qS9inmUhEMaOBIW7/whAnSwveW/LtZw=="],
+
+ "is-array-buffer": ["is-array-buffer@3.0.5", "", { "dependencies": { "call-bind": "^1.0.8", "call-bound": "^1.0.3", "get-intrinsic": "^1.2.6" } }, "sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A=="],
+
+ "is-arrayish": ["is-arrayish@0.2.1", "", {}, "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg=="],
+
+ "is-async-function": ["is-async-function@2.1.1", "", { "dependencies": { "async-function": "^1.0.0", "call-bound": "^1.0.3", "get-proto": "^1.0.1", "has-tostringtag": "^1.0.2", "safe-regex-test": "^1.1.0" } }, "sha512-9dgM/cZBnNvjzaMYHVoxxfPj2QXt22Ev7SuuPrs+xav0ukGB0S6d4ydZdEiM48kLx5kDV+QBPrpVnFyefL8kkQ=="],
+
+ "is-bigint": ["is-bigint@1.1.0", "", { "dependencies": { "has-bigints": "^1.0.2" } }, "sha512-n4ZT37wG78iz03xPRKJrHTdZbe3IicyucEtdRsV5yglwc3GyUfbAfpSeD0FJ41NbUNSt5wbhqfp1fS+BgnvDFQ=="],
+
+ "is-boolean-object": ["is-boolean-object@1.2.2", "", { "dependencies": { "call-bound": "^1.0.3", "has-tostringtag": "^1.0.2" } }, "sha512-wa56o2/ElJMYqjCjGkXri7it5FbebW5usLw/nPmCMs5DeZ7eziSYZhSmPRn0txqeW4LnAmQQU7FgqLpsEFKM4A=="],
+
+ "is-bun-module": ["is-bun-module@2.0.0", "", { "dependencies": { "semver": "^7.7.1" } }, "sha512-gNCGbnnnnFAUGKeZ9PdbyeGYJqewpmc2aKHUEMO5nQPWU9lOmv7jcmQIv+qHD8fXW6W7qfuCwX4rY9LNRjXrkQ=="],
+
+ "is-callable": ["is-callable@1.2.7", "", {}, "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA=="],
+
+ "is-core-module": ["is-core-module@2.16.1", "", { "dependencies": { "hasown": "^2.0.2" } }, "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w=="],
+
+ "is-data-view": ["is-data-view@1.0.2", "", { "dependencies": { "call-bound": "^1.0.2", "get-intrinsic": "^1.2.6", "is-typed-array": "^1.1.13" } }, "sha512-RKtWF8pGmS87i2D6gqQu/l7EYRlVdfzemCJN/P3UOs//x1QE7mfhvzHIApBTRf7axvT6DMGwSwBXYCT0nfB9xw=="],
+
+ "is-date-object": ["is-date-object@1.1.0", "", { "dependencies": { "call-bound": "^1.0.2", "has-tostringtag": "^1.0.2" } }, "sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg=="],
+
+ "is-decimal": ["is-decimal@2.0.1", "", {}, "sha512-AAB9hiomQs5DXWcRB1rqsxGUstbRroFOPPVAomNk/3XHR5JyEZChOyTWe2oayKnsSsr/kcGqF+z6yuH6HHpN0A=="],
+
+ "is-docker": ["is-docker@3.0.0", "", { "bin": "cli.js" }, "sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ=="],
+
+ "is-extendable": ["is-extendable@1.0.1", "", { "dependencies": { "is-plain-object": "^2.0.4" } }, "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA=="],
+
+ "is-extglob": ["is-extglob@2.1.1", "", {}, "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ=="],
+
+ "is-finalizationregistry": ["is-finalizationregistry@1.1.1", "", { "dependencies": { "call-bound": "^1.0.3" } }, "sha512-1pC6N8qWJbWoPtEjgcL2xyhQOP491EQjeUo3qTKcmV8YSDDJrOepfG8pcC7h/QgnQHYSv0mJ3Z/ZWxmatVrysg=="],
+
+ "is-fullwidth-code-point": ["is-fullwidth-code-point@3.0.0", "", {}, "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg=="],
+
+ "is-generator-function": ["is-generator-function@1.1.2", "", { "dependencies": { "call-bound": "^1.0.4", "generator-function": "^2.0.0", "get-proto": "^1.0.1", "has-tostringtag": "^1.0.2", "safe-regex-test": "^1.1.0" } }, "sha512-upqt1SkGkODW9tsGNG5mtXTXtECizwtS2kA161M+gJPc1xdb/Ax629af6YrTwcOeQHbewrPNlE5Dx7kzvXTizA=="],
+
+ "is-glob": ["is-glob@4.0.3", "", { "dependencies": { "is-extglob": "^2.1.1" } }, "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg=="],
+
+ "is-hexadecimal": ["is-hexadecimal@2.0.1", "", {}, "sha512-DgZQp241c8oO6cA1SbTEWiXeoxV42vlcJxgH+B3hi1AiqqKruZR3ZGF8In3fj4+/y/7rHvlOZLZtgJ/4ttYGZg=="],
+
+ "is-in-ssh": ["is-in-ssh@1.0.0", "", {}, "sha512-jYa6Q9rH90kR1vKB6NM7qqd1mge3Fx4Dhw5TVlK1MUBqhEOuCagrEHMevNuCcbECmXZ0ThXkRm+Ymr51HwEPAw=="],
+
+ "is-inside-container": ["is-inside-container@1.0.0", "", { "dependencies": { "is-docker": "^3.0.0" }, "bin": "cli.js" }, "sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA=="],
+
+ "is-interactive": ["is-interactive@2.0.0", "", {}, "sha512-qP1vozQRI+BMOPcjFzrjXuQvdak2pHNUMZoeG2eRbiSqyvbEf/wQtEOTOX1guk6E3t36RkaqiSt8A/6YElNxLQ=="],
+
+ "is-map": ["is-map@2.0.3", "", {}, "sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw=="],
+
+ "is-mobile": ["is-mobile@5.0.0", "", {}, "sha512-Tz/yndySvLAEXh+Uk8liFCxOwVH6YutuR74utvOcu7I9Di+DwM0mtdPVZNaVvvBUM2OXxne/NhOs1zAO7riusQ=="],
+
+ "is-negative-zero": ["is-negative-zero@2.0.3", "", {}, "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw=="],
+
+ "is-number": ["is-number@7.0.0", "", {}, "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng=="],
+
+ "is-number-object": ["is-number-object@1.1.1", "", { "dependencies": { "call-bound": "^1.0.3", "has-tostringtag": "^1.0.2" } }, "sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw=="],
+
+ "is-plain-obj": ["is-plain-obj@4.1.0", "", {}, "sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg=="],
+
+ "is-plain-object": ["is-plain-object@5.0.0", "", {}, "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q=="],
+
+ "is-potential-custom-element-name": ["is-potential-custom-element-name@1.0.1", "", {}, "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ=="],
+
+ "is-promise": ["is-promise@4.0.0", "", {}, "sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ=="],
+
+ "is-regex": ["is-regex@1.2.1", "", { "dependencies": { "call-bound": "^1.0.2", "gopd": "^1.2.0", "has-tostringtag": "^1.0.2", "hasown": "^2.0.2" } }, "sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g=="],
+
+ "is-set": ["is-set@2.0.3", "", {}, "sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg=="],
+
+ "is-shared-array-buffer": ["is-shared-array-buffer@1.0.4", "", { "dependencies": { "call-bound": "^1.0.3" } }, "sha512-ISWac8drv4ZGfwKl5slpHG9OwPNty4jOWPRIhBpxOoD+hqITiwuipOQ2bNthAzwA3B4fIjO4Nln74N0S9byq8A=="],
+
+ "is-string": ["is-string@1.1.1", "", { "dependencies": { "call-bound": "^1.0.3", "has-tostringtag": "^1.0.2" } }, "sha512-BtEeSsoaQjlSPBemMQIrY1MY0uM6vnS1g5fmufYOtnxLGUZM2178PKbhsk7Ffv58IX+ZtcvoGwccYsh0PglkAA=="],
+
+ "is-symbol": ["is-symbol@1.1.1", "", { "dependencies": { "call-bound": "^1.0.2", "has-symbols": "^1.1.0", "safe-regex-test": "^1.1.0" } }, "sha512-9gGx6GTtCQM73BgmHQXfDmLtfjjTUDSyoxTCbp5WtoixAhfgsDirWIcVQ/IHpvI5Vgd5i/J5F7B9cN/WlVbC/w=="],
+
+ "is-typed-array": ["is-typed-array@1.1.15", "", { "dependencies": { "which-typed-array": "^1.1.16" } }, "sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ=="],
+
+ "is-unicode-supported": ["is-unicode-supported@2.1.0", "", {}, "sha512-mE00Gnza5EEB3Ds0HfMyllZzbBrmLOX3vfWoj9A9PEnTfratQ/BcaJOuMhnkhjXvb2+FkY3VuHqtAGpTPmglFQ=="],
+
+ "is-weakmap": ["is-weakmap@2.0.2", "", {}, "sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w=="],
+
+ "is-weakref": ["is-weakref@1.1.1", "", { "dependencies": { "call-bound": "^1.0.3" } }, "sha512-6i9mGWSlqzNMEqpCp93KwRS1uUOodk2OJ6b+sq7ZPDSy2WuI5NFIxp/254TytR8ftefexkWn5xNiHUNpPOfSew=="],
+
+ "is-weakset": ["is-weakset@2.0.4", "", { "dependencies": { "call-bound": "^1.0.3", "get-intrinsic": "^1.2.6" } }, "sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ=="],
+
+ "is-wsl": ["is-wsl@3.1.0", "", { "dependencies": { "is-inside-container": "^1.0.0" } }, "sha512-UcVfVfaK4Sc4m7X3dUSoHoozQGBEFeDC+zVo06t98xe8CzHSZZBekNXH+tu0NalHolcJ/QAGqS46Hef7QXBIMw=="],
+
+ "isarray": ["isarray@2.0.5", "", {}, "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw=="],
+
+ "isexe": ["isexe@2.0.0", "", {}, "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="],
+
+ "isobject": ["isobject@3.0.1", "", {}, "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg=="],
+
+ "istanbul-lib-coverage": ["istanbul-lib-coverage@3.2.2", "", {}, "sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg=="],
+
+ "istanbul-lib-report": ["istanbul-lib-report@3.0.1", "", { "dependencies": { "istanbul-lib-coverage": "^3.0.0", "make-dir": "^4.0.0", "supports-color": "^7.1.0" } }, "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw=="],
+
+ "istanbul-reports": ["istanbul-reports@3.2.0", "", { "dependencies": { "html-escaper": "^2.0.0", "istanbul-lib-report": "^3.0.0" } }, "sha512-HGYWWS/ehqTV3xN10i23tkPkpH46MLCIMFNCaaKNavAXTF1RkqxawEPtnjnGZ6XKSInBKkiOA5BKS+aZiY3AvA=="],
+
+ "iterator.prototype": ["iterator.prototype@1.1.5", "", { "dependencies": { "define-data-property": "^1.1.4", "es-object-atoms": "^1.0.0", "get-intrinsic": "^1.2.6", "get-proto": "^1.0.0", "has-symbols": "^1.1.0", "set-function-name": "^2.0.2" } }, "sha512-H0dkQoCa3b2VEeKQBOxFph+JAbcrQdE7KC0UkqwpLmv2EC4P41QXP+rqo9wYodACiG5/WM5s9oDApTU8utwj9g=="],
+
+ "jiti": ["jiti@2.6.1", "", { "bin": "lib/jiti-cli.mjs" }, "sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ=="],
+
+ "joi": ["joi@18.0.2", "", { "dependencies": { "@hapi/address": "^5.1.1", "@hapi/formula": "^3.0.2", "@hapi/hoek": "^11.0.7", "@hapi/pinpoint": "^2.0.1", "@hapi/tlds": "^1.1.1", "@hapi/topo": "^6.0.2", "@standard-schema/spec": "^1.0.0" } }, "sha512-RuCOQMIt78LWnktPoeBL0GErkNaJPTBGcYuyaBvUOQSpcpcLfWrHPPihYdOGbV5pam9VTWbeoF7TsGiHugcjGA=="],
+
+ "jose": ["jose@6.2.1", "", {}, "sha512-jUaKr1yrbfaImV7R2TN/b3IcZzsw38/chqMpo2XJ7i2F8AfM/lA4G1goC3JVEwg0H7UldTmSt3P68nt31W7/mw=="],
+
+ "joycon": ["joycon@3.1.1", "", {}, "sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw=="],
+
+ "js-cookie": ["js-cookie@3.0.5", "", {}, "sha512-cEiJEAEoIbWfCZYKWhVwFuvPX1gETRYPw6LlaTKoxD3s2AkXzkCjnp6h0V77ozyqj0jakteJ4YqDJT830+lVGw=="],
+
+ "js-tokens": ["js-tokens@4.0.0", "", {}, "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ=="],
+
+ "js-yaml": ["js-yaml@4.1.1", "", { "dependencies": { "argparse": "^2.0.1" }, "bin": "bin/js-yaml.js" }, "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA=="],
+
+ "jsdom": ["jsdom@29.0.1", "", { "dependencies": { "@asamuzakjp/css-color": "^5.0.1", "@asamuzakjp/dom-selector": "^7.0.3", "@bramus/specificity": "^2.4.2", "@csstools/css-syntax-patches-for-csstree": "^1.1.1", "@exodus/bytes": "^1.15.0", "css-tree": "^3.2.1", "data-urls": "^7.0.0", "decimal.js": "^10.6.0", "html-encoding-sniffer": "^6.0.0", "is-potential-custom-element-name": "^1.0.1", "lru-cache": "^11.2.7", "parse5": "^8.0.0", "saxes": "^6.0.0", "symbol-tree": "^3.2.4", "tough-cookie": "^6.0.1", "undici": "^7.24.5", "w3c-xmlserializer": "^5.0.0", "webidl-conversions": "^8.0.1", "whatwg-mimetype": "^5.0.0", "whatwg-url": "^16.0.1", "xml-name-validator": "^5.0.0" }, "peerDependencies": { "canvas": "^3.0.0" }, "optionalPeers": ["canvas"] }, "sha512-z6JOK5gRO7aMybVq/y/MlIpKh8JIi68FBKMUtKkK2KH/wMSRlCxQ682d08LB9fYXplyY/UXG8P4XXTScmdjApg=="],
+
+ "jsesc": ["jsesc@3.1.0", "", { "bin": "bin/jsesc" }, "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA=="],
+
+ "json-buffer": ["json-buffer@3.0.1", "", {}, "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ=="],
+
+ "json-parse-even-better-errors": ["json-parse-even-better-errors@2.3.1", "", {}, "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w=="],
+
+ "json-schema-traverse": ["json-schema-traverse@0.4.1", "", {}, "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg=="],
+
+ "json-schema-typed": ["json-schema-typed@8.0.2", "", {}, "sha512-fQhoXdcvc3V28x7C7BMs4P5+kNlgUURe2jmUT1T//oBRMDrqy1QPelJimwZGo7Hg9VPV3EQV5Bnq4hbFy2vetA=="],
+
+ "json-stable-stringify-without-jsonify": ["json-stable-stringify-without-jsonify@1.0.1", "", {}, "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw=="],
+
+ "json2mq": ["json2mq@0.2.0", "", { "dependencies": { "string-convert": "^0.2.0" } }, "sha512-SzoRg7ux5DWTII9J2qkrZrqV1gt+rTaoufMxEzXbS26Uid0NwaJd123HcoB80TgubEppxxIGdNxCx50fEoEWQA=="],
+
+ "json5": ["json5@1.0.2", "", { "dependencies": { "minimist": "^1.2.0" }, "bin": "lib/cli.js" }, "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA=="],
+
+ "jsx-ast-utils": ["jsx-ast-utils@3.3.5", "", { "dependencies": { "array-includes": "^3.1.6", "array.prototype.flat": "^1.3.1", "object.assign": "^4.1.4", "object.values": "^1.1.6" } }, "sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ=="],
+
+ "katex": ["katex@0.16.40", "", { "dependencies": { "commander": "^8.3.0" }, "bin": "cli.js" }, "sha512-1DJcK/L05k1Y9Gf7wMcyuqFOL6BiY3vY0CFcAM/LPRN04NALxcl6u7lOWNsp3f/bCHWxigzQl6FbR95XJ4R84Q=="],
+
+ "keytar": ["keytar@7.9.0", "", { "dependencies": { "node-addon-api": "^4.3.0", "prebuild-install": "^7.0.1" } }, "sha512-VPD8mtVtm5JNtA2AErl6Chp06JBfy7diFQ7TQQhdpWOl6MrCRB+eRbvAZUsbGQS9kiMq0coJsy0W0vHpDCkWsQ=="],
+
+ "keyv": ["keyv@4.5.4", "", { "dependencies": { "json-buffer": "3.0.1" } }, "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw=="],
+
+ "khroma": ["khroma@2.1.0", "", {}, "sha512-Ls993zuzfayK269Svk9hzpeGUKob/sIgZzyHYdjQoAdQetRKpOLj+k/QQQ/6Qi0Yz65mlROrfd+Ev+1+7dz9Kw=="],
+
+ "langium": ["langium@4.2.1", "", { "dependencies": { "chevrotain": "~11.1.1", "chevrotain-allstar": "~0.3.1", "vscode-languageserver": "~9.0.1", "vscode-languageserver-textdocument": "~1.0.11", "vscode-uri": "~3.1.0" } }, "sha512-zu9QWmjpzJcomzdJQAHgDVhLGq5bLosVak1KVa40NzQHXfqr4eAHupvnPOVXEoLkg6Ocefvf/93d//SB7du4YQ=="],
+
+ "language-subtag-registry": ["language-subtag-registry@0.3.23", "", {}, "sha512-0K65Lea881pHotoGEa5gDlMxt3pctLi2RplBb7Ezh4rRdLEOtgi7n4EwK9lamnUCkKBqaeKRVebTq6BAxSkpXQ=="],
+
+ "language-tags": ["language-tags@1.0.9", "", { "dependencies": { "language-subtag-registry": "^0.3.20" } }, "sha512-MbjN408fEndfiQXbFQ1vnd+1NoLDsnQW41410oQBXiyXDMYH5z505juWa4KUE1LqxRC7DgOgZDbKLxHIwm27hA=="],
+
+ "layout-base": ["layout-base@1.0.2", "", {}, "sha512-8h2oVEZNktL4BH2JCOI90iD1yXwL6iNW7KcCKT2QZgQJR2vbqDsldCTPRU9NifTCqHZci57XvQQ15YTu+sTYPg=="],
+
+ "leva": ["leva@0.10.1", "", { "dependencies": { "@radix-ui/react-portal": "^1.1.4", "@radix-ui/react-tooltip": "^1.1.8", "@stitches/react": "^1.2.8", "@use-gesture/react": "^10.2.5", "colord": "^2.9.2", "dequal": "^2.0.2", "merge-value": "^1.0.0", "react-colorful": "^5.5.1", "react-dropzone": "^12.0.0", "v8n": "^1.3.3", "zustand": "^3.6.9" }, "peerDependencies": { "react": "^18.0.0 || ^19.0.0", "react-dom": "^18.0.0 || ^19.0.0" } }, "sha512-BcjnfUX8jpmwZUz2L7AfBtF9vn4ggTH33hmeufDULbP3YgNZ/C+ss/oO3stbrqRQyaOmRwy70y7BGTGO81S3rA=="],
+
+ "levn": ["levn@0.4.1", "", { "dependencies": { "prelude-ls": "^1.2.1", "type-check": "~0.4.0" } }, "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ=="],
+
+ "lightningcss": ["lightningcss@1.31.1", "", { "dependencies": { "detect-libc": "^2.0.3" }, "optionalDependencies": { "lightningcss-android-arm64": "1.31.1", "lightningcss-darwin-arm64": "1.31.1", "lightningcss-darwin-x64": "1.31.1", "lightningcss-freebsd-x64": "1.31.1", "lightningcss-linux-arm-gnueabihf": "1.31.1", "lightningcss-linux-arm64-gnu": "1.31.1", "lightningcss-linux-arm64-musl": "1.31.1", "lightningcss-linux-x64-gnu": "1.31.1", "lightningcss-linux-x64-musl": "1.31.1", "lightningcss-win32-arm64-msvc": "1.31.1", "lightningcss-win32-x64-msvc": "1.31.1" } }, "sha512-l51N2r93WmGUye3WuFoN5k10zyvrVs0qfKBhyC5ogUQ6Ew6JUSswh78mbSO+IU3nTWsyOArqPCcShdQSadghBQ=="],
+
+ "lightningcss-android-arm64": ["lightningcss-android-arm64@1.31.1", "", { "os": "android", "cpu": "arm64" }, "sha512-HXJF3x8w9nQ4jbXRiNppBCqeZPIAfUo8zE/kOEGbW5NZvGc/K7nMxbhIr+YlFlHW5mpbg/YFPdbnCh1wAXCKFg=="],
+
+ "lightningcss-darwin-arm64": ["lightningcss-darwin-arm64@1.31.1", "", { "os": "darwin", "cpu": "arm64" }, "sha512-02uTEqf3vIfNMq3h/z2cJfcOXnQ0GRwQrkmPafhueLb2h7mqEidiCzkE4gBMEH65abHRiQvhdcQ+aP0D0g67sg=="],
+
+ "lightningcss-darwin-x64": ["lightningcss-darwin-x64@1.31.1", "", { "os": "darwin", "cpu": "x64" }, "sha512-1ObhyoCY+tGxtsz1lSx5NXCj3nirk0Y0kB/g8B8DT+sSx4G9djitg9ejFnjb3gJNWo7qXH4DIy2SUHvpoFwfTA=="],
+
+ "lightningcss-freebsd-x64": ["lightningcss-freebsd-x64@1.31.1", "", { "os": "freebsd", "cpu": "x64" }, "sha512-1RINmQKAItO6ISxYgPwszQE1BrsVU5aB45ho6O42mu96UiZBxEXsuQ7cJW4zs4CEodPUioj/QrXW1r9pLUM74A=="],
+
+ "lightningcss-linux-arm-gnueabihf": ["lightningcss-linux-arm-gnueabihf@1.31.1", "", { "os": "linux", "cpu": "arm" }, "sha512-OOCm2//MZJ87CdDK62rZIu+aw9gBv4azMJuA8/KB74wmfS3lnC4yoPHm0uXZ/dvNNHmnZnB8XLAZzObeG0nS1g=="],
+
+ "lightningcss-linux-arm64-gnu": ["lightningcss-linux-arm64-gnu@1.31.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-WKyLWztD71rTnou4xAD5kQT+982wvca7E6QoLpoawZ1gP9JM0GJj4Tp5jMUh9B3AitHbRZ2/H3W5xQmdEOUlLg=="],
+
+ "lightningcss-linux-arm64-musl": ["lightningcss-linux-arm64-musl@1.31.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-mVZ7Pg2zIbe3XlNbZJdjs86YViQFoJSpc41CbVmKBPiGmC4YrfeOyz65ms2qpAobVd7WQsbW4PdsSJEMymyIMg=="],
+
+ "lightningcss-linux-x64-gnu": ["lightningcss-linux-x64-gnu@1.31.1", "", { "os": "linux", "cpu": "x64" }, "sha512-xGlFWRMl+0KvUhgySdIaReQdB4FNudfUTARn7q0hh/V67PVGCs3ADFjw+6++kG1RNd0zdGRlEKa+T13/tQjPMA=="],
+
+ "lightningcss-linux-x64-musl": ["lightningcss-linux-x64-musl@1.31.1", "", { "os": "linux", "cpu": "x64" }, "sha512-eowF8PrKHw9LpoZii5tdZwnBcYDxRw2rRCyvAXLi34iyeYfqCQNA9rmUM0ce62NlPhCvof1+9ivRaTY6pSKDaA=="],
+
+ "lightningcss-win32-arm64-msvc": ["lightningcss-win32-arm64-msvc@1.31.1", "", { "os": "win32", "cpu": "arm64" }, "sha512-aJReEbSEQzx1uBlQizAOBSjcmr9dCdL3XuC/6HLXAxmtErsj2ICo5yYggg1qOODQMtnjNQv2UHb9NpOuFtYe4w=="],
+
+ "lightningcss-win32-x64-msvc": ["lightningcss-win32-x64-msvc@1.31.1", "", { "os": "win32", "cpu": "x64" }, "sha512-I9aiFrbd7oYHwlnQDqr1Roz+fTz61oDDJX7n9tYF9FJymH1cIN1DtKw3iYt6b8WZgEjoNwVSncwF4wx/ZedMhw=="],
+
+ "lines-and-columns": ["lines-and-columns@1.2.4", "", {}, "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg=="],
+
+ "lint-staged": ["lint-staged@16.4.0", "", { "dependencies": { "commander": "^14.0.3", "listr2": "^9.0.5", "picomatch": "^4.0.3", "string-argv": "^0.3.2", "tinyexec": "^1.0.4", "yaml": "^2.8.2" }, "bin": "bin/lint-staged.js" }, "sha512-lBWt8hujh/Cjysw5GYVmZpFHXDCgZzhrOm8vbcUdobADZNOK/bRshr2kM3DfgrrtR1DQhfupW9gnIXOfiFi+bw=="],
+
+ "listr2": ["listr2@9.0.5", "", { "dependencies": { "cli-truncate": "^5.0.0", "colorette": "^2.0.20", "eventemitter3": "^5.0.1", "log-update": "^6.1.0", "rfdc": "^1.4.1", "wrap-ansi": "^9.0.0" } }, "sha512-ME4Fb83LgEgwNw96RKNvKV4VTLuXfoKudAmm2lP8Kk87KaMK0/Xrx/aAkMWmT8mDb+3MlFDspfbCs7adjRxA2g=="],
+
+ "lit": ["lit@3.3.2", "", { "dependencies": { "@lit/reactive-element": "^2.1.0", "lit-element": "^4.2.0", "lit-html": "^3.3.0" } }, "sha512-NF9zbsP79l4ao2SNrH3NkfmFgN/hBYSQo90saIVI1o5GpjAdCPVstVzO1MrLOakHoEhYkrtRjPK6Ob521aoYWQ=="],
+
+ "lit-element": ["lit-element@4.2.2", "", { "dependencies": { "@lit-labs/ssr-dom-shim": "^1.5.0", "@lit/reactive-element": "^2.1.0", "lit-html": "^3.3.0" } }, "sha512-aFKhNToWxoyhkNDmWZwEva2SlQia+jfG0fjIWV//YeTaWrVnOxD89dPKfigCUspXFmjzOEUQpOkejH5Ly6sG0w=="],
+
+ "lit-html": ["lit-html@3.3.2", "", { "dependencies": { "@types/trusted-types": "^2.0.2" } }, "sha512-Qy9hU88zcmaxBXcc10ZpdK7cOLXvXpRoBxERdtqV9QOrfpMZZ6pSYP91LhpPtap3sFMUiL7Tw2RImbe0Al2/kw=="],
+
+ "locate-path": ["locate-path@6.0.0", "", { "dependencies": { "p-locate": "^5.0.0" } }, "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw=="],
+
+ "lodash": ["lodash@4.17.23", "", {}, "sha512-LgVTMpQtIopCi79SJeDiP0TfWi5CNEc/L/aRdTh3yIvmZXTnheWpKjSZhnvMl8iXbC1tFg9gdHHDMLoV7CnG+w=="],
+
+ "lodash-es": ["lodash-es@4.17.23", "", {}, "sha512-kVI48u3PZr38HdYz98UmfPnXl2DXrpdctLrFLCd3kOx1xUkOmpFPx7gCWWM5MPkL/fD8zb+Ph0QzjGFs4+hHWg=="],
+
+ "lodash.merge": ["lodash.merge@4.6.2", "", {}, "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ=="],
+
+ "log-symbols": ["log-symbols@7.0.1", "", { "dependencies": { "is-unicode-supported": "^2.0.0", "yoctocolors": "^2.1.1" } }, "sha512-ja1E3yCr9i/0hmBVaM0bfwDjnGy8I/s6PP4DFp+yP+a+mrHO4Rm7DtmnqROTUkHIkqffC84YY7AeqX6oFk0WFg=="],
+
+ "log-update": ["log-update@6.1.0", "", { "dependencies": { "ansi-escapes": "^7.0.0", "cli-cursor": "^5.0.0", "slice-ansi": "^7.1.0", "strip-ansi": "^7.1.0", "wrap-ansi": "^9.0.0" } }, "sha512-9ie8ItPR6tjY5uYJh8K/Zrv/RMZ5VOlOWvtZdEHYSTFKZfIBPQa9tOAEeAWhd+AnIneLJ22w5fjOYtoutpWq5w=="],
+
+ "longest-streak": ["longest-streak@3.1.0", "", {}, "sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g=="],
+
+ "loose-envify": ["loose-envify@1.4.0", "", { "dependencies": { "js-tokens": "^3.0.0 || ^4.0.0" }, "bin": "cli.js" }, "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q=="],
+
+ "lowdb": ["lowdb@7.0.1", "", { "dependencies": { "steno": "^4.0.2" } }, "sha512-neJAj8GwF0e8EpycYIDFqEPcx9Qz4GUho20jWFR7YiFeXzF1YMLdxB36PypcTSPMA+4+LvgyMacYhlr18Zlymw=="],
+
+ "lru-cache": ["lru-cache@11.2.7", "", {}, "sha512-aY/R+aEsRelme17KGQa/1ZSIpLpNYYrhcrepKTZgE+W3WM16YMCaPwOHLHsmopZHELU0Ojin1lPVxKR0MihncA=="],
+
+ "lru_map": ["lru_map@0.4.1", "", {}, "sha512-I+lBvqMMFfqaV8CJCISjI3wbjmwVu/VyOoU7+qtu9d7ioW5klMgsTTiUOUp+DJvfTTzKXoPbyC6YfgkNcyPSOg=="],
+
+ "lucide-react": ["lucide-react@0.469.0", "", { "peerDependencies": { "react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, "sha512-28vvUnnKQ/dBwiCQtwJw7QauYnE7yd2Cyp4tTTJpvglX4EMpbflcdBgrgToX2j71B3YvugK/NH3BGUk+E/p/Fw=="],
+
+ "lz-string": ["lz-string@1.5.0", "", { "bin": { "lz-string": "bin/bin.js" } }, "sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ=="],
+
+ "magic-string": ["magic-string@0.30.21", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.5" } }, "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ=="],
+
+ "make-dir": ["make-dir@4.0.0", "", { "dependencies": { "semver": "^7.5.3" } }, "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw=="],
+
+ "markdown-extensions": ["markdown-extensions@2.0.0", "", {}, "sha512-o5vL7aDWatOTX8LzaS1WMoaoxIiLRQJuIKKe2wAw6IeULDHaqbiqiggmx+pKvZDb1Sj+pE46Sn1T7lCqfFtg1Q=="],
+
+ "markdown-table": ["markdown-table@3.0.4", "", {}, "sha512-wiYz4+JrLyb/DqW2hkFJxP7Vd7JuTDm77fvbM8VfEQdmSMqcImWeeRbHwZjBjIFki/VaMK2BhFi7oUUZeM5bqw=="],
+
+ "marked": ["marked@14.0.0", "", { "bin": "bin/marked.js" }, "sha512-uIj4+faQ+MgHgwUW1l2PsPglZLOLOT1uErt06dAPtx2kjteLAkbsd/0FiYg/MGS+i7ZKLb7w2WClxHkzOOuryQ=="],
+
+ "math-intrinsics": ["math-intrinsics@1.1.0", "", {}, "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g=="],
+
+ "mdast-util-find-and-replace": ["mdast-util-find-and-replace@3.0.2", "", { "dependencies": { "@types/mdast": "^4.0.0", "escape-string-regexp": "^5.0.0", "unist-util-is": "^6.0.0", "unist-util-visit-parents": "^6.0.0" } }, "sha512-Tmd1Vg/m3Xz43afeNxDIhWRtFZgM2VLyaf4vSTYwudTyeuTneoL3qtWMA5jeLyz/O1vDJmmV4QuScFCA2tBPwg=="],
+
+ "mdast-util-from-markdown": ["mdast-util-from-markdown@2.0.3", "", { "dependencies": { "@types/mdast": "^4.0.0", "@types/unist": "^3.0.0", "decode-named-character-reference": "^1.0.0", "devlop": "^1.0.0", "mdast-util-to-string": "^4.0.0", "micromark": "^4.0.0", "micromark-util-decode-numeric-character-reference": "^2.0.0", "micromark-util-decode-string": "^2.0.0", "micromark-util-normalize-identifier": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0", "unist-util-stringify-position": "^4.0.0" } }, "sha512-W4mAWTvSlKvf8L6J+VN9yLSqQ9AOAAvHuoDAmPkz4dHf553m5gVj2ejadHJhoJmcmxEnOv6Pa8XJhpxE93kb8Q=="],
+
+ "mdast-util-gfm": ["mdast-util-gfm@3.1.0", "", { "dependencies": { "mdast-util-from-markdown": "^2.0.0", "mdast-util-gfm-autolink-literal": "^2.0.0", "mdast-util-gfm-footnote": "^2.0.0", "mdast-util-gfm-strikethrough": "^2.0.0", "mdast-util-gfm-table": "^2.0.0", "mdast-util-gfm-task-list-item": "^2.0.0", "mdast-util-to-markdown": "^2.0.0" } }, "sha512-0ulfdQOM3ysHhCJ1p06l0b0VKlhU0wuQs3thxZQagjcjPrlFRqY215uZGHHJan9GEAXd9MbfPjFJz+qMkVR6zQ=="],
+
+ "mdast-util-gfm-autolink-literal": ["mdast-util-gfm-autolink-literal@2.0.1", "", { "dependencies": { "@types/mdast": "^4.0.0", "ccount": "^2.0.0", "devlop": "^1.0.0", "mdast-util-find-and-replace": "^3.0.0", "micromark-util-character": "^2.0.0" } }, "sha512-5HVP2MKaP6L+G6YaxPNjuL0BPrq9orG3TsrZ9YXbA3vDw/ACI4MEsnoDpn6ZNm7GnZgtAcONJyPhOP8tNJQavQ=="],
+
+ "mdast-util-gfm-footnote": ["mdast-util-gfm-footnote@2.1.0", "", { "dependencies": { "@types/mdast": "^4.0.0", "devlop": "^1.1.0", "mdast-util-from-markdown": "^2.0.0", "mdast-util-to-markdown": "^2.0.0", "micromark-util-normalize-identifier": "^2.0.0" } }, "sha512-sqpDWlsHn7Ac9GNZQMeUzPQSMzR6Wv0WKRNvQRg0KqHh02fpTz69Qc1QSseNX29bhz1ROIyNyxExfawVKTm1GQ=="],
+
+ "mdast-util-gfm-strikethrough": ["mdast-util-gfm-strikethrough@2.0.0", "", { "dependencies": { "@types/mdast": "^4.0.0", "mdast-util-from-markdown": "^2.0.0", "mdast-util-to-markdown": "^2.0.0" } }, "sha512-mKKb915TF+OC5ptj5bJ7WFRPdYtuHv0yTRxK2tJvi+BDqbkiG7h7u/9SI89nRAYcmap2xHQL9D+QG/6wSrTtXg=="],
+
+ "mdast-util-gfm-table": ["mdast-util-gfm-table@2.0.0", "", { "dependencies": { "@types/mdast": "^4.0.0", "devlop": "^1.0.0", "markdown-table": "^3.0.0", "mdast-util-from-markdown": "^2.0.0", "mdast-util-to-markdown": "^2.0.0" } }, "sha512-78UEvebzz/rJIxLvE7ZtDd/vIQ0RHv+3Mh5DR96p7cS7HsBhYIICDBCu8csTNWNO6tBWfqXPWekRuj2FNOGOZg=="],
+
+ "mdast-util-gfm-task-list-item": ["mdast-util-gfm-task-list-item@2.0.0", "", { "dependencies": { "@types/mdast": "^4.0.0", "devlop": "^1.0.0", "mdast-util-from-markdown": "^2.0.0", "mdast-util-to-markdown": "^2.0.0" } }, "sha512-IrtvNvjxC1o06taBAVJznEnkiHxLFTzgonUdy8hzFVeDun0uTjxxrRGVaNFqkU1wJR3RBPEfsxmU6jDWPofrTQ=="],
+
+ "mdast-util-math": ["mdast-util-math@3.0.0", "", { "dependencies": { "@types/hast": "^3.0.0", "@types/mdast": "^4.0.0", "devlop": "^1.0.0", "longest-streak": "^3.0.0", "mdast-util-from-markdown": "^2.0.0", "mdast-util-to-markdown": "^2.1.0", "unist-util-remove-position": "^5.0.0" } }, "sha512-Tl9GBNeG/AhJnQM221bJR2HPvLOSnLE/T9cJI9tlc6zwQk2nPk/4f0cHkOdEixQPC/j8UtKDdITswvLAy1OZ1w=="],
+
+ "mdast-util-mdx": ["mdast-util-mdx@3.0.0", "", { "dependencies": { "mdast-util-from-markdown": "^2.0.0", "mdast-util-mdx-expression": "^2.0.0", "mdast-util-mdx-jsx": "^3.0.0", "mdast-util-mdxjs-esm": "^2.0.0", "mdast-util-to-markdown": "^2.0.0" } }, "sha512-JfbYLAW7XnYTTbUsmpu0kdBUVe+yKVJZBItEjwyYJiDJuZ9w4eeaqks4HQO+R7objWgS2ymV60GYpI14Ug554w=="],
+
+ "mdast-util-mdx-expression": ["mdast-util-mdx-expression@2.0.1", "", { "dependencies": { "@types/estree-jsx": "^1.0.0", "@types/hast": "^3.0.0", "@types/mdast": "^4.0.0", "devlop": "^1.0.0", "mdast-util-from-markdown": "^2.0.0", "mdast-util-to-markdown": "^2.0.0" } }, "sha512-J6f+9hUp+ldTZqKRSg7Vw5V6MqjATc+3E4gf3CFNcuZNWD8XdyI6zQ8GqH7f8169MM6P7hMBRDVGnn7oHB9kXQ=="],
+
+ "mdast-util-mdx-jsx": ["mdast-util-mdx-jsx@3.2.0", "", { "dependencies": { "@types/estree-jsx": "^1.0.0", "@types/hast": "^3.0.0", "@types/mdast": "^4.0.0", "@types/unist": "^3.0.0", "ccount": "^2.0.0", "devlop": "^1.1.0", "mdast-util-from-markdown": "^2.0.0", "mdast-util-to-markdown": "^2.0.0", "parse-entities": "^4.0.0", "stringify-entities": "^4.0.0", "unist-util-stringify-position": "^4.0.0", "vfile-message": "^4.0.0" } }, "sha512-lj/z8v0r6ZtsN/cGNNtemmmfoLAFZnjMbNyLzBafjzikOM+glrjNHPlf6lQDOTccj9n5b0PPihEBbhneMyGs1Q=="],
+
+ "mdast-util-mdxjs-esm": ["mdast-util-mdxjs-esm@2.0.1", "", { "dependencies": { "@types/estree-jsx": "^1.0.0", "@types/hast": "^3.0.0", "@types/mdast": "^4.0.0", "devlop": "^1.0.0", "mdast-util-from-markdown": "^2.0.0", "mdast-util-to-markdown": "^2.0.0" } }, "sha512-EcmOpxsZ96CvlP03NghtH1EsLtr0n9Tm4lPUJUBccV9RwUOneqSycg19n5HGzCf+10LozMRSObtVr3ee1WoHtg=="],
+
+ "mdast-util-newline-to-break": ["mdast-util-newline-to-break@2.0.0", "", { "dependencies": { "@types/mdast": "^4.0.0", "mdast-util-find-and-replace": "^3.0.0" } }, "sha512-MbgeFca0hLYIEx/2zGsszCSEJJ1JSCdiY5xQxRcLDDGa8EPvlLPupJ4DSajbMPAnC0je8jfb9TiUATnxxrHUog=="],
+
+ "mdast-util-phrasing": ["mdast-util-phrasing@4.1.0", "", { "dependencies": { "@types/mdast": "^4.0.0", "unist-util-is": "^6.0.0" } }, "sha512-TqICwyvJJpBwvGAMZjj4J2n0X8QWp21b9l0o7eXyVJ25YNWYbJDVIyD1bZXE6WtV6RmKJVYmQAKWa0zWOABz2w=="],
+
+ "mdast-util-to-hast": ["mdast-util-to-hast@13.2.1", "", { "dependencies": { "@types/hast": "^3.0.0", "@types/mdast": "^4.0.0", "@ungap/structured-clone": "^1.0.0", "devlop": "^1.0.0", "micromark-util-sanitize-uri": "^2.0.0", "trim-lines": "^3.0.0", "unist-util-position": "^5.0.0", "unist-util-visit": "^5.0.0", "vfile": "^6.0.0" } }, "sha512-cctsq2wp5vTsLIcaymblUriiTcZd0CwWtCbLvrOzYCDZoWyMNV8sZ7krj09FSnsiJi3WVsHLM4k6Dq/yaPyCXA=="],
+
+ "mdast-util-to-markdown": ["mdast-util-to-markdown@2.1.2", "", { "dependencies": { "@types/mdast": "^4.0.0", "@types/unist": "^3.0.0", "longest-streak": "^3.0.0", "mdast-util-phrasing": "^4.0.0", "mdast-util-to-string": "^4.0.0", "micromark-util-classify-character": "^2.0.0", "micromark-util-decode-string": "^2.0.0", "unist-util-visit": "^5.0.0", "zwitch": "^2.0.0" } }, "sha512-xj68wMTvGXVOKonmog6LwyJKrYXZPvlwabaryTjLh9LuvovB/KAH+kvi8Gjj+7rJjsFi23nkUxRQv1KqSroMqA=="],
+
+ "mdast-util-to-string": ["mdast-util-to-string@4.0.0", "", { "dependencies": { "@types/mdast": "^4.0.0" } }, "sha512-0H44vDimn51F0YwvxSJSm0eCDOJTRlmN0R1yBh4HLj9wiV1Dn0QoXGbvFAWj2hSItVTlCmBF1hqKlIyUBVFLPg=="],
+
+ "mdn-data": ["mdn-data@2.27.1", "", {}, "sha512-9Yubnt3e8A0OKwxYSXyhLymGW4sCufcLG6VdiDdUGVkPhpqLxlvP5vl1983gQjJl3tqbrM731mjaZaP68AgosQ=="],
+
+ "media-typer": ["media-typer@1.1.0", "", {}, "sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw=="],
+
+ "merge-descriptors": ["merge-descriptors@2.0.0", "", {}, "sha512-Snk314V5ayFLhp3fkUREub6WtjBfPdCPY1Ln8/8munuLuiYhsABgBVWsozAG+MWMbVEvcdcpbi9R7ww22l9Q3g=="],
+
+ "merge-value": ["merge-value@1.0.0", "", { "dependencies": { "get-value": "^2.0.6", "is-extendable": "^1.0.0", "mixin-deep": "^1.2.0", "set-value": "^2.0.0" } }, "sha512-fJMmvat4NeKz63Uv9iHWcPDjCWcCkoiRoajRTEO8hlhUC6rwaHg0QCF9hBOTjZmm4JuglPckPSTtcuJL5kp0TQ=="],
+
+ "merge2": ["merge2@1.4.1", "", {}, "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg=="],
+
+ "mermaid": ["mermaid@11.13.0", "", { "dependencies": { "@braintree/sanitize-url": "^7.1.1", "@iconify/utils": "^3.0.2", "@mermaid-js/parser": "^1.0.1", "@types/d3": "^7.4.3", "@upsetjs/venn.js": "^2.0.0", "cytoscape": "^3.33.1", "cytoscape-cose-bilkent": "^4.1.0", "cytoscape-fcose": "^2.2.0", "d3": "^7.9.0", "d3-sankey": "^0.12.3", "dagre-d3-es": "7.0.14", "dayjs": "^1.11.19", "dompurify": "^3.3.1", "katex": "^0.16.25", "khroma": "^2.1.0", "lodash-es": "^4.17.23", "marked": "^16.3.0", "roughjs": "^4.6.6", "stylis": "^4.3.6", "ts-dedent": "^2.2.0", "uuid": "^11.1.0" } }, "sha512-fEnci+Immw6lKMFI8sqzjlATTyjLkRa6axrEgLV2yHTfv8r+h1wjFbV6xeRtd4rUV1cS4EpR9rwp3Rci7TRWDw=="],
+
+ "micromark": ["micromark@4.0.2", "", { "dependencies": { "@types/debug": "^4.0.0", "debug": "^4.0.0", "decode-named-character-reference": "^1.0.0", "devlop": "^1.0.0", "micromark-core-commonmark": "^2.0.0", "micromark-factory-space": "^2.0.0", "micromark-util-character": "^2.0.0", "micromark-util-chunked": "^2.0.0", "micromark-util-combine-extensions": "^2.0.0", "micromark-util-decode-numeric-character-reference": "^2.0.0", "micromark-util-encode": "^2.0.0", "micromark-util-normalize-identifier": "^2.0.0", "micromark-util-resolve-all": "^2.0.0", "micromark-util-sanitize-uri": "^2.0.0", "micromark-util-subtokenize": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-zpe98Q6kvavpCr1NPVSCMebCKfD7CA2NqZ+rykeNhONIJBpc1tFKt9hucLGwha3jNTNI8lHpctWJWoimVF4PfA=="],
+
+ "micromark-core-commonmark": ["micromark-core-commonmark@2.0.3", "", { "dependencies": { "decode-named-character-reference": "^1.0.0", "devlop": "^1.0.0", "micromark-factory-destination": "^2.0.0", "micromark-factory-label": "^2.0.0", "micromark-factory-space": "^2.0.0", "micromark-factory-title": "^2.0.0", "micromark-factory-whitespace": "^2.0.0", "micromark-util-character": "^2.0.0", "micromark-util-chunked": "^2.0.0", "micromark-util-classify-character": "^2.0.0", "micromark-util-html-tag-name": "^2.0.0", "micromark-util-normalize-identifier": "^2.0.0", "micromark-util-resolve-all": "^2.0.0", "micromark-util-subtokenize": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-RDBrHEMSxVFLg6xvnXmb1Ayr2WzLAWjeSATAoxwKYJV94TeNavgoIdA0a9ytzDSVzBy2YKFK+emCPOEibLeCrg=="],
+
+ "micromark-extension-cjk-friendly": ["micromark-extension-cjk-friendly@1.2.3", "", { "dependencies": { "devlop": "^1.1.0", "micromark-extension-cjk-friendly-util": "2.1.1", "micromark-util-chunked": "^2.0.1", "micromark-util-resolve-all": "^2.0.1", "micromark-util-symbol": "^2.0.1" }, "peerDependencies": { "micromark": "^4.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-gRzVLUdjXBLX6zNPSnHGDoo+ZTp5zy+MZm0g3sv+3chPXY7l9gW+DnrcHcZh/jiPR6MjPKO4AEJNp4Aw6V9z5Q=="],
+
+ "micromark-extension-cjk-friendly-util": ["micromark-extension-cjk-friendly-util@2.1.1", "", { "dependencies": { "get-east-asian-width": "^1.3.0", "micromark-util-character": "^2.1.1", "micromark-util-symbol": "^2.0.1" } }, "sha512-egs6+12JU2yutskHY55FyR48ZiEcFOJFyk9rsiyIhcJ6IvWB6ABBqVrBw8IobqJTDZ/wdSr9eoXDPb5S2nW1bg=="],
+
+ "micromark-extension-gfm": ["micromark-extension-gfm@3.0.0", "", { "dependencies": { "micromark-extension-gfm-autolink-literal": "^2.0.0", "micromark-extension-gfm-footnote": "^2.0.0", "micromark-extension-gfm-strikethrough": "^2.0.0", "micromark-extension-gfm-table": "^2.0.0", "micromark-extension-gfm-tagfilter": "^2.0.0", "micromark-extension-gfm-task-list-item": "^2.0.0", "micromark-util-combine-extensions": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-vsKArQsicm7t0z2GugkCKtZehqUm31oeGBV/KVSorWSy8ZlNAv7ytjFhvaryUiCUJYqs+NoE6AFhpQvBTM6Q4w=="],
+
+ "micromark-extension-gfm-autolink-literal": ["micromark-extension-gfm-autolink-literal@2.1.0", "", { "dependencies": { "micromark-util-character": "^2.0.0", "micromark-util-sanitize-uri": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-oOg7knzhicgQ3t4QCjCWgTmfNhvQbDDnJeVu9v81r7NltNCVmhPy1fJRX27pISafdjL+SVc4d3l48Gb6pbRypw=="],
+
+ "micromark-extension-gfm-footnote": ["micromark-extension-gfm-footnote@2.1.0", "", { "dependencies": { "devlop": "^1.0.0", "micromark-core-commonmark": "^2.0.0", "micromark-factory-space": "^2.0.0", "micromark-util-character": "^2.0.0", "micromark-util-normalize-identifier": "^2.0.0", "micromark-util-sanitize-uri": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-/yPhxI1ntnDNsiHtzLKYnE3vf9JZ6cAisqVDauhp4CEHxlb4uoOTxOCJ+9s51bIB8U1N1FJ1RXOKTIlD5B/gqw=="],
+
+ "micromark-extension-gfm-strikethrough": ["micromark-extension-gfm-strikethrough@2.1.0", "", { "dependencies": { "devlop": "^1.0.0", "micromark-util-chunked": "^2.0.0", "micromark-util-classify-character": "^2.0.0", "micromark-util-resolve-all": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-ADVjpOOkjz1hhkZLlBiYA9cR2Anf8F4HqZUO6e5eDcPQd0Txw5fxLzzxnEkSkfnD0wziSGiv7sYhk/ktvbf1uw=="],
+
+ "micromark-extension-gfm-table": ["micromark-extension-gfm-table@2.1.1", "", { "dependencies": { "devlop": "^1.0.0", "micromark-factory-space": "^2.0.0", "micromark-util-character": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-t2OU/dXXioARrC6yWfJ4hqB7rct14e8f7m0cbI5hUmDyyIlwv5vEtooptH8INkbLzOatzKuVbQmAYcbWoyz6Dg=="],
+
+ "micromark-extension-gfm-tagfilter": ["micromark-extension-gfm-tagfilter@2.0.0", "", { "dependencies": { "micromark-util-types": "^2.0.0" } }, "sha512-xHlTOmuCSotIA8TW1mDIM6X2O1SiX5P9IuDtqGonFhEK0qgRI4yeC6vMxEV2dgyr2TiD+2PQ10o+cOhdVAcwfg=="],
+
+ "micromark-extension-gfm-task-list-item": ["micromark-extension-gfm-task-list-item@2.1.0", "", { "dependencies": { "devlop": "^1.0.0", "micromark-factory-space": "^2.0.0", "micromark-util-character": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-qIBZhqxqI6fjLDYFTBIa4eivDMnP+OZqsNwmQ3xNLE4Cxwc+zfQEfbs6tzAo2Hjq+bh6q5F+Z8/cksrLFYWQQw=="],
+
+ "micromark-extension-math": ["micromark-extension-math@3.1.0", "", { "dependencies": { "@types/katex": "^0.16.0", "devlop": "^1.0.0", "katex": "^0.16.0", "micromark-factory-space": "^2.0.0", "micromark-util-character": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-lvEqd+fHjATVs+2v/8kg9i5Q0AP2k85H0WUOwpIVvUML8BapsMvh1XAogmQjOCsLpoKRCVQqEkQBB3NhVBcsOg=="],
+
+ "micromark-extension-mdx-expression": ["micromark-extension-mdx-expression@3.0.1", "", { "dependencies": { "@types/estree": "^1.0.0", "devlop": "^1.0.0", "micromark-factory-mdx-expression": "^2.0.0", "micromark-factory-space": "^2.0.0", "micromark-util-character": "^2.0.0", "micromark-util-events-to-acorn": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-dD/ADLJ1AeMvSAKBwO22zG22N4ybhe7kFIZ3LsDI0GlsNr2A3KYxb0LdC1u5rj4Nw+CHKY0RVdnHX8vj8ejm4Q=="],
+
+ "micromark-extension-mdx-jsx": ["micromark-extension-mdx-jsx@3.0.2", "", { "dependencies": { "@types/estree": "^1.0.0", "devlop": "^1.0.0", "estree-util-is-identifier-name": "^3.0.0", "micromark-factory-mdx-expression": "^2.0.0", "micromark-factory-space": "^2.0.0", "micromark-util-character": "^2.0.0", "micromark-util-events-to-acorn": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0", "vfile-message": "^4.0.0" } }, "sha512-e5+q1DjMh62LZAJOnDraSSbDMvGJ8x3cbjygy2qFEi7HCeUT4BDKCvMozPozcD6WmOt6sVvYDNBKhFSz3kjOVQ=="],
+
+ "micromark-extension-mdx-md": ["micromark-extension-mdx-md@2.0.0", "", { "dependencies": { "micromark-util-types": "^2.0.0" } }, "sha512-EpAiszsB3blw4Rpba7xTOUptcFeBFi+6PY8VnJ2hhimH+vCQDirWgsMpz7w1XcZE7LVrSAUGb9VJpG9ghlYvYQ=="],
+
+ "micromark-extension-mdxjs": ["micromark-extension-mdxjs@3.0.0", "", { "dependencies": { "acorn": "^8.0.0", "acorn-jsx": "^5.0.0", "micromark-extension-mdx-expression": "^3.0.0", "micromark-extension-mdx-jsx": "^3.0.0", "micromark-extension-mdx-md": "^2.0.0", "micromark-extension-mdxjs-esm": "^3.0.0", "micromark-util-combine-extensions": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-A873fJfhnJ2siZyUrJ31l34Uqwy4xIFmvPY1oj+Ean5PHcPBYzEsvqvWGaWcfEIr11O5Dlw3p2y0tZWpKHDejQ=="],
+
+ "micromark-extension-mdxjs-esm": ["micromark-extension-mdxjs-esm@3.0.0", "", { "dependencies": { "@types/estree": "^1.0.0", "devlop": "^1.0.0", "micromark-core-commonmark": "^2.0.0", "micromark-util-character": "^2.0.0", "micromark-util-events-to-acorn": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0", "unist-util-position-from-estree": "^2.0.0", "vfile-message": "^4.0.0" } }, "sha512-DJFl4ZqkErRpq/dAPyeWp15tGrcrrJho1hKK5uBS70BCtfrIFg81sqcTVu3Ta+KD1Tk5vAtBNElWxtAa+m8K9A=="],
+
+ "micromark-factory-destination": ["micromark-factory-destination@2.0.1", "", { "dependencies": { "micromark-util-character": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-Xe6rDdJlkmbFRExpTOmRj9N3MaWmbAgdpSrBQvCFqhezUn4AHqJHbaEnfbVYYiexVSs//tqOdY/DxhjdCiJnIA=="],
+
+ "micromark-factory-label": ["micromark-factory-label@2.0.1", "", { "dependencies": { "devlop": "^1.0.0", "micromark-util-character": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-VFMekyQExqIW7xIChcXn4ok29YE3rnuyveW3wZQWWqF4Nv9Wk5rgJ99KzPvHjkmPXF93FXIbBp6YdW3t71/7Vg=="],
+
+ "micromark-factory-mdx-expression": ["micromark-factory-mdx-expression@2.0.3", "", { "dependencies": { "@types/estree": "^1.0.0", "devlop": "^1.0.0", "micromark-factory-space": "^2.0.0", "micromark-util-character": "^2.0.0", "micromark-util-events-to-acorn": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0", "unist-util-position-from-estree": "^2.0.0", "vfile-message": "^4.0.0" } }, "sha512-kQnEtA3vzucU2BkrIa8/VaSAsP+EJ3CKOvhMuJgOEGg9KDC6OAY6nSnNDVRiVNRqj7Y4SlSzcStaH/5jge8JdQ=="],
+
+ "micromark-factory-space": ["micromark-factory-space@2.0.1", "", { "dependencies": { "micromark-util-character": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-zRkxjtBxxLd2Sc0d+fbnEunsTj46SWXgXciZmHq0kDYGnck/ZSGj9/wULTV95uoeYiK5hRXP2mJ98Uo4cq/LQg=="],
+
+ "micromark-factory-title": ["micromark-factory-title@2.0.1", "", { "dependencies": { "micromark-factory-space": "^2.0.0", "micromark-util-character": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-5bZ+3CjhAd9eChYTHsjy6TGxpOFSKgKKJPJxr293jTbfry2KDoWkhBb6TcPVB4NmzaPhMs1Frm9AZH7OD4Cjzw=="],
+
+ "micromark-factory-whitespace": ["micromark-factory-whitespace@2.0.1", "", { "dependencies": { "micromark-factory-space": "^2.0.0", "micromark-util-character": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-Ob0nuZ3PKt/n0hORHyvoD9uZhr+Za8sFoP+OnMcnWK5lngSzALgQYKMr9RJVOWLqQYuyn6ulqGWSXdwf6F80lQ=="],
+
+ "micromark-util-character": ["micromark-util-character@2.1.1", "", { "dependencies": { "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q=="],
+
+ "micromark-util-chunked": ["micromark-util-chunked@2.0.1", "", { "dependencies": { "micromark-util-symbol": "^2.0.0" } }, "sha512-QUNFEOPELfmvv+4xiNg2sRYeS/P84pTW0TCgP5zc9FpXetHY0ab7SxKyAQCNCc1eK0459uoLI1y5oO5Vc1dbhA=="],
+
+ "micromark-util-classify-character": ["micromark-util-classify-character@2.0.1", "", { "dependencies": { "micromark-util-character": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-K0kHzM6afW/MbeWYWLjoHQv1sgg2Q9EccHEDzSkxiP/EaagNzCm7T/WMKZ3rjMbvIpvBiZgwR3dKMygtA4mG1Q=="],
+
+ "micromark-util-combine-extensions": ["micromark-util-combine-extensions@2.0.1", "", { "dependencies": { "micromark-util-chunked": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-OnAnH8Ujmy59JcyZw8JSbK9cGpdVY44NKgSM7E9Eh7DiLS2E9RNQf0dONaGDzEG9yjEl5hcqeIsj4hfRkLH/Bg=="],
+
+ "micromark-util-decode-numeric-character-reference": ["micromark-util-decode-numeric-character-reference@2.0.2", "", { "dependencies": { "micromark-util-symbol": "^2.0.0" } }, "sha512-ccUbYk6CwVdkmCQMyr64dXz42EfHGkPQlBj5p7YVGzq8I7CtjXZJrubAYezf7Rp+bjPseiROqe7G6foFd+lEuw=="],
+
+ "micromark-util-decode-string": ["micromark-util-decode-string@2.0.1", "", { "dependencies": { "decode-named-character-reference": "^1.0.0", "micromark-util-character": "^2.0.0", "micromark-util-decode-numeric-character-reference": "^2.0.0", "micromark-util-symbol": "^2.0.0" } }, "sha512-nDV/77Fj6eH1ynwscYTOsbK7rR//Uj0bZXBwJZRfaLEJ1iGBR6kIfNmlNqaqJf649EP0F3NWNdeJi03elllNUQ=="],
+
+ "micromark-util-encode": ["micromark-util-encode@2.0.1", "", {}, "sha512-c3cVx2y4KqUnwopcO9b/SCdo2O67LwJJ/UyqGfbigahfegL9myoEFoDYZgkT7f36T0bLrM9hZTAaAyH+PCAXjw=="],
+
+ "micromark-util-events-to-acorn": ["micromark-util-events-to-acorn@2.0.3", "", { "dependencies": { "@types/estree": "^1.0.0", "@types/unist": "^3.0.0", "devlop": "^1.0.0", "estree-util-visit": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0", "vfile-message": "^4.0.0" } }, "sha512-jmsiEIiZ1n7X1Rr5k8wVExBQCg5jy4UXVADItHmNk1zkwEVhBuIUKRu3fqv+hs4nxLISi2DQGlqIOGiFxgbfHg=="],
+
+ "micromark-util-html-tag-name": ["micromark-util-html-tag-name@2.0.1", "", {}, "sha512-2cNEiYDhCWKI+Gs9T0Tiysk136SnR13hhO8yW6BGNyhOC4qYFnwF1nKfD3HFAIXA5c45RrIG1ub11GiXeYd1xA=="],
+
+ "micromark-util-normalize-identifier": ["micromark-util-normalize-identifier@2.0.1", "", { "dependencies": { "micromark-util-symbol": "^2.0.0" } }, "sha512-sxPqmo70LyARJs0w2UclACPUUEqltCkJ6PhKdMIDuJ3gSf/Q+/GIe3WKl0Ijb/GyH9lOpUkRAO2wp0GVkLvS9Q=="],
+
+ "micromark-util-resolve-all": ["micromark-util-resolve-all@2.0.1", "", { "dependencies": { "micromark-util-types": "^2.0.0" } }, "sha512-VdQyxFWFT2/FGJgwQnJYbe1jjQoNTS4RjglmSjTUlpUMa95Htx9NHeYW4rGDJzbjvCsl9eLjMQwGeElsqmzcHg=="],
+
+ "micromark-util-sanitize-uri": ["micromark-util-sanitize-uri@2.0.1", "", { "dependencies": { "micromark-util-character": "^2.0.0", "micromark-util-encode": "^2.0.0", "micromark-util-symbol": "^2.0.0" } }, "sha512-9N9IomZ/YuGGZZmQec1MbgxtlgougxTodVwDzzEouPKo3qFWvymFHWcnDi2vzV1ff6kas9ucW+o3yzJK9YB1AQ=="],
+
+ "micromark-util-subtokenize": ["micromark-util-subtokenize@2.1.0", "", { "dependencies": { "devlop": "^1.0.0", "micromark-util-chunked": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-XQLu552iSctvnEcgXw6+Sx75GflAPNED1qx7eBJ+wydBb2KCbRZe+NwvIEEMM83uml1+2WSXpBAcp9IUCgCYWA=="],
+
+ "micromark-util-symbol": ["micromark-util-symbol@2.0.1", "", {}, "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q=="],
+
+ "micromark-util-types": ["micromark-util-types@2.0.2", "", {}, "sha512-Yw0ECSpJoViF1qTU4DC6NwtC4aWGt1EkzaQB8KPPyCRR8z9TWeV0HbEFGTO+ZY1wB22zmxnJqhPyTpOVCpeHTA=="],
+
+ "micromatch": ["micromatch@4.0.8", "", { "dependencies": { "braces": "^3.0.3", "picomatch": "^2.3.1" } }, "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA=="],
+
+ "mime-db": ["mime-db@1.54.0", "", {}, "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ=="],
+
+ "mime-types": ["mime-types@3.0.2", "", { "dependencies": { "mime-db": "^1.54.0" } }, "sha512-Lbgzdk0h4juoQ9fCKXW4by0UJqj+nOOrI9MJ1sSj4nI8aI2eo1qmvQEie4VD1glsS250n15LsWsYtCugiStS5A=="],
+
+ "mimic-function": ["mimic-function@5.0.1", "", {}, "sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA=="],
+
+ "mimic-response": ["mimic-response@3.1.0", "", {}, "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ=="],
+
+ "min-indent": ["min-indent@1.0.1", "", {}, "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg=="],
+
+ "minimatch": ["minimatch@3.1.5", "", { "dependencies": { "brace-expansion": "^1.1.7" } }, "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w=="],
+
+ "minimist": ["minimist@1.2.8", "", {}, "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA=="],
+
+ "minipass": ["minipass@7.1.3", "", {}, "sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A=="],
+
+ "mixin-deep": ["mixin-deep@1.3.2", "", { "dependencies": { "for-in": "^1.0.2", "is-extendable": "^1.0.1" } }, "sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA=="],
+
+ "mkdirp-classic": ["mkdirp-classic@0.5.3", "", {}, "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A=="],
+
+ "mlly": ["mlly@1.8.2", "", { "dependencies": { "acorn": "^8.16.0", "pathe": "^2.0.3", "pkg-types": "^1.3.1", "ufo": "^1.6.3" } }, "sha512-d+ObxMQFmbt10sretNDytwt85VrbkhhUA/JBGm1MPaWJ65Cl4wOgLaB1NYvJSZ0Ef03MMEU/0xpPMXUIQ29UfA=="],
+
+ "monaco-editor": ["monaco-editor@0.55.1", "", { "dependencies": { "dompurify": "3.2.7", "marked": "14.0.0" } }, "sha512-jz4x+TJNFHwHtwuV9vA9rMujcZRb0CEilTEwG2rRSpe/A7Jdkuj8xPKttCgOh+v/lkHy7HsZ64oj+q3xoAFl9A=="],
+
+ "motion": ["motion@12.38.0", "", { "dependencies": { "framer-motion": "^12.38.0", "tslib": "^2.4.0" }, "peerDependencies": { "@emotion/is-prop-valid": "*", "react": "^18.0.0 || ^19.0.0", "react-dom": "^18.0.0 || ^19.0.0" } }, "sha512-uYfXzeHlgThchzwz5Te47dlv5JOUC7OB4rjJ/7XTUgtBZD8CchMN8qEJ4ZVsUmTyYA44zjV0fBwsiktRuFnn+w=="],
+
+ "motion-dom": ["motion-dom@12.38.0", "", { "dependencies": { "motion-utils": "^12.36.0" } }, "sha512-pdkHLD8QYRp8VfiNLb8xIBJis1byQ9gPT3Jnh2jqfFtAsWUA3dEepDlsWe/xMpO8McV+VdpKVcp+E+TGJEtOoA=="],
+
+ "motion-utils": ["motion-utils@12.36.0", "", {}, "sha512-eHWisygbiwVvf6PZ1vhaHCLamvkSbPIeAYxWUuL3a2PD/TROgE7FvfHWTIH4vMl798QLfMw15nRqIaRDXTlYRg=="],
+
+ "ms": ["ms@2.1.3", "", {}, "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="],
+
+ "nanoid": ["nanoid@3.3.11", "", { "bin": "bin/nanoid.cjs" }, "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w=="],
+
+ "napi-build-utils": ["napi-build-utils@2.0.0", "", {}, "sha512-GEbrYkbfF7MoNaoh2iGG84Mnf/WZfB0GdGEsM8wz7Expx/LlWf5U8t9nvJKXSp3qr5IsEbK04cBGhol/KwOsWA=="],
+
+ "napi-postinstall": ["napi-postinstall@0.3.4", "", { "bin": "lib/cli.js" }, "sha512-PHI5f1O0EP5xJ9gQmFGMS6IZcrVvTjpXjz7Na41gTE7eE2hK11lg04CECCYEEjdc17EV4DO+fkGEtt7TpTaTiQ=="],
+
+ "natural-compare": ["natural-compare@1.4.0", "", {}, "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw=="],
+
+ "negotiator": ["negotiator@1.0.0", "", {}, "sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg=="],
+
+ "next": ["next@16.1.7", "", { "dependencies": { "@next/env": "16.1.7", "@swc/helpers": "0.5.15", "baseline-browser-mapping": "^2.9.19", "caniuse-lite": "^1.0.30001579", "postcss": "8.4.31", "styled-jsx": "5.1.6" }, "optionalDependencies": { "@next/swc-darwin-arm64": "16.1.7", "@next/swc-darwin-x64": "16.1.7", "@next/swc-linux-arm64-gnu": "16.1.7", "@next/swc-linux-arm64-musl": "16.1.7", "@next/swc-linux-x64-gnu": "16.1.7", "@next/swc-linux-x64-musl": "16.1.7", "@next/swc-win32-arm64-msvc": "16.1.7", "@next/swc-win32-x64-msvc": "16.1.7", "sharp": "^0.34.4" }, "peerDependencies": { "@opentelemetry/api": "^1.1.0", "@playwright/test": "^1.51.1", "babel-plugin-react-compiler": "*", "react": "^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0", "react-dom": "^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0", "sass": "^1.3.0" }, "optionalPeers": ["@opentelemetry/api", "babel-plugin-react-compiler", "sass"], "bin": "dist/bin/next" }, "sha512-WM0L7WrSvKwoLegLYr6V+mz+RIofqQgVAfHhMp9a88ms0cFX8iX9ew+snpWlSBwpkURJOUdvCEt3uLl3NNzvWg=="],
+
+ "next-intl": ["next-intl@4.8.3", "", { "dependencies": { "@formatjs/intl-localematcher": "^0.8.1", "@parcel/watcher": "^2.4.1", "@swc/core": "^1.15.2", "icu-minify": "^4.8.3", "negotiator": "^1.0.0", "next-intl-swc-plugin-extractor": "^4.8.3", "po-parser": "^2.1.1", "use-intl": "^4.8.3" }, "peerDependencies": { "next": "^12.0.0 || ^13.0.0 || ^14.0.0 || ^15.0.0 || ^16.0.0", "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || >=19.0.0-rc <19.0.0 || ^19.0.0", "typescript": "^5.0.0" } }, "sha512-PvdBDWg+Leh7BR7GJUQbCDVVaBRn37GwDBWc9sv0rVQOJDQ5JU1rVzx9EEGuOGYo0DHAl70++9LQ7HxTawdL7w=="],
+
+ "next-intl-swc-plugin-extractor": ["next-intl-swc-plugin-extractor@4.8.3", "", {}, "sha512-YcaT+R9z69XkGhpDarVFWUprrCMbxgIQYPUaXoE6LGVnLjGdo8hu3gL6bramDVjNKViYY8a/pXPy7Bna0mXORg=="],
+
+ "node-abi": ["node-abi@3.87.0", "", { "dependencies": { "semver": "^7.3.5" } }, "sha512-+CGM1L1CgmtheLcBuleyYOn7NWPVu0s0EJH2C4puxgEZb9h8QpR9G2dBfZJOAUhi7VQxuBPMd0hiISWcTyiYyQ=="],
+
+ "node-addon-api": ["node-addon-api@4.3.0", "", {}, "sha512-73sE9+3UaLYYFmDsFZnqCInzPyh3MqIwZO9cw58yIqAZhONrrabrYyYe3TuIqtIiOuTXVhsGau8hcrhhwSsDIQ=="],
+
+ "node-machine-id": ["node-machine-id@1.1.12", "", {}, "sha512-QNABxbrPa3qEIfrE6GOJ7BYIuignnJw7iQ2YPbc3Nla1HzRJjXzZOiikfF8m7eAMfichLt3M4VgLOetqgDmgGQ=="],
+
+ "node-releases": ["node-releases@2.0.27", "", {}, "sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA=="],
+
+ "numeral": ["numeral@2.0.6", "", {}, "sha512-qaKRmtYPZ5qdw4jWJD6bxEf1FJEqllJrwxCLIm0sQU/A7v2/czigzOb+C2uSiFsa9lBUzeH7M1oK+Q+OLxL3kA=="],
+
+ "object-assign": ["object-assign@4.1.1", "", {}, "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg=="],
+
+ "object-inspect": ["object-inspect@1.13.4", "", {}, "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew=="],
+
+ "object-keys": ["object-keys@1.1.1", "", {}, "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA=="],
+
+ "object.assign": ["object.assign@4.1.7", "", { "dependencies": { "call-bind": "^1.0.8", "call-bound": "^1.0.3", "define-properties": "^1.2.1", "es-object-atoms": "^1.0.0", "has-symbols": "^1.1.0", "object-keys": "^1.1.1" } }, "sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw=="],
+
+ "object.entries": ["object.entries@1.1.9", "", { "dependencies": { "call-bind": "^1.0.8", "call-bound": "^1.0.4", "define-properties": "^1.2.1", "es-object-atoms": "^1.1.1" } }, "sha512-8u/hfXFRBD1O0hPUjioLhoWFHRmt6tKA4/vZPyckBr18l1KE9uHrFaFaUi8MDRTpi4uak2goyPTSNJLXX2k2Hw=="],
+
+ "object.fromentries": ["object.fromentries@2.0.8", "", { "dependencies": { "call-bind": "^1.0.7", "define-properties": "^1.2.1", "es-abstract": "^1.23.2", "es-object-atoms": "^1.0.0" } }, "sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ=="],
+
+ "object.groupby": ["object.groupby@1.0.3", "", { "dependencies": { "call-bind": "^1.0.7", "define-properties": "^1.2.1", "es-abstract": "^1.23.2" } }, "sha512-+Lhy3TQTuzXI5hevh8sBGqbmurHbbIjAi0Z4S63nthVLmLxfbj4T54a4CfZrXIrt9iP4mVAPYMo/v99taj3wjQ=="],
+
+ "object.values": ["object.values@1.2.1", "", { "dependencies": { "call-bind": "^1.0.8", "call-bound": "^1.0.3", "define-properties": "^1.2.1", "es-object-atoms": "^1.0.0" } }, "sha512-gXah6aZrcUxjWg2zR2MwouP2eHlCBzdV4pygudehaKXSGW4v2AsRQUK+lwwXhii6KFZcunEnmSUoYp5CXibxtA=="],
+
+ "obug": ["obug@2.1.1", "", {}, "sha512-uTqF9MuPraAQ+IsnPf366RG4cP9RtUi7MLO1N3KEc+wb0a6yKpeL0lmk2IB1jY5KHPAlTc6T/JRdC/YqxHNwkQ=="],
+
+ "on-change": ["on-change@4.0.2", "", {}, "sha512-cMtCyuJmTx/bg2HCpHo3ZLeF7FZnBOapLqZHr2AlLeJ5Ul0Zu2mUJJz051Fdwu/Et2YW04ZD+TtU+gVy0ACNCA=="],
+
+ "on-exit-leak-free": ["on-exit-leak-free@2.1.2", "", {}, "sha512-0eJJY6hXLGf1udHwfNftBqH+g73EU4B504nZeKpz1sYRKafAghwxEJunB2O7rDZkL4PGfsMVnTXZ2EjibbqcsA=="],
+
+ "on-finished": ["on-finished@2.4.1", "", { "dependencies": { "ee-first": "1.1.1" } }, "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg=="],
+
+ "once": ["once@1.4.0", "", { "dependencies": { "wrappy": "1" } }, "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w=="],
+
+ "onetime": ["onetime@7.0.0", "", { "dependencies": { "mimic-function": "^5.0.0" } }, "sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ=="],
+
+ "oniguruma-parser": ["oniguruma-parser@0.12.1", "", {}, "sha512-8Unqkvk1RYc6yq2WBYRj4hdnsAxVze8i7iPfQr8e4uSP3tRv0rpZcbGUDvxfQQcdwHt/e9PrMvGCsa8OqG9X3w=="],
+
+ "oniguruma-to-es": ["oniguruma-to-es@4.3.5", "", { "dependencies": { "oniguruma-parser": "^0.12.1", "regex": "^6.1.0", "regex-recursion": "^6.0.2" } }, "sha512-Zjygswjpsewa0NLTsiizVuMQZbp0MDyM6lIt66OxsF21npUDlzpHi1Mgb/qhQdkb+dWFTzJmFbEWdvZgRho8eQ=="],
+
+ "open": ["open@11.0.0", "", { "dependencies": { "default-browser": "^5.4.0", "define-lazy-prop": "^3.0.0", "is-in-ssh": "^1.0.0", "is-inside-container": "^1.0.0", "powershell-utils": "^0.1.0", "wsl-utils": "^0.3.0" } }, "sha512-smsWv2LzFjP03xmvFoJ331ss6h+jixfA4UUV/Bsiyuu4YJPfN+FIQGOIiv4w9/+MoHkfkJ22UIaQWRVFRfH6Vw=="],
+
+ "optionator": ["optionator@0.9.4", "", { "dependencies": { "deep-is": "^0.1.3", "fast-levenshtein": "^2.0.6", "levn": "^0.4.1", "prelude-ls": "^1.2.1", "type-check": "^0.4.0", "word-wrap": "^1.2.5" } }, "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g=="],
+
+ "ora": ["ora@9.3.0", "", { "dependencies": { "chalk": "^5.6.2", "cli-cursor": "^5.0.0", "cli-spinners": "^3.2.0", "is-interactive": "^2.0.0", "is-unicode-supported": "^2.1.0", "log-symbols": "^7.0.1", "stdin-discarder": "^0.3.1", "string-width": "^8.1.0" } }, "sha512-lBX72MWFduWEf7v7uWf5DHp9Jn5BI8bNPGuFgtXMmr2uDz2Gz2749y3am3agSDdkhHPHYmmxEGSKH85ZLGzgXw=="],
+
+ "own-keys": ["own-keys@1.0.1", "", { "dependencies": { "get-intrinsic": "^1.2.6", "object-keys": "^1.1.1", "safe-push-apply": "^1.0.0" } }, "sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg=="],
+
+ "p-limit": ["p-limit@3.1.0", "", { "dependencies": { "yocto-queue": "^0.1.0" } }, "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ=="],
+
+ "p-locate": ["p-locate@5.0.0", "", { "dependencies": { "p-limit": "^3.0.2" } }, "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw=="],
+
+ "package-manager-detector": ["package-manager-detector@1.6.0", "", {}, "sha512-61A5ThoTiDG/C8s8UMZwSorAGwMJ0ERVGj2OjoW5pAalsNOg15+iQiPzrLJ4jhZ1HJzmC2PIHT2oEiH3R5fzNA=="],
+
+ "parent-module": ["parent-module@1.0.1", "", { "dependencies": { "callsites": "^3.0.0" } }, "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g=="],
+
+ "parse-entities": ["parse-entities@4.0.2", "", { "dependencies": { "@types/unist": "^2.0.0", "character-entities-legacy": "^3.0.0", "character-reference-invalid": "^2.0.0", "decode-named-character-reference": "^1.0.0", "is-alphanumerical": "^2.0.0", "is-decimal": "^2.0.0", "is-hexadecimal": "^2.0.0" } }, "sha512-GG2AQYWoLgL877gQIKeRPGO1xF9+eG1ujIb5soS5gPvLQ1y2o8FL90w2QWNdf9I361Mpp7726c+lj3U0qK1uGw=="],
+
+ "parse-json": ["parse-json@5.2.0", "", { "dependencies": { "@babel/code-frame": "^7.0.0", "error-ex": "^1.3.1", "json-parse-even-better-errors": "^2.3.0", "lines-and-columns": "^1.1.6" } }, "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg=="],
+
+ "parse5": ["parse5@8.0.0", "", { "dependencies": { "entities": "^6.0.0" } }, "sha512-9m4m5GSgXjL4AjumKzq1Fgfp3Z8rsvjRNbnkVwfu2ImRqE5D0LnY2QfDen18FSY9C573YU5XxSapdHZTZ2WolA=="],
+
+ "parseurl": ["parseurl@1.3.3", "", {}, "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ=="],
+
+ "path-data-parser": ["path-data-parser@0.1.0", "", {}, "sha512-NOnmBpt5Y2RWbuv0LMzsayp3lVylAHLPUTut412ZA3l+C4uw4ZVkQbjShYCQ8TCpUMdPapr4YjUqLYD6v68j+w=="],
+
+ "path-exists": ["path-exists@4.0.0", "", {}, "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w=="],
+
+ "path-key": ["path-key@3.1.1", "", {}, "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q=="],
+
+ "path-parse": ["path-parse@1.0.7", "", {}, "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw=="],
+
+ "path-scurry": ["path-scurry@2.0.2", "", { "dependencies": { "lru-cache": "^11.0.0", "minipass": "^7.1.2" } }, "sha512-3O/iVVsJAPsOnpwWIeD+d6z/7PmqApyQePUtCndjatj/9I5LylHvt5qluFaBT3I5h3r1ejfR056c+FCv+NnNXg=="],
+
+ "path-to-regexp": ["path-to-regexp@8.4.0", "", {}, "sha512-PuseHIvAnz3bjrM2rGJtSgo1zjgxapTLZ7x2pjhzWwlp4SJQgK3f3iZIQwkpEnBaKz6seKBADpM4B4ySkuYypg=="],
+
+ "path-type": ["path-type@4.0.0", "", {}, "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw=="],
+
+ "pathe": ["pathe@2.0.3", "", {}, "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w=="],
+
+ "picocolors": ["picocolors@1.1.1", "", {}, "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA=="],
+
+ "picomatch": ["picomatch@4.0.4", "", {}, "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A=="],
+
+ "pino": ["pino@10.3.1", "", { "dependencies": { "@pinojs/redact": "^0.4.0", "atomic-sleep": "^1.0.0", "on-exit-leak-free": "^2.1.0", "pino-abstract-transport": "^3.0.0", "pino-std-serializers": "^7.0.0", "process-warning": "^5.0.0", "quick-format-unescaped": "^4.0.3", "real-require": "^0.2.0", "safe-stable-stringify": "^2.3.1", "sonic-boom": "^4.0.1", "thread-stream": "^4.0.0" }, "bin": "bin.js" }, "sha512-r34yH/GlQpKZbU1BvFFqOjhISRo1MNx1tWYsYvmj6KIRHSPMT2+yHOEb1SG6NMvRoHRF0a07kCOox/9yakl1vg=="],
+
+ "pino-abstract-transport": ["pino-abstract-transport@3.0.0", "", { "dependencies": { "split2": "^4.0.0" } }, "sha512-wlfUczU+n7Hy/Ha5j9a/gZNy7We5+cXp8YL+X+PG8S0KXxw7n/JXA3c46Y0zQznIJ83URJiwy7Lh56WLokNuxg=="],
+
+ "pino-pretty": ["pino-pretty@13.1.3", "", { "dependencies": { "colorette": "^2.0.7", "dateformat": "^4.6.3", "fast-copy": "^4.0.0", "fast-safe-stringify": "^2.1.1", "help-me": "^5.0.0", "joycon": "^3.1.1", "minimist": "^1.2.6", "on-exit-leak-free": "^2.1.0", "pino-abstract-transport": "^3.0.0", "pump": "^3.0.0", "secure-json-parse": "^4.0.0", "sonic-boom": "^4.0.1", "strip-json-comments": "^5.0.2" }, "bin": "bin.js" }, "sha512-ttXRkkOz6WWC95KeY9+xxWL6AtImwbyMHrL1mSwqwW9u+vLp/WIElvHvCSDg0xO/Dzrggz1zv3rN5ovTRVowKg=="],
+
+ "pino-std-serializers": ["pino-std-serializers@7.1.0", "", {}, "sha512-BndPH67/JxGExRgiX1dX0w1FvZck5Wa4aal9198SrRhZjH3GxKQUKIBnYJTdj2HDN3UQAS06HlfcSbQj2OHmaw=="],
+
+ "pkce-challenge": ["pkce-challenge@5.0.1", "", {}, "sha512-wQ0b/W4Fr01qtpHlqSqspcj3EhBvimsdh0KlHhH8HRZnMsEa0ea2fTULOXOS9ccQr3om+GcGRk4e+isrZWV8qQ=="],
+
+ "pkg-types": ["pkg-types@1.3.1", "", { "dependencies": { "confbox": "^0.1.8", "mlly": "^1.7.4", "pathe": "^2.0.1" } }, "sha512-/Jm5M4RvtBFVkKWRu2BLUTNP8/M2a+UwuAX+ae4770q1qVGtfjG+WTCupoZixokjmHiry8uI+dlY8KXYV5HVVQ=="],
+
+ "pkijs": ["pkijs@3.3.3", "", { "dependencies": { "@noble/hashes": "1.4.0", "asn1js": "^3.0.6", "bytestreamjs": "^2.0.1", "pvtsutils": "^1.3.6", "pvutils": "^1.1.3", "tslib": "^2.8.1" } }, "sha512-+KD8hJtqQMYoTuL1bbGOqxb4z+nZkTAwVdNtWwe8Tc2xNbEmdJYIYoc6Qt0uF55e6YW6KuTHw1DjQ18gMhzepw=="],
+
+ "playwright": ["playwright@1.58.2", "", { "dependencies": { "playwright-core": "1.58.2" }, "optionalDependencies": { "fsevents": "2.3.2" }, "bin": "cli.js" }, "sha512-vA30H8Nvkq/cPBnNw4Q8TWz1EJyqgpuinBcHET0YVJVFldr8JDNiU9LaWAE1KqSkRYazuaBhTpB5ZzShOezQ6A=="],
+
+ "playwright-core": ["playwright-core@1.58.2", "", { "bin": "cli.js" }, "sha512-yZkEtftgwS8CsfYo7nm0KE8jsvm6i/PTgVtB8DL726wNf6H2IMsDuxCpJj59KDaxCtSnrWan2AeDqM7JBaultg=="],
+
+ "po-parser": ["po-parser@2.1.1", "", {}, "sha512-ECF4zHLbUItpUgE3OTtLKlPjeBN+fKEczj2zYjDfCGOzicNs0GK3Vg2IoAYwx7LH/XYw43fZQP6xnZ4TkNxSLQ=="],
+
+ "points-on-curve": ["points-on-curve@0.2.0", "", {}, "sha512-0mYKnYYe9ZcqMCWhUjItv/oHjvgEsfKvnUTg8sAtnHr3GVy7rGkXCb6d5cSyqrWqL4k81b9CPg3urd+T7aop3A=="],
+
+ "points-on-path": ["points-on-path@0.2.1", "", { "dependencies": { "path-data-parser": "0.1.0", "points-on-curve": "0.2.0" } }, "sha512-25ClnWWuw7JbWZcgqY/gJ4FQWadKxGWk+3kR/7kD0tCaDtPPMj7oHu2ToLaVhfpnHrZzYby2w6tUA0eOIuUg8g=="],
+
+ "polished": ["polished@4.3.1", "", { "dependencies": { "@babel/runtime": "^7.17.8" } }, "sha512-OBatVyC/N7SCW/FaDHrSd+vn0o5cS855TOmYi4OkdWUMSJCET/xip//ch8xGUvtr3i44X9LVyWwQlRMTN3pwSA=="],
+
+ "possible-typed-array-names": ["possible-typed-array-names@1.1.0", "", {}, "sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg=="],
+
+ "postcss": ["postcss@8.5.8", "", { "dependencies": { "nanoid": "^3.3.11", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-OW/rX8O/jXnm82Ey1k44pObPtdblfiuWnrd8X7GJ7emImCOstunGbXUpp7HdBrFQX6rJzn3sPT397Wp5aCwCHg=="],
+
+ "powershell-utils": ["powershell-utils@0.1.0", "", {}, "sha512-dM0jVuXJPsDN6DvRpea484tCUaMiXWjuCn++HGTqUWzGDjv5tZkEZldAJ/UMlqRYGFrD/etByo4/xOuC/snX2A=="],
+
+ "prebuild-install": ["prebuild-install@7.1.3", "", { "dependencies": { "detect-libc": "^2.0.0", "expand-template": "^2.0.3", "github-from-package": "0.0.0", "minimist": "^1.2.3", "mkdirp-classic": "^0.5.3", "napi-build-utils": "^2.0.0", "node-abi": "^3.3.0", "pump": "^3.0.0", "rc": "^1.2.7", "simple-get": "^4.0.0", "tar-fs": "^2.0.0", "tunnel-agent": "^0.6.0" }, "bin": "bin.js" }, "sha512-8Mf2cbV7x1cXPUILADGI3wuhfqWvtiLA1iclTDbFRZkgRQS0NqsPZphna9V+HyTEadheuPmjaJMsbzKQFOzLug=="],
+
+ "prelude-ls": ["prelude-ls@1.2.1", "", {}, "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g=="],
+
+ "prettier": ["prettier@3.8.1", "", { "bin": "bin/prettier.cjs" }, "sha512-UOnG6LftzbdaHZcKoPFtOcCKztrQ57WkHDeRD9t/PTQtmT0NHSeWWepj6pS0z/N7+08BHFDQVUrfmfMRcZwbMg=="],
+
+ "pretty-format": ["pretty-format@27.5.1", "", { "dependencies": { "ansi-regex": "^5.0.1", "ansi-styles": "^5.0.0", "react-is": "^17.0.1" } }, "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ=="],
+
+ "process-warning": ["process-warning@5.0.0", "", {}, "sha512-a39t9ApHNx2L4+HBnQKqxxHNs1r7KF+Intd8Q/g1bUh6q0WIp9voPXJ/x0j+ZL45KF1pJd9+q2jLIRMfvEshkA=="],
+
+ "prop-types": ["prop-types@15.8.1", "", { "dependencies": { "loose-envify": "^1.4.0", "object-assign": "^4.1.1", "react-is": "^16.13.1" } }, "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg=="],
+
+ "property-information": ["property-information@7.1.0", "", {}, "sha512-TwEZ+X+yCJmYfL7TPUOcvBZ4QfoT5YenQiJuX//0th53DE6w0xxLEtfK3iyryQFddXuvkIk51EEgrJQ0WJkOmQ=="],
+
+ "proxy-addr": ["proxy-addr@2.0.7", "", { "dependencies": { "forwarded": "0.2.0", "ipaddr.js": "1.9.1" } }, "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg=="],
+
+ "proxy-from-env": ["proxy-from-env@1.1.0", "", {}, "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg=="],
+
+ "pump": ["pump@3.0.3", "", { "dependencies": { "end-of-stream": "^1.1.0", "once": "^1.3.1" } }, "sha512-todwxLMY7/heScKmntwQG8CXVkWUOdYxIvY2s0VWAAMh/nd8SoYiRaKjlr7+iCs984f2P8zvrfWcDDYVb73NfA=="],
+
+ "punycode": ["punycode@2.3.1", "", {}, "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg=="],
+
+ "pvtsutils": ["pvtsutils@1.3.6", "", { "dependencies": { "tslib": "^2.8.1" } }, "sha512-PLgQXQ6H2FWCaeRak8vvk1GW462lMxB5s3Jm673N82zI4vqtVUPuZdffdZbPDFRoU8kAhItWFtPCWiPpp4/EDg=="],
+
+ "pvutils": ["pvutils@1.1.5", "", {}, "sha512-KTqnxsgGiQ6ZAzZCVlJH5eOjSnvlyEgx1m8bkRJfOhmGRqfo5KLvmAlACQkrjEtOQ4B7wF9TdSLIs9O90MX9xA=="],
+
+ "qs": ["qs@6.14.2", "", { "dependencies": { "side-channel": "^1.1.0" } }, "sha512-V/yCWTTF7VJ9hIh18Ugr2zhJMP01MY7c5kh4J870L7imm6/DIzBsNLTXzMwUA3yZ5b/KBqLx8Kp3uRvd7xSe3Q=="],
+
+ "query-string": ["query-string@9.3.1", "", { "dependencies": { "decode-uri-component": "^0.4.1", "filter-obj": "^5.1.0", "split-on-first": "^3.0.0" } }, "sha512-5fBfMOcDi5SA9qj5jZhWAcTtDfKF5WFdd2uD9nVNlbxVv1baq65aALy6qofpNEGELHvisjjasxQp7BlM9gvMzw=="],
+
+ "queue-microtask": ["queue-microtask@1.2.3", "", {}, "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A=="],
+
+ "quick-format-unescaped": ["quick-format-unescaped@4.0.4", "", {}, "sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg=="],
+
+ "range-parser": ["range-parser@1.2.1", "", {}, "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg=="],
+
+ "raw-body": ["raw-body@3.0.2", "", { "dependencies": { "bytes": "~3.1.2", "http-errors": "~2.0.1", "iconv-lite": "~0.7.0", "unpipe": "~1.0.0" } }, "sha512-K5zQjDllxWkf7Z5xJdV0/B0WTNqx6vxG70zJE4N0kBs4LovmEYWJzQGxC9bS9RAKu3bgM40lrd5zoLJ12MQ5BA=="],
+
+ "rc": ["rc@1.2.8", "", { "dependencies": { "deep-extend": "^0.6.0", "ini": "~1.3.0", "minimist": "^1.2.0", "strip-json-comments": "~2.0.1" }, "bin": "cli.js" }, "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw=="],
+
+ "rc-collapse": ["rc-collapse@4.0.0", "", { "dependencies": { "@babel/runtime": "^7.10.1", "classnames": "2.x", "rc-motion": "^2.3.4", "rc-util": "^5.27.0" }, "peerDependencies": { "react": ">=16.9.0", "react-dom": ">=16.9.0" } }, "sha512-SwoOByE39/3oIokDs/BnkqI+ltwirZbP8HZdq1/3SkPSBi7xDdvWHTp7cpNI9ullozkR6mwTWQi6/E/9huQVrA=="],
+
+ "rc-dialog": ["rc-dialog@9.6.0", "", { "dependencies": { "@babel/runtime": "^7.10.1", "@rc-component/portal": "^1.0.0-8", "classnames": "^2.2.6", "rc-motion": "^2.3.0", "rc-util": "^5.21.0" }, "peerDependencies": { "react": ">=16.9.0", "react-dom": ">=16.9.0" } }, "sha512-ApoVi9Z8PaCQg6FsUzS8yvBEQy0ZL2PkuvAgrmohPkN3okps5WZ5WQWPc1RNuiOKaAYv8B97ACdsFU5LizzCqg=="],
+
+ "rc-footer": ["rc-footer@0.6.8", "", { "dependencies": { "@babel/runtime": "^7.11.1", "classnames": "^2.2.1" }, "peerDependencies": { "react": ">=16.0.0", "react-dom": ">=16.0.0" } }, "sha512-JBZ+xcb6kkex8XnBd4VHw1ZxjV6kmcwUumSHaIFdka2qzMCo7Klcy4sI6G0XtUpG/vtpislQCc+S9Bc+NLHYMg=="],
+
+ "rc-image": ["rc-image@7.12.0", "", { "dependencies": { "@babel/runtime": "^7.11.2", "@rc-component/portal": "^1.0.2", "classnames": "^2.2.6", "rc-dialog": "~9.6.0", "rc-motion": "^2.6.2", "rc-util": "^5.34.1" }, "peerDependencies": { "react": ">=16.9.0", "react-dom": ">=16.9.0" } }, "sha512-cZ3HTyyckPnNnUb9/DRqduqzLfrQRyi+CdHjdqgsyDpI3Ln5UX1kXnAhPBSJj9pVRzwRFgqkN7p9b6HBDjmu/Q=="],
+
+ "rc-input": ["rc-input@1.8.0", "", { "dependencies": { "@babel/runtime": "^7.11.1", "classnames": "^2.2.1", "rc-util": "^5.18.1" }, "peerDependencies": { "react": ">=16.0.0", "react-dom": ">=16.0.0" } }, "sha512-KXvaTbX+7ha8a/k+eg6SYRVERK0NddX8QX7a7AnRvUa/rEH0CNMlpcBzBkhI0wp2C8C4HlMoYl8TImSN+fuHKA=="],
+
+ "rc-input-number": ["rc-input-number@9.5.0", "", { "dependencies": { "@babel/runtime": "^7.10.1", "@rc-component/mini-decimal": "^1.0.1", "classnames": "^2.2.5", "rc-input": "~1.8.0", "rc-util": "^5.40.1" }, "peerDependencies": { "react": ">=16.9.0", "react-dom": ">=16.9.0" } }, "sha512-bKaEvB5tHebUURAEXw35LDcnRZLq3x1k7GxfAqBMzmpHkDGzjAtnUL8y4y5N15rIFIg5IJgwr211jInl3cipag=="],
+
+ "rc-menu": ["rc-menu@9.16.1", "", { "dependencies": { "@babel/runtime": "^7.10.1", "@rc-component/trigger": "^2.0.0", "classnames": "2.x", "rc-motion": "^2.4.3", "rc-overflow": "^1.3.1", "rc-util": "^5.27.0" }, "peerDependencies": { "react": ">=16.9.0", "react-dom": ">=16.9.0" } }, "sha512-ghHx6/6Dvp+fw8CJhDUHFHDJ84hJE3BXNCzSgLdmNiFErWSOaZNsihDAsKq9ByTALo/xkNIwtDFGIl6r+RPXBg=="],
+
+ "rc-motion": ["rc-motion@2.9.5", "", { "dependencies": { "@babel/runtime": "^7.11.1", "classnames": "^2.2.1", "rc-util": "^5.44.0" }, "peerDependencies": { "react": ">=16.9.0", "react-dom": ">=16.9.0" } }, "sha512-w+XTUrfh7ArbYEd2582uDrEhmBHwK1ZENJiSJVb7uRxdE7qJSYjbO2eksRXmndqyKqKoYPc9ClpPh5242mV1vA=="],
+
+ "rc-overflow": ["rc-overflow@1.5.0", "", { "dependencies": { "@babel/runtime": "^7.11.1", "classnames": "^2.2.1", "rc-resize-observer": "^1.0.0", "rc-util": "^5.37.0" }, "peerDependencies": { "react": ">=16.9.0", "react-dom": ">=16.9.0" } }, "sha512-Lm/v9h0LymeUYJf0x39OveU52InkdRXqnn2aYXfWmo8WdOonIKB2kfau+GF0fWq6jPgtdO9yMqveGcK6aIhJmg=="],
+
+ "rc-resize-observer": ["rc-resize-observer@1.4.3", "", { "dependencies": { "@babel/runtime": "^7.20.7", "classnames": "^2.2.1", "rc-util": "^5.44.1", "resize-observer-polyfill": "^1.5.1" }, "peerDependencies": { "react": ">=16.9.0", "react-dom": ">=16.9.0" } }, "sha512-YZLjUbyIWox8E9i9C3Tm7ia+W7euPItNWSPX5sCcQTYbnwDb5uNpnLHQCG1f22oZWUhLw4Mv2tFmeWe68CDQRQ=="],
+
+ "rc-util": ["rc-util@5.44.4", "", { "dependencies": { "@babel/runtime": "^7.18.3", "react-is": "^18.2.0" }, "peerDependencies": { "react": ">=16.9.0", "react-dom": ">=16.9.0" } }, "sha512-resueRJzmHG9Q6rI/DfK6Kdv9/Lfls05vzMs1Sk3M2P+3cJa+MakaZyWY8IPfehVuhPJFKrIY1IK4GqbiaiY5w=="],
+
+ "re-resizable": ["re-resizable@6.11.2", "", { "peerDependencies": { "react": "^16.13.1 || ^17.0.0 || ^18.0.0 || ^19.0.0", "react-dom": "^16.13.1 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, "sha512-2xI2P3OHs5qw7K0Ud1aLILK6MQxW50TcO+DetD9eIV58j84TqYeHoZcL9H4GXFXXIh7afhH8mv5iUCXII7OW7A=="],
+
+ "react": ["react@19.2.4", "", {}, "sha512-9nfp2hYpCwOjAN+8TZFGhtWEwgvWHXqESH8qT89AT/lWklpLON22Lc8pEtnpsZz7VmawabSU0gCjnj8aC0euHQ=="],
+
+ "react-avatar-editor": ["react-avatar-editor@14.0.0", "", { "peerDependencies": { "react": "^0.14.0 || ^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", "react-dom": "^0.14.0 || ^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, "sha512-NaQM3oo4u0a1/Njjutc2FjwKX35vQV+t6S8hovsbAlMpBN1ntIwP/g+Yr9eDIIfaNtRXL0AqboTnPmRxhD/i8A=="],
+
+ "react-colorful": ["react-colorful@5.6.1", "", { "peerDependencies": { "react": ">=16.8.0", "react-dom": ">=16.8.0" } }, "sha512-1exovf0uGTGyq5mXQT0zgQ80uvj2PCwvF8zY1RN9/vbJVSjSo3fsB/4L3ObbF7u70NduSiK4xu4Y6q1MHoUGEw=="],
+
+ "react-dom": ["react-dom@19.2.4", "", { "dependencies": { "scheduler": "^0.27.0" }, "peerDependencies": { "react": "^19.2.4" } }, "sha512-AXJdLo8kgMbimY95O2aKQqsz2iWi9jMgKJhRBAxECE4IFxfcazB2LmzloIoibJI3C12IlY20+KFaLv+71bUJeQ=="],
+
+ "react-draggable": ["react-draggable@4.5.0", "", { "dependencies": { "clsx": "^2.1.1", "prop-types": "^15.8.1" }, "peerDependencies": { "react": ">= 16.3.0", "react-dom": ">= 16.3.0" } }, "sha512-VC+HBLEZ0XJxnOxVAZsdRi8rD04Iz3SiiKOoYzamjylUcju/hP9np/aZdLHf/7WOD268WMoNJMvYfB5yAK45cw=="],
+
+ "react-dropzone": ["react-dropzone@12.1.0", "", { "dependencies": { "attr-accept": "^2.2.2", "file-selector": "^0.5.0", "prop-types": "^15.8.1" }, "peerDependencies": { "react": ">= 16.8" } }, "sha512-iBYHA1rbopIvtzokEX4QubO6qk5IF/x3BtKGu74rF2JkQDXnwC4uO/lHKpaw4PJIV6iIAYOlwLv2FpiGyqHNog=="],
+
+ "react-error-boundary": ["react-error-boundary@6.1.1", "", { "peerDependencies": { "react": "^18.0.0 || ^19.0.0" } }, "sha512-BrYwPOdXi5mqkk5lw+Uvt0ThHx32rCt3BkukS4X23A2AIWDPSGX6iaWTc0y9TU/mHDA/6qOSGel+B2ERkOvD1w=="],
+
+ "react-fast-compare": ["react-fast-compare@3.2.2", "", {}, "sha512-nsO+KSNgo1SbJqJEYRE9ERzo7YtYbou/OqjSQKxV7jcKox7+usiUVZOAC+XnDOABXggQTno0Y1CpVnuWEc1boQ=="],
+
+ "react-hotkeys-hook": ["react-hotkeys-hook@5.2.4", "", { "peerDependencies": { "react": ">=16.8.0", "react-dom": ">=16.8.0" } }, "sha512-BgKg+A1+TawkYluh5Bo4cTmcgMN5L29uhJbDUQdHwPX+qgXRjIPYU5kIDHyxnAwCkCBiu9V5OpB2mpyeluVF2A=="],
+
+ "react-is": ["react-is@16.13.1", "", {}, "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="],
+
+ "react-markdown": ["react-markdown@10.1.0", "", { "dependencies": { "@types/hast": "^3.0.0", "@types/mdast": "^4.0.0", "devlop": "^1.0.0", "hast-util-to-jsx-runtime": "^2.0.0", "html-url-attributes": "^3.0.0", "mdast-util-to-hast": "^13.0.0", "remark-parse": "^11.0.0", "remark-rehype": "^11.0.0", "unified": "^11.0.0", "unist-util-visit": "^5.0.0", "vfile": "^6.0.0" }, "peerDependencies": { "@types/react": ">=18", "react": ">=18" } }, "sha512-qKxVopLT/TyA6BX3Ue5NwabOsAzm0Q7kAPwq6L+wWDwisYs7R8vZ0nRXqq6rkueboxpkjvLGU9fWifiX/ZZFxQ=="],
+
+ "react-merge-refs": ["react-merge-refs@3.0.2", "", { "peerDependencies": { "react": ">=16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, "sha512-MSZAfwFfdbEvwkKWP5EI5chuLYnNUxNS7vyS0i1Jp+wtd8J4Ga2ddzhaE68aMol2Z4vCnRM/oGOo1a3V75UPlw=="],
+
+ "react-redux": ["react-redux@9.2.0", "", { "dependencies": { "@types/use-sync-external-store": "^0.0.6", "use-sync-external-store": "^1.4.0" }, "peerDependencies": { "@types/react": "^18.2.25 || ^19", "react": "^18.0 || ^19", "redux": "^5.0.0" } }, "sha512-ROY9fvHhwOD9ySfrF0wmvu//bKCQ6AeZZq1nJNtbDC+kk5DuSuNX/n6YWYF/SYy7bSba4D4FSz8DJeKY/S/r+g=="],
+
+ "react-rnd": ["react-rnd@10.5.3", "", { "dependencies": { "re-resizable": "^6.11.2", "react-draggable": "^4.5.0", "tslib": "2.6.2" }, "peerDependencies": { "react": ">=16.3.0", "react-dom": ">=16.3.0" } }, "sha512-s/sIT3pGZnQ+57egijkTp9mizjIWrJz68Pq6yd+F/wniFY3IriML18dUXnQe/HP9uMiJ+9MAp44hljG99fZu6Q=="],
+
+ "react-zoom-pan-pinch": ["react-zoom-pan-pinch@3.7.0", "", { "peerDependencies": { "react": "*", "react-dom": "*" } }, "sha512-UmReVZ0TxlKzxSbYiAj+LeGRW8s8LraAFTXRAxzMYnNRgGPsxCudwZKVkjvGmjtx7SW/hZamt69NUmGf4xrkXA=="],
+
+ "readable-stream": ["readable-stream@3.6.2", "", { "dependencies": { "inherits": "^2.0.3", "string_decoder": "^1.1.1", "util-deprecate": "^1.0.1" } }, "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA=="],
+
+ "real-require": ["real-require@0.2.0", "", {}, "sha512-57frrGM/OCTLqLOAh0mhVA9VBMHd+9U7Zb2THMGdBUoZVOtGbJzjxsYGDJ3A9AYYCP4hn6y1TVbaOfzWtm5GFg=="],
+
+ "recharts": ["recharts@3.8.0", "", { "dependencies": { "@reduxjs/toolkit": "^1.9.0 || 2.x.x", "clsx": "^2.1.1", "decimal.js-light": "^2.5.1", "es-toolkit": "^1.39.3", "eventemitter3": "^5.0.1", "immer": "^10.1.1", "react-redux": "8.x.x || 9.x.x", "reselect": "5.1.1", "tiny-invariant": "^1.3.3", "use-sync-external-store": "^1.2.2", "victory-vendor": "^37.0.2" }, "peerDependencies": { "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", "react-dom": "^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", "react-is": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, "sha512-Z/m38DX3L73ExO4Tpc9/iZWHmHnlzWG4njQbxsF5aSjwqmHNDDIm0rdEBArkwsBvR8U6EirlEHiQNYWCVh9sGQ=="],
+
+ "recma-build-jsx": ["recma-build-jsx@1.0.0", "", { "dependencies": { "@types/estree": "^1.0.0", "estree-util-build-jsx": "^3.0.0", "vfile": "^6.0.0" } }, "sha512-8GtdyqaBcDfva+GUKDr3nev3VpKAhup1+RvkMvUxURHpW7QyIvk9F5wz7Vzo06CEMSilw6uArgRqhpiUcWp8ew=="],
+
+ "recma-jsx": ["recma-jsx@1.0.1", "", { "dependencies": { "acorn-jsx": "^5.0.0", "estree-util-to-js": "^2.0.0", "recma-parse": "^1.0.0", "recma-stringify": "^1.0.0", "unified": "^11.0.0" }, "peerDependencies": { "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, "sha512-huSIy7VU2Z5OLv6oFLosQGGDqPqdO1iq6bWNAdhzMxSJP7RAso4fCZ1cKu8j9YHCZf3TPrq4dw3okhrylgcd7w=="],
+
+ "recma-parse": ["recma-parse@1.0.0", "", { "dependencies": { "@types/estree": "^1.0.0", "esast-util-from-js": "^2.0.0", "unified": "^11.0.0", "vfile": "^6.0.0" } }, "sha512-OYLsIGBB5Y5wjnSnQW6t3Xg7q3fQ7FWbw/vcXtORTnyaSFscOtABg+7Pnz6YZ6c27fG1/aN8CjfwoUEUIdwqWQ=="],
+
+ "recma-stringify": ["recma-stringify@1.0.0", "", { "dependencies": { "@types/estree": "^1.0.0", "estree-util-to-js": "^2.0.0", "unified": "^11.0.0", "vfile": "^6.0.0" } }, "sha512-cjwII1MdIIVloKvC9ErQ+OgAtwHBmcZ0Bg4ciz78FtbT8In39aAYbaA7zvxQ61xVMSPE8WxhLwLbhif4Js2C+g=="],
+
+ "redent": ["redent@3.0.0", "", { "dependencies": { "indent-string": "^4.0.0", "strip-indent": "^3.0.0" } }, "sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg=="],
+
+ "redux": ["redux@5.0.1", "", {}, "sha512-M9/ELqF6fy8FwmkpnF0S3YKOqMyoWJ4+CS5Efg2ct3oY9daQvd/Pc71FpGZsVsbl3Cpb+IIcjBDUnnyBdQbq4w=="],
+
+ "redux-thunk": ["redux-thunk@3.1.0", "", { "peerDependencies": { "redux": "^5.0.0" } }, "sha512-NW2r5T6ksUKXCabzhL9z+h206HQw/NJkcLm1GPImRQ8IzfXwRGqjVhKJGauHirT0DAuyy6hjdnMZaRoAcy0Klw=="],
+
+ "reflect-metadata": ["reflect-metadata@0.2.2", "", {}, "sha512-urBwgfrvVP/eAyXx4hluJivBKzuEbSQs9rKWCrCkbSxNv8mxPcUZKeuoF3Uy4mJl3Lwprp6yy5/39VWigZ4K6Q=="],
+
+ "reflect.getprototypeof": ["reflect.getprototypeof@1.0.10", "", { "dependencies": { "call-bind": "^1.0.8", "define-properties": "^1.2.1", "es-abstract": "^1.23.9", "es-errors": "^1.3.0", "es-object-atoms": "^1.0.0", "get-intrinsic": "^1.2.7", "get-proto": "^1.0.1", "which-builtin-type": "^1.2.1" } }, "sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw=="],
+
+ "regex": ["regex@6.1.0", "", { "dependencies": { "regex-utilities": "^2.3.0" } }, "sha512-6VwtthbV4o/7+OaAF9I5L5V3llLEsoPyq9P1JVXkedTP33c7MfCG0/5NOPcSJn0TzXcG9YUrR0gQSWioew3LDg=="],
+
+ "regex-recursion": ["regex-recursion@6.0.2", "", { "dependencies": { "regex-utilities": "^2.3.0" } }, "sha512-0YCaSCq2VRIebiaUviZNs0cBz1kg5kVS2UKUfNIx8YVs1cN3AV7NTctO5FOKBA+UT2BPJIWZauYHPqJODG50cg=="],
+
+ "regex-utilities": ["regex-utilities@2.3.0", "", {}, "sha512-8VhliFJAWRaUiVvREIiW2NXXTmHs4vMNnSzuJVhscgmGav3g9VDxLrQndI3dZZVVdp0ZO/5v0xmX516/7M9cng=="],
+
+ "regexp.prototype.flags": ["regexp.prototype.flags@1.5.4", "", { "dependencies": { "call-bind": "^1.0.8", "define-properties": "^1.2.1", "es-errors": "^1.3.0", "get-proto": "^1.0.1", "gopd": "^1.2.0", "set-function-name": "^2.0.2" } }, "sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA=="],
+
+ "rehype-github-alerts": ["rehype-github-alerts@4.2.0", "", { "dependencies": { "@primer/octicons": "^19.20.0", "hast-util-from-html": "^2.0.3", "hast-util-is-element": "^3.0.0", "unist-util-visit": "^5.0.0" } }, "sha512-6di6kEu9WUHKLKrkKG2xX6AOuaCMGghg0Wq7MEuM/jBYUPVIq6PJpMe00dxMfU+/YSBtDXhffpDimgDi+BObIQ=="],
+
+ "rehype-katex": ["rehype-katex@7.0.1", "", { "dependencies": { "@types/hast": "^3.0.0", "@types/katex": "^0.16.0", "hast-util-from-html-isomorphic": "^2.0.0", "hast-util-to-text": "^4.0.0", "katex": "^0.16.0", "unist-util-visit-parents": "^6.0.0", "vfile": "^6.0.0" } }, "sha512-OiM2wrZ/wuhKkigASodFoo8wimG3H12LWQaH8qSPVJn9apWKFSH3YOCtbKpBorTVw/eI7cuT21XBbvwEswbIOA=="],
+
+ "rehype-raw": ["rehype-raw@7.0.0", "", { "dependencies": { "@types/hast": "^3.0.0", "hast-util-raw": "^9.0.0", "vfile": "^6.0.0" } }, "sha512-/aE8hCfKlQeA8LmyeyQvQF3eBiLRGNlfBJEvWH7ivp9sBqs7TNqBL5X3v157rM4IFETqDnIOO+z5M/biZbo9Ww=="],
+
+ "rehype-recma": ["rehype-recma@1.0.0", "", { "dependencies": { "@types/estree": "^1.0.0", "@types/hast": "^3.0.0", "hast-util-to-estree": "^3.0.0" } }, "sha512-lqA4rGUf1JmacCNWWZx0Wv1dHqMwxzsDWYMTowuplHF3xH0N/MmrZ/G3BDZnzAkRmxDadujCjaKM2hqYdCBOGw=="],
+
+ "remark-breaks": ["remark-breaks@4.0.0", "", { "dependencies": { "@types/mdast": "^4.0.0", "mdast-util-newline-to-break": "^2.0.0", "unified": "^11.0.0" } }, "sha512-IjEjJOkH4FuJvHZVIW0QCDWxcG96kCq7An/KVH2NfJe6rKZU2AsHeB3OEjPNRxi4QC34Xdx7I2KGYn6IpT7gxQ=="],
+
+ "remark-cjk-friendly": ["remark-cjk-friendly@1.2.3", "", { "dependencies": { "micromark-extension-cjk-friendly": "1.2.3" }, "peerDependencies": { "@types/mdast": "^4.0.0", "unified": "^11.0.0" } }, "sha512-UvAgxwlNk+l9Oqgl/9MWK2eWRS7zgBW/nXX9AthV7nd/3lNejF138E7Xbmk9Zs4WjTJGs721r7fAEc7tNFoH7g=="],
+
+ "remark-gfm": ["remark-gfm@4.0.1", "", { "dependencies": { "@types/mdast": "^4.0.0", "mdast-util-gfm": "^3.0.0", "micromark-extension-gfm": "^3.0.0", "remark-parse": "^11.0.0", "remark-stringify": "^11.0.0", "unified": "^11.0.0" } }, "sha512-1quofZ2RQ9EWdeN34S79+KExV1764+wCUGop5CPL1WGdD0ocPpu91lzPGbwWMECpEpd42kJGQwzRfyov9j4yNg=="],
+
+ "remark-github": ["remark-github@12.0.0", "", { "dependencies": { "@types/mdast": "^4.0.0", "mdast-util-find-and-replace": "^3.0.0", "mdast-util-to-string": "^4.0.0", "to-vfile": "^8.0.0", "unist-util-visit": "^5.0.0", "vfile": "^6.0.0" } }, "sha512-ByefQKFN184LeiGRCabfl7zUJsdlMYWEhiLX1gpmQ11yFg6xSuOTW7LVCv0oc1x+YvUMJW23NU36sJX2RWGgvg=="],
+
+ "remark-math": ["remark-math@6.0.0", "", { "dependencies": { "@types/mdast": "^4.0.0", "mdast-util-math": "^3.0.0", "micromark-extension-math": "^3.0.0", "unified": "^11.0.0" } }, "sha512-MMqgnP74Igy+S3WwnhQ7kqGlEerTETXMvJhrUzDikVZ2/uogJCb+WHUg97hK9/jcfc0dkD73s3LN8zU49cTEtA=="],
+
+ "remark-mdx": ["remark-mdx@3.1.1", "", { "dependencies": { "mdast-util-mdx": "^3.0.0", "micromark-extension-mdxjs": "^3.0.0" } }, "sha512-Pjj2IYlUY3+D8x00UJsIOg5BEvfMyeI+2uLPn9VO9Wg4MEtN/VTIq2NEJQfde9PnX15KgtHyl9S0BcTnWrIuWg=="],
+
+ "remark-parse": ["remark-parse@11.0.0", "", { "dependencies": { "@types/mdast": "^4.0.0", "mdast-util-from-markdown": "^2.0.0", "micromark-util-types": "^2.0.0", "unified": "^11.0.0" } }, "sha512-FCxlKLNGknS5ba/1lmpYijMUzX2esxW5xQqjWxw2eHFfS2MSdaHVINFmhjo+qN1WhZhNimq0dZATN9pH0IDrpA=="],
+
+ "remark-rehype": ["remark-rehype@11.1.2", "", { "dependencies": { "@types/hast": "^3.0.0", "@types/mdast": "^4.0.0", "mdast-util-to-hast": "^13.0.0", "unified": "^11.0.0", "vfile": "^6.0.0" } }, "sha512-Dh7l57ianaEoIpzbp0PC9UKAdCSVklD8E5Rpw7ETfbTl3FqcOOgq5q2LVDhgGCkaBv7p24JXikPdvhhmHvKMsw=="],
+
+ "remark-stringify": ["remark-stringify@11.0.0", "", { "dependencies": { "@types/mdast": "^4.0.0", "mdast-util-to-markdown": "^2.0.0", "unified": "^11.0.0" } }, "sha512-1OSmLd3awB/t8qdoEOMazZkNsfVTeY4fTsgzcQFdXNq8ToTN4ZGwrMnlda4K6smTFKD+GRV6O48i6Z4iKgPPpw=="],
+
+ "remend": ["remend@1.3.0", "", {}, "sha512-iIhggPkhW3hFImKtB10w0dz4EZbs28mV/dmbcYVonWEJ6UGHHpP+bFZnTh6GNWJONg5m+U56JrL+8IxZRdgWjw=="],
+
+ "require-directory": ["require-directory@2.1.1", "", {}, "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q=="],
+
+ "require-from-string": ["require-from-string@2.0.2", "", {}, "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw=="],
+
+ "requires-port": ["requires-port@1.0.0", "", {}, "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ=="],
+
+ "reselect": ["reselect@5.1.1", "", {}, "sha512-K/BG6eIky/SBpzfHZv/dd+9JBFiS4SWV7FIujVyJRux6e45+73RaUHXLmIR1f7WOMaQ0U1km6qwklRQxpJJY0w=="],
+
+ "resize-observer-polyfill": ["resize-observer-polyfill@1.5.1", "", {}, "sha512-LwZrotdHOo12nQuZlHEmtuXdqGoOD0OhaxopaNFxWzInpEgaLWoVuAMbTzixuosCx2nEG58ngzW3vxdWoxIgdg=="],
+
+ "resolve": ["resolve@1.22.11", "", { "dependencies": { "is-core-module": "^2.16.1", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" }, "bin": "bin/resolve" }, "sha512-RfqAvLnMl313r7c9oclB1HhUEAezcpLjz95wFH4LVuhk9JF/r22qmVP9AMmOU4vMX7Q8pN8jwNg/CSpdFnMjTQ=="],
+
+ "resolve-from": ["resolve-from@4.0.0", "", {}, "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g=="],
+
+ "resolve-pkg-maps": ["resolve-pkg-maps@1.0.0", "", {}, "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw=="],
+
+ "restore-cursor": ["restore-cursor@5.1.0", "", { "dependencies": { "onetime": "^7.0.0", "signal-exit": "^4.1.0" } }, "sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA=="],
+
+ "reusify": ["reusify@1.1.0", "", {}, "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw=="],
+
+ "rfdc": ["rfdc@1.4.1", "", {}, "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA=="],
+
+ "robust-predicates": ["robust-predicates@3.0.3", "", {}, "sha512-NS3levdsRIUOmiJ8FZWCP7LG3QpJyrs/TE0Zpf1yvZu8cAJJ6QMW92H1c7kWpdIHo8RvmLxN/o2JXTKHp74lUA=="],
+
+ "rolldown": ["rolldown@1.0.0-rc.9", "", { "dependencies": { "@oxc-project/types": "=0.115.0", "@rolldown/pluginutils": "1.0.0-rc.9" }, "optionalDependencies": { "@rolldown/binding-android-arm64": "1.0.0-rc.9", "@rolldown/binding-darwin-arm64": "1.0.0-rc.9", "@rolldown/binding-darwin-x64": "1.0.0-rc.9", "@rolldown/binding-freebsd-x64": "1.0.0-rc.9", "@rolldown/binding-linux-arm-gnueabihf": "1.0.0-rc.9", "@rolldown/binding-linux-arm64-gnu": "1.0.0-rc.9", "@rolldown/binding-linux-arm64-musl": "1.0.0-rc.9", "@rolldown/binding-linux-ppc64-gnu": "1.0.0-rc.9", "@rolldown/binding-linux-s390x-gnu": "1.0.0-rc.9", "@rolldown/binding-linux-x64-gnu": "1.0.0-rc.9", "@rolldown/binding-linux-x64-musl": "1.0.0-rc.9", "@rolldown/binding-openharmony-arm64": "1.0.0-rc.9", "@rolldown/binding-wasm32-wasi": "1.0.0-rc.9", "@rolldown/binding-win32-arm64-msvc": "1.0.0-rc.9", "@rolldown/binding-win32-x64-msvc": "1.0.0-rc.9" }, "bin": "bin/cli.mjs" }, "sha512-9EbgWge7ZH+yqb4d2EnELAntgPTWbfL8ajiTW+SyhJEC4qhBbkCKbqFV4Ge4zmu5ziQuVbWxb/XwLZ+RIO7E8Q=="],
+
+ "roughjs": ["roughjs@4.6.6", "", { "dependencies": { "hachure-fill": "^0.5.2", "path-data-parser": "^0.1.0", "points-on-curve": "^0.2.0", "points-on-path": "^0.2.1" } }, "sha512-ZUz/69+SYpFN/g/lUlo2FXcIjRkSu3nDarreVdGGndHEBJ6cXPdKguS8JGxwj5HA5xIbVKSmLgr5b3AWxtRfvQ=="],
+
+ "router": ["router@2.2.0", "", { "dependencies": { "debug": "^4.4.0", "depd": "^2.0.0", "is-promise": "^4.0.0", "parseurl": "^1.3.3", "path-to-regexp": "^8.0.0" } }, "sha512-nLTrUKm2UyiL7rlhapu/Zl45FwNgkZGaCpZbIHajDYgwlJCOzLSk+cIPAnsEqV955GjILJnKbdQC1nVPz+gAYQ=="],
+
+ "run-applescript": ["run-applescript@7.1.0", "", {}, "sha512-DPe5pVFaAsinSaV6QjQ6gdiedWDcRCbUuiQfQa2wmWV7+xC9bGulGI8+TdRmoFkAPaBXk8CrAbnlY2ISniJ47Q=="],
+
+ "run-parallel": ["run-parallel@1.2.0", "", { "dependencies": { "queue-microtask": "^1.2.2" } }, "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA=="],
+
+ "rw": ["rw@1.3.3", "", {}, "sha512-PdhdWy89SiZogBLaw42zdeqtRJ//zFd2PgQavcICDUgJT5oW10QCRKbJ6bg4r0/UY2M6BWd5tkxuGFRvCkgfHQ=="],
+
+ "rxjs": ["rxjs@7.8.2", "", { "dependencies": { "tslib": "^2.1.0" } }, "sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA=="],
+
+ "safe-array-concat": ["safe-array-concat@1.1.3", "", { "dependencies": { "call-bind": "^1.0.8", "call-bound": "^1.0.2", "get-intrinsic": "^1.2.6", "has-symbols": "^1.1.0", "isarray": "^2.0.5" } }, "sha512-AURm5f0jYEOydBj7VQlVvDrjeFgthDdEF5H1dP+6mNpoXOMo1quQqJ4wvJDyRZ9+pO3kGWoOdmV08cSv2aJV6Q=="],
+
+ "safe-buffer": ["safe-buffer@5.2.1", "", {}, "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ=="],
+
+ "safe-push-apply": ["safe-push-apply@1.0.0", "", { "dependencies": { "es-errors": "^1.3.0", "isarray": "^2.0.5" } }, "sha512-iKE9w/Z7xCzUMIZqdBsp6pEQvwuEebH4vdpjcDWnyzaI6yl6O9FHvVpmGelvEHNsoY6wGblkxR6Zty/h00WiSA=="],
+
+ "safe-regex-test": ["safe-regex-test@1.1.0", "", { "dependencies": { "call-bound": "^1.0.2", "es-errors": "^1.3.0", "is-regex": "^1.2.1" } }, "sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw=="],
+
+ "safe-stable-stringify": ["safe-stable-stringify@2.5.0", "", {}, "sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA=="],
+
+ "safer-buffer": ["safer-buffer@2.1.2", "", {}, "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="],
+
+ "saxes": ["saxes@6.0.0", "", { "dependencies": { "xmlchars": "^2.2.0" } }, "sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA=="],
+
+ "scheduler": ["scheduler@0.27.0", "", {}, "sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q=="],
+
+ "screenfull": ["screenfull@5.2.0", "", {}, "sha512-9BakfsO2aUQN2K9Fdbj87RJIEZ82Q9IGim7FqM5OsebfoFC6ZHXgDq/KvniuLTPdeM8wY2o6Dj3WQ7KeQCj3cA=="],
+
+ "scroll-into-view-if-needed": ["scroll-into-view-if-needed@3.1.0", "", { "dependencies": { "compute-scroll-into-view": "^3.0.2" } }, "sha512-49oNpRjWRvnU8NyGVmUaYG4jtTkNonFZI86MmGRDqBphEK2EXT9gdEUoQPZhuBM8yWHxCWbobltqYO5M4XrUvQ=="],
+
+ "secure-json-parse": ["secure-json-parse@4.1.0", "", {}, "sha512-l4KnYfEyqYJxDwlNVyRfO2E4NTHfMKAWdUuA8J0yve2Dz/E/PdBepY03RvyJpssIpRFwJoCD55wA+mEDs6ByWA=="],
+
+ "selfsigned": ["selfsigned@5.5.0", "", { "dependencies": { "@peculiar/x509": "^1.14.2", "pkijs": "^3.3.3" } }, "sha512-ftnu3TW4+3eBfLRFnDEkzGxSF/10BJBkaLJuBHZX0kiPS7bRdlpZGu6YGt4KngMkdTwJE6MbjavFpqHvqVt+Ew=="],
+
+ "semver": ["semver@6.3.1", "", { "bin": "bin/semver.js" }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="],
+
+ "semver-compare": ["semver-compare@1.0.0", "", {}, "sha512-YM3/ITh2MJ5MtzaM429anh+x2jiLVjqILF4m4oyQB18W7Ggea7BfqdH/wGMK7dDiMghv/6WG7znWMwUDzJiXow=="],
+
+ "send": ["send@1.2.1", "", { "dependencies": { "debug": "^4.4.3", "encodeurl": "^2.0.0", "escape-html": "^1.0.3", "etag": "^1.8.1", "fresh": "^2.0.0", "http-errors": "^2.0.1", "mime-types": "^3.0.2", "ms": "^2.1.3", "on-finished": "^2.4.1", "range-parser": "^1.2.1", "statuses": "^2.0.2" } }, "sha512-1gnZf7DFcoIcajTjTwjwuDjzuz4PPcY2StKPlsGAQ1+YH20IRVrBaXSWmdjowTJ6u8Rc01PoYOGHXfP1mYcZNQ=="],
+
+ "serve-static": ["serve-static@2.2.1", "", { "dependencies": { "encodeurl": "^2.0.0", "escape-html": "^1.0.3", "parseurl": "^1.3.3", "send": "^1.2.0" } }, "sha512-xRXBn0pPqQTVQiC8wyQrKs2MOlX24zQ0POGaj0kultvoOCstBQM5yvOhAVSUwOMjQtTvsPWoNCHfPGwaaQJhTw=="],
+
+ "set-function-length": ["set-function-length@1.2.2", "", { "dependencies": { "define-data-property": "^1.1.4", "es-errors": "^1.3.0", "function-bind": "^1.1.2", "get-intrinsic": "^1.2.4", "gopd": "^1.0.1", "has-property-descriptors": "^1.0.2" } }, "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg=="],
+
+ "set-function-name": ["set-function-name@2.0.2", "", { "dependencies": { "define-data-property": "^1.1.4", "es-errors": "^1.3.0", "functions-have-names": "^1.2.3", "has-property-descriptors": "^1.0.2" } }, "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ=="],
+
+ "set-proto": ["set-proto@1.0.0", "", { "dependencies": { "dunder-proto": "^1.0.1", "es-errors": "^1.3.0", "es-object-atoms": "^1.0.0" } }, "sha512-RJRdvCo6IAnPdsvP/7m6bsQqNnn1FCBX5ZNtFL98MmFF/4xAIJTIg1YbHW5DC2W5SKZanrC6i4HsJqlajw/dZw=="],
+
+ "set-value": ["set-value@2.0.1", "", { "dependencies": { "extend-shallow": "^2.0.1", "is-extendable": "^0.1.1", "is-plain-object": "^2.0.3", "split-string": "^3.0.1" } }, "sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw=="],
+
+ "setprototypeof": ["setprototypeof@1.2.0", "", {}, "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw=="],
+
+ "sharp": ["sharp@0.34.5", "", { "dependencies": { "@img/colour": "^1.0.0", "detect-libc": "^2.1.2", "semver": "^7.7.3" }, "optionalDependencies": { "@img/sharp-darwin-arm64": "0.34.5", "@img/sharp-darwin-x64": "0.34.5", "@img/sharp-libvips-darwin-arm64": "1.2.4", "@img/sharp-libvips-darwin-x64": "1.2.4", "@img/sharp-libvips-linux-arm": "1.2.4", "@img/sharp-libvips-linux-arm64": "1.2.4", "@img/sharp-libvips-linux-ppc64": "1.2.4", "@img/sharp-libvips-linux-riscv64": "1.2.4", "@img/sharp-libvips-linux-s390x": "1.2.4", "@img/sharp-libvips-linux-x64": "1.2.4", "@img/sharp-libvips-linuxmusl-arm64": "1.2.4", "@img/sharp-libvips-linuxmusl-x64": "1.2.4", "@img/sharp-linux-arm": "0.34.5", "@img/sharp-linux-arm64": "0.34.5", "@img/sharp-linux-ppc64": "0.34.5", "@img/sharp-linux-riscv64": "0.34.5", "@img/sharp-linux-s390x": "0.34.5", "@img/sharp-linux-x64": "0.34.5", "@img/sharp-linuxmusl-arm64": "0.34.5", "@img/sharp-linuxmusl-x64": "0.34.5", "@img/sharp-wasm32": "0.34.5", "@img/sharp-win32-arm64": "0.34.5", "@img/sharp-win32-ia32": "0.34.5", "@img/sharp-win32-x64": "0.34.5" } }, "sha512-Ou9I5Ft9WNcCbXrU9cMgPBcCK8LiwLqcbywW3t4oDV37n1pzpuNLsYiAV8eODnjbtQlSDwZ2cUEeQz4E54Hltg=="],
+
+ "shebang-command": ["shebang-command@2.0.0", "", { "dependencies": { "shebang-regex": "^3.0.0" } }, "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA=="],
+
+ "shebang-regex": ["shebang-regex@3.0.0", "", {}, "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A=="],
+
+ "shell-quote": ["shell-quote@1.8.3", "", {}, "sha512-ObmnIF4hXNg1BqhnHmgbDETF8dLPCggZWBjkQfhZpbszZnYur5DUljTcCHii5LC3J5E0yeO/1LIMyH+UvHQgyw=="],
+
+ "shiki": ["shiki@3.23.0", "", { "dependencies": { "@shikijs/core": "3.23.0", "@shikijs/engine-javascript": "3.23.0", "@shikijs/engine-oniguruma": "3.23.0", "@shikijs/langs": "3.23.0", "@shikijs/themes": "3.23.0", "@shikijs/types": "3.23.0", "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4" } }, "sha512-55Dj73uq9ZXL5zyeRPzHQsK7Nbyt6Y10k5s7OjuFZGMhpp4r/rsLBH0o/0fstIzX1Lep9VxefWljK/SKCzygIA=="],
+
+ "shiki-stream": ["shiki-stream@0.1.4", "", { "dependencies": { "@shikijs/core": "^3.0.0" }, "peerDependencies": { "react": "^19.0.0", "solid-js": "^1.9.0", "vue": "^3.2.0" }, "optionalPeers": ["solid-js", "vue"] }, "sha512-4pz6JGSDmVTTkPJ/ueixHkFAXY4ySCc+unvCaDZV7hqq/sdJZirRxgIXSuNSKgiFlGTgRR97sdu2R8K55sPsrw=="],
+
+ "side-channel": ["side-channel@1.1.0", "", { "dependencies": { "es-errors": "^1.3.0", "object-inspect": "^1.13.3", "side-channel-list": "^1.0.0", "side-channel-map": "^1.0.1", "side-channel-weakmap": "^1.0.2" } }, "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw=="],
+
+ "side-channel-list": ["side-channel-list@1.0.0", "", { "dependencies": { "es-errors": "^1.3.0", "object-inspect": "^1.13.3" } }, "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA=="],
+
+ "side-channel-map": ["side-channel-map@1.0.1", "", { "dependencies": { "call-bound": "^1.0.2", "es-errors": "^1.3.0", "get-intrinsic": "^1.2.5", "object-inspect": "^1.13.3" } }, "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA=="],
+
+ "side-channel-weakmap": ["side-channel-weakmap@1.0.2", "", { "dependencies": { "call-bound": "^1.0.2", "es-errors": "^1.3.0", "get-intrinsic": "^1.2.5", "object-inspect": "^1.13.3", "side-channel-map": "^1.0.1" } }, "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A=="],
+
+ "siginfo": ["siginfo@2.0.0", "", {}, "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g=="],
+
+ "signal-exit": ["signal-exit@4.1.0", "", {}, "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw=="],
+
+ "simple-concat": ["simple-concat@1.0.1", "", {}, "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q=="],
+
+ "simple-get": ["simple-get@4.0.1", "", { "dependencies": { "decompress-response": "^6.0.0", "once": "^1.3.1", "simple-concat": "^1.0.0" } }, "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA=="],
+
+ "slice-ansi": ["slice-ansi@7.1.2", "", { "dependencies": { "ansi-styles": "^6.2.1", "is-fullwidth-code-point": "^5.0.0" } }, "sha512-iOBWFgUX7caIZiuutICxVgX1SdxwAVFFKwt1EvMYYec/NWO5meOJ6K5uQxhrYBdQJne4KxiqZc+KptFOWFSI9w=="],
+
+ "smart-buffer": ["smart-buffer@4.2.0", "", {}, "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg=="],
+
+ "socks": ["socks@2.8.7", "", { "dependencies": { "ip-address": "^10.0.1", "smart-buffer": "^4.2.0" } }, "sha512-HLpt+uLy/pxB+bum/9DzAgiKS8CX1EvbWxI4zlmgGCExImLdiad2iCwXT5Z4c9c3Eq8rP2318mPW2c+QbtjK8A=="],
+
+ "sonic-boom": ["sonic-boom@4.2.1", "", { "dependencies": { "atomic-sleep": "^1.0.0" } }, "sha512-w6AxtubXa2wTXAUsZMMWERrsIRAdrK0Sc+FUytWvYAhBJLyuI4llrMIC1DtlNSdI99EI86KZum2MMq3EAZlF9Q=="],
+
+ "source-map": ["source-map@0.7.6", "", {}, "sha512-i5uvt8C3ikiWeNZSVZNWcfZPItFQOsYTUAOkcUPGd8DqDy1uOUikjt5dG+uRlwyvR108Fb9DOd4GvXfT0N2/uQ=="],
+
+ "source-map-js": ["source-map-js@1.2.1", "", {}, "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA=="],
+
+ "space-separated-tokens": ["space-separated-tokens@2.0.2", "", {}, "sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q=="],
+
+ "split-on-first": ["split-on-first@3.0.0", "", {}, "sha512-qxQJTx2ryR0Dw0ITYyekNQWpz6f8dGd7vffGNflQQ3Iqj9NJ6qiZ7ELpZsJ/QBhIVAiDfXdag3+Gp8RvWa62AA=="],
+
+ "split-string": ["split-string@3.1.0", "", { "dependencies": { "extend-shallow": "^3.0.0" } }, "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw=="],
+
+ "split2": ["split2@4.2.0", "", {}, "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg=="],
+
+ "stable-hash": ["stable-hash@0.0.5", "", {}, "sha512-+L3ccpzibovGXFK+Ap/f8LOS0ahMrHTf3xu7mMLSpEGU0EO9ucaysSylKo9eRDFNhWve/y275iPmIZ4z39a9iA=="],
+
+ "stackback": ["stackback@0.0.2", "", {}, "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw=="],
+
+ "state-local": ["state-local@1.0.7", "", {}, "sha512-HTEHMNieakEnoe33shBYcZ7NX83ACUjCu8c40iOGEZsngj9zRnkqS9j1pqQPXwobB0ZcVTk27REb7COQ0UR59w=="],
+
+ "statuses": ["statuses@2.0.2", "", {}, "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw=="],
+
+ "std-env": ["std-env@4.0.0", "", {}, "sha512-zUMPtQ/HBY3/50VbpkupYHbRroTRZJPRLvreamgErJVys0ceuzMkD44J/QjqhHjOzK42GQ3QZIeFG1OYfOtKqQ=="],
+
+ "stdin-discarder": ["stdin-discarder@0.3.1", "", {}, "sha512-reExS1kSGoElkextOcPkel4NE99S0BWxjUHQeDFnR8S993JxpPX7KU4MNmO19NXhlJp+8dmdCbKQVNgLJh2teA=="],
+
+ "steno": ["steno@4.0.2", "", {}, "sha512-yhPIQXjrlt1xv7dyPQg2P17URmXbuM5pdGkpiMB3RenprfiBlvK415Lctfe0eshk90oA7/tNq7WEiMK8RSP39A=="],
+
+ "stop-iteration-iterator": ["stop-iteration-iterator@1.1.0", "", { "dependencies": { "es-errors": "^1.3.0", "internal-slot": "^1.1.0" } }, "sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ=="],
+
+ "string-argv": ["string-argv@0.3.2", "", {}, "sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q=="],
+
+ "string-convert": ["string-convert@0.2.1", "", {}, "sha512-u/1tdPl4yQnPBjnVrmdLo9gtuLvELKsAoRapekWggdiQNvvvum+jYF329d84NAa660KQw7pB2n36KrIKVoXa3A=="],
+
+ "string-width": ["string-width@8.1.1", "", { "dependencies": { "get-east-asian-width": "^1.3.0", "strip-ansi": "^7.1.0" } }, "sha512-KpqHIdDL9KwYk22wEOg/VIqYbrnLeSApsKT/bSj6Ez7pn3CftUiLAv2Lccpq1ALcpLV9UX1Ppn92npZWu2w/aw=="],
+
+ "string.prototype.includes": ["string.prototype.includes@2.0.1", "", { "dependencies": { "call-bind": "^1.0.7", "define-properties": "^1.2.1", "es-abstract": "^1.23.3" } }, "sha512-o7+c9bW6zpAdJHTtujeePODAhkuicdAryFsfVKwA+wGw89wJ4GTY484WTucM9hLtDEOpOvI+aHnzqnC5lHp4Rg=="],
+
+ "string.prototype.matchall": ["string.prototype.matchall@4.0.12", "", { "dependencies": { "call-bind": "^1.0.8", "call-bound": "^1.0.3", "define-properties": "^1.2.1", "es-abstract": "^1.23.6", "es-errors": "^1.3.0", "es-object-atoms": "^1.0.0", "get-intrinsic": "^1.2.6", "gopd": "^1.2.0", "has-symbols": "^1.1.0", "internal-slot": "^1.1.0", "regexp.prototype.flags": "^1.5.3", "set-function-name": "^2.0.2", "side-channel": "^1.1.0" } }, "sha512-6CC9uyBL+/48dYizRf7H7VAYCMCNTBeM78x/VTUe9bFEaxBepPJDa1Ow99LqI/1yF7kuy7Q3cQsYMrcjGUcskA=="],
+
+ "string.prototype.repeat": ["string.prototype.repeat@1.0.0", "", { "dependencies": { "define-properties": "^1.1.3", "es-abstract": "^1.17.5" } }, "sha512-0u/TldDbKD8bFCQ/4f5+mNRrXwZ8hg2w7ZR8wa16e8z9XpePWl3eGEcUD0OXpEH/VJH/2G3gjUtR3ZOiBe2S/w=="],
+
+ "string.prototype.trim": ["string.prototype.trim@1.2.10", "", { "dependencies": { "call-bind": "^1.0.8", "call-bound": "^1.0.2", "define-data-property": "^1.1.4", "define-properties": "^1.2.1", "es-abstract": "^1.23.5", "es-object-atoms": "^1.0.0", "has-property-descriptors": "^1.0.2" } }, "sha512-Rs66F0P/1kedk5lyYyH9uBzuiI/kNRmwJAR9quK6VOtIpZ2G+hMZd+HQbbv25MgCA6gEffoMZYxlTod4WcdrKA=="],
+
+ "string.prototype.trimend": ["string.prototype.trimend@1.0.9", "", { "dependencies": { "call-bind": "^1.0.8", "call-bound": "^1.0.2", "define-properties": "^1.2.1", "es-object-atoms": "^1.0.0" } }, "sha512-G7Ok5C6E/j4SGfyLCloXTrngQIQU3PWtXGst3yM7Bea9FRURf1S42ZHlZZtsNque2FN2PoUhfZXYLNWwEr4dLQ=="],
+
+ "string.prototype.trimstart": ["string.prototype.trimstart@1.0.8", "", { "dependencies": { "call-bind": "^1.0.7", "define-properties": "^1.2.1", "es-object-atoms": "^1.0.0" } }, "sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg=="],
+
+ "string_decoder": ["string_decoder@1.3.0", "", { "dependencies": { "safe-buffer": "~5.2.0" } }, "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA=="],
+
+ "stringify-entities": ["stringify-entities@4.0.4", "", { "dependencies": { "character-entities-html4": "^2.0.0", "character-entities-legacy": "^3.0.0" } }, "sha512-IwfBptatlO+QCJUo19AqvrPNqlVMpW9YEL2LIVY+Rpv2qsjCGxaDLNRgeGsQWJhfItebuJhsGSLjaBbNSQ+ieg=="],
+
+ "strip-ansi": ["strip-ansi@7.1.2", "", { "dependencies": { "ansi-regex": "^6.0.1" } }, "sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA=="],
+
+ "strip-bom": ["strip-bom@3.0.0", "", {}, "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA=="],
+
+ "strip-indent": ["strip-indent@3.0.0", "", { "dependencies": { "min-indent": "^1.0.0" } }, "sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ=="],
+
+ "strip-json-comments": ["strip-json-comments@5.0.3", "", {}, "sha512-1tB5mhVo7U+ETBKNf92xT4hrQa3pm0MZ0PQvuDnWgAAGHDsfp4lPSpiS6psrSiet87wyGPh9ft6wmhOMQ0hDiw=="],
+
+ "style-to-js": ["style-to-js@1.1.21", "", { "dependencies": { "style-to-object": "1.0.14" } }, "sha512-RjQetxJrrUJLQPHbLku6U/ocGtzyjbJMP9lCNK7Ag0CNh690nSH8woqWH9u16nMjYBAok+i7JO1NP2pOy8IsPQ=="],
+
+ "style-to-object": ["style-to-object@1.0.14", "", { "dependencies": { "inline-style-parser": "0.2.7" } }, "sha512-LIN7rULI0jBscWQYaSswptyderlarFkjQ+t79nzty8tcIAceVomEVlLzH5VP4Cmsv6MtKhs7qaAiwlcp+Mgaxw=="],
+
+ "styled-jsx": ["styled-jsx@5.1.6", "", { "dependencies": { "client-only": "0.0.1" }, "peerDependencies": { "react": ">= 16.8.0 || 17.x.x || ^18.0.0-0 || ^19.0.0-0" } }, "sha512-qSVyDTeMotdvQYoHWLNGwRFJHC+i+ZvdBRYosOFgC+Wg1vx4frN2/RG/NA7SYqqvKNLf39P2LSRA2pu6n0XYZA=="],
+
+ "stylis": ["stylis@4.3.6", "", {}, "sha512-yQ3rwFWRfwNUY7H5vpU0wfdkNSnvnJinhF9830Swlaxl03zsOjCfmX0ugac+3LtK0lYSgwL/KXc8oYL3mG4YFQ=="],
+
+ "supports-color": ["supports-color@8.1.1", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q=="],
+
+ "supports-preserve-symlinks-flag": ["supports-preserve-symlinks-flag@1.0.0", "", {}, "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w=="],
+
+ "swr": ["swr@2.4.1", "", { "dependencies": { "dequal": "^2.0.3", "use-sync-external-store": "^1.6.0" }, "peerDependencies": { "react": "^16.11.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, "sha512-2CC6CiKQtEwaEeNiqWTAw9PGykW8SR5zZX8MZk6TeAvEAnVS7Visz8WzphqgtQ8v2xz/4Q5K+j+SeMaKXeeQIA=="],
+
+ "symbol-tree": ["symbol-tree@3.2.4", "", {}, "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw=="],
+
+ "tabbable": ["tabbable@6.4.0", "", {}, "sha512-05PUHKSNE8ou2dwIxTngl4EzcnsCDZGJ/iCLtDflR/SHB/ny14rXc+qU5P4mG9JkusiV7EivzY9Mhm55AzAvCg=="],
+
+ "tailwindcss": ["tailwindcss@4.2.1", "", {}, "sha512-/tBrSQ36vCleJkAOsy9kbNTgaxvGbyOamC30PRePTQe/o1MFwEKHQk4Cn7BNGaPtjp+PuUrByJehM1hgxfq4sw=="],
+
+ "tapable": ["tapable@2.3.0", "", {}, "sha512-g9ljZiwki/LfxmQADO3dEY1CbpmXT5Hm2fJ+QaGKwSXUylMybePR7/67YW7jOrrvjEgL1Fmz5kzyAjWVWLlucg=="],
+
+ "tar-fs": ["tar-fs@2.1.4", "", { "dependencies": { "chownr": "^1.1.1", "mkdirp-classic": "^0.5.2", "pump": "^3.0.0", "tar-stream": "^2.1.4" } }, "sha512-mDAjwmZdh7LTT6pNleZ05Yt65HC3E+NiQzl672vQG38jIrehtJk/J3mNwIg+vShQPcLF/LV7CMnDW6vjj6sfYQ=="],
+
+ "tar-stream": ["tar-stream@2.2.0", "", { "dependencies": { "bl": "^4.0.3", "end-of-stream": "^1.4.1", "fs-constants": "^1.0.0", "inherits": "^2.0.3", "readable-stream": "^3.1.1" } }, "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ=="],
+
+ "test-exclude": ["test-exclude@8.0.0", "", { "dependencies": { "@istanbuljs/schema": "^0.1.2", "glob": "^13.0.6", "minimatch": "^10.2.2" } }, "sha512-ZOffsNrXYggvU1mDGHk54I96r26P8SyMjO5slMKSc7+IWmtB/MQKnEC2fP51imB3/pT6YK5cT5E8f+Dd9KdyOQ=="],
+
+ "thread-stream": ["thread-stream@4.0.0", "", { "dependencies": { "real-require": "^0.2.0" } }, "sha512-4iMVL6HAINXWf1ZKZjIPcz5wYaOdPhtO8ATvZ+Xqp3BTdaqtAwQkNmKORqcIo5YkQqGXq5cwfswDwMqqQNrpJA=="],
+
+ "throttle-debounce": ["throttle-debounce@5.0.2", "", {}, "sha512-B71/4oyj61iNH0KeCamLuE2rmKuTO5byTOSVwECM5FA7TiAiAW+UqTKZ9ERueC4qvgSttUhdmq1mXC3kJqGX7A=="],
+
+ "tiny-invariant": ["tiny-invariant@1.3.3", "", {}, "sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg=="],
+
+ "tinybench": ["tinybench@2.9.0", "", {}, "sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg=="],
+
+ "tinyexec": ["tinyexec@1.0.4", "", {}, "sha512-u9r3uZC0bdpGOXtlxUIdwf9pkmvhqJdrVCH9fapQtgy/OeTTMZ1nqH7agtvEfmGui6e1XxjcdrlxvxJvc3sMqw=="],
+
+ "tinyglobby": ["tinyglobby@0.2.15", "", { "dependencies": { "fdir": "^6.5.0", "picomatch": "^4.0.3" } }, "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ=="],
+
+ "tinyrainbow": ["tinyrainbow@3.1.0", "", {}, "sha512-Bf+ILmBgretUrdJxzXM0SgXLZ3XfiaUuOj/IKQHuTXip+05Xn+uyEYdVg0kYDipTBcLrCVyUzAPz7QmArb0mmw=="],
+
+ "tldts": ["tldts@7.0.27", "", { "dependencies": { "tldts-core": "^7.0.27" }, "bin": { "tldts": "bin/cli.js" } }, "sha512-I4FZcVFcqCRuT0ph6dCDpPuO4Xgzvh+spkcTr1gK7peIvxWauoloVO0vuy1FQnijT63ss6AsHB6+OIM4aXHbPg=="],
+
+ "tldts-core": ["tldts-core@7.0.27", "", {}, "sha512-YQ7uPjgWUibIK6DW5lrKujGwUKhLevU4hcGbP5O6TcIUb+oTjJYJVWPS4nZsIHrEEEG6myk/oqAJUEQmpZrHsg=="],
+
+ "to-regex-range": ["to-regex-range@5.0.1", "", { "dependencies": { "is-number": "^7.0.0" } }, "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ=="],
+
+ "to-vfile": ["to-vfile@8.0.0", "", { "dependencies": { "vfile": "^6.0.0" } }, "sha512-IcmH1xB5576MJc9qcfEC/m/nQCFt3fzMHz45sSlgJyTWjRbKW1HAkJpuf3DgE57YzIlZcwcBZA5ENQbBo4aLkg=="],
+
+ "toidentifier": ["toidentifier@1.0.1", "", {}, "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA=="],
+
+ "tough-cookie": ["tough-cookie@6.0.1", "", { "dependencies": { "tldts": "^7.0.5" } }, "sha512-LktZQb3IeoUWB9lqR5EWTHgW/VTITCXg4D21M+lvybRVdylLrRMnqaIONLVb5mav8vM19m44HIcGq4qASeu2Qw=="],
+
+ "tr46": ["tr46@6.0.0", "", { "dependencies": { "punycode": "^2.3.1" } }, "sha512-bLVMLPtstlZ4iMQHpFHTR7GAGj2jxi8Dg0s2h2MafAE4uSWF98FC/3MomU51iQAMf8/qDUbKWf5GxuvvVcXEhw=="],
+
+ "tree-kill": ["tree-kill@1.2.2", "", { "bin": "cli.js" }, "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A=="],
+
+ "trim-lines": ["trim-lines@3.0.1", "", {}, "sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg=="],
+
+ "trough": ["trough@2.2.0", "", {}, "sha512-tmMpK00BjZiUyVyvrBK7knerNgmgvcV/KLVyuma/SC+TQN167GrMRciANTz09+k3zW8L8t60jWO1GpfkZdjTaw=="],
+
+ "ts-api-utils": ["ts-api-utils@2.4.0", "", { "peerDependencies": { "typescript": ">=4.8.4" } }, "sha512-3TaVTaAv2gTiMB35i3FiGJaRfwb3Pyn/j3m/bfAvGe8FB7CF6u+LMYqYlDh7reQf7UNvoTvdfAqHGmPGOSsPmA=="],
+
+ "ts-dedent": ["ts-dedent@2.2.0", "", {}, "sha512-q5W7tVM71e2xjHZTlgfTDoPF/SmqKG5hddq9SzR49CH2hayqRKJtQ4mtRlSxKaJlR/+9rEM+mnBHf7I2/BQcpQ=="],
+
+ "ts-md5": ["ts-md5@2.0.1", "", {}, "sha512-yF35FCoEOFBzOclSkMNEUbFQZuv89KEQ+5Xz03HrMSGUGB1+r+El+JiGOFwsP4p9RFNzwlrydYoTLvPOuICl9w=="],
+
+ "tsconfig-paths": ["tsconfig-paths@3.15.0", "", { "dependencies": { "@types/json5": "^0.0.29", "json5": "^1.0.2", "minimist": "^1.2.6", "strip-bom": "^3.0.0" } }, "sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg=="],
+
+ "tslib": ["tslib@2.8.1", "", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="],
+
+ "tsx": ["tsx@4.21.0", "", { "dependencies": { "esbuild": "~0.27.0", "get-tsconfig": "^4.7.5" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "bin": "dist/cli.mjs" }, "sha512-5C1sg4USs1lfG0GFb2RLXsdpXqBSEhAaA/0kPL01wxzpMqLILNxIxIOKiILz+cdg/pLnOUxFYOR5yhHU666wbw=="],
+
+ "tsyringe": ["tsyringe@4.10.0", "", { "dependencies": { "tslib": "^1.9.3" } }, "sha512-axr3IdNuVIxnaK5XGEUFTu3YmAQ6lllgrvqfEoR16g/HGnYY/6We4oWENtAnzK6/LpJ2ur9PAb80RBt7/U4ugw=="],
+
+ "tunnel-agent": ["tunnel-agent@0.6.0", "", { "dependencies": { "safe-buffer": "^5.0.1" } }, "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w=="],
+
+ "type-check": ["type-check@0.4.0", "", { "dependencies": { "prelude-ls": "^1.2.1" } }, "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew=="],
+
+ "type-is": ["type-is@2.0.1", "", { "dependencies": { "content-type": "^1.0.5", "media-typer": "^1.1.0", "mime-types": "^3.0.0" } }, "sha512-OZs6gsjF4vMp32qrCbiVSkrFmXtG/AZhY3t0iAMrMBiAZyV9oALtXO8hsrHbMXF9x6L3grlFuwW2oAz7cav+Gw=="],
+
+ "typed-array-buffer": ["typed-array-buffer@1.0.3", "", { "dependencies": { "call-bound": "^1.0.3", "es-errors": "^1.3.0", "is-typed-array": "^1.1.14" } }, "sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw=="],
+
+ "typed-array-byte-length": ["typed-array-byte-length@1.0.3", "", { "dependencies": { "call-bind": "^1.0.8", "for-each": "^0.3.3", "gopd": "^1.2.0", "has-proto": "^1.2.0", "is-typed-array": "^1.1.14" } }, "sha512-BaXgOuIxz8n8pIq3e7Atg/7s+DpiYrxn4vdot3w9KbnBhcRQq6o3xemQdIfynqSeXeDrF32x+WvfzmOjPiY9lg=="],
+
+ "typed-array-byte-offset": ["typed-array-byte-offset@1.0.4", "", { "dependencies": { "available-typed-arrays": "^1.0.7", "call-bind": "^1.0.8", "for-each": "^0.3.3", "gopd": "^1.2.0", "has-proto": "^1.2.0", "is-typed-array": "^1.1.15", "reflect.getprototypeof": "^1.0.9" } }, "sha512-bTlAFB/FBYMcuX81gbL4OcpH5PmlFHqlCCpAl8AlEzMz5k53oNDvN8p1PNOWLEmI2x4orp3raOFB51tv9X+MFQ=="],
+
+ "typed-array-length": ["typed-array-length@1.0.7", "", { "dependencies": { "call-bind": "^1.0.7", "for-each": "^0.3.3", "gopd": "^1.0.1", "is-typed-array": "^1.1.13", "possible-typed-array-names": "^1.0.0", "reflect.getprototypeof": "^1.0.6" } }, "sha512-3KS2b+kL7fsuk/eJZ7EQdnEmQoaho/r6KUef7hxvltNA5DR8NAUM+8wJMbJyZ4G9/7i3v5zPBIMN5aybAh2/Jg=="],
+
+ "typescript": ["typescript@5.9.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw=="],
+
+ "typescript-eslint": ["typescript-eslint@8.57.1", "", { "dependencies": { "@typescript-eslint/eslint-plugin": "8.57.1", "@typescript-eslint/parser": "8.57.1", "@typescript-eslint/typescript-estree": "8.57.1", "@typescript-eslint/utils": "8.57.1" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-fLvZWf+cAGw3tqMCYzGIU6yR8K+Y9NT2z23RwOjlNFF2HwSB3KhdEFI5lSBv8tNmFkkBShSjsCjzx1vahZfISA=="],
+
+ "ufo": ["ufo@1.6.3", "", {}, "sha512-yDJTmhydvl5lJzBmy/hyOAA0d+aqCBuwl818haVdYCRrWV84o7YyeVm4QlVHStqNrrJSTb6jKuFAVqAFsr+K3Q=="],
+
+ "unbox-primitive": ["unbox-primitive@1.1.0", "", { "dependencies": { "call-bound": "^1.0.3", "has-bigints": "^1.0.2", "has-symbols": "^1.1.0", "which-boxed-primitive": "^1.1.1" } }, "sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw=="],
+
+ "undici": ["undici@7.24.4", "", {}, "sha512-BM/JzwwaRXxrLdElV2Uo6cTLEjhSb3WXboncJamZ15NgUURmvlXvxa6xkwIOILIjPNo9i8ku136ZvWV0Uly8+w=="],
+
+ "undici-types": ["undici-types@7.18.2", "", {}, "sha512-AsuCzffGHJybSaRrmr5eHr81mwJU3kjw6M+uprWvCXiNeN9SOGwQ3Jn8jb8m3Z6izVgknn1R0FTCEAP2QrLY/w=="],
+
+ "unified": ["unified@11.0.5", "", { "dependencies": { "@types/unist": "^3.0.0", "bail": "^2.0.0", "devlop": "^1.0.0", "extend": "^3.0.0", "is-plain-obj": "^4.0.0", "trough": "^2.0.0", "vfile": "^6.0.0" } }, "sha512-xKvGhPWw3k84Qjh8bI3ZeJjqnyadK+GEFtazSfZv/rKeTkTjOJho6mFqh2SM96iIcZokxiOpg78GazTSg8+KHA=="],
+
+ "unist-util-find-after": ["unist-util-find-after@5.0.0", "", { "dependencies": { "@types/unist": "^3.0.0", "unist-util-is": "^6.0.0" } }, "sha512-amQa0Ep2m6hE2g72AugUItjbuM8X8cGQnFoHk0pGfrFeT9GZhzN5SW8nRsiGKK7Aif4CrACPENkA6P/Lw6fHGQ=="],
+
+ "unist-util-is": ["unist-util-is@6.0.1", "", { "dependencies": { "@types/unist": "^3.0.0" } }, "sha512-LsiILbtBETkDz8I9p1dQ0uyRUWuaQzd/cuEeS1hoRSyW5E5XGmTzlwY1OrNzzakGowI9Dr/I8HVaw4hTtnxy8g=="],
+
+ "unist-util-position": ["unist-util-position@5.0.0", "", { "dependencies": { "@types/unist": "^3.0.0" } }, "sha512-fucsC7HjXvkB5R3kTCO7kUjRdrS0BJt3M/FPxmHMBOm8JQi2BsHAHFsy27E0EolP8rp0NzXsJ+jNPyDWvOJZPA=="],
+
+ "unist-util-position-from-estree": ["unist-util-position-from-estree@2.0.0", "", { "dependencies": { "@types/unist": "^3.0.0" } }, "sha512-KaFVRjoqLyF6YXCbVLNad/eS4+OfPQQn2yOd7zF/h5T/CSL2v8NpN6a5TPvtbXthAGw5nG+PuTtq+DdIZr+cRQ=="],
+
+ "unist-util-remove-position": ["unist-util-remove-position@5.0.0", "", { "dependencies": { "@types/unist": "^3.0.0", "unist-util-visit": "^5.0.0" } }, "sha512-Hp5Kh3wLxv0PHj9m2yZhhLt58KzPtEYKQQ4yxfYFEO7EvHwzyDYnduhHnY1mDxoqr7VUwVuHXk9RXKIiYS1N8Q=="],
+
+ "unist-util-stringify-position": ["unist-util-stringify-position@4.0.0", "", { "dependencies": { "@types/unist": "^3.0.0" } }, "sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ=="],
+
+ "unist-util-visit": ["unist-util-visit@5.1.0", "", { "dependencies": { "@types/unist": "^3.0.0", "unist-util-is": "^6.0.0", "unist-util-visit-parents": "^6.0.0" } }, "sha512-m+vIdyeCOpdr/QeQCu2EzxX/ohgS8KbnPDgFni4dQsfSCtpz8UqDyY5GjRru8PDKuYn7Fq19j1CQ+nJSsGKOzg=="],
+
+ "unist-util-visit-parents": ["unist-util-visit-parents@6.0.2", "", { "dependencies": { "@types/unist": "^3.0.0", "unist-util-is": "^6.0.0" } }, "sha512-goh1s1TBrqSqukSc8wrjwWhL0hiJxgA8m4kFxGlQ+8FYQ3C/m11FcTs4YYem7V664AhHVvgoQLk890Ssdsr2IQ=="],
+
+ "unpipe": ["unpipe@1.0.0", "", {}, "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ=="],
+
+ "unrs-resolver": ["unrs-resolver@1.11.1", "", { "dependencies": { "napi-postinstall": "^0.3.0" }, "optionalDependencies": { "@unrs/resolver-binding-android-arm-eabi": "1.11.1", "@unrs/resolver-binding-android-arm64": "1.11.1", "@unrs/resolver-binding-darwin-arm64": "1.11.1", "@unrs/resolver-binding-darwin-x64": "1.11.1", "@unrs/resolver-binding-freebsd-x64": "1.11.1", "@unrs/resolver-binding-linux-arm-gnueabihf": "1.11.1", "@unrs/resolver-binding-linux-arm-musleabihf": "1.11.1", "@unrs/resolver-binding-linux-arm64-gnu": "1.11.1", "@unrs/resolver-binding-linux-arm64-musl": "1.11.1", "@unrs/resolver-binding-linux-ppc64-gnu": "1.11.1", "@unrs/resolver-binding-linux-riscv64-gnu": "1.11.1", "@unrs/resolver-binding-linux-riscv64-musl": "1.11.1", "@unrs/resolver-binding-linux-s390x-gnu": "1.11.1", "@unrs/resolver-binding-linux-x64-gnu": "1.11.1", "@unrs/resolver-binding-linux-x64-musl": "1.11.1", "@unrs/resolver-binding-wasm32-wasi": "1.11.1", "@unrs/resolver-binding-win32-arm64-msvc": "1.11.1", "@unrs/resolver-binding-win32-ia32-msvc": "1.11.1", "@unrs/resolver-binding-win32-x64-msvc": "1.11.1" } }, "sha512-bSjt9pjaEBnNiGgc9rUiHGKv5l4/TGzDmYw3RhnkJGtLhbnnA/5qJj7x3dNDCRx/PJxu774LlH8lCOlB4hEfKg=="],
+
+ "update-browserslist-db": ["update-browserslist-db@1.2.3", "", { "dependencies": { "escalade": "^3.2.0", "picocolors": "^1.1.1" }, "peerDependencies": { "browserslist": ">= 4.21.0" }, "bin": "cli.js" }, "sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w=="],
+
+ "uri-js": ["uri-js@4.4.1", "", { "dependencies": { "punycode": "^2.1.0" } }, "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg=="],
+
+ "url-join": ["url-join@5.0.0", "", {}, "sha512-n2huDr9h9yzd6exQVnH/jU5mr+Pfx08LRXXZhkLLetAMESRj+anQsTAh940iMrIetKAmry9coFuZQ2jY8/p3WA=="],
+
+ "use-intl": ["use-intl@4.8.3", "", { "dependencies": { "@formatjs/fast-memoize": "^3.1.0", "@schummar/icu-type-parser": "1.21.5", "icu-minify": "^4.8.3", "intl-messageformat": "^11.1.0" }, "peerDependencies": { "react": "^17.0.0 || ^18.0.0 || >=19.0.0-rc <19.0.0 || ^19.0.0" } }, "sha512-nLxlC/RH+le6g3amA508Itnn/00mE+J22ui21QhOWo5V9hCEC43+WtnRAITbJW0ztVZphev5X9gvOf2/Dk9PLA=="],
+
+ "use-merge-value": ["use-merge-value@1.2.0", "", { "peerDependencies": { "react": ">= 16.x" } }, "sha512-DXgG0kkgJN45TcyoXL49vJnn55LehnrmoHc7MbKi+QDBvr8dsesqws8UlyIWGHMR+JXgxc1nvY+jDGMlycsUcw=="],
+
+ "use-sync-external-store": ["use-sync-external-store@1.6.0", "", { "peerDependencies": { "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, "sha512-Pp6GSwGP/NrPIrxVFAIkOQeyw8lFenOHijQWkUTrDvrF4ALqylP2C/KCkeS9dpUM3KvYRQhna5vt7IL95+ZQ9w=="],
+
+ "util-deprecate": ["util-deprecate@1.0.2", "", {}, "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw=="],
+
+ "uuid": ["uuid@13.0.0", "", { "bin": "dist-node/bin/uuid" }, "sha512-XQegIaBTVUjSHliKqcnFqYypAd4S+WCYt5NIeRs6w/UAry7z8Y9j5ZwRRL4kzq9U3sD6v+85er9FvkEaBpji2w=="],
+
+ "v8-to-istanbul": ["v8-to-istanbul@9.3.0", "", { "dependencies": { "@jridgewell/trace-mapping": "^0.3.12", "@types/istanbul-lib-coverage": "^2.0.1", "convert-source-map": "^2.0.0" } }, "sha512-kiGUalWN+rgBJ/1OHZsBtU4rXZOfj/7rKQxULKlIzwzQSvMJUUNgPwJEEh7gU6xEVxC0ahoOBvN2YI8GH6FNgA=="],
+
+ "v8n": ["v8n@1.5.1", "", {}, "sha512-LdabyT4OffkyXFCe9UT+uMkxNBs5rcTVuZClvxQr08D5TUgo1OFKkoT65qYRCsiKBl/usHjpXvP4hHMzzDRj3A=="],
+
+ "vary": ["vary@1.1.2", "", {}, "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg=="],
+
+ "vfile": ["vfile@6.0.3", "", { "dependencies": { "@types/unist": "^3.0.0", "vfile-message": "^4.0.0" } }, "sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q=="],
+
+ "vfile-location": ["vfile-location@5.0.3", "", { "dependencies": { "@types/unist": "^3.0.0", "vfile": "^6.0.0" } }, "sha512-5yXvWDEgqeiYiBe1lbxYF7UMAIm/IcopxMHrMQDq3nvKcjPKIhZklUKL+AE7J7uApI4kwe2snsK+eI6UTj9EHg=="],
+
+ "vfile-message": ["vfile-message@4.0.3", "", { "dependencies": { "@types/unist": "^3.0.0", "unist-util-stringify-position": "^4.0.0" } }, "sha512-QTHzsGd1EhbZs4AsQ20JX1rC3cOlt/IWJruk893DfLRr57lcnOeMaWG4K0JrRta4mIJZKth2Au3mM3u03/JWKw=="],
+
+ "victory-vendor": ["victory-vendor@37.3.6", "", { "dependencies": { "@types/d3-array": "^3.0.3", "@types/d3-ease": "^3.0.0", "@types/d3-interpolate": "^3.0.1", "@types/d3-scale": "^4.0.2", "@types/d3-shape": "^3.1.0", "@types/d3-time": "^3.0.0", "@types/d3-timer": "^3.0.0", "d3-array": "^3.1.6", "d3-ease": "^3.0.1", "d3-interpolate": "^3.0.1", "d3-scale": "^4.0.2", "d3-shape": "^3.1.0", "d3-time": "^3.0.0", "d3-timer": "^3.0.1" } }, "sha512-SbPDPdDBYp+5MJHhBCAyI7wKM3d5ivekigc2Dk2s7pgbZ9wIgIBYGVw4zGHBml/qTFbexrofXW6Gu4noGxrOwQ=="],
+
+ "virtua": ["virtua@0.48.8", "", { "peerDependencies": { "react": ">=16.14.0", "react-dom": ">=16.14.0", "solid-js": ">=1.0", "svelte": ">=5.0", "vue": ">=3.2" }, "optionalPeers": ["solid-js", "svelte", "vue"] }, "sha512-jpsxOw5V4B6hg44JePRLo9DL0TV7N1lBEVtPjKpAJebXyhI2s9lfiXJESaLapNtr3vtiSk/pWHiLf7B2a6UcgQ=="],
+
+ "vite": ["vite@8.0.0", "", { "dependencies": { "@oxc-project/runtime": "0.115.0", "lightningcss": "^1.32.0", "picomatch": "^4.0.3", "postcss": "^8.5.8", "rolldown": "1.0.0-rc.9", "tinyglobby": "^0.2.15" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^20.19.0 || >=22.12.0", "@vitejs/devtools": "^0.0.0-alpha.31", "esbuild": "^0.27.0", "jiti": ">=1.21.0", "less": "^4.0.0", "sass": "^1.70.0", "sass-embedded": "^1.70.0", "stylus": ">=0.54.8", "sugarss": "^5.0.0", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["@vitejs/devtools", "less", "sass", "sass-embedded", "stylus", "sugarss", "terser"], "bin": "bin/vite.js" }, "sha512-fPGaRNj9Zytaf8LEiBhY7Z6ijnFKdzU/+mL8EFBaKr7Vw1/FWcTBAMW0wLPJAGMPX38ZPVCVgLceWiEqeoqL2Q=="],
+
+ "vitest": ["vitest@4.1.0", "", { "dependencies": { "@vitest/expect": "4.1.0", "@vitest/mocker": "4.1.0", "@vitest/pretty-format": "4.1.0", "@vitest/runner": "4.1.0", "@vitest/snapshot": "4.1.0", "@vitest/spy": "4.1.0", "@vitest/utils": "4.1.0", "es-module-lexer": "^2.0.0", "expect-type": "^1.3.0", "magic-string": "^0.30.21", "obug": "^2.1.1", "pathe": "^2.0.3", "picomatch": "^4.0.3", "std-env": "^4.0.0-rc.1", "tinybench": "^2.9.0", "tinyexec": "^1.0.2", "tinyglobby": "^0.2.15", "tinyrainbow": "^3.0.3", "vite": "^6.0.0 || ^7.0.0 || ^8.0.0-0", "why-is-node-running": "^2.3.0" }, "peerDependencies": { "@edge-runtime/vm": "*", "@opentelemetry/api": "^1.9.0", "@types/node": "^20.0.0 || ^22.0.0 || >=24.0.0", "@vitest/browser-playwright": "4.1.0", "@vitest/browser-preview": "4.1.0", "@vitest/browser-webdriverio": "4.1.0", "@vitest/ui": "4.1.0", "happy-dom": "*", "jsdom": "*", "vite": "^6.0.0 || ^7.0.0 || ^8.0.0-0" }, "optionalPeers": ["@edge-runtime/vm", "@opentelemetry/api", "@vitest/browser-playwright", "@vitest/browser-preview", "@vitest/browser-webdriverio", "@vitest/ui", "happy-dom", "jsdom"], "bin": "vitest.mjs" }, "sha512-YbDrMF9jM2Lqc++2530UourxZHmkKLxrs4+mYhEwqWS97WJ7wOYEkcr+QfRgJ3PW9wz3odRijLZjHEaRLTNbqw=="],
+
+ "vscode-jsonrpc": ["vscode-jsonrpc@8.2.0", "", {}, "sha512-C+r0eKJUIfiDIfwJhria30+TYWPtuHJXHtI7J0YlOmKAo7ogxP20T0zxB7HZQIFhIyvoBPwWskjxrvAtfjyZfA=="],
+
+ "vscode-languageserver": ["vscode-languageserver@9.0.1", "", { "dependencies": { "vscode-languageserver-protocol": "3.17.5" }, "bin": { "installServerIntoExtension": "bin/installServerIntoExtension" } }, "sha512-woByF3PDpkHFUreUa7Hos7+pUWdeWMXRd26+ZX2A8cFx6v/JPTtd4/uN0/jB6XQHYaOlHbio03NTHCqrgG5n7g=="],
+
+ "vscode-languageserver-protocol": ["vscode-languageserver-protocol@3.17.5", "", { "dependencies": { "vscode-jsonrpc": "8.2.0", "vscode-languageserver-types": "3.17.5" } }, "sha512-mb1bvRJN8SVznADSGWM9u/b07H7Ecg0I3OgXDuLdn307rl/J3A9YD6/eYOssqhecL27hK1IPZAsaqh00i/Jljg=="],
+
+ "vscode-languageserver-textdocument": ["vscode-languageserver-textdocument@1.0.12", "", {}, "sha512-cxWNPesCnQCcMPeenjKKsOCKQZ/L6Tv19DTRIGuLWe32lyzWhihGVJ/rcckZXJxfdKCFvRLS3fpBIsV/ZGX4zA=="],
+
+ "vscode-languageserver-types": ["vscode-languageserver-types@3.17.5", "", {}, "sha512-Ld1VelNuX9pdF39h2Hgaeb5hEZM2Z3jUrrMgWQAu82jMtZp7p3vJT3BzToKtZI7NgQssZje5o0zryOrhQvzQAg=="],
+
+ "vscode-uri": ["vscode-uri@3.1.0", "", {}, "sha512-/BpdSx+yCQGnCvecbyXdxHDkuk55/G3xwnC0GqY4gmQ3j+A+g8kzzgB4Nk/SINjqn6+waqw3EgbVF2QKExkRxQ=="],
+
+ "w3c-xmlserializer": ["w3c-xmlserializer@5.0.0", "", { "dependencies": { "xml-name-validator": "^5.0.0" } }, "sha512-o8qghlI8NZHU1lLPrpi2+Uq7abh4GGPpYANlalzWxyWteJOCsr/P+oPBA49TOLu5FTZO4d3F9MnWJfiMo4BkmA=="],
+
+ "wait-on": ["wait-on@9.0.4", "", { "dependencies": { "axios": "^1.13.5", "joi": "^18.0.2", "lodash": "^4.17.23", "minimist": "^1.2.8", "rxjs": "^7.8.2" }, "bin": "bin/wait-on" }, "sha512-k8qrgfwrPVJXTeFY8tl6BxVHiclK11u72DVKhpybHfUL/K6KM4bdyK9EhIVYGytB5MJe/3lq4Tf0hrjM+pvJZQ=="],
+
+ "web-namespaces": ["web-namespaces@2.0.1", "", {}, "sha512-bKr1DkiNa2krS7qxNtdrtHAmzuYGFQLiQ13TsorsdT6ULTkPLKuu5+GsFpDlg6JFjUTwX2DyhMPG2be8uPrqsQ=="],
+
+ "webidl-conversions": ["webidl-conversions@8.0.1", "", {}, "sha512-BMhLD/Sw+GbJC21C/UgyaZX41nPt8bUTg+jWyDeg7e7YN4xOM05YPSIXceACnXVtqyEw/LMClUQMtMZ+PGGpqQ=="],
+
+ "whatwg-mimetype": ["whatwg-mimetype@5.0.0", "", {}, "sha512-sXcNcHOC51uPGF0P/D4NVtrkjSU2fNsm9iog4ZvZJsL3rjoDAzXZhkm2MWt1y+PUdggKAYVoMAIYcs78wJ51Cw=="],
+
+ "whatwg-url": ["whatwg-url@16.0.1", "", { "dependencies": { "@exodus/bytes": "^1.11.0", "tr46": "^6.0.0", "webidl-conversions": "^8.0.1" } }, "sha512-1to4zXBxmXHV3IiSSEInrreIlu02vUOvrhxJJH5vcxYTBDAx51cqZiKdyTxlecdKNSjj8EcxGBxNf6Vg+945gw=="],
+
+ "which": ["which@2.0.2", "", { "dependencies": { "isexe": "^2.0.0" }, "bin": { "node-which": "bin/node-which" } }, "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA=="],
+
+ "which-boxed-primitive": ["which-boxed-primitive@1.1.1", "", { "dependencies": { "is-bigint": "^1.1.0", "is-boolean-object": "^1.2.1", "is-number-object": "^1.1.1", "is-string": "^1.1.1", "is-symbol": "^1.1.1" } }, "sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA=="],
+
+ "which-builtin-type": ["which-builtin-type@1.2.1", "", { "dependencies": { "call-bound": "^1.0.2", "function.prototype.name": "^1.1.6", "has-tostringtag": "^1.0.2", "is-async-function": "^2.0.0", "is-date-object": "^1.1.0", "is-finalizationregistry": "^1.1.0", "is-generator-function": "^1.0.10", "is-regex": "^1.2.1", "is-weakref": "^1.0.2", "isarray": "^2.0.5", "which-boxed-primitive": "^1.1.0", "which-collection": "^1.0.2", "which-typed-array": "^1.1.16" } }, "sha512-6iBczoX+kDQ7a3+YJBnh3T+KZRxM/iYNPXicqk66/Qfm1b93iu+yOImkg0zHbj5LNOcNv1TEADiZ0xa34B4q6Q=="],
+
+ "which-collection": ["which-collection@1.0.2", "", { "dependencies": { "is-map": "^2.0.3", "is-set": "^2.0.3", "is-weakmap": "^2.0.2", "is-weakset": "^2.0.3" } }, "sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw=="],
+
+ "which-typed-array": ["which-typed-array@1.1.20", "", { "dependencies": { "available-typed-arrays": "^1.0.7", "call-bind": "^1.0.8", "call-bound": "^1.0.4", "for-each": "^0.3.5", "get-proto": "^1.0.1", "gopd": "^1.2.0", "has-tostringtag": "^1.0.2" } }, "sha512-LYfpUkmqwl0h9A2HL09Mms427Q1RZWuOHsukfVcKRq9q95iQxdw0ix1JQrqbcDR9PH1QDwf5Qo8OZb5lksZ8Xg=="],
+
+ "why-is-node-running": ["why-is-node-running@2.3.0", "", { "dependencies": { "siginfo": "^2.0.0", "stackback": "0.0.2" }, "bin": "cli.js" }, "sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w=="],
+
+ "word-wrap": ["word-wrap@1.2.5", "", {}, "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA=="],
+
+ "wrap-ansi": ["wrap-ansi@9.0.2", "", { "dependencies": { "ansi-styles": "^6.2.1", "string-width": "^7.0.0", "strip-ansi": "^7.1.0" } }, "sha512-42AtmgqjV+X1VpdOfyTGOYRi0/zsoLqtXQckTmqTeybT+BDIbM/Guxo7x3pE2vtpr1ok6xRqM9OpBe+Jyoqyww=="],
+
+ "wrappy": ["wrappy@1.0.2", "", {}, "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="],
+
+ "wreq-js": ["wreq-js@2.2.0", "", { "os": [ "linux", "win32", "darwin", ], "cpu": [ "x64", "arm64", ] }, "sha512-lXW1/bvdPTpFMdfBftkJIp6OzxkAqAON4dlrKrmaFNT86eu60VCEVmEdK3nWY1ZyiEZ6IXQPRrc1uXG394BoBA=="],
+
+ "wsl-utils": ["wsl-utils@0.3.1", "", { "dependencies": { "is-wsl": "^3.1.0", "powershell-utils": "^0.1.0" } }, "sha512-g/eziiSUNBSsdDJtCLB8bdYEUMj4jR7AGeUo96p/3dTafgjHhpF4RiCFPiRILwjQoDXx5MqkBr4fwWtR3Ky4Wg=="],
+
+ "xml-name-validator": ["xml-name-validator@5.0.0", "", {}, "sha512-EvGK8EJ3DhaHfbRlETOWAS5pO9MZITeauHKJyb8wyajUfQUenkIg2MvLDTZ4T/TgIcm3HU0TFBgWWboAZ30UHg=="],
+
+ "xmlchars": ["xmlchars@2.2.0", "", {}, "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw=="],
+
+ "y18n": ["y18n@5.0.8", "", {}, "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA=="],
+
+ "yallist": ["yallist@3.1.1", "", {}, "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g=="],
+
+ "yaml": ["yaml@2.8.3", "", { "bin": "bin.mjs" }, "sha512-AvbaCLOO2Otw/lW5bmh9d/WEdcDFdQp2Z2ZUH3pX9U2ihyUY0nvLv7J6TrWowklRGPYbB/IuIMfYgxaCPg5Bpg=="],
+
+ "yargs": ["yargs@17.7.2", "", { "dependencies": { "cliui": "^8.0.1", "escalade": "^3.1.1", "get-caller-file": "^2.0.5", "require-directory": "^2.1.1", "string-width": "^4.2.3", "y18n": "^5.0.5", "yargs-parser": "^21.1.1" } }, "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w=="],
+
+ "yargs-parser": ["yargs-parser@21.1.1", "", {}, "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw=="],
+
+ "yazl": ["yazl@3.3.1", "", { "dependencies": { "buffer-crc32": "^1.0.0" } }, "sha512-BbETDVWG+VcMUle37k5Fqp//7SDOK2/1+T7X8TD96M3D9G8jK5VLUdQVdVjGi8im7FGkazX7kk5hkU8X4L5Bng=="],
+
+ "yocto-queue": ["yocto-queue@0.1.0", "", {}, "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q=="],
+
+ "yoctocolors": ["yoctocolors@2.1.2", "", {}, "sha512-CzhO+pFNo8ajLM2d2IW/R93ipy99LWjtwblvC1RsoSUMZgyLbYFr221TnSNT7GjGdYui6P459mw9JH/g/zW2ug=="],
+
+ "zod": ["zod@4.3.6", "", {}, "sha512-rftlrkhHZOcjDwkGlnUtZZkvaPHCsDATp4pGpuOOMDaTdDDXF91wuVDJoWoPsKX/3YPQ5fHuF3STjcYyKr+Qhg=="],
+
+ "zod-to-json-schema": ["zod-to-json-schema@3.25.1", "", { "peerDependencies": { "zod": "^3.25 || ^4" } }, "sha512-pM/SU9d3YAggzi6MtR4h7ruuQlqKtad8e9S0fmxcMi+ueAK5Korys/aWcV9LIIHTVbj01NdzxcnXSN+O74ZIVA=="],
+
+ "zod-validation-error": ["zod-validation-error@4.0.2", "", { "peerDependencies": { "zod": "^3.25.0 || ^4.0.0" } }, "sha512-Q6/nZLe6jxuU80qb/4uJ4t5v2VEZ44lzQjPDhYJNztRQ4wyWc6VF3D3Kb/fAuPetZQnhS3hnajCf9CsWesghLQ=="],
+
+ "zustand": ["zustand@5.0.12", "", { "peerDependencies": { "@types/react": ">=18.0.0", "immer": ">=9.0.6", "react": ">=18.0.0", "use-sync-external-store": ">=1.2.0" } }, "sha512-i77ae3aZq4dhMlRhJVCYgMLKuSiZAaUPAct2AksxQ+gOtimhGMdXljRT21P5BNpeT4kXlLIckvkPM029OljD7g=="],
+
+ "zwitch": ["zwitch@2.0.4", "", {}, "sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A=="],
+
+ "@babel/core/json5": ["json5@2.2.3", "", { "bin": "lib/cli.js" }, "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg=="],
+
+ "@babel/helper-compilation-targets/lru-cache": ["lru-cache@5.1.1", "", { "dependencies": { "yallist": "^3.0.2" } }, "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w=="],
+
+ "@emotion/babel-plugin/@emotion/hash": ["@emotion/hash@0.9.2", "", {}, "sha512-MyqliTZGuOm3+5ZRSaaBGP3USLw6+EGykkwZns2EPC5g8jJ4z9OrdZY9apkl3+UP9+sdz76YYkwCKP5gh8iY3g=="],
+
+ "@emotion/babel-plugin/convert-source-map": ["convert-source-map@1.9.0", "", {}, "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A=="],
+
+ "@emotion/babel-plugin/source-map": ["source-map@0.5.7", "", {}, "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ=="],
+
+ "@emotion/babel-plugin/stylis": ["stylis@4.2.0", "", {}, "sha512-Orov6g6BB1sDfYgzWfTHDOxamtX1bE/zo104Dh9e6fqJ3PooipYyfJ0pUmrZO2wAvO8YbEyeFrkV91XTsGMSrw=="],
+
+ "@emotion/cache/stylis": ["stylis@4.2.0", "", {}, "sha512-Orov6g6BB1sDfYgzWfTHDOxamtX1bE/zo104Dh9e6fqJ3PooipYyfJ0pUmrZO2wAvO8YbEyeFrkV91XTsGMSrw=="],
+
+ "@emotion/serialize/@emotion/hash": ["@emotion/hash@0.9.2", "", {}, "sha512-MyqliTZGuOm3+5ZRSaaBGP3USLw6+EGykkwZns2EPC5g8jJ4z9OrdZY9apkl3+UP9+sdz76YYkwCKP5gh8iY3g=="],
+
+ "@emotion/serialize/@emotion/unitless": ["@emotion/unitless@0.10.0", "", {}, "sha512-dFoMUuQA20zvtVTuxZww6OHoJYgrzfKM1t52mVySDJnMSEa08ruEvdYQbhvyu6soU+NeLVd3yKfTfT0NeV6qGg=="],
+
+ "@eslint-community/eslint-utils/eslint-visitor-keys": ["eslint-visitor-keys@3.4.3", "", {}, "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag=="],
+
+ "@eslint/eslintrc/globals": ["globals@14.0.0", "", {}, "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ=="],
+
+ "@eslint/eslintrc/strip-json-comments": ["strip-json-comments@3.1.1", "", {}, "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig=="],
+
+ "@lobehub/fluent-emoji/emoji-regex": ["emoji-regex@10.6.0", "", {}, "sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A=="],
+
+ "@lobehub/fluent-emoji/lucide-react": ["lucide-react@0.562.0", "", { "peerDependencies": { "react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, "sha512-82hOAu7y0dbVuFfmO4bYF1XEwYk/mEbM5E+b1jgci/udUBEE/R7LF5Ip0CCEmXe8AybRM8L+04eP+LGZeDvkiw=="],
+
+ "@lobehub/ui/immer": ["immer@11.1.4", "", {}, "sha512-XREFCPo6ksxVzP4E0ekD5aMdf8WMwmdNaz6vuvxgI40UaEiu6q3p8X52aU6GdyvLY3XXX/8R7JOTXStz/nBbRw=="],
+
+ "@lobehub/ui/lucide-react": ["lucide-react@0.563.0", "", { "peerDependencies": { "react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, "sha512-8dXPB2GI4dI8jV4MgUDGBeLdGk8ekfqVZ0BdLcrRzocGgG75ltNEmWS+gE7uokKF/0oSUuczNDT+g9hFJ23FkA=="],
+
+ "@lobehub/ui/marked": ["marked@17.0.5", "", { "bin": "bin/marked.js" }, "sha512-6hLvc0/JEbRjRgzI6wnT2P1XuM1/RrrDEX0kPt0N7jGm1133g6X7DlxFasUIx+72aKAr904GTxhSLDrd5DIlZg=="],
+
+ "@modelcontextprotocol/sdk/ajv": ["ajv@8.18.0", "", { "dependencies": { "fast-deep-equal": "^3.1.3", "fast-uri": "^3.0.1", "json-schema-traverse": "^1.0.0", "require-from-string": "^2.0.2" } }, "sha512-PlXPeEWMXMZ7sPYOHqmDyCJzcfNrUr3fGNKtezX14ykXOEIvyK81d+qydx89KY5O71FKMPaQ2vBfBFI5NHR63A=="],
+
+ "@parcel/watcher/node-addon-api": ["node-addon-api@7.1.1", "", {}, "sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ=="],
+
+ "@radix-ui/react-arrow/@radix-ui/react-primitive": ["@radix-ui/react-primitive@2.1.3", "", { "dependencies": { "@radix-ui/react-slot": "1.2.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" } }, "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ=="],
+
+ "@radix-ui/react-dismissable-layer/@radix-ui/react-primitive": ["@radix-ui/react-primitive@2.1.3", "", { "dependencies": { "@radix-ui/react-slot": "1.2.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" } }, "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ=="],
+
+ "@radix-ui/react-popper/@radix-ui/react-primitive": ["@radix-ui/react-primitive@2.1.3", "", { "dependencies": { "@radix-ui/react-slot": "1.2.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" } }, "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ=="],
+
+ "@radix-ui/react-tooltip/@radix-ui/react-portal": ["@radix-ui/react-portal@1.1.9", "", { "dependencies": { "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-use-layout-effect": "1.1.1" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" } }, "sha512-bpIxvq03if6UNwXZ+HTK71JLh4APvnXntDc6XOX8UVq4XQOVl7lwok0AvIl+b8zgCw3fSaVTZMpAPPagXbKmHQ=="],
+
+ "@radix-ui/react-tooltip/@radix-ui/react-primitive": ["@radix-ui/react-primitive@2.1.3", "", { "dependencies": { "@radix-ui/react-slot": "1.2.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" } }, "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ=="],
+
+ "@radix-ui/react-tooltip/@radix-ui/react-slot": ["@radix-ui/react-slot@1.2.3", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.2" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" } }, "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A=="],
+
+ "@radix-ui/react-visually-hidden/@radix-ui/react-primitive": ["@radix-ui/react-primitive@2.1.3", "", { "dependencies": { "@radix-ui/react-slot": "1.2.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" } }, "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ=="],
+
+ "@rc-component/dialog/@rc-component/portal": ["@rc-component/portal@2.2.0", "", { "dependencies": { "@rc-component/util": "^1.2.1", "clsx": "^2.1.1" }, "peerDependencies": { "react": ">=18.0.0", "react-dom": ">=18.0.0" } }, "sha512-oc6FlA+uXCMiwArHsJyHcIkX4q6uKyndrPol2eWX8YPkAnztHOPsFIRtmWG4BMlGE5h7YIRE3NiaJ5VS8Lb1QQ=="],
+
+ "@rc-component/drawer/@rc-component/portal": ["@rc-component/portal@2.2.0", "", { "dependencies": { "@rc-component/util": "^1.2.1", "clsx": "^2.1.1" }, "peerDependencies": { "react": ">=18.0.0", "react-dom": ">=18.0.0" } }, "sha512-oc6FlA+uXCMiwArHsJyHcIkX4q6uKyndrPol2eWX8YPkAnztHOPsFIRtmWG4BMlGE5h7YIRE3NiaJ5VS8Lb1QQ=="],
+
+ "@rc-component/image/@rc-component/portal": ["@rc-component/portal@2.2.0", "", { "dependencies": { "@rc-component/util": "^1.2.1", "clsx": "^2.1.1" }, "peerDependencies": { "react": ">=18.0.0", "react-dom": ">=18.0.0" } }, "sha512-oc6FlA+uXCMiwArHsJyHcIkX4q6uKyndrPol2eWX8YPkAnztHOPsFIRtmWG4BMlGE5h7YIRE3NiaJ5VS8Lb1QQ=="],
+
+ "@rc-component/tour/@rc-component/portal": ["@rc-component/portal@2.2.0", "", { "dependencies": { "@rc-component/util": "^1.2.1", "clsx": "^2.1.1" }, "peerDependencies": { "react": ">=18.0.0", "react-dom": ">=18.0.0" } }, "sha512-oc6FlA+uXCMiwArHsJyHcIkX4q6uKyndrPol2eWX8YPkAnztHOPsFIRtmWG4BMlGE5h7YIRE3NiaJ5VS8Lb1QQ=="],
+
+ "@rc-component/trigger/@rc-component/portal": ["@rc-component/portal@2.2.0", "", { "dependencies": { "@rc-component/util": "^1.2.1", "clsx": "^2.1.1" }, "peerDependencies": { "react": ">=18.0.0", "react-dom": ">=18.0.0" } }, "sha512-oc6FlA+uXCMiwArHsJyHcIkX4q6uKyndrPol2eWX8YPkAnztHOPsFIRtmWG4BMlGE5h7YIRE3NiaJ5VS8Lb1QQ=="],
+
+ "@rc-component/util/react-is": ["react-is@18.3.1", "", {}, "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg=="],
+
+ "@reduxjs/toolkit/immer": ["immer@11.1.4", "", {}, "sha512-XREFCPo6ksxVzP4E0ekD5aMdf8WMwmdNaz6vuvxgI40UaEiu6q3p8X52aU6GdyvLY3XXX/8R7JOTXStz/nBbRw=="],
+
+ "@testing-library/dom/aria-query": ["aria-query@5.3.0", "", { "dependencies": { "dequal": "^2.0.3" } }, "sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A=="],
+
+ "@testing-library/dom/dom-accessibility-api": ["dom-accessibility-api@0.5.16", "", {}, "sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg=="],
+
+ "@typescript-eslint/eslint-plugin/ignore": ["ignore@7.0.5", "", {}, "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg=="],
+
+ "@typescript-eslint/typescript-estree/minimatch": ["minimatch@10.2.4", "", { "dependencies": { "brace-expansion": "^5.0.2" } }, "sha512-oRjTw/97aTBN0RHbYCdtF1MQfvusSIBQM0IZEgzl6426+8jSC0nF1a/GmnVLpfB9yyr6g6FTqWqiZVbxrtaCIg=="],
+
+ "@typescript-eslint/typescript-estree/semver": ["semver@7.7.4", "", { "bin": "bin/semver.js" }, "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA=="],
+
+ "@typescript-eslint/visitor-keys/eslint-visitor-keys": ["eslint-visitor-keys@5.0.1", "", {}, "sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA=="],
+
+ "@unrs/resolver-binding-wasm32-wasi/@napi-rs/wasm-runtime": ["@napi-rs/wasm-runtime@0.2.12", "", { "dependencies": { "@emnapi/core": "^1.4.3", "@emnapi/runtime": "^1.4.3", "@tybys/wasm-util": "^0.10.0" } }, "sha512-ZVWUcfwY4E/yPitQJl481FjFo3K22D6qF0DuFH6Y/nbnE11GY5uguDxZMGXPQ8WQ0128MXQD7TnfHyK4oWoIJQ=="],
+
+ "ajv-formats/ajv": ["ajv@8.18.0", "", { "dependencies": { "fast-deep-equal": "^3.1.3", "fast-uri": "^3.0.1", "json-schema-traverse": "^1.0.0", "require-from-string": "^2.0.2" } }, "sha512-PlXPeEWMXMZ7sPYOHqmDyCJzcfNrUr3fGNKtezX14ykXOEIvyK81d+qydx89KY5O71FKMPaQ2vBfBFI5NHR63A=="],
+
+ "chalk/supports-color": ["supports-color@7.2.0", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw=="],
+
+ "cliui/string-width": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="],
+
+ "cliui/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="],
+
+ "cliui/wrap-ansi": ["wrap-ansi@7.0.0", "", { "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", "strip-ansi": "^6.0.0" } }, "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q=="],
+
+ "cosmiconfig/yaml": ["yaml@1.10.3", "", {}, "sha512-vIYeF1u3CjlhAFekPPAk2h/Kv4T3mAkMox5OymRiJQB0spDP10LHvt+K7G9Ny6NuuMAb25/6n1qyUjAcGNf/AA=="],
+
+ "cytoscape-fcose/cose-base": ["cose-base@2.2.0", "", { "dependencies": { "layout-base": "^2.0.0" } }, "sha512-AzlgcsCbUMymkADOJtQm3wO9S3ltPfYOFD5033keQn9NJzIbtnZj+UdBJe7DYml/8TdbtHJW3j58SOnKhWY/5g=="],
+
+ "d3-dsv/commander": ["commander@7.2.0", "", {}, "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw=="],
+
+ "d3-dsv/iconv-lite": ["iconv-lite@0.6.3", "", { "dependencies": { "safer-buffer": ">= 2.1.2 < 3.0.0" } }, "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw=="],
+
+ "d3-sankey/d3-array": ["d3-array@2.12.1", "", { "dependencies": { "internmap": "^1.0.0" } }, "sha512-B0ErZK/66mHtEsR1TkPEEkwdy+WDesimkM5gpZr5Dsg54BiTA5RXtYW5qTLIAcekaS9xfZrzBLF/OAkB3Qn1YQ=="],
+
+ "d3-sankey/d3-shape": ["d3-shape@1.3.7", "", { "dependencies": { "d3-path": "1" } }, "sha512-EUkvKjqPFUAZyOlhY5gzCxCeI0Aep04LwIRpsZ/mLFelJiUfnK56jo5JMDSE7yyP2kLSb6LtF+S5chMk7uqPqw=="],
+
+ "eslint-import-resolver-node/debug": ["debug@3.2.7", "", { "dependencies": { "ms": "^2.1.1" } }, "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ=="],
+
+ "eslint-module-utils/debug": ["debug@3.2.7", "", { "dependencies": { "ms": "^2.1.1" } }, "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ=="],
+
+ "eslint-plugin-import/debug": ["debug@3.2.7", "", { "dependencies": { "ms": "^2.1.1" } }, "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ=="],
+
+ "eslint-plugin-react/resolve": ["resolve@2.0.0-next.5", "", { "dependencies": { "is-core-module": "^2.13.0", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" }, "bin": "bin/resolve" }, "sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA=="],
+
+ "extend-shallow/is-extendable": ["is-extendable@0.1.1", "", {}, "sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw=="],
+
+ "fast-glob/glob-parent": ["glob-parent@5.1.2", "", { "dependencies": { "is-glob": "^4.0.1" } }, "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow=="],
+
+ "form-data/mime-types": ["mime-types@2.1.35", "", { "dependencies": { "mime-db": "1.52.0" } }, "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw=="],
+
+ "glob/minimatch": ["minimatch@10.2.4", "", { "dependencies": { "brace-expansion": "^5.0.2" } }, "sha512-oRjTw/97aTBN0RHbYCdtF1MQfvusSIBQM0IZEgzl6426+8jSC0nF1a/GmnVLpfB9yyr6g6FTqWqiZVbxrtaCIg=="],
+
+ "hast-util-from-html/parse5": ["parse5@7.3.0", "", { "dependencies": { "entities": "^6.0.0" } }, "sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw=="],
+
+ "hast-util-raw/parse5": ["parse5@7.3.0", "", { "dependencies": { "entities": "^6.0.0" } }, "sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw=="],
+
+ "http-proxy/eventemitter3": ["eventemitter3@4.0.7", "", {}, "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw=="],
+
+ "is-bun-module/semver": ["semver@7.7.4", "", { "bin": "bin/semver.js" }, "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA=="],
+
+ "is-extendable/is-plain-object": ["is-plain-object@2.0.4", "", { "dependencies": { "isobject": "^3.0.1" } }, "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og=="],
+
+ "istanbul-lib-report/supports-color": ["supports-color@7.2.0", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw=="],
+
+ "jsdom/undici": ["undici@7.24.6", "", {}, "sha512-Xi4agocCbRzt0yYMZGMA6ApD7gvtUFaxm4ZmeacWI4cZxaF6C+8I8QfofC20NAePiB/IcvZmzkJ7XPa471AEtA=="],
+
+ "katex/commander": ["commander@8.3.0", "", {}, "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww=="],
+
+ "leva/zustand": ["zustand@3.7.2", "", { "peerDependencies": { "react": ">=16.8" } }, "sha512-PIJDIZKtokhof+9+60cpockVOq05sJzHCriyvaLBmEJixseQ1a5Kdov6fWZfWOu5SK9c+FhH1jU0tntLxRJYMA=="],
+
+ "make-dir/semver": ["semver@7.7.4", "", { "bin": "bin/semver.js" }, "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA=="],
+
+ "mdast-util-find-and-replace/escape-string-regexp": ["escape-string-regexp@5.0.0", "", {}, "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw=="],
+
+ "mermaid/marked": ["marked@16.4.2", "", { "bin": "bin/marked.js" }, "sha512-TI3V8YYWvkVf3KJe1dRkpnjs68JUPyEa5vjKrp1XEEJUAOaQc+Qj+L1qWbPd0SJuAdQkFU0h73sXXqwDYxsiDA=="],
+
+ "mermaid/uuid": ["uuid@11.1.0", "", { "bin": "dist/esm/bin/uuid" }, "sha512-0/A9rDy9P7cJ+8w1c9WD9V//9Wj15Ce2MPz8Ri6032usz+NfePxx5AcN3bN+r6ZL6jEo066/yNYB3tn4pQEx+A=="],
+
+ "micromatch/picomatch": ["picomatch@2.3.2", "", {}, "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA=="],
+
+ "next/@swc/helpers": ["@swc/helpers@0.5.15", "", { "dependencies": { "tslib": "^2.8.0" } }, "sha512-JQ5TuMi45Owi4/BIMAJBoSQoOJu12oOk/gADqlcUL9JEdHB8vyjUSsxqeNXnmXHjYKMi2WcYtezGEEhqUI/E2g=="],
+
+ "next/postcss": ["postcss@8.4.31", "", { "dependencies": { "nanoid": "^3.3.6", "picocolors": "^1.0.0", "source-map-js": "^1.0.2" } }, "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ=="],
+
+ "node-abi/semver": ["semver@7.7.4", "", { "bin": "bin/semver.js" }, "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA=="],
+
+ "ora/chalk": ["chalk@5.6.2", "", {}, "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA=="],
+
+ "parse-entities/@types/unist": ["@types/unist@2.0.11", "", {}, "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA=="],
+
+ "playwright/fsevents": ["fsevents@2.3.2", "", { "os": "darwin" }, "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA=="],
+
+ "pretty-format/ansi-styles": ["ansi-styles@5.2.0", "", {}, "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA=="],
+
+ "pretty-format/react-is": ["react-is@17.0.2", "", {}, "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w=="],
+
+ "rc/strip-json-comments": ["strip-json-comments@2.0.1", "", {}, "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ=="],
+
+ "rc-menu/@rc-component/trigger": ["@rc-component/trigger@2.3.1", "", { "dependencies": { "@babel/runtime": "^7.23.2", "@rc-component/portal": "^1.1.0", "classnames": "^2.3.2", "rc-motion": "^2.0.0", "rc-resize-observer": "^1.3.1", "rc-util": "^5.44.0" }, "peerDependencies": { "react": ">=16.9.0", "react-dom": ">=16.9.0" } }, "sha512-ORENF39PeXTzM+gQEshuk460Z8N4+6DkjpxlpE7Q3gYy1iBpLrx0FOJz3h62ryrJZ/3zCAUIkT1Pb/8hHWpb3A=="],
+
+ "rc-util/react-is": ["react-is@18.3.1", "", {}, "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg=="],
+
+ "react-rnd/tslib": ["tslib@2.6.2", "", {}, "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q=="],
+
+ "rolldown/@rolldown/pluginutils": ["@rolldown/pluginutils@1.0.0-rc.9", "", {}, "sha512-w6oiRWgEBl04QkFZgmW+jnU1EC9b57Oihi2ot3HNWIQRqgHp5PnYDia5iZ5FF7rpa4EQdiqMDXjlqKGXBhsoXw=="],
+
+ "set-value/is-extendable": ["is-extendable@0.1.1", "", {}, "sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw=="],
+
+ "set-value/is-plain-object": ["is-plain-object@2.0.4", "", { "dependencies": { "isobject": "^3.0.1" } }, "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og=="],
+
+ "sharp/semver": ["semver@7.7.4", "", { "bin": "bin/semver.js" }, "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA=="],
+
+ "slice-ansi/ansi-styles": ["ansi-styles@6.2.3", "", {}, "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg=="],
+
+ "slice-ansi/is-fullwidth-code-point": ["is-fullwidth-code-point@5.1.0", "", { "dependencies": { "get-east-asian-width": "^1.3.1" } }, "sha512-5XHYaSyiqADb4RnZ1Bdad6cPp8Toise4TzEjcOYDHZkTCbKgiUl7WTUCpNWHuxmDt91wnsZBc9xinNzopv3JMQ=="],
+
+ "split-string/extend-shallow": ["extend-shallow@3.0.2", "", { "dependencies": { "assign-symbols": "^1.0.0", "is-extendable": "^1.0.1" } }, "sha512-BwY5b5Ql4+qZoefgMj2NUmx+tehVTH/Kf4k1ZEtOHNFcm2wSxMRo992l6X3TIgni2eZVTZ85xMOjF31fwZAj6Q=="],
+
+ "strip-ansi/ansi-regex": ["ansi-regex@6.2.2", "", {}, "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg=="],
+
+ "test-exclude/minimatch": ["minimatch@10.2.4", "", { "dependencies": { "brace-expansion": "^5.0.2" } }, "sha512-oRjTw/97aTBN0RHbYCdtF1MQfvusSIBQM0IZEgzl6426+8jSC0nF1a/GmnVLpfB9yyr6g6FTqWqiZVbxrtaCIg=="],
+
+ "tsyringe/tslib": ["tslib@1.14.1", "", {}, "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg=="],
+
+ "vite/lightningcss": ["lightningcss@1.32.0", "", { "dependencies": { "detect-libc": "^2.0.3" }, "optionalDependencies": { "lightningcss-android-arm64": "1.32.0", "lightningcss-darwin-arm64": "1.32.0", "lightningcss-darwin-x64": "1.32.0", "lightningcss-freebsd-x64": "1.32.0", "lightningcss-linux-arm-gnueabihf": "1.32.0", "lightningcss-linux-arm64-gnu": "1.32.0", "lightningcss-linux-arm64-musl": "1.32.0", "lightningcss-linux-x64-gnu": "1.32.0", "lightningcss-linux-x64-musl": "1.32.0", "lightningcss-win32-arm64-msvc": "1.32.0", "lightningcss-win32-x64-msvc": "1.32.0" } }, "sha512-NXYBzinNrblfraPGyrbPoD19C1h9lfI/1mzgWYvXUTe414Gz/X1FD2XBZSZM7rRTrMA8JL3OtAaGifrIKhQ5yQ=="],
+
+ "wrap-ansi/ansi-styles": ["ansi-styles@6.2.3", "", {}, "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg=="],
+
+ "wrap-ansi/string-width": ["string-width@7.2.0", "", { "dependencies": { "emoji-regex": "^10.3.0", "get-east-asian-width": "^1.0.0", "strip-ansi": "^7.1.0" } }, "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ=="],
+
+ "yargs/string-width": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="],
+
+ "@modelcontextprotocol/sdk/ajv/json-schema-traverse": ["json-schema-traverse@1.0.0", "", {}, "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug=="],
+
+ "@radix-ui/react-arrow/@radix-ui/react-primitive/@radix-ui/react-slot": ["@radix-ui/react-slot@1.2.3", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.2" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" } }, "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A=="],
+
+ "@radix-ui/react-dismissable-layer/@radix-ui/react-primitive/@radix-ui/react-slot": ["@radix-ui/react-slot@1.2.3", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.2" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" } }, "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A=="],
+
+ "@radix-ui/react-popper/@radix-ui/react-primitive/@radix-ui/react-slot": ["@radix-ui/react-slot@1.2.3", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.2" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" } }, "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A=="],
+
+ "@radix-ui/react-visually-hidden/@radix-ui/react-primitive/@radix-ui/react-slot": ["@radix-ui/react-slot@1.2.3", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.2" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" } }, "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A=="],
+
+ "@typescript-eslint/typescript-estree/minimatch/brace-expansion": ["brace-expansion@5.0.5", "", { "dependencies": { "balanced-match": "^4.0.2" } }, "sha512-VZznLgtwhn+Mact9tfiwx64fA9erHH/MCXEUfB/0bX/6Fz6ny5EGTXYltMocqg4xFAQZtnO3DHWWXi8RiuN7cQ=="],
+
+ "ajv-formats/ajv/json-schema-traverse": ["json-schema-traverse@1.0.0", "", {}, "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug=="],
+
+ "cliui/string-width/emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="],
+
+ "cytoscape-fcose/cose-base/layout-base": ["layout-base@2.0.1", "", {}, "sha512-dp3s92+uNI1hWIpPGH3jK2kxE2lMjdXdr+DH8ynZHpd6PUlH6x6cbuXnoMmiNumznqaNO31xu9e79F0uuZ0JFg=="],
+
+ "d3-sankey/d3-array/internmap": ["internmap@1.0.1", "", {}, "sha512-lDB5YccMydFBtasVtxnZ3MRBHuaoE8GKsppq+EchKL2U4nK/DmEpPHNH8MZe5HkMtpSiTSOZwfN0tzYjO/lJEw=="],
+
+ "d3-sankey/d3-shape/d3-path": ["d3-path@1.0.9", "", {}, "sha512-VLaYcn81dtHVTjEHd8B+pbe9yHWpXKZUC87PzoFmsFrJqgFwDe/qxfp5MlfsfM1V5E/iVt0MmEbWQ7FVIXh/bg=="],
+
+ "form-data/mime-types/mime-db": ["mime-db@1.52.0", "", {}, "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg=="],
+
+ "glob/minimatch/brace-expansion": ["brace-expansion@5.0.5", "", { "dependencies": { "balanced-match": "^4.0.2" } }, "sha512-VZznLgtwhn+Mact9tfiwx64fA9erHH/MCXEUfB/0bX/6Fz6ny5EGTXYltMocqg4xFAQZtnO3DHWWXi8RiuN7cQ=="],
+
+ "test-exclude/minimatch/brace-expansion": ["brace-expansion@5.0.5", "", { "dependencies": { "balanced-match": "^4.0.2" } }, "sha512-VZznLgtwhn+Mact9tfiwx64fA9erHH/MCXEUfB/0bX/6Fz6ny5EGTXYltMocqg4xFAQZtnO3DHWWXi8RiuN7cQ=="],
+
+ "vite/lightningcss/lightningcss-android-arm64": ["lightningcss-android-arm64@1.32.0", "", { "os": "android", "cpu": "arm64" }, "sha512-YK7/ClTt4kAK0vo6w3X+Pnm0D2cf2vPHbhOXdoNti1Ga0al1P4TBZhwjATvjNwLEBCnKvjJc2jQgHXH0NEwlAg=="],
+
+ "vite/lightningcss/lightningcss-darwin-arm64": ["lightningcss-darwin-arm64@1.32.0", "", { "os": "darwin", "cpu": "arm64" }, "sha512-RzeG9Ju5bag2Bv1/lwlVJvBE3q6TtXskdZLLCyfg5pt+HLz9BqlICO7LZM7VHNTTn/5PRhHFBSjk5lc4cmscPQ=="],
+
+ "vite/lightningcss/lightningcss-darwin-x64": ["lightningcss-darwin-x64@1.32.0", "", { "os": "darwin", "cpu": "x64" }, "sha512-U+QsBp2m/s2wqpUYT/6wnlagdZbtZdndSmut/NJqlCcMLTWp5muCrID+K5UJ6jqD2BFshejCYXniPDbNh73V8w=="],
+
+ "vite/lightningcss/lightningcss-freebsd-x64": ["lightningcss-freebsd-x64@1.32.0", "", { "os": "freebsd", "cpu": "x64" }, "sha512-JCTigedEksZk3tHTTthnMdVfGf61Fky8Ji2E4YjUTEQX14xiy/lTzXnu1vwiZe3bYe0q+SpsSH/CTeDXK6WHig=="],
+
+ "vite/lightningcss/lightningcss-linux-arm-gnueabihf": ["lightningcss-linux-arm-gnueabihf@1.32.0", "", { "os": "linux", "cpu": "arm" }, "sha512-x6rnnpRa2GL0zQOkt6rts3YDPzduLpWvwAF6EMhXFVZXD4tPrBkEFqzGowzCsIWsPjqSK+tyNEODUBXeeVHSkw=="],
+
+ "vite/lightningcss/lightningcss-linux-arm64-gnu": ["lightningcss-linux-arm64-gnu@1.32.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-0nnMyoyOLRJXfbMOilaSRcLH3Jw5z9HDNGfT/gwCPgaDjnx0i8w7vBzFLFR1f6CMLKF8gVbebmkUN3fa/kQJpQ=="],
+
+ "vite/lightningcss/lightningcss-linux-arm64-musl": ["lightningcss-linux-arm64-musl@1.32.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-UpQkoenr4UJEzgVIYpI80lDFvRmPVg6oqboNHfoH4CQIfNA+HOrZ7Mo7KZP02dC6LjghPQJeBsvXhJod/wnIBg=="],
+
+ "vite/lightningcss/lightningcss-linux-x64-gnu": ["lightningcss-linux-x64-gnu@1.32.0", "", { "os": "linux", "cpu": "x64" }, "sha512-V7Qr52IhZmdKPVr+Vtw8o+WLsQJYCTd8loIfpDaMRWGUZfBOYEJeyJIkqGIDMZPwPx24pUMfwSxxI8phr/MbOA=="],
+
+ "vite/lightningcss/lightningcss-linux-x64-musl": ["lightningcss-linux-x64-musl@1.32.0", "", { "os": "linux", "cpu": "x64" }, "sha512-bYcLp+Vb0awsiXg/80uCRezCYHNg1/l3mt0gzHnWV9XP1W5sKa5/TCdGWaR/zBM2PeF/HbsQv/j2URNOiVuxWg=="],
+
+ "vite/lightningcss/lightningcss-win32-arm64-msvc": ["lightningcss-win32-arm64-msvc@1.32.0", "", { "os": "win32", "cpu": "arm64" }, "sha512-8SbC8BR40pS6baCM8sbtYDSwEVQd4JlFTOlaD3gWGHfThTcABnNDBda6eTZeqbofalIJhFx0qKzgHJmcPTnGdw=="],
+
+ "vite/lightningcss/lightningcss-win32-x64-msvc": ["lightningcss-win32-x64-msvc@1.32.0", "", { "os": "win32", "cpu": "x64" }, "sha512-Amq9B/SoZYdDi1kFrojnoqPLxYhQ4Wo5XiL8EVJrVsB8ARoC1PWW6VGtT0WKCemjy8aC+louJnjS7U18x3b06Q=="],
+
+ "wrap-ansi/string-width/emoji-regex": ["emoji-regex@10.6.0", "", {}, "sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A=="],
+
+ "yargs/string-width/emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="],
+
+ "yargs/string-width/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="],
+
+ "@typescript-eslint/typescript-estree/minimatch/brace-expansion/balanced-match": ["balanced-match@4.0.4", "", {}, "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA=="],
+
+ "glob/minimatch/brace-expansion/balanced-match": ["balanced-match@4.0.4", "", {}, "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA=="],
+
+ "test-exclude/minimatch/brace-expansion/balanced-match": ["balanced-match@4.0.4", "", {}, "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA=="],
+ }
+}
diff --git a/COVERAGE_PLAN.md b/docs/COVERAGE_PLAN.md
similarity index 100%
rename from COVERAGE_PLAN.md
rename to docs/COVERAGE_PLAN.md
diff --git a/docs/USER_GUIDE.md b/docs/USER_GUIDE.md
index e149dbac77..859a428f3f 100644
--- a/docs/USER_GUIDE.md
+++ b/docs/USER_GUIDE.md
@@ -507,26 +507,27 @@ post_install() {
### Environment Variables
-| Variable | Default | Description |
-| -------------------------------------- | ------------------------------------ | ------------------------------------------------------------------------------------------ |
-| `JWT_SECRET` | `omniroute-default-secret-change-me` | JWT signing secret (**change in production**) |
-| `INITIAL_PASSWORD` | `123456` | First login password |
-| `DATA_DIR` | `~/.omniroute` | Data directory (db, usage, logs) |
-| `PORT` | framework default | Service port (`20128` in examples) |
-| `HOSTNAME` | framework default | Bind host (Docker defaults to `0.0.0.0`) |
-| `NODE_ENV` | runtime default | Set `production` for deploy |
-| `BASE_URL` | `http://localhost:20128` | Server-side internal base URL |
-| `CLOUD_URL` | `https://omniroute.dev` | Cloud sync endpoint base URL |
-| `API_KEY_SECRET` | `endpoint-proxy-api-key-secret` | HMAC secret for generated API keys |
-| `REQUIRE_API_KEY` | `false` | Enforce Bearer API key on `/v1/*` |
-| `ALLOW_API_KEY_REVEAL` | `false` | Allow Api Manager to copy full API keys on demand |
-| `DISABLE_SQLITE_AUTO_BACKUP` | `false` | Disable automatic SQLite snapshots before writes/import/restore; manual backups still work |
-| `ENABLE_REQUEST_LOGS` | `false` | Enables request/response logs |
-| `AUTH_COOKIE_SECURE` | `false` | Force `Secure` auth cookie (behind HTTPS reverse proxy) |
-| `CLOUDFLARED_BIN` | unset | Use an existing `cloudflared` binary instead of managed download |
-| `OMNIROUTE_MEMORY_MB` | `512` | Node.js heap limit in MB |
-| `PROMPT_CACHE_MAX_SIZE` | `50` | Max prompt cache entries |
-| `SEMANTIC_CACHE_MAX_SIZE` | `100` | Max semantic cache entries |
+| Variable | Default | Description |
+| --------------------------------------- | ------------------------------------ | --------------------------------------------------------------------------------------------------------- |
+| `JWT_SECRET` | `omniroute-default-secret-change-me` | JWT signing secret (**change in production**) |
+| `INITIAL_PASSWORD` | `123456` | First login password |
+| `DATA_DIR` | `~/.omniroute` | Data directory (db, usage, logs) |
+| `PORT` | framework default | Service port (`20128` in examples) |
+| `HOSTNAME` | framework default | Bind host (Docker defaults to `0.0.0.0`) |
+| `NODE_ENV` | runtime default | Set `production` for deploy |
+| `BASE_URL` | `http://localhost:20128` | Server-side internal base URL |
+| `CLOUD_URL` | `https://omniroute.dev` | Cloud sync endpoint base URL |
+| `API_KEY_SECRET` | `endpoint-proxy-api-key-secret` | HMAC secret for generated API keys |
+| `REQUIRE_API_KEY` | `false` | Enforce Bearer API key on `/v1/*` |
+| `ALLOW_API_KEY_REVEAL` | `false` | Allow Api Manager to copy full API keys on demand |
+| `PROVIDER_LIMITS_SYNC_INTERVAL_MINUTES` | `70` | Server-side refresh cadence for cached Provider Limits data; UI refresh buttons still trigger manual sync |
+| `DISABLE_SQLITE_AUTO_BACKUP` | `false` | Disable automatic SQLite snapshots before writes/import/restore; manual backups still work |
+| `ENABLE_REQUEST_LOGS` | `false` | Enables request/response logs |
+| `AUTH_COOKIE_SECURE` | `false` | Force `Secure` auth cookie (behind HTTPS reverse proxy) |
+| `CLOUDFLARED_BIN` | unset | Use an existing `cloudflared` binary instead of managed download |
+| `OMNIROUTE_MEMORY_MB` | `512` | Node.js heap limit in MB |
+| `PROMPT_CACHE_MAX_SIZE` | `50` | Max prompt cache entries |
+| `SEMANTIC_CACHE_MAX_SIZE` | `100` | Max semantic cache entries |
For the full environment variable reference, see the [README](../README.md).
@@ -769,10 +770,10 @@ OmniRoute implements provider-level resilience with four components:
Manage database backups in **Dashboard → Settings → System & Storage**.
-| Action | Description |
-| ------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| **Export Database** | Downloads the current SQLite database as a `.sqlite` file |
-| **Export All (.tar.gz)** | Downloads a full backup archive including: database, settings, combos, provider connections (no credentials), API key metadata |
+| Action | Description |
+| ------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------- |
+| **Export Database** | Downloads the current SQLite database as a `.sqlite` file |
+| **Export All (.tar.gz)** | Downloads a full backup archive including: database, settings, combos, provider connections (no credentials), API key metadata |
| **Import Database** | Upload a `.sqlite` file to replace the current database. A pre-import backup is automatically created unless `DISABLE_SQLITE_AUTO_BACKUP=true` |
```bash
diff --git a/docs/adr/0001-proxy-registry-limit-generalization.md b/docs/adr/0001-proxy-registry-limit-generalization.md
deleted file mode 100644
index bb7d766e14..0000000000
--- a/docs/adr/0001-proxy-registry-limit-generalization.md
+++ /dev/null
@@ -1,46 +0,0 @@
-# ADR-0001: Proxy Registry + Usage Control Generalization
-
-Date: 2026-03-17
-Status: Accepted
-
-## Context
-
-OmniRoute sudah punya:
-
-- Proxy assignment berbasis config-map (`global`, `providers`, `combos`, `keys`).
-- Quota-aware selection khusus provider tertentu (notably `codex`).
-
-Gap utama:
-
-- Proxy belum menjadi aset reusable yang bisa di-manage sebagai entitas (metadata, where-used, safe delete).
-- Usage policy belum konsisten lintas provider.
-- Error contract API belum seragam untuk endpoint manajemen.
-
-## Decision
-
-1. Tambah **Proxy Registry** sebagai domain baru di DB (`proxy_registry`, `proxy_assignments`).
-2. Pertahankan kompatibilitas assignment lama (fallback ke `proxyConfig` lama).
-3. Resolver runtime pakai prioritas:
- - account -> provider -> global (registry)
- - fallback ke legacy resolver jika registry belum ada assignment
-4. Wajib redaction kredensial di output list registry default.
-5. Standarkan error JSON untuk endpoint manajemen proxy agar konsisten dan punya `requestId`.
-
-## Consequences
-
-Positif:
-
-- Proxy reusable dan bisa dilacak pemakaiannya.
-- Safe delete bisa ditegakkan (409 saat masih dipakai).
-- Migrasi bertahap tanpa breaking change runtime.
-
-Negatif:
-
-- Ada dual-source sementara (registry + legacy config) sampai migrasi selesai.
-- Butuh endpoint assignment tambahan dan pemetaan scope yang konsisten.
-
-## Follow-up
-
-- Migrasi UI provider/account dari input raw proxy ke selector registry.
-- Tambah health telemetry per proxy dan alerting.
-- Generalisasi usage control ke provider lain melalui interface policy yang sama.
diff --git a/docs/adr/0002-api-error-contract-management-endpoints.md b/docs/adr/0002-api-error-contract-management-endpoints.md
deleted file mode 100644
index fced830c61..0000000000
--- a/docs/adr/0002-api-error-contract-management-endpoints.md
+++ /dev/null
@@ -1,32 +0,0 @@
-# ADR-0002: Error Contract for Management Endpoints
-
-Date: 2026-03-17
-Status: Accepted
-
-## Decision
-
-Management endpoints (proxy config, proxy registry, and proxy assignments) return a uniform error body:
-
-```json
-{
- "error": {
- "message": "Human-readable summary",
- "type": "invalid_request | not_found | conflict | server_error",
- "details": {}
- },
- "requestId": "uuid"
-}
-```
-
-## Status Mapping
-
-- 400: invalid request / validation failure
-- 404: resource not found
-- 409: resource conflict (for example, proxy still assigned)
-- 500: unexpected server error
-
-## Notes
-
-- `requestId` is mandatory for log correlation.
-- `details` is optional and only used for safe validation details.
-- Sensitive secrets (proxy credentials, tokens) must never appear in `message` or `details`.
diff --git a/docs/adr/0003-security-checklist-proxy-limits.md b/docs/adr/0003-security-checklist-proxy-limits.md
deleted file mode 100644
index 5ff89da6a0..0000000000
--- a/docs/adr/0003-security-checklist-proxy-limits.md
+++ /dev/null
@@ -1,16 +0,0 @@
-# ADR-0003: Security Checklist for Proxy Registry and Usage Controls
-
-Date: 2026-03-17
-Status: Accepted
-
-## Checklist
-
-- Validate all management payloads with Zod.
-- Reject malformed scope assignment updates with status 400.
-- Reject deleting an in-use proxy with status 409 unless forced.
-- Never expose proxy username/password in list responses by default.
-- Never log raw credentials or token values.
-- Keep error responses free from internal stack traces.
-- Protect management endpoints with existing auth middleware policy.
-- Audit mutating operations: create/update/delete/assign/migrate.
-- Ensure resolver fallback to legacy config while migration is in transition.
diff --git a/docs/i18n/README.md b/docs/i18n/README.md
index bb250f5ee4..8c8a0369bd 100644
--- a/docs/i18n/README.md
+++ b/docs/i18n/README.md
@@ -33,3 +33,4 @@ Translations of documentation into 30 languages. Code blocks remain in English.
- 🇮🇱 **עברית** (`he`): [Docs Root](./he/README.md)
- 🇵🇭 **Filipino** (`phi`): [Docs Root](./phi/README.md)
- 🇧🇷 **Português (Brasil)** (`pt-BR`): [Docs Root](./pt-BR/README.md)
+- 🇨🇿 **Čeština** (`cs`): [Docs Root](./cs/README.md)
diff --git a/docs/i18n/ar/CHANGELOG.md b/docs/i18n/ar/CHANGELOG.md
index 15b3637d59..1cba534503 100644
--- a/docs/i18n/ar/CHANGELOG.md
+++ b/docs/i18n/ar/CHANGELOG.md
@@ -1,12 +1,92 @@
# Changelog (العربية)
-🌐 **Languages:** 🇺🇸 [English](../../../CHANGELOG.md) · 🇪🇸 [es](../es/CHANGELOG.md) · 🇫🇷 [fr](../fr/CHANGELOG.md) · 🇩🇪 [de](../de/CHANGELOG.md) · 🇮🇹 [it](../it/CHANGELOG.md) · 🇷🇺 [ru](../ru/CHANGELOG.md) · 🇨🇳 [zh-CN](../zh-CN/CHANGELOG.md) · 🇯🇵 [ja](../ja/CHANGELOG.md) · 🇰🇷 [ko](../ko/CHANGELOG.md) · 🇸🇦 [ar](../ar/CHANGELOG.md) · 🇮🇳 [in](../in/CHANGELOG.md) · 🇹🇭 [th](../th/CHANGELOG.md) · 🇻🇳 [vi](../vi/CHANGELOG.md) · 🇮🇩 [id](../id/CHANGELOG.md) · 🇲🇾 [ms](../ms/CHANGELOG.md) · 🇳🇱 [nl](../nl/CHANGELOG.md) · 🇵🇱 [pl](../pl/CHANGELOG.md) · 🇸🇪 [sv](../sv/CHANGELOG.md) · 🇳🇴 [no](../no/CHANGELOG.md) · 🇩🇰 [da](../da/CHANGELOG.md) · 🇫🇮 [fi](../fi/CHANGELOG.md) · 🇵🇹 [pt](../pt/CHANGELOG.md) · 🇷🇴 [ro](../ro/CHANGELOG.md) · 🇭🇺 [hu](../hu/CHANGELOG.md) · 🇧🇬 [bg](../bg/CHANGELOG.md) · 🇸🇰 [sk](../sk/CHANGELOG.md) · 🇺🇦 [uk-UA](../uk-UA/CHANGELOG.md) · 🇮🇱 [he](../he/CHANGELOG.md) · 🇵🇭 [phi](../phi/CHANGELOG.md) · 🇧🇷 [pt-BR](../pt-BR/CHANGELOG.md)
+🌐 **Languages:** 🇺🇸 [English](../../../CHANGELOG.md) · 🇪🇸 [es](../es/CHANGELOG.md) · 🇫🇷 [fr](../fr/CHANGELOG.md) · 🇩🇪 [de](../de/CHANGELOG.md) · 🇮🇹 [it](../it/CHANGELOG.md) · 🇷🇺 [ru](../ru/CHANGELOG.md) · 🇨🇳 [zh-CN](../zh-CN/CHANGELOG.md) · 🇯🇵 [ja](../ja/CHANGELOG.md) · 🇰🇷 [ko](../ko/CHANGELOG.md) · 🇸🇦 [ar](../ar/CHANGELOG.md) · 🇮🇳 [in](../in/CHANGELOG.md) · 🇹🇭 [th](../th/CHANGELOG.md) · 🇻🇳 [vi](../vi/CHANGELOG.md) · 🇮🇩 [id](../id/CHANGELOG.md) · 🇲🇾 [ms](../ms/CHANGELOG.md) · 🇳🇱 [nl](../nl/CHANGELOG.md) · 🇵🇱 [pl](../pl/CHANGELOG.md) · 🇸🇪 [sv](../sv/CHANGELOG.md) · 🇳🇴 [no](../no/CHANGELOG.md) · 🇩🇰 [da](../da/CHANGELOG.md) · 🇫🇮 [fi](../fi/CHANGELOG.md) · 🇵🇹 [pt](../pt/CHANGELOG.md) · 🇷🇴 [ro](../ro/CHANGELOG.md) · 🇭🇺 [hu](../hu/CHANGELOG.md) · 🇧🇬 [bg](../bg/CHANGELOG.md) · 🇸🇰 [sk](../sk/CHANGELOG.md) · 🇺🇦 [uk-UA](../uk-UA/CHANGELOG.md) · 🇮🇱 [he](../he/CHANGELOG.md) · 🇵🇭 [phi](../phi/CHANGELOG.md) · 🇧🇷 [pt-BR](../pt-BR/CHANGELOG.md) · 🇨🇿 [cs](../cs/CHANGELOG.md)
---
-
## [Unreleased]
+### 🛠️ Maintenance
+
+- **AGENTS.md rewrite:** Condensed from 297→153 lines. Added build/lint/test commands (including single-test execution), code style guidelines (Prettier, TypeScript, ESLint, naming, imports, error handling, security), and trimmed verbose architecture tables for AI agent consumption.
+
+## [3.4.2] - 2026-04-01
+
+### 🐛 Bug Fixes
+
+- **CI Stabilization:** Fixed failing analytics/settings Playwright selectors and request assertions so GitHub Actions E2E runs pass reliably across localized UIs and switch-based controls.
+- **Deterministic Tests:** Removed date-sensitive quota fixtures from Copilot usage tests and aligned idempotency/model catalog tests with the merged runtime behavior.
+- **MCP Type Hardening:** Removed zero-budget explicit `any` regressions from the MCP server tool registration path, restoring the `check:any-budget:t11` workflow gate.
+
+### 🛠️ Maintenance
+
+- **Release Branch Integration:** Consolidated the active feature branches into `release/v3.4.2` on top of current `main` and validated the branch with lint, unit, coverage, build, and CI-mode E2E runs.
+
+## [3.4.1] - 2026-03-31
+
+> [!WARNING]
+> **BREAKING CHANGE: request logging, retention, and logging environment variables have been redesigned.**
+> On the first startup after upgrading, OmniRoute archives legacy request logs from `DATA_DIR/logs/`, legacy `DATA_DIR/call_logs/`, and `DATA_DIR/log.txt` into `DATA_DIR/log_archives/*.zip`, then removes the deprecated layout and switches to the new unified artifact format under `DATA_DIR/call_logs/`.
+
+### ✨ New Features
+
+- **.ENV Migration Utility:** Included `scripts/migrate-env.mjs` to seamlessly migrate `= 18 < 24 (recommended: 22 LTS)
+- **npm** 10+
+- **Git**
+
+### Clone & Install
+
+```bash
+git clone https://github.com/diegosouzapw/OmniRoute.git
+cd OmniRoute
+npm install
+```
+
+### Environment Variables
+
+```bash
+# Create your .env from the template
+cp .env.example .env
+
+# Generate required secrets
+echo "JWT_SECRET=$(openssl rand -base64 48)" >> .env
+echo "API_KEY_SECRET=$(openssl rand -hex 32)" >> .env
+```
+
+Key variables for development:
+
+| Variable | Development Default | Description |
+| ---------------------- | ------------------------ | --------------------- |
+| `PORT` | `20128` | Server port |
+| `NEXT_PUBLIC_BASE_URL` | `http://localhost:20128` | Base URL for frontend |
+| `JWT_SECRET` | (generate above) | JWT signing secret |
+| `INITIAL_PASSWORD` | `CHANGEME` | First login password |
+| `APP_LOG_LEVEL` | `info` | Log verbosity level |
+
+### Dashboard Settings
+
+The dashboard provides UI toggles for features that can also be configured via environment variables:
+
+| Setting Location | Toggle | Description |
+| ------------------- | ------------------ | ------------------------------ |
+| Settings → Advanced | Debug Mode | Enable debug request logs (UI) |
+| Settings → General | Sidebar Visibility | Show/hide sidebar sections |
+
+These settings are stored in the database and persist across restarts, overriding env var defaults when set.
+
+### Running Locally
+
+```bash
+# Development mode (hot reload)
+npm run dev
+
+# Production build
+npm run build
+npm run start
+
+# Common port configuration
+PORT=20128 NEXT_PUBLIC_BASE_URL=http://localhost:20128 npm run dev
+```
+
+Default URLs:
+
+- **Dashboard**: `http://localhost:20128/dashboard`
+- **API**: `http://localhost:20128/v1`
+
+---
+
+## Git Workflow
+
+> ⚠️ **NEVER commit directly to `main`.** Always use feature branches.
+
+```bash
+git checkout -b feat/your-feature-name
+# ... make changes ...
+git commit -m "feat: describe your change"
+git push -u origin feat/your-feature-name
+# Open a Pull Request on GitHub
+```
+
+### Branch Naming
+
+| Prefix | Purpose |
+| ----------- | ------------------------- |
+| `feat/` | New features |
+| `fix/` | Bug fixes |
+| `refactor/` | Code restructuring |
+| `docs/` | Documentation changes |
+| `test/` | Test additions/fixes |
+| `chore/` | Tooling, CI, dependencies |
+
+### Commit Messages
+
+Follow [Conventional Commits](https://www.conventionalcommits.org/):
+
+```
+feat: add circuit breaker for provider calls
+fix: resolve JWT secret validation edge case
+docs: update SECURITY.md with PII protection
+test: add observability unit tests
+refactor(db): consolidate rate limit tables
+```
+
+Scopes: `db`, `sse`, `oauth`, `dashboard`, `api`, `cli`, `docker`, `ci`, `mcp`, `a2a`, `memory`, `skills`.
+
+---
+
+## Running Tests
+
+```bash
+# All tests (unit + vitest + ecosystem + e2e)
+npm run test:all
+
+# Single test file (Node.js native test runner — most tests use this)
+node --import tsx/esm --test tests/unit/your-file.test.mjs
+
+# Vitest (MCP server, autoCombo, cache)
+npm run test:vitest
+
+# E2E tests (requires Playwright)
+npm run test:e2e
+
+# Protocol clients E2E (MCP transports, A2A)
+npm run test:protocols:e2e
+
+# Ecosystem compatibility tests
+npm run test:ecosystem
+
+# Coverage (55% min statements/lines/functions; 60% branches)
+npm run test:coverage
+npm run coverage:report
+
+# Lint + format check
+npm run lint
+npm run check
+```
+
+Coverage notes:
+
+- `npm run test:coverage` measures source coverage for the main unit test suite, excludes `tests/**`, and includes `open-sse/**`
+- `npm run coverage:report` prints the detailed file-by-file report from the latest coverage run
+- `npm run test:coverage:legacy` preserves the older metric for historical comparison
+- See `docs/COVERAGE_PLAN.md` for the phased coverage improvement roadmap
+
+Current test status: **122 unit test files** covering:
+
+- Provider translators and format conversion
+- Rate limiting, circuit breaker, and resilience
+- Semantic cache, idempotency, progress tracking
+- Database operations and schema (21 DB modules)
+- OAuth flows and authentication
+- API endpoint validation (Zod v4)
+- MCP server tools and scope enforcement
+- Memory and Skills systems
+
+---
+
+## Code Style
+
+- **ESLint** — Run `npm run lint` before committing
+- **Prettier** — Auto-formatted via `lint-staged` on commit (2 spaces, semicolons, double quotes, 100 char width, es5 trailing commas)
+- **TypeScript** — All `src/` code uses `.ts`/`.tsx`; `open-sse/` uses `.ts`/`.js`; document with TSDoc (`@param`, `@returns`, `@throws`)
+- **No `eval()`** — ESLint enforces `no-eval`, `no-implied-eval`, `no-new-func`
+- **Zod validation** — Use Zod v4 schemas for all API input validation
+- **Naming**: Files = camelCase/kebab-case, components = PascalCase, constants = UPPER_SNAKE
+
+---
+
+## Project Structure
+
+```
+src/ # TypeScript (.ts / .tsx)
+├── app/ # Next.js 16 App Router
+│ ├── (dashboard)/ # Dashboard pages (23 sections)
+│ ├── api/ # API routes (51 directories)
+│ └── login/ # Auth pages (.tsx)
+├── domain/ # Policy engine (policyEngine, comboResolver, costRules, etc.)
+├── lib/ # Core business logic (.ts)
+│ ├── a2a/ # Agent-to-Agent v0.3 protocol server
+│ ├── acp/ # Agent Communication Protocol registry
+│ ├── compliance/ # Compliance policy engine
+│ ├── db/ # SQLite database layer (21 modules + 16 migrations)
+│ ├── memory/ # Persistent conversational memory
+│ ├── oauth/ # OAuth providers, services, and utilities
+│ ├── skills/ # Extensible skill framework
+│ ├── usage/ # Usage tracking and cost calculation
+│ └── localDb.ts # Re-export layer only — never add logic here
+├── middleware/ # Request middleware (promptInjectionGuard)
+├── mitm/ # MITM proxy (cert, DNS, target routing)
+├── shared/
+│ ├── components/ # React components (.tsx)
+│ ├── constants/ # Provider definitions (60+), MCP scopes, routing strategies
+│ ├── utils/ # Circuit breaker, sanitizer, auth helpers
+│ └── validation/ # Zod v4 schemas
+└── sse/ # SSE proxy pipeline
+
+open-sse/ # @omniroute/open-sse workspace
+├── executors/ # 14 provider-specific request executors
+├── handlers/ # 11 request handlers (chat, responses, embeddings, images, etc.)
+├── mcp-server/ # MCP server (25 tools, 3 transports, 10 scopes)
+├── services/ # 36+ services (combo, autoCombo, rateLimitManager, etc.)
+├── translator/ # Format translators (OpenAI ↔ Claude ↔ Gemini ↔ Responses ↔ Ollama)
+├── transformer/ # Responses API transformer
+└── utils/ # 22 utility modules (stream, TLS, proxy, logging)
+
+electron/ # Electron desktop app (cross-platform)
+
+tests/
+├── unit/ # Node.js test runner (122 test files)
+├── integration/ # Integration tests
+├── e2e/ # Playwright tests
+├── security/ # Security tests
+├── translator/ # Translator-specific tests
+└── load/ # Load tests
+
+docs/ # Documentation
+├── ARCHITECTURE.md # System architecture
+├── API_REFERENCE.md # All endpoints
+├── USER_GUIDE.md # Provider setup, CLI integration
+├── TROUBLESHOOTING.md # Common issues
+├── MCP-SERVER.md # MCP server (25 tools)
+├── A2A-SERVER.md # A2A agent protocol
+├── AUTO-COMBO.md # Auto-combo engine
+├── CLI-TOOLS.md # CLI tools integration
+├── COVERAGE_PLAN.md # Test coverage improvement plan
+├── openapi.yaml # OpenAPI specification
+└── adr/ # Architecture Decision Records
+```
+
+---
+
+## Adding a New Provider
+
+### Step 1: Register Provider Constants
+
+Add to `src/shared/constants/providers.ts` — Zod-validated at module load.
+
+### Step 2: Add Executor (if custom logic needed)
+
+Create executor in `open-sse/executors/your-provider.ts` extending the base executor.
+
+### Step 3: Add Translator (if non-OpenAI format)
+
+Create request/response translators in `open-sse/translator/`.
+
+### Step 4: Add OAuth Config (if OAuth-based)
+
+Add OAuth credentials in `src/lib/oauth/constants/oauth.ts` and service in `src/lib/oauth/services/`.
+
+### Step 5: Register Models
+
+Add model definitions in `open-sse/config/providerRegistry.ts`.
+
+### Step 6: Add Tests
+
+Write unit tests in `tests/unit/` covering at minimum:
+
+- Provider registration
+- Request/response translation
+- Error handling
+
+---
+
+## Pull Request Checklist
+
+- [ ] Tests pass (`npm test`)
+- [ ] Linting passes (`npm run lint`)
+- [ ] Build succeeds (`npm run build`)
+- [ ] TypeScript types added for new public functions and interfaces
+- [ ] No hardcoded secrets or fallback values
+- [ ] All inputs validated with Zod schemas
+- [ ] CHANGELOG updated (if user-facing change)
+- [ ] Documentation updated (if applicable)
+
+---
+
+## Releasing
+
+Releases are managed via the `/generate-release` workflow. When a new GitHub Release is created, the package is **automatically published to npm** via GitHub Actions.
+
+---
+
+## Getting Help
+
+- **Architecture**: See [`docs/ARCHITECTURE.md`](docs/ARCHITECTURE.md)
+- **API Reference**: See [`docs/API_REFERENCE.md`](docs/API_REFERENCE.md)
+- **Issues**: [github.com/diegosouzapw/OmniRoute/issues](https://github.com/diegosouzapw/OmniRoute/issues)
+- **ADRs**: See `docs/adr/` for architectural decision records
diff --git a/docs/i18n/ar/FEATURES.md b/docs/i18n/ar/FEATURES.md
deleted file mode 100644
index 020be4ff72..0000000000
--- a/docs/i18n/ar/FEATURES.md
+++ /dev/null
@@ -1,147 +0,0 @@
-# OmniRoute — Dashboard Features Gallery (العربية)
-
-🌐 **Languages:** 🇺🇸 [English](../../../README.md) · 🇧🇷 [pt-BR](../pt-BR/README.md) · 🇪🇸 [es](../es/README.md) · 🇫🇷 [fr](../fr/README.md) · 🇩🇪 [de](../de/README.md) · 🇮🇹 [it](../it/README.md) · 🇷🇺 [ru](../ru/README.md) · 🇨🇳 [zh-CN](../zh-CN/README.md) · 🇯🇵 [ja](../ja/README.md) · 🇰🇷 [ko](../ko/README.md) · 🇸🇦 [ar](../ar/README.md) · 🇮🇳 [in](../in/README.md) · 🇹🇭 [th](../th/README.md) · 🇻🇳 [vi](../vi/README.md) · 🇮🇩 [id](../id/README.md) · 🇲🇾 [ms](../ms/README.md) · 🇳🇱 [nl](../nl/README.md) · 🇵🇱 [pl](../pl/README.md) · 🇸🇪 [sv](../sv/README.md) · 🇳🇴 [no](../no/README.md) · 🇩🇰 [da](../da/README.md) · 🇫🇮 [fi](../fi/README.md) · 🇵🇹 [pt](../pt/README.md) · 🇷🇴 [ro](../ro/README.md) · 🇭🇺 [hu](../hu/README.md) · 🇧🇬 [bg](../bg/README.md) · 🇸🇰 [sk](../sk/README.md) · 🇺🇦 [uk-UA](../uk-UA/README.md) · 🇮🇱 [he](../he/README.md) · 🇵🇭 [phi](../phi/README.md)
-
-> 🇺🇸 [English](../../../docs/FEATURES.md)
-
----
-
-Visual guide to every section of the OmniRoute dashboard.
-
----
-
-## 🔌 Providers
-
-Manage AI provider connections: OAuth providers (Claude Code, Codex, Gemini CLI), API key providers (Groq, DeepSeek, OpenRouter), and free providers (Qoder, Qwen, Kiro). Kiro accounts include credit balance tracking — remaining credits, total allowance, and renewal date visible in Dashboard → Usage.
-
-
-
----
-
-## 🎨 Combos
-
-Create model routing combos with 6 strategies: priority, weighted, round-robin, random, least-used, and cost-optimized. Each combo chains multiple models with automatic fallback and includes quick templates and readiness checks.
-
-
-
----
-
-## 📊 Analytics
-
-Comprehensive usage analytics with token consumption, cost estimates, activity heatmaps, weekly distribution charts, and per-provider breakdowns.
-
-
-
----
-
-## 🏥 System Health
-
-Real-time monitoring: uptime, memory, version, latency percentiles (p50/p95/p99), cache statistics, and provider circuit breaker states.
-
-
-
----
-
-## 🔧 Translator Playground
-
-Four modes for debugging API translations: **Playground** (format converter), **Chat Tester** (live requests), **Test Bench** (batch tests), and **Live Monitor** (real-time stream).
-
-
-
----
-
-## 🎮 Model Playground _(v2.0.9+)_
-
-Test any model directly from the dashboard. Select provider, model, and endpoint, write prompts with Monaco Editor, stream responses in real-time, abort mid-stream, and view timing metrics.
-
----
-
-## 🎨 Themes _(v2.0.5+)_
-
-Customizable color themes for the entire dashboard. Choose from 7 preset colors (Coral, Blue, Red, Green, Violet, Orange, Cyan) or create a custom theme by picking any hex color. Supports light, dark, and system mode.
-
----
-
-## ⚙️ Settings
-
-Comprehensive settings panel with tabs:
-
-- **General** — System storage, backup management (export/import database)
-- **Appearance** — Theme selector (dark/light/system), color theme presets and custom colors, health log visibility, sidebar item visibility controls
-- **Security** — API endpoint protection, custom provider blocking, IP filtering, session info
-- **Routing** — Model aliases, background task degradation
-- **Resilience** — Rate limit persistence, circuit breaker tuning
-- **Advanced** — Configuration overrides
-
-
-
----
-
-## 🔧 CLI Tools
-
-One-click configuration for AI coding tools: Claude Code, Codex CLI, Gemini CLI, OpenClaw, Kilo Code, Antigravity, Cline, Continue, Cursor, and Factory Droid. Features automated config apply/reset, connection profiles, and model mapping.
-
-
-
----
-
-## 🤖 CLI Agents _(v2.0.11+)_
-
-Dashboard for discovering and managing CLI agents. Shows a grid of 14 built-in agents (Codex, Claude, Goose, Gemini CLI, OpenClaw, Aider, OpenCode, Cline, Qwen Code, ForgeCode, Amazon Q, Open Interpreter, Cursor CLI, Warp) with:
-
-- **Installation status** — Installed / Not Found with version detection
-- **Protocol badges** — stdio, HTTP, etc.
-- **Custom agents** — Register any CLI tool via form (name, binary, version command, spawn args)
-- **CLI Fingerprint Matching** — Per-provider toggle to match native CLI request signatures, reducing ban risk while preserving proxy IP
-
----
-
-## 🖼️ Media _(v2.0.3+)_
-
-Generate images, videos, and music from the dashboard. Supports OpenAI, xAI, Together, Hyperbolic, SD WebUI, ComfyUI, AnimateDiff, Stable Audio Open, and MusicGen.
-
----
-
-## 📝 Request Logs
-
-Real-time request logging with filtering by provider, model, account, and API key. Shows status codes, token usage, latency, and response details.
-
-
-
----
-
-## 🌐 API Endpoint
-
-Your unified API endpoint with capability breakdown: Chat Completions, Responses API, Embeddings, Image Generation, Reranking, Audio Transcription, Text-to-Speech, Moderations, and registered API keys. Cloud proxy support for remote access.
-
-
-
----
-
-## 🔑 API Key Management
-
-Create, scope, and revoke API keys. Each key can be restricted to specific models/providers with full access or read-only permissions. Visual key management with usage tracking.
-
----
-
-## 📋 Audit Log
-
-Administrative action tracking with filtering by action type, actor, target, IP address, and timestamp. Full security event history.
-
----
-
-## 🖥️ Desktop Application
-
-Native Electron desktop app for Windows, macOS, and Linux. Run OmniRoute as a standalone application with system tray integration, offline support, auto-update, and one-click install.
-
-Key features:
-
-- Server readiness polling (no blank screen on cold start)
-- System tray with port management
-- Content Security Policy
-- Single-instance lock
-- Auto-update on restart
-- Platform-conditional UI (macOS traffic lights, Windows/Linux default titlebar)
-- Hardened Electron build packaging — symlinked `node_modules` in the standalone bundle is detected and rejected before packaging, preventing runtime dependency on the build machine (v2.5.5+)
-
-📖 See [`electron/README.md`](../electron/README.md) for full documentation.
diff --git a/docs/i18n/ar/README.md b/docs/i18n/ar/README.md
index f459de83fc..12773d778f 100644
--- a/docs/i18n/ar/README.md
+++ b/docs/i18n/ar/README.md
@@ -1,13 +1,12 @@
# 🚀 OmniRoute — The Free AI Gateway (العربية)
-🌐 **Languages:** 🇺🇸 [English](../../../README.md) · 🇪🇸 [es](../es/README.md) · 🇫🇷 [fr](../fr/README.md) · 🇩🇪 [de](../de/README.md) · 🇮🇹 [it](../it/README.md) · 🇷🇺 [ru](../ru/README.md) · 🇨🇳 [zh-CN](../zh-CN/README.md) · 🇯🇵 [ja](../ja/README.md) · 🇰🇷 [ko](../ko/README.md) · 🇸🇦 [ar](../ar/README.md) · 🇮🇳 [in](../in/README.md) · 🇹🇭 [th](../th/README.md) · 🇻🇳 [vi](../vi/README.md) · 🇮🇩 [id](../id/README.md) · 🇲🇾 [ms](../ms/README.md) · 🇳🇱 [nl](../nl/README.md) · 🇵🇱 [pl](../pl/README.md) · 🇸🇪 [sv](../sv/README.md) · 🇳🇴 [no](../no/README.md) · 🇩🇰 [da](../da/README.md) · 🇫🇮 [fi](../fi/README.md) · 🇵🇹 [pt](../pt/README.md) · 🇷🇴 [ro](../ro/README.md) · 🇭🇺 [hu](../hu/README.md) · 🇧🇬 [bg](../bg/README.md) · 🇸🇰 [sk](../sk/README.md) · 🇺🇦 [uk-UA](../uk-UA/README.md) · 🇮🇱 [he](../he/README.md) · 🇵🇭 [phi](../phi/README.md) · 🇧🇷 [pt-BR](../pt-BR/README.md)
+🌐 **Languages:** 🇺🇸 [English](../../../README.md) · 🇪🇸 [es](../es/README.md) · 🇫🇷 [fr](../fr/README.md) · 🇩🇪 [de](../de/README.md) · 🇮🇹 [it](../it/README.md) · 🇷🇺 [ru](../ru/README.md) · 🇨🇳 [zh-CN](../zh-CN/README.md) · 🇯🇵 [ja](../ja/README.md) · 🇰🇷 [ko](../ko/README.md) · 🇸🇦 [ar](../ar/README.md) · 🇮🇳 [in](../in/README.md) · 🇹🇭 [th](../th/README.md) · 🇻🇳 [vi](../vi/README.md) · 🇮🇩 [id](../id/README.md) · 🇲🇾 [ms](../ms/README.md) · 🇳🇱 [nl](../nl/README.md) · 🇵🇱 [pl](../pl/README.md) · 🇸🇪 [sv](../sv/README.md) · 🇳🇴 [no](../no/README.md) · 🇩🇰 [da](../da/README.md) · 🇫🇮 [fi](../fi/README.md) · 🇵🇹 [pt](../pt/README.md) · 🇷🇴 [ro](../ro/README.md) · 🇭🇺 [hu](../hu/README.md) · 🇧🇬 [bg](../bg/README.md) · 🇸🇰 [sk](../sk/README.md) · 🇺🇦 [uk-UA](../uk-UA/README.md) · 🇮🇱 [he](../he/README.md) · 🇵🇭 [phi](../phi/README.md) · 🇧🇷 [pt-BR](../pt-BR/README.md) · 🇨🇿 [cs](../cs/README.md)
---
-
### Never stop coding. Smart routing to **FREE & low-cost AI models** with automatic fallback.
-_Your universal API proxy — one endpoint, 67+ providers, zero downtime. Now with **MCP & A2A** agent orchestration._
+_Your universal API proxy — one endpoint, 60+ providers, zero downtime. Now with **MCP Server (25 tools)**, **A2A Protocol**, **Memory/Skills Systems** & **Electron Desktop App**._
**Chat Completions • Embeddings • Image Generation • Video • Music • Audio • Reranking • **Web Search** • MCP Server • A2A Protocol • 100% TypeScript**
@@ -47,15 +46,17 @@ _Your universal API proxy — one endpoint, 67+ providers, zero downtime. Now wi
> - `APP_LOG_FILE_PATH`
> - `APP_LOG_MAX_FILE_SIZE`
> - `APP_LOG_RETENTION_DAYS`
+> - `APP_LOG_MAX_FILES`
> - `APP_LOG_LEVEL`
> - `APP_LOG_FORMAT`
> - `CALL_LOG_RETENTION_DAYS`
+> - `CALL_LOG_MAX_ENTRIES`
>
> For release details and upgrade notes, see the [CHANGELOG](CHANGELOG.md).
---
-## 🆕 What's New in v3.0.0
+## 🆕 What's New
> **Upgrading from v2.9.5?** — See the [full CHANGELOG](CHANGELOG.md#300--2026-03-22-release-candidate--not-yet-merged-to-main) for all changes.
@@ -275,7 +276,7 @@ Developers pay $20–200/month for Claude Pro, Codex Pro, or GitHub Copilot. Eve
- **Smart 4-Tier Fallback** — If subscription quota runs out, automatically redirects to API Key → Cheap → Free with zero manual intervention
- **Real-Time Quota Tracking** — Shows token consumption in real-time with reset countdown (5h, daily, weekly)
- **Multi-Account Support** — Multiple accounts per provider with auto round-robin — when one runs out, switches to the next
-- **Custom Combos** — Customizable fallback chains with 6 balancing strategies (fill-first, round-robin, P2C, random, least-used, cost-optimized)
+- **Custom Combos** — Customizable fallback chains with 9 balancing strategies (priority, weighted, fill-first, round-robin, P2C, random, least-used, cost-optimized, strict-random)
- **Codex Business Quotas** — Business/Team workspace quota monitoring directly in the dashboard
@@ -287,7 +288,7 @@ OpenAI uses one format, Claude (Anthropic) uses another, Gemini yet another. If
**How OmniRoute solves it:**
-- **Unified Endpoint** — A single `http://localhost:20128/v1` serves as proxy for all 67+ providers
+- **Unified Endpoint** — A single `http://localhost:20128/v1` serves as proxy for all 60+ providers
- **Format Translation** — Automatic and transparent: OpenAI ↔ Claude ↔ Gemini ↔ Responses API
- **Response Sanitization** — Strips non-standard fields (`x_groq`, `usage_breakdown`, `service_tier`) that break OpenAI SDK v1.83+
- **Role Normalization** — Converts `developer` → `system` for non-OpenAI providers; `system` → `user` for GLM/ERNIE
@@ -373,7 +374,7 @@ Developers use Cursor, Claude Code, Codex CLI, OpenClaw, Gemini CLI, Kilo Code..
- **CLI Tools Dashboard** — Dedicated page with one-click setup for Claude Code, Codex CLI, OpenClaw, Kilo Code, Antigravity, Cline
- **GitHub Copilot Config Generator** — Generates `chatLanguageModels.json` for VS Code with bulk model selection
- **Onboarding Wizard** — Guided 4-step setup for first-time users
-- **One endpoint, all models** — Configure `http://localhost:20128/v1` once, access 67+ providers
+- **One endpoint, all models** — Configure `http://localhost:20128/v1` once, access 60+ providers
@@ -420,7 +421,7 @@ When a call fails, the dev doesn't know if it was a rate limit, expired token, w
- **SQLite Proxy Logs** — Persistent logs that survive server restarts
- **Translator Playground** — 4 debugging modes: Playground (format translation), Chat Tester (round-trip), Test Bench (batch), Live Monitor (real-time)
- **Request Telemetry** — p50/p95/p99 latency + X-Request-Id tracing
-- **File-Based Logging with Rotation** — Console interceptor captures everything to JSON log with size-based rotation
+- **File-Based Logging with Rotation** — App logs rotate by size, retention days, and archive count; call log artifacts rotate by retention days and file count
- **System Info Report** — `npm run system-info` generates `system-info.txt` with your full environment (Node version, OmniRoute version, OS, CLI tools, Docker/PM2 status). Attach it when reporting issues for instant triage.
@@ -515,7 +516,7 @@ Developers who want all responses in a specific language, with a specific tone,
- **System Prompt Injection** — Global prompt applied to all requests
- **Thinking Budget Validation** — Reasoning token allocation control per request (passthrough, auto, custom, adaptive)
-- **6 Routing Strategies** — Global strategies that determine how requests are distributed
+- **9 Routing Strategies** — Global strategies that determine how requests are distributed
- **Wildcard Router** — `provider/*` patterns route dynamically to any provider
- **Combo Enable/Disable Toggle** — Toggle combos directly from the dashboard
- **Provider Toggle** — Enable/disable all connections for a provider with one click
@@ -582,7 +583,7 @@ Different clients should have least-privilege access to tool categories.
**How OmniRoute solves it:**
-- 9 granular MCP scopes for controlled tool access
+- 10 granular MCP scopes for controlled tool access
- Scope enforcement and visibility in MCP management UI
- Safe default posture for operational tooling
@@ -1326,19 +1327,19 @@ OmniRoute v2.0 is built as an operational platform, not just a relay proxy.
### 🤖 Agent & Protocol Operations (v2.0)
-| Feature | What It Does |
-| ------------------------------------- | -------------------------------------------------------------------------------------------------- |
-| 🔧 **MCP Server (16 tools)** | IDE/agent tools via 3 transports: stdio, SSE (`/api/mcp/sse`), Streamable HTTP (`/api/mcp/stream`) |
-| 🤝 **A2A Server (JSON-RPC + SSE)** | Agent-to-agent task execution with sync and streaming flows |
-| 🧭 **Consolidated Endpoints Page** | Tabbed management page with Endpoint Proxy, MCP, A2A, and API Endpoints tabs |
-| 🎚️ **Service Enable/Disable Toggles** | ON/OFF switches for MCP and A2A with settings persistence (default: OFF) |
-| 🛰️ **MCP Runtime Heartbeat** | Real process status (pid, uptime, heartbeat age, transport, scope mode) |
-| 📋 **MCP Audit Trail** | Filterable audit logs with success/failure and key attribution |
-| 🔐 **MCP Scope Enforcement** | 9 granular scope permissions for controlled tool access |
-| 📡 **A2A Task Lifecycle Management** | List/filter tasks, inspect events/artifacts, cancel running tasks |
-| 📋 **Agent Card Discovery** | `/.well-known/agent.json` for client auto-discovery |
-| 🧪 **Protocol E2E Test Harness** | Real MCP SDK + A2A client flows in `test:protocols:e2e` |
-| ⚙️ **Operational Controls** | Switch combo, apply resilience profiles, reset breakers from one control surface |
+| Feature | What It Does |
+| ------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------- |
+| 🔧 **MCP Server (25 tools)** | IDE/agent tools via 3 transports: stdio, SSE (`/api/mcp/sse`), Streamable HTTP (`/api/mcp/stream`). 18 core + 3 memory + 4 skill tools |
+| 🤝 **A2A Server (JSON-RPC + SSE)** | Agent-to-agent task execution with sync and streaming flows |
+| 🧭 **Consolidated Endpoints Page** | Tabbed management page with Endpoint Proxy, MCP, A2A, and API Endpoints tabs |
+| 🎚️ **Service Enable/Disable Toggles** | ON/OFF switches for MCP and A2A with settings persistence (default: OFF) |
+| 🛰️ **MCP Runtime Heartbeat** | Real process status (pid, uptime, heartbeat age, transport, scope mode) |
+| 📋 **MCP Audit Trail** | Filterable audit logs with success/failure and key attribution |
+| 🔐 **MCP Scope Enforcement** | 10 granular scope permissions for controlled tool access |
+| 📡 **A2A Task Lifecycle Management** | List/filter tasks, inspect events/artifacts, cancel running tasks |
+| 📋 **Agent Card Discovery** | `/.well-known/agent.json` for client auto-discovery |
+| 🧪 **Protocol E2E Test Harness** | Real MCP SDK + A2A client flows in `test:protocols:e2e` |
+| ⚙️ **Operational Controls** | Switch combo, apply resilience profiles, reset breakers from one control surface |
### 🧠 Routing & Intelligence
@@ -1349,7 +1350,7 @@ OmniRoute v2.0 is built as an operational platform, not just a relay proxy.
| 🔄 **Format Translation** | OpenAI ↔ Claude ↔ Gemini ↔ Responses with schema-safe conversions |
| 👥 **Multi-Account Support** | Multiple accounts per provider with intelligent selection |
| 🔄 **Auto Token Refresh** | OAuth tokens refresh automatically with retry |
-| 🎨 **Custom Combos** | 6 balancing strategies + fallback chain control |
+| 🎨 **Custom Combos** | 9 balancing strategies + fallback chain control |
| 🌐 **Wildcard Router** | `provider/*` dynamic routing |
| 🧠 **Thinking Budget Controls** | Passthrough, auto, custom, and adaptive reasoning limits |
| 🔀 **Model Aliases** | Built-in + custom model aliasing and migration safety |
@@ -1950,6 +1951,7 @@ opencode
- Request artifacts are written to `DATA_DIR/call_logs/` as one JSON file per request
- Enable pipeline capture from Dashboard → Logs → Request Logs if you need detailed per-stage payloads
- Set `APP_LOG_TO_FILE=true` if you also want application console logs in `logs/application/app.log`
+- Adjust `APP_LOG_MAX_FILE_SIZE`, `APP_LOG_RETENTION_DAYS`, `APP_LOG_MAX_FILES`, and `CALL_LOG_MAX_ENTRIES` as needed
**Connection test shows "Invalid" for OpenAI-compatible providers**
diff --git a/docs/i18n/ar/RELEASE_CHECKLIST.md b/docs/i18n/ar/RELEASE_CHECKLIST.md
deleted file mode 100644
index 903e812c3f..0000000000
--- a/docs/i18n/ar/RELEASE_CHECKLIST.md
+++ /dev/null
@@ -1,37 +0,0 @@
-🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/RELEASE_CHECKLIST.md) · 🇪🇸 [es](../es/RELEASE_CHECKLIST.md) · 🇫🇷 [fr](../fr/RELEASE_CHECKLIST.md) · 🇩🇪 [de](../de/RELEASE_CHECKLIST.md) · 🇮🇹 [it](../it/RELEASE_CHECKLIST.md) · 🇷🇺 [ru](../ru/RELEASE_CHECKLIST.md) · 🇨🇳 [zh-CN](../zh-CN/RELEASE_CHECKLIST.md) · 🇯🇵 [ja](../ja/RELEASE_CHECKLIST.md) · 🇰🇷 [ko](../ko/RELEASE_CHECKLIST.md) · 🇸🇦 [ar](../ar/RELEASE_CHECKLIST.md) · 🇮🇳 [in](../in/RELEASE_CHECKLIST.md) · 🇹🇭 [th](../th/RELEASE_CHECKLIST.md) · 🇻🇳 [vi](../vi/RELEASE_CHECKLIST.md) · 🇮🇩 [id](../id/RELEASE_CHECKLIST.md) · 🇲🇾 [ms](../ms/RELEASE_CHECKLIST.md) · 🇳🇱 [nl](../nl/RELEASE_CHECKLIST.md) · 🇵🇱 [pl](../pl/RELEASE_CHECKLIST.md) · 🇸🇪 [sv](../sv/RELEASE_CHECKLIST.md) · 🇳🇴 [no](../no/RELEASE_CHECKLIST.md) · 🇩🇰 [da](../da/RELEASE_CHECKLIST.md) · 🇫🇮 [fi](../fi/RELEASE_CHECKLIST.md) · 🇵🇹 [pt](../pt/RELEASE_CHECKLIST.md) · 🇷🇴 [ro](../ro/RELEASE_CHECKLIST.md) · 🇭🇺 [hu](../hu/RELEASE_CHECKLIST.md) · 🇧🇬 [bg](../bg/RELEASE_CHECKLIST.md) · 🇸🇰 [sk](../sk/RELEASE_CHECKLIST.md) · 🇺🇦 [uk-UA](../uk-UA/RELEASE_CHECKLIST.md) · 🇮🇱 [he](../he/RELEASE_CHECKLIST.md) · 🇵🇭 [phi](../phi/RELEASE_CHECKLIST.md)
-
----
-
-# Release Checklist
-
-Use this checklist before tagging or publishing a new OmniRoute release.
-
-## Version and Changelog
-
-1. Bump `package.json` version (`x.y.z`) in the release branch.
-2. Move release notes from `## [Unreleased]` in `CHANGELOG.md` to a dated section:
- - `## [x.y.z] — YYYY-MM-DD`
-3. Keep `## [Unreleased]` as the first changelog section for upcoming work.
-4. Ensure the latest semver section in `CHANGELOG.md` equals `package.json` version.
-
-## API Docs
-
-1. Update `docs/openapi.yaml`:
- - `info.version` must equal `package.json` version.
-2. Validate endpoint examples if API contracts changed.
-
-## Runtime Docs
-
-1. Review `docs/ARCHITECTURE.md` for storage/runtime drift.
-2. Review `docs/TROUBLESHOOTING.md` for env var and operational drift.
-3. Update localized docs if source docs changed significantly.
-
-## Automated Check
-
-Run the sync guard locally before opening PR:
-
-```bash
-npm run check:docs-sync
-```
-
-CI also runs this check in `.github/workflows/ci.yml` (lint job).
diff --git a/docs/i18n/ar/SECURITY.md b/docs/i18n/ar/SECURITY.md
new file mode 100644
index 0000000000..bee390b97c
--- /dev/null
+++ b/docs/i18n/ar/SECURITY.md
@@ -0,0 +1,179 @@
+# Security Policy (العربية)
+
+🌐 **Languages:** 🇺🇸 [English](../../../SECURITY.md) · 🇪🇸 [es](../es/SECURITY.md) · 🇫🇷 [fr](../fr/SECURITY.md) · 🇩🇪 [de](../de/SECURITY.md) · 🇮🇹 [it](../it/SECURITY.md) · 🇷🇺 [ru](../ru/SECURITY.md) · 🇨🇳 [zh-CN](../zh-CN/SECURITY.md) · 🇯🇵 [ja](../ja/SECURITY.md) · 🇰🇷 [ko](../ko/SECURITY.md) · 🇸🇦 [ar](../ar/SECURITY.md) · 🇮🇳 [in](../in/SECURITY.md) · 🇹🇭 [th](../th/SECURITY.md) · 🇻🇳 [vi](../vi/SECURITY.md) · 🇮🇩 [id](../id/SECURITY.md) · 🇲🇾 [ms](../ms/SECURITY.md) · 🇳🇱 [nl](../nl/SECURITY.md) · 🇵🇱 [pl](../pl/SECURITY.md) · 🇸🇪 [sv](../sv/SECURITY.md) · 🇳🇴 [no](../no/SECURITY.md) · 🇩🇰 [da](../da/SECURITY.md) · 🇫🇮 [fi](../fi/SECURITY.md) · 🇵🇹 [pt](../pt/SECURITY.md) · 🇷🇴 [ro](../ro/SECURITY.md) · 🇭🇺 [hu](../hu/SECURITY.md) · 🇧🇬 [bg](../bg/SECURITY.md) · 🇸🇰 [sk](../sk/SECURITY.md) · 🇺🇦 [uk-UA](../uk-UA/SECURITY.md) · 🇮🇱 [he](../he/SECURITY.md) · 🇵🇭 [phi](../phi/SECURITY.md) · 🇧🇷 [pt-BR](../pt-BR/SECURITY.md) · 🇨🇿 [cs](../cs/SECURITY.md)
+
+---
+
+## Reporting Vulnerabilities
+
+If you discover a security vulnerability in OmniRoute, please report it responsibly:
+
+1. **DO NOT** open a public GitHub issue
+2. Use [GitHub Security Advisories](https://github.com/diegosouzapw/OmniRoute/security/advisories/new)
+3. Include: description, reproduction steps, and potential impact
+
+## Response Timeline
+
+| Stage | Target |
+| ------------------- | --------------------------- |
+| Acknowledgment | 48 hours |
+| Triage & Assessment | 5 business days |
+| Patch Release | 14 business days (critical) |
+
+## Supported Versions
+
+| Version | Support Status |
+| ------- | -------------- |
+| 3.4.x | ✅ Active |
+| 3.0.x | ✅ Security |
+| < 3.0.0 | ❌ Unsupported |
+
+---
+
+## Security Architecture
+
+OmniRoute implements a multi-layered security model:
+
+```
+Request → CORS → API Key Auth → Prompt Injection Guard → Input Sanitizer → Rate Limiter → Circuit Breaker → Provider
+```
+
+### 🔐 Authentication & Authorization
+
+| Feature | Implementation |
+| -------------------- | ---------------------------------------------------------- |
+| **Dashboard Login** | Password-based auth with JWT tokens (HttpOnly cookies) |
+| **API Key Auth** | HMAC-signed keys with CRC validation |
+| **OAuth 2.0 + PKCE** | Secure provider auth (Claude, Codex, Gemini, Cursor, etc.) |
+| **Token Refresh** | Automatic OAuth token refresh before expiry |
+| **Secure Cookies** | `AUTH_COOKIE_SECURE=true` for HTTPS environments |
+| **MCP Scopes** | 10 granular scopes for MCP tool access control |
+
+### 🛡️ Encryption at Rest
+
+All sensitive data stored in SQLite is encrypted using **AES-256-GCM** with scrypt key derivation:
+
+- API keys, access tokens, refresh tokens, and ID tokens
+- Versioned format: `enc:v1:::`
+- Passthrough mode (plaintext) when `STORAGE_ENCRYPTION_KEY` is not set
+
+```bash
+# Generate encryption key:
+STORAGE_ENCRYPTION_KEY=$(openssl rand -hex 32)
+```
+
+### 🧠 Prompt Injection Guard
+
+Middleware that detects and blocks prompt injection attacks in LLM requests:
+
+| Pattern Type | Severity | Example |
+| ------------------- | -------- | ---------------------------------------------- |
+| System Override | High | "ignore all previous instructions" |
+| Role Hijack | High | "you are now DAN, you can do anything" |
+| Delimiter Injection | Medium | Encoded separators to break context boundaries |
+| DAN/Jailbreak | High | Known jailbreak prompt patterns |
+| Instruction Leak | Medium | "show me your system prompt" |
+
+Configure via dashboard (Settings → Security) or `.env`:
+
+```env
+INPUT_SANITIZER_ENABLED=true
+INPUT_SANITIZER_MODE=block # warn | block | redact
+```
+
+### 🔒 PII Redaction
+
+Automatic detection and optional redaction of personally identifiable information:
+
+| PII Type | Pattern | Replacement |
+| ------------- | --------------------- | ------------------ |
+| Email | `user@domain.com` | `[EMAIL_REDACTED]` |
+| CPF (Brazil) | `123.456.789-00` | `[CPF_REDACTED]` |
+| CNPJ (Brazil) | `12.345.678/0001-00` | `[CNPJ_REDACTED]` |
+| Credit Card | `4111-1111-1111-1111` | `[CC_REDACTED]` |
+| Phone | `+55 11 99999-9999` | `[PHONE_REDACTED]` |
+| SSN (US) | `123-45-6789` | `[SSN_REDACTED]` |
+
+```env
+PII_REDACTION_ENABLED=true
+```
+
+### 🌐 Network Security
+
+| Feature | Description |
+| ------------------------ | ---------------------------------------------------------------- |
+| **CORS** | Configurable origin control (`CORS_ORIGIN` env var, default `*`) |
+| **IP Filtering** | Allowlist/blocklist IP ranges in dashboard |
+| **Rate Limiting** | Per-provider rate limits with automatic backoff |
+| **Anti-Thundering Herd** | Mutex + per-connection locking prevents cascading 502s |
+| **TLS Fingerprint** | Browser-like TLS fingerprint spoofing to reduce bot detection |
+| **CLI Fingerprint** | Per-provider header/body ordering to match native CLI signatures |
+
+### 🔌 Resilience & Availability
+
+| Feature | Description |
+| ----------------------- | ------------------------------------------------------------------ |
+| **Circuit Breaker** | 3-state (Closed → Open → Half-Open) per provider, SQLite-persisted |
+| **Request Idempotency** | 5-second dedup window for duplicate requests |
+| **Exponential Backoff** | Automatic retry with increasing delays |
+| **Health Dashboard** | Real-time provider health monitoring |
+
+### 📋 Compliance
+
+| Feature | Description |
+| ------------------ | ----------------------------------------------------------- |
+| **Log Retention** | Automatic cleanup after `CALL_LOG_RETENTION_DAYS` |
+| **No-Log Opt-out** | Per API key `noLog` flag disables request logging |
+| **Audit Log** | Administrative actions tracked in `audit_log` table |
+| **MCP Audit** | SQLite-backed audit logging for all MCP tool calls |
+| **Zod Validation** | All API inputs validated with Zod v4 schemas at module load |
+
+---
+
+## Required Environment Variables
+
+All secrets must be set before starting the server. The server will **fail fast** if they are missing or weak.
+
+```bash
+# REQUIRED — server will not start without these:
+JWT_SECRET=$(openssl rand -base64 48) # min 32 chars
+API_KEY_SECRET=$(openssl rand -hex 32) # min 16 chars
+
+# RECOMMENDED — enables encryption at rest:
+STORAGE_ENCRYPTION_KEY=$(openssl rand -hex 32)
+```
+
+The server actively rejects known-weak values like `changeme`, `secret`, or `password`.
+
+---
+
+## Docker Security
+
+- Use non-root user in production
+- Mount secrets as read-only volumes
+- Never copy `.env` files into Docker images
+- Use `.dockerignore` to exclude sensitive files
+- Set `AUTH_COOKIE_SECURE=true` when behind HTTPS
+
+```bash
+docker run -d \
+ --name omniroute \
+ --restart unless-stopped \
+ --read-only \
+ -p 20128:20128 \
+ -v omniroute-data:/app/data \
+ -e JWT_SECRET="$(openssl rand -base64 48)" \
+ -e API_KEY_SECRET="$(openssl rand -hex 32)" \
+ -e STORAGE_ENCRYPTION_KEY="$(openssl rand -hex 32)" \
+ diegosouzapw/omniroute:latest
+```
+
+---
+
+## Dependencies
+
+- Run `npm audit` regularly
+- Keep dependencies updated
+- The project uses `husky` + `lint-staged` for pre-commit checks
+- CI pipeline runs ESLint security rules on every push
+- Provider constants validated at module load via Zod (`src/shared/validation/providerSchema.ts`)
diff --git a/docs/i18n/ar/VM_DEPLOYMENT_GUIDE.md b/docs/i18n/ar/VM_DEPLOYMENT_GUIDE.md
deleted file mode 100644
index c9bd2d844f..0000000000
--- a/docs/i18n/ar/VM_DEPLOYMENT_GUIDE.md
+++ /dev/null
@@ -1,401 +0,0 @@
-# OmniRoute — دليل النشر على VM باستخدام Cloudflare
-
-🌐 **Languages:** 🇺🇸 [English](../../VM_DEPLOYMENT_GUIDE.md) | 🇧🇷 [Português (Brasil)](../pt-BR/VM_DEPLOYMENT_GUIDE.md) | 🇪🇸 [Español](../es/VM_DEPLOYMENT_GUIDE.md) | 🇫🇷 [Français](../fr/VM_DEPLOYMENT_GUIDE.md) | 🇮🇹 [Italiano](../it/VM_DEPLOYMENT_GUIDE.md) | 🇷🇺 [Русский](../ru/VM_DEPLOYMENT_GUIDE.md) | 🇨🇳 [中文 (简体)](../zh-CN/VM_DEPLOYMENT_GUIDE.md) | 🇩🇪 [Deutsch](../de/VM_DEPLOYMENT_GUIDE.md) | 🇮🇳 [हिन्दी](../in/VM_DEPLOYMENT_GUIDE.md) | 🇹🇭 [ไทย](../th/VM_DEPLOYMENT_GUIDE.md) | 🇺🇦 [Українська](../uk-UA/VM_DEPLOYMENT_GUIDE.md) | 🇸🇦 [العربية](../ar/VM_DEPLOYMENT_GUIDE.md) | 🇯🇵 [日本語](../ja/VM_DEPLOYMENT_GUIDE.md) | 🇻🇳 [Tiếng Việt](../vi/VM_DEPLOYMENT_GUIDE.md) | 🇧🇬 [Български](../bg/VM_DEPLOYMENT_GUIDE.md) | 🇩🇰 [Dansk](../da/VM_DEPLOYMENT_GUIDE.md) | 🇫🇮 [Suomi](../fi/VM_DEPLOYMENT_GUIDE.md) | 🇮🇱 [עברית](../he/VM_DEPLOYMENT_GUIDE.md) | 🇭🇺 [Magyar](../hu/VM_DEPLOYMENT_GUIDE.md) | 🇮🇩 [Bahasa Indonesia](../id/VM_DEPLOYMENT_GUIDE.md) | 🇰🇷 [한국어](../ko/VM_DEPLOYMENT_GUIDE.md) | 🇲🇾 [Bahasa Melayu](../ms/VM_DEPLOYMENT_GUIDE.md) | 🇳🇱 [Nederlands](../nl/VM_DEPLOYMENT_GUIDE.md) | 🇳🇴 [Norsk](../no/VM_DEPLOYMENT_GUIDE.md) | 🇵🇹 [Português (Portugal)](../pt/VM_DEPLOYMENT_GUIDE.md) | 🇷🇴 [Română](../ro/VM_DEPLOYMENT_GUIDE.md) | 🇵🇱 [Polski](../pl/VM_DEPLOYMENT_GUIDE.md) | 🇸🇰 [Slovenčina](../sk/VM_DEPLOYMENT_GUIDE.md) | 🇸🇪 [Svenska](../sv/VM_DEPLOYMENT_GUIDE.md) | 🇵🇭 [Filipino](../phi/VM_DEPLOYMENT_GUIDE.md) | 🇨🇿 [Čeština](../cs/VM_DEPLOYMENT_GUIDE.md)
-
-الدليل الكامل لتثبيت OmniRoute وتكوينه على VM (VPS) مع المجال المُدار عبر Cloudflare.
-
----
-
-## المتطلبات الأساسية
-
-| العنصر | الحد الأدنى | موصى به |
-| ---------------------------- | ----------------------------------- | ----------------------------------- |
-| ** وحدة المعالجة المركزية ** | 1 وحدة المعالجة المركزية الافتراضية | 2 وحدة المعالجة المركزية الافتراضية |
-| **ذاكرة الوصول العشوائي** | 1 جيجا | 2 جيجا |
-| **القرص** | 10 جيجا اس اس دي | 25 جيجا اس اس دي |
-| **نظام التشغيل** | أوبونتو 22.04 LTS | أوبونتو 24.04 LTS |
-| **المجال** | مسجل في Cloudflare | — |
-| ** عامل الميناء ** | محرك دوكر 24+ | عامل الميناء 27+ |
-
-**المزودون الذين تم اختبارهم**: Akamai (Linode)، DigitalOcean، Vultr، Hetzner، AWS Lightsail.
-
----
-
-## 1. قم بتكوين الجهاز الافتراضي
-
-### 1.1 إنشاء المثيل
-
-على موفر VPS المفضل لديك:
-
-- اختر Ubuntu 24.04 LTS
-- حدد الحد الأدنى للخطة (1 vCPU / 1 جيجابايت من ذاكرة الوصول العشوائي)
-- قم بتعيين كلمة مرور جذر قوية أو قم بتكوين مفتاح SSH
-- لاحظ **عنوان IP العام** (على سبيل المثال، `203.0.113.10`)
-
-### 1.2 الاتصال عبر SSH
-
-```bash
-ssh root@203.0.113.10
-```
-
-### 1.3 تحديث النظام
-
-```bash
-apt update && apt upgrade -y
-```
-
-### 1.4 تثبيت عامل الميناء
-
-```bash
-# Install dependencies
-apt install -y ca-certificates curl gnupg
-
-# Add official Docker repository
-install -m 0755 -d /etc/apt/keyrings
-curl -fsSL https://download.docker.com/linux/ubuntu/gpg | gpg --dearmor -o /etc/apt/keyrings/docker.gpg
-chmod a+r /etc/apt/keyrings/docker.gpg
-echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu $ (. /etc/os-release && echo “$VERSION_CODENAME”) stable" | tee /etc/apt/sources.list.d/docker.list > /dev/null
-apt update
-apt install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin
-```
-
-### 1.5 تثبيت nginx
-
-```bash
-apt install -y nginx
-```
-
-### 1.6 تكوين جدار الحماية (UFW)
-
-```bash
-ufw default deny incoming
-ufw default allow outgoing
-ufw allow 22/tcp # SSH
-ufw allow 80/tcp # HTTP (redirect)
-ufw allow 443/tcp # HTTPS
-ufw enable
-```
-
-> **نصيحة**: للحصول على الحد الأقصى من الأمان، قم بتقييد المنفذين 80 و443 بعناوين Cloudflare IP فقط. راجع قسم [Advanced Security](#advanced-security).
-
----
-
-## 2. قم بتثبيت OmniRoute
-
-### 2.1 إنشاء دليل التكوين
-
-```bash
-mkdir -p /opt/omniroute
-```
-
-### 2.2 إنشاء ملف متغيرات البيئة
-
-```bash
-cat > /opt/omniroute/.env << ‘EOF’
-# === Security ===
-JWT_SECRET=CHANGE-TO-A-UNIQUE-64-CHAR-SECRET-KEY
-INITIAL_PASSWORD=YourSecurePassword123!
-API_KEY_SECRET=REPLACE-WITH-ANOTHER-SECRET-KEY
-STORAGE_ENCRYPTION_KEY=REPLACE-WITH-THIRD-SECRET-KEY
-STORAGE_ENCRYPTION_KEY_VERSION=v1
-MACHINE_ID_SALT=CHANGE-TO-A-UNIQUE-SALT
-
-# === App ===
-PORT=20128
-NODE_ENV=production
-HOSTNAME=0.0.0.0
-DATA_DIR=/app/data
-STORAGE_DRIVER=sqlite
-ENABLE_REQUEST_LOGS=true
-AUTH_COOKIE_SECURE=false
-REQUIRE_API_KEY=false
-
-# === Domain (change to your domain) ===
-BASE_URL=https://llms.seudominio.com
-NEXT_PUBLIC_BASE_URL=https://llms.seudominio.com
-
-# === Cloud Sync (optional) ===
-# CLOUD_URL=https://cloud.omniroute.online
-# NEXT_PUBLIC_CLOUD_URL=https://cloud.omniroute.online
-EOF
-```
-
-> ⚠️ **هام**: أنشئ مفاتيح سرية فريدة! استخدم `openssl rand -hex 32` لكل مفتاح.
-
-### 2.3 ابدأ الحاوية
-
-```bash
-docker pull diegosouzapw/omniroute:latest
-
-docker run -d \
- --name omniroute \
- --restart unless-stopped \
- --env-file /opt/omniroute/.env \
- -p 20128:20128 \
- -v omniroute-data:/app/data \
- diegosouzapw/omniroute:latest
-```
-
-### 2.4 التحقق من أنه قيد التشغيل
-
-```bash
-docker ps | grep omniroute
-docker logs omniroute --tail 20
-```
-
-يجب أن يعرض: `[DB] SQLite database ready` و`listening on port 20128`.
-
----
-
-## 3. تكوين nginx (الوكيل العكسي)
-
-### 3.1 إنشاء شهادة SSL (أصل Cloudflare)
-
-في لوحة معلومات Cloudflare:
-
-1. انتقل إلى **SSL/TLS → خادم الأصل**
-2. انقر **إنشاء شهادة**
-3. احتفظ بالإعدادات الافتراضية (15 عامًا، \*.yourdomain.com)
-4. انسخ **شهادة المنشأ** و**المفتاح الخاص**
-
-```bash
-mkdir -p /etc/nginx/ssl
-
-# Paste the certificate
-nano /etc/nginx/ssl/origin.crt
-
-# Paste the private key
-nano /etc/nginx/ssl/origin.key
-
-chmod 600 /etc/nginx/ssl/origin.key
-```
-
-### 3.2 تكوين إنجينكس
-
-```bash
-cat > /etc/nginx/sites-available/omniroute << ‘NGINX’
-# Default server — blocks direct access via IP
-server {
- listen 80 default_server;
- listen [::]:80 default_server;
- listen 443 ssl default_server;
- listen [::]:443 ssl default_server;
- ssl_certificate /etc/nginx/ssl/origin.crt;
- ssl_certificate_key /etc/nginx/ssl/origin.key;
- server_name _;
- return 444;
-}
-
-# OmniRoute — HTTPS
-server {
- listen 443 ssl;
- listen [::]:443 ssl;
- server_name llms.yourdomain.com; # Change to your domain
-
- ssl_certificate /etc/nginx/ssl/origin.crt;
- ssl_certificate_key /etc/nginx/ssl/origin.key;
- ssl_protocols TLSv1.2 TLSv1.3;
-
- client_max_body_size 100M;
-
- location / {
- proxy_pass http://127.0.0.1:20128;
- proxy_set_header Host $host;
- proxy_set_header X-Real-IP $remote_addr;
- proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
- proxy_set_header X-Forwarded-Proto $scheme;
-
- # WebSocket support
- proxy_http_version 1.1;
- proxy_set_header Upgrade $http_upgrade;
- proxy_set_header Connection “upgrade”;
-
- # SSE (Server-Sent Events) — streaming AI responses
- proxy_buffering off;
- proxy_cache off;
- proxy_read_timeout 300s;
- proxy_send_timeout 300s;
- }
-}
-
-# HTTP → HTTPS redirect
-server {
- listen 80;
- listen [::]:80;
- server_name llms.yourdomain.com;
- return 301 https://$server_name$request_uri;
-}
-NGINX
-```
-
-### 3.3 تمكين واختبار
-
-```bash
-# Remove default configuration
-rm -f /etc/nginx/sites-enabled/default
-
-# Enable OmniRoute
-ln -sf /etc/nginx/sites-available/omniroute /etc/nginx/sites-enabled/omniroute
-
-# Test and reload
-nginx -t && systemctl reload nginx
-```
-
----
-
-## 4. تكوين Cloudflare DNS
-
-### 4.1 إضافة سجل DNS
-
-في لوحة معلومات Cloudflare → DNS:
-
-| اكتب | الاسم | المحتوى | الوكيل |
-| ---- | ------ | ---------------------- | -------- |
-| أ | `llms` | `203.0.113.10` (VM IP) | ✅ توكيل |
-
-### 4.2 تكوين SSL
-
-ضمن **SSL/TLS → نظرة عامة**:
-
-- الوضع: **كامل (صارم)**
-
-ضمن **SSL/TLS → شهادات الحافة**:
-
-- استخدم HTTPS دائمًا: ✅ قيد التشغيل
-- الحد الأدنى لإصدار TLS: TLS 1.2
-- إعادة كتابة HTTPS تلقائيًا: ✅ تشغيل
-
-### 4.3 الاختبار
-
-```bash
-curl -sI https://llms.seudominio.com/health
-# Should return HTTP/2 200
-```
-
----
-
-## 5. العمليات والصيانة
-
-### الترقية إلى الإصدار الجديد
-
-```bash
-docker pull diegosouzapw/omniroute:latest
-docker stop omniroute && docker rm omniroute
-docker run -d --name omniroute --restart unless-stopped \
- --env-file /opt/omniroute/.env \
- -p 20128:20128 \
- -v omniroute-data:/app/data \
- diegosouzapw/omniroute:latest
-```
-
-### عرض السجلات
-
-```bash
-docker logs -f omniroute # Real-time stream
-docker logs omniroute --tail 50 # Last 50 lines
-```
-
-### النسخ الاحتياطي لقاعدة البيانات يدويا
-
-```bash
-# Copy data from the volume to the host
-docker cp omniroute:/app/data ./backup-$(date +%F)
-
-# Or compress the entire volume
-docker run --rm -v omniroute-data:/data -v $(pwd):/backup \
- alpine tar czf /backup/omniroute-data-$(date +%F).tar.gz /data
-```
-
-### الاستعادة من النسخة الاحتياطية
-
-```bash
-docker stop omniroute
-docker run --rm -v omniroute-data:/data -v $(pwd):/backup \
- alpine sh -c “rm -rf /data/* && tar xzf /backup/omniroute-data-YYYY-MM-DD.tar.gz -C /”
-docker start omniroute
-```
-
----
-
-## 6. الأمان المتقدم
-
-### تقييد nginx على عناوين IP الخاصة بـ Cloudflare
-
-```bash
-cat > /etc/nginx/cloudflare-ips.conf << ‘CF’
-# Cloudflare IPv4 ranges — update periodically
-# https://www.cloudflare.com/ips-v4/
-set_real_ip_from 173.245.48.0/20;
-set_real_ip_from 103.21.244.0/22;
-set_real_ip_from 103.22.200.0/22;
-set_real_ip_from 103.31.4.0/22;
-set_real_ip_from 141.101.64.0/18;
-set_real_ip_from 108.162.192.0/18;
-set_real_ip_from 190.93.240.0/20;
-set_real_ip_from 188.114.96.0/20;
-set_real_ip_from 197.234.240.0/22;
-set_real_ip_from 198.41.128.0/17;
-set_real_ip_from 162.158.0.0/15;
-set_real_ip_from 104.16.0.0/13;
-set_real_ip_from 104.24.0.0/14;
-set_real_ip_from 172.64.0.0/13;
-set_real_ip_from 131.0.72.0/22;
-real_ip_header CF-Connecting-IP;
-CF
-```
-
-أضف ما يلي إلى `nginx.conf` داخل الكتلة `http {}`:
-
-```nginx
-include /etc/nginx/cloudflare-ips.conf;
-```
-
-### تثبيت Fail2ban
-
-```bash
-apt install -y fail2ban
-systemctl enable fail2ban
-systemctl start fail2ban
-
-# Check status
-fail2ban-client status sshd
-```
-
-### منع الوصول المباشر إلى منفذ Docker
-
-```bash
-# Prevent direct external access to port 20128
-iptables -I DOCKER-USER -p tcp --dport 20128 -j DROP
-iptables -I DOCKER-USER -i lo -p tcp --dport 20128 -j ACCEPT
-
-# Persist the rules
-apt install -y iptables-persistent
-netfilter-persistent save
-```
-
----
-
-## 7. النشر إلى عمال Cloudflare (اختياري)
-
-للوصول عن بعد عبر Cloudflare Workers (دون الكشف عن الجهاز الافتراضي مباشرة):
-
-```bash
-# In the local repository
-cd omnirouteCloud
-npm install
-npx wrangler login
-npx wrangler deploy
-```
-
-راجع الوثائق الكاملة على [omnirouteCloud/README.md](../omnirouteCloud/README.md).
-
----
-
-## ملخص المنفذ
-
-| ميناء | الخدمة | الوصول |
-| ----- | ------------- | ----------------------------- |
-| 22 | سش | عام (مع Fail2ban) |
-| 80 | إنجينكس HTTP | إعادة التوجيه → HTTPS |
-| 443 | إنجينكس HTTPS | عبر وكيل Cloudflare |
-| 20128 | أومنيروتي | المضيف المحلي فقط (عبر nginx) |
diff --git a/docs/i18n/ar/docs/A2A-SERVER.md b/docs/i18n/ar/docs/A2A-SERVER.md
new file mode 100644
index 0000000000..58c345a0b5
--- /dev/null
+++ b/docs/i18n/ar/docs/A2A-SERVER.md
@@ -0,0 +1,200 @@
+# OmniRoute A2A Server Documentation (العربية)
+
+🌐 **Languages:** 🇺🇸 [English](../../../../docs/A2A-SERVER.md) · 🇪🇸 [es](../../es/docs/A2A-SERVER.md) · 🇫🇷 [fr](../../fr/docs/A2A-SERVER.md) · 🇩🇪 [de](../../de/docs/A2A-SERVER.md) · 🇮🇹 [it](../../it/docs/A2A-SERVER.md) · 🇷🇺 [ru](../../ru/docs/A2A-SERVER.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/A2A-SERVER.md) · 🇯🇵 [ja](../../ja/docs/A2A-SERVER.md) · 🇰🇷 [ko](../../ko/docs/A2A-SERVER.md) · 🇸🇦 [ar](../../ar/docs/A2A-SERVER.md) · 🇮🇳 [in](../../in/docs/A2A-SERVER.md) · 🇹🇭 [th](../../th/docs/A2A-SERVER.md) · 🇻🇳 [vi](../../vi/docs/A2A-SERVER.md) · 🇮🇩 [id](../../id/docs/A2A-SERVER.md) · 🇲🇾 [ms](../../ms/docs/A2A-SERVER.md) · 🇳🇱 [nl](../../nl/docs/A2A-SERVER.md) · 🇵🇱 [pl](../../pl/docs/A2A-SERVER.md) · 🇸🇪 [sv](../../sv/docs/A2A-SERVER.md) · 🇳🇴 [no](../../no/docs/A2A-SERVER.md) · 🇩🇰 [da](../../da/docs/A2A-SERVER.md) · 🇫🇮 [fi](../../fi/docs/A2A-SERVER.md) · 🇵🇹 [pt](../../pt/docs/A2A-SERVER.md) · 🇷🇴 [ro](../../ro/docs/A2A-SERVER.md) · 🇭🇺 [hu](../../hu/docs/A2A-SERVER.md) · 🇧🇬 [bg](../../bg/docs/A2A-SERVER.md) · 🇸🇰 [sk](../../sk/docs/A2A-SERVER.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/A2A-SERVER.md) · 🇮🇱 [he](../../he/docs/A2A-SERVER.md) · 🇵🇭 [phi](../../phi/docs/A2A-SERVER.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/A2A-SERVER.md) · 🇨🇿 [cs](../../cs/docs/A2A-SERVER.md)
+
+---
+
+> Agent-to-Agent Protocol v0.3 — OmniRoute as an intelligent routing agent
+
+## Agent Discovery
+
+```bash
+curl http://localhost:20128/.well-known/agent.json
+```
+
+Returns the Agent Card describing OmniRoute's capabilities, skills, and authentication requirements.
+
+---
+
+## Authentication
+
+All `/a2a` requests require an API key via the `Authorization` header:
+
+```
+Authorization: Bearer YOUR_OMNIROUTE_API_KEY
+```
+
+If no API key is configured on the server, authentication is bypassed.
+
+---
+
+## JSON-RPC 2.0 Methods
+
+### `message/send` — Synchronous Execution
+
+Sends a message to a skill and waits for the complete response.
+
+```bash
+curl -X POST http://localhost:20128/a2a \
+ -H "Content-Type: application/json" \
+ -H "Authorization: Bearer YOUR_KEY" \
+ -d '{
+ "jsonrpc": "2.0",
+ "id": "1",
+ "method": "message/send",
+ "params": {
+ "skill": "smart-routing",
+ "messages": [{"role": "user", "content": "Write a hello world in Python"}],
+ "metadata": {"model": "auto", "combo": "fast-coding"}
+ }
+ }'
+```
+
+**Response:**
+
+```json
+{
+ "jsonrpc": "2.0",
+ "id": "1",
+ "result": {
+ "task": { "id": "uuid", "state": "completed" },
+ "artifacts": [{ "type": "text", "content": "..." }],
+ "metadata": {
+ "routing_explanation": "Selected claude-sonnet via provider \"anthropic\" (latency: 1200ms, cost: $0.003)",
+ "cost_envelope": { "estimated": 0.005, "actual": 0.003, "currency": "USD" },
+ "resilience_trace": [
+ { "event": "primary_selected", "provider": "anthropic", "timestamp": "..." }
+ ],
+ "policy_verdict": { "allowed": true, "reason": "within budget and quota limits" }
+ }
+ }
+}
+```
+
+### `message/stream` — SSE Streaming
+
+Same as `message/send` but returns Server-Sent Events for real-time streaming.
+
+```bash
+curl -N -X POST http://localhost:20128/a2a \
+ -H "Content-Type: application/json" \
+ -H "Authorization: Bearer YOUR_KEY" \
+ -d '{
+ "jsonrpc": "2.0",
+ "id": "1",
+ "method": "message/stream",
+ "params": {
+ "skill": "smart-routing",
+ "messages": [{"role": "user", "content": "Explain quantum computing"}]
+ }
+ }'
+```
+
+**SSE Events:**
+
+```
+data: {"jsonrpc":"2.0","method":"message/stream","params":{"task":{"id":"...","state":"working"},"chunk":{"type":"text","content":"..."}}}
+
+: heartbeat 2026-03-03T17:00:00Z
+
+data: {"jsonrpc":"2.0","method":"message/stream","params":{"task":{"id":"...","state":"completed"},"metadata":{...}}}
+```
+
+### `tasks/get` — Query Task Status
+
+```bash
+curl -X POST http://localhost:20128/a2a \
+ -H "Content-Type: application/json" \
+ -H "Authorization: Bearer YOUR_KEY" \
+ -d '{"jsonrpc":"2.0","id":"2","method":"tasks/get","params":{"taskId":"TASK_UUID"}}'
+```
+
+### `tasks/cancel` — Cancel a Task
+
+```bash
+curl -X POST http://localhost:20128/a2a \
+ -H "Content-Type: application/json" \
+ -H "Authorization: Bearer YOUR_KEY" \
+ -d '{"jsonrpc":"2.0","id":"3","method":"tasks/cancel","params":{"taskId":"TASK_UUID"}}'
+```
+
+---
+
+## Available Skills
+
+| Skill | Description |
+| :----------------- | :------------------------------------------------------------------------------------------------------------------------------ |
+| `smart-routing` | Routes prompts through OmniRoute's intelligent pipeline. Returns response with routing explanation, cost, and resilience trace. |
+| `quota-management` | Answers natural-language queries about provider quotas, suggests free combos, and provides quota rankings. |
+
+---
+
+## Task Lifecycle
+
+```
+submitted → working → completed
+ → failed
+ → cancelled
+```
+
+- Tasks expire after 5 minutes (configurable)
+- Terminal states: `completed`, `failed`, `cancelled`
+- Event log tracks every state transition
+
+---
+
+## Error Codes
+
+| Code | Meaning |
+| :----- | :----------------------------- |
+| -32700 | Parse error (invalid JSON) |
+| -32600 | Invalid request / Unauthorized |
+| -32601 | Method or skill not found |
+| -32602 | Invalid params |
+| -32603 | Internal error |
+
+---
+
+## Integration Examples
+
+### Python (requests)
+
+```python
+import requests
+
+resp = requests.post("http://localhost:20128/a2a", json={
+ "jsonrpc": "2.0", "id": "1",
+ "method": "message/send",
+ "params": {
+ "skill": "smart-routing",
+ "messages": [{"role": "user", "content": "Hello"}]
+ }
+}, headers={"Authorization": "Bearer YOUR_KEY"})
+
+result = resp.json()["result"]
+print(result["artifacts"][0]["content"])
+print(result["metadata"]["routing_explanation"])
+```
+
+### TypeScript (fetch)
+
+```typescript
+const resp = await fetch("http://localhost:20128/a2a", {
+ method: "POST",
+ headers: {
+ "Content-Type": "application/json",
+ Authorization: "Bearer YOUR_KEY",
+ },
+ body: JSON.stringify({
+ jsonrpc: "2.0",
+ id: "1",
+ method: "message/send",
+ params: {
+ skill: "smart-routing",
+ messages: [{ role: "user", content: "Hello" }],
+ },
+ }),
+});
+const { result } = await resp.json();
+console.log(result.metadata.routing_explanation);
+```
diff --git a/docs/i18n/ar/docs/API_REFERENCE.md b/docs/i18n/ar/docs/API_REFERENCE.md
new file mode 100644
index 0000000000..bdfbcb4b40
--- /dev/null
+++ b/docs/i18n/ar/docs/API_REFERENCE.md
@@ -0,0 +1,465 @@
+# API Reference (العربية)
+
+🌐 **Languages:** 🇺🇸 [English](../../../../docs/API_REFERENCE.md) · 🇪🇸 [es](../../es/docs/API_REFERENCE.md) · 🇫🇷 [fr](../../fr/docs/API_REFERENCE.md) · 🇩🇪 [de](../../de/docs/API_REFERENCE.md) · 🇮🇹 [it](../../it/docs/API_REFERENCE.md) · 🇷🇺 [ru](../../ru/docs/API_REFERENCE.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/API_REFERENCE.md) · 🇯🇵 [ja](../../ja/docs/API_REFERENCE.md) · 🇰🇷 [ko](../../ko/docs/API_REFERENCE.md) · 🇸🇦 [ar](../../ar/docs/API_REFERENCE.md) · 🇮🇳 [in](../../in/docs/API_REFERENCE.md) · 🇹🇭 [th](../../th/docs/API_REFERENCE.md) · 🇻🇳 [vi](../../vi/docs/API_REFERENCE.md) · 🇮🇩 [id](../../id/docs/API_REFERENCE.md) · 🇲🇾 [ms](../../ms/docs/API_REFERENCE.md) · 🇳🇱 [nl](../../nl/docs/API_REFERENCE.md) · 🇵🇱 [pl](../../pl/docs/API_REFERENCE.md) · 🇸🇪 [sv](../../sv/docs/API_REFERENCE.md) · 🇳🇴 [no](../../no/docs/API_REFERENCE.md) · 🇩🇰 [da](../../da/docs/API_REFERENCE.md) · 🇫🇮 [fi](../../fi/docs/API_REFERENCE.md) · 🇵🇹 [pt](../../pt/docs/API_REFERENCE.md) · 🇷🇴 [ro](../../ro/docs/API_REFERENCE.md) · 🇭🇺 [hu](../../hu/docs/API_REFERENCE.md) · 🇧🇬 [bg](../../bg/docs/API_REFERENCE.md) · 🇸🇰 [sk](../../sk/docs/API_REFERENCE.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/API_REFERENCE.md) · 🇮🇱 [he](../../he/docs/API_REFERENCE.md) · 🇵🇭 [phi](../../phi/docs/API_REFERENCE.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/API_REFERENCE.md) · 🇨🇿 [cs](../../cs/docs/API_REFERENCE.md)
+
+---
+
+Complete reference for all OmniRoute API endpoints.
+
+---
+
+## Table of Contents
+
+- [Chat Completions](#chat-completions)
+- [Embeddings](#embeddings)
+- [Image Generation](#image-generation)
+- [List Models](#list-models)
+- [Compatibility Endpoints](#compatibility-endpoints)
+- [Semantic Cache](#semantic-cache)
+- [Dashboard & Management](#dashboard--management)
+- [Request Processing](#request-processing)
+- [Authentication](#authentication)
+
+---
+
+## Chat Completions
+
+```bash
+POST /v1/chat/completions
+Authorization: Bearer your-api-key
+Content-Type: application/json
+
+{
+ "model": "cc/claude-opus-4-6",
+ "messages": [
+ {"role": "user", "content": "Write a function to..."}
+ ],
+ "stream": true
+}
+```
+
+### Custom Headers
+
+| Header | Direction | Description |
+| ------------------------ | --------- | ------------------------------------------------ |
+| `X-OmniRoute-No-Cache` | Request | Set to `true` to bypass cache |
+| `X-OmniRoute-Progress` | Request | Set to `true` for progress events |
+| `X-Session-Id` | Request | Sticky session key for external session affinity |
+| `x_session_id` | Request | Underscore variant also accepted (direct HTTP) |
+| `Idempotency-Key` | Request | Dedup key (5s window) |
+| `X-Request-Id` | Request | Alternative dedup key |
+| `X-OmniRoute-Cache` | Response | `HIT` or `MISS` (non-streaming) |
+| `X-OmniRoute-Idempotent` | Response | `true` if deduplicated |
+| `X-OmniRoute-Progress` | Response | `enabled` if progress tracking on |
+| `X-OmniRoute-Session-Id` | Response | Effective session ID used by OmniRoute |
+
+> Nginx note: if you rely on underscore headers (for example `x_session_id`), enable `underscores_in_headers on;`.
+
+---
+
+## Embeddings
+
+```bash
+POST /v1/embeddings
+Authorization: Bearer your-api-key
+Content-Type: application/json
+
+{
+ "model": "nebius/Qwen/Qwen3-Embedding-8B",
+ "input": "The food was delicious"
+}
+```
+
+Available providers: Nebius, OpenAI, Mistral, Together AI, Fireworks, NVIDIA.
+
+```bash
+# List all embedding models
+GET /v1/embeddings
+```
+
+---
+
+## Image Generation
+
+```bash
+POST /v1/images/generations
+Authorization: Bearer your-api-key
+Content-Type: application/json
+
+{
+ "model": "openai/dall-e-3",
+ "prompt": "A beautiful sunset over mountains",
+ "size": "1024x1024"
+}
+```
+
+Available providers: OpenAI (DALL-E), xAI (Grok Image), Together AI (FLUX), Fireworks AI.
+
+```bash
+# List all image models
+GET /v1/images/generations
+```
+
+---
+
+## List Models
+
+```bash
+GET /v1/models
+Authorization: Bearer your-api-key
+
+→ Returns all chat, embedding, and image models + combos in OpenAI format
+```
+
+---
+
+## Compatibility Endpoints
+
+| Method | Path | Format |
+| ------ | --------------------------- | ---------------------- |
+| POST | `/v1/chat/completions` | OpenAI |
+| POST | `/v1/messages` | Anthropic |
+| POST | `/v1/responses` | OpenAI Responses |
+| POST | `/v1/embeddings` | OpenAI |
+| POST | `/v1/images/generations` | OpenAI |
+| GET | `/v1/models` | OpenAI |
+| POST | `/v1/messages/count_tokens` | Anthropic |
+| GET | `/v1beta/models` | Gemini |
+| POST | `/v1beta/models/{...path}` | Gemini generateContent |
+| POST | `/v1/api/chat` | Ollama |
+
+### Dedicated Provider Routes
+
+```bash
+POST /v1/providers/{provider}/chat/completions
+POST /v1/providers/{provider}/embeddings
+POST /v1/providers/{provider}/images/generations
+```
+
+The provider prefix is auto-added if missing. Mismatched models return `400`.
+
+---
+
+## Semantic Cache
+
+```bash
+# Get cache stats
+GET /api/cache/stats
+
+# Clear all caches
+DELETE /api/cache/stats
+```
+
+Response example:
+
+```json
+{
+ "semanticCache": {
+ "memorySize": 42,
+ "memoryMaxSize": 500,
+ "dbSize": 128,
+ "hitRate": 0.65
+ },
+ "idempotency": {
+ "activeKeys": 3,
+ "windowMs": 5000
+ }
+}
+```
+
+---
+
+## Dashboard & Management
+
+### Authentication
+
+| Endpoint | Method | Description |
+| ----------------------------- | ------- | --------------------- |
+| `/api/auth/login` | POST | Login |
+| `/api/auth/logout` | POST | Logout |
+| `/api/settings/require-login` | GET/PUT | Toggle login required |
+
+### Provider Management
+
+| Endpoint | Method | Description |
+| ---------------------------- | --------------- | ------------------------ |
+| `/api/providers` | GET/POST | List / create providers |
+| `/api/providers/[id]` | GET/PUT/DELETE | Manage a provider |
+| `/api/providers/[id]/test` | POST | Test provider connection |
+| `/api/providers/[id]/models` | GET | List provider models |
+| `/api/providers/validate` | POST | Validate provider config |
+| `/api/provider-nodes*` | Various | Provider node management |
+| `/api/provider-models` | GET/POST/DELETE | Custom models |
+
+### OAuth Flows
+
+| Endpoint | Method | Description |
+| -------------------------------- | ------- | ----------------------- |
+| `/api/oauth/[provider]/[action]` | Various | Provider-specific OAuth |
+
+### Routing & Config
+
+| Endpoint | Method | Description |
+| --------------------- | -------- | ----------------------------- |
+| `/api/models/alias` | GET/POST | Model aliases |
+| `/api/models/catalog` | GET | All models by provider + type |
+| `/api/combos*` | Various | Combo management |
+| `/api/keys*` | Various | API key management |
+| `/api/pricing` | GET | Model pricing |
+
+### Usage & Analytics
+
+| Endpoint | Method | Description |
+| --------------------------- | ------ | -------------------- |
+| `/api/usage/history` | GET | Usage history |
+| `/api/usage/logs` | GET | Usage logs |
+| `/api/usage/request-logs` | GET | Request-level logs |
+| `/api/usage/[connectionId]` | GET | Per-connection usage |
+
+### Settings
+
+| Endpoint | Method | Description |
+| ------------------------------- | ------------- | ---------------------- |
+| `/api/settings` | GET/PUT/PATCH | General settings |
+| `/api/settings/proxy` | GET/PUT | Network proxy config |
+| `/api/settings/proxy/test` | POST | Test proxy connection |
+| `/api/settings/ip-filter` | GET/PUT | IP allowlist/blocklist |
+| `/api/settings/thinking-budget` | GET/PUT | Reasoning token budget |
+| `/api/settings/system-prompt` | GET/PUT | Global system prompt |
+
+### Monitoring
+
+| Endpoint | Method | Description |
+| ------------------------ | ---------- | ---------------------------------------------------------------------------------------------------- |
+| `/api/sessions` | GET | Active session tracking |
+| `/api/rate-limits` | GET | Per-account rate limits |
+| `/api/monitoring/health` | GET | Health check + provider summary (`catalogCount`, `configuredCount`, `activeCount`, `monitoredCount`) |
+| `/api/cache/stats` | GET/DELETE | Cache stats / clear |
+
+### Backup & Export/Import
+
+| Endpoint | Method | Description |
+| --------------------------- | ------ | --------------------------------------- |
+| `/api/db-backups` | GET | List available backups |
+| `/api/db-backups` | PUT | Create a manual backup |
+| `/api/db-backups` | POST | Restore from a specific backup |
+| `/api/db-backups/export` | GET | Download database as .sqlite file |
+| `/api/db-backups/import` | POST | Upload .sqlite file to replace database |
+| `/api/db-backups/exportAll` | GET | Download full backup as .tar.gz archive |
+
+### Cloud Sync
+
+| Endpoint | Method | Description |
+| ---------------------- | ------- | --------------------- |
+| `/api/sync/cloud` | Various | Cloud sync operations |
+| `/api/sync/initialize` | POST | Initialize sync |
+| `/api/cloud/*` | Various | Cloud management |
+
+### Tunnels
+
+| Endpoint | Method | Description |
+| -------------------------- | ------ | ----------------------------------------------------------------------- |
+| `/api/tunnels/cloudflared` | GET | Read Cloudflare Quick Tunnel install/runtime status for the dashboard |
+| `/api/tunnels/cloudflared` | POST | Enable or disable the Cloudflare Quick Tunnel (`action=enable/disable`) |
+
+### CLI Tools
+
+| Endpoint | Method | Description |
+| ---------------------------------- | ------ | ------------------- |
+| `/api/cli-tools/claude-settings` | GET | Claude CLI status |
+| `/api/cli-tools/codex-settings` | GET | Codex CLI status |
+| `/api/cli-tools/droid-settings` | GET | Droid CLI status |
+| `/api/cli-tools/openclaw-settings` | GET | OpenClaw CLI status |
+| `/api/cli-tools/runtime/[toolId]` | GET | Generic CLI runtime |
+
+CLI responses include: `installed`, `runnable`, `command`, `commandPath`, `runtimeMode`, `reason`.
+
+### ACP Agents
+
+| Endpoint | Method | Description |
+| ----------------- | ------ | -------------------------------------------------------- |
+| `/api/acp/agents` | GET | List all detected agents (built-in + custom) with status |
+| `/api/acp/agents` | POST | Add custom agent or refresh detection cache |
+| `/api/acp/agents` | DELETE | Remove a custom agent by `id` query param |
+
+GET response includes `agents[]` (id, name, binary, version, installed, protocol, isCustom) and `summary` (total, installed, notFound, builtIn, custom).
+
+### Resilience & Rate Limits
+
+| Endpoint | Method | Description |
+| ----------------------- | --------- | ------------------------------- |
+| `/api/resilience` | GET/PATCH | Get/update resilience profiles |
+| `/api/resilience/reset` | POST | Reset circuit breakers |
+| `/api/rate-limits` | GET | Per-account rate limit status |
+| `/api/rate-limit` | GET | Global rate limit configuration |
+
+### Evals
+
+| Endpoint | Method | Description |
+| ------------ | -------- | --------------------------------- |
+| `/api/evals` | GET/POST | List eval suites / run evaluation |
+
+### Policies
+
+| Endpoint | Method | Description |
+| --------------- | --------------- | ----------------------- |
+| `/api/policies` | GET/POST/DELETE | Manage routing policies |
+
+### Compliance
+
+| Endpoint | Method | Description |
+| --------------------------- | ------ | ----------------------------- |
+| `/api/compliance/audit-log` | GET | Compliance audit log (last N) |
+
+### v1beta (Gemini-Compatible)
+
+| Endpoint | Method | Description |
+| -------------------------- | ------ | --------------------------------- |
+| `/v1beta/models` | GET | List models in Gemini format |
+| `/v1beta/models/{...path}` | POST | Gemini `generateContent` endpoint |
+
+These endpoints mirror Gemini's API format for clients that expect native Gemini SDK compatibility.
+
+### Internal / System APIs
+
+| Endpoint | Method | Description |
+| --------------- | ------ | ---------------------------------------------------- |
+| `/api/init` | GET | Application initialization check (used on first run) |
+| `/api/tags` | GET | Ollama-compatible model tags (for Ollama clients) |
+| `/api/restart` | POST | Trigger graceful server restart |
+| `/api/shutdown` | POST | Trigger graceful server shutdown |
+
+> **Note:** These endpoints are used internally by the system or for Ollama client compatibility. They are not typically called by end users.
+
+---
+
+## Audio Transcription
+
+```bash
+POST /v1/audio/transcriptions
+Authorization: Bearer your-api-key
+Content-Type: multipart/form-data
+```
+
+Transcribe audio files using Deepgram or AssemblyAI.
+
+**Request:**
+
+```bash
+curl -X POST http://localhost:20128/v1/audio/transcriptions \
+ -H "Authorization: Bearer your-api-key" \
+ -F "file=@recording.mp3" \
+ -F "model=deepgram/nova-3"
+```
+
+**Response:**
+
+```json
+{
+ "text": "Hello, this is the transcribed audio content.",
+ "task": "transcribe",
+ "language": "en",
+ "duration": 12.5
+}
+```
+
+**Supported providers:** `deepgram/nova-3`, `assemblyai/best`.
+
+**Supported formats:** `mp3`, `wav`, `m4a`, `flac`, `ogg`, `webm`.
+
+---
+
+## Ollama Compatibility
+
+For clients that use Ollama's API format:
+
+```bash
+# Chat endpoint (Ollama format)
+POST /v1/api/chat
+
+# Model listing (Ollama format)
+GET /api/tags
+```
+
+Requests are automatically translated between Ollama and internal formats.
+
+---
+
+## Telemetry
+
+```bash
+# Get latency telemetry summary (p50/p95/p99 per provider)
+GET /api/telemetry/summary
+```
+
+**Response:**
+
+```json
+{
+ "providers": {
+ "claudeCode": { "p50": 245, "p95": 890, "p99": 1200, "count": 150 },
+ "github": { "p50": 180, "p95": 620, "p99": 950, "count": 320 }
+ }
+}
+```
+
+---
+
+## Budget
+
+```bash
+# Get budget status for all API keys
+GET /api/usage/budget
+
+# Set or update a budget
+POST /api/usage/budget
+Content-Type: application/json
+
+{
+ "keyId": "key-123",
+ "limit": 50.00,
+ "period": "monthly"
+}
+```
+
+---
+
+## Model Availability
+
+```bash
+# Get real-time model availability across all providers
+GET /api/models/availability
+
+# Check availability for a specific model
+POST /api/models/availability
+Content-Type: application/json
+
+{
+ "model": "claude-sonnet-4-5-20250929"
+}
+```
+
+---
+
+## Request Processing
+
+1. Client sends request to `/v1/*`
+2. Route handler calls `handleChat`, `handleEmbedding`, `handleAudioTranscription`, or `handleImageGeneration`
+3. Model is resolved (direct provider/model or alias/combo)
+4. Credentials selected from local DB with account availability filtering
+5. For chat: `handleChatCore` — format detection, translation, cache check, idempotency check
+6. Provider executor sends upstream request
+7. Response translated back to client format (chat) or returned as-is (embeddings/images/audio)
+8. Usage/logging recorded
+9. Fallback applies on errors according to combo rules
+
+Full architecture reference: [`ARCHITECTURE.md`](ARCHITECTURE.md)
+
+---
+
+## Authentication
+
+- Dashboard routes (`/dashboard/*`) use `auth_token` cookie
+- Login uses saved password hash; fallback to `INITIAL_PASSWORD`
+- `requireLogin` toggleable via `/api/settings/require-login`
+- `/v1/*` routes optionally require Bearer API key when `REQUIRE_API_KEY=true`
diff --git a/docs/i18n/ar/docs/ARCHITECTURE.md b/docs/i18n/ar/docs/ARCHITECTURE.md
new file mode 100644
index 0000000000..aedd88fbf8
--- /dev/null
+++ b/docs/i18n/ar/docs/ARCHITECTURE.md
@@ -0,0 +1,814 @@
+# OmniRoute Architecture (العربية)
+
+🌐 **Languages:** 🇺🇸 [English](../../../../docs/ARCHITECTURE.md) · 🇪🇸 [es](../../es/docs/ARCHITECTURE.md) · 🇫🇷 [fr](../../fr/docs/ARCHITECTURE.md) · 🇩🇪 [de](../../de/docs/ARCHITECTURE.md) · 🇮🇹 [it](../../it/docs/ARCHITECTURE.md) · 🇷🇺 [ru](../../ru/docs/ARCHITECTURE.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/ARCHITECTURE.md) · 🇯🇵 [ja](../../ja/docs/ARCHITECTURE.md) · 🇰🇷 [ko](../../ko/docs/ARCHITECTURE.md) · 🇸🇦 [ar](../../ar/docs/ARCHITECTURE.md) · 🇮🇳 [in](../../in/docs/ARCHITECTURE.md) · 🇹🇭 [th](../../th/docs/ARCHITECTURE.md) · 🇻🇳 [vi](../../vi/docs/ARCHITECTURE.md) · 🇮🇩 [id](../../id/docs/ARCHITECTURE.md) · 🇲🇾 [ms](../../ms/docs/ARCHITECTURE.md) · 🇳🇱 [nl](../../nl/docs/ARCHITECTURE.md) · 🇵🇱 [pl](../../pl/docs/ARCHITECTURE.md) · 🇸🇪 [sv](../../sv/docs/ARCHITECTURE.md) · 🇳🇴 [no](../../no/docs/ARCHITECTURE.md) · 🇩🇰 [da](../../da/docs/ARCHITECTURE.md) · 🇫🇮 [fi](../../fi/docs/ARCHITECTURE.md) · 🇵🇹 [pt](../../pt/docs/ARCHITECTURE.md) · 🇷🇴 [ro](../../ro/docs/ARCHITECTURE.md) · 🇭🇺 [hu](../../hu/docs/ARCHITECTURE.md) · 🇧🇬 [bg](../../bg/docs/ARCHITECTURE.md) · 🇸🇰 [sk](../../sk/docs/ARCHITECTURE.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/ARCHITECTURE.md) · 🇮🇱 [he](../../he/docs/ARCHITECTURE.md) · 🇵🇭 [phi](../../phi/docs/ARCHITECTURE.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/ARCHITECTURE.md) · 🇨🇿 [cs](../../cs/docs/ARCHITECTURE.md)
+
+---
+
+_Last updated: 2026-03-28_
+
+## Executive Summary
+
+OmniRoute is a local AI routing gateway and dashboard built on Next.js.
+It provides a single OpenAI-compatible endpoint (`/v1/*`) and routes traffic across multiple upstream providers with translation, fallback, token refresh, and usage tracking.
+
+Core capabilities:
+
+- OpenAI-compatible API surface for CLI/tools (28 providers)
+- Request/response translation across provider formats
+- Model combo fallback (multi-model sequence)
+- Account-level fallback (multi-account per provider)
+- OAuth + API-key provider connection management
+- Embedding generation via `/v1/embeddings` (6 providers, 9 models)
+- Image generation via `/v1/images/generations` (4 providers, 9 models)
+- Think tag parsing (`...`) for reasoning models
+- Response sanitization for strict OpenAI SDK compatibility
+- Role normalization (developer→system, system→user) for cross-provider compatibility
+- Structured output conversion (json_schema → Gemini responseSchema)
+- Local persistence for providers, keys, aliases, combos, settings, pricing
+- Usage/cost tracking and request logging
+- Optional cloud sync for multi-device/state sync
+- IP allowlist/blocklist for API access control
+- Thinking budget management (passthrough/auto/custom/adaptive)
+- Global system prompt injection
+- Session tracking and fingerprinting
+- Per-account enhanced rate limiting with provider-specific profiles
+- Circuit breaker pattern for provider resilience
+- Anti-thundering herd protection with mutex locking
+- Signature-based request deduplication cache
+- Domain layer: model availability, cost rules, fallback policy, lockout policy
+- Domain state persistence (SQLite write-through cache for fallbacks, budgets, lockouts, circuit breakers)
+- Policy engine for centralized request evaluation (lockout → budget → fallback)
+- Request telemetry with p50/p95/p99 latency aggregation
+- Correlation ID (X-Request-Id) for end-to-end tracing
+- Compliance audit logging with opt-out per API key
+- Eval framework for LLM quality assurance
+- Resilience UI dashboard with real-time circuit breaker status
+- Modular OAuth providers (12 individual modules under `src/lib/oauth/providers/`)
+
+Primary runtime model:
+
+- Next.js app routes under `src/app/api/*` implement both dashboard APIs and compatibility APIs
+- A shared SSE/routing core in `src/sse/*` + `open-sse/*` handles provider execution, translation, streaming, fallback, and usage
+
+## Scope and Boundaries
+
+### In Scope
+
+- Local gateway runtime
+- Dashboard management APIs
+- Provider authentication and token refresh
+- Request translation and SSE streaming
+- Local state + usage persistence
+- Optional cloud sync orchestration
+
+### Out of Scope
+
+- Cloud service implementation behind `NEXT_PUBLIC_CLOUD_URL`
+- Provider SLA/control plane outside local process
+- External CLI binaries themselves (Claude CLI, Codex CLI, etc.)
+
+## Dashboard Surface (Current)
+
+Main pages under `src/app/(dashboard)/dashboard/`:
+
+- `/dashboard` — quick start + provider overview
+- `/dashboard/endpoint` — endpoint proxy + MCP + A2A + API endpoint tabs
+- `/dashboard/providers` — provider connections and credentials
+- `/dashboard/combos` — combo strategies, templates, model routing rules
+- `/dashboard/costs` — cost aggregation and pricing visibility
+- `/dashboard/analytics` — usage analytics and evaluations
+- `/dashboard/limits` — quota/rate controls
+- `/dashboard/cli-tools` — CLI onboarding, runtime detection, config generation
+- `/dashboard/agents` — detected ACP agents + custom agent registration
+- `/dashboard/media` — image/video/music playground
+- `/dashboard/search-tools` — search provider testing and history
+- `/dashboard/health` — uptime, circuit breakers, rate limits
+- `/dashboard/logs` — request/proxy/audit/console logs
+- `/dashboard/settings` — system settings tabs (general, routing, combo defaults, etc.)
+- `/dashboard/api-manager` — API key lifecycle and model permissions
+
+## High-Level System Context
+
+```mermaid
+flowchart LR
+ subgraph Clients[Developer Clients]
+ C1[Claude Code]
+ C2[Codex CLI]
+ C3[OpenClaw / Droid / Cline / Continue / Roo]
+ C4[Custom OpenAI-compatible clients]
+ BROWSER[Browser Dashboard]
+ end
+
+ subgraph Router[OmniRoute Local Process]
+ API[V1 Compatibility API\n/v1/*]
+ DASH[Dashboard + Management API\n/api/*]
+ CORE[SSE + Translation Core\nopen-sse + src/sse]
+ DB[(storage.sqlite)]
+ UDB[(usage tables + log artifacts)]
+ end
+
+ subgraph Upstreams[Upstream Providers]
+ P1[OAuth Providers\nClaude/Codex/Gemini/Qwen/Qoder/GitHub/Kiro/Cursor/Antigravity]
+ P2[API Key Providers\nOpenAI/Anthropic/OpenRouter/GLM/Kimi/MiniMax\nDeepSeek/Groq/xAI/Mistral/Perplexity\nTogether/Fireworks/Cerebras/Cohere/NVIDIA]
+ P3[Compatible Nodes\nOpenAI-compatible / Anthropic-compatible]
+ end
+
+ subgraph Cloud[Optional Cloud Sync]
+ CLOUD[Cloud Sync Endpoint\nNEXT_PUBLIC_CLOUD_URL]
+ end
+
+ C1 --> API
+ C2 --> API
+ C3 --> API
+ C4 --> API
+ BROWSER --> DASH
+
+ API --> CORE
+ DASH --> DB
+ CORE --> DB
+ CORE --> UDB
+
+ CORE --> P1
+ CORE --> P2
+ CORE --> P3
+
+ DASH --> CLOUD
+```
+
+## Core Runtime Components
+
+## 1) API and Routing Layer (Next.js App Routes)
+
+Main directories:
+
+- `src/app/api/v1/*` and `src/app/api/v1beta/*` for compatibility APIs
+- `src/app/api/*` for management/configuration APIs
+- Next rewrites in `next.config.mjs` map `/v1/*` to `/api/v1/*`
+
+Important compatibility routes:
+
+- `src/app/api/v1/chat/completions/route.ts`
+- `src/app/api/v1/messages/route.ts`
+- `src/app/api/v1/responses/route.ts`
+- `src/app/api/v1/models/route.ts` — includes custom models with `custom: true`
+- `src/app/api/v1/embeddings/route.ts` — embedding generation (6 providers)
+- `src/app/api/v1/images/generations/route.ts` — image generation (4+ providers incl. Antigravity/Nebius)
+- `src/app/api/v1/messages/count_tokens/route.ts`
+- `src/app/api/v1/providers/[provider]/chat/completions/route.ts` — dedicated per-provider chat
+- `src/app/api/v1/providers/[provider]/embeddings/route.ts` — dedicated per-provider embeddings
+- `src/app/api/v1/providers/[provider]/images/generations/route.ts` — dedicated per-provider images
+- `src/app/api/v1beta/models/route.ts`
+- `src/app/api/v1beta/models/[...path]/route.ts`
+
+Management domains:
+
+- Auth/settings: `src/app/api/auth/*`, `src/app/api/settings/*`
+- Providers/connections: `src/app/api/providers*`
+- Provider nodes: `src/app/api/provider-nodes*`
+- Custom models: `src/app/api/provider-models` (GET/POST/DELETE)
+- Model catalog: `src/app/api/models/route.ts` (GET)
+- Proxy config: `src/app/api/settings/proxy` (GET/PUT/DELETE) + `src/app/api/settings/proxy/test` (POST)
+- OAuth: `src/app/api/oauth/*`
+- Keys/aliases/combos/pricing: `src/app/api/keys*`, `src/app/api/models/alias`, `src/app/api/combos*`, `src/app/api/pricing`
+- Usage: `src/app/api/usage/*`
+- Sync/cloud: `src/app/api/sync/*`, `src/app/api/cloud/*`
+- CLI tooling helpers: `src/app/api/cli-tools/*`
+- IP filter: `src/app/api/settings/ip-filter` (GET/PUT)
+- Thinking budget: `src/app/api/settings/thinking-budget` (GET/PUT)
+- System prompt: `src/app/api/settings/system-prompt` (GET/PUT)
+- Sessions: `src/app/api/sessions` (GET)
+- Rate limits: `src/app/api/rate-limits` (GET)
+- Resilience: `src/app/api/resilience` (GET/PATCH) — provider profiles, circuit breaker, rate limit state
+- Resilience reset: `src/app/api/resilience/reset` (POST) — reset breakers + cooldowns
+- Cache stats: `src/app/api/cache/stats` (GET/DELETE)
+- Model availability: `src/app/api/models/availability` (GET/POST)
+- Telemetry: `src/app/api/telemetry/summary` (GET)
+- Budget: `src/app/api/usage/budget` (GET/POST)
+- Fallback chains: `src/app/api/fallback/chains` (GET/POST/DELETE)
+- Compliance audit: `src/app/api/compliance/audit-log` (GET)
+- Evals: `src/app/api/evals` (GET/POST), `src/app/api/evals/[suiteId]` (GET)
+- Policies: `src/app/api/policies` (GET/POST)
+
+## 2) SSE + Translation Core
+
+Main flow modules:
+
+- Entry: `src/sse/handlers/chat.ts`
+- Core orchestration: `open-sse/handlers/chatCore.ts`
+- Provider execution adapters: `open-sse/executors/*`
+- Format detection/provider config: `open-sse/services/provider.ts`
+- Model parse/resolve: `src/sse/services/model.ts`, `open-sse/services/model.ts`
+- Account fallback logic: `open-sse/services/accountFallback.ts`
+- Translation registry: `open-sse/translator/index.ts`
+- Stream transformations: `open-sse/utils/stream.ts`, `open-sse/utils/streamHandler.ts`
+- Usage extraction/normalization: `open-sse/utils/usageTracking.ts`
+- Think tag parser: `open-sse/utils/thinkTagParser.ts`
+- Embedding handler: `open-sse/handlers/embeddings.ts`
+- Embedding provider registry: `open-sse/config/embeddingRegistry.ts`
+- Image generation handler: `open-sse/handlers/imageGeneration.ts`
+- Image provider registry: `open-sse/config/imageRegistry.ts`
+- Response sanitization: `open-sse/handlers/responseSanitizer.ts`
+- Role normalization: `open-sse/services/roleNormalizer.ts`
+
+Services (business logic):
+
+- Account selection/scoring: `open-sse/services/accountSelector.ts`
+- Context lifecycle management: `open-sse/services/contextManager.ts`
+- IP filter enforcement: `open-sse/services/ipFilter.ts`
+- Session tracking: `open-sse/services/sessionManager.ts`
+- Request deduplication: `open-sse/services/signatureCache.ts`
+- System prompt injection: `open-sse/services/systemPrompt.ts`
+- Thinking budget management: `open-sse/services/thinkingBudget.ts`
+- Wildcard model routing: `open-sse/services/wildcardRouter.ts`
+- Rate limit management: `open-sse/services/rateLimitManager.ts`
+- Circuit breaker: `open-sse/services/circuitBreaker.ts`
+
+Domain layer modules:
+
+- Model availability: `src/lib/domain/modelAvailability.ts`
+- Cost rules/budgets: `src/lib/domain/costRules.ts`
+- Fallback policy: `src/lib/domain/fallbackPolicy.ts`
+- Combo resolver: `src/lib/domain/comboResolver.ts`
+- Lockout policy: `src/lib/domain/lockoutPolicy.ts`
+- Policy engine: `src/domain/policyEngine.ts` — centralized lockout → budget → fallback evaluation
+- Error codes catalog: `src/lib/domain/errorCodes.ts`
+- Request ID: `src/lib/domain/requestId.ts`
+- Fetch timeout: `src/lib/domain/fetchTimeout.ts`
+- Request telemetry: `src/lib/domain/requestTelemetry.ts`
+- Compliance/audit: `src/lib/domain/compliance/index.ts`
+- Eval runner: `src/lib/domain/evalRunner.ts`
+- Domain state persistence: `src/lib/db/domainState.ts` — SQLite CRUD for fallback chains, budgets, cost history, lockout state, circuit breakers
+
+OAuth provider modules (12 individual files under `src/lib/oauth/providers/`):
+
+- Registry index: `src/lib/oauth/providers/index.ts`
+- Individual providers: `claude.ts`, `codex.ts`, `gemini.ts`, `antigravity.ts`, `qoder.ts`, `qwen.ts`, `kimi-coding.ts`, `github.ts`, `kiro.ts`, `cursor.ts`, `kilocode.ts`, `cline.ts`
+- Thin wrapper: `src/lib/oauth/providers.ts` — re-exports from individual modules
+
+## 3) Persistence Layer
+
+Primary state DB (SQLite):
+
+- Core infra: `src/lib/db/core.ts` (better-sqlite3, migrations, WAL)
+- Re-export facade: `src/lib/localDb.ts` (thin compatibility layer for callers)
+- file: `${DATA_DIR}/storage.sqlite` (or `$XDG_CONFIG_HOME/omniroute/storage.sqlite` when set, else `~/.omniroute/storage.sqlite`)
+- entities (tables + KV namespaces): providerConnections, providerNodes, modelAliases, combos, apiKeys, settings, pricing, **customModels**, **proxyConfig**, **ipFilter**, **thinkingBudget**, **systemPrompt**
+
+Usage persistence:
+
+- facade: `src/lib/usageDb.ts` (decomposed modules in `src/lib/usage/*`)
+- SQLite tables in `storage.sqlite`: `usage_history`, `call_logs`, `proxy_logs`
+- optional file artifacts remain for compatibility/debug (`${DATA_DIR}/log.txt`, `${DATA_DIR}/call_logs/`, `/logs/...`)
+- legacy JSON files are migrated to SQLite by startup migrations when present
+
+Domain State DB (SQLite):
+
+- `src/lib/db/domainState.ts` — CRUD operations for domain state
+- Tables (created in `src/lib/db/core.ts`): `domain_fallback_chains`, `domain_budgets`, `domain_cost_history`, `domain_lockout_state`, `domain_circuit_breakers`
+- Write-through cache pattern: in-memory Maps are authoritative at runtime; mutations are written synchronously to SQLite; state is restored from DB on cold start
+
+## 4) Auth + Security Surfaces
+
+- Dashboard cookie auth: `src/proxy.ts`, `src/app/api/auth/login/route.ts`
+- API key generation/verification: `src/shared/utils/apiKey.ts`
+- Provider secrets persisted in `providerConnections` entries
+- Outbound proxy support via `open-sse/utils/proxyFetch.ts` (env vars) and `open-sse/utils/networkProxy.ts` (configurable per-provider or global)
+
+## 5) Cloud Sync
+
+- Scheduler init: `src/lib/initCloudSync.ts`, `src/shared/services/initializeCloudSync.ts`, `src/shared/services/modelSyncScheduler.ts`
+- Periodic task: `src/shared/services/cloudSyncScheduler.ts`
+- Periodic task: `src/shared/services/modelSyncScheduler.ts`
+- Control route: `src/app/api/sync/cloud/route.ts`
+
+## Request Lifecycle (`/v1/chat/completions`)
+
+```mermaid
+sequenceDiagram
+ autonumber
+ participant Client as CLI/SDK Client
+ participant Route as /api/v1/chat/completions
+ participant Chat as src/sse/handlers/chat
+ participant Core as open-sse/handlers/chatCore
+ participant Model as Model Resolver
+ participant Auth as Credential Selector
+ participant Exec as Provider Executor
+ participant Prov as Upstream Provider
+ participant Stream as Stream Translator
+ participant Usage as usageDb
+
+ Client->>Route: POST /v1/chat/completions
+ Route->>Chat: handleChat(request)
+ Chat->>Model: parse/resolve model or combo
+
+ alt Combo model
+ Chat->>Chat: iterate combo models (handleComboChat)
+ end
+
+ Chat->>Auth: getProviderCredentials(provider)
+ Auth-->>Chat: active account + tokens/api key
+
+ Chat->>Core: handleChatCore(body, modelInfo, credentials)
+ Core->>Core: detect source format
+ Core->>Core: translate request to target format
+ Core->>Exec: execute(provider, transformedBody)
+ Exec->>Prov: upstream API call
+ Prov-->>Exec: SSE/JSON response
+ Exec-->>Core: response + metadata
+
+ alt 401/403
+ Core->>Exec: refreshCredentials()
+ Exec-->>Core: updated tokens
+ Core->>Exec: retry request
+ end
+
+ Core->>Stream: translate/normalize stream to client format
+ Stream-->>Client: SSE chunks / JSON response
+
+ Stream->>Usage: extract usage + persist history/log
+```
+
+## Combo + Account Fallback Flow
+
+```mermaid
+flowchart TD
+ A[Incoming model string] --> B{Is combo name?}
+ B -- Yes --> C[Load combo models sequence]
+ B -- No --> D[Single model path]
+
+ C --> E[Try model N]
+ E --> F[Resolve provider/model]
+ D --> F
+
+ F --> G[Select account credentials]
+ G --> H{Credentials available?}
+ H -- No --> I[Return provider unavailable]
+ H -- Yes --> J[Execute request]
+
+ J --> K{Success?}
+ K -- Yes --> L[Return response]
+ K -- No --> M{Fallback-eligible error?}
+
+ M -- No --> N[Return error]
+ M -- Yes --> O[Mark account unavailable cooldown]
+ O --> P{Another account for provider?}
+ P -- Yes --> G
+ P -- No --> Q{In combo with next model?}
+ Q -- Yes --> E
+ Q -- No --> R[Return all unavailable]
+```
+
+Fallback decisions are driven by `open-sse/services/accountFallback.ts` using status codes and error-message heuristics. Combo routing adds one extra guard: provider-scoped 400s such as upstream content-block and role-validation failures are treated as model-local failures so later combo targets can still run.
+
+## OAuth Onboarding and Token Refresh Lifecycle
+
+```mermaid
+sequenceDiagram
+ autonumber
+ participant UI as Dashboard UI
+ participant OAuth as /api/oauth/[provider]/[action]
+ participant ProvAuth as Provider Auth Server
+ participant DB as localDb
+ participant Test as /api/providers/[id]/test
+ participant Exec as Provider Executor
+
+ UI->>OAuth: GET authorize or device-code
+ OAuth->>ProvAuth: create auth/device flow
+ ProvAuth-->>OAuth: auth URL or device code payload
+ OAuth-->>UI: flow data
+
+ UI->>OAuth: POST exchange or poll
+ OAuth->>ProvAuth: token exchange/poll
+ ProvAuth-->>OAuth: access/refresh tokens
+ OAuth->>DB: createProviderConnection(oauth data)
+ OAuth-->>UI: success + connection id
+
+ UI->>Test: POST /api/providers/[id]/test
+ Test->>Exec: validate credentials / optional refresh
+ Exec-->>Test: valid or refreshed token info
+ Test->>DB: update status/tokens/errors
+ Test-->>UI: validation result
+```
+
+Refresh during live traffic is executed inside `open-sse/handlers/chatCore.ts` via executor `refreshCredentials()`.
+
+## Cloud Sync Lifecycle (Enable / Sync / Disable)
+
+```mermaid
+sequenceDiagram
+ autonumber
+ participant UI as Endpoint Page UI
+ participant Sync as /api/sync/cloud
+ participant DB as localDb
+ participant Cloud as External Cloud Sync
+ participant Claude as ~/.claude/settings.json
+
+ UI->>Sync: POST action=enable
+ Sync->>DB: set cloudEnabled=true
+ Sync->>DB: ensure API key exists
+ Sync->>Cloud: POST /sync/{machineId} (providers/aliases/combos/keys)
+ Cloud-->>Sync: sync result
+ Sync->>Cloud: GET /{machineId}/v1/verify
+ Sync-->>UI: enabled + verification status
+
+ UI->>Sync: POST action=sync
+ Sync->>Cloud: POST /sync/{machineId}
+ Cloud-->>Sync: remote data
+ Sync->>DB: update newer local tokens/status
+ Sync-->>UI: synced
+
+ UI->>Sync: POST action=disable
+ Sync->>DB: set cloudEnabled=false
+ Sync->>Cloud: DELETE /sync/{machineId}
+ Sync->>Claude: switch ANTHROPIC_BASE_URL back to local (if needed)
+ Sync-->>UI: disabled
+```
+
+Periodic sync is triggered by `CloudSyncScheduler` when cloud is enabled.
+
+## Data Model and Storage Map
+
+```mermaid
+erDiagram
+ SETTINGS ||--o{ PROVIDER_CONNECTION : controls
+ PROVIDER_NODE ||--o{ PROVIDER_CONNECTION : backs_compatible_provider
+ PROVIDER_CONNECTION ||--o{ USAGE_ENTRY : emits_usage
+
+ SETTINGS {
+ boolean cloudEnabled
+ number stickyRoundRobinLimit
+ boolean requireLogin
+ string password_hash
+ string fallbackStrategy
+ json rateLimitDefaults
+ json providerProfiles
+ }
+
+ PROVIDER_CONNECTION {
+ string id
+ string provider
+ string authType
+ string name
+ number priority
+ boolean isActive
+ string apiKey
+ string accessToken
+ string refreshToken
+ string expiresAt
+ string testStatus
+ string lastError
+ string rateLimitedUntil
+ json providerSpecificData
+ }
+
+ PROVIDER_NODE {
+ string id
+ string type
+ string name
+ string prefix
+ string apiType
+ string baseUrl
+ }
+
+ MODEL_ALIAS {
+ string alias
+ string targetModel
+ }
+
+ COMBO {
+ string id
+ string name
+ string[] models
+ }
+
+ API_KEY {
+ string id
+ string name
+ string key
+ string machineId
+ }
+
+ USAGE_ENTRY {
+ string provider
+ string model
+ number prompt_tokens
+ number completion_tokens
+ string connectionId
+ string timestamp
+ }
+
+ CUSTOM_MODEL {
+ string id
+ string name
+ string providerId
+ }
+
+ PROXY_CONFIG {
+ string global
+ json providers
+ }
+
+ IP_FILTER {
+ string mode
+ string[] allowlist
+ string[] blocklist
+ }
+
+ THINKING_BUDGET {
+ string mode
+ number customBudget
+ string effortLevel
+ }
+
+ SYSTEM_PROMPT {
+ boolean enabled
+ string prompt
+ string position
+ }
+```
+
+Physical storage files:
+
+- primary runtime DB: `${DATA_DIR}/storage.sqlite`
+- request log lines: `${DATA_DIR}/log.txt` (compat/debug artifact)
+- structured call payload archives: `${DATA_DIR}/call_logs/`
+- optional translator/request debug sessions: `/logs/...`
+
+## Deployment Topology
+
+```mermaid
+flowchart LR
+ subgraph LocalHost[Developer Host]
+ CLI[CLI Tools]
+ Browser[Dashboard Browser]
+ end
+
+ subgraph ContainerOrProcess[OmniRoute Runtime]
+ Next[Next.js Server\nPORT=20128]
+ Core[SSE Core + Executors]
+ MainDB[(storage.sqlite)]
+ UsageDB[(usage tables + log artifacts)]
+ end
+
+ subgraph External[External Services]
+ Providers[AI Providers]
+ SyncCloud[Cloud Sync Service]
+ end
+
+ CLI --> Next
+ Browser --> Next
+ Next --> Core
+ Next --> MainDB
+ Core --> MainDB
+ Core --> UsageDB
+ Core --> Providers
+ Next --> SyncCloud
+```
+
+## Module Mapping (Decision-Critical)
+
+### Route and API Modules
+
+- `src/app/api/v1/*`, `src/app/api/v1beta/*`: compatibility APIs
+- `src/app/api/v1/providers/[provider]/*`: dedicated per-provider routes (chat, embeddings, images)
+- `src/app/api/providers*`: provider CRUD, validation, testing
+- `src/app/api/provider-nodes*`: custom compatible node management
+- `src/app/api/provider-models`: custom model management (CRUD)
+- `src/app/api/models/route.ts`: model catalog API (aliases + custom models)
+- `src/app/api/oauth/*`: OAuth/device-code flows
+- `src/app/api/keys*`: local API key lifecycle
+- `src/app/api/models/alias`: alias management
+- `src/app/api/combos*`: fallback combo management
+- `src/app/api/pricing`: pricing overrides for cost calculation
+- `src/app/api/settings/proxy`: proxy configuration (GET/PUT/DELETE)
+- `src/app/api/settings/proxy/test`: outbound proxy connectivity test (POST)
+- `src/app/api/usage/*`: usage and logs APIs
+- `src/app/api/sync/*` + `src/app/api/cloud/*`: cloud sync and cloud-facing helpers
+- `src/app/api/cli-tools/*`: local CLI config writers/checkers
+- `src/app/api/settings/ip-filter`: IP allowlist/blocklist (GET/PUT)
+- `src/app/api/settings/thinking-budget`: thinking token budget config (GET/PUT)
+- `src/app/api/settings/system-prompt`: global system prompt (GET/PUT)
+- `src/app/api/sessions`: active session listing (GET)
+- `src/app/api/rate-limits`: per-account rate limit status (GET)
+
+### Routing and Execution Core
+
+- `src/sse/handlers/chat.ts`: request parse, combo handling, account selection loop
+- `open-sse/handlers/chatCore.ts`: translation, executor dispatch, retry/refresh handling, stream setup
+- `open-sse/executors/*`: provider-specific network and format behavior
+
+### Translation Registry and Format Converters
+
+- `open-sse/translator/index.ts`: translator registry and orchestration
+- Request translators: `open-sse/translator/request/*`
+- Response translators: `open-sse/translator/response/*`
+- Format constants: `open-sse/translator/formats.ts`
+
+### Persistence
+
+- `src/lib/db/*`: persistent config/state and domain persistence on SQLite
+- `src/lib/localDb.ts`: compatibility re-export for DB modules
+- `src/lib/usageDb.ts`: usage history/call logs facade on top of SQLite tables
+
+## Provider Executor Coverage (Strategy Pattern)
+
+Each provider has a specialized executor extending `BaseExecutor` (in `open-sse/executors/base.ts`), which provides URL building, header construction, retry with exponential backoff, credential refresh hooks, and the `execute()` orchestration method.
+
+| Executor | Provider(s) | Special Handling |
+| --------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------ | -------------------------------------------------------------------- |
+| `DefaultExecutor` | OpenAI, Claude, Gemini, Qwen, Qoder, OpenRouter, GLM, Kimi, MiniMax, DeepSeek, Groq, xAI, Mistral, Perplexity, Together, Fireworks, Cerebras, Cohere, NVIDIA | Dynamic URL/header config per provider |
+| `AntigravityExecutor` | Google Antigravity | Custom project/session IDs, Retry-After parsing |
+| `CodexExecutor` | OpenAI Codex | Injects system instructions, forces reasoning effort |
+| `CursorExecutor` | Cursor IDE | ConnectRPC protocol, Protobuf encoding, request signing via checksum |
+| `GithubExecutor` | GitHub Copilot | Copilot token refresh, VSCode-mimicking headers |
+| `KiroExecutor` | AWS CodeWhisperer/Kiro | AWS EventStream binary format → SSE conversion |
+| `GeminiCLIExecutor` | Gemini CLI | Google OAuth token refresh cycle |
+
+All other providers (including custom compatible nodes) use the `DefaultExecutor`.
+
+## Provider Compatibility Matrix
+
+| Provider | Format | Auth | Stream | Non-Stream | Token Refresh | Usage API |
+| ---------------- | ---------------- | --------------------- | ---------------- | ---------- | ------------- | ------------------ |
+| Claude | claude | API Key / OAuth | ✅ | ✅ | ✅ | ⚠️ Admin only |
+| Gemini | gemini | API Key / OAuth | ✅ | ✅ | ✅ | ⚠️ Cloud Console |
+| Gemini CLI | gemini-cli | OAuth | ✅ | ✅ | ✅ | ⚠️ Cloud Console |
+| Antigravity | antigravity | OAuth | ✅ | ✅ | ✅ | ✅ Full quota API |
+| OpenAI | openai | API Key | ✅ | ✅ | ❌ | ❌ |
+| Codex | openai-responses | OAuth | ✅ forced | ❌ | ✅ | ✅ Rate limits |
+| GitHub Copilot | openai | OAuth + Copilot Token | ✅ | ✅ | ✅ | ✅ Quota snapshots |
+| Cursor | cursor | Custom checksum | ✅ | ✅ | ❌ | ❌ |
+| Kiro | kiro | AWS SSO OIDC | ✅ (EventStream) | ❌ | ✅ | ✅ Usage limits |
+| Qwen | openai | OAuth | ✅ | ✅ | ✅ | ⚠️ Per request |
+| Qoder | openai | OAuth (Basic) | ✅ | ✅ | ✅ | ⚠️ Per request |
+| OpenRouter | openai | API Key | ✅ | ✅ | ❌ | ❌ |
+| GLM/Kimi/MiniMax | claude | API Key | ✅ | ✅ | ❌ | ❌ |
+| DeepSeek | openai | API Key | ✅ | ✅ | ❌ | ❌ |
+| Groq | openai | API Key | ✅ | ✅ | ❌ | ❌ |
+| xAI (Grok) | openai | API Key | ✅ | ✅ | ❌ | ❌ |
+| Mistral | openai | API Key | ✅ | ✅ | ❌ | ❌ |
+| Perplexity | openai | API Key | ✅ | ✅ | ❌ | ❌ |
+| Together AI | openai | API Key | ✅ | ✅ | ❌ | ❌ |
+| Fireworks AI | openai | API Key | ✅ | ✅ | ❌ | ❌ |
+| Cerebras | openai | API Key | ✅ | ✅ | ❌ | ❌ |
+| Cohere | openai | API Key | ✅ | ✅ | ❌ | ❌ |
+| NVIDIA NIM | openai | API Key | ✅ | ✅ | ❌ | ❌ |
+
+## Format Translation Coverage
+
+Detected source formats include:
+
+- `openai`
+- `openai-responses`
+- `claude`
+- `gemini`
+
+Target formats include:
+
+- OpenAI chat/Responses
+- Claude
+- Gemini/Gemini-CLI/Antigravity envelope
+- Kiro
+- Cursor
+
+Translations use **OpenAI as the hub format** — all conversions go through OpenAI as intermediate:
+
+```
+Source Format → OpenAI (hub) → Target Format
+```
+
+Translations are selected dynamically based on source payload shape and provider target format.
+
+Additional processing layers in the translation pipeline:
+
+- **Response sanitization** — Strips non-standard fields from OpenAI-format responses (both streaming and non-streaming) to ensure strict SDK compliance
+- **Role normalization** — Converts `developer` → `system` for non-OpenAI targets; merges `system` → `user` for models that reject the system role (GLM, ERNIE)
+- **Think tag extraction** — Parses `...` blocks from content into `reasoning_content` field
+- **Structured output** — Converts OpenAI `response_format.json_schema` to Gemini's `responseMimeType` + `responseSchema`
+
+## Supported API Endpoints
+
+| Endpoint | Format | Handler |
+| -------------------------------------------------- | ------------------ | ------------------------------------------------------------------- |
+| `POST /v1/chat/completions` | OpenAI Chat | `src/sse/handlers/chat.ts` |
+| `POST /v1/messages` | Claude Messages | Same handler (auto-detected) |
+| `POST /v1/responses` | OpenAI Responses | `open-sse/handlers/responsesHandler.ts` |
+| `POST /v1/embeddings` | OpenAI Embeddings | `open-sse/handlers/embeddings.ts` |
+| `GET /v1/embeddings` | Model listing | API route |
+| `POST /v1/images/generations` | OpenAI Images | `open-sse/handlers/imageGeneration.ts` |
+| `GET /v1/images/generations` | Model listing | API route |
+| `POST /v1/providers/{provider}/chat/completions` | OpenAI Chat | Dedicated per-provider with model validation |
+| `POST /v1/providers/{provider}/embeddings` | OpenAI Embeddings | Dedicated per-provider with model validation |
+| `POST /v1/providers/{provider}/images/generations` | OpenAI Images | Dedicated per-provider with model validation |
+| `POST /v1/messages/count_tokens` | Claude Token Count | API route |
+| `GET /v1/models` | OpenAI Models list | API route (chat + embedding + image + custom models) |
+| `GET /api/models/catalog` | Catalog | All models grouped by provider + type |
+| `POST /v1beta/models/*:streamGenerateContent` | Gemini native | API route |
+| `GET/PUT/DELETE /api/settings/proxy` | Proxy Config | Network proxy configuration |
+| `POST /api/settings/proxy/test` | Proxy Connectivity | Proxy health/connectivity test endpoint |
+| `GET/POST/DELETE /api/provider-models` | Provider Models | Provider model metadata backing custom and managed available models |
+
+## Bypass Handler
+
+The bypass handler (`open-sse/utils/bypassHandler.ts`) intercepts known "throwaway" requests from Claude CLI — warmup pings, title extractions, and token counts — and returns a **fake response** without consuming upstream provider tokens. This is triggered only when `User-Agent` contains `claude-cli`.
+
+## Request Logger Pipeline
+
+The request logger (`open-sse/utils/requestLogger.ts`) provides a 7-stage debug logging pipeline, disabled by default, enabled via `ENABLE_REQUEST_LOGS=true`:
+
+```
+1_req_client.json → 2_req_source.json → 3_req_openai.json → 4_req_target.json
+→ 5_res_provider.txt → 6_res_openai.txt → 7_res_client.txt
+```
+
+Files are written to `/logs//` for each request session.
+
+## Failure Modes and Resilience
+
+## 1) Account/Provider Availability
+
+- provider account cooldown on transient/rate/auth errors
+- account fallback before failing request
+- combo model fallback when current model/provider path is exhausted
+
+## 2) Token Expiry
+
+- pre-check and refresh with retry for refreshable providers
+- 401/403 retry after refresh attempt in core path
+
+## 3) Stream Safety
+
+- disconnect-aware stream controller
+- translation stream with end-of-stream flush and `[DONE]` handling
+- usage estimation fallback when provider usage metadata is missing
+
+## 4) Cloud Sync Degradation
+
+- sync errors are surfaced but local runtime continues
+- scheduler has retry-capable logic, but periodic execution currently calls single-attempt sync by default
+
+## 5) Data Integrity
+
+- SQLite schema migrations and auto-upgrade hooks at startup
+- legacy JSON → SQLite migration compatibility path
+
+## Observability and Operational Signals
+
+Runtime visibility sources:
+
+- console logs from `src/sse/utils/logger.ts`
+- per-request usage aggregates in SQLite (`usage_history`, `call_logs`, `proxy_logs`)
+- four-stage detailed payload captures in SQLite (`request_detail_logs`) when `settings.detailed_logs_enabled=true`
+- textual request status log in `log.txt` (optional/compat)
+- optional deep request/translation logs under `logs/` when `ENABLE_REQUEST_LOGS=true`
+- dashboard usage endpoints (`/api/usage/*`) for UI consumption
+
+Detailed request payload capture stores up to four JSON payload stages per routed call:
+
+- raw request received from the client
+- translated request actually sent upstream
+- provider response reconstructed as JSON; streamed responses are compacted to the final summary plus stream metadata
+- final client response returned by OmniRoute; streamed responses are stored in the same compact summary form
+
+## Security-Sensitive Boundaries
+
+- JWT secret (`JWT_SECRET`) secures dashboard session cookie verification/signing
+- Initial password bootstrap (`INITIAL_PASSWORD`) should be explicitly configured for first-run provisioning
+- API key HMAC secret (`API_KEY_SECRET`) secures generated local API key format
+- Provider secrets (API keys/tokens) are persisted in local DB and should be protected at filesystem level
+- Cloud sync endpoints rely on API key auth + machine id semantics
+
+## Environment and Runtime Matrix
+
+Environment variables actively used by code:
+
+- App/auth: `JWT_SECRET`, `INITIAL_PASSWORD`
+- Storage: `DATA_DIR`
+- Compatible node behavior: `ALLOW_MULTI_CONNECTIONS_PER_COMPAT_NODE`
+- Optional storage base override (Linux/macOS when `DATA_DIR` unset): `XDG_CONFIG_HOME`
+- Security hashing: `API_KEY_SECRET`, `MACHINE_ID_SALT`
+- Logging: `ENABLE_REQUEST_LOGS`
+- Sync/cloud URLing: `NEXT_PUBLIC_BASE_URL`, `NEXT_PUBLIC_CLOUD_URL`
+- Outbound proxy: `HTTP_PROXY`, `HTTPS_PROXY`, `ALL_PROXY`, `NO_PROXY` and lowercase variants
+- SOCKS5 feature flags: `ENABLE_SOCKS5_PROXY`, `NEXT_PUBLIC_ENABLE_SOCKS5_PROXY`
+- Platform/runtime helpers (not app-specific config): `APPDATA`, `NODE_ENV`, `PORT`, `HOSTNAME`
+
+## Known Architectural Notes
+
+1. `usageDb` and `localDb` share the same base directory policy (`DATA_DIR` -> `XDG_CONFIG_HOME/omniroute` -> `~/.omniroute`) with legacy file migration.
+2. `/api/v1/route.ts` delegates to the same unified catalog builder used by `/api/v1/models` (`src/app/api/v1/models/catalog.ts`) to avoid semantic drift.
+3. Request logger writes full headers/body when enabled; treat log directory as sensitive.
+4. Cloud behavior depends on correct `NEXT_PUBLIC_BASE_URL` and cloud endpoint reachability.
+5. The `open-sse/` directory is published as the `@omniroute/open-sse` **npm workspace package**. Source code imports it via `@omniroute/open-sse/...` (resolved by Next.js `transpilePackages`). File paths in this document still use the directory name `open-sse/` for consistency.
+6. Charts in the dashboard use **Recharts** (SVG-based) for accessible, interactive analytics visualizations (model usage bar charts, provider breakdown tables with success rates).
+7. E2E tests use **Playwright** (`tests/e2e/`), run via `npm run test:e2e`. Unit tests use **Node.js test runner** (`tests/unit/`), run via `npm run test:unit`. Source code under `src/` is **TypeScript** (`.ts`/`.tsx`); the `open-sse/` workspace remains JavaScript (`.js`).
+8. Settings page is organized into 5 tabs: Security, Routing (6 global strategies: fill-first, round-robin, p2c, random, least-used, cost-optimized), Resilience (editable rate limits, circuit breaker, policies), AI (thinking budget, system prompt, prompt cache), Advanced (proxy).
+
+## Operational Verification Checklist
+
+- Build from source: `npm run build`
+- Build Docker image: `docker build -t omniroute .`
+- Start service and verify:
+- `GET /api/settings`
+- `GET /api/v1/models`
+- CLI target base URL should be `http://:20128/v1` when `PORT=20128`
diff --git a/docs/i18n/ar/docs/AUTO-COMBO.md b/docs/i18n/ar/docs/AUTO-COMBO.md
new file mode 100644
index 0000000000..27191bc97e
--- /dev/null
+++ b/docs/i18n/ar/docs/AUTO-COMBO.md
@@ -0,0 +1,67 @@
+# OmniRoute Auto-Combo Engine (العربية)
+
+🌐 **Languages:** 🇺🇸 [English](../../../../docs/AUTO-COMBO.md) · 🇪🇸 [es](../../es/docs/AUTO-COMBO.md) · 🇫🇷 [fr](../../fr/docs/AUTO-COMBO.md) · 🇩🇪 [de](../../de/docs/AUTO-COMBO.md) · 🇮🇹 [it](../../it/docs/AUTO-COMBO.md) · 🇷🇺 [ru](../../ru/docs/AUTO-COMBO.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/AUTO-COMBO.md) · 🇯🇵 [ja](../../ja/docs/AUTO-COMBO.md) · 🇰🇷 [ko](../../ko/docs/AUTO-COMBO.md) · 🇸🇦 [ar](../../ar/docs/AUTO-COMBO.md) · 🇮🇳 [in](../../in/docs/AUTO-COMBO.md) · 🇹🇭 [th](../../th/docs/AUTO-COMBO.md) · 🇻🇳 [vi](../../vi/docs/AUTO-COMBO.md) · 🇮🇩 [id](../../id/docs/AUTO-COMBO.md) · 🇲🇾 [ms](../../ms/docs/AUTO-COMBO.md) · 🇳🇱 [nl](../../nl/docs/AUTO-COMBO.md) · 🇵🇱 [pl](../../pl/docs/AUTO-COMBO.md) · 🇸🇪 [sv](../../sv/docs/AUTO-COMBO.md) · 🇳🇴 [no](../../no/docs/AUTO-COMBO.md) · 🇩🇰 [da](../../da/docs/AUTO-COMBO.md) · 🇫🇮 [fi](../../fi/docs/AUTO-COMBO.md) · 🇵🇹 [pt](../../pt/docs/AUTO-COMBO.md) · 🇷🇴 [ro](../../ro/docs/AUTO-COMBO.md) · 🇭🇺 [hu](../../hu/docs/AUTO-COMBO.md) · 🇧🇬 [bg](../../bg/docs/AUTO-COMBO.md) · 🇸🇰 [sk](../../sk/docs/AUTO-COMBO.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/AUTO-COMBO.md) · 🇮🇱 [he](../../he/docs/AUTO-COMBO.md) · 🇵🇭 [phi](../../phi/docs/AUTO-COMBO.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/AUTO-COMBO.md) · 🇨🇿 [cs](../../cs/docs/AUTO-COMBO.md)
+
+---
+
+> Self-managing model chains with adaptive scoring
+
+## How It Works
+
+The Auto-Combo Engine dynamically selects the best provider/model for each request using a **6-factor scoring function**:
+
+| Factor | Weight | Description |
+| :--------- | :----- | :---------------------------------------------- |
+| Quota | 0.20 | Remaining capacity [0..1] |
+| Health | 0.25 | Circuit breaker: CLOSED=1.0, HALF=0.5, OPEN=0.0 |
+| CostInv | 0.20 | Inverse cost (cheaper = higher score) |
+| LatencyInv | 0.15 | Inverse p95 latency (faster = higher) |
+| TaskFit | 0.10 | Model × task type fitness score |
+| Stability | 0.10 | Low variance in latency/errors |
+
+## Mode Packs
+
+| Pack | Focus | Key Weight |
+| :---------------------- | :----------- | :--------------- |
+| 🚀 **Ship Fast** | Speed | latencyInv: 0.35 |
+| 💰 **Cost Saver** | Economy | costInv: 0.40 |
+| 🎯 **Quality First** | Best model | taskFit: 0.40 |
+| 📡 **Offline Friendly** | Availability | quota: 0.40 |
+
+## Self-Healing
+
+- **Temporary exclusion**: Score < 0.2 → excluded for 5 min (progressive backoff, max 30 min)
+- **Circuit breaker awareness**: OPEN → auto-excluded; HALF_OPEN → probe requests
+- **Incident mode**: >50% OPEN → disable exploration, maximize stability
+- **Cooldown recovery**: After exclusion, first request is a "probe" with reduced timeout
+
+## Bandit Exploration
+
+5% of requests (configurable) are routed to random providers for exploration. Disabled in incident mode.
+
+## API
+
+```bash
+# Create auto-combo
+curl -X POST http://localhost:20128/api/combos/auto \
+ -H "Content-Type: application/json" \
+ -d '{"id":"my-auto","name":"Auto Coder","candidatePool":["anthropic","google","openai"],"modePack":"ship-fast"}'
+
+# List auto-combos
+curl http://localhost:20128/api/combos/auto
+```
+
+## Task Fitness
+
+30+ models scored across 6 task types (`coding`, `review`, `planning`, `analysis`, `debugging`, `documentation`). Supports wildcard patterns (e.g., `*-coder` → high coding score).
+
+## Files
+
+| File | Purpose |
+| :------------------------------------------- | :------------------------------------ |
+| `open-sse/services/autoCombo/scoring.ts` | Scoring function & pool normalization |
+| `open-sse/services/autoCombo/taskFitness.ts` | Model × task fitness lookup |
+| `open-sse/services/autoCombo/engine.ts` | Selection logic, bandit, budget cap |
+| `open-sse/services/autoCombo/selfHealing.ts` | Exclusion, probes, incident mode |
+| `open-sse/services/autoCombo/modePacks.ts` | 4 weight profiles |
+| `src/app/api/combos/auto/route.ts` | REST API |
diff --git a/docs/i18n/ar/docs/CLI-TOOLS.md b/docs/i18n/ar/docs/CLI-TOOLS.md
new file mode 100644
index 0000000000..1e01011145
--- /dev/null
+++ b/docs/i18n/ar/docs/CLI-TOOLS.md
@@ -0,0 +1,348 @@
+# CLI Tools Setup Guide — OmniRoute (العربية)
+
+🌐 **Languages:** 🇺🇸 [English](../../../../docs/CLI-TOOLS.md) · 🇪🇸 [es](../../es/docs/CLI-TOOLS.md) · 🇫🇷 [fr](../../fr/docs/CLI-TOOLS.md) · 🇩🇪 [de](../../de/docs/CLI-TOOLS.md) · 🇮🇹 [it](../../it/docs/CLI-TOOLS.md) · 🇷🇺 [ru](../../ru/docs/CLI-TOOLS.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/CLI-TOOLS.md) · 🇯🇵 [ja](../../ja/docs/CLI-TOOLS.md) · 🇰🇷 [ko](../../ko/docs/CLI-TOOLS.md) · 🇸🇦 [ar](../../ar/docs/CLI-TOOLS.md) · 🇮🇳 [in](../../in/docs/CLI-TOOLS.md) · 🇹🇭 [th](../../th/docs/CLI-TOOLS.md) · 🇻🇳 [vi](../../vi/docs/CLI-TOOLS.md) · 🇮🇩 [id](../../id/docs/CLI-TOOLS.md) · 🇲🇾 [ms](../../ms/docs/CLI-TOOLS.md) · 🇳🇱 [nl](../../nl/docs/CLI-TOOLS.md) · 🇵🇱 [pl](../../pl/docs/CLI-TOOLS.md) · 🇸🇪 [sv](../../sv/docs/CLI-TOOLS.md) · 🇳🇴 [no](../../no/docs/CLI-TOOLS.md) · 🇩🇰 [da](../../da/docs/CLI-TOOLS.md) · 🇫🇮 [fi](../../fi/docs/CLI-TOOLS.md) · 🇵🇹 [pt](../../pt/docs/CLI-TOOLS.md) · 🇷🇴 [ro](../../ro/docs/CLI-TOOLS.md) · 🇭🇺 [hu](../../hu/docs/CLI-TOOLS.md) · 🇧🇬 [bg](../../bg/docs/CLI-TOOLS.md) · 🇸🇰 [sk](../../sk/docs/CLI-TOOLS.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/CLI-TOOLS.md) · 🇮🇱 [he](../../he/docs/CLI-TOOLS.md) · 🇵🇭 [phi](../../phi/docs/CLI-TOOLS.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/CLI-TOOLS.md) · 🇨🇿 [cs](../../cs/docs/CLI-TOOLS.md)
+
+---
+
+This guide explains how to install and configure all supported AI coding CLI tools
+to use **OmniRoute** as the unified backend, giving you centralized key management,
+cost tracking, model switching, and request logging across every tool.
+
+---
+
+## How It Works
+
+```
+Claude / Codex / OpenCode / Cline / KiloCode / Continue / Kiro / Cursor / Copilot
+ │
+ ▼ (all point to OmniRoute)
+ http://YOUR_SERVER:20128/v1
+ │
+ ▼ (OmniRoute routes to the right provider)
+ Anthropic / OpenAI / Gemini / DeepSeek / Groq / Mistral / ...
+```
+
+**Benefits:**
+
+- One API key to manage all tools
+- Cost tracking across all CLIs in the dashboard
+- Model switching without reconfiguring every tool
+- Works locally and on remote servers (VPS)
+
+---
+
+## Supported Tools (Dashboard Source of Truth)
+
+The dashboard cards in `/dashboard/cli-tools` are generated from `src/shared/constants/cliTools.ts`.
+Current list (v3.0.0-rc.16):
+
+| Tool | ID | Command | Setup Mode | Install Method |
+| ------------------ | ------------- | ---------- | ---------- | -------------- |
+| **Claude Code** | `claude` | `claude` | env | npm |
+| **OpenAI Codex** | `codex` | `codex` | custom | npm |
+| **Factory Droid** | `droid` | `droid` | custom | bundled/CLI |
+| **OpenClaw** | `openclaw` | `openclaw` | custom | bundled/CLI |
+| **Cursor** | `cursor` | app | guide | desktop app |
+| **Cline** | `cline` | `cline` | custom | npm |
+| **Kilo Code** | `kilo` | `kilocode` | custom | npm |
+| **Continue** | `continue` | extension | guide | VS Code |
+| **Antigravity** | `antigravity` | internal | mitm | OmniRoute |
+| **GitHub Copilot** | `copilot` | extension | custom | VS Code |
+| **OpenCode** | `opencode` | `opencode` | guide | npm |
+| **Kiro AI** | `kiro` | app/cli | mitm | desktop/CLI |
+
+### CLI fingerprint sync (Agents + Settings)
+
+`/dashboard/agents` and `Settings > CLI Fingerprint` use `src/shared/constants/cliCompatProviders.ts`.
+This keeps provider IDs aligned with CLI cards and legacy IDs.
+
+| CLI ID | Fingerprint Provider ID |
+| ---------------------------------------------------------------------------------------------------- | ----------------------- |
+| `kilo` | `kilocode` |
+| `copilot` | `github` |
+| `claude` / `codex` / `antigravity` / `kiro` / `cursor` / `cline` / `opencode` / `droid` / `openclaw` | same ID |
+
+Legacy IDs still accepted for compatibility: `copilot`, `kimi-coding`, `qwen`.
+
+---
+
+## Step 1 — Get an OmniRoute API Key
+
+1. Open the OmniRoute dashboard → **API Manager** (`/dashboard/api-manager`)
+2. Click **Create API Key**
+3. Give it a name (e.g. `cli-tools`) and select all permissions
+4. Copy the key — you'll need it for every CLI below
+
+> Your key looks like: `sk-xxxxxxxxxxxxxxxx-xxxxxxxxx`
+
+---
+
+## Step 2 — Install CLI Tools
+
+All npm-based tools require Node.js 18+:
+
+```bash
+# Claude Code (Anthropic)
+npm install -g @anthropic-ai/claude-code
+
+# OpenAI Codex
+npm install -g @openai/codex
+
+# OpenCode
+npm install -g opencode-ai
+
+# Cline
+npm install -g cline
+
+# KiloCode
+npm install -g kilocode
+
+# Kiro CLI (Amazon — requires curl + unzip)
+apt-get install -y unzip # on Debian/Ubuntu
+curl -fsSL https://cli.kiro.dev/install | bash
+export PATH="$HOME/.local/bin:$PATH" # add to ~/.bashrc
+```
+
+**Verify:**
+
+```bash
+claude --version # 2.x.x
+codex --version # 0.x.x
+opencode --version # x.x.x
+cline --version # 2.x.x
+kilocode --version # x.x.x (or: kilo --version)
+kiro-cli --version # 1.x.x
+```
+
+---
+
+## Step 3 — Set Global Environment Variables
+
+Add to `~/.bashrc` (or `~/.zshrc`), then run `source ~/.bashrc`:
+
+```bash
+# OmniRoute Universal Endpoint
+export OPENAI_BASE_URL="http://localhost:20128/v1"
+export OPENAI_API_KEY="sk-your-omniroute-key"
+export ANTHROPIC_BASE_URL="http://localhost:20128/v1"
+export ANTHROPIC_API_KEY="sk-your-omniroute-key"
+export GEMINI_BASE_URL="http://localhost:20128/v1"
+export GEMINI_API_KEY="sk-your-omniroute-key"
+```
+
+> For a **remote server** replace `localhost:20128` with the server IP or domain,
+> e.g. `http://192.168.0.15:20128`.
+
+---
+
+## Step 4 — Configure Each Tool
+
+### Claude Code
+
+```bash
+# Via CLI:
+claude config set --global api-base-url http://localhost:20128/v1
+
+# Or create ~/.claude/settings.json:
+mkdir -p ~/.claude && cat > ~/.claude/settings.json << EOF
+{
+ "apiBaseUrl": "http://localhost:20128/v1",
+ "apiKey": "sk-your-omniroute-key"
+}
+EOF
+```
+
+**Test:** `claude "say hello"`
+
+---
+
+### OpenAI Codex
+
+```bash
+mkdir -p ~/.codex && cat > ~/.codex/config.yaml << EOF
+model: auto
+apiKey: sk-your-omniroute-key
+apiBaseUrl: http://localhost:20128/v1
+EOF
+```
+
+**Test:** `codex "what is 2+2?"`
+
+---
+
+### OpenCode
+
+```bash
+mkdir -p ~/.config/opencode && cat > ~/.config/opencode/config.toml << EOF
+[provider.openai]
+base_url = "http://localhost:20128/v1"
+api_key = "sk-your-omniroute-key"
+EOF
+```
+
+**Test:** `opencode`
+
+---
+
+### Cline (CLI or VS Code)
+
+**CLI mode:**
+
+```bash
+mkdir -p ~/.cline/data && cat > ~/.cline/data/globalState.json << EOF
+{
+ "apiProvider": "openai",
+ "openAiBaseUrl": "http://localhost:20128/v1",
+ "openAiApiKey": "sk-your-omniroute-key"
+}
+EOF
+```
+
+**VS Code mode:**
+Cline extension settings → API Provider: `OpenAI Compatible` → Base URL: `http://localhost:20128/v1`
+
+Or use the OmniRoute dashboard → **CLI Tools → Cline → Apply Config**.
+
+---
+
+### KiloCode (CLI or VS Code)
+
+**CLI mode:**
+
+```bash
+kilocode --api-base http://localhost:20128/v1 --api-key sk-your-omniroute-key
+```
+
+**VS Code settings:**
+
+```json
+{
+ "kilo-code.openAiBaseUrl": "http://localhost:20128/v1",
+ "kilo-code.apiKey": "sk-your-omniroute-key"
+}
+```
+
+Or use the OmniRoute dashboard → **CLI Tools → KiloCode → Apply Config**.
+
+---
+
+### Continue (VS Code Extension)
+
+Edit `~/.continue/config.yaml`:
+
+```yaml
+models:
+ - name: OmniRoute
+ provider: openai
+ model: auto
+ apiBase: http://localhost:20128/v1
+ apiKey: sk-your-omniroute-key
+ default: true
+```
+
+Restart VS Code after editing.
+
+---
+
+### Kiro CLI (Amazon)
+
+```bash
+# Login to your AWS/Kiro account:
+kiro-cli login
+
+# The CLI uses its own auth — OmniRoute is not needed as backend for Kiro CLI itself.
+# Use kiro-cli alongside OmniRoute for other tools.
+kiro-cli status
+```
+
+---
+
+### Cursor (Desktop App)
+
+> **Note:** Cursor routes requests through its cloud. For OmniRoute integration,
+> enable **Cloud Endpoint** in OmniRoute Settings and use your public domain URL.
+
+Via GUI: **Settings → Models → OpenAI API Key**
+
+- Base URL: `https://your-domain.com/v1`
+- API Key: your OmniRoute key
+
+---
+
+## Dashboard Auto-Configuration
+
+The OmniRoute dashboard automates configuration for most tools:
+
+1. Go to `http://localhost:20128/dashboard/cli-tools`
+2. Expand any tool card
+3. Select your API key from the dropdown
+4. Click **Apply Config** (if tool is detected as installed)
+5. Or copy the generated config snippet manually
+
+---
+
+## Built-in Agents: Droid & OpenClaw
+
+**Droid** and **OpenClaw** are AI agents built directly into OmniRoute — no installation needed.
+They run as internal routes and use OmniRoute's model routing automatically.
+
+- Access: `http://localhost:20128/dashboard/agents`
+- Configure: same combos and providers as all other tools
+- No API key or CLI install required
+
+---
+
+## Available API Endpoints
+
+| Endpoint | Description | Use For |
+| -------------------------- | ----------------------------- | --------------------------- |
+| `/v1/chat/completions` | Standard chat (all providers) | All modern tools |
+| `/v1/responses` | Responses API (OpenAI format) | Codex, agentic workflows |
+| `/v1/completions` | Legacy text completions | Older tools using `prompt:` |
+| `/v1/embeddings` | Text embeddings | RAG, search |
+| `/v1/images/generations` | Image generation | DALL-E, Flux, etc. |
+| `/v1/audio/speech` | Text-to-speech | ElevenLabs, OpenAI TTS |
+| `/v1/audio/transcriptions` | Speech-to-text | Deepgram, AssemblyAI |
+
+---
+
+## استكشاف الأخطاء
+
+| Error | Cause | Fix |
+| ------------------------- | ----------------------- | ------------------------------------------ |
+| `Connection refused` | OmniRoute not running | `pm2 start omniroute` |
+| `401 Unauthorized` | Wrong API key | Check in `/dashboard/api-manager` |
+| `No combo configured` | No active routing combo | Set up in `/dashboard/combos` |
+| `invalid model` | Model not in catalog | Use `auto` or check `/dashboard/providers` |
+| CLI shows "not installed" | Binary not in PATH | Check `which ` |
+| `kiro-cli: not found` | Not in PATH | `export PATH="$HOME/.local/bin:$PATH"` |
+
+---
+
+## Quick Setup Script (One Command)
+
+```bash
+# Install all CLIs and configure for OmniRoute (replace with your key and server URL)
+OMNIROUTE_URL="http://localhost:20128/v1"
+OMNIROUTE_KEY="sk-your-omniroute-key"
+
+npm install -g @anthropic-ai/claude-code @openai/codex opencode-ai cline kilocode
+
+# Kiro CLI
+apt-get install -y unzip 2>/dev/null; curl -fsSL https://cli.kiro.dev/install | bash
+
+# Write configs
+mkdir -p ~/.claude ~/.codex ~/.config/opencode ~/.continue
+
+cat > ~/.claude/settings.json <<< "{\"apiBaseUrl\":\"$OMNIROUTE_URL\",\"apiKey\":\"$OMNIROUTE_KEY\"}"
+cat > ~/.codex/config.yaml <<< "model: auto\napiKey: $OMNIROUTE_KEY\napiBaseUrl: $OMNIROUTE_URL"
+cat >> ~/.bashrc << EOF
+export OPENAI_BASE_URL="$OMNIROUTE_URL"
+export OPENAI_API_KEY="$OMNIROUTE_KEY"
+export ANTHROPIC_BASE_URL="$OMNIROUTE_URL"
+export ANTHROPIC_API_KEY="$OMNIROUTE_KEY"
+EOF
+
+source ~/.bashrc
+echo "✅ All CLIs installed and configured for OmniRoute"
+```
diff --git a/docs/i18n/ar/CODEBASE_DOCUMENTATION.md b/docs/i18n/ar/docs/CODEBASE_DOCUMENTATION.md
similarity index 91%
rename from docs/i18n/ar/CODEBASE_DOCUMENTATION.md
rename to docs/i18n/ar/docs/CODEBASE_DOCUMENTATION.md
index e2d7950052..a97476043b 100644
--- a/docs/i18n/ar/CODEBASE_DOCUMENTATION.md
+++ b/docs/i18n/ar/docs/CODEBASE_DOCUMENTATION.md
@@ -1,11 +1,9 @@
-🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/CODEBASE_DOCUMENTATION.md) · 🇪🇸 [es](../es/CODEBASE_DOCUMENTATION.md) · 🇫🇷 [fr](../fr/CODEBASE_DOCUMENTATION.md) · 🇩🇪 [de](../de/CODEBASE_DOCUMENTATION.md) · 🇮🇹 [it](../it/CODEBASE_DOCUMENTATION.md) · 🇷🇺 [ru](../ru/CODEBASE_DOCUMENTATION.md) · 🇨🇳 [zh-CN](../zh-CN/CODEBASE_DOCUMENTATION.md) · 🇯🇵 [ja](../ja/CODEBASE_DOCUMENTATION.md) · 🇰🇷 [ko](../ko/CODEBASE_DOCUMENTATION.md) · 🇸🇦 [ar](../ar/CODEBASE_DOCUMENTATION.md) · 🇮🇳 [in](../in/CODEBASE_DOCUMENTATION.md) · 🇹🇭 [th](../th/CODEBASE_DOCUMENTATION.md) · 🇻🇳 [vi](../vi/CODEBASE_DOCUMENTATION.md) · 🇮🇩 [id](../id/CODEBASE_DOCUMENTATION.md) · 🇲🇾 [ms](../ms/CODEBASE_DOCUMENTATION.md) · 🇳🇱 [nl](../nl/CODEBASE_DOCUMENTATION.md) · 🇵🇱 [pl](../pl/CODEBASE_DOCUMENTATION.md) · 🇸🇪 [sv](../sv/CODEBASE_DOCUMENTATION.md) · 🇳🇴 [no](../no/CODEBASE_DOCUMENTATION.md) · 🇩🇰 [da](../da/CODEBASE_DOCUMENTATION.md) · 🇫🇮 [fi](../fi/CODEBASE_DOCUMENTATION.md) · 🇵🇹 [pt](../pt/CODEBASE_DOCUMENTATION.md) · 🇷🇴 [ro](../ro/CODEBASE_DOCUMENTATION.md) · 🇭🇺 [hu](../hu/CODEBASE_DOCUMENTATION.md) · 🇧🇬 [bg](../bg/CODEBASE_DOCUMENTATION.md) · 🇸🇰 [sk](../sk/CODEBASE_DOCUMENTATION.md) · 🇺🇦 [uk-UA](../uk-UA/CODEBASE_DOCUMENTATION.md) · 🇮🇱 [he](../he/CODEBASE_DOCUMENTATION.md) · 🇵🇭 [phi](../phi/CODEBASE_DOCUMENTATION.md)
+# omniroute — Codebase Documentation (العربية)
+
+🌐 **Languages:** 🇺🇸 [English](../../../../docs/CODEBASE_DOCUMENTATION.md) · 🇪🇸 [es](../../es/docs/CODEBASE_DOCUMENTATION.md) · 🇫🇷 [fr](../../fr/docs/CODEBASE_DOCUMENTATION.md) · 🇩🇪 [de](../../de/docs/CODEBASE_DOCUMENTATION.md) · 🇮🇹 [it](../../it/docs/CODEBASE_DOCUMENTATION.md) · 🇷🇺 [ru](../../ru/docs/CODEBASE_DOCUMENTATION.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/CODEBASE_DOCUMENTATION.md) · 🇯🇵 [ja](../../ja/docs/CODEBASE_DOCUMENTATION.md) · 🇰🇷 [ko](../../ko/docs/CODEBASE_DOCUMENTATION.md) · 🇸🇦 [ar](../../ar/docs/CODEBASE_DOCUMENTATION.md) · 🇮🇳 [in](../../in/docs/CODEBASE_DOCUMENTATION.md) · 🇹🇭 [th](../../th/docs/CODEBASE_DOCUMENTATION.md) · 🇻🇳 [vi](../../vi/docs/CODEBASE_DOCUMENTATION.md) · 🇮🇩 [id](../../id/docs/CODEBASE_DOCUMENTATION.md) · 🇲🇾 [ms](../../ms/docs/CODEBASE_DOCUMENTATION.md) · 🇳🇱 [nl](../../nl/docs/CODEBASE_DOCUMENTATION.md) · 🇵🇱 [pl](../../pl/docs/CODEBASE_DOCUMENTATION.md) · 🇸🇪 [sv](../../sv/docs/CODEBASE_DOCUMENTATION.md) · 🇳🇴 [no](../../no/docs/CODEBASE_DOCUMENTATION.md) · 🇩🇰 [da](../../da/docs/CODEBASE_DOCUMENTATION.md) · 🇫🇮 [fi](../../fi/docs/CODEBASE_DOCUMENTATION.md) · 🇵🇹 [pt](../../pt/docs/CODEBASE_DOCUMENTATION.md) · 🇷🇴 [ro](../../ro/docs/CODEBASE_DOCUMENTATION.md) · 🇭🇺 [hu](../../hu/docs/CODEBASE_DOCUMENTATION.md) · 🇧🇬 [bg](../../bg/docs/CODEBASE_DOCUMENTATION.md) · 🇸🇰 [sk](../../sk/docs/CODEBASE_DOCUMENTATION.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/CODEBASE_DOCUMENTATION.md) · 🇮🇱 [he](../../he/docs/CODEBASE_DOCUMENTATION.md) · 🇵🇭 [phi](../../phi/docs/CODEBASE_DOCUMENTATION.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/CODEBASE_DOCUMENTATION.md) · 🇨🇿 [cs](../../cs/docs/CODEBASE_DOCUMENTATION.md)
---
-# omniroute — Codebase Documentation
-
-🌐 **Languages:** 🇺🇸 [English](CODEBASE_DOCUMENTATION.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/CODEBASE_DOCUMENTATION.md) | 🇪🇸 [Español](i18n/es/CODEBASE_DOCUMENTATION.md) | 🇫🇷 [Français](i18n/fr/CODEBASE_DOCUMENTATION.md) | 🇮🇹 [Italiano](i18n/it/CODEBASE_DOCUMENTATION.md) | 🇷🇺 [Русский](i18n/ru/CODEBASE_DOCUMENTATION.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/CODEBASE_DOCUMENTATION.md) | 🇩🇪 [Deutsch](i18n/de/CODEBASE_DOCUMENTATION.md) | 🇮🇳 [हिन्दी](i18n/in/CODEBASE_DOCUMENTATION.md) | 🇹🇭 [ไทย](i18n/th/CODEBASE_DOCUMENTATION.md) | 🇺🇦 [Українська](i18n/uk-UA/CODEBASE_DOCUMENTATION.md) | 🇸🇦 [العربية](i18n/ar/CODEBASE_DOCUMENTATION.md) | 🇯🇵 [日本語](i18n/ja/CODEBASE_DOCUMENTATION.md) | 🇻🇳 [Tiếng Việt](i18n/vi/CODEBASE_DOCUMENTATION.md) | 🇧🇬 [Български](i18n/bg/CODEBASE_DOCUMENTATION.md) | 🇩🇰 [Dansk](i18n/da/CODEBASE_DOCUMENTATION.md) | 🇫🇮 [Suomi](i18n/fi/CODEBASE_DOCUMENTATION.md) | 🇮🇱 [עברית](i18n/he/CODEBASE_DOCUMENTATION.md) | 🇭🇺 [Magyar](i18n/hu/CODEBASE_DOCUMENTATION.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/CODEBASE_DOCUMENTATION.md) | 🇰🇷 [한국어](i18n/ko/CODEBASE_DOCUMENTATION.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/CODEBASE_DOCUMENTATION.md) | 🇳🇱 [Nederlands](i18n/nl/CODEBASE_DOCUMENTATION.md) | 🇳🇴 [Norsk](i18n/no/CODEBASE_DOCUMENTATION.md) | 🇵🇹 [Português (Portugal)](i18n/pt/CODEBASE_DOCUMENTATION.md) | 🇷🇴 [Română](i18n/ro/CODEBASE_DOCUMENTATION.md) | 🇵🇱 [Polski](i18n/pl/CODEBASE_DOCUMENTATION.md) | 🇸🇰 [Slovenčina](i18n/sk/CODEBASE_DOCUMENTATION.md) | 🇸🇪 [Svenska](i18n/sv/CODEBASE_DOCUMENTATION.md) | 🇵🇭 [Filipino](i18n/phi/CODEBASE_DOCUMENTATION.md)
-
> A comprehensive, beginner-friendly guide to the **omniroute** multi-provider AI proxy router.
---
@@ -352,7 +350,7 @@ flowchart LR
The **format translation engine** using a self-registering plugin system.
-#### Architecture
+#### الهندسة
```mermaid
graph TD
diff --git a/docs/i18n/ar/docs/COVERAGE_PLAN.md b/docs/i18n/ar/docs/COVERAGE_PLAN.md
new file mode 100644
index 0000000000..d376b93ddd
--- /dev/null
+++ b/docs/i18n/ar/docs/COVERAGE_PLAN.md
@@ -0,0 +1,170 @@
+# Test Coverage Plan (العربية)
+
+🌐 **Languages:** 🇺🇸 [English](../../../../docs/COVERAGE_PLAN.md) · 🇪🇸 [es](../../es/docs/COVERAGE_PLAN.md) · 🇫🇷 [fr](../../fr/docs/COVERAGE_PLAN.md) · 🇩🇪 [de](../../de/docs/COVERAGE_PLAN.md) · 🇮🇹 [it](../../it/docs/COVERAGE_PLAN.md) · 🇷🇺 [ru](../../ru/docs/COVERAGE_PLAN.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/COVERAGE_PLAN.md) · 🇯🇵 [ja](../../ja/docs/COVERAGE_PLAN.md) · 🇰🇷 [ko](../../ko/docs/COVERAGE_PLAN.md) · 🇸🇦 [ar](../../ar/docs/COVERAGE_PLAN.md) · 🇮🇳 [in](../../in/docs/COVERAGE_PLAN.md) · 🇹🇭 [th](../../th/docs/COVERAGE_PLAN.md) · 🇻🇳 [vi](../../vi/docs/COVERAGE_PLAN.md) · 🇮🇩 [id](../../id/docs/COVERAGE_PLAN.md) · 🇲🇾 [ms](../../ms/docs/COVERAGE_PLAN.md) · 🇳🇱 [nl](../../nl/docs/COVERAGE_PLAN.md) · 🇵🇱 [pl](../../pl/docs/COVERAGE_PLAN.md) · 🇸🇪 [sv](../../sv/docs/COVERAGE_PLAN.md) · 🇳🇴 [no](../../no/docs/COVERAGE_PLAN.md) · 🇩🇰 [da](../../da/docs/COVERAGE_PLAN.md) · 🇫🇮 [fi](../../fi/docs/COVERAGE_PLAN.md) · 🇵🇹 [pt](../../pt/docs/COVERAGE_PLAN.md) · 🇷🇴 [ro](../../ro/docs/COVERAGE_PLAN.md) · 🇭🇺 [hu](../../hu/docs/COVERAGE_PLAN.md) · 🇧🇬 [bg](../../bg/docs/COVERAGE_PLAN.md) · 🇸🇰 [sk](../../sk/docs/COVERAGE_PLAN.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/COVERAGE_PLAN.md) · 🇮🇱 [he](../../he/docs/COVERAGE_PLAN.md) · 🇵🇭 [phi](../../phi/docs/COVERAGE_PLAN.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/COVERAGE_PLAN.md) · 🇨🇿 [cs](../../cs/docs/COVERAGE_PLAN.md)
+
+---
+
+Last updated: 2026-03-28
+
+## Baseline
+
+There are multiple coverage numbers depending on how the report is computed. For planning, only one of them is useful.
+
+| Metric | Scope | Statements / Lines | Branches | Functions | Notes |
+| -------------------- | ----------------------------------------------------- | -----------------: | -------: | --------: | --------------------------------------------------- |
+| Legacy | Old `npm run test:coverage` | 79.42% | 75.15% | 67.94% | Inflated: counts test files and excludes `open-sse` |
+| Diagnostic | Source-only, excluding tests and excluding `open-sse` | 68.16% | 63.55% | 64.06% | Useful only to isolate `src/**` |
+| Recommended baseline | Source-only, excluding tests and including `open-sse` | 56.95% | 66.05% | 57.80% | This is the project-wide baseline to improve |
+
+The recommended baseline is the number to optimize against.
+
+## Rules
+
+- Coverage targets apply to source files, not to `tests/**`.
+- `open-sse/**` is part of the product and must remain in scope.
+- New code should not reduce coverage in touched areas.
+- Prefer testing behavior and branch outcomes over implementation details.
+- Prefer temp SQLite databases and small fixtures over broad mocks for `src/lib/db/**`.
+
+## Current command set
+
+- `npm run test:coverage`
+ - Main source coverage gate for the unit test suite
+ - Generates `text-summary`, `html`, `json-summary`, and `lcov`
+- `npm run coverage:report`
+ - Detailed file-by-file report from the latest run
+- `npm run test:coverage:legacy`
+ - Historical comparison only
+
+## Milestones
+
+| Phase | Target | Focus |
+| ------- | ---------------------: | ------------------------------------------------- |
+| Phase 1 | 60% statements / lines | Quick wins and low-risk utility coverage |
+| Phase 2 | 65% statements / lines | DB and route foundations |
+| Phase 3 | 70% statements / lines | Provider validation and usage analytics |
+| Phase 4 | 75% statements / lines | `open-sse` translators and helpers |
+| Phase 5 | 80% statements / lines | `open-sse` handlers and executor branches |
+| Phase 6 | 85% statements / lines | Harder edge cases, branch debt, regression suites |
+| Phase 7 | 90% statements / lines | Final sweep, gap closure, strict ratchet |
+
+Branches and functions should ratchet upward with each phase, but the primary hard target is statements / lines.
+
+## Priority hotspots
+
+These files or areas offer the best return for the next phases:
+
+1. `open-sse/handlers`
+ - `chatCore.ts` at 7.57%
+ - Overall directory at 29.07%
+2. `open-sse/translator/request`
+ - Overall directory at 36.39%
+ - Many translators are still near single-digit coverage
+3. `open-sse/translator/response`
+ - Overall directory at 8.07%
+4. `open-sse/executors`
+ - Overall directory at 36.62%
+5. `src/lib/db`
+ - `models.ts` at 20.66%
+ - `registeredKeys.ts` at 34.46%
+ - `modelComboMappings.ts` at 36.25%
+ - `settings.ts` at 46.40%
+ - `webhooks.ts` at 33.33%
+6. `src/lib/usage`
+ - `usageHistory.ts` at 21.12%
+ - `usageStats.ts` at 9.56%
+ - `costCalculator.ts` at 30.00%
+7. `src/lib/providers`
+ - `validation.ts` at 41.16%
+8. Low-risk utility and API files for early gains
+ - `src/shared/utils/upstreamError.ts`
+ - `src/shared/utils/apiAuth.ts`
+ - `src/lib/api/errorResponse.ts`
+ - `src/app/api/settings/require-login/route.ts`
+ - `src/app/api/providers/[id]/models/route.ts`
+
+## Execution checklist
+
+### Phase 1: 56.95% -> 60%
+
+- [x] Fix coverage metric so it reflects source code instead of test files
+- [x] Keep a legacy coverage script for comparison
+- [x] Record the baseline and hotspots in-repo
+- [ ] Add focused tests for low-risk utilities:
+ - `src/shared/utils/upstreamError.ts`
+ - `src/shared/utils/fetchTimeout.ts`
+ - `src/lib/api/errorResponse.ts`
+ - `src/shared/utils/apiAuth.ts`
+ - `src/lib/display/names.ts`
+- [ ] Add route tests for:
+ - `src/app/api/settings/require-login/route.ts`
+ - `src/app/api/providers/[id]/models/route.ts`
+
+### Phase 2: 60% -> 65%
+
+- [ ] Add DB-backed tests for:
+ - `src/lib/db/modelComboMappings.ts`
+ - `src/lib/db/settings.ts`
+ - `src/lib/db/registeredKeys.ts`
+- [ ] Cover branch behavior in:
+ - `src/lib/providers/validation.ts`
+ - `src/app/api/v1/embeddings/route.ts`
+ - `src/app/api/v1/moderations/route.ts`
+
+### Phase 3: 65% -> 70%
+
+- [ ] Add usage analytics tests for:
+ - `src/lib/usage/usageHistory.ts`
+ - `src/lib/usage/usageStats.ts`
+ - `src/lib/usage/costCalculator.ts`
+- [ ] Expand route coverage for proxy management and settings branches
+
+### Phase 4: 70% -> 75%
+
+- [ ] Cover translator helpers and central translation paths:
+ - `open-sse/translator/index.ts`
+ - `open-sse/translator/helpers/*`
+ - `open-sse/translator/request/*`
+ - `open-sse/translator/response/*`
+
+### Phase 5: 75% -> 80%
+
+- [ ] Add handler-level tests for:
+ - `open-sse/handlers/chatCore.ts`
+ - `open-sse/handlers/responsesHandler.js`
+ - `open-sse/handlers/imageGeneration.js`
+ - `open-sse/handlers/embeddings.js`
+- [ ] Add executor branch coverage for provider-specific auth, retries, and endpoint overrides
+
+### Phase 6: 80% -> 85%
+
+- [ ] Merge more edge-case suites into the main coverage path
+- [ ] Increase function coverage for DB modules with weak constructor/helper coverage
+- [ ] Close branch gaps in `settings.ts`, `registeredKeys.ts`, `validation.ts`, and translator helpers
+
+### Phase 7: 85% -> 90%
+
+- [ ] Treat the remaining low-coverage files as blockers
+- [ ] Add regression tests for every uncovered production bug fixed during the push to 90%
+- [ ] Raise the coverage gate in CI only after the local baseline is stable for at least two consecutive runs
+
+## Ratchet policy
+
+Update `npm run test:coverage` thresholds only after the project actually exceeds the next milestone with a comfortable buffer.
+
+Recommended ratchet sequence:
+
+1. 55/60/55
+2. 60/62/58
+3. 65/64/62
+4. 70/66/66
+5. 75/70/72
+6. 80/75/78
+7. 85/80/84
+8. 90/85/88
+
+Order is `statements-lines / branches / functions`.
+
+## Known gap
+
+The current coverage command measures the main Node unit suite and includes source reached from it, including `open-sse`. It does not yet merge Vitest coverage into a single unified report. That merge is worth doing later, but it is not a blocker for starting the 60% -> 80% climb.
diff --git a/docs/i18n/ar/docs/FEATURES.md b/docs/i18n/ar/docs/FEATURES.md
index bfcb823b16..9e2f7279ea 100644
--- a/docs/i18n/ar/docs/FEATURES.md
+++ b/docs/i18n/ar/docs/FEATURES.md
@@ -1,6 +1,6 @@
# OmniRoute — Dashboard Features Gallery (العربية)
-🌐 **Languages:** 🇺🇸 [English](../../../../docs/FEATURES.md) · 🇪🇸 [es](../../es/docs/FEATURES.md) · 🇫🇷 [fr](../../fr/docs/FEATURES.md) · 🇩🇪 [de](../../de/docs/FEATURES.md) · 🇮🇹 [it](../../it/docs/FEATURES.md) · 🇷🇺 [ru](../../ru/docs/FEATURES.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/FEATURES.md) · 🇯🇵 [ja](../../ja/docs/FEATURES.md) · 🇰🇷 [ko](../../ko/docs/FEATURES.md) · 🇸🇦 [ar](../../ar/docs/FEATURES.md) · 🇮🇳 [in](../../in/docs/FEATURES.md) · 🇹🇭 [th](../../th/docs/FEATURES.md) · 🇻🇳 [vi](../../vi/docs/FEATURES.md) · 🇮🇩 [id](../../id/docs/FEATURES.md) · 🇲🇾 [ms](../../ms/docs/FEATURES.md) · 🇳🇱 [nl](../../nl/docs/FEATURES.md) · 🇵🇱 [pl](../../pl/docs/FEATURES.md) · 🇸🇪 [sv](../../sv/docs/FEATURES.md) · 🇳🇴 [no](../../no/docs/FEATURES.md) · 🇩🇰 [da](../../da/docs/FEATURES.md) · 🇫🇮 [fi](../../fi/docs/FEATURES.md) · 🇵🇹 [pt](../../pt/docs/FEATURES.md) · 🇷🇴 [ro](../../ro/docs/FEATURES.md) · 🇭🇺 [hu](../../hu/docs/FEATURES.md) · 🇧🇬 [bg](../../bg/docs/FEATURES.md) · 🇸🇰 [sk](../../sk/docs/FEATURES.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/FEATURES.md) · 🇮🇱 [he](../../he/docs/FEATURES.md) · 🇵🇭 [phi](../../phi/docs/FEATURES.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/FEATURES.md)
+🌐 **Languages:** 🇺🇸 [English](../../../../docs/FEATURES.md) · 🇪🇸 [es](../../es/docs/FEATURES.md) · 🇫🇷 [fr](../../fr/docs/FEATURES.md) · 🇩🇪 [de](../../de/docs/FEATURES.md) · 🇮🇹 [it](../../it/docs/FEATURES.md) · 🇷🇺 [ru](../../ru/docs/FEATURES.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/FEATURES.md) · 🇯🇵 [ja](../../ja/docs/FEATURES.md) · 🇰🇷 [ko](../../ko/docs/FEATURES.md) · 🇸🇦 [ar](../../ar/docs/FEATURES.md) · 🇮🇳 [in](../../in/docs/FEATURES.md) · 🇹🇭 [th](../../th/docs/FEATURES.md) · 🇻🇳 [vi](../../vi/docs/FEATURES.md) · 🇮🇩 [id](../../id/docs/FEATURES.md) · 🇲🇾 [ms](../../ms/docs/FEATURES.md) · 🇳🇱 [nl](../../nl/docs/FEATURES.md) · 🇵🇱 [pl](../../pl/docs/FEATURES.md) · 🇸🇪 [sv](../../sv/docs/FEATURES.md) · 🇳🇴 [no](../../no/docs/FEATURES.md) · 🇩🇰 [da](../../da/docs/FEATURES.md) · 🇫🇮 [fi](../../fi/docs/FEATURES.md) · 🇵🇹 [pt](../../pt/docs/FEATURES.md) · 🇷🇴 [ro](../../ro/docs/FEATURES.md) · 🇭🇺 [hu](../../hu/docs/FEATURES.md) · 🇧🇬 [bg](../../bg/docs/FEATURES.md) · 🇸🇰 [sk](../../sk/docs/FEATURES.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/FEATURES.md) · 🇮🇱 [he](../../he/docs/FEATURES.md) · 🇵🇭 [phi](../../phi/docs/FEATURES.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/FEATURES.md) · 🇨🇿 [cs](../../cs/docs/FEATURES.md)
---
@@ -10,7 +10,7 @@ Visual guide to every section of the OmniRoute dashboard.
## 🔌 Providers
-Manage AI provider connections: OAuth providers (Claude Code, Codex, Gemini CLI), API key providers (Groq, DeepSeek, OpenRouter), and free providers (iFlow, Qwen, Kiro). Kiro accounts include credit balance tracking — remaining credits, total allowance, and renewal date visible in Dashboard → Usage.
+Manage AI provider connections: OAuth providers (Claude Code, Codex, Gemini CLI), API key providers (Groq, DeepSeek, OpenRouter), and free providers (Qoder, Qwen, Kiro). Kiro accounts include credit balance tracking — remaining credits, total allowance, and renewal date visible in Dashboard → Usage.

diff --git a/docs/i18n/ar/docs/MCP-SERVER.md b/docs/i18n/ar/docs/MCP-SERVER.md
new file mode 100644
index 0000000000..ab8c27c157
--- /dev/null
+++ b/docs/i18n/ar/docs/MCP-SERVER.md
@@ -0,0 +1,87 @@
+# OmniRoute MCP Server Documentation (العربية)
+
+🌐 **Languages:** 🇺🇸 [English](../../../../docs/MCP-SERVER.md) · 🇪🇸 [es](../../es/docs/MCP-SERVER.md) · 🇫🇷 [fr](../../fr/docs/MCP-SERVER.md) · 🇩🇪 [de](../../de/docs/MCP-SERVER.md) · 🇮🇹 [it](../../it/docs/MCP-SERVER.md) · 🇷🇺 [ru](../../ru/docs/MCP-SERVER.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/MCP-SERVER.md) · 🇯🇵 [ja](../../ja/docs/MCP-SERVER.md) · 🇰🇷 [ko](../../ko/docs/MCP-SERVER.md) · 🇸🇦 [ar](../../ar/docs/MCP-SERVER.md) · 🇮🇳 [in](../../in/docs/MCP-SERVER.md) · 🇹🇭 [th](../../th/docs/MCP-SERVER.md) · 🇻🇳 [vi](../../vi/docs/MCP-SERVER.md) · 🇮🇩 [id](../../id/docs/MCP-SERVER.md) · 🇲🇾 [ms](../../ms/docs/MCP-SERVER.md) · 🇳🇱 [nl](../../nl/docs/MCP-SERVER.md) · 🇵🇱 [pl](../../pl/docs/MCP-SERVER.md) · 🇸🇪 [sv](../../sv/docs/MCP-SERVER.md) · 🇳🇴 [no](../../no/docs/MCP-SERVER.md) · 🇩🇰 [da](../../da/docs/MCP-SERVER.md) · 🇫🇮 [fi](../../fi/docs/MCP-SERVER.md) · 🇵🇹 [pt](../../pt/docs/MCP-SERVER.md) · 🇷🇴 [ro](../../ro/docs/MCP-SERVER.md) · 🇭🇺 [hu](../../hu/docs/MCP-SERVER.md) · 🇧🇬 [bg](../../bg/docs/MCP-SERVER.md) · 🇸🇰 [sk](../../sk/docs/MCP-SERVER.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/MCP-SERVER.md) · 🇮🇱 [he](../../he/docs/MCP-SERVER.md) · 🇵🇭 [phi](../../phi/docs/MCP-SERVER.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/MCP-SERVER.md) · 🇨🇿 [cs](../../cs/docs/MCP-SERVER.md)
+
+---
+
+> Model Context Protocol server with 16 intelligent tools
+
+## تثبيت
+
+OmniRoute MCP is built-in. Start it with:
+
+```bash
+omniroute --mcp
+```
+
+Or via the open-sse transport:
+
+```bash
+# HTTP streamable transport (port 20130)
+omniroute --dev # MCP auto-starts on /mcp endpoint
+```
+
+## IDE Configuration
+
+See [IDE Configs](integrations/ide-configs.md) for Antigravity, Cursor, Copilot, and Claude Desktop setup.
+
+---
+
+## Essential Tools (8)
+
+| Tool | Description |
+| :------------------------------ | :--------------------------------------- |
+| `omniroute_get_health` | Gateway health, circuit breakers, uptime |
+| `omniroute_list_combos` | All configured combos with models |
+| `omniroute_get_combo_metrics` | Performance metrics for a specific combo |
+| `omniroute_switch_combo` | Switch active combo by ID/name |
+| `omniroute_check_quota` | Quota status per provider or all |
+| `omniroute_route_request` | Send a chat completion through OmniRoute |
+| `omniroute_cost_report` | Cost analytics for a time period |
+| `omniroute_list_models_catalog` | Full model catalog with capabilities |
+
+## Advanced Tools (8)
+
+| Tool | Description |
+| :--------------------------------- | :---------------------------------------------------------- |
+| `omniroute_simulate_route` | Dry-run routing simulation with fallback tree |
+| `omniroute_set_budget_guard` | Session budget with degrade/block/alert actions |
+| `omniroute_set_resilience_profile` | Apply conservative/balanced/aggressive preset |
+| `omniroute_test_combo` | Live-test all models in a combo via a real upstream request |
+| `omniroute_get_provider_metrics` | Detailed metrics for one provider |
+| `omniroute_best_combo_for_task` | Task-fitness recommendation with alternatives |
+| `omniroute_explain_route` | Explain a past routing decision |
+| `omniroute_get_session_snapshot` | Full session state: costs, tokens, errors |
+
+## Authentication
+
+MCP tools are authenticated via API key scopes. Each tool requires specific scopes:
+
+| Scope | Tools |
+| :------------- | :----------------------------------------------- |
+| `read:health` | get_health, get_provider_metrics |
+| `read:combos` | list_combos, get_combo_metrics |
+| `write:combos` | switch_combo |
+| `read:quota` | check_quota |
+| `write:route` | route_request, simulate_route, test_combo |
+| `read:usage` | cost_report, get_session_snapshot, explain_route |
+| `write:config` | set_budget_guard, set_resilience_profile |
+| `read:models` | list_models_catalog, best_combo_for_task |
+
+## Audit Logging
+
+Every tool call is logged to `mcp_tool_audit` with:
+
+- Tool name, arguments, result
+- Duration (ms), success/failure
+- API key hash, timestamp
+
+## Files
+
+| File | Purpose |
+| :------------------------------------------- | :------------------------------------------ |
+| `open-sse/mcp-server/server.ts` | MCP server creation + 16 tool registrations |
+| `open-sse/mcp-server/transport.ts` | Stdio + HTTP transport |
+| `open-sse/mcp-server/auth.ts` | API key + scope validation |
+| `open-sse/mcp-server/audit.ts` | Tool call audit logging |
+| `open-sse/mcp-server/tools/advancedTools.ts` | 8 advanced tool handlers |
diff --git a/docs/i18n/ar/docs/RELEASE_CHECKLIST.md b/docs/i18n/ar/docs/RELEASE_CHECKLIST.md
new file mode 100644
index 0000000000..51d2cb71ed
--- /dev/null
+++ b/docs/i18n/ar/docs/RELEASE_CHECKLIST.md
@@ -0,0 +1,37 @@
+# Release Checklist (العربية)
+
+🌐 **Languages:** 🇺🇸 [English](../../../../docs/RELEASE_CHECKLIST.md) · 🇪🇸 [es](../../es/docs/RELEASE_CHECKLIST.md) · 🇫🇷 [fr](../../fr/docs/RELEASE_CHECKLIST.md) · 🇩🇪 [de](../../de/docs/RELEASE_CHECKLIST.md) · 🇮🇹 [it](../../it/docs/RELEASE_CHECKLIST.md) · 🇷🇺 [ru](../../ru/docs/RELEASE_CHECKLIST.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/RELEASE_CHECKLIST.md) · 🇯🇵 [ja](../../ja/docs/RELEASE_CHECKLIST.md) · 🇰🇷 [ko](../../ko/docs/RELEASE_CHECKLIST.md) · 🇸🇦 [ar](../../ar/docs/RELEASE_CHECKLIST.md) · 🇮🇳 [in](../../in/docs/RELEASE_CHECKLIST.md) · 🇹🇭 [th](../../th/docs/RELEASE_CHECKLIST.md) · 🇻🇳 [vi](../../vi/docs/RELEASE_CHECKLIST.md) · 🇮🇩 [id](../../id/docs/RELEASE_CHECKLIST.md) · 🇲🇾 [ms](../../ms/docs/RELEASE_CHECKLIST.md) · 🇳🇱 [nl](../../nl/docs/RELEASE_CHECKLIST.md) · 🇵🇱 [pl](../../pl/docs/RELEASE_CHECKLIST.md) · 🇸🇪 [sv](../../sv/docs/RELEASE_CHECKLIST.md) · 🇳🇴 [no](../../no/docs/RELEASE_CHECKLIST.md) · 🇩🇰 [da](../../da/docs/RELEASE_CHECKLIST.md) · 🇫🇮 [fi](../../fi/docs/RELEASE_CHECKLIST.md) · 🇵🇹 [pt](../../pt/docs/RELEASE_CHECKLIST.md) · 🇷🇴 [ro](../../ro/docs/RELEASE_CHECKLIST.md) · 🇭🇺 [hu](../../hu/docs/RELEASE_CHECKLIST.md) · 🇧🇬 [bg](../../bg/docs/RELEASE_CHECKLIST.md) · 🇸🇰 [sk](../../sk/docs/RELEASE_CHECKLIST.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/RELEASE_CHECKLIST.md) · 🇮🇱 [he](../../he/docs/RELEASE_CHECKLIST.md) · 🇵🇭 [phi](../../phi/docs/RELEASE_CHECKLIST.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/RELEASE_CHECKLIST.md) · 🇨🇿 [cs](../../cs/docs/RELEASE_CHECKLIST.md)
+
+---
+
+Use this checklist before tagging or publishing a new OmniRoute release.
+
+## Version and Changelog
+
+1. Bump `package.json` version (`x.y.z`) in the release branch.
+2. Move release notes from `## [Unreleased]` in `CHANGELOG.md` to a dated section:
+ - `## [x.y.z] — YYYY-MM-DD`
+3. Keep `## [Unreleased]` as the first changelog section for upcoming work.
+4. Ensure the latest semver section in `CHANGELOG.md` equals `package.json` version.
+
+## API Docs
+
+1. Update `docs/openapi.yaml`:
+ - `info.version` must equal `package.json` version.
+2. Validate endpoint examples if API contracts changed.
+
+## Runtime Docs
+
+1. Review `docs/ARCHITECTURE.md` for storage/runtime drift.
+2. Review `docs/TROUBLESHOOTING.md` for env var and operational drift.
+3. Update localized docs if source docs changed significantly.
+
+## Automated Check
+
+Run the sync guard locally before opening PR:
+
+```bash
+npm run check:docs-sync
+```
+
+CI also runs this check in `.github/workflows/ci.yml` (lint job).
diff --git a/docs/i18n/da/TROUBLESHOOTING.md b/docs/i18n/ar/docs/TROUBLESHOOTING.md
similarity index 77%
rename from docs/i18n/da/TROUBLESHOOTING.md
rename to docs/i18n/ar/docs/TROUBLESHOOTING.md
index 63c148000a..2bbdea5394 100644
--- a/docs/i18n/da/TROUBLESHOOTING.md
+++ b/docs/i18n/ar/docs/TROUBLESHOOTING.md
@@ -1,11 +1,9 @@
-🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/TROUBLESHOOTING.md) · 🇪🇸 [es](../es/TROUBLESHOOTING.md) · 🇫🇷 [fr](../fr/TROUBLESHOOTING.md) · 🇩🇪 [de](../de/TROUBLESHOOTING.md) · 🇮🇹 [it](../it/TROUBLESHOOTING.md) · 🇷🇺 [ru](../ru/TROUBLESHOOTING.md) · 🇨🇳 [zh-CN](../zh-CN/TROUBLESHOOTING.md) · 🇯🇵 [ja](../ja/TROUBLESHOOTING.md) · 🇰🇷 [ko](../ko/TROUBLESHOOTING.md) · 🇸🇦 [ar](../ar/TROUBLESHOOTING.md) · 🇮🇳 [in](../in/TROUBLESHOOTING.md) · 🇹🇭 [th](../th/TROUBLESHOOTING.md) · 🇻🇳 [vi](../vi/TROUBLESHOOTING.md) · 🇮🇩 [id](../id/TROUBLESHOOTING.md) · 🇲🇾 [ms](../ms/TROUBLESHOOTING.md) · 🇳🇱 [nl](../nl/TROUBLESHOOTING.md) · 🇵🇱 [pl](../pl/TROUBLESHOOTING.md) · 🇸🇪 [sv](../sv/TROUBLESHOOTING.md) · 🇳🇴 [no](../no/TROUBLESHOOTING.md) · 🇩🇰 [da](../da/TROUBLESHOOTING.md) · 🇫🇮 [fi](../fi/TROUBLESHOOTING.md) · 🇵🇹 [pt](../pt/TROUBLESHOOTING.md) · 🇷🇴 [ro](../ro/TROUBLESHOOTING.md) · 🇭🇺 [hu](../hu/TROUBLESHOOTING.md) · 🇧🇬 [bg](../bg/TROUBLESHOOTING.md) · 🇸🇰 [sk](../sk/TROUBLESHOOTING.md) · 🇺🇦 [uk-UA](../uk-UA/TROUBLESHOOTING.md) · 🇮🇱 [he](../he/TROUBLESHOOTING.md) · 🇵🇭 [phi](../phi/TROUBLESHOOTING.md)
+# Troubleshooting (العربية)
+
+🌐 **Languages:** 🇺🇸 [English](../../../../docs/TROUBLESHOOTING.md) · 🇪🇸 [es](../../es/docs/TROUBLESHOOTING.md) · 🇫🇷 [fr](../../fr/docs/TROUBLESHOOTING.md) · 🇩🇪 [de](../../de/docs/TROUBLESHOOTING.md) · 🇮🇹 [it](../../it/docs/TROUBLESHOOTING.md) · 🇷🇺 [ru](../../ru/docs/TROUBLESHOOTING.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/TROUBLESHOOTING.md) · 🇯🇵 [ja](../../ja/docs/TROUBLESHOOTING.md) · 🇰🇷 [ko](../../ko/docs/TROUBLESHOOTING.md) · 🇸🇦 [ar](../../ar/docs/TROUBLESHOOTING.md) · 🇮🇳 [in](../../in/docs/TROUBLESHOOTING.md) · 🇹🇭 [th](../../th/docs/TROUBLESHOOTING.md) · 🇻🇳 [vi](../../vi/docs/TROUBLESHOOTING.md) · 🇮🇩 [id](../../id/docs/TROUBLESHOOTING.md) · 🇲🇾 [ms](../../ms/docs/TROUBLESHOOTING.md) · 🇳🇱 [nl](../../nl/docs/TROUBLESHOOTING.md) · 🇵🇱 [pl](../../pl/docs/TROUBLESHOOTING.md) · 🇸🇪 [sv](../../sv/docs/TROUBLESHOOTING.md) · 🇳🇴 [no](../../no/docs/TROUBLESHOOTING.md) · 🇩🇰 [da](../../da/docs/TROUBLESHOOTING.md) · 🇫🇮 [fi](../../fi/docs/TROUBLESHOOTING.md) · 🇵🇹 [pt](../../pt/docs/TROUBLESHOOTING.md) · 🇷🇴 [ro](../../ro/docs/TROUBLESHOOTING.md) · 🇭🇺 [hu](../../hu/docs/TROUBLESHOOTING.md) · 🇧🇬 [bg](../../bg/docs/TROUBLESHOOTING.md) · 🇸🇰 [sk](../../sk/docs/TROUBLESHOOTING.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/TROUBLESHOOTING.md) · 🇮🇱 [he](../../he/docs/TROUBLESHOOTING.md) · 🇵🇭 [phi](../../phi/docs/TROUBLESHOOTING.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/TROUBLESHOOTING.md) · 🇨🇿 [cs](../../cs/docs/TROUBLESHOOTING.md)
---
-# Troubleshooting
-
-🌐 **Languages:** 🇺🇸 [English](TROUBLESHOOTING.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/TROUBLESHOOTING.md) | 🇪🇸 [Español](i18n/es/TROUBLESHOOTING.md) | 🇫🇷 [Français](i18n/fr/TROUBLESHOOTING.md) | 🇮🇹 [Italiano](i18n/it/TROUBLESHOOTING.md) | 🇷🇺 [Русский](i18n/ru/TROUBLESHOOTING.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/TROUBLESHOOTING.md) | 🇩🇪 [Deutsch](i18n/de/TROUBLESHOOTING.md) | 🇮🇳 [हिन्दी](i18n/in/TROUBLESHOOTING.md) | 🇹🇭 [ไทย](i18n/th/TROUBLESHOOTING.md) | 🇺🇦 [Українська](i18n/uk-UA/TROUBLESHOOTING.md) | 🇸🇦 [العربية](i18n/ar/TROUBLESHOOTING.md) | 🇯🇵 [日本語](i18n/ja/TROUBLESHOOTING.md) | 🇻🇳 [Tiếng Việt](i18n/vi/TROUBLESHOOTING.md) | 🇧🇬 [Български](i18n/bg/TROUBLESHOOTING.md) | 🇩🇰 [Dansk](i18n/da/TROUBLESHOOTING.md) | 🇫🇮 [Suomi](i18n/fi/TROUBLESHOOTING.md) | 🇮🇱 [עברית](i18n/he/TROUBLESHOOTING.md) | 🇭🇺 [Magyar](i18n/hu/TROUBLESHOOTING.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/TROUBLESHOOTING.md) | 🇰🇷 [한국어](i18n/ko/TROUBLESHOOTING.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/TROUBLESHOOTING.md) | 🇳🇱 [Nederlands](i18n/nl/TROUBLESHOOTING.md) | 🇳🇴 [Norsk](i18n/no/TROUBLESHOOTING.md) | 🇵🇹 [Português (Portugal)](i18n/pt/TROUBLESHOOTING.md) | 🇷🇴 [Română](i18n/ro/TROUBLESHOOTING.md) | 🇵🇱 [Polski](i18n/pl/TROUBLESHOOTING.md) | 🇸🇰 [Slovenčina](i18n/sk/TROUBLESHOOTING.md) | 🇸🇪 [Svenska](i18n/sv/TROUBLESHOOTING.md) | 🇵🇭 [Filipino](i18n/phi/TROUBLESHOOTING.md)
-
Common problems and solutions for OmniRoute.
---
diff --git a/docs/i18n/ar/USER_GUIDE.md b/docs/i18n/ar/docs/USER_GUIDE.md
similarity index 82%
rename from docs/i18n/ar/USER_GUIDE.md
rename to docs/i18n/ar/docs/USER_GUIDE.md
index cc5cd9715c..fec281bdac 100644
--- a/docs/i18n/ar/USER_GUIDE.md
+++ b/docs/i18n/ar/docs/USER_GUIDE.md
@@ -1,8 +1,6 @@
# User Guide (العربية)
-🌐 **Languages:** 🇺🇸 [English](../../USER_GUIDE.md) · 🇧🇷 [pt-BR](../pt-BR/USER_GUIDE.md) · 🇪🇸 [es](../es/USER_GUIDE.md) · 🇫🇷 [fr](../fr/USER_GUIDE.md) · 🇩🇪 [de](../de/USER_GUIDE.md) · 🇮🇹 [it](../it/USER_GUIDE.md) · 🇷🇺 [ru](../ru/USER_GUIDE.md) · 🇨🇳 [zh-CN](../zh-CN/USER_GUIDE.md) · 🇯🇵 [ja](../ja/USER_GUIDE.md) · 🇰🇷 [ko](../ko/USER_GUIDE.md) · 🇸🇦 [ar](../ar/USER_GUIDE.md) · 🇮🇳 [in](../in/USER_GUIDE.md) · 🇹🇭 [th](../th/USER_GUIDE.md) · 🇻🇳 [vi](../vi/USER_GUIDE.md) · 🇮🇩 [id](../id/USER_GUIDE.md) · 🇲🇾 [ms](../ms/USER_GUIDE.md) · 🇳🇱 [nl](../nl/USER_GUIDE.md) · 🇵🇱 [pl](../pl/USER_GUIDE.md) · 🇸🇪 [sv](../sv/USER_GUIDE.md) · 🇳🇴 [no](../no/USER_GUIDE.md) · 🇩🇰 [da](../da/USER_GUIDE.md) · 🇫🇮 [fi](../fi/USER_GUIDE.md) · 🇵🇹 [pt](../pt/USER_GUIDE.md) · 🇷🇴 [ro](../ro/USER_GUIDE.md) · 🇭🇺 [hu](../hu/USER_GUIDE.md) · 🇧🇬 [bg](../bg/USER_GUIDE.md) · 🇸🇰 [sk](../sk/USER_GUIDE.md) · 🇺🇦 [uk-UA](../uk-UA/USER_GUIDE.md) · 🇮🇱 [he](../he/USER_GUIDE.md) · 🇵🇭 [phi](../phi/USER_GUIDE.md)
-
-> 🇺🇸 [English](../../USER_GUIDE.md)
+🌐 **Languages:** 🇺🇸 [English](../../../../docs/USER_GUIDE.md) · 🇪🇸 [es](../../es/docs/USER_GUIDE.md) · 🇫🇷 [fr](../../fr/docs/USER_GUIDE.md) · 🇩🇪 [de](../../de/docs/USER_GUIDE.md) · 🇮🇹 [it](../../it/docs/USER_GUIDE.md) · 🇷🇺 [ru](../../ru/docs/USER_GUIDE.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/USER_GUIDE.md) · 🇯🇵 [ja](../../ja/docs/USER_GUIDE.md) · 🇰🇷 [ko](../../ko/docs/USER_GUIDE.md) · 🇸🇦 [ar](../../ar/docs/USER_GUIDE.md) · 🇮🇳 [in](../../in/docs/USER_GUIDE.md) · 🇹🇭 [th](../../th/docs/USER_GUIDE.md) · 🇻🇳 [vi](../../vi/docs/USER_GUIDE.md) · 🇮🇩 [id](../../id/docs/USER_GUIDE.md) · 🇲🇾 [ms](../../ms/docs/USER_GUIDE.md) · 🇳🇱 [nl](../../nl/docs/USER_GUIDE.md) · 🇵🇱 [pl](../../pl/docs/USER_GUIDE.md) · 🇸🇪 [sv](../../sv/docs/USER_GUIDE.md) · 🇳🇴 [no](../../no/docs/USER_GUIDE.md) · 🇩🇰 [da](../../da/docs/USER_GUIDE.md) · 🇫🇮 [fi](../../fi/docs/USER_GUIDE.md) · 🇵🇹 [pt](../../pt/docs/USER_GUIDE.md) · 🇷🇴 [ro](../../ro/docs/USER_GUIDE.md) · 🇭🇺 [hu](../../hu/docs/USER_GUIDE.md) · 🇧🇬 [bg](../../bg/docs/USER_GUIDE.md) · 🇸🇰 [sk](../../sk/docs/USER_GUIDE.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/USER_GUIDE.md) · 🇮🇱 [he](../../he/docs/USER_GUIDE.md) · 🇵🇭 [phi](../../phi/docs/USER_GUIDE.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/USER_GUIDE.md) · 🇨🇿 [cs](../../cs/docs/USER_GUIDE.md)
---
@@ -320,7 +318,7 @@ Model: cc/claude-opus-4-6
---
-## 🚀 Deployment
+## النشر
### Global npm install (Recommended)
@@ -511,23 +509,26 @@ post_install() {
### Environment Variables
-| Variable | Default | Description |
-| ------------------------- | ------------------------------------ | ------------------------------------------------------- |
-| `JWT_SECRET` | `omniroute-default-secret-change-me` | JWT signing secret (**change in production**) |
-| `INITIAL_PASSWORD` | `123456` | First login password |
-| `DATA_DIR` | `~/.omniroute` | Data directory (db, usage, logs) |
-| `PORT` | framework default | Service port (`20128` in examples) |
-| `HOSTNAME` | framework default | Bind host (Docker defaults to `0.0.0.0`) |
-| `NODE_ENV` | runtime default | Set `production` for deploy |
-| `BASE_URL` | `http://localhost:20128` | Server-side internal base URL |
-| `CLOUD_URL` | `https://omniroute.dev` | Cloud sync endpoint base URL |
-| `API_KEY_SECRET` | `endpoint-proxy-api-key-secret` | HMAC secret for generated API keys |
-| `REQUIRE_API_KEY` | `false` | Enforce Bearer API key on `/v1/*` |
-| `ENABLE_REQUEST_LOGS` | `false` | Enables request/response logs |
-| `AUTH_COOKIE_SECURE` | `false` | Force `Secure` auth cookie (behind HTTPS reverse proxy) |
-| `OMNIROUTE_MEMORY_MB` | `512` | Node.js heap limit in MB |
-| `PROMPT_CACHE_MAX_SIZE` | `50` | Max prompt cache entries |
-| `SEMANTIC_CACHE_MAX_SIZE` | `100` | Max semantic cache entries |
+| Variable | Default | Description |
+| ---------------------------- | ------------------------------------ | ------------------------------------------------------------------------------------------ |
+| `JWT_SECRET` | `omniroute-default-secret-change-me` | JWT signing secret (**change in production**) |
+| `INITIAL_PASSWORD` | `123456` | First login password |
+| `DATA_DIR` | `~/.omniroute` | Data directory (db, usage, logs) |
+| `PORT` | framework default | Service port (`20128` in examples) |
+| `HOSTNAME` | framework default | Bind host (Docker defaults to `0.0.0.0`) |
+| `NODE_ENV` | runtime default | Set `production` for deploy |
+| `BASE_URL` | `http://localhost:20128` | Server-side internal base URL |
+| `CLOUD_URL` | `https://omniroute.dev` | Cloud sync endpoint base URL |
+| `API_KEY_SECRET` | `endpoint-proxy-api-key-secret` | HMAC secret for generated API keys |
+| `REQUIRE_API_KEY` | `false` | Enforce Bearer API key on `/v1/*` |
+| `ALLOW_API_KEY_REVEAL` | `false` | Allow Api Manager to copy full API keys on demand |
+| `DISABLE_SQLITE_AUTO_BACKUP` | `false` | Disable automatic SQLite snapshots before writes/import/restore; manual backups still work |
+| `ENABLE_REQUEST_LOGS` | `false` | Enables request/response logs |
+| `AUTH_COOKIE_SECURE` | `false` | Force `Secure` auth cookie (behind HTTPS reverse proxy) |
+| `CLOUDFLARED_BIN` | unset | Use an existing `cloudflared` binary instead of managed download |
+| `OMNIROUTE_MEMORY_MB` | `512` | Node.js heap limit in MB |
+| `PROMPT_CACHE_MAX_SIZE` | `50` | Max prompt cache entries |
+| `SEMANTIC_CACHE_MAX_SIZE` | `100` | Max semantic cache entries |
For the full environment variable reference, see the [README](../README.md).
@@ -598,6 +599,11 @@ curl -X POST http://localhost:20128/api/provider-models \
Or use Dashboard: **Providers → [Provider] → Custom Models**.
+Notes:
+
+- OpenRouter and OpenAI/Anthropic-compatible providers are managed from **Available Models** only. Manual add, import, and auto-sync all land in the same available-model list, so there is no separate Custom Models section for those providers.
+- The **Custom Models** section is intended for providers that do not expose managed available-model imports.
+
### Dedicated Provider Routes
Route requests directly to a specific provider with model validation:
@@ -642,6 +648,14 @@ Returns models grouped by provider with types (`chat`, `embedding`, `image`).
- Automatic background sync with timeout + fail-fast
- Prefer server-side `BASE_URL`/`CLOUD_URL` in production
+### Cloudflare Quick Tunnel
+
+- Available in **Dashboard → Endpoints** for Docker and other self-hosted deployments
+- Creates a temporary `https://*.trycloudflare.com` URL that forwards to your current OpenAI-compatible `/v1` endpoint
+- First enable installs `cloudflared` only when needed; later restarts reuse the same managed binary
+- Tunnel URLs are ephemeral and change every time you stop/start the tunnel
+- Set `CLOUDFLARED_BIN` if you prefer using a preinstalled `cloudflared` binary instead of the managed download
+
### LLM Gateway Intelligence (Phase 9)
- **Semantic Cache** — Auto-caches non-streaming, temperature=0 responses (bypass with `X-OmniRoute-No-Cache: true`)
@@ -757,11 +771,11 @@ OmniRoute implements provider-level resilience with four components:
Manage database backups in **Dashboard → Settings → System & Storage**.
-| Action | Description |
-| ------------------------ | ------------------------------------------------------------------------------------------------------------------------------ |
-| **Export Database** | Downloads the current SQLite database as a `.sqlite` file |
-| **Export All (.tar.gz)** | Downloads a full backup archive including: database, settings, combos, provider connections (no credentials), API key metadata |
-| **Import Database** | Upload a `.sqlite` file to replace the current database. A pre-import backup is automatically created |
+| Action | Description |
+| ------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------- |
+| **Export Database** | Downloads the current SQLite database as a `.sqlite` file |
+| **Export All (.tar.gz)** | Downloads a full backup archive including: database, settings, combos, provider connections (no credentials), API key metadata |
+| **Import Database** | Upload a `.sqlite` file to replace the current database. A pre-import backup is automatically created unless `DISABLE_SQLITE_AUTO_BACKUP=true` |
```bash
# API: Export database
@@ -787,10 +801,11 @@ curl -X POST http://localhost:20128/api/db-backups/import \
### Settings Dashboard
-The settings page is organized into 5 tabs for easy navigation:
+The settings page is organized into 6 tabs for easy navigation:
| Tab | Contents |
| -------------- | ---------------------------------------------------------------------------------------------- |
+| **General** | System storage tools, appearance settings, theme controls, and per-item sidebar visibility |
| **Security** | Login/Password settings, IP Access Control, API auth for `/models`, and Provider Blocking |
| **Routing** | Global routing strategy (6 options), wildcard model aliases, fallback chains, combo defaults |
| **Resilience** | Provider profiles, editable rate limits, circuit breaker status, policies & locked identifiers |
diff --git a/docs/i18n/ar/docs/VM_DEPLOYMENT_GUIDE.md b/docs/i18n/ar/docs/VM_DEPLOYMENT_GUIDE.md
new file mode 100644
index 0000000000..e43cb85ad4
--- /dev/null
+++ b/docs/i18n/ar/docs/VM_DEPLOYMENT_GUIDE.md
@@ -0,0 +1,403 @@
+# OmniRoute — Deployment Guide on VM with Cloudflare (العربية)
+
+🌐 **Languages:** 🇺🇸 [English](../../../../docs/VM_DEPLOYMENT_GUIDE.md) · 🇪🇸 [es](../../es/docs/VM_DEPLOYMENT_GUIDE.md) · 🇫🇷 [fr](../../fr/docs/VM_DEPLOYMENT_GUIDE.md) · 🇩🇪 [de](../../de/docs/VM_DEPLOYMENT_GUIDE.md) · 🇮🇹 [it](../../it/docs/VM_DEPLOYMENT_GUIDE.md) · 🇷🇺 [ru](../../ru/docs/VM_DEPLOYMENT_GUIDE.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/VM_DEPLOYMENT_GUIDE.md) · 🇯🇵 [ja](../../ja/docs/VM_DEPLOYMENT_GUIDE.md) · 🇰🇷 [ko](../../ko/docs/VM_DEPLOYMENT_GUIDE.md) · 🇸🇦 [ar](../../ar/docs/VM_DEPLOYMENT_GUIDE.md) · 🇮🇳 [in](../../in/docs/VM_DEPLOYMENT_GUIDE.md) · 🇹🇭 [th](../../th/docs/VM_DEPLOYMENT_GUIDE.md) · 🇻🇳 [vi](../../vi/docs/VM_DEPLOYMENT_GUIDE.md) · 🇮🇩 [id](../../id/docs/VM_DEPLOYMENT_GUIDE.md) · 🇲🇾 [ms](../../ms/docs/VM_DEPLOYMENT_GUIDE.md) · 🇳🇱 [nl](../../nl/docs/VM_DEPLOYMENT_GUIDE.md) · 🇵🇱 [pl](../../pl/docs/VM_DEPLOYMENT_GUIDE.md) · 🇸🇪 [sv](../../sv/docs/VM_DEPLOYMENT_GUIDE.md) · 🇳🇴 [no](../../no/docs/VM_DEPLOYMENT_GUIDE.md) · 🇩🇰 [da](../../da/docs/VM_DEPLOYMENT_GUIDE.md) · 🇫🇮 [fi](../../fi/docs/VM_DEPLOYMENT_GUIDE.md) · 🇵🇹 [pt](../../pt/docs/VM_DEPLOYMENT_GUIDE.md) · 🇷🇴 [ro](../../ro/docs/VM_DEPLOYMENT_GUIDE.md) · 🇭🇺 [hu](../../hu/docs/VM_DEPLOYMENT_GUIDE.md) · 🇧🇬 [bg](../../bg/docs/VM_DEPLOYMENT_GUIDE.md) · 🇸🇰 [sk](../../sk/docs/VM_DEPLOYMENT_GUIDE.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/VM_DEPLOYMENT_GUIDE.md) · 🇮🇱 [he](../../he/docs/VM_DEPLOYMENT_GUIDE.md) · 🇵🇭 [phi](../../phi/docs/VM_DEPLOYMENT_GUIDE.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/VM_DEPLOYMENT_GUIDE.md) · 🇨🇿 [cs](../../cs/docs/VM_DEPLOYMENT_GUIDE.md)
+
+---
+
+Complete guide to install and configure OmniRoute on a VM (VPS) with domain managed via Cloudflare.
+
+---
+
+## Prerequisites
+
+| Item | Minimum | Recommended |
+| ---------- | ------------------------ | ---------------- |
+| **CPU** | 1 vCPU | 2 vCPU |
+| **RAM** | 1 GB | 2 GB |
+| **Disk** | 10 GB SSD | 25 GB SSD |
+| **OS** | Ubuntu 22.04 LTS | Ubuntu 24.04 LTS |
+| **Domain** | Registered on Cloudflare | — |
+| **Docker** | Docker Engine 24+ | Docker 27+ |
+
+**Tested providers**: Akamai (Linode), DigitalOcean, Vultr, Hetzner, AWS Lightsail.
+
+---
+
+## 1. Configure the VM
+
+### 1.1 Create the instance
+
+On your preferred VPS provider:
+
+- Choose Ubuntu 24.04 LTS
+- Select the minimum plan (1 vCPU / 1 GB RAM)
+- Set a strong root password or configure SSH key
+- Note the **public IP** (e.g., `203.0.113.10`)
+
+### 1.2 Connect via SSH
+
+```bash
+ssh root@203.0.113.10
+```
+
+### 1.3 Update the system
+
+```bash
+apt update && apt upgrade -y
+```
+
+### 1.4 Install Docker
+
+```bash
+# Install dependencies
+apt install -y ca-certificates curl gnupg
+
+# Add official Docker repository
+install -m 0755 -d /etc/apt/keyrings
+curl -fsSL https://download.docker.com/linux/ubuntu/gpg | gpg --dearmor -o /etc/apt/keyrings/docker.gpg
+chmod a+r /etc/apt/keyrings/docker.gpg
+echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu $ (. /etc/os-release && echo “$VERSION_CODENAME”) stable" | tee /etc/apt/sources.list.d/docker.list > /dev/null
+apt update
+apt install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin
+```
+
+### 1.5 Install nginx
+
+```bash
+apt install -y nginx
+```
+
+### 1.6 Configure Firewall (UFW)
+
+```bash
+ufw default deny incoming
+ufw default allow outgoing
+ufw allow 22/tcp # SSH
+ufw allow 80/tcp # HTTP (redirect)
+ufw allow 443/tcp # HTTPS
+ufw enable
+```
+
+> **Tip**: For maximum security, restrict ports 80 and 443 to Cloudflare IPs only. See the [Advanced Security](#advanced-security) section.
+
+---
+
+## 2. Install OmniRoute
+
+### 2.1 Create configuration directory
+
+```bash
+mkdir -p /opt/omniroute
+```
+
+### 2.2 Create environment variables file
+
+```bash
+cat > /opt/omniroute/.env << ‘EOF’
+# === Security ===
+JWT_SECRET=CHANGE-TO-A-UNIQUE-64-CHAR-SECRET-KEY
+INITIAL_PASSWORD=YourSecurePassword123!
+API_KEY_SECRET=REPLACE-WITH-ANOTHER-SECRET-KEY
+STORAGE_ENCRYPTION_KEY=REPLACE-WITH-THIRD-SECRET-KEY
+STORAGE_ENCRYPTION_KEY_VERSION=v1
+MACHINE_ID_SALT=CHANGE-TO-A-UNIQUE-SALT
+
+# === App ===
+PORT=20128
+NODE_ENV=production
+HOSTNAME=0.0.0.0
+DATA_DIR=/app/data
+STORAGE_DRIVER=sqlite
+ENABLE_REQUEST_LOGS=true
+AUTH_COOKIE_SECURE=false
+REQUIRE_API_KEY=false
+
+# === Domain (change to your domain) ===
+BASE_URL=https://llms.seudominio.com
+NEXT_PUBLIC_BASE_URL=https://llms.seudominio.com
+
+# === Cloud Sync (optional) ===
+# CLOUD_URL=https://cloud.omniroute.online
+# NEXT_PUBLIC_CLOUD_URL=https://cloud.omniroute.online
+EOF
+```
+
+> ⚠️ **IMPORTANT**: Generate unique secret keys! Use `openssl rand -hex 32` for each key.
+
+### 2.3 Start the container
+
+```bash
+docker pull diegosouzapw/omniroute:latest
+
+docker run -d \
+ --name omniroute \
+ --restart unless-stopped \
+ --env-file /opt/omniroute/.env \
+ -p 20128:20128 \
+ -v omniroute-data:/app/data \
+ diegosouzapw/omniroute:latest
+```
+
+### 2.4 Verify that it is running
+
+```bash
+docker ps | grep omniroute
+docker logs omniroute --tail 20
+```
+
+It should display: `[DB] SQLite database ready` and `listening on port 20128`.
+
+---
+
+## 3. Configure nginx (Reverse Proxy)
+
+### 3.1 Generate SSL certificate (Cloudflare Origin)
+
+In the Cloudflare dashboard:
+
+1. Go to **SSL/TLS → Origin Server**
+2. Click **Create Certificate**
+3. Keep the defaults (15 years, \*.yourdomain.com)
+4. Copy the **Origin Certificate** and the **Private Key**
+
+```bash
+mkdir -p /etc/nginx/ssl
+
+# Paste the certificate
+nano /etc/nginx/ssl/origin.crt
+
+# Paste the private key
+nano /etc/nginx/ssl/origin.key
+
+chmod 600 /etc/nginx/ssl/origin.key
+```
+
+### 3.2 Nginx Configuration
+
+```bash
+cat > /etc/nginx/sites-available/omniroute << ‘NGINX’
+# Default server — blocks direct access via IP
+server {
+ listen 80 default_server;
+ listen [::]:80 default_server;
+ listen 443 ssl default_server;
+ listen [::]:443 ssl default_server;
+ ssl_certificate /etc/nginx/ssl/origin.crt;
+ ssl_certificate_key /etc/nginx/ssl/origin.key;
+ server_name _;
+ return 444;
+}
+
+# OmniRoute — HTTPS
+server {
+ listen 443 ssl;
+ listen [::]:443 ssl;
+ server_name llms.yourdomain.com; # Change to your domain
+
+ ssl_certificate /etc/nginx/ssl/origin.crt;
+ ssl_certificate_key /etc/nginx/ssl/origin.key;
+ ssl_protocols TLSv1.2 TLSv1.3;
+
+ client_max_body_size 100M;
+
+ location / {
+ proxy_pass http://127.0.0.1:20128;
+ proxy_set_header Host $host;
+ proxy_set_header X-Real-IP $remote_addr;
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
+ proxy_set_header X-Forwarded-Proto $scheme;
+
+ # WebSocket support
+ proxy_http_version 1.1;
+ proxy_set_header Upgrade $http_upgrade;
+ proxy_set_header Connection “upgrade”;
+
+ # SSE (Server-Sent Events) — streaming AI responses
+ proxy_buffering off;
+ proxy_cache off;
+ proxy_read_timeout 300s;
+ proxy_send_timeout 300s;
+ }
+}
+
+# HTTP → HTTPS redirect
+server {
+ listen 80;
+ listen [::]:80;
+ server_name llms.yourdomain.com;
+ return 301 https://$server_name$request_uri;
+}
+NGINX
+```
+
+### 3.3 Enable and Test
+
+```bash
+# Remove default configuration
+rm -f /etc/nginx/sites-enabled/default
+
+# Enable OmniRoute
+ln -sf /etc/nginx/sites-available/omniroute /etc/nginx/sites-enabled/omniroute
+
+# Test and reload
+nginx -t && systemctl reload nginx
+```
+
+---
+
+## 4. Configure Cloudflare DNS
+
+### 4.1 Add DNS record
+
+In the Cloudflare dashboard → DNS:
+
+| Type | Name | Content | Proxy |
+| ---- | ------ | ---------------------- | ---------- |
+| A | `llms` | `203.0.113.10` (VM IP) | ✅ Proxied |
+
+### 4.2 Configure SSL
+
+Under **SSL/TLS → Overview**:
+
+- Mode: **Full (Strict)**
+
+Under **SSL/TLS → Edge Certificates**:
+
+- Always Use HTTPS: ✅ On
+- Minimum TLS Version: TLS 1.2
+- Automatic HTTPS Rewrites: ✅ On
+
+### 4.3 Testing
+
+```bash
+curl -sI https://llms.seudominio.com/health
+# Should return HTTP/2 200
+```
+
+---
+
+## 5. Operations and Maintenance
+
+### Upgrade to a new version
+
+```bash
+docker pull diegosouzapw/omniroute:latest
+docker stop omniroute && docker rm omniroute
+docker run -d --name omniroute --restart unless-stopped \
+ --env-file /opt/omniroute/.env \
+ -p 20128:20128 \
+ -v omniroute-data:/app/data \
+ diegosouzapw/omniroute:latest
+```
+
+### View logs
+
+```bash
+docker logs -f omniroute # Real-time stream
+docker logs omniroute --tail 50 # Last 50 lines
+```
+
+### Manual database backup
+
+```bash
+# Copy data from the volume to the host
+docker cp omniroute:/app/data ./backup-$(date +%F)
+
+# Or compress the entire volume
+docker run --rm -v omniroute-data:/data -v $(pwd):/backup \
+ alpine tar czf /backup/omniroute-data-$(date +%F).tar.gz /data
+```
+
+### Restore from backup
+
+```bash
+docker stop omniroute
+docker run --rm -v omniroute-data:/data -v $(pwd):/backup \
+ alpine sh -c “rm -rf /data/* && tar xzf /backup/omniroute-data-YYYY-MM-DD.tar.gz -C /”
+docker start omniroute
+```
+
+---
+
+## 6. Advanced Security
+
+### Restrict nginx to Cloudflare IPs
+
+```bash
+cat > /etc/nginx/cloudflare-ips.conf << ‘CF’
+# Cloudflare IPv4 ranges — update periodically
+# https://www.cloudflare.com/ips-v4/
+set_real_ip_from 173.245.48.0/20;
+set_real_ip_from 103.21.244.0/22;
+set_real_ip_from 103.22.200.0/22;
+set_real_ip_from 103.31.4.0/22;
+set_real_ip_from 141.101.64.0/18;
+set_real_ip_from 108.162.192.0/18;
+set_real_ip_from 190.93.240.0/20;
+set_real_ip_from 188.114.96.0/20;
+set_real_ip_from 197.234.240.0/22;
+set_real_ip_from 198.41.128.0/17;
+set_real_ip_from 162.158.0.0/15;
+set_real_ip_from 104.16.0.0/13;
+set_real_ip_from 104.24.0.0/14;
+set_real_ip_from 172.64.0.0/13;
+set_real_ip_from 131.0.72.0/22;
+real_ip_header CF-Connecting-IP;
+CF
+```
+
+Add the following to `nginx.conf` inside the `http {}` block:
+
+```nginx
+include /etc/nginx/cloudflare-ips.conf;
+```
+
+### Install fail2ban
+
+```bash
+apt install -y fail2ban
+systemctl enable fail2ban
+systemctl start fail2ban
+
+# Check status
+fail2ban-client status sshd
+```
+
+### Block direct access to the Docker port
+
+```bash
+# Prevent direct external access to port 20128
+iptables -I DOCKER-USER -p tcp --dport 20128 -j DROP
+iptables -I DOCKER-USER -i lo -p tcp --dport 20128 -j ACCEPT
+
+# Persist the rules
+apt install -y iptables-persistent
+netfilter-persistent save
+```
+
+---
+
+## 7. Deploy to Cloudflare Workers (Optional)
+
+For remote access via Cloudflare Workers (without exposing the VM directly):
+
+```bash
+# In the local repository
+cd omnirouteCloud
+npm install
+npx wrangler login
+npx wrangler deploy
+```
+
+See the full documentation at [omnirouteCloud/README.md](../omnirouteCloud/README.md).
+
+---
+
+## Port Summary
+
+| Port | Service | Access |
+| ----- | ----------- | -------------------------- |
+| 22 | SSH | Public (with fail2ban) |
+| 80 | nginx HTTP | Redirect → HTTPS |
+| 443 | nginx HTTPS | Via Cloudflare Proxy |
+| 20128 | OmniRoute | Localhost only (via nginx) |
diff --git a/docs/i18n/ar/src/lib/a2a/README.md b/docs/i18n/ar/src/lib/a2a/README.md
new file mode 100644
index 0000000000..2ded085cac
--- /dev/null
+++ b/docs/i18n/ar/src/lib/a2a/README.md
@@ -0,0 +1,752 @@
+# OmniRoute A2A Server (العربية)
+
+🌐 **Languages:** 🇺🇸 [English](../../../../../../src/lib/a2a/README.md) · 🇪🇸 [es](../../../../es/src/lib/a2a/README.md) · 🇫🇷 [fr](../../../../fr/src/lib/a2a/README.md) · 🇩🇪 [de](../../../../de/src/lib/a2a/README.md) · 🇮🇹 [it](../../../../it/src/lib/a2a/README.md) · 🇷🇺 [ru](../../../../ru/src/lib/a2a/README.md) · 🇨🇳 [zh-CN](../../../../zh-CN/src/lib/a2a/README.md) · 🇯🇵 [ja](../../../../ja/src/lib/a2a/README.md) · 🇰🇷 [ko](../../../../ko/src/lib/a2a/README.md) · 🇸🇦 [ar](../../../../ar/src/lib/a2a/README.md) · 🇮🇳 [in](../../../../in/src/lib/a2a/README.md) · 🇹🇭 [th](../../../../th/src/lib/a2a/README.md) · 🇻🇳 [vi](../../../../vi/src/lib/a2a/README.md) · 🇮🇩 [id](../../../../id/src/lib/a2a/README.md) · 🇲🇾 [ms](../../../../ms/src/lib/a2a/README.md) · 🇳🇱 [nl](../../../../nl/src/lib/a2a/README.md) · 🇵🇱 [pl](../../../../pl/src/lib/a2a/README.md) · 🇸🇪 [sv](../../../../sv/src/lib/a2a/README.md) · 🇳🇴 [no](../../../../no/src/lib/a2a/README.md) · 🇩🇰 [da](../../../../da/src/lib/a2a/README.md) · 🇫🇮 [fi](../../../../fi/src/lib/a2a/README.md) · 🇵🇹 [pt](../../../../pt/src/lib/a2a/README.md) · 🇷🇴 [ro](../../../../ro/src/lib/a2a/README.md) · 🇭🇺 [hu](../../../../hu/src/lib/a2a/README.md) · 🇧🇬 [bg](../../../../bg/src/lib/a2a/README.md) · 🇸🇰 [sk](../../../../sk/src/lib/a2a/README.md) · 🇺🇦 [uk-UA](../../../../uk-UA/src/lib/a2a/README.md) · 🇮🇱 [he](../../../../he/src/lib/a2a/README.md) · 🇵🇭 [phi](../../../../phi/src/lib/a2a/README.md) · 🇧🇷 [pt-BR](../../../../pt-BR/src/lib/a2a/README.md) · 🇨🇿 [cs](../../../../cs/src/lib/a2a/README.md)
+
+---
+
+> **Agent-to-Agent Protocol v0.3** — Enables any AI agent to use OmniRoute as an intelligent routing agent via JSON-RPC 2.0.
+
+The A2A Server exposes OmniRoute as a **first-class agent** that other agents can discover, delegate tasks to, and collaborate with using the [A2A Protocol](https://google.github.io/A2A/).
+
+---
+
+## الهندسة
+
+```
+┌──────────────────────────────────────────────────────────────────┐
+│ Orchestrator Agent │
+│ (LangChain, CrewAI, AutoGen, Custom Agent) │
+└──────────────────────┬───────────────────────────────────────────┘
+ │ 1. GET /.well-known/agent.json (discover)
+ │ 2. POST /a2a (JSON-RPC 2.0)
+ ▼
+┌──────────────────────────────────────────────────────────────────┐
+│ OmniRoute A2A Server │
+│ ┌────────────────┐ ┌────────────────┐ ┌───────────────────┐ │
+│ │ Task Manager │ │ Skill Engine │ │ SSE Streaming │ │
+│ │ (lifecycle) │──│ (registry) │──│ (real-time) │ │
+│ └────────────────┘ └────────┬───────┘ └───────────────────┘ │
+│ │ │
+│ Skills: │ │
+│ ├─ smart-routing ──────────┤ ┌────────────────────────────┐ │
+│ └─ quota-management ───────┘ │ Routing Decision Logger │ │
+│ └────────────────────────────┘ │
+└──────────────────────────────────────────────────────────────────┘
+ │
+ ▼ OmniRoute Gateway (internal)
+ /v1/chat/completions, /api/combos, /api/usage/quota
+```
+
+---
+
+## بداية سريعة
+
+### Agent Discovery
+
+Every A2A-compatible agent exposes an **Agent Card** at `/.well-known/agent.json`:
+
+```bash
+curl http://localhost:20128/.well-known/agent.json
+```
+
+**Response:**
+
+```json
+{
+ "name": "OmniRoute",
+ "description": "Intelligent AI gateway with auto-routing across 50+ providers",
+ "url": "http://localhost:20128/a2a",
+ "version": "1.8.1",
+ "capabilities": {
+ "streaming": true,
+ "pushNotifications": false
+ },
+ "skills": [
+ {
+ "id": "smart-routing",
+ "name": "Smart Routing",
+ "description": "Routes prompts through OmniRoute intelligent pipeline",
+ "tags": ["routing", "llm", "multi-provider", "cost-optimization"],
+ "examples": [
+ "Write a hello world in Python",
+ "Explain quantum computing using the cheapest provider"
+ ]
+ },
+ {
+ "id": "quota-management",
+ "name": "Quota Management",
+ "description": "Natural-language queries about provider quotas",
+ "tags": ["quota", "analytics", "cost"],
+ "examples": [
+ "Which provider has the most quota remaining?",
+ "Suggest a free combo for coding"
+ ]
+ }
+ ],
+ "authentication": {
+ "schemes": ["bearer"],
+ "apiKeyHeader": "Authorization"
+ }
+}
+```
+
+---
+
+## JSON-RPC 2.0 Methods
+
+### `message/send` — Synchronous Execution
+
+Send a message to a skill and receive the complete response.
+
+```bash
+curl -X POST http://localhost:20128/a2a \
+ -H "Content-Type: application/json" \
+ -H "Authorization: Bearer YOUR_KEY" \
+ -d '{
+ "jsonrpc": "2.0",
+ "id": "1",
+ "method": "message/send",
+ "params": {
+ "skill": "smart-routing",
+ "messages": [{"role": "user", "content": "Write a Python hello world"}],
+ "metadata": {"model": "auto", "combo": "fast-coding"}
+ }
+ }'
+```
+
+**Response:**
+
+```json
+{
+ "jsonrpc": "2.0",
+ "id": "1",
+ "result": {
+ "task": { "id": "a1b2c3d4-...", "state": "completed" },
+ "artifacts": [{ "type": "text", "content": "print('Hello, World!')" }],
+ "metadata": {
+ "routing_explanation": "Selected claude-sonnet via provider \"anthropic\" (latency: 1200ms, cost: $0.0030)",
+ "cost_envelope": { "estimated": 0.005, "actual": 0.003, "currency": "USD" },
+ "resilience_trace": [
+ { "event": "primary_selected", "provider": "anthropic", "timestamp": "2026-03-04T..." }
+ ],
+ "policy_verdict": { "allowed": true, "reason": "within budget and quota limits" }
+ }
+ }
+}
+```
+
+### `message/stream` — SSE Streaming
+
+Same as `message/send` but returns Server-Sent Events for real-time streaming.
+
+```bash
+curl -N -X POST http://localhost:20128/a2a \
+ -H "Content-Type: application/json" \
+ -H "Authorization: Bearer YOUR_KEY" \
+ -d '{
+ "jsonrpc": "2.0",
+ "id": "1",
+ "method": "message/stream",
+ "params": {
+ "skill": "smart-routing",
+ "messages": [{"role": "user", "content": "Explain quantum computing"}]
+ }
+ }'
+```
+
+**SSE Events:**
+
+```
+data: {"jsonrpc":"2.0","method":"message/stream","params":{"task":{"id":"...","state":"working"},"chunk":{"type":"text","content":"Quantum computing..."}}}
+
+: heartbeat 2026-03-04T21:00:00Z
+
+data: {"jsonrpc":"2.0","method":"message/stream","params":{"task":{"id":"...","state":"completed"},"metadata":{...}}}
+```
+
+### `tasks/get` — Query Task Status
+
+```bash
+curl -X POST http://localhost:20128/a2a \
+ -H "Content-Type: application/json" \
+ -H "Authorization: Bearer YOUR_KEY" \
+ -d '{"jsonrpc":"2.0","id":"2","method":"tasks/get","params":{"taskId":"TASK_UUID"}}'
+```
+
+### `tasks/cancel` — Cancel a Running Task
+
+```bash
+curl -X POST http://localhost:20128/a2a \
+ -H "Content-Type: application/json" \
+ -H "Authorization: Bearer YOUR_KEY" \
+ -d '{"jsonrpc":"2.0","id":"3","method":"tasks/cancel","params":{"taskId":"TASK_UUID"}}'
+```
+
+---
+
+## Skills Reference
+
+### `smart-routing`
+
+Routes prompts through OmniRoute's intelligent pipeline with full observability.
+
+**Parameters (in `metadata`):**
+
+| Parameter | Type | Default | Description |
+| --------- | -------- | ------------ | ---------------------------------------------------------------------------------------- |
+| `model` | `string` | `"auto"` | Target model (e.g., `claude-sonnet-4`, `gpt-4o`, `auto`) |
+| `combo` | `string` | active combo | Specific combo to route through |
+| `budget` | `number` | none | Maximum cost in USD for this request |
+| `role` | `string` | none | Task role hint: `coding`, `review`, `planning`, `analysis`, `debugging`, `documentation` |
+
+**Returns:**
+
+| Field | Description |
+| ------------------------------ | --------------------------------------------------------- |
+| `artifacts[].content` | The LLM response text |
+| `metadata.routing_explanation` | Human-readable explanation of routing decision |
+| `metadata.cost_envelope` | Estimated vs actual cost with currency |
+| `metadata.resilience_trace` | Array of events (primary_selected, fallback_needed, etc.) |
+| `metadata.policy_verdict` | Whether the request was allowed and why |
+
+### `quota-management`
+
+Answers natural-language queries about provider quotas.
+
+**Query types (inferred from message content):**
+
+| Query Pattern | Response Type |
+| ---------------------------------------------- | -------------------------------------------------------- |
+| Contains `"ranking"`, `"most quota"`, `"best"` | Providers ranked by remaining quota |
+| Contains `"free"`, `"suggest"` | Lists free combos or suggests free-tier providers |
+| Default | Full quota summary with warnings for low-quota providers |
+
+---
+
+## Task Lifecycle
+
+```
+submitted ──→ working ──→ completed
+ ──→ failed
+ ──────────→ cancelled
+```
+
+| State | Description |
+| ----------- | ----------------------------------------------------- |
+| `submitted` | Task created, queued for execution |
+| `working` | Skill handler is executing |
+| `completed` | Execution succeeded, artifacts available |
+| `failed` | Execution failed or task expired (TTL: 5 min default) |
+| `cancelled` | Cancelled by client via `tasks/cancel` |
+
+- Terminal states: `completed`, `failed`, `cancelled` (no further transitions)
+- Expired tasks in `submitted` or `working` are auto-marked as `failed`
+- Tasks are garbage-collected after 2× TTL
+
+---
+
+## Client Examples
+
+### Python — Orchestrator Agent
+
+```python
+"""
+A2A Client — Python example.
+Discovers OmniRoute agent, sends a task, and processes the result.
+"""
+import requests
+import json
+
+BASE_URL = "http://localhost:20128"
+API_KEY = "your-api-key"
+HEADERS = {
+ "Content-Type": "application/json",
+ "Authorization": f"Bearer {API_KEY}",
+}
+
+# 1. Discover agent capabilities
+agent_card = requests.get(f"{BASE_URL}/.well-known/agent.json").json()
+print(f"Agent: {agent_card['name']} v{agent_card['version']}")
+print(f"Skills: {[s['id'] for s in agent_card['skills']]}")
+
+# 2. Send a smart-routing task
+response = requests.post(f"{BASE_URL}/a2a", headers=HEADERS, json={
+ "jsonrpc": "2.0",
+ "id": "task-1",
+ "method": "message/send",
+ "params": {
+ "skill": "smart-routing",
+ "messages": [{"role": "user", "content": "Write a Python quicksort implementation"}],
+ "metadata": {
+ "model": "auto",
+ "combo": "fast-coding",
+ "budget": 0.10,
+ }
+ }
+})
+result = response.json()["result"]
+print(f"\n📝 Response: {result['artifacts'][0]['content'][:200]}...")
+print(f"🔀 Routing: {result['metadata']['routing_explanation']}")
+print(f"💰 Cost: ${result['metadata']['cost_envelope']['actual']}")
+print(f"🛡️ Policy: {result['metadata']['policy_verdict']['reason']}")
+
+# 3. Query quota status
+quota_resp = requests.post(f"{BASE_URL}/a2a", headers=HEADERS, json={
+ "jsonrpc": "2.0",
+ "id": "task-2",
+ "method": "message/send",
+ "params": {
+ "skill": "quota-management",
+ "messages": [{"role": "user", "content": "Which provider has the most quota remaining?"}],
+ }
+})
+quota_result = quota_resp.json()["result"]
+print(f"\n📊 Quota: {quota_result['artifacts'][0]['content']}")
+```
+
+### TypeScript — Multi-Agent Orchestrator
+
+```typescript
+/**
+ * A2A Client — TypeScript example.
+ * Shows agent discovery, task delegation, and streaming.
+ */
+
+const BASE_URL = "http://localhost:20128";
+const API_KEY = "your-api-key";
+
+interface JsonRpcResponse {
+ jsonrpc: "2.0";
+ id: string | number;
+ result?: T;
+ error?: { code: number; message: string };
+}
+
+async function a2aCall(method: string, params: Record): Promise {
+ const resp = await fetch(`${BASE_URL}/a2a`, {
+ method: "POST",
+ headers: {
+ "Content-Type": "application/json",
+ Authorization: `Bearer ${API_KEY}`,
+ },
+ body: JSON.stringify({
+ jsonrpc: "2.0",
+ id: `${method}-${Date.now()}`,
+ method,
+ params,
+ }),
+ });
+ const json: JsonRpcResponse = await resp.json();
+ if (json.error) throw new Error(`[${json.error.code}] ${json.error.message}`);
+ return json.result!;
+}
+
+// ── Agent Discovery ──
+const agentCard = await fetch(`${BASE_URL}/.well-known/agent.json`).then((r) => r.json());
+console.log(`Connected to: ${agentCard.name} (${agentCard.skills.length} skills)`);
+
+// ── Smart Routing: Send a coding task ──
+const routingResult = await a2aCall("message/send", {
+ skill: "smart-routing",
+ messages: [{ role: "user", content: "Implement a Redis cache wrapper in TypeScript" }],
+ metadata: { model: "claude-sonnet-4", role: "coding" },
+});
+console.log("Response:", routingResult.artifacts[0].content);
+console.log("Provider:", routingResult.metadata.routing_explanation);
+
+// ── Quota Management: Find free alternatives ──
+const quotaResult = await a2aCall("message/send", {
+ skill: "quota-management",
+ messages: [{ role: "user", content: "Suggest free combos for documentation" }],
+});
+console.log("Free combos:", quotaResult.artifacts[0].content);
+
+// ── Streaming: Real-time response ──
+const streamResp = await fetch(`${BASE_URL}/a2a`, {
+ method: "POST",
+ headers: {
+ "Content-Type": "application/json",
+ Authorization: `Bearer ${API_KEY}`,
+ },
+ body: JSON.stringify({
+ jsonrpc: "2.0",
+ id: "stream-1",
+ method: "message/stream",
+ params: {
+ skill: "smart-routing",
+ messages: [{ role: "user", content: "Explain microservices architecture" }],
+ },
+ }),
+});
+
+const reader = streamResp.body!.getReader();
+const decoder = new TextDecoder();
+while (true) {
+ const { done, value } = await reader.read();
+ if (done) break;
+ const chunk = decoder.decode(value);
+ for (const line of chunk.split("\n")) {
+ if (line.startsWith("data: ")) {
+ const event = JSON.parse(line.slice(6));
+ if (event.params.chunk) {
+ process.stdout.write(event.params.chunk.content);
+ }
+ if (event.params.task.state === "completed") {
+ console.log("\n✅ Stream completed");
+ }
+ }
+ }
+}
+```
+
+### Python — LangChain A2A Integration
+
+```python
+"""
+LangChain integration — Use OmniRoute A2A as a custom LLM.
+"""
+from langchain.llms.base import BaseLLM
+from langchain.schema import LLMResult, Generation
+import requests
+from typing import List, Optional
+
+class OmniRouteA2A(BaseLLM):
+ base_url: str = "http://localhost:20128"
+ api_key: str = ""
+ model: str = "auto"
+ combo: Optional[str] = None
+
+ @property
+ def _llm_type(self) -> str:
+ return "omniroute-a2a"
+
+ def _call(self, prompt: str, stop: Optional[List[str]] = None, **kwargs) -> str:
+ response = requests.post(
+ f"{self.base_url}/a2a",
+ headers={
+ "Content-Type": "application/json",
+ "Authorization": f"Bearer {self.api_key}",
+ },
+ json={
+ "jsonrpc": "2.0",
+ "id": "langchain-1",
+ "method": "message/send",
+ "params": {
+ "skill": "smart-routing",
+ "messages": [{"role": "user", "content": prompt}],
+ "metadata": {
+ "model": self.model,
+ **({"combo": self.combo} if self.combo else {}),
+ },
+ },
+ },
+ )
+ result = response.json()["result"]
+ return result["artifacts"][0]["content"]
+
+ def _generate(self, prompts: List[str], stop=None, **kwargs) -> LLMResult:
+ return LLMResult(
+ generations=[[Generation(text=self._call(p, stop))] for p in prompts]
+ )
+
+# Usage
+llm = OmniRouteA2A(
+ base_url="http://localhost:20128",
+ api_key="your-key",
+ model="auto",
+ combo="fast-coding",
+)
+result = llm("Write a Python function to merge two sorted lists")
+print(result)
+```
+
+### Go — A2A Client
+
+```go
+package main
+
+import (
+ "bytes"
+ "encoding/json"
+ "fmt"
+ "io"
+ "net/http"
+)
+
+const baseURL = "http://localhost:20128"
+const apiKey = "your-api-key"
+
+type JsonRpcRequest struct {
+ Jsonrpc string `json:"jsonrpc"`
+ ID string `json:"id"`
+ Method string `json:"method"`
+ Params interface{} `json:"params"`
+}
+
+type JsonRpcResponse struct {
+ Jsonrpc string `json:"jsonrpc"`
+ ID string `json:"id"`
+ Result interface{} `json:"result"`
+ Error *struct {
+ Code int `json:"code"`
+ Message string `json:"message"`
+ } `json:"error"`
+}
+
+func a2aCall(method string, params interface{}) (*JsonRpcResponse, error) {
+ body, _ := json.Marshal(JsonRpcRequest{
+ Jsonrpc: "2.0",
+ ID: "go-1",
+ Method: method,
+ Params: params,
+ })
+
+ req, _ := http.NewRequest("POST", baseURL+"/a2a", bytes.NewReader(body))
+ req.Header.Set("Content-Type", "application/json")
+ req.Header.Set("Authorization", "Bearer "+apiKey)
+
+ resp, err := http.DefaultClient.Do(req)
+ if err != nil {
+ return nil, err
+ }
+ defer resp.Body.Close()
+ data, _ := io.ReadAll(resp.Body)
+
+ var result JsonRpcResponse
+ json.Unmarshal(data, &result)
+ return &result, nil
+}
+
+func main() {
+ // Discover agent
+ resp, _ := http.Get(baseURL + "/.well-known/agent.json")
+ defer resp.Body.Close()
+ body, _ := io.ReadAll(resp.Body)
+ fmt.Println("Agent Card:", string(body))
+
+ // Send smart-routing task
+ result, _ := a2aCall("message/send", map[string]interface{}{
+ "skill": "smart-routing",
+ "messages": []map[string]string{{"role": "user", "content": "Hello from Go!"}},
+ "metadata": map[string]interface{}{"model": "auto"},
+ })
+ out, _ := json.MarshalIndent(result.Result, "", " ")
+ fmt.Println("Result:", string(out))
+}
+```
+
+---
+
+## Use Cases
+
+### 🤖 Use Case 1: Multi-Agent Coding Pipeline
+
+An orchestrator agent delegates code generation to OmniRoute, then passes the output to a review agent.
+
+```python
+def coding_pipeline(task: str):
+ # Step 1: Generate code via OmniRoute A2A
+ code_result = a2a_send("smart-routing", [
+ {"role": "user", "content": f"Write production-quality code: {task}"}
+ ], metadata={"model": "auto", "role": "coding"})
+ code = code_result["artifacts"][0]["content"]
+
+ # Step 2: Review the code via OmniRoute A2A (different model)
+ review_result = a2a_send("smart-routing", [
+ {"role": "user", "content": f"Review this code for bugs and improvements:\n\n{code}"}
+ ], metadata={"model": "auto", "role": "review"})
+ review = review_result["artifacts"][0]["content"]
+
+ # Step 3: Check costs
+ print(f"Code cost: ${code_result['metadata']['cost_envelope']['actual']}")
+ print(f"Review cost: ${review_result['metadata']['cost_envelope']['actual']}")
+
+ return {"code": code, "review": review}
+```
+
+### 💡 Use Case 2: Quota-Aware Agent Swarm
+
+Multiple agents share quota through OmniRoute, using the quota skill to coordinate.
+
+```python
+async def quota_aware_agent(agent_name: str, task: str):
+ # Check quota before starting
+ quota = a2a_send("quota-management", [
+ {"role": "user", "content": "Which provider has the most quota remaining?"}
+ ])
+ print(f"[{agent_name}] {quota['artifacts'][0]['content']}")
+
+ # Send request with budget constraint
+ result = a2a_send("smart-routing", [
+ {"role": "user", "content": task}
+ ], metadata={"budget": 0.05})
+
+ policy = result["metadata"]["policy_verdict"]
+ if not policy["allowed"]:
+ print(f"[{agent_name}] ⚠️ Budget exceeded: {policy['reason']}")
+ # Fall back to free combo
+ quota = a2a_send("quota-management", [
+ {"role": "user", "content": "Suggest free combos"}
+ ])
+ print(f"[{agent_name}] Free alternatives: {quota['artifacts'][0]['content']}")
+
+ return result
+```
+
+### 📊 Use Case 3: Real-Time Streaming Dashboard
+
+A monitoring agent streams responses and displays progress in real-time.
+
+```typescript
+async function streamingDashboard(prompt: string) {
+ const response = await fetch(`${BASE_URL}/a2a`, {
+ method: "POST",
+ headers: { "Content-Type": "application/json", Authorization: `Bearer ${API_KEY}` },
+ body: JSON.stringify({
+ jsonrpc: "2.0",
+ id: "dash-1",
+ method: "message/stream",
+ params: { skill: "smart-routing", messages: [{ role: "user", content: prompt }] },
+ }),
+ });
+
+ let totalChunks = 0;
+ const reader = response.body!.getReader();
+ const decoder = new TextDecoder();
+
+ while (true) {
+ const { done, value } = await reader.read();
+ if (done) break;
+
+ for (const line of decoder.decode(value).split("\n")) {
+ if (line.startsWith("data: ")) {
+ const event = JSON.parse(line.slice(6));
+ const state = event.params.task.state;
+
+ if (state === "working" && event.params.chunk) {
+ totalChunks++;
+ process.stdout.write(
+ `\r[Chunk ${totalChunks}] ${event.params.chunk.content.slice(0, 50)}...`
+ );
+ }
+ if (state === "completed") {
+ const meta = event.params.metadata;
+ console.log(
+ `\n✅ Done | Cost: $${meta?.cost_envelope?.actual || 0} | Route: ${meta?.routing_explanation || "N/A"}`
+ );
+ }
+ if (state === "failed") {
+ console.error(`\n❌ Failed: ${event.params.metadata?.error}`);
+ }
+ }
+ }
+ }
+}
+```
+
+### 🔁 Use Case 4: Task Polling Pattern
+
+For long-running tasks, poll the task status instead of waiting synchronously.
+
+```python
+import time
+
+def poll_task(task_id: str, timeout: int = 60):
+ """Poll task status until completion or timeout."""
+ start = time.time()
+ while time.time() - start < timeout:
+ result = requests.post(f"{BASE_URL}/a2a", headers=HEADERS, json={
+ "jsonrpc": "2.0",
+ "id": "poll-1",
+ "method": "tasks/get",
+ "params": {"taskId": task_id},
+ }).json()
+
+ task = result["result"]["task"]
+ state = task["state"]
+ print(f" Task {task_id[:8]}... state={state}")
+
+ if state in ("completed", "failed", "cancelled"):
+ return task
+ time.sleep(2)
+
+ # Timeout — cancel the task
+ requests.post(f"{BASE_URL}/a2a", headers=HEADERS, json={
+ "jsonrpc": "2.0",
+ "id": "cancel-1",
+ "method": "tasks/cancel",
+ "params": {"taskId": task_id},
+ })
+ raise TimeoutError(f"Task {task_id} timed out after {timeout}s")
+```
+
+---
+
+## Error Codes
+
+| Code | Constant | Meaning |
+| ------ | ------------------------ | ---------------------------------------- |
+| -32700 | — | Parse error (invalid JSON) |
+| -32600 | `INVALID_REQUEST` | Invalid JSON-RPC request or unauthorized |
+| -32601 | `METHOD_NOT_FOUND` | Unknown method or skill |
+| -32602 | `INVALID_PARAMS` | Missing or invalid parameters |
+| -32603 | `INTERNAL_ERROR` | Skill execution failed |
+| -32001 | `TASK_NOT_FOUND` | Task ID not found |
+| -32002 | `TASK_ALREADY_COMPLETED` | Cannot modify a completed task |
+| -32003 | `UNAUTHORIZED` | Invalid or missing API key |
+| -32004 | `BUDGET_EXCEEDED` | Request exceeds configured budget |
+| -32005 | `PROVIDER_UNAVAILABLE` | No available providers |
+
+---
+
+## Authentication
+
+All `/a2a` requests require a Bearer token via the `Authorization` header:
+
+```
+Authorization: Bearer YOUR_OMNIROUTE_API_KEY
+```
+
+If no API key is configured on the server (`OMNIROUTE_API_KEY` is empty), authentication is bypassed.
+
+---
+
+## File Structure
+
+```
+src/lib/a2a/
+├── taskManager.ts # Task lifecycle (create/update/cancel/list), TTL, cleanup
+├── taskExecution.ts # Generic task executor with state management
+├── streaming.ts # SSE stream formatting, heartbeat, chunk/completion events
+├── routingLogger.ts # Routing decision logger (stats, history, retention)
+└── skills/
+ ├── smartRouting.ts # Smart routing skill (routes via /v1/chat/completions)
+ └── quotaManagement.ts # Quota management skill (natural-language quota queries)
+
+src/app/a2a/
+└── route.ts # Next.js API route handler (JSON-RPC 2.0 dispatch)
+
+open-sse/mcp-server/
+└── schemas/a2a.ts # Zod schemas (AgentCard, Task, JSON-RPC, SSE events)
+```
+
+---
+
+## Comparison: MCP vs A2A
+
+| Feature | MCP Server | A2A Server |
+| ----------------- | ---------------------------- | ------------------------------------------------- |
+| **Protocol** | Model Context Protocol | Agent-to-Agent Protocol v0.3 |
+| **Transport** | stdio / HTTP | HTTP (JSON-RPC 2.0) |
+| **Discovery** | Tool listing via MCP | `/.well-known/agent.json` |
+| **Granularity** | 16 individual tools | 2 high-level skills |
+| **Best for** | IDE agents (Cursor, VS Code) | Multi-agent systems (LangChain, CrewAI) |
+| **Streaming** | Not supported | SSE via `message/stream` |
+| **Task tracking** | No | Full lifecycle (submitted → completed) |
+| **Observability** | Audit log per tool call | Cost envelope + resilience trace + policy verdict |
+
+---
+
+## الرخصة
+
+Part of [OmniRoute](https://github.com/diegosouzapw/OmniRoute) — MIT License.
diff --git a/docs/i18n/bg/CHANGELOG.md b/docs/i18n/bg/CHANGELOG.md
index 1a1b54d984..ad4d497a74 100644
--- a/docs/i18n/bg/CHANGELOG.md
+++ b/docs/i18n/bg/CHANGELOG.md
@@ -1,12 +1,92 @@
# Changelog (Български)
-🌐 **Languages:** 🇺🇸 [English](../../../CHANGELOG.md) · 🇪🇸 [es](../es/CHANGELOG.md) · 🇫🇷 [fr](../fr/CHANGELOG.md) · 🇩🇪 [de](../de/CHANGELOG.md) · 🇮🇹 [it](../it/CHANGELOG.md) · 🇷🇺 [ru](../ru/CHANGELOG.md) · 🇨🇳 [zh-CN](../zh-CN/CHANGELOG.md) · 🇯🇵 [ja](../ja/CHANGELOG.md) · 🇰🇷 [ko](../ko/CHANGELOG.md) · 🇸🇦 [ar](../ar/CHANGELOG.md) · 🇮🇳 [in](../in/CHANGELOG.md) · 🇹🇭 [th](../th/CHANGELOG.md) · 🇻🇳 [vi](../vi/CHANGELOG.md) · 🇮🇩 [id](../id/CHANGELOG.md) · 🇲🇾 [ms](../ms/CHANGELOG.md) · 🇳🇱 [nl](../nl/CHANGELOG.md) · 🇵🇱 [pl](../pl/CHANGELOG.md) · 🇸🇪 [sv](../sv/CHANGELOG.md) · 🇳🇴 [no](../no/CHANGELOG.md) · 🇩🇰 [da](../da/CHANGELOG.md) · 🇫🇮 [fi](../fi/CHANGELOG.md) · 🇵🇹 [pt](../pt/CHANGELOG.md) · 🇷🇴 [ro](../ro/CHANGELOG.md) · 🇭🇺 [hu](../hu/CHANGELOG.md) · 🇧🇬 [bg](../bg/CHANGELOG.md) · 🇸🇰 [sk](../sk/CHANGELOG.md) · 🇺🇦 [uk-UA](../uk-UA/CHANGELOG.md) · 🇮🇱 [he](../he/CHANGELOG.md) · 🇵🇭 [phi](../phi/CHANGELOG.md) · 🇧🇷 [pt-BR](../pt-BR/CHANGELOG.md)
+🌐 **Languages:** 🇺🇸 [English](../../../CHANGELOG.md) · 🇪🇸 [es](../es/CHANGELOG.md) · 🇫🇷 [fr](../fr/CHANGELOG.md) · 🇩🇪 [de](../de/CHANGELOG.md) · 🇮🇹 [it](../it/CHANGELOG.md) · 🇷🇺 [ru](../ru/CHANGELOG.md) · 🇨🇳 [zh-CN](../zh-CN/CHANGELOG.md) · 🇯🇵 [ja](../ja/CHANGELOG.md) · 🇰🇷 [ko](../ko/CHANGELOG.md) · 🇸🇦 [ar](../ar/CHANGELOG.md) · 🇮🇳 [in](../in/CHANGELOG.md) · 🇹🇭 [th](../th/CHANGELOG.md) · 🇻🇳 [vi](../vi/CHANGELOG.md) · 🇮🇩 [id](../id/CHANGELOG.md) · 🇲🇾 [ms](../ms/CHANGELOG.md) · 🇳🇱 [nl](../nl/CHANGELOG.md) · 🇵🇱 [pl](../pl/CHANGELOG.md) · 🇸🇪 [sv](../sv/CHANGELOG.md) · 🇳🇴 [no](../no/CHANGELOG.md) · 🇩🇰 [da](../da/CHANGELOG.md) · 🇫🇮 [fi](../fi/CHANGELOG.md) · 🇵🇹 [pt](../pt/CHANGELOG.md) · 🇷🇴 [ro](../ro/CHANGELOG.md) · 🇭🇺 [hu](../hu/CHANGELOG.md) · 🇧🇬 [bg](../bg/CHANGELOG.md) · 🇸🇰 [sk](../sk/CHANGELOG.md) · 🇺🇦 [uk-UA](../uk-UA/CHANGELOG.md) · 🇮🇱 [he](../he/CHANGELOG.md) · 🇵🇭 [phi](../phi/CHANGELOG.md) · 🇧🇷 [pt-BR](../pt-BR/CHANGELOG.md) · 🇨🇿 [cs](../cs/CHANGELOG.md)
---
-
## [Unreleased]
+### 🛠️ Maintenance
+
+- **AGENTS.md rewrite:** Condensed from 297→153 lines. Added build/lint/test commands (including single-test execution), code style guidelines (Prettier, TypeScript, ESLint, naming, imports, error handling, security), and trimmed verbose architecture tables for AI agent consumption.
+
+## [3.4.2] - 2026-04-01
+
+### 🐛 Bug Fixes
+
+- **CI Stabilization:** Fixed failing analytics/settings Playwright selectors and request assertions so GitHub Actions E2E runs pass reliably across localized UIs and switch-based controls.
+- **Deterministic Tests:** Removed date-sensitive quota fixtures from Copilot usage tests and aligned idempotency/model catalog tests with the merged runtime behavior.
+- **MCP Type Hardening:** Removed zero-budget explicit `any` regressions from the MCP server tool registration path, restoring the `check:any-budget:t11` workflow gate.
+
+### 🛠️ Maintenance
+
+- **Release Branch Integration:** Consolidated the active feature branches into `release/v3.4.2` on top of current `main` and validated the branch with lint, unit, coverage, build, and CI-mode E2E runs.
+
+## [3.4.1] - 2026-03-31
+
+> [!WARNING]
+> **BREAKING CHANGE: request logging, retention, and logging environment variables have been redesigned.**
+> On the first startup after upgrading, OmniRoute archives legacy request logs from `DATA_DIR/logs/`, legacy `DATA_DIR/call_logs/`, and `DATA_DIR/log.txt` into `DATA_DIR/log_archives/*.zip`, then removes the deprecated layout and switches to the new unified artifact format under `DATA_DIR/call_logs/`.
+
+### ✨ New Features
+
+- **.ENV Migration Utility:** Included `scripts/migrate-env.mjs` to seamlessly migrate `= 18 < 24 (recommended: 22 LTS)
+- **npm** 10+
+- **Git**
+
+### Clone & Install
+
+```bash
+git clone https://github.com/diegosouzapw/OmniRoute.git
+cd OmniRoute
+npm install
+```
+
+### Environment Variables
+
+```bash
+# Create your .env from the template
+cp .env.example .env
+
+# Generate required secrets
+echo "JWT_SECRET=$(openssl rand -base64 48)" >> .env
+echo "API_KEY_SECRET=$(openssl rand -hex 32)" >> .env
+```
+
+Key variables for development:
+
+| Variable | Development Default | Description |
+| ---------------------- | ------------------------ | --------------------- |
+| `PORT` | `20128` | Server port |
+| `NEXT_PUBLIC_BASE_URL` | `http://localhost:20128` | Base URL for frontend |
+| `JWT_SECRET` | (generate above) | JWT signing secret |
+| `INITIAL_PASSWORD` | `CHANGEME` | First login password |
+| `APP_LOG_LEVEL` | `info` | Log verbosity level |
+
+### Dashboard Settings
+
+The dashboard provides UI toggles for features that can also be configured via environment variables:
+
+| Setting Location | Toggle | Description |
+| ------------------- | ------------------ | ------------------------------ |
+| Settings → Advanced | Debug Mode | Enable debug request logs (UI) |
+| Settings → General | Sidebar Visibility | Show/hide sidebar sections |
+
+These settings are stored in the database and persist across restarts, overriding env var defaults when set.
+
+### Running Locally
+
+```bash
+# Development mode (hot reload)
+npm run dev
+
+# Production build
+npm run build
+npm run start
+
+# Common port configuration
+PORT=20128 NEXT_PUBLIC_BASE_URL=http://localhost:20128 npm run dev
+```
+
+Default URLs:
+
+- **Dashboard**: `http://localhost:20128/dashboard`
+- **API**: `http://localhost:20128/v1`
+
+---
+
+## Git Workflow
+
+> ⚠️ **NEVER commit directly to `main`.** Always use feature branches.
+
+```bash
+git checkout -b feat/your-feature-name
+# ... make changes ...
+git commit -m "feat: describe your change"
+git push -u origin feat/your-feature-name
+# Open a Pull Request on GitHub
+```
+
+### Branch Naming
+
+| Prefix | Purpose |
+| ----------- | ------------------------- |
+| `feat/` | New features |
+| `fix/` | Bug fixes |
+| `refactor/` | Code restructuring |
+| `docs/` | Documentation changes |
+| `test/` | Test additions/fixes |
+| `chore/` | Tooling, CI, dependencies |
+
+### Commit Messages
+
+Follow [Conventional Commits](https://www.conventionalcommits.org/):
+
+```
+feat: add circuit breaker for provider calls
+fix: resolve JWT secret validation edge case
+docs: update SECURITY.md with PII protection
+test: add observability unit tests
+refactor(db): consolidate rate limit tables
+```
+
+Scopes: `db`, `sse`, `oauth`, `dashboard`, `api`, `cli`, `docker`, `ci`, `mcp`, `a2a`, `memory`, `skills`.
+
+---
+
+## Running Tests
+
+```bash
+# All tests (unit + vitest + ecosystem + e2e)
+npm run test:all
+
+# Single test file (Node.js native test runner — most tests use this)
+node --import tsx/esm --test tests/unit/your-file.test.mjs
+
+# Vitest (MCP server, autoCombo, cache)
+npm run test:vitest
+
+# E2E tests (requires Playwright)
+npm run test:e2e
+
+# Protocol clients E2E (MCP transports, A2A)
+npm run test:protocols:e2e
+
+# Ecosystem compatibility tests
+npm run test:ecosystem
+
+# Coverage (55% min statements/lines/functions; 60% branches)
+npm run test:coverage
+npm run coverage:report
+
+# Lint + format check
+npm run lint
+npm run check
+```
+
+Coverage notes:
+
+- `npm run test:coverage` measures source coverage for the main unit test suite, excludes `tests/**`, and includes `open-sse/**`
+- `npm run coverage:report` prints the detailed file-by-file report from the latest coverage run
+- `npm run test:coverage:legacy` preserves the older metric for historical comparison
+- See `docs/COVERAGE_PLAN.md` for the phased coverage improvement roadmap
+
+Current test status: **122 unit test files** covering:
+
+- Provider translators and format conversion
+- Rate limiting, circuit breaker, and resilience
+- Semantic cache, idempotency, progress tracking
+- Database operations and schema (21 DB modules)
+- OAuth flows and authentication
+- API endpoint validation (Zod v4)
+- MCP server tools and scope enforcement
+- Memory and Skills systems
+
+---
+
+## Code Style
+
+- **ESLint** — Run `npm run lint` before committing
+- **Prettier** — Auto-formatted via `lint-staged` on commit (2 spaces, semicolons, double quotes, 100 char width, es5 trailing commas)
+- **TypeScript** — All `src/` code uses `.ts`/`.tsx`; `open-sse/` uses `.ts`/`.js`; document with TSDoc (`@param`, `@returns`, `@throws`)
+- **No `eval()`** — ESLint enforces `no-eval`, `no-implied-eval`, `no-new-func`
+- **Zod validation** — Use Zod v4 schemas for all API input validation
+- **Naming**: Files = camelCase/kebab-case, components = PascalCase, constants = UPPER_SNAKE
+
+---
+
+## Project Structure
+
+```
+src/ # TypeScript (.ts / .tsx)
+├── app/ # Next.js 16 App Router
+│ ├── (dashboard)/ # Dashboard pages (23 sections)
+│ ├── api/ # API routes (51 directories)
+│ └── login/ # Auth pages (.tsx)
+├── domain/ # Policy engine (policyEngine, comboResolver, costRules, etc.)
+├── lib/ # Core business logic (.ts)
+│ ├── a2a/ # Agent-to-Agent v0.3 protocol server
+│ ├── acp/ # Agent Communication Protocol registry
+│ ├── compliance/ # Compliance policy engine
+│ ├── db/ # SQLite database layer (21 modules + 16 migrations)
+│ ├── memory/ # Persistent conversational memory
+│ ├── oauth/ # OAuth providers, services, and utilities
+│ ├── skills/ # Extensible skill framework
+│ ├── usage/ # Usage tracking and cost calculation
+│ └── localDb.ts # Re-export layer only — never add logic here
+├── middleware/ # Request middleware (promptInjectionGuard)
+├── mitm/ # MITM proxy (cert, DNS, target routing)
+├── shared/
+│ ├── components/ # React components (.tsx)
+│ ├── constants/ # Provider definitions (60+), MCP scopes, routing strategies
+│ ├── utils/ # Circuit breaker, sanitizer, auth helpers
+│ └── validation/ # Zod v4 schemas
+└── sse/ # SSE proxy pipeline
+
+open-sse/ # @omniroute/open-sse workspace
+├── executors/ # 14 provider-specific request executors
+├── handlers/ # 11 request handlers (chat, responses, embeddings, images, etc.)
+├── mcp-server/ # MCP server (25 tools, 3 transports, 10 scopes)
+├── services/ # 36+ services (combo, autoCombo, rateLimitManager, etc.)
+├── translator/ # Format translators (OpenAI ↔ Claude ↔ Gemini ↔ Responses ↔ Ollama)
+├── transformer/ # Responses API transformer
+└── utils/ # 22 utility modules (stream, TLS, proxy, logging)
+
+electron/ # Electron desktop app (cross-platform)
+
+tests/
+├── unit/ # Node.js test runner (122 test files)
+├── integration/ # Integration tests
+├── e2e/ # Playwright tests
+├── security/ # Security tests
+├── translator/ # Translator-specific tests
+└── load/ # Load tests
+
+docs/ # Documentation
+├── ARCHITECTURE.md # System architecture
+├── API_REFERENCE.md # All endpoints
+├── USER_GUIDE.md # Provider setup, CLI integration
+├── TROUBLESHOOTING.md # Common issues
+├── MCP-SERVER.md # MCP server (25 tools)
+├── A2A-SERVER.md # A2A agent protocol
+├── AUTO-COMBO.md # Auto-combo engine
+├── CLI-TOOLS.md # CLI tools integration
+├── COVERAGE_PLAN.md # Test coverage improvement plan
+├── openapi.yaml # OpenAPI specification
+└── adr/ # Architecture Decision Records
+```
+
+---
+
+## Adding a New Provider
+
+### Step 1: Register Provider Constants
+
+Add to `src/shared/constants/providers.ts` — Zod-validated at module load.
+
+### Step 2: Add Executor (if custom logic needed)
+
+Create executor in `open-sse/executors/your-provider.ts` extending the base executor.
+
+### Step 3: Add Translator (if non-OpenAI format)
+
+Create request/response translators in `open-sse/translator/`.
+
+### Step 4: Add OAuth Config (if OAuth-based)
+
+Add OAuth credentials in `src/lib/oauth/constants/oauth.ts` and service in `src/lib/oauth/services/`.
+
+### Step 5: Register Models
+
+Add model definitions in `open-sse/config/providerRegistry.ts`.
+
+### Step 6: Add Tests
+
+Write unit tests in `tests/unit/` covering at minimum:
+
+- Provider registration
+- Request/response translation
+- Error handling
+
+---
+
+## Pull Request Checklist
+
+- [ ] Tests pass (`npm test`)
+- [ ] Linting passes (`npm run lint`)
+- [ ] Build succeeds (`npm run build`)
+- [ ] TypeScript types added for new public functions and interfaces
+- [ ] No hardcoded secrets or fallback values
+- [ ] All inputs validated with Zod schemas
+- [ ] CHANGELOG updated (if user-facing change)
+- [ ] Documentation updated (if applicable)
+
+---
+
+## Releasing
+
+Releases are managed via the `/generate-release` workflow. When a new GitHub Release is created, the package is **automatically published to npm** via GitHub Actions.
+
+---
+
+## Getting Help
+
+- **Architecture**: See [`docs/ARCHITECTURE.md`](docs/ARCHITECTURE.md)
+- **API Reference**: See [`docs/API_REFERENCE.md`](docs/API_REFERENCE.md)
+- **Issues**: [github.com/diegosouzapw/OmniRoute/issues](https://github.com/diegosouzapw/OmniRoute/issues)
+- **ADRs**: See `docs/adr/` for architectural decision records
diff --git a/docs/i18n/bg/FEATURES.md b/docs/i18n/bg/FEATURES.md
deleted file mode 100644
index 5df3ee54bf..0000000000
--- a/docs/i18n/bg/FEATURES.md
+++ /dev/null
@@ -1,147 +0,0 @@
-# OmniRoute — Dashboard Features Gallery (Български)
-
-🌐 **Languages:** 🇺🇸 [English](../../../README.md) · 🇧🇷 [pt-BR](../pt-BR/README.md) · 🇪🇸 [es](../es/README.md) · 🇫🇷 [fr](../fr/README.md) · 🇩🇪 [de](../de/README.md) · 🇮🇹 [it](../it/README.md) · 🇷🇺 [ru](../ru/README.md) · 🇨🇳 [zh-CN](../zh-CN/README.md) · 🇯🇵 [ja](../ja/README.md) · 🇰🇷 [ko](../ko/README.md) · 🇸🇦 [ar](../ar/README.md) · 🇮🇳 [in](../in/README.md) · 🇹🇭 [th](../th/README.md) · 🇻🇳 [vi](../vi/README.md) · 🇮🇩 [id](../id/README.md) · 🇲🇾 [ms](../ms/README.md) · 🇳🇱 [nl](../nl/README.md) · 🇵🇱 [pl](../pl/README.md) · 🇸🇪 [sv](../sv/README.md) · 🇳🇴 [no](../no/README.md) · 🇩🇰 [da](../da/README.md) · 🇫🇮 [fi](../fi/README.md) · 🇵🇹 [pt](../pt/README.md) · 🇷🇴 [ro](../ro/README.md) · 🇭🇺 [hu](../hu/README.md) · 🇧🇬 [bg](../bg/README.md) · 🇸🇰 [sk](../sk/README.md) · 🇺🇦 [uk-UA](../uk-UA/README.md) · 🇮🇱 [he](../he/README.md) · 🇵🇭 [phi](../phi/README.md)
-
-> 🇺🇸 [English](../../../docs/FEATURES.md)
-
----
-
-Visual guide to every section of the OmniRoute dashboard.
-
----
-
-## 🔌 Providers
-
-Manage AI provider connections: OAuth providers (Claude Code, Codex, Gemini CLI), API key providers (Groq, DeepSeek, OpenRouter), and free providers (Qoder, Qwen, Kiro). Kiro accounts include credit balance tracking — remaining credits, total allowance, and renewal date visible in Dashboard → Usage.
-
-
-
----
-
-## 🎨 Combos
-
-Create model routing combos with 6 strategies: priority, weighted, round-robin, random, least-used, and cost-optimized. Each combo chains multiple models with automatic fallback and includes quick templates and readiness checks.
-
-
-
----
-
-## 📊 Analytics
-
-Comprehensive usage analytics with token consumption, cost estimates, activity heatmaps, weekly distribution charts, and per-provider breakdowns.
-
-
-
----
-
-## 🏥 System Health
-
-Real-time monitoring: uptime, memory, version, latency percentiles (p50/p95/p99), cache statistics, and provider circuit breaker states.
-
-
-
----
-
-## 🔧 Translator Playground
-
-Four modes for debugging API translations: **Playground** (format converter), **Chat Tester** (live requests), **Test Bench** (batch tests), and **Live Monitor** (real-time stream).
-
-
-
----
-
-## 🎮 Model Playground _(v2.0.9+)_
-
-Test any model directly from the dashboard. Select provider, model, and endpoint, write prompts with Monaco Editor, stream responses in real-time, abort mid-stream, and view timing metrics.
-
----
-
-## 🎨 Themes _(v2.0.5+)_
-
-Customizable color themes for the entire dashboard. Choose from 7 preset colors (Coral, Blue, Red, Green, Violet, Orange, Cyan) or create a custom theme by picking any hex color. Supports light, dark, and system mode.
-
----
-
-## ⚙️ Settings
-
-Comprehensive settings panel with tabs:
-
-- **General** — System storage, backup management (export/import database)
-- **Appearance** — Theme selector (dark/light/system), color theme presets and custom colors, health log visibility, sidebar item visibility controls
-- **Security** — API endpoint protection, custom provider blocking, IP filtering, session info
-- **Routing** — Model aliases, background task degradation
-- **Resilience** — Rate limit persistence, circuit breaker tuning
-- **Advanced** — Configuration overrides
-
-
-
----
-
-## 🔧 CLI Tools
-
-One-click configuration for AI coding tools: Claude Code, Codex CLI, Gemini CLI, OpenClaw, Kilo Code, Antigravity, Cline, Continue, Cursor, and Factory Droid. Features automated config apply/reset, connection profiles, and model mapping.
-
-
-
----
-
-## 🤖 CLI Agents _(v2.0.11+)_
-
-Dashboard for discovering and managing CLI agents. Shows a grid of 14 built-in agents (Codex, Claude, Goose, Gemini CLI, OpenClaw, Aider, OpenCode, Cline, Qwen Code, ForgeCode, Amazon Q, Open Interpreter, Cursor CLI, Warp) with:
-
-- **Installation status** — Installed / Not Found with version detection
-- **Protocol badges** — stdio, HTTP, etc.
-- **Custom agents** — Register any CLI tool via form (name, binary, version command, spawn args)
-- **CLI Fingerprint Matching** — Per-provider toggle to match native CLI request signatures, reducing ban risk while preserving proxy IP
-
----
-
-## 🖼️ Media _(v2.0.3+)_
-
-Generate images, videos, and music from the dashboard. Supports OpenAI, xAI, Together, Hyperbolic, SD WebUI, ComfyUI, AnimateDiff, Stable Audio Open, and MusicGen.
-
----
-
-## 📝 Request Logs
-
-Real-time request logging with filtering by provider, model, account, and API key. Shows status codes, token usage, latency, and response details.
-
-
-
----
-
-## 🌐 API Endpoint
-
-Your unified API endpoint with capability breakdown: Chat Completions, Responses API, Embeddings, Image Generation, Reranking, Audio Transcription, Text-to-Speech, Moderations, and registered API keys. Cloud proxy support for remote access.
-
-
-
----
-
-## 🔑 API Key Management
-
-Create, scope, and revoke API keys. Each key can be restricted to specific models/providers with full access or read-only permissions. Visual key management with usage tracking.
-
----
-
-## 📋 Audit Log
-
-Administrative action tracking with filtering by action type, actor, target, IP address, and timestamp. Full security event history.
-
----
-
-## 🖥️ Desktop Application
-
-Native Electron desktop app for Windows, macOS, and Linux. Run OmniRoute as a standalone application with system tray integration, offline support, auto-update, and one-click install.
-
-Key features:
-
-- Server readiness polling (no blank screen on cold start)
-- System tray with port management
-- Content Security Policy
-- Single-instance lock
-- Auto-update on restart
-- Platform-conditional UI (macOS traffic lights, Windows/Linux default titlebar)
-- Hardened Electron build packaging — symlinked `node_modules` in the standalone bundle is detected and rejected before packaging, preventing runtime dependency on the build machine (v2.5.5+)
-
-📖 See [`electron/README.md`](../electron/README.md) for full documentation.
diff --git a/docs/i18n/bg/README.md b/docs/i18n/bg/README.md
index 2161b8281d..15dfbef8b7 100644
--- a/docs/i18n/bg/README.md
+++ b/docs/i18n/bg/README.md
@@ -1,13 +1,12 @@
# 🚀 OmniRoute — The Free AI Gateway (Български)
-🌐 **Languages:** 🇺🇸 [English](../../../README.md) · 🇪🇸 [es](../es/README.md) · 🇫🇷 [fr](../fr/README.md) · 🇩🇪 [de](../de/README.md) · 🇮🇹 [it](../it/README.md) · 🇷🇺 [ru](../ru/README.md) · 🇨🇳 [zh-CN](../zh-CN/README.md) · 🇯🇵 [ja](../ja/README.md) · 🇰🇷 [ko](../ko/README.md) · 🇸🇦 [ar](../ar/README.md) · 🇮🇳 [in](../in/README.md) · 🇹🇭 [th](../th/README.md) · 🇻🇳 [vi](../vi/README.md) · 🇮🇩 [id](../id/README.md) · 🇲🇾 [ms](../ms/README.md) · 🇳🇱 [nl](../nl/README.md) · 🇵🇱 [pl](../pl/README.md) · 🇸🇪 [sv](../sv/README.md) · 🇳🇴 [no](../no/README.md) · 🇩🇰 [da](../da/README.md) · 🇫🇮 [fi](../fi/README.md) · 🇵🇹 [pt](../pt/README.md) · 🇷🇴 [ro](../ro/README.md) · 🇭🇺 [hu](../hu/README.md) · 🇧🇬 [bg](../bg/README.md) · 🇸🇰 [sk](../sk/README.md) · 🇺🇦 [uk-UA](../uk-UA/README.md) · 🇮🇱 [he](../he/README.md) · 🇵🇭 [phi](../phi/README.md) · 🇧🇷 [pt-BR](../pt-BR/README.md)
+🌐 **Languages:** 🇺🇸 [English](../../../README.md) · 🇪🇸 [es](../es/README.md) · 🇫🇷 [fr](../fr/README.md) · 🇩🇪 [de](../de/README.md) · 🇮🇹 [it](../it/README.md) · 🇷🇺 [ru](../ru/README.md) · 🇨🇳 [zh-CN](../zh-CN/README.md) · 🇯🇵 [ja](../ja/README.md) · 🇰🇷 [ko](../ko/README.md) · 🇸🇦 [ar](../ar/README.md) · 🇮🇳 [in](../in/README.md) · 🇹🇭 [th](../th/README.md) · 🇻🇳 [vi](../vi/README.md) · 🇮🇩 [id](../id/README.md) · 🇲🇾 [ms](../ms/README.md) · 🇳🇱 [nl](../nl/README.md) · 🇵🇱 [pl](../pl/README.md) · 🇸🇪 [sv](../sv/README.md) · 🇳🇴 [no](../no/README.md) · 🇩🇰 [da](../da/README.md) · 🇫🇮 [fi](../fi/README.md) · 🇵🇹 [pt](../pt/README.md) · 🇷🇴 [ro](../ro/README.md) · 🇭🇺 [hu](../hu/README.md) · 🇧🇬 [bg](../bg/README.md) · 🇸🇰 [sk](../sk/README.md) · 🇺🇦 [uk-UA](../uk-UA/README.md) · 🇮🇱 [he](../he/README.md) · 🇵🇭 [phi](../phi/README.md) · 🇧🇷 [pt-BR](../pt-BR/README.md) · 🇨🇿 [cs](../cs/README.md)
---
-
### Never stop coding. Smart routing to **FREE & low-cost AI models** with automatic fallback.
-_Your universal API proxy — one endpoint, 67+ providers, zero downtime. Now with **MCP & A2A** agent orchestration._
+_Your universal API proxy — one endpoint, 60+ providers, zero downtime. Now with **MCP Server (25 tools)**, **A2A Protocol**, **Memory/Skills Systems** & **Electron Desktop App**._
**Chat Completions • Embeddings • Image Generation • Video • Music • Audio • Reranking • **Web Search** • MCP Server • A2A Protocol • 100% TypeScript**
@@ -47,15 +46,17 @@ _Your universal API proxy — one endpoint, 67+ providers, zero downtime. Now wi
> - `APP_LOG_FILE_PATH`
> - `APP_LOG_MAX_FILE_SIZE`
> - `APP_LOG_RETENTION_DAYS`
+> - `APP_LOG_MAX_FILES`
> - `APP_LOG_LEVEL`
> - `APP_LOG_FORMAT`
> - `CALL_LOG_RETENTION_DAYS`
+> - `CALL_LOG_MAX_ENTRIES`
>
> For release details and upgrade notes, see the [CHANGELOG](CHANGELOG.md).
---
-## 🆕 What's New in v3.0.0
+## 🆕 What's New
> **Upgrading from v2.9.5?** — See the [full CHANGELOG](CHANGELOG.md#300--2026-03-22-release-candidate--not-yet-merged-to-main) for all changes.
@@ -275,7 +276,7 @@ Developers pay $20–200/month for Claude Pro, Codex Pro, or GitHub Copilot. Eve
- **Smart 4-Tier Fallback** — If subscription quota runs out, automatically redirects to API Key → Cheap → Free with zero manual intervention
- **Real-Time Quota Tracking** — Shows token consumption in real-time with reset countdown (5h, daily, weekly)
- **Multi-Account Support** — Multiple accounts per provider with auto round-robin — when one runs out, switches to the next
-- **Custom Combos** — Customizable fallback chains with 6 balancing strategies (fill-first, round-robin, P2C, random, least-used, cost-optimized)
+- **Custom Combos** — Customizable fallback chains with 9 balancing strategies (priority, weighted, fill-first, round-robin, P2C, random, least-used, cost-optimized, strict-random)
- **Codex Business Quotas** — Business/Team workspace quota monitoring directly in the dashboard
@@ -287,7 +288,7 @@ OpenAI uses one format, Claude (Anthropic) uses another, Gemini yet another. If
**How OmniRoute solves it:**
-- **Unified Endpoint** — A single `http://localhost:20128/v1` serves as proxy for all 67+ providers
+- **Unified Endpoint** — A single `http://localhost:20128/v1` serves as proxy for all 60+ providers
- **Format Translation** — Automatic and transparent: OpenAI ↔ Claude ↔ Gemini ↔ Responses API
- **Response Sanitization** — Strips non-standard fields (`x_groq`, `usage_breakdown`, `service_tier`) that break OpenAI SDK v1.83+
- **Role Normalization** — Converts `developer` → `system` for non-OpenAI providers; `system` → `user` for GLM/ERNIE
@@ -373,7 +374,7 @@ Developers use Cursor, Claude Code, Codex CLI, OpenClaw, Gemini CLI, Kilo Code..
- **CLI Tools Dashboard** — Dedicated page with one-click setup for Claude Code, Codex CLI, OpenClaw, Kilo Code, Antigravity, Cline
- **GitHub Copilot Config Generator** — Generates `chatLanguageModels.json` for VS Code with bulk model selection
- **Onboarding Wizard** — Guided 4-step setup for first-time users
-- **One endpoint, all models** — Configure `http://localhost:20128/v1` once, access 67+ providers
+- **One endpoint, all models** — Configure `http://localhost:20128/v1` once, access 60+ providers
@@ -420,7 +421,7 @@ When a call fails, the dev doesn't know if it was a rate limit, expired token, w
- **SQLite Proxy Logs** — Persistent logs that survive server restarts
- **Translator Playground** — 4 debugging modes: Playground (format translation), Chat Tester (round-trip), Test Bench (batch), Live Monitor (real-time)
- **Request Telemetry** — p50/p95/p99 latency + X-Request-Id tracing
-- **File-Based Logging with Rotation** — Console interceptor captures everything to JSON log with size-based rotation
+- **File-Based Logging with Rotation** — App logs rotate by size, retention days, and archive count; call log artifacts rotate by retention days and file count
- **System Info Report** — `npm run system-info` generates `system-info.txt` with your full environment (Node version, OmniRoute version, OS, CLI tools, Docker/PM2 status). Attach it when reporting issues for instant triage.
@@ -515,7 +516,7 @@ Developers who want all responses in a specific language, with a specific tone,
- **System Prompt Injection** — Global prompt applied to all requests
- **Thinking Budget Validation** — Reasoning token allocation control per request (passthrough, auto, custom, adaptive)
-- **6 Routing Strategies** — Global strategies that determine how requests are distributed
+- **9 Routing Strategies** — Global strategies that determine how requests are distributed
- **Wildcard Router** — `provider/*` patterns route dynamically to any provider
- **Combo Enable/Disable Toggle** — Toggle combos directly from the dashboard
- **Provider Toggle** — Enable/disable all connections for a provider with one click
@@ -582,7 +583,7 @@ Different clients should have least-privilege access to tool categories.
**How OmniRoute solves it:**
-- 9 granular MCP scopes for controlled tool access
+- 10 granular MCP scopes for controlled tool access
- Scope enforcement and visibility in MCP management UI
- Safe default posture for operational tooling
@@ -1326,19 +1327,19 @@ OmniRoute v2.0 is built as an operational platform, not just a relay proxy.
### 🤖 Agent & Protocol Operations (v2.0)
-| Feature | What It Does |
-| ------------------------------------- | -------------------------------------------------------------------------------------------------- |
-| 🔧 **MCP Server (16 tools)** | IDE/agent tools via 3 transports: stdio, SSE (`/api/mcp/sse`), Streamable HTTP (`/api/mcp/stream`) |
-| 🤝 **A2A Server (JSON-RPC + SSE)** | Agent-to-agent task execution with sync and streaming flows |
-| 🧭 **Consolidated Endpoints Page** | Tabbed management page with Endpoint Proxy, MCP, A2A, and API Endpoints tabs |
-| 🎚️ **Service Enable/Disable Toggles** | ON/OFF switches for MCP and A2A with settings persistence (default: OFF) |
-| 🛰️ **MCP Runtime Heartbeat** | Real process status (pid, uptime, heartbeat age, transport, scope mode) |
-| 📋 **MCP Audit Trail** | Filterable audit logs with success/failure and key attribution |
-| 🔐 **MCP Scope Enforcement** | 9 granular scope permissions for controlled tool access |
-| 📡 **A2A Task Lifecycle Management** | List/filter tasks, inspect events/artifacts, cancel running tasks |
-| 📋 **Agent Card Discovery** | `/.well-known/agent.json` for client auto-discovery |
-| 🧪 **Protocol E2E Test Harness** | Real MCP SDK + A2A client flows in `test:protocols:e2e` |
-| ⚙️ **Operational Controls** | Switch combo, apply resilience profiles, reset breakers from one control surface |
+| Feature | What It Does |
+| ------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------- |
+| 🔧 **MCP Server (25 tools)** | IDE/agent tools via 3 transports: stdio, SSE (`/api/mcp/sse`), Streamable HTTP (`/api/mcp/stream`). 18 core + 3 memory + 4 skill tools |
+| 🤝 **A2A Server (JSON-RPC + SSE)** | Agent-to-agent task execution with sync and streaming flows |
+| 🧭 **Consolidated Endpoints Page** | Tabbed management page with Endpoint Proxy, MCP, A2A, and API Endpoints tabs |
+| 🎚️ **Service Enable/Disable Toggles** | ON/OFF switches for MCP and A2A with settings persistence (default: OFF) |
+| 🛰️ **MCP Runtime Heartbeat** | Real process status (pid, uptime, heartbeat age, transport, scope mode) |
+| 📋 **MCP Audit Trail** | Filterable audit logs with success/failure and key attribution |
+| 🔐 **MCP Scope Enforcement** | 10 granular scope permissions for controlled tool access |
+| 📡 **A2A Task Lifecycle Management** | List/filter tasks, inspect events/artifacts, cancel running tasks |
+| 📋 **Agent Card Discovery** | `/.well-known/agent.json` for client auto-discovery |
+| 🧪 **Protocol E2E Test Harness** | Real MCP SDK + A2A client flows in `test:protocols:e2e` |
+| ⚙️ **Operational Controls** | Switch combo, apply resilience profiles, reset breakers from one control surface |
### 🧠 Routing & Intelligence
@@ -1349,7 +1350,7 @@ OmniRoute v2.0 is built as an operational platform, not just a relay proxy.
| 🔄 **Format Translation** | OpenAI ↔ Claude ↔ Gemini ↔ Responses with schema-safe conversions |
| 👥 **Multi-Account Support** | Multiple accounts per provider with intelligent selection |
| 🔄 **Auto Token Refresh** | OAuth tokens refresh automatically with retry |
-| 🎨 **Custom Combos** | 6 balancing strategies + fallback chain control |
+| 🎨 **Custom Combos** | 9 balancing strategies + fallback chain control |
| 🌐 **Wildcard Router** | `provider/*` dynamic routing |
| 🧠 **Thinking Budget Controls** | Passthrough, auto, custom, and adaptive reasoning limits |
| 🔀 **Model Aliases** | Built-in + custom model aliasing and migration safety |
@@ -1950,6 +1951,7 @@ opencode
- Request artifacts are written to `DATA_DIR/call_logs/` as one JSON file per request
- Enable pipeline capture from Dashboard → Logs → Request Logs if you need detailed per-stage payloads
- Set `APP_LOG_TO_FILE=true` if you also want application console logs in `logs/application/app.log`
+- Adjust `APP_LOG_MAX_FILE_SIZE`, `APP_LOG_RETENTION_DAYS`, `APP_LOG_MAX_FILES`, and `CALL_LOG_MAX_ENTRIES` as needed
**Connection test shows "Invalid" for OpenAI-compatible providers**
diff --git a/docs/i18n/bg/RELEASE_CHECKLIST.md b/docs/i18n/bg/RELEASE_CHECKLIST.md
deleted file mode 100644
index 903e812c3f..0000000000
--- a/docs/i18n/bg/RELEASE_CHECKLIST.md
+++ /dev/null
@@ -1,37 +0,0 @@
-🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/RELEASE_CHECKLIST.md) · 🇪🇸 [es](../es/RELEASE_CHECKLIST.md) · 🇫🇷 [fr](../fr/RELEASE_CHECKLIST.md) · 🇩🇪 [de](../de/RELEASE_CHECKLIST.md) · 🇮🇹 [it](../it/RELEASE_CHECKLIST.md) · 🇷🇺 [ru](../ru/RELEASE_CHECKLIST.md) · 🇨🇳 [zh-CN](../zh-CN/RELEASE_CHECKLIST.md) · 🇯🇵 [ja](../ja/RELEASE_CHECKLIST.md) · 🇰🇷 [ko](../ko/RELEASE_CHECKLIST.md) · 🇸🇦 [ar](../ar/RELEASE_CHECKLIST.md) · 🇮🇳 [in](../in/RELEASE_CHECKLIST.md) · 🇹🇭 [th](../th/RELEASE_CHECKLIST.md) · 🇻🇳 [vi](../vi/RELEASE_CHECKLIST.md) · 🇮🇩 [id](../id/RELEASE_CHECKLIST.md) · 🇲🇾 [ms](../ms/RELEASE_CHECKLIST.md) · 🇳🇱 [nl](../nl/RELEASE_CHECKLIST.md) · 🇵🇱 [pl](../pl/RELEASE_CHECKLIST.md) · 🇸🇪 [sv](../sv/RELEASE_CHECKLIST.md) · 🇳🇴 [no](../no/RELEASE_CHECKLIST.md) · 🇩🇰 [da](../da/RELEASE_CHECKLIST.md) · 🇫🇮 [fi](../fi/RELEASE_CHECKLIST.md) · 🇵🇹 [pt](../pt/RELEASE_CHECKLIST.md) · 🇷🇴 [ro](../ro/RELEASE_CHECKLIST.md) · 🇭🇺 [hu](../hu/RELEASE_CHECKLIST.md) · 🇧🇬 [bg](../bg/RELEASE_CHECKLIST.md) · 🇸🇰 [sk](../sk/RELEASE_CHECKLIST.md) · 🇺🇦 [uk-UA](../uk-UA/RELEASE_CHECKLIST.md) · 🇮🇱 [he](../he/RELEASE_CHECKLIST.md) · 🇵🇭 [phi](../phi/RELEASE_CHECKLIST.md)
-
----
-
-# Release Checklist
-
-Use this checklist before tagging or publishing a new OmniRoute release.
-
-## Version and Changelog
-
-1. Bump `package.json` version (`x.y.z`) in the release branch.
-2. Move release notes from `## [Unreleased]` in `CHANGELOG.md` to a dated section:
- - `## [x.y.z] — YYYY-MM-DD`
-3. Keep `## [Unreleased]` as the first changelog section for upcoming work.
-4. Ensure the latest semver section in `CHANGELOG.md` equals `package.json` version.
-
-## API Docs
-
-1. Update `docs/openapi.yaml`:
- - `info.version` must equal `package.json` version.
-2. Validate endpoint examples if API contracts changed.
-
-## Runtime Docs
-
-1. Review `docs/ARCHITECTURE.md` for storage/runtime drift.
-2. Review `docs/TROUBLESHOOTING.md` for env var and operational drift.
-3. Update localized docs if source docs changed significantly.
-
-## Automated Check
-
-Run the sync guard locally before opening PR:
-
-```bash
-npm run check:docs-sync
-```
-
-CI also runs this check in `.github/workflows/ci.yml` (lint job).
diff --git a/docs/i18n/bg/SECURITY.md b/docs/i18n/bg/SECURITY.md
new file mode 100644
index 0000000000..aba3c49e3c
--- /dev/null
+++ b/docs/i18n/bg/SECURITY.md
@@ -0,0 +1,179 @@
+# Security Policy (Български)
+
+🌐 **Languages:** 🇺🇸 [English](../../../SECURITY.md) · 🇪🇸 [es](../es/SECURITY.md) · 🇫🇷 [fr](../fr/SECURITY.md) · 🇩🇪 [de](../de/SECURITY.md) · 🇮🇹 [it](../it/SECURITY.md) · 🇷🇺 [ru](../ru/SECURITY.md) · 🇨🇳 [zh-CN](../zh-CN/SECURITY.md) · 🇯🇵 [ja](../ja/SECURITY.md) · 🇰🇷 [ko](../ko/SECURITY.md) · 🇸🇦 [ar](../ar/SECURITY.md) · 🇮🇳 [in](../in/SECURITY.md) · 🇹🇭 [th](../th/SECURITY.md) · 🇻🇳 [vi](../vi/SECURITY.md) · 🇮🇩 [id](../id/SECURITY.md) · 🇲🇾 [ms](../ms/SECURITY.md) · 🇳🇱 [nl](../nl/SECURITY.md) · 🇵🇱 [pl](../pl/SECURITY.md) · 🇸🇪 [sv](../sv/SECURITY.md) · 🇳🇴 [no](../no/SECURITY.md) · 🇩🇰 [da](../da/SECURITY.md) · 🇫🇮 [fi](../fi/SECURITY.md) · 🇵🇹 [pt](../pt/SECURITY.md) · 🇷🇴 [ro](../ro/SECURITY.md) · 🇭🇺 [hu](../hu/SECURITY.md) · 🇧🇬 [bg](../bg/SECURITY.md) · 🇸🇰 [sk](../sk/SECURITY.md) · 🇺🇦 [uk-UA](../uk-UA/SECURITY.md) · 🇮🇱 [he](../he/SECURITY.md) · 🇵🇭 [phi](../phi/SECURITY.md) · 🇧🇷 [pt-BR](../pt-BR/SECURITY.md) · 🇨🇿 [cs](../cs/SECURITY.md)
+
+---
+
+## Reporting Vulnerabilities
+
+If you discover a security vulnerability in OmniRoute, please report it responsibly:
+
+1. **DO NOT** open a public GitHub issue
+2. Use [GitHub Security Advisories](https://github.com/diegosouzapw/OmniRoute/security/advisories/new)
+3. Include: description, reproduction steps, and potential impact
+
+## Response Timeline
+
+| Stage | Target |
+| ------------------- | --------------------------- |
+| Acknowledgment | 48 hours |
+| Triage & Assessment | 5 business days |
+| Patch Release | 14 business days (critical) |
+
+## Supported Versions
+
+| Version | Support Status |
+| ------- | -------------- |
+| 3.4.x | ✅ Active |
+| 3.0.x | ✅ Security |
+| < 3.0.0 | ❌ Unsupported |
+
+---
+
+## Security Architecture
+
+OmniRoute implements a multi-layered security model:
+
+```
+Request → CORS → API Key Auth → Prompt Injection Guard → Input Sanitizer → Rate Limiter → Circuit Breaker → Provider
+```
+
+### 🔐 Authentication & Authorization
+
+| Feature | Implementation |
+| -------------------- | ---------------------------------------------------------- |
+| **Dashboard Login** | Password-based auth with JWT tokens (HttpOnly cookies) |
+| **API Key Auth** | HMAC-signed keys with CRC validation |
+| **OAuth 2.0 + PKCE** | Secure provider auth (Claude, Codex, Gemini, Cursor, etc.) |
+| **Token Refresh** | Automatic OAuth token refresh before expiry |
+| **Secure Cookies** | `AUTH_COOKIE_SECURE=true` for HTTPS environments |
+| **MCP Scopes** | 10 granular scopes for MCP tool access control |
+
+### 🛡️ Encryption at Rest
+
+All sensitive data stored in SQLite is encrypted using **AES-256-GCM** with scrypt key derivation:
+
+- API keys, access tokens, refresh tokens, and ID tokens
+- Versioned format: `enc:v1:::`
+- Passthrough mode (plaintext) when `STORAGE_ENCRYPTION_KEY` is not set
+
+```bash
+# Generate encryption key:
+STORAGE_ENCRYPTION_KEY=$(openssl rand -hex 32)
+```
+
+### 🧠 Prompt Injection Guard
+
+Middleware that detects and blocks prompt injection attacks in LLM requests:
+
+| Pattern Type | Severity | Example |
+| ------------------- | -------- | ---------------------------------------------- |
+| System Override | High | "ignore all previous instructions" |
+| Role Hijack | High | "you are now DAN, you can do anything" |
+| Delimiter Injection | Medium | Encoded separators to break context boundaries |
+| DAN/Jailbreak | High | Known jailbreak prompt patterns |
+| Instruction Leak | Medium | "show me your system prompt" |
+
+Configure via dashboard (Settings → Security) or `.env`:
+
+```env
+INPUT_SANITIZER_ENABLED=true
+INPUT_SANITIZER_MODE=block # warn | block | redact
+```
+
+### 🔒 PII Redaction
+
+Automatic detection and optional redaction of personally identifiable information:
+
+| PII Type | Pattern | Replacement |
+| ------------- | --------------------- | ------------------ |
+| Email | `user@domain.com` | `[EMAIL_REDACTED]` |
+| CPF (Brazil) | `123.456.789-00` | `[CPF_REDACTED]` |
+| CNPJ (Brazil) | `12.345.678/0001-00` | `[CNPJ_REDACTED]` |
+| Credit Card | `4111-1111-1111-1111` | `[CC_REDACTED]` |
+| Phone | `+55 11 99999-9999` | `[PHONE_REDACTED]` |
+| SSN (US) | `123-45-6789` | `[SSN_REDACTED]` |
+
+```env
+PII_REDACTION_ENABLED=true
+```
+
+### 🌐 Network Security
+
+| Feature | Description |
+| ------------------------ | ---------------------------------------------------------------- |
+| **CORS** | Configurable origin control (`CORS_ORIGIN` env var, default `*`) |
+| **IP Filtering** | Allowlist/blocklist IP ranges in dashboard |
+| **Rate Limiting** | Per-provider rate limits with automatic backoff |
+| **Anti-Thundering Herd** | Mutex + per-connection locking prevents cascading 502s |
+| **TLS Fingerprint** | Browser-like TLS fingerprint spoofing to reduce bot detection |
+| **CLI Fingerprint** | Per-provider header/body ordering to match native CLI signatures |
+
+### 🔌 Resilience & Availability
+
+| Feature | Description |
+| ----------------------- | ------------------------------------------------------------------ |
+| **Circuit Breaker** | 3-state (Closed → Open → Half-Open) per provider, SQLite-persisted |
+| **Request Idempotency** | 5-second dedup window for duplicate requests |
+| **Exponential Backoff** | Automatic retry with increasing delays |
+| **Health Dashboard** | Real-time provider health monitoring |
+
+### 📋 Compliance
+
+| Feature | Description |
+| ------------------ | ----------------------------------------------------------- |
+| **Log Retention** | Automatic cleanup after `CALL_LOG_RETENTION_DAYS` |
+| **No-Log Opt-out** | Per API key `noLog` flag disables request logging |
+| **Audit Log** | Administrative actions tracked in `audit_log` table |
+| **MCP Audit** | SQLite-backed audit logging for all MCP tool calls |
+| **Zod Validation** | All API inputs validated with Zod v4 schemas at module load |
+
+---
+
+## Required Environment Variables
+
+All secrets must be set before starting the server. The server will **fail fast** if they are missing or weak.
+
+```bash
+# REQUIRED — server will not start without these:
+JWT_SECRET=$(openssl rand -base64 48) # min 32 chars
+API_KEY_SECRET=$(openssl rand -hex 32) # min 16 chars
+
+# RECOMMENDED — enables encryption at rest:
+STORAGE_ENCRYPTION_KEY=$(openssl rand -hex 32)
+```
+
+The server actively rejects known-weak values like `changeme`, `secret`, or `password`.
+
+---
+
+## Docker Security
+
+- Use non-root user in production
+- Mount secrets as read-only volumes
+- Never copy `.env` files into Docker images
+- Use `.dockerignore` to exclude sensitive files
+- Set `AUTH_COOKIE_SECURE=true` when behind HTTPS
+
+```bash
+docker run -d \
+ --name omniroute \
+ --restart unless-stopped \
+ --read-only \
+ -p 20128:20128 \
+ -v omniroute-data:/app/data \
+ -e JWT_SECRET="$(openssl rand -base64 48)" \
+ -e API_KEY_SECRET="$(openssl rand -hex 32)" \
+ -e STORAGE_ENCRYPTION_KEY="$(openssl rand -hex 32)" \
+ diegosouzapw/omniroute:latest
+```
+
+---
+
+## Dependencies
+
+- Run `npm audit` regularly
+- Keep dependencies updated
+- The project uses `husky` + `lint-staged` for pre-commit checks
+- CI pipeline runs ESLint security rules on every push
+- Provider constants validated at module load via Zod (`src/shared/validation/providerSchema.ts`)
diff --git a/docs/i18n/bg/VM_DEPLOYMENT_GUIDE.md b/docs/i18n/bg/VM_DEPLOYMENT_GUIDE.md
deleted file mode 100644
index 60aa723bf6..0000000000
--- a/docs/i18n/bg/VM_DEPLOYMENT_GUIDE.md
+++ /dev/null
@@ -1,401 +0,0 @@
-# OmniRoute — Ръководство за внедряване на VM с Cloudflare
-
-🌐 **Languages:** 🇺🇸 [English](../../VM_DEPLOYMENT_GUIDE.md) | 🇧🇷 [Português (Brasil)](../pt-BR/VM_DEPLOYMENT_GUIDE.md) | 🇪🇸 [Español](../es/VM_DEPLOYMENT_GUIDE.md) | 🇫🇷 [Français](../fr/VM_DEPLOYMENT_GUIDE.md) | 🇮🇹 [Italiano](../it/VM_DEPLOYMENT_GUIDE.md) | 🇷🇺 [Русский](../ru/VM_DEPLOYMENT_GUIDE.md) | 🇨🇳 [中文 (简体)](../zh-CN/VM_DEPLOYMENT_GUIDE.md) | 🇩🇪 [Deutsch](../de/VM_DEPLOYMENT_GUIDE.md) | 🇮🇳 [हिन्दी](../in/VM_DEPLOYMENT_GUIDE.md) | 🇹🇭 [ไทย](../th/VM_DEPLOYMENT_GUIDE.md) | 🇺🇦 [Українська](../uk-UA/VM_DEPLOYMENT_GUIDE.md) | 🇸🇦 [العربية](../ar/VM_DEPLOYMENT_GUIDE.md) | 🇯🇵 [日本語](../ja/VM_DEPLOYMENT_GUIDE.md) | 🇻🇳 [Tiếng Việt](../vi/VM_DEPLOYMENT_GUIDE.md) | 🇧🇬 [Български](../bg/VM_DEPLOYMENT_GUIDE.md) | 🇩🇰 [Dansk](../da/VM_DEPLOYMENT_GUIDE.md) | 🇫🇮 [Suomi](../fi/VM_DEPLOYMENT_GUIDE.md) | 🇮🇱 [עברית](../he/VM_DEPLOYMENT_GUIDE.md) | 🇭🇺 [Magyar](../hu/VM_DEPLOYMENT_GUIDE.md) | 🇮🇩 [Bahasa Indonesia](../id/VM_DEPLOYMENT_GUIDE.md) | 🇰🇷 [한국어](../ko/VM_DEPLOYMENT_GUIDE.md) | 🇲🇾 [Bahasa Melayu](../ms/VM_DEPLOYMENT_GUIDE.md) | 🇳🇱 [Nederlands](../nl/VM_DEPLOYMENT_GUIDE.md) | 🇳🇴 [Norsk](../no/VM_DEPLOYMENT_GUIDE.md) | 🇵🇹 [Português (Portugal)](../pt/VM_DEPLOYMENT_GUIDE.md) | 🇷🇴 [Română](../ro/VM_DEPLOYMENT_GUIDE.md) | 🇵🇱 [Polski](../pl/VM_DEPLOYMENT_GUIDE.md) | 🇸🇰 [Slovenčina](../sk/VM_DEPLOYMENT_GUIDE.md) | 🇸🇪 [Svenska](../sv/VM_DEPLOYMENT_GUIDE.md) | 🇵🇭 [Filipino](../phi/VM_DEPLOYMENT_GUIDE.md) | 🇨🇿 [Čeština](../cs/VM_DEPLOYMENT_GUIDE.md)
-
-Пълно ръководство за инсталиране и конфигуриране на OmniRoute на VM (VPS) с домейн, управляван чрез Cloudflare.
-
----
-
-## Предпоставки
-
-| Артикул | Минимум | Препоръчва се |
-| ---------- | ------------------------ | ---------------- |
-| **CPU** | 1 vCPU | 2 vCPU |
-| **RAM** | 1 GB | 2 GB |
-| **Диск** | 10 GB SSD | 25 GB SSD |
-| **OS** | Ubuntu 22.04 LTS | Ubuntu 24.04 LTS |
-| **Домейн** | Регистриран в Cloudflare | — |
-| **Докер** | Docker Engine 24+ | Докер 27+ |
-
-**Тествани доставчици**: Akamai (Linode), DigitalOcean, Vultr, Hetzner, AWS Lightsail.
-
----
-
-## 1. Конфигурирайте VM
-
-### 1.1 Създайте екземпляра
-
-На предпочитания от вас VPS доставчик:
-
-- Изберете Ubuntu 24.04 LTS
-- Изберете минималния план (1 vCPU / 1 GB RAM)
-- Задайте силна root парола или конфигурирайте SSH ключ
-- Обърнете внимание на **публичния IP** (напр. `203.0.113.10`)
-
-### 1.2 Свързване чрез SSH
-
-```bash
-ssh root@203.0.113.10
-```
-
-### 1.3 Актуализирайте системата
-
-```bash
-apt update && apt upgrade -y
-```
-
-### 1.4 Инсталирайте Docker
-
-```bash
-# Install dependencies
-apt install -y ca-certificates curl gnupg
-
-# Add official Docker repository
-install -m 0755 -d /etc/apt/keyrings
-curl -fsSL https://download.docker.com/linux/ubuntu/gpg | gpg --dearmor -o /etc/apt/keyrings/docker.gpg
-chmod a+r /etc/apt/keyrings/docker.gpg
-echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu $ (. /etc/os-release && echo “$VERSION_CODENAME”) stable" | tee /etc/apt/sources.list.d/docker.list > /dev/null
-apt update
-apt install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin
-```
-
-### 1.5 Инсталирайте nginx
-
-```bash
-apt install -y nginx
-```
-
-### 1.6 Конфигуриране на защитна стена (UFW)
-
-```bash
-ufw default deny incoming
-ufw default allow outgoing
-ufw allow 22/tcp # SSH
-ufw allow 80/tcp # HTTP (redirect)
-ufw allow 443/tcp # HTTPS
-ufw enable
-```
-
-> **Съвет**: За максимална сигурност ограничете портове 80 и 443 само до IP адреси на Cloudflare. Вижте раздела [Advanced Security](#advanced-security).
-
----
-
-## 2. Инсталирайте OmniRoute
-
-### 2.1 Създайте конфигурационна директория
-
-```bash
-mkdir -p /opt/omniroute
-```
-
-### 2.2 Създайте файл с променливи на средата
-
-```bash
-cat > /opt/omniroute/.env << ‘EOF’
-# === Security ===
-JWT_SECRET=CHANGE-TO-A-UNIQUE-64-CHAR-SECRET-KEY
-INITIAL_PASSWORD=YourSecurePassword123!
-API_KEY_SECRET=REPLACE-WITH-ANOTHER-SECRET-KEY
-STORAGE_ENCRYPTION_KEY=REPLACE-WITH-THIRD-SECRET-KEY
-STORAGE_ENCRYPTION_KEY_VERSION=v1
-MACHINE_ID_SALT=CHANGE-TO-A-UNIQUE-SALT
-
-# === App ===
-PORT=20128
-NODE_ENV=production
-HOSTNAME=0.0.0.0
-DATA_DIR=/app/data
-STORAGE_DRIVER=sqlite
-ENABLE_REQUEST_LOGS=true
-AUTH_COOKIE_SECURE=false
-REQUIRE_API_KEY=false
-
-# === Domain (change to your domain) ===
-BASE_URL=https://llms.seudominio.com
-NEXT_PUBLIC_BASE_URL=https://llms.seudominio.com
-
-# === Cloud Sync (optional) ===
-# CLOUD_URL=https://cloud.omniroute.online
-# NEXT_PUBLIC_CLOUD_URL=https://cloud.omniroute.online
-EOF
-```
-
-> ⚠️ **ВАЖНО**: Генерирайте уникални секретни ключове! Използвайте `openssl rand -hex 32` за всеки ключ.
-
-### 2.3 Стартирайте контейнера
-
-```bash
-docker pull diegosouzapw/omniroute:latest
-
-docker run -d \
- --name omniroute \
- --restart unless-stopped \
- --env-file /opt/omniroute/.env \
- -p 20128:20128 \
- -v omniroute-data:/app/data \
- diegosouzapw/omniroute:latest
-```
-
-### 2.4 Проверете дали работи
-
-```bash
-docker ps | grep omniroute
-docker logs omniroute --tail 20
-```
-
-Трябва да показва: `[DB] SQLite database ready` и `listening on port 20128`.
-
----
-
-## 3. Конфигурирайте nginx (обратен прокси)
-
-### 3.1 Генериране на SSL сертификат (Cloudflare Origin)
-
-В таблото за управление на Cloudflare:
-
-1. Отидете на **SSL/TLS → Origin Server**
-2. Щракнете върху **Създаване на сертификат**
-3. Запазете настройките по подразбиране (15 години, \*.yourdomain.com)
-4. Копирайте **Сертификата за произход** и **Личния ключ**
-
-```bash
-mkdir -p /etc/nginx/ssl
-
-# Paste the certificate
-nano /etc/nginx/ssl/origin.crt
-
-# Paste the private key
-nano /etc/nginx/ssl/origin.key
-
-chmod 600 /etc/nginx/ssl/origin.key
-```
-
-### 3.2 Конфигурация на Nginx
-
-```bash
-cat > /etc/nginx/sites-available/omniroute << ‘NGINX’
-# Default server — blocks direct access via IP
-server {
- listen 80 default_server;
- listen [::]:80 default_server;
- listen 443 ssl default_server;
- listen [::]:443 ssl default_server;
- ssl_certificate /etc/nginx/ssl/origin.crt;
- ssl_certificate_key /etc/nginx/ssl/origin.key;
- server_name _;
- return 444;
-}
-
-# OmniRoute — HTTPS
-server {
- listen 443 ssl;
- listen [::]:443 ssl;
- server_name llms.yourdomain.com; # Change to your domain
-
- ssl_certificate /etc/nginx/ssl/origin.crt;
- ssl_certificate_key /etc/nginx/ssl/origin.key;
- ssl_protocols TLSv1.2 TLSv1.3;
-
- client_max_body_size 100M;
-
- location / {
- proxy_pass http://127.0.0.1:20128;
- proxy_set_header Host $host;
- proxy_set_header X-Real-IP $remote_addr;
- proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
- proxy_set_header X-Forwarded-Proto $scheme;
-
- # WebSocket support
- proxy_http_version 1.1;
- proxy_set_header Upgrade $http_upgrade;
- proxy_set_header Connection “upgrade”;
-
- # SSE (Server-Sent Events) — streaming AI responses
- proxy_buffering off;
- proxy_cache off;
- proxy_read_timeout 300s;
- proxy_send_timeout 300s;
- }
-}
-
-# HTTP → HTTPS redirect
-server {
- listen 80;
- listen [::]:80;
- server_name llms.yourdomain.com;
- return 301 https://$server_name$request_uri;
-}
-NGINX
-```
-
-### 3.3 Активиране и тестване
-
-```bash
-# Remove default configuration
-rm -f /etc/nginx/sites-enabled/default
-
-# Enable OmniRoute
-ln -sf /etc/nginx/sites-available/omniroute /etc/nginx/sites-enabled/omniroute
-
-# Test and reload
-nginx -t && systemctl reload nginx
-```
-
----
-
-## 4. Конфигурирайте Cloudflare DNS
-
-### 4.1 Добавете DNS запис
-
-В таблото за управление на Cloudflare → DNS:
-
-| Тип | Име | Съдържание | Прокси |
-| --- | ------ | ---------------------- | ------------ |
-| A | `llms` | `203.0.113.10` (VM IP) | ✅ Проксиран |
-
-### 4.2 Конфигурирайте SSL
-
-Под **SSL/TLS → Общ преглед**:
-
-- Режим: **Пълен (строг)**
-
-Под **SSL/TLS → Edge Certificates**:
-
-- Винаги използвайте HTTPS: ✅ Вкл
-- Минимална TLS версия: TLS 1.2
-- Автоматично пренаписване на HTTPS: ✅ Включено
-
-### 4.3 Тестване
-
-```bash
-curl -sI https://llms.seudominio.com/health
-# Should return HTTP/2 200
-```
-
----
-
-## 5. Операции и поддръжка
-
-### Надстройте до нова версия
-
-```bash
-docker pull diegosouzapw/omniroute:latest
-docker stop omniroute && docker rm omniroute
-docker run -d --name omniroute --restart unless-stopped \
- --env-file /opt/omniroute/.env \
- -p 20128:20128 \
- -v omniroute-data:/app/data \
- diegosouzapw/omniroute:latest
-```
-
-### Преглед на регистрационни файлове
-
-```bash
-docker logs -f omniroute # Real-time stream
-docker logs omniroute --tail 50 # Last 50 lines
-```
-
-### Ръчно архивиране на база данни
-
-```bash
-# Copy data from the volume to the host
-docker cp omniroute:/app/data ./backup-$(date +%F)
-
-# Or compress the entire volume
-docker run --rm -v omniroute-data:/data -v $(pwd):/backup \
- alpine tar czf /backup/omniroute-data-$(date +%F).tar.gz /data
-```
-
-### Възстановяване от резервно копие
-
-```bash
-docker stop omniroute
-docker run --rm -v omniroute-data:/data -v $(pwd):/backup \
- alpine sh -c “rm -rf /data/* && tar xzf /backup/omniroute-data-YYYY-MM-DD.tar.gz -C /”
-docker start omniroute
-```
-
----
-
-## 6. Разширена сигурност
-
-### Ограничете nginx до IP адреси на Cloudflare
-
-```bash
-cat > /etc/nginx/cloudflare-ips.conf << ‘CF’
-# Cloudflare IPv4 ranges — update periodically
-# https://www.cloudflare.com/ips-v4/
-set_real_ip_from 173.245.48.0/20;
-set_real_ip_from 103.21.244.0/22;
-set_real_ip_from 103.22.200.0/22;
-set_real_ip_from 103.31.4.0/22;
-set_real_ip_from 141.101.64.0/18;
-set_real_ip_from 108.162.192.0/18;
-set_real_ip_from 190.93.240.0/20;
-set_real_ip_from 188.114.96.0/20;
-set_real_ip_from 197.234.240.0/22;
-set_real_ip_from 198.41.128.0/17;
-set_real_ip_from 162.158.0.0/15;
-set_real_ip_from 104.16.0.0/13;
-set_real_ip_from 104.24.0.0/14;
-set_real_ip_from 172.64.0.0/13;
-set_real_ip_from 131.0.72.0/22;
-real_ip_header CF-Connecting-IP;
-CF
-```
-
-Добавете следното към `nginx.conf` в блока `http {}`:
-
-```nginx
-include /etc/nginx/cloudflare-ips.conf;
-```
-
-### Инсталирайте fail2ban
-
-```bash
-apt install -y fail2ban
-systemctl enable fail2ban
-systemctl start fail2ban
-
-# Check status
-fail2ban-client status sshd
-```
-
-### Блокирайте директния достъп до порта на Docker
-
-```bash
-# Prevent direct external access to port 20128
-iptables -I DOCKER-USER -p tcp --dport 20128 -j DROP
-iptables -I DOCKER-USER -i lo -p tcp --dport 20128 -j ACCEPT
-
-# Persist the rules
-apt install -y iptables-persistent
-netfilter-persistent save
-```
-
----
-
-## 7. Разположете в Cloudflare Workers (по избор)
-
-За отдалечен достъп чрез Cloudflare Workers (без директно излагане на VM):
-
-```bash
-# In the local repository
-cd omnirouteCloud
-npm install
-npx wrangler login
-npx wrangler deploy
-```
-
-Вижте пълната документация на [omnirouteCloud/README.md](../omnirouteCloud/README.md).
-
----
-
-## Резюме на порта
-
-| Пристанище | Обслужване | Достъп |
-| ---------- | ----------- | ------------------------------ |
-| 22 | SSH | Публичен (с fail2ban) |
-| 80 | nginx HTTP | Пренасочване → HTTPS |
-| 443 | nginx HTTPS | Чрез прокси Cloudflare |
-| 20128 | OmniRoute | Само локален хост (чрез nginx) |
diff --git a/docs/i18n/bg/docs/A2A-SERVER.md b/docs/i18n/bg/docs/A2A-SERVER.md
new file mode 100644
index 0000000000..f07600eb54
--- /dev/null
+++ b/docs/i18n/bg/docs/A2A-SERVER.md
@@ -0,0 +1,200 @@
+# OmniRoute A2A Server Documentation (Български)
+
+🌐 **Languages:** 🇺🇸 [English](../../../../docs/A2A-SERVER.md) · 🇪🇸 [es](../../es/docs/A2A-SERVER.md) · 🇫🇷 [fr](../../fr/docs/A2A-SERVER.md) · 🇩🇪 [de](../../de/docs/A2A-SERVER.md) · 🇮🇹 [it](../../it/docs/A2A-SERVER.md) · 🇷🇺 [ru](../../ru/docs/A2A-SERVER.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/A2A-SERVER.md) · 🇯🇵 [ja](../../ja/docs/A2A-SERVER.md) · 🇰🇷 [ko](../../ko/docs/A2A-SERVER.md) · 🇸🇦 [ar](../../ar/docs/A2A-SERVER.md) · 🇮🇳 [in](../../in/docs/A2A-SERVER.md) · 🇹🇭 [th](../../th/docs/A2A-SERVER.md) · 🇻🇳 [vi](../../vi/docs/A2A-SERVER.md) · 🇮🇩 [id](../../id/docs/A2A-SERVER.md) · 🇲🇾 [ms](../../ms/docs/A2A-SERVER.md) · 🇳🇱 [nl](../../nl/docs/A2A-SERVER.md) · 🇵🇱 [pl](../../pl/docs/A2A-SERVER.md) · 🇸🇪 [sv](../../sv/docs/A2A-SERVER.md) · 🇳🇴 [no](../../no/docs/A2A-SERVER.md) · 🇩🇰 [da](../../da/docs/A2A-SERVER.md) · 🇫🇮 [fi](../../fi/docs/A2A-SERVER.md) · 🇵🇹 [pt](../../pt/docs/A2A-SERVER.md) · 🇷🇴 [ro](../../ro/docs/A2A-SERVER.md) · 🇭🇺 [hu](../../hu/docs/A2A-SERVER.md) · 🇧🇬 [bg](../../bg/docs/A2A-SERVER.md) · 🇸🇰 [sk](../../sk/docs/A2A-SERVER.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/A2A-SERVER.md) · 🇮🇱 [he](../../he/docs/A2A-SERVER.md) · 🇵🇭 [phi](../../phi/docs/A2A-SERVER.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/A2A-SERVER.md) · 🇨🇿 [cs](../../cs/docs/A2A-SERVER.md)
+
+---
+
+> Agent-to-Agent Protocol v0.3 — OmniRoute as an intelligent routing agent
+
+## Agent Discovery
+
+```bash
+curl http://localhost:20128/.well-known/agent.json
+```
+
+Returns the Agent Card describing OmniRoute's capabilities, skills, and authentication requirements.
+
+---
+
+## Authentication
+
+All `/a2a` requests require an API key via the `Authorization` header:
+
+```
+Authorization: Bearer YOUR_OMNIROUTE_API_KEY
+```
+
+If no API key is configured on the server, authentication is bypassed.
+
+---
+
+## JSON-RPC 2.0 Methods
+
+### `message/send` — Synchronous Execution
+
+Sends a message to a skill and waits for the complete response.
+
+```bash
+curl -X POST http://localhost:20128/a2a \
+ -H "Content-Type: application/json" \
+ -H "Authorization: Bearer YOUR_KEY" \
+ -d '{
+ "jsonrpc": "2.0",
+ "id": "1",
+ "method": "message/send",
+ "params": {
+ "skill": "smart-routing",
+ "messages": [{"role": "user", "content": "Write a hello world in Python"}],
+ "metadata": {"model": "auto", "combo": "fast-coding"}
+ }
+ }'
+```
+
+**Response:**
+
+```json
+{
+ "jsonrpc": "2.0",
+ "id": "1",
+ "result": {
+ "task": { "id": "uuid", "state": "completed" },
+ "artifacts": [{ "type": "text", "content": "..." }],
+ "metadata": {
+ "routing_explanation": "Selected claude-sonnet via provider \"anthropic\" (latency: 1200ms, cost: $0.003)",
+ "cost_envelope": { "estimated": 0.005, "actual": 0.003, "currency": "USD" },
+ "resilience_trace": [
+ { "event": "primary_selected", "provider": "anthropic", "timestamp": "..." }
+ ],
+ "policy_verdict": { "allowed": true, "reason": "within budget and quota limits" }
+ }
+ }
+}
+```
+
+### `message/stream` — SSE Streaming
+
+Same as `message/send` but returns Server-Sent Events for real-time streaming.
+
+```bash
+curl -N -X POST http://localhost:20128/a2a \
+ -H "Content-Type: application/json" \
+ -H "Authorization: Bearer YOUR_KEY" \
+ -d '{
+ "jsonrpc": "2.0",
+ "id": "1",
+ "method": "message/stream",
+ "params": {
+ "skill": "smart-routing",
+ "messages": [{"role": "user", "content": "Explain quantum computing"}]
+ }
+ }'
+```
+
+**SSE Events:**
+
+```
+data: {"jsonrpc":"2.0","method":"message/stream","params":{"task":{"id":"...","state":"working"},"chunk":{"type":"text","content":"..."}}}
+
+: heartbeat 2026-03-03T17:00:00Z
+
+data: {"jsonrpc":"2.0","method":"message/stream","params":{"task":{"id":"...","state":"completed"},"metadata":{...}}}
+```
+
+### `tasks/get` — Query Task Status
+
+```bash
+curl -X POST http://localhost:20128/a2a \
+ -H "Content-Type: application/json" \
+ -H "Authorization: Bearer YOUR_KEY" \
+ -d '{"jsonrpc":"2.0","id":"2","method":"tasks/get","params":{"taskId":"TASK_UUID"}}'
+```
+
+### `tasks/cancel` — Cancel a Task
+
+```bash
+curl -X POST http://localhost:20128/a2a \
+ -H "Content-Type: application/json" \
+ -H "Authorization: Bearer YOUR_KEY" \
+ -d '{"jsonrpc":"2.0","id":"3","method":"tasks/cancel","params":{"taskId":"TASK_UUID"}}'
+```
+
+---
+
+## Available Skills
+
+| Skill | Description |
+| :----------------- | :------------------------------------------------------------------------------------------------------------------------------ |
+| `smart-routing` | Routes prompts through OmniRoute's intelligent pipeline. Returns response with routing explanation, cost, and resilience trace. |
+| `quota-management` | Answers natural-language queries about provider quotas, suggests free combos, and provides quota rankings. |
+
+---
+
+## Task Lifecycle
+
+```
+submitted → working → completed
+ → failed
+ → cancelled
+```
+
+- Tasks expire after 5 minutes (configurable)
+- Terminal states: `completed`, `failed`, `cancelled`
+- Event log tracks every state transition
+
+---
+
+## Error Codes
+
+| Code | Meaning |
+| :----- | :----------------------------- |
+| -32700 | Parse error (invalid JSON) |
+| -32600 | Invalid request / Unauthorized |
+| -32601 | Method or skill not found |
+| -32602 | Invalid params |
+| -32603 | Internal error |
+
+---
+
+## Integration Examples
+
+### Python (requests)
+
+```python
+import requests
+
+resp = requests.post("http://localhost:20128/a2a", json={
+ "jsonrpc": "2.0", "id": "1",
+ "method": "message/send",
+ "params": {
+ "skill": "smart-routing",
+ "messages": [{"role": "user", "content": "Hello"}]
+ }
+}, headers={"Authorization": "Bearer YOUR_KEY"})
+
+result = resp.json()["result"]
+print(result["artifacts"][0]["content"])
+print(result["metadata"]["routing_explanation"])
+```
+
+### TypeScript (fetch)
+
+```typescript
+const resp = await fetch("http://localhost:20128/a2a", {
+ method: "POST",
+ headers: {
+ "Content-Type": "application/json",
+ Authorization: "Bearer YOUR_KEY",
+ },
+ body: JSON.stringify({
+ jsonrpc: "2.0",
+ id: "1",
+ method: "message/send",
+ params: {
+ skill: "smart-routing",
+ messages: [{ role: "user", content: "Hello" }],
+ },
+ }),
+});
+const { result } = await resp.json();
+console.log(result.metadata.routing_explanation);
+```
diff --git a/docs/i18n/bg/docs/API_REFERENCE.md b/docs/i18n/bg/docs/API_REFERENCE.md
new file mode 100644
index 0000000000..f8377b7fed
--- /dev/null
+++ b/docs/i18n/bg/docs/API_REFERENCE.md
@@ -0,0 +1,465 @@
+# API Reference (Български)
+
+🌐 **Languages:** 🇺🇸 [English](../../../../docs/API_REFERENCE.md) · 🇪🇸 [es](../../es/docs/API_REFERENCE.md) · 🇫🇷 [fr](../../fr/docs/API_REFERENCE.md) · 🇩🇪 [de](../../de/docs/API_REFERENCE.md) · 🇮🇹 [it](../../it/docs/API_REFERENCE.md) · 🇷🇺 [ru](../../ru/docs/API_REFERENCE.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/API_REFERENCE.md) · 🇯🇵 [ja](../../ja/docs/API_REFERENCE.md) · 🇰🇷 [ko](../../ko/docs/API_REFERENCE.md) · 🇸🇦 [ar](../../ar/docs/API_REFERENCE.md) · 🇮🇳 [in](../../in/docs/API_REFERENCE.md) · 🇹🇭 [th](../../th/docs/API_REFERENCE.md) · 🇻🇳 [vi](../../vi/docs/API_REFERENCE.md) · 🇮🇩 [id](../../id/docs/API_REFERENCE.md) · 🇲🇾 [ms](../../ms/docs/API_REFERENCE.md) · 🇳🇱 [nl](../../nl/docs/API_REFERENCE.md) · 🇵🇱 [pl](../../pl/docs/API_REFERENCE.md) · 🇸🇪 [sv](../../sv/docs/API_REFERENCE.md) · 🇳🇴 [no](../../no/docs/API_REFERENCE.md) · 🇩🇰 [da](../../da/docs/API_REFERENCE.md) · 🇫🇮 [fi](../../fi/docs/API_REFERENCE.md) · 🇵🇹 [pt](../../pt/docs/API_REFERENCE.md) · 🇷🇴 [ro](../../ro/docs/API_REFERENCE.md) · 🇭🇺 [hu](../../hu/docs/API_REFERENCE.md) · 🇧🇬 [bg](../../bg/docs/API_REFERENCE.md) · 🇸🇰 [sk](../../sk/docs/API_REFERENCE.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/API_REFERENCE.md) · 🇮🇱 [he](../../he/docs/API_REFERENCE.md) · 🇵🇭 [phi](../../phi/docs/API_REFERENCE.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/API_REFERENCE.md) · 🇨🇿 [cs](../../cs/docs/API_REFERENCE.md)
+
+---
+
+Complete reference for all OmniRoute API endpoints.
+
+---
+
+## Table of Contents
+
+- [Chat Completions](#chat-completions)
+- [Embeddings](#embeddings)
+- [Image Generation](#image-generation)
+- [List Models](#list-models)
+- [Compatibility Endpoints](#compatibility-endpoints)
+- [Semantic Cache](#semantic-cache)
+- [Dashboard & Management](#dashboard--management)
+- [Request Processing](#request-processing)
+- [Authentication](#authentication)
+
+---
+
+## Chat Completions
+
+```bash
+POST /v1/chat/completions
+Authorization: Bearer your-api-key
+Content-Type: application/json
+
+{
+ "model": "cc/claude-opus-4-6",
+ "messages": [
+ {"role": "user", "content": "Write a function to..."}
+ ],
+ "stream": true
+}
+```
+
+### Custom Headers
+
+| Header | Direction | Description |
+| ------------------------ | --------- | ------------------------------------------------ |
+| `X-OmniRoute-No-Cache` | Request | Set to `true` to bypass cache |
+| `X-OmniRoute-Progress` | Request | Set to `true` for progress events |
+| `X-Session-Id` | Request | Sticky session key for external session affinity |
+| `x_session_id` | Request | Underscore variant also accepted (direct HTTP) |
+| `Idempotency-Key` | Request | Dedup key (5s window) |
+| `X-Request-Id` | Request | Alternative dedup key |
+| `X-OmniRoute-Cache` | Response | `HIT` or `MISS` (non-streaming) |
+| `X-OmniRoute-Idempotent` | Response | `true` if deduplicated |
+| `X-OmniRoute-Progress` | Response | `enabled` if progress tracking on |
+| `X-OmniRoute-Session-Id` | Response | Effective session ID used by OmniRoute |
+
+> Nginx note: if you rely on underscore headers (for example `x_session_id`), enable `underscores_in_headers on;`.
+
+---
+
+## Embeddings
+
+```bash
+POST /v1/embeddings
+Authorization: Bearer your-api-key
+Content-Type: application/json
+
+{
+ "model": "nebius/Qwen/Qwen3-Embedding-8B",
+ "input": "The food was delicious"
+}
+```
+
+Available providers: Nebius, OpenAI, Mistral, Together AI, Fireworks, NVIDIA.
+
+```bash
+# List all embedding models
+GET /v1/embeddings
+```
+
+---
+
+## Image Generation
+
+```bash
+POST /v1/images/generations
+Authorization: Bearer your-api-key
+Content-Type: application/json
+
+{
+ "model": "openai/dall-e-3",
+ "prompt": "A beautiful sunset over mountains",
+ "size": "1024x1024"
+}
+```
+
+Available providers: OpenAI (DALL-E), xAI (Grok Image), Together AI (FLUX), Fireworks AI.
+
+```bash
+# List all image models
+GET /v1/images/generations
+```
+
+---
+
+## List Models
+
+```bash
+GET /v1/models
+Authorization: Bearer your-api-key
+
+→ Returns all chat, embedding, and image models + combos in OpenAI format
+```
+
+---
+
+## Compatibility Endpoints
+
+| Method | Path | Format |
+| ------ | --------------------------- | ---------------------- |
+| POST | `/v1/chat/completions` | OpenAI |
+| POST | `/v1/messages` | Anthropic |
+| POST | `/v1/responses` | OpenAI Responses |
+| POST | `/v1/embeddings` | OpenAI |
+| POST | `/v1/images/generations` | OpenAI |
+| GET | `/v1/models` | OpenAI |
+| POST | `/v1/messages/count_tokens` | Anthropic |
+| GET | `/v1beta/models` | Gemini |
+| POST | `/v1beta/models/{...path}` | Gemini generateContent |
+| POST | `/v1/api/chat` | Ollama |
+
+### Dedicated Provider Routes
+
+```bash
+POST /v1/providers/{provider}/chat/completions
+POST /v1/providers/{provider}/embeddings
+POST /v1/providers/{provider}/images/generations
+```
+
+The provider prefix is auto-added if missing. Mismatched models return `400`.
+
+---
+
+## Semantic Cache
+
+```bash
+# Get cache stats
+GET /api/cache/stats
+
+# Clear all caches
+DELETE /api/cache/stats
+```
+
+Response example:
+
+```json
+{
+ "semanticCache": {
+ "memorySize": 42,
+ "memoryMaxSize": 500,
+ "dbSize": 128,
+ "hitRate": 0.65
+ },
+ "idempotency": {
+ "activeKeys": 3,
+ "windowMs": 5000
+ }
+}
+```
+
+---
+
+## Dashboard & Management
+
+### Authentication
+
+| Endpoint | Method | Description |
+| ----------------------------- | ------- | --------------------- |
+| `/api/auth/login` | POST | Login |
+| `/api/auth/logout` | POST | Logout |
+| `/api/settings/require-login` | GET/PUT | Toggle login required |
+
+### Provider Management
+
+| Endpoint | Method | Description |
+| ---------------------------- | --------------- | ------------------------ |
+| `/api/providers` | GET/POST | List / create providers |
+| `/api/providers/[id]` | GET/PUT/DELETE | Manage a provider |
+| `/api/providers/[id]/test` | POST | Test provider connection |
+| `/api/providers/[id]/models` | GET | List provider models |
+| `/api/providers/validate` | POST | Validate provider config |
+| `/api/provider-nodes*` | Various | Provider node management |
+| `/api/provider-models` | GET/POST/DELETE | Custom models |
+
+### OAuth Flows
+
+| Endpoint | Method | Description |
+| -------------------------------- | ------- | ----------------------- |
+| `/api/oauth/[provider]/[action]` | Various | Provider-specific OAuth |
+
+### Routing & Config
+
+| Endpoint | Method | Description |
+| --------------------- | -------- | ----------------------------- |
+| `/api/models/alias` | GET/POST | Model aliases |
+| `/api/models/catalog` | GET | All models by provider + type |
+| `/api/combos*` | Various | Combo management |
+| `/api/keys*` | Various | API key management |
+| `/api/pricing` | GET | Model pricing |
+
+### Usage & Analytics
+
+| Endpoint | Method | Description |
+| --------------------------- | ------ | -------------------- |
+| `/api/usage/history` | GET | Usage history |
+| `/api/usage/logs` | GET | Usage logs |
+| `/api/usage/request-logs` | GET | Request-level logs |
+| `/api/usage/[connectionId]` | GET | Per-connection usage |
+
+### Settings
+
+| Endpoint | Method | Description |
+| ------------------------------- | ------------- | ---------------------- |
+| `/api/settings` | GET/PUT/PATCH | General settings |
+| `/api/settings/proxy` | GET/PUT | Network proxy config |
+| `/api/settings/proxy/test` | POST | Test proxy connection |
+| `/api/settings/ip-filter` | GET/PUT | IP allowlist/blocklist |
+| `/api/settings/thinking-budget` | GET/PUT | Reasoning token budget |
+| `/api/settings/system-prompt` | GET/PUT | Global system prompt |
+
+### Monitoring
+
+| Endpoint | Method | Description |
+| ------------------------ | ---------- | ---------------------------------------------------------------------------------------------------- |
+| `/api/sessions` | GET | Active session tracking |
+| `/api/rate-limits` | GET | Per-account rate limits |
+| `/api/monitoring/health` | GET | Health check + provider summary (`catalogCount`, `configuredCount`, `activeCount`, `monitoredCount`) |
+| `/api/cache/stats` | GET/DELETE | Cache stats / clear |
+
+### Backup & Export/Import
+
+| Endpoint | Method | Description |
+| --------------------------- | ------ | --------------------------------------- |
+| `/api/db-backups` | GET | List available backups |
+| `/api/db-backups` | PUT | Create a manual backup |
+| `/api/db-backups` | POST | Restore from a specific backup |
+| `/api/db-backups/export` | GET | Download database as .sqlite file |
+| `/api/db-backups/import` | POST | Upload .sqlite file to replace database |
+| `/api/db-backups/exportAll` | GET | Download full backup as .tar.gz archive |
+
+### Cloud Sync
+
+| Endpoint | Method | Description |
+| ---------------------- | ------- | --------------------- |
+| `/api/sync/cloud` | Various | Cloud sync operations |
+| `/api/sync/initialize` | POST | Initialize sync |
+| `/api/cloud/*` | Various | Cloud management |
+
+### Tunnels
+
+| Endpoint | Method | Description |
+| -------------------------- | ------ | ----------------------------------------------------------------------- |
+| `/api/tunnels/cloudflared` | GET | Read Cloudflare Quick Tunnel install/runtime status for the dashboard |
+| `/api/tunnels/cloudflared` | POST | Enable or disable the Cloudflare Quick Tunnel (`action=enable/disable`) |
+
+### CLI Tools
+
+| Endpoint | Method | Description |
+| ---------------------------------- | ------ | ------------------- |
+| `/api/cli-tools/claude-settings` | GET | Claude CLI status |
+| `/api/cli-tools/codex-settings` | GET | Codex CLI status |
+| `/api/cli-tools/droid-settings` | GET | Droid CLI status |
+| `/api/cli-tools/openclaw-settings` | GET | OpenClaw CLI status |
+| `/api/cli-tools/runtime/[toolId]` | GET | Generic CLI runtime |
+
+CLI responses include: `installed`, `runnable`, `command`, `commandPath`, `runtimeMode`, `reason`.
+
+### ACP Agents
+
+| Endpoint | Method | Description |
+| ----------------- | ------ | -------------------------------------------------------- |
+| `/api/acp/agents` | GET | List all detected agents (built-in + custom) with status |
+| `/api/acp/agents` | POST | Add custom agent or refresh detection cache |
+| `/api/acp/agents` | DELETE | Remove a custom agent by `id` query param |
+
+GET response includes `agents[]` (id, name, binary, version, installed, protocol, isCustom) and `summary` (total, installed, notFound, builtIn, custom).
+
+### Resilience & Rate Limits
+
+| Endpoint | Method | Description |
+| ----------------------- | --------- | ------------------------------- |
+| `/api/resilience` | GET/PATCH | Get/update resilience profiles |
+| `/api/resilience/reset` | POST | Reset circuit breakers |
+| `/api/rate-limits` | GET | Per-account rate limit status |
+| `/api/rate-limit` | GET | Global rate limit configuration |
+
+### Evals
+
+| Endpoint | Method | Description |
+| ------------ | -------- | --------------------------------- |
+| `/api/evals` | GET/POST | List eval suites / run evaluation |
+
+### Policies
+
+| Endpoint | Method | Description |
+| --------------- | --------------- | ----------------------- |
+| `/api/policies` | GET/POST/DELETE | Manage routing policies |
+
+### Compliance
+
+| Endpoint | Method | Description |
+| --------------------------- | ------ | ----------------------------- |
+| `/api/compliance/audit-log` | GET | Compliance audit log (last N) |
+
+### v1beta (Gemini-Compatible)
+
+| Endpoint | Method | Description |
+| -------------------------- | ------ | --------------------------------- |
+| `/v1beta/models` | GET | List models in Gemini format |
+| `/v1beta/models/{...path}` | POST | Gemini `generateContent` endpoint |
+
+These endpoints mirror Gemini's API format for clients that expect native Gemini SDK compatibility.
+
+### Internal / System APIs
+
+| Endpoint | Method | Description |
+| --------------- | ------ | ---------------------------------------------------- |
+| `/api/init` | GET | Application initialization check (used on first run) |
+| `/api/tags` | GET | Ollama-compatible model tags (for Ollama clients) |
+| `/api/restart` | POST | Trigger graceful server restart |
+| `/api/shutdown` | POST | Trigger graceful server shutdown |
+
+> **Note:** These endpoints are used internally by the system or for Ollama client compatibility. They are not typically called by end users.
+
+---
+
+## Audio Transcription
+
+```bash
+POST /v1/audio/transcriptions
+Authorization: Bearer your-api-key
+Content-Type: multipart/form-data
+```
+
+Transcribe audio files using Deepgram or AssemblyAI.
+
+**Request:**
+
+```bash
+curl -X POST http://localhost:20128/v1/audio/transcriptions \
+ -H "Authorization: Bearer your-api-key" \
+ -F "file=@recording.mp3" \
+ -F "model=deepgram/nova-3"
+```
+
+**Response:**
+
+```json
+{
+ "text": "Hello, this is the transcribed audio content.",
+ "task": "transcribe",
+ "language": "en",
+ "duration": 12.5
+}
+```
+
+**Supported providers:** `deepgram/nova-3`, `assemblyai/best`.
+
+**Supported formats:** `mp3`, `wav`, `m4a`, `flac`, `ogg`, `webm`.
+
+---
+
+## Ollama Compatibility
+
+For clients that use Ollama's API format:
+
+```bash
+# Chat endpoint (Ollama format)
+POST /v1/api/chat
+
+# Model listing (Ollama format)
+GET /api/tags
+```
+
+Requests are automatically translated between Ollama and internal formats.
+
+---
+
+## Telemetry
+
+```bash
+# Get latency telemetry summary (p50/p95/p99 per provider)
+GET /api/telemetry/summary
+```
+
+**Response:**
+
+```json
+{
+ "providers": {
+ "claudeCode": { "p50": 245, "p95": 890, "p99": 1200, "count": 150 },
+ "github": { "p50": 180, "p95": 620, "p99": 950, "count": 320 }
+ }
+}
+```
+
+---
+
+## Budget
+
+```bash
+# Get budget status for all API keys
+GET /api/usage/budget
+
+# Set or update a budget
+POST /api/usage/budget
+Content-Type: application/json
+
+{
+ "keyId": "key-123",
+ "limit": 50.00,
+ "period": "monthly"
+}
+```
+
+---
+
+## Model Availability
+
+```bash
+# Get real-time model availability across all providers
+GET /api/models/availability
+
+# Check availability for a specific model
+POST /api/models/availability
+Content-Type: application/json
+
+{
+ "model": "claude-sonnet-4-5-20250929"
+}
+```
+
+---
+
+## Request Processing
+
+1. Client sends request to `/v1/*`
+2. Route handler calls `handleChat`, `handleEmbedding`, `handleAudioTranscription`, or `handleImageGeneration`
+3. Model is resolved (direct provider/model or alias/combo)
+4. Credentials selected from local DB with account availability filtering
+5. For chat: `handleChatCore` — format detection, translation, cache check, idempotency check
+6. Provider executor sends upstream request
+7. Response translated back to client format (chat) or returned as-is (embeddings/images/audio)
+8. Usage/logging recorded
+9. Fallback applies on errors according to combo rules
+
+Full architecture reference: [`ARCHITECTURE.md`](ARCHITECTURE.md)
+
+---
+
+## Authentication
+
+- Dashboard routes (`/dashboard/*`) use `auth_token` cookie
+- Login uses saved password hash; fallback to `INITIAL_PASSWORD`
+- `requireLogin` toggleable via `/api/settings/require-login`
+- `/v1/*` routes optionally require Bearer API key when `REQUIRE_API_KEY=true`
diff --git a/docs/i18n/bg/docs/ARCHITECTURE.md b/docs/i18n/bg/docs/ARCHITECTURE.md
new file mode 100644
index 0000000000..01ffe3a560
--- /dev/null
+++ b/docs/i18n/bg/docs/ARCHITECTURE.md
@@ -0,0 +1,814 @@
+# OmniRoute Architecture (Български)
+
+🌐 **Languages:** 🇺🇸 [English](../../../../docs/ARCHITECTURE.md) · 🇪🇸 [es](../../es/docs/ARCHITECTURE.md) · 🇫🇷 [fr](../../fr/docs/ARCHITECTURE.md) · 🇩🇪 [de](../../de/docs/ARCHITECTURE.md) · 🇮🇹 [it](../../it/docs/ARCHITECTURE.md) · 🇷🇺 [ru](../../ru/docs/ARCHITECTURE.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/ARCHITECTURE.md) · 🇯🇵 [ja](../../ja/docs/ARCHITECTURE.md) · 🇰🇷 [ko](../../ko/docs/ARCHITECTURE.md) · 🇸🇦 [ar](../../ar/docs/ARCHITECTURE.md) · 🇮🇳 [in](../../in/docs/ARCHITECTURE.md) · 🇹🇭 [th](../../th/docs/ARCHITECTURE.md) · 🇻🇳 [vi](../../vi/docs/ARCHITECTURE.md) · 🇮🇩 [id](../../id/docs/ARCHITECTURE.md) · 🇲🇾 [ms](../../ms/docs/ARCHITECTURE.md) · 🇳🇱 [nl](../../nl/docs/ARCHITECTURE.md) · 🇵🇱 [pl](../../pl/docs/ARCHITECTURE.md) · 🇸🇪 [sv](../../sv/docs/ARCHITECTURE.md) · 🇳🇴 [no](../../no/docs/ARCHITECTURE.md) · 🇩🇰 [da](../../da/docs/ARCHITECTURE.md) · 🇫🇮 [fi](../../fi/docs/ARCHITECTURE.md) · 🇵🇹 [pt](../../pt/docs/ARCHITECTURE.md) · 🇷🇴 [ro](../../ro/docs/ARCHITECTURE.md) · 🇭🇺 [hu](../../hu/docs/ARCHITECTURE.md) · 🇧🇬 [bg](../../bg/docs/ARCHITECTURE.md) · 🇸🇰 [sk](../../sk/docs/ARCHITECTURE.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/ARCHITECTURE.md) · 🇮🇱 [he](../../he/docs/ARCHITECTURE.md) · 🇵🇭 [phi](../../phi/docs/ARCHITECTURE.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/ARCHITECTURE.md) · 🇨🇿 [cs](../../cs/docs/ARCHITECTURE.md)
+
+---
+
+_Last updated: 2026-03-28_
+
+## Executive Summary
+
+OmniRoute is a local AI routing gateway and dashboard built on Next.js.
+It provides a single OpenAI-compatible endpoint (`/v1/*`) and routes traffic across multiple upstream providers with translation, fallback, token refresh, and usage tracking.
+
+Core capabilities:
+
+- OpenAI-compatible API surface for CLI/tools (28 providers)
+- Request/response translation across provider formats
+- Model combo fallback (multi-model sequence)
+- Account-level fallback (multi-account per provider)
+- OAuth + API-key provider connection management
+- Embedding generation via `/v1/embeddings` (6 providers, 9 models)
+- Image generation via `/v1/images/generations` (4 providers, 9 models)
+- Think tag parsing (`...`) for reasoning models
+- Response sanitization for strict OpenAI SDK compatibility
+- Role normalization (developer→system, system→user) for cross-provider compatibility
+- Structured output conversion (json_schema → Gemini responseSchema)
+- Local persistence for providers, keys, aliases, combos, settings, pricing
+- Usage/cost tracking and request logging
+- Optional cloud sync for multi-device/state sync
+- IP allowlist/blocklist for API access control
+- Thinking budget management (passthrough/auto/custom/adaptive)
+- Global system prompt injection
+- Session tracking and fingerprinting
+- Per-account enhanced rate limiting with provider-specific profiles
+- Circuit breaker pattern for provider resilience
+- Anti-thundering herd protection with mutex locking
+- Signature-based request deduplication cache
+- Domain layer: model availability, cost rules, fallback policy, lockout policy
+- Domain state persistence (SQLite write-through cache for fallbacks, budgets, lockouts, circuit breakers)
+- Policy engine for centralized request evaluation (lockout → budget → fallback)
+- Request telemetry with p50/p95/p99 latency aggregation
+- Correlation ID (X-Request-Id) for end-to-end tracing
+- Compliance audit logging with opt-out per API key
+- Eval framework for LLM quality assurance
+- Resilience UI dashboard with real-time circuit breaker status
+- Modular OAuth providers (12 individual modules under `src/lib/oauth/providers/`)
+
+Primary runtime model:
+
+- Next.js app routes under `src/app/api/*` implement both dashboard APIs and compatibility APIs
+- A shared SSE/routing core in `src/sse/*` + `open-sse/*` handles provider execution, translation, streaming, fallback, and usage
+
+## Scope and Boundaries
+
+### In Scope
+
+- Local gateway runtime
+- Dashboard management APIs
+- Provider authentication and token refresh
+- Request translation and SSE streaming
+- Local state + usage persistence
+- Optional cloud sync orchestration
+
+### Out of Scope
+
+- Cloud service implementation behind `NEXT_PUBLIC_CLOUD_URL`
+- Provider SLA/control plane outside local process
+- External CLI binaries themselves (Claude CLI, Codex CLI, etc.)
+
+## Dashboard Surface (Current)
+
+Main pages under `src/app/(dashboard)/dashboard/`:
+
+- `/dashboard` — quick start + provider overview
+- `/dashboard/endpoint` — endpoint proxy + MCP + A2A + API endpoint tabs
+- `/dashboard/providers` — provider connections and credentials
+- `/dashboard/combos` — combo strategies, templates, model routing rules
+- `/dashboard/costs` — cost aggregation and pricing visibility
+- `/dashboard/analytics` — usage analytics and evaluations
+- `/dashboard/limits` — quota/rate controls
+- `/dashboard/cli-tools` — CLI onboarding, runtime detection, config generation
+- `/dashboard/agents` — detected ACP agents + custom agent registration
+- `/dashboard/media` — image/video/music playground
+- `/dashboard/search-tools` — search provider testing and history
+- `/dashboard/health` — uptime, circuit breakers, rate limits
+- `/dashboard/logs` — request/proxy/audit/console logs
+- `/dashboard/settings` — system settings tabs (general, routing, combo defaults, etc.)
+- `/dashboard/api-manager` — API key lifecycle and model permissions
+
+## High-Level System Context
+
+```mermaid
+flowchart LR
+ subgraph Clients[Developer Clients]
+ C1[Claude Code]
+ C2[Codex CLI]
+ C3[OpenClaw / Droid / Cline / Continue / Roo]
+ C4[Custom OpenAI-compatible clients]
+ BROWSER[Browser Dashboard]
+ end
+
+ subgraph Router[OmniRoute Local Process]
+ API[V1 Compatibility API\n/v1/*]
+ DASH[Dashboard + Management API\n/api/*]
+ CORE[SSE + Translation Core\nopen-sse + src/sse]
+ DB[(storage.sqlite)]
+ UDB[(usage tables + log artifacts)]
+ end
+
+ subgraph Upstreams[Upstream Providers]
+ P1[OAuth Providers\nClaude/Codex/Gemini/Qwen/Qoder/GitHub/Kiro/Cursor/Antigravity]
+ P2[API Key Providers\nOpenAI/Anthropic/OpenRouter/GLM/Kimi/MiniMax\nDeepSeek/Groq/xAI/Mistral/Perplexity\nTogether/Fireworks/Cerebras/Cohere/NVIDIA]
+ P3[Compatible Nodes\nOpenAI-compatible / Anthropic-compatible]
+ end
+
+ subgraph Cloud[Optional Cloud Sync]
+ CLOUD[Cloud Sync Endpoint\nNEXT_PUBLIC_CLOUD_URL]
+ end
+
+ C1 --> API
+ C2 --> API
+ C3 --> API
+ C4 --> API
+ BROWSER --> DASH
+
+ API --> CORE
+ DASH --> DB
+ CORE --> DB
+ CORE --> UDB
+
+ CORE --> P1
+ CORE --> P2
+ CORE --> P3
+
+ DASH --> CLOUD
+```
+
+## Core Runtime Components
+
+## 1) API and Routing Layer (Next.js App Routes)
+
+Main directories:
+
+- `src/app/api/v1/*` and `src/app/api/v1beta/*` for compatibility APIs
+- `src/app/api/*` for management/configuration APIs
+- Next rewrites in `next.config.mjs` map `/v1/*` to `/api/v1/*`
+
+Important compatibility routes:
+
+- `src/app/api/v1/chat/completions/route.ts`
+- `src/app/api/v1/messages/route.ts`
+- `src/app/api/v1/responses/route.ts`
+- `src/app/api/v1/models/route.ts` — includes custom models with `custom: true`
+- `src/app/api/v1/embeddings/route.ts` — embedding generation (6 providers)
+- `src/app/api/v1/images/generations/route.ts` — image generation (4+ providers incl. Antigravity/Nebius)
+- `src/app/api/v1/messages/count_tokens/route.ts`
+- `src/app/api/v1/providers/[provider]/chat/completions/route.ts` — dedicated per-provider chat
+- `src/app/api/v1/providers/[provider]/embeddings/route.ts` — dedicated per-provider embeddings
+- `src/app/api/v1/providers/[provider]/images/generations/route.ts` — dedicated per-provider images
+- `src/app/api/v1beta/models/route.ts`
+- `src/app/api/v1beta/models/[...path]/route.ts`
+
+Management domains:
+
+- Auth/settings: `src/app/api/auth/*`, `src/app/api/settings/*`
+- Providers/connections: `src/app/api/providers*`
+- Provider nodes: `src/app/api/provider-nodes*`
+- Custom models: `src/app/api/provider-models` (GET/POST/DELETE)
+- Model catalog: `src/app/api/models/route.ts` (GET)
+- Proxy config: `src/app/api/settings/proxy` (GET/PUT/DELETE) + `src/app/api/settings/proxy/test` (POST)
+- OAuth: `src/app/api/oauth/*`
+- Keys/aliases/combos/pricing: `src/app/api/keys*`, `src/app/api/models/alias`, `src/app/api/combos*`, `src/app/api/pricing`
+- Usage: `src/app/api/usage/*`
+- Sync/cloud: `src/app/api/sync/*`, `src/app/api/cloud/*`
+- CLI tooling helpers: `src/app/api/cli-tools/*`
+- IP filter: `src/app/api/settings/ip-filter` (GET/PUT)
+- Thinking budget: `src/app/api/settings/thinking-budget` (GET/PUT)
+- System prompt: `src/app/api/settings/system-prompt` (GET/PUT)
+- Sessions: `src/app/api/sessions` (GET)
+- Rate limits: `src/app/api/rate-limits` (GET)
+- Resilience: `src/app/api/resilience` (GET/PATCH) — provider profiles, circuit breaker, rate limit state
+- Resilience reset: `src/app/api/resilience/reset` (POST) — reset breakers + cooldowns
+- Cache stats: `src/app/api/cache/stats` (GET/DELETE)
+- Model availability: `src/app/api/models/availability` (GET/POST)
+- Telemetry: `src/app/api/telemetry/summary` (GET)
+- Budget: `src/app/api/usage/budget` (GET/POST)
+- Fallback chains: `src/app/api/fallback/chains` (GET/POST/DELETE)
+- Compliance audit: `src/app/api/compliance/audit-log` (GET)
+- Evals: `src/app/api/evals` (GET/POST), `src/app/api/evals/[suiteId]` (GET)
+- Policies: `src/app/api/policies` (GET/POST)
+
+## 2) SSE + Translation Core
+
+Main flow modules:
+
+- Entry: `src/sse/handlers/chat.ts`
+- Core orchestration: `open-sse/handlers/chatCore.ts`
+- Provider execution adapters: `open-sse/executors/*`
+- Format detection/provider config: `open-sse/services/provider.ts`
+- Model parse/resolve: `src/sse/services/model.ts`, `open-sse/services/model.ts`
+- Account fallback logic: `open-sse/services/accountFallback.ts`
+- Translation registry: `open-sse/translator/index.ts`
+- Stream transformations: `open-sse/utils/stream.ts`, `open-sse/utils/streamHandler.ts`
+- Usage extraction/normalization: `open-sse/utils/usageTracking.ts`
+- Think tag parser: `open-sse/utils/thinkTagParser.ts`
+- Embedding handler: `open-sse/handlers/embeddings.ts`
+- Embedding provider registry: `open-sse/config/embeddingRegistry.ts`
+- Image generation handler: `open-sse/handlers/imageGeneration.ts`
+- Image provider registry: `open-sse/config/imageRegistry.ts`
+- Response sanitization: `open-sse/handlers/responseSanitizer.ts`
+- Role normalization: `open-sse/services/roleNormalizer.ts`
+
+Services (business logic):
+
+- Account selection/scoring: `open-sse/services/accountSelector.ts`
+- Context lifecycle management: `open-sse/services/contextManager.ts`
+- IP filter enforcement: `open-sse/services/ipFilter.ts`
+- Session tracking: `open-sse/services/sessionManager.ts`
+- Request deduplication: `open-sse/services/signatureCache.ts`
+- System prompt injection: `open-sse/services/systemPrompt.ts`
+- Thinking budget management: `open-sse/services/thinkingBudget.ts`
+- Wildcard model routing: `open-sse/services/wildcardRouter.ts`
+- Rate limit management: `open-sse/services/rateLimitManager.ts`
+- Circuit breaker: `open-sse/services/circuitBreaker.ts`
+
+Domain layer modules:
+
+- Model availability: `src/lib/domain/modelAvailability.ts`
+- Cost rules/budgets: `src/lib/domain/costRules.ts`
+- Fallback policy: `src/lib/domain/fallbackPolicy.ts`
+- Combo resolver: `src/lib/domain/comboResolver.ts`
+- Lockout policy: `src/lib/domain/lockoutPolicy.ts`
+- Policy engine: `src/domain/policyEngine.ts` — centralized lockout → budget → fallback evaluation
+- Error codes catalog: `src/lib/domain/errorCodes.ts`
+- Request ID: `src/lib/domain/requestId.ts`
+- Fetch timeout: `src/lib/domain/fetchTimeout.ts`
+- Request telemetry: `src/lib/domain/requestTelemetry.ts`
+- Compliance/audit: `src/lib/domain/compliance/index.ts`
+- Eval runner: `src/lib/domain/evalRunner.ts`
+- Domain state persistence: `src/lib/db/domainState.ts` — SQLite CRUD for fallback chains, budgets, cost history, lockout state, circuit breakers
+
+OAuth provider modules (12 individual files under `src/lib/oauth/providers/`):
+
+- Registry index: `src/lib/oauth/providers/index.ts`
+- Individual providers: `claude.ts`, `codex.ts`, `gemini.ts`, `antigravity.ts`, `qoder.ts`, `qwen.ts`, `kimi-coding.ts`, `github.ts`, `kiro.ts`, `cursor.ts`, `kilocode.ts`, `cline.ts`
+- Thin wrapper: `src/lib/oauth/providers.ts` — re-exports from individual modules
+
+## 3) Persistence Layer
+
+Primary state DB (SQLite):
+
+- Core infra: `src/lib/db/core.ts` (better-sqlite3, migrations, WAL)
+- Re-export facade: `src/lib/localDb.ts` (thin compatibility layer for callers)
+- file: `${DATA_DIR}/storage.sqlite` (or `$XDG_CONFIG_HOME/omniroute/storage.sqlite` when set, else `~/.omniroute/storage.sqlite`)
+- entities (tables + KV namespaces): providerConnections, providerNodes, modelAliases, combos, apiKeys, settings, pricing, **customModels**, **proxyConfig**, **ipFilter**, **thinkingBudget**, **systemPrompt**
+
+Usage persistence:
+
+- facade: `src/lib/usageDb.ts` (decomposed modules in `src/lib/usage/*`)
+- SQLite tables in `storage.sqlite`: `usage_history`, `call_logs`, `proxy_logs`
+- optional file artifacts remain for compatibility/debug (`${DATA_DIR}/log.txt`, `${DATA_DIR}/call_logs/`, `/logs/...`)
+- legacy JSON files are migrated to SQLite by startup migrations when present
+
+Domain State DB (SQLite):
+
+- `src/lib/db/domainState.ts` — CRUD operations for domain state
+- Tables (created in `src/lib/db/core.ts`): `domain_fallback_chains`, `domain_budgets`, `domain_cost_history`, `domain_lockout_state`, `domain_circuit_breakers`
+- Write-through cache pattern: in-memory Maps are authoritative at runtime; mutations are written synchronously to SQLite; state is restored from DB on cold start
+
+## 4) Auth + Security Surfaces
+
+- Dashboard cookie auth: `src/proxy.ts`, `src/app/api/auth/login/route.ts`
+- API key generation/verification: `src/shared/utils/apiKey.ts`
+- Provider secrets persisted in `providerConnections` entries
+- Outbound proxy support via `open-sse/utils/proxyFetch.ts` (env vars) and `open-sse/utils/networkProxy.ts` (configurable per-provider or global)
+
+## 5) Cloud Sync
+
+- Scheduler init: `src/lib/initCloudSync.ts`, `src/shared/services/initializeCloudSync.ts`, `src/shared/services/modelSyncScheduler.ts`
+- Periodic task: `src/shared/services/cloudSyncScheduler.ts`
+- Periodic task: `src/shared/services/modelSyncScheduler.ts`
+- Control route: `src/app/api/sync/cloud/route.ts`
+
+## Request Lifecycle (`/v1/chat/completions`)
+
+```mermaid
+sequenceDiagram
+ autonumber
+ participant Client as CLI/SDK Client
+ participant Route as /api/v1/chat/completions
+ participant Chat as src/sse/handlers/chat
+ participant Core as open-sse/handlers/chatCore
+ participant Model as Model Resolver
+ participant Auth as Credential Selector
+ participant Exec as Provider Executor
+ participant Prov as Upstream Provider
+ participant Stream as Stream Translator
+ participant Usage as usageDb
+
+ Client->>Route: POST /v1/chat/completions
+ Route->>Chat: handleChat(request)
+ Chat->>Model: parse/resolve model or combo
+
+ alt Combo model
+ Chat->>Chat: iterate combo models (handleComboChat)
+ end
+
+ Chat->>Auth: getProviderCredentials(provider)
+ Auth-->>Chat: active account + tokens/api key
+
+ Chat->>Core: handleChatCore(body, modelInfo, credentials)
+ Core->>Core: detect source format
+ Core->>Core: translate request to target format
+ Core->>Exec: execute(provider, transformedBody)
+ Exec->>Prov: upstream API call
+ Prov-->>Exec: SSE/JSON response
+ Exec-->>Core: response + metadata
+
+ alt 401/403
+ Core->>Exec: refreshCredentials()
+ Exec-->>Core: updated tokens
+ Core->>Exec: retry request
+ end
+
+ Core->>Stream: translate/normalize stream to client format
+ Stream-->>Client: SSE chunks / JSON response
+
+ Stream->>Usage: extract usage + persist history/log
+```
+
+## Combo + Account Fallback Flow
+
+```mermaid
+flowchart TD
+ A[Incoming model string] --> B{Is combo name?}
+ B -- Yes --> C[Load combo models sequence]
+ B -- No --> D[Single model path]
+
+ C --> E[Try model N]
+ E --> F[Resolve provider/model]
+ D --> F
+
+ F --> G[Select account credentials]
+ G --> H{Credentials available?}
+ H -- No --> I[Return provider unavailable]
+ H -- Yes --> J[Execute request]
+
+ J --> K{Success?}
+ K -- Yes --> L[Return response]
+ K -- No --> M{Fallback-eligible error?}
+
+ M -- No --> N[Return error]
+ M -- Yes --> O[Mark account unavailable cooldown]
+ O --> P{Another account for provider?}
+ P -- Yes --> G
+ P -- No --> Q{In combo with next model?}
+ Q -- Yes --> E
+ Q -- No --> R[Return all unavailable]
+```
+
+Fallback decisions are driven by `open-sse/services/accountFallback.ts` using status codes and error-message heuristics. Combo routing adds one extra guard: provider-scoped 400s such as upstream content-block and role-validation failures are treated as model-local failures so later combo targets can still run.
+
+## OAuth Onboarding and Token Refresh Lifecycle
+
+```mermaid
+sequenceDiagram
+ autonumber
+ participant UI as Dashboard UI
+ participant OAuth as /api/oauth/[provider]/[action]
+ participant ProvAuth as Provider Auth Server
+ participant DB as localDb
+ participant Test as /api/providers/[id]/test
+ participant Exec as Provider Executor
+
+ UI->>OAuth: GET authorize or device-code
+ OAuth->>ProvAuth: create auth/device flow
+ ProvAuth-->>OAuth: auth URL or device code payload
+ OAuth-->>UI: flow data
+
+ UI->>OAuth: POST exchange or poll
+ OAuth->>ProvAuth: token exchange/poll
+ ProvAuth-->>OAuth: access/refresh tokens
+ OAuth->>DB: createProviderConnection(oauth data)
+ OAuth-->>UI: success + connection id
+
+ UI->>Test: POST /api/providers/[id]/test
+ Test->>Exec: validate credentials / optional refresh
+ Exec-->>Test: valid or refreshed token info
+ Test->>DB: update status/tokens/errors
+ Test-->>UI: validation result
+```
+
+Refresh during live traffic is executed inside `open-sse/handlers/chatCore.ts` via executor `refreshCredentials()`.
+
+## Cloud Sync Lifecycle (Enable / Sync / Disable)
+
+```mermaid
+sequenceDiagram
+ autonumber
+ participant UI as Endpoint Page UI
+ participant Sync as /api/sync/cloud
+ participant DB as localDb
+ participant Cloud as External Cloud Sync
+ participant Claude as ~/.claude/settings.json
+
+ UI->>Sync: POST action=enable
+ Sync->>DB: set cloudEnabled=true
+ Sync->>DB: ensure API key exists
+ Sync->>Cloud: POST /sync/{machineId} (providers/aliases/combos/keys)
+ Cloud-->>Sync: sync result
+ Sync->>Cloud: GET /{machineId}/v1/verify
+ Sync-->>UI: enabled + verification status
+
+ UI->>Sync: POST action=sync
+ Sync->>Cloud: POST /sync/{machineId}
+ Cloud-->>Sync: remote data
+ Sync->>DB: update newer local tokens/status
+ Sync-->>UI: synced
+
+ UI->>Sync: POST action=disable
+ Sync->>DB: set cloudEnabled=false
+ Sync->>Cloud: DELETE /sync/{machineId}
+ Sync->>Claude: switch ANTHROPIC_BASE_URL back to local (if needed)
+ Sync-->>UI: disabled
+```
+
+Periodic sync is triggered by `CloudSyncScheduler` when cloud is enabled.
+
+## Data Model and Storage Map
+
+```mermaid
+erDiagram
+ SETTINGS ||--o{ PROVIDER_CONNECTION : controls
+ PROVIDER_NODE ||--o{ PROVIDER_CONNECTION : backs_compatible_provider
+ PROVIDER_CONNECTION ||--o{ USAGE_ENTRY : emits_usage
+
+ SETTINGS {
+ boolean cloudEnabled
+ number stickyRoundRobinLimit
+ boolean requireLogin
+ string password_hash
+ string fallbackStrategy
+ json rateLimitDefaults
+ json providerProfiles
+ }
+
+ PROVIDER_CONNECTION {
+ string id
+ string provider
+ string authType
+ string name
+ number priority
+ boolean isActive
+ string apiKey
+ string accessToken
+ string refreshToken
+ string expiresAt
+ string testStatus
+ string lastError
+ string rateLimitedUntil
+ json providerSpecificData
+ }
+
+ PROVIDER_NODE {
+ string id
+ string type
+ string name
+ string prefix
+ string apiType
+ string baseUrl
+ }
+
+ MODEL_ALIAS {
+ string alias
+ string targetModel
+ }
+
+ COMBO {
+ string id
+ string name
+ string[] models
+ }
+
+ API_KEY {
+ string id
+ string name
+ string key
+ string machineId
+ }
+
+ USAGE_ENTRY {
+ string provider
+ string model
+ number prompt_tokens
+ number completion_tokens
+ string connectionId
+ string timestamp
+ }
+
+ CUSTOM_MODEL {
+ string id
+ string name
+ string providerId
+ }
+
+ PROXY_CONFIG {
+ string global
+ json providers
+ }
+
+ IP_FILTER {
+ string mode
+ string[] allowlist
+ string[] blocklist
+ }
+
+ THINKING_BUDGET {
+ string mode
+ number customBudget
+ string effortLevel
+ }
+
+ SYSTEM_PROMPT {
+ boolean enabled
+ string prompt
+ string position
+ }
+```
+
+Physical storage files:
+
+- primary runtime DB: `${DATA_DIR}/storage.sqlite`
+- request log lines: `${DATA_DIR}/log.txt` (compat/debug artifact)
+- structured call payload archives: `${DATA_DIR}/call_logs/`
+- optional translator/request debug sessions: `/logs/...`
+
+## Deployment Topology
+
+```mermaid
+flowchart LR
+ subgraph LocalHost[Developer Host]
+ CLI[CLI Tools]
+ Browser[Dashboard Browser]
+ end
+
+ subgraph ContainerOrProcess[OmniRoute Runtime]
+ Next[Next.js Server\nPORT=20128]
+ Core[SSE Core + Executors]
+ MainDB[(storage.sqlite)]
+ UsageDB[(usage tables + log artifacts)]
+ end
+
+ subgraph External[External Services]
+ Providers[AI Providers]
+ SyncCloud[Cloud Sync Service]
+ end
+
+ CLI --> Next
+ Browser --> Next
+ Next --> Core
+ Next --> MainDB
+ Core --> MainDB
+ Core --> UsageDB
+ Core --> Providers
+ Next --> SyncCloud
+```
+
+## Module Mapping (Decision-Critical)
+
+### Route and API Modules
+
+- `src/app/api/v1/*`, `src/app/api/v1beta/*`: compatibility APIs
+- `src/app/api/v1/providers/[provider]/*`: dedicated per-provider routes (chat, embeddings, images)
+- `src/app/api/providers*`: provider CRUD, validation, testing
+- `src/app/api/provider-nodes*`: custom compatible node management
+- `src/app/api/provider-models`: custom model management (CRUD)
+- `src/app/api/models/route.ts`: model catalog API (aliases + custom models)
+- `src/app/api/oauth/*`: OAuth/device-code flows
+- `src/app/api/keys*`: local API key lifecycle
+- `src/app/api/models/alias`: alias management
+- `src/app/api/combos*`: fallback combo management
+- `src/app/api/pricing`: pricing overrides for cost calculation
+- `src/app/api/settings/proxy`: proxy configuration (GET/PUT/DELETE)
+- `src/app/api/settings/proxy/test`: outbound proxy connectivity test (POST)
+- `src/app/api/usage/*`: usage and logs APIs
+- `src/app/api/sync/*` + `src/app/api/cloud/*`: cloud sync and cloud-facing helpers
+- `src/app/api/cli-tools/*`: local CLI config writers/checkers
+- `src/app/api/settings/ip-filter`: IP allowlist/blocklist (GET/PUT)
+- `src/app/api/settings/thinking-budget`: thinking token budget config (GET/PUT)
+- `src/app/api/settings/system-prompt`: global system prompt (GET/PUT)
+- `src/app/api/sessions`: active session listing (GET)
+- `src/app/api/rate-limits`: per-account rate limit status (GET)
+
+### Routing and Execution Core
+
+- `src/sse/handlers/chat.ts`: request parse, combo handling, account selection loop
+- `open-sse/handlers/chatCore.ts`: translation, executor dispatch, retry/refresh handling, stream setup
+- `open-sse/executors/*`: provider-specific network and format behavior
+
+### Translation Registry and Format Converters
+
+- `open-sse/translator/index.ts`: translator registry and orchestration
+- Request translators: `open-sse/translator/request/*`
+- Response translators: `open-sse/translator/response/*`
+- Format constants: `open-sse/translator/formats.ts`
+
+### Persistence
+
+- `src/lib/db/*`: persistent config/state and domain persistence on SQLite
+- `src/lib/localDb.ts`: compatibility re-export for DB modules
+- `src/lib/usageDb.ts`: usage history/call logs facade on top of SQLite tables
+
+## Provider Executor Coverage (Strategy Pattern)
+
+Each provider has a specialized executor extending `BaseExecutor` (in `open-sse/executors/base.ts`), which provides URL building, header construction, retry with exponential backoff, credential refresh hooks, and the `execute()` orchestration method.
+
+| Executor | Provider(s) | Special Handling |
+| --------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------ | -------------------------------------------------------------------- |
+| `DefaultExecutor` | OpenAI, Claude, Gemini, Qwen, Qoder, OpenRouter, GLM, Kimi, MiniMax, DeepSeek, Groq, xAI, Mistral, Perplexity, Together, Fireworks, Cerebras, Cohere, NVIDIA | Dynamic URL/header config per provider |
+| `AntigravityExecutor` | Google Antigravity | Custom project/session IDs, Retry-After parsing |
+| `CodexExecutor` | OpenAI Codex | Injects system instructions, forces reasoning effort |
+| `CursorExecutor` | Cursor IDE | ConnectRPC protocol, Protobuf encoding, request signing via checksum |
+| `GithubExecutor` | GitHub Copilot | Copilot token refresh, VSCode-mimicking headers |
+| `KiroExecutor` | AWS CodeWhisperer/Kiro | AWS EventStream binary format → SSE conversion |
+| `GeminiCLIExecutor` | Gemini CLI | Google OAuth token refresh cycle |
+
+All other providers (including custom compatible nodes) use the `DefaultExecutor`.
+
+## Provider Compatibility Matrix
+
+| Provider | Format | Auth | Stream | Non-Stream | Token Refresh | Usage API |
+| ---------------- | ---------------- | --------------------- | ---------------- | ---------- | ------------- | ------------------ |
+| Claude | claude | API Key / OAuth | ✅ | ✅ | ✅ | ⚠️ Admin only |
+| Gemini | gemini | API Key / OAuth | ✅ | ✅ | ✅ | ⚠️ Cloud Console |
+| Gemini CLI | gemini-cli | OAuth | ✅ | ✅ | ✅ | ⚠️ Cloud Console |
+| Antigravity | antigravity | OAuth | ✅ | ✅ | ✅ | ✅ Full quota API |
+| OpenAI | openai | API Key | ✅ | ✅ | ❌ | ❌ |
+| Codex | openai-responses | OAuth | ✅ forced | ❌ | ✅ | ✅ Rate limits |
+| GitHub Copilot | openai | OAuth + Copilot Token | ✅ | ✅ | ✅ | ✅ Quota snapshots |
+| Cursor | cursor | Custom checksum | ✅ | ✅ | ❌ | ❌ |
+| Kiro | kiro | AWS SSO OIDC | ✅ (EventStream) | ❌ | ✅ | ✅ Usage limits |
+| Qwen | openai | OAuth | ✅ | ✅ | ✅ | ⚠️ Per request |
+| Qoder | openai | OAuth (Basic) | ✅ | ✅ | ✅ | ⚠️ Per request |
+| OpenRouter | openai | API Key | ✅ | ✅ | ❌ | ❌ |
+| GLM/Kimi/MiniMax | claude | API Key | ✅ | ✅ | ❌ | ❌ |
+| DeepSeek | openai | API Key | ✅ | ✅ | ❌ | ❌ |
+| Groq | openai | API Key | ✅ | ✅ | ❌ | ❌ |
+| xAI (Grok) | openai | API Key | ✅ | ✅ | ❌ | ❌ |
+| Mistral | openai | API Key | ✅ | ✅ | ❌ | ❌ |
+| Perplexity | openai | API Key | ✅ | ✅ | ❌ | ❌ |
+| Together AI | openai | API Key | ✅ | ✅ | ❌ | ❌ |
+| Fireworks AI | openai | API Key | ✅ | ✅ | ❌ | ❌ |
+| Cerebras | openai | API Key | ✅ | ✅ | ❌ | ❌ |
+| Cohere | openai | API Key | ✅ | ✅ | ❌ | ❌ |
+| NVIDIA NIM | openai | API Key | ✅ | ✅ | ❌ | ❌ |
+
+## Format Translation Coverage
+
+Detected source formats include:
+
+- `openai`
+- `openai-responses`
+- `claude`
+- `gemini`
+
+Target formats include:
+
+- OpenAI chat/Responses
+- Claude
+- Gemini/Gemini-CLI/Antigravity envelope
+- Kiro
+- Cursor
+
+Translations use **OpenAI as the hub format** — all conversions go through OpenAI as intermediate:
+
+```
+Source Format → OpenAI (hub) → Target Format
+```
+
+Translations are selected dynamically based on source payload shape and provider target format.
+
+Additional processing layers in the translation pipeline:
+
+- **Response sanitization** — Strips non-standard fields from OpenAI-format responses (both streaming and non-streaming) to ensure strict SDK compliance
+- **Role normalization** — Converts `developer` → `system` for non-OpenAI targets; merges `system` → `user` for models that reject the system role (GLM, ERNIE)
+- **Think tag extraction** — Parses `...` blocks from content into `reasoning_content` field
+- **Structured output** — Converts OpenAI `response_format.json_schema` to Gemini's `responseMimeType` + `responseSchema`
+
+## Supported API Endpoints
+
+| Endpoint | Format | Handler |
+| -------------------------------------------------- | ------------------ | ------------------------------------------------------------------- |
+| `POST /v1/chat/completions` | OpenAI Chat | `src/sse/handlers/chat.ts` |
+| `POST /v1/messages` | Claude Messages | Same handler (auto-detected) |
+| `POST /v1/responses` | OpenAI Responses | `open-sse/handlers/responsesHandler.ts` |
+| `POST /v1/embeddings` | OpenAI Embeddings | `open-sse/handlers/embeddings.ts` |
+| `GET /v1/embeddings` | Model listing | API route |
+| `POST /v1/images/generations` | OpenAI Images | `open-sse/handlers/imageGeneration.ts` |
+| `GET /v1/images/generations` | Model listing | API route |
+| `POST /v1/providers/{provider}/chat/completions` | OpenAI Chat | Dedicated per-provider with model validation |
+| `POST /v1/providers/{provider}/embeddings` | OpenAI Embeddings | Dedicated per-provider with model validation |
+| `POST /v1/providers/{provider}/images/generations` | OpenAI Images | Dedicated per-provider with model validation |
+| `POST /v1/messages/count_tokens` | Claude Token Count | API route |
+| `GET /v1/models` | OpenAI Models list | API route (chat + embedding + image + custom models) |
+| `GET /api/models/catalog` | Catalog | All models grouped by provider + type |
+| `POST /v1beta/models/*:streamGenerateContent` | Gemini native | API route |
+| `GET/PUT/DELETE /api/settings/proxy` | Proxy Config | Network proxy configuration |
+| `POST /api/settings/proxy/test` | Proxy Connectivity | Proxy health/connectivity test endpoint |
+| `GET/POST/DELETE /api/provider-models` | Provider Models | Provider model metadata backing custom and managed available models |
+
+## Bypass Handler
+
+The bypass handler (`open-sse/utils/bypassHandler.ts`) intercepts known "throwaway" requests from Claude CLI — warmup pings, title extractions, and token counts — and returns a **fake response** without consuming upstream provider tokens. This is triggered only when `User-Agent` contains `claude-cli`.
+
+## Request Logger Pipeline
+
+The request logger (`open-sse/utils/requestLogger.ts`) provides a 7-stage debug logging pipeline, disabled by default, enabled via `ENABLE_REQUEST_LOGS=true`:
+
+```
+1_req_client.json → 2_req_source.json → 3_req_openai.json → 4_req_target.json
+→ 5_res_provider.txt → 6_res_openai.txt → 7_res_client.txt
+```
+
+Files are written to `/logs//` for each request session.
+
+## Failure Modes and Resilience
+
+## 1) Account/Provider Availability
+
+- provider account cooldown on transient/rate/auth errors
+- account fallback before failing request
+- combo model fallback when current model/provider path is exhausted
+
+## 2) Token Expiry
+
+- pre-check and refresh with retry for refreshable providers
+- 401/403 retry after refresh attempt in core path
+
+## 3) Stream Safety
+
+- disconnect-aware stream controller
+- translation stream with end-of-stream flush and `[DONE]` handling
+- usage estimation fallback when provider usage metadata is missing
+
+## 4) Cloud Sync Degradation
+
+- sync errors are surfaced but local runtime continues
+- scheduler has retry-capable logic, but periodic execution currently calls single-attempt sync by default
+
+## 5) Data Integrity
+
+- SQLite schema migrations and auto-upgrade hooks at startup
+- legacy JSON → SQLite migration compatibility path
+
+## Observability and Operational Signals
+
+Runtime visibility sources:
+
+- console logs from `src/sse/utils/logger.ts`
+- per-request usage aggregates in SQLite (`usage_history`, `call_logs`, `proxy_logs`)
+- four-stage detailed payload captures in SQLite (`request_detail_logs`) when `settings.detailed_logs_enabled=true`
+- textual request status log in `log.txt` (optional/compat)
+- optional deep request/translation logs under `logs/` when `ENABLE_REQUEST_LOGS=true`
+- dashboard usage endpoints (`/api/usage/*`) for UI consumption
+
+Detailed request payload capture stores up to four JSON payload stages per routed call:
+
+- raw request received from the client
+- translated request actually sent upstream
+- provider response reconstructed as JSON; streamed responses are compacted to the final summary plus stream metadata
+- final client response returned by OmniRoute; streamed responses are stored in the same compact summary form
+
+## Security-Sensitive Boundaries
+
+- JWT secret (`JWT_SECRET`) secures dashboard session cookie verification/signing
+- Initial password bootstrap (`INITIAL_PASSWORD`) should be explicitly configured for first-run provisioning
+- API key HMAC secret (`API_KEY_SECRET`) secures generated local API key format
+- Provider secrets (API keys/tokens) are persisted in local DB and should be protected at filesystem level
+- Cloud sync endpoints rely on API key auth + machine id semantics
+
+## Environment and Runtime Matrix
+
+Environment variables actively used by code:
+
+- App/auth: `JWT_SECRET`, `INITIAL_PASSWORD`
+- Storage: `DATA_DIR`
+- Compatible node behavior: `ALLOW_MULTI_CONNECTIONS_PER_COMPAT_NODE`
+- Optional storage base override (Linux/macOS when `DATA_DIR` unset): `XDG_CONFIG_HOME`
+- Security hashing: `API_KEY_SECRET`, `MACHINE_ID_SALT`
+- Logging: `ENABLE_REQUEST_LOGS`
+- Sync/cloud URLing: `NEXT_PUBLIC_BASE_URL`, `NEXT_PUBLIC_CLOUD_URL`
+- Outbound proxy: `HTTP_PROXY`, `HTTPS_PROXY`, `ALL_PROXY`, `NO_PROXY` and lowercase variants
+- SOCKS5 feature flags: `ENABLE_SOCKS5_PROXY`, `NEXT_PUBLIC_ENABLE_SOCKS5_PROXY`
+- Platform/runtime helpers (not app-specific config): `APPDATA`, `NODE_ENV`, `PORT`, `HOSTNAME`
+
+## Known Architectural Notes
+
+1. `usageDb` and `localDb` share the same base directory policy (`DATA_DIR` -> `XDG_CONFIG_HOME/omniroute` -> `~/.omniroute`) with legacy file migration.
+2. `/api/v1/route.ts` delegates to the same unified catalog builder used by `/api/v1/models` (`src/app/api/v1/models/catalog.ts`) to avoid semantic drift.
+3. Request logger writes full headers/body when enabled; treat log directory as sensitive.
+4. Cloud behavior depends on correct `NEXT_PUBLIC_BASE_URL` and cloud endpoint reachability.
+5. The `open-sse/` directory is published as the `@omniroute/open-sse` **npm workspace package**. Source code imports it via `@omniroute/open-sse/...` (resolved by Next.js `transpilePackages`). File paths in this document still use the directory name `open-sse/` for consistency.
+6. Charts in the dashboard use **Recharts** (SVG-based) for accessible, interactive analytics visualizations (model usage bar charts, provider breakdown tables with success rates).
+7. E2E tests use **Playwright** (`tests/e2e/`), run via `npm run test:e2e`. Unit tests use **Node.js test runner** (`tests/unit/`), run via `npm run test:unit`. Source code under `src/` is **TypeScript** (`.ts`/`.tsx`); the `open-sse/` workspace remains JavaScript (`.js`).
+8. Settings page is organized into 5 tabs: Security, Routing (6 global strategies: fill-first, round-robin, p2c, random, least-used, cost-optimized), Resilience (editable rate limits, circuit breaker, policies), AI (thinking budget, system prompt, prompt cache), Advanced (proxy).
+
+## Operational Verification Checklist
+
+- Build from source: `npm run build`
+- Build Docker image: `docker build -t omniroute .`
+- Start service and verify:
+- `GET /api/settings`
+- `GET /api/v1/models`
+- CLI target base URL should be `http://:20128/v1` when `PORT=20128`
diff --git a/docs/i18n/bg/docs/AUTO-COMBO.md b/docs/i18n/bg/docs/AUTO-COMBO.md
new file mode 100644
index 0000000000..ae23e60325
--- /dev/null
+++ b/docs/i18n/bg/docs/AUTO-COMBO.md
@@ -0,0 +1,67 @@
+# OmniRoute Auto-Combo Engine (Български)
+
+🌐 **Languages:** 🇺🇸 [English](../../../../docs/AUTO-COMBO.md) · 🇪🇸 [es](../../es/docs/AUTO-COMBO.md) · 🇫🇷 [fr](../../fr/docs/AUTO-COMBO.md) · 🇩🇪 [de](../../de/docs/AUTO-COMBO.md) · 🇮🇹 [it](../../it/docs/AUTO-COMBO.md) · 🇷🇺 [ru](../../ru/docs/AUTO-COMBO.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/AUTO-COMBO.md) · 🇯🇵 [ja](../../ja/docs/AUTO-COMBO.md) · 🇰🇷 [ko](../../ko/docs/AUTO-COMBO.md) · 🇸🇦 [ar](../../ar/docs/AUTO-COMBO.md) · 🇮🇳 [in](../../in/docs/AUTO-COMBO.md) · 🇹🇭 [th](../../th/docs/AUTO-COMBO.md) · 🇻🇳 [vi](../../vi/docs/AUTO-COMBO.md) · 🇮🇩 [id](../../id/docs/AUTO-COMBO.md) · 🇲🇾 [ms](../../ms/docs/AUTO-COMBO.md) · 🇳🇱 [nl](../../nl/docs/AUTO-COMBO.md) · 🇵🇱 [pl](../../pl/docs/AUTO-COMBO.md) · 🇸🇪 [sv](../../sv/docs/AUTO-COMBO.md) · 🇳🇴 [no](../../no/docs/AUTO-COMBO.md) · 🇩🇰 [da](../../da/docs/AUTO-COMBO.md) · 🇫🇮 [fi](../../fi/docs/AUTO-COMBO.md) · 🇵🇹 [pt](../../pt/docs/AUTO-COMBO.md) · 🇷🇴 [ro](../../ro/docs/AUTO-COMBO.md) · 🇭🇺 [hu](../../hu/docs/AUTO-COMBO.md) · 🇧🇬 [bg](../../bg/docs/AUTO-COMBO.md) · 🇸🇰 [sk](../../sk/docs/AUTO-COMBO.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/AUTO-COMBO.md) · 🇮🇱 [he](../../he/docs/AUTO-COMBO.md) · 🇵🇭 [phi](../../phi/docs/AUTO-COMBO.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/AUTO-COMBO.md) · 🇨🇿 [cs](../../cs/docs/AUTO-COMBO.md)
+
+---
+
+> Self-managing model chains with adaptive scoring
+
+## How It Works
+
+The Auto-Combo Engine dynamically selects the best provider/model for each request using a **6-factor scoring function**:
+
+| Factor | Weight | Description |
+| :--------- | :----- | :---------------------------------------------- |
+| Quota | 0.20 | Remaining capacity [0..1] |
+| Health | 0.25 | Circuit breaker: CLOSED=1.0, HALF=0.5, OPEN=0.0 |
+| CostInv | 0.20 | Inverse cost (cheaper = higher score) |
+| LatencyInv | 0.15 | Inverse p95 latency (faster = higher) |
+| TaskFit | 0.10 | Model × task type fitness score |
+| Stability | 0.10 | Low variance in latency/errors |
+
+## Mode Packs
+
+| Pack | Focus | Key Weight |
+| :---------------------- | :----------- | :--------------- |
+| 🚀 **Ship Fast** | Speed | latencyInv: 0.35 |
+| 💰 **Cost Saver** | Economy | costInv: 0.40 |
+| 🎯 **Quality First** | Best model | taskFit: 0.40 |
+| 📡 **Offline Friendly** | Availability | quota: 0.40 |
+
+## Self-Healing
+
+- **Temporary exclusion**: Score < 0.2 → excluded for 5 min (progressive backoff, max 30 min)
+- **Circuit breaker awareness**: OPEN → auto-excluded; HALF_OPEN → probe requests
+- **Incident mode**: >50% OPEN → disable exploration, maximize stability
+- **Cooldown recovery**: After exclusion, first request is a "probe" with reduced timeout
+
+## Bandit Exploration
+
+5% of requests (configurable) are routed to random providers for exploration. Disabled in incident mode.
+
+## API
+
+```bash
+# Create auto-combo
+curl -X POST http://localhost:20128/api/combos/auto \
+ -H "Content-Type: application/json" \
+ -d '{"id":"my-auto","name":"Auto Coder","candidatePool":["anthropic","google","openai"],"modePack":"ship-fast"}'
+
+# List auto-combos
+curl http://localhost:20128/api/combos/auto
+```
+
+## Task Fitness
+
+30+ models scored across 6 task types (`coding`, `review`, `planning`, `analysis`, `debugging`, `documentation`). Supports wildcard patterns (e.g., `*-coder` → high coding score).
+
+## Files
+
+| File | Purpose |
+| :------------------------------------------- | :------------------------------------ |
+| `open-sse/services/autoCombo/scoring.ts` | Scoring function & pool normalization |
+| `open-sse/services/autoCombo/taskFitness.ts` | Model × task fitness lookup |
+| `open-sse/services/autoCombo/engine.ts` | Selection logic, bandit, budget cap |
+| `open-sse/services/autoCombo/selfHealing.ts` | Exclusion, probes, incident mode |
+| `open-sse/services/autoCombo/modePacks.ts` | 4 weight profiles |
+| `src/app/api/combos/auto/route.ts` | REST API |
diff --git a/docs/i18n/bg/docs/CLI-TOOLS.md b/docs/i18n/bg/docs/CLI-TOOLS.md
new file mode 100644
index 0000000000..250b245f18
--- /dev/null
+++ b/docs/i18n/bg/docs/CLI-TOOLS.md
@@ -0,0 +1,348 @@
+# CLI Tools Setup Guide — OmniRoute (Български)
+
+🌐 **Languages:** 🇺🇸 [English](../../../../docs/CLI-TOOLS.md) · 🇪🇸 [es](../../es/docs/CLI-TOOLS.md) · 🇫🇷 [fr](../../fr/docs/CLI-TOOLS.md) · 🇩🇪 [de](../../de/docs/CLI-TOOLS.md) · 🇮🇹 [it](../../it/docs/CLI-TOOLS.md) · 🇷🇺 [ru](../../ru/docs/CLI-TOOLS.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/CLI-TOOLS.md) · 🇯🇵 [ja](../../ja/docs/CLI-TOOLS.md) · 🇰🇷 [ko](../../ko/docs/CLI-TOOLS.md) · 🇸🇦 [ar](../../ar/docs/CLI-TOOLS.md) · 🇮🇳 [in](../../in/docs/CLI-TOOLS.md) · 🇹🇭 [th](../../th/docs/CLI-TOOLS.md) · 🇻🇳 [vi](../../vi/docs/CLI-TOOLS.md) · 🇮🇩 [id](../../id/docs/CLI-TOOLS.md) · 🇲🇾 [ms](../../ms/docs/CLI-TOOLS.md) · 🇳🇱 [nl](../../nl/docs/CLI-TOOLS.md) · 🇵🇱 [pl](../../pl/docs/CLI-TOOLS.md) · 🇸🇪 [sv](../../sv/docs/CLI-TOOLS.md) · 🇳🇴 [no](../../no/docs/CLI-TOOLS.md) · 🇩🇰 [da](../../da/docs/CLI-TOOLS.md) · 🇫🇮 [fi](../../fi/docs/CLI-TOOLS.md) · 🇵🇹 [pt](../../pt/docs/CLI-TOOLS.md) · 🇷🇴 [ro](../../ro/docs/CLI-TOOLS.md) · 🇭🇺 [hu](../../hu/docs/CLI-TOOLS.md) · 🇧🇬 [bg](../../bg/docs/CLI-TOOLS.md) · 🇸🇰 [sk](../../sk/docs/CLI-TOOLS.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/CLI-TOOLS.md) · 🇮🇱 [he](../../he/docs/CLI-TOOLS.md) · 🇵🇭 [phi](../../phi/docs/CLI-TOOLS.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/CLI-TOOLS.md) · 🇨🇿 [cs](../../cs/docs/CLI-TOOLS.md)
+
+---
+
+This guide explains how to install and configure all supported AI coding CLI tools
+to use **OmniRoute** as the unified backend, giving you centralized key management,
+cost tracking, model switching, and request logging across every tool.
+
+---
+
+## How It Works
+
+```
+Claude / Codex / OpenCode / Cline / KiloCode / Continue / Kiro / Cursor / Copilot
+ │
+ ▼ (all point to OmniRoute)
+ http://YOUR_SERVER:20128/v1
+ │
+ ▼ (OmniRoute routes to the right provider)
+ Anthropic / OpenAI / Gemini / DeepSeek / Groq / Mistral / ...
+```
+
+**Benefits:**
+
+- One API key to manage all tools
+- Cost tracking across all CLIs in the dashboard
+- Model switching without reconfiguring every tool
+- Works locally and on remote servers (VPS)
+
+---
+
+## Supported Tools (Dashboard Source of Truth)
+
+The dashboard cards in `/dashboard/cli-tools` are generated from `src/shared/constants/cliTools.ts`.
+Current list (v3.0.0-rc.16):
+
+| Tool | ID | Command | Setup Mode | Install Method |
+| ------------------ | ------------- | ---------- | ---------- | -------------- |
+| **Claude Code** | `claude` | `claude` | env | npm |
+| **OpenAI Codex** | `codex` | `codex` | custom | npm |
+| **Factory Droid** | `droid` | `droid` | custom | bundled/CLI |
+| **OpenClaw** | `openclaw` | `openclaw` | custom | bundled/CLI |
+| **Cursor** | `cursor` | app | guide | desktop app |
+| **Cline** | `cline` | `cline` | custom | npm |
+| **Kilo Code** | `kilo` | `kilocode` | custom | npm |
+| **Continue** | `continue` | extension | guide | VS Code |
+| **Antigravity** | `antigravity` | internal | mitm | OmniRoute |
+| **GitHub Copilot** | `copilot` | extension | custom | VS Code |
+| **OpenCode** | `opencode` | `opencode` | guide | npm |
+| **Kiro AI** | `kiro` | app/cli | mitm | desktop/CLI |
+
+### CLI fingerprint sync (Agents + Settings)
+
+`/dashboard/agents` and `Settings > CLI Fingerprint` use `src/shared/constants/cliCompatProviders.ts`.
+This keeps provider IDs aligned with CLI cards and legacy IDs.
+
+| CLI ID | Fingerprint Provider ID |
+| ---------------------------------------------------------------------------------------------------- | ----------------------- |
+| `kilo` | `kilocode` |
+| `copilot` | `github` |
+| `claude` / `codex` / `antigravity` / `kiro` / `cursor` / `cline` / `opencode` / `droid` / `openclaw` | same ID |
+
+Legacy IDs still accepted for compatibility: `copilot`, `kimi-coding`, `qwen`.
+
+---
+
+## Step 1 — Get an OmniRoute API Key
+
+1. Open the OmniRoute dashboard → **API Manager** (`/dashboard/api-manager`)
+2. Click **Create API Key**
+3. Give it a name (e.g. `cli-tools`) and select all permissions
+4. Copy the key — you'll need it for every CLI below
+
+> Your key looks like: `sk-xxxxxxxxxxxxxxxx-xxxxxxxxx`
+
+---
+
+## Step 2 — Install CLI Tools
+
+All npm-based tools require Node.js 18+:
+
+```bash
+# Claude Code (Anthropic)
+npm install -g @anthropic-ai/claude-code
+
+# OpenAI Codex
+npm install -g @openai/codex
+
+# OpenCode
+npm install -g opencode-ai
+
+# Cline
+npm install -g cline
+
+# KiloCode
+npm install -g kilocode
+
+# Kiro CLI (Amazon — requires curl + unzip)
+apt-get install -y unzip # on Debian/Ubuntu
+curl -fsSL https://cli.kiro.dev/install | bash
+export PATH="$HOME/.local/bin:$PATH" # add to ~/.bashrc
+```
+
+**Verify:**
+
+```bash
+claude --version # 2.x.x
+codex --version # 0.x.x
+opencode --version # x.x.x
+cline --version # 2.x.x
+kilocode --version # x.x.x (or: kilo --version)
+kiro-cli --version # 1.x.x
+```
+
+---
+
+## Step 3 — Set Global Environment Variables
+
+Add to `~/.bashrc` (or `~/.zshrc`), then run `source ~/.bashrc`:
+
+```bash
+# OmniRoute Universal Endpoint
+export OPENAI_BASE_URL="http://localhost:20128/v1"
+export OPENAI_API_KEY="sk-your-omniroute-key"
+export ANTHROPIC_BASE_URL="http://localhost:20128/v1"
+export ANTHROPIC_API_KEY="sk-your-omniroute-key"
+export GEMINI_BASE_URL="http://localhost:20128/v1"
+export GEMINI_API_KEY="sk-your-omniroute-key"
+```
+
+> For a **remote server** replace `localhost:20128` with the server IP or domain,
+> e.g. `http://192.168.0.15:20128`.
+
+---
+
+## Step 4 — Configure Each Tool
+
+### Claude Code
+
+```bash
+# Via CLI:
+claude config set --global api-base-url http://localhost:20128/v1
+
+# Or create ~/.claude/settings.json:
+mkdir -p ~/.claude && cat > ~/.claude/settings.json << EOF
+{
+ "apiBaseUrl": "http://localhost:20128/v1",
+ "apiKey": "sk-your-omniroute-key"
+}
+EOF
+```
+
+**Test:** `claude "say hello"`
+
+---
+
+### OpenAI Codex
+
+```bash
+mkdir -p ~/.codex && cat > ~/.codex/config.yaml << EOF
+model: auto
+apiKey: sk-your-omniroute-key
+apiBaseUrl: http://localhost:20128/v1
+EOF
+```
+
+**Test:** `codex "what is 2+2?"`
+
+---
+
+### OpenCode
+
+```bash
+mkdir -p ~/.config/opencode && cat > ~/.config/opencode/config.toml << EOF
+[provider.openai]
+base_url = "http://localhost:20128/v1"
+api_key = "sk-your-omniroute-key"
+EOF
+```
+
+**Test:** `opencode`
+
+---
+
+### Cline (CLI or VS Code)
+
+**CLI mode:**
+
+```bash
+mkdir -p ~/.cline/data && cat > ~/.cline/data/globalState.json << EOF
+{
+ "apiProvider": "openai",
+ "openAiBaseUrl": "http://localhost:20128/v1",
+ "openAiApiKey": "sk-your-omniroute-key"
+}
+EOF
+```
+
+**VS Code mode:**
+Cline extension settings → API Provider: `OpenAI Compatible` → Base URL: `http://localhost:20128/v1`
+
+Or use the OmniRoute dashboard → **CLI Tools → Cline → Apply Config**.
+
+---
+
+### KiloCode (CLI or VS Code)
+
+**CLI mode:**
+
+```bash
+kilocode --api-base http://localhost:20128/v1 --api-key sk-your-omniroute-key
+```
+
+**VS Code settings:**
+
+```json
+{
+ "kilo-code.openAiBaseUrl": "http://localhost:20128/v1",
+ "kilo-code.apiKey": "sk-your-omniroute-key"
+}
+```
+
+Or use the OmniRoute dashboard → **CLI Tools → KiloCode → Apply Config**.
+
+---
+
+### Continue (VS Code Extension)
+
+Edit `~/.continue/config.yaml`:
+
+```yaml
+models:
+ - name: OmniRoute
+ provider: openai
+ model: auto
+ apiBase: http://localhost:20128/v1
+ apiKey: sk-your-omniroute-key
+ default: true
+```
+
+Restart VS Code after editing.
+
+---
+
+### Kiro CLI (Amazon)
+
+```bash
+# Login to your AWS/Kiro account:
+kiro-cli login
+
+# The CLI uses its own auth — OmniRoute is not needed as backend for Kiro CLI itself.
+# Use kiro-cli alongside OmniRoute for other tools.
+kiro-cli status
+```
+
+---
+
+### Cursor (Desktop App)
+
+> **Note:** Cursor routes requests through its cloud. For OmniRoute integration,
+> enable **Cloud Endpoint** in OmniRoute Settings and use your public domain URL.
+
+Via GUI: **Settings → Models → OpenAI API Key**
+
+- Base URL: `https://your-domain.com/v1`
+- API Key: your OmniRoute key
+
+---
+
+## Dashboard Auto-Configuration
+
+The OmniRoute dashboard automates configuration for most tools:
+
+1. Go to `http://localhost:20128/dashboard/cli-tools`
+2. Expand any tool card
+3. Select your API key from the dropdown
+4. Click **Apply Config** (if tool is detected as installed)
+5. Or copy the generated config snippet manually
+
+---
+
+## Built-in Agents: Droid & OpenClaw
+
+**Droid** and **OpenClaw** are AI agents built directly into OmniRoute — no installation needed.
+They run as internal routes and use OmniRoute's model routing automatically.
+
+- Access: `http://localhost:20128/dashboard/agents`
+- Configure: same combos and providers as all other tools
+- No API key or CLI install required
+
+---
+
+## Available API Endpoints
+
+| Endpoint | Description | Use For |
+| -------------------------- | ----------------------------- | --------------------------- |
+| `/v1/chat/completions` | Standard chat (all providers) | All modern tools |
+| `/v1/responses` | Responses API (OpenAI format) | Codex, agentic workflows |
+| `/v1/completions` | Legacy text completions | Older tools using `prompt:` |
+| `/v1/embeddings` | Text embeddings | RAG, search |
+| `/v1/images/generations` | Image generation | DALL-E, Flux, etc. |
+| `/v1/audio/speech` | Text-to-speech | ElevenLabs, OpenAI TTS |
+| `/v1/audio/transcriptions` | Speech-to-text | Deepgram, AssemblyAI |
+
+---
+
+## Отстраняване на проблеми
+
+| Error | Cause | Fix |
+| ------------------------- | ----------------------- | ------------------------------------------ |
+| `Connection refused` | OmniRoute not running | `pm2 start omniroute` |
+| `401 Unauthorized` | Wrong API key | Check in `/dashboard/api-manager` |
+| `No combo configured` | No active routing combo | Set up in `/dashboard/combos` |
+| `invalid model` | Model not in catalog | Use `auto` or check `/dashboard/providers` |
+| CLI shows "not installed" | Binary not in PATH | Check `which ` |
+| `kiro-cli: not found` | Not in PATH | `export PATH="$HOME/.local/bin:$PATH"` |
+
+---
+
+## Quick Setup Script (One Command)
+
+```bash
+# Install all CLIs and configure for OmniRoute (replace with your key and server URL)
+OMNIROUTE_URL="http://localhost:20128/v1"
+OMNIROUTE_KEY="sk-your-omniroute-key"
+
+npm install -g @anthropic-ai/claude-code @openai/codex opencode-ai cline kilocode
+
+# Kiro CLI
+apt-get install -y unzip 2>/dev/null; curl -fsSL https://cli.kiro.dev/install | bash
+
+# Write configs
+mkdir -p ~/.claude ~/.codex ~/.config/opencode ~/.continue
+
+cat > ~/.claude/settings.json <<< "{\"apiBaseUrl\":\"$OMNIROUTE_URL\",\"apiKey\":\"$OMNIROUTE_KEY\"}"
+cat > ~/.codex/config.yaml <<< "model: auto\napiKey: $OMNIROUTE_KEY\napiBaseUrl: $OMNIROUTE_URL"
+cat >> ~/.bashrc << EOF
+export OPENAI_BASE_URL="$OMNIROUTE_URL"
+export OPENAI_API_KEY="$OMNIROUTE_KEY"
+export ANTHROPIC_BASE_URL="$OMNIROUTE_URL"
+export ANTHROPIC_API_KEY="$OMNIROUTE_KEY"
+EOF
+
+source ~/.bashrc
+echo "✅ All CLIs installed and configured for OmniRoute"
+```
diff --git a/docs/i18n/bg/CODEBASE_DOCUMENTATION.md b/docs/i18n/bg/docs/CODEBASE_DOCUMENTATION.md
similarity index 91%
rename from docs/i18n/bg/CODEBASE_DOCUMENTATION.md
rename to docs/i18n/bg/docs/CODEBASE_DOCUMENTATION.md
index e2d7950052..c11218f38e 100644
--- a/docs/i18n/bg/CODEBASE_DOCUMENTATION.md
+++ b/docs/i18n/bg/docs/CODEBASE_DOCUMENTATION.md
@@ -1,11 +1,9 @@
-🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/CODEBASE_DOCUMENTATION.md) · 🇪🇸 [es](../es/CODEBASE_DOCUMENTATION.md) · 🇫🇷 [fr](../fr/CODEBASE_DOCUMENTATION.md) · 🇩🇪 [de](../de/CODEBASE_DOCUMENTATION.md) · 🇮🇹 [it](../it/CODEBASE_DOCUMENTATION.md) · 🇷🇺 [ru](../ru/CODEBASE_DOCUMENTATION.md) · 🇨🇳 [zh-CN](../zh-CN/CODEBASE_DOCUMENTATION.md) · 🇯🇵 [ja](../ja/CODEBASE_DOCUMENTATION.md) · 🇰🇷 [ko](../ko/CODEBASE_DOCUMENTATION.md) · 🇸🇦 [ar](../ar/CODEBASE_DOCUMENTATION.md) · 🇮🇳 [in](../in/CODEBASE_DOCUMENTATION.md) · 🇹🇭 [th](../th/CODEBASE_DOCUMENTATION.md) · 🇻🇳 [vi](../vi/CODEBASE_DOCUMENTATION.md) · 🇮🇩 [id](../id/CODEBASE_DOCUMENTATION.md) · 🇲🇾 [ms](../ms/CODEBASE_DOCUMENTATION.md) · 🇳🇱 [nl](../nl/CODEBASE_DOCUMENTATION.md) · 🇵🇱 [pl](../pl/CODEBASE_DOCUMENTATION.md) · 🇸🇪 [sv](../sv/CODEBASE_DOCUMENTATION.md) · 🇳🇴 [no](../no/CODEBASE_DOCUMENTATION.md) · 🇩🇰 [da](../da/CODEBASE_DOCUMENTATION.md) · 🇫🇮 [fi](../fi/CODEBASE_DOCUMENTATION.md) · 🇵🇹 [pt](../pt/CODEBASE_DOCUMENTATION.md) · 🇷🇴 [ro](../ro/CODEBASE_DOCUMENTATION.md) · 🇭🇺 [hu](../hu/CODEBASE_DOCUMENTATION.md) · 🇧🇬 [bg](../bg/CODEBASE_DOCUMENTATION.md) · 🇸🇰 [sk](../sk/CODEBASE_DOCUMENTATION.md) · 🇺🇦 [uk-UA](../uk-UA/CODEBASE_DOCUMENTATION.md) · 🇮🇱 [he](../he/CODEBASE_DOCUMENTATION.md) · 🇵🇭 [phi](../phi/CODEBASE_DOCUMENTATION.md)
+# omniroute — Codebase Documentation (Български)
+
+🌐 **Languages:** 🇺🇸 [English](../../../../docs/CODEBASE_DOCUMENTATION.md) · 🇪🇸 [es](../../es/docs/CODEBASE_DOCUMENTATION.md) · 🇫🇷 [fr](../../fr/docs/CODEBASE_DOCUMENTATION.md) · 🇩🇪 [de](../../de/docs/CODEBASE_DOCUMENTATION.md) · 🇮🇹 [it](../../it/docs/CODEBASE_DOCUMENTATION.md) · 🇷🇺 [ru](../../ru/docs/CODEBASE_DOCUMENTATION.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/CODEBASE_DOCUMENTATION.md) · 🇯🇵 [ja](../../ja/docs/CODEBASE_DOCUMENTATION.md) · 🇰🇷 [ko](../../ko/docs/CODEBASE_DOCUMENTATION.md) · 🇸🇦 [ar](../../ar/docs/CODEBASE_DOCUMENTATION.md) · 🇮🇳 [in](../../in/docs/CODEBASE_DOCUMENTATION.md) · 🇹🇭 [th](../../th/docs/CODEBASE_DOCUMENTATION.md) · 🇻🇳 [vi](../../vi/docs/CODEBASE_DOCUMENTATION.md) · 🇮🇩 [id](../../id/docs/CODEBASE_DOCUMENTATION.md) · 🇲🇾 [ms](../../ms/docs/CODEBASE_DOCUMENTATION.md) · 🇳🇱 [nl](../../nl/docs/CODEBASE_DOCUMENTATION.md) · 🇵🇱 [pl](../../pl/docs/CODEBASE_DOCUMENTATION.md) · 🇸🇪 [sv](../../sv/docs/CODEBASE_DOCUMENTATION.md) · 🇳🇴 [no](../../no/docs/CODEBASE_DOCUMENTATION.md) · 🇩🇰 [da](../../da/docs/CODEBASE_DOCUMENTATION.md) · 🇫🇮 [fi](../../fi/docs/CODEBASE_DOCUMENTATION.md) · 🇵🇹 [pt](../../pt/docs/CODEBASE_DOCUMENTATION.md) · 🇷🇴 [ro](../../ro/docs/CODEBASE_DOCUMENTATION.md) · 🇭🇺 [hu](../../hu/docs/CODEBASE_DOCUMENTATION.md) · 🇧🇬 [bg](../../bg/docs/CODEBASE_DOCUMENTATION.md) · 🇸🇰 [sk](../../sk/docs/CODEBASE_DOCUMENTATION.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/CODEBASE_DOCUMENTATION.md) · 🇮🇱 [he](../../he/docs/CODEBASE_DOCUMENTATION.md) · 🇵🇭 [phi](../../phi/docs/CODEBASE_DOCUMENTATION.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/CODEBASE_DOCUMENTATION.md) · 🇨🇿 [cs](../../cs/docs/CODEBASE_DOCUMENTATION.md)
---
-# omniroute — Codebase Documentation
-
-🌐 **Languages:** 🇺🇸 [English](CODEBASE_DOCUMENTATION.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/CODEBASE_DOCUMENTATION.md) | 🇪🇸 [Español](i18n/es/CODEBASE_DOCUMENTATION.md) | 🇫🇷 [Français](i18n/fr/CODEBASE_DOCUMENTATION.md) | 🇮🇹 [Italiano](i18n/it/CODEBASE_DOCUMENTATION.md) | 🇷🇺 [Русский](i18n/ru/CODEBASE_DOCUMENTATION.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/CODEBASE_DOCUMENTATION.md) | 🇩🇪 [Deutsch](i18n/de/CODEBASE_DOCUMENTATION.md) | 🇮🇳 [हिन्दी](i18n/in/CODEBASE_DOCUMENTATION.md) | 🇹🇭 [ไทย](i18n/th/CODEBASE_DOCUMENTATION.md) | 🇺🇦 [Українська](i18n/uk-UA/CODEBASE_DOCUMENTATION.md) | 🇸🇦 [العربية](i18n/ar/CODEBASE_DOCUMENTATION.md) | 🇯🇵 [日本語](i18n/ja/CODEBASE_DOCUMENTATION.md) | 🇻🇳 [Tiếng Việt](i18n/vi/CODEBASE_DOCUMENTATION.md) | 🇧🇬 [Български](i18n/bg/CODEBASE_DOCUMENTATION.md) | 🇩🇰 [Dansk](i18n/da/CODEBASE_DOCUMENTATION.md) | 🇫🇮 [Suomi](i18n/fi/CODEBASE_DOCUMENTATION.md) | 🇮🇱 [עברית](i18n/he/CODEBASE_DOCUMENTATION.md) | 🇭🇺 [Magyar](i18n/hu/CODEBASE_DOCUMENTATION.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/CODEBASE_DOCUMENTATION.md) | 🇰🇷 [한국어](i18n/ko/CODEBASE_DOCUMENTATION.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/CODEBASE_DOCUMENTATION.md) | 🇳🇱 [Nederlands](i18n/nl/CODEBASE_DOCUMENTATION.md) | 🇳🇴 [Norsk](i18n/no/CODEBASE_DOCUMENTATION.md) | 🇵🇹 [Português (Portugal)](i18n/pt/CODEBASE_DOCUMENTATION.md) | 🇷🇴 [Română](i18n/ro/CODEBASE_DOCUMENTATION.md) | 🇵🇱 [Polski](i18n/pl/CODEBASE_DOCUMENTATION.md) | 🇸🇰 [Slovenčina](i18n/sk/CODEBASE_DOCUMENTATION.md) | 🇸🇪 [Svenska](i18n/sv/CODEBASE_DOCUMENTATION.md) | 🇵🇭 [Filipino](i18n/phi/CODEBASE_DOCUMENTATION.md)
-
> A comprehensive, beginner-friendly guide to the **omniroute** multi-provider AI proxy router.
---
@@ -352,7 +350,7 @@ flowchart LR
The **format translation engine** using a self-registering plugin system.
-#### Architecture
+#### Архитектура
```mermaid
graph TD
diff --git a/docs/i18n/bg/docs/COVERAGE_PLAN.md b/docs/i18n/bg/docs/COVERAGE_PLAN.md
new file mode 100644
index 0000000000..dc4b31b34f
--- /dev/null
+++ b/docs/i18n/bg/docs/COVERAGE_PLAN.md
@@ -0,0 +1,170 @@
+# Test Coverage Plan (Български)
+
+🌐 **Languages:** 🇺🇸 [English](../../../../docs/COVERAGE_PLAN.md) · 🇪🇸 [es](../../es/docs/COVERAGE_PLAN.md) · 🇫🇷 [fr](../../fr/docs/COVERAGE_PLAN.md) · 🇩🇪 [de](../../de/docs/COVERAGE_PLAN.md) · 🇮🇹 [it](../../it/docs/COVERAGE_PLAN.md) · 🇷🇺 [ru](../../ru/docs/COVERAGE_PLAN.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/COVERAGE_PLAN.md) · 🇯🇵 [ja](../../ja/docs/COVERAGE_PLAN.md) · 🇰🇷 [ko](../../ko/docs/COVERAGE_PLAN.md) · 🇸🇦 [ar](../../ar/docs/COVERAGE_PLAN.md) · 🇮🇳 [in](../../in/docs/COVERAGE_PLAN.md) · 🇹🇭 [th](../../th/docs/COVERAGE_PLAN.md) · 🇻🇳 [vi](../../vi/docs/COVERAGE_PLAN.md) · 🇮🇩 [id](../../id/docs/COVERAGE_PLAN.md) · 🇲🇾 [ms](../../ms/docs/COVERAGE_PLAN.md) · 🇳🇱 [nl](../../nl/docs/COVERAGE_PLAN.md) · 🇵🇱 [pl](../../pl/docs/COVERAGE_PLAN.md) · 🇸🇪 [sv](../../sv/docs/COVERAGE_PLAN.md) · 🇳🇴 [no](../../no/docs/COVERAGE_PLAN.md) · 🇩🇰 [da](../../da/docs/COVERAGE_PLAN.md) · 🇫🇮 [fi](../../fi/docs/COVERAGE_PLAN.md) · 🇵🇹 [pt](../../pt/docs/COVERAGE_PLAN.md) · 🇷🇴 [ro](../../ro/docs/COVERAGE_PLAN.md) · 🇭🇺 [hu](../../hu/docs/COVERAGE_PLAN.md) · 🇧🇬 [bg](../../bg/docs/COVERAGE_PLAN.md) · 🇸🇰 [sk](../../sk/docs/COVERAGE_PLAN.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/COVERAGE_PLAN.md) · 🇮🇱 [he](../../he/docs/COVERAGE_PLAN.md) · 🇵🇭 [phi](../../phi/docs/COVERAGE_PLAN.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/COVERAGE_PLAN.md) · 🇨🇿 [cs](../../cs/docs/COVERAGE_PLAN.md)
+
+---
+
+Last updated: 2026-03-28
+
+## Baseline
+
+There are multiple coverage numbers depending on how the report is computed. For planning, only one of them is useful.
+
+| Metric | Scope | Statements / Lines | Branches | Functions | Notes |
+| -------------------- | ----------------------------------------------------- | -----------------: | -------: | --------: | --------------------------------------------------- |
+| Legacy | Old `npm run test:coverage` | 79.42% | 75.15% | 67.94% | Inflated: counts test files and excludes `open-sse` |
+| Diagnostic | Source-only, excluding tests and excluding `open-sse` | 68.16% | 63.55% | 64.06% | Useful only to isolate `src/**` |
+| Recommended baseline | Source-only, excluding tests and including `open-sse` | 56.95% | 66.05% | 57.80% | This is the project-wide baseline to improve |
+
+The recommended baseline is the number to optimize against.
+
+## Rules
+
+- Coverage targets apply to source files, not to `tests/**`.
+- `open-sse/**` is part of the product and must remain in scope.
+- New code should not reduce coverage in touched areas.
+- Prefer testing behavior and branch outcomes over implementation details.
+- Prefer temp SQLite databases and small fixtures over broad mocks for `src/lib/db/**`.
+
+## Current command set
+
+- `npm run test:coverage`
+ - Main source coverage gate for the unit test suite
+ - Generates `text-summary`, `html`, `json-summary`, and `lcov`
+- `npm run coverage:report`
+ - Detailed file-by-file report from the latest run
+- `npm run test:coverage:legacy`
+ - Historical comparison only
+
+## Milestones
+
+| Phase | Target | Focus |
+| ------- | ---------------------: | ------------------------------------------------- |
+| Phase 1 | 60% statements / lines | Quick wins and low-risk utility coverage |
+| Phase 2 | 65% statements / lines | DB and route foundations |
+| Phase 3 | 70% statements / lines | Provider validation and usage analytics |
+| Phase 4 | 75% statements / lines | `open-sse` translators and helpers |
+| Phase 5 | 80% statements / lines | `open-sse` handlers and executor branches |
+| Phase 6 | 85% statements / lines | Harder edge cases, branch debt, regression suites |
+| Phase 7 | 90% statements / lines | Final sweep, gap closure, strict ratchet |
+
+Branches and functions should ratchet upward with each phase, but the primary hard target is statements / lines.
+
+## Priority hotspots
+
+These files or areas offer the best return for the next phases:
+
+1. `open-sse/handlers`
+ - `chatCore.ts` at 7.57%
+ - Overall directory at 29.07%
+2. `open-sse/translator/request`
+ - Overall directory at 36.39%
+ - Many translators are still near single-digit coverage
+3. `open-sse/translator/response`
+ - Overall directory at 8.07%
+4. `open-sse/executors`
+ - Overall directory at 36.62%
+5. `src/lib/db`
+ - `models.ts` at 20.66%
+ - `registeredKeys.ts` at 34.46%
+ - `modelComboMappings.ts` at 36.25%
+ - `settings.ts` at 46.40%
+ - `webhooks.ts` at 33.33%
+6. `src/lib/usage`
+ - `usageHistory.ts` at 21.12%
+ - `usageStats.ts` at 9.56%
+ - `costCalculator.ts` at 30.00%
+7. `src/lib/providers`
+ - `validation.ts` at 41.16%
+8. Low-risk utility and API files for early gains
+ - `src/shared/utils/upstreamError.ts`
+ - `src/shared/utils/apiAuth.ts`
+ - `src/lib/api/errorResponse.ts`
+ - `src/app/api/settings/require-login/route.ts`
+ - `src/app/api/providers/[id]/models/route.ts`
+
+## Execution checklist
+
+### Phase 1: 56.95% -> 60%
+
+- [x] Fix coverage metric so it reflects source code instead of test files
+- [x] Keep a legacy coverage script for comparison
+- [x] Record the baseline and hotspots in-repo
+- [ ] Add focused tests for low-risk utilities:
+ - `src/shared/utils/upstreamError.ts`
+ - `src/shared/utils/fetchTimeout.ts`
+ - `src/lib/api/errorResponse.ts`
+ - `src/shared/utils/apiAuth.ts`
+ - `src/lib/display/names.ts`
+- [ ] Add route tests for:
+ - `src/app/api/settings/require-login/route.ts`
+ - `src/app/api/providers/[id]/models/route.ts`
+
+### Phase 2: 60% -> 65%
+
+- [ ] Add DB-backed tests for:
+ - `src/lib/db/modelComboMappings.ts`
+ - `src/lib/db/settings.ts`
+ - `src/lib/db/registeredKeys.ts`
+- [ ] Cover branch behavior in:
+ - `src/lib/providers/validation.ts`
+ - `src/app/api/v1/embeddings/route.ts`
+ - `src/app/api/v1/moderations/route.ts`
+
+### Phase 3: 65% -> 70%
+
+- [ ] Add usage analytics tests for:
+ - `src/lib/usage/usageHistory.ts`
+ - `src/lib/usage/usageStats.ts`
+ - `src/lib/usage/costCalculator.ts`
+- [ ] Expand route coverage for proxy management and settings branches
+
+### Phase 4: 70% -> 75%
+
+- [ ] Cover translator helpers and central translation paths:
+ - `open-sse/translator/index.ts`
+ - `open-sse/translator/helpers/*`
+ - `open-sse/translator/request/*`
+ - `open-sse/translator/response/*`
+
+### Phase 5: 75% -> 80%
+
+- [ ] Add handler-level tests for:
+ - `open-sse/handlers/chatCore.ts`
+ - `open-sse/handlers/responsesHandler.js`
+ - `open-sse/handlers/imageGeneration.js`
+ - `open-sse/handlers/embeddings.js`
+- [ ] Add executor branch coverage for provider-specific auth, retries, and endpoint overrides
+
+### Phase 6: 80% -> 85%
+
+- [ ] Merge more edge-case suites into the main coverage path
+- [ ] Increase function coverage for DB modules with weak constructor/helper coverage
+- [ ] Close branch gaps in `settings.ts`, `registeredKeys.ts`, `validation.ts`, and translator helpers
+
+### Phase 7: 85% -> 90%
+
+- [ ] Treat the remaining low-coverage files as blockers
+- [ ] Add regression tests for every uncovered production bug fixed during the push to 90%
+- [ ] Raise the coverage gate in CI only after the local baseline is stable for at least two consecutive runs
+
+## Ratchet policy
+
+Update `npm run test:coverage` thresholds only after the project actually exceeds the next milestone with a comfortable buffer.
+
+Recommended ratchet sequence:
+
+1. 55/60/55
+2. 60/62/58
+3. 65/64/62
+4. 70/66/66
+5. 75/70/72
+6. 80/75/78
+7. 85/80/84
+8. 90/85/88
+
+Order is `statements-lines / branches / functions`.
+
+## Known gap
+
+The current coverage command measures the main Node unit suite and includes source reached from it, including `open-sse`. It does not yet merge Vitest coverage into a single unified report. That merge is worth doing later, but it is not a blocker for starting the 60% -> 80% climb.
diff --git a/docs/i18n/bg/docs/FEATURES.md b/docs/i18n/bg/docs/FEATURES.md
index f497f4cfd1..bf49c0d3f4 100644
--- a/docs/i18n/bg/docs/FEATURES.md
+++ b/docs/i18n/bg/docs/FEATURES.md
@@ -1,6 +1,6 @@
# OmniRoute — Dashboard Features Gallery (Български)
-🌐 **Languages:** 🇺🇸 [English](../../../../docs/FEATURES.md) · 🇪🇸 [es](../../es/docs/FEATURES.md) · 🇫🇷 [fr](../../fr/docs/FEATURES.md) · 🇩🇪 [de](../../de/docs/FEATURES.md) · 🇮🇹 [it](../../it/docs/FEATURES.md) · 🇷🇺 [ru](../../ru/docs/FEATURES.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/FEATURES.md) · 🇯🇵 [ja](../../ja/docs/FEATURES.md) · 🇰🇷 [ko](../../ko/docs/FEATURES.md) · 🇸🇦 [ar](../../ar/docs/FEATURES.md) · 🇮🇳 [in](../../in/docs/FEATURES.md) · 🇹🇭 [th](../../th/docs/FEATURES.md) · 🇻🇳 [vi](../../vi/docs/FEATURES.md) · 🇮🇩 [id](../../id/docs/FEATURES.md) · 🇲🇾 [ms](../../ms/docs/FEATURES.md) · 🇳🇱 [nl](../../nl/docs/FEATURES.md) · 🇵🇱 [pl](../../pl/docs/FEATURES.md) · 🇸🇪 [sv](../../sv/docs/FEATURES.md) · 🇳🇴 [no](../../no/docs/FEATURES.md) · 🇩🇰 [da](../../da/docs/FEATURES.md) · 🇫🇮 [fi](../../fi/docs/FEATURES.md) · 🇵🇹 [pt](../../pt/docs/FEATURES.md) · 🇷🇴 [ro](../../ro/docs/FEATURES.md) · 🇭🇺 [hu](../../hu/docs/FEATURES.md) · 🇧🇬 [bg](../../bg/docs/FEATURES.md) · 🇸🇰 [sk](../../sk/docs/FEATURES.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/FEATURES.md) · 🇮🇱 [he](../../he/docs/FEATURES.md) · 🇵🇭 [phi](../../phi/docs/FEATURES.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/FEATURES.md)
+🌐 **Languages:** 🇺🇸 [English](../../../../docs/FEATURES.md) · 🇪🇸 [es](../../es/docs/FEATURES.md) · 🇫🇷 [fr](../../fr/docs/FEATURES.md) · 🇩🇪 [de](../../de/docs/FEATURES.md) · 🇮🇹 [it](../../it/docs/FEATURES.md) · 🇷🇺 [ru](../../ru/docs/FEATURES.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/FEATURES.md) · 🇯🇵 [ja](../../ja/docs/FEATURES.md) · 🇰🇷 [ko](../../ko/docs/FEATURES.md) · 🇸🇦 [ar](../../ar/docs/FEATURES.md) · 🇮🇳 [in](../../in/docs/FEATURES.md) · 🇹🇭 [th](../../th/docs/FEATURES.md) · 🇻🇳 [vi](../../vi/docs/FEATURES.md) · 🇮🇩 [id](../../id/docs/FEATURES.md) · 🇲🇾 [ms](../../ms/docs/FEATURES.md) · 🇳🇱 [nl](../../nl/docs/FEATURES.md) · 🇵🇱 [pl](../../pl/docs/FEATURES.md) · 🇸🇪 [sv](../../sv/docs/FEATURES.md) · 🇳🇴 [no](../../no/docs/FEATURES.md) · 🇩🇰 [da](../../da/docs/FEATURES.md) · 🇫🇮 [fi](../../fi/docs/FEATURES.md) · 🇵🇹 [pt](../../pt/docs/FEATURES.md) · 🇷🇴 [ro](../../ro/docs/FEATURES.md) · 🇭🇺 [hu](../../hu/docs/FEATURES.md) · 🇧🇬 [bg](../../bg/docs/FEATURES.md) · 🇸🇰 [sk](../../sk/docs/FEATURES.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/FEATURES.md) · 🇮🇱 [he](../../he/docs/FEATURES.md) · 🇵🇭 [phi](../../phi/docs/FEATURES.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/FEATURES.md) · 🇨🇿 [cs](../../cs/docs/FEATURES.md)
---
@@ -10,7 +10,7 @@ Visual guide to every section of the OmniRoute dashboard.
## 🔌 Providers
-Manage AI provider connections: OAuth providers (Claude Code, Codex, Gemini CLI), API key providers (Groq, DeepSeek, OpenRouter), and free providers (iFlow, Qwen, Kiro). Kiro accounts include credit balance tracking — remaining credits, total allowance, and renewal date visible in Dashboard → Usage.
+Manage AI provider connections: OAuth providers (Claude Code, Codex, Gemini CLI), API key providers (Groq, DeepSeek, OpenRouter), and free providers (Qoder, Qwen, Kiro). Kiro accounts include credit balance tracking — remaining credits, total allowance, and renewal date visible in Dashboard → Usage.

diff --git a/docs/i18n/bg/docs/MCP-SERVER.md b/docs/i18n/bg/docs/MCP-SERVER.md
new file mode 100644
index 0000000000..5efd42c421
--- /dev/null
+++ b/docs/i18n/bg/docs/MCP-SERVER.md
@@ -0,0 +1,87 @@
+# OmniRoute MCP Server Documentation (Български)
+
+🌐 **Languages:** 🇺🇸 [English](../../../../docs/MCP-SERVER.md) · 🇪🇸 [es](../../es/docs/MCP-SERVER.md) · 🇫🇷 [fr](../../fr/docs/MCP-SERVER.md) · 🇩🇪 [de](../../de/docs/MCP-SERVER.md) · 🇮🇹 [it](../../it/docs/MCP-SERVER.md) · 🇷🇺 [ru](../../ru/docs/MCP-SERVER.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/MCP-SERVER.md) · 🇯🇵 [ja](../../ja/docs/MCP-SERVER.md) · 🇰🇷 [ko](../../ko/docs/MCP-SERVER.md) · 🇸🇦 [ar](../../ar/docs/MCP-SERVER.md) · 🇮🇳 [in](../../in/docs/MCP-SERVER.md) · 🇹🇭 [th](../../th/docs/MCP-SERVER.md) · 🇻🇳 [vi](../../vi/docs/MCP-SERVER.md) · 🇮🇩 [id](../../id/docs/MCP-SERVER.md) · 🇲🇾 [ms](../../ms/docs/MCP-SERVER.md) · 🇳🇱 [nl](../../nl/docs/MCP-SERVER.md) · 🇵🇱 [pl](../../pl/docs/MCP-SERVER.md) · 🇸🇪 [sv](../../sv/docs/MCP-SERVER.md) · 🇳🇴 [no](../../no/docs/MCP-SERVER.md) · 🇩🇰 [da](../../da/docs/MCP-SERVER.md) · 🇫🇮 [fi](../../fi/docs/MCP-SERVER.md) · 🇵🇹 [pt](../../pt/docs/MCP-SERVER.md) · 🇷🇴 [ro](../../ro/docs/MCP-SERVER.md) · 🇭🇺 [hu](../../hu/docs/MCP-SERVER.md) · 🇧🇬 [bg](../../bg/docs/MCP-SERVER.md) · 🇸🇰 [sk](../../sk/docs/MCP-SERVER.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/MCP-SERVER.md) · 🇮🇱 [he](../../he/docs/MCP-SERVER.md) · 🇵🇭 [phi](../../phi/docs/MCP-SERVER.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/MCP-SERVER.md) · 🇨🇿 [cs](../../cs/docs/MCP-SERVER.md)
+
+---
+
+> Model Context Protocol server with 16 intelligent tools
+
+## Инсталиране
+
+OmniRoute MCP is built-in. Start it with:
+
+```bash
+omniroute --mcp
+```
+
+Or via the open-sse transport:
+
+```bash
+# HTTP streamable transport (port 20130)
+omniroute --dev # MCP auto-starts on /mcp endpoint
+```
+
+## IDE Configuration
+
+See [IDE Configs](integrations/ide-configs.md) for Antigravity, Cursor, Copilot, and Claude Desktop setup.
+
+---
+
+## Essential Tools (8)
+
+| Tool | Description |
+| :------------------------------ | :--------------------------------------- |
+| `omniroute_get_health` | Gateway health, circuit breakers, uptime |
+| `omniroute_list_combos` | All configured combos with models |
+| `omniroute_get_combo_metrics` | Performance metrics for a specific combo |
+| `omniroute_switch_combo` | Switch active combo by ID/name |
+| `omniroute_check_quota` | Quota status per provider or all |
+| `omniroute_route_request` | Send a chat completion through OmniRoute |
+| `omniroute_cost_report` | Cost analytics for a time period |
+| `omniroute_list_models_catalog` | Full model catalog with capabilities |
+
+## Advanced Tools (8)
+
+| Tool | Description |
+| :--------------------------------- | :---------------------------------------------------------- |
+| `omniroute_simulate_route` | Dry-run routing simulation with fallback tree |
+| `omniroute_set_budget_guard` | Session budget with degrade/block/alert actions |
+| `omniroute_set_resilience_profile` | Apply conservative/balanced/aggressive preset |
+| `omniroute_test_combo` | Live-test all models in a combo via a real upstream request |
+| `omniroute_get_provider_metrics` | Detailed metrics for one provider |
+| `omniroute_best_combo_for_task` | Task-fitness recommendation with alternatives |
+| `omniroute_explain_route` | Explain a past routing decision |
+| `omniroute_get_session_snapshot` | Full session state: costs, tokens, errors |
+
+## Authentication
+
+MCP tools are authenticated via API key scopes. Each tool requires specific scopes:
+
+| Scope | Tools |
+| :------------- | :----------------------------------------------- |
+| `read:health` | get_health, get_provider_metrics |
+| `read:combos` | list_combos, get_combo_metrics |
+| `write:combos` | switch_combo |
+| `read:quota` | check_quota |
+| `write:route` | route_request, simulate_route, test_combo |
+| `read:usage` | cost_report, get_session_snapshot, explain_route |
+| `write:config` | set_budget_guard, set_resilience_profile |
+| `read:models` | list_models_catalog, best_combo_for_task |
+
+## Audit Logging
+
+Every tool call is logged to `mcp_tool_audit` with:
+
+- Tool name, arguments, result
+- Duration (ms), success/failure
+- API key hash, timestamp
+
+## Files
+
+| File | Purpose |
+| :------------------------------------------- | :------------------------------------------ |
+| `open-sse/mcp-server/server.ts` | MCP server creation + 16 tool registrations |
+| `open-sse/mcp-server/transport.ts` | Stdio + HTTP transport |
+| `open-sse/mcp-server/auth.ts` | API key + scope validation |
+| `open-sse/mcp-server/audit.ts` | Tool call audit logging |
+| `open-sse/mcp-server/tools/advancedTools.ts` | 8 advanced tool handlers |
diff --git a/docs/i18n/bg/docs/RELEASE_CHECKLIST.md b/docs/i18n/bg/docs/RELEASE_CHECKLIST.md
new file mode 100644
index 0000000000..451d2cd518
--- /dev/null
+++ b/docs/i18n/bg/docs/RELEASE_CHECKLIST.md
@@ -0,0 +1,37 @@
+# Release Checklist (Български)
+
+🌐 **Languages:** 🇺🇸 [English](../../../../docs/RELEASE_CHECKLIST.md) · 🇪🇸 [es](../../es/docs/RELEASE_CHECKLIST.md) · 🇫🇷 [fr](../../fr/docs/RELEASE_CHECKLIST.md) · 🇩🇪 [de](../../de/docs/RELEASE_CHECKLIST.md) · 🇮🇹 [it](../../it/docs/RELEASE_CHECKLIST.md) · 🇷🇺 [ru](../../ru/docs/RELEASE_CHECKLIST.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/RELEASE_CHECKLIST.md) · 🇯🇵 [ja](../../ja/docs/RELEASE_CHECKLIST.md) · 🇰🇷 [ko](../../ko/docs/RELEASE_CHECKLIST.md) · 🇸🇦 [ar](../../ar/docs/RELEASE_CHECKLIST.md) · 🇮🇳 [in](../../in/docs/RELEASE_CHECKLIST.md) · 🇹🇭 [th](../../th/docs/RELEASE_CHECKLIST.md) · 🇻🇳 [vi](../../vi/docs/RELEASE_CHECKLIST.md) · 🇮🇩 [id](../../id/docs/RELEASE_CHECKLIST.md) · 🇲🇾 [ms](../../ms/docs/RELEASE_CHECKLIST.md) · 🇳🇱 [nl](../../nl/docs/RELEASE_CHECKLIST.md) · 🇵🇱 [pl](../../pl/docs/RELEASE_CHECKLIST.md) · 🇸🇪 [sv](../../sv/docs/RELEASE_CHECKLIST.md) · 🇳🇴 [no](../../no/docs/RELEASE_CHECKLIST.md) · 🇩🇰 [da](../../da/docs/RELEASE_CHECKLIST.md) · 🇫🇮 [fi](../../fi/docs/RELEASE_CHECKLIST.md) · 🇵🇹 [pt](../../pt/docs/RELEASE_CHECKLIST.md) · 🇷🇴 [ro](../../ro/docs/RELEASE_CHECKLIST.md) · 🇭🇺 [hu](../../hu/docs/RELEASE_CHECKLIST.md) · 🇧🇬 [bg](../../bg/docs/RELEASE_CHECKLIST.md) · 🇸🇰 [sk](../../sk/docs/RELEASE_CHECKLIST.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/RELEASE_CHECKLIST.md) · 🇮🇱 [he](../../he/docs/RELEASE_CHECKLIST.md) · 🇵🇭 [phi](../../phi/docs/RELEASE_CHECKLIST.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/RELEASE_CHECKLIST.md) · 🇨🇿 [cs](../../cs/docs/RELEASE_CHECKLIST.md)
+
+---
+
+Use this checklist before tagging or publishing a new OmniRoute release.
+
+## Version and Changelog
+
+1. Bump `package.json` version (`x.y.z`) in the release branch.
+2. Move release notes from `## [Unreleased]` in `CHANGELOG.md` to a dated section:
+ - `## [x.y.z] — YYYY-MM-DD`
+3. Keep `## [Unreleased]` as the first changelog section for upcoming work.
+4. Ensure the latest semver section in `CHANGELOG.md` equals `package.json` version.
+
+## API Docs
+
+1. Update `docs/openapi.yaml`:
+ - `info.version` must equal `package.json` version.
+2. Validate endpoint examples if API contracts changed.
+
+## Runtime Docs
+
+1. Review `docs/ARCHITECTURE.md` for storage/runtime drift.
+2. Review `docs/TROUBLESHOOTING.md` for env var and operational drift.
+3. Update localized docs if source docs changed significantly.
+
+## Automated Check
+
+Run the sync guard locally before opening PR:
+
+```bash
+npm run check:docs-sync
+```
+
+CI also runs this check in `.github/workflows/ci.yml` (lint job).
diff --git a/docs/i18n/bg/TROUBLESHOOTING.md b/docs/i18n/bg/docs/TROUBLESHOOTING.md
similarity index 77%
rename from docs/i18n/bg/TROUBLESHOOTING.md
rename to docs/i18n/bg/docs/TROUBLESHOOTING.md
index 63c148000a..002fdc491f 100644
--- a/docs/i18n/bg/TROUBLESHOOTING.md
+++ b/docs/i18n/bg/docs/TROUBLESHOOTING.md
@@ -1,11 +1,9 @@
-🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/TROUBLESHOOTING.md) · 🇪🇸 [es](../es/TROUBLESHOOTING.md) · 🇫🇷 [fr](../fr/TROUBLESHOOTING.md) · 🇩🇪 [de](../de/TROUBLESHOOTING.md) · 🇮🇹 [it](../it/TROUBLESHOOTING.md) · 🇷🇺 [ru](../ru/TROUBLESHOOTING.md) · 🇨🇳 [zh-CN](../zh-CN/TROUBLESHOOTING.md) · 🇯🇵 [ja](../ja/TROUBLESHOOTING.md) · 🇰🇷 [ko](../ko/TROUBLESHOOTING.md) · 🇸🇦 [ar](../ar/TROUBLESHOOTING.md) · 🇮🇳 [in](../in/TROUBLESHOOTING.md) · 🇹🇭 [th](../th/TROUBLESHOOTING.md) · 🇻🇳 [vi](../vi/TROUBLESHOOTING.md) · 🇮🇩 [id](../id/TROUBLESHOOTING.md) · 🇲🇾 [ms](../ms/TROUBLESHOOTING.md) · 🇳🇱 [nl](../nl/TROUBLESHOOTING.md) · 🇵🇱 [pl](../pl/TROUBLESHOOTING.md) · 🇸🇪 [sv](../sv/TROUBLESHOOTING.md) · 🇳🇴 [no](../no/TROUBLESHOOTING.md) · 🇩🇰 [da](../da/TROUBLESHOOTING.md) · 🇫🇮 [fi](../fi/TROUBLESHOOTING.md) · 🇵🇹 [pt](../pt/TROUBLESHOOTING.md) · 🇷🇴 [ro](../ro/TROUBLESHOOTING.md) · 🇭🇺 [hu](../hu/TROUBLESHOOTING.md) · 🇧🇬 [bg](../bg/TROUBLESHOOTING.md) · 🇸🇰 [sk](../sk/TROUBLESHOOTING.md) · 🇺🇦 [uk-UA](../uk-UA/TROUBLESHOOTING.md) · 🇮🇱 [he](../he/TROUBLESHOOTING.md) · 🇵🇭 [phi](../phi/TROUBLESHOOTING.md)
+# Troubleshooting (Български)
+
+🌐 **Languages:** 🇺🇸 [English](../../../../docs/TROUBLESHOOTING.md) · 🇪🇸 [es](../../es/docs/TROUBLESHOOTING.md) · 🇫🇷 [fr](../../fr/docs/TROUBLESHOOTING.md) · 🇩🇪 [de](../../de/docs/TROUBLESHOOTING.md) · 🇮🇹 [it](../../it/docs/TROUBLESHOOTING.md) · 🇷🇺 [ru](../../ru/docs/TROUBLESHOOTING.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/TROUBLESHOOTING.md) · 🇯🇵 [ja](../../ja/docs/TROUBLESHOOTING.md) · 🇰🇷 [ko](../../ko/docs/TROUBLESHOOTING.md) · 🇸🇦 [ar](../../ar/docs/TROUBLESHOOTING.md) · 🇮🇳 [in](../../in/docs/TROUBLESHOOTING.md) · 🇹🇭 [th](../../th/docs/TROUBLESHOOTING.md) · 🇻🇳 [vi](../../vi/docs/TROUBLESHOOTING.md) · 🇮🇩 [id](../../id/docs/TROUBLESHOOTING.md) · 🇲🇾 [ms](../../ms/docs/TROUBLESHOOTING.md) · 🇳🇱 [nl](../../nl/docs/TROUBLESHOOTING.md) · 🇵🇱 [pl](../../pl/docs/TROUBLESHOOTING.md) · 🇸🇪 [sv](../../sv/docs/TROUBLESHOOTING.md) · 🇳🇴 [no](../../no/docs/TROUBLESHOOTING.md) · 🇩🇰 [da](../../da/docs/TROUBLESHOOTING.md) · 🇫🇮 [fi](../../fi/docs/TROUBLESHOOTING.md) · 🇵🇹 [pt](../../pt/docs/TROUBLESHOOTING.md) · 🇷🇴 [ro](../../ro/docs/TROUBLESHOOTING.md) · 🇭🇺 [hu](../../hu/docs/TROUBLESHOOTING.md) · 🇧🇬 [bg](../../bg/docs/TROUBLESHOOTING.md) · 🇸🇰 [sk](../../sk/docs/TROUBLESHOOTING.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/TROUBLESHOOTING.md) · 🇮🇱 [he](../../he/docs/TROUBLESHOOTING.md) · 🇵🇭 [phi](../../phi/docs/TROUBLESHOOTING.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/TROUBLESHOOTING.md) · 🇨🇿 [cs](../../cs/docs/TROUBLESHOOTING.md)
---
-# Troubleshooting
-
-🌐 **Languages:** 🇺🇸 [English](TROUBLESHOOTING.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/TROUBLESHOOTING.md) | 🇪🇸 [Español](i18n/es/TROUBLESHOOTING.md) | 🇫🇷 [Français](i18n/fr/TROUBLESHOOTING.md) | 🇮🇹 [Italiano](i18n/it/TROUBLESHOOTING.md) | 🇷🇺 [Русский](i18n/ru/TROUBLESHOOTING.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/TROUBLESHOOTING.md) | 🇩🇪 [Deutsch](i18n/de/TROUBLESHOOTING.md) | 🇮🇳 [हिन्दी](i18n/in/TROUBLESHOOTING.md) | 🇹🇭 [ไทย](i18n/th/TROUBLESHOOTING.md) | 🇺🇦 [Українська](i18n/uk-UA/TROUBLESHOOTING.md) | 🇸🇦 [العربية](i18n/ar/TROUBLESHOOTING.md) | 🇯🇵 [日本語](i18n/ja/TROUBLESHOOTING.md) | 🇻🇳 [Tiếng Việt](i18n/vi/TROUBLESHOOTING.md) | 🇧🇬 [Български](i18n/bg/TROUBLESHOOTING.md) | 🇩🇰 [Dansk](i18n/da/TROUBLESHOOTING.md) | 🇫🇮 [Suomi](i18n/fi/TROUBLESHOOTING.md) | 🇮🇱 [עברית](i18n/he/TROUBLESHOOTING.md) | 🇭🇺 [Magyar](i18n/hu/TROUBLESHOOTING.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/TROUBLESHOOTING.md) | 🇰🇷 [한국어](i18n/ko/TROUBLESHOOTING.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/TROUBLESHOOTING.md) | 🇳🇱 [Nederlands](i18n/nl/TROUBLESHOOTING.md) | 🇳🇴 [Norsk](i18n/no/TROUBLESHOOTING.md) | 🇵🇹 [Português (Portugal)](i18n/pt/TROUBLESHOOTING.md) | 🇷🇴 [Română](i18n/ro/TROUBLESHOOTING.md) | 🇵🇱 [Polski](i18n/pl/TROUBLESHOOTING.md) | 🇸🇰 [Slovenčina](i18n/sk/TROUBLESHOOTING.md) | 🇸🇪 [Svenska](i18n/sv/TROUBLESHOOTING.md) | 🇵🇭 [Filipino](i18n/phi/TROUBLESHOOTING.md)
-
Common problems and solutions for OmniRoute.
---
diff --git a/docs/i18n/bg/USER_GUIDE.md b/docs/i18n/bg/docs/USER_GUIDE.md
similarity index 82%
rename from docs/i18n/bg/USER_GUIDE.md
rename to docs/i18n/bg/docs/USER_GUIDE.md
index d6649af4a7..d68a4c1dfe 100644
--- a/docs/i18n/bg/USER_GUIDE.md
+++ b/docs/i18n/bg/docs/USER_GUIDE.md
@@ -1,8 +1,6 @@
# User Guide (Български)
-🌐 **Languages:** 🇺🇸 [English](../../USER_GUIDE.md) · 🇧🇷 [pt-BR](../pt-BR/USER_GUIDE.md) · 🇪🇸 [es](../es/USER_GUIDE.md) · 🇫🇷 [fr](../fr/USER_GUIDE.md) · 🇩🇪 [de](../de/USER_GUIDE.md) · 🇮🇹 [it](../it/USER_GUIDE.md) · 🇷🇺 [ru](../ru/USER_GUIDE.md) · 🇨🇳 [zh-CN](../zh-CN/USER_GUIDE.md) · 🇯🇵 [ja](../ja/USER_GUIDE.md) · 🇰🇷 [ko](../ko/USER_GUIDE.md) · 🇸🇦 [ar](../ar/USER_GUIDE.md) · 🇮🇳 [in](../in/USER_GUIDE.md) · 🇹🇭 [th](../th/USER_GUIDE.md) · 🇻🇳 [vi](../vi/USER_GUIDE.md) · 🇮🇩 [id](../id/USER_GUIDE.md) · 🇲🇾 [ms](../ms/USER_GUIDE.md) · 🇳🇱 [nl](../nl/USER_GUIDE.md) · 🇵🇱 [pl](../pl/USER_GUIDE.md) · 🇸🇪 [sv](../sv/USER_GUIDE.md) · 🇳🇴 [no](../no/USER_GUIDE.md) · 🇩🇰 [da](../da/USER_GUIDE.md) · 🇫🇮 [fi](../fi/USER_GUIDE.md) · 🇵🇹 [pt](../pt/USER_GUIDE.md) · 🇷🇴 [ro](../ro/USER_GUIDE.md) · 🇭🇺 [hu](../hu/USER_GUIDE.md) · 🇧🇬 [bg](../bg/USER_GUIDE.md) · 🇸🇰 [sk](../sk/USER_GUIDE.md) · 🇺🇦 [uk-UA](../uk-UA/USER_GUIDE.md) · 🇮🇱 [he](../he/USER_GUIDE.md) · 🇵🇭 [phi](../phi/USER_GUIDE.md)
-
-> 🇺🇸 [English](../../USER_GUIDE.md)
+🌐 **Languages:** 🇺🇸 [English](../../../../docs/USER_GUIDE.md) · 🇪🇸 [es](../../es/docs/USER_GUIDE.md) · 🇫🇷 [fr](../../fr/docs/USER_GUIDE.md) · 🇩🇪 [de](../../de/docs/USER_GUIDE.md) · 🇮🇹 [it](../../it/docs/USER_GUIDE.md) · 🇷🇺 [ru](../../ru/docs/USER_GUIDE.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/USER_GUIDE.md) · 🇯🇵 [ja](../../ja/docs/USER_GUIDE.md) · 🇰🇷 [ko](../../ko/docs/USER_GUIDE.md) · 🇸🇦 [ar](../../ar/docs/USER_GUIDE.md) · 🇮🇳 [in](../../in/docs/USER_GUIDE.md) · 🇹🇭 [th](../../th/docs/USER_GUIDE.md) · 🇻🇳 [vi](../../vi/docs/USER_GUIDE.md) · 🇮🇩 [id](../../id/docs/USER_GUIDE.md) · 🇲🇾 [ms](../../ms/docs/USER_GUIDE.md) · 🇳🇱 [nl](../../nl/docs/USER_GUIDE.md) · 🇵🇱 [pl](../../pl/docs/USER_GUIDE.md) · 🇸🇪 [sv](../../sv/docs/USER_GUIDE.md) · 🇳🇴 [no](../../no/docs/USER_GUIDE.md) · 🇩🇰 [da](../../da/docs/USER_GUIDE.md) · 🇫🇮 [fi](../../fi/docs/USER_GUIDE.md) · 🇵🇹 [pt](../../pt/docs/USER_GUIDE.md) · 🇷🇴 [ro](../../ro/docs/USER_GUIDE.md) · 🇭🇺 [hu](../../hu/docs/USER_GUIDE.md) · 🇧🇬 [bg](../../bg/docs/USER_GUIDE.md) · 🇸🇰 [sk](../../sk/docs/USER_GUIDE.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/USER_GUIDE.md) · 🇮🇱 [he](../../he/docs/USER_GUIDE.md) · 🇵🇭 [phi](../../phi/docs/USER_GUIDE.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/USER_GUIDE.md) · 🇨🇿 [cs](../../cs/docs/USER_GUIDE.md)
---
@@ -320,7 +318,7 @@ Model: cc/claude-opus-4-6
---
-## 🚀 Deployment
+## Разгръщане
### Global npm install (Recommended)
@@ -511,23 +509,26 @@ post_install() {
### Environment Variables
-| Variable | Default | Description |
-| ------------------------- | ------------------------------------ | ------------------------------------------------------- |
-| `JWT_SECRET` | `omniroute-default-secret-change-me` | JWT signing secret (**change in production**) |
-| `INITIAL_PASSWORD` | `123456` | First login password |
-| `DATA_DIR` | `~/.omniroute` | Data directory (db, usage, logs) |
-| `PORT` | framework default | Service port (`20128` in examples) |
-| `HOSTNAME` | framework default | Bind host (Docker defaults to `0.0.0.0`) |
-| `NODE_ENV` | runtime default | Set `production` for deploy |
-| `BASE_URL` | `http://localhost:20128` | Server-side internal base URL |
-| `CLOUD_URL` | `https://omniroute.dev` | Cloud sync endpoint base URL |
-| `API_KEY_SECRET` | `endpoint-proxy-api-key-secret` | HMAC secret for generated API keys |
-| `REQUIRE_API_KEY` | `false` | Enforce Bearer API key on `/v1/*` |
-| `ENABLE_REQUEST_LOGS` | `false` | Enables request/response logs |
-| `AUTH_COOKIE_SECURE` | `false` | Force `Secure` auth cookie (behind HTTPS reverse proxy) |
-| `OMNIROUTE_MEMORY_MB` | `512` | Node.js heap limit in MB |
-| `PROMPT_CACHE_MAX_SIZE` | `50` | Max prompt cache entries |
-| `SEMANTIC_CACHE_MAX_SIZE` | `100` | Max semantic cache entries |
+| Variable | Default | Description |
+| ---------------------------- | ------------------------------------ | ------------------------------------------------------------------------------------------ |
+| `JWT_SECRET` | `omniroute-default-secret-change-me` | JWT signing secret (**change in production**) |
+| `INITIAL_PASSWORD` | `123456` | First login password |
+| `DATA_DIR` | `~/.omniroute` | Data directory (db, usage, logs) |
+| `PORT` | framework default | Service port (`20128` in examples) |
+| `HOSTNAME` | framework default | Bind host (Docker defaults to `0.0.0.0`) |
+| `NODE_ENV` | runtime default | Set `production` for deploy |
+| `BASE_URL` | `http://localhost:20128` | Server-side internal base URL |
+| `CLOUD_URL` | `https://omniroute.dev` | Cloud sync endpoint base URL |
+| `API_KEY_SECRET` | `endpoint-proxy-api-key-secret` | HMAC secret for generated API keys |
+| `REQUIRE_API_KEY` | `false` | Enforce Bearer API key on `/v1/*` |
+| `ALLOW_API_KEY_REVEAL` | `false` | Allow Api Manager to copy full API keys on demand |
+| `DISABLE_SQLITE_AUTO_BACKUP` | `false` | Disable automatic SQLite snapshots before writes/import/restore; manual backups still work |
+| `ENABLE_REQUEST_LOGS` | `false` | Enables request/response logs |
+| `AUTH_COOKIE_SECURE` | `false` | Force `Secure` auth cookie (behind HTTPS reverse proxy) |
+| `CLOUDFLARED_BIN` | unset | Use an existing `cloudflared` binary instead of managed download |
+| `OMNIROUTE_MEMORY_MB` | `512` | Node.js heap limit in MB |
+| `PROMPT_CACHE_MAX_SIZE` | `50` | Max prompt cache entries |
+| `SEMANTIC_CACHE_MAX_SIZE` | `100` | Max semantic cache entries |
For the full environment variable reference, see the [README](../README.md).
@@ -598,6 +599,11 @@ curl -X POST http://localhost:20128/api/provider-models \
Or use Dashboard: **Providers → [Provider] → Custom Models**.
+Notes:
+
+- OpenRouter and OpenAI/Anthropic-compatible providers are managed from **Available Models** only. Manual add, import, and auto-sync all land in the same available-model list, so there is no separate Custom Models section for those providers.
+- The **Custom Models** section is intended for providers that do not expose managed available-model imports.
+
### Dedicated Provider Routes
Route requests directly to a specific provider with model validation:
@@ -642,6 +648,14 @@ Returns models grouped by provider with types (`chat`, `embedding`, `image`).
- Automatic background sync with timeout + fail-fast
- Prefer server-side `BASE_URL`/`CLOUD_URL` in production
+### Cloudflare Quick Tunnel
+
+- Available in **Dashboard → Endpoints** for Docker and other self-hosted deployments
+- Creates a temporary `https://*.trycloudflare.com` URL that forwards to your current OpenAI-compatible `/v1` endpoint
+- First enable installs `cloudflared` only when needed; later restarts reuse the same managed binary
+- Tunnel URLs are ephemeral and change every time you stop/start the tunnel
+- Set `CLOUDFLARED_BIN` if you prefer using a preinstalled `cloudflared` binary instead of the managed download
+
### LLM Gateway Intelligence (Phase 9)
- **Semantic Cache** — Auto-caches non-streaming, temperature=0 responses (bypass with `X-OmniRoute-No-Cache: true`)
@@ -757,11 +771,11 @@ OmniRoute implements provider-level resilience with four components:
Manage database backups in **Dashboard → Settings → System & Storage**.
-| Action | Description |
-| ------------------------ | ------------------------------------------------------------------------------------------------------------------------------ |
-| **Export Database** | Downloads the current SQLite database as a `.sqlite` file |
-| **Export All (.tar.gz)** | Downloads a full backup archive including: database, settings, combos, provider connections (no credentials), API key metadata |
-| **Import Database** | Upload a `.sqlite` file to replace the current database. A pre-import backup is automatically created |
+| Action | Description |
+| ------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------- |
+| **Export Database** | Downloads the current SQLite database as a `.sqlite` file |
+| **Export All (.tar.gz)** | Downloads a full backup archive including: database, settings, combos, provider connections (no credentials), API key metadata |
+| **Import Database** | Upload a `.sqlite` file to replace the current database. A pre-import backup is automatically created unless `DISABLE_SQLITE_AUTO_BACKUP=true` |
```bash
# API: Export database
@@ -787,10 +801,11 @@ curl -X POST http://localhost:20128/api/db-backups/import \
### Settings Dashboard
-The settings page is organized into 5 tabs for easy navigation:
+The settings page is organized into 6 tabs for easy navigation:
| Tab | Contents |
| -------------- | ---------------------------------------------------------------------------------------------- |
+| **General** | System storage tools, appearance settings, theme controls, and per-item sidebar visibility |
| **Security** | Login/Password settings, IP Access Control, API auth for `/models`, and Provider Blocking |
| **Routing** | Global routing strategy (6 options), wildcard model aliases, fallback chains, combo defaults |
| **Resilience** | Provider profiles, editable rate limits, circuit breaker status, policies & locked identifiers |
diff --git a/docs/i18n/bg/docs/VM_DEPLOYMENT_GUIDE.md b/docs/i18n/bg/docs/VM_DEPLOYMENT_GUIDE.md
new file mode 100644
index 0000000000..0e75a7842e
--- /dev/null
+++ b/docs/i18n/bg/docs/VM_DEPLOYMENT_GUIDE.md
@@ -0,0 +1,403 @@
+# OmniRoute — Deployment Guide on VM with Cloudflare (Български)
+
+🌐 **Languages:** 🇺🇸 [English](../../../../docs/VM_DEPLOYMENT_GUIDE.md) · 🇪🇸 [es](../../es/docs/VM_DEPLOYMENT_GUIDE.md) · 🇫🇷 [fr](../../fr/docs/VM_DEPLOYMENT_GUIDE.md) · 🇩🇪 [de](../../de/docs/VM_DEPLOYMENT_GUIDE.md) · 🇮🇹 [it](../../it/docs/VM_DEPLOYMENT_GUIDE.md) · 🇷🇺 [ru](../../ru/docs/VM_DEPLOYMENT_GUIDE.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/VM_DEPLOYMENT_GUIDE.md) · 🇯🇵 [ja](../../ja/docs/VM_DEPLOYMENT_GUIDE.md) · 🇰🇷 [ko](../../ko/docs/VM_DEPLOYMENT_GUIDE.md) · 🇸🇦 [ar](../../ar/docs/VM_DEPLOYMENT_GUIDE.md) · 🇮🇳 [in](../../in/docs/VM_DEPLOYMENT_GUIDE.md) · 🇹🇭 [th](../../th/docs/VM_DEPLOYMENT_GUIDE.md) · 🇻🇳 [vi](../../vi/docs/VM_DEPLOYMENT_GUIDE.md) · 🇮🇩 [id](../../id/docs/VM_DEPLOYMENT_GUIDE.md) · 🇲🇾 [ms](../../ms/docs/VM_DEPLOYMENT_GUIDE.md) · 🇳🇱 [nl](../../nl/docs/VM_DEPLOYMENT_GUIDE.md) · 🇵🇱 [pl](../../pl/docs/VM_DEPLOYMENT_GUIDE.md) · 🇸🇪 [sv](../../sv/docs/VM_DEPLOYMENT_GUIDE.md) · 🇳🇴 [no](../../no/docs/VM_DEPLOYMENT_GUIDE.md) · 🇩🇰 [da](../../da/docs/VM_DEPLOYMENT_GUIDE.md) · 🇫🇮 [fi](../../fi/docs/VM_DEPLOYMENT_GUIDE.md) · 🇵🇹 [pt](../../pt/docs/VM_DEPLOYMENT_GUIDE.md) · 🇷🇴 [ro](../../ro/docs/VM_DEPLOYMENT_GUIDE.md) · 🇭🇺 [hu](../../hu/docs/VM_DEPLOYMENT_GUIDE.md) · 🇧🇬 [bg](../../bg/docs/VM_DEPLOYMENT_GUIDE.md) · 🇸🇰 [sk](../../sk/docs/VM_DEPLOYMENT_GUIDE.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/VM_DEPLOYMENT_GUIDE.md) · 🇮🇱 [he](../../he/docs/VM_DEPLOYMENT_GUIDE.md) · 🇵🇭 [phi](../../phi/docs/VM_DEPLOYMENT_GUIDE.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/VM_DEPLOYMENT_GUIDE.md) · 🇨🇿 [cs](../../cs/docs/VM_DEPLOYMENT_GUIDE.md)
+
+---
+
+Complete guide to install and configure OmniRoute on a VM (VPS) with domain managed via Cloudflare.
+
+---
+
+## Prerequisites
+
+| Item | Minimum | Recommended |
+| ---------- | ------------------------ | ---------------- |
+| **CPU** | 1 vCPU | 2 vCPU |
+| **RAM** | 1 GB | 2 GB |
+| **Disk** | 10 GB SSD | 25 GB SSD |
+| **OS** | Ubuntu 22.04 LTS | Ubuntu 24.04 LTS |
+| **Domain** | Registered on Cloudflare | — |
+| **Docker** | Docker Engine 24+ | Docker 27+ |
+
+**Tested providers**: Akamai (Linode), DigitalOcean, Vultr, Hetzner, AWS Lightsail.
+
+---
+
+## 1. Configure the VM
+
+### 1.1 Create the instance
+
+On your preferred VPS provider:
+
+- Choose Ubuntu 24.04 LTS
+- Select the minimum plan (1 vCPU / 1 GB RAM)
+- Set a strong root password or configure SSH key
+- Note the **public IP** (e.g., `203.0.113.10`)
+
+### 1.2 Connect via SSH
+
+```bash
+ssh root@203.0.113.10
+```
+
+### 1.3 Update the system
+
+```bash
+apt update && apt upgrade -y
+```
+
+### 1.4 Install Docker
+
+```bash
+# Install dependencies
+apt install -y ca-certificates curl gnupg
+
+# Add official Docker repository
+install -m 0755 -d /etc/apt/keyrings
+curl -fsSL https://download.docker.com/linux/ubuntu/gpg | gpg --dearmor -o /etc/apt/keyrings/docker.gpg
+chmod a+r /etc/apt/keyrings/docker.gpg
+echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu $ (. /etc/os-release && echo “$VERSION_CODENAME”) stable" | tee /etc/apt/sources.list.d/docker.list > /dev/null
+apt update
+apt install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin
+```
+
+### 1.5 Install nginx
+
+```bash
+apt install -y nginx
+```
+
+### 1.6 Configure Firewall (UFW)
+
+```bash
+ufw default deny incoming
+ufw default allow outgoing
+ufw allow 22/tcp # SSH
+ufw allow 80/tcp # HTTP (redirect)
+ufw allow 443/tcp # HTTPS
+ufw enable
+```
+
+> **Tip**: For maximum security, restrict ports 80 and 443 to Cloudflare IPs only. See the [Advanced Security](#advanced-security) section.
+
+---
+
+## 2. Install OmniRoute
+
+### 2.1 Create configuration directory
+
+```bash
+mkdir -p /opt/omniroute
+```
+
+### 2.2 Create environment variables file
+
+```bash
+cat > /opt/omniroute/.env << ‘EOF’
+# === Security ===
+JWT_SECRET=CHANGE-TO-A-UNIQUE-64-CHAR-SECRET-KEY
+INITIAL_PASSWORD=YourSecurePassword123!
+API_KEY_SECRET=REPLACE-WITH-ANOTHER-SECRET-KEY
+STORAGE_ENCRYPTION_KEY=REPLACE-WITH-THIRD-SECRET-KEY
+STORAGE_ENCRYPTION_KEY_VERSION=v1
+MACHINE_ID_SALT=CHANGE-TO-A-UNIQUE-SALT
+
+# === App ===
+PORT=20128
+NODE_ENV=production
+HOSTNAME=0.0.0.0
+DATA_DIR=/app/data
+STORAGE_DRIVER=sqlite
+ENABLE_REQUEST_LOGS=true
+AUTH_COOKIE_SECURE=false
+REQUIRE_API_KEY=false
+
+# === Domain (change to your domain) ===
+BASE_URL=https://llms.seudominio.com
+NEXT_PUBLIC_BASE_URL=https://llms.seudominio.com
+
+# === Cloud Sync (optional) ===
+# CLOUD_URL=https://cloud.omniroute.online
+# NEXT_PUBLIC_CLOUD_URL=https://cloud.omniroute.online
+EOF
+```
+
+> ⚠️ **IMPORTANT**: Generate unique secret keys! Use `openssl rand -hex 32` for each key.
+
+### 2.3 Start the container
+
+```bash
+docker pull diegosouzapw/omniroute:latest
+
+docker run -d \
+ --name omniroute \
+ --restart unless-stopped \
+ --env-file /opt/omniroute/.env \
+ -p 20128:20128 \
+ -v omniroute-data:/app/data \
+ diegosouzapw/omniroute:latest
+```
+
+### 2.4 Verify that it is running
+
+```bash
+docker ps | grep omniroute
+docker logs omniroute --tail 20
+```
+
+It should display: `[DB] SQLite database ready` and `listening on port 20128`.
+
+---
+
+## 3. Configure nginx (Reverse Proxy)
+
+### 3.1 Generate SSL certificate (Cloudflare Origin)
+
+In the Cloudflare dashboard:
+
+1. Go to **SSL/TLS → Origin Server**
+2. Click **Create Certificate**
+3. Keep the defaults (15 years, \*.yourdomain.com)
+4. Copy the **Origin Certificate** and the **Private Key**
+
+```bash
+mkdir -p /etc/nginx/ssl
+
+# Paste the certificate
+nano /etc/nginx/ssl/origin.crt
+
+# Paste the private key
+nano /etc/nginx/ssl/origin.key
+
+chmod 600 /etc/nginx/ssl/origin.key
+```
+
+### 3.2 Nginx Configuration
+
+```bash
+cat > /etc/nginx/sites-available/omniroute << ‘NGINX’
+# Default server — blocks direct access via IP
+server {
+ listen 80 default_server;
+ listen [::]:80 default_server;
+ listen 443 ssl default_server;
+ listen [::]:443 ssl default_server;
+ ssl_certificate /etc/nginx/ssl/origin.crt;
+ ssl_certificate_key /etc/nginx/ssl/origin.key;
+ server_name _;
+ return 444;
+}
+
+# OmniRoute — HTTPS
+server {
+ listen 443 ssl;
+ listen [::]:443 ssl;
+ server_name llms.yourdomain.com; # Change to your domain
+
+ ssl_certificate /etc/nginx/ssl/origin.crt;
+ ssl_certificate_key /etc/nginx/ssl/origin.key;
+ ssl_protocols TLSv1.2 TLSv1.3;
+
+ client_max_body_size 100M;
+
+ location / {
+ proxy_pass http://127.0.0.1:20128;
+ proxy_set_header Host $host;
+ proxy_set_header X-Real-IP $remote_addr;
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
+ proxy_set_header X-Forwarded-Proto $scheme;
+
+ # WebSocket support
+ proxy_http_version 1.1;
+ proxy_set_header Upgrade $http_upgrade;
+ proxy_set_header Connection “upgrade”;
+
+ # SSE (Server-Sent Events) — streaming AI responses
+ proxy_buffering off;
+ proxy_cache off;
+ proxy_read_timeout 300s;
+ proxy_send_timeout 300s;
+ }
+}
+
+# HTTP → HTTPS redirect
+server {
+ listen 80;
+ listen [::]:80;
+ server_name llms.yourdomain.com;
+ return 301 https://$server_name$request_uri;
+}
+NGINX
+```
+
+### 3.3 Enable and Test
+
+```bash
+# Remove default configuration
+rm -f /etc/nginx/sites-enabled/default
+
+# Enable OmniRoute
+ln -sf /etc/nginx/sites-available/omniroute /etc/nginx/sites-enabled/omniroute
+
+# Test and reload
+nginx -t && systemctl reload nginx
+```
+
+---
+
+## 4. Configure Cloudflare DNS
+
+### 4.1 Add DNS record
+
+In the Cloudflare dashboard → DNS:
+
+| Type | Name | Content | Proxy |
+| ---- | ------ | ---------------------- | ---------- |
+| A | `llms` | `203.0.113.10` (VM IP) | ✅ Proxied |
+
+### 4.2 Configure SSL
+
+Under **SSL/TLS → Overview**:
+
+- Mode: **Full (Strict)**
+
+Under **SSL/TLS → Edge Certificates**:
+
+- Always Use HTTPS: ✅ On
+- Minimum TLS Version: TLS 1.2
+- Automatic HTTPS Rewrites: ✅ On
+
+### 4.3 Testing
+
+```bash
+curl -sI https://llms.seudominio.com/health
+# Should return HTTP/2 200
+```
+
+---
+
+## 5. Operations and Maintenance
+
+### Upgrade to a new version
+
+```bash
+docker pull diegosouzapw/omniroute:latest
+docker stop omniroute && docker rm omniroute
+docker run -d --name omniroute --restart unless-stopped \
+ --env-file /opt/omniroute/.env \
+ -p 20128:20128 \
+ -v omniroute-data:/app/data \
+ diegosouzapw/omniroute:latest
+```
+
+### View logs
+
+```bash
+docker logs -f omniroute # Real-time stream
+docker logs omniroute --tail 50 # Last 50 lines
+```
+
+### Manual database backup
+
+```bash
+# Copy data from the volume to the host
+docker cp omniroute:/app/data ./backup-$(date +%F)
+
+# Or compress the entire volume
+docker run --rm -v omniroute-data:/data -v $(pwd):/backup \
+ alpine tar czf /backup/omniroute-data-$(date +%F).tar.gz /data
+```
+
+### Restore from backup
+
+```bash
+docker stop omniroute
+docker run --rm -v omniroute-data:/data -v $(pwd):/backup \
+ alpine sh -c “rm -rf /data/* && tar xzf /backup/omniroute-data-YYYY-MM-DD.tar.gz -C /”
+docker start omniroute
+```
+
+---
+
+## 6. Advanced Security
+
+### Restrict nginx to Cloudflare IPs
+
+```bash
+cat > /etc/nginx/cloudflare-ips.conf << ‘CF’
+# Cloudflare IPv4 ranges — update periodically
+# https://www.cloudflare.com/ips-v4/
+set_real_ip_from 173.245.48.0/20;
+set_real_ip_from 103.21.244.0/22;
+set_real_ip_from 103.22.200.0/22;
+set_real_ip_from 103.31.4.0/22;
+set_real_ip_from 141.101.64.0/18;
+set_real_ip_from 108.162.192.0/18;
+set_real_ip_from 190.93.240.0/20;
+set_real_ip_from 188.114.96.0/20;
+set_real_ip_from 197.234.240.0/22;
+set_real_ip_from 198.41.128.0/17;
+set_real_ip_from 162.158.0.0/15;
+set_real_ip_from 104.16.0.0/13;
+set_real_ip_from 104.24.0.0/14;
+set_real_ip_from 172.64.0.0/13;
+set_real_ip_from 131.0.72.0/22;
+real_ip_header CF-Connecting-IP;
+CF
+```
+
+Add the following to `nginx.conf` inside the `http {}` block:
+
+```nginx
+include /etc/nginx/cloudflare-ips.conf;
+```
+
+### Install fail2ban
+
+```bash
+apt install -y fail2ban
+systemctl enable fail2ban
+systemctl start fail2ban
+
+# Check status
+fail2ban-client status sshd
+```
+
+### Block direct access to the Docker port
+
+```bash
+# Prevent direct external access to port 20128
+iptables -I DOCKER-USER -p tcp --dport 20128 -j DROP
+iptables -I DOCKER-USER -i lo -p tcp --dport 20128 -j ACCEPT
+
+# Persist the rules
+apt install -y iptables-persistent
+netfilter-persistent save
+```
+
+---
+
+## 7. Deploy to Cloudflare Workers (Optional)
+
+For remote access via Cloudflare Workers (without exposing the VM directly):
+
+```bash
+# In the local repository
+cd omnirouteCloud
+npm install
+npx wrangler login
+npx wrangler deploy
+```
+
+See the full documentation at [omnirouteCloud/README.md](../omnirouteCloud/README.md).
+
+---
+
+## Port Summary
+
+| Port | Service | Access |
+| ----- | ----------- | -------------------------- |
+| 22 | SSH | Public (with fail2ban) |
+| 80 | nginx HTTP | Redirect → HTTPS |
+| 443 | nginx HTTPS | Via Cloudflare Proxy |
+| 20128 | OmniRoute | Localhost only (via nginx) |
diff --git a/docs/i18n/bg/src/lib/a2a/README.md b/docs/i18n/bg/src/lib/a2a/README.md
new file mode 100644
index 0000000000..51ea7b5055
--- /dev/null
+++ b/docs/i18n/bg/src/lib/a2a/README.md
@@ -0,0 +1,752 @@
+# OmniRoute A2A Server (Български)
+
+🌐 **Languages:** 🇺🇸 [English](../../../../../../src/lib/a2a/README.md) · 🇪🇸 [es](../../../../es/src/lib/a2a/README.md) · 🇫🇷 [fr](../../../../fr/src/lib/a2a/README.md) · 🇩🇪 [de](../../../../de/src/lib/a2a/README.md) · 🇮🇹 [it](../../../../it/src/lib/a2a/README.md) · 🇷🇺 [ru](../../../../ru/src/lib/a2a/README.md) · 🇨🇳 [zh-CN](../../../../zh-CN/src/lib/a2a/README.md) · 🇯🇵 [ja](../../../../ja/src/lib/a2a/README.md) · 🇰🇷 [ko](../../../../ko/src/lib/a2a/README.md) · 🇸🇦 [ar](../../../../ar/src/lib/a2a/README.md) · 🇮🇳 [in](../../../../in/src/lib/a2a/README.md) · 🇹🇭 [th](../../../../th/src/lib/a2a/README.md) · 🇻🇳 [vi](../../../../vi/src/lib/a2a/README.md) · 🇮🇩 [id](../../../../id/src/lib/a2a/README.md) · 🇲🇾 [ms](../../../../ms/src/lib/a2a/README.md) · 🇳🇱 [nl](../../../../nl/src/lib/a2a/README.md) · 🇵🇱 [pl](../../../../pl/src/lib/a2a/README.md) · 🇸🇪 [sv](../../../../sv/src/lib/a2a/README.md) · 🇳🇴 [no](../../../../no/src/lib/a2a/README.md) · 🇩🇰 [da](../../../../da/src/lib/a2a/README.md) · 🇫🇮 [fi](../../../../fi/src/lib/a2a/README.md) · 🇵🇹 [pt](../../../../pt/src/lib/a2a/README.md) · 🇷🇴 [ro](../../../../ro/src/lib/a2a/README.md) · 🇭🇺 [hu](../../../../hu/src/lib/a2a/README.md) · 🇧🇬 [bg](../../../../bg/src/lib/a2a/README.md) · 🇸🇰 [sk](../../../../sk/src/lib/a2a/README.md) · 🇺🇦 [uk-UA](../../../../uk-UA/src/lib/a2a/README.md) · 🇮🇱 [he](../../../../he/src/lib/a2a/README.md) · 🇵🇭 [phi](../../../../phi/src/lib/a2a/README.md) · 🇧🇷 [pt-BR](../../../../pt-BR/src/lib/a2a/README.md) · 🇨🇿 [cs](../../../../cs/src/lib/a2a/README.md)
+
+---
+
+> **Agent-to-Agent Protocol v0.3** — Enables any AI agent to use OmniRoute as an intelligent routing agent via JSON-RPC 2.0.
+
+The A2A Server exposes OmniRoute as a **first-class agent** that other agents can discover, delegate tasks to, and collaborate with using the [A2A Protocol](https://google.github.io/A2A/).
+
+---
+
+## Архитектура
+
+```
+┌──────────────────────────────────────────────────────────────────┐
+│ Orchestrator Agent │
+│ (LangChain, CrewAI, AutoGen, Custom Agent) │
+└──────────────────────┬───────────────────────────────────────────┘
+ │ 1. GET /.well-known/agent.json (discover)
+ │ 2. POST /a2a (JSON-RPC 2.0)
+ ▼
+┌──────────────────────────────────────────────────────────────────┐
+│ OmniRoute A2A Server │
+│ ┌────────────────┐ ┌────────────────┐ ┌───────────────────┐ │
+│ │ Task Manager │ │ Skill Engine │ │ SSE Streaming │ │
+│ │ (lifecycle) │──│ (registry) │──│ (real-time) │ │
+│ └────────────────┘ └────────┬───────┘ └───────────────────┘ │
+│ │ │
+│ Skills: │ │
+│ ├─ smart-routing ──────────┤ ┌────────────────────────────┐ │
+│ └─ quota-management ───────┘ │ Routing Decision Logger │ │
+│ └────────────────────────────┘ │
+└──────────────────────────────────────────────────────────────────┘
+ │
+ ▼ OmniRoute Gateway (internal)
+ /v1/chat/completions, /api/combos, /api/usage/quota
+```
+
+---
+
+## Бърз старт
+
+### Agent Discovery
+
+Every A2A-compatible agent exposes an **Agent Card** at `/.well-known/agent.json`:
+
+```bash
+curl http://localhost:20128/.well-known/agent.json
+```
+
+**Response:**
+
+```json
+{
+ "name": "OmniRoute",
+ "description": "Intelligent AI gateway with auto-routing across 50+ providers",
+ "url": "http://localhost:20128/a2a",
+ "version": "1.8.1",
+ "capabilities": {
+ "streaming": true,
+ "pushNotifications": false
+ },
+ "skills": [
+ {
+ "id": "smart-routing",
+ "name": "Smart Routing",
+ "description": "Routes prompts through OmniRoute intelligent pipeline",
+ "tags": ["routing", "llm", "multi-provider", "cost-optimization"],
+ "examples": [
+ "Write a hello world in Python",
+ "Explain quantum computing using the cheapest provider"
+ ]
+ },
+ {
+ "id": "quota-management",
+ "name": "Quota Management",
+ "description": "Natural-language queries about provider quotas",
+ "tags": ["quota", "analytics", "cost"],
+ "examples": [
+ "Which provider has the most quota remaining?",
+ "Suggest a free combo for coding"
+ ]
+ }
+ ],
+ "authentication": {
+ "schemes": ["bearer"],
+ "apiKeyHeader": "Authorization"
+ }
+}
+```
+
+---
+
+## JSON-RPC 2.0 Methods
+
+### `message/send` — Synchronous Execution
+
+Send a message to a skill and receive the complete response.
+
+```bash
+curl -X POST http://localhost:20128/a2a \
+ -H "Content-Type: application/json" \
+ -H "Authorization: Bearer YOUR_KEY" \
+ -d '{
+ "jsonrpc": "2.0",
+ "id": "1",
+ "method": "message/send",
+ "params": {
+ "skill": "smart-routing",
+ "messages": [{"role": "user", "content": "Write a Python hello world"}],
+ "metadata": {"model": "auto", "combo": "fast-coding"}
+ }
+ }'
+```
+
+**Response:**
+
+```json
+{
+ "jsonrpc": "2.0",
+ "id": "1",
+ "result": {
+ "task": { "id": "a1b2c3d4-...", "state": "completed" },
+ "artifacts": [{ "type": "text", "content": "print('Hello, World!')" }],
+ "metadata": {
+ "routing_explanation": "Selected claude-sonnet via provider \"anthropic\" (latency: 1200ms, cost: $0.0030)",
+ "cost_envelope": { "estimated": 0.005, "actual": 0.003, "currency": "USD" },
+ "resilience_trace": [
+ { "event": "primary_selected", "provider": "anthropic", "timestamp": "2026-03-04T..." }
+ ],
+ "policy_verdict": { "allowed": true, "reason": "within budget and quota limits" }
+ }
+ }
+}
+```
+
+### `message/stream` — SSE Streaming
+
+Same as `message/send` but returns Server-Sent Events for real-time streaming.
+
+```bash
+curl -N -X POST http://localhost:20128/a2a \
+ -H "Content-Type: application/json" \
+ -H "Authorization: Bearer YOUR_KEY" \
+ -d '{
+ "jsonrpc": "2.0",
+ "id": "1",
+ "method": "message/stream",
+ "params": {
+ "skill": "smart-routing",
+ "messages": [{"role": "user", "content": "Explain quantum computing"}]
+ }
+ }'
+```
+
+**SSE Events:**
+
+```
+data: {"jsonrpc":"2.0","method":"message/stream","params":{"task":{"id":"...","state":"working"},"chunk":{"type":"text","content":"Quantum computing..."}}}
+
+: heartbeat 2026-03-04T21:00:00Z
+
+data: {"jsonrpc":"2.0","method":"message/stream","params":{"task":{"id":"...","state":"completed"},"metadata":{...}}}
+```
+
+### `tasks/get` — Query Task Status
+
+```bash
+curl -X POST http://localhost:20128/a2a \
+ -H "Content-Type: application/json" \
+ -H "Authorization: Bearer YOUR_KEY" \
+ -d '{"jsonrpc":"2.0","id":"2","method":"tasks/get","params":{"taskId":"TASK_UUID"}}'
+```
+
+### `tasks/cancel` — Cancel a Running Task
+
+```bash
+curl -X POST http://localhost:20128/a2a \
+ -H "Content-Type: application/json" \
+ -H "Authorization: Bearer YOUR_KEY" \
+ -d '{"jsonrpc":"2.0","id":"3","method":"tasks/cancel","params":{"taskId":"TASK_UUID"}}'
+```
+
+---
+
+## Skills Reference
+
+### `smart-routing`
+
+Routes prompts through OmniRoute's intelligent pipeline with full observability.
+
+**Parameters (in `metadata`):**
+
+| Parameter | Type | Default | Description |
+| --------- | -------- | ------------ | ---------------------------------------------------------------------------------------- |
+| `model` | `string` | `"auto"` | Target model (e.g., `claude-sonnet-4`, `gpt-4o`, `auto`) |
+| `combo` | `string` | active combo | Specific combo to route through |
+| `budget` | `number` | none | Maximum cost in USD for this request |
+| `role` | `string` | none | Task role hint: `coding`, `review`, `planning`, `analysis`, `debugging`, `documentation` |
+
+**Returns:**
+
+| Field | Description |
+| ------------------------------ | --------------------------------------------------------- |
+| `artifacts[].content` | The LLM response text |
+| `metadata.routing_explanation` | Human-readable explanation of routing decision |
+| `metadata.cost_envelope` | Estimated vs actual cost with currency |
+| `metadata.resilience_trace` | Array of events (primary_selected, fallback_needed, etc.) |
+| `metadata.policy_verdict` | Whether the request was allowed and why |
+
+### `quota-management`
+
+Answers natural-language queries about provider quotas.
+
+**Query types (inferred from message content):**
+
+| Query Pattern | Response Type |
+| ---------------------------------------------- | -------------------------------------------------------- |
+| Contains `"ranking"`, `"most quota"`, `"best"` | Providers ranked by remaining quota |
+| Contains `"free"`, `"suggest"` | Lists free combos or suggests free-tier providers |
+| Default | Full quota summary with warnings for low-quota providers |
+
+---
+
+## Task Lifecycle
+
+```
+submitted ──→ working ──→ completed
+ ──→ failed
+ ──────────→ cancelled
+```
+
+| State | Description |
+| ----------- | ----------------------------------------------------- |
+| `submitted` | Task created, queued for execution |
+| `working` | Skill handler is executing |
+| `completed` | Execution succeeded, artifacts available |
+| `failed` | Execution failed or task expired (TTL: 5 min default) |
+| `cancelled` | Cancelled by client via `tasks/cancel` |
+
+- Terminal states: `completed`, `failed`, `cancelled` (no further transitions)
+- Expired tasks in `submitted` or `working` are auto-marked as `failed`
+- Tasks are garbage-collected after 2× TTL
+
+---
+
+## Client Examples
+
+### Python — Orchestrator Agent
+
+```python
+"""
+A2A Client — Python example.
+Discovers OmniRoute agent, sends a task, and processes the result.
+"""
+import requests
+import json
+
+BASE_URL = "http://localhost:20128"
+API_KEY = "your-api-key"
+HEADERS = {
+ "Content-Type": "application/json",
+ "Authorization": f"Bearer {API_KEY}",
+}
+
+# 1. Discover agent capabilities
+agent_card = requests.get(f"{BASE_URL}/.well-known/agent.json").json()
+print(f"Agent: {agent_card['name']} v{agent_card['version']}")
+print(f"Skills: {[s['id'] for s in agent_card['skills']]}")
+
+# 2. Send a smart-routing task
+response = requests.post(f"{BASE_URL}/a2a", headers=HEADERS, json={
+ "jsonrpc": "2.0",
+ "id": "task-1",
+ "method": "message/send",
+ "params": {
+ "skill": "smart-routing",
+ "messages": [{"role": "user", "content": "Write a Python quicksort implementation"}],
+ "metadata": {
+ "model": "auto",
+ "combo": "fast-coding",
+ "budget": 0.10,
+ }
+ }
+})
+result = response.json()["result"]
+print(f"\n📝 Response: {result['artifacts'][0]['content'][:200]}...")
+print(f"🔀 Routing: {result['metadata']['routing_explanation']}")
+print(f"💰 Cost: ${result['metadata']['cost_envelope']['actual']}")
+print(f"🛡️ Policy: {result['metadata']['policy_verdict']['reason']}")
+
+# 3. Query quota status
+quota_resp = requests.post(f"{BASE_URL}/a2a", headers=HEADERS, json={
+ "jsonrpc": "2.0",
+ "id": "task-2",
+ "method": "message/send",
+ "params": {
+ "skill": "quota-management",
+ "messages": [{"role": "user", "content": "Which provider has the most quota remaining?"}],
+ }
+})
+quota_result = quota_resp.json()["result"]
+print(f"\n📊 Quota: {quota_result['artifacts'][0]['content']}")
+```
+
+### TypeScript — Multi-Agent Orchestrator
+
+```typescript
+/**
+ * A2A Client — TypeScript example.
+ * Shows agent discovery, task delegation, and streaming.
+ */
+
+const BASE_URL = "http://localhost:20128";
+const API_KEY = "your-api-key";
+
+interface JsonRpcResponse {
+ jsonrpc: "2.0";
+ id: string | number;
+ result?: T;
+ error?: { code: number; message: string };
+}
+
+async function a2aCall(method: string, params: Record): Promise {
+ const resp = await fetch(`${BASE_URL}/a2a`, {
+ method: "POST",
+ headers: {
+ "Content-Type": "application/json",
+ Authorization: `Bearer ${API_KEY}`,
+ },
+ body: JSON.stringify({
+ jsonrpc: "2.0",
+ id: `${method}-${Date.now()}`,
+ method,
+ params,
+ }),
+ });
+ const json: JsonRpcResponse = await resp.json();
+ if (json.error) throw new Error(`[${json.error.code}] ${json.error.message}`);
+ return json.result!;
+}
+
+// ── Agent Discovery ──
+const agentCard = await fetch(`${BASE_URL}/.well-known/agent.json`).then((r) => r.json());
+console.log(`Connected to: ${agentCard.name} (${agentCard.skills.length} skills)`);
+
+// ── Smart Routing: Send a coding task ──
+const routingResult = await a2aCall("message/send", {
+ skill: "smart-routing",
+ messages: [{ role: "user", content: "Implement a Redis cache wrapper in TypeScript" }],
+ metadata: { model: "claude-sonnet-4", role: "coding" },
+});
+console.log("Response:", routingResult.artifacts[0].content);
+console.log("Provider:", routingResult.metadata.routing_explanation);
+
+// ── Quota Management: Find free alternatives ──
+const quotaResult = await a2aCall("message/send", {
+ skill: "quota-management",
+ messages: [{ role: "user", content: "Suggest free combos for documentation" }],
+});
+console.log("Free combos:", quotaResult.artifacts[0].content);
+
+// ── Streaming: Real-time response ──
+const streamResp = await fetch(`${BASE_URL}/a2a`, {
+ method: "POST",
+ headers: {
+ "Content-Type": "application/json",
+ Authorization: `Bearer ${API_KEY}`,
+ },
+ body: JSON.stringify({
+ jsonrpc: "2.0",
+ id: "stream-1",
+ method: "message/stream",
+ params: {
+ skill: "smart-routing",
+ messages: [{ role: "user", content: "Explain microservices architecture" }],
+ },
+ }),
+});
+
+const reader = streamResp.body!.getReader();
+const decoder = new TextDecoder();
+while (true) {
+ const { done, value } = await reader.read();
+ if (done) break;
+ const chunk = decoder.decode(value);
+ for (const line of chunk.split("\n")) {
+ if (line.startsWith("data: ")) {
+ const event = JSON.parse(line.slice(6));
+ if (event.params.chunk) {
+ process.stdout.write(event.params.chunk.content);
+ }
+ if (event.params.task.state === "completed") {
+ console.log("\n✅ Stream completed");
+ }
+ }
+ }
+}
+```
+
+### Python — LangChain A2A Integration
+
+```python
+"""
+LangChain integration — Use OmniRoute A2A as a custom LLM.
+"""
+from langchain.llms.base import BaseLLM
+from langchain.schema import LLMResult, Generation
+import requests
+from typing import List, Optional
+
+class OmniRouteA2A(BaseLLM):
+ base_url: str = "http://localhost:20128"
+ api_key: str = ""
+ model: str = "auto"
+ combo: Optional[str] = None
+
+ @property
+ def _llm_type(self) -> str:
+ return "omniroute-a2a"
+
+ def _call(self, prompt: str, stop: Optional[List[str]] = None, **kwargs) -> str:
+ response = requests.post(
+ f"{self.base_url}/a2a",
+ headers={
+ "Content-Type": "application/json",
+ "Authorization": f"Bearer {self.api_key}",
+ },
+ json={
+ "jsonrpc": "2.0",
+ "id": "langchain-1",
+ "method": "message/send",
+ "params": {
+ "skill": "smart-routing",
+ "messages": [{"role": "user", "content": prompt}],
+ "metadata": {
+ "model": self.model,
+ **({"combo": self.combo} if self.combo else {}),
+ },
+ },
+ },
+ )
+ result = response.json()["result"]
+ return result["artifacts"][0]["content"]
+
+ def _generate(self, prompts: List[str], stop=None, **kwargs) -> LLMResult:
+ return LLMResult(
+ generations=[[Generation(text=self._call(p, stop))] for p in prompts]
+ )
+
+# Usage
+llm = OmniRouteA2A(
+ base_url="http://localhost:20128",
+ api_key="your-key",
+ model="auto",
+ combo="fast-coding",
+)
+result = llm("Write a Python function to merge two sorted lists")
+print(result)
+```
+
+### Go — A2A Client
+
+```go
+package main
+
+import (
+ "bytes"
+ "encoding/json"
+ "fmt"
+ "io"
+ "net/http"
+)
+
+const baseURL = "http://localhost:20128"
+const apiKey = "your-api-key"
+
+type JsonRpcRequest struct {
+ Jsonrpc string `json:"jsonrpc"`
+ ID string `json:"id"`
+ Method string `json:"method"`
+ Params interface{} `json:"params"`
+}
+
+type JsonRpcResponse struct {
+ Jsonrpc string `json:"jsonrpc"`
+ ID string `json:"id"`
+ Result interface{} `json:"result"`
+ Error *struct {
+ Code int `json:"code"`
+ Message string `json:"message"`
+ } `json:"error"`
+}
+
+func a2aCall(method string, params interface{}) (*JsonRpcResponse, error) {
+ body, _ := json.Marshal(JsonRpcRequest{
+ Jsonrpc: "2.0",
+ ID: "go-1",
+ Method: method,
+ Params: params,
+ })
+
+ req, _ := http.NewRequest("POST", baseURL+"/a2a", bytes.NewReader(body))
+ req.Header.Set("Content-Type", "application/json")
+ req.Header.Set("Authorization", "Bearer "+apiKey)
+
+ resp, err := http.DefaultClient.Do(req)
+ if err != nil {
+ return nil, err
+ }
+ defer resp.Body.Close()
+ data, _ := io.ReadAll(resp.Body)
+
+ var result JsonRpcResponse
+ json.Unmarshal(data, &result)
+ return &result, nil
+}
+
+func main() {
+ // Discover agent
+ resp, _ := http.Get(baseURL + "/.well-known/agent.json")
+ defer resp.Body.Close()
+ body, _ := io.ReadAll(resp.Body)
+ fmt.Println("Agent Card:", string(body))
+
+ // Send smart-routing task
+ result, _ := a2aCall("message/send", map[string]interface{}{
+ "skill": "smart-routing",
+ "messages": []map[string]string{{"role": "user", "content": "Hello from Go!"}},
+ "metadata": map[string]interface{}{"model": "auto"},
+ })
+ out, _ := json.MarshalIndent(result.Result, "", " ")
+ fmt.Println("Result:", string(out))
+}
+```
+
+---
+
+## Use Cases
+
+### 🤖 Use Case 1: Multi-Agent Coding Pipeline
+
+An orchestrator agent delegates code generation to OmniRoute, then passes the output to a review agent.
+
+```python
+def coding_pipeline(task: str):
+ # Step 1: Generate code via OmniRoute A2A
+ code_result = a2a_send("smart-routing", [
+ {"role": "user", "content": f"Write production-quality code: {task}"}
+ ], metadata={"model": "auto", "role": "coding"})
+ code = code_result["artifacts"][0]["content"]
+
+ # Step 2: Review the code via OmniRoute A2A (different model)
+ review_result = a2a_send("smart-routing", [
+ {"role": "user", "content": f"Review this code for bugs and improvements:\n\n{code}"}
+ ], metadata={"model": "auto", "role": "review"})
+ review = review_result["artifacts"][0]["content"]
+
+ # Step 3: Check costs
+ print(f"Code cost: ${code_result['metadata']['cost_envelope']['actual']}")
+ print(f"Review cost: ${review_result['metadata']['cost_envelope']['actual']}")
+
+ return {"code": code, "review": review}
+```
+
+### 💡 Use Case 2: Quota-Aware Agent Swarm
+
+Multiple agents share quota through OmniRoute, using the quota skill to coordinate.
+
+```python
+async def quota_aware_agent(agent_name: str, task: str):
+ # Check quota before starting
+ quota = a2a_send("quota-management", [
+ {"role": "user", "content": "Which provider has the most quota remaining?"}
+ ])
+ print(f"[{agent_name}] {quota['artifacts'][0]['content']}")
+
+ # Send request with budget constraint
+ result = a2a_send("smart-routing", [
+ {"role": "user", "content": task}
+ ], metadata={"budget": 0.05})
+
+ policy = result["metadata"]["policy_verdict"]
+ if not policy["allowed"]:
+ print(f"[{agent_name}] ⚠️ Budget exceeded: {policy['reason']}")
+ # Fall back to free combo
+ quota = a2a_send("quota-management", [
+ {"role": "user", "content": "Suggest free combos"}
+ ])
+ print(f"[{agent_name}] Free alternatives: {quota['artifacts'][0]['content']}")
+
+ return result
+```
+
+### 📊 Use Case 3: Real-Time Streaming Dashboard
+
+A monitoring agent streams responses and displays progress in real-time.
+
+```typescript
+async function streamingDashboard(prompt: string) {
+ const response = await fetch(`${BASE_URL}/a2a`, {
+ method: "POST",
+ headers: { "Content-Type": "application/json", Authorization: `Bearer ${API_KEY}` },
+ body: JSON.stringify({
+ jsonrpc: "2.0",
+ id: "dash-1",
+ method: "message/stream",
+ params: { skill: "smart-routing", messages: [{ role: "user", content: prompt }] },
+ }),
+ });
+
+ let totalChunks = 0;
+ const reader = response.body!.getReader();
+ const decoder = new TextDecoder();
+
+ while (true) {
+ const { done, value } = await reader.read();
+ if (done) break;
+
+ for (const line of decoder.decode(value).split("\n")) {
+ if (line.startsWith("data: ")) {
+ const event = JSON.parse(line.slice(6));
+ const state = event.params.task.state;
+
+ if (state === "working" && event.params.chunk) {
+ totalChunks++;
+ process.stdout.write(
+ `\r[Chunk ${totalChunks}] ${event.params.chunk.content.slice(0, 50)}...`
+ );
+ }
+ if (state === "completed") {
+ const meta = event.params.metadata;
+ console.log(
+ `\n✅ Done | Cost: $${meta?.cost_envelope?.actual || 0} | Route: ${meta?.routing_explanation || "N/A"}`
+ );
+ }
+ if (state === "failed") {
+ console.error(`\n❌ Failed: ${event.params.metadata?.error}`);
+ }
+ }
+ }
+ }
+}
+```
+
+### 🔁 Use Case 4: Task Polling Pattern
+
+For long-running tasks, poll the task status instead of waiting synchronously.
+
+```python
+import time
+
+def poll_task(task_id: str, timeout: int = 60):
+ """Poll task status until completion or timeout."""
+ start = time.time()
+ while time.time() - start < timeout:
+ result = requests.post(f"{BASE_URL}/a2a", headers=HEADERS, json={
+ "jsonrpc": "2.0",
+ "id": "poll-1",
+ "method": "tasks/get",
+ "params": {"taskId": task_id},
+ }).json()
+
+ task = result["result"]["task"]
+ state = task["state"]
+ print(f" Task {task_id[:8]}... state={state}")
+
+ if state in ("completed", "failed", "cancelled"):
+ return task
+ time.sleep(2)
+
+ # Timeout — cancel the task
+ requests.post(f"{BASE_URL}/a2a", headers=HEADERS, json={
+ "jsonrpc": "2.0",
+ "id": "cancel-1",
+ "method": "tasks/cancel",
+ "params": {"taskId": task_id},
+ })
+ raise TimeoutError(f"Task {task_id} timed out after {timeout}s")
+```
+
+---
+
+## Error Codes
+
+| Code | Constant | Meaning |
+| ------ | ------------------------ | ---------------------------------------- |
+| -32700 | — | Parse error (invalid JSON) |
+| -32600 | `INVALID_REQUEST` | Invalid JSON-RPC request or unauthorized |
+| -32601 | `METHOD_NOT_FOUND` | Unknown method or skill |
+| -32602 | `INVALID_PARAMS` | Missing or invalid parameters |
+| -32603 | `INTERNAL_ERROR` | Skill execution failed |
+| -32001 | `TASK_NOT_FOUND` | Task ID not found |
+| -32002 | `TASK_ALREADY_COMPLETED` | Cannot modify a completed task |
+| -32003 | `UNAUTHORIZED` | Invalid or missing API key |
+| -32004 | `BUDGET_EXCEEDED` | Request exceeds configured budget |
+| -32005 | `PROVIDER_UNAVAILABLE` | No available providers |
+
+---
+
+## Authentication
+
+All `/a2a` requests require a Bearer token via the `Authorization` header:
+
+```
+Authorization: Bearer YOUR_OMNIROUTE_API_KEY
+```
+
+If no API key is configured on the server (`OMNIROUTE_API_KEY` is empty), authentication is bypassed.
+
+---
+
+## File Structure
+
+```
+src/lib/a2a/
+├── taskManager.ts # Task lifecycle (create/update/cancel/list), TTL, cleanup
+├── taskExecution.ts # Generic task executor with state management
+├── streaming.ts # SSE stream formatting, heartbeat, chunk/completion events
+├── routingLogger.ts # Routing decision logger (stats, history, retention)
+└── skills/
+ ├── smartRouting.ts # Smart routing skill (routes via /v1/chat/completions)
+ └── quotaManagement.ts # Quota management skill (natural-language quota queries)
+
+src/app/a2a/
+└── route.ts # Next.js API route handler (JSON-RPC 2.0 dispatch)
+
+open-sse/mcp-server/
+└── schemas/a2a.ts # Zod schemas (AgentCard, Task, JSON-RPC, SSE events)
+```
+
+---
+
+## Comparison: MCP vs A2A
+
+| Feature | MCP Server | A2A Server |
+| ----------------- | ---------------------------- | ------------------------------------------------- |
+| **Protocol** | Model Context Protocol | Agent-to-Agent Protocol v0.3 |
+| **Transport** | stdio / HTTP | HTTP (JSON-RPC 2.0) |
+| **Discovery** | Tool listing via MCP | `/.well-known/agent.json` |
+| **Granularity** | 16 individual tools | 2 high-level skills |
+| **Best for** | IDE agents (Cursor, VS Code) | Multi-agent systems (LangChain, CrewAI) |
+| **Streaming** | Not supported | SSE via `message/stream` |
+| **Task tracking** | No | Full lifecycle (submitted → completed) |
+| **Observability** | Audit log per tool call | Cost envelope + resilience trace + policy verdict |
+
+---
+
+## Лиценз
+
+Part of [OmniRoute](https://github.com/diegosouzapw/OmniRoute) — MIT License.
diff --git a/docs/i18n/cs/A2A-SERVER.md b/docs/i18n/cs/A2A-SERVER.md
deleted file mode 100644
index eeea4337cc..0000000000
--- a/docs/i18n/cs/A2A-SERVER.md
+++ /dev/null
@@ -1,196 +0,0 @@
-# Dokumentace k serveru OmniRoute A2A
-
-> Protokol Agent-to-Agent v0.3 — OmniRoute jako inteligentní směrovací agent
-
-## Objevování agentů
-
-```bash
-curl http://localhost:20128/.well-known/agent.json
-```
-
-Vrátí kartu agenta popisující schopnosti, dovednosti a požadavky na ověřování OmniRoute.
-
----
-
-## Ověřování
-
-Všechny požadavky `/a2a` vyžadují klíč API zadaný prostřednictvím hlavičky `Authorization` :
-
-```
-Authorization: Bearer YOUR_OMNIROUTE_API_KEY
-```
-
-Pokud na serveru není nakonfigurován žádný klíč API, ověřování se obejde.
-
----
-
-## Metody JSON-RPC 2.0
-
-### `message/send` — synchronní spuštění
-
-Odešle zprávu dovednosti a čeká na úplnou odpověď.
-
-```bash
-curl -X POST http://localhost:20128/a2a \
- -H "Content-Type: application/json" \
- -H "Authorization: Bearer YOUR_KEY" \
- -d '{
- "jsonrpc": "2.0",
- "id": "1",
- "method": "message/send",
- "params": {
- "skill": "smart-routing",
- "messages": [{"role": "user", "content": "Write a hello world in Python"}],
- "metadata": {"model": "auto", "combo": "fast-coding"}
- }
- }'
-```
-
-**Odpověď:**
-
-```json
-{
- "jsonrpc": "2.0",
- "id": "1",
- "result": {
- "task": { "id": "uuid", "state": "completed" },
- "artifacts": [{ "type": "text", "content": "..." }],
- "metadata": {
- "routing_explanation": "Selected claude-sonnet via provider \"anthropic\" (latency: 1200ms, cost: $0.003)",
- "cost_envelope": { "estimated": 0.005, "actual": 0.003, "currency": "USD" },
- "resilience_trace": [
- { "event": "primary_selected", "provider": "anthropic", "timestamp": "..." }
- ],
- "policy_verdict": { "allowed": true, "reason": "within budget and quota limits" }
- }
- }
-}
-```
-
-### `message/stream` — SSE streamování
-
-Stejné jako `message/send` , ale vrací události odeslané serverem pro streamování v reálném čase.
-
-```bash
-curl -N -X POST http://localhost:20128/a2a \
- -H "Content-Type: application/json" \
- -H "Authorization: Bearer YOUR_KEY" \
- -d '{
- "jsonrpc": "2.0",
- "id": "1",
- "method": "message/stream",
- "params": {
- "skill": "smart-routing",
- "messages": [{"role": "user", "content": "Explain quantum computing"}]
- }
- }'
-```
-
-**Události SSE:**
-
-```
-data: {"jsonrpc":"2.0","method":"message/stream","params":{"task":{"id":"...","state":"working"},"chunk":{"type":"text","content":"..."}}}
-
-: heartbeat 2026-03-03T17:00:00Z
-
-data: {"jsonrpc":"2.0","method":"message/stream","params":{"task":{"id":"...","state":"completed"},"metadata":{...}}}
-```
-
-### `tasks/get` — Dotaz na stav úlohy
-
-```bash
-curl -X POST http://localhost:20128/a2a \
- -H "Content-Type: application/json" \
- -H "Authorization: Bearer YOUR_KEY" \
- -d '{"jsonrpc":"2.0","id":"2","method":"tasks/get","params":{"taskId":"TASK_UUID"}}'
-```
-
-### `tasks/cancel` — Zrušit úkol
-
-```bash
-curl -X POST http://localhost:20128/a2a \
- -H "Content-Type: application/json" \
- -H "Authorization: Bearer YOUR_KEY" \
- -d '{"jsonrpc":"2.0","id":"3","method":"tasks/cancel","params":{"taskId":"TASK_UUID"}}'
-```
-
----
-
-## Dostupné dovednosti
-
-Dovednost | Popis
-:-- | :--
-`smart-routing` | Směruje výzvy prostřednictvím inteligentního kanálu OmniRoute. Vrací odpověď s vysvětlením směrování, náklady a trasou odolnosti.
-`quota-management` | Odpovídá na dotazy v přirozeném jazyce týkající se kvót poskytovatelů, navrhuje bezplatné kombinace a poskytuje hodnocení kvót.
-
----
-
-## Životní cyklus úkolu
-
-```
-submitted → working → completed
- → failed
- → cancelled
-```
-
-- Úkoly vyprší po 5 minutách (konfigurovatelné)
-- Stavy terminálu: `completed` , `failed` , `cancelled`
-- Záznam událostí sleduje každý přechod stavu
-
----
-
-## Chybové kódy
-
-Kód | Význam
-:-- | :--
--32700 | Chyba při analýze (neplatný JSON)
--32600 | Neplatný požadavek / Neautorizovaný
--32601 | Metoda nebo dovednost nenalezena
--32602 | Neplatné parametry
--32603 | Interní chyba
-
----
-
-## Příklady integrace
-
-### Python (požadavky)
-
-```python
-import requests
-
-resp = requests.post("http://localhost:20128/a2a", json={
- "jsonrpc": "2.0", "id": "1",
- "method": "message/send",
- "params": {
- "skill": "smart-routing",
- "messages": [{"role": "user", "content": "Hello"}]
- }
-}, headers={"Authorization": "Bearer YOUR_KEY"})
-
-result = resp.json()["result"]
-print(result["artifacts"][0]["content"])
-print(result["metadata"]["routing_explanation"])
-```
-
-### TypeScript (načtení)
-
-```typescript
-const resp = await fetch("http://localhost:20128/a2a", {
- method: "POST",
- headers: {
- "Content-Type": "application/json",
- Authorization: "Bearer YOUR_KEY",
- },
- body: JSON.stringify({
- jsonrpc: "2.0",
- id: "1",
- method: "message/send",
- params: {
- skill: "smart-routing",
- messages: [{ role: "user", content: "Hello" }],
- },
- }),
-});
-const { result } = await resp.json();
-console.log(result.metadata.routing_explanation);
-```
diff --git a/docs/i18n/cs/API_REFERENCE.md b/docs/i18n/cs/API_REFERENCE.md
deleted file mode 100644
index faa9628318..0000000000
--- a/docs/i18n/cs/API_REFERENCE.md
+++ /dev/null
@@ -1,453 +0,0 @@
-# Referenční informace k API
-
-🌐 **Jazyky:** 🇺🇸 [angličtina](API_REFERENCE.md) | 🇧🇷 [Português (Brazílie)](i18n/pt-BR/API_REFERENCE.md) | 🇪🇸 [Español](i18n/es/API_REFERENCE.md) | 🇫🇷 [Français](i18n/fr/API_REFERENCE.md) | 🇮🇹 [Italiano](i18n/it/API_REFERENCE.md) | 🇷🇺 [Русский](i18n/ru/API_REFERENCE.md) | 🇨🇳[中文 (简体)](i18n/zh-CN/API_REFERENCE.md) | 🇩🇪 [Deutsch](i18n/de/API_REFERENCE.md) | 🇮🇳 [हिन्दी](i18n/in/API_REFERENCE.md) | 🇹🇭 [ไทย](i18n/th/API_REFERENCE.md) | 🇺🇦 [Українська](i18n/uk-UA/API_REFERENCE.md) | 🇸🇦 [العربية](i18n/ar/API_REFERENCE.md) | 🇯🇵[日本語](i18n/ja/API_REFERENCE.md)| 🇻🇳 [Tiếng Việt](i18n/vi/API_REFERENCE.md) | 🇧🇬 [Български](i18n/bg/API_REFERENCE.md) | 🇩🇰 [Dánsko](i18n/da/API_REFERENCE.md) | 🇫🇮 [Suomi](i18n/fi/API_REFERENCE.md) | 🇮🇱 [עברית](i18n/he/API_REFERENCE.md) | 🇭🇺 [maďarština](i18n/hu/API_REFERENCE.md) | 🇮🇩 [Bahasa Indonésie](i18n/id/API_REFERENCE.md) | 🇰🇷 [한국어](i18n/ko/API_REFERENCE.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/API_REFERENCE.md) | 🇳🇱 [Nizozemsko](i18n/nl/API_REFERENCE.md) | 🇳🇴 [Norsk](i18n/no/API_REFERENCE.md) | 🇵🇹 [Português (Portugalsko)](i18n/pt/API_REFERENCE.md) | 🇷🇴 [Română](i18n/ro/API_REFERENCE.md) | 🇵🇱 [Polski](i18n/pl/API_REFERENCE.md) | 🇸🇰 [Slovenčina](i18n/sk/API_REFERENCE.md) | 🇸🇪 [Svenska](i18n/sv/API_REFERENCE.md) | 🇵🇭 [Filipínec](i18n/phi/API_REFERENCE.md) | 🇨🇿 [Čeština](i18n/cs/API_REFERENCE.md)
-
-Kompletní referenční příručka pro všechny koncové body rozhraní OmniRoute API.
-
----
-
-## Obsah
-
-- [Dokončení chatu](#chat-completions)
-- [Vložení](#embeddings)
-- [Generování obrázků](#image-generation)
-- [Seznam modelů](#list-models)
-- [Koncové body kompatibility](#compatibility-endpoints)
-- [Sémantická mezipaměť](#semantic-cache)
-- [Řídicí panel a správa](#dashboard--management)
-- [Zpracování žádosti](#request-processing)
-- [Ověřování](#authentication)
-
----
-
-## Dokončení chatu
-
-```bash
-POST /v1/chat/completions
-Authorization: Bearer your-api-key
-Content-Type: application/json
-
-{
- "model": "cc/claude-opus-4-6",
- "messages": [
- {"role": "user", "content": "Write a function to..."}
- ],
- "stream": true
-}
-```
-
-### Vlastní záhlaví
-
-| Záhlaví | Směr | Popis |
-| ------------------------ | ------- | ------------------------------------------------- |
-| `X-OmniRoute-No-Cache` | Žádost | Nastavením na `true` se vynechá mezipaměť |
-| `X-OmniRoute-Progress` | Žádost | Nastaveno na `true` pro události průběhu |
-| `Idempotency-Key` | Žádost | Klíč pro deduplikaci (okno 5 s) |
-| `X-Request-Id` | Žádost | Alternativní klíč pro odstranění duplicitních dat |
-| `X-OmniRoute-Cache` | Odpověď | `HIT` or `MISS` (nestreamované) |
-| `X-OmniRoute-Idempotent` | Odpověď | `true` , pokud je odstraněna duplikace |
-| `X-OmniRoute-Progress` | Odpověď | `enabled` pokud je zapnuto sledování průběhu |
-
-> Poznámka Nginx: pokud spoléháte na hlavičky s podtržítkem (například `x_session_id`), povolte `underscores_in_headers on;`.
-
----
-
-## Vložení
-
-```bash
-POST /v1/embeddings
-Authorization: Bearer your-api-key
-Content-Type: application/json
-
-{
- "model": "nebius/Qwen/Qwen3-Embedding-8B",
- "input": "The food was delicious"
-}
-```
-
-Dostupní poskytovatelé: Nebius, OpenAI, Mistral, Together AI, Fireworks, NVIDIA.
-
-```bash
-# List all embedding models
-GET /v1/embeddings
-```
-
----
-
-## Generování obrázků
-
-```bash
-POST /v1/images/generations
-Authorization: Bearer your-api-key
-Content-Type: application/json
-
-{
- "model": "openai/dall-e-3",
- "prompt": "A beautiful sunset over mountains",
- "size": "1024x1024"
-}
-```
-
-Dostupní poskytovatelé: OpenAI (DALL-E), xAI (Grok Image), Together AI (FLUX), Fireworks AI.
-
-```bash
-# List all image models
-GET /v1/images/generations
-```
-
----
-
-## Seznam modelů
-
-```bash
-GET /v1/models
-Authorization: Bearer your-api-key
-
-→ Returns all chat, embedding, and image models + combos in OpenAI format
-```
-
----
-
-## Koncové body kompatibility
-
-| Metoda | Cesta | Formát |
-| ------ | --------------------------- | --------------------- |
-| POST | `/v1/chat/completions` | OpenAI |
-| POST | `/v1/messages` | Anthropic |
-| POST | `/v1/responses` | Reakce OpenAI |
-| POST | `/v1/embeddings` | OpenAI |
-| POST | `/v1/images/generations` | OpenAI |
-| GET | `/v1/models` | OpenAI |
-| POST | `/v1/messages/count_tokens` | Anthropic |
-| GET | `/v1beta/models` | Blíženci |
-| POST | `/v1beta/models/{...path}` | Gemini generuje obsah |
-| POST | `/v1/api/chat` | Ollama |
-
-### Vyhrazené trasy poskytovatelů
-
-```bash
-POST /v1/providers/{provider}/chat/completions
-POST /v1/providers/{provider}/embeddings
-POST /v1/providers/{provider}/images/generations
-```
-
-Pokud chybí prefix poskytovatele, automaticky se přidá. Neshodné modely vrátí chybu `400` .
-
----
-
-## Sémantická mezipaměť
-
-```bash
-# Get cache stats
-GET /api/cache
-
-# Clear all caches
-DELETE /api/cache
-```
-
-Příklad odpovědi:
-
-```json
-{
- "semanticCache": {
- "memorySize": 42,
- "memoryMaxSize": 500,
- "dbSize": 128,
- "hitRate": 0.65
- },
- "idempotency": {
- "activeKeys": 3,
- "windowMs": 5000
- }
-}
-```
-
----
-
-## Řídicí panel a správa
-
-### Ověřování
-
-| Koncový bod | Metoda | Popis |
-| ----------------------------- | ------- | ------------------------------- |
-| `/api/auth/login` | POST | Přihlášení |
-| `/api/auth/logout` | POST | Odhlásit se |
-| `/api/settings/require-login` | GET/PUT | Vyžaduje se přepnutí přihlášení |
-
-### Správa poskytovatelů
-
-| Koncový bod | Metoda | Popis |
-| ---------------------------- | --------------- | --------------------------------- |
-| `/api/providers` | GET/POST | Seznam / vytvoření poskytovatelů |
-| `/api/providers/[id]` | GET/PUT/DELETE | Správa poskytovatele |
-| `/api/providers/[id]/test` | POST | Testovací připojení poskytovatele |
-| `/api/providers/[id]/models` | GET | Seznam modelů poskytovatelů |
-| `/api/providers/validate` | POST | Ověření konfigurace poskytovatele |
-| `/api/provider-nodes*` | Různé | Správa uzlů poskytovatelů |
-| `/api/provider-models` | GET/POST/DELETE | Vlastní modely |
-
-### Toky OAuth
-
-| Koncový bod | Metoda | Popis |
-| -------------------------------- | ------ | ---------------------------------- |
-| `/api/oauth/[provider]/[action]` | Různé | OAuth specifický pro poskytovatele |
-
-### Směrování a konfigurace
-
-| Koncový bod | Metoda | Popis |
-| --------------------- | -------- | ----------------------------------------- |
-| `/api/models/alias` | GET/POST | Aliasy modelů |
-| `/api/models/catalog` | GET | Všechny modely podle poskytovatele + typu |
-| `/api/combos*` | Různé | Správa kombinací |
-| `/api/keys*` | Různé | Správa klíčů API |
-| `/api/pricing` | GET | Cena modelu |
-
-### Využití a analýzy
-
-| Koncový bod | Metoda | Popis |
-| --------------------------- | ------ | ----------------------------- |
-| `/api/usage/history` | GET | Historie používání |
-| `/api/usage/logs` | GET | Protokoly používání |
-| `/api/usage/request-logs` | GET | Protokoly na úrovni požadavků |
-| `/api/usage/[connectionId]` | GET | Využití na připojení |
-
-### Nastavení
-
-| Koncový bod | Metoda | Popis |
-| ------------------------------- | ------- | -------------------------------------- |
-| `/api/settings` | GET/PUT | Obecná nastavení |
-| `/api/settings/proxy` | GET/PUT | Konfigurace síťového proxy serveru |
-| `/api/settings/proxy/test` | POST | Testovací připojení k proxy serveru |
-| `/api/settings/ip-filter` | GET/PUT | Seznam povolených/blokovaných IP adres |
-| `/api/settings/thinking-budget` | GET/PUT | Zdůvodnění rozpočtu tokenů |
-| `/api/settings/system-prompt` | GET/PUT | Globální systémový výzva |
-
-### Monitorování
-
-| Koncový bod | Metoda | Popis |
-| ------------------------ | ---------- | ------------------------------- |
-| `/api/sessions` | GET | Sledování aktivních relací |
-| `/api/rate-limits` | GET | Limity sazeb na účet |
-| `/api/monitoring/health` | GET | Kontrola stavu |
-| `/api/cache` | GET/DELETE | Statistiky mezipaměti / vymazat |
-
-### Zálohování a export/import
-
-| Koncový bod | Metoda | Popis |
-| --------------------------- | ------ | ---------------------------------------------- |
-| `/api/db-backups` | GET | Seznam dostupných záloh |
-| `/api/db-backups` | DÁT | Vytvořte ruční zálohu |
-| `/api/db-backups` | POST | Obnovení z konkrétní zálohy |
-| `/api/db-backups/export` | GET | Stáhnout databázi jako soubor .sqlite |
-| `/api/db-backups/import` | POST | Nahrajte soubor .sqlite pro nahrazení databáze |
-| `/api/db-backups/exportAll` | GET | Stáhnout plnou zálohu jako archiv .tar.gz |
-
-### Synchronizace s cloudem
-
-| Koncový bod | Metoda | Popis |
-| ---------------------- | ------ | ------------------------------- |
-| `/api/sync/cloud` | Různé | Operace synchronizace s cloudem |
-| `/api/sync/initialize` | POST | Inicializovat synchronizaci |
-| `/api/cloud/*` | Různé | Správa cloudu |
-
-### Nástroje CLI
-
-| Koncový bod | Metoda | Popis |
-| ---------------------------------- | ------ | ---------------------------------------- |
-| `/api/cli-tools/claude-settings` | GET | Stav Clauda CLI |
-| `/api/cli-tools/codex-settings` | GET | Stav příkazového řádku Codexu |
-| `/api/cli-tools/droid-settings` | GET | Stav příkazového řádku Droidu |
-| `/api/cli-tools/openclaw-settings` | GET | Stav rozhraní příkazového řádku OpenClaw |
-| `/api/cli-tools/runtime/[toolId]` | GET | Generické běhové prostředí CLI |
-
-Mezi odpovědi CLI patří: `installed` , `runnable` , `command` , `commandPath` , `runtimeMode` , `reason` .
-
-### Agenti ACP
-
-| Koncový bod | Metoda | Popis |
-| ----------------- | ------- | ----------------------------------------------------------------------------- |
-| `/api/acp/agents` | GET | Zobrazit seznam všech detekovaných agentů (vestavěných + vlastních) se stavem |
-| `/api/acp/agents` | POST | Přidat vlastního agenta nebo obnovit mezipaměť detekce |
-| `/api/acp/agents` | VYMAZAT | Odebrání vlastního agenta podle parametru dotazu `id` |
-
-Odpověď GET obsahuje `agents[]` (id, name, binary, version, installed, protocol, isCustom) a `summary` (total, installed, notFound, builtIn, custom).
-
-### Odolnost a limity rychlosti
-
-| Koncový bod | Metoda | Popis |
-| ----------------------- | ------- | --------------------------------------- |
-| `/api/resilience` | GET/PUT | Získání/aktualizace profilů odolnosti |
-| `/api/resilience/reset` | POST | Resetujte jističe |
-| `/api/rate-limits` | GET | Stav limitu sazby na účet |
-| `/api/rate-limit` | GET | Konfigurace globálního limitu rychlosti |
-
-### Evals
-
-| Koncový bod | Metoda | Popis |
-| ------------ | -------- | -------------------------------------- |
-| `/api/evals` | GET/POST | Vypsat eval sady / spustit vyhodnocení |
-
-### Zásady
-
-| Koncový bod | Metoda | Popis |
-| --------------- | --------------- | ------------------------ |
-| `/api/policies` | GET/POST/DELETE | Správa směrovacích zásad |
-
-### Dodržování
-
-| Koncový bod | Metoda | Popis |
-| --------------------------- | ------ | ---------------------------------- |
-| `/api/compliance/audit-log` | GET | Protokol auditu shody (poslední N) |
-
-### v1beta (kompatibilní s Gemini)
-
-| Koncový bod | Metoda | Popis |
-| -------------------------- | ------ | ------------------------------------ |
-| `/v1beta/models` | GET | Seznam modelů ve formátu Gemini |
-| `/v1beta/models/{...path}` | POST | Koncový bod Gemini `generateContent` |
-
-Tyto koncové body zrcadlí formát API Gemini pro klienty, kteří očekávají nativní kompatibilitu sady Gemini SDK.
-
-### Interní / systémová API
-
-| Koncový bod | Metoda | Popis |
-| --------------- | ------ | --------------------------------------------------------------- |
-| `/api/init` | GET | Kontrola inicializace aplikace (používá se při prvním spuštění) |
-| `/api/tags` | GET | Tagy modelů kompatibilní s Ollamou (pro klienty Ollamy) |
-| `/api/restart` | POST | Spustit řádný restart serveru |
-| `/api/shutdown` | POST | Spustit řádné vypnutí serveru |
-
-> **Poznámka:** Tyto koncové body používá interně systém nebo pro kompatibilitu s klienty Ollama. Koncoví uživatelé je obvykle nevolají.
-
----
-
-## Přepis zvuku
-
-```bash
-POST /v1/audio/transcriptions
-Authorization: Bearer your-api-key
-Content-Type: multipart/form-data
-```
-
-Přepisujte zvukové soubory pomocí Deepgramu nebo AssemblyAI.
-
-**Žádost:**
-
-```bash
-curl -X POST http://localhost:20128/v1/audio/transcriptions \
- -H "Authorization: Bearer your-api-key" \
- -F "file=@recording.mp3" \
- -F "model=deepgram/nova-3"
-```
-
-**Odpověď:**
-
-```json
-{
- "text": "Hello, this is the transcribed audio content.",
- "task": "transcribe",
- "language": "en",
- "duration": 12.5
-}
-```
-
-**Podporovaní poskytovatelé:** `deepgram/nova-3` , `assemblyai/best` .
-
-**Podporované formáty:** `mp3` , `wav` , `m4a` , `flac` , `ogg` , `webm` .
-
----
-
-## Kompatibilita s Ollamou
-
-Pro klienty, kteří používají formát API od Ollamy:
-
-```bash
-# Chat endpoint (Ollama format)
-POST /v1/api/chat
-
-# Model listing (Ollama format)
-GET /api/tags
-```
-
-Požadavky jsou automaticky překládány mezi formátem Ollama a interním formátem.
-
----
-
-## Telemetrie
-
-```bash
-# Get latency telemetry summary (p50/p95/p99 per provider)
-GET /api/telemetry/summary
-```
-
-**Odpověď:**
-
-```json
-{
- "providers": {
- "claudeCode": { "p50": 245, "p95": 890, "p99": 1200, "count": 150 },
- "github": { "p50": 180, "p95": 620, "p99": 950, "count": 320 }
- }
-}
-```
-
----
-
-## Rozpočet
-
-```bash
-# Get budget status for all API keys
-GET /api/usage/budget
-
-# Set or update a budget
-POST /api/usage/budget
-Content-Type: application/json
-
-{
- "keyId": "key-123",
- "limit": 50.00,
- "period": "monthly"
-}
-```
-
----
-
-## Dostupnost modelu
-
-```bash
-# Get real-time model availability across all providers
-GET /api/models/availability
-
-# Check availability for a specific model
-POST /api/models/availability
-Content-Type: application/json
-
-{
- "model": "claude-sonnet-4-5-20250929"
-}
-```
-
----
-
-## Zpracování žádosti
-
-1. Klient odesílá požadavek na `/v1/*`
-2. Obslužná rutina trasy volá `handleChat` , `handleEmbedding` , `handleAudioTranscription` nebo `handleImageGeneration`
-3. Model je vyřešen (přímý poskytovatel/model nebo alias/kombinace)
-4. Přihlašovací údaje vybrané z lokální databáze s filtrováním dostupnosti účtů
-5. Pro chat: `handleChatCore` — detekce formátu, překlad, kontrola mezipaměti, kontrola idempotence
-6. Prováděcí program poskytovatele odesílá požadavek nadřazenému serveru
-7. Odpověď přeložena zpět do klientského formátu (chat) nebo vrácena tak, jak je (vložené prvky/obrázky/zvuk)
-8. Zaznamenáno použití/protokolování
-9. Záložní metoda se použije na chyby podle pravidel kombinace.
-
-Úplný referenční popis architektury: [`ARCHITECTURE.md`](ARCHITECTURE.md)
-
----
-
-## Ověřování
-
-- Trasy dashboardu ( `/dashboard/*` ) používají soubor cookie `auth_token`
-- Přihlášení používá uložený hash hesla; záložní nastavení je `INITIAL_PASSWORD`
-- `requireLogin` lze přepínat přes `/api/settings/require-login`
-- Trasy `/v1/*` volitelně vyžadují klíč API nosiče, pokud `REQUIRE_API_KEY=true`
diff --git a/docs/i18n/cs/ARCHITECTURE.md b/docs/i18n/cs/ARCHITECTURE.md
deleted file mode 100644
index 3b2153f2cd..0000000000
--- a/docs/i18n/cs/ARCHITECTURE.md
+++ /dev/null
@@ -1,782 +0,0 @@
-# Architektura OmniRoute
-
-🌐 **Jazyky:** 🇺🇸 [angličtina](ARCHITECTURE.md) | 🇧🇷 [Português (Brazílie)](i18n/pt-BR/ARCHITECTURE.md) | 🇪🇸 [Español](i18n/es/ARCHITECTURE.md) | 🇫🇷 [Français](i18n/fr/ARCHITECTURE.md) | 🇮🇹 [Italiano](i18n/it/ARCHITECTURE.md) | 🇷🇺 [Русский](i18n/ru/ARCHITECTURE.md) | 🇨🇳[中文 (简体)](i18n/zh-CN/ARCHITECTURE.md) | 🇩🇪 [Deutsch](i18n/de/ARCHITECTURE.md) | 🇮🇳 [हिन्दी](i18n/in/ARCHITECTURE.md) | 🇹🇭 [ไทย](i18n/th/ARCHITECTURE.md) | 🇺🇦 [Українська](i18n/uk-UA/ARCHITECTURE.md) | 🇸🇦 [العربية](i18n/ar/ARCHITECTURE.md) | 🇯🇵[日本語](i18n/ja/ARCHITECTURE.md)| 🇻🇳 [Tiếng Việt](i18n/vi/ARCHITECTURE.md) | 🇧🇬 [Български](i18n/bg/ARCHITECTURE.md) | 🇩🇰 [Dánsko](i18n/da/ARCHITECTURE.md) | 🇫🇮 [Suomi](i18n/fi/ARCHITECTURE.md) | 🇮🇱 [עברית](i18n/he/ARCHITECTURE.md) | 🇭🇺 [maďarština](i18n/hu/ARCHITECTURE.md) | 🇮🇩 [Bahasa Indonésie](i18n/id/ARCHITECTURE.md) | 🇰🇷 [한국어](i18n/ko/ARCHITECTURE.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/ARCHITECTURE.md) | 🇳🇱 [Nizozemsko](i18n/nl/ARCHITECTURE.md) | 🇳🇴 [Norsk](i18n/no/ARCHITECTURE.md) | 🇵🇹 [Português (Portugalsko)](i18n/pt/ARCHITECTURE.md) | 🇷🇴 [Română](i18n/ro/ARCHITECTURE.md) | 🇵🇱 [Polski](i18n/pl/ARCHITECTURE.md) | 🇸🇰 [Slovenčina](i18n/sk/ARCHITECTURE.md) | 🇸🇪 [Svenska](i18n/sv/ARCHITECTURE.md) | 🇵🇭 [Filipínec](i18n/phi/ARCHITECTURE.md) | 🇨🇿 [Čeština](i18n/cs/ARCHITECTURE.md)
-
-_Poslední aktualizace: 2026-03-04_
-
-## Shrnutí pro manažery
-
-OmniRoute je lokální směrovací brána a dashboard s umělou inteligencí postavený na Next.js. Poskytuje jeden koncový bod kompatibilní s OpenAI ( `/v1/*` ) a směruje provoz napříč několika upstreamovými poskytovateli s překladem, záložními funkcemi, obnovou tokenů a sledováním využití.
-
-Základní schopnosti:
-
-- API prostředí kompatibilní s OpenAI pro CLI/nástroje (28 poskytovatelů)
-- Překlad požadavků/odpovědí napříč formáty poskytovatelů
-- Záložní kombinace modelů (sekvence s více modely)
-- Záložní řešení na úrovni účtu (více účtů na poskytovatele)
-- Správa připojení poskytovatele OAuth + API klíčů
-- Generování embeddingů pomocí `/v1/embeddings` (6 poskytovatelů, 9 modelů)
-- Generování obrázků pomocí `/v1/images/generations` (4 poskytovatelé, 9 modelů)
-- Pro modely uvažování zvažte analýzu tagů ( `...` ).
-- Sanitizace odpovědí pro striktní kompatibilitu s OpenAI SDK
-- Normalizace rolí (vývojář→systém, systém→uživatel) pro kompatibilitu mezi poskytovateli
-- Konverze strukturovaného výstupu (json_schema → Gemini responseSchema)
-- Lokální perzistence pro poskytovatele, klíče, aliasy, kombinace, nastavení, ceny
-- Sledování využití/nákladů a protokolování požadavků
-- Volitelná cloudová synchronizace pro synchronizaci více zařízení/stavů
-- Seznam povolených/blokovaných IP adres pro řízení přístupu k API
-- Řízení rozpočtu (průchozí/automatické/vlastní/adaptivní)
-- Globální systémová výzva k vložení
-- Sledování relací a otisky prstů
-- Vylepšené omezení sazeb pro jednotlivé účty s profily specifickými pro poskytovatele
-- Vzor jističů pro odolnost poskytovatele
-- Ochrana stáda proti hromům s uzamčením mutexů
-- Mezipaměť pro deduplikaci požadavků založená na podpisech
-- Vrstva domény: dostupnost modelu, pravidla nákladů, záložní politika, politika blokování
-- Perzistence stavu domény (mezipaměť SQLite pro zápis pro záložní funkce, rozpočty, uzamčení, jističe)
-- Modul zásad pro centralizované vyhodnocování požadavků (uzamčení → rozpočet → záložní)
-- Vyžádat telemetrii s agregací latence p50/p95/p99
-- Korelační ID (X-Request-Id) pro trasování typu end-to-end
-- Protokolování auditu shody s předpisy s možností odhlášení pro každý klíč API
-- Evaluační rámec pro zajištění kvality LLM
-- Řídicí panel uživatelského rozhraní Resilience se stavem jističe v reálném čase
-- Modulární poskytovatelé OAuth (12 jednotlivých modulů v adresáři `src/lib/oauth/providers/` )
-
-Primární běhový model:
-
-- Trasy aplikace Next.js v `src/app/api/*` implementují jak API dashboardů, tak i API kompatibility.
-- Sdílené jádro SSE/routing v `src/sse/*` + `open-sse/*` zvládá spouštění poskytovatelů, překlad, streamování, záložní operace a využití.
-
-## Rozsah a hranice
-
-### V rozsahu
-
-- Běhové prostředí lokální brány
-- Rozhraní API pro správu řídicích panelů
-- Ověřování poskytovatele a aktualizace tokenu
-- Žádost o překlad a streamování SSE
-- Lokální stav + perzistence využití
-- Volitelná orchestrace synchronizace s cloudem
-
-### Mimo rozsah
-
-- Implementace cloudové služby za `NEXT_PUBLIC_CLOUD_URL`
-- SLA/řídicí rovina poskytovatele mimo lokální proces
-- Samotné externí binární soubory CLI (Claude CLI, Codex CLI atd.)
-
-## Kontext systému na vysoké úrovni
-
-```mermaid
-flowchart LR
- subgraph Clients[Developer Clients]
- C1[Claude Code]
- C2[Codex CLI]
- C3[OpenClaw / Droid / Cline / Continue / Roo]
- C4[Custom OpenAI-compatible clients]
- BROWSER[Browser Dashboard]
- end
-
- subgraph Router[OmniRoute Local Process]
- API[V1 Compatibility API\n/v1/*]
- DASH[Dashboard + Management API\n/api/*]
- CORE[SSE + Translation Core\nopen-sse + src/sse]
- DB[(storage.sqlite)]
- UDB[(usage tables + log artifacts)]
- end
-
- subgraph Upstreams[Upstream Providers]
- P1[OAuth Providers\nClaude/Codex/Gemini/Qwen/Qoder/GitHub/Kiro/Cursor/Antigravity]
- P2[API Key Providers\nOpenAI/Anthropic/OpenRouter/GLM/Kimi/MiniMax\nDeepSeek/Groq/xAI/Mistral/Perplexity\nTogether/Fireworks/Cerebras/Cohere/NVIDIA]
- P3[Compatible Nodes\nOpenAI-compatible / Anthropic-compatible]
- end
-
- subgraph Cloud[Optional Cloud Sync]
- CLOUD[Cloud Sync Endpoint\nNEXT_PUBLIC_CLOUD_URL]
- end
-
- C1 --> API
- C2 --> API
- C3 --> API
- C4 --> API
- BROWSER --> DASH
-
- API --> CORE
- DASH --> DB
- CORE --> DB
- CORE --> UDB
-
- CORE --> P1
- CORE --> P2
- CORE --> P3
-
- DASH --> CLOUD
-```
-
-## Základní běhové komponenty
-
-## 1) API a směrovací vrstva (trasy aplikací Next.js)
-
-Hlavní adresáře:
-
-- `src/app/api/v1/*` a `src/app/api/v1beta/*` pro rozhraní API pro zajištění kompatibility
-- `src/app/api/*` pro API pro správu/konfiguraci
-- Další přepisy v `next.config.mjs` mapují `/v1/*` na `/api/v1/*`
-
-Důležité způsoby kompatibility:
-
-- `src/app/api/v1/chat/completions/route.ts`
-- `src/app/api/v1/messages/route.ts`
-- `src/app/api/v1/responses/route.ts`
-- `src/app/api/v1/models/route.ts` — obsahuje vlastní modely s `custom: true`
-- `src/app/api/v1/embeddings/route.ts` — generování embeddingů (6 poskytovatelů)
-- `src/app/api/v1/images/generations/route.ts` — generování obrázků (4+ poskytovatelů včetně Antigravity/Nebius)
-- `src/app/api/v1/messages/count_tokens/route.ts`
-- `src/app/api/v1/providers/[provider]/chat/completions/route.ts` — vyhrazený chat pro jednotlivé poskytovatele
-- `src/app/api/v1/providers/[provider]/embeddings/route.ts` — vyhrazená vkládání pro jednotlivé poskytovatele
-- `src/app/api/v1/providers/[provider]/images/generations/route.ts` — vyhrazené obrazy pro jednotlivé poskytovatele
-- `src/app/api/v1beta/models/route.ts`
-- `src/app/api/v1beta/models/[...path]/route.ts`
-
-Domény správy:
-
-- Auth/settings: `src/app/api/auth/*` , `src/app/api/settings/*`
-- Poskytovatelé/připojení: `src/app/api/providers*`
-- Uzly poskytovatele: `src/app/api/provider-nodes*`
-- Vlastní modely: `src/app/api/provider-models` (GET/POST/DELETE)
-- Katalog modelů: `src/app/api/models/route.ts` (GET)
-- Konfigurace proxy: `src/app/api/settings/proxy` (GET/PUT/DELETE) + `src/app/api/settings/proxy/test` (POST)
-- OAuth: `src/app/api/oauth/*`
-- Klíče/aliasy/kombinace/ceny: `src/app/api/keys*` , `src/app/api/models/alias` , `src/app/api/combos*` , `src/app/api/pricing`
-- Použití: `src/app/api/usage/*`
-- Synchronizace/cloud: `src/app/api/sync/*` , `src/app/api/cloud/*`
-- Pomocné nástroje pro CLI: `src/app/api/cli-tools/*`
-- IP filtr: `src/app/api/settings/ip-filter` (GET/PUT)
-- Rozpočet pro myšlení: `src/app/api/settings/thinking-budget` (GET/PUT)
-- Systémový příkaz: `src/app/api/settings/system-prompt` (GET/PUT)
-- Relace: `src/app/api/sessions` (GET)
-- Limity rychlosti: `src/app/api/rate-limits` (GET)
-- Odolnost: `src/app/api/resilience` (GET/PATCH) — profily poskytovatelů, jistič, stav limitu rychlosti
-- Reset odolnosti: `src/app/api/resilience/reset` (POST) — reset jističů + doby zchlazení
-- Statistiky mezipaměti: `src/app/api/cache/stats` (GET/DELETE)
-- Dostupnost modelu: `src/app/api/models/availability` (GET/POST)
-- Telemetrie: `src/app/api/telemetry/summary` (GET)
-- Rozpočet: `src/app/api/usage/budget` (GET/POST)
-- Záložní řetězce: `src/app/api/fallback/chains` (GET/POST/DELETE)
-- Audit shody: `src/app/api/compliance/audit-log` (GET)
-- Evals: `src/app/api/evals` (GET/POST), `src/app/api/evals/[suiteId]` (GET)
-- Zásady: `src/app/api/policies` (GET/POST)
-
-## 2) SSE + Překladatelské jádro
-
-Hlavní moduly toku:
-
-- Záznam: `src/sse/handlers/chat.ts`
-- Orchestrace jádra: `open-sse/handlers/chatCore.ts`
-- Adaptéry pro spuštění poskytovatelů: `open-sse/executors/*`
-- Detekce formátu/konfigurace poskytovatele: `open-sse/services/provider.ts`
-- Analýza/řešení modelu: `src/sse/services/model.ts` , `open-sse/services/model.ts`
-- Logika záložního účtu: `open-sse/services/accountFallback.ts`
-- Registr překladů: `open-sse/translator/index.ts`
-- Transformace streamů: `open-sse/utils/stream.ts` , `open-sse/utils/streamHandler.ts`
-- Extrakce/normalizace využití: `open-sse/utils/usageTracking.ts`
-- Analyzátor tagů Think: `open-sse/utils/thinkTagParser.ts`
-- Obslužná rutina pro vkládání: `open-sse/handlers/embeddings.ts`
-- Registr poskytovatelů vkládání: `open-sse/config/embeddingRegistry.ts`
-- Obslužná rutina generování obrázků: `open-sse/handlers/imageGeneration.ts`
-- Registr poskytovatelů obrázků: `open-sse/config/imageRegistry.ts`
-- Sanitizace odpovědí: `open-sse/handlers/responseSanitizer.ts`
-- Normalizace rolí: `open-sse/services/roleNormalizer.ts`
-
-Služby (obchodní logika):
-
-- Výběr/skórování účtu: `open-sse/services/accountSelector.ts`
-- Správa životního cyklu kontextu: `open-sse/services/contextManager.ts`
-- Vynucení filtrování IP adres: `open-sse/services/ipFilter.ts`
-- Sledování relací: `open-sse/services/sessionManager.ts`
-- Požadavek na deduplikaci: `open-sse/services/signatureCache.ts`
-- Vložení systémového promptu: `open-sse/services/systemPrompt.ts`
-- Řízení rozpočtu v duchu myšlenek: `open-sse/services/thinkingBudget.ts`
-- Směrování pomocí modelu zástupných znaků: `open-sse/services/wildcardRouter.ts`
-- Správa limitů rychlosti: `open-sse/services/rateLimitManager.ts`
-- Jistič: `open-sse/services/circuitBreaker.ts`
-
-Moduly doménové vrstvy:
-
-- Dostupnost modelu: `src/lib/domain/modelAvailability.ts`
-- Pravidla/rozpočty nákladů: `src/lib/domain/costRules.ts`
-- Záložní zásady: `src/lib/domain/fallbackPolicy.ts`
-- Kombinovaný resolver: `src/lib/domain/comboResolver.ts`
-- Zásady uzamčení: `src/lib/domain/lockoutPolicy.ts`
-- Modul zásad: `src/domain/policyEngine.ts` — centralizované uzamčení → rozpočet → vyhodnocení záložního režimu
-- Katalog chybových kódů: `src/lib/domain/errorCodes.ts`
-- ID požadavku: `src/lib/domain/requestId.ts`
-- Časový limit načtení: `src/lib/domain/fetchTimeout.ts`
-- Požadovat telemetrii: `src/lib/domain/requestTelemetry.ts`
-- Shoda/audit: `src/lib/domain/compliance/index.ts`
-- Zkušební běžec: `src/lib/domain/evalRunner.ts`
-- Perzistence stavu domény: `src/lib/db/domainState.ts` — SQLite CRUD pro záložní řetězce, rozpočty, historii nákladů, stav uzamčení, jističe
-
-Moduly poskytovatelů OAuth (12 jednotlivých souborů v adresáři `src/lib/oauth/providers/` ):
-
-- Index registru: `src/lib/oauth/providers/index.ts`
-- Jednotliví poskytovatelé: `claude.ts` , `codex.ts` , `gemini.ts` , `antigravity.ts` , `qoder.ts` , `qwen.ts` , `kimi-coding.ts` , `github.ts` , `kiro.ts` , `cursor.ts` , `kilocode.ts` , `cline.ts`
-- Thin wrapper: `src/lib/oauth/providers.ts` — reexporty z jednotlivých modulů
-
-## 3) Vrstva perzistence
-
-Primární stavová databáze (SQLite):
-
-- Základní infrastruktura: `src/lib/db/core.ts` (better-sqlite3, migrace, WAL)
-- Reexportní fasáda: `src/lib/localDb.ts` (tenká vrstva kompatibility pro volající)
-- soubor: `${DATA_DIR}/storage.sqlite` (nebo `$XDG_CONFIG_HOME/omniroute/storage.sqlite` pokud je nastaveno, jinak `~/.omniroute/storage.sqlite` )
-- entity (tabulky + jmenné prostory KV): providerConnections, providerNodes, modelAliases, combos, apiKeys, settings, pricing, **customModels** , **proxyConfig** , **ipFilter** , **thinkingBudget** , **systemPrompt**
-
-Trvalost používání:
-
-- fasáda: `src/lib/usageDb.ts` (dekomponované moduly v `src/lib/usage/*` )
-- SQLite tabulky v `storage.sqlite` : `usage_history` , `call_logs` , `proxy_logs`
-- Volitelné artefakty souborů zůstávají pro účely kompatibility/ladění ( `${DATA_DIR}/log.txt` , `${DATA_DIR}/call_logs/` , `/logs/...` )
-- Starší soubory JSON jsou migrovány do SQLite při migracích při spuštění, pokud jsou k dispozici.
-
-Databáze stavu domény (SQLite):
-
-- `src/lib/db/domainState.ts` — CRUD operace pro stav domény
-- Tabulky (vytvořené v `src/lib/db/core.ts` ): `domain_fallback_chains` , `domain_budgets` , `domain_cost_history` , `domain_lockout_state` , `domain_circuit_breakers`
-- Vzor mezipaměti pro zápis: mapy v paměti jsou autoritativní za běhu; mutace se zapisují synchronně do SQLite; stav se obnovuje z databáze při studeném startu.
-
-## 4) Ověřovací a bezpečnostní povrchy
-
-- Autorizace souborů cookie v dashboardu: `src/proxy.ts` , `src/app/api/auth/login/route.ts`
-- Generování/ověření klíče API: `src/shared/utils/apiKey.ts`
-- Tajné kódy poskytovatele přetrvávaly v položkách `providerConnections`
-- Podpora odchozí proxy přes `open-sse/utils/proxyFetch.ts` (proměnné prostředí) a `open-sse/utils/networkProxy.ts` (konfigurovatelné pro jednotlivé poskytovatele nebo globálně)
-
-## 5) Synchronizace s cloudem
-
-- Inicializace plánovače: `src/lib/initCloudSync.ts` , `src/shared/services/initializeCloudSync.ts`
-- Periodická úloha: `src/shared/services/cloudSyncScheduler.ts`
-- Řídicí trasa: `src/app/api/sync/cloud/route.ts`
-
-## Životní cyklus požadavku ( `/v1/chat/completions` )
-
-```mermaid
-sequenceDiagram
- autonumber
- participant Client as CLI/SDK Client
- participant Route as /api/v1/chat/completions
- participant Chat as src/sse/handlers/chat
- participant Core as open-sse/handlers/chatCore
- participant Model as Model Resolver
- participant Auth as Credential Selector
- participant Exec as Provider Executor
- participant Prov as Upstream Provider
- participant Stream as Stream Translator
- participant Usage as usageDb
-
- Client->>Route: POST /v1/chat/completions
- Route->>Chat: handleChat(request)
- Chat->>Model: parse/resolve model or combo
-
- alt Combo model
- Chat->>Chat: iterate combo models (handleComboChat)
- end
-
- Chat->>Auth: getProviderCredentials(provider)
- Auth-->>Chat: active account + tokens/api key
-
- Chat->>Core: handleChatCore(body, modelInfo, credentials)
- Core->>Core: detect source format
- Core->>Core: translate request to target format
- Core->>Exec: execute(provider, transformedBody)
- Exec->>Prov: upstream API call
- Prov-->>Exec: SSE/JSON response
- Exec-->>Core: response + metadata
-
- alt 401/403
- Core->>Exec: refreshCredentials()
- Exec-->>Core: updated tokens
- Core->>Exec: retry request
- end
-
- Core->>Stream: translate/normalize stream to client format
- Stream-->>Client: SSE chunks / JSON response
-
- Stream->>Usage: extract usage + persist history/log
-```
-
-## Kombinovaný + záložní proces pro účet
-
-```mermaid
-flowchart TD
- A[Incoming model string] --> B{Is combo name?}
- B -- Yes --> C[Load combo models sequence]
- B -- No --> D[Single model path]
-
- C --> E[Try model N]
- E --> F[Resolve provider/model]
- D --> F
-
- F --> G[Select account credentials]
- G --> H{Credentials available?}
- H -- No --> I[Return provider unavailable]
- H -- Yes --> J[Execute request]
-
- J --> K{Success?}
- K -- Yes --> L[Return response]
- K -- No --> M{Fallback-eligible error?}
-
- M -- No --> N[Return error]
- M -- Yes --> O[Mark account unavailable cooldown]
- O --> P{Another account for provider?}
- P -- Yes --> G
- P -- No --> Q{In combo with next model?}
- Q -- Yes --> E
- Q -- No --> R[Return all unavailable]
-```
-
-Rozhodnutí o záložních metodách jsou řízena souborem `open-sse/services/accountFallback.ts` s využitím stavových kódů a heuristik chybových zpráv.
-
-## Životní cyklus aktualizace OAuth a onboardingu tokenu
-
-```mermaid
-sequenceDiagram
- autonumber
- participant UI as Dashboard UI
- participant OAuth as /api/oauth/[provider]/[action]
- participant ProvAuth as Provider Auth Server
- participant DB as localDb
- participant Test as /api/providers/[id]/test
- participant Exec as Provider Executor
-
- UI->>OAuth: GET authorize or device-code
- OAuth->>ProvAuth: create auth/device flow
- ProvAuth-->>OAuth: auth URL or device code payload
- OAuth-->>UI: flow data
-
- UI->>OAuth: POST exchange or poll
- OAuth->>ProvAuth: token exchange/poll
- ProvAuth-->>OAuth: access/refresh tokens
- OAuth->>DB: createProviderConnection(oauth data)
- OAuth-->>UI: success + connection id
-
- UI->>Test: POST /api/providers/[id]/test
- Test->>Exec: validate credentials / optional refresh
- Exec-->>Test: valid or refreshed token info
- Test->>DB: update status/tokens/errors
- Test-->>UI: validation result
-```
-
-Obnovení během živého provozu se provádí uvnitř `open-sse/handlers/chatCore.ts` pomocí exekutoru `refreshCredentials()` .
-
-## Životní cyklus synchronizace s cloudem (Povolit / Synchronizovat / Zakázat)
-
-```mermaid
-sequenceDiagram
- autonumber
- participant UI as Endpoint Page UI
- participant Sync as /api/sync/cloud
- participant DB as localDb
- participant Cloud as External Cloud Sync
- participant Claude as ~/.claude/settings.json
-
- UI->>Sync: POST action=enable
- Sync->>DB: set cloudEnabled=true
- Sync->>DB: ensure API key exists
- Sync->>Cloud: POST /sync/{machineId} (providers/aliases/combos/keys)
- Cloud-->>Sync: sync result
- Sync->>Cloud: GET /{machineId}/v1/verify
- Sync-->>UI: enabled + verification status
-
- UI->>Sync: POST action=sync
- Sync->>Cloud: POST /sync/{machineId}
- Cloud-->>Sync: remote data
- Sync->>DB: update newer local tokens/status
- Sync-->>UI: synced
-
- UI->>Sync: POST action=disable
- Sync->>DB: set cloudEnabled=false
- Sync->>Cloud: DELETE /sync/{machineId}
- Sync->>Claude: switch ANTHROPIC_BASE_URL back to local (if needed)
- Sync-->>UI: disabled
-```
-
-Pravidelnou synchronizaci spouští `CloudSyncScheduler` , když je povolen cloud.
-
-## Datový model a mapa úložiště
-
-```mermaid
-erDiagram
- SETTINGS ||--o{ PROVIDER_CONNECTION : controls
- PROVIDER_NODE ||--o{ PROVIDER_CONNECTION : backs_compatible_provider
- PROVIDER_CONNECTION ||--o{ USAGE_ENTRY : emits_usage
-
- SETTINGS {
- boolean cloudEnabled
- number stickyRoundRobinLimit
- boolean requireLogin
- string password_hash
- string fallbackStrategy
- json rateLimitDefaults
- json providerProfiles
- }
-
- PROVIDER_CONNECTION {
- string id
- string provider
- string authType
- string name
- number priority
- boolean isActive
- string apiKey
- string accessToken
- string refreshToken
- string expiresAt
- string testStatus
- string lastError
- string rateLimitedUntil
- json providerSpecificData
- }
-
- PROVIDER_NODE {
- string id
- string type
- string name
- string prefix
- string apiType
- string baseUrl
- }
-
- MODEL_ALIAS {
- string alias
- string targetModel
- }
-
- COMBO {
- string id
- string name
- string[] models
- }
-
- API_KEY {
- string id
- string name
- string key
- string machineId
- }
-
- USAGE_ENTRY {
- string provider
- string model
- number prompt_tokens
- number completion_tokens
- string connectionId
- string timestamp
- }
-
- CUSTOM_MODEL {
- string id
- string name
- string providerId
- }
-
- PROXY_CONFIG {
- string global
- json providers
- }
-
- IP_FILTER {
- string mode
- string[] allowlist
- string[] blocklist
- }
-
- THINKING_BUDGET {
- string mode
- number customBudget
- string effortLevel
- }
-
- SYSTEM_PROMPT {
- boolean enabled
- string prompt
- string position
- }
-```
-
-Soubory fyzického úložiště:
-
-- primární běhová databáze: `${DATA_DIR}/storage.sqlite`
-- řádky protokolu požadavku: `${DATA_DIR}/log.txt` (artefakt kompatibility/ladění)
-- Archivy strukturovaných dat volání: `${DATA_DIR}/call_logs/`
-- volitelné relace překladače/vyžádání ladění: `/logs/...`
-
-## Topologie nasazení
-
-```mermaid
-flowchart LR
- subgraph LocalHost[Developer Host]
- CLI[CLI Tools]
- Browser[Dashboard Browser]
- end
-
- subgraph ContainerOrProcess[OmniRoute Runtime]
- Next[Next.js Server\nPORT=20128]
- Core[SSE Core + Executors]
- MainDB[(storage.sqlite)]
- UsageDB[(usage tables + log artifacts)]
- end
-
- subgraph External[External Services]
- Providers[AI Providers]
- SyncCloud[Cloud Sync Service]
- end
-
- CLI --> Next
- Browser --> Next
- Next --> Core
- Next --> MainDB
- Core --> MainDB
- Core --> UsageDB
- Core --> Providers
- Next --> SyncCloud
-```
-
-## Mapování modulů (kritické pro rozhodnutí)
-
-### Moduly tras a API
-
-- `src/app/api/v1/*` , `src/app/api/v1beta/*` : API pro zajištění kompatibility
-- `src/app/api/v1/providers/[provider]/*` : vyhrazené trasy pro jednotlivé poskytovatele (chat, vkládání, obrázky)
-- `src/app/api/providers*` : CRUD poskytovatele, validace, testování
-- `src/app/api/provider-nodes*` : správa uzlů kompatibilních s vlastními nástroji
-- `src/app/api/provider-models` : správa vlastních modelů (CRUD)
-- `src/app/api/models/route.ts` : API katalogu modelů (aliasy + vlastní modely)
-- `src/app/api/oauth/*` : Toky OAuth/kódu zařízení
-- `src/app/api/keys*` : životní cyklus lokálního klíče API
-- `src/app/api/models/alias` : správa aliasů
-- `src/app/api/combos*` : správa záložních kombinací
-- `src/app/api/pricing` : přepsání cen pro výpočet nákladů
-- `src/app/api/settings/proxy` : konfigurace proxy (GET/PUT/DELETE)
-- `src/app/api/settings/proxy/test` : test připojení odchozí proxy (POST)
-- `src/app/api/usage/*` : API pro použití a protokoly
-- `src/app/api/sync/*` + `src/app/api/cloud/*` : synchronizace s cloudem a pomocníci pro práci s cloudem
-- `src/app/api/cli-tools/*` : lokální programy pro zápis/kontrolu konfigurace CLI
-- `src/app/api/settings/ip-filter` : Seznam povolených/blokovaných IP adres (GET/PUT)
-- `src/app/api/settings/thinking-budget` : konfigurace rozpočtu tokenu thinking (GET/PUT)
-- `src/app/api/settings/system-prompt` : globální systémový příkaz (GET/PUT)
-- `src/app/api/sessions` : výpis aktivních relací (GET)
-- `src/app/api/rate-limits` : stav limitu rychlosti pro účet (GET)
-
-### Směrovací a spouštěcí jádro
-
-- `src/sse/handlers/chat.ts` : parsování požadavků, zpracování kombinací, smyčka výběru účtu
-- `open-sse/handlers/chatCore.ts` : překlad, odeslání exekutoru, zpracování opakování/obnovení, nastavení streamu
-- `open-sse/executors/*` : chování sítě a formátu specifické pro poskytovatele
-
-### Registr překladů a převodníky formátů
-
-- `open-sse/translator/index.ts` : registr a orchestrace překladačů
-- Žádost o překladatele: `open-sse/translator/request/*`
-- Překladače odpovědí: `open-sse/translator/response/*`
-- Formátovací konstanty: `open-sse/translator/formats.ts`
-
-### Perzistence
-
-- `src/lib/db/*` : perzistentní ukládání konfigurace/stavu a domény v SQLite
-- `src/lib/localDb.ts` : reexport kompatibility pro databázové moduly
-- `src/lib/usageDb.ts` : fasáda historie použití/záznamů volání nad tabulkami SQLite
-
-## Pokrytí poskytovatele a vykonavatele (strategický vzorec)
-
-Každý poskytovatel má specializovaný exekutor rozšiřující `BaseExecutor` (v `open-sse/executors/base.ts` ), který zajišťuje vytváření URL adres, konstrukci hlaviček, opakování s exponenciálním odkladem, hooky pro obnovení pověření a orchestrační metodu `execute()` .
-
-| Vykonavatel | Poskytovatel(é) | Speciální manipulace |
-| --------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------- |
-| `DefaultExecutor` | OpenAI, Claude, Gemini, Qwen, Qoder, OpenRouter, GLM, Kimi, MiniMax, DeepSeek, Groq, xAI, Mistral, Perplexity, Together, Fireworks, Cerebras, Cohere, NVIDIA | Konfigurace dynamické adresy URL/záhlaví pro každého poskytovatele |
-| `AntigravityExecutor` | Google Antigravity | Vlastní ID projektů/relací, analýza Opakování po |
-| `CodexExecutor` | OpenAI Codex | Vkládá systémové instrukce, vynucuje úsilí k uvažování |
-| `CursorExecutor` | IDE kurzoru | Protokol ConnectRPC, kódování Protobuf, podepisování požadavků pomocí kontrolního součtu |
-| `GithubExecutor` | GitHub Copilot | Aktualizace tokenu Copilot, hlavičky napodobující VSCode |
-| `KiroExecutor` | AWS CodeWhisperer/Kiro | Binární formát AWS EventStream → konverze SSE |
-| `GeminiCLIExecutor` | Gemini CLI | Cyklus obnovy tokenu Google OAuth |
-
-Všichni ostatní poskytovatelé (včetně uzlů kompatibilních s vlastními funkcemi) používají `DefaultExecutor` .
-
-## Matice kompatibility poskytovatelů
-
-| Poskytovatel | Formát | Autorizace | Proud | Nestreamované | Obnovení tokenu | API pro použití |
-| ------------------------------ | --------------- | ---------------------------------- | -------------------- | ------------- | --------------- | --------------------------- |
-| Claude | Claude | Klíč API / OAuth | ✅ | ✅ | ✅ | ⚠️ Pouze pro administrátory |
-| Blíženci | Blíženci | Klíč API / OAuth | ✅ | ✅ | ✅ | ⚠️ Cloudová konzole |
-| Gemini CLI | gemini-cli | OAuth | ✅ | ✅ | ✅ | ⚠️ Cloudová konzole |
-| Antigravity | antigravitace | OAuth | ✅ | ✅ | ✅ | ✅ Plná kvóta API |
-| OpenAI | otevřeno | Klíč API | ✅ | ✅ | ❌ | ❌ |
-| Kodex | openai-odpovědi | OAuth | ✅ vynucený | ❌ | ✅ | ✅ Limity sazeb |
-| GitHub Copilot | otevřeno | OAuth + token Copilota | ✅ | ✅ | ✅ | ✅ Snímky kvót |
-| Kurzor | kurzor | Vlastní kontrolní součet | ✅ | ✅ | ❌ | ❌ |
-| Kiro | Kiro | OIDC pro jednotné přihlašování AWS | ✅ (Stream událostí) | ❌ | ✅ | ✅ Limity použití |
-| Qwen | otevřeno | OAuth | ✅ | ✅ | ✅ | ⚠️ Na vyžádání |
-| Qoder | otevřeno | OAuth (základní) | ✅ | ✅ | ✅ | ⚠️ Na vyžádání |
-| OpenRouter | otevřeno | Klíč API | ✅ | ✅ | ❌ | ❌ |
-| GLM/Kimi/MiniMax | Claude | Klíč API | ✅ | ✅ | ❌ | ❌ |
-| Hluboké vyhledávání | otevřeno | Klíč API | ✅ | ✅ | ❌ | ❌ |
-| Groq | otevřeno | Klíč API | ✅ | ✅ | ❌ | ❌ |
-| xAI (Grok) | otevřeno | Klíč API | ✅ | ✅ | ❌ | ❌ |
-| Mistral | otevřeno | Klíč API | ✅ | ✅ | ❌ | ❌ |
-| Zmatek | otevřeno | Klíč API | ✅ | ✅ | ❌ | ❌ |
-| Společně s umělou inteligencí | otevřeno | Klíč API | ✅ | ✅ | ❌ | ❌ |
-| Ohňostroj s umělou inteligencí | otevřeno | Klíč API | ✅ | ✅ | ❌ | ❌ |
-| Mozky | otevřeno | Klíč API | ✅ | ✅ | ❌ | ❌ |
-| Soudržný | otevřeno | Klíč API | ✅ | ✅ | ❌ | ❌ |
-| NVIDIA NIM | otevřeno | Klíč API | ✅ | ✅ | ❌ | ❌ |
-
-## Pokrytí překladů formátů
-
-Mezi detekované zdrojové formáty patří:
-
-- `openai`
-- `openai-responses`
-- `claude`
-- `gemini`
-
-Cílové formáty zahrnují:
-
-- Chat/Odpovědi v OpenAI
-- Claude
-- Obálka Gemini/Gemini-CLI/Antigravity
-- Kiro
-- Kurzor
-
-Překlady používají **jako ústřední formát OpenAI** – všechny konverze procházejí OpenAI jako zprostředkovatel:
-
-```
-Source Format → OpenAI (hub) → Target Format
-```
-
-Překlady jsou vybírány dynamicky na základě tvaru zdrojového datového obsahu a formátu cílového poskytovatele.
-
-Další vrstvy zpracování v překladovém kanálu:
-
-- **Sanitizace odpovědí** – Odstraňuje nestandardní pole z odpovědí ve formátu OpenAI (streamovaných i nestreamovaných), aby byla zajištěna přísná shoda se SDK.
-- **Normalizace rolí** — Převádí `developer` → `system` pro cíle mimo OpenAI; slučuje `system` → `user` pro modely, které odmítají systémovou roli (GLM, ERNIE)
-- **Extrakce tagu Think** — Analyzuje bloky `...` z obsahu do pole `reasoning_content`
-- **Strukturovaný výstup** — Převede OpenAI `response_format.json_schema` na `responseMimeType` + `responseSchema` z Gemini.
-
-## Podporované koncové body API
-
-| Koncový bod | Formát | Psovod |
-| -------------------------------------------------- | ------------------------- | ------------------------------------------------------- |
-| `POST /v1/chat/completions` | Chat s OpenAI | `src/sse/handlers/chat.ts` |
-| `POST /v1/messages` | Claude Messages | Stejný obslužný program (automaticky detekováno) |
-| `POST /v1/responses` | Reakce OpenAI | `open-sse/handlers/responsesHandler.ts` |
-| `POST /v1/embeddings` | Vkládání OpenAI | `open-sse/handlers/embeddings.ts` |
-| `GET /v1/embeddings` | Seznam modelů | Trasa API |
-| `POST /v1/images/generations` | Obrázky OpenAI | `open-sse/handlers/imageGeneration.ts` |
-| `GET /v1/images/generations` | Seznam modelů | Trasa API |
-| `POST /v1/providers/{provider}/chat/completions` | Chat s OpenAI | Vyhrazené pro každého poskytovatele s ověřováním modelu |
-| `POST /v1/providers/{provider}/embeddings` | Vkládání OpenAI | Vyhrazené pro každého poskytovatele s ověřováním modelu |
-| `POST /v1/providers/{provider}/images/generations` | Obrázky OpenAI | Vyhrazené pro každého poskytovatele s ověřováním modelu |
-| `POST /v1/messages/count_tokens` | Počet žetonů Claude | Trasa API |
-| `GET /v1/models` | Seznam modelů OpenAI | Trasa API (chat + vkládání + obrázek + vlastní modely) |
-| `GET /api/models/catalog` | Katalog | Všechny modely seskupené podle poskytovatele + typu |
-| `POST /v1beta/models/*:streamGenerateContent` | Rodák z Blíženců | Trasa API |
-| `GET/PUT/DELETE /api/settings/proxy` | Konfigurace proxy serveru | Konfigurace síťového proxy serveru |
-| `POST /api/settings/proxy/test` | Připojení proxy serveru | Koncový bod testu stavu/připojení proxy serveru |
-| `GET/POST/DELETE /api/provider-models` | Vlastní modely | Správa vlastních modelů pro každého poskytovatele |
-
-## Obejít obslužnou rutinu
-
-Obslužná rutina bypassu ( `open-sse/utils/bypassHandler.ts` ) zachycuje známé „throwaway“ požadavky z Claude CLI – warmup pingy, extrakce titulků a počty tokenů – a vrací **falešnou odpověď** bez spotřebování tokenů upstreamového poskytovatele. Toto se spustí pouze tehdy, když `User-Agent` obsahuje `claude-cli` .
-
-## Kanál protokolování požadavků
-
-Záznamník požadavků ( `open-sse/utils/requestLogger.ts` ) poskytuje 7stupňový kanál protokolování ladění, ve výchozím nastavení zakázaný a povolený pomocí `ENABLE_REQUEST_LOGS=true` :
-
-```
-1_req_client.json → 2_req_source.json → 3_req_openai.json → 4_req_target.json
-→ 5_res_provider.txt → 6_res_openai.txt → 7_res_client.txt
-```
-
-Soubory se zapisují do `/logs//` pro každou relaci požadavku.
-
-## Způsoby selhání a odolnost
-
-## 1) Dostupnost účtu/poskytovatele
-
-- Doba ochlazování účtu poskytovatele při přechodných chybách/chybách rychlosti/autentizace
-- záložní účet před selháním požadavku
-- záložní kombinovaný model, když je aktuální cesta modelu/poskytovatele vyčerpána
-
-## 2) Platnost tokenu
-
-- předběžná kontrola a obnovení s opakovaným pokusem o obnovení poskytovatelů
-- Opakování 401/403 po pokusu o obnovení v hlavní cestě
-
-## 3) Bezpečnost streamu
-
-- streamovací řadič s vědomím odpojení
-- překladový proud s vyprázdněním konce proudu a zpracováním `[DONE]`
-- Záložní odhad využití, když chybí metadata využití poskytovatele
-
-## 4) Zhoršení cloudové synchronizace
-
-- Zobrazují se chyby synchronizace, ale lokální běhové prostředí pokračuje.
-- Plánovač má logiku umožňující opakování, ale periodické provádění v současné době ve výchozím nastavení volá synchronizaci s jedním pokusem.
-
-## 5) Integrita dat
-
-- Migrace schématu SQLite a automatické aktualizace hooků při spuštění
-- Cesta kompatibility migrace starší verze JSON → SQLite
-
-## Pozorovatelnost a provozní signály
-
-Zdroje viditelnosti za běhu:
-
-- protokoly konzole ze `src/sse/utils/logger.ts`
-- Agregace využití na požadavek v SQLite ( `usage_history` , `call_logs` , `proxy_logs` )
-- textový stav požadavku přihlášení `log.txt` (volitelné/kompatibilní)
-- volitelné hluboké protokoly požadavků/překladů v `logs/` pokud `ENABLE_REQUEST_LOGS=true`
-- Koncové body použití dashboardu ( `/api/usage/*` ) pro spotřebu v uživatelském rozhraní
-
-## Hranice citlivé z hlediska zabezpečení
-
-- Tajný kód JWT ( `JWT_SECRET` ) zajišťuje ověřování/podepisování souborů cookie relace dashboardu.
-- Počáteční bootstrap hesla ( `INITIAL_PASSWORD` ) by měl být explicitně nakonfigurován pro zřizování při prvním spuštění.
-- Tajný klíč API HMAC ( `API_KEY_SECRET` ) zabezpečuje formát vygenerovaného lokálního klíče API.
-- Tajné klíče/tokeny poskytovatele (klíče/tokeny API) jsou uloženy v lokální databázi a měly by být chráněny na úrovni souborového systému.
-- Koncové body synchronizace cloudu se spoléhají na sémantiku ověřování klíče API + ID počítače.
-
-## Matice prostředí a běhového prostředí
-
-Proměnné prostředí aktivně používané kódem:
-
-- Aplikace/autentizace: `JWT_SECRET` , `INITIAL_PASSWORD`
-- Úložiště: `DATA_DIR`
-- Chování kompatibilního uzlu: `ALLOW_MULTI_CONNECTIONS_PER_COMPAT_NODE`
-- Volitelné přepsání úložné základny (Linux/macOS, když `DATA_DIR` není nastaveno): `XDG_CONFIG_HOME`
-- Bezpečnostní hashování: `API_KEY_SECRET` , `MACHINE_ID_SALT`
-- Protokolování: `ENABLE_REQUEST_LOGS`
-- Synchronizace/cloudové URL: `NEXT_PUBLIC_BASE_URL` , `NEXT_PUBLIC_CLOUD_URL`
-- Odchozí proxy: `HTTP_PROXY` , `HTTPS_PROXY` , `ALL_PROXY` , `NO_PROXY` a varianty s malými písmeny
-- Příznaky funkcí SOCKS5: `ENABLE_SOCKS5_PROXY` , `NEXT_PUBLIC_ENABLE_SOCKS5_PROXY`
-- Pomocníci pro platformu/běhové prostředí (ne konfigurace specifická pro aplikaci): `APPDATA` , `NODE_ENV` , `PORT` , `HOSTNAME`
-
-## Známé architektonické poznámky
-
-1. `usageDb` a `localDb` sdílejí stejnou základní adresářovou politiku ( `DATA_DIR` -> `XDG_CONFIG_HOME/omniroute` -> `~/.omniroute` ) se starší migrací souborů.
-2. `/api/v1/route.ts` deleguje na stejný jednotný nástroj pro tvorbu katalogů, který používá `/api/v1/models` ( `src/app/api/v1/models/catalog.ts` ), aby se zabránilo sémantickému posunu.
-3. Pokud je povoleno, zaznamenávač požadavků zapisuje celé záhlaví/tělo; adresář protokolu je považován za citlivý.
-4. Chování cloudu závisí na správné adrese `NEXT_PUBLIC_BASE_URL` a dosažitelnosti cloudového koncového bodu.
-5. Adresář `open-sse/` je publikován jako **balíček npm workspace** `@omniroute/open-sse` . Zdrojový kód jej importuje přes `@omniroute/open-sse/...` (vyřešeno pomocí `transpilePackages` v Next.js). Cesty k souborům v tomto dokumentu stále používají název adresáře `open-sse/` pro účely konzistence.
-6. Grafy v dashboardu používají **Recharts** (založené na SVG) pro přístupné a interaktivní vizualizace analytiky (sloupcové grafy využití modelu, tabulky s rozpisem poskytovatelů s mírou úspěšnosti).
-7. E2E testy používají **Playwright** ( `tests/e2e/` ), spouštěné pomocí `npm run test:e2e` . Unit testy používají **Node.js test runner** ( `tests/unit/` ), spouštěné pomocí `npm run test:unit` . Zdrojový kód pod `src/` je **TypeScript** ( `.ts` / `.tsx` ); pracovní prostor `open-sse/` zůstává JavaScript ( `.js` ).
-8. Stránka nastavení je uspořádána do 5 záložek: Zabezpečení, Směrování (6 globálních strategií: fill-first, round robin, p2c, náhodné, nejméně používané, nákladově optimalizované), Odolnost (upravitelné limity rychlosti, jistič, zásady), AI (rozpočet promyšlený, systémový výzva, mezipaměť výzev), Pokročilé (proxy).
-
-## Kontrolní seznam provozního ověření
-
-- Sestavení ze zdroje: `npm run build`
-- Sestavení obrazu Dockeru: `docker build -t omniroute .`
-- Spusťte službu a ověřte:
-- `GET /api/settings`
-- `GET /api/v1/models`
-- Základní URL cíle CLI by měla být `http://:20128/v1` , pokud `PORT=20128`
diff --git a/docs/i18n/cs/AUTO-COMBO.md b/docs/i18n/cs/AUTO-COMBO.md
deleted file mode 100644
index 70232be750..0000000000
--- a/docs/i18n/cs/AUTO-COMBO.md
+++ /dev/null
@@ -1,63 +0,0 @@
-# OmniRoute Auto-Combo Engine
-
-> Samosprávné řetězce modelů s adaptivním bodováním
-
-## Jak to funguje
-
-Systém Auto-Combo dynamicky vybírá nejlepšího poskytovatele/model pro každý požadavek pomocí **6faktorové skórovací funkce** :
-
-Faktor | Hmotnost | Popis
-:-- | :-- | :--
-Kvóta | 0,20 | Zbývající kapacita [0..1]
-Zdraví | 0,25 | Jistič: ZAVŘENO=1,0, POLOVINA=0,5, OTEVŘENO=0,0
-Náklady na fakturu | 0,20 | Inverzní náklady (levnější = vyšší skóre)
-LatencyInv | 0,15 | Inverzní latence p95 (rychlejší = vyšší)
-TaskFit | 0,10 | Skóre zdatnost modelu × typu úlohy
-Stabilita | 0,10 | Nízká variabilita latence/chyb
-
-## Balíčky módů
-
-Balíček | Soustředit | Hmotnost klíče
-:-- | :-- | :--
-🚀 **Rychlé odeslání** | Rychlost | latenceInv: 0,35
-💰 **Úspora nákladů** | Ekonomika | Náklady na účet: 0,40
-🎯 **Kvalita na prvním místě** | Nejlepší model | taskFit: 0,40
-📡 **Vhodné pro offline použití** | Dostupnost | kvóta: 0,40
-
-## Samoléčení
-
-- **Dočasné vyloučení** : Skóre < 0,2 → vyloučeno na 5 minut (postupné oddlužování, max. 30 minut)
-- **Upozornění na jistič** : OTEVŘENO → automatické vyloučení; POLOVIČNÍ OTEVŘENO → požadavky sondy
-- **Režim incidentu** : >50% OTEVŘENO → deaktivovat průzkum, maximalizovat stabilitu
-- **Obnova po zchlazení** : Po vyloučení je první požadavek „sonda“ se zkráceným časovým limitem.
-
-## Průzkum banditů
-
-5 % požadavků (konfigurovatelných) je směrováno k náhodným poskytovatelům k prozkoumání. V režimu incidentu je toto nastavení zakázáno.
-
-## API
-
-```bash
-# Create auto-combo
-curl -X POST http://localhost:20128/api/combos/auto \
- -H "Content-Type: application/json" \
- -d '{"id":"my-auto","name":"Auto Coder","candidatePool":["anthropic","google","openai"],"modePack":"ship-fast"}'
-
-# List auto-combos
-curl http://localhost:20128/api/combos/auto
-```
-
-## Úkol Fitness
-
-Více než 30 modelů hodnocených v 6 typech úkolů ( `coding` , `review` , `planning` , `analysis` , `debugging` , `documentation` ). Podporuje zástupné znaky (např. `*-coder` → vysoké skóre kódování).
-
-## Soubory
-
-Soubor | Účel
-:-- | :--
-`open-sse/services/autoCombo/scoring.ts` | Skórovací funkce a normalizace poolu
-`open-sse/services/autoCombo/taskFitness.ts` | Vyhledávání vhodnosti modelu × úkolu
-`open-sse/services/autoCombo/engine.ts` | Logika výběru, bandita, rozpočtový strop
-`open-sse/services/autoCombo/selfHealing.ts` | Vyloučení, sondy, režim incidentu
-`open-sse/services/autoCombo/modePacks.ts` | 4 hmotnostní profily
-`src/app/api/combos/auto/route.ts` | REST API
diff --git a/docs/i18n/cs/CHANGELOG.md b/docs/i18n/cs/CHANGELOG.md
index f6db8a8d16..1aeb98c251 100644
--- a/docs/i18n/cs/CHANGELOG.md
+++ b/docs/i18n/cs/CHANGELOG.md
@@ -1,275 +1,2011 @@
-# Seznam změn
+# Changelog (Čeština)
-## [Nevydané]
+🌐 **Languages:** 🇺🇸 [English](../../../CHANGELOG.md) · 🇪🇸 [es](../es/CHANGELOG.md) · 🇫🇷 [fr](../fr/CHANGELOG.md) · 🇩🇪 [de](../de/CHANGELOG.md) · 🇮🇹 [it](../it/CHANGELOG.md) · 🇷🇺 [ru](../ru/CHANGELOG.md) · 🇨🇳 [zh-CN](../zh-CN/CHANGELOG.md) · 🇯🇵 [ja](../ja/CHANGELOG.md) · 🇰🇷 [ko](../ko/CHANGELOG.md) · 🇸🇦 [ar](../ar/CHANGELOG.md) · 🇮🇳 [in](../in/CHANGELOG.md) · 🇹🇭 [th](../th/CHANGELOG.md) · 🇻🇳 [vi](../vi/CHANGELOG.md) · 🇮🇩 [id](../id/CHANGELOG.md) · 🇲🇾 [ms](../ms/CHANGELOG.md) · 🇳🇱 [nl](../nl/CHANGELOG.md) · 🇵🇱 [pl](../pl/CHANGELOG.md) · 🇸🇪 [sv](../sv/CHANGELOG.md) · 🇳🇴 [no](../no/CHANGELOG.md) · 🇩🇰 [da](../da/CHANGELOG.md) · 🇫🇮 [fi](../fi/CHANGELOG.md) · 🇵🇹 [pt](../pt/CHANGELOG.md) · 🇷🇴 [ro](../ro/CHANGELOG.md) · 🇭🇺 [hu](../hu/CHANGELOG.md) · 🇧🇬 [bg](../bg/CHANGELOG.md) · 🇸🇰 [sk](../sk/CHANGELOG.md) · 🇺🇦 [uk-UA](../uk-UA/CHANGELOG.md) · 🇮🇱 [he](../he/CHANGELOG.md) · 🇵🇭 [phi](../phi/CHANGELOG.md) · 🇧🇷 [pt-BR](../pt-BR/CHANGELOG.md) · 🇨🇿 [cs](../cs/CHANGELOG.md)
---
-## [2.7.8] — 18. 3. 2026
+## [Unreleased]
-> Sprint: Chyba ukládání rozpočtu + funkce kombinovaného agenta v uživatelském rozhraní + oprava zabezpečení tagu omniModel.
+### 🛠️ Maintenance
-### 🐛 Opravy chyb
+- **AGENTS.md rewrite:** Condensed from 297→153 lines. Added build/lint/test commands (including single-test execution), code style guidelines (Prettier, TypeScript, ESLint, naming, imports, error handling, security), and trimmed verbose architecture tables for AI agent consumption.
-- **fix(budget)** : „Uložit limity“ již nevrací chybu 422 — `warningThreshold` se nyní správně odesílá jako zlomek (0–1) místo procenta (0–100) (#451)
-- **oprava(kombinace)** : interní tag mezipaměti `` je nyní odstraněn před přeposíláním požadavků poskytovatelům, čímž se zabrání přerušení relace mezipaměti (#454)
+## [3.4.2] - 2026-04-01
-### ✨ Funkce
+### 🐛 Bug Fixes
-- **feat(combos)** : Do modálního okna pro vytváření/úpravy komb přidána sekce Funkce agenta – zpřístupnění přepsání `system_message` , `tool_filter_regex` a `context_cache_protection` přímo z dashboardu (#454)
+- **CI Stabilization:** Fixed failing analytics/settings Playwright selectors and request assertions so GitHub Actions E2E runs pass reliably across localized UIs and switch-based controls.
+- **Deterministic Tests:** Removed date-sensitive quota fixtures from Copilot usage tests and aligned idempotency/model catalog tests with the merged runtime behavior.
+- **MCP Type Hardening:** Removed zero-budget explicit `any` regressions from the MCP server tool registration path, restoring the `check:any-budget:t11` workflow gate.
+
+### 🛠️ Maintenance
+
+- **Release Branch Integration:** Consolidated the active feature branches into `release/v3.4.2` on top of current `main` and validated the branch with lint, unit, coverage, build, and CI-mode E2E runs.
+
+## [3.4.1] - 2026-03-31
+
+> [!WARNING]
+> **BREAKING CHANGE: request logging, retention, and logging environment variables have been redesigned.**
+> On the first startup after upgrading, OmniRoute archives legacy request logs from `DATA_DIR/logs/`, legacy `DATA_DIR/call_logs/`, and `DATA_DIR/log.txt` into `DATA_DIR/log_archives/*.zip`, then removes the deprecated layout and switches to the new unified artifact format under `DATA_DIR/call_logs/`.
+
+### ✨ New Features
+
+- **.ENV Migration Utility:** Included `scripts/migrate-env.mjs` to seamlessly migrate ` Sprint: Pád Dockeru pino, oprava workeru Codex CLI responses, synchronizace zámků balíčků.
+### Funkce
-### 🐛 Opravy chyb
+- **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)
+- **Model Registry Update:** Injected `gpt-5.4-mini` into the Codex provider's array of models (#756)
+- **Provider Limit Tracking:** Track and display when provider rate limits were last refreshed per account (#843)
-- **oprava(docker)** : `pino-abstract-transport` a `pino-pretty` jsou nyní explicitně kopírovány ve fázi Docker Runner — Samostatné trasování Next.js tyto závislosti peerů přehlíží, což způsobuje pád `Cannot find module pino-abstract-transport` při spuštění (#449)
-- **fix(responses)** : Odstranění `initTranslators()` z trasy `/v1/responses` — worker Next.js `the worker has exited` uncaughtException při požadavcích Codex CLI (#450)
+### 🐛 Bug Fixes
-### 🔧 Údržba
-
-- **chore(deps)** : `package-lock.json` je nyní commitován při každém upgradu verze, aby se zajistilo, že Docker `npm ci` použije přesné verze závislostí.
+- **Qwen Auth Routing:** Re-routed Qwen OAuth completions from the DashScope API to the Web Inference API (`chat.qwen.ai`), resolving authorization failures (#844, #807, #832)
+- **Qwen Auto-Retry Loop:** Added targeted 429 Quota Exceeded backoff handling inside `chatCore` protecting burst requests
+- **Codex OAuth Fallback:** Modern browser popup blocking no longer traps the user; it automatically falls back to manual URL entry (#808)
+- **Claude Token Refresh:** Anthropic's strict `application/json` boundaries are now respected during token generation instead of encoded URLs (#836)
+- **Codex Messages Schema:** Stripped purist `messages` injects from native passthrough requests to avoid structural rejections from the ChatGPT upstream (#806)
+- **CLI Detection Size Limit:** Safely bumped the Node binary scanning upper bound from 100MB to 350MB, allowing heavy standalone tools like Claude Code (229MB) and OpenCode (153MB) to be correctly detected by the VPS runtime (#809)
+- **CLI Runtime Environment:** Restored ability for CLI configurations to respect user override paths (`CLI_{PROVIDER}_BIN`) bypassing strict path-bound discovery rules
+- **Nvidia Header Conflicts:** Removed `prompt_cache_key` properties from upstream headers when calling non-Anthropic providers (#848)
+- **Codex Fast Tier Toggle:** Restored Codex service tier toggle contrast in light mode (#842)
+- **Test Infrastructure:** Updated `t28-model-catalog-updates` test that incorrectly expected the outdated DashScope endpoint for the Qwen native registry
---
-## [2.7.5] — 18. 3. 2026
+## [3.3.9] - 2026-03-31
-> Sprint: Vylepšení uživatelského rozhraní a oprava kontroly stavu rozhraní Windows CLI.
+### 🐛 Bug Fixes
-### 🐛 Opravy chyb
-
-- **fix(ux)** : Zobrazit na přihlašovací stránce nápovědu k výchozímu heslu — noví uživatelé nyní pod polem pro zadání hesla vidí `"Default password: 123456"` (#437)
-- **fix(cli)** : Claude CLI a další nástroje nainstalované npm jsou nyní správně detekovány jako spustitelné ve Windows — spawn používá `shell:true` k rozpoznání `.cmd` wrapperů přes PATHEXT (#447)
+- **Custom Provider Rotation:** Integrated `getRotatingApiKey` internally inside DefaultExecutor, ensuring `extraApiKeys` rotation triggers correctly for custom and compatible upstream providers (#815)
---
-## [2.7.4] — 18. 3. 2026
+## [3.3.8] - 2026-03-30
-> Sprint: Panel vyhledávacích nástrojů, opravy i18n, limity Copilota, oprava validace Serperu.
+### Funkce
-### 🚀 Vlastnosti
+- **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)
+- **Prompt Cache Tracking:** Added tracking capabilities and frontend visualization (Stats card) for semantic and prompt caching in the Dashboard UI
-- **feat(search)** : Přidáno hřiště pro vyhledávání (10. koncový bod), stránka s nástroji pro vyhledávání s porovnáním poskytovatelů/kanálovým přeřazením/historií vyhledávání, lokální směrování pro přeřazení, ochrana autorizace ve vyhledávacím API (#443 od @Regis-RCR)
- - Nová trasa: `/dashboard/search-tools`
- - Položka postranního panelu v sekci Ladění
- - `GET /api/search/providers` a `GET /api/search/stats` s ochranou autorizace
- - Lokální směrování provider_nodes pro `/v1/rerank`
- - 30+ klíčů i18n ve vyhledávacím jmenném prostoru
+### 🐛 Bug Fixes
-### 🐛 Opravy chyb
-
-- **fix(search)** : Oprava normalizátoru Brave News (vracel 0 výsledků), vynucení zkrácení max_results po normalizaci, oprava URL pro načítání stránek z koncových bodů (#443 od @Regis-RCR)
-- **fix(analytics)** : Lokalizace popisků dnů/dat v analytických nástrojích — nahrazení pevně zakódovaných portugalských řetězců pomocí `Intl.DateTimeFormat(locale)` (#444 od @hijak)
-- **oprava(copilot)** : Oprava zobrazení typu účtu GitHub Copilot, filtrování zavádějících řádků neomezených kvót z dashboardu limitů (#445 od @hijak)
-- **oprava(poskytovatelé)** : Zastavit odmítání platných klíčů Serper API – odpovědi jiné než 4xx považovat za platné ověřování (#446 od @hijak)
+- **Cache Dashboard Sizing:** Improved the UI layout sizes and context headers for the advanced cache pages (#835)
+- **Debug Sidebar Visibility:** Fixed an issue where the debug toggle wouldn't correctly show/hide sidebar debug details (#834)
+- **Gemini Model Prefixing:** Modified the namespace fallback to properly route via `gemini-cli/` instead of `gc/` to respect upstream specs (#831)
+- **OpenRouter Sync:** Improved compatibility synchronization to automatically ingest the available models catalog correctly from OpenRouter (#830)
+- **Streaming Payloads Mapping:** Reserialization of reasoning fields natively resolves conflict alias paths when output is streaming to edge devices
---
-## [2.7.3] — 18. 3. 2026
+## [3.3.7] - 2026-03-30
-> Sprint: Oprava záložní kvóty pro přímé API Codexu.
+### 🐛 Bug Fixes
-### 🐛 Opravy chyb
-
-- **oprava(codex)** : Blokování týdenních vyčerpávajících účtů v přímém záložním rozhraní API (#440)
- - Porovnávání prefixů `resolveQuotaWindow()` : `"weekly"` nyní odpovídá klíčům mezipaměti `"weekly (7d)"`
- - `applyCodexWindowPolicy()` správně vynucuje přepínání `useWeekly` / `use5h`
- - 4 nové regresní testy (celkem 766)
+- **OpenCode Config:** Restructured generated `opencode.json` to use the `@ai-sdk/openai-compatible` record-based schema with `options` and `models` as object maps instead of flat arrays, fixing config validation failures (#816)
+- **i18n Missing Keys:** Added missing `cloudflaredUrlNotice` translation key across all 30 language files to prevent `MISSING_MESSAGE` console errors in the Endpoint page (#823)
---
-## [2.7.2] — 18. 3. 2026
+## [3.3.6] - 2026-03-30
-> Sprint: Opravy kontrastu uživatelského rozhraní v režimu Light.
+### 🐛 Bug Fixes
-### 🐛 Opravy chyb
-
-- **fix(logs)** : Oprava kontrastu světelného režimu v protokolech požadavků, tlačítek filtrů a kombinovaného odznaku (#378)
- - Tlačítka filtrů Chyba/Úspěch/Kombinace jsou nyní čitelná i ve světlém režimu.
- - Odznak kombinované řady používá ve světlém režimu silnější fialovou barvu
+- **Token Accounting:** Included prompt cache tokens safely in historical usage inputs calculations for correct quota deductions (PR #822)
+- **Combo Test Probes:** Fixed combo testing logic false negatives by resolving parsing for reasoning-only responses and enabled massive parallelization via Promise.all (PR #828)
+- **Docker Quick Tunnels:** Embedded required ca-certificates inside the base runtime container to resolve Cloudflared TLS startup failures, and surfaced stdout network errors replacing generic exit codes (PR #829)
---
-## [2.7.1] — 17. 3. 2026
+## [3.3.5] - 2026-03-30
-> Sprint: Sjednocené směrování webového vyhledávání (POST /v1/search) s 5 poskytovateli + opravy zabezpečení Next.js 16.1.7 (6 CVE).
+### ✨ New Features
-### ✨ Nové funkce
+- **Gemini Quota Tracking:** Added real-time Gemini CLI quota tracking via the `retrieveUserQuota` API (PR #825)
+- **Cache Dashboard:** Enhanced the Cache Dashboard to display prompt cache metrics, 24h trends, and estimated cost savings (PR #824)
-- **feat(search)** : Sjednocené směrování webového vyhledávání — `POST /v1/search` s 5 poskytovateli (Serper, Brave, Perplexity, Exa, Tavily)
- - Automatické přepnutí napříč poskytovateli, více než 6 500 bezplatných vyhledávání/měsíc
- - Mezipaměť v paměti se slučováním požadavků (konfigurovatelné TTL)
- - Dashboard: Karta Analytika vyhledávání v `/dashboard/analytics` s rozpisem poskytovatelů, mírou zásahů do mezipaměti a sledováním nákladů
- - Nové API: `GET /api/v1/search/analytics` pro statistiky vyhledávacích požadavků
- - Migrace databáze: sloupec `request_type` v `call_logs` pro sledování požadavků mimo chat
- - Ověření Zod ( `v1SearchSchema` ), chráněné autorizací, náklady zaznamenány pomocí `recordCost()`
+### 🐛 Bug Fixes
-### 🔒 Bezpečnost
-
-- **deps** : Next.js 16.1.6 → 16.1.7 — opravuje 6 CVE:
- - **Kritické** : CVE-2026-29057 (pašování HTTP požadavků přes http-proxy)
- - **Vysoká** : CVE-2026-27977, CVE-2026-27978 (WebSocket + akce serveru)
- - **Médium** : CVE-2026-27979, CVE-2026-27980, CVE-2026-jcc7
-
-### 📁 Nové soubory
-
-| Soubor | Účel |
-| ---------------------------------------------------------------- | -------------------------------------------------------- |
-| `open-sse/handlers/search.ts` | Vyhledávací obslužná rutina s routováním 5 poskytovatelů |
-| `open-sse/config/searchRegistry.ts` | Registr poskytovatelů (autorizace, náklady, kvóta, TTL) |
-| `open-sse/services/searchCache.ts` | Mezipaměť v paměti se slučováním požadavků |
-| `src/app/api/v1/search/route.ts` | Trasa Next.js (POST + GET) |
-| `src/app/api/v1/search/analytics/route.ts` | API pro statistiky vyhledávání |
-| `src/app/(dashboard)/dashboard/analytics/SearchAnalyticsTab.tsx` | Karta analytického panelu |
-| `src/lib/db/migrations/007_search_request_type.sql` | Migrace databáze |
-| `tests/unit/search-registry.test.mjs` | 277 řádků jednotkových testů |
+- **User Experience:** Removed invasive auto-opening OAuth modal loops on barren provider detailed pages (PR #820)
+- **Dependency Updates:** Bumped and locked down dependencies for development and production trees including Next.js 16.2.1, Recharts, and TailwindCSS 4.2.2 (PR #826, #827)
---
-## [2.7.0] — 17. 3. 2026
+## [3.3.4] - 2026-03-30
-> Sprint: Funkce inspirované ClawRouterem – příznak volání toolCalling, vícejazyčná detekce záměru, benchmarkem řízený fallback, deduplikace požadavků, plugin RouterStrategy, ceny Grok-4 Fast + GLM-5 + MiniMax M2.5 + Kimi K2.5.
+### ✨ New Features
-### ✨ Nové modely a ceny
+- **A2A Workflows:** Added deterministic FSM orchestrator for multi-step agent workflows.
+- **Graceful Degradation:** Added a new multi-layer fallback framework to preserve core functionality during partial system outages.
+- **Config Audit:** Added an audit trail with diff detection to track changes and enable configuration rollbacks.
+- **Provider Health:** Added provider expiration tracking with proactive UI alerts for expiring API keys.
+- **Adaptive Routing:** Added an adaptive volume and complexity detector to override routing strategies dynamically based on load.
+- **Provider Diversity:** Implemented provider diversity scoring via Shannon entropy to improve load distribution.
+- **Auto-Disable Bounds:** Added an Auto-Disable Banned Accounts setting toggle to the Resilience dashboard.
-- **feat. (ceny)** : xAI Grok-4 Fast — `$0.20/$0.50 per 1M tokens` , latence 1143 ms p50, podpora volání nástrojů
-- **feat. (ceny)** : xAI Grok-4 (standardní) — `$0.20/$1.50 per 1M tokens` , což je důvodem k odmítnutí.
-- **výkon (ceny)** : GLM-5 přes Z.AI — `$0.5/1M` , 128 tisíc výstupních kontextů
-- **výkon (ceny)** : MiniMax M2.5 — `$0.30/1M input` , uvažování + agentní úkoly
-- **feat.(ceny)** : DeepSeek V3.2 — aktualizované ceny `$0.27/$1.10 per 1M`
-- **výkon (cena)** : Kimi K2.5 přes Moonshot API — přímý přístup k Moonshot API
-- **feat(providers)** : Přidán poskytovatel Z.AI (alias `zai` ) — rodina GLM-5 s výstupem 128K
+### 🐛 Bug Fixes
-### 🧠 Směrovací inteligence
+- **Codex & Claude Compatibility:** Fixed UI fallbacks, patched Codex non-streaming integration issues, and resolved CLI runtime detection on Windows.
+- **Release Automation:** Expanded permissions required for the Electron App build in GitHub Actions.
+- **Cloudflare Runtime:** Addressed correct runtime isolation exit codes for Cloudflared tunnel components.
-- **feat(registry)** : příznak `toolCalling` pro každý model v registru poskytovatelů – kombinace nyní mohou preferovat/vyžadovat modely s možností volání nástrojů
-- **feat(scoring)** : Detekce vícejazyčného záměru pro skórování AutoCombo — skriptové/jazykové vzory PT/ZH/ES/AR ovlivňují výběr modelu podle kontextu požadavku
-- **feat(fallback)** : Řetězce záložních metod řízené benchmarky — skutečná data o latenci (p50 z `comboMetrics` ) používaná k dynamickému přeskupení priorit záložních metod
-- **feat(dedup)** : Vyžádání deduplikace pomocí content-hash — 5sekundové okno idempotence zabraňuje duplicitním voláním poskytovatele v opakovaném pokusu o odeslání klientům
-- **feat(router)** : Připojitelné rozhraní `RouterStrategy` v `autoCombo/routerStrategy.ts` — lze vložit vlastní logiku směrování bez úpravy jádra
+### 🧪 Tests
-### 🔧 Vylepšení serveru MCP
-
-- **feat(mcp)** : 2 nová pokročilá schémata nástrojů: `omniroute_get_provider_metrics` (p50/p95/p99 na poskytovatele) a `omniroute_explain_route` (vysvětlení rozhodnutí o směrování)
-- **feat(mcp)** : Aktualizovány rozsahy autorizace nástroje MCP – přidán rozsah `metrics:read` pro nástroje pro metriky poskytovatelů
-- **feat(mcp)** : `omniroute_best_combo_for_task` nyní akceptuje parametr `languageHint` pro vícejazyčné směrování
-
-### 📊 Pozorovatelnost
-
-- **feat(metrics)** : Soubor `comboMetrics.ts` rozšířen o sledování percentilů latence v reálném čase pro každého poskytovatele/účet.
-- **feat(health)** : Rozhraní Health API ( `/api/monitoring/health` ) nyní vrací pole `p50Latency` a `errorRate` pro každého poskytovatele.
-- **feat(usage)** : Migrace historie použití pro sledování latence pro jednotlivé modely
-
-### 🗄️ Migrace databází
-
-- **feat(migrations)** : Nový sloupec `latency_p50` v tabulce `combo_metrics` — nulový, bezpečný pro stávající uživatele
-
-### 🐛 Opravy chyb / Uzavření
-
-- **close(#411)** : rozlišení hašovaných modulů better-sqlite3 ve Windows — opraveno ve verzi 2.6.10 (f02c5b5)
-- **close(#409)** : Dokončení chatu GitHub Copilot selhává u modelů Claude při připojení souborů – opraveno ve verzi 2.6.9 (838f1d6)
-- **close(#405)** : Duplikát #411 – vyřešeno
-
-## [2.6.10] — 17. 3. 2026
-
-> Oprava pro Windows: stažení předkompilovaného better-sqlite3 bez node-gyp/Pythonu/MSVC (#426).
-
-### 🐛 Opravy chyb
-
-- **fix(install/#426)** : Ve Windows dříve selhával příkaz `npm install -g omniroute` s `better_sqlite3.node is not a valid Win32 application` , protože přiložený nativní binární soubor byl zkompilován pro Linux. Přidává **strategii 1.5** do `scripts/postinstall.mjs` : používá `@mapbox/node-pre-gyp install --fallback-to-build=false` (přiloženo v rámci `better-sqlite3` ) ke stažení správného předkompilovaného binárního souboru pro aktuální OS/arch bez nutnosti použití jakýchkoli nástrojů pro sestavení (žádný node-gyp, žádný Python, žádný MSVC). Vrací se k `npm rebuild` pouze v případě, že stahování selže. Přidává chybové zprávy specifické pro platformu s jasnými pokyny k ruční opravě.
+- **Test Suite Updates:** Expanded test coverage for volume detectors, provider diversity, configuration audit, and FSM.
---
-## [2.6.9] — 17. 3. 2026
+## [3.3.3] - 2026-03-29
-> Opravy CI (t11 s libovolným rozpočtem), oprava chyby č. 409 (souborové přílohy přes Copilot+Claude), korekce pracovního postupu vydání.
+### 🐛 Bug Fixes
-### 🐛 Opravy chyb
-
-- **fix(ci)** : Odstranění slova „any“ z komentářů v `openai-responses.ts` a `chatCore.ts` , které neprošly kontrolou rozpočtu t11 `\bany\b` (falešně pozitivní výsledek z počítání regexů v komentářích).
-- **oprava(chatCore)** : Normalizovat nepodporované typy částí obsahu před přeposláním poskytovatelům (#409 — Kurzor odesílá `{type:"file"}` když jsou připojeny soubory `.md` ; Copilot a další poskytovatelé kompatibilní s OpenAI odmítají s "type musí být buď 'image_url', nebo 'text'"; oprava převádí bloky `file` / `document` na `text` a odstraňuje neznámé typy)
-
-### 🔧 Pracovní postup
-
-- **chore(generate-release)** : Přidat pravidlo pro atomický commit — navýšení verze ( `npm version patch` ) MUSÍ proběhnout před commitem souborů funkcí, aby se zajistilo, že tag vždy ukazuje na commit obsahující všechny změny verzí dohromady.
+- **CI/CD Reliability:** Patched GitHub Actions to stable dependency versions (`actions/checkout@v4`, `actions/upload-artifact@v4`) to mitigate unannounced builder environment deprecations.
+- **Image Fallbacks:** Replaced arbitrary fallback chains in `ProviderIcon.tsx` with explicit asset validation to prevent UI loading `` components for files that don't exist, eliminating `404` errors in dashboard console logs (#745).
+- **Admin Updater:** Dynamic source-installation detection for the dashboard Updater. Safely disables the `Update Now` button when OmniRoute is built locally rather than through npm, prompting for `git pull` (#743).
+- **Update ERESOLVE Error:** Injected `package.json` overrides for `react`/`react-dom` and enabled `--legacy-peer-deps` within the internal automatic updater scripts to resolve breaking dependency tree conflicts with `@lobehub/ui`.
---
-## [2.6.8] — 17. 3. 2026
+## [3.3.2] - 2026-03-29
-> Sprint: Kombinace jako agent (systémový příkaz + filtr nástrojů), ochrana kontextového ukládání do mezipaměti, automatická aktualizace, podrobné protokoly, MITM Kiro IDE.
+### ✨ New Features
-### 🗄️ Migrace databází (bez nutnosti aktualizace – bezpečné pro stávající uživatele)
+- **Cloudflare Tunnels:** Cloudflare Quick Tunnel integration with dashboard controls (PR #772).
+- **Diagnostics:** Semantic cache bypass for combo live tests (PR #773).
-- **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** : Nová tabulka `request_detail_logs` s triggerem kruhového bufferu s 500 záznamy, možnost přihlášení přes přepínač nastavení
+### 🐛 Bug Fixes
-### ✨ Funkce
-
-- **feat(combo)** : Přepsání systémových zpráv pro Combo (#399 — pole `system_message` nahrazuje nebo vkládá systémový výzvu před přesměrováním poskytovateli)
-- **feat(combo)** : Regulární výraz filtru nástrojů pro každou kombinaci (#399 — `tool_filter_regex` uchovává pouze nástroje odpovídající vzoru; podporuje formáty OpenAI + Anthropic)
-- **feat(combo)** : Ochrana před ukládáním do mezipaměti kontextu (#401 — `context_cache_protection` označuje odpovědi s `provider/model` a modelem pins pro zajištění kontinuity relace)
-- **feat(settings)** : Automatická aktualizace přes Nastavení (#320 — `GET /api/system/version` + `POST /api/system/update` — kontroluje registr npm a aktualizuje na pozadí s restartem pm2)
-- **feat(logs)** : Podrobné protokoly požadavků (#378 — zachycuje kompletní těla procesů ve 4 fázích: požadavek klienta, přeložený požadavek, odpověď poskytovatele, odpověď klienta — přepínání přihlášení, ořezávání na 64 kB, kruhová vyrovnávací paměť s 500 záznamy)
-- **feat(mitm)** : Profil MITM Kiro IDE (#336 — `src/mitm/targets/kiro.ts` cílí na api.anthropic.com, znovu využívá stávající infrastrukturu MITM)
+- **Streaming Stability:** Apply `FETCH_TIMEOUT_MS` to streaming requests' initial `fetch()` call to prevent 300s Node.js TCP timeout causing silent task failures (#769).
+- **i18n:** Add missing `windsurf` and `copilot` entries to `toolDescriptions` across all 33 locale files (#748).
+- **GLM Coding Audit:** Complete provider audit fixing ReDoS vulnerabilities, context window sizing (128k/16k), and model registry syncing (PR #778).
---
-## [2.6.7] — 17. 3. 2026
+## [3.3.1] - 2026-03-29
-> Sprint: Vylepšení SSE, rozšíření lokálních provider_nodes, registr proxy, opravy Claude passthrough.
+### 🐛 Bug Fixes
-### ✨ Funkce
-
-- **feat(health)** : Kontrola stavu lokálních `provider_nodes` na pozadí s exponenciálním zpožděním (30s→300s) a `Promise.allSettled` pro zamezení blokování (#423, @Regis-RCR)
-- **feat(embeddings)** : Směrování `/v1/embeddings` do lokálních uzlů `provider_nodes` — `buildDynamicEmbeddingProvider()` s ověřením názvu hostitele (#422, @Regis-RCR)
-- **feat(audio)** : Směrování TTS/STT do lokálních `provider_nodes` — `buildDynamicAudioProvider()` s ochranou SSRF (#416, @Regis-RCR)
-- **feat(proxy)** : Registr proxy, API pro správu a zobecnění limitů kvót (#429, @Regis-RCR)
-
-### 🐛 Opravy chyb
-
-- **fix(sse)** : Odstranění polí specifických pro Claude ( `metadata` , `anthropic_version` ), pokud je cíl kompatibilní s OpenAI (#421, @prakersh)
-- **fix(sse)** : Extrahuje využití Claude SSE ( `input_tokens` , `output_tokens` , cache tokeny) v režimu průchozího streamu (#420, @prakersh)
-- **fix(sse)** : Generování záložního `call_id` pro volání nástrojů s chybějícími/prázdnými ID (#419, @prakersh)
-- **oprava(sse)** : Průchod mezi Claudey a Claudey — přední tělo zcela nedotčeno, bez opětovného překladu (#418, @prakersh)
-- **fix(sse)** : Filtrovat osiřelé položky `tool_result` po zhuštění kontextu Claude Code, aby se zabránilo chybám 400 (#417, @prakersh)
-- **fix(sse)** : Přeskočit volání nástrojů s prázdnými názvy v překladači Responses API, aby se zabránilo nekonečným smyčkám `placeholder_tool` (#415, @prakersh)
-- **fix(sse)** : Odstranění prázdných bloků textového obsahu před překladem (#427, @prakersh)
-- **fix(api)** : Přidáno `refreshable: true` do testovací konfigurace Claude OAuth (#428, @prakersh)
-
-### 📦 Závislosti
-
-- Zvýšení `vitest` , `@vitest/*` a související devDependencies (#414, @dependabot)
+- **OpenAI Codex:** Fallback processing fix for `type: "text"` elements carrying null or empty datasets that caused 400 rejection (#742).
+- **Opencode:** Update schema alignment to singular `provider` to match official spec (#774).
+- **Gemini CLI:** Inject missing end-user quota headers preventing 403 authorization lockouts (#775).
+- **DB Recovery:** Refactor multipart payload imports into raw binary buffered arrays to bypass reverse proxy max body limits (#770).
---
-## [2.6.6] — 17. 3. 2026
+## [3.3.0] - 2026-03-29
-> Oprava: Kompatibilita s Turbopackem/Dockerem — odebrání protokolu `node:` ze všech importů `src/` .
+### ✨ Enhancements & Refactoring
-### 🐛 Opravy chyb
+- **Release Stabilization** — Finalized v3.2.9 release (combo diagnostics, quality gates, Gemini tool fix) and created missing git tag. Consolidated all staged changes into a single atomic release commit.
-- **fix(build)** : Z příkazů `import` v 17 souborech v `src/` byl odstraněn prefix `node:` protocol. Importy `node:fs` , `node:path` , `node:url` , `node:os` atd. způsobovaly, že `Ecmascript file had an error` v sestaveních Turbopack (Next.js 15 Docker) a při upgradech ze starších globálních instalací npm. Dotčené soubory: `migrationRunner.ts` , `core.ts` , `backup.ts` , `prompts.ts` , `dataPaths.ts` a 12 dalších v `src/app/api/` a `src/lib/` .
-- **chore(workflow)** : Aktualizován `generate-release.md` , aby synchronizace Docker Hubu a nasazení duálního VPS zahrnovaly **povinné** kroky v každé verzi.
+### 🐛 Bug Fixes
+
+- **Auto-Update Test** — Fixed `buildDockerComposeUpdateScript` test assertion to match unexpanded shell variable references (`$TARGET_TAG`, `${TARGET_TAG#v}`) in the generated deploy script, aligning with the refactored template from v3.2.8.
+- **Circuit Breaker Test** — Hardened `combo-circuit-breaker.test.mjs` by injecting `maxRetries: 0` to prevent retry inflation from skewing failure count assertions during breaker state transitions.
---
-## [2.6.5] — 17. 3. 2026
+## [3.2.9] - 2026-03-29
-> Sprint: filtrování parametrů modelu uvažování, oprava chyby 404 lokálního poskytovatele, poskytovatel Kilo Gateway, vylepšení závislostí.
+### ✨ Enhancements & Refactoring
-### ✨ Nové funkce
+- **Combo Diagnostics** — Introduced a live test bypass flag (`forceLiveComboTest`) allowing administrators to execute real upstream health checks that bypass all local circuit-breaker and cooldown state mechanisms, enabling precise diagnostics during rolling outages (PR #759)
+- **Quality Gates** — Added automated response quality validation for combos and officially integrated `claude-4.6` model support into the core routing schemas (PR #762)
-- **feat(api)** : Přidán **Kilo Gateway** ( `api.kilo.ai` ) jako nový poskytovatel API klíčů (alias `kg` ) — více než 335 modelů, 6 bezplatných modelů, 3 modely automatického směrování ( `kilo-auto/frontier` , `kilo-auto/balanced` , `kilo-auto/free` ). Průchozí modely podporovány přes endpoint `/api/gateway/models` . (PR #408 od @Regis-RCR)
+### 🐛 Bug Fixes
-### 🐛 Opravy chyb
+- **Tool Definition Validation** — Repaired Gemini API integration by normalizing enum types inside tool definitions, preventing upstream HTTP 400 parameter errors (PR #760)
-- **fix(sse)** : Odstranění nepodporovaných parametrů pro modely uvažování (o1, o1-mini, o1-pro, o3, o3-mini). Modely v rodině `o1` / `o3` odmítají `temperature` , `top_p` , `frequency_penalty` , `presence_penalty` , `logprobs` , `top_logprobs` a `n` s HTTP 400. Parametry jsou nyní odstraňovány na vrstvě `chatCore` před přeposíláním. Používá deklarativní pole `unsupportedParams` pro každý model a předpočítanou mapu O(1) pro vyhledávání. (PR #412 od @Regis-RCR)
-- **fix(sse)** : Kód 404 lokálního poskytovatele nyní vede k **uzamčení pouze modelu (5 sekund)** namísto uzamčení na úrovni připojení (2 minuty). Když lokální inferenční backend (Ollama, LM Studio, oMLX) vrátí kód 404 pro neznámý model, připojení zůstane aktivní a ostatní modely okamžitě pokračují v práci. Také opravuje již existující chybu, kdy `model` nebyl předán funkci `markAccountUnavailable()` . Lokální poskytovatelé detekováni pomocí názvu hostitele ( `localhost` , `127.0.0.1` , `::1` , rozšiřitelné pomocí proměnné prostředí `LOCAL_HOSTNAMES` ). (PR #410 od @Regis-RCR)
+---
-### 📦 Závislosti
+## [3.2.8] - 2026-03-29
+
+### ✨ Enhancements & Refactoring
+
+- **Docker Auto-Update UI** — Integrated a detached background update process for Docker Compose deployments. The Dashboard UI now seamlessly tracks update lifecycle events combining JSON REST responses with SSE streaming progress overlays for robust cross-environment reliability.
+- **Cache Analytics** — Repaired zero-metrics visualization mapping by migrating Semantic Cache telemetry logs directly into the centralized tracking SQLite module.
+
+### 🐛 Bug Fixes
+
+- **Authentication Logic** — Fixed a bug where saving dashboard settings or adding models failed with a 401 Unauthorized error when `requireLogin` was disabled. API endpoints now correctly evaluate the global authentication toggle. Resolved global redirection by reactivating `src/middleware.ts`.
+- **CLI Tool Detection (Windows)** — Prevented fatal initialization exceptions during CLI environment detection by catching `cross-spawn` ENOENT errors correctly. Adds explicit detection paths for `\AppData\Local\droid\droid.exe`.
+- **Codex Native Passthrough** — Normalized model translation parameters preventing context poisoning in proxy pass-through mode, enforcing generic `store: false` constraints explicitly for all Codex-originated requests.
+- **SSE Token Reporting** — Normalized provider tool-call chunk `finish_reason` detection, fixing 0% Usage analytics for stream-only responses missing strict `` indicators.
+- **DeepSeek Tags** — Implemented an explicit `` extraction mapping inside `responsesHandler.ts`, ensuring DeepSeek reasoning streams map equivalently to native Anthropic `` structures.
+
+---
+
+## [3.2.7] - 2026-03-29
+
+### Fixed
+
+- **Seamless UI Updates**: The "Update Now" feature on the Dashboard now provides live, transparent feedback using Server-Sent Events (SSE). It performs package installation, native module rebuilds (better-sqlite3), and PM2 restarts reliably while showing real-time loaders instead of silently hanging.
+
+---
+
+## [3.2.6] — 2026-03-29
+
+### ✨ Enhancements & Refactoring
+
+- **API Key Reveal (#740)** — Added a scoped API key copy flow in the Api Manager, protected by the `ALLOW_API_KEY_REVEAL` environment variable.
+- **Sidebar Visibility Controls (#739)** — Admins can now hide any sidebar navigation link via the Appearance settings to reduce visual clutter.
+- **Strict Combo Testing (#735)** — Hardened the combo health check endpoint to require live text responses from models instead of just soft reachability signals.
+- **Streamed Detailed Logs (#734)** — Switched detailed request logging for SSE streams to reconstruct the final payload, saving immense amounts of SQLite database size and significantly cleaning up the UI.
+
+### 🐛 Bug Fixes
+
+- **OpenCode Go MiniMax Auth (#733)** — Corrected the authentication header logic for `minimax` models on OpenCode Go to use `x-api-key` instead of standard bearer tokens across the `/messages` protocol.
+
+---
+
+## [3.2.5] — 2026-03-29
+
+### ✨ Enhancements & Refactoring
+
+- **Void Linux Deployment Support (#732)** — Integrated `xbps-src` packaging template and instructions to natively compile and install OmniRoute with `better-sqlite3` bindings via cross-compilation target.
+
+## [3.2.4] — 2026-03-29
+
+### ✨ Enhancements & Refactoring
+
+- **Qoder AI Migration (#660)** — Completely migrated the legacy `iFlow` core provider onto `Qoder AI` maintaining stable API routing capabilities.
+
+### 🐛 Bug Fixes
+
+- **Gemini Tools HTTP 400 Payload Invalid Argument (#731)** — Prevented `thoughtSignature` array injections inside standard Gemini `functionCall` sequences blocking agentic routing flows.
+
+---
+
+## [3.2.3] — 2026-03-29
+
+### ✨ Enhancements & Refactoring
+
+- **Provider Limits Quota UI (#728)** — Normalized quota limit logic and data labeling inside the Limits interface.
+
+### 🐛 Bug Fixes
+
+- **Core Routing Schemas & Leaks** — Expanded `comboStrategySchema` to natively support `fill-first` and `p2c` strategies to unblock complex combo editing natively.
+- **Thinking Tags Extraction (CLI)** — Restructured CLI token responses sanitizer RegEx capturing model reasoning structures inside streams avoiding broken `` extractions breaking response text output format.
+- **Strict Format Enforcements** — Hardened pipeline sanitization execution making it universally apply to translation mode targets.
+
+---
+
+## [3.2.2] — 2026-03-29
+
+### ✨ New Features
+
+- **Four-Stage Request Log Pipeline (#705)** — Refactored log persistence to save comprehensive payloads at four distinct pipeline stages: Client Request, Translated Provider Request, Provider Response, and Translated Client Response. Introduced `streamPayloadCollector` for robust SSE stream truncation and payload serialization.
+
+### 🐛 Bug Fixes
+
+- **Mobile UI Fixes (#659)** — Prevented table components on the dashboard from breaking the layout on narrow viewports by adding proper horizontal scrolling and overflow containment to `DashboardLayout`.
+- **Claude Prompt Cache Fixes (#708)** — Ensured `cache_control` blocks in Claude-to-Claude fallback loops are faithfully preserved and passed safely back to Anthropic models.
+- **Gemini Tool Definitions (#725)** — Fixed schema translation errors when declaring simple `object` parameter types for Gemini function calling.
+
+## [3.2.1] — 2026-03-29
+
+### ✨ New Features
+
+- **Global Fallback Provider (#689)** — When all combo models are exhausted (502/503), OmniRoute now attempts a configurable global fallback model before returning the error. Set `globalFallbackModel` in settings to enable.
+
+### 🐛 Bug Fixes
+
+- **Fix #721** — Fixed context pinning bypass during tool-call responses. Non-streaming tagging used wrong JSON path (`json.messages` → `json.choices[0].message`). Streaming injection now triggers on `finish_reason` chunks for tool-call-only streams. `injectModelTag()` now appends synthetic pin messages for non-string content.
+- **Fix #709** — Confirmed already fixed (v3.1.9) — `system-info.mjs` creates directories recursively. Closed.
+- **Fix #707** — Confirmed already fixed (v3.1.9) — empty tool name sanitization in `chatCore.ts`. Closed.
+
+### 🧪 Tests
+
+- Added 6 unit tests for context pinning with tool-call responses (null content, array content, roundtrip, re-injection)
+
+## [3.2.0] — 2026-03-28
+
+### ✨ New Features
+
+- **Cache Management UI** — Added a dedicated semantic caching dashboard at \`/dashboard/cache\` with targeted API invalidation and 31-language i18n support (PR #701 by @oyi77)
+- **GLM Quota Tracking** — Added real-time usage and session quota tracking for the GLM Coding (Z.AI) provider (PR #698 by @christopher-s)
+- **Detailed Log Payloads** — Wired full four-stage pipeline payload capturing (original, translated, provider-response, streamed-deltas) directly into the UI (PR #705 by @rdself)
+
+### 🐛 Bug Fixes
+
+- **Fix #708** — Prevented token bleeding for Claude Code users routing through OmniRoute by correctly preserving native \`cache_control\` headers during Claude-to-Claude passthrough (PR #708 by @tombii)
+- **Fix #719** — Setup internal auth boundaries for \`ModelSyncScheduler\` to prevent unauthenticated daemon failures on startup (PR #719 by @rdself)
+- **Fix #718** — Rebuilt badge rendering in Provider Limits UI preventing bad quota boundaries overlap (PR #718 by @rdself)
+- **Fix #704** — Fixed Combo Fallbacks breaking on HTTP 400 content-policy errors preventing model-rotation dead-routing (PR #704 by @rdself)
+
+### 🔒 Security & Dependencies
+
+- Bumped \`path-to-regexp\` to \`8.4.0\` resolving dependabot vulnerabilities (PR #715)
+
+## [3.1.10] — 2026-03-28
+
+### 🐛 Bug Fixes
+
+- **Fix #706** — Fixed icon fallback rendering caused by Tailwind V4 `font-sans` override by applying `!important` to `.material-symbols-outlined`.
+- **Fix #703** — Fixed GitHub Copilot broken streams by enabling `responses` to `openai` format translation for any custom models leveraging `apiFormat: "responses"`.
+- **Fix #702** — Replaced flat-rate usage tracking with accurate DB pricing calculations for both streaming and non-streaming responses.
+- **Fix #716** — Cleaned up Claude tool-call translation state, correctly parsing streaming arguments and preventing OpenAI `tool_calls` chunks from repeating the `id` field.
+
+## [3.1.9] — 2026-03-28
+
+### ✨ New Features
+
+- **Schema Coercion** — Auto-coerce string-encoded numeric JSON Schema constraints (e.g. `"minimum": "1"`) to proper types, preventing 400 errors from Cursor, Cline, and other clients sending malformed tool schemas.
+- **Tool Description Sanitization** — Ensure tool descriptions are always strings; converts `null`, `undefined`, or numeric descriptions to empty strings before sending to providers.
+- **Clear All Models Button** — Added i18n translations for the "Clear All Models" provider action across all 30 languages.
+- **Codex Auth Export** — Added Codex `auth.json` export and apply-local buttons for seamless CLI integration.
+- **Windsurf BYOK Notes** — Added official limitation warnings to the Windsurf CLI tool card documenting BYOK constraints.
+
+### 🐛 Bug Fixes
+
+- **Fix #709** — `system-info.mjs` no longer crashes when the output directory doesn't exist (added `mkdirSync` with recursive flag).
+- **Fix #710** — A2A `TaskManager` singleton now uses `globalThis` to prevent state leakage across Next.js API route recompilations in dev mode. E2E test suite updated to handle 401 gracefully.
+- **Fix #711** — Added provider-specific `max_tokens` cap enforcement for upstream requests.
+- **Fix #605 / #592** — Strip `proxy_` prefix from tool names in non-streaming Claude responses; fixed LongCat validation URL.
+- **Call Logs Max Cap** — Upgraded `getMaxCallLogs()` with caching layer, env var support (`CALL_LOGS_MAX`), and DB settings integration.
+
+### 🧪 Tests
+
+- Test suite expanded from 964 → 1027 tests (63 new tests)
+- Added `schema-coercion.test.mjs` — 9 tests for numeric field coercion and tool description sanitization
+- Added `t40-opencode-cli-tools-integration.test.mjs` — OpenCode/Windsurf CLI integration tests
+- Enhanced feature-tests branch with comprehensive coverage tooling
+
+### 📁 New Files
+
+| File | Purpose |
+| -------------------------------------------------------- | ----------------------------------------------------------- |
+| `open-sse/translator/helpers/schemaCoercion.ts` | Schema coercion and tool description sanitization utilities |
+| `tests/unit/schema-coercion.test.mjs` | Unit tests for schema coercion |
+| `tests/unit/t40-opencode-cli-tools-integration.test.mjs` | CLI tool integration tests |
+| `COVERAGE_PLAN.md` | Test coverage planning document |
+
+### 🐛 Bug Fixes
+
+- **Claude Prompt Caching Passthrough** — Fixed cache_control markers being stripped in Claude passthrough mode (Claude → OmniRoute → Claude), which caused Claude Code users to deplete their Anthropic API quota 5-10x faster than direct connections. OmniRoute now preserves client's cache_control markers when sourceFormat and targetFormat are both Claude, ensuring prompt caching works correctly and dramatically reducing token consumption.
+
+## [3.1.8] - 2026-03-27
+
+### 🐛 Bug Fixes & Features
+
+- **Platform Core:** Implemented global state handling for Hidden Models & Combos preventing them from cluttering the catalog or leaking into connected MCP agents (#681).
+- **Stability:** Patched streaming crashes related to the native Antigravity provider integration failing due to unhandled undefined state arrays (#684).
+- **Localization Sync:** Deployed a fully overhauled `i18n` synchronizer detecting missing nested JSON properties and retro-fitting 30 locales sequentially (#685).## [3.1.7] - 2026-03-27
+
+### 🐛 Bug Fixes
+
+- **Streaming Stability:** Fixed `hasValuableContent` returning `undefined` for empty chunks in SSE streams (#676).
+- **Tool Calling:** Fixed an issue in `sseParser.ts` where non-streaming Claude responses with multiple tool calls dropped the `id` of subsequent tool calls due to incorrect index-based deduplication (#671).
+
+---
+
+## [3.1.6] — 2026-03-27
+
+### 🐛 Bug Fixes
+
+- **Claude Native Tool Name Restoration** — Tool names like `TodoWrite` are no longer prefixed with `proxy_` in Claude passthrough responses (both streaming and non-streaming). Includes unit test coverage (PR #663 by @coobabm)
+- **Clear All Models Alias Cleanup** — "Clear All Models" button now also removes associated model aliases, preventing ghost models in the UI (PR #664 by @rdself)
+
+---
+
+## [3.1.5] — 2026-03-27
+
+### 🐛 Bug Fixes
+
+- **Backoff Auto-Decay** — Rate-limited accounts now auto-recover when their cooldown window expires, fixing a deadlock where high `backoffLevel` permanently deprioritized accounts (PR #657 by @brendandebeasi)
+
+### 🌍 i18n
+
+- **Chinese translation overhaul** — Comprehensive rewrite of `zh-CN.json` with improved accuracy (PR #658 by @only4copilot)
+
+---
+
+## [3.1.4] — 2026-03-27
+
+### 🐛 Bug Fixes
+
+- **Streaming Override Fix** — Explicit `stream: true` in request body now takes priority over `Accept: application/json` header. Clients sending both will correctly receive SSE streaming responses (#656)
+
+### 🌍 i18n
+
+- **Czech string improvements** — Refined terminology across `cs.json` (PR #655 by @zen0bit)
+
+---
+
+## [3.1.3] — 2026-03-26
+
+### 🌍 i18n & Community
+
+- **~70 missing translation keys** added to `en.json` and 12 languages (PR #652 by @zen0bit)
+- **Czech documentation updated** — CLI-TOOLS, API_REFERENCE, VM_DEPLOYMENT guides (PR #652)
+- **Translation validation scripts** — `check_translations.py` and `validate_translation.py` for CI/QA (PR #651 by @zen0bit)
+
+---
+
+## [3.1.2] — 2026-03-26
+
+### 🐛 Bug Fixes
+
+- **Critical: Tool Calling Regression** — Fixed `proxy_Bash` errors by disabling the `proxy_` tool name prefix in the Claude passthrough path. Tools like `Bash`, `Read`, `Write` were being renamed to `proxy_Bash`, `proxy_Read`, etc., causing Claude to reject them (#618)
+- **Kiro Account Ban Documentation** — Documented as upstream AWS anti-fraud false positive, not an OmniRoute issue (#649)
+
+### 🧪 Tests
+
+- **936 tests, 0 failures**
+
+---
+
+## [3.1.1] — 2026-03-26
+
+### ✨ New Features
+
+- **Vision Capability Metadata**: Added `capabilities.vision`, `input_modalities`, and `output_modalities` to `/v1/models` entries for vision-capable models (PR #646)
+- **Gemini 3.1 Models**: Added `gemini-3.1-pro-preview` and `gemini-3.1-flash-lite-preview` to the Antigravity provider (#645)
+
+### 🐛 Bug Fixes
+
+- **Ollama Cloud 401 Error**: Fixed incorrect API base URL — changed from `api.ollama.com` to official `ollama.com/v1/chat/completions` (#643)
+- **Expired Token Retry**: Added bounded retry with exponential backoff (5→10→20 min) for expired OAuth connections instead of permanently skipping them (PR #647)
+
+### 🧪 Tests
+
+- **936 tests, 0 failures**
+
+---
+
+## [3.1.0] — 2026-03-26
+
+### ✨ New Features
+
+- **GitHub Issue Templates**: Added standardized bug report, feature request, and config/proxy issue templates (#641)
+- **Clear All Models**: Added a "Clear All Models" button to the provider detail page with i18n support in 29 languages (#634)
+
+### 🐛 Bug Fixes
+
+- **Locale Conflict (`in.json`)**: Renamed the Hindi locale file from `in.json` (Indonesian ISO code) to `hi.json` to fix translation conflicts in Weblate (#642)
+- **Codex Empty Tool Names**: Moved tool name sanitization before the native Codex passthrough, fixing 400 errors from upstream providers when tools had empty names (#637)
+- **Streaming Newline Artifacts**: Added `collapseExcessiveNewlines` to the response sanitizer, collapsing runs of 3+ consecutive newlines from thinking models into a standard double newline (#638)
+- **Claude Reasoning Effort**: Converted OpenAI `reasoning_effort` param to Claude's native `thinking` budget block across all request paths, including automatic `max_tokens` adjustment (#627)
+- **Qwen Token Refresh**: Implemented proactive pre-expiry OAuth token refreshes (5-minute buffer) to prevent requests from failing when using short-lived tokens (#631)
+
+### 🧪 Tests
+
+- **936 tests, 0 failures** (+10 tests since 3.0.9)
+
+---
+
+## [3.0.9] — 2026-03-26
+
+### 🐛 Bug Fixes
+
+- **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
+
+### Bezpečnost
+
+- Updated `yaml` package to fix stack overflow vulnerability (GHSA-48c2-rrv3-qjmp)
+
+### 📋 Issue Triage
+
+- Closed #613 (Codestral — resolved with Custom Provider workaround)
+- Commented on #615 (OpenCode dual-endpoint — workaround provided, tracked as feature request)
+- Commented on #618 (tool call visibility — requesting v3.0.9 test)
+- Commented on #627 (effort level — already supported)
+
+---
+
+## [3.0.8] — 2026-03-25
+
+### 🐛 Bug Fixes
+
+- **Translation Failures for OpenAI-format Providers in Claude CLI (#632):**
+ - Handle `reasoning_details[]` array format from StepFun/OpenRouter — converts to `reasoning_content`
+ - Handle `reasoning` field alias from some providers → normalized to `reasoning_content`
+ - Cross-map usage field names: `input_tokens`↔`prompt_tokens`, `output_tokens`↔`completion_tokens` in `filterUsageForFormat`
+ - Fix `extractUsage` to accept both `input_tokens`/`output_tokens` and `prompt_tokens`/`completion_tokens` as valid usage fields
+ - Applied to both streaming (`sanitizeStreamingChunk`, `openai-to-claude.ts` translator) and non-streaming (`sanitizeMessage`) paths
+
+---
+
+## [3.0.7] — 2026-03-25
+
+### 🐛 Bug Fixes
+
+- **Antigravity Token Refresh:** Fixed `client_secret is missing` error for npm-installed users — the `clientSecretDefault` was empty in providerRegistry, causing Google to reject token refresh requests (#588)
+- **OpenCode Zen Models:** Added `modelsUrl` to the OpenCode Zen registry entry so "Import from /models" works correctly (#612)
+- **Streaming Artifacts:** Fixed excessive newlines left in responses after thinking-tag signature stripping (#626)
+- **Proxy Fallback:** Added automatic retry without proxy when SOCKS5 relay fails
+- **Proxy Test:** Test endpoint now resolves real credentials from DB via proxyId
+
+### ✨ New Features
+
+- **Playground Account/Key Selector:** Persistent, always-visible dropdown to select specific provider accounts/keys for testing — fetches all connections at startup and filters by selected provider
+- **CLI Tools Dynamic Models:** Model selection now dynamically fetches from `/v1/models` API — providers like Kiro now show their full model catalog
+- **Antigravity Model List:** Updated with Claude Sonnet 4.5, Claude Sonnet 4, GPT 5, GPT 5 Mini; enabled `passthroughModels` for dynamic model access (#628)
+
+### 🔧 Maintenance
+
+- Merged PR #625 — Provider Limits light mode background fix
+
+---
+
+## [3.0.6] — 2026-03-25
+
+### 🐛 Bug Fixes
+
+- **Limits/Proxy:** Fixed Codex limit fetching for accounts behind SOCKS5 proxies — token refresh now runs inside proxy context
+- **CI:** Fixed integration test `v1/models` assertion failure in CI environments without provider connections
+- **Settings:** Proxy test button now shows success/failure results immediately (previously hidden behind health data)
+
+### ✨ New Features
+
+- **Playground:** Added Account selector dropdown — test specific connections individually when a provider has multiple accounts
+
+### 🔧 Maintenance
+
+- Merged PR #623 — LongCat API base URL path correction
+
+---
+
+## [3.0.5] — 2026-03-25
+
+### ✨ New Features
+
+- **Limits UI:** Added tag grouping feature to the connections dashboard to improve visual organization for accounts with custom tags.
+
+---
+
+## [3.0.4] — 2026-03-25
+
+### 🐛 Bug Fixes
+
+- **Streaming:** Fixed `TextDecoder` state corruption inside combo `sanitize` TransformStream which caused SSE garbled output matching multibyte characters (PR #614)
+- **Providers UI:** Safely render HTML tags inside provider connection error tooltips using `dangerouslySetInnerHTML`
+- **Proxy Settings:** Added missing `username` and `password` payload body properties allowing authenticated proxies to be successfully verified from the Dashboard.
+- **Provider API:** Bound soft exception returns to `getCodexUsage` preventing API HTTP 500 failures when token fetch fails
+
+---
+
+## [3.0.3] — 2026-03-25
+
+### ✨ New Features
+
+- **Auto-Sync Models:** Added a UI toggle and `sync-models` endpoint to automatically synchronise model lists per provider using a scheduled interval scheduler (PR #597)
+
+### 🐛 Bug Fixes
+
+- **Timeouts:** Elevated default proxies `FETCH_TIMEOUT_MS` and `STREAM_IDLE_TIMEOUT_MS` to 10 minutes to properly support deep reasoning models (like o1) without aborting requests (Fixes #609)
+- **CLI Tool Detection:** Improved cross-platform detection handling NVM paths, Windows `PATHEXT` (preventing `.cmd` wrappers issue), and custom NPM prefixes (PR #598)
+- **Streaming Logs:** Implemented `tool_calls` delta accumulation in streaming response logs so function calls are tracked and persisted accurately in DB (PR #603)
+- **Model Catalog:** Removed auth exemption, properly hiding `comfyui` and `sdwebui` models when no provider is explicitly configured (PR #599)
+
+### 🌐 Translations
+
+- **cs:** Improved Czech translation strings across the app (PR #601)
+
+## [3.0.2] — 2026-03-25
+
+### 🚀 Enhancements & Features
+
+#### feat(ui): Connection Tag Grouping
+
+- Added a Tag/Group field to `EditConnectionModal` (stored in `providerSpecificData.tag`) without requiring DB schema migrations.
+- Connections in the provider view now dynamically group by tag with visual dividers.
+- Untagged connections appear first without a header, followed by tagged groups in alphabetical order.
+- The tag grouping automatically applies to the Codex/Copilot/Antigravity Limits section since toggles exist inside connection rows.
+
+### 🐛 Bug Fixes
+
+#### fix(ui): Proxy Management UI Stabilization
+
+- **Missing badges on connection cards:** Fixed by using `resolveProxyForConnection()` rather than static mapping.
+- **Test Connection disabled in saved mode:** Enabled the Test button by resolving proxy config from the saved list.
+- **Config Modal freezing:** Added `onClose()` calls after save/clear to prevent the UI from freezing.
+- **Double usage counting:** `ProxyRegistryManager` now loads usage eagerly on mount with deduplication by `scope` + `scopeId`. Usage counts were replaced with a Test button displaying IP/latency inline.
+
+#### fix(translator): `function_call` prefix stripping
+
+- Repaired an incomplete fix from PR #607 where only `tool_use` blocks stripped Claude's `proxy_` tool prefix. Now, clients using the OpenAI Responses API format will also correctly receive tool tools without the `proxy_` prefix.
+
+---
+
+## [3.0.1] — 2026-03-25
+
+### 🔧 Hotfix Patch — Critical Bug Fixes
+
+Three critical regressions reported by users after the v3.0.0 launch have been resolved.
+
+#### fix(translator): strip `proxy_` prefix in non-streaming Claude responses (#605)
+
+The `proxy_` prefix added by Claude OAuth was only stripped from **streaming** responses. In **non-streaming** mode, `translateNonStreamingResponse` had no access to the `toolNameMap`, causing clients to receive mangled tool names like `proxy_read_file` instead of `read_file`.
+
+**Fix:** Added optional `toolNameMap` parameter to `translateNonStreamingResponse` and applied prefix stripping in the Claude `tool_use` block handler. `chatCore.ts` now passes the map through.
+
+#### fix(validation): add LongCat specialty validator to skip /models probe (#592)
+
+LongCat AI does not expose `GET /v1/models`. The generic `validateOpenAICompatibleProvider` validator fell through to a chat-completions fallback only if `validationModelId` was set, which LongCat doesn't configure. This caused provider validation to fail with a misleading error on add/save.
+
+**Fix:** Added `longcat` to the specialty validators map, probing `/chat/completions` directly and treating any non-auth response as a pass.
+
+#### fix(translator): normalize object tool schemas for Anthropic (#595)
+
+MCP tools (e.g. `pencil`, `computer_use`) forward tool definitions with `{type:"object"}` but without a `properties` field. Anthropic's API rejects these with: `object schema missing properties`.
+
+**Fix:** In `openai-to-claude.ts`, inject `properties: {}` as a safe default when `type` is `"object"` and `properties` is absent.
+
+---
+
+### 🔀 Community PRs Merged (2)
+
+| PR | Author | Summary |
+| -------- | ------- | -------------------------------------------------------------------------- |
+| **#589** | @flobo3 | docs(i18n): fix Russian translation for Playground and Testbed |
+| **#591** | @rdself | fix(ui): improve Provider Limits light mode contrast and plan tier display |
+
+---
+
+### ✅ Issues Resolved
+
+`#592` `#595` `#605`
+
+---
+
+### 🧪 Tests
+
+- **926 tests, 0 failures** (unchanged from v3.0.0)
+
+---
+
+## [3.0.0] — 2026-03-24
+
+### 🎉 OmniRoute v3.0.0 — The Free AI Gateway, Now with 67+ Providers
+
+> **The biggest release ever.** From 36 providers in v2.9.5 to **67+ providers** in v3.0.0 — with MCP Server, A2A Protocol, auto-combo engine, Provider Icons, Registered Keys API, 926 tests, and contributions from **12 community members** across **10 merged PRs**.
+>
+> Consolidated from v3.0.0-rc.1 through rc.17 (17 release candidates over 3 days of intense development).
+
+---
+
+### 🆕 New Providers (+31 since v2.9.5)
+
+| Provider | Alias | Tier | Notes |
+| ----------------------------- | --------------- | ----------- | --------------------------------------------------------------------------- |
+| **OpenCode Zen** | `opencode-zen` | Free | 3 models via `opencode.ai/zen/v1` (PR #530 by @kang-heewon) |
+| **OpenCode Go** | `opencode-go` | Paid | 4 models via `opencode.ai/zen/go/v1` (PR #530 by @kang-heewon) |
+| **LongCat AI** | `lc` | Free | 50M tokens/day (Flash-Lite) + 500K/day (Chat/Thinking) during public beta |
+| **Pollinations AI** | `pol` | Free | No API key needed — GPT-5, Claude, Gemini, DeepSeek V3, Llama 4 (1 req/15s) |
+| **Cloudflare Workers AI** | `cf` | Free | 10K Neurons/day — ~150 LLM responses or 500s Whisper audio, edge inference |
+| **Scaleway AI** | `scw` | Free | 1M free tokens for new accounts — EU/GDPR compliant (Paris) |
+| **AI/ML API** | `aiml` | Free | $0.025/day free credits — 200+ models via single endpoint |
+| **Puter AI** | `pu` | Free | 500+ models (GPT-5, Claude Opus 4, Gemini 3 Pro, Grok 4, DeepSeek V3) |
+| **Alibaba Cloud (DashScope)** | `ali` | Paid | International + China endpoints via `alicode`/`alicode-intl` |
+| **Alibaba Coding Plan** | `bcp` | Paid | Alibaba Model Studio with Anthropic-compatible API |
+| **Kimi Coding (API Key)** | `kmca` | Paid | Dedicated API-key-based Kimi access (separate from OAuth) |
+| **MiniMax Coding** | `minimax` | Paid | International endpoint |
+| **MiniMax (China)** | `minimax-cn` | Paid | China-specific endpoint |
+| **Z.AI (GLM-5)** | `zai` | Paid | Zhipu AI next-gen GLM models |
+| **Vertex AI** | `vertex` | Paid | Google Cloud — Service Account JSON or OAuth access_token |
+| **Ollama Cloud** | `ollamacloud` | Paid | Ollama's hosted API service |
+| **Synthetic** | `synthetic` | Paid | Passthrough models gateway |
+| **Kilo Gateway** | `kg` | Paid | Passthrough models gateway |
+| **Perplexity Search** | `pplx-search` | Paid | Dedicated search-grounded endpoint |
+| **Serper Search** | `serper-search` | Paid | Web search API integration |
+| **Brave Search** | `brave-search` | Paid | Brave Search API integration |
+| **Exa Search** | `exa-search` | Paid | Neural search API integration |
+| **Tavily Search** | `tavily-search` | Paid | AI search API integration |
+| **NanoBanana** | `nb` | Paid | Image generation API |
+| **ElevenLabs** | `el` | Paid | Text-to-speech voice synthesis |
+| **Cartesia** | `cartesia` | Paid | Ultra-fast TTS voice synthesis |
+| **PlayHT** | `playht` | Paid | Voice cloning and TTS |
+| **Inworld** | `inworld` | Paid | AI character voice chat |
+| **SD WebUI** | `sdwebui` | Self-hosted | Stable Diffusion local image generation |
+| **ComfyUI** | `comfyui` | Self-hosted | ComfyUI local workflow node-based generation |
+| **GLM Coding** | `glm` | Paid | BigModel/Zhipu coding-specific endpoint |
+
+**Total: 67+ providers** (4 Free, 8 OAuth, 55 API Key) + unlimited OpenAI/Anthropic-Compatible custom providers.
+
+---
+
+### ✨ Major Features
+
+#### 🔑 Registered Keys Provisioning API (#464)
+
+Auto-generate and issue OmniRoute API keys programmatically with per-provider and per-account quota enforcement.
+
+| Endpoint | Method | Description |
+| ------------------------------- | ------------ | ------------------------------------------------ |
+| `/api/v1/registered-keys` | `POST` | Issue a new key — raw key returned **once only** |
+| `/api/v1/registered-keys` | `GET` | List registered keys (masked) |
+| `/api/v1/registered-keys/{id}` | `GET/DELETE` | Get metadata / Revoke |
+| `/api/v1/quotas/check` | `GET` | Pre-validate quota before issuing |
+| `/api/v1/providers/{id}/limits` | `GET/PUT` | Configure per-provider issuance limits |
+| `/api/v1/accounts/{id}/limits` | `GET/PUT` | Configure per-account issuance limits |
+| `/api/v1/issues/report` | `POST` | Report quota events to GitHub Issues |
+
+**Security:** Keys stored as SHA-256 hashes. Raw key shown once on creation, never retrievable again.
+
+#### 🎨 Provider Icons via @lobehub/icons (#529)
+
+130+ provider logos using `@lobehub/icons` React components (SVG). Fallback chain: **Lobehub SVG → existing PNG → generic icon**. Applied across Dashboard, Providers, and Agents pages with standardized `ProviderIcon` component.
+
+#### 🔄 Model Auto-Sync Scheduler (#488)
+
+Auto-refreshes model lists for connected providers every **24 hours**. Runs on server startup. Configurable via `MODEL_SYNC_INTERVAL_HOURS`.
+
+#### 🔀 Per-Model Combo Routing (#563)
+
+Map model name patterns (glob) to specific combos for automatic routing:
+
+- `claude-sonnet*` → code-combo, `gpt-4o*` → openai-combo, `gemini-*` → google-combo
+- New `model_combo_mappings` table with glob-to-regex matching
+- Dashboard UI section: "Model Routing Rules" with inline add/edit/toggle/delete
+
+#### 🧭 API Endpoints Dashboard
+
+Interactive catalog, webhooks management, OpenAPI viewer — all in one tabbed page at `/dashboard/endpoint`.
+
+#### 🔍 Web Search Providers
+
+5 new search provider integrations: **Perplexity Search**, **Serper**, **Brave Search**, **Exa**, **Tavily** — enabling grounded AI responses with real-time web data.
+
+#### 📊 Search Analytics
+
+New tab in `/dashboard/analytics` — provider breakdown, cache hit rate, cost tracking. API: `GET /api/v1/search/analytics`.
+
+#### 🛡️ Per-API-Key Rate Limits (#452)
+
+`max_requests_per_day` and `max_requests_per_minute` columns with in-memory sliding-window enforcement returning HTTP 429.
+
+#### 🎵 Media Playground
+
+Full media generation playground at `/dashboard/media`: Image Generation, Video, Music, Audio Transcription (2GB upload limit), and Text-to-Speech.
+
+---
+
+### 🔒 Security & CI/CD
+
+- **CodeQL remediation** — Fixed 10+ alerts: 6 polynomial-redos, 1 insecure-randomness (`Math.random()` → `crypto.randomUUID()`), 1 shell-command-injection
+- **Route validation** — Zod schemas + `validateBody()` on **176/176 API routes** — CI enforced
+- **CVE fix** — dompurify XSS vulnerability (GHSA-v2wj-7wpq-c8vv) resolved via npm overrides
+- **Flatted** — Bumped 3.3.3 → 3.4.2 (CWE-1321 prototype pollution)
+- **Docker** — Upgraded `docker/setup-buildx-action` v3 → v4
+
+---
+
+### 🐛 Bug Fixes (40+)
+
+#### OAuth & Auth
+
+- **#537** — Gemini CLI OAuth: clear actionable error when `GEMINI_OAUTH_CLIENT_SECRET` missing in Docker
+- **#549** — CLI settings routes now resolve real API key from `keyId` (not masked strings)
+- **#574** — Login no longer freezes after skipping wizard password setup
+- **#506** — Cross-platform `machineId` rewritten (Windows REG.exe → macOS ioreg → Linux → hostname fallback)
+
+#### Providers & Routing
+
+- **#536** — LongCat AI: fixed `baseUrl` and `authHeader`
+- **#535** — Pinned model override: `body.model` correctly set to `pinnedModel`
+- **#570** — Unprefixed Claude models now resolve to Anthropic provider
+- **#585** — `` internal tags no longer leak to clients in SSE streaming
+- **#493** — Custom provider model naming no longer mangled by prefix stripping
+- **#490** — Streaming + context cache protection via `TransformStream` injection
+- **#511** — `` tag injected into first content chunk (not after `[DONE]`)
+
+#### CLI & Tools
+
+- **#527** — Claude Code + Codex loop: `tool_result` blocks now converted to text
+- **#524** — OpenCode config saved correctly (XDG_CONFIG_HOME, TOML format)
+- **#522** — API Manager: removed misleading "Copy masked key" button
+- **#546** — `--version` returning `unknown` on Windows (PR by @k0valik)
+- **#544** — Secure CLI tool detection via known installation paths (PR by @k0valik)
+- **#510** — Windows MSYS2/Git-Bash paths normalized automatically
+- **#492** — CLI detects `mise`/`nvm`-managed Node when `app/server.js` missing
+
+#### Streaming & SSE
+
+- **PR #587** — Revert `resolveDataDir` import in responsesTransformer for Cloudflare Workers compat (@k0valik)
+- **PR #495** — Bottleneck 429 infinite wait: drop waiting jobs on rate limit (@xandr0s)
+- **#483** — Stop trailing `data: null` after `[DONE]` signal
+- **#473** — Zombie SSE streams: timeout reduced 300s → 120s for faster fallback
+
+#### Media & Transcription
+
+- **Transcription** — Deepgram `video/mp4` → `audio/mp4` MIME mapping, auto language detection, punctuation
+- **TTS** — `[object Object]` error display fixed for ElevenLabs-style nested errors
+- **Upload limits** — Media transcription increased to 2GB (nginx `client_max_body_size 2g` + `maxDuration=300`)
+
+---
+
+### 🔧 Infrastructure & Improvements
+
+#### Sub2api Gap Analysis (T01–T15 + T23–T42)
+
+- **T01** — `requested_model` column in call logs (migration 009)
+- **T02** — Strip empty text blocks from nested `tool_result.content`
+- **T03** — Parse `x-codex-5h-*` / `x-codex-7d-*` quota headers
+- **T04** — `X-Session-Id` header for external sticky routing
+- **T05** — Rate-limit DB persistence with dedicated API
+- **T06** — Account deactivated → permanent block (1-year cooldown)
+- **T07** — X-Forwarded-For IP validation (`extractClientIp()`)
+- **T08** — Per-API-key session limits with sliding-window enforcement
+- **T09** — Codex vs Spark rate-limit scopes (separate pools)
+- **T10** — Credits exhausted → distinct 1h cooldown fallback
+- **T11** — `max` reasoning effort → 131072 budget tokens
+- **T12** — MiniMax M2.7 pricing entries
+- **T13** — Stale quota display fix (reset window awareness)
+- **T14** — Proxy fast-fail TCP check (≤2s, cached 30s)
+- **T15** — Array content normalization for Anthropic
+- **T23** — Intelligent quota reset fallback (header extraction)
+- **T24** — `503` cooldown + `406` mapping
+- **T25** — Provider validation fallback
+- **T29** — Vertex AI Service Account JWT auth
+- **T33** — Thinking level to budget conversion
+- **T36** — `403` vs `429` error classification
+- **T38** — Centralized model specifications (`modelSpecs.ts`)
+- **T39** — Endpoint fallback for `fetchAvailableModels`
+- **T41** — Background task auto-redirect to flash models
+- **T42** — Image generation aspect ratio mapping
+
+#### Other Improvements
+
+- **Per-model upstream custom headers** — via configuration UI (PR #575 by @zhangqiang8vip)
+- **Model context length** — configurable in model metadata (PR #578 by @hijak)
+- **Model prefix stripping** — option to remove provider prefix from model names (PR #582 by @jay77721)
+- **Gemini CLI deprecation** — marked deprecated with Google OAuth restriction warning
+- **YAML parser** — replaced custom parser with `js-yaml` for correct OpenAPI spec parsing
+- **ZWS v5** — HMR leak fix (485 DB connections → 1, memory 2.4GB → 195MB)
+- **Log export** — New JSON export button on dashboard with time range dropdown
+- **Update notification banner** — dashboard homepage shows when new versions are available
+
+---
+
+### 🌐 i18n & Documentation
+
+- **30 languages** at 100% parity — 2,788 missing keys synced
+- **Czech** — Full translation: 22 docs, 2,606 UI strings (PR by @zen0bit)
+- **Chinese (zh-CN)** — Complete retranslation (PR by @only4copilot)
+- **VM Deployment Guide** — Translated to English as source document
+- **API Reference** — Added `/v1/embeddings` and `/v1/audio/speech` endpoints
+- **Provider count** — Updated from 36+/40+/44+ to **67+** across README and all 30 i18n READMEs
+
+---
+
+### 🔀 Community PRs Merged (10)
+
+| PR | Author | Summary |
+| -------- | --------------- | -------------------------------------------------------------------- |
+| **#587** | @k0valik | fix(sse): revert resolveDataDir import for Cloudflare Workers compat |
+| **#582** | @jay77721 | feat(proxy): model name prefix stripping option |
+| **#581** | @jay77721 | fix(npm): link electron-release to npm-publish workflow |
+| **#578** | @hijak | feat: configurable context length in model metadata |
+| **#575** | @zhangqiang8vip | feat: per-model upstream headers, compat PATCH, chat alignment |
+| **#562** | @coobabm | fix: MCP session management, Claude passthrough, detectFormat |
+| **#561** | @zen0bit | fix(i18n): Czech translation corrections |
+| **#555** | @k0valik | fix(sse): centralized `resolveDataDir()` for path resolution |
+| **#546** | @k0valik | fix(cli): `--version` returning `unknown` on Windows |
+| **#544** | @k0valik | fix(cli): secure CLI tool detection via installation paths |
+| **#542** | @rdself | fix(ui): light mode contrast CSS theme variables |
+| **#530** | @kang-heewon | feat: OpenCode Zen + Go providers with `OpencodeExecutor` |
+| **#512** | @zhangqiang8vip | feat: per-protocol model compatibility (`compatByProtocol`) |
+| **#497** | @zhangqiang8vip | fix: dev-mode HMR resource leaks (ZWS v5) |
+| **#495** | @xandr0s | fix: Bottleneck 429 infinite wait (drop waiting jobs) |
+| **#494** | @zhangqiang8vip | feat: MiniMax developer→system role fix |
+| **#480** | @prakersh | fix: stream flush usage extraction |
+| **#479** | @prakersh | feat: Codex 5.3/5.4 and Anthropic pricing entries |
+| **#475** | @only4copilot | feat(i18n): improved Chinese translation |
+
+**Thank you to all contributors!** 🙏
+
+---
+
+### 📋 Issues Resolved (50+)
+
+`#452` `#458` `#462` `#464` `#466` `#473` `#474` `#481` `#483` `#487` `#488` `#489` `#490` `#491` `#492` `#493` `#506` `#508` `#509` `#510` `#511` `#513` `#520` `#521` `#522` `#524` `#525` `#527` `#529` `#531` `#532` `#535` `#536` `#537` `#541` `#546` `#549` `#563` `#570` `#574` `#585`
+
+---
+
+### 🧪 Tests
+
+- **926 tests, 0 failures** (up from 821 in v2.9.5)
+- +105 new tests covering: model-combo mappings, registered keys, OpencodeExecutor, Bailian provider, route validation, error classification, aspect ratio mapping, and more
+
+---
+
+### 📦 Database Migrations
+
+| Migration | Description |
+| --------- | --------------------------------------------------------------------- |
+| **008** | `registered_keys`, `provider_key_limits`, `account_key_limits` tables |
+| **009** | `requested_model` column in `call_logs` |
+| **010** | `model_combo_mappings` table for per-model combo routing |
+
+---
+
+### ⬆️ Upgrading from v2.9.5
+
+```bash
+# npm
+npm install -g omniroute@3.0.0
+
+# Docker
+docker pull diegosouzapw/omniroute:3.0.0
+
+# Migrations run automatically on first startup
+```
+
+> **Breaking changes:** None. All existing configurations, combos, and API keys are preserved.
+> Database migrations 008-010 run automatically on startup.
+
+---
+
+## [3.0.0-rc.17] — 2026-03-24
+
+### 🔒 Security & CI/CD
+
+- **CodeQL remediation** — Fixed 10+ alerts:
+ - 6 polynomial-redos in `provider.ts` / `chatCore.ts` (replaced `(?:^|/)` alternation patterns with segment-based matching)
+ - 1 insecure-randomness in `acp/manager.ts` (`Math.random()` → `crypto.randomUUID()`)
+ - 1 shell-command-injection in `prepublish.mjs` (`JSON.stringify()` path escaping)
+- **Route validation** — Added Zod schemas + `validateBody()` to 5 routes missing validation:
+ - `model-combo-mappings` (POST, PUT), `webhooks` (POST, PUT), `openapi/try` (POST)
+ - CI `check:route-validation:t06` now passes: **176/176 routes validated**
+
+### 🐛 Bug Fixes
+
+- **#585** — `` internal tags no longer leak to clients in SSE responses. Added outbound sanitization `TransformStream` in `combo.ts`
+
+### ⚙️ Infrastructure
+
+- **Docker** — Upgraded `docker/setup-buildx-action` from v3 → v4 (Node.js 20 deprecation fix)
+- **CI cleanup** — Deleted 150+ failed/cancelled workflow runs
+
+### 🧪 Tests
+
+- Test suite: **926 tests, 0 failures** (+3 new)
+
+---
+
+## [3.0.0-rc.16] — 2026-03-24
+
+### ✨ New Features
+
+- Increased media transcription limits
+- Added Model Context Length to registry metadata
+- Added per-model upstream custom headers via configuration UI
+- Fixed multiple bugs, Zod valiadation for patches, and resolved various community issues.
+
+## [3.0.0-rc.15] — 2026-03-24
+
+### ✨ New Features
+
+- **#563** — Per-model Combo Routing: map model name patterns (glob) to specific combos for automatic routing
+ - New `model_combo_mappings` table (migration 010) with pattern, combo_id, priority, enabled
+ - `resolveComboForModel()` DB function with glob-to-regex matching (case-insensitive, `*` and `?` wildcards)
+ - `getComboForModel()` in `model.ts`: augments `getCombo()` with model-pattern fallback
+ - `chat.ts`: routing decision now checks model-combo mappings before single-model handling
+ - API: `GET/POST /api/model-combo-mappings`, `GET/PUT/DELETE /api/model-combo-mappings/:id`
+ - Dashboard: "Model Routing Rules" section added to Combos page with inline add/edit/toggle/delete
+ - Examples: `claude-sonnet*` → code-combo, `gpt-4o*` → openai-combo, `gemini-*` → google-combo
+
+### 🌐 i18n
+
+- **Full i18n Sync**: 2,788 missing keys added across 30 language files — all languages now at 100% parity with `en.json`
+- **Agents page i18n**: OpenCode Integration section fully internationalized (title, description, scanning, download labels)
+- **6 new keys** added to `agents` namespace for OpenCode section
+
+### 🎨 UI/UX
+
+- **Provider Icons**: 16 missing provider icons added (3 copied, 2 downloaded, 11 SVG created)
+- **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)
+
+### 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**
+
+### 🧪 Tests
+
+- Test suite: **923 tests, 0 failures** (+15 new model-combo mapping tests)
+
+---
+
+## [3.0.0-rc.14] — 2026-03-23
+
+### 🔀 Community PRs Merged
+
+| PR | Author | Summary |
+| -------- | -------- | -------------------------------------------------------------------------------------------- |
+| **#562** | @coobabm | fix(ux): MCP session management, Claude passthrough normalization, OAuth modal, detectFormat |
+| **#561** | @zen0bit | fix(i18n): Czech translation corrections — HTTP method names and documentation updates |
+
+### 🧪 Tests
+
+- Test suite: **908 tests, 0 failures**
+
+---
+
+## [3.0.0-rc.13] — 2026-03-23
+
+### 🔧 Bug Fixes
+
+- **config:** resolve real API key from `keyId` in CLI settings routes (`codex-settings`, `droid-settings`, `kilo-settings`) to prevent writing masked strings (#549)
+
+---
+
+## [3.0.0-rc.12] — 2026-03-23
+
+### 🔀 Community PRs Merged
+
+| PR | Author | Summary |
+| -------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| **#546** | @k0valik | fix(cli): `--version` returning `unknown` on Windows — use `JSON.parse(readFileSync)` instead of ESM import |
+| **#555** | @k0valik | fix(sse): centralized `resolveDataDir()` for path resolution in credentials, autoCombo, responses logger, and request logger |
+| **#544** | @k0valik | fix(cli): secure CLI tool detection via known installation paths (8 tools) with symlink validation, file-type checks, size bounds, minimal env in healthcheck |
+| **#542** | @rdself | fix(ui): improve light mode contrast — add missing CSS theme variables (`bg-primary`, `bg-subtle`, `text-primary`) and fix dark-only colors in log detail |
+
+### 🔧 Bug Fixes
+
+- **TDZ fix in `cliRuntime.ts`** — `validateEnvPath` was used before initialization at module startup by `getExpectedParentPaths()`. Reordered declarations to fix `ReferenceError`.
+- **Build fixes** — Added `pino` and `pino-pretty` to `serverExternalPackages` to prevent Turbopack from breaking Pino's internal worker loading.
+
+### 🧪 Tests
+
+- Test suite: **905 tests, 0 failures**
+
+---
+
+## [3.0.0-rc.10] — 2026-03-23
+
+### 🔧 Bug Fixes
+
+- **#509 / #508** — Electron build regression: downgraded Next.js from `16.1.x` to `16.0.10` to eliminate Turbopack module-hashing instability that caused blank screens in the Electron desktop bundle.
+- **Unit test fixes** — Corrected two stale test assertions (`nanobanana-image-handler` aspect ratio/resolution, `thinking-budget` Gemini `thinkingConfig` field mapping) that had drifted after recent implementation changes.
+- **#541** — Responded to user feedback about installation complexity; no code changes required.
+
+---
+
+## [3.0.0-rc.9] — 2026-03-23
+
+### ✨ New Features
+
+- **T29** — Vertex AI SA JSON Executor: implemented using the `jose` library to handle JWT/Service Account auth, along with configurable regions in the UI and automatic partner model URL building.
+- **T42** — Image generation aspect ratio mapping: created `sizeMapper` logic for generic OpenAI formats (`size`), added native `imagen3` handling, and updated NanoBanana endpoints to utilize mapped aspect ratios automatically.
+- **T38** — Centralized model specifications: `modelSpecs.ts` created for limits and parameters per model.
+
+### 🔧 Improvements
+
+- **T40** — OpenCode CLI tools integration: native `opencode-zen` and `opencode-go` integration completed in earlier PR.
+
+---
+
+## [3.0.0-rc.8] — 2026-03-23
+
+### 🔧 Bug Fixes & Improvements (Fallback, Quota & Budget)
+
+- **T24** — `503` cooldown await fix + `406` mapping: mapped `406 Not Acceptable` to `503 Service Unavailable` with proper cooldown intervals.
+- **T25** — Provider validation fallback: graceful fallback to standard validation models when a specific `validationModelId` is not present.
+- **T36** — `403` vs `429` provider handling refinement: extracted into `errorClassifier.ts` to properly segregate hard permissions failures (`403`) from rate limits (`429`).
+- **T39** — Endpoint Fallback for `fetchAvailableModels`: implemented a tri-tier mechanism (`/models` -> `/v1/models` -> local generic catalog) + `list_models_catalog` MCP tool updates to reflect `source` and `warning`.
+- **T33** — Thinking level to budget conversion: translates qualitative thinking levels into precise budget allocations.
+- **T41** — Background task auto redirect: routes heavy background evaluation tasks to flash/efficient models automatically.
+- **T23** — Intelligent quota reset fallback: accurately extracts `x-ratelimit-reset` / `retry-after` header values or maps static cooldowns.
+
+---
+
+## [3.0.0-rc.7] — 2026-03-23 _(What's New vs v2.9.5 — will be released as v3.0.0)_
+
+> **Upgrade from v2.9.5:** 16 issues resolved · 2 community PRs merged · 2 new providers · 7 new API endpoints · 3 new features · DB migration 008+009 · 832 tests passing · 15 sub2api gap improvements (T01–T15 complete).
+
+### 🆕 New Providers
+
+| Provider | Alias | Tier | Notes |
+| ---------------- | -------------- | ---- | -------------------------------------------------------------- |
+| **OpenCode Zen** | `opencode-zen` | Free | 3 models via `opencode.ai/zen/v1` (PR #530 by @kang-heewon) |
+| **OpenCode Go** | `opencode-go` | Paid | 4 models via `opencode.ai/zen/go/v1` (PR #530 by @kang-heewon) |
+
+Both providers use the new `OpencodeExecutor` with multi-format routing (`/chat/completions`, `/messages`, `/responses`, `/models/{model}:generateContent`).
+
+---
+
+### ✨ New Features
+
+#### 🔑 Registered Keys Provisioning API (#464)
+
+Auto-generate and issue OmniRoute API keys programmatically with per-provider and per-account quota enforcement.
+
+| Endpoint | Method | Description |
+| ------------------------------------- | --------- | ------------------------------------------------ |
+| `/api/v1/registered-keys` | `POST` | Issue a new key — raw key returned **once only** |
+| `/api/v1/registered-keys` | `GET` | List registered keys (masked) |
+| `/api/v1/registered-keys/{id}` | `GET` | Get key metadata |
+| `/api/v1/registered-keys/{id}` | `DELETE` | Revoke a key |
+| `/api/v1/registered-keys/{id}/revoke` | `POST` | Revoke (for clients without DELETE support) |
+| `/api/v1/quotas/check` | `GET` | Pre-validate quota before issuing |
+| `/api/v1/providers/{id}/limits` | `GET/PUT` | Configure per-provider issuance limits |
+| `/api/v1/accounts/{id}/limits` | `GET/PUT` | Configure per-account issuance limits |
+| `/api/v1/issues/report` | `POST` | Report quota events to GitHub Issues |
+
+**DB — Migration 008:** Three new tables: `registered_keys`, `provider_key_limits`, `account_key_limits`.
+**Security:** Keys stored as SHA-256 hashes. Raw key shown once on creation, never retrievable again.
+**Quota types:** `maxActiveKeys`, `dailyIssueLimit`, `hourlyIssueLimit` per provider and per account.
+**Idempotency:** `idempotency_key` field prevents duplicate issuance. Returns `409 IDEMPOTENCY_CONFLICT` if key was already used.
+**Budget per key:** `dailyBudget` / `hourlyBudget` — limits how many requests a key can route per window.
+**GitHub reporting:** Optional. Set `GITHUB_ISSUES_REPO` + `GITHUB_ISSUES_TOKEN` to auto-create GitHub issues on quota exceeded or issuance failures.
+
+#### 🎨 Provider Icons — @lobehub/icons (#529)
+
+All provider icons in the dashboard now use `@lobehub/icons` React components (130+ providers with SVG).
+Fallback chain: **Lobehub SVG → existing `/providers/{id}.png` → generic icon**. Uses a proper React `ErrorBoundary` pattern.
+
+#### 🔄 Model Auto-Sync Scheduler (#488)
+
+OmniRoute now automatically refreshes model lists for connected providers every **24 hours**.
+
+- Runs on server startup via the existing `/api/sync/initialize` hook
+- Configurable via `MODEL_SYNC_INTERVAL_HOURS` environment variable
+- Covers 16 major providers
+- Records last sync time in the settings database
+
+---
+
+### 🔧 Bug Fixes
+
+#### OAuth & Auth
+
+- **#537 — Gemini CLI OAuth:** Clear actionable error when `GEMINI_OAUTH_CLIENT_SECRET` is missing in Docker/self-hosted deployments. Previously showed cryptic `client_secret is missing` from Google. Now provides specific `docker-compose.yml` and `~/.omniroute/.env` instructions.
+
+#### Providers & Routing
+
+- **#536 — LongCat AI:** Fixed `baseUrl` (`api.longcat.chat/openai`) and `authHeader` (`Authorization: Bearer`).
+- **#535 — Pinned model override:** `body.model` is now correctly set to `pinnedModel` when context-cache protection is active.
+- **#532 — OpenCode Go key validation:** Now uses the `zen/v1` test endpoint (`testKeyBaseUrl`) — same key works for both tiers.
+
+#### CLI & Tools
+
+- **#527 — Claude Code + Codex loop:** `tool_result` blocks are now converted to text instead of dropped, stopping infinite tool-result loops.
+- **#524 — OpenCode config save:** Added `saveOpenCodeConfig()` handler (XDG_CONFIG_HOME aware, writes TOML).
+- **#521 — Login stuck:** Login no longer freezes after skipping password setup — redirects correctly to onboarding.
+- **#522 — API Manager:** Removed misleading "Copy masked key" button (replaced with a lock icon tooltip).
+- **#532 — OpenCode Go config:** Guide settings handler now handles `opencode` toolId.
+
+#### Developer Experience
+
+- **#489 — Antigravity:** Missing `googleProjectId` returns a structured 422 error with reconnect guidance instead of a cryptic crash.
+- **#510 — Windows paths:** MSYS2/Git-Bash paths (`/c/Program Files/...`) are now normalized to `C:\\Program Files\\...` automatically.
+- **#492 — CLI startup:** `omniroute` CLI now detects `mise`/`nvm`-managed Node when `app/server.js` is missing and shows targeted fix instructions.
+
+---
+
+### 📖 Documentation Updates
+
+- **#513** — Docker password reset: `INITIAL_PASSWORD` env var workaround documented
+- **#520** — pnpm: `pnpm approve-builds better-sqlite3` step documented
+
+---
+
+### ✅ Issues Resolved in v3.0.0
+
+`#464` `#488` `#489` `#492` `#510` `#513` `#520` `#521` `#522` `#524` `#527` `#529` `#532` `#535` `#536` `#537`
+
+---
+
+### 🔀 Community PRs Merged
+
+| PR | Author | Summary |
+| -------- | ------------ | ---------------------------------------------------------------------- |
+| **#530** | @kang-heewon | OpenCode Zen + Go providers with `OpencodeExecutor` and improved tests |
+
+---
+
+## [3.0.0-rc.7] - 2026-03-23
+
+### 🔧 Improvements (sub2api Gap Analysis — T05, T08, T09, T13, T14)
+
+- **T05** — Rate-limit DB persistence: `setConnectionRateLimitUntil()`, `isConnectionRateLimited()`, `getRateLimitedConnections()` in `providers.ts`. The existing `rate_limited_until` column is now exposed as a dedicated API — OAuth token refresh must NOT touch this field to prevent rate-limit loops.
+- **T08** — Per-API-key session limit: `max_sessions INTEGER DEFAULT 0` added to `api_keys` via auto-migration. `sessionManager.ts` gains `registerKeySession()`, `unregisterKeySession()`, `checkSessionLimit()`, and `getActiveSessionCountForKey()`. Callers in `chatCore.js` can enforce the limit and decrement on `req.close`.
+- **T09** — Codex vs Spark rate-limit scopes: `getCodexModelScope()` and `getCodexRateLimitKey()` in `codex.ts`. Standard models (`gpt-5.x-codex`, `codex-mini`) get scope `"codex"`; spark models (`codex-spark*`) get scope `"spark"`. Rate-limit keys should be `${accountId}:${scope}` so exhausting one pool doesn't block the other.
+- **T13** — Stale quota display fix: `getEffectiveQuotaUsage(used, resetAt)` returns `0` when the reset window has passed; `formatResetCountdown(resetAt)` returns a human-readable countdown string (e.g. `"2h 35m"`). Both exported from `providers.ts` + `localDb.ts` for dashboard consumption.
+- **T14** — Proxy fast-fail: new `src/lib/proxyHealth.ts` with `isProxyReachable(proxyUrl, timeoutMs=2000)` (TCP check, ≤2s instead of 30s timeout), `getCachedProxyHealth()`, `invalidateProxyHealth()`, and `getAllProxyHealthStatuses()`. Results cached 30s by default; configurable via `PROXY_FAST_FAIL_TIMEOUT_MS` / `PROXY_HEALTH_CACHE_TTL_MS`.
+
+### 🧪 Tests
+
+- Test suite: **832 tests, 0 failures**
+
+---
+
+## [3.0.0-rc.6] - 2026-03-23
+
+### 🔧 Bug Fixes & Improvements (sub2api Gap Analysis — T01–T15)
+
+- **T01** — `requested_model` column in `call_logs` (migration 009): track which model the client originally requested vs the actual routed model. Enables fallback rate analytics.
+- **T02** — Strip empty text blocks from nested `tool_result.content`: prevents Anthropic 400 errors (`text content blocks must be non-empty`) when Claude Code chains tool results.
+- **T03** — Parse `x-codex-5h-*` / `x-codex-7d-*` headers: `parseCodexQuotaHeaders()` + `getCodexResetTime()` extract Codex quota windows for precise cooldown scheduling instead of generic 5-min fallback.
+- **T04** — `X-Session-Id` header for external sticky routing: `extractExternalSessionId()` in `sessionManager.ts` reads `x-session-id` / `x-omniroute-session` headers with `ext:` prefix to avoid collision with internal SHA-256 session IDs. Nginx-compatible (hyphenated header).
+- **T06** — Account deactivated → permanent block: `isAccountDeactivated()` in `accountFallback.ts` detects 401 deactivation signals and applies a 1-year cooldown to prevent retrying permanently dead accounts.
+- **T07** — X-Forwarded-For IP validation: new `src/lib/ipUtils.ts` with `extractClientIp()` and `getClientIpFromRequest()` — skips `unknown`/non-IP entries in `X-Forwarded-For` chains (Nginx/proxy-forwarded requests).
+- **T10** — Credits exhausted → distinct fallback: `isCreditsExhausted()` in `accountFallback.ts` returns 1h cooldown with `creditsExhausted` flag, distinct from generic 429 rate limiting.
+- **T11** — `max` reasoning effort → 131072 budget tokens: `EFFORT_BUDGETS` and `THINKING_LEVEL_MAP` updated; reverse mapping now returns `"max"` for full-budget responses. Unit test updated.
+- **T12** — MiniMax M2.7 pricing entries added: `minimax-m2.7`, `MiniMax-M2.7`, `minimax-m2.7-highspeed` added to pricing table (sub2api PR #1120). M2.5/GLM-4.7/GLM-5/Kimi pricing already existed.
+- **T15** — Array content normalization: `normalizeContentToString()` helper in `openai-to-claude.ts` correctly collapses array-formatted system/tool messages to string before sending to Anthropic.
+
+### 🧪 Tests
+
+- Test suite: **832 tests, 0 failures** (unchanged from rc.5)
+
+---
+
+## [3.0.0-rc.5] - 2026-03-22
+
+### ✨ New Features
+
+- **#464** — Registered Keys Provisioning API: auto-issue API keys with per-provider & per-account quota enforcement
+ - `POST /api/v1/registered-keys` — issue keys with idempotency support
+ - `GET /api/v1/registered-keys` — list (masked) registered keys
+ - `GET /api/v1/registered-keys/{id}` — get key metadata
+ - `DELETE /api/v1/registered-keys/{id}` / `POST ../{id}/revoke` — revoke keys
+ - `GET /api/v1/quotas/check` — pre-validate before issuing
+ - `PUT /api/v1/providers/{id}/limits` — set provider issuance limits
+ - `PUT /api/v1/accounts/{id}/limits` — set account issuance limits
+ - `POST /api/v1/issues/report` — optional GitHub issue reporting
+ - DB migration 008: `registered_keys`, `provider_key_limits`, `account_key_limits` tables
+
+---
+
+## [3.0.0-rc.4] - 2026-03-22
+
+### ✨ New Features
+
+- **#530 (PR)** — OpenCode Zen and OpenCode Go providers added (by @kang-heewon)
+ - New `OpencodeExecutor` with multi-format routing (`/chat/completions`, `/messages`, `/responses`)
+ - 7 models across both tiers
+
+---
+
+## [3.0.0-rc.3] - 2026-03-22
+
+### ✨ New Features
+
+- **#529** — Provider icons now use [@lobehub/icons](https://github.com/lobehub/lobe-icons) with graceful PNG fallback and a `ProviderIcon` component (130+ providers supported)
+- **#488** — Auto-update model lists every 24h via `modelSyncScheduler` (configurable via `MODEL_SYNC_INTERVAL_HOURS`)
+
+### 🔧 Bug Fixes
+
+- **#537** — Gemini CLI OAuth: now shows clear actionable error when `GEMINI_OAUTH_CLIENT_SECRET` is missing in Docker/self-hosted deployments
+
+---
+
+## [3.0.0-rc.2] - 2026-03-22
+
+### 🔧 Bug Fixes
+
+- **#536** — LongCat AI key validation: fixed baseUrl (`api.longcat.chat/openai`) and authHeader (`Authorization: Bearer`)
+- **#535** — Pinned model override: `body.model` is now set to `pinnedModel` when context-cache protection detects a pinned model
+- **#524** — OpenCode config now saved correctly: added `saveOpenCodeConfig()` handler (XDG_CONFIG_HOME aware, writes TOML)
+
+---
+
+## [3.0.0-rc.1] - 2026-03-22
+
+### 🔧 Bug Fixes
+
+- **#521** — Login no longer gets stuck after skipping password setup (redirects to onboarding)
+- **#522** — API Manager: Removed misleading "Copy masked key" button (replaced with lock icon tooltip)
+- **#527** — Claude Code + Codex superpowers loop: `tool_result` blocks now converted to text instead of dropped
+- **#532** — OpenCode GO API key validation now uses the correct `zen/v1` endpoint (`testKeyBaseUrl`)
+- **#489** — Antigravity: missing `googleProjectId` returns structured 422 error with reconnect guidance
+- **#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
+
+### Dokumentace
+
+- **#513** — Docker password reset: `INITIAL_PASSWORD` env var workaround documented
+- **#520** — pnpm: `pnpm approve-builds better-sqlite3` documented
+
+### ✅ Closed Issues
+
+#489, #492, #510, #513, #520, #521, #522, #525, #527, #532
+
+---
+
+## [2.9.5] — 2026-03-22
+
+> Sprint: New OpenCode providers, embedding credentials fix, CLI masked key bug, CACHE_TAG_PATTERN fix.
+
+### 🐛 Bug Fixes
+
+- **CLI tools save masked API key to config files** — `claude-settings`, `cline-settings`, and `openclaw-settings` POST routes now accept a `keyId` param and resolve the real API key from DB before writing to disk. `ClaudeToolCard` updated to send `keyId` instead of the masked display string. Fixes #523, #526.
+- **Custom embedding providers: `No credentials` error** — `/v1/embeddings` now tracks `credentialsProviderId` separately from the routing prefix, so credentials are fetched from the matching provider node ID rather than the public prefix string. Fixes a regression where `google/gemini-embedding-001` and similar custom-provider models would always fail with a credentials error. Fixes #532-related. (PR #528 by @jacob2826)
+- **Context cache protection regex misses `\n` prefix** — `CACHE_TAG_PATTERN` in `comboAgentMiddleware.ts` updated to match both literal `\n` (backslash-n) and actual newline U+000A that `combo.ts` streaming injects around the `` tag after fix #515. Fixes #531.
+
+### ✨ New Providers
+
+- **OpenCode Zen** — Free tier gateway at `opencode.ai/zen/v1` with 3 models: `minimax-m2.5-free`, `big-pickle`, `gpt-5-nano`
+- **OpenCode Go** — Subscription service at `opencode.ai/zen/go/v1` with 4 models: `glm-5`, `kimi-k2.5`, `minimax-m2.7` (Claude format), `minimax-m2.5` (Claude format)
+- Both providers use the new `OpencodeExecutor` which routes dynamically to `/chat/completions`, `/messages`, `/responses`, or `/models/{model}:generateContent` based on the requested model. (PR #530 by @kang-heewon)
+
+---
+
+## [2.9.4] — 2026-03-21
+
+> Sprint: Bug fixes — preserve Codex prompt cache key, fix tagContent JSON escaping, sync expired token status to DB.
+
+### 🐛 Bug Fixes
+
+- **fix(translator)**: Preserve `prompt_cache_key` in Responses API → Chat Completions translation (#517)
+ — The field is a cache-affinity signal used by Codex; stripping it was preventing prompt cache hits.
+ Fixed in `openai-responses.ts` and `responsesApiHelper.ts`.
+
+- **fix(combo)**: Escape `\n` in `tagContent` so injected JSON string is valid (#515)
+ — Template literal newlines (U+000A) are not allowed unescaped inside JSON string values.
+ Replaced with `\\n` literal sequences in `open-sse/services/combo.ts`.
+
+- **fix(usage)**: Sync expired token status back to DB on live auth failure (#491)
+ — When the Limits & Quotas live check returns 401/403, the connection `testStatus` is now updated
+ to `"expired"` in the database so the Providers page reflects the same degraded state.
+ Fixed in `src/app/api/usage/[connectionId]/route.ts`.
+
+---
+
+## [2.9.3] — 2026-03-21
+
+> Sprint: Add 5 new free AI providers — LongCat, Pollinations, Cloudflare AI, Scaleway, AI/ML API.
+
+### ✨ New Providers
+
+- **feat(providers/longcat)**: Add LongCat AI (`lc/`) — 50M tokens/day free (Flash-Lite) + 500K/day (Chat/Thinking) during public beta. OpenAI-compatible, standard Bearer auth.
+- **feat(providers/pollinations)**: Add Pollinations AI (`pol/`) — no API key required. Proxies GPT-5, Claude, Gemini, DeepSeek V3, Llama 4 (1 req/15s free). Custom executor handles optional auth.
+- **feat(providers/cloudflare-ai)**: Add Cloudflare Workers AI (`cf/`) — 10K Neurons/day free (~150 LLM responses or 500s Whisper audio). 50+ models on global edge. Custom executor builds dynamic URL with `accountId` from credentials.
+- **feat(providers/scaleway)**: Add Scaleway Generative APIs (`scw/`) — 1M free tokens for new accounts. EU/GDPR compliant (Paris). Qwen3 235B, Llama 3.1 70B, Mistral Small 3.2.
+- **feat(providers/aimlapi)**: Add AI/ML API (`aiml/`) — $0.025/day free credit, 200+ models (GPT-4o, Claude, Gemini, Llama) via single aggregator endpoint.
+
+### 🔄 Provider Updates
+
+- **feat(providers/together)**: Add `hasFree: true` + 3 permanently free model IDs: `Llama-3.3-70B-Instruct-Turbo-Free`, `Llama-Vision-Free`, `DeepSeek-R1-Distill-Llama-70B-Free`
+- **feat(providers/gemini)**: Add `hasFree: true` + `freeNote` (1,500 req/day, no credit card needed, aistudio.google.com)
+- **chore(providers/gemini)**: Rename display name to `Gemini (Google AI Studio)` for clarity
+
+### ⚙️ Infrastructure
+
+- **feat(executors/pollinations)**: New `PollinationsExecutor` — omits `Authorization` header when no API key provided
+- **feat(executors/cloudflare-ai)**: New `CloudflareAIExecutor` — dynamic URL construction requires `accountId` in provider credentials
+- **feat(executors)**: Register `pollinations`, `pol`, `cloudflare-ai`, `cf` executor mappings
+
+### 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
+- **docs(readme)**: Updated pricing table with 4 new free tier rows
+- **docs(i18n/pt-BR)**: Updated pricing table + added LongCat/Pollinations/Cloudflare AI/Scaleway sections in Portuguese
+- **docs(new-features/ai)**: 10 task spec files + master implementation plan in `docs/new-features/ai/`
+
+### 🧪 Tests
+
+- Test suite: **821 tests, 0 failures** (unchanged)
+
+---
+
+## [2.9.2] — 2026-03-21
+
+> Sprint: Fix media transcription (Deepgram/HuggingFace Content-Type, language detection) and TTS error display.
+
+### 🐛 Bug Fixes
+
+- **fix(transcription)**: Deepgram and HuggingFace audio transcription now correctly map `video/mp4` → `audio/mp4` and other media MIME types via new `resolveAudioContentType()` helper. Previously, uploading `.mp4` files consistently returned "No speech detected" because Deepgram was receiving `Content-Type: video/mp4`.
+- **fix(transcription)**: Added `detect_language=true` to Deepgram requests — auto-detects audio language (Portuguese, Spanish, etc.) instead of defaulting to English. Fixes non-English transcriptions returning empty or garbage results.
+- **fix(transcription)**: Added `punctuate=true` to Deepgram requests for higher-quality transcription output with correct punctuation.
+- **fix(tts)**: `[object Object]` error display in Text-to-Speech responses fixed in both `audioSpeech.ts` and `audioTranscription.ts`. The `upstreamErrorResponse()` function now correctly extracts nested string messages from providers like ElevenLabs that return `{ error: { message: "...", status_code: 401 } }` instead of a flat error string.
+
+### 🧪 Tests
+
+- Test suite: **821 tests, 0 failures** (unchanged)
+
+### Triaged Issues
+
+- **#508** — Tool call format regression: requested proxy logs and provider chain info (`needs-info`)
+- **#510** — Windows CLI healthcheck path: requested shell/Node version info (`needs-info`)
+- **#485** — Kiro MCP tool calls: closed as external Kiro issue (not OmniRoute)
+- **#442** — Baseten /models endpoint: closed (documented manual workaround)
+- **#464** — Key provisioning API: acknowledged as roadmap item
+
+---
+
+## [2.9.1] — 2026-03-21
+
+> Sprint: Fix SSE omniModel data loss, merge per-protocol model compatibility.
+
+### Bug Fixes
+
+- **#511** — Critical: `` tag was sent after `finish_reason:stop` in SSE streams, causing data loss. Tag is now injected into the first non-empty content chunk, guaranteeing delivery before SDKs close the connection.
+
+### Merged PRs
+
+- **PR #512** (@zhangqiang8vip): Per-protocol model compatibility — `normalizeToolCallId` and `preserveOpenAIDeveloperRole` can now be configured per client protocol (OpenAI, Claude, Responses API). New `compatByProtocol` field in model config with Zod validation.
+
+### Triaged Issues
+
+- **#510** — Windows CLI healthcheck_failed: requested PATH/version info
+- **#509** — Turbopack Electron regression: upstream Next.js bug, documented workarounds
+- **#508** — macOS black screen: suggested `--disable-gpu` workaround
+
+---
+
+## [2.9.0] — 2026-03-20
+
+> Sprint: Cross-platform machineId fix, per-API-key rate limits, streaming context cache, Alibaba DashScope, search analytics, ZWS v5, and 8 issues closed.
+
+### ✨ New Features
+
+- **feat(search)**: Search Analytics tab in `/dashboard/analytics` — provider breakdown, cache hit rate, cost tracking. New API: `GET /api/v1/search/analytics` (#feat/search-provider-routing)
+- **feat(provider)**: Alibaba Cloud DashScope added with custom endpoint path validation — configurable `chatPath` and `modelsPath` per node (#feat/custom-endpoint-paths)
+- **feat(api)**: Per-API-key request-count limits — `max_requests_per_day` and `max_requests_per_minute` columns with in-memory sliding-window enforcement returning HTTP 429 (#452)
+- **feat(dev)**: ZWS v5 — HMR leak fix (485 DB connections → 1), memory 2.4GB → 195MB, `globalThis` singletons, Edge Runtime warning fix (@zhangqiang8vip)
+
+### 🐛 Bug Fixes
+
+- **fix(#506)**: Cross-platform `machineId` — `getMachineIdRaw()` rewritten with try/catch waterfall (Windows REG.exe → macOS ioreg → Linux file read → hostname → `os.hostname()`). Eliminates `process.platform` branching that Next.js bundler dead-code-eliminated, fixing `'head' is not recognized` on Windows. Also fixes #466.
+- **fix(#493)**: Custom provider model naming — removed incorrect prefix stripping in `DefaultExecutor.transformRequest()` that mangled org-scoped model IDs like `zai-org/GLM-5-FP8`.
+- **fix(#490)**: Streaming + context cache protection — `TransformStream` intercepts SSE to inject `` tag before `[DONE]` marker, enabling context cache protection for streaming responses.
+- **fix(#458)**: Combo schema validation — `system_message`, `tool_filter_regex`, `context_cache_protection` fields now pass Zod validation on save.
+- **fix(#487)**: KIRO MITM card cleanup — removed ZWS_README, generified `AntigravityToolCard` to use dynamic tool metadata.
+
+### 🧪 Tests
+
+- Added Anthropic-format tools filter unit tests (PR #397) — 8 regression tests for `tool.name` without `.function` wrapper
+- Test suite: **821 tests, 0 failures** (up from 813)
+
+### 📋 Issues Closed (8)
+
+- **#506** — Windows machineId `head` not recognized (fixed)
+- **#493** — Custom provider model naming (fixed)
+- **#490** — Streaming context cache (fixed)
+- **#452** — Per-API-key request limits (implemented)
+- **#466** — Windows login failure (same root cause as #506)
+- **#504** — MITM inactive (expected behavior)
+- **#462** — Gemini CLI PSA (resolved)
+- **#434** — Electron app crash (duplicate of #402)
+
+## [2.8.9] — 2026-03-20
+
+> Sprint: Merge community PRs, fix KIRO MITM card, dependency updates.
+
+### Merged PRs
+
+- **PR #498** (@Sajid11194): Fix Windows machine ID crash (`undefined\REG.exe`). Replaces `node-machine-id` with native OS registry queries. **Closes #486.**
+- **PR #497** (@zhangqiang8vip): Fix dev-mode HMR resource leaks — 485 leaked DB connections → 1, memory 2.4GB → 195MB. `globalThis` singletons, Edge Runtime warning fix, Windows test stability. (+1168/-338 across 22 files)
+- **PRs #499-503** (Dependabot): GitHub Actions updates — `docker/build-push-action@7`, `actions/checkout@6`, `peter-evans/dockerhub-description@5`, `docker/setup-qemu-action@4`, `docker/login-action@4`.
+
+### Bug Fixes
+
+- **#505** — KIRO MITM card now displays tool-specific instructions (`api.anthropic.com`) instead of Antigravity-specific text.
+- **#504** — Responded with UX clarification (MITM "Inactive" is expected behavior when proxy is not running).
+
+---
+
+## [2.8.8] — 2026-03-20
+
+> Sprint: Fix OAuth batch test crash, add "Test All" button to individual provider pages.
+
+### Bug Fixes
+
+- **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).
+
+### 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.
+
+---
+
+## [2.8.7] — 2026-03-20
+
+> Sprint: Merge PR #495 (Bottleneck 429 drop), fix #496 (custom embedding providers), triage features.
+
+### Bug Fixes
+
+- **Bottleneck 429 infinite wait** (PR #495 by @xandr0s): On 429, `limiter.stop({ dropWaitingJobs: true })` immediately fails all queued requests so upstream callers can trigger fallback. Limiter is deleted from Map so next request creates a fresh instance.
+- **Custom embedding models unresolvable** (#496): `POST /v1/embeddings` now resolves custom embedding models from ALL provider_nodes (not just localhost). Enables models like `google/gemini-embedding-001` added via dashboard.
+
+### Issues Responded
+
+- **#452** — Per-API-key request-count limits (acknowledged, on roadmap)
+- **#464** — Auto-issue API keys with provider/account limits (needs more detail)
+- **#488** — Auto-update model lists (acknowledged, on roadmap)
+- **#496** — Custom embedding provider resolution (fixed)
+
+---
+
+## [2.8.6] — 2026-03-20
+
+> Sprint: Merge PR #494 (MiniMax role fix), fix KIRO MITM dashboard, triage 8 issues.
+
+### 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).
+- **DB**: New `getModelPreserveOpenAIDeveloperRole()` and `mergeModelCompatOverride()` in `models.ts`.
+
+### Bug Fixes
+
+- **KIRO MITM dashboard** (#481/#487): `CLIToolsPageClient` now routes any `configType: "mitm"` tool to `AntigravityToolCard` (MITM Start/Stop controls). Previously only Antigravity was hardcoded.
+- **AntigravityToolCard generic**: Uses `tool.image`, `tool.description`, `tool.id` instead of hardcoded Antigravity values. Guards against missing `defaultModels`.
+
+### Cleanup
+
+- Removed `ZWS_README_V2.md` (development-only docs from PR #494).
+
+### Issues Triaged (8)
+
+- **#487** — Closed (KIRO MITM fixed in this release)
+- **#486** — needs-info (Windows REG.exe PATH issue)
+- **#489** — needs-info (Antigravity projectId missing, OAuth reconnect needed)
+- **#492** — needs-info (missing app/server.js on mise-managed Node)
+- **#490** — Acknowledged (streaming + context cache blocking, fix planned)
+- **#491** — Acknowledged (Codex auth state inconsistency)
+- **#493** — Acknowledged (Modal provider model name prefix, workaround provided)
+- **#488** — Feature request backlog (auto-update model lists)
+
+---
+
+## [2.8.5] — 2026-03-19
+
+> Sprint: Fix zombie SSE streams, context cache first-turn, KIRO MITM, and triage 5 external issues.
+
+### Bug Fixes
+
+- **Zombie SSE Streams** (#473): Reduce `STREAM_IDLE_TIMEOUT_MS` from 300s → 120s for faster combo fallback when providers hang mid-stream. Configurable via env var.
+- **Context Cache Tag** (#474): Fix `injectModelTag()` to handle first-turn requests (no assistant messages) — context cache protection now works from the very first response.
+- **KIRO MITM** (#481): Change KIRO `configType` from `guide` → `mitm` so the dashboard renders MITM Start/Stop controls.
+- **E2E Test** (CI): Fix `providers-bailian-coding-plan.spec.ts` — dismiss pre-existing modal overlay before clicking Add API Key button.
+
+### Closed Issues
+
+- #473 — Zombie SSE streams bypass combo fallback
+- #474 — Context cache `` tag missing on first turn
+- #481 — MITM for KIRO not activatable from dashboard
+- #468 — Gemini CLI remote server (superseded by #462 deprecation)
+- #438 — Claude unable to write files (external CLI issue)
+- #439 — AppImage doesn't work (documented libfuse2 workaround)
+- #402 — ARM64 DMG "damaged" (documented xattr -cr workaround)
+- #460 — CLI not runnable on Windows (documented PATH fix)
+
+---
+
+## [2.8.4] — 2026-03-19
+
+> Sprint: Gemini CLI deprecation, VM guide i18n fix, dependabot security fix, provider schema expansion.
+
+### 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
+
+### Bug Fixes
+
+- **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)
+
+### Bezpečnost
+
+- **deps**: Bump `flatted` 3.3.3 → 3.4.2 — fixes CWE-1321 prototype pollution (#484, @dependabot)
+
+### Closed Issues
+
+- #472 — Model Aliases regression (fixed in v2.8.2)
+- #471 — VM guide translations broken
+- #483 — Trailing `data: null` after `[DONE]` (fixed in v2.8.3)
+
+### Merged PRs
+
+- #484 — deps: bump flatted from 3.3.3 to 3.4.2 (@dependabot)
+
+---
+
+## [2.8.3] — 2026-03-19
+
+> Sprint: Czech i18n, SSE protocol fix, VM guide translation.
+
+### 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)
+
+### Bug Fixes
+
+- **SSE Protocol** (#483): Stop sending trailing `data: null` after `[DONE]` signal — fixes `AI_TypeValidationError` in strict AI SDK clients (Zod-based validators)
+
+### Merged PRs
+
+- #482 — Add Czech language + Fix VM_DEPLOYMENT_GUIDE.md English source (@zen0bit)
+
+---
+
+## [2.8.2] — 2026-03-19
+
+> Sprint: 2 merged PRs, model aliases routing fix, log export, and issue triage.
+
+### 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)
+
+### Bug Fixes
+
+- **Model Aliases Routing** (#472): Settings → Model Aliases now correctly affect provider routing, not just format detection. Previously `resolveModelAlias()` output was only used for `getModelTargetFormat()` but the original model ID was sent to the provider
+- **Stream Flush Usage** (#480): Usage data from the last SSE event in the buffer is now correctly extracted during stream flush (merged from @prakersh)
+
+### Merged PRs
+
+- #480 — Extract usage from remaining buffer in flush handler (@prakersh)
+- #479 — Add missing Codex 5.3/5.4 and Anthropic model ID pricing entries (@prakersh)
+
+---
+
+## [2.8.1] — 2026-03-19
+
+> Sprint: Five community PRs — streaming call log fixes, Kiro compatibility, cache token analytics, Chinese translation, and configurable tool call IDs.
+
+### 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)
+- **feat(api)**: Key PATCH API expanded to support `allowedConnections`, `name`, `autoResolve`, `isActive`, and `accessSchedule` fields (#470)
+- **feat(dashboard)**: Response-first layout in request log detail UI (#470)
+- **feat(i18n)**: Improved Chinese (zh-CN) translation — complete retranslation (#475, @only4copilot)
+
+### 🐛 Bug Fixes
+
+- **fix(kiro)**: Strip injected `model` field from request body — Kiro API rejects unknown top-level fields (#478, @prakersh)
+- **fix(usage)**: Include cache read + cache creation tokens in usage history input totals for accurate analytics (#477, @prakersh)
+- **fix(callLogs)**: Support Claude format usage fields (`input_tokens`/`output_tokens`) alongside OpenAI format, include all cache token variants (#476, @prakersh)
+
+---
+
+## [2.8.0] — 2026-03-19
+
+> Sprint: Bailian Coding Plan provider with editable base URLs, plus community contributions for Alibaba Cloud and Kimi Coding.
+
+### 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)
+
+### 🧪 Tests
+
+- Added 30+ unit tests and 2 e2e scenarios for Bailian Coding Plan provider covering auth validation, schema hardening, route-level behavior, and cross-layer integration
+
+---
+
+## [2.7.10] — 2026-03-19
+
+> Sprint: Two new community-contributed providers (Alibaba Cloud Coding, Kimi Coding API-key) and Docker pino fix.
+
+### 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)
+
+### 🐛 Bug Fixes
+
+- **fix(docker)**: Added missing `split2` dependency to Docker image — `pino-abstract-transport` requires it at runtime but it was not being copied into the standalone container, causing `Cannot find module 'split2'` crashes (#459)
+
+---
+
+## [2.7.9] — 2026-03-18
+
+> Sprint: Codex responses subpath passthrough natively supported, Windows MITM crash fixed, and Combos agent schemas adjusted.
+
+### 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)
+
+### 🐛 Bug Fixes
+
+- **fix(combos)**: Zod schemas (`updateComboSchema` and `createComboSchema`) now include `system_message`, `tool_filter_regex`, and `context_cache_protection`. Fixes bug where agent-specific settings created via the dashboard were silently discarded by the backend validation layer (#458)
+- **fix(mitm)**: Kiro MITM profile crash on Windows fixed — `node-machine-id` failed due to missing `REG.exe` env, and the fallback threw a fatal `crypto is not defined` error. Fallback now safely and correctly imports crypto (#456)
+
+---
+
+## [2.7.8] — 2026-03-18
+
+> Sprint: Budget save bug + combo agent features UI + omniModel tag security fix.
+
+### 🐛 Bug Fixes
+
+- **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)
+
+### 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)
+
+---
+
+## [2.7.7] — 2026-03-18
+
+> Sprint: Docker pino crash, Codex CLI responses worker fix, package-lock sync.
+
+### 🐛 Bug Fixes
+
+- **fix(docker)**: `pino-abstract-transport` and `pino-pretty` now explicitly copied in Docker runner stage — Next.js standalone trace misses these peer deps, causing `Cannot find module pino-abstract-transport` crash on startup (#449)
+- **fix(responses)**: Remove `initTranslators()` from `/v1/responses` route — was crashing Next.js worker with `the worker has exited` uncaughtException on Codex CLI requests (#450)
+
+### 🔧 Maintenance
+
+- **chore(deps)**: `package-lock.json` now committed on every version bump to ensure Docker `npm ci` uses exact dependency versions
+
+---
+
+## [2.7.5] — 2026-03-18
+
+> Sprint: UX improvements and Windows CLI healthcheck fix.
+
+### 🐛 Bug Fixes
+
+- **fix(ux)**: Show default password hint on login page — new users now see `"Default password: 123456"` below the password input (#437)
+- **fix(cli)**: Claude CLI and other npm-installed tools now correctly detected as runnable on Windows — spawn uses `shell:true` to resolve `.cmd` wrappers via PATHEXT (#447)
+
+---
+
+## [2.7.4] — 2026-03-18
+
+> Sprint: Search Tools dashboard, i18n fixes, Copilot limits, Serper validation fix.
+
+### 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`
+ - Sidebar entry under Debug section
+ - `GET /api/search/providers` and `GET /api/search/stats` with auth guards
+ - Local provider_nodes routing for `/v1/rerank`
+ - 30+ i18n keys in search namespace
+
+### 🐛 Bug Fixes
+
+- **fix(search)**: Fix Brave news normalizer (was returning 0 results), enforce max_results truncation post-normalization, fix Endpoints page fetch URL (#443 by @Regis-RCR)
+- **fix(analytics)**: Localize analytics day/date labels — replace hardcoded Portuguese strings with `Intl.DateTimeFormat(locale)` (#444 by @hijak)
+- **fix(copilot)**: Correct GitHub Copilot account type display, filter misleading unlimited quota rows from limits dashboard (#445 by @hijak)
+- **fix(providers)**: Stop rejecting valid Serper API keys — treat non-4xx responses as valid authentication (#446 by @hijak)
+
+---
+
+## [2.7.3] — 2026-03-18
+
+> Sprint: Codex direct API quota fallback fix.
+
+### 🐛 Bug Fixes
+
+- **fix(codex)**: Block weekly-exhausted accounts in direct API fallback (#440)
+ - `resolveQuotaWindow()` prefix matching: `"weekly"` now matches `"weekly (7d)"` cache keys
+ - `applyCodexWindowPolicy()` enforces `useWeekly`/`use5h` toggles correctly
+ - 4 new regression tests (766 total)
+
+---
+
+## [2.7.2] — 2026-03-18
+
+> Sprint: Light mode UI contrast fixes.
+
+### 🐛 Bug Fixes
+
+- **fix(logs)**: Fix light mode contrast in request logs filter buttons and combo badge (#378)
+ - Error/Success/Combo filter buttons now readable in light mode
+ - Combo row badge uses stronger violet in light mode
+
+---
+
+## [2.7.1] — 2026-03-17
+
+> Sprint: Unified web search routing (POST /v1/search) with 5 providers + Next.js 16.1.7 security fixes (6 CVEs).
+
+### ✨ New Features
+
+- **feat(search)**: Unified web search routing — `POST /v1/search` with 5 providers (Serper, Brave, Perplexity, Exa, Tavily)
+ - Auto-failover across providers, 6,500+ free searches/month
+ - In-memory cache with request coalescing (configurable TTL)
+ - Dashboard: Search Analytics tab in `/dashboard/analytics` with provider breakdown, cache hit rate, cost tracking
+ - New API: `GET /api/v1/search/analytics` for search request statistics
+ - DB migration: `request_type` column on `call_logs` for non-chat request tracking
+ - Zod validation (`v1SearchSchema`), auth-gated, cost recorded via `recordCost()`
+
+### Bezpečnost
+
+- **deps**: Next.js 16.1.6 → 16.1.7 — fixes 6 CVEs:
+ - **Critical**: CVE-2026-29057 (HTTP request smuggling via http-proxy)
+ - **High**: CVE-2026-27977, CVE-2026-27978 (WebSocket + Server Actions)
+ - **Medium**: CVE-2026-27979, CVE-2026-27980, CVE-2026-jcc7
+
+### 📁 New Files
+
+| File | Purpose |
+| ---------------------------------------------------------------- | ------------------------------------------ |
+| `open-sse/handlers/search.ts` | Search handler with 5-provider routing |
+| `open-sse/config/searchRegistry.ts` | Provider registry (auth, cost, quota, TTL) |
+| `open-sse/services/searchCache.ts` | In-memory cache with request coalescing |
+| `src/app/api/v1/search/route.ts` | Next.js route (POST + GET) |
+| `src/app/api/v1/search/analytics/route.ts` | Search stats API |
+| `src/app/(dashboard)/dashboard/analytics/SearchAnalyticsTab.tsx` | Analytics dashboard tab |
+| `src/lib/db/migrations/007_search_request_type.sql` | DB migration |
+| `tests/unit/search-registry.test.mjs` | 277 lines of unit tests |
+
+---
+
+## [2.7.0] — 2026-03-17
+
+> Sprint: ClawRouter-inspired features — toolCalling flag, multilingual intent detection, benchmark-driven fallback, request deduplication, pluggable RouterStrategy, Grok-4 Fast + GLM-5 + MiniMax M2.5 + Kimi K2.5 pricing.
+
+### ✨ New Models & Pricing
+
+- **feat(pricing)**: xAI Grok-4 Fast — `$0.20/$0.50 per 1M tokens`, 1143ms p50 latency, tool calling supported
+- **feat(pricing)**: xAI Grok-4 (standard) — `$0.20/$1.50 per 1M tokens`, reasoning flagship
+- **feat(pricing)**: GLM-5 via Z.AI — `$0.5/1M`, 128K output context
+- **feat(pricing)**: MiniMax M2.5 — `$0.30/1M input`, reasoning + agentic tasks
+- **feat(pricing)**: DeepSeek V3.2 — updated pricing `$0.27/$1.10 per 1M`
+- **feat(pricing)**: Kimi K2.5 via Moonshot API — direct Moonshot API access
+- **feat(providers)**: Z.AI provider added (`zai` alias) — GLM-5 family with 128K output
+
+### 🧠 Routing Intelligence
+
+- **feat(registry)**: `toolCalling` flag per model in provider registry — combos can now prefer/require tool-calling capable models
+- **feat(scoring)**: Multilingual intent detection for AutoCombo scoring — PT/ZH/ES/AR script/language patterns influence model selection per request context
+- **feat(fallback)**: Benchmark-driven fallback chains — real latency data (p50 from `comboMetrics`) used to re-order fallback priority dynamically
+- **feat(dedup)**: Request deduplication via content-hash — 5-second idempotency window prevents duplicate provider calls from retrying clients
+- **feat(router)**: Pluggable `RouterStrategy` interface in `autoCombo/routerStrategy.ts` — custom routing logic can be injected without modifying core
+
+### 🔧 MCP Server Improvements
+
+- **feat(mcp)**: 2 new advanced tool schemas: `omniroute_get_provider_metrics` (p50/p95/p99 per provider) and `omniroute_explain_route` (routing decision explanation)
+- **feat(mcp)**: MCP tool auth scopes updated — `metrics:read` scope added for provider metrics tools
+- **feat(mcp)**: `omniroute_best_combo_for_task` now accepts `languageHint` parameter for multilingual routing
+
+### 📊 Observability
+
+- **feat(metrics)**: `comboMetrics.ts` extended with real-time latency percentile tracking per provider/account
+- **feat(health)**: Health API (`/api/monitoring/health`) now returns per-provider `p50Latency` and `errorRate` fields
+- **feat(usage)**: Usage history migration for per-model latency tracking
+
+### 🗄️ DB Migrations
+
+- **feat(migrations)**: New column `latency_p50` in `combo_metrics` table — zero-breaking, safe for existing users
+
+### 🐛 Bug Fixes / Closures
+
+- **close(#411)**: better-sqlite3 hashed module resolution on Windows — fixed in v2.6.10 (f02c5b5)
+- **close(#409)**: GitHub Copilot chat completions fail with Claude models when files attached — fixed in v2.6.9 (838f1d6)
+- **close(#405)**: Duplicate of #411 — resolved
+
+## [2.6.10] — 2026-03-17
+
+> Windows fix: better-sqlite3 prebuilt download without node-gyp/Python/MSVC (#426).
+
+### 🐛 Bug Fixes
+
+- **fix(install/#426)**: On Windows, `npm install -g omniroute` used to fail with `better_sqlite3.node is not a valid Win32 application` because the bundled native binary was compiled for Linux. Adds **Strategy 1.5** to `scripts/postinstall.mjs`: uses `@mapbox/node-pre-gyp install --fallback-to-build=false` (bundled within `better-sqlite3`) to download the correct prebuilt binary for the current OS/arch without requiring any build tools (no node-gyp, no Python, no MSVC). Falls back to `npm rebuild` only if the download fails. Adds platform-specific error messages with clear manual fix instructions.
+
+---
+
+## [2.6.9] — 2026-03-17
+
+> CI fixes (t11 any-budget), bug fix #409 (file attachments via Copilot+Claude), release workflow correction.
+
+### 🐛 Bug Fixes
+
+- **fix(ci)**: Remove word "any" from comments in `openai-responses.ts` and `chatCore.ts` that were failing the t11 `\bany\b` budget check (false positive from regex counting comments)
+- **fix(chatCore)**: Normalize unsupported content part types before forwarding to providers (#409 — Cursor sends `{type:"file"}` when `.md` files are attached; Copilot and other OpenAI-compat providers reject with "type has to be either 'image_url' or 'text'"; fix converts `file`/`document` blocks to `text` and drops unknown types)
+
+### 🔧 Workflow
+
+- **chore(generate-release)**: Add ATOMIC COMMIT RULE — version bump (`npm version patch`) MUST happen before committing feature files to ensure tag always points to a commit containing all version changes together
+
+---
+
+## [2.6.8] — 2026-03-17
+
+> Sprint: Combo as Agent (system prompt + tool filter), Context Caching Protection, Auto-Update, Detailed Logs, MITM Kiro IDE.
+
+### 🗄️ DB Migrations (zero-breaking — safe for existing users)
+
+- **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
+
+### 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)
+- **feat(combo)**: Context Caching Protection (#401 — `context_cache_protection` tags responses with `provider/model` and pins model for session continuity)
+- **feat(settings)**: Auto-Update via Settings (#320 — `GET /api/system/version` + `POST /api/system/update` — checks npm registry and updates in background with pm2 restart)
+- **feat(logs)**: Detailed Request Logs (#378 — captures full pipeline bodies at 4 stages: client request, translated request, provider response, client response — opt-in toggle, 64KB trim, 500-entry ring-buffer)
+- **feat(mitm)**: MITM Kiro IDE profile (#336 — `src/mitm/targets/kiro.ts` targets api.anthropic.com, reuses existing MITM infrastructure)
+
+---
+
+## [2.6.7] — 2026-03-17
+
+> Sprint: SSE improvements, local provider_nodes extensions, proxy registry, Claude passthrough fixes.
+
+### 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)
+- **feat(audio)**: Route TTS/STT to local `provider_nodes` — `buildDynamicAudioProvider()` with SSRF protection (#416, @Regis-RCR)
+- **feat(proxy)**: Proxy registry, management APIs, and quota-limit generalization (#429, @Regis-RCR)
+
+### 🐛 Bug Fixes
+
+- **fix(sse)**: Strip Claude-specific fields (`metadata`, `anthropic_version`) when target is OpenAI-compat (#421, @prakersh)
+- **fix(sse)**: Extract Claude SSE usage (`input_tokens`, `output_tokens`, cache tokens) in passthrough stream mode (#420, @prakersh)
+- **fix(sse)**: Generate fallback `call_id` for tool calls with missing/empty IDs (#419, @prakersh)
+- **fix(sse)**: Claude-to-Claude passthrough — forward body completely untouched, no re-translation (#418, @prakersh)
+- **fix(sse)**: Filter orphaned `tool_result` items after Claude Code context compaction to avoid 400 errors (#417, @prakersh)
+- **fix(sse)**: Skip empty-name tool calls in Responses API translator to prevent `placeholder_tool` infinite loops (#415, @prakersh)
+- **fix(sse)**: Strip empty text content blocks before translation (#427, @prakersh)
+- **fix(api)**: Add `refreshable: true` to Claude OAuth test config (#428, @prakersh)
+
+### 📦 Dependencies
+
+- Bump `vitest`, `@vitest/*` and related devDependencies (#414, @dependabot)
+
+---
+
+## [2.6.6] — 2026-03-17
+
+> Hotfix: Turbopack/Docker compatibility — remove `node:` protocol from all `src/` imports.
+
+### 🐛 Bug Fixes
+
+- **fix(build)**: Removed `node:` protocol prefix from `import` statements in 17 files under `src/`. The `node:fs`, `node:path`, `node:url`, `node:os` etc. imports caused `Ecmascript file had an error` on Turbopack builds (Next.js 15 Docker) and on upgrades from older npm global installs. Affected files: `migrationRunner.ts`, `core.ts`, `backup.ts`, `prompts.ts`, `dataPaths.ts`, and 12 others in `src/app/api/` and `src/lib/`.
+- **chore(workflow)**: Updated `generate-release.md` to make Docker Hub sync and dual-VPS deploy **mandatory** steps in every release.
+
+---
+
+## [2.6.5] — 2026-03-17
+
+> Sprint: reasoning model param filtering, local provider 404 fix, Kilo Gateway provider, dependency bumps.
+
+### ✨ New Features
+
+- **feat(api)**: Added **Kilo Gateway** (`api.kilo.ai`) as a new API Key provider (alias `kg`) — 335+ models, 6 free models, 3 auto-routing models (`kilo-auto/frontier`, `kilo-auto/balanced`, `kilo-auto/free`). Passthrough models supported via `/api/gateway/models` endpoint. (PR #408 by @Regis-RCR)
+
+### 🐛 Bug Fixes
+
+- **fix(sse)**: Strip unsupported parameters for reasoning models (o1, o1-mini, o1-pro, o3, o3-mini). Models in the `o1`/`o3` family reject `temperature`, `top_p`, `frequency_penalty`, `presence_penalty`, `logprobs`, `top_logprobs`, and `n` with HTTP 400. Parameters are now stripped at the `chatCore` layer before forwarding. Uses a declarative `unsupportedParams` field per model and a precomputed O(1) Map for lookup. (PR #412 by @Regis-RCR)
+- **fix(sse)**: Local provider 404 now results in a **model-only lockout (5 seconds)** instead of a connection-level lockout (2 minutes). When a local inference backend (Ollama, LM Studio, oMLX) returns 404 for an unknown model, the connection remains active and other models continue working immediately. Also fixes a pre-existing bug where `model` was not passed to `markAccountUnavailable()`. Local providers detected via hostname (`localhost`, `127.0.0.1`, `::1`, extensible via `LOCAL_HOSTNAMES` env var). (PR #410 by @Regis-RCR)
+
+### 📦 Dependencies
- `better-sqlite3` 12.6.2 → 12.8.0
- `undici` 7.24.2 → 7.24.4
@@ -278,438 +2014,438 @@
---
-## [2.6.4] — 17. 3. 2026
+## [2.6.4] — 2026-03-17
-### 🐛 Opravy chyb
+### 🐛 Bug Fixes
-- **fix(providers)** : Odstraněny neexistující názvy modelů u 5 poskytovatelů:
- - **gemini / gemini-cli** : odstraněny `gemini-3.1-pro/flash` a `gemini-3-*-preview` (neexistují v Google API v1beta); nahrazeny `gemini-2.5-pro` , `gemini-2.5-flash` , `gemini-2.0-flash` , `gemini-1.5-pro/flash`
- - **antigravity** : odstraněny `gemini-3.1-pro-high/low` a `gemini-3-flash` (neplatné interní aliasy); nahrazeny skutečnými modely z verze 2.x
- - **github (Copilot)** : odstraněny `gemini-3-flash-preview` a `gemini-3-pro-preview` ; nahrazeny `gemini-2.5-flash`
- - **nvidia** : opraveno `nvidia/llama-3.3-70b-instruct` → `meta/llama-3.3-70b-instruct` (NVIDIA NIM používá pro modely Meta jmenný prostor `meta/` /); přidány `nvidia/llama-3.1-70b-instruct` a `nvidia/llama-3.1-405b-instruct`
-- **fix(db/combo)** : Aktualizováno `free-stack` combo na vzdálené databázi: odstraněno `qw/qwen3-coder-plus` (prošlý obnovovací token), opraveno `nvidia/llama-3.3-70b-instruct` → `nvidia/meta/llama-3.3-70b-instruct` , opraveno `gemini/gemini-3.1-flash` → `gemini/gemini-2.5-flash` , přidáno `if/deepseek-v3.2`
+- **fix(providers)**: Removed non-existent model names across 5 providers:
+ - **gemini / gemini-cli**: removed `gemini-3.1-pro/flash` and `gemini-3-*-preview` (don't exist in Google API v1beta); replaced with `gemini-2.5-pro`, `gemini-2.5-flash`, `gemini-2.0-flash`, `gemini-1.5-pro/flash`
+ - **antigravity**: removed `gemini-3.1-pro-high/low` and `gemini-3-flash` (invalid internal aliases); replaced with real 2.x models
+ - **github (Copilot)**: removed `gemini-3-flash-preview` and `gemini-3-pro-preview`; replaced with `gemini-2.5-flash`
+ - **nvidia**: corrected `nvidia/llama-3.3-70b-instruct` → `meta/llama-3.3-70b-instruct` (NVIDIA NIM uses `meta/` namespace for Meta models); added `nvidia/llama-3.1-70b-instruct` and `nvidia/llama-3.1-405b-instruct`
+- **fix(db/combo)**: Updated `free-stack` combo on remote DB: removed `qw/qwen3-coder-plus` (expired refresh token), corrected `nvidia/llama-3.3-70b-instruct` → `nvidia/meta/llama-3.3-70b-instruct`, corrected `gemini/gemini-3.1-flash` → `gemini/gemini-2.5-flash`, added `if/deepseek-v3.2`
---
-## [2.6.3] — 16. 3. 2026
+## [2.6.3] — 2026-03-16
-> Sprint: hash-strip zod/pino zapečený do build pipeline, přidán syntetický poskytovatel, opravena cesta VPS PM2.
+> Sprint: zod/pino hash-strip baked into build pipeline, Synthetic provider added, VPS PM2 path corrected.
-### 🐛 Opravy chyb
+### 🐛 Bug Fixes
-- **fix(build)** : Turbopack hash-strip se nyní spouští při **kompilaci** pro VŠECHNY balíčky — nejen `better-sqlite3` . Krok 5.6 v `prepublish.mjs` prochází každý `.js` v `app/.next/server/` a odstraňuje 16znakovou hexadecimální příponu z jakékoli hashované `require()` . Opravuje `zod-dcb22c...` , `pino-...` atd. MODULE_NOT_FOUND u globálních instalací npm. Zavírá #398.
-- **Oprava (nasazení)** : PM2 na obou VPS ukazoval na zastaralé adresáře git-clone. V globálním balíčku npm překonfigurováno na `app/server.js` . Aktualizován pracovní postup `/deploy-vps` pro použití `npm pack + scp` (registr npm odmítá balíčky o velikosti 299 MB).
+- **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).
-### ✨ Funkce
+### Funkce
-- **feat(provider)** : Synthetic ( [synthetic.new](https://synthetic.new) ) — inference kompatibilní s OpenAI zaměřená na soukromí. `passthroughModels: true` pro dynamický katalog modelů HuggingFace. Počáteční modely: Kimi K2.5, MiniMax M2.5, GLM 4.7, DeepSeek V3.2. (PR #404 od @Regis-RCR)
+- **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)
-### 📋 Problémy uzavřeny
+### 📋 Issues Closed
-- **zavřít #398** : regrese hashování npm — opraveno hashováním při kompilaci v prepublish
-- **triáž č. 324** : Snímek obrazovky s chybou bez kroků – požadovány podrobnosti o reprodukci
+- **close #398**: npm hash regression — fixed by compile-time hash-strip in prepublish
+- **triage #324**: Bug screenshot without steps — requested reproduction details
---
-## [2.6.2] — 16. 3. 2026
+## [2.6.2] — 2026-03-16
-> Sprint: hashování modulů kompletně opraveno, sloučeny 2 PR (filtr Anthropic tools + vlastní cesty k endpointům), přidán poskytovatel Alibaba Cloud DashScope, uzavřeny 3 zastaralé problémy.
+> Sprint: module hashing fully fixed, 2 PRs merged (Anthropic tools filter + custom endpoint paths), Alibaba Cloud DashScope provider added, 3 stale issues closed.
-### 🐛 Opravy chyb
+### 🐛 Bug Fixes
-- **fix(build)** : Rozšířeno hashování `externals` webpacku tak, aby zahrnovalo VŠECHNY `serverExternalPackages` , nejen `better-sqlite3` . Next.js 16 Turbopack hashuje `zod` , `pino` a všechny ostatní externí balíčky serveru do názvů jako `zod-dcb22c6336e0bc69` , které za běhu v `node_modules` neexistují. HASH_PATTERN regex catch-all nyní odstraňuje 16znakovou příponu a vrací se k základnímu názvu balíčku. Také přidána `NEXT_PRIVATE_BUILD_WORKER=0` v `prepublish.mjs` pro posílení režimu webpacku a následné skenování po sestavení, které hlásí všechny zbývající hashované reference. (#396, #398, PR #403)
-- **fix(chat)** : Názvy nástrojů v anthropic formátu ( `tool.name` bez wrapperu `.function` ) byly tiše vynechány filtrem prázdných názvů zavedeným v bodě #346. LiteLLM proxyuje požadavky s prefixem `anthropic/` ve formátu Anthropic Messages API, což způsobuje filtrování všech nástrojů a Anthropic vrací chybu `400: tool_choice.any may only be specified while providing tools` . Opraveno návratem k `tool.name` , když chybí `tool.function.name` . Přidáno 8 regresních jednotkových testů. (PR #397)
+- **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)
-### ✨ Funkce
+### Funkce
-- **feat(api)** : Vlastní cesty koncových bodů pro uzly poskytovatelů kompatibilní s OpenAI — konfigurace `chatPath` a `modelsPath` pro každý uzel (např. `/v4/chat/completions` ) v uživatelském rozhraní pro připojení poskytovatele. Zahrnuje migraci databáze ( `003_provider_node_custom_paths.sql` ) a sanitizaci cesty URL (bez `..` traversal, musí začínat znakem `/` ). (PR #400)
-- **feat(provider)** : Alibaba Cloud DashScope přidán jako poskytovatel kompatibilní s OpenAI. Mezinárodní endpoint: `dashscope-intl.aliyuncs.com/compatible-mode/v1` . 12 modelů: `qwen-max` , `qwen-plus` , `qwen-turbo` , `qwen3-coder-plus/flash` , `qwq-plus` , `qwq-32b` , `qwen3-32b` , `qwen3-235b-a22b` . Autorizace: Nosný API klíč.
+- **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.
-### 📋 Problémy uzavřeny
+### 📋 Issues Closed
-- **zavřít #323** : Chyba připojení Cline `[object Object]` – opraveno ve verzi 2.3.7; uživateli bylo doručeno pokyny k upgradu z verze 2.2.9
-- **zavřít #337** : Sledování úvěru Kiro — implementováno ve verzi 2.5.5 (#381); odkázalo uživatele na Dashboard → Použití
-- **triage #402** : Poškozený soubor ARM64 macOS DMG – požadovaná verze macOS, přesná chyba a doporučené alternativní řešení `xattr -d com.apple.quarantine`
+- **close #323**: Cline connection error `[object Object]` — fixed in v2.3.7; instructed user to upgrade from v2.2.9
+- **close #337**: Kiro credit tracking — implemented in v2.5.5 (#381); pointed user to Dashboard → Usage
+- **triage #402**: ARM64 macOS DMG damaged — requested macOS version, exact error, and advised `xattr -d com.apple.quarantine` workaround
---
-## [2.6.1] — 15. 3. 2026
+## [2.6.1] — 2026-03-15
-> Kritická oprava při spuštění: Globální instalace npm v2.6.0 havarovaly s chybou 500 kvůli chybě hashování názvů modulů Turbopack/webpack v instrumentačním hooku Next.js 16.
+> Critical startup fix: v2.6.0 global npm installs crashed with a 500 error due to a Turbopack/webpack module-name hashing bug in the Next.js 16 instrumentation hook.
-### 🐛 Opravy chyb
+### 🐛 Bug Fixes
-- **fix(build)** : Vynutit, aby byl `better-sqlite3` vždy vyžadován přesným názvem balíčku v balíčku webpack server. Next.js 16 zkompiloval instrumentační hook do samostatného chunku a vygeneroval `require('better-sqlite3-')` — hashovaný název modulu, který neexistuje v `node_modules` — přestože byl balíček uveden v `serverExternalPackages` . Do konfigurace webpacku serveru byla přidána explicitní funkce `externals` , takže bundler vždy vygeneruje `require('better-sqlite3')` , čímž se vyřeší `500 Internal Server Error` při spuštění čistých globálních instalací. (#394, PR #395)
+- **fix(build)**: Force `better-sqlite3` to always be required by its exact package name in the webpack server bundle. Next.js 16 compiled the instrumentation hook into a separate chunk and emitted `require('better-sqlite3-')` — a hashed module name that doesn't exist in `node_modules` — even though the package was listed in `serverExternalPackages`. Added an explicit `externals` function to the server webpack config so the bundler always emits `require('better-sqlite3')`, resolving the startup `500 Internal Server Error` on clean global installs. (#394, PR #395)
### 🔧 CI
-- **ci** : Do `npm-publish.yml` přidána `workflow_dispatch` se zabezpečením synchronizace verzí pro manuální spouštěče (#392).
-- **ci** : Přidán `workflow_dispatch` do `docker-publish.yml` , aktualizovány akce GitHubu na nejnovější verze (#392)
+- **ci**: Added `workflow_dispatch` to `npm-publish.yml` with version sync safeguard for manual triggers (#392)
+- **ci**: Added `workflow_dispatch` to `docker-publish.yml`, updated GitHub Actions to latest versions (#392)
---
-## [2.6.0] - 15. 3. 2026
+## [2.6.0] - 2026-03-15
-> Sprint řešení problémů: Opraveny 4 chyby, vylepšeno uživatelské rozhraní protokolů, přidáno sledování kreditů Kiro.
+> Issue resolution sprint: 4 bugs fixed, logs UX improved, Kiro credit tracking added.
-### 🐛 Opravy chyb
+### 🐛 Bug Fixes
-- **oprava(média)** : ComfyUI a SD WebUI se již nezobrazují v seznamu poskytovatelů na stránce Média, pokud nejsou nakonfigurovány — při připojení načtou `/api/providers` a skryjí lokální poskytovatele bez připojení (#390)
-- **oprava(auth)** : Round-robin již po zpoždění znovu nevybírá účty s omezenou rychlostí ihned – `backoffLevel` se nyní používá jako primární třídicí klíč v rotaci LRU (#340)
-- **oprava(oauth)** : Qoder (a další poskytovatelé, kteří přesměrovávají na své vlastní uživatelské rozhraní) již nenechávají modální okno OAuth zaseknuté na „Čekání na autorizaci“ – detektor zavřených vyskakovacích oken automaticky přechází do režimu ručního zadávání URL (#344)
-- **oprava(logy)** : Tabulka protokolů požadavků je nyní čitelná ve světlém režimu – stavové odznaky, počty tokenů a kombinované tagy používají adaptivní `dark:` barevné třídy (#378)
+- **fix(media)**: ComfyUI and SD WebUI no longer appear in the Media page provider list when unconfigured — fetches `/api/providers` on mount and hides local providers with no connections (#390)
+- **fix(auth)**: Round-robin no longer re-selects rate-limited accounts immediately after cooldown — `backoffLevel` is now used as primary sort key in the LRU rotation (#340)
+- **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)
-### ✨ Funkce
+### Funkce
-- **feat(kiro)** : Do fetcheru využití přidáno sledování kreditů Kiro — dotazy `getUserCredits` z endpointu AWS CodeWhisperer (#337)
+- **feat(kiro)**: Kiro credit tracking added to usage fetcher — queries `getUserCredits` from AWS CodeWhisperer endpoint (#337)
-### 🛠 Domácí práce
+### 🛠 Chores
-- **chore(tests)** : Zarovnání `test:plan3` , `test:fixes` , `test:security` pro použití stejného zavaděče `tsx/esm` jako u `npm test` – eliminuje falešně negativní výsledky rozlišení modulů v cílených bězích (PR #386)
+- **chore(tests)**: Aligned `test:plan3`, `test:fixes`, `test:security` to use same `tsx/esm` loader as `npm test` — eliminates module resolution false negatives in targeted runs (PR #386)
---
-## [2.5.9] - 15. 3. 2026
+## [2.5.9] - 2026-03-15
-> Oprava nativní passthrough Codexu + posílení validace těla trasy.
+> Codex native passthrough fix + route body validation hardening.
-### 🐛 Opravy chyb
+### 🐛 Bug Fixes
-- **fix(codex)** : Zachovává nativní průchod Responses API pro klienty Codexu – zabraňuje zbytečným mutacím překladu (PR #387)
-- **fix(api)** : Ověřování těl požadavků na trasách pro stanovení cen/synchronizaci a směrování úloh – zabraňuje pádům způsobeným chybně formátovanými vstupy (PR #388)
-- **fix(auth)** : Tajné hodnoty JWT přetrvávají i po restartech pomocí `src/lib/db/secrets.ts` — eliminuje chyby 401 po restartu PM2 (PR #388)
+- **fix(codex)**: Preserve native Responses API passthrough for Codex clients — avoids unnecessary translation mutations (PR #387)
+- **fix(api)**: Validate request bodies on pricing/sync and task-routing routes — prevents crashes from malformed inputs (PR #388)
+- **fix(auth)**: JWT secrets persist across restarts via `src/lib/db/secrets.ts` — eliminates 401 errors after pm2 restart (PR #388)
---
-## [2.5.8] - 15. 3. 2026
+## [2.5.8] - 2026-03-15
-> Oprava sestavení: obnovení připojení VPS přerušeného nedokončeným publikováním v2.5.7.
+> Build fix: restore VPS connectivity broken by v2.5.7 incomplete publish.
-### 🐛 Opravy chyb
+### 🐛 Bug Fixes
-- **oprava(build)** : `scripts/prepublish.mjs` se stále používají, zastaralý příznak `--webpack` způsobuje tiché selhání samostatného sestavení Next.js — publikování npm dokončeno bez `app/server.js` , což narušuje nasazení VPS
+- **fix(build)**: `scripts/prepublish.mjs` still used deprecated `--webpack` flag causing Next.js standalone build to fail silently — npm publish completed without `app/server.js`, breaking VPS deployment
---
-## [2.5.7] - 15. 3. 2026
+## [2.5.7] - 2026-03-15
-> Opravy chyb při zpracování v Media Playground.
+> Media playground error handling fixes.
-### 🐛 Opravy chyb
+### 🐛 Bug Fixes
-- **oprava(média)** : Přepis „Vyžadován klíč API“ falešně pozitivní, pokud zvuk neobsahuje žádnou řeč (hudba, ticho) – nyní se místo toho zobrazuje „Není detekována žádná řeč“
-- **oprava(media)** : `upstreamErrorResponse` v `audioTranscription.ts` a `audioSpeech.ts` nyní vrací správný JSON ( `{error:{message}}` ), což umožňuje správnou detekci chyb přihlašovacích údajů 401/403 v MediaPageClient
-- **oprava(média)** : `parseApiError` nyní zpracovává pole `err_msg` v Deepgramu a detekuje `"api key"` v chybových zprávách pro přesnou klasifikaci chyb přihlašovacích údajů.
+- **fix(media)**: Transcription "API Key Required" false positive when audio contains no speech (music, silence) — now shows "No speech detected" instead
+- **fix(media)**: `upstreamErrorResponse` in `audioTranscription.ts` and `audioSpeech.ts` now returns proper JSON (`{error:{message}}`), enabling correct 401/403 credential error detection in the MediaPageClient
+- **fix(media)**: `parseApiError` now handles Deepgram's `err_msg` field and detects `"api key"` in error messages for accurate credential error classification
---
-## [2.5.6] - 15. 3. 2026
+## [2.5.6] - 2026-03-15
-> Kritické opravy zabezpečení/autentizace: OAuth v Antigravity nefunkční + relace JWT ztraceny po restartu.
+> Critical security/auth fixes: Antigravity OAuth broken + JWT sessions lost after restart.
-### 🐛 Opravy chyb
+### 🐛 Bug Fixes
-- **fix(oauth) #384** : Antigravity Google OAuth nyní správně odesílá `client_secret` do koncového bodu tokenu. Záložní volbou pro `ANTIGRAVITY_OAUTH_CLIENT_SECRET` byl prázdný řetězec, což je chyba – `client_secret` tedy nebyl v požadavku nikdy zahrnut, což způsobovalo chyby `"client_secret is missing"` u všech uživatelů bez vlastní proměnné prostředí. Zavírá #383.
-- **fix(auth) #385** : `JWT_SECRET` je nyní ukládán do SQLite ( `namespace='secrets'` ) při první generaci a znovu načten při následných spuštěních. Dříve byl při každém spuštění procesu generován nový náhodný tajný klíč, který po jakémkoli restartu nebo upgradu zneplatňoval všechny existující soubory cookie/relace. Ovlivňuje `JWT_SECRET` i `API_KEY_SECRET` . Zavírá #382.
+- **fix(oauth) #384**: Antigravity Google OAuth now correctly sends `client_secret` to the token endpoint. The fallback for `ANTIGRAVITY_OAUTH_CLIENT_SECRET` was an empty string, which is falsy — so `client_secret` was never included in the request, causing `"client_secret is missing"` errors for all users without a custom env var. Closes #383.
+- **fix(auth) #385**: `JWT_SECRET` is now persisted to SQLite (`namespace='secrets'`) on first generation and reloaded on subsequent starts. Previously, a new random secret was generated each process startup, invalidating all existing cookies/sessions after any restart or upgrade. Affects both `JWT_SECRET` and `API_KEY_SECRET`. Closes #382.
---
-## [2.5.5] - 15. 3. 2026
+## [2.5.5] - 2026-03-15
-> Oprava odstranění duplicitních dat v seznamu modelů, posílení samostatného sestavení Electronu a sledování kreditů Kiro.
+> Model list dedup fix, Electron standalone build hardening, and Kiro credit tracking.
-### 🐛 Opravy chyb
+### 🐛 Bug Fixes
-- **fix(models) #380** : `GET /api/models` nyní zahrnuje aliasy poskytovatelů při sestavování filtru aktivního poskytovatele — modely pro `claude` (alias `cc` ) a `github` (alias `gh` ) se vždy zobrazovaly bez ohledu na to, zda bylo nakonfigurováno připojení, protože klíče `PROVIDER_MODELS` jsou aliasy, ale připojení k databázi jsou uložena pod ID poskytovatelů. Opraveno rozšířením každého aktivního ID poskytovatele o jeho alias pomocí `PROVIDER_ID_TO_ALIAS` . Zavírá #353.
-- **fix(electron) #379** : Nové `scripts/prepare-electron-standalone.mjs` připraví vyhrazený balíček `/.next/electron-standalone` před zabalením Electronu. Pokud je `node_modules` symbolický odkaz, dojde k ukončení s chybou (electron-builder by na sestavovací stroj odeslal běhovou závislost). Multiplatformní sanitizace cest pomocí `path.basename` . Od @kfiramar.
+- **fix(models) #380**: `GET /api/models` now includes provider aliases when building the active-provider filter — models for `claude` (alias `cc`) and `github` (alias `gh`) were always shown regardless of whether a connection was configured, because `PROVIDER_MODELS` keys are aliases but DB connections are stored under provider IDs. Fixed by expanding each active provider ID to also include its alias via `PROVIDER_ID_TO_ALIAS`. Closes #353.
+- **fix(electron) #379**: New `scripts/prepare-electron-standalone.mjs` stages a dedicated `/.next/electron-standalone` bundle before Electron packaging. Aborts with a clear error if `node_modules` is a symlink (electron-builder would ship a runtime dependency on the build machine). Cross-platform path sanitization via `path.basename`. By @kfiramar.
-### ✨ Nové funkce
+### ✨ New Features
-- **feat(kiro) #381** : Sledování zůstatku kreditů Kiro — koncový bod využití nyní vrací data o kreditech pro Kiro účty voláním `codewhisperer.us-east-1.amazonaws.com/getUserCredits` (stejný koncový bod, který Kiro IDE používá interně). Vrací zbývající kredity, celkový limit, datum obnovení a úroveň předplatného. Uzavírá #337.
+- **feat(kiro) #381**: Kiro credit balance tracking — usage endpoint now returns credit data for Kiro accounts by calling `codewhisperer.us-east-1.amazonaws.com/getUserCredits` (same endpoint Kiro IDE uses internally). Returns remaining credits, total allowance, renewal date, and subscription tier. Closes #337.
-## [2.5.4] - 15. 3. 2026
+## [2.5.4] - 2026-03-15
-> Oprava spouštění loggeru, oprava zabezpečení přihlašovacího bootstrapu a vylepšení spolehlivosti vývojářského HMR. Zlepšení infrastruktury CI.
+> Logger startup fix, login bootstrap security fix, and dev HMR reliability improvement. CI infrastructure hardened.
-### 🐛 Opravy chyb (PR #374, #375, #376 od @kfiramar)
+### 🐛 Bug Fixes (PRs #374, #375, #376 by @kfiramar)
-- **oprava(logger) #376** : Obnovit cestu k protokolovacímu modulu pino transport — `formatters.level` v kombinaci s `transport.targets` je odmítnut modulem pino. Konfigurace založené na transportu nyní odstraňují formátovač úrovní pomocí funkce `getTransportCompatibleConfig()` . Také opravuje numerické mapování úrovní v `/api/logs/console` : `30→info, 40→warn, 50→error` (bylo posunuto o jednu).
-- **oprava(login) #375** : Přihlašovací stránka se nyní bootuje z veřejného endpointu `/api/settings/require-login` namísto chráněného `/api/settings` . V nastaveních chráněných heslem dostávala stránka předběžného ověřování chybu 401 a zbytečně se vracela k bezpečným výchozím hodnotám. Veřejná trasa nyní vrací všechna bootstrapová metadata ( `requireLogin` , `hasPassword` , `setupComplete` ) s konzervativní fallback chybou 200.
-- **oprava(dev) #374** : Přidání `localhost` a `127.0.0.1` do `allowedDevOrigins` v `next.config.mjs` — HMR websocket byl blokován při přístupu k aplikaci přes loopback adresu, což opakovaně produkovalo varování cross-origin.
+- **fix(logger) #376**: Restore pino transport logger path — `formatters.level` combined with `transport.targets` is rejected by pino. Transport-backed configs now strip the level formatter via `getTransportCompatibleConfig()`. Also corrects numeric level mapping in `/api/logs/console`: `30→info, 40→warn, 50→error` (was shifted by one).
+- **fix(login) #375**: Login page now bootstraps from the public `/api/settings/require-login` endpoint instead of the protected `/api/settings`. In password-protected setups, the pre-auth page was receiving a 401 and falling back to safe defaults unnecessarily. The public route now returns all bootstrap metadata (`requireLogin`, `hasPassword`, `setupComplete`) with a conservative 200 fallback on error.
+- **fix(dev) #374**: Add `localhost` and `127.0.0.1` to `allowedDevOrigins` in `next.config.mjs` — HMR websocket was blocked when accessing the app via loopback address, producing repeated cross-origin warnings.
-### 🔧 CI a infrastruktura
+### 🔧 CI & Infrastructure
-- **Oprava chyb ESLint OOM** : `eslint.config.mjs` nyní ignoruje `vscode-extension/**` , `electron/**` , `docs/**` , `app/.next/**` a `clipr/**` — ESLint havaroval s chybou JS haldy OOM skenováním binárních blobů a kompilovaných chunků VS Code.
-- **Oprava jednotkového testu** : Z 2 testovacích souborů byl odstraněn zastaralý `ALTER TABLE provider_connections ADD COLUMN "group"` – sloupec je nyní součástí základního schématu (přidáno v #373), což způsobovalo `SQLITE_ERROR: duplicate column name` při každém spuštění CI.
-- **Pre-commit hook** : Do `.husky/pre-commit` přidán `npm run test:unit` — unit testy nyní blokují poškozené commity dříve, než se dostanou do CI.
+- **ESLint OOM fix**: `eslint.config.mjs` now ignores `vscode-extension/**`, `electron/**`, `docs/**`, `app/.next/**`, and `clipr/**` — ESLint was crashing with a JS heap OOM by scanning VS Code binary blobs and compiled chunks.
+- **Unit test fix**: Removed stale `ALTER TABLE provider_connections ADD COLUMN "group"` from 2 test files — column is now part of the base schema (added in #373), causing `SQLITE_ERROR: duplicate column name` on every CI run.
+- **Pre-commit hook**: Added `npm run test:unit` to `.husky/pre-commit` — unit tests now block broken commits before they reach CI.
-## [2.5.3] - 14. 3. 2026
+## [2.5.3] - 2026-03-14
-> Opravy kritických chyb: migrace schématu databáze, načítání spouštěcího prostředí, mazání chyb poskytovatele a oprava popisků i18n. Vylepšení kvality kódu nad každým PR.
+> Critical bugfixes: DB schema migration, startup env loading, provider error state clearing, and i18n tooltip fix. Code quality improvements on top of each PR.
-### 🐛 Opravy chyb (PR #369, #371, #372, #373 od @kfiramar)
+### 🐛 Bug Fixes (PRs #369, #371, #372, #373 by @kfiramar)
-- **oprava(db) #373** : Přidání sloupce `provider_connections.group` do základního schématu + migrace zpětného doplnění pro existující databáze — sloupec byl použit ve všech dotazech, ale chyběl v definici schématu
-- **fix(i18n) #371** : Nahrazení neexistujícího klíče `t("deleteConnection")` existujícím `providers.delete` — oprava `MISSING_MESSAGE: providers.deleteConnection` na stránce s podrobnostmi o poskytovateli
-- **oprava(auth) #372** : Vymazat zastaralá chybová metadata ( `errorCode` , `lastErrorType` , `lastErrorSource` ) z účtů poskytovatelů po skutečném zotavení – dříve se obnovené účty zobrazovaly jako selhané
-- **oprava(startup) #369** : Sjednocení načítání env napříč `npm run start` , `run-standalone.mjs` a Electron s ohledem na prioritu `DATA_DIR/.env → ~/.omniroute/.env → ./.env` — zabránění generování nového `STORAGE_ENCRYPTION_KEY` přes existující šifrovanou databázi
+- **fix(db) #373**: Add `provider_connections.group` column to base schema + backfill migration for existing databases — column was used in all queries but missing from schema definition
+- **fix(i18n) #371**: Replace non-existent `t("deleteConnection")` key with existing `providers.delete` key — fixes `MISSING_MESSAGE: providers.deleteConnection` runtime error on provider detail page
+- **fix(auth) #372**: Clear stale error metadata (`errorCode`, `lastErrorType`, `lastErrorSource`) from provider accounts after genuine recovery — previously, recovered accounts kept appearing as failed
+- **fix(startup) #369**: Unify env loading across `npm run start`, `run-standalone.mjs`, and Electron to respect `DATA_DIR/.env → ~/.omniroute/.env → ./.env` priority — prevents generating a new `STORAGE_ENCRYPTION_KEY` over an existing encrypted database
-### 🔧 Kvalita kódu
+### 🔧 Code Quality
-- Zdokumentované vzory `result.success` vs. `response?.ok` v `auth.ts` (oba úmyslné, nyní vysvětlené)
-- Normalizované `overridePath?.trim()` v `electron/main.js` pro shodu s `bootstrap-env.mjs`
-- Přidán komentář k objednávce sloučení `preferredEnv` při spuštění Electronu
+- Documented `result.success` vs `response?.ok` patterns in `auth.ts` (both intentional, now explained)
+- Normalized `overridePath?.trim()` in `electron/main.js` to match `bootstrap-env.mjs`
+- Added `preferredEnv` merge order comment in Electron startup
-> Oprava kvót pro účty Codex s automatickou rotací, rychlým přepínáním úrovní, modelem gpt-5.4 a označením analytických nástrojů.
+> Codex account quota policy with auto-rotation, fast tier toggle, gpt-5.4 model, and analytics label fix.
-### ✨ Nové funkce (PR #366, #367, #368)
+### ✨ New Features (PRs #366, #367, #368)
-- **Zásady kvót Codexu (PR #366)** : Okno kvóty 5 hodin/týden pro účet se přepíná v dashboardu poskytovatele. Účty jsou automaticky přeskočeny, když povolená okna dosáhnou prahové hodnoty 90 %, a znovu povoleny po `resetAt` . Zahrnuje `quotaCache.ts` s vedlejším efektem pro získávání statusu zdarma.
-- **Přepínání rychlé úrovně Codexu (PR #367)** : Dashboard → Nastavení → Úroveň služeb Codexu. Přepínání ve výchozím nastavení vkládá `service_tier: "flex"` pouze pro požadavky Codexu, což snižuje náklady o ~80 %. Celý stack: karta UI + koncový bod API + exekutor + překladač + obnovení po spuštění.
-- **Model gpt-5.4 (PR #368)** : Přidává `cx/gpt-5.4` a `codex/gpt-5.4` do registru modelů Codex. Regresní test je součástí.
+- **Codex Quota Policy (PR #366)**: Per-account 5h/weekly quota window toggles in Provider dashboard. Accounts are automatically skipped when enabled windows reach 90% threshold and re-admitted after `resetAt`. Includes `quotaCache.ts` with side-effect free status getter.
+- **Codex Fast Tier Toggle (PR #367)**: Dashboard → Settings → Codex Service Tier. Default-off toggle injects `service_tier: "flex"` only for Codex requests, reducing cost ~80%. Full stack: UI tab + API endpoint + executor + translator + startup restore.
+- **gpt-5.4 Model (PR #368)**: Adds `cx/gpt-5.4` and `codex/gpt-5.4` to the Codex model registry. Regression test included.
-### 🐛 Opravy chyb
+### 🐛 Bug Fixes
-- **oprava č. 356** : Analytické grafy (Nejlepší poskytovatel, Podle účtu, Rozdělení poskytovatelů) nyní zobrazují lidsky čitelné názvy/štítky poskytovatelů namísto nezpracovaných interních ID u poskytovatelů kompatibilních s OpenAI.
+- **fix #356**: Analytics charts (Top Provider, By Account, Provider Breakdown) now display human-readable provider names/labels instead of raw internal IDs for OpenAI-compatible providers.
-> Hlavní vydání: strategie striktně náhodného směrování, řízení přístupu k klíčům API, skupiny připojení, synchronizace externích cen a opravy kritických chyb pro modely myšlení, kombinované testování a validaci názvů nástrojů.
+> Major release: strict-random routing strategy, API key access controls, connection groups, external pricing sync, and critical bug fixes for thinking models, combo testing, and tool name validation.
-### ✨ Nové funkce (PR #363 a #365)
+### ✨ New Features (PRs #363 & #365)
-- **Strategie striktně náhodného směrování** : Fisher-Yatesův náhodný balíček s garancí neopakování a serializací mutexů pro souběžné požadavky. Nezávislé balíčky pro každé kombo a providera.
-- **Řízení přístupu ke klíčům API** : `allowedConnections` (omezení připojení, která může klíč používat), `is_active` (povolení/zakázání klíče s kódem 403), `accessSchedule` (řízení přístupu na základě času), přepínání `autoResolve` , přejmenování klíčů pomocí PATCH.
-- **Skupiny připojení** : Seskupování připojení poskytovatelů podle prostředí. Harmonické zobrazení na stránce Limity s perzistencí localStorage a inteligentním automatickým přepínáním.
-- **Synchronizace externích cen (LiteLLM)** : 3stupňové rozlišení cen (uživatelské přepsání → synchronizace → výchozí hodnoty). Možnost přihlášení přes `PRICING_SYNC_ENABLED=true` . Nástroj MCP `omniroute_sync_pricing` . 23 nových testů.
-- **i18n** : 30 jazyků aktualizováno strategií striktní náhodnosti, řetězce pro správu klíčů API. pt-BR plně přeloženo.
+- **Strict-Random Routing Strategy**: Fisher-Yates shuffle deck with anti-repeat guarantee and mutex serialization for concurrent requests. Independent decks per combo and per provider.
+- **API Key Access Controls**: `allowedConnections` (restrict which connections a key can use), `is_active` (enable/disable key with 403), `accessSchedule` (time-based access control), `autoResolve` toggle, rename keys via PATCH.
+- **Connection Groups**: Group provider connections by environment. Accordion view in Limits page with localStorage persistence and smart auto-switch.
+- **External Pricing Sync (LiteLLM)**: 3-tier pricing resolution (user overrides → synced → defaults). Opt-in via `PRICING_SYNC_ENABLED=true`. MCP tool `omniroute_sync_pricing`. 23 new tests.
+- **i18n**: 30 languages updated with strict-random strategy, API key management strings. pt-BR fully translated.
-### 🐛 Opravy chyb
+### 🐛 Bug Fixes
-- **Oprava č. 355** : Časový limit nečinnosti streamu zvýšen z 60 s na 300 s – zabraňuje přerušení modelů s rozšířeným myšlením (claude-opus-4-6, o3 atd.) během dlouhých fází uvažování. Konfigurovatelné pomocí `STREAM_IDLE_TIMEOUT_MS` .
-- **Oprava č. 350** : Kombinovaný test nyní obchází `REQUIRE_API_KEY=true` pomocí interní hlavičky a univerzálně používá formát kompatibilní s OpenAI. Časový limit prodloužen z 15 s na 20 s.
-- **oprava #346** : Nástroje s prázdným `function.name` (přeposláno Claudem Code) jsou nyní filtrovány předtím, než je obdrží upstreamoví poskytovatelé, čímž se zabrání chybám „Neplatný vstup[N].name: prázdný řetězec“.
+- **fix #355**: Stream idle timeout increased from 60s to 300s — prevents aborting extended-thinking models (claude-opus-4-6, o3, etc.) during long reasoning phases. Configurable via `STREAM_IDLE_TIMEOUT_MS`.
+- **fix #350**: Combo test now bypasses `REQUIRE_API_KEY=true` using internal header, and uses OpenAI-compatible format universally. Timeout extended from 15s to 20s.
+- **fix #346**: Tools with empty `function.name` (forwarded by Claude Code) are now filtered before upstream providers receive them, preventing "Invalid input[N].name: empty string" errors.
-### 🗑️ Uzavřené problémy
+### 🗑️ Closed Issues
-- **#341** : Sekce ladění odstraněna – nahrazena je `/dashboard/logs` a `/dashboard/health` .
+- **#341**: Debug section removed — replacement is `/dashboard/logs` and `/dashboard/health`.
-> Podpora API Key Round-Robin pro nastavení poskytovatelů s více klíči a potvrzení již zavedeného směrování zástupných znaků a rolování oken kvót.
+> API Key Round-Robin support for multi-key provider setups, and confirmation of wildcard routing and quota window rolling already in place.
-### ✨ Nové funkce
+### ✨ New Features
-- **Round-Robin klíčů API (T07)** : Připojení poskytovatelů nyní mohou obsahovat více klíčů API (Upravit připojení → Další klíče API). Požadavky rotují round-robin mezi primárními a dalšími klíči pomocí `providerSpecificData.extraApiKeys[]` . Klíče jsou uchovávány v paměti indexované pro každé připojení – nejsou nutné žádné změny schématu databáze.
+- **API Key Round-Robin (T07)**: Provider connections can now hold multiple API keys (Edit Connection → Extra API Keys). Requests rotate round-robin between primary + extra keys via `providerSpecificData.extraApiKeys[]`. Keys are held in-memory indexed per connection — no DB schema changes required.
-### 📝 Již implementováno (potvrzeno auditem)
+### 📝 Already Implemented (confirmed in audit)
-- **Směrování modelu s wildcard znaky (T13)** : soubor `wildcardRouter.ts` s porovnáváním zástupných znaků ve stylu glob ( `gpt*` , `claude-?-sonnet` atd.) je již integrován do `model.ts` s hodnocením specificity.
-- **Posunování okna kvót (T08)** : `accountFallback.ts:isModelLocked()` již automaticky posouvá okno vpřed – pokud `Date.now() > entry.until` , zámek se okamžitě smaže (žádné blokování zastaralých funkcí).
+- **Wildcard Model Routing (T13)**: `wildcardRouter.ts` with glob-style wildcard matching (`gpt*`, `claude-?-sonnet`, etc.) is already integrated into `model.ts` with specificity ranking.
+- **Quota Window Rolling (T08)**: `accountFallback.ts:isModelLocked()` already auto-advances the window — if `Date.now() > entry.until`, lock is deleted immediately (no stale blocking).
-> Vylepšení uživatelského rozhraní, doplnění strategií směrování a elegantní zpracování chyb pro omezení využití.
+> UI polish, routing strategy additions, and graceful error handling for usage limits.
-### ✨ Nové funkce
+### ✨ New Features
-- **Strategie směrování Fill-First a P2C** : Do výběru kombinované strategie přidány strategie `fill-first` (vyčerpání kvóty před přesunem) a `p2c` (výběr Power-of-Two-Choices s nízkou latencí) s kompletními panely s pokyny a barevně odlišenými odznaky.
-- **Přednastavené modely Free Stack** : Vytvoření kombinace pomocí šablony Free Stack nyní automaticky vyplní 7 nejlepších modelů bezplatných poskytovatelů ve své třídě (Gemini CLI, Kiro, Qoder×2, Qwen, NVIDIA NIM, Groq). Uživatelé stačí aktivovat poskytovatele a ihned získají kombinaci 0 $/měsíc.
-- **Širší kombo modální okno** : Modální okno pro vytvoření/úpravu komba nyní používá `max-w-4xl` pro pohodlnou úpravu velkých komb.
+- **Fill-First & P2C Routing Strategies**: Added `fill-first` (drain quota before moving on) and `p2c` (Power-of-Two-Choices low-latency selection) to combo strategy picker, with full guidance panels and color-coded badges.
+- **Free Stack Preset Models**: Creating a combo with the Free Stack template now auto-fills 7 best-in-class free provider models (Gemini CLI, Kiro, Qoder×2, Qwen, NVIDIA NIM, Groq). Users just activate the providers and get a $0/month combo out-of-the-box.
+- **Wider Combo Modal**: Create/Edit combo modal now uses `max-w-4xl` for comfortable editing of large combos.
-### 🐛 Opravy chyb
+### 🐛 Bug Fixes
-- **Stránka s limity HTTP 500 pro Codex a GitHub** : `getCodexUsage()` a `getGitHubUsage()` nyní vracejí uživatelsky přívětivou zprávu, když poskytovatel vrátí 401/403 (vypršelý token), místo aby vyvolaly chybu 500 na stránce s limity.
-- **Falešně pozitivní MaintenanceBanner** : Banner již při načítání stránky falešně nezobrazuje „Server je nedostupný“. Opraveno okamžitým voláním `checkHealth()` při připojení a odstraněním zastaralého uzavření `show` -state.
-- **Popisky ikon poskytovatele** : Tlačítka s ikonami pro úpravu (tužka) a odstranění v řádku připojení poskytovatele nyní obsahují nativní HTML popisky – všech 6 ikon akcí je nyní samodokumentovaných.
+- **Limits page HTTP 500 for Codex & GitHub**: `getCodexUsage()` and `getGitHubUsage()` now return a user-friendly message when the provider returns 401/403 (expired token), instead of throwing and causing a 500 error on the Limits page.
+- **MaintenanceBanner false-positive**: Banner no longer shows "Server is unreachable" spuriously on page load. Fixed by calling `checkHealth()` immediately on mount and removing stale `show`-state closure.
+- **Provider icon tooltips**: Edit (pencil) and delete icon buttons in the provider connection row now have native HTML tooltips — all 6 action icons are now self-documented.
-> Několik vylepšení z analýzy problémů komunity, podpora nových poskytovatelů, opravy chyb pro sledování tokenů, směrování modelů a spolehlivost streamování.
+> Multiple improvements from community issue analysis, new provider support, bug fixes for token tracking, model routing, and streaming reliability.
-### ✨ Nové funkce
+### ✨ New Features
-- **Inteligentní směrování s ohledem na úlohy (T05)** : Automatický výběr modelu na základě typu obsahu požadavku — kódování → deepseek-chat, analýza → gemini-2.5-pro, vision → gpt-4o, sumarizace → gemini-2.5-flash. Konfigurovatelné v Nastavení. Nové API `GET/PUT/POST /api/settings/task-routing` .
-- **Poskytovatel HuggingFace** : Přidán HuggingFace Router jako poskytovatel kompatibilní s OpenAI s Llama 3.1 70B/8B, Qwen 2.5 72B, Mistral 7B, Phi-3.5 Mini.
-- **Poskytovatel Vertex AI** : Přidán poskytovatel Vertex AI (Google Cloud) s Gemini 2.5 Pro/Flash, Gemma 2 27B, Claude přes Vertex.
-- **Nahrávání souborů do Playgroundu** : Nahrávání zvuku pro přepis, nahrávání obrázků pro modely vidění (automatická detekce podle názvu modelu), inline vykreslování obrázků pro výsledky generování obrázků.
-- **Vizuální zpětná vazba při výběru modelu** : Již přidané modely v kombinovaném výběru nyní zobrazují zelený odznak ✓ – zabraňuje záměně duplicitních modelů.
-- **Kompatibilita s Qwen (PR #352)** : Aktualizováno nastavení otisků uživatelského agenta a rozhraní CLI pro kompatibilitu s poskytovateli Qwen.
-- **Správa stavu round-robin (PR #349)** : Vylepšená logika round-robin pro zpracování vyloučených účtů a správné udržování stavu rotace.
-- **Uživatelská zkušenost se schránkou (PR #360)** : Vylepšené operace se schránkou s možností zálohování pro nezabezpečené kontexty; vylepšení normalizace nástroje Claude.
+- **Task-Aware Smart Routing (T05)**: Automatic model selection based on request content type — coding → deepseek-chat, analysis → gemini-2.5-pro, vision → gpt-4o, summarization → gemini-2.5-flash. Configurable via Settings. New `GET/PUT/POST /api/settings/task-routing` API.
+- **HuggingFace Provider**: Added HuggingFace Router as an OpenAI-compatible provider with Llama 3.1 70B/8B, Qwen 2.5 72B, Mistral 7B, Phi-3.5 Mini.
+- **Vertex AI Provider**: Added Vertex AI (Google Cloud) provider with Gemini 2.5 Pro/Flash, Gemma 2 27B, Claude via Vertex.
+- **Playground File Uploads**: Audio upload for transcription, image upload for vision models (auto-detect by model name), inline image rendering for image generation results.
+- **Model Select Visual Feedback**: Already-added models in combo picker now show ✓ green badge — prevents duplicate confusion.
+- **Qwen Compatibility (PR #352)**: Updated User-Agent and CLI fingerprint settings for Qwen provider compatibility.
+- **Round-Robin State Management (PR #349)**: Enhanced round-robin logic to handle excluded accounts and maintain rotation state correctly.
+- **Clipboard UX (PR #360)**: Hardened clipboard operations with fallback for non-secure contexts; Claude tool normalization improvements.
-### 🐛 Opravy chyb
+### 🐛 Bug Fixes
-- **Oprava č. 302 – OpenAI SDK stream=False zanechává tool_calls** : T01 Accept header negotiation již nevynucuje streamování, pokud je `body.stream` explicitně `false` . Způsobovalo to tiché zanechávání tool_calls při použití OpenAI Python SDK v režimu bez streamování.
-- **Oprava č. 73 — Claude Haiku směrován do OpenAI bez prefixu poskytovatele** : modely `claude-*` odeslané bez prefixu poskytovatele nyní správně směrují k poskytovateli `antigravity` (antropickému). Přidána také heuristika `gemini-*` / `gemma-*` → `gemini` .
-- **Oprava č. 74 – Počet tokenů je pro streamování Antigravity/Claude vždy 0** : Událost SSE `message_start` , která obsahuje `input_tokens` nebyla analyzována funkcí `extractUsage()` , což způsobovalo pokles všech počtů vstupních tokenů. Sledování vstupních/výstupních tokenů nyní funguje správně pro streamované odpovědi.
-- **Oprava č. 180 – Duplikáty importovaných modelů bez zpětné vazby** : `ModelSelectModal` nyní zobrazuje ✓ zelené zvýraznění u modelů, které jsou již v kombinaci, takže je zřejmé, že jsou již přidány.
-- **Chyby generování mediálních stránek** : Výsledky obrázků se nyní vykreslují jako tagy `
` místo nezpracovaného JSON. Výsledky přepisu se zobrazují jako čitelný text. Chyby přihlašovacích údajů zobrazují oranžový banner místo tiché chyby.
-- **Tlačítko pro obnovení tokenu na stránce poskytovatele** : Pro poskytovatele OAuth bylo přidáno uživatelské rozhraní pro ruční obnovení tokenu.
+- **Fix #302 — OpenAI SDK stream=False drops tool_calls**: T01 Accept header negotiation no longer forces streaming when `body.stream` is explicitly `false`. Was causing tool_calls to be silently dropped when using the OpenAI Python SDK in non-streaming mode.
+- **Fix #73 — Claude Haiku routed to OpenAI without provider prefix**: `claude-*` models sent without a provider prefix now correctly route to the `antigravity` (Anthropic) provider. Added `gemini-*`/`gemma-*` → `gemini` heuristic as well.
+- **Fix #74 — Token counts always 0 for Antigravity/Claude streaming**: The `message_start` SSE event which carries `input_tokens` was not being parsed by `extractUsage()`, causing all input token counts to drop. Input/output token tracking now works correctly for streaming responses.
+- **Fix #180 — Model import duplicates with no feedback**: `ModelSelectModal` now shows ✓ green highlight for models already in the combo, making it obvious they're already added.
+- **Media page generation errors**: Image results now render as `
` tags instead of raw JSON. Transcription results shown as readable text. Credential errors show an amber banner instead of silent failure.
+- **Token refresh button on provider page**: Manual token refresh UI added for OAuth providers.
-### 🔧 Vylepšení
+### 🔧 Improvements
-- **Registr poskytovatelů** : Do `providerRegistry.ts` a `providers.ts` (frontend) přidány prvky HuggingFace a Vertex AI.
-- **Čtení mezipaměti** : Nový `src/lib/db/readCache.ts` pro efektivní ukládání do mezipaměti čtení databáze.
-- **Mezipaměť kvót** : Vylepšená mezipaměť kvót s vyřazením na základě TTL.
+- **Provider Registry**: HuggingFace and Vertex AI added to `providerRegistry.ts` and `providers.ts` (frontend).
+- **Read Cache**: New `src/lib/db/readCache.ts` for efficient DB read caching.
+- **Quota Cache**: Improved quota cache with TTL-based eviction.
-### 📦 Závislosti
+### 📦 Dependencies
- `dompurify` → 3.3.3 (PR #347)
- `undici` → 7.24.2 (PR #348, #361)
- `docker/setup-qemu-action` → v4 (PR #342)
- `docker/setup-buildx-action` → v4 (PR #343)
-### 📁 Nové soubory
+### 📁 New Files
-| Soubor | Účel |
-| --------------------------------------------- | ------------------------------------------------- |
-| `open-sse/services/taskAwareRouter.ts` | Logika směrování s ohledem na úlohy (7 typů úloh) |
-| `src/app/api/settings/task-routing/route.ts` | API pro konfiguraci směrování úloh |
-| `src/app/api/providers/[id]/refresh/route.ts` | Ruční aktualizace tokenu OAuth |
-| `src/lib/db/readCache.ts` | Efektivní mezipaměť pro čtení databáze |
-| `src/shared/utils/clipboard.ts` | Zpevněná schránka s funkcí |
+| File | Purpose |
+| --------------------------------------------- | --------------------------------------- |
+| `open-sse/services/taskAwareRouter.ts` | Task-aware routing logic (7 task types) |
+| `src/app/api/settings/task-routing/route.ts` | Task routing config API |
+| `src/app/api/providers/[id]/refresh/route.ts` | Manual OAuth token refresh |
+| `src/lib/db/readCache.ts` | Efficient DB read cache |
+| `src/shared/utils/clipboard.ts` | Hardened clipboard with fallback |
-## [2.4.1] - 13. 3. 2026
+## [2.4.1] - 2026-03-13
-### 🐛 Oprava
+### 🐛 Fix
-- **Modální okno s kombinacemi: Šablona Volný zásobník viditelná a výrazná** – Šablona Volný zásobník byla skrytá (4. v mřížce se 3 sloupci). Opraveno: přesunuto na pozici 1, přepnuto na mřížku 2x2, takže jsou viditelné všechny 4 šablony, zelený okraj + zvýraznění odznaku ZDARMA.
+- **Combos modal: Free Stack visible and prominent** — Free Stack template was hidden (4th in 3-column grid). Fixed: moved to position 1, switched to 2x2 grid so all 4 templates are visible, green border + FREE badge highlight.
-## [2.4.0] - 13. 3. 2026
+## [2.4.0] - 2026-03-13
-> **Hlavní vydání** – ekosystém Free Stack, přepracované transkripční hřiště, více než 44 poskytovatelů, komplexní dokumentace k bezplatné úrovni a vylepšení uživatelského rozhraní napříč všemi oblastmi.
+> **Major release** — Free Stack ecosystem, transcription playground overhaul, 44+ providers, comprehensive free tier documentation, and UI improvements across the board.
-### ✨ Funkce
+### Funkce
-- **Kombinace: Šablona Free Stack** — Nová 4. šablona „Free Stack (0 $)“ využívající round-robin napříč Kiro + Qoder + Qwen + Gemini CLI. Při prvním použití doporučuje předpřipravenou kombinaci s nulovými náklady.
-- **Média/Přepis: Deepgram jako výchozí** – Deepgram (Nova 3, 200 dolarů zdarma) je nyní výchozím poskytovatelem přepisu. AssemblyAI (50 dolarů zdarma) a Groq Whisper (navždy zdarma) jsou zobrazeny s odznaky bezplatného kreditu.
-- **README: Sekce „Začít zdarma“** – Nová tabulka s 5 kroky v předběžném souboru README, která ukazuje, jak nastavit umělou inteligenci s nulovými náklady během několika minut.
-- **README: Kombinace bezplatného přepisu** – Nová sekce s návrhem kombinací Deepgram/AssemblyAI/Groq a informacemi o bezplatném kreditu pro každého poskytovatele.
-- **providers.ts: příznak hasFree** — NVIDIA NIM, Cerebras a Groq označené odznakem hasFree a freeNote pro uživatelské rozhraní poskytovatelů.
-- **i18n: klíče templateFreeStack** — kombinovaná šablona Free Stack přeložená a synchronizovaná do všech 30 jazyků.
+- **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.
+- **README: "Start Free" section** — New early-README 5-step table showing how to set up zero-cost AI in minutes.
+- **README: Free Transcription Combo** — New section with Deepgram/AssemblyAI/Groq combo suggestion and per-provider free credit details.
+- **providers.ts: hasFree flag** — NVIDIA NIM, Cerebras, and Groq marked with hasFree badge and freeNote for the providers UI.
+- **i18n: templateFreeStack keys** — Free Stack combo template translated and synced to all 30 languages.
-## [2.3.16] - 13. 3. 2026
+## [2.3.16] - 2026-03-13
-### 📖 Dokumentace
+### Dokumentace
-- **README: 44+ poskytovatelů** — Všechny 3 výskyty výrazu „36+ poskytovatelů“ byly aktualizovány na „44+“, což odráží skutečný počet kódové základny (44 poskytovatelů v souboru providers.ts).
-- **README: Nová sekce „🆓 Bezplatné modely – Co skutečně získáte“** – Přidána tabulka 7 poskytovatelů s limity rychlosti pro každý model pro: Kiro (Claude neomezeně přes AWS Builder ID), Qoder (5 modelů neomezeně), Qwen (4 modely neomezeně), Gemini CLI (180K/měsíc), NVIDIA NIM (~40 RPM dev-forever), Cerebras (1M tok/den / 60K TPM), Groq (30 RPM / 14.4K RPD). Zahrnuje doporučení pro kombinaci /usr/bin/bash Ultimate Free Stack.
-- **Soubor README: Aktualizace cenové tabulky** – přidán Cerebras do úrovně API KEY, opravena změna NVIDIA z „1000 kreditů“ na „navždy zdarma pro vývojáře“, aktualizovány počty a názvy modelů Qoder/Qwen
-- **README: Modely Qoder 8→5** (s názvy: kimi-k2-thinking, qwen3-coder-plus, deepseek-r1, minimax-m2, kimi-k2)
-- **README: Modely Qwen 3→4** (s názvy: qwen3-coder-plus, qwen3-coder-flash, qwen3-coder-next, vision-model)
+- **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.
+- **README: Pricing Table Updated** — Added Cerebras to API KEY tier, fixed NVIDIA from "1000 credits" to "dev-forever free", updated Qoder/Qwen model counts and names
+- **README: Qoder 8→5 models** (named: kimi-k2-thinking, qwen3-coder-plus, deepseek-r1, minimax-m2, kimi-k2)
+- **README: Qwen 3→4 models** (named: qwen3-coder-plus, qwen3-coder-flash, qwen3-coder-next, vision-model)
-## [2.3.15] - 13. 3. 2026
+## [2.3.15] - 2026-03-13
-### ✨ Funkce
+### Funkce
-- **Panel automatických kombinací (priorita úrovně)** : Přidána `🏷️ Tier` jako 7. faktor bodování v zobrazení rozpisu faktorů `/dashboard/auto-combo` – nyní je viditelných všech 7 faktorů bodování automatických kombinací.
-- **i18n — sekce autoCombo** : Pro panel Auto-Combo bylo přidáno 20 nových překladových klíčů ( `title` , `status` , `modePack` , `providerScores` , `factorTierPriority` atd.) do všech 30 jazykových souborů.
+- **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.
-## [2.3.14] - 13. 3. 2026
+## [2.3.14] - 2026-03-13
-### 🐛 Opravy chyb
+### 🐛 Bug Fixes
-- **Qoder OAuth (#339)** : Obnoven platný výchozí `clientSecret` – dříve to byl prázdný řetězec, který při každém pokusu o připojení způsoboval chybu „Chybné přihlašovací údaje klienta“. Veřejné přihlašovací údaje jsou nyní výchozím záložním nastavením (lze je přepsat pomocí proměnné prostředí `QODER_OAUTH_CLIENT_SECRET` ).
-- **MITM server nenalezen (#335)** : `prepublish.mjs` nyní kompiluje `src/mitm/*.ts` do JavaScriptu pomocí `tsc` před zkopírováním do npm balíčku. Dříve se kopírovaly pouze nezpracované soubory `.ts` – což znamenalo, že `server.js` nikdy neexistoval v globálních instalacích npm/Volta.
-- **Chybí projectId v GeminiCLI (#338)** : Namísto vyvolání hardwarové chyby 500, když v uložených přihlašovacích údajích chybí `projectId` (např. po restartu Dockeru), OmniRoute nyní zaznamená varování a pokusí se o požadavek – vrátí smysluplnou chybu na straně poskytovatele místo pádu OmniRoute.
-- **Neshoda verzí balíčku Electron (#323)** : Synchronizována verze `electron/package.json` s verzí `2.3.13` (dříve `2.0.13` ), takže binární verze pro stolní počítače odpovídá balíčku npm.
+- **Qoder OAuth (#339)**: Restored the valid default `clientSecret` — was previously an empty string, causing "Bad client credentials" on every connect attempt. The public credential is now the default fallback (overridable via `QODER_OAUTH_CLIENT_SECRET` env var).
+- **MITM server not found (#335)**: `prepublish.mjs` now compiles `src/mitm/*.ts` to JavaScript using `tsc` before copying to the npm bundle. Previously only raw `.ts` files were copied — meaning `server.js` never existed in npm/Volta global installs.
+- **GeminiCLI missing projectId (#338)**: Instead of throwing a hard 500 error when `projectId` is missing from stored credentials (e.g. after Docker restart), OmniRoute now logs a warning and attempts the request — returning a meaningful provider-side error instead of an OmniRoute crash.
+- **Electron version mismatch (#323)**: Synced `electron/package.json` version to `2.3.13` (was `2.0.13`) so the desktop binary version matches the npm package.
-### ✨ Nové modely (#334)
+### ✨ New Models (#334)
-- **Kiro** : `claude-sonnet-4` , `claude-opus-4.6` , `deepseek-v3.2` , `minimax-m2.1` , `qwen3-coder-next` , `auto`
-- **Kodex** : `gpt5.4`
+- **Kiro**: `claude-sonnet-4`, `claude-opus-4.6`, `deepseek-v3.2`, `minimax-m2.1`, `qwen3-coder-next`, `auto`
+- **Codex**: `gpt5.4`
-### 🔧 Vylepšení
+### 🔧 Improvements
-- **Bodové hodnocení (API + validace)** : Do schématu Zod `ScoringWeights` a trasy API `combos/auto` přidána `tierPriority` (váha `0.05` ) – 7. faktor bodování je nyní plně akceptován rozhraním REST API a ověřován na vstupu. Váha `stability` upravena z `0.10` na `0.05` , aby celkový součet zůstal `1.0` .
+- **Tier Scoring (API + Validation)**: Added `tierPriority` (weight `0.05`) to the `ScoringWeights` Zod schema and the `combos/auto` API route — the 7th scoring factor is now fully accepted by the REST API and validated on input. `stability` weight adjusted from `0.10` to `0.05` to keep total sum = `1.0`.
-### ✨ Nové funkce
+### ✨ New Features
-- **Víceúrovňové bodování kvót (automatické kombinování)** : Přidána `tierPriority` jako 7. faktor bodování – účty s úrovněmi Ultra/Pro jsou nyní upřednostňovány před úrovněmi Free, pokud jsou ostatní faktory stejné. Nová volitelná pole `accountTier` a `quotaResetIntervalSecs` u `ProviderCandidate` . Všechny 4 balíčky režimů byly aktualizovány ( `ship-fast` , `cost-saver` , `quality-first` , `offline-friendly` ).
-- **Záložní model v rámci rodiny (T5)** : Pokud model není k dispozici (404/400/403), OmniRoute se nyní automaticky vrátí k sourozeneckým modelům ze stejné rodiny, než vrátí chybu ( `modelFamilyFallback.ts` ).
-- **Konfigurovatelný časový limit API Bridge** : Proměnná prostředí `API_BRIDGE_PROXY_TIMEOUT_MS` umožňuje operátorům ladit časový limit proxy (výchozí hodnota 30 s). Opravuje chyby 504 při pomalých odezvách upstreamu. (#332)
-- **Historie hvězd** : Widget star-history.com byl ve všech 30 souborech README nahrazen widgetem starchart.cc ( `?variant=adaptive` ) – přizpůsobuje se světlému/tmavému tématu a aktualizacím v reálném čase.
+- **Tiered Quota Scoring (Auto-Combo)**: Added `tierPriority` as a 7th scoring factor — accounts with Ultra/Pro tiers are now preferred over Free tiers when other factors are equal. New optional fields `accountTier` and `quotaResetIntervalSecs` on `ProviderCandidate`. All 4 mode packs updated (`ship-fast`, `cost-saver`, `quality-first`, `offline-friendly`).
+- **Intra-Family Model Fallback (T5)**: When a model is unavailable (404/400/403), OmniRoute now automatically falls back to sibling models from the same family before returning an error (`modelFamilyFallback.ts`).
+- **Configurable API Bridge Timeout**: `API_BRIDGE_PROXY_TIMEOUT_MS` env var lets operators tune the proxy timeout (default 30s). Fixes 504 errors on slow upstream responses. (#332)
+- **Star History**: Replaced star-history.com widget with starchart.cc (`?variant=adaptive`) in all 30 READMEs — adapts to light/dark theme, real-time updates.
-### 🐛 Opravy chyb
+### 🐛 Bug Fixes
-- **Auth — První heslo** : Při nastavování prvního hesla pro dashboard je nyní akceptována proměnná prostředí `INITIAL_PASSWORD` . Používá `timingSafeEqual` pro porovnávání v konstantním čase, čímž se zabraňuje útokům na časování. (#333)
-- **Zkrácení souboru README** : Opraven chybějící uzavírací tag `` v sekci Řešení problémů, který způsoboval, že GitHub zastavil vykreslování všeho pod ním (Tech Stack, Dokumentace, Plán, Přispěvatelé).
-- **Instalace pnpm** : Z `package.json` byl odstraněn redundantní přepis `@swc/helpers` , který kolidoval s přímou závislostí a způsoboval chyby `EOVERRIDE` na pnpm. Přidána konfigurace `pnpm.onlyBuiltDependencies` .
-- **Vložení cesty do CLI (T12)** : V `cliRuntime.ts` byl přidán validátor `isSafePath()` pro blokování procházení cesty a metaznaků shellu v proměnných prostředí `CLI_*_BIN` .
-- **CI** : Po odstranění přepsání byl obnoven `package-lock.json` pro opravu chyb `npm ci` v akcích GitHubu.
+- **Auth — First-time password**: `INITIAL_PASSWORD` env var is now accepted when setting the first dashboard password. Uses `timingSafeEqual` for constant-time comparison, preventing timing attacks. (#333)
+- **README Truncation**: Fixed a missing `` closing tag in the Troubleshooting section that caused GitHub to stop rendering everything below it (Tech Stack, Docs, Roadmap, Contributors).
+- **pnpm install**: Removed redundant `@swc/helpers` override from `package.json` that conflicted with the direct dependency, causing `EOVERRIDE` errors on pnpm. Added `pnpm.onlyBuiltDependencies` config.
+- **CLI Path Injection (T12)**: Added `isSafePath()` validator in `cliRuntime.ts` to block path traversal and shell metacharacters in `CLI_*_BIN` env vars.
+- **CI**: Regenerated `package-lock.json` after override removal to fix `npm ci` failures on GitHub Actions.
-### 🔧 Vylepšení
+### 🔧 Improvements
-- **Formát odpovědi (T1)** : `response_format` (json_schema/json_object) se nyní vkládá jako systémový výzva pro Claude, což umožňuje kompatibilitu strukturovaného výstupu.
-- **429 Opakování (T2)** : Opakování odpovědí 429 v rámci URL (2× pokusy s 2s zpožděním) před návratem k další URL.
-- **Záhlaví rozhraní příkazového řádku Gemini (T3)** : Přidány záhlaví otisků prstů `User-Agent` a `X-Goog-Api-Client` pro kompatibilitu s rozhraním příkazového řádku Gemini.
-- **Cenový katalog (T9)** : Přidány ceníky pro `deepseek-3.1` , `deepseek-3.2` a `qwen3-coder-next` .
+- **Response Format (T1)**: `response_format` (json_schema/json_object) now injected as a system prompt for Claude, enabling structured output compatibility.
+- **429 Retry (T2)**: Intra-URL retry for 429 responses (2× attempts with 2s delay) before falling back to next URL.
+- **Gemini CLI Headers (T3)**: Added `User-Agent` and `X-Goog-Api-Client` fingerprint headers for Gemini CLI compatibility.
+- **Pricing Catalog (T9)**: Added `deepseek-3.1`, `deepseek-3.2`, and `qwen3-coder-next` pricing entries.
-### 📁 Nové soubory
+### 📁 New Files
-| Soubor | Účel |
-| ------------------------------------------ | ------------------------------------------------------------------ |
-| `open-sse/services/modelFamilyFallback.ts` | Definice modelových rodin a logika záložních řešení v rámci rodiny |
+| File | Purpose |
+| ------------------------------------------ | -------------------------------------------------------- |
+| `open-sse/services/modelFamilyFallback.ts` | Model family definitions and intra-family fallback logic |
-### Opraveno
+### Fixed
-- **KiloCode** : časový limit kontroly stavu kilocode již byl opraven ve verzi 2.3.11.
-- **OpenCode** : Přidání opencode do registru cliRuntime s 15sekundovým časovým limitem pro kontrolu stavu
-- **OpenClaw / Cursor** : Prodloužení časového limitu kontroly stavu na 15 sekund pro varianty s pomalým startem.
-- **VPS** : Nainstalujte npm balíčky pro droid a openclaw; aktivujte CLI_EXTRA_PATHS pro kiro-cli
-- **cliRuntime** : Přidána registrace nástroje opencode a prodloužena časová prodleva pro pokračování
+- **KiloCode**: kilocode healthcheck timeout already fixed in v2.3.11
+- **OpenCode**: Add opencode to cliRuntime registry with 15s healthcheck timeout
+- **OpenClaw / Cursor**: Increase healthcheck timeout to 15s for slow-start variants
+- **VPS**: Install droid and openclaw npm packages; activate CLI_EXTRA_PATHS for kiro-cli
+- **cliRuntime**: Add opencode tool registration and increase timeout for continue
-## [2.3.11] - 12. 3. 2026
+## [2.3.11] - 2026-03-12
-### Opraveno
+### Fixed
-- **KiloCode healthcheck** : Zvýšení `healthcheckTimeoutMs` z 4000 ms na 15000 ms — kilocode při spuštění vykreslí banner s logem ASCII, což v prostředích s pomalým/studeným startem způsobí chybu `healthcheck_failed`
+- **KiloCode healthcheck**: Increase `healthcheckTimeoutMs` from 4000ms to 15000ms — kilocode renders an ASCII logo banner on startup causing false `healthcheck_failed` on slow/cold-start environments
-## [2.3.10] - 12. 3. 2026
+## [2.3.10] - 2026-03-12
-### Opraveno
+### Fixed
-- **Lint** : Oprava chyby `check:any-budget:t11` — nahrazení `as any` za `as Record` v OAuthModal.tsx (3 výskyty)
+- **Lint**: Fix `check:any-budget:t11` failure — replace `as any` with `as Record` in OAuthModal.tsx (3 occurrences)
-### Dokumenty
+### Docs
-- **CLI-TOOLS.md** : Kompletní průvodce všemi 11 nástroji CLI (claude, codex, gemini, opencode, cline, kilocode, continue, kiro-cli, cursor, droid, openclaw)
-- **i18n** : CLI-TOOLS.md synchronizovaný do 30 jazyků s přeloženým názvem a úvodem
+- **CLI-TOOLS.md**: Complete guide for all 11 CLI tools (claude, codex, gemini, opencode, cline, kilocode, continue, kiro-cli, cursor, droid, openclaw)
+- **i18n**: CLI-TOOLS.md synced to 30 languages with translated title + intro
-## [2.3.8] - 12. 3. 2026
+## [2.3.8] - 2026-03-12
-## [2.3.9] - 12. 3. 2026
+## [2.3.9] - 2026-03-12
-### Přidáno
+### Added
-- **/v1/completions** : Nový starší endpoint pro dokončení OpenAI – přijímá jak řetězec `prompt` , tak pole `messages` , automaticky se normalizuje do formátu chatu
-- **EndpointPage** : Nyní zobrazuje všechny 3 typy koncových bodů kompatibilních s OpenAI: Dokončování chatu, API odpovědí a Legacy Dokončování.
-- **i18n** : Přidán `completionsLegacy/completionsLegacyDesc` do 30 jazykových souborů.
+- **/v1/completions**: New legacy OpenAI completions endpoint — accepts both `prompt` string and `messages` array, normalizes to chat format automatically
+- **EndpointPage**: Now shows all 3 OpenAI-compatible endpoint types: Chat Completions, Responses API, and Legacy Completions
+- **i18n**: Added `completionsLegacy/completionsLegacyDesc` to 30 language files
-### Opraveno
+### Fixed
-- **OAuthModal** : Oprava zobrazení objektu `[object Object]` u všech chyb připojení OAuth – správně extrahovat `.message` z objektů odpovědí na chyby ve všech 3 `throw new Error(data.error)` (exchange, device-code, authorize)
-- Ovlivňuje Cline, Codex, GitHub, Qwen, Kiro a všechny ostatní poskytovatele OAuth.
+- **OAuthModal**: Fix `[object Object]` displayed on all OAuth connection errors — properly extract `.message` from error response objects in all 3 `throw new Error(data.error)` calls (exchange, device-code, authorize)
+- Affects Cline, Codex, GitHub, Qwen, Kiro, and all other OAuth providers
-## [2.3.7] - 12. 3. 2026
+## [2.3.7] - 2026-03-12
-### Opraveno
+### Fixed
-- **Cline OAuth** : Před dekódování base64 přidána `decodeURIComponent` , aby autorizační kódy kódované pomocí URL z URL zpětného volání byly správně analyzovány, opraveny chyby „neplatný nebo vypršený autorizační kód“ ve vzdálených instalacích (LAN IP).
-- **Cline OAuth** : `mapTokens` nyní vyplňuje `name = firstName + lastName || email` , takže účty Cline zobrazují skutečná uživatelská jména místo „Account #ID“.
-- **Názvy účtů OAuth** : Všechny toky výměny OAuth (exchange, poll, poll-callback) nyní normalizují `name = email` pokud název chybí, takže každý účet OAuth zobrazuje svůj e-mail jako zobrazovaný popisek v dashboardu Poskytovatelé.
-- **Názvy účtů OAuth** : V souboru `db/providers.ts` byla odstraněna sekvenční záložní možnost „Účet N“ – účty bez e-mailu/jména nyní používají stabilní popisek založený na ID pomocí `getAccountDisplayName()` namísto sekvenčního čísla, které se mění při smazání účtů.
+- **Cline OAuth**: Add `decodeURIComponent` before base64 decode so URL-encoded auth codes from the callback URL are parsed correctly, fixing "invalid or expired authorization code" errors on remote (LAN IP) setups
+- **Cline OAuth**: `mapTokens` now populates `name = firstName + lastName || email` so Cline accounts show real user names instead of "Account #ID"
+- **OAuth account names**: All OAuth exchange flows (exchange, poll, poll-callback) now normalize `name = email` when name is missing, so every OAuth account shows its email as the display label in the Providers dashboard
+- **OAuth account names**: Removed sequential "Account N" fallback in `db/providers.ts` — accounts with no email/name now use a stable ID-based label via `getAccountDisplayName()` instead of a sequential number that changes when accounts are deleted
-## [2.3.6] - 12. 3. 2026
+## [2.3.6] - 2026-03-12
-### Opraveno
+### Fixed
-- **Dávkový test poskytovatele** : Opraveno schéma Zod pro akceptování `providerId: null` (frontend odesílá null pro režimy bez poskytovatele); nesprávně vracelo „Neplatný požadavek“ pro všechny dávkové testy.
-- **Modální okno testování poskytovatele** : Opraveno zobrazení `[object Object]` normalizací objektů chyb API na řetězce před vykreslením v `setTestResults` a `ProviderTestResultsView`
-- **i18n** : Do `en.json` přidány chybějící klíče `cliTools.toolDescriptions.opencode` , `cliTools.toolDescriptions.kiro` , `cliTools.guides.opencode` , `cliTools.guides.kiro`
-- **i18n** : Synchronizováno chybějící 1111 klíčů ve všech 29 souborech v neanglických jazycích s použitím anglických hodnot jako záložních hodnot.
+- **Provider test batch**: Fixed Zod schema to accept `providerId: null` (frontend sends null for non-provider modes); was incorrectly returning "Invalid request" for all batch tests
+- **Provider test modal**: Fixed `[object Object]` display by normalizing API error objects to strings before rendering in `setTestResults` and `ProviderTestResultsView`
+- **i18n**: Added missing keys `cliTools.toolDescriptions.opencode`, `cliTools.toolDescriptions.kiro`, `cliTools.guides.opencode`, `cliTools.guides.kiro` to `en.json`
+- **i18n**: Synchronized 1111 missing keys across all 29 non-English language files using English values as fallbacks
-## [2.3.5] - 11. 3. 2026
+## [2.3.5] - 2026-03-11
-### Opraveno
+### Fixed
-- **@swc/helpers** : Přidána trvalá oprava `postinstall` pro kopírování `@swc/helpers` do `node_modules` samostatné aplikace – zabraňuje pádu MODULE_NOT_FOUND při globálních instalacích npm.
+- **@swc/helpers**: Added permanent `postinstall` fix to copy `@swc/helpers` into the standalone app's `node_modules` — prevents MODULE_NOT_FOUND crash on global npm installs
-## [2.3.4] - 10. 3. 2026
+## [2.3.4] - 2026-03-10
-### Přidáno
+### Added
-- Integrace více poskytovatelů a vylepšení dashboardu
+- Multiple provider integrations and dashboard improvements
diff --git a/docs/i18n/cs/CLI-TOOLS.md b/docs/i18n/cs/CLI-TOOLS.md
deleted file mode 100644
index 9d0c0899fb..0000000000
--- a/docs/i18n/cs/CLI-TOOLS.md
+++ /dev/null
@@ -1,344 +0,0 @@
-# Průvodce nastavením nástrojů CLI — OmniRoute
-
-Tato příručka vysvětluje, jak nainstalovat a nakonfigurovat všechny podporované nástroje CLI pro kódování umělé inteligence
-tak, aby **OmniRoute** fungoval jako jednotný backend, což vám umožní centralizovanou správu klíčů,
-sledování nákladů, přepínání modelů a protokolování požadavků napříč všemi nástroji.
-
----
-
-## Jak to funguje
-
-```
-Claude / Codex / OpenCode / Cline / KiloCode / Continue / Kiro / Cursor / Copilot
- │
- ▼ (všechny ukazují na OmniRoute)
- http://VASE_SERVER:20128/v1
- │
- ▼ (OmniRoute směruje ke správnému poskytovateli)
- Anthropic / OpenAI / Gemini / DeepSeek / Groq / Mistral / ...
-```
-
-**Výhody:**
-
-- Jeden API klíč pro správu všech nástrojů
-- Sledování nákladů napříč všemi CLI v dashboardu
-- Přepínání modelů bez nutnosti překonfigurování každého nástroje
-- Funguje lokálně i na vzdálených serverech (VPS)
-
----
-
-## Podporované nástroje (Zdroj pravdy v dashboardu)
-
-Karty dashboardu v `/dashboard/cli-tools` jsou generovány z `src/shared/constants/cliTools.ts`.
-Aktuální seznam (v3.0.0-rc.16):
-
-| Nástroj | ID | Příkaz | Režim nastavení | Metoda instalace |
-| ------------------ | ------------- | ------------ | --------------- | ---------------- |
-| **Claude Code** | `claude` | `claude` | env | npm |
-| **OpenAI Codex** | `codex` | `codex` | custom | npm |
-| **Factory Droid** | `droid` | `droid` | custom | bundled/CLI |
-| **OpenClaw** | `openclaw` | `openclaw` | custom | bundled/CLI |
-| **Cursor** | `cursor` | aplikace | guide | desktop app |
-| **Cline** | `cline` | `cline` | custom | npm |
-| **Kilo Code** | `kilo` | `kilocode` | custom | npm |
-| **Continue** | `continue` | rozšíření | guide | VS Code |
-| **Antigravity** | `antigravity` | interní | mitm | OmniRoute |
-| **GitHub Copilot** | `copilot` | rozšíření | custom | VS Code |
-| **OpenCode** | `opencode` | `opencode` | guide | npm |
-| **Kiro AI** | `kiro` | aplikace/CLI | mitm | desktop/CLI |
-
-### Synchronizace otisků CLI (Agenti + Nastavení)
-
-`/dashboard/agents` a `Nastavení > CLI Otisk` používají `src/shared/constants/cliCompatProviders.ts`.
-To udržuje ID poskytovatelů v souladu s kartami CLI a staršími ID.
-
-| CLI ID | ID poskytovatele otisku |
-| ---------------------------------------------------------------------------------------------------- | ----------------------- |
-| `kilo` | `kilocode` |
-| `copilot` | `github` |
-| `claude` / `codex` / `antigravity` / `kiro` / `cursor` / `cline` / `opencode` / `droid` / `openclaw` | stejné ID |
-
-Starší ID jsou stále přijímána pro kompatibilitu: `copilot`, `kimi-coding`, `qwen`.
-
----
-
-## Krok 1 — Získejte OmniRoute API klíč
-
-1. Otevřete OmniRoute dashboard → **Správce API** (`/dashboard/api-manager`)
-2. Klikněte na **Vytvořit API klíč**
-3. Dejte mu název (např. `cli-tools`) a vyberte všechna oprávnění
-4. Zkopírujte klíč — budete ho potřebovat pro každý CLI níže
-
-> Váš klíč vypadá takto: `sk-xxxxxxxxxxxxxxxx-xxxxxxxxx`
-
----
-
-## Krok 2 — Nainstalujte nástroje CLI
-
-Všechny nástroje založené na npm vyžadují Node.js 18+:
-
-```bash
-# Claude Code (Anthropic)
-npm install -g @anthropic-ai/claude-code
-
-# OpenAI Codex
-npm install -g @openai/codex
-
-# OpenCode
-npm install -g opencode-ai
-
-# Cline
-npm install -g cline
-
-# KiloCode
-npm install -g kilocode
-
-# Kiro CLI (Amazon — vyžaduje curl + unzip)
-apt-get install -y unzip # na Debian/Ubuntu
-curl -fsSL https://cli.kiro.dev/install | bash
-export PATH="$HOME/.local/bin:$PATH" # přidat do ~/.bashrc
-```
-
-**Ověření:**
-
-```bash
-claude --version # 2.x.x
-codex --version # 0.x.x
-opencode --version # x.x.x
-cline --version # 2.x.x
-kilocode --version # x.x.x (nebo: kilo --version)
-kiro-cli --version # 1.x.x
-```
-
----
-
-## Krok 3 — Nastavte globální proměnné prostředí
-
-Přidejte do `~/.bashrc` (nebo `~/.zshrc`), pak spusťte `source ~/.bashrc`:
-
-```bash
-# OmniRoute Univerzální koncový bod
-export OPENAI_BASE_URL="http://localhost:20128/v1"
-export OPENAI_API_KEY="sk-vase-omniroute-klic"
-export ANTHROPIC_BASE_URL="http://localhost:20128/v1"
-export ANTHROPIC_API_KEY="sk-vase-omniroute-klic"
-export GEMINI_BASE_URL="http://localhost:20128/v1"
-export GEMINI_API_KEY="sk-vase-omniroute-klic"
-```
-
-> Pro **vzdálený server** nahraďte `localhost:20128` IP adresou nebo doménou serveru,
-> např. `http://192.168.0.15:20128`.
-
----
-
-## Krok 4 — Nakonfigurujte každý nástroj
-
-### Claude Code
-
-```bash
-# Via CLI:
-claude config set --global api-base-url http://localhost:20128/v1
-
-# Nebo vytvořte ~/.claude/settings.json:
-mkdir -p ~/.claude && cat > ~/.claude/settings.json << EOF
-{
- "apiBaseUrl": "http://localhost:20128/v1",
- "apiKey": "sk-vase-omniroute-klic"
-}
-EOF
-```
-
-**Test:** `claude "say hello"`
-
----
-
-### OpenAI Codex
-
-```bash
-mkdir -p ~/.codex && cat > ~/.codex/config.yaml << EOF
-model: auto
-apiKey: sk-vase-omniroute-klic
-apiBaseUrl: http://localhost:20128/v1
-EOF
-```
-
-**Test:** `codex "what is 2+2?"`
-
----
-
-### OpenCode
-
-```bash
-mkdir -p ~/.config/opencode && cat > ~/.config/opencode/config.toml << EOF
-[provider.openai]
-base_url = "http://localhost:20128/v1"
-api_key = "sk-vase-omniroute-klic"
-EOF
-```
-
-**Test:** `opencode`
-
----
-
-### Cline (CLI nebo VS Code)
-
-**Režim CLI:**
-
-```bash
-mkdir -p ~/.cline/data && cat > ~/.cline/data/globalState.json << EOF
-{
- "apiProvider": "openai",
- "openAiBaseUrl": "http://localhost:20128/v1",
- "openAiApiKey": "sk-vase-omniroute-klic"
-}
-EOF
-```
-
-**Režim VS Code:**
-Nastavení rozšíření Cline → API Provider: `OpenAI Compatible` → Base URL: `http://localhost:20128/v1`
-
-Nebo použijte OmniRoute dashboard → **CLI Nástroje → Cline → Použít konfiguraci**.
-
----
-
-### KiloCode (CLI nebo VS Code)
-
-**Režim CLI:**
-
-```bash
-kilocode --api-base http://localhost:20128/v1 --api-key sk-vase-omniroute-klic
-```
-
-**Nastavení VS Code:**
-
-```json
-{
- "kilo-code.openAiBaseUrl": "http://localhost:20128/v1",
- "kilo-code.apiKey": "sk-vase-omniroute-klic"
-}
-```
-
-Nebo použijte OmniRoute dashboard → **CLI Nástroje → KiloCode → Použít konfiguraci**.
-
----
-
-### Continue (Rozšíření VS Code)
-
-Upravte `~/.continue/config.yaml`:
-
-```yaml
-models:
- - name: OmniRoute
- provider: openai
- model: auto
- apiBase: http://localhost:20128/v1
- apiKey: sk-vase-omniroute-klic
- default: true
-```
-
-Po úpravě restartujte VS Code.
-
----
-
-### Kiro CLI (Amazon)
-
-```bash
-# Přihlaste se ke svému AWS/Kiro účtu:
-kiro-cli login
-
-# CLI používá vlastní autentifikaci — OmniRoute není potřeba jako backend pro samotný Kiro CLI.
-# Používejte kiro-cli společně s OmniRoute pro ostatní nástroje.
-kiro-cli status
-```
-
----
-
-### Cursor (Desktop aplikace)
-
-> **Poznámka:** Cursor směruje požadavky přes svůj cloud. Pro integraci s OmniRoute,
-> povolte **Cloud Endpoint** v nastavení OmniRoute a použijte vaši veřejnou doménu.
-
-Via GUI: **Settings → Models → OpenAI API Key**
-
-- Base URL: `https://vase-domena.com/v1`
-- API Key: váš OmniRoute klíč
-
----
-
-## Automatická konfigurace v dashboardu
-
-OmniRoute dashboard automatizuje konfiguraci většiny nástrojů:
-
-1. Jděte na `http://localhost:20128/dashboard/cli-tools`
-2. Rozbalte libovolnou kartu nástroje
-3. Vyberte svůj API klíč z rozbalovacího seznamu
-4. Klikněte na **Použít konfiguraci** (pokud je nástroj detekován jako nainstalovaný)
-5. Nebo ručně zkopírujte vygenerovaný konfigurační snippet
-
----
-
-## Vestavěný agenti: Droid & OpenClaw
-
-**Droid** a **OpenClaw** jsou AI agenti vestavění přímo do OmniRoute — není potřeba žádná instalace.
-Běží jako interní trasy a automaticky používají směrování modelů OmniRoute.
-
-- Přístup: `http://localhost:20128/dashboard/agents`
-- Konfigurace: stejné kombinace a poskytovatelé jako všechny ostatní nástroje
-- Není potřeba API klíč ani instalace CLI
-
----
-
-## Dostupné API koncové body
-
-| Koncový bod | Popis | Použití pro |
-| -------------------------- | --------------------------------------- | ------------------------------------- |
-| `/v1/chat/completions` | Standardní chat (všichni poskytovatelé) | Všechny moderní nástroje |
-| `/v1/responses` | Responses API (formát OpenAI) | Codex, agentní workflowy |
-| `/v1/completions` | Legacy textové dokončení | Starší nástroje používající `prompt:` |
-| `/v1/embeddings` | Textové vložení | RAG, vyhledávání |
-| `/v1/images/generations` | Generování obrázků | DALL-E, Flux, atd. |
-| `/v1/audio/speech` | Text-to-speech | ElevenLabs, OpenAI TTS |
-| `/v1/audio/transcriptions` | Speech-to-text | Deepgram, AssemblyAI |
-
----
-
-## Řešení problémů
-
-| Chyba | Příčina | Oprava |
-| ----------------------------- | ----------------------- | -------------------------------------------------------- |
-| `Connection refused` | OmniRoute neběží | `pm2 start omniroute` |
-| `401 Unauthorized` | Špatný API klíč | Zkontrolujte v `/dashboard/api-manager` |
-| `No combo configured` | Žádná aktivní kombinace | Nastavte v `/dashboard/combos` |
-| `invalid model` | Model není v katalogu | Použijte `auto` nebo zkontrolujte `/dashboard/providers` |
-| CLI zobrazuje "not installed" | Binárka není v PATH | Zkontrolujte `which ` |
-| `kiro-cli: not found` | Není v PATH | `export PATH="$HOME/.local/bin:$PATH"` |
-
----
-
-## Rychlý skript pro nastavení (jeden příkaz)
-
-```bash
-# Nainstalujte všechny CLI a nakonfigurujte pro OmniRoute (nahraďte svým klíčem a URL serveru)
-OMNIROUTE_URL="http://localhost:20128/v1"
-OMNIROUTE_KEY="sk-vase-omniroute-klic"
-
-npm install -g @anthropic-ai/claude-code @openai/codex opencode-ai cline kilocode
-
-# Kiro CLI
-apt-get install -y unzip 2>/dev/null; curl -fsSL https://cli.kiro.dev/install | bash
-
-# Zápis konfigurací
-mkdir -p ~/.claude ~/.codex ~/.config/opencode ~/.continue
-
-cat > ~/.claude/settings.json <<< "{\"apiBaseUrl\":\"$OMNIROUTE_URL\",\"apiKey\":\"$OMNIROUTE_KEY\"}"
-cat > ~/.codex/config.yaml <<< "model: auto\napiKey: $OMNIROUTE_KEY\napiBaseUrl: $OMNIROUTE_URL"
-cat >> ~/.bashrc << EOF
-export OPENAI_BASE_URL="$OMNIROUTE_URL"
-export OPENAI_API_KEY="$OMNIROUTE_KEY"
-export ANTHROPIC_BASE_URL="$OMNIROUTE_URL"
-export ANTHROPIC_API_KEY="$OMNIROUTE_KEY"
-EOF
-
-source ~/.bashrc
-echo "✅ Všechny CLI nainstalovány a nakonfigurovány pro OmniRoute"
-```
diff --git a/docs/i18n/cs/CODEBASE_DOCUMENTATION.md b/docs/i18n/cs/CODEBASE_DOCUMENTATION.md
deleted file mode 100644
index 55b277e345..0000000000
--- a/docs/i18n/cs/CODEBASE_DOCUMENTATION.md
+++ /dev/null
@@ -1,589 +0,0 @@
-# omniroute — Dokumentace kódové základny
-
-🌐 **Jazyky:** 🇺🇸 [angličtina](CODEBASE_DOCUMENTATION.md) | 🇧🇷 [Português (Brazílie)](i18n/pt-BR/CODEBASE_DOCUMENTATION.md) | 🇪🇸 [Español](i18n/es/CODEBASE_DOCUMENTATION.md) | 🇫🇷 [Français](i18n/fr/CODEBASE_DOCUMENTATION.md) | 🇮🇹 [Italiano](i18n/it/CODEBASE_DOCUMENTATION.md) | 🇷🇺 [Русский](i18n/ru/CODEBASE_DOCUMENTATION.md) | 🇨🇳[中文 (简体)](i18n/zh-CN/CODEBASE_DOCUMENTATION.md) | 🇩🇪 [Deutsch](i18n/de/CODEBASE_DOCUMENTATION.md) | 🇮🇳 [हिन्दी](i18n/in/CODEBASE_DOCUMENTATION.md) | 🇹🇭 [ไทย](i18n/th/CODEBASE_DOCUMENTATION.md) | 🇺🇦 [Українська](i18n/uk-UA/CODEBASE_DOCUMENTATION.md) | 🇸🇦 [العربية](i18n/ar/CODEBASE_DOCUMENTATION.md) | 🇯🇵[日本語](i18n/ja/CODEBASE_DOCUMENTATION.md)| 🇻🇳 [Tiếng Việt](i18n/vi/CODEBASE_DOCUMENTATION.md) | 🇧🇬 [Български](i18n/bg/CODEBASE_DOCUMENTATION.md) | 🇩🇰 [Dánsko](i18n/da/CODEBASE_DOCUMENTATION.md) | 🇫🇮 [Suomi](i18n/fi/CODEBASE_DOCUMENTATION.md) | 🇮🇱 [עברית](i18n/he/CODEBASE_DOCUMENTATION.md) | 🇭🇺 [maďarština](i18n/hu/CODEBASE_DOCUMENTATION.md) | 🇮🇩 [Bahasa Indonésie](i18n/id/CODEBASE_DOCUMENTATION.md) | 🇰🇷 [한국어](i18n/ko/CODEBASE_DOCUMENTATION.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/CODEBASE_DOCUMENTATION.md) | 🇳🇱 [Nizozemsko](i18n/nl/CODEBASE_DOCUMENTATION.md) | 🇳🇴 [Norsk](i18n/no/CODEBASE_DOCUMENTATION.md) | 🇵🇹 [Português (Portugalsko)](i18n/pt/CODEBASE_DOCUMENTATION.md) | 🇷🇴 [Română](i18n/ro/CODEBASE_DOCUMENTATION.md) | 🇵🇱 [Polski](i18n/pl/CODEBASE_DOCUMENTATION.md) | 🇸🇰 [Slovenčina](i18n/sk/CODEBASE_DOCUMENTATION.md) | 🇸🇪 [Svenska](i18n/sv/CODEBASE_DOCUMENTATION.md) | 🇵🇭 [Filipínec](i18n/phi/CODEBASE_DOCUMENTATION.md) | 🇨🇿 [Čeština](i18n/cs/CODEBASE_DOCUMENTATION.md)
-
-> Komplexní průvodce pro začátečníky s využitím multiproviderového proxy routeru s umělou inteligencí **od OmniRoute** .
-
----
-
-## 1. Co je to omniroute?
-
-Omniroute je **proxy router** , který se nachází mezi klienty umělé inteligence (Claude CLI, Codex, Cursor IDE atd.) a poskytovateli umělé inteligence (Anthropic, Google, OpenAI, AWS, GitHub atd.). Řeší jeden velký problém:
-
-> **Různí klienti AI hovoří různými „jazyky“ (formáty API) a různí poskytovatelé AI také očekávají různé „jazyky“.** Omniroute mezi nimi automaticky překládá.
-
-Představte si to jako univerzálního překladatele v Organizaci spojených národů – kterýkoli delegát může mluvit jakýmkoli jazykem a překladatel ho pro kteréhokoli jiného delegáta převede.
-
----
-
-## 2. Přehled architektury
-
-```mermaid
-graph LR
- subgraph Clients
- A[Claude CLI]
- B[Codex]
- C[Cursor IDE]
- D[OpenAI-compatible]
- end
-
- subgraph omniroute
- E[Handler Layer]
- F[Translator Layer]
- G[Executor Layer]
- H[Services Layer]
- end
-
- subgraph Providers
- I[Anthropic Claude]
- J[Google Gemini]
- K[OpenAI / Codex]
- L[GitHub Copilot]
- M[AWS Kiro]
- N[Antigravity]
- O[Cursor API]
- end
-
- A --> E
- B --> E
- C --> E
- D --> E
- E --> F
- F --> G
- G --> I
- G --> J
- G --> K
- G --> L
- G --> M
- G --> N
- G --> O
- H -.-> E
- H -.-> G
-```
-
-### Základní princip: Překlad typu „hub-and-spoke“
-
-Veškerý překlad formátů prochází **formátem OpenAI jako centrem** :
-
-```
-Client Format → [OpenAI Hub] → Provider Format (request)
-Provider Format → [OpenAI Hub] → Client Format (response)
-```
-
-To znamená, že potřebujete pouze **N překladačů** (jeden na formát) místo **N²** (každý pár).
-
----
-
-## 3. Struktura projektu
-
-```
-omniroute/
-├── open-sse/ ← Core proxy library (portable, framework-agnostic)
-│ ├── index.js ← Main entry point, exports everything
-│ ├── config/ ← Configuration & constants
-│ ├── executors/ ← Provider-specific request execution
-│ ├── handlers/ ← Request handling orchestration
-│ ├── services/ ← Business logic (auth, models, fallback, usage)
-│ ├── translator/ ← Format translation engine
-│ │ ├── request/ ← Request translators (8 files)
-│ │ ├── response/ ← Response translators (7 files)
-│ │ └── helpers/ ← Shared translation utilities (6 files)
-│ └── utils/ ← Utility functions
-├── src/ ← Application layer (Express/Worker runtime)
-│ ├── app/ ← Web UI, API routes, middleware
-│ ├── lib/ ← Database, auth, and shared library code
-│ ├── mitm/ ← Man-in-the-middle proxy utilities
-│ ├── models/ ← Database models
-│ ├── shared/ ← Shared utilities (wrappers around open-sse)
-│ ├── sse/ ← SSE endpoint handlers
-│ └── store/ ← State management
-├── data/ ← Runtime data (credentials, logs)
-│ └── provider-credentials.json (external credentials override, gitignored)
-└── tester/ ← Test utilities
-```
-
----
-
-## 4. Rozdělení podle modulů
-
-### 4.1 Konfigurace ( `open-sse/config/` )
-
-Jediný **zdroj pravdivých informací** pro všechny konfigurace poskytovatelů.
-
-| Soubor | Účel |
-| ----------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
-| `constants.ts` | Objekt `PROVIDERS` se základními URL adresami, přihlašovacími údaji OAuth (výchozí), záhlavími a výchozími systémovými výzvami pro každého poskytovatele. Definuje také `HTTP_STATUS` , `ERROR_TYPES` , `COOLDOWN_MS` , `BACKOFF_CONFIG` a `SKIP_PATTERNS` . |
-| `credentialLoader.ts` | Načte externí přihlašovací údaje z `data/provider-credentials.json` a sloučí je s pevně zakódovanými výchozími hodnotami v `PROVIDERS` . Uchovává tajné údaje mimo kontrolu zdrojového kódu a zároveň zachovává zpětnou kompatibilitu. |
-| `providerModels.ts` | Centrální registr modelů: mapuje aliasy poskytovatelů → ID modelů. Funkce jako `getModels()` , `getProviderByAlias()` . |
-| `codexInstructions.ts` | Systémové instrukce vložené do požadavků Codexu (omezení úprav, pravidla sandboxu, zásady schvalování). |
-| `defaultThinkingSignature.ts` | Výchozí „myšlenkové“ podpisy pro modely Claude a Gemini. |
-| `ollamaModels.ts` | Definice schématu pro lokální Ollama modely (název, velikost, rodina, kvantizace). |
-
-#### Postup načítání přihlašovacích údajů
-
-```mermaid
-flowchart TD
- A["App starts"] --> B["constants.ts defines PROVIDERS\nwith hardcoded defaults"]
- B --> C{"data/provider-credentials.json\nexists?"}
- C -->|Yes| D["credentialLoader reads JSON"]
- C -->|No| E["Use hardcoded defaults"]
- D --> F{"For each provider in JSON"}
- F --> G{"Provider exists\nin PROVIDERS?"}
- G -->|No| H["Log warning, skip"]
- G -->|Yes| I{"Value is object?"}
- I -->|No| J["Log warning, skip"]
- I -->|Yes| K["Merge clientId, clientSecret,\ntokenUrl, authUrl, refreshUrl"]
- K --> F
- H --> F
- J --> F
- F -->|Done| L["PROVIDERS ready with\nmerged credentials"]
- E --> L
-```
-
----
-
-### 4.2 Vykonavatelé ( `open-sse/executors/` )
-
-Prováděcí metody zapouzdřují **logiku specifickou pro poskytovatele** pomocí **vzoru strategie** . Každý prováděcí metody podle potřeby přepisují základní metody.
-
-```mermaid
-classDiagram
- class BaseExecutor {
- +buildUrl(model, stream, options)
- +buildHeaders(credentials, stream, body)
- +transformRequest(body, model, stream, credentials)
- +execute(url, options)
- +shouldRetry(status, error)
- +refreshCredentials(credentials, log)
- }
-
- class DefaultExecutor {
- +refreshCredentials()
- }
-
- class AntigravityExecutor {
- +buildUrl()
- +buildHeaders()
- +transformRequest()
- +shouldRetry()
- +refreshCredentials()
- }
-
- class CursorExecutor {
- +buildUrl()
- +buildHeaders()
- +transformRequest()
- +parseResponse()
- +generateChecksum()
- }
-
- class KiroExecutor {
- +buildUrl()
- +buildHeaders()
- +transformRequest()
- +parseEventStream()
- +refreshCredentials()
- }
-
- BaseExecutor <|-- DefaultExecutor
- BaseExecutor <|-- AntigravityExecutor
- BaseExecutor <|-- CursorExecutor
- BaseExecutor <|-- KiroExecutor
- BaseExecutor <|-- CodexExecutor
- BaseExecutor <|-- GeminiCLIExecutor
- BaseExecutor <|-- GithubExecutor
-```
-
-| Vykonavatel | Poskytovatel | Klíčové specializace |
-| ---------------- | ------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------ |
-| `base.ts` | — | Abstraktní základ: tvorba URL adres, hlavičky, logika opakování, aktualizace přihlašovacích údajů |
-| `default.ts` | Claude, Gemini, OpenAI, GLM, Kimi, MiniMax | Aktualizace generického tokenu OAuth pro standardní poskytovatele |
-| `antigravity.ts` | Kód Google Cloud | Generování ID projektu/relace, záložní více URL adres, vlastní analýza opakovaných pokusů z chybových zpráv („reset po 2h7m23s“) |
-| `cursor.ts` | IDE kurzoru | **Nejsložitější** : autorizace kontrolního součtu SHA-256, kódování požadavků Protobuf, analýza binárních EventStream → SSE odpovědí |
-| `codex.ts` | OpenAI Codex | Vkládá systémové instrukce, spravuje úrovně myšlení, odstraňuje nepodporované parametry |
-| `gemini-cli.ts` | Google Gemini CLI | Vytvoření vlastní URL adresy ( `streamGenerateContent` ), aktualizace tokenu Google OAuth |
-| `github.ts` | GitHub Copilot | Systém duálních tokenů (GitHub OAuth + Copilot token), napodobování hlaviček VSCode |
-| `kiro.ts` | AWS CodeWhisperer | Binární parsování AWS EventStream, rámce událostí AMZN, odhad tokenů |
-| `index.ts` | — | Továrna: název poskytovatele map → třída exekutoru s výchozím záložním nastavením |
-
----
-
-### 4.3 Obslužné rutiny ( `open-sse/handlers/` )
-
-**Orchestrační vrstva** – koordinuje překlad, provádění, streamování a zpracování chyb.
-
-| Soubor | Účel |
-| --------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| `chatCore.ts` | **Centrální orchestrátor** (~600 řádků). Zvládá kompletní životní cyklus požadavku: detekce formátu → překlad → odeslání exekutoru → streamovaná/nestreamovaná odpověď → aktualizace tokenu → zpracování chyb → protokolování využití. |
-| `responsesHandler.ts` | Adaptér pro OpenAI Responses API: převádí formát odpovědí → Dokončení chatu → odesílá do `chatCore` → převádí SSE zpět do formátu odpovědí. |
-| `embeddings.ts` | Obslužná rutina generování embeddingu: řeší model embeddingu → poskytovatele, odesílá do API poskytovatele, vrací odpověď na embedding kompatibilní s OpenAI. Podporuje 6+ poskytovatelů. |
-| `imageGeneration.ts` | Obslužná rutina generování obrázků: řeší model obrázku → poskytovatele, podporuje režimy kompatibilní s OpenAI, Gemini-image (Antigravity) a fallback (Nebius). Vrací obrázky v base64 nebo URL. |
-
-#### Životní cyklus požadavku (chatCore.ts)
-
-```mermaid
-sequenceDiagram
- participant Client
- participant chatCore
- participant Translator
- participant Executor
- participant Provider
-
- Client->>chatCore: Request (any format)
- chatCore->>chatCore: Detect source format
- chatCore->>chatCore: Check bypass patterns
- chatCore->>chatCore: Resolve model & provider
- chatCore->>Translator: Translate request (source → OpenAI → target)
- chatCore->>Executor: Get executor for provider
- Executor->>Executor: Build URL, headers, transform request
- Executor->>Executor: Refresh credentials if needed
- Executor->>Provider: HTTP fetch (streaming or non-streaming)
-
- alt Streaming
- Provider-->>chatCore: SSE stream
- chatCore->>chatCore: Pipe through SSE transform stream
- Note over chatCore: Transform stream translates
each chunk: target → OpenAI → source
- chatCore-->>Client: Translated SSE stream
- else Non-streaming
- Provider-->>chatCore: JSON response
- chatCore->>Translator: Translate response
- chatCore-->>Client: Translated JSON
- end
-
- alt Error (401, 429, 500...)
- chatCore->>Executor: Retry with credential refresh
- chatCore->>chatCore: Account fallback logic
- end
-```
-
----
-
-### 4.4 Služby ( `open-sse/services/` )
-
-Obchodní logika, která podporuje obslužné rutiny a vykonavatele.
-
-| Soubor | Účel |
-| -------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| `provider.ts` | **Detekce formátu** ( `detectFormat` ): analyzuje strukturu těla požadavku a identifikuje formáty Claude/OpenAI/Gemini/Antigravity/Responses (včetně heuristiky `max_tokens` pro Claude). Dále: tvorba URL, tvorba hlaviček, normalizace konfigurace thinking. Podporuje dynamické poskytovatele kompatibilní `openai-compatible-*` a `anthropic-compatible-*` . |
-| `model.ts` | Analýza řetězců modelu ( `claude/model-name` → `{provider: "claude", model: "model-name"}` ), rozlišení aliasů s detekcí kolizí, sanitizace vstupu (odmítá průchod cestou/řídicí znaky) a rozlišení informací o modelu s podporou asynchronních metod pro získávání aliasů. |
-| `accountFallback.ts` | Ovládání limitů rychlosti: exponenciální upomínka (1 s → 2 s → 4 s → max. 2 min), správa doby zpoždění účtu, klasifikace chyb (které chyby spouštějí fallback a které ne). |
-| `tokenRefresh.ts` | Aktualizace tokenu OAuth pro **všechny poskytovatele** : Google (Gemini, Antigravity), Claude, Codex, Qwen, Qoder, GitHub (duální token OAuth + Copilot), Kiro (AWS SSO OIDC + sociální ověřování). Zahrnuje mezipaměť deduplikace promise za provozu a opakování s exponenciálním zpožděním. |
-| `combo.ts` | **Kombinované modely** : řetězce záložních modelů. Pokud model A selže s chybou způsobilou pro záložní model, zkuste model B, poté C atd. Vrací skutečné stavové kódy upstreamu. |
-| `usage.ts` | Načítá data o kvótách/využití z API poskytovatelů (kvóty GitHub Copilot, kvóty modelu Antigravity, limity rychlosti Codexu, rozpisy využití Kiro, nastavení Claude). |
-| `accountSelector.ts` | Inteligentní výběr účtu s algoritmem bodování: pro výběr optimálního účtu pro každý požadavek se zohledňuje priorita, zdravotní stav, pozice v systému round robin a stav ochlazování. |
-| `contextManager.ts` | Správa životního cyklu kontextu požadavku: vytváří a sleduje objekty kontextu pro každý požadavek s metadaty (ID požadavku, časová razítka, informace o poskytovateli) pro ladění a protokolování. |
-| `ipFilter.ts` | Řízení přístupu založené na IP adrese: podporuje režimy povolených seznamů a blokovaných seznamů. Před zpracováním požadavků API ověřuje IP adresu klienta podle nakonfigurovaných pravidel. |
-| `sessionManager.ts` | Sledování relací s otisky prstů klientů: sleduje aktivní relace pomocí hašovaných identifikátorů klientů, monitoruje počty požadavků a poskytuje metriky relací. |
-| `signatureCache.ts` | Mezipaměť deduplikace na základě signatur požadavků: zabraňuje duplicitním požadavkům ukládáním nedávných signatur požadavků do mezipaměti a vrácením odpovědí z mezipaměti pro identické požadavky v rámci časového okna. |
-| `systemPrompt.ts` | Globální vložení systémového výzvy: přidá konfigurovatelnou systémovou výzvu ke všem požadavkům s možností kompatibility pro jednotlivé poskytovatele. |
-| `thinkingBudget.ts` | Správa rozpočtu tokenů uvažování: podporuje režimy průchodu, automatický (konfigurace strip thinking), vlastní (pevný rozpočet) a adaptivní (měřítko složitosti) pro řízení tokenů myšlení/uvažování. |
-| `wildcardRouter.ts` | Směrování podle vzorů zástupných znaků: rozpoznává vzory zástupných znaků (např. `*/claude-*` ) na konkrétní páry poskytovatel/model na základě dostupnosti a priority. |
-
-#### Deduplikace obnovení tokenů
-
-```mermaid
-sequenceDiagram
- participant R1 as Request 1
- participant R2 as Request 2
- participant Cache as refreshPromiseCache
- participant OAuth as OAuth Provider
-
- R1->>Cache: getAccessToken("gemini", token)
- Cache->>Cache: No in-flight promise
- Cache->>OAuth: Start refresh
- R2->>Cache: getAccessToken("gemini", token)
- Cache->>Cache: Found in-flight promise
- Cache-->>R2: Return existing promise
- OAuth-->>Cache: New access token
- Cache-->>R1: New access token
- Cache-->>R2: Same access token (shared)
- Cache->>Cache: Delete cache entry
-```
-
-#### Záložní stavový automat účtu
-
-```mermaid
-stateDiagram-v2
- [*] --> Active
- Active --> Error: Request fails (401/429/500)
- Error --> Cooldown: Apply backoff
- Cooldown --> Active: Cooldown expires
- Active --> Active: Request succeeds (reset backoff)
-
- state Error {
- [*] --> ClassifyError
- ClassifyError --> ShouldFallback: Rate limit / Auth / Transient
- ClassifyError --> NoFallback: 400 Bad Request
- }
-
- state Cooldown {
- [*] --> ExponentialBackoff
- ExponentialBackoff: Level 0 = 1s
- ExponentialBackoff: Level 1 = 2s
- ExponentialBackoff: Level 2 = 4s
- ExponentialBackoff: Max = 2min
- }
-```
-
-#### Řetězec kombinovaných modelů
-
-```mermaid
-flowchart LR
- A["Request with\ncombo model"] --> B["Model A"]
- B -->|"2xx Success"| C["Return response"]
- B -->|"429/401/500"| D{"Fallback\neligible?"}
- D -->|Yes| E["Model B"]
- D -->|No| F["Return error"]
- E -->|"2xx Success"| C
- E -->|"429/401/500"| G{"Fallback\neligible?"}
- G -->|Yes| H["Model C"]
- G -->|No| F
- H -->|"2xx Success"| C
- H -->|"Fail"| I["All failed →\nReturn last status"]
-```
-
----
-
-### 4.5 Překladač ( `open-sse/translator/` )
-
-**Modul pro překlad formátů** využívající systém samoregistrujících se pluginů.
-
-#### Architektura
-
-```mermaid
-graph TD
- subgraph "Request Translation"
- A["Claude → OpenAI"]
- B["Gemini → OpenAI"]
- C["Antigravity → OpenAI"]
- D["OpenAI Responses → OpenAI"]
- E["OpenAI → Claude"]
- F["OpenAI → Gemini"]
- G["OpenAI → Kiro"]
- H["OpenAI → Cursor"]
- end
-
- subgraph "Response Translation"
- I["Claude → OpenAI"]
- J["Gemini → OpenAI"]
- K["Kiro → OpenAI"]
- L["Cursor → OpenAI"]
- M["OpenAI → Claude"]
- N["OpenAI → Antigravity"]
- O["OpenAI → Responses"]
- end
-```
-
-| Adresář | Soubory | Popis |
-| ------------ | -------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| `request/` | 8 překladatelů | Převod těl požadavků mezi formáty. Každý soubor se při importu sám zaregistruje pomocí `register(from, to, fn)` . |
-| `response/` | 7 překladatelů | Převádí bloky odpovědí streamovaných dat mezi formáty. Zpracovává typy událostí SSE, myšlenkové bloky a volání nástrojů. |
-| `helpers/` | 6 pomocníků | Sdílené utility: `claudeHelper` (extrakce systémových prompts, thinking config), `geminiHelper` (mapování částí/obsahu), `openaiHelper` (filtrování formátů), `toolCallHelper` (generování ID, vkládání chybějících odpovědí), `maxTokensHelper` , `responsesApiHelper` . |
-| `index.ts` | — | Překladový engine: `translateRequest()` , `translateResponse()` , správa stavu, registr. |
-| `formats.ts` | — | Formátovací konstanty: `OPENAI` , `CLAUDE` , `GEMINI` , `ANTIGRAVITY` , `KIRO` , `CURSOR` , `OPENAI_RESPONSES` . |
-
-#### Klíčový design: Samoregistrující se pluginy
-
-```javascript
-// Each translator file calls register() on import:
-import { register } from "../index.js";
-register("claude", "openai", translateClaudeToOpenAI);
-
-// The index.js imports all translator files, triggering registration:
-import "./request/claude-to-openai.js"; // ← self-registers
-```
-
----
-
-### 4.6 Nástroje ( `open-sse/utils/` )
-
-| Soubor | Účel |
-| ------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| `error.ts` | Vytváření chybové odezvy (formát kompatibilní s OpenAI), parsování chyb v upstreamu, extrakce doby opakování Antigravity z chybových zpráv, streamování chyb SSE. |
-| `stream.ts` | **SSE Transform Stream** — základní streamovací kanál. Dva režimy: `TRANSLATE` (plný překlad formátu) a `PASSTHROUGH` (normalizace + extrakce využití). Zpracovává ukládání bloků do vyrovnávací paměti, odhad využití a sledování délky obsahu. Instance kodéru/dekodéru pro každý stream se vyhýbají sdílenému stavu. |
-| `streamHelpers.ts` | Nízkoúrovňové utility SSE: `parseSSELine` (tolerantní k bílým znakům), `hasValuableContent` (filtruje prázdné segmenty pro OpenAI/Claude/Gemini), `fixInvalidId` , `formatSSE` (serializace SSE s ohledem na formát s čištěním `perf_metrics` ). |
-| `usageTracking.ts` | Extrakce využití tokenů z libovolného formátu (Claude/OpenAI/Gemini/Responses), odhad s oddělenými poměry znaků na token pro jednotlivé nástroje/zprávy, přidání vyrovnávací paměti (bezpečnostní rezerva 2000 tokenů), filtrování polí specifických pro formát, protokolování konzole s barvami ANSI. |
-| `requestLogger.ts` | Protokolování požadavků na základě souborů (přihlášení pomocí `ENABLE_REQUEST_LOGS=true` ). Vytváří složky relací s očíslovanými soubory: `1_req_client.json` → `7_res_client.txt` . Veškeré I/O operace jsou asynchronní (aktivní a zapomenutý). Maskuje citlivé hlavičky. |
-| `bypassHandler.ts` | Zachycuje specifické vzory z Claude CLI (extrakce názvu, zahřívání, počet) a vrací falešné odpovědi bez volání jakéhokoli poskytovatele. Podporuje streamování i nestreamování. Záměrně omezeno na rozsah Claude CLI. |
-| `networkProxy.ts` | Rozpozná URL odchozí proxy pro daného poskytovatele s prioritou: konfigurace specifická pro poskytovatele → globální konfigurace → proměnné prostředí ( `HTTPS_PROXY` / `HTTP_PROXY` / `ALL_PROXY` ). Podporuje výjimky `NO_PROXY` . Ukládá konfiguraci do mezipaměti po dobu 30 sekund. |
-
-#### Streamovací kanál SSE
-
-```mermaid
-flowchart TD
- A["Provider SSE stream"] --> B["TextDecoder\n(per-stream instance)"]
- B --> C["Buffer lines\n(split on newline)"]
- C --> D["parseSSELine()\n(trim whitespace, parse JSON)"]
- D --> E{"Mode?"}
- E -->|TRANSLATE| F["translateResponse()\ntarget → OpenAI → source"]
- E -->|PASSTHROUGH| G["fixInvalidId()\nnormalize chunk"]
- F --> H["hasValuableContent()\nfilter empty chunks"]
- G --> H
- H -->|"Has content"| I["extractUsage()\ntrack token counts"]
- H -->|"Empty"| J["Skip chunk"]
- I --> K["formatSSE()\nserialize + clean perf_metrics"]
- K --> L["TextEncoder\n(per-stream instance)"]
- L --> M["Enqueue to\nclient stream"]
-
- style A fill:#f9f,stroke:#333
- style M fill:#9f9,stroke:#333
-```
-
-#### Struktura relace protokolování požadavků
-
-```
-logs/
-└── claude_gemini_claude-sonnet_20260208_143045/
- ├── 1_req_client.json ← Raw client request
- ├── 2_req_source.json ← After initial conversion
- ├── 3_req_openai.json ← OpenAI intermediate format
- ├── 4_req_target.json ← Final target format
- ├── 5_res_provider.txt ← Provider SSE chunks (streaming)
- ├── 5_res_provider.json ← Provider response (non-streaming)
- ├── 6_res_openai.txt ← OpenAI intermediate chunks
- ├── 7_res_client.txt ← Client-facing SSE chunks
- └── 6_error.json ← Error details (if any)
-```
-
----
-
-### 4.7 Aplikační vrstva ( `src/` )
-
-| Adresář | Účel |
-| ------------- | ------------------------------------------------------------------------------------------------- |
-| `src/app/` | Webové uživatelské rozhraní, trasy API, middleware Express, obslužné rutiny zpětných volání OAuth |
-| `src/lib/` | Přístup k databázi ( `localDb.ts` , `usageDb.ts` ), ověřování, sdílení |
-| `src/mitm/` | Nástroje proxy typu „man-in-the-middle“ pro zachycení provozu poskytovatelů |
-| `src/models/` | Definice modelů databáze |
-| `src/shared/` | Obálky kolem funkcí open-sse (provider, stream, error atd.) |
-| `src/sse/` | Obslužné rutiny koncových bodů SSE, které propojují knihovnu open-sse s trasami Express |
-| `src/store/` | Správa stavu aplikací |
-
-#### Významné trasy API
-
-| Trasa | Metody | Účel |
-| --------------------------------------------- | --------------- | ------------------------------------------------------------------------------------------------ |
-| `/api/provider-models` | GET/POST/DELETE | CRUD pro vlastní modely na poskytovatele |
-| `/api/models/catalog` | GET | Agregovaný katalog všech modelů (chat, embedding, image, custom) seskupených podle poskytovatele |
-| `/api/settings/proxy` | GET/PUT/DELETE | Konfigurace hierarchické odchozí proxy ( `global/providers/combos/keys` ) |
-| `/api/settings/proxy/test` | POST | Ověřuje připojení proxy a vrací veřejnou IP adresu/latenci |
-| `/v1/providers/[provider]/chat/completions` | POST | Vyhrazené dokončování chatu pro jednotlivé poskytovatele s ověřováním modelu |
-| `/v1/providers/[provider]/embeddings` | POST | Vyhrazené vkládání pro jednotlivé poskytovatele s ověřováním modelu |
-| `/v1/providers/[provider]/images/generations` | POST | Vyhrazené generování obrázků pro každého poskytovatele s ověřováním modelu |
-| `/api/settings/ip-filter` | GET/PUT | Správa povolených/blokovaných IP adres |
-| `/api/settings/thinking-budget` | GET/PUT | Konfigurace rozpočtu tokenů zdůvodnění (průchozí/automatická/vlastní/adaptivní) |
-| `/api/settings/system-prompt` | GET/PUT | Globální vložení systémového promptu pro všechny požadavky |
-| `/api/sessions` | GET | Sledování a metriky aktivních relací |
-| `/api/rate-limits` | GET | Stav limitu sazby na účet |
-
----
-
-## 5. Klíčové návrhové vzory
-
-### 5.1 Překlad typu Hub-and-Spoke
-
-Všechny formáty se překládají prostřednictvím **formátu OpenAI jako ústředny** . Přidání nového poskytovatele vyžaduje napsání pouze **jednoho páru** překladačů (do/z OpenAI), nikoli N párů.
-
-### 5.2 Vzor strategie exekutora
-
-Každý poskytovatel má vyhrazenou třídu exekutoru, která dědí z `BaseExecutor` . Továrna v `executors/index.ts` vybere ten správný za běhu.
-
-### 5.3 Systém samoregistračních pluginů
-
-Moduly překladače se při importu registrují pomocí `register()` . Přidání nového překladače znamená pouze vytvoření souboru a jeho import.
-
-### 5.4 Záložní účet s exponenciálním oddlužením
-
-Když poskytovatel vrátí 429/401/500, systém může přepnout na další účet s exponenciálním zpožděním (1s → 2s → 4s → max. 2min).
-
-### 5.5 Kombinované modelové řetězy
-
-„Kombinace“ seskupuje více řetězců `provider/model` . Pokud první selže, automaticky se vrátí k dalšímu.
-
-### 5.6 Stavový streamovací překlad
-
-Překlad odpovědí udržuje stav napříč bloky SSE (sledování myšlenkových bloků, akumulace volání nástrojů, indexování bloků obsahu) prostřednictvím mechanismu `initState()` .
-
-### 5.7 Bezpečnostní vyrovnávací paměť pro použití
-
-K hlášenému využití je přidána vyrovnávací paměť o kapacitě 2000 tokenů, aby se zabránilo tomu, že klienti dosáhnou limitů kontextového okna v důsledku režijních nákladů systémových výzev a překladu formátu.
-
----
-
-## 6. Podporované formáty
-
-| Formát | Směr | Identifikátor |
-| ----------------------- | ----------- | ------------------ |
-| OpenAI Chat Completions | zdroj + cíl | `openai` |
-| OpenAI Responses API | zdroj + cíl | `openai-responses` |
-| Anthropic Claude | zdroj + cíl | `claude` |
-| Google Gemini | zdroj + cíl | `gemini` |
-| Google Gemini CLI | jen cíl | `gemini-cli` |
-| Antigravity | zdroj + cíl | `antigravity` |
-| AWS Kiro | jen cíl | `kiro` |
-| Cursor | jen cíl | `cursor` |
-
----
-
-## 7. Podporovaní poskytovatelé
-
-| Poskytovatel | Metoda ověřování | Vykonavatel | Klíčové poznámky |
-| ------------------------ | ------------------------ | ----------- | -------------------------------------------- |
-| Anthropic Claude | API klíč nebo OAuth | Výchozí | Používá hlavičku `x-api-key` |
-| Google Gemini | API klíč nebo OAuth | Výchozí | Používá hlavičku `x-goog-api-key` |
-| Google Gemini CLI | OAuth | GeminiCLI | Používá koncový bod `streamGenerateContent` |
-| Antigravity | OAuth | Antigravity | Záložní více URL, analýza opakovaných pokusů |
-| OpenAI | API klíč | Výchozí | Autorizace standardního nosiče |
-| Codex | OAuth | Codex | Vkládá systémové instrukce, řídí myšlení |
-| GitHub Copilot | OAuth + Copilot token | Github | Duální token, napodobování záhlaví VSCode |
-| Kiro (AWS) | AWS SSO OIDC nebo Social | Kiro | Analýza binárního EventStreamu |
-| Cursor IDE | Checksum auth | Cursor | Kódování Protobuf, kontrolní součty SHA-256 |
-| Qwen | OAuth | Výchozí | Standardní ověřování |
-| Qoder | OAuth (Basic + Bearer) | Výchozí | Duální hlavička pro autorizaci |
-| OpenRouter | API klíč | Výchozí | Autorizace standardního nosiče |
-| GLM, Kimi, MiniMax | API klíč | Výchozí | Kompatibilní s Claude, použijte `x-api-key` |
-| `openai-compatible-*` | API klíč | Výchozí | Dynamické: jakýkoli OpenAI kompatibilní |
-| `anthropic-compatible-*` | API klíč | Výchozí | Dynamické: jakýkoli Claude kompatibilní |
-
----
-
-## 8. Souhrn datového toku
-
-### Žádost o streamování
-
-```mermaid
-flowchart LR
- A["Client"] --> B["detectFormat()"]
- B --> C["translateRequest()\nsource → OpenAI → target"]
- C --> D["Executor\nbuildUrl + buildHeaders"]
- D --> E["fetch(providerURL)"]
- E --> F["createSSEStream()\nTRANSLATE mode"]
- F --> G["parseSSELine()"]
- G --> H["translateResponse()\ntarget → OpenAI → source"]
- H --> I["extractUsage()\n+ addBuffer"]
- I --> J["formatSSE()"]
- J --> K["Client receives\ntranslated SSE"]
- K --> L["logUsage()\nsaveRequestUsage()"]
-```
-
-### Žádost o nestreamování
-
-```mermaid
-flowchart LR
- A["Client"] --> B["detectFormat()"]
- B --> C["translateRequest()\nsource → OpenAI → target"]
- C --> D["Executor.execute()"]
- D --> E["translateResponse()\ntarget → OpenAI → source"]
- E --> F["Return JSON\nresponse"]
-```
-
-### Obtokový tok (Claude CLI)
-
-```mermaid
-flowchart LR
- A["Claude CLI request"] --> B{"Match bypass\npattern?"}
- B -->|"Title/Warmup/Count"| C["Generate fake\nOpenAI response"]
- B -->|"No match"| D["Normal flow"]
- C --> E["Translate to\nsource format"]
- E --> F["Return without\ncalling provider"]
-```
diff --git a/docs/i18n/cs/CONTRIBUTING.md b/docs/i18n/cs/CONTRIBUTING.md
index c5032002c9..4a85334808 100644
--- a/docs/i18n/cs/CONTRIBUTING.md
+++ b/docs/i18n/cs/CONTRIBUTING.md
@@ -1,18 +1,22 @@
-# Přispívání k OmniRoute
+# Contributing to OmniRoute (Čeština)
-Děkujeme za váš zájem o přispění! Tato příručka obsahuje vše, co potřebujete k zahájení.
+🌐 **Languages:** 🇺🇸 [English](../../../CONTRIBUTING.md) · 🇪🇸 [es](../es/CONTRIBUTING.md) · 🇫🇷 [fr](../fr/CONTRIBUTING.md) · 🇩🇪 [de](../de/CONTRIBUTING.md) · 🇮🇹 [it](../it/CONTRIBUTING.md) · 🇷🇺 [ru](../ru/CONTRIBUTING.md) · 🇨🇳 [zh-CN](../zh-CN/CONTRIBUTING.md) · 🇯🇵 [ja](../ja/CONTRIBUTING.md) · 🇰🇷 [ko](../ko/CONTRIBUTING.md) · 🇸🇦 [ar](../ar/CONTRIBUTING.md) · 🇮🇳 [in](../in/CONTRIBUTING.md) · 🇹🇭 [th](../th/CONTRIBUTING.md) · 🇻🇳 [vi](../vi/CONTRIBUTING.md) · 🇮🇩 [id](../id/CONTRIBUTING.md) · 🇲🇾 [ms](../ms/CONTRIBUTING.md) · 🇳🇱 [nl](../nl/CONTRIBUTING.md) · 🇵🇱 [pl](../pl/CONTRIBUTING.md) · 🇸🇪 [sv](../sv/CONTRIBUTING.md) · 🇳🇴 [no](../no/CONTRIBUTING.md) · 🇩🇰 [da](../da/CONTRIBUTING.md) · 🇫🇮 [fi](../fi/CONTRIBUTING.md) · 🇵🇹 [pt](../pt/CONTRIBUTING.md) · 🇷🇴 [ro](../ro/CONTRIBUTING.md) · 🇭🇺 [hu](../hu/CONTRIBUTING.md) · 🇧🇬 [bg](../bg/CONTRIBUTING.md) · 🇸🇰 [sk](../sk/CONTRIBUTING.md) · 🇺🇦 [uk-UA](../uk-UA/CONTRIBUTING.md) · 🇮🇱 [he](../he/CONTRIBUTING.md) · 🇵🇭 [phi](../phi/CONTRIBUTING.md) · 🇧🇷 [pt-BR](../pt-BR/CONTRIBUTING.md) · 🇨🇿 [cs](../cs/CONTRIBUTING.md)
---
-## Nastavení vývoje
+Thank you for your interest in contributing! This guide covers everything you need to get started.
-### Předpoklady
+---
-- **Node.js** 20+ (doporučeno: 22 LTS)
+## Development Setup
+
+### Prerequisites
+
+- **Node.js** >= 18 < 24 (recommended: 22 LTS)
- **npm** 10+
- **Git**
-### Klonovat a instalovat
+### Clone & Install
```bash
git clone https://github.com/diegosouzapw/OmniRoute.git
@@ -20,7 +24,7 @@ cd OmniRoute
npm install
```
-### Proměnné prostředí
+### Environment Variables
```bash
# Create your .env from the template
@@ -31,17 +35,28 @@ echo "JWT_SECRET=$(openssl rand -base64 48)" >> .env
echo "API_KEY_SECRET=$(openssl rand -hex 32)" >> .env
```
-Klíčové proměnné pro vývoj:
+Key variables for development:
-Proměnná | Výchozí nastavení pro vývoj | Popis
---- | --- | ---
-`PORT` | `3000` | Port serveru
-`NEXT_PUBLIC_BASE_URL` | `http://localhost:3000` | Základní URL pro frontend
-`JWT_SECRET` | (vygenerovat výše) | Tajemství podpisu JWT
-`INITIAL_PASSWORD` | `123456` | První přihlašovací heslo
-`ENABLE_REQUEST_LOGS` | `false` | Povolit protokoly požadavků na ladění
+| Variable | Development Default | Description |
+| ---------------------- | ------------------------ | --------------------- |
+| `PORT` | `20128` | Server port |
+| `NEXT_PUBLIC_BASE_URL` | `http://localhost:20128` | Base URL for frontend |
+| `JWT_SECRET` | (generate above) | JWT signing secret |
+| `INITIAL_PASSWORD` | `CHANGEME` | First login password |
+| `APP_LOG_LEVEL` | `info` | Log verbosity level |
-### Spuštěno lokálně
+### Dashboard Settings
+
+The dashboard provides UI toggles for features that can also be configured via environment variables:
+
+| Setting Location | Toggle | Description |
+| ------------------- | ------------------ | ------------------------------ |
+| Settings → Advanced | Debug Mode | Enable debug request logs (UI) |
+| Settings → General | Sidebar Visibility | Show/hide sidebar sections |
+
+These settings are stored in the database and persist across restarts, overriding env var defaults when set.
+
+### Running Locally
```bash
# Development mode (hot reload)
@@ -55,16 +70,16 @@ npm run start
PORT=20128 NEXT_PUBLIC_BASE_URL=http://localhost:20128 npm run dev
```
-Výchozí adresy URL:
+Default URLs:
-- **Dashboard** : `http://localhost:3000/dashboard`
-- **API** : `http://localhost:3000/v1`
+- **Dashboard**: `http://localhost:20128/dashboard`
+- **API**: `http://localhost:20128/v1`
---
-## Pracovní postup Gitu
+## Git Workflow
-> ⚠️ **NIKDY se necommitujte přímo do `main` .** Vždy používejte větve feature.
+> ⚠️ **NEVER commit directly to `main`.** Always use feature branches.
```bash
git checkout -b feat/your-feature-name
@@ -74,20 +89,20 @@ git push -u origin feat/your-feature-name
# Open a Pull Request on GitHub
```
-### Pojmenování poboček
+### Branch Naming
-Předpona | Účel
---- | ---
-`feat/` | Nové funkce
-`fix/` | Opravy chyb
-`refactor/` | Restrukturalizace kódu
-`docs/` | Změny dokumentace
-`test/` | Doplnění/opravy testů
-`chore/` | Nástroje, CI, závislosti
+| Prefix | Purpose |
+| ----------- | ------------------------- |
+| `feat/` | New features |
+| `fix/` | Bug fixes |
+| `refactor/` | Code restructuring |
+| `docs/` | Documentation changes |
+| `test/` | Test additions/fixes |
+| `chore/` | Tooling, CI, dependencies |
-### Zprávy o potvrzení
+### Commit Messages
-Postupujte podle [konvenčních commitů](https://www.conventionalcommits.org/) :
+Follow [Conventional Commits](https://www.conventionalcommits.org/):
```
feat: add circuit breaker for provider calls
@@ -97,177 +112,188 @@ test: add observability unit tests
refactor(db): consolidate rate limit tables
```
-Rozsahy: `db` , `sse` , `oauth` , `dashboard` , `api` , `cli` , `docker` , `ci` .
+Scopes: `db`, `sse`, `oauth`, `dashboard`, `api`, `cli`, `docker`, `ci`, `mcp`, `a2a`, `memory`, `skills`.
---
-## Spouštění testů
+## Running Tests
```bash
-# All unit tests
-npm test
-npm run test:unit
+# All tests (unit + vitest + ecosystem + e2e)
+npm run test:all
-# Specific test suites
-npm run test:security # Security tests
-npm run test:fixes # Fix verification tests
+# Single test file (Node.js native test runner — most tests use this)
+node --import tsx/esm --test tests/unit/your-file.test.mjs
-# With coverage
-npm run test:coverage
+# Vitest (MCP server, autoCombo, cache)
+npm run test:vitest
# E2E tests (requires Playwright)
npm run test:e2e
+# Protocol clients E2E (MCP transports, A2A)
+npm run test:protocols:e2e
+
+# Ecosystem compatibility tests
+npm run test:ecosystem
+
+# Coverage (55% min statements/lines/functions; 60% branches)
+npm run test:coverage
+npm run coverage:report
+
# Lint + format check
npm run lint
npm run check
```
-Aktuální stav testování: **368+ jednotkových testů** zahrnujících:
+Coverage notes:
-- Poskytovatelé překladů a konverze formátů
-- Omezení rychlosti, jistič a odolnost
-- Sémantická mezipaměť, idempotence, sledování průběhu
-- Databázové operace a schéma
-- Toky a ověřování OAuth
-- Ověření koncového bodu API
+- `npm run test:coverage` measures source coverage for the main unit test suite, excludes `tests/**`, and includes `open-sse/**`
+- `npm run coverage:report` prints the detailed file-by-file report from the latest coverage run
+- `npm run test:coverage:legacy` preserves the older metric for historical comparison
+- See `docs/COVERAGE_PLAN.md` for the phased coverage improvement roadmap
+
+Current test status: **122 unit test files** covering:
+
+- Provider translators and format conversion
+- Rate limiting, circuit breaker, and resilience
+- Semantic cache, idempotency, progress tracking
+- Database operations and schema (21 DB modules)
+- OAuth flows and authentication
+- API endpoint validation (Zod v4)
+- MCP server tools and scope enforcement
+- Memory and Skills systems
---
-## Styl kódu
+## Code Style
-- **ESLint** — Spustí `npm run lint` před commitem
-- **Hezčí** – Automaticky naformátováno pomocí `lint-staged` při commitu
-- **TypeScript** — Veškerý kód `src/` používá `.ts` / `.tsx` ; dokument s TSDoc ( `@param` , `@returns` , `@throws` )
-- **No `eval()`** — ESLint vynucuje `no-eval` , `no-implied-eval` , `no-new-func`
-- **Ověření Zod** — Použití schémat Zod pro ověřování vstupu API
+- **ESLint** — Run `npm run lint` before committing
+- **Prettier** — Auto-formatted via `lint-staged` on commit (2 spaces, semicolons, double quotes, 100 char width, es5 trailing commas)
+- **TypeScript** — All `src/` code uses `.ts`/`.tsx`; `open-sse/` uses `.ts`/`.js`; document with TSDoc (`@param`, `@returns`, `@throws`)
+- **No `eval()`** — ESLint enforces `no-eval`, `no-implied-eval`, `no-new-func`
+- **Zod validation** — Use Zod v4 schemas for all API input validation
+- **Naming**: Files = camelCase/kebab-case, components = PascalCase, constants = UPPER_SNAKE
---
-## Struktura projektu
+## Project Structure
```
src/ # TypeScript (.ts / .tsx)
-├── app/ # Next.js App Router
-│ ├── (dashboard)/ # Dashboard pages (.tsx)
-│ ├── api/ # API routes (.ts)
+├── app/ # Next.js 16 App Router
+│ ├── (dashboard)/ # Dashboard pages (23 sections)
+│ ├── api/ # API routes (51 directories)
│ └── login/ # Auth pages (.tsx)
-├── domain/ # Domain types and response helpers (.ts)
+├── domain/ # Policy engine (policyEngine, comboResolver, costRules, etc.)
├── lib/ # Core business logic (.ts)
-│ ├── db/ # SQLite database layer
-│ ├── oauth/ # OAuth services per provider
-│ ├── cacheLayer.ts # LRU cache
-│ ├── semanticCache.ts # Semantic response cache
-│ ├── idempotencyLayer.ts # Request deduplication
-│ └── localDb.ts # Settings facade (LowDB for config, SQLite for domain data)
+│ ├── a2a/ # Agent-to-Agent v0.3 protocol server
+│ ├── acp/ # Agent Communication Protocol registry
+│ ├── compliance/ # Compliance policy engine
+│ ├── db/ # SQLite database layer (21 modules + 16 migrations)
+│ ├── memory/ # Persistent conversational memory
+│ ├── oauth/ # OAuth providers, services, and utilities
+│ ├── skills/ # Extensible skill framework
+│ ├── usage/ # Usage tracking and cost calculation
+│ └── localDb.ts # Re-export layer only — never add logic here
+├── middleware/ # Request middleware (promptInjectionGuard)
+├── mitm/ # MITM proxy (cert, DNS, target routing)
├── shared/
│ ├── components/ # React components (.tsx)
-│ ├── middleware/ # Correlation IDs, etc.
-│ ├── utils/ # Circuit breaker, sanitizer, etc.
-│ └── validation/ # Zod schemas
-└── sse/ # SSE chat handlers (.ts)
+│ ├── constants/ # Provider definitions (60+), MCP scopes, routing strategies
+│ ├── utils/ # Circuit breaker, sanitizer, auth helpers
+│ └── validation/ # Zod v4 schemas
+└── sse/ # SSE proxy pipeline
-open-sse/ # @omniroute/open-sse workspace (JavaScript)
-├── handlers/ # chatCore.js — main request handler
-├── services/ # Rate limit, fallback
-├── translators/ # Format converters (OpenAI ↔ Claude ↔ Gemini)
-└── utils/ # Progress tracker, stream helpers
+open-sse/ # @omniroute/open-sse workspace
+├── executors/ # 14 provider-specific request executors
+├── handlers/ # 11 request handlers (chat, responses, embeddings, images, etc.)
+├── mcp-server/ # MCP server (25 tools, 3 transports, 10 scopes)
+├── services/ # 36+ services (combo, autoCombo, rateLimitManager, etc.)
+├── translator/ # Format translators (OpenAI ↔ Claude ↔ Gemini ↔ Responses ↔ Ollama)
+├── transformer/ # Responses API transformer
+└── utils/ # 22 utility modules (stream, TLS, proxy, logging)
+
+electron/ # Electron desktop app (cross-platform)
tests/
-├── unit/ # Node.js test runner (.test.mjs)
-└── e2e/ # Playwright tests
+├── unit/ # Node.js test runner (122 test files)
+├── integration/ # Integration tests
+├── e2e/ # Playwright tests
+├── security/ # Security tests
+├── translator/ # Translator-specific tests
+└── load/ # Load tests
docs/ # Documentation
-├── USER_GUIDE.md # Provider setup, CLI integration
-├── API_REFERENCE.md # All endpoints
-├── TROUBLESHOOTING.md # Common issues
├── ARCHITECTURE.md # System architecture
+├── API_REFERENCE.md # All endpoints
+├── USER_GUIDE.md # Provider setup, CLI integration
+├── TROUBLESHOOTING.md # Common issues
+├── MCP-SERVER.md # MCP server (25 tools)
+├── A2A-SERVER.md # A2A agent protocol
+├── AUTO-COMBO.md # Auto-combo engine
+├── CLI-TOOLS.md # CLI tools integration
+├── COVERAGE_PLAN.md # Test coverage improvement plan
+├── openapi.yaml # OpenAPI specification
└── adr/ # Architecture Decision Records
```
---
-## Přidání nového poskytovatele
+## Adding a New Provider
-### Krok 1: Služba OAuth (pokud používáte OAuth)
+### Step 1: Register Provider Constants
-Vytvořte `src/lib/oauth/services/your-provider.ts` rozšiřující `OAuthService` :
+Add to `src/shared/constants/providers.ts` — Zod-validated at module load.
-```typescript
-import { OAuthService } from "../OAuthService";
+### Step 2: Add Executor (if custom logic needed)
-export class YourProviderService extends OAuthService {
- constructor() {
- super({
- name: "your-provider",
- authUrl: "https://provider.com/oauth/authorize",
- tokenUrl: "https://provider.com/oauth/token",
- clientId: "...",
- scopes: ["..."],
- });
- }
-}
-```
+Create executor in `open-sse/executors/your-provider.ts` extending the base executor.
-### Krok 2: Registrace poskytovatele
+### Step 3: Add Translator (if non-OpenAI format)
-Přidat do `src/lib/oauth/providers.ts` :
+Create request/response translators in `open-sse/translator/`.
-```typescript
-import { YourProviderService } from "./services/your-provider";
-// Add to the providers map
-```
+### Step 4: Add OAuth Config (if OAuth-based)
-### Krok 3: Přidání konstant
+Add OAuth credentials in `src/lib/oauth/constants/oauth.ts` and service in `src/lib/oauth/services/`.
-Přidejte konstanty poskytovatele do `src/lib/providerConstants.ts` :
+### Step 5: Register Models
-- Předpona poskytovatele (např. `yp/` )
-- Výchozí modely
-- Informace o cenách
+Add model definitions in `open-sse/config/providerRegistry.ts`.
-### Krok 4: Přidání překladače (pokud se nejedná o formát OpenAI)
+### Step 6: Add Tests
-Pokud poskytovatel používá vlastní formát API, vytvořte překladač v `open-sse/translators/` .
+Write unit tests in `tests/unit/` covering at minimum:
-### Krok 5: Přidání časového limitu
-
-Přidejte konfiguraci časového limitu požadavku do `src/shared/utils/requestTimeout.ts` .
-
-### Krok 6: Přidání testů
-
-Pište jednotkové testy v `tests/unit/` které pokrývají minimálně:
-
-- Registrace poskytovatele
-- Překlad žádostí/odpovědí
-- Ošetření chyb
+- Provider registration
+- Request/response translation
+- Error handling
---
-## Kontrolní seznam žádostí o natažení
+## Pull Request Checklist
-- [ ] Testy prošly ( `npm test` )
-- [ ] Průchody pro linting ( `npm run lint` )
-- [ ] Sestavení proběhlo úspěšně ( `npm run build` )
-- [ ] Pro nové veřejné funkce a rozhraní přidány typy TypeScript
-- [ ] Žádné pevně zakódované tajné kódy ani záložní hodnoty
-- [ ] Aktualizován CHANGELOG (pokud se změna týká uživatele)
-- [ ] Aktualizovaná dokumentace (pokud je to relevantní)
+- [ ] Tests pass (`npm test`)
+- [ ] Linting passes (`npm run lint`)
+- [ ] Build succeeds (`npm run build`)
+- [ ] TypeScript types added for new public functions and interfaces
+- [ ] No hardcoded secrets or fallback values
+- [ ] All inputs validated with Zod schemas
+- [ ] CHANGELOG updated (if user-facing change)
+- [ ] Documentation updated (if applicable)
---
-## Uvolnění
+## Releasing
-Když je vytvořena nová verze GitHubu (např. `v0.4.0` ), balíček je **automaticky publikován do npm** prostřednictvím akcí GitHubu:
-
-```bash
-gh release create v0.4.0 --title "v0.4.0" --generate-notes
-```
+Releases are managed via the `/generate-release` workflow. When a new GitHub Release is created, the package is **automatically published to npm** via GitHub Actions.
---
-## Získání pomoci
+## Getting Help
-- **Architektura** : Viz [`docs/ARCHITECTURE.md`](docs/ARCHITECTURE.md)
-- **Problémy** : [github.com/diegosouzapw/OmniRoute/issues](https://github.com/diegosouzapw/OmniRoute/issues)
-- **ADR** : Viz `docs/adr/`
+- **Architecture**: See [`docs/ARCHITECTURE.md`](docs/ARCHITECTURE.md)
+- **API Reference**: See [`docs/API_REFERENCE.md`](docs/API_REFERENCE.md)
+- **Issues**: [github.com/diegosouzapw/OmniRoute/issues](https://github.com/diegosouzapw/OmniRoute/issues)
+- **ADRs**: See `docs/adr/` for architectural decision records
diff --git a/docs/i18n/cs/FEATURES.md b/docs/i18n/cs/FEATURES.md
deleted file mode 100644
index 9bc266b440..0000000000
--- a/docs/i18n/cs/FEATURES.md
+++ /dev/null
@@ -1,143 +0,0 @@
-# OmniRoute — Galerie funkcí řídicího panelu
-
-🌐 **Jazyky:** 🇺🇸 [angličtina](FEATURES.md) | 🇧🇷 [Português (Brazílie)](i18n/pt-BR/FEATURES.md) | 🇪🇸 [Español](i18n/es/FEATURES.md) | 🇫🇷 [Français](i18n/fr/FEATURES.md) | 🇮🇹 [Italiano](i18n/it/FEATURES.md) | 🇷🇺 [Русский](i18n/ru/FEATURES.md) | 🇨🇳[中文 (简体)](i18n/zh-CN/FEATURES.md) | 🇩🇪 [Deutsch](i18n/de/FEATURES.md) | 🇮🇳 [हिन्दी](i18n/in/FEATURES.md) | 🇹🇭 [ไทย](i18n/th/FEATURES.md) | 🇺🇦 [Українська](i18n/uk-UA/FEATURES.md) | 🇸🇦 [العربية](i18n/ar/FEATURES.md) | 🇯🇵[日本語](i18n/ja/FEATURES.md)| 🇻🇳 [Tiếng Việt](i18n/vi/FEATURES.md) | 🇧🇬 [Български](i18n/bg/FEATURES.md) | 🇩🇰 [Dánsko](i18n/da/FEATURES.md) | 🇫🇮 [Suomi](i18n/fi/FEATURES.md) | 🇮🇱 [עברית](i18n/he/FEATURES.md) | 🇭🇺 [maďarština](i18n/hu/FEATURES.md) | 🇮🇩 [Bahasa Indonésie](i18n/id/FEATURES.md) | 🇰🇷 [한국어](i18n/ko/FEATURES.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/FEATURES.md) | 🇳🇱 [Nizozemsko](i18n/nl/FEATURES.md) | 🇳🇴 [Norsk](i18n/no/FEATURES.md) | 🇵🇹 [Português (Portugalsko)](i18n/pt/FEATURES.md) | 🇷🇴 [Română](i18n/ro/FEATURES.md) | 🇵🇱 [Polski](i18n/pl/FEATURES.md) | 🇸🇰 [Slovenčina](i18n/sk/FEATURES.md) | 🇸🇪 [Svenska](i18n/sv/FEATURES.md) | 🇵🇭 [Filipínec](i18n/phi/FEATURES.md) | 🇨🇿 [Čeština](i18n/cs/FEATURES.md)
-
-Vizuální průvodce všemi částmi ovládacího panelu OmniRoute.
-
----
-
-## 🔌 Poskytovatelé
-
-Spravujte připojení poskytovatelů AI: poskytovatelé OAuth (Claude Code, Codex, Gemini CLI), poskytovatelé klíčů API (Groq, DeepSeek, OpenRouter) a bezplatní poskytovatelé (Qoder, Qwen, Kiro). Účty Kiro zahrnují sledování zůstatku kreditů – zbývající kredity, celkový limit a datum obnovení jsou viditelné v Dashboard → Usage.
-
-
-
----
-
-## 🎨 Kombinace
-
-Vytvářejte kombinace směrování modelů pomocí 6 strategií: prioritní, vážená, kruhová, náhodná, nejméně používaná a nákladově optimalizovaná. Každá kombinace řetězí více modelů s automatickým přepínáním mezi nimi a zahrnuje rychlé šablony a kontroly připravenosti.
-
-
-
----
-
-## 📊 Analytika
-
-Komplexní analýzy využití se spotřebou tokenů, odhady nákladů, mapami aktivit, týdenními distribučními grafy a rozpisy podle jednotlivých poskytovatelů.
-
-
-
----
-
-## 🏥 Stav systému
-
-Monitorování v reálném čase: dostupnost, paměť, verze, percentily latence (p50/p95/p99), statistiky mezipaměti a stavy jističů poskytovatelů.
-
-
-
----
-
-## 🔧 Překladatelské hřiště
-
-Čtyři režimy pro ladění překladů API: **Playground** (převodník formátů), **Chat Tester** (živé požadavky), **Test Bench** (dávkové testy) a **Live Monitor** (stream v reálném čase).
-
-
-
----
-
-## 🎮 Modelové hřiště _(v2.0.9+)_
-
-Otestujte libovolný model přímo z řídicího panelu. Vyberte poskytovatele, model a koncový bod, pište výzvy pomocí editoru Monaco, streamujte odpovědi v reálném čase, přerušte stream a zobrazte metriky časování.
-
----
-
-## 🎨 Témata _(v2.0.5+)_
-
-Přizpůsobitelná barevná témata pro celý dashboard. Vyberte si ze 7 přednastavených barev (korálová, modrá, červená, zelená, fialová, oranžová, azurová) nebo si vytvořte vlastní téma výběrem libovolné hexadecimální barvy. Podporuje světlý, tmavý a systémový režim.
-
----
-
-## ⚙️ Nastavení
-
-Komplexní panel nastavení s kartami:
-
-- **Obecné** – Systémové úložiště, správa záloh (export/import databáze)
-- **Vzhled** – Výběr motivu (tmavý/světlý/systémový), přednastavené barevné motivy a vlastní barvy, viditelnost protokolu stavu
-- **Zabezpečení** — ochrana koncových bodů API, blokování vlastních poskytovatelů, filtrování IP adres, informace o relaci
-- **Směrování** — Aliasy modelů, degradace úloh na pozadí
-- **Odolnost** — Perzistence omezení rychlosti, ladění jističe
-- **Pokročilé** – Přepsání konfigurace
-
-
-
----
-
-## 🔧 Nástroje CLI
-
-Konfigurace nástrojů pro kódování s umělou inteligencí jedním kliknutím: Claude Code, Codex CLI, Gemini CLI, OpenClaw, Kilo Code, Antigravity, Cline, Continue, Cursor a Factory Droid. Nabízí automatické použití/resetování konfigurace, profily připojení a mapování modelů.
-
-
-
----
-
-## 🤖 Agenti CLI _(v2.0.11+)_
-
-Ovládací panel pro vyhledávání a správu agentů CLI. Zobrazuje mřížku 14 vestavěných agentů (Codex, Claude, Goose, Gemini CLI, OpenClaw, Aider, OpenCode, Cline, Qwen Code, ForgeCode, Amazon Q, Open Interpreter, Cursor CLI, Warp) s:
-
-- **Stav instalace** — Nainstalováno / Nenalezeno s detekcí verze
-- **Odznaky protokolů** – stdio, HTTP atd.
-- **Vlastní agenti** — Registrace libovolného nástroje CLI pomocí formuláře (název, binární soubor, verze příkazu, argumenty spawn)
-- **Porovnávání otisků prstů v příkazovém řádku** – Přepínání pro jednotlivé poskytovatele pro porovnávání nativních podpisů požadavků v příkazovém řádku, čímž se snižuje riziko zablokování a zároveň se zachovává IP adresa proxy.
-
----
-
-## 🖼️ Média _(v2.0.3+)_
-
-Generujte obrázky, videa a hudbu z řídicího panelu. Podporuje OpenAI, xAI, Together, Hyperbolic, SD WebUI, ComfyUI, AnimateDiff, Stable Audio Open a MusicGen.
-
----
-
-## 📝 Vyžádat si protokoly
-
-Protokolování požadavků v reálném čase s filtrováním podle poskytovatele, modelu, účtu a klíče API. Zobrazuje stavové kódy, využití tokenů, latenci a podrobnosti o odpovědi.
-
-
-
----
-
-## 🌐 Koncový bod API
-
-Váš jednotný koncový bod API s rozpisem funkcí: Dokončování chatu, API odpovědí, vkládání, generování obrázků, změna pořadí, přepis zvuku, převod textu na řeč, moderování a registrované klíče API. Podpora cloudového proxy pro vzdálený přístup.
-
-
-
----
-
-## 🔑 Správa klíčů API
-
-Vytvářejte, upravujte rozsah a rušte klíče API. Každý klíč lze omezit na konkrétní modely/poskytovatele s plným přístupem nebo oprávněním pouze pro čtení. Vizuální správa klíčů se sledováním využití.
-
----
-
-## 📋 Záznam auditu
-
-Sledování administrativních akcí s filtrováním podle typu akce, aktéra, cíle, IP adresy a časového razítka. Úplná historie bezpečnostních událostí.
-
----
-
-## 🖥️ Desktopová aplikace
-
-Desktopová aplikace Native Electron pro Windows, macOS a Linux. Spouštějte OmniRoute jako samostatnou aplikaci s integrací do systémové lišty, podporou offline, automatickými aktualizacemi a instalací jedním kliknutím.
-
-Klíčové vlastnosti:
-
-- Dotazování připravenosti serveru (žádná prázdná obrazovka při studeném startu)
-- Systémový panel se správou portů
-- Zásady zabezpečení obsahu
-- Jednoinstanční zámek
-- Automatická aktualizace při restartu
-- Podmíněné uživatelské rozhraní pro platformu (semafory pro macOS, výchozí záhlaví okna pro Windows/Linux)
-- Zpevněné balení buildů Electron — symbolicky odkazované `node_modules` v samostatném balíčku jsou detekovány a odmítnuty před balením, čímž se zabrání závislosti na buildovacím stroji za běhu (v2.5.5+)
-
-📖 Úplnou dokumentaci naleznete v [`electron/README.md`](../electron/README.md) .
diff --git a/docs/i18n/cs/MCP-SERVER.md b/docs/i18n/cs/MCP-SERVER.md
deleted file mode 100644
index ee2df76e53..0000000000
--- a/docs/i18n/cs/MCP-SERVER.md
+++ /dev/null
@@ -1,83 +0,0 @@
-# Dokumentace k serveru OmniRoute MCP
-
-> Server protokolu kontextu modelu s 16 inteligentními nástroji
-
-## Instalace
-
-OmniRoute MCP je integrovaný. Spusťte ho pomocí:
-
-```bash
-omniroute --mcp
-```
-
-Nebo prostřednictvím open-sse transportu:
-
-```bash
-# HTTP streamable transport (port 20130)
-omniroute --dev # MCP auto-starts on /mcp endpoint
-```
-
-## Konfigurace IDE
-
-Viz [konfigurace IDE](integrations/ide-configs.md) pro nastavení Antigravity, Cursoru, Copilota a Claude Desktopu.
-
----
-
-## Základní nástroje (8)
-
-Nástroj | Popis
-:-- | :--
-`omniroute_get_health` | Stav brány, jističe, provozuschopnost
-`omniroute_list_combos` | Všechny nakonfigurované kombinace s modely
-`omniroute_get_combo_metrics` | Metriky výkonu pro konkrétní kombinaci
-`omniroute_switch_combo` | Přepnout aktivní kombinaci podle ID/jména
-`omniroute_check_quota` | Stav kvóty pro jednotlivé poskytovatele nebo všechny
-`omniroute_route_request` | Odeslání dokončení chatu přes OmniRoute
-`omniroute_cost_report` | Analýza nákladů za určité časové období
-`omniroute_list_models_catalog` | Kompletní katalog modelů s funkcemi
-
-## Pokročilé nástroje (8)
-
-Nástroj | Popis
-:-- | :--
-`omniroute_simulate_route` | Simulace trasování na dryru s fallback stromem
-`omniroute_set_budget_guard` | Rozpočet relace s akcemi degradace/blokování/upozornění
-`omniroute_set_resilience_profile` | Použít konzervativní/vyvážený/agresivní předvolbu
-`omniroute_test_combo` | Živé testování všech modelů v kombinaci
-`omniroute_get_provider_metrics` | Podrobné metriky pro jednoho poskytovatele
-`omniroute_best_combo_for_task` | Doporučení pro splnění úkolu a jeho vhodnosti s alternativami
-`omniroute_explain_route` | Vysvětlete minulé rozhodnutí o trase
-`omniroute_get_session_snapshot` | Stav celé relace: náklady, tokeny, chyby
-
-## Ověřování
-
-Nástroje MCP jsou ověřovány pomocí rozsahů klíčů API. Každý nástroj vyžaduje specifické rozsahy:
-
-Rozsah | Nástroje
-:-- | :--
-`read:health` | get_health, get_provider_metrics
-`read:combos` | seznam_kombinací, získání_kombinovaných_metrik
-`write:combos` | přepínač_kombinace
-`read:quota` | check_quote
-`write:route` | požadavek_trasy, simulace_trasy, testovací_kombinace
-`read:usage` | zpráva_o_nákladech, získání_snímku_relace, vysvětlení_trasy
-`write:config` | set_budget_guard, set_resilience_profile
-`read:models` | seznam_modelů_katalog, nejlepší_kombinace_pro_úkol
-
-## Protokolování auditu
-
-Každé volání nástroje je zaznamenáno do `mcp_tool_audit` s touto funkcí:
-
-- Název nástroje, argumenty, výsledek
-- Trvání (ms), úspěch/neúspěch
-- Haš klíče API, časové razítko
-
-## Soubory
-
-Soubor | Účel
-:-- | :--
-`open-sse/mcp-server/server.ts` | Vytvoření MCP serveru + 16 registrací nástrojů
-`open-sse/mcp-server/transport.ts` | Stdio + HTTP transport
-`open-sse/mcp-server/auth.ts` | Ověření klíče API + rozsahu
-`open-sse/mcp-server/audit.ts` | Protokolování auditu volání nástrojů
-`open-sse/mcp-server/tools/advancedTools.ts` | 8 pokročilých manipulátorů s nástroji
diff --git a/docs/i18n/cs/README.md b/docs/i18n/cs/README.md
index 67ad8c173f..5f1e13788d 100644
--- a/docs/i18n/cs/README.md
+++ b/docs/i18n/cs/README.md
@@ -1,145 +1,239 @@
-# 🚀 OmniRoute — Bezplatná brána umělé inteligence
+# 🚀 OmniRoute — The Free AI Gateway (Čeština)
-### Nikdy nepřestávejte s kódováním. Chytré směrování k **BEZPLATNÝM a levným modelům AI** s automatickým přepínáním mezi záložními systémy.
+🌐 **Languages:** 🇺🇸 [English](../../../README.md) · 🇪🇸 [es](../es/README.md) · 🇫🇷 [fr](../fr/README.md) · 🇩🇪 [de](../de/README.md) · 🇮🇹 [it](../it/README.md) · 🇷🇺 [ru](../ru/README.md) · 🇨🇳 [zh-CN](../zh-CN/README.md) · 🇯🇵 [ja](../ja/README.md) · 🇰🇷 [ko](../ko/README.md) · 🇸🇦 [ar](../ar/README.md) · 🇮🇳 [in](../in/README.md) · 🇹🇭 [th](../th/README.md) · 🇻🇳 [vi](../vi/README.md) · 🇮🇩 [id](../id/README.md) · 🇲🇾 [ms](../ms/README.md) · 🇳🇱 [nl](../nl/README.md) · 🇵🇱 [pl](../pl/README.md) · 🇸🇪 [sv](../sv/README.md) · 🇳🇴 [no](../no/README.md) · 🇩🇰 [da](../da/README.md) · 🇫🇮 [fi](../fi/README.md) · 🇵🇹 [pt](../pt/README.md) · 🇷🇴 [ro](../ro/README.md) · 🇭🇺 [hu](../hu/README.md) · 🇧🇬 [bg](../bg/README.md) · 🇸🇰 [sk](../sk/README.md) · 🇺🇦 [uk-UA](../uk-UA/README.md) · 🇮🇱 [he](../he/README.md) · 🇵🇭 [phi](../phi/README.md) · 🇧🇷 [pt-BR](../pt-BR/README.md) · 🇨🇿 [cs](../cs/README.md)
-_Váš univerzální API proxy – jeden endpoint, více než 44 poskytovatelů, nulové výpadky. Nyní s orchestrací agentů **MCP a A2A** ._
+---
-**Dokončení chatu • Vkládání • Generování obrázků • Video • Hudba • Audio • Změna pořadí • **Vyhledávání na webu** • MCP server • A2A protokol • 100% TypeScript**
+### Never stop coding. Smart routing to **FREE & low-cost AI models** with automatic fallback.
+
+_Your universal API proxy — one endpoint, 60+ providers, zero downtime. Now with **MCP Server (25 tools)**, **A2A Protocol**, **Memory/Skills Systems** & **Electron Desktop App**._
+
+**Chat Completions • Embeddings • Image Generation • Video • Music • Audio • Reranking • **Web Search** • MCP Server • A2A Protocol • 100% TypeScript**
---
+
+[](https://www.npmjs.com/package/omniroute)
+[](https://www.npmjs.com/package/omniroute)
+[](https://hub.docker.com/r/diegosouzapw/omniroute)
+[](https://hub.docker.com/r/diegosouzapw/omniroute)
+[](https://github.com/diegosouzapw/OmniRoute/blob/main/LICENSE)
+[](https://omniroute.online)
+[](https://chat.whatsapp.com/JI7cDQ1GyaiDHhVBpLxf8b?mode=gi_t)
+
+[🌐 Website](https://omniroute.online) • [🚀 Quick Start](#-quick-start) • [💡 Features](#-key-features) • [📖 Docs](#-documentation) • [💰 Pricing](#-pricing-at-a-glance) • [💬 WhatsApp](https://chat.whatsapp.com/JI7cDQ1GyaiDHhVBpLxf8b?mode=gi_t)
+
-




-🌐 Webové stránky • 🚀 Rychlý start • 💡 Funkce • 📖 Dokumentace • 💰 Ceník • 💬 WhatsApp
-
-🌐 **Dostupné v:** 🇺🇸 [Angličtina](README.md) | 🇧🇷 [Português (Brazílie)](docs/i18n/pt-BR/README.md) | 🇪🇸 [Español](docs/i18n/es/README.md) | 🇫🇷 [Français](docs/i18n/fr/README.md) | 🇮🇹 [Italiano](docs/i18n/it/README.md) | 🇷🇺 [Русский](docs/i18n/ru/README.md) | 🇨🇳[中文 (简体)](docs/i18n/zh-CN/README.md) | 🇩🇪 [Deutsch](docs/i18n/de/README.md) | 🇮🇳 [हिन्दी](docs/i18n/in/README.md) | 🇹🇭 [ไทย](docs/i18n/th/README.md) | 🇺🇦 [Українська](docs/i18n/uk-UA/README.md) | 🇸🇦 [العربية](docs/i18n/ar/README.md) | 🇯🇵[日本語](docs/i18n/ja/README.md)| 🇻🇳 [Tiếng Việt](docs/i18n/vi/README.md) | 🇧🇬 [Български](docs/i18n/bg/README.md) | 🇩🇰 [Dánsko](docs/i18n/da/README.md) | 🇫🇮 [Suomi](docs/i18n/fi/README.md) | 🇮🇱 [עברית](docs/i18n/he/README.md) | 🇭🇺 [maďarština](docs/i18n/hu/README.md) | 🇮🇩 [Bahasa Indonésie](docs/i18n/id/README.md) | 🇰🇷 [한국어](docs/i18n/ko/README.md) | 🇲🇾 [Bahasa Melayu](docs/i18n/ms/README.md) | 🇳🇱 [Nizozemsko](docs/i18n/nl/README.md) | 🇳🇴 [Norsk](docs/i18n/no/README.md) | 🇵🇹 [Português (Portugalsko)](docs/i18n/pt/README.md) | 🇷🇴 [Română](docs/i18n/ro/README.md) | 🇵🇱 [Polski](docs/i18n/pl/README.md) | 🇸🇰 [Slovenčina](docs/i18n/sk/README.md) | 🇸🇪 [Svenska](docs/i18n/sv/README.md) | 🇵🇭 [Filipínec](docs/i18n/phi/README.md) | 🇨🇿 [Čeština](docs/i18n/cs/README.md)
+🌐 **Available in:** 🇺🇸 [English](README.md) | 🇧🇷 [Português (Brasil)](docs/i18n/pt-BR/README.md) | 🇪🇸 [Español](docs/i18n/es/README.md) | 🇫🇷 [Français](docs/i18n/fr/README.md) | 🇮🇹 [Italiano](docs/i18n/it/README.md) | 🇷🇺 [Русский](docs/i18n/ru/README.md) | 🇨🇳 [中文 (简体)](docs/i18n/zh-CN/README.md) | 🇩🇪 [Deutsch](docs/i18n/de/README.md) | 🇮🇳 [हिन्दी](docs/i18n/in/README.md) | 🇹🇭 [ไทย](docs/i18n/th/README.md) | 🇺🇦 [Українська](docs/i18n/uk-UA/README.md) | 🇸🇦 [العربية](docs/i18n/ar/README.md) | 🇯🇵 [日本語](docs/i18n/ja/README.md) | 🇻🇳 [Tiếng Việt](docs/i18n/vi/README.md) | 🇧🇬 [Български](docs/i18n/bg/README.md) | 🇩🇰 [Dansk](docs/i18n/da/README.md) | 🇫🇮 [Suomi](docs/i18n/fi/README.md) | 🇮🇱 [עברית](docs/i18n/he/README.md) | 🇭🇺 [Magyar](docs/i18n/hu/README.md) | 🇮🇩 [Bahasa Indonesia](docs/i18n/id/README.md) | 🇰🇷 [한국어](docs/i18n/ko/README.md) | 🇲🇾 [Bahasa Melayu](docs/i18n/ms/README.md) | 🇳🇱 [Nederlands](docs/i18n/nl/README.md) | 🇳🇴 [Norsk](docs/i18n/no/README.md) | 🇵🇹 [Português (Portugal)](docs/i18n/pt/README.md) | 🇷🇴 [Română](docs/i18n/ro/README.md) | 🇵🇱 [Polski](docs/i18n/pl/README.md) | 🇸🇰 [Slovenčina](docs/i18n/sk/README.md) | 🇸🇪 [Svenska](docs/i18n/sv/README.md) | 🇵🇭 [Filipino](docs/i18n/phi/README.md) | 🇨🇿 [Čeština](docs/i18n/cs/README.md)
---
-### 🆕 What's New in v3.0.0
+## Breaking Change: Unified Logging Upgrade
-| Area | Change |
-| ------------------------------- | --------------------------------------------------------------------------------- |
-| 🔒 **CodeQL Security** | Fixed 10+ CodeQL alerts: polynomial-redos, insecure-randomness, shell-injection |
-| ✅ **Route Validation** | All 176 API routes validated with Zod schemas + `validateBody()` |
-| 🐛 **omniModel Tag Leak** | Internal `` tags no longer leak to clients in SSE streams (#585) |
-| 🔑 **Registered Keys API** | Auto-provision API keys via `POST /api/v1/registered-keys` with quota enforcement |
-| 👁️ **Scoped API Key Reveal** 🆕 | Opt-in recovery of API keys via `ALLOW_API_KEY_REVEAL` |
-| 🎨 **Provider Icons** | 130+ provider logos via `@lobehub/icons` (SVG) with PNG fallback |
-| 🔄 **Model Auto-Sync** | 24h scheduler refreshes model lists for 16 providers |
-| 🌐 **OpenCode Zen/Go** | Two new providers: free tier + subscription tier |
-| 🔧 **926 Tests** | Full test suite passes with 0 failures |
-
-### 🆕 What's New in v3.0.0
-
-| Area | Change |
-| -------------------------- | --------------------------------------------------------------------------------- |
-| 🔒 **CodeQL Security** | Fixed 10+ CodeQL alerts: polynomial-redos, insecure-randomness, shell-injection |
-| ✅ **Route Validation** | All 176 API routes validated with Zod schemas + `validateBody()` |
-| 🐛 **omniModel Tag Leak** | Internal `` tags no longer leak to clients in SSE streams (#585) |
-| 🔑 **Registered Keys API** | Auto-provision API keys via `POST /api/v1/registered-keys` with quota enforcement |
-| 🎨 **Provider Icons** | 130+ provider logos via `@lobehub/icons` (SVG) with PNG fallback |
-| 🔄 **Model Auto-Sync** | 24h scheduler refreshes model lists for 16 providers |
-| 🌐 **OpenCode Zen/Go** | Two new providers: free tier + subscription tier |
-| 🔧 **926 Tests** | Full test suite passes with 0 failures |
+> [!WARNING]
+> **This release changes both the on-disk request log layout and the logging environment variables.**
+>
+> If you are upgrading an existing instance:
+>
+> - Request logs now live in `DATA_DIR/call_logs/YYYY-MM-DD/` as **one JSON artifact per request**.
+> - The old `DATA_DIR/logs/` session folders and `DATA_DIR/log.txt` summary file are removed.
+> - On the first startup after upgrading, OmniRoute creates a safety backup at `DATA_DIR/log_archives/*.zip` before removing the deprecated request log layout.
+> - Legacy logging env vars such as `LOG_TO_FILE`, `LOG_FILE_PATH`, `LOG_MAX_FILE_SIZE`, `LOG_RETENTION_DAYS`, `LOG_LEVEL`, `LOG_FORMAT`, `ENABLE_REQUEST_LOGS`, `CALL_LOGS_MAX`, `CALL_LOG_PAYLOAD_MODE`, and `PROXY_LOG_MAX_ENTRIES` are no longer supported.
+> - Use the new env model instead:
+> - `APP_LOG_TO_FILE`
+> - `APP_LOG_FILE_PATH`
+> - `APP_LOG_MAX_FILE_SIZE`
+> - `APP_LOG_RETENTION_DAYS`
+> - `APP_LOG_MAX_FILES`
+> - `APP_LOG_LEVEL`
+> - `APP_LOG_FORMAT`
+> - `CALL_LOG_RETENTION_DAYS`
+> - `CALL_LOG_MAX_ENTRIES`
+>
+> For release details and upgrade notes, see the [CHANGELOG](CHANGELOG.md).
---
-## 🖼️ Hlavní ovládací panel
+## 🆕 What's New
-
+> **Upgrading from v2.9.5?** — See the [full CHANGELOG](CHANGELOG.md#300--2026-03-22-release-candidate--not-yet-merged-to-main) for all changes.
+
+| Area | Change |
+| ---------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| 🔒 **CodeQL Security** | Fixed 10+ CodeQL alerts: polynomial-redos, insecure-randomness, shell-injection remediation |
+| ✅ **Route Validation** | All 176 API routes now validated with Zod schemas + `validateBody()` — CI `check:route-validation:t06` passes |
+| 🐛 **omniModel Tag Leak** | Internal `` tags no longer leak to clients in SSE streaming responses (#585) |
+| 🔑 **Registered Keys API** | Auto-provision API keys via `POST /api/v1/registered-keys` with per-provider/account quota enforcement, idempotency, SHA-256 storage, and optional GitHub issue reporting |
+| 🎨 **Provider Icons** | 130+ provider logos via `@lobehub/icons` (SVG) with PNG → generic fallback chain |
+| 🔄 **Model Auto-Sync** | 24h scheduler and manual UI toggle to sync model lists for built-in and custom OpenAI-compatible providers |
+| 🌐 **OpenCode Zen/Go** | Two new providers from @kang-heewon via PR #530: free tier + subscription tier via `OpencodeExecutor` |
+| 🐛 **Gemini CLI OAuth** | Actionable error when `GEMINI_OAUTH_CLIENT_SECRET` is missing in Docker (was cryptic Google error) |
+| 🐛 **OpenCode config** | `saveOpenCodeConfig()` now correctly writes TOML to `XDG_CONFIG_HOME` |
+| 🐛 **Pinned model override** | `body.model` correctly set to `pinnedModel` on context-cache protection |
+| 🐛 **Codex/Claude loop** | `tool_result` blocks now converted to text to stop infinite loops |
+| 🐛 **Login redirect** | Login no longer freezes after skipping password setup |
+| 🐛 **Windows paths** | MSYS2/Git-Bash paths (`/c/...`) normalized to `C:\...` automatically |
---
-## 📸 Náhled řídicího panelu
+## 🖼️ Main Dashboard
+
+
+

+
+
+---
+
+## 📸 Dashboard Preview
-Kliknutím zobrazíte snímky obrazovky z řídicího panelu
-
+Click to see dashboard screenshots
-| Strana | Snímek obrazovky |
-| ----------------------- | --------------------------------------------------- |
-| **Poskytovatelé** |  |
-| **Kombinace** |  |
-| **Analytika** |  |
-| **Zdraví** |  |
-| **Překladatel** |  |
-| **Nastavení** |  |
-| **Nástroje CLI** |  |
-| **Protokoly používání** |  |
-| **Koncové body** |  |
+| Page | Screenshot |
+| -------------- | ------------------------------------------------- |
+| **Providers** |  |
+| **Combos** |  |
+| **Analytics** |  |
+| **Health** |  |
+| **Translator** |  |
+| **Settings** |  |
+| **CLI Tools** |  |
+| **Usage Logs** |  |
+| **Endpoints** |  |
+
+
---
-### 🤖 Bezplatný poskytovatel umělé inteligence pro vaše oblíbené programátory
+### 🤖 Free AI Provider for your favorite coding agents
-_Připojte libovolný nástroj IDE nebo CLI s umělou inteligencí přes OmniRoute — bezplatnou API bránu pro neomezené kódování._
+_Connect any AI-powered IDE or CLI tool through OmniRoute — free API gateway for unlimited coding._
-📡 Všichni agenti se připojují přes http://localhost:20128/v1 nebo http://cloud.omniroute.online/v1 — jedna konfigurace, neomezené modely a kvóty
+📡 All agents connect via http://localhost:20128/v1 or http://cloud.omniroute.online/v1 — one config, unlimited models and quota
---
-## 🤔 Proč OmniRoute?
+## 🤔 Why OmniRoute?
-**Přestaňte plýtvat penězi a narážet na limity:**
+**Stop wasting money and hitting limits:**
--
Kvóta předplatného vyprší každý měsíc
--
Limity rychlosti vám zabrání v kódování
--
Drahá API (20–50 USD/měsíc na poskytovatele)
--
Ruční přepínání mezi poskytovateli
+-
Subscription quota expires unused every month
+-
Rate limits stop you mid-coding
+-
Expensive APIs ($20-50/month per provider)
+-
Manual switching between providers
-**OmniRoute to řeší:**
+**OmniRoute solves this:**
-- ✅ **Maximalizujte předplatné** – Sledujte kvótu, využijte každou částku před resetováním
-- ✅ **Automatické záložní** – Předplatné → API klíč → Levné → Zdarma, žádné výpadky
-- ✅ **Více účtů** – Round-robin mezi účty u jednotlivých poskytovatelů
-- ✅ **Univerzální** - Funguje s Claude Code, Codex, Gemini CLI, Cursor, Cline, OpenClaw a jakýmkoli nástrojem CLI
+- ✅ **Maximize subscriptions** - Track quota, use every bit before reset
+- ✅ **Auto fallback** - Subscription → API Key → Cheap → Free, zero downtime
+- ✅ **Multi-account** - Round-robin between accounts per provider
+- ✅ **Universal** - Works with Claude Code, Codex, Gemini CLI, Cursor, Cline, OpenClaw, any CLI tool
---
-## 📧 Podpora
+## 📧 Support
-> 💬 **Přidejte se k naší komunitě!** [Skupina WhatsApp](https://chat.whatsapp.com/JI7cDQ1GyaiDHhVBpLxf8b?mode=gi_t) — Získejte pomoc, sdílejte tipy a buďte v obraze.
+> 💬 **Join our community!** [WhatsApp Group](https://chat.whatsapp.com/JI7cDQ1GyaiDHhVBpLxf8b?mode=gi_t) — Get help, share tips, and stay updated.
-- **Webová stránka** : [omniroute.online](https://omniroute.online)
-- **GitHub** : [github.com/diegosouzapw/OmniRoute](https://github.com/diegosouzapw/OmniRoute)
-- **Problémy** : [github.com/diegosouzapw/OmniRoute/issues](https://github.com/diegosouzapw/OmniRoute/issues)
-- **WhatsApp** : [Komunitní skupina](https://chat.whatsapp.com/JI7cDQ1GyaiDHhVBpLxf8b?mode=gi_t)
-- **Přispívání** : Viz [CONTRIBUTING.md](CONTRIBUTING.md) , otevřete žádost o příspěvek nebo si vyberte `good first issue`
-- **Původní projekt** : [9router od decolua](https://github.com/decolua/9router)
+- **Website**: [omniroute.online](https://omniroute.online)
+- **GitHub**: [github.com/diegosouzapw/OmniRoute](https://github.com/diegosouzapw/OmniRoute)
+- **Issues**: [github.com/diegosouzapw/OmniRoute/issues](https://github.com/diegosouzapw/OmniRoute/issues)
+- **WhatsApp**: [Community Group](https://chat.whatsapp.com/JI7cDQ1GyaiDHhVBpLxf8b?mode=gi_t)
+- **Contributing**: See [CONTRIBUTING.md](CONTRIBUTING.md), open a PR, or pick a `good first issue`
+- **Original Project**: [9router by decolua](https://github.com/decolua/9router)
-### 🐛 Hlásíte chybu?
+### 🐛 Reporting a Bug?
-Při otevírání problému spusťte příkaz system-info a přiložte vygenerovaný soubor:
+When opening an issue, please run the system-info command and attach the generated file:
```bash
npm run system-info
```
-Tím se vygeneruje soubor `system-info.txt` s verzí Node.js, verzí OmniRoute, podrobnostmi o operačním systému, nainstalovanými nástroji CLI (qoder, gemini, claude, codex, antigravity, droid atd.), stavem Dockeru/PM2 a systémovými balíčky – vše, co potřebujeme k rychlé reprodukci vašeho problému. Soubor přiložte přímo k vašemu problému na GitHubu.
+This generates a `system-info.txt` with your Node.js version, OmniRoute version, OS details, installed CLI tools (qoder, gemini, claude, codex, antigravity, droid, etc.), Docker/PM2 status, and system packages — everything we need to reproduce your issue quickly. Attach the file directly to your GitHub issue.
---
-## 🔄 Jak to funguje
+## 🔄 How It Works
```
┌─────────────┐
@@ -168,423 +262,453 @@ Result: Never stop coding, minimal cost
---
-## 🎯 Co řeší OmniRoute — 30 skutečných problémů a případů použití
+## 🎯 What OmniRoute Solves — 30 Real Pain Points & Use Cases
-> **Každý vývojář používající nástroje umělé inteligence se s těmito problémy setkává denně.** OmniRoute byl vytvořen tak, aby je všechny vyřešil – od překročení nákladů po regionální bloky, od nefunkčních toků OAuth až po operace s protokoly a sledovatelnost v podniku.
+> **Every developer using AI tools faces these problems daily.** OmniRoute was built to solve them all — from cost overruns to regional blocks, from broken OAuth flows to protocol operations and enterprise observability.
-💸 1. „Platím si drahé předplatné, ale stále mě ruší limity“
+💸 1. "I pay for an expensive subscription but still get interrupted by limits"
+
+Developers pay $20–200/month for Claude Pro, Codex Pro, or GitHub Copilot. Even paying, quota has a ceiling — 5h of usage, weekly limits, or per-minute rate limits. Mid-coding session, the provider stops responding and the developer loses flow and productivity.
+
+**How OmniRoute solves it:**
+
+- **Smart 4-Tier Fallback** — If subscription quota runs out, automatically redirects to API Key → Cheap → Free with zero manual intervention
+- **Real-Time Quota Tracking** — Shows token consumption in real-time with reset countdown (5h, daily, weekly)
+- **Multi-Account Support** — Multiple accounts per provider with auto round-robin — when one runs out, switches to the next
+- **Custom Combos** — Customizable fallback chains with 9 balancing strategies (priority, weighted, fill-first, round-robin, P2C, random, least-used, cost-optimized, strict-random)
+- **Codex Business Quotas** — Business/Team workspace quota monitoring directly in the dashboard
+
-Vývojáři platí za Claude Pro, Codex Pro nebo GitHub Copilot 20–200 dolarů měsíčně. I při platbě má kvóta strop – 5 hodin používání, týdenní limity nebo limity rychlosti za minutu. Uprostřed kódovací relace poskytovatel přestane reagovat a vývojář ztrácí plynulost a produktivitu.
-
-**Jak to OmniRoute řeší:**
-
-- **Inteligentní čtyřúrovňová záložní služba** – Pokud dojde kvóta předplatného, automaticky se přesměruje na API klíč → Levné → Zdarma bez manuálního zásahu
-- **Sledování kvót v reálném čase** – Zobrazuje spotřebu tokenů v reálném čase s odpočítáváním resetování (5 hodin, denně, týdně)
-- **Podpora více účtů** – Více účtů u jednoho poskytovatele s automatickým přepínáním – když jeden dojde, přepne se na další
-- **Vlastní kombinace** — Přizpůsobitelné záložní řetězce se 6 strategiemi vyvažování (fill-first, round robin, P2C, náhodné, nejméně používané, nákladově optimalizované)
-- **Codex Business Quotas** — Sledování kvót pracovního prostoru firmy/týmu přímo v dashboardu
-
-🔌 2. „Potřebuji použít více poskytovatelů, ale každý má jiné API“
+🔌 2. "I need to use multiple providers but each has a different API"
+
+OpenAI uses one format, Claude (Anthropic) uses another, Gemini yet another. If a dev wants to test models from different providers or fallback between them, they need to reconfigure SDKs, change endpoints, deal with incompatible formats. Custom providers (FriendLI, NIM) have non-standard model endpoints.
+
+**How OmniRoute solves it:**
+
+- **Unified Endpoint** — A single `http://localhost:20128/v1` serves as proxy for all 60+ providers
+- **Format Translation** — Automatic and transparent: OpenAI ↔ Claude ↔ Gemini ↔ Responses API
+- **Response Sanitization** — Strips non-standard fields (`x_groq`, `usage_breakdown`, `service_tier`) that break OpenAI SDK v1.83+
+- **Role Normalization** — Converts `developer` → `system` for non-OpenAI providers; `system` → `user` for GLM/ERNIE
+- **Think Tag Extraction** — Extracts `` blocks from models like DeepSeek R1 into standardized `reasoning_content`
+- **Structured Output for Gemini** — `json_schema` → `responseMimeType`/`responseSchema` automatic conversion
+- **`stream` defaults to `false`** — Aligns with OpenAI spec, avoiding unexpected SSE in Python/Rust/Go SDKs
+
-OpenAI používá jeden formát, Claude (Anthropic) jiný a Gemini ještě třetí. Pokud chce vývojář testovat modely od různých poskytovatelů nebo mezi nimi přecházet, musí překonfigurovat SDK, změnit koncové body a vypořádat se s nekompatibilními formáty. Vlastní poskytovatelé (FriendLI, NIM) mají nestandardní koncové body modelů.
-
-**Jak to OmniRoute řeší:**
-
-- **Sjednocený koncový bod** — Jeden `http://localhost:20128/v1` slouží jako proxy pro všech 67+ poskytovatelů.
-- **Překlad formátu** — Automatický a transparentní: OpenAI ↔ Claude ↔ Gemini ↔ Responses API
-- **Sanitizace odpovědí** — Odstraňuje nestandardní pole ( `x_groq` , `usage_breakdown` , `service_tier` ), která porušují OpenAI SDK v1.83+
-- **Normalizace rolí** — Převádí `developer` → `system` pro poskytovatele bez OpenAI; `system` → `user` pro GLM/ERNIE
-- **Extrakce tagů Think** — Extrahuje bloky `` z modelů, jako je DeepSeek R1, do standardizovaného `reasoning_content`
-- **Strukturovaný výstup pro Gemini** — `json_schema` → automatická konverze `responseMimeType` / `responseSchema`
-- **Výchozí hodnota `stream` je `false`** – Odpovídá specifikaci OpenAI, čímž se zabrání neočekávanému SSE v Python/Rust/Go SDK.
-
-🌐 3. „Můj poskytovatel AI blokuje můj region/zemi“
+🌐 3. "My AI provider blocks my region/country"
+
+Providers like OpenAI/Codex block access from certain geographic regions. Users get errors like `unsupported_country_region_territory` during OAuth and API connections. This is especially frustrating for developers from developing countries.
+
+**How OmniRoute solves it:**
+
+- **3-Level Proxy Config** — Configurable proxy at 3 levels: global (all traffic), per-provider (one provider only), and per-connection/key
+- **Color-Coded Proxy Badges** — Visual indicators: 🟢 global proxy, 🟡 provider proxy, 🔵 connection proxy, always showing the IP
+- **OAuth Token Exchange Through Proxy** — OAuth flow also goes through the proxy, solving `unsupported_country_region_territory`
+- **Connection Tests via Proxy** — Connection tests use the configured proxy (no more direct bypass)
+- **SOCKS5 Support** — Full SOCKS5 proxy support for outbound routing
+- **TLS Fingerprint Spoofing** — Browser-like TLS fingerprint via `wreq-js` to bypass bot detection
+- **🔏 CLI Fingerprint Matching** — Reorders headers and body fields to match native CLI binary signatures, drastically reducing account flagging risk. The proxy IP is preserved — you get both stealth **and** IP masking simultaneously
+
-Poskytovatelé jako OpenAI/Codex blokují přístup z určitých geografických oblastí. Uživatelé se během připojení OAuth a API dostávají k chybám jako `unsupported_country_region_territory` . To je obzvláště frustrující pro vývojáře z rozvojových zemí.
-
-**Jak to OmniRoute řeší:**
-
-- **3úrovňová konfigurace proxy** – Konfigurovatelná proxy na 3 úrovních: globální (veškerý provoz), pro jednotlivé poskytovatele (pouze jeden poskytovatel) a pro jednotlivé připojení/klíč
-- **Barevně kódované odznaky proxy** – Vizuální indikátory: 🟢 globální proxy, 🟡 proxy poskytovatele, 🔵 proxy připojení, vždy zobrazující IP adresu
-- **Výměna tokenů OAuth prostřednictvím proxy** – tok OAuth také prochází přes proxy, čímž se řeší `unsupported_country_region_territory`
-- **Testy připojení přes proxy** – Testy připojení používají nakonfigurovaný proxy (již žádné přímé obcházení)
-- **Podpora SOCKS5** — Plná podpora proxy SOCKS5 pro odchozí směrování
-- **TLS Fingerprint Spoofing** — Otisk prstu TLS podobný prohlížeči pomocí `wreq-js` pro obcházení detekce botů
-- **🔏 Porovnávání otisků prstů v CLI** — Změní pořadí záhlaví a polí v těle serveru tak, aby odpovídala nativním binárním podpisům v CLI, čímž drasticky snižuje riziko nahlašování účtu. IP adresa proxy je zachována — získáte současně stealth **i** maskování IP adresy.
-
-🆓 4. „Chci používat umělou inteligenci pro kódování, ale nemám peníze“
+🆓 4. "I want to use AI for coding but I have no money"
+
+Not everyone can pay $20–200/month for AI subscriptions. Students, devs from emerging countries, hobbyists, and freelancers need access to quality models at zero cost.
+
+**How OmniRoute solves it:**
+
+- **Free Tier Providers Built-in** — Native support for 100% free providers: Qoder (5 unlimited models via OAuth: kimi-k2-thinking, qwen3-coder-plus, deepseek-r1, minimax-m2, kimi-k2), Qwen (4 unlimited models: qwen3-coder-plus, qwen3-coder-flash, qwen3-coder-next, vision-model), Kiro (Claude + AWS Builder ID for free), Gemini CLI (180K tokens/month free)
+- **Ollama Cloud** — Cloud-hosted Ollama models at `api.ollama.com` with free "Light usage" tier; use `ollamacloud/` prefix
+- **Free-Only Combos** — Chain `gc/gemini-3-flash → if/kimi-k2-thinking → qw/qwen3-coder-plus` = $0/month with zero downtime
+- **NVIDIA NIM Free Access** — ~40 RPM dev-forever free access to 70+ models at build.nvidia.com (transitioning from credits to pure rate limits)
+- **Cost Optimized Strategy** — Routing strategy that automatically chooses the cheapest available provider
+
-Ne každý si může dovolit zaplatit 20–200 dolarů měsíčně za předplatné AI. Studenti, vývojáři z rozvíjejících se zemí, amatéři a freelanceři potřebují přístup ke kvalitním modelům za nulovou cenu.
-
-**Jak to OmniRoute řeší:**
-
-- **Vestavění poskytovatelé bezplatné úrovně** — Nativní podpora pro 100% bezplatné poskytovatele: Qoder (5 neomezených modelů přes OAuth: kimi-k2-thinking, qwen3-coder-plus, deepseek-r1, minimax-m2, kimi-k2), Qwen (4 neomezené modely: qwen3-coder-plus, qwen3-coder-flash, qwen3-coder-next, vision-model), Kiro (Claude + AWS Builder ID zdarma), Gemini CLI (180 tisíc tokenů/měsíc zdarma)
-- **Ollama Cloud** — Cloudově hostované modely Ollama na `api.ollama.com` s bezplatnou úrovní „Light usage“; použijte prefix `ollamacloud/`
-- **Kombinace pouze zdarma** — Chain `gc/gemini-3-flash → if/kimi-k2-thinking → qw/qwen3-coder-plus` = 0 $/měsíc s nulovými prostoji
-- **NVIDIA NIM Free Access** — ~40 RPM developerský přístup k více než 70 modelům na build.nvidia.com (přechod z kreditů na čisté limity rychlosti)
-- **Strategie optimalizace nákladů** – Strategie směrování, která automaticky vybere nejlevnějšího dostupného poskytovatele
-
-🔒 5. „Potřebuji chránit svou bránu umělé inteligence před neoprávněným přístupem“
+🔒 5. "I need to protect my AI gateway from unauthorized access"
+
+When exposing an AI gateway to the network (LAN, VPS, Docker), anyone with the address can consume the developer's tokens/quota. Without protection, APIs are vulnerable to misuse, prompt injection, and abuse.
+
+**How OmniRoute solves it:**
+
+- **API Key Management** — Generation, rotation, and scoping per provider with a dedicated `/dashboard/api-manager` page
+- **Model-Level Permissions** — Restrict API keys to specific models (`openai/*`, wildcard patterns), with Allow All/Restrict toggle
+- **API Endpoint Protection** — Require a key for `/v1/models` and block specific providers from the listing
+- **Auth Guard + CSRF Protection** — All dashboard routes protected with `withAuth` middleware + CSRF tokens
+- **Rate Limiter** — Per-IP rate limiting with configurable windows
+- **IP Filtering** — Allowlist/blocklist for access control
+- **Prompt Injection Guard** — Sanitization against malicious prompt patterns
+- **AES-256-GCM Encryption** — Credentials encrypted at rest
+
-Při zpřístupnění brány umělé inteligence síti (LAN, VPS, Docker) může kdokoli s adresou spotřebovat tokeny/kvótu vývojáře. Bez ochrany jsou API zranitelná vůči zneužití, prompt injection a dalšímu zneužití.
-
-**Jak to OmniRoute řeší:**
-
-- **Správa klíčů API** – generování, rotace a vymezování rozsahu pro každého poskytovatele s vyhrazenou stránkou `/dashboard/api-manager`
-- **Oprávnění na úrovni modelu** – Omezení klíčů API na konkrétní modely ( `openai/*` , zástupné znaky) pomocí přepínače Povolit vše/Omezit
-- **Ochrana koncových bodů API** – Vyžaduje klíč pro `/v1/models` a blokuje konkrétní poskytovatele ze seznamu
-- **Auth Guard + CSRF Protection** — Všechny trasy dashboardu chráněné middlewarem `withAuth` + tokeny CSRF
-- **Omezovač rychlosti** — Omezování rychlosti na IP s konfigurovatelnými okny
-- **Filtrování IP adres** — Seznam povolených/blokovaných adres pro řízení přístupu
-- **Ochrana proti vkládání výzev** – Sanitizace proti škodlivým vzorcům výzev
-- **Šifrování AES-256-GCM** – přihlašovací údaje jsou v klidovém stavu šifrovány
-
-🛑 6. „Můj poskytovatel selhal a já ztratil/a programovací tok“
+🛑 6. "My provider went down and I lost my coding flow"
+
+AI providers can become unstable, return 5xx errors, or hit temporary rate limits. If a dev depends on a single provider, they're interrupted. Without circuit breakers, repeated retries can crash the application.
+
+**How OmniRoute solves it:**
+
+- **Circuit Breaker per-model** — Auto-open/close with configurable thresholds and cooldown (Closed/Open/Half-Open), scoped per-model to avoid cascading blocks
+- **Exponential Backoff** — Progressive retry delays
+- **Anti-Thundering Herd** — Mutex + semaphore protection against concurrent retry storms
+- **Combo Fallback Chains** — If the primary provider fails, automatically falls through the chain with no intervention
+- **Combo Circuit Breaker** — Auto-disables failing providers within a combo chain
+- **Health Dashboard** — Uptime monitoring, circuit breaker states, lockouts, cache stats, p50/p95/p99 latency
+
-Poskytovatelé umělé inteligence se mohou stát nestabilními, vracet chyby 5xx nebo dosáhnout dočasných limitů rychlosti. Pokud je vývojář závislý na jediném poskytovateli, je jeho práce přerušena. Bez jističů může opakované pokusy vést k pádu aplikace.
-
-**Jak to OmniRoute řeší:**
-
-- **Jistič pro každý model** – Automatické otevírání/zavírání s konfigurovatelnými prahovými hodnotami a dobou ochlazování (Zavřeno/Otevřeno/Poloviční otevření), rozsah definovaný pro každý model, aby se zabránilo kaskádování bloků
-- **Exponenciální odklad** — Progresivní zpoždění opakování
-- **Anti-Thundering Herd** — ochrana Mutex + semafor proti souběžným bouřím s opakovanými pokusy
-- **Kombinované záložní řetězce** – Pokud primární poskytovatel selže, automaticky se propadne řetězcem bez zásahu.
-- **Kombinovaný jistič** – Automaticky deaktivuje selhávajícího poskytovatele v rámci kombinovaného řetězce
-- **Dashboard stavu** — Monitorování provozuschopnosti, stavy jističů, uzamčení, statistiky mezipaměti, latence p50/p95/p99
-
-🔧 7. „Konfigurace každého nástroje umělé inteligence je zdlouhavá a opakující se“
+🔧 7. "Configuring each AI tool is tedious and repetitive"
+
+Developers use Cursor, Claude Code, Codex CLI, OpenClaw, Gemini CLI, Kilo Code... Each tool needs a different config (API endpoint, key, model). Reconfiguring when switching providers or models is a waste of time.
+
+**How OmniRoute solves it:**
+
+- **CLI Tools Dashboard** — Dedicated page with one-click setup for Claude Code, Codex CLI, OpenClaw, Kilo Code, Antigravity, Cline
+- **GitHub Copilot Config Generator** — Generates `chatLanguageModels.json` for VS Code with bulk model selection
+- **Onboarding Wizard** — Guided 4-step setup for first-time users
+- **One endpoint, all models** — Configure `http://localhost:20128/v1` once, access 60+ providers
+
-Vývojáři používají Cursor, Claude Code, Codex CLI, OpenClaw, Gemini CLI, Kilo Code... Každý nástroj potřebuje jinou konfiguraci (API endpoint, klíč, model). Překonfigurování při změně poskytovatele nebo modelu je ztráta času.
-
-**Jak to OmniRoute řeší:**
-
-- **Panel nástrojů CLI** — Vyhrazená stránka s nastavením jedním kliknutím pro Claude Code, Codex CLI, OpenClaw, Kilo Code, Antigravity a Cline
-- **Generátor konfigurace GitHub Copilot** – Generuje `chatLanguageModels.json` pro VS Code s hromadným výběrem modelu
-- **Průvodce zaváděním** – 4krokové nastavení pro začínající uživatele
-- **Jeden koncový bod, všechny modely** – jednou nakonfigurujte `http://localhost:20128/v1` a získejte přístup k více než 44 poskytovatelům
-
-🔑 8. „Správa OAuth tokenů od více poskytovatelů je peklo“
+🔑 8. "Managing OAuth tokens from multiple providers is hell"
+
+Claude Code, Codex, Gemini CLI, Copilot — all use OAuth 2.0 with expiring tokens. Developers need to re-authenticate constantly, deal with `client_secret is missing`, `redirect_uri_mismatch`, and failures on remote servers. OAuth on LAN/VPS is particularly problematic.
+
+**How OmniRoute solves it:**
+
+- **Auto Token Refresh** — OAuth tokens refresh in background before expiration
+- **OAuth 2.0 (PKCE) Built-in** — Automatic flow for Claude Code, Codex, Gemini CLI, Copilot, Kiro, Qwen, Qoder
+- **Multi-Account OAuth** — Multiple accounts per provider via JWT/ID token extraction
+- **OAuth LAN/Remote Fix** — Private IP detection for `redirect_uri` + manual URL mode for remote servers
+- **OAuth Behind Nginx** — Uses `window.location.origin` for reverse proxy compatibility
+- **Remote OAuth Guide** — Step-by-step guide for Google Cloud credentials on VPS/Docker
+
-Claude Code, Codex, Gemini CLI, Copilot – všechny používají OAuth 2.0 s tokeny s vypršením platnosti. Vývojáři se musí neustále znovu autentizovat, řešit chyby `client_secret is missing` , `redirect_uri_mismatch` a chyby na vzdálených serverech. Obzvláště problematický je OAuth v LAN/VPS.
-
-**Jak to OmniRoute řeší:**
-
-- **Automatická aktualizace tokenů** – Tokeny OAuth se obnovují na pozadí před vypršením platnosti.
-- **Vestavěný OAuth 2.0 (PKCE)** – Automatický tok pro Claude Code, Codex, Gemini CLI, Copilot, Kiro, Qwen, Qoder
-- **Multi-Account OAuth** — Více účtů na poskytovatele prostřednictvím extrakce tokenů JWT/ID
-- **OAuth LAN/Remote Fix** — Detekce privátní IP adresy pro `redirect_uri` + manuální režim URL pro vzdálené servery
-- **OAuth Behind Nginx** — Používá `window.location.origin` pro kompatibilitu s reverzní proxy
-- **Průvodce vzdáleným OAuth** – Podrobný návod k přihlašovacím údajům Google Cloud na VPS/Dockeru
-
-📊 9. „Nevím, kolik utrácím ani kde“
+📊 9. "I don't know how much I'm spending or where"
+
+Developers use multiple paid providers but have no unified view of spending. Each provider has its own billing dashboard, but there's no consolidated view. Unexpected costs can pile up.
+
+**How OmniRoute solves it:**
+
+- **Cost Analytics Dashboard** — Per-token cost tracking and budget management per provider
+- **Budget Limits per Tier** — Spending ceiling per tier that triggers automatic fallback
+- **Per-Model Pricing Configuration** — Configurable prices per model
+- **Usage Statistics Per API Key** — Request count and last-used timestamp per key
+- **Analytics Dashboard** — Stat cards, model usage chart, provider table with success rates and latency
+
-Vývojáři používají více placených poskytovatelů, ale nemají jednotný přehled o výdajích. Každý poskytovatel má svůj vlastní fakturační panel, ale neexistuje žádný konsolidovaný přehled. Mohou se hromadit neočekávané náklady.
-
-**Jak to OmniRoute řeší:**
-
-- **Dashboard pro analýzu nákladů** – Sledování nákladů na token a správa rozpočtu pro každého poskytovatele
-- **Rozpočtové limity na úroveň** – Strop výdajů na úroveň, který spouští automatický záložní režim
-- **Konfigurace cen podle modelu** – Konfigurovatelné ceny podle modelu
-- **Statistiky použití pro každý klíč API** — Počet požadavků a časové razítko posledního použití pro každý klíč
-- **Analytický panel** – Statistické karty, graf využití modelu, tabulka poskytovatelů s mírou úspěšnosti a latencí
-
-🐛 10. „Nedokážu diagnostikovat chyby a problémy ve volání umělé inteligence.“
+🐛 10. "I can't diagnose errors and problems in AI calls"
+
+When a call fails, the dev doesn't know if it was a rate limit, expired token, wrong format, or provider error. Fragmented logs across different terminals. Without observability, debugging is trial-and-error.
+
+**How OmniRoute solves it:**
+
+- **Unified Logs Dashboard** — 4 tabs: Request Logs, Proxy Logs, Audit Logs, Console
+- **Console Log Viewer** — Real-time terminal-style viewer with color-coded levels, auto-scroll, search, filter
+- **SQLite Proxy Logs** — Persistent logs that survive server restarts
+- **Translator Playground** — 4 debugging modes: Playground (format translation), Chat Tester (round-trip), Test Bench (batch), Live Monitor (real-time)
+- **Request Telemetry** — p50/p95/p99 latency + X-Request-Id tracing
+- **File-Based Logging with Rotation** — App logs rotate by size, retention days, and archive count; call log artifacts rotate by retention days and file count
+- **System Info Report** — `npm run system-info` generates `system-info.txt` with your full environment (Node version, OmniRoute version, OS, CLI tools, Docker/PM2 status). Attach it when reporting issues for instant triage.
+
-Když volání selže, vývojář neví, zda se jednalo o limit rychlosti, vypršelý token, špatný formát nebo chybu poskytovatele. Fragmentované protokoly napříč různými terminály. Bez sledovatelnosti je ladění metodou pokus-omyl.
-
-**Jak to OmniRoute řeší:**
-
-- **Panel jednotných protokolů** – 4 karty: Protokoly požadavků, Protokoly proxy, Protokoly auditu, Konzole
-- **Prohlížeč protokolů konzole** — Prohlížeč protokolů v reálném čase ve stylu terminálu s barevně kódovanými úrovněmi, automatickým posouváním, vyhledáváním a filtrováním
-- **Protokoly proxy SQLite** – trvalé protokoly, které přežijí restart serveru
-- **Překladačské hřiště** — 4 režimy ladění: Hřiště (překlad formátu), Tester chatu (okružní), Testovací stůl (dávkový), Živý monitor (v reálném čase)
-- **Telemetrie požadavků** — latence p50/p95/p99 + trasování X-Request-Id
-- **Souborové protokolování s rotací** – Konzolový interceptor zachycuje vše do protokolu JSON s rotací na základě velikosti
-- **Zpráva o systémových informacích** — příkaz `npm run system-info` vygeneruje `system-info.txt` s kompletním popisem vašeho prostředí (verze uzlu, verze OmniRoute, operační systém, nástroje CLI, stav Dockeru/PM2). Přiložte jej při hlášení problémů pro okamžité třídění.
-
-🏗️ 11. „Nasazení a údržba brány je složitá“
+🏗️ 11. "Deploying and maintaining the gateway is complex"
+
+Installing, configuring, and maintaining an AI proxy across different environments (local, VPS, Docker, cloud) is labor-intensive. Problems like hardcoded paths, `EACCES` on directories, port conflicts, and cross-platform builds add friction.
+
+**How OmniRoute solves it:**
+
+- **npm global install** — `npm install -g omniroute && omniroute` — done
+- **Docker Multi-Platform** — AMD64 + ARM64 native (Apple Silicon, AWS Graviton, Raspberry Pi)
+- **Docker Compose Profiles** — `base` (no CLI tools) and `cli` (with Claude Code, Codex, OpenClaw)
+- **Electron Desktop App** — Native app for Windows/macOS/Linux with system tray, auto-start, offline mode
+- **Split-Port Mode** — API and Dashboard on separate ports for advanced scenarios (reverse proxy, container networking)
+- **Cloud Sync** — Config synchronization across devices via Cloudflare Workers
+- **DB Backups** — Automatic backup, restore, export and import of all settings, with `DISABLE_SQLITE_AUTO_BACKUP` for externally managed backups
+
-Instalace, konfigurace a údržba AI proxy v různých prostředích (lokální, VPS, Docker, cloud) je pracná. Problémy, jako jsou pevně zakódované cesty, `EACCES` u adresářů, konflikty portů a multiplatformní sestavení, přispívají k obtížím.
-
-**Jak to OmniRoute řeší:**
-
-- **npm globální instalace** — `npm install -g omniroute && omniroute` — hotovo
-- **Docker Multi-Platform** — AMD64 + nativní ARM64 (Apple Silicon, AWS Graviton, Raspberry Pi)
-- **Profily Docker Compose** — `base` (bez nástrojů CLI) a `cli` (s Claude Code, Codex, OpenClaw)
-- **Desktopová aplikace Electron** — Nativní aplikace pro Windows/macOS/Linux se systémovou lištou, automatickým spuštěním a offline režimem
-- **Režim rozdělených portů** – API a řídicí panel na samostatných portech pro pokročilé scénáře (reverzní proxy, síťování kontejnerů)
-- **Cloud Sync** – Konfigurace synchronizace mezi zařízeními pomocí Cloudflare Workers
-- **Zálohy databází** — Automatické zálohování, obnovení, export a import všech nastavení
-
-🌍 12. „Rozhraní je pouze v angličtině a můj tým nemluví anglicky“
+🌍 12. "The interface is English-only and my team doesn't speak English"
+
+Teams in non-English-speaking countries, especially in Latin America, Asia, and Europe, struggle with English-only interfaces. Language barriers reduce adoption and increase configuration errors.
+
+**How OmniRoute solves it:**
+
+- **Dashboard i18n — 30 Languages** — All 500+ keys translated including Arabic, Bulgarian, Danish, German, Spanish, Finnish, French, Hebrew, Hindi, Hungarian, Indonesian, Italian, Japanese, Korean, Malay, Dutch, Norwegian, Polish, Portuguese (PT/BR), Romanian, Russian, Slovak, Swedish, Thai, Ukrainian, Vietnamese, Chinese, Filipino, English
+- **RTL Support** — Right-to-left support for Arabic and Hebrew
+- **Multi-Language READMEs** — 30 complete documentation translations
+- **Language Selector** — Globe icon in header for real-time switching
+
-Týmy v neanglicky mluvících zemích, zejména v Latinské Americe, Asii a Evropě, se potýkají s rozhraními pouze v angličtině. Jazykové bariéry snižují míru přijetí a zvyšují chyby v konfiguraci.
-
-**Jak to OmniRoute řeší:**
-
-- **Dashboard i18n — 30 jazyků** — Všech 500+ kláves je přeloženo včetně arabštiny, bulharštiny, dánštiny, němčiny, španělštiny, finštiny, francouzštiny, hebrejštiny, hindštiny, maďarštiny, indonéštiny, italštiny, japonštiny, korejštiny, malajštiny, holandštiny, norštiny, polštiny, portugalštiny (PT/BR), rumunštiny, ruštiny, slovenštiny, švédštiny, thajštiny, ukrajinštiny, vietnamštiny, čínštiny, filipínštiny a angličtiny
-- **Podpora RTL** – Podpora psaní zprava doleva pro arabštinu a hebrejštinu
-- **Vícejazyčné soubory README** — 30 kompletních překladů dokumentace
-- **Výběr jazyka** — Ikona glóbu v záhlaví pro přepínání v reálném čase
-
-🔄 13. „Potřebuji víc než jen chat – potřebuji vložené soubory, obrázky, zvuk.“
+🔄 13. "I need more than chat — I need embeddings, images, audio"
+
+AI isn't just chat completion. Devs need to generate images, transcribe audio, create embeddings for RAG, rerank documents, and moderate content. Each API has a different endpoint and format.
+
+**How OmniRoute solves it:**
+
+- **Embeddings** — `/v1/embeddings` with 6 providers and 9+ models
+- **Image Generation** — `/v1/images/generations` with 10 providers and 20+ models (OpenAI, xAI, Together, Fireworks, Nebius, Hyperbolic, NanoBanana, Antigravity, SD WebUI, ComfyUI)
+- **Text-to-Video** — `/v1/videos/generations` — ComfyUI (AnimateDiff, SVD) and SD WebUI
+- **Text-to-Music** — `/v1/music/generations` — ComfyUI (Stable Audio Open, MusicGen)
+- **Audio Transcription** — `/v1/audio/transcriptions` — Whisper + Nvidia NIM, HuggingFace, Qwen3
+- **Text-to-Speech** — `/v1/audio/speech` — ElevenLabs, Nvidia NIM, HuggingFace, Coqui, Tortoise, Qwen3, **Inworld**, **Cartesia**, **PlayHT**, + existing providers
+- **Moderations** — `/v1/moderations` — Content safety checks
+- **Reranking** — `/v1/rerank` — Document relevance reranking
+- **Responses API** — Full `/v1/responses` support for Codex
+
-Umělá inteligence není jen dokončování chatu. Vývojáři potřebují generovat obrázky, přepisovat zvuk, vytvářet embeddedy pro RAG, měnit pořadí dokumentů a moderovat obsah. Každé API má jiný koncový bod a formát.
-
-**Jak to OmniRoute řeší:**
-
-- **Vkládání** — `/v1/embeddings` s 6 poskytovateli a 9+ modely
-- **Generování obrázků** — `/v1/images/generations` s 10 poskytovateli a více než 20 modely (OpenAI, xAI, Together, Fireworks, Nebius, Hyperbolic, NanoBanana, Antigravity, SD WebUI, ComfyUI)
-- **Převod textu na video** — `/v1/videos/generations` — ComfyUI (AnimateDiff, SVD) a SD WebUI
-- **Převod textu na hudbu** — `/v1/music/generations` — ComfyUI (Stable Audio Open, MusicGen)
-- **Přepis zvuku** — `/v1/audio/transcriptions` — Whisper + Nvidia NIM, HuggingFace, Qwen3
-- **Převod textu na řeč** — `/v1/audio/speech` — ElevenLabs, Nvidia NIM, HuggingFace, Coqui, Tortoise, Qwen3, **Inworld** , **Cartesia** , **PlayHT** a další stávající poskytovatelé
-- **Moderování** — `/v1/moderations` — Kontroly bezpečnosti obsahu
-- **Změna pořadí** — `/v1/rerank` — Změna pořadí relevance dokumentu
-- **Responses API** — Plná podpora `/v1/responses` pro Codex
-
-🧪 14. „Nemám způsob, jak testovat a porovnávat kvalitu napříč modely.“
+🧪 14. "I have no way to test and compare quality across models"
+
+Developers want to know which model is best for their use case — code, translation, reasoning — but comparing manually is slow. No integrated eval tools exist.
+
+**How OmniRoute solves it:**
+
+- **LLM Evaluations** — Golden set testing with 10 pre-loaded cases covering greetings, math, geography, code generation, JSON compliance, translation, markdown, safety refusal
+- **4 Match Strategies** — `exact`, `contains`, `regex`, `custom` (JS function)
+- **Translator Playground Test Bench** — Batch testing with multiple inputs and expected outputs, cross-provider comparison
+- **Chat Tester** — Full round-trip with visual response rendering
+- **Live Monitor** — Real-time stream of all requests flowing through the proxy
+
-Vývojáři chtějí vědět, který model je pro jejich případ použití nejlepší – kód, překlad, uvažování – ale ruční porovnávání je pomalé. Neexistují žádné integrované nástroje pro vyhodnocování.
-
-**Jak to OmniRoute řeší:**
-
-- **Hodnocení LLM** — Testování Golden setu s 10 předinstalovanými případy zahrnujícími pozdravy, matematiku, geografii, generování kódu, dodržování JSON, překlad, markdown, odmítnutí bezpečnostních požadavků
-- **4 strategie shody** — `exact` , `contains` , `regex` , `custom` (JS funkce)
-- **Testovací lavice pro překladatelské hřiště** — Dávkové testování s více vstupy a očekávanými výstupy, porovnání napříč poskytovateli
-- **Tester chatu** — Kompletní okružní cesta s vizuálním vykreslováním odpovědí
-- **Živý monitor** — Stream všech požadavků procházejících proxy serverem v reálném čase
-
-📈 15. „Potřebuji škálovat bez ztráty výkonu“
+📈 15. "I need to scale without losing performance"
+
+As request volume grows, without caching the same questions generate duplicate costs. Without idempotency, duplicate requests waste processing. Per-provider rate limits must be respected.
+
+**How OmniRoute solves it:**
+
+- **Semantic Cache** — Two-tier cache (signature + semantic) reduces cost and latency
+- **Request Idempotency** — 5s deduplication window for identical requests
+- **Rate Limit Detection** — Per-provider RPM, min gap, and max concurrent tracking
+- **Editable Rate Limits** — Configurable defaults in Settings → Resilience with persistence
+- **API Key Validation Cache** — 3-tier cache for production performance
+- **Health Dashboard with Telemetry** — p50/p95/p99 latency, cache stats, uptime
+
-S rostoucím objemem požadavků generují stejné otázky bez ukládání do mezipaměti duplicitní náklady. Bez idempotence duplicitní požadavky plýtvají zpracováním. Je nutné dodržovat limity rychlosti na poskytovatele.
-
-**Jak to OmniRoute řeší:**
-
-- **Sémantická mezipaměť** — Dvouvrstvá mezipaměť (signatura + sémantika) snižuje náklady a latenci
-- **Idempotence požadavku** — 5s deduplikační okno pro identické požadavky
-- **Detekce limitu rychlosti** – sledování otáček za minutu (RPM), minimální mezera a maximální souběžné sledování pro každého poskytovatele
-- **Upravitelné limity rychlosti** — Konfigurovatelné výchozí hodnoty v Nastavení → Odolnost s perzistencí
-- **Mezipaměť pro ověření klíčů API** — třívrstvá mezipaměť pro výkon produkčního prostředí
-- **Dashboard s telemetrií** – latence p50/p95/p99, statistiky mezipaměti, dostupnost
-
-🤖 16. „Chci mít chování modelů globálně pod kontrolou“
+🤖 16. "I want to control model behavior globally"
+
+Developers who want all responses in a specific language, with a specific tone, or want to limit reasoning tokens. Configuring this in every tool/request is impractical.
+
+**How OmniRoute solves it:**
+
+- **System Prompt Injection** — Global prompt applied to all requests
+- **Thinking Budget Validation** — Reasoning token allocation control per request (passthrough, auto, custom, adaptive)
+- **9 Routing Strategies** — Global strategies that determine how requests are distributed
+- **Wildcard Router** — `provider/*` patterns route dynamically to any provider
+- **Combo Enable/Disable Toggle** — Toggle combos directly from the dashboard
+- **Provider Toggle** — Enable/disable all connections for a provider with one click
+- **Blocked Providers** — Exclude specific providers from `/v1/models` listing
+
-Vývojáři, kteří chtějí všechny odpovědi v určitém jazyce, se specifickým tónem nebo chtějí omezit tokeny pro uvažování. Konfigurace této funkce v každém nástroji/požadavku je nepraktická.
-
-**Jak to OmniRoute řeší:**
-
-- **Vložení systémového prompt** – Globální prompt aplikovaný na všechny požadavky
-- **Validace rozpočtu Thinking** — Řízení alokace tokenů na požadavek (průchozí, automatické, vlastní, adaptivní)
-- **6 strategií směrování** – Globální strategie, které určují, jak jsou požadavky distribuovány
-- **Směrovač se zástupnými znaky** — vzory `provider/*` dynamicky směrují k libovolnému poskytovateli
-- **Přepínání povolení/zakázání kombinací** – Přepínání kombinací přímo z řídicího panelu
-- **Přepínání poskytovatele** – Povolení/zakázání všech připojení pro poskytovatele jedním kliknutím
-- **Blokovaní poskytovatelé** – Vyloučení konkrétních poskytovatelů ze seznamu `/v1/models`
-
-🧰 17. „Potřebuji nástroje MCP jako prvotřídní produktové funkce.“
+🧰 17. "I need MCP tools as first-class product capabilities"
+
+Many AI gateways expose MCP only as a hidden implementation detail. Teams need a visible, manageable operation layer.
+
+**How OmniRoute solves it:**
+
+- MCP appears in the dashboard navigation and endpoint protocol tab
+- Dedicated MCP management page with process, tools, scopes, and audit
+- Built-in quick-start for `omniroute --mcp` and client onboarding
+
-Mnoho bran umělé inteligence odhaluje MCP pouze jako skrytý implementační detail. Týmy potřebují viditelnou a spravovatelnou operační vrstvu.
-
-**Jak to OmniRoute řeší:**
-
-- MCP se zobrazuje v navigaci na řídicím panelu a na kartě protokolu koncového bodu.
-- Vyhrazená stránka pro správu MCP s procesy, nástroji, rozsahy a auditem
-- Vestavěný rychlý start pro `omniroute --mcp` a onboarding klienta
-
-🧠 18. „Potřebuji orchestraci A2A se synchronizací a cestami úloh streamu.“
+🧠 18. "I need A2A orchestration with sync + stream task paths"
+
+Agent workflows need both direct replies and long-running streamed execution with lifecycle control.
+
+**How OmniRoute solves it:**
+
+- A2A JSON-RPC endpoint (`POST /a2a`) with `message/send` and `message/stream`
+- SSE streaming with terminal state propagation
+- Task lifecycle APIs for `tasks/get` and `tasks/cancel`
+
-Pracovní postupy agentů vyžadují jak přímé odpovědi, tak dlouhodobé streamované provádění s kontrolou životního cyklu.
-
-**Jak to OmniRoute řeší:**
-
-- Koncový bod A2A JSON-RPC ( `POST /a2a` ) s `message/send` `message/stream`
-- Streamování SSE s šířením stavu terminálu
-- Rozhraní API životního cyklu úloh pro `tasks/get` a `tasks/cancel`
-
-🛰️ 19. „Potřebuji skutečný stav procesu MCP, ne odhadovaný stav.“
+🛰️ 19. "I need real MCP process health, not guessed status"
+
+Operational teams need to know if MCP is actually alive, not just whether an API is reachable.
+
+**How OmniRoute solves it:**
+
+- Runtime heartbeat file with PID, timestamps, transport, tool count, and scope mode
+- MCP status API combining heartbeat + recent activity
+- UI status cards for process/uptime/heartbeat freshness
+
-Provozní týmy potřebují vědět, zda je MCP skutečně aktivní, nejen zda je API dosažitelné.
-
-**Jak to OmniRoute řeší:**
-
-- Soubor běhového heartbeatu s PID, časovými razítky, transportem, počtem nástrojů a režimem rozsahu
-- API stavu MCP kombinující prezenční signál a nedávnou aktivitu
-- Karty stavu uživatelského rozhraní pro zobrazení aktuálnosti procesů/provozuschopnosti/prezenčního signálu
-
-📋 20. „Potřebuji auditovatelné provedení nástroje MCP“
+📋 20. "I need auditable MCP tool execution"
+
+When tools mutate config or trigger ops actions, teams need forensic traceability.
+
+**How OmniRoute solves it:**
+
+- SQLite-backed audit logging for MCP tool calls
+- Filters by tool, success/failure, API key, and pagination
+- Dashboard audit table + stats endpoints for automation
+
-Když nástroje mění konfiguraci nebo spouštějí operační akce, týmy potřebují forenzní sledovatelnost.
-
-**Jak to OmniRoute řeší:**
-
-- Protokolování auditu pro volání nástrojů MCP s podporou SQLite
-- Filtruje podle nástroje, úspěchu/neúspěchu, klíče API a stránkování
-- Tabulka auditu dashboardu + koncové body statistik pro automatizaci
-
-🔐 21. „Potřebuji omezená oprávnění MCP pro každou integraci.“
+🔐 21. "I need scoped MCP permissions per integration"
+
+Different clients should have least-privilege access to tool categories.
+
+**How OmniRoute solves it:**
+
+- 10 granular MCP scopes for controlled tool access
+- Scope enforcement and visibility in MCP management UI
+- Safe default posture for operational tooling
+
-Různí klienti by měli mít přístup ke kategoriím nástrojů s nejnižšími oprávněními.
-
-**Jak to OmniRoute řeší:**
-
-- 9 detailních MCP sond pro kontrolovaný přístup k nástrojům
-- Vynucení rozsahu a viditelnost v uživatelském rozhraní správy MCP
-- Bezpečná výchozí poloha pro provozní nástroje
-
-⚙️ 22. „Potřebuji provozní kontroly bez nutnosti přesouvání“
+⚙️ 22. "I need operational controls without redeploying"
+
+Teams need quick runtime changes during incidents or cost events.
+
+**How OmniRoute solves it:**
+
+- Switch combo activation directly from MCP dashboard
+- Apply resilience profiles from pre-defined policy packs
+- Reset circuit breaker state from the same operations panel
+
-Týmy potřebují rychlé změny v běhovém prostředí během incidentů nebo nákladových událostí.
-
-**Jak to OmniRoute řeší:**
-
-- Přepněte aktivaci komba přímo z řídicího panelu MCP
-- Používejte profily odolnosti z předdefinovaných balíčků zásad
-- Resetujte stav jističe ze stejného ovládacího panelu
-
-🔄 23. „Potřebuji živý přehled o životním cyklu úkolů A2A a jejich zrušení.“
+🔄 23. "I need live A2A task lifecycle visibility and cancellation"
+
+Without lifecycle visibility, task incidents become hard to triage.
+
+**How OmniRoute solves it:**
+
+- Task listing/filtering by state/skill with pagination
+- Drill-down on task metadata, events, and artifacts
+- Task cancellation endpoint and UI action with confirmation
+
-Bez přehledu o životním cyklu je obtížné třídit incidenty úkolů.
-
-**Jak to OmniRoute řeší:**
-
-- Výpis/filtrování úkolů podle státu/dovednosti s stránkováním
-- Podrobný přehled metadat úloh, událostí a artefaktů
-- Koncový bod zrušení úlohy a akce uživatelského rozhraní s potvrzením
-
-🌊 24. „Potřebuji metriky aktivního streamu pro A2A zátěž“
+🌊 24. "I need active stream metrics for A2A load"
+
+Streaming workflows require operational insight into concurrency and live connections.
+
+**How OmniRoute solves it:**
+
+- Active stream counters integrated into A2A status
+- Last task timestamp and per-state counts
+- A2A dashboard cards for real-time ops monitoring
+
-Streamovací pracovní postupy vyžadují provozní přehled o souběžnosti a živých připojeních.
-
-**Jak to OmniRoute řeší:**
-
-- Čítače aktivních streamů integrované do stavu A2A
-- Časové razítko posledního úkolu a počty pro jednotlivé stavy
-- Karty A2A dashboardu pro monitorování provozu v reálném čase
-
-🪪 25. „Potřebuji standardní vyhledávání agentů pro klienty“
+🪪 25. "I need standard agent discovery for clients"
+
+External clients and orchestrators need machine-readable metadata for onboarding.
+
+**How OmniRoute solves it:**
+
+- Agent Card exposed at `/.well-known/agent.json`
+- Capabilities and skills shown in management UI
+- A2A status API includes discovery metadata for automation
+
-Externí klienti a orchestratoři potřebují pro onboarding strojově čitelná metadata.
-
-**Jak to OmniRoute řeší:**
-
-- Karta agenta je k dispozici v souboru `/.well-known/agent.json`
-- Schopnosti a dovednosti zobrazené v uživatelském rozhraní pro správu
-- API pro stav A2A zahrnuje metadata pro zjišťování pro automatizaci
-
-🧭 26. „Potřebuji v uživatelském rozhraní produktu zjistitelnost protokolu.“
+🧭 26. "I need protocol discoverability in the product UX"
+
+If users cannot discover protocol surfaces, adoption and support quality drop.
+
+**How OmniRoute solves it:**
+
+- Consolidated **Endpoints** page with tabs for Proxy, MCP, A2A, and API Endpoints
+- Inline service status toggles (Online/Offline) for MCP and A2A
+- Links from overview to dedicated management tabs
+
-Pokud uživatelé nemohou objevit protokolové povrchy, kvalita přijetí a podpory klesá.
-
-**Jak to OmniRoute řeší:**
-
-- Stránka Konsolidované **koncové body** s kartami pro koncové body Proxy, MCP, A2A a API
-- Přepínání stavu inline služby (Online/Offline) pro MCP a A2A
-- Odkazy z přehledu na vyhrazené karty pro správu
-
-🧪 27. „Potřebuji komplexní ověření protokolu se skutečnými klienty.“
+🧪 27. "I need end-to-end protocol validation with real clients"
+
+Mock tests are not enough to validate protocol compatibility before release.
+
+**How OmniRoute solves it:**
+
+- E2E suite that boots app and uses real MCP SDK client transport
+- A2A client tests for discovery, send, stream, get, and cancel flows
+- Cross-check assertions against MCP audit and A2A tasks APIs
+
-Simulované testy nestačí k ověření kompatibility protokolu před vydáním.
-
-**Jak to OmniRoute řeší:**
-
-- Sada E2E, která spouští aplikaci a používá skutečný transport klienta MCP SDK.
-- Klientské testy A2A pro toky zjišťování, odesílání, streamování, načítání a zrušení
-- Křížová kontrola tvrzení oproti API pro audit MCP a úkoly A2A
-
-📡 28. „Potřebuji jednotnou pozorovatelnost napříč všemi rozhraními“
+📡 28. "I need unified observability across all interfaces"
+
+Splitting observability by protocol creates blind spots and longer MTTR.
+
+**How OmniRoute solves it:**
+
+- Unified dashboards/logs/analytics in one product
+- Health + audit + request telemetry across OpenAI, MCP, and A2A layers
+- Operational APIs for status and automation
+
-Rozdělení pozorovatelnosti podle protokolu vytváří slepá místa a delší MTTR.
-
-**Jak to OmniRoute řeší:**
-
-- Sjednocené dashboardy/logy/analytiky v jednom produktu
-- Stav + audit + telemetrie požadavků napříč vrstvami OpenAI, MCP a A2A
-- Provozní API pro stav a automatizaci
-
-💼 29. „Potřebuji jeden runtime pro proxy + nástroje + orchestraci agentů“
+💼 29. "I need one runtime for proxy + tools + agent orchestration"
+
+Running many separate services increases operational cost and failure modes.
+
+**How OmniRoute solves it:**
+
+- OpenAI-compatible proxy, MCP server, and A2A server in one stack
+- Shared auth, resilience, data store, and observability
+- Consistent policy model across all interaction surfaces
+
-Spouštění mnoha samostatných služeb zvyšuje provozní náklady a počet poruch.
-
-**Jak to OmniRoute řeší:**
-
-- Proxy, MCP server a A2A server kompatibilní s OpenAI v jednom balíčku
-- Sdílené ověřování, odolnost, úložiště dat a pozorovatelnost
-- Konzistentní model politik napříč všemi interakčními plochami
-
-🚀 30. „Potřebuji agentské pracovní postupy bez slepení kódu.“
+🚀 30. "I need to ship agentic workflows without glue-code sprawl"
+
+Teams lose velocity when stitching multiple ad-hoc services and scripts.
+
+**How OmniRoute solves it:**
+
+- Unified endpoint strategy for clients and agents
+- Built-in protocol management UIs and smoke validation paths
+- Production-ready foundations (security, logging, resilience, backup)
+
-Týmy ztrácejí rychlost při spojování více ad-hoc služeb a skriptů.
+### Example Playbooks (Integrated Use Cases)
-**Jak to OmniRoute řeší:**
-
-- Sjednocená strategie koncových bodů pro klienty a agenty
-- Vestavěná uživatelská rozhraní pro správu protokolů a cesty pro ověřování kouře
-- Základy připravené pro produkční prostředí (zabezpečení, protokolování, odolnost, zálohování)
-
-### Příklady herních plánů (integrované případy užití)
-
-**Příručka A: Maximalizace placeného předplatného + levné zálohování**
+**Playbook A: Maximize paid subscription + cheap backup**
```txt
Combo: "maximize-claude"
@@ -596,7 +720,7 @@ Monthly cost: $20 + small backup spend
Outcome: higher quality, near-zero interruption
```
-**Příručka B: Kódovací stack s nulovými náklady**
+**Playbook B: Zero-cost coding stack**
```txt
Combo: "free-forever"
@@ -608,7 +732,7 @@ Monthly cost: $0
Outcome: stable free coding workflow
```
-**Příručka C: Nonstop záložní řetězec**
+**Playbook C: 24/7 always-on fallback chain**
```txt
Combo: "always-on"
@@ -621,7 +745,7 @@ Combo: "always-on"
Outcome: deep fallback depth for deadline-critical workloads
```
-**Příručka D: Operace agentů s MCP + A2A**
+**Playbook D: Agent ops with MCP + A2A**
```txt
1) Start MCP transport (`omniroute --mcp`) for tool-driven operations
@@ -632,32 +756,32 @@ Outcome: deep fallback depth for deadline-critical workloads
---
-## 🆓 Začněte zdarma — Nulové náklady na konfiguraci
+## 🆓 Start Free — Zero Configuration Cost
-> Nastavte si kódování s umělou inteligencí během několika minut za **0 $/měsíc** . Propojte tyto bezplatné účty a využijte vestavěnou kombinaci **Free Stack** .
+> Setup AI coding in minutes at **$0/month**. Connect these free accounts and use the built-in **Free Stack** combo.
-| Krok | Akce | Poskytovatelé odemčeni |
-| ---- | -------------------------------------------------------------- | ----------------------------------------------------------------- |
-| 1 | Připojení **Kiro** (AWS Builder ID OAuth) | Claude Sonnet 4.5, Haiku 4.5 – **neomezeně** |
-| 2 | Připojení k **Qoder** (Google OAuth) | kimi-k2-myšlení, qwen3-coder-plus, deepseek-r1... — **neomezeně** |
-| 3 | Připojení **Qwen** (kód zařízení) | qwen3-coder-plus, qwen3-coder-flash... — **neomezeně** |
-| 4 | Připojení **rozhraní příkazového řádku Gemini** (Google OAuth) | gemini-3-flash, gemini-2.5-pro — **180 000 GBP/měsíc zdarma** |
-| 5 | `/dashboard/combos` → Šablona **Free Stack (0 $)** | Automatické zařazení všech bezplatných poskytovatelů do routingu |
+| Step | Action | Providers Unlocked |
+| ---- | -------------------------------------------------- | ------------------------------------------------------------------ |
+| 1 | Connect **Kiro** (AWS Builder ID OAuth) | Claude Sonnet 4.5, Haiku 4.5 — **unlimited** |
+| 2 | Connect **Qoder** (Google OAuth) | kimi-k2-thinking, qwen3-coder-plus, deepseek-r1... — **unlimited** |
+| 3 | Connect **Qwen** (Device Code) | qwen3-coder-plus, qwen3-coder-flash... — **unlimited** |
+| 4 | Connect **Gemini CLI** (Google OAuth) | gemini-3-flash, gemini-2.5-pro — **180K/mo free** |
+| 5 | `/dashboard/combos` → **Free Stack ($0)** template | Round-robin all free providers automatically |
-**V libovolném IDE/CLI naveďte:** `http://localhost:20128/v1` · Klíč API: `any-string` · Hotovo.
+**Point any IDE/CLI to:** `http://localhost:20128/v1` · API Key: `any-string` · Done.
-> **Volitelné doplňkové krytí (také zdarma):** Groq API klíč (30 RPM zdarma), NVIDIA NIM (40 RPM zdarma, 70+ modelů), Cerebras (1 milion tok/den).
+> **Optional extra coverage (also free):** Groq API key (30 RPM free), NVIDIA NIM (40 RPM free, 70+ models), Cerebras (1M tok/day), LongCat API key (50M tokens/day!), Cloudflare Workers AI (10K Neurons/day, 50+ models).
-## ⚡ Rychlý start
+## Rychlý start
-### 1) Nainstalujte a spusťte
+### 1) Install and run
```bash
npm install -g omniroute
omniroute
```
-> **Uživatelé pnpm:** Po instalaci spusťte `pnpm approve-builds -g` , abyste povolili nativní skripty pro sestavení vyžadované programy `better-sqlite3` a `@swc/core` :
+> **pnpm users:** Run `pnpm approve-builds -g` after install to enable native build scripts required by `better-sqlite3` and `@swc/core`:
>
> ```bash
> pnpm install -g omniroute
@@ -665,17 +789,17 @@ omniroute
> omniroute
> ```
-Dashboard se otevírá na `http://localhost:20128` a základní URL API je `http://localhost:20128/v1` .
+Dashboard opens at `http://localhost:20128` and API base URL is `http://localhost:20128/v1`.
-| Příkaz | Popis |
-| ----------------------- | ------------------------------------------------------------------- |
-| `omniroute` | Spuštění serveru ( `PORT=20128` , API a dashboard na stejném portu) |
-| `omniroute --port 3000` | Nastavte kanonický/API port na 3000 |
-| `omniroute --mcp` | Spuštění MCP serveru (transport stdio) |
-| `omniroute --no-open` | Neotevírat prohlížeč automaticky |
-| `omniroute --help` | Zobrazit nápovědu |
+| Command | Description |
+| ----------------------- | ----------------------------------------------------------- |
+| `omniroute` | Start server (`PORT=20128`, API and dashboard on same port) |
+| `omniroute --port 3000` | Set canonical/API port to 3000 |
+| `omniroute --mcp` | Start MCP server (stdio transport) |
+| `omniroute --no-open` | Don't auto-open browser |
+| `omniroute --help` | Show help |
-Volitelný režim s rozděleným portem:
+Optional split-port mode:
```bash
PORT=20128 DASHBOARD_PORT=20129 omniroute
@@ -683,13 +807,13 @@ PORT=20128 DASHBOARD_PORT=20129 omniroute
# Dashboard: http://localhost:20129
```
-### 2) Připojte poskytovatele a vytvořte si klíč API
+### 2) Connect providers and create your API key
-1. Otevřete Dashboard → `Providers` a připojte alespoň jednoho poskytovatele (klíč OAuth nebo API).
-2. Otevřete Dashboard → `Endpoints` a vytvořte API klíč.
-3. (Volitelné) Otevřete Dashboard → `Combos` a nastavte záložní řetězec.
+1. Open Dashboard → `Providers` and connect at least one provider (OAuth or API key).
+2. Open Dashboard → `Endpoints` and create an API key.
+3. (Optional) Open Dashboard → `Combos` and set your fallback chain.
-### 3) Nasměrujte svůj kódovací nástroj na OmniRoute
+### 3) Point your coding tool to OmniRoute
```txt
Base URL: http://localhost:20128/v1
@@ -697,22 +821,22 @@ API Key: [copy from Endpoint page]
Model: if/kimi-k2-thinking (or any provider/model prefix)
```
-Funguje s Claude Code, Codex CLI, Gemini CLI, Cursor, Cline, OpenClaw, OpenCode a SDK kompatibilními s OpenAI.
+Works with Claude Code, Codex CLI, Gemini CLI, Cursor, Cline, OpenClaw, OpenCode, and OpenAI-compatible SDKs.
-### 4) Povolení a ověření protokolů (v2.0)
+### 4) Enable and validate protocols (v2.0)
-**MCP (pro operace řízené nástroji):**
+**MCP (for tool-driven operations):**
```bash
omniroute --mcp
```
-Pak připojte svého MCP klienta přes `stdio` a otestujte nástroje jako:
+Then connect your MCP client over `stdio` and test tools like:
- `omniroute_get_health`
- `omniroute_list_combos`
-**A2A (pro pracovní postupy mezi agenty):**
+**A2A (for agent-to-agent workflows):**
```bash
curl http://localhost:20128/.well-known/agent.json
@@ -724,15 +848,15 @@ curl -X POST http://localhost:20128/a2a \
-d '{"jsonrpc":"2.0","id":"quickstart","method":"message/send","params":{"skill":"quota-management","messages":[{"role":"user","content":"Give me a short quota summary."}]}}'
```
-### 5) Ověřte vše od začátku do konce (doporučeno)
+### 5) Validate everything end-to-end (recommended)
```bash
npm run test:protocols:e2e
```
-Tato sada ověřuje skutečné toky klientů MCP a A2A v porovnání se spuštěnou aplikací.
+This suite validates real MCP and A2A client flows against a running app.
-### Alternativa: spustit ze zdroje
+### Alternative: run from source
```bash
cp .env.example .env
@@ -740,13 +864,120 @@ npm install
PORT=20128 DASHBOARD_PORT=20129 NEXT_PUBLIC_BASE_URL=http://localhost:20129 npm run dev
```
+
+Void Linux (`xbps-src` template)
+
+For Void Linux users, you can build a native package using `xbps-src`. Save this block as `srcpkgs/omniroute/template`:
+
+```bash
+# Template file for 'omniroute'
+pkgname=omniroute
+version=3.4.1
+revision=1
+hostmakedepends="nodejs python3 make"
+depends="openssl"
+short_desc="Universal AI gateway with smart routing for multiple LLM providers"
+maintainer="zenobit "
+license="MIT"
+homepage="https://github.com/diegosouzapw/OmniRoute"
+distfiles="https://github.com/diegosouzapw/OmniRoute/archive/refs/tags/v${version}.tar.gz"
+checksum=009400afee90a9f32599d8fe734145cfd84098140b7287990183dde45ae2245b
+system_accounts="_omniroute"
+omniroute_homedir="/var/lib/omniroute"
+export NODE_ENV=production
+export npm_config_engine_strict=false
+export npm_config_loglevel=error
+export npm_config_fund=false
+export npm_config_audit=false
+
+do_build() {
+ # Determine target CPU arch for node-gyp
+ local _gyp_arch
+ case "$XBPS_TARGET_MACHINE" in
+ aarch64*) _gyp_arch=arm64 ;;
+ armv7*|armv6*) _gyp_arch=arm ;;
+ i686*) _gyp_arch=ia32 ;;
+ *) _gyp_arch=x64 ;;
+ esac
+
+ # 1) Install all deps – skip scripts (no network in do_build, native modules
+ # compiled separately below; better-sqlite3 is serverExternalPackage so
+ # Next.js does not execute it during next build)
+ NODE_ENV=development npm ci --ignore-scripts
+
+ # 2) Build the Next.js standalone bundle
+ npm run build
+
+ # 3) Copy static assets into standalone
+ cp -r .next/static .next/standalone/.next/static
+ [ -d public ] && cp -r public .next/standalone/public || true
+
+ # 4) Compile better-sqlite3 native binding for the target architecture.
+ # Use node-gyp directly so CC/CXX from xbps-src cross-toolchain are used
+ # without npm altering them.
+ local _node_gyp=/usr/lib/node_modules/npm/node_modules/node-gyp/bin/node-gyp.js
+ (cd node_modules/better-sqlite3 && node "$_node_gyp" rebuild --arch="$_gyp_arch")
+
+ # 5) Place the compiled binding into the standalone bundle
+ local _bs3_release=.next/standalone/node_modules/better-sqlite3/build/Release
+ mkdir -p "$_bs3_release"
+ cp node_modules/better-sqlite3/build/Release/better_sqlite3.node "$_bs3_release/"
+
+ # 6) Remove arch-specific sharp bundles – upstream sets images.unoptimized=true
+ # so sharp is not used at runtime; x64 .so files would break aarch64 strip
+ rm -rf .next/standalone/node_modules/@img
+
+ # 7) Copy pino runtime deps omitted by Next.js static analysis:
+ # pino-abstract-transport – required by pino's worker thread
+ # split2 – dep of pino-abstract-transport
+ # process-warning – dep of pino itself
+ for _mod in pino-abstract-transport split2 process-warning; do
+ cp -r "node_modules/$_mod" .next/standalone/node_modules/
+ done
+}
+
+do_check() {
+ npm run test:unit
+}
+
+do_install() {
+ vmkdir usr/lib/omniroute/.next
+
+ vcopy .next/standalone/. usr/lib/omniroute/.next/standalone
+
+ # Prevent removal of empty Next.js app router dirs by the post-install hook
+ for _d in \
+ .next/standalone/.next/server/app/dashboard \
+ .next/standalone/.next/server/app/dashboard/settings \
+ .next/standalone/.next/server/app/dashboard/providers; do
+ touch "${DESTDIR}/usr/lib/omniroute/${_d}/.keep"
+ done
+
+ cat > "${WRKDIR}/omniroute" <<'EOF'
+#!/bin/sh
+export PORT="${PORT:-20128}"
+export DATA_DIR="${DATA_DIR:-${XDG_DATA_HOME:-${HOME}/.local/share}/omniroute}"
+export LOG_TO_FILE="${LOG_TO_FILE:-false}"
+mkdir -p "${DATA_DIR}"
+exec node /usr/lib/omniroute/.next/standalone/server.js "$@"
+EOF
+ vbin "${WRKDIR}/omniroute"
+}
+
+post_install() {
+ vlicense LICENSE
+}
+```
+
+
+
---
## 🐳 Docker
-OmniRoute je k dispozici jako veřejný obraz Dockeru na [Docker Hubu](https://hub.docker.com/r/diegosouzapw/omniroute) .
+OmniRoute is available as a public Docker image on [Docker Hub](https://hub.docker.com/r/diegosouzapw/omniroute).
-**Rychlý běh:**
+**Quick run:**
```bash
docker run -d \
@@ -757,7 +988,7 @@ docker run -d \
diegosouzapw/omniroute:latest
```
-**Se souborem prostředí:**
+**With environment file:**
```bash
# Copy and edit .env first
@@ -772,7 +1003,7 @@ docker run -d \
diegosouzapw/omniroute:latest
```
-**Používání Docker Compose:**
+**Using Docker Compose:**
```bash
# Base profile (no CLI tools)
@@ -782,24 +1013,62 @@ docker compose --profile base up -d
docker compose --profile cli up -d
```
-| Obraz | Štítek | Velikost | Popis |
-| ------------------------ | -------- | -------- | ------------------------- |
-| `diegosouzapw/omniroute` | `latest` | ~250 MB | Nejnovější stabilní verze |
-| `diegosouzapw/omniroute` | `1.0.3` | ~250 MB | Aktuální verze |
+Dashboard support for Docker deployments now includes a one-click **Cloudflare Quick Tunnel** on `Dashboard → Endpoints`. The first enable downloads `cloudflared` only when needed, starts a temporary tunnel to your current `/v1` endpoint, and shows the generated `https://*.trycloudflare.com/v1` URL directly below your normal public URL.
+
+Notes:
+
+- Quick Tunnel URLs are temporary and change after every restart.
+- Managed install currently supports Linux, macOS, and Windows on `x64` / `arm64`.
+- Docker images bundle system CA roots and pass them to managed `cloudflared`, which avoids TLS trust failures when the tunnel bootstraps inside the container.
+- Set `CLOUDFLARED_BIN=/absolute/path/to/cloudflared` if you want OmniRoute to use an existing binary instead of downloading one.
+
+**Using Docker Compose with Caddy (HTTPS Auto-TLS):**
+
+OmniRoute can be securely exposed using Caddy's automatic SSL provisioning. Ensure your domain's DNS A record points to your server's IP.
+
+```yaml
+services:
+ omniroute:
+ image: diegosouzapw/omniroute:latest
+ container_name: omniroute
+ restart: unless-stopped
+ volumes:
+ - omniroute-data:/app/data
+ environment:
+ - PORT=20128
+ - NEXT_PUBLIC_BASE_URL=https://your-domain.com
+
+ caddy:
+ image: caddy:latest
+ container_name: caddy
+ restart: unless-stopped
+ ports:
+ - "80:80"
+ - "443:443"
+ command: caddy reverse-proxy --from https://your-domain.com --to http://omniroute:20128
+
+volumes:
+ omniroute-data:
+```
+
+| Image | Tag | Size | Description |
+| ------------------------ | -------- | ------ | --------------------- |
+| `diegosouzapw/omniroute` | `latest` | ~250MB | Latest stable release |
+| `diegosouzapw/omniroute` | `1.0.3` | ~250MB | Current version |
---
-## 🖥️ Desktopová aplikace – offline a vždy zapnutá
+## 🖥️ Desktop App — Offline & Always-On
-> 🆕 **NOVINKA!** OmniRoute je nyní k dispozici jako **nativní desktopová aplikace** pro Windows, macOS a Linux.
+> 🆕 **NEW!** OmniRoute is now available as a **native desktop application** for Windows, macOS, and Linux.
-Spusťte OmniRoute jako samostatnou desktopovou aplikaci – pro lokální modely není potřeba žádný terminál, prohlížeč ani internet. Aplikace založená na platformě Electron obsahuje:
+Run OmniRoute as a standalone desktop app — no terminal, no browser, no internet required for local models. The Electron-based app includes:
-- 🖥️ **Nativní okno** — Vyhrazené okno aplikace s integrací do systémové lišty
-- 🔄 **Automatické spuštění** — Spuštění OmniRoute po přihlášení do systému
-- 🔔 **Nativní oznámení** – Získejte upozornění na vyčerpání kvóty nebo problémy s poskytovateli
-- ⚡ **Instalace jedním kliknutím** — NSIS (Windows), DMG (macOS), AppImage (Linux)
-- 🌐 **Offline režim** — Funguje plně offline s přiloženým serverem
+- 🖥️ **Native Window** — Dedicated app window with system tray integration
+- 🔄 **Auto-Start** — Launch OmniRoute on system login
+- 🔔 **Native Notifications** — Get alerts for quota exhaustion or provider issues
+- ⚡ **One-Click Install** — NSIS (Windows), DMG (macOS), AppImage (Linux)
+- 🌐 **Offline Mode** — Works fully offline with bundled server
### Rychlý start
@@ -814,47 +1083,51 @@ npm run electron:build:mac # macOS (.dmg) — x64 & arm64
npm run electron:build:linux # Linux (.AppImage)
```
-### Systémový zásobník
+### System Tray
-Po minimalizaci se OmniRoute nachází v systémové liště a nabízí rychlé akce:
+When minimized, OmniRoute lives in your system tray with quick actions:
-- Otevřít řídicí panel
-- Změnit port serveru
-- Ukončit aplikaci
+- Open dashboard
+- Change server port
+- Quit application
-📖 Úplná dokumentace: [`electron/README.md`](electron/README.md)
+📖 Full documentation: [`electron/README.md`](electron/README.md)
---
-## 💰 Přehled cen
+## 💰 Pricing at a Glance
-| Úroveň | Poskytovatel | Náklady | Obnovení kvóty | Nejlepší pro |
-| --------------------------- | -------------------------------- | ------------------------------------ | ------------------------------------------ | --------------------------------------------------------- |
-| **💳 PŘEDPLATNÉ** | Claude Code (profesionál) | 20 dolarů měsíčně | 5 hodin + týdně | Již přihlášen/a k odběru |
-| Kodex (Plus/Pro) | 20–200 USD/měsíc | 5 hodin + týdně | Uživatelé OpenAI |
-| Gemini CLI | **UVOLNIT** | 180 tisíc měsíčně + 1 tisíc denně | Každý! |
-| GitHub Copilot | 10–19 USD/měsíc | Měsíční | Uživatelé GitHubu |
-| **🔑 KLÍČ API** | NVIDIA NIM | **ZDARMA** (vývoj navždy) | ~40 ot./min | 70+ otevřených modelů |
-| Mozky | **ZDARMA** (1 milion tok/den) | 60 000 otáček za minutu / 30 ot./min | Nejrychlejší na světě |
-| Groq | **ZDARMA** (30 ot./min.) | 14,4 tisíc otáček za minutu | Ultrarychlá lama/gema |
-| DeepSeek V3.2 | 0,27/1,10 USD za 1 milion | Žádný | Nejlepší zdůvodnění ceny a kvality |
-| xAI Grok-4 Rychlý | **0,20/0,50 USD za 1 milion** 🆕 | Žádný | Nejrychlejší + volání nástroje, ultranízké |
-| xAI Grok-4 (standardní) | 0,20/1,50 USD za 1 milion 🆕 | Žádný | Vlajková loď Reasoning od xAI |
-| Mistral | Zkušební verze zdarma + placené | Omezená sazba | Evropská umělá inteligence |
-| OpenRouter | Platba za použití | Žádný | Více než 100 modelů agregováno. |
-| **💰 LEVNÉ** | GLM-5 (přes Z.AI) 🆕 | 0,5 USD/1 milion | Denně v 10:00 | Výstup 128 tisíc obrazových bodů, nejnovější vlajková loď |
-| GLM-4.7 | 0,6 USD/1 milion | Denně v 10:00 | Záloha rozpočtu |
-| MiniMax M2.5 🆕 | Vstup 0,3 USD/1 milion | 5hodinové válcování | Úvaha + agentní úkoly |
-| MiniMax M2.1 | 0,2 USD/1 milion | 5hodinové válcování | Nejlevnější varianta |
-| Kimi K2.5 (Moonshot API) 🆕 | Platba za použití | Žádný | Přímý přístup k Moonshot API |
-| Kimi K2 | 9 dolarů měsíčně bez závazků | 10 milionů tokenů/měsíc | Předvídatelné náklady |
-| **🆓 ZDARMA** | Qoder | **0 dolarů** | Neomezený | 5 modelů neomezeně |
-| Qwen | **0 dolarů** | Neomezený | 4 modely neomezeně |
-| Kiro | **0 dolarů** | Neomezený | Claude Sonnet/Haiku (tvorce AWS) |
+| Tier | Provider | Cost | Quota Reset | Best For |
+| ------------------- | --------------------------- | ------------------------- | ---------------- | --------------------------------- |
+| **💳 SUBSCRIPTION** | Claude Code (Pro) | $20/mo | 5h + weekly | Already subscribed |
+| | Codex (Plus/Pro) | $20-200/mo | 5h + weekly | OpenAI users |
+| | Gemini CLI | **FREE** | 180K/mo + 1K/day | Everyone! |
+| | GitHub Copilot | $10-19/mo | Monthly | GitHub users |
+| **🔑 API KEY** | NVIDIA NIM | **FREE** (dev forever) | ~40 RPM | 70+ open models |
+| | Cerebras | **FREE** (1M tok/day) | 60K TPM / 30 RPM | World's fastest |
+| | Groq | **FREE** (30 RPM) | 14.4K RPD | Ultra-fast Llama/Gemma |
+| | DeepSeek V3.2 | $0.27/$1.10 per 1M | None | Best price/quality reasoning |
+| | xAI Grok-4 Fast | **$0.20/$0.50 per 1M** 🆕 | None | Fastest + tool calling, ultralow |
+| | xAI Grok-4 (standard) | $0.20/$1.50 per 1M 🆕 | None | Reasoning flagship from xAI |
+| | Mistral | Free trial + paid | Rate limited | European AI |
+| | OpenRouter | Pay-per-use | None | 100+ models aggr. |
+| **💰 CHEAP** | GLM-5 (via Z.AI) 🆕 | $0.5/1M | Daily 10AM | 128K output, newest flagship |
+| | GLM-4.7 | $0.6/1M | Daily 10AM | Budget backup |
+| | MiniMax M2.5 🆕 | $0.3/1M input | 5-hour rolling | Reasoning + agentic tasks |
+| | MiniMax M2.1 | $0.2/1M | 5-hour rolling | Cheapest option |
+| | Kimi K2.5 (Moonshot API) 🆕 | Pay-per-use | None | Direct Moonshot API access |
+| | Kimi K2 | $9/mo flat | 10M tokens/mo | Predictable cost |
+| **🆓 FREE** | Qoder | **$0** | Unlimited | 5 models unlimited |
+| | Qwen | **$0** | Unlimited | 4 models unlimited |
+| | Kiro | **$0** | Unlimited | Claude Sonnet/Haiku (AWS Builder) |
+| | LongCat Flash-Lite 🆕 | **$0** (50M tok/day 🔥) | 1 RPS | Largest free quota on Earth |
+| | Pollinations AI 🆕 | **$0** (no key needed) | 1 req/15s | GPT-5, Claude, DeepSeek, Llama 4 |
+| | Cloudflare Workers AI 🆕 | **$0** (10K Neurons/day) | ~150 resp/day | 50+ models, global edge |
+| | Scaleway AI 🆕 | **$0** (1M tokens total) | Rate limited | EU/GDPR, Qwen3 235B, Llama 70B |
-> 🆕 **Přidány nové modely (březen 2026):** řada Grok-4 Fast za 0,20 USD/0,50 USD/M (benchmarkováno na 1143 ms – o 30 % rychlejší než Gemini 2.5 Flash), GLM-5 přes Z.AI s výstupem 128K, uvažování MiniMax M2.5, aktualizované ceny DeepSeek V3.2, Kimi K2.5 přes Moonshot Direct API.
+> 🆕 **New models added (Mar 2026):** Grok-4 Fast family at $0.20/$0.50/M (benchmarked at 1143ms — 30% faster than Gemini 2.5 Flash), GLM-5 via Z.AI with 128K output, MiniMax M2.5 reasoning, DeepSeek V3.2 updated pricing, Kimi K2.5 via Moonshot direct API.
-**💡 Kombinovaný balík za 0 $ — Kompletní bezplatná instalace:**
+**💡 $0 Combo Stack — The Complete Free Setup:**
```
# 🆓 Ultimate Free Stack 2026 — 11 Providers, $0 Forever
@@ -871,99 +1144,146 @@ NVIDIA NIM (nvidia/) → 70+ open models — 40 RPM forever
Cerebras (cerebras/) → Llama/Qwen world-fastest — 1M tok/day
```
-**Nulové náklady. Nikdy nepřestávejte s kódováním.** Nakonfigurujte si to jako jednu kombinaci OmniRoute a všechny záložní režimy se provede automaticky – žádné ruční přepínání.
+**Zero cost. Never stops coding.** Configure this as one OmniRoute combo and all fallbacks happen automatically — no manual switching ever.
---
---
-## 🆓 Bezplatné modely – Co skutečně získáte
+## 🆓 Free Models — What You Actually Get
-> Všechny níže uvedené modely jsou **100% zdarma a nevyžadují žádnou kreditní kartu** . OmniRoute mezi nimi automaticky propojí trasy, když dojde jedna kvóta – zkombinujte je všechny a získejte tak nerozlučnou kombinaci za 0 dolarů.
+> All models below are **100% free with zero credit card required**. OmniRoute auto-routes between them when one quota runs out — combine them all for an unbreakable $0 combo.
-### 🔵 CLAUDE MODELS (přes Kiro — AWS Builder ID)
+### 🔵 CLAUDE MODELS (via Kiro — AWS Builder ID)
-| Model | Předpona | Omezit | Limit rychlosti |
-| ------------------- | -------- | ------------- | ------------------------- |
-| `claude-sonnet-4.5` | `kr/` | **Neomezený** | Žádný hlášený denní limit |
-| `claude-haiku-4.5` | `kr/` | **Neomezený** | Žádný hlášený denní limit |
-| `claude-opus-4.6` | `kr/` | **Neomezený** | Nejnovější opus od Kira |
+| Model | Prefix | Limit | Rate Limit |
+| ------------------- | ------ | ------------- | --------------------- |
+| `claude-sonnet-4.5` | `kr/` | **Unlimited** | No reported daily cap |
+| `claude-haiku-4.5` | `kr/` | **Unlimited** | No reported daily cap |
+| `claude-opus-4.6` | `kr/` | **Unlimited** | Latest Opus via Kiro |
-### 🟢 MODELY QODER (Bezplatné OAuth — bez nutnosti platit kreditní kartou)
+### 🟢 QODER MODELS (Free OAuth — No Credit Card)
-| Model | Předpona | Omezit | Limit rychlosti |
-| ------------------ | -------- | ------------- | ------------------- |
-| `kimi-k2-thinking` | `if/` | **Neomezený** | Žádný hlášený strop |
-| `qwen3-coder-plus` | `if/` | **Neomezený** | Žádný hlášený strop |
-| `deepseek-r1` | `if/` | **Neomezený** | Žádný hlášený strop |
-| `minimax-m2.1` | `if/` | **Neomezený** | Žádný hlášený strop |
-| `kimi-k2` | `if/` | **Neomezený** | Žádný hlášený strop |
+| Model | Prefix | Limit | Rate Limit |
+| ------------------ | ------ | ------------- | --------------- |
+| `kimi-k2-thinking` | `if/` | **Unlimited** | No reported cap |
+| `qwen3-coder-plus` | `if/` | **Unlimited** | No reported cap |
+| `deepseek-r1` | `if/` | **Unlimited** | No reported cap |
+| `minimax-m2.1` | `if/` | **Unlimited** | No reported cap |
+| `kimi-k2` | `if/` | **Unlimited** | No reported cap |
-### 🟡 MODELY QWEN (Ověření kódu zařízení)
+### 🟡 QWEN MODELS (Device Code Auth)
-| Model | Předpona | Omezit | Limit rychlosti |
-| ------------------- | -------- | ------------- | ---------------------- |
-| `qwen3-coder-plus` | `qw/` | **Neomezený** | Žádný hlášený strop |
-| `qwen3-coder-flash` | `qw/` | **Neomezený** | Žádný hlášený strop |
-| `qwen3-coder-next` | `qw/` | **Neomezený** | Žádný hlášený strop |
-| `vision-model` | `qw/` | **Neomezený** | Multimodální (obrázky) |
+| Model | Prefix | Limit | Rate Limit |
+| ------------------- | ------ | ------------- | ------------------- |
+| `qwen3-coder-plus` | `qw/` | **Unlimited** | No reported cap |
+| `qwen3-coder-flash` | `qw/` | **Unlimited** | No reported cap |
+| `qwen3-coder-next` | `qw/` | **Unlimited** | No reported cap |
+| `vision-model` | `qw/` | **Unlimited** | Multimodal (images) |
-### 🟣 Rozhraní GEMINI CLI (Google OAuth)
+### 🟣 GEMINI CLI (Google OAuth)
-| Model | Předpona | Omezit | Limit rychlosti |
-| ------------------------ | -------- | ------------------------------------- | --------------- |
-| `gemini-3-flash-preview` | `gc/` | **180 tisíc tok/měsíc** + 1 tisíc/den | Měsíční reset |
-| `gemini-2.5-pro` | `gc/` | 180 tisíc měsíčně (sdílený bazén) | Vysoká kvalita |
+| Model | Prefix | Limit | Rate Limit |
+| ------------------------ | ------ | --------------------------- | ------------- |
+| `gemini-3-flash-preview` | `gc/` | **180K tok/month** + 1K/day | Monthly reset |
+| `gemini-2.5-pro` | `gc/` | 180K/month (shared pool) | High quality |
-### ⚫ NVIDIA NIM (Bezplatný klíč API — build.nvidia.com)
+### ⚫ NVIDIA NIM (Free API Key — build.nvidia.com)
-| Úroveň | Denní limit | Limit rychlosti | Poznámky |
-| ---------------- | ------------------ | --------------- | ---------------------------------------------------------------------- |
-| Zdarma (vývojář) | Žádný limit tokenů | **~40 ot./min** | Více než 70 modelů; přechod na čisté limity sazeb v polovině roku 2025 |
+| Tier | Daily Limit | Rate Limit | Notes |
+| ---------- | ------------ | ----------- | ------------------------------------------------------ |
+| Free (Dev) | No token cap | **~40 RPM** | 70+ models; transitioning to pure rate limits mid-2025 |
-Oblíbené bezplatné modely: `moonshotai/kimi-k2.5` (Kimi K2.5), `z-ai/glm4.7` (GLM 4.7), `deepseek-ai/deepseek-v3.2` (DeepSeek V3.2), `nvidia/llama-3.3-70b-instruct` , `deepseek/deepseek-r1`
+Popular free models: `moonshotai/kimi-k2.5` (Kimi K2.5), `z-ai/glm4.7` (GLM 4.7), `deepseek-ai/deepseek-v3.2` (DeepSeek V3.2), `nvidia/llama-3.3-70b-instruct`, `deepseek/deepseek-r1`
-### ⚪ CEREBRAS (Bezplatný klíč API — inference.cerebras.ai)
+### ⚪ CEREBRAS (Free API Key — inference.cerebras.ai)
-| Úroveň | Denní limit | Limit rychlosti | Poznámky |
-| ------- | ----------------------- | ------------------------------------ | ------------------------------------------------------ |
-| Uvolnit | **1 milion tokenů/den** | 60 000 otáček za minutu / 30 ot./min | Nejrychlejší inference LLM na světě; denně se resetuje |
+| Tier | Daily Limit | Rate Limit | Notes |
+| ---- | ----------------- | ---------------- | ------------------------------------------- |
+| Free | **1M tokens/day** | 60K TPM / 30 RPM | World's fastest LLM inference; resets daily |
-Dostupné zdarma: `llama-3.3-70b` , `llama-3.1-8b` , `deepseek-r1-distill-llama-70b`
+Available free: `llama-3.3-70b`, `llama-3.1-8b`, `deepseek-r1-distill-llama-70b`
-### 🔴 GROQ (Bezplatný API klíč — console.groq.com)
+### 🔴 GROQ (Free API Key — console.groq.com)
-| Úroveň | Denní limit | Limit rychlosti | Poznámky |
-| ------- | ------------------------------- | ------------------- | ------------------------------------------- |
-| Uvolnit | **14,4 tisíc otáček za minutu** | 30 ot./min na model | Žádná kreditní karta; limit 429, neúčtováno |
+| Tier | Daily Limit | Rate Limit | Notes |
+| ---- | ------------- | ---------------- | ----------------------------------------- |
+| Free | **14.4K RPD** | 30 RPM per model | No credit card; 429 on limit, not charged |
-K dispozici zdarma: `llama-3.3-70b-versatile` , `gemma2-9b-it` , `mixtral-8x7b` , `whisper-large-v3`
+Available free: `llama-3.3-70b-versatile`, `gemma2-9b-it`, `mixtral-8x7b`, `whisper-large-v3`
-> **💡 Ultimátní bezplatný zásobník:**
+### 🔴 LONGCAT AI (Free API Key — longcat.chat) 🆕
+
+| Model | Prefix | Daily Free Quota | Notes |
+| ----------------------------- | ------ | ----------------- | ----------------------- |
+| `LongCat-Flash-Lite` | `lc/` | **50M tokens** 💥 | Largest free quota ever |
+| `LongCat-Flash-Chat` | `lc/` | 500K tokens | Multi-turn chat |
+| `LongCat-Flash-Thinking` | `lc/` | 500K tokens | Reasoning / CoT |
+| `LongCat-Flash-Thinking-2601` | `lc/` | 500K tokens | Jan 2026 version |
+| `LongCat-Flash-Omni-2603` | `lc/` | 500K tokens | Multimodal |
+
+> 100% free while in public beta. Sign up at [longcat.chat](https://longcat.chat) with email or phone. Resets daily 00:00 UTC.
+
+### 🟢 POLLINATIONS AI (No API Key Required) 🆕
+
+| Model | Prefix | Rate Limit | Provider Behind |
+| ---------- | ------ | ---------- | ------------------ |
+| `openai` | `pol/` | 1 req/15s | GPT-5 |
+| `claude` | `pol/` | 1 req/15s | Anthropic Claude |
+| `gemini` | `pol/` | 1 req/15s | Google Gemini |
+| `deepseek` | `pol/` | 1 req/15s | DeepSeek V3 |
+| `llama` | `pol/` | 1 req/15s | Meta Llama 4 Scout |
+| `mistral` | `pol/` | 1 req/15s | Mistral AI |
+
+> ✨ **Zero friction:** No signup, no API key. Add the Pollinations provider with an empty key field and it works immediately.
+
+### 🟠 CLOUDFLARE WORKERS AI (Free API Key — cloudflare.com) 🆕
+
+| Tier | Daily Neurons | Equivalent Usage | Notes |
+| ---- | ------------- | --------------------------------------- | ----------------------- |
+| Free | **10,000** | ~150 LLM resp / 500s audio / 15K embeds | Global edge, 50+ models |
+
+Popular free models: `@cf/meta/llama-3.3-70b-instruct`, `@cf/google/gemma-3-12b-it`, `@cf/openai/whisper-large-v3-turbo` (free audio!), `@cf/qwen/qwen2.5-coder-15b-instruct`
+
+> Requires API Token + Account ID from [dash.cloudflare.com](https://dash.cloudflare.com). Store Account ID in provider settings.
+
+### 🟣 SCALEWAY AI (1M Free Tokens — scaleway.com) 🆕
+
+| Tier | Free Quota | Location | Notes |
+| ---- | ------------- | ------------ | ----------------------------------- |
+| Free | **1M tokens** | 🇫🇷 Paris, EU | No credit card needed within limits |
+
+Available free: `qwen3-235b-a22b-instruct-2507` (Qwen3 235B!), `llama-3.1-70b-instruct`, `mistral-small-3.2-24b-instruct-2506`, `deepseek-v3-0324`
+
+> EU/GDPR compliant. Get API key at [console.scaleway.com](https://console.scaleway.com).
+
+> **💡 The Ultimate Free Stack (11 Providers, $0 Forever):**
>
> ```
-> Kiro (Claude, unlimited)
-> → Qoder (5 models, unlimited)
-> → Qwen (4 models, unlimited)
-> → Gemini CLI (180K/mo)
-> → Cerebras (1M tok/day)
-> → Groq (14.4K req/day)
-> → NVIDIA NIM (40 RPM, 70+ models)
+> Kiro (kr/) → Claude Sonnet/Haiku UNLIMITED
+> Qoder (if/) → kimi-k2-thinking, qwen3-coder-plus, deepseek-r1 UNLIMITED
+> LongCat Lite (lc/) → LongCat-Flash-Lite — 50M tokens/day 🔥
+> Pollinations (pol/) → GPT-5, Claude, DeepSeek, Llama 4 — no key needed
+> Qwen (qw/) → qwen3-coder models UNLIMITED
+> Gemini (gemini/) → Gemini 2.5 Flash — 1,500 req/day free
+> Cloudflare AI (cf/) → 50+ models — 10K Neurons/day
+> Scaleway (scw/) → Qwen3 235B, Llama 70B — 1M free tokens (EU)
+> Groq (groq/) → Llama/Gemma — 14.4K req/day ultra-fast
+> NVIDIA NIM (nvidia/) → 70+ open models — 40 RPM forever
+> Cerebras (cerebras/) → Llama/Qwen world-fastest — 1M tok/day
> ```
->
-> Nakonfigurujte si to jako kombinaci OmniRoute a už nikdy nebudete platit za umělou inteligenci.
-## 🎙️ Kombinovaná transkripce zdarma
+## 🎙️ Free Transcription Combo
-> Přepisujte libovolné audio/video za **0 $** – Deepgram leady za 200 $ zdarma, AssemblyAI za 50 $ jako záložní nástroj, Groq Whisper jako neomezená nouzová záloha.
+> Transcribe any audio/video for **$0** — Deepgram leads with $200 free, AssemblyAI $50 fallback, Groq Whisper as unlimited emergency backup.
-| Poskytovatel | Bezplatné kredity | Nejlepší model | Limit rychlosti |
-| ----------------- | ---------------------------------- | ----------------------------------------------------- | ---------------------------------- |
-| 🟢 **Deepgram** | **200 dolarů zdarma** (registrace) | `nova-3` — nejvyšší přesnost, více než 30 jazyků | Žádný limit RPM pro kredity zdarma |
-| 🔵 **AssemblyAI** | **50 dolarů zdarma** (registrace) | `universal-3-pro` — kapitoly, sentiment, osobní údaje | Žádný limit RPM pro kredity zdarma |
-| 🔴 **Groq** | **Navždy zdarma** | `whisper-large-v3` — OpenAI Šepot | 30 ot./min (omezená rychlost) |
+| Provider | Free Credits | Best Model | Rate Limit |
+| ----------------- | ---------------------- | -------------------------------------------- | ---------------------------- |
+| 🟢 **Deepgram** | **$200 free** (signup) | `nova-3` — best accuracy, 30+ languages | No RPM limit on free credits |
+| 🔵 **AssemblyAI** | **$50 free** (signup) | `universal-3-pro` — chapters, sentiment, PII | No RPM limit on free credits |
+| 🔴 **Groq** | **Free forever** | `whisper-large-v3` — OpenAI Whisper | 30 RPM (rate limited) |
-**Navrhovaná kombinace v `/dashboard/combos` :**
+**Suggested combo in `/dashboard/combos`:**
```
Name: free-transcription
@@ -974,109 +1294,145 @@ Nodes:
[3] groq/whisper-large-v3 → free forever, emergency fallback
```
-Pak v `/dashboard/media` → záložka **Přepis** : nahrajte libovolný zvukový nebo video soubor → vyberte kombinovaný koncový bod → získejte přepis v podporovaných formátech.
+Then in `/dashboard/media` → **Transcription** tab: upload any audio or video file → select your combo endpoint → get transcription in supported formats.
-## 💡 Klíčové vlastnosti
+## 💡 Key Features
-OmniRoute v2.0 je navržen jako operační platforma, nikoli pouze jako proxy pro relé.
+OmniRoute v2.0 is built as an operational platform, not just a relay proxy.
-### 🤖 Operace s agenty a protokoly (v2.0)
+### 🆕 New — ClawRouter-Inspired Improvements (Mar 2026)
-| Funkce | Co to dělá |
-| --------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------- |
-| 🔧 **MCP Server (16 nástrojů)** | Nástroje IDE/agent prostřednictvím 3 transportů: stdio, SSE ( `/api/mcp/sse` ), Streamovatelný HTTP ( `/api/mcp/stream` ) |
-| 🤝 **A2A server (JSON-RPC + SSE)** | Spouštění úloh mezi agenty se synchronizací a streamováním |
-| 🧭 **Konsolidovaná stránka koncových bodů** | Stránka pro správu s kartami Endpoint Proxy, MCP, A2A a API Endpoints |
-| 🎚️ **Přepínače pro povolení/zakázání služby** | Přepínače ZAP/VYP pro MCP a A2A s trvalým nastavením (výchozí: VYP) |
-| 🛰️ **Srdeční tep za běhu MCP** | Skutečný stav procesu (pid, doba provozuschopnosti, stáří heartbeatu, transport, režim rozsahu) |
-| 📋 **Auditní záznam MCP** | Filtrovatelné protokoly auditu s hodnocením úspěchu/neúspěchu a klíčovým přiřazením |
-| 🔐 **Vynucování rozsahu MCP** | 9 podrobných oprávnění pro řízený přístup k nástrojům |
-| 📡 **Správa životního cyklu úkolů A2A** | Seznam/filtrování úloh, kontrola událostí/artefaktů, zrušení spuštěných úloh |
-| 📋 **Objevení karty agenta** | `/.well-known/agent.json` pro automatické vyhledávání klientů |
-| 🧪 **Testovací postroj Protocol E2E** | Skutečné MCP SDK + toky klientů A2A v `test:protocols:e2e` |
-| ⚙️ **Provozní kontroly** | Kombinace přepínačů, použití profilů odolnosti, resetování jističů z jednoho ovládacího panelu |
+| Feature | What It Does |
+| ------------------------------------ | ------------------------------------------------------------------------------------------- |
+| ⚡ **Grok-4 Fast Family** | xAI models at $0.20/$0.50/M — benchmarked 1143ms (30% faster than Gemini 2.5 Flash) |
+| 🧠 **GLM-5 via Z.AI** | 128K output context, $0.5/1M — newest flagship from the GLM family |
+| 🔮 **MiniMax M2.5** | Reasoning + agentic tasks at $0.30/1M — significant upgrade from M2.1 |
+| 🎯 **toolCalling Flag per Model** | Per-model `toolCalling: true/false` in registry — AutoCombo skips non-tool-capable models |
+| 🌍 **Multilingual Intent Detection** | PT/ZH/ES/AR keywords in AutoCombo scoring — better model selection for non-English content |
+| 📊 **Benchmark-Driven Fallbacks** | Real p95 latency from live requests feeds combo scoring — AutoCombo learns from actual data |
+| 🔁 **Request Deduplication** | Content-hash based dedup window — multi-agent safe, prevents duplicate charges |
+| 🔌 **Pluggable RouterStrategy** | Extensible `RouterStrategy` interface — add custom routing logic as plugins |
-### 🧠 Směrování a inteligence
+### 🚀 Previous v2.0.9+ — Playground, CLI Fingerprints & ACP
-| Funkce | Co to dělá |
-| ----------------------------------------------- | ----------------------------------------------------------------------------- |
-| 🎯 **Inteligentní čtyřúrovňový záložní systém** | Automatická trasa: Předplatné → API klíč → Levné → Zdarma |
-| 📊 **Sledování kvót v reálném čase** | Počet tokenů v reálném čase + odpočet resetování pro každého poskytovatele |
-| 🔄 **Překlad formátu** | OpenAI ↔ Claude ↔ Gemini ↔ Odpovědi s konverzemi bezpečnými pro schéma |
-| 👥 **Podpora více účtů** | Více účtů na poskytovatele s inteligentním výběrem |
-| 🔄 **Automatická aktualizace tokenů** | Tokeny OAuth se automaticky obnovují při opakovaném pokusu. |
-| 🎨 **Vlastní kombinace** | 6 vyvažovacích strategií + řízení záložního řetězce |
-| 🌐 **Směrovač se zástupnými znaky** | dynamické směrování `provider/*` |
-| 🧠 **Přemýšlení o rozpočtových kontrolách** | Limity pro průchozí, automatické, vlastní a adaptivní uvažování |
-| 🔀 **Aliasy modelů** | Vestavěné + vlastní aliasování modelů a bezpečnost migrace |
-| ⚡ **Degradace pozadí** | Směrujte úlohy na pozadí s nízkou prioritou na levnější modely |
-| 🧪 **Chytré směrování s ohledem na úkoly** | Automatický výběr modelu podle typu obsahu (kódování/vize/analýza/sumarizace) |
-| 💬 **Vstřikování do systému** | Globální kontroly chování uplatňované konzistentně |
-| 📄 **Kompatibilita API pro odpovědi** | Plná podpora `/v1/responses` pro Codex a pokročilé agentické pracovní postupy |
+| Feature | What It Does |
+| ------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| 🎮 **Model Playground** | Dashboard page to test any model directly — provider/model/endpoint selectors, Monaco Editor, streaming, abort, timing |
+| 🔏 **CLI Fingerprint Matching** | Per-provider header/body ordering to match native CLI signatures — toggle per provider in Settings > Security. **Your proxy IP is preserved** |
+| 🤝 **ACP Support (Agent Client Protocol)** | CLI agent discovery (Codex, Claude, Goose, Gemini CLI, OpenClaw + 9 more), process spawner, `/api/acp/agents` endpoint |
+| 🤖 **ACP Agents Dashboard** | Debug › Agents page — grid of 14 agents with install status, version, custom agent form for any CLI tool. **OpenCode** users get a "Download opencode.json" button that auto-generates a ready-to-use config with all available models. |
+| 🔧 **Custom Model `apiFormat` Routing** | Custom models with `apiFormat: "responses"` now correctly route to the Responses API translator |
+| 🏢 **Codex Workspace Isolation** | Multiple Codex workspaces per email — OAuth correctly separates connections by workspace ID |
+| 🔄 **Electron Auto-Update** | Desktop app checks for updates + auto-install on restart |
-### 🎵 Multimodální API
+### 🤖 Agent & Protocol Operations (v2.0)
-| Funkce | Co to dělá |
-| ----------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| 🖼️ **Generování obrázků** | `/v1/images/generations` s cloudovým a lokálním backendem |
-| 📐 **Vložení** | `/v1/embeddings` pro vyhledávání a RAG pipelines |
-| 🎤 **Přepis zvuku** | `/v1/audio/transcriptions` (Whisper a další poskytovatelé) |
-| 🔊 **Převod textu na řeč** | `/v1/audio/speech` (více enginů/poskytovatelů) |
-| 🎬 **Generování videa** | `/v1/videos/generations` (pracovní postupy ComfyUI + SD WebUI) |
-| 🎵 **Hudební generace** | `/v1/music/generations` (pracovní postupy ComfyUI) |
-| 🛡️ **Moderování** | Bezpečnostní kontroly `/v1/moderations` |
-| 🔀 **Změna pořadí** | `/v1/rerank` pro hodnocení relevance |
-| 🔍 **Vyhledávání na webu** 🆕 | `/v1/search` — 5 poskytovatelů (Serper, Brave, Perplexity, Exa, Tavily), více než 6 500 zdarma/měsíc, automatické přepnutí na záložní systém, mezipaměť |
+| Feature | What It Does |
+| ------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------- |
+| 🔧 **MCP Server (25 tools)** | IDE/agent tools via 3 transports: stdio, SSE (`/api/mcp/sse`), Streamable HTTP (`/api/mcp/stream`). 18 core + 3 memory + 4 skill tools |
+| 🤝 **A2A Server (JSON-RPC + SSE)** | Agent-to-agent task execution with sync and streaming flows |
+| 🧭 **Consolidated Endpoints Page** | Tabbed management page with Endpoint Proxy, MCP, A2A, and API Endpoints tabs |
+| 🎚️ **Service Enable/Disable Toggles** | ON/OFF switches for MCP and A2A with settings persistence (default: OFF) |
+| 🛰️ **MCP Runtime Heartbeat** | Real process status (pid, uptime, heartbeat age, transport, scope mode) |
+| 📋 **MCP Audit Trail** | Filterable audit logs with success/failure and key attribution |
+| 🔐 **MCP Scope Enforcement** | 10 granular scope permissions for controlled tool access |
+| 📡 **A2A Task Lifecycle Management** | List/filter tasks, inspect events/artifacts, cancel running tasks |
+| 📋 **Agent Card Discovery** | `/.well-known/agent.json` for client auto-discovery |
+| 🧪 **Protocol E2E Test Harness** | Real MCP SDK + A2A client flows in `test:protocols:e2e` |
+| ⚙️ **Operational Controls** | Switch combo, apply resilience profiles, reset breakers from one control surface |
-### 🛡️ Odolnost, bezpečnost a správa věcí veřejných
+### 🧠 Routing & Intelligence
-| Funkce | Co to dělá |
-| ------------------------------------------- | ----------------------------------------------------------------------------------------------------------------- |
-| 🔌 **Jističe** | Vypnutí/obnovení pro každý model s ovládáním prahových hodnot |
-| 🎯 **Modely s ohledem na koncové body** | Vlastní modely deklarují podporované koncové body + formát API |
-| 🛡️ **Stádo proti hromům** | Ochrana mutexu a semaforu při událostech opakování/rychlosti |
-| 🧠 **Sémantická + podpisová mezipaměť** | Snížení nákladů/latence díky dvěma vrstvám mezipaměti |
-| ⚡ **Žádost o idempotenci** | Okno ochrany proti duplikacím |
-| 🔒 **Falšování otisků prstů pomocí TLS** | Otisk TLS podobný prohlížeči – **snižuje detekci botů a nahlašování účtů** |
-| 🔏 **Porovnávání otisků prstů v CLI** | Shoduje se s nativními podpisy požadavků CLI – **snižuje riziko zablokování a zároveň zachovává IP adresu proxy** |
-| 🌐 **Filtrování IP adres** | Ovládání seznamu povolených/blokovaných položek pro odhalená nasazení |
-| 📊 **Upravitelné limity rychlosti** | Konfigurovatelné globální/na úrovni poskytovatele limity s perzistencí |
-| 🔑 **Správa klíčů API a stanovení rozsahu** | Bezpečné vydávání/rotace klíčů a kontroly modelu/poskytovatele |
-| 🛡️ **Chráněné `/models`** | Volitelné ověřování a skrytí poskytovatele pro katalog modelů |
+| Feature | What It Does |
+| ---------------------------------- | ------------------------------------------------------------------------ |
+| 🎯 **Smart 4-Tier Fallback** | Auto-route: Subscription → API Key → Cheap → Free |
+| 📊 **Real-Time Quota Tracking** | Live token count + reset countdown per provider |
+| 🔄 **Format Translation** | OpenAI ↔ Claude ↔ Gemini ↔ Responses with schema-safe conversions |
+| 👥 **Multi-Account Support** | Multiple accounts per provider with intelligent selection |
+| 🔄 **Auto Token Refresh** | OAuth tokens refresh automatically with retry |
+| 🎨 **Custom Combos** | 9 balancing strategies + fallback chain control |
+| 🌐 **Wildcard Router** | `provider/*` dynamic routing |
+| 🧠 **Thinking Budget Controls** | Passthrough, auto, custom, and adaptive reasoning limits |
+| 🔀 **Model Aliases** | Built-in + custom model aliasing and migration safety |
+| ⚡ **Background Degradation** | Route low-priority background tasks to cheaper models |
+| 🧪 **Task-Aware Smart Routing** | Auto-select model by content type (coding/vision/analysis/summarization) |
+| 🔄 **A2A Agent Workflows** | Deterministic FSM orchestrator for stateful multi-step agent executions |
+| 🔀 **Adaptive Routing** | Dynamic strategy override based on token volume and prompt complexity |
+| 🎲 **Provider Diversity** | Shannon entropy scoring balancing auto-combo traffic distribution |
+| 💬 **System Prompt Injection** | Global behavior controls applied consistently |
+| 📄 **Responses API Compatibility** | Full `/v1/responses` support for Codex and advanced agentic workflows |
-### 📊 Pozorovatelnost a analytika
+### 🎵 Multi-Modal APIs
-| Funkce | Co to dělá |
-| ----------------------------------- | ---------------------------------------------------------------------- |
-| 📝 **Žádost + protokolování proxy** | Úplné protokolování požadavků/odpovědí a proxy |
-| 📉 **Streamed Detailed Logs** 🆕 | Reconstructs SSE payload streams cleanly into the UI |
-| 📋 **Sjednocený panel protokolů** | Zobrazení požadavků, proxy, auditu a konzole na jedné stránce |
-| 🔍 **Vyžádat si telemetrii** | Latence p50/p95/p99 a trasování požadavků |
-| 🏥 **Panel zdraví** | Doba provozuschopnosti, stavy jističů, uzamčení, statistiky mezipaměti |
-| 💰 **Sledování nákladů** | Kontrola rozpočtu a přehled o cenách pro jednotlivé modely |
-| 📈 **Analytické vizualizace** | Přehledy využití modelů/poskytovatelů a zobrazení trendů |
-| 🧪 **Rámec hodnocení** | Testování zlaté sady s konfigurovatelnými strategiemi shody |
+| Feature | What It Does |
+| -------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| 🖼️ **Image Generation** | `/v1/images/generations` with cloud and local backends |
+| 📐 **Embeddings** | `/v1/embeddings` for search and RAG pipelines |
+| 🎤 **Audio Transcription** | `/v1/audio/transcriptions` — 7 providers (Deepgram Nova 3, AssemblyAI, Groq Whisper, HuggingFace, ElevenLabs, OpenAI, Azure), auto-language detection, MP4/MP3/WAV support |
+| 🔊 **Text-to-Speech** | `/v1/audio/speech` — 10 providers (ElevenLabs, OpenAI, Deepgram, Cartesia, PlayHT, HuggingFace, Nvidia NIM, Inworld, Coqui, Tortoise) with correct error messages |
+| 🎬 **Video Generation** | `/v1/videos/generations` (ComfyUI + SD WebUI workflows) |
+| 🎵 **Music Generation** | `/v1/music/generations` (ComfyUI workflows) |
+| 🛡️ **Moderations** | `/v1/moderations` safety checks |
+| 🔀 **Reranking** | `/v1/rerank` for relevance scoring |
+| 🔍 **Web Search** 🆕 | `/v1/search` — 5 providers (Serper, Brave, Perplexity, Exa, Tavily), 6,500+ free/month, auto-failover, cache |
-### ☁️ Nasazení a platforma
+### 🛡️ Resilience, Security & Governance
-| Funkce | Co to dělá |
-| ----------------------------------------------- | ------------------------------------------------------------------------- |
-| 🌐 **Nasazení kdekoli** | Localhost, VPS, Docker, cloudová prostředí |
-| 💾 **Synchronizace s cloudem** | Synchronizace konfigurace přes cloud worker |
-| 🔄 **Zálohování/Obnovení** | Toky exportu/importu a obnovy po havárii |
-| 🧙 **Průvodce nástupem** | Průvodce prvním spuštěním |
-| 🔧 **Panel nástrojů CLI** | Nastavení oblíbených kódovacích nástrojů jedním kliknutím |
-| 🎮 **Modelové hřiště** | Otestujte libovolného poskytovatele/model/koncový bod z řídicího panelu |
-| 🔏 **Přepínač otisků prstů v příkazovém řádku** | Porovnávání otisků prstů podle poskytovatele v Nastavení > Zabezpečení |
-| 🌐 **i18n (30 jazyků)** | Plná jazyková podpora dashboardu a dokumentace s psaním zprava doleva |
-| 🧹 **Clear All Models** | One-click model list clearing in provider details |
-| 👁️ **Sidebar Controls** 🆕 | Hide components and integrations from Appearance Settings |
-| 📋 **Issue Templates** | Standardized GitHub templates for bugs and features |
-| 📂 **Adresář vlastních dat** | Přepsání `DATA_DIR` pro umístění úložiště |
+| Feature | What It Does |
+| ----------------------------------- | -------------------------------------------------------------------------------------- |
+| 🔌 **Circuit Breakers** | Per-model trip/recover with threshold controls |
+| 🎯 **Endpoint-Aware Models** | Custom models declare supported endpoints + API format |
+| 🛡️ **Anti-Thundering Herd** | Mutex + semaphore protections on retry/rate events |
+| 🧠 **Semantic + Signature Cache** | Cost/latency reduction with two cache layers |
+| ⚡ **Request Idempotency** | Duplicate protection window |
+| 🔒 **TLS Fingerprint Spoofing** | Browser-like TLS fingerprint — **reduces bot detection and account flagging** |
+| 🔏 **CLI Fingerprint Matching** | Matches native CLI request signatures — **reduces ban risk while preserving proxy IP** |
+| 🌐 **IP Filtering** | Allowlist/blocklist control for exposed deployments |
+| 📊 **Editable Rate Limits** | Configurable global/provider-level limits with persistence |
+| 📉 **Graceful Degradation** | Multi-layer capability fallbacks protecting core gateway operations |
+| 📜 **Config Audit Trail** | Diff-based change tracking preventing operational drift with simple rollbacks |
+| ⏳ **Provider Health Sync** | Proactive token expiration monitoring triggering alerts before authorization failures |
+| 🚪 **Auto-Disable Banned Accounts** | Operational circuit breaker sealing permanently blocked token accounts automatically |
+| 🔑 **API Key Management + Scoping** | Secure key issuance/rotation and model/provider controls |
+| 👁️ **Scoped API Key Reveal** 🆕 | Opt-in recovery of API keys via `ALLOW_API_KEY_REVEAL` |
+| 🛡️ **Protected `/models`** | Optional auth gating and provider hiding for model catalog |
-### Hluboký pohled na funkce
+### 📊 Observability & Analytics
-#### Chytrá záložní funkce s praktickou kontrolou nákladů
+| Feature | What It Does |
+| -------------------------------- | ----------------------------------------------------- |
+| 📝 **Request + Proxy Logging** | Full request/response and proxy logging |
+| 📉 **Streamed Detailed Logs** 🆕 | Reconstructs SSE payload streams cleanly into the UI |
+| 📋 **Unified Logs Dashboard** | Request, proxy, audit, and console views in one page |
+| 🔍 **Request Telemetry** | p50/p95/p99 latency and request tracing |
+| 🏥 **Health Dashboard** | Uptime, breaker states, lockouts, cache stats |
+| 💰 **Cost Tracking** | Budget controls and per-model pricing visibility |
+| 📈 **Analytics Visualizations** | Model/provider usage insights and trend views |
+| 🧪 **Evaluation Framework** | Golden set testing with configurable match strategies |
+| 📡 **Live Diagnostics** 🆕 | Semantic cache bypass for accurate combo live testing |
+
+### ☁️ Deployment & Platform
+
+| Feature | What It Does |
+| ------------------------------ | --------------------------------------------------------------------- |
+| 🌐 **Deploy Anywhere** | Localhost, VPS, Docker, Cloud environments |
+| 🚇 **Cloudflare Tunnel** 🆕 | One-click Quick Tunnel integration from the dashboard |
+| 🔑 **API Key Model Filtering** | Native /v1/models response filtered via assigned Bearer context roles |
+| ⚡ **Smart Cache Bypass** | Configurable TTL heuristics and forced refetch controls |
+| 🔄 **Backup/Restore** | Export/import and disaster recovery flows |
+| 🧙 **Onboarding Wizard** | First-run guided setup |
+| 🔧 **CLI Tools Dashboard** | One-click setup for popular coding tools |
+| 🎮 **Model Playground** | Test any provider/model/endpoint from the dashboard |
+| 🔏 **CLI Fingerprint Toggle** | Per-provider fingerprint matching in Settings > Security |
+| 🌐 **i18n (30 languages)** | Full dashboard + docs language support with RTL coverage |
+| 🧹 **Clear All Models** | One-click model list clearing in provider details |
+| 👁️ **Sidebar Controls** 🆕 | Hide components and integrations from Appearance Settings |
+| 📋 **Issue Templates** | Standardized GitHub templates for bugs and features |
+| 📂 **Custom Data Directory** | `DATA_DIR` override for storage location |
+
+### Feature Deep Dive
+
+#### Smart fallback with practical cost control
```txt
Combo: "my-coding-stack"
@@ -1086,91 +1442,91 @@ Combo: "my-coding-stack"
4. if/kimi-k2-thinking
```
-Když selže kvóta, rychlost nebo stav, OmniRoute automaticky přejde k dalšímu kandidátovi bez nutnosti ručního přepínání.
+When quota, rate, or health fails, OmniRoute automatically moves to the next candidate without manual switching.
-#### Správa protokolů, která je viditelná a ovladatelná
+#### Protocol management that is visible and operable
-- MCP + A2A jsou viditelné v uživatelském rozhraní a dokumentaci (nejsou skryté)
-- API pro stav protokolu zpřístupňují živá provozní data ( `/api/mcp/*` , `/api/a2a/*` )
-- Dashboardy zahrnují akce pro operace 2. dne (přepínání kombinací, resetování jističů, zrušení úkolů)
+- MCP + A2A are discoverable in UI and docs (not hidden)
+- Protocol status APIs expose live operational data (`/api/mcp/*`, `/api/a2a/*`)
+- Dashboards include actions for day-2 ops (combo toggles, breaker resets, task cancellation)
-#### Pracovní postup překladatele + validace
+#### Translator + validation workflow
-Oblast překladatele zahrnuje:
+The Translator area includes:
-- **Hřiště** : kontroly transformace požadavků
-- **Tester chatu** : kompletní okružní cesta požadavku/odpovědi
-- **Testovací stolice** : více případů v jednom běhu
-- **Živý monitor** : zobrazení provozu v reálném čase
+- **Playground**: request transformation checks
+- **Chat Tester**: full request/response round-trip
+- **Test Bench**: multiple cases in one run
+- **Live Monitor**: real-time traffic view
-Plus validace protokolu se skutečnými klienty pomocí `npm run test:protocols:e2e` .
+Plus protocol validation with real clients via `npm run test:protocols:e2e`.
-> 📖 **[Soubor README pro MCP Server](open-sse/mcp-server/README.md)** — Referenční informace o nástrojích, konfigurace IDE a příklady klientů
+> 📖 **[MCP Server README](open-sse/mcp-server/README.md)** — Tool reference, IDE configs, and client examples
>
-> 📖 **[Soubor README pro A2A Server](src/lib/a2a/README.md)** — Dovednosti, metody JSON-RPC, streamování a životní cyklus úloh
+> 📖 **[A2A Server README](src/lib/a2a/README.md)** — Skills, JSON-RPC methods, streaming, and task lifecycle
-## 🧪 Hodnocení (Evals)
+## 🧪 Evaluations (Evals)
-OmniRoute obsahuje vestavěný hodnotící rámec pro testování kvality odpovědí LLM v porovnání se zlatou sadou. Přístup k němu je možný přes **Analýzy → Hodnocení** v dashboardu.
+OmniRoute includes a built-in evaluation framework to test LLM response quality against a golden set. Access it via **Analytics → Evals** in the dashboard.
-### Vestavěná zlatá sada
+### Built-in Golden Set
-Předinstalovaná sada „OmniRoute Golden Set“ obsahuje testovací případy pro:
+The pre-loaded "OmniRoute Golden Set" contains test cases for:
-- Zdravím, matematika, zeměpis, generování kódu
-- Shoda s formátem JSON, překlad, generování markdownů
-- Bezpečnostní odmítnutí (škodlivý obsah), počítání, booleovská logika
+- Greetings, math, geography, code generation
+- JSON format compliance, translation, markdown generation
+- Safety refusal (harmful content), counting, boolean logic
-### Strategie hodnocení
+### Evaluation Strategies
-| Strategie | Popis | Příklad |
-| ---------- | ------------------------------------------------------------------------ | -------------------------------- |
-| `exact` | Výstup se musí přesně shodovat | `"4"` |
-| `contains` | Výstup musí obsahovat podřetězec (bez rozlišení velkých a malých písmen) | `"Paris"` |
-| `regex` | Výstup musí odpovídat vzoru regulárních výrazů | `"1.*2.*3"` |
-| `custom` | Vlastní JS funkce vrací true/false | `(output) => output.length > 10` |
+| Strategy | Description | Example |
+| ---------- | ------------------------------------------------ | -------------------------------- |
+| `exact` | Output must match exactly | `"4"` |
+| `contains` | Output must contain substring (case-insensitive) | `"Paris"` |
+| `regex` | Output must match regex pattern | `"1.*2.*3"` |
+| `custom` | Custom JS function returns true/false | `(output) => output.length > 10` |
---
-## 📖 Průvodce nastavením
+## 📖 Setup Guide
-### Nastavení protokolu (MCP + A2A)
+### Protocol Setup (MCP + A2A)
-🧩 Nastavení MCP (Model Context Protocol)
-
+🧩 MCP Setup (Model Context Protocol)
-Spuštění MCP transportu v režimu stdio:
+Start MCP transport in stdio mode:
```bash
omniroute --mcp
```
-Doporučený postup ověření:
+Recommended validation flow:
-1. Připojte svého MCP klienta přes stdio.
-2. Spusťte `omniroute_get_health` .
-3. Spusťte `omniroute_list_combos` .
-4. Otevřete `/dashboard/mcp` pro ověření prezenčního signálu, aktivity a auditu.
+1. Connect your MCP client over stdio.
+2. Run `omniroute_get_health`.
+3. Run `omniroute_list_combos`.
+4. Open `/dashboard/mcp` to confirm heartbeat, activity, and audit.
-Užitečná API pro automatizaci:
+Useful APIs for automation:
- `GET /api/mcp/status`
- `GET /api/mcp/tools`
- `GET /api/mcp/audit`
- `GET /api/mcp/audit/stats`
-
-🤝 Nastavení A2A (Agent2Agent)
-Objevte agenta:
+
+🤝 A2A Setup (Agent2Agent)
+
+Discover the agent:
```bash
curl http://localhost:20128/.well-known/agent.json
```
-Odeslat úkol:
+Send a task:
```bash
curl -X POST http://localhost:20128/a2a \
@@ -1178,36 +1534,38 @@ curl -X POST http://localhost:20128/a2a \
-d '{"jsonrpc":"2.0","id":"setup-a2a","method":"message/send","params":{"skill":"quota-management","messages":[{"role":"user","content":"Summarize quota status."}]}}'
```
-Správa životního cyklu:
+Manage lifecycle:
- `GET /api/a2a/status`
- `GET /api/a2a/tasks`
- `GET /api/a2a/tasks/:id`
- `POST /api/a2a/tasks/:id/cancel`
-Provozní uživatelské rozhraní:
+Operational UI:
-- `/dashboard/a2a` pro pozorovatelnost úloh/stavů/streamů a akce kouření
+- `/dashboard/a2a` for task/state/stream observability and smoke actions
-
-🧪 Komplexní validace protokolu
-Ověřte oba protokoly se skutečnými klienty:
+
+🧪 End-to-end protocol validation
+
+Validate both protocols with real clients:
```bash
npm run test:protocols:e2e
```
-Tím se ověřuje:
+This verifies:
-- Připojení/seznam/volání klienta MCP SDK
-- A2A objevování/odesílání/streamování/získávání/zrušení
-- Křížová kontrola dat v auditu MCP a API pro správu úloh A2A
+- MCP SDK client connect/list/call
+- A2A discovery/send/stream/get/cancel
+- Cross-check data in MCP audit and A2A task management APIs
+
+
-💳 Poskytovatelé předplatného
-
+💳 Subscription Providers
### Claude Code (Pro/Max)
@@ -1222,7 +1580,7 @@ Models:
cc/claude-haiku-4-5-20251001
```
-**Tip pro profesionály:** Pro složité úkoly používejte Opus, pro rychlost Sonnet. OmniRoute sleduje kvótu pro každý model!
+**Pro Tip:** Use Opus for complex tasks, Sonnet for speed. OmniRoute tracks quota per model!
### OpenAI Codex (Plus/Pro)
@@ -1236,24 +1594,24 @@ Models:
cx/gpt-5.1-codex-max
```
-#### Správa limitů účtu Codex (5h + týdně)
+#### Codex Account Limit Management (5h + Weekly)
-Každý účet Codex má nyní přepínače zásad v `Dashboard -> Providers` :
+Each Codex account now has policy toggles in `Dashboard -> Providers`:
-- `5h` (ZAP/VYP): vynutit politiku 5hodinového prahu okna.
-- `Weekly` (ZAP/VYP): vynutit zásadu týdenního prahu okna.
-- Prahové chování: když povolené okno dosáhne využití >=90 %, je daný účet přeskočen.
-- Chování rotace: OmniRoute automaticky přesměruje na další způsobilý účet Codex.
-- Chování při resetování: Po `resetAt` určité doby se účet automaticky opět stane způsobilým.
+- `5h` (ON/OFF): enforce the 5-hour window threshold policy.
+- `Weekly` (ON/OFF): enforce the weekly window threshold policy.
+- Threshold behavior: when an enabled window reaches >=90% usage, that account is skipped.
+- Rotation behavior: OmniRoute routes to the next eligible Codex account automatically.
+- Reset behavior: when the provider `resetAt` time passes, the account becomes eligible again automatically.
-Scénáře:
+Scenarios:
-- `5h ON` + `Weekly ON` : účet je přeskočen, když kterékoli z oken dosáhne prahové hodnoty.
-- `5h OFF` + `Weekly ON` : účet může být zablokován pouze týdenním používáním.
-- `5h ON` + `Weekly OFF` : účet může být zablokován pouze při 5hodinovém používání.
-- `resetAt` passed: účet se automaticky znovu zapne (bez ručního opětovného povolení).
+- `5h ON` + `Weekly ON`: account is skipped when either window reaches threshold.
+- `5h OFF` + `Weekly ON`: only weekly usage can block the account.
+- `5h ON` + `Weekly OFF`: only 5-hour usage can block the account.
+- `resetAt` passed: account re-enters rotation automatically (no manual re-enable).
-### Gemini CLI (ZDARMA 180 000/měsíc!)
+### Gemini CLI (FREE 180K/month!)
```bash
Dashboard → Providers → Connect Gemini CLI
@@ -1265,7 +1623,7 @@ Models:
gc/gemini-2.5-pro
```
-**Nejlepší hodnota:** Obrovská bezplatná úroveň! Použijte ji před placenými úrovněmi.
+**Best Value:** Huge free tier! Use this before paid tiers.
### GitHub Copilot
@@ -1280,88 +1638,93 @@ Models:
gh/gemini-3-pro
```
-
-🔑 Poskytovatelé klíčů API
-### NVIDIA NIM (BEZPLATNÝ přístup pro vývojáře — více než 70 modelů)
-
-1. Registrace: [build.nvidia.com](https://build.nvidia.com)
-2. Získejte zdarma klíč API (včetně 1000 inferenčních kreditů)
-3. Ovládací panel → Přidat poskytovatele → NVIDIA NIM:
- - Klíč API: `nvapi-your-key`
-
-**Modely:** `nvidia/llama-3.3-70b-instruct` , `nvidia/mistral-7b-instruct` a více než 50 dalších
-
-**Tip pro profesionály:** API kompatibilní s OpenAI – funguje bez problémů s překladem formátů OmniRoute!
-
-### Hluboké vyhledávání
-
-1. Registrace: [platform.deepseek.com](https://platform.deepseek.com)
-2. Získat klíč API
-3. Ovládací panel → Přidat poskytovatele → DeepSeek
-
-**Modely:** `deepseek/deepseek-chat` , `deepseek/deepseek-coder`
-
-### Groq (k dispozici je bezplatná úroveň!)
-
-1. Registrace: [console.groq.com](https://console.groq.com)
-2. Získejte klíč API (včetně bezplatné úrovně)
-3. Ovládací panel → Přidat poskytovatele → Groq
-
-**Modely:** `groq/llama-3.3-70b` , `groq/mixtral-8x7b`
-
-**Tip pro profesionály:** Ultrarychlá inference – nejlepší pro kódování v reálném čase!
-
-### OpenRouter (100+ modelů)
-
-1. Registrace: [openrouter.ai](https://openrouter.ai)
-2. Získat klíč API
-3. Ovládací panel → Přidat poskytovatele → OpenRouter
-
-**Modely:** Získejte přístup k více než 100 modelům od všech hlavních poskytovatelů prostřednictvím jediného klíče API.
-
-💰 Levní poskytovatelé (záložní)
+🔑 API Key Providers
+
+### NVIDIA NIM (FREE developer access — 70+ models)
+
+1. Sign up: [build.nvidia.com](https://build.nvidia.com)
+2. Get free API key (1000 inference credits included)
+3. Dashboard → Add Provider → NVIDIA NIM:
+ - API Key: `nvapi-your-key`
+
+**Models:** `nvidia/llama-3.3-70b-instruct`, `nvidia/mistral-7b-instruct`, and 50+ more
+
+**Pro Tip:** OpenAI-compatible API — works seamlessly with OmniRoute's format translation!
+
+### DeepSeek
+
+1. Sign up: [platform.deepseek.com](https://platform.deepseek.com)
+2. Get API key
+3. Dashboard → Add Provider → DeepSeek
+
+**Models:** `deepseek/deepseek-chat`, `deepseek/deepseek-coder`
+
+### Groq (Free Tier Available!)
+
+1. Sign up: [console.groq.com](https://console.groq.com)
+2. Get API key (free tier included)
+3. Dashboard → Add Provider → Groq
+
+**Models:** `groq/llama-3.3-70b`, `groq/mixtral-8x7b`
+
+**Pro Tip:** Ultra-fast inference — best for real-time coding!
+
+### OpenRouter (100+ Models)
+
+1. Sign up: [openrouter.ai](https://openrouter.ai)
+2. Get API key
+3. Dashboard → Add Provider → OpenRouter
+
+**Models:** Access 100+ models from all major providers through a single API key.
+
+**Dashboard behavior:** OpenRouter models are managed from **Available Models**. Manual add, import, and auto-sync all update the same list.
+
-### GLM-4.7 (Denní reset, 0,6 USD/1 milion)
-
-1. Registrace: [Zhipu AI](https://open.bigmodel.cn/)
-2. Získejte klíč API z kódovacího plánu
-3. Nástěnka → Přidat klíč API:
- - Poskytovatel: `glm`
- - Klíč API: `your-key`
-
-**Použití:** `glm/glm-4.7`
-
-**Tip pro profesionály:** Programovací plán nabízí 3× kvótu za cenu 1/7! Obnovuje se denně v 10:00.
-
-### MiniMax M2.1 (5h reset, 0,20 $/1 milion)
-
-1. Registrace: [MiniMax](https://www.minimax.io/)
-2. Získat klíč API
-3. Nástěnka → Přidat klíč API
-
-**Použití:** `minimax/MiniMax-M2.1`
-
-**Tip pro profesionály:** Nejlevnější varianta pro dlouhý kontext (1 milion tokenů)!
-
-### Kimi K2 (paušální poplatek 9 dolarů měsíčně)
-
-1. Odebírat: [Moonshot AI](https://platform.moonshot.ai/)
-2. Získat klíč API
-3. Nástěnka → Přidat klíč API
-
-**Použití:** `kimi/kimi-latest`
-
-**Tip pro profesionály:** Fixních 9 $/měsíc za 10 milionů tokenů = efektivní náklady 0,90 $/1 milion!
-
-🆓 BEZPLATNÍ poskytovatelé (nouzové zálohování)
+💰 Cheap Providers (Backup)
+
+### GLM-4.7 (Daily reset, $0.6/1M)
+
+1. Sign up: [Zhipu AI](https://open.bigmodel.cn/)
+2. Get API key from Coding Plan
+3. Dashboard → Add API Key:
+ - Provider: `glm`
+ - API Key: `your-key`
+
+**Use:** `glm/glm-4.7`
+
+**Pro Tip:** Coding Plan offers 3× quota at 1/7 cost! Reset daily 10:00 AM.
+
+### MiniMax M2.1 (5h reset, $0.20/1M)
+
+1. Sign up: [MiniMax](https://www.minimax.io/)
+2. Get API key
+3. Dashboard → Add API Key
+
+**Use:** `minimax/MiniMax-M2.1`
+
+**Pro Tip:** Cheapest option for long context (1M tokens)!
+
+### Kimi K2 ($9/month flat)
+
+1. Subscribe: [Moonshot AI](https://platform.moonshot.ai/)
+2. Get API key
+3. Dashboard → Add API Key
+
+**Use:** `kimi/kimi-latest`
+
+**Pro Tip:** Fixed $9/month for 10M tokens = $0.90/1M effective cost!
+
-### Qoder (5 BEZPLATNÝCH modelů přes OAuth)
+
+🆓 FREE Providers (Emergency Backup)
+
+### Qoder (5 FREE models via OAuth)
```bash
Dashboard → Connect Qoder
@@ -1376,7 +1739,7 @@ Models:
if/deepseek-r1
```
-### Qwen (4 modely ZDARMA s kódem zařízení)
+### Qwen (4 FREE models via Device Code)
```bash
Dashboard → Connect Qwen
@@ -1388,7 +1751,7 @@ Models:
qw/qwen3-coder-flash
```
-### Kiro (Claude ZDARMA)
+### Kiro (Claude FREE)
```bash
Dashboard → Connect Kiro
@@ -1400,11 +1763,12 @@ Models:
kr/claude-haiku-4.5
```
-
-🎨 Vytvořte kombinace
-### Příklad 1: Maximalizace předplatného → Levné zálohování
+
+🎨 Create Combos
+
+### Example 1: Maximize Subscription → Cheap Backup
```
Dashboard → Combos → Create New
@@ -1418,7 +1782,7 @@ Models:
Use in CLI: premium-coding
```
-### Příklad 2: Pouze zdarma (nulové náklady)
+### Example 2: Free-Only (Zero Cost)
```
Name: free-combo
@@ -1430,11 +1794,12 @@ Models:
Cost: $0 forever!
```
-
-🔧 Integrace s rozhraním příkazového řádku
-### IDE kurzoru
+
+🔧 CLI Integration
+
+### Cursor IDE
```
Settings → Models → Advanced:
@@ -1445,7 +1810,7 @@ Settings → Models → Advanced:
### Claude Code
-Pro konfiguraci jedním kliknutím použijte stránku **Nástroje CLI** na řídicím panelu nebo ručně upravte soubor `~/.claude/settings.json` .
+Use the **CLI Tools** page in the dashboard for one-click configuration, or edit `~/.claude/settings.json` manually.
### Codex CLI
@@ -1458,13 +1823,13 @@ codex "your prompt"
### OpenClaw
-**Možnost 1 – Dashboard (doporučeno):**
+**Option 1 — Dashboard (recommended):**
```
Dashboard → CLI Tools → OpenClaw → Select Model → Apply
```
-**Možnost 2 – Manuální úprava:** Úprava `~/.openclaw/openclaw.json` :
+**Option 2 — Manual:** Edit `~/.openclaw/openclaw.json`:
```json
{
@@ -1480,9 +1845,9 @@ Dashboard → CLI Tools → OpenClaw → Select Model → Apply
}
```
-> **Poznámka:** OpenClaw funguje pouze s lokálním OmniRoute. Místo `localhost` použijte `127.0.0.1` , abyste se vyhnuli problémům s rozlišením IPv6.
+> **Note:** OpenClaw only works with local OmniRoute. Use `127.0.0.1` instead of `localhost` to avoid IPv6 resolution issues.
-### Cline / Pokračovat / RooCode
+### Cline / Continue / RooCode
```
Settings → API Configuration:
@@ -1494,7 +1859,7 @@ Settings → API Configuration:
### OpenCode
-**Krok 1:** Přidání OmniRoute jako vlastního poskytovatele:
+**Step 1:** Add OmniRoute as a custom provider:
```bash
opencode
@@ -1502,7 +1867,7 @@ opencode
# Select "Other" → Enter ID: "omniroute" → Enter your OmniRoute API key
```
-**Krok 2:** Vytvořte/upravte `opencode.json` v kořenovém adresáři projektu:
+**Step 2:** Create/edit `opencode.json` in your project root:
```json
{
@@ -1524,121 +1889,126 @@ opencode
}
```
-**Krok 3:** Vyberte model v OpenCode:
+**Step 3:** Select the model in OpenCode:
```bash
/models
# Select any OmniRoute model from the list
```
-> **Tip:** Do sekce `models` přidejte jakýkoli model dostupný ve vašem koncovém bodu OmniRoute `/v1/models` . Použijte formát `provider/model-id` z vašeho dashboardu OmniRoute.
+> **Tip:** Add any model available in your OmniRoute `/v1/models` endpoint to the `models` section. Use the format `provider/model-id` from your OmniRoute dashboard.
+
+
---
-## 🐛 Řešení problémů
+## Řešení problémů
-Kliknutím rozbalíte průvodce řešením problémů
-
+Click to expand troubleshooting guide
-**"Jazykový model neposkytoval zprávy"**
+**"Language model did not provide messages"**
-- Kvóta poskytovatele vyčerpána → Zkontrolujte sledování kvót na řídicím panelu
-- Řešení: Použijte záložní kombinovanou variantu nebo přejděte na levnější úroveň
+- Provider quota exhausted → Check dashboard quota tracker
+- Solution: Use combo fallback or switch to cheaper tier
-**Omezení rychlosti**
+**Rate limiting**
-- Kvóta předplatného vyčerpána → Přechod na GLM/MiniMax
-- Přidat kombo: `cc/claude-opus-4-6 → glm/glm-4.7 → if/kimi-k2-thinking`
+- Subscription quota out → Fallback to GLM/MiniMax
+- Add combo: `cc/claude-opus-4-6 → glm/glm-4.7 → if/kimi-k2-thinking`
-**Platnost tokenu OAuth vypršela**
+**OAuth token expired**
-- Automaticky aktualizováno službou OmniRoute
-- Pokud problémy přetrvávají: Ovládací panel → Poskytovatel → Znovu připojit
+- Auto-refreshed by OmniRoute
+- If issues persist: Dashboard → Provider → Reconnect
-**Vysoké náklady**
+**High costs**
-- Zkontrolujte statistiky využití v sekci Nástěnka → Náklady
-- Přepnout primární model na GLM/MiniMax
-- Pro nekritické úlohy použijte bezplatnou úroveň (Gemini CLI, Qoder).
+- Check usage stats in Dashboard → Costs
+- Switch primary model to GLM/MiniMax
+- Use free tier (Gemini CLI, Qoder) for non-critical tasks
-**Porty řídicího panelu/API jsou nesprávné**
+**Dashboard/API ports are wrong**
-- `PORT` je kanonický základní port (a standardně port API)
-- `API_PORT` přepisuje pouze posluchač API kompatibilní s OpenAI.
-- `DASHBOARD_PORT` přepisuje pouze posluchač dashboard/Next.js
-- Nastavte `NEXT_PUBLIC_BASE_URL` na vaši veřejnou URL adresu řídicího panelu (pro zpětná volání OAuth)
+- `PORT` is the canonical base port (and API port by default)
+- `API_PORT` overrides only OpenAI-compatible API listener
+- `DASHBOARD_PORT` overrides only dashboard/Next.js listener
+- Set `NEXT_PUBLIC_BASE_URL` to your dashboard/public URL (for OAuth callbacks)
-**Chyby synchronizace s cloudem**
+**Cloud sync errors**
-- Ověřte, zda `BASE_URL` odkazuje na vaši spuštěnou instanci.
-- Ověřte, zda `CLOUD_URL` odkazuje na váš očekávaný cloudový koncový bod.
-- Udržujte hodnoty `NEXT_PUBLIC_*` v souladu s hodnotami na straně serveru.
+- Verify `BASE_URL` points to your running instance
+- Verify `CLOUD_URL` points to your expected cloud endpoint
+- Keep `NEXT_PUBLIC_*` values aligned with server-side values
-**První přihlášení nefunguje**
+**First login not working**
-- Zkontrolujte `INITIAL_PASSWORD` v souboru `.env`
-- Pokud není nastaveno, záložní heslo je `123456`
+- Check `INITIAL_PASSWORD` in `.env`
+- If unset, fallback password is `123456`
-**Žádné protokoly požadavků**
+**No request logs**
-- Nastavte `ENABLE_REQUEST_LOGS=true` v `.env`
+- Request artifacts are written to `DATA_DIR/call_logs/` as one JSON file per request
+- Enable pipeline capture from Dashboard → Logs → Request Logs if you need detailed per-stage payloads
+- Set `APP_LOG_TO_FILE=true` if you also want application console logs in `logs/application/app.log`
+- Adjust `APP_LOG_MAX_FILE_SIZE`, `APP_LOG_RETENTION_DAYS`, `APP_LOG_MAX_FILES`, and `CALL_LOG_MAX_ENTRIES` as needed
-**Test připojení ukazuje „Neplatné“ pro poskytovatele kompatibilní s OpenAI**
+**Connection test shows "Invalid" for OpenAI-compatible providers**
-- Mnoho poskytovatelů nezpřístupňuje koncový bod `/models`
-- OmniRoute v1.0.6+ zahrnuje záložní ověření pomocí dokončení chatu
-- Zajistěte, aby základní URL adresa obsahovala příponu `/v1`
+- Many providers don't expose a `/models` endpoint
+- OmniRoute v1.0.6+ includes fallback validation via chat completions
+- Ensure base URL includes `/v1` suffix
-### 🔐 OAuth na vzdáleném serveru
+### 🔐 OAuth on a Remote Server
+
-> **⚠️ Důležité pro uživatele, kteří provozují OmniRoute na VPS, Dockeru nebo jakémkoli vzdáleném serveru**
+> **⚠️ Important for users running OmniRoute on a VPS, Docker, or any remote server**
-#### Proč selhává OAuth v rozhraní CLI Antigravity / Gemini na vzdálených serverech?
+#### Why does Antigravity / Gemini CLI OAuth fail on remote servers?
-Poskytovatelé rozhraní CLI **Antigravity** a **Gemini** používají **Google OAuth 2.0** . Google vyžaduje, aby se `redirect_uri` v toku OAuth přesně shodoval s jedním z předregistrovaných URI v konzoli Google Cloud Console aplikace.
+The **Antigravity** and **Gemini CLI** providers use **Google OAuth 2.0**. Google requires the `redirect_uri` in the OAuth flow to exactly match one of the pre-registered URIs in the app's Google Cloud Console.
-Přihlašovací údaje OAuth, které jsou součástí OmniRoute, jsou registrovány **pouze pro `localhost`** . Když přistupujete k OmniRoute na vzdáleném serveru (např. `https://omniroute.myserver.com` ), Google odmítne ověření pomocí:
+The OAuth credentials bundled in OmniRoute are registered **for `localhost` only**. When you access OmniRoute on a remote server (e.g. `https://omniroute.myserver.com`), Google rejects the authentication with:
```
Error 400: redirect_uri_mismatch
```
-#### Řešení: Nakonfigurujte si vlastní přihlašovací údaje OAuth
+#### Solution: Configure your own OAuth credentials
-V Google Cloud Console je potřeba vytvořit **ID klienta OAuth 2.0** s URI vašeho serveru.
+You need to create an **OAuth 2.0 Client ID** in Google Cloud Console with your server's URI.
-#### Krok za krokem
+#### Step-by-step
-**1. Otevřete konzoli Google Cloud**
+**1. Open Google Cloud Console**
-Přejděte na: [https://console.cloud.google.com/apis/credentials](https://console.cloud.google.com/apis/credentials)
+Go to: [https://console.cloud.google.com/apis/credentials](https://console.cloud.google.com/apis/credentials)
-**2. Vytvořte nové ID klienta OAuth 2.0**
+**2. Create a new OAuth 2.0 Client ID**
-- Klikněte na **„+ Vytvořit přihlašovací údaje“** → **„ID klienta OAuth“**
-- Typ aplikace: **„Webová aplikace“**
-- Název: cokoli chcete (např. `OmniRoute Remote` )
+- Click **"+ Create Credentials"** → **"OAuth client ID"**
+- Application type: **"Web application"**
+- Name: anything you like (e.g. `OmniRoute Remote`)
-**3. Přidejte autorizované URI pro přesměrování**
+**3. Add Authorized Redirect URIs**
-Do pole **„Autorizované identifikátory URI pro přesměrování“** přidejte:
+In the **"Authorized redirect URIs"** field, add:
```
https://your-server.com/callback
```
-> Nahraďte `your-server.com` doménou nebo IP adresou vašeho serveru (v případě potřeby uveďte i port, např. `http://45.33.32.156:20128/callback` ).
+> Replace `your-server.com` with your server's domain or IP (include the port if needed, e.g. `http://45.33.32.156:20128/callback`).
-**4. Uložte a zkopírujte přihlašovací údaje**
+**4. Save and copy the credentials**
-Po vytvoření Google zobrazí **ID klienta** a **tajný kód klienta** .
+After creating, Google will show the **Client ID** and **Client Secret**.
-**5. Nastavení proměnných prostředí**
+**5. Set environment variables**
-Ve vašem souboru `.env` (nebo proměnných prostředí Docker):
+In your `.env` (or Docker environment variables):
```bash
# For Antigravity:
@@ -1651,7 +2021,7 @@ GEMINI_OAUTH_CLIENT_SECRET=GOCSPX-your-secret
GEMINI_CLI_OAUTH_CLIENT_SECRET=GOCSPX-your-secret
```
-**6. Restartujte OmniRoute**
+**6. Restart OmniRoute**
```bash
# npm:
@@ -1661,125 +2031,206 @@ npm run dev
docker restart omniroute
```
-**7. Zkuste se znovu připojit**
+**7. Try connecting again**
-Řídicí panel → Poskytovatelé → Antigravity (nebo Gemini CLI) → OAuth
+Dashboard → Providers → Antigravity (or Gemini CLI) → OAuth
-Google nyní bude správně přesměrovávat na `https://your-server.com/callback` .
+Google will now redirect correctly to `https://your-server.com/callback`.
---
-#### Dočasné řešení (bez vlastních přihlašovacích údajů)
+#### Temporary workaround (without custom credentials)
-Pokud si teď nechcete nastavovat vlastní přihlašovací údaje, můžete stále použít **ruční postup pro URL** :
+If you don't want to set up your own credentials right now, you can still use the **manual URL flow**:
-1. OmniRoute otevírá autorizační URL od Googlu
-2. Po autorizaci se Google pokusí přesměrovat na `localhost` (což selže na vzdáleném serveru).
-3. **Zkopírujte celou URL adresu** z adresního řádku prohlížeče (i když se stránka nenačte)
-4. Vložte tuto URL adresu do pole zobrazeného v modálním okně připojení OmniRoute.
-5. Klikněte na **„Připojit“**
+1. OmniRoute opens the Google authorization URL
+2. After authorizing, Google tries to redirect to `localhost` (which fails on the remote server)
+3. **Copy the full URL** from your browser's address bar (even if the page doesn't load)
+4. Paste that URL into the field shown in the OmniRoute connection modal
+5. Click **"Connect"**
-> To funguje, protože autorizační kód v URL adrese je platný bez ohledu na to, zda se načetla přesměrovací stránka.
+> This works because the authorization code in the URL is valid regardless of whether the redirect page loaded.
---
-#### Dočasné řešení (bez vlastních přihlašovacích údajů)
-
-Chcete-li získat přístup k přihlašovacím údajům bez vlastní konfigurace, můžete použít následující postup:
-
-1. OmniRoute otevře URL autorizace Google
-2. Po autorizaci se Google pokusí přesměrovat na `localhost` (což selže na vzdáleném serveru)
-3. **Zkopírujte celou URL adresu** z adresního řádku prohlížeče
-4. Vložte tuto URL adresu do pole zobrazeného v modálním okně připojení OmniRoute
-5. Klikněte na **„Připojit"**
-
-> Toto řešení funguje, protože autorizační kód v URL adrese je platný bez ohledu na načtení přesměrovací stránky.
-
----
-
-## 🛠️ Technologický stack
-
-Kliknutím rozbalíte podrobnosti o technologickém stacku
+🇧🇷 Versão em Português
+
+#### Por que o OAuth do Antigravity / Gemini CLI falha em servidores remotos?
+
+Os provedores **Antigravity** e **Gemini CLI** usam **Google OAuth 2.0** para autenticação. O Google exige que a `redirect_uri` usada no fluxo OAuth seja **exatamente** uma das URIs pré-cadastradas no Google Cloud Console do aplicativo.
+
+As credenciais OAuth embutidas no OmniRoute estão cadastradas **apenas para `localhost`**. Quando você acessa o OmniRoute em um servidor remoto (ex: `https://omniroute.meuservidor.com`), o Google rejeita a autenticação com:
+
+```
+Error 400: redirect_uri_mismatch
+```
+
+#### Solução: Configure suas próprias credenciais OAuth
+
+Você precisa criar um **OAuth 2.0 Client ID** no Google Cloud Console com a URI do seu servidor.
+
+#### Passo a passo
+
+**1. Acesse o Google Cloud Console**
+
+Abra: [https://console.cloud.google.com/apis/credentials](https://console.cloud.google.com/apis/credentials)
+
+**2. Crie um novo OAuth 2.0 Client ID**
+
+- Clique em **"+ Create Credentials"** → **"OAuth client ID"**
+- Tipo de aplicativo: **"Web application"**
+- Nome: escolha qualquer nome (ex: `OmniRoute Remote`)
+
+**3. Adicione as Authorized Redirect URIs**
+
+No campo **"Authorized redirect URIs"**, adicione:
+
+```
+https://seu-servidor.com/callback
+```
+
+> Substitua `seu-servidor.com` pelo domínio ou IP do seu servidor (inclua a porta se necessário, ex: `http://45.33.32.156:20128/callback`).
+
+**4. Salve e copie as credenciais**
+
+Após criar, o Google mostrará o **Client ID** e o **Client Secret**.
+
+**5. Configure as variáveis de ambiente**
+
+No seu `.env` (ou nas variáveis de ambiente do Docker):
+
+```bash
+# Para Antigravity:
+ANTIGRAVITY_OAUTH_CLIENT_ID=seu-client-id.apps.googleusercontent.com
+ANTIGRAVITY_OAUTH_CLIENT_SECRET=GOCSPX-seu-secret
+
+# Para Gemini CLI:
+GEMINI_OAUTH_CLIENT_ID=seu-client-id.apps.googleusercontent.com
+GEMINI_OAUTH_CLIENT_SECRET=GOCSPX-seu-secret
+GEMINI_CLI_OAUTH_CLIENT_SECRET=GOCSPX-seu-secret
+```
+
+**6. Reinicie o OmniRoute**
+
+```bash
+# Se usando npm:
+npm run dev
+
+# Se usando Docker:
+docker restart omniroute
+```
+
+**7. Tente conectar novamente**
+
+Dashboard → Providers → Antigravity (ou Gemini CLI) → OAuth
+
+Agora o Google redirecionará corretamente para `https://seu-servidor.com/callback` e a autenticação funcionará.
+
+---
+
+#### Workaround temporário (sem configurar credenciais próprias)
+
+Se não quiser criar credenciais próprias agora, ainda é possível usar o fluxo **manual de URL**:
+
+1. O OmniRoute abrirá a URL de autorização do Google
+2. Após você autorizar, o Google tentará redirecionar para `localhost` (que falha no servidor remoto)
+3. **Copie a URL completa** da barra de endereço do seu browser (mesmo que a página não carregue)
+4. Cole essa URL no campo que aparece no modal de conexão do OmniRoute
+5. Clique em **"Connect"**
+
+> Este workaround funciona porque o código de autorização na URL é válido independente do redirect ter carregado ou não.
+
-- **Runtime** : Node.js 18–22 LTS (⚠️ Node.js 24+ **není podporován** — nativní binární soubory `better-sqlite3` jsou nekompatibilní)
-- **Jazyk** : TypeScript 5.9 — **100% TypeScript** napříč `src/` a `open-sse/` ( `any` v základních modulech od verze 2.0)
-- **Framework** : Next.js 16 + React 19 + Tailwind CSS 4
-- **Databáze** : LowDB (JSON) + SQLite (stav domény + protokoly proxy + audit MCP + rozhodnutí o směrování)
-- **Schémata** : Zod (validace I/O nástrojů MCP, API smlouvy)
-- **Protokoly** : MCP (stdio/HTTP) + A2A v0.3 (JSON-RPC 2.0 + SSE)
-- **Streamování** : Události odeslané serverem (SSE)
-- **Autorizace** : OAuth 2.0 (PKCE) + JWT + API klíče + autorizace s rozsahem MCP
-- **Testování** : Node.js test runner + Vitest (900+ testů včetně unit, integračních, E2E)
-- **CI/CD** : Akce GitHubu (automatické publikování v npm + Docker Hub při vydání)
-- **Webová stránka** : [omniroute.online](https://omniroute.online)
-- **Balíček** : [npmjs.com/package/omniroute](https://www.npmjs.com/package/omniroute)
-- **Docker** : [hub.docker.com/r/diegosouzapw/omniroute](https://hub.docker.com/r/diegosouzapw/omniroute)
-- **Odolnost** : Jistič, exponenciální odstavení, ochrana proti hromům, falešné TLS, automatické kombinované samoopravování
+---
+
+
+
+## 🛠️ Tech Stack
+
+
+Click to expand tech stack details
+
+- **Runtime**: Node.js 18–22 LTS (⚠️ Node.js 24+ is **not supported** — `better-sqlite3` native binaries are incompatible)
+- **Language**: TypeScript 5.9 — **100% TypeScript** across `src/` and `open-sse/` (zero `any` in core modules since v2.0)
+- **Framework**: Next.js 16 + React 19 + Tailwind CSS 4
+- **Database**: LowDB (JSON) + SQLite (domain state + proxy logs + MCP audit + routing decisions)
+- **Schemas**: Zod (MCP tool I/O validation, API contracts)
+- **Protocols**: MCP (stdio/HTTP) + A2A v0.3 (JSON-RPC 2.0 + SSE)
+- **Streaming**: Server-Sent Events (SSE)
+- **Auth**: OAuth 2.0 (PKCE) + JWT + API Keys + MCP Scoped Authorization
+- **Testing**: Node.js test runner + Vitest (900+ tests including unit, integration, E2E)
+- **CI/CD**: GitHub Actions (auto npm publish + Docker Hub on release)
+- **Website**: [omniroute.online](https://omniroute.online)
+- **Package**: [npmjs.com/package/omniroute](https://www.npmjs.com/package/omniroute)
+- **Docker**: [hub.docker.com/r/diegosouzapw/omniroute](https://hub.docker.com/r/diegosouzapw/omniroute)
+- **Resilience**: Circuit breaker, exponential backoff, anti-thundering herd, TLS spoofing, auto-combo self-healing
+
+
---
-## 📖 Dokumentace
+## Dokumentace
-| Dokument | Popis |
-| ------------------------------------------------------------ | ----------------------------------------------------------------------- |
-| [Uživatelská příručka](docs/USER_GUIDE.md) | Poskytovatelé, kombinace, integrace CLI, nasazení |
-| [Referenční informace k API](docs/API_REFERENCE.md) | Všechny koncové body s příklady |
-| [MCP server](open-sse/mcp-server/README.md) | 16 nástrojů MCP, konfigurace IDE, klienti Python/TS/Go |
-| [Server A2A](src/lib/a2a/README.md) | Protokol JSON-RPC 2.0, dovednosti, streamování, správa úloh |
-| [Auto-Combo Engine](docs/auto-combo.md) | 6faktorové bodování, balíčky režimů, samoléčba |
-| [Odstraňování problémů](docs/TROUBLESHOOTING.md) | Běžné problémy a jejich řešení |
-| [Architektura](docs/ARCHITECTURE.md) | Architektura a interní prvky systému |
-| [Přispívání](CONTRIBUTING.md) | Nastavení a pokyny pro vývoj |
-| [Specifikace OpenAPI](docs/openapi.yaml) | Specifikace OpenAPI 3.0 |
-| [Bezpečnostní zásady](SECURITY.md) | Hlášení zranitelností a bezpečnostní postupy |
-| [Nasazení virtuálního počítače](docs/VM_DEPLOYMENT_GUIDE.md) | Kompletní průvodce: Nastavení virtuálního počítače + nginx + Cloudflare |
-| [Galerie funkcí](docs/FEATURES.md) | Vizuální prohlídka řídicího panelu se snímky obrazovky |
-| [Kontrolní seznam vydání](docs/RELEASE_CHECKLIST.md) | Kroky ověření před vydáním |
+| Document | Description |
+| ---------------------------------------------- | --------------------------------------------------- |
+| [User Guide](docs/USER_GUIDE.md) | Providers, combos, CLI integration, deployment |
+| [API Reference](docs/API_REFERENCE.md) | All endpoints with examples |
+| [MCP Server](open-sse/mcp-server/README.md) | 16 MCP tools, IDE configs, Python/TS/Go clients |
+| [A2A Server](src/lib/a2a/README.md) | JSON-RPC 2.0 protocol, skills, streaming, task mgmt |
+| [Auto-Combo Engine](docs/auto-combo.md) | 6-factor scoring, mode packs, self-healing |
+| [Troubleshooting](docs/TROUBLESHOOTING.md) | Common problems and solutions |
+| [Architecture](docs/ARCHITECTURE.md) | System architecture and internals |
+| [Contributing](CONTRIBUTING.md) | Development setup and guidelines |
+| [OpenAPI Spec](docs/openapi.yaml) | OpenAPI 3.0 specification |
+| [Security Policy](SECURITY.md) | Vulnerability reporting and security practices |
+| [VM Deployment](docs/VM_DEPLOYMENT_GUIDE.md) | Complete guide: VM + nginx + Cloudflare setup |
+| [Features Gallery](docs/FEATURES.md) | Visual dashboard tour with screenshots |
+| [Release Checklist](docs/RELEASE_CHECKLIST.md) | Pre-release validation steps |
---
-## 🗺️ Plán
+## 🗺️ Roadmap
-OmniRoute má **v plánu více než 210 funkcí** v několika fázích vývoje. Zde jsou klíčové oblasti:
+OmniRoute has **210+ features planned** across multiple development phases. Here are the key areas:
-| Kategorie | Plánované funkce | Hlavní body |
-| ---------------------------------------- | ---------------- | ------------------------------------------------------------------------------------------------------------------------ |
-| 🧠 **Směrování a inteligence** | 25+ | Směrování s nejnižší latencí, směrování založené na tagech, kontrola kvót před výstupem, výběr účtu P2C |
-| 🔒 **Zabezpečení a dodržování předpisů** | 20+ | Zpevnění SSRF, maskování přihlašovacích údajů, limit rychlosti pro každý koncový bod, stanovení rozsahu klíčů pro správu |
-| 📊 **Pozorovatelnost** | 15+ | Integrace OpenTelemetry, sledování kvót v reálném čase, sledování nákladů podle modelu |
-| 🔄 **Integrace poskytovatelů** | 20+ | Dynamický registr modelů, doba zchlazení poskytovatelů, Codex pro více účtů, analýza kvót Copilota |
-| ⚡ **Výkon** | 15+ | Dvojitá vrstva mezipaměti, mezipaměť výzev, mezipaměť odpovědí, udržování streamování, dávkové API |
-| 🌐 **Ekosystém** | 10+ | WebSocket API, horké opětovné načítání konfigurace, distribuované úložiště konfigurace, komerční režim |
+| Category | Planned Features | Highlights |
+| ----------------------------- | ---------------- | -------------------------------------------------------------------------------------- |
+| 🧠 **Routing & Intelligence** | 25+ | Lowest-latency routing, tag-based routing, quota preflight, P2C account selection |
+| 🔒 **Security & Compliance** | 20+ | SSRF hardening, credential cloaking, rate-limit per endpoint, management key scoping |
+| 📊 **Observability** | 15+ | OpenTelemetry integration, real-time quota monitoring, cost tracking per model |
+| 🔄 **Provider Integrations** | 20+ | Dynamic model registry, provider cooldowns, multi-account Codex, Copilot quota parsing |
+| ⚡ **Performance** | 15+ | Dual cache layer, prompt cache, response cache, streaming keepalive, batch API |
+| 🌐 **Ecosystem** | 10+ | WebSocket API, config hot-reload, distributed config store, commercial mode |
-### 🔜 Již brzy
+### 🔜 Coming Soon
-- 🔗 **Integrace OpenCode** — Nativní podpora poskytovatelů pro IDE kódování s AI v OpenCode
-- 🔗 **Integrace TRAE** — Plná podpora vývojového rámce TRAE pro umělou inteligenci
-- 📦 **Dávkové API** — Asynchronní dávkové zpracování hromadných požadavků
-- 🎯 **Směrování na základě tagů** — Směrování požadavků na základě vlastních tagů a metadat
-- 💰 **Strategie nejnižších nákladů** – Automaticky vybere nejlevnějšího dostupného poskytovatele
+- 🔗 **OpenCode Integration** — Native provider support for the OpenCode AI coding IDE
+- 🔗 **TRAE Integration** — Full support for the TRAE AI development framework
+- 📦 **Batch API** — Asynchronous batch processing for bulk requests
+- 🎯 **Tag-Based Routing** — Route requests based on custom tags and metadata
+- 💰 **Lowest-Cost Strategy** — Automatically select the cheapest available provider
-> 📝 Úplné specifikace funkcí jsou k dispozici v [`docs/new-features/`](docs/new-features/) (217 podrobných specifikací)
+> 📝 Full feature specifications available in [`docs/new-features/`](docs/new-features/) (217 detailed specs)
---
-## 👥 Přispěvatelé
+## 👥 Contributors
-[](https://github.com/diegosouzapw/OmniRoute/graphs/contributors)
+[](https://github.com/diegosouzapw/OmniRoute/graphs/contributors)
-### Jak přispět
+### How to Contribute
-1. Vytvoření forku repozitáře
-2. Vytvořte si vlastní větev feature ( `git checkout -b feature/amazing-feature` )
-3. Potvrďte změny ( `git commit -m 'Add amazing feature'` )
-4. Odeslat do větve ( `git push origin feature/amazing-feature` )
-5. Otevřít žádost o změny (pull request)
+1. Fork the repository
+2. Create your feature branch (`git checkout -b feature/amazing-feature`)
+3. Commit your changes (`git commit -m 'Add amazing feature'`)
+4. Push to the branch (`git push origin feature/amazing-feature`)
+5. Open a Pull Request
-Podrobné pokyny naleznete na [CONTRIBUTING.md](CONTRIBUTING.md) .
+See [CONTRIBUTING.md](CONTRIBUTING.md) for detailed guidelines.
-### Vydání nové verze
+### Releasing a New Version
```bash
# Create a release — npm publish happens automatically
@@ -1788,29 +2239,29 @@ gh release create v2.0.0 --title "v2.0.0" --generate-notes
---
-## 📊 Hvězdná historie
+## 📊 Star History
-## Hvězdáři v průběhu času
+## Stargazers over time
-## [](https://starchart.cc/diegosouzapw/OmniRoute)
+## [](https://starchart.cc/diegosouzapw/OmniRoute)
-## 🙏 Poděkování
+## 🙏 Acknowledgments
-Zvláštní poděkování patří **[9routeru](https://github.com/decolua/9router)** od **[decolua](https://github.com/decolua)** – původnímu projektu, který inspiroval tento fork. OmniRoute staví na tomto neuvěřitelném základu s dalšími funkcemi, multimodálními API a kompletním přepsáním TypeScriptu.
+Special thanks to **[9router](https://github.com/decolua/9router)** by **[decolua](https://github.com/decolua)** — the original project that inspired this fork. OmniRoute builds upon that incredible foundation with additional features, multi-modal APIs, and a full TypeScript rewrite.
-Zvláštní poděkování patří **[CLIProxyAPI](https://github.com/router-for-me/CLIProxyAPI)** – původní implementaci Go, která inspirovala tento JavaScriptový port.
+Special thanks to **[CLIProxyAPI](https://github.com/router-for-me/CLIProxyAPI)** — the original Go implementation that inspired this JavaScript port.
---
-## 📄 Licence
+## Licence
-Licence MIT - podrobnosti viz [LICENCE](LICENSE) .
+MIT License - see [LICENSE](LICENSE) for details.
---
-
Vytvořeno s ❤️ pro vývojáře, kteří programují 24 hodin denně, 7 dní v týdnu
-
-
omniroute.online
+
Built with ❤️ for developers who code 24/7
+
+
omniroute.online
diff --git a/docs/i18n/cs/RELEASE_CHECKLIST.md b/docs/i18n/cs/RELEASE_CHECKLIST.md
deleted file mode 100644
index 0a1768134f..0000000000
--- a/docs/i18n/cs/RELEASE_CHECKLIST.md
+++ /dev/null
@@ -1,33 +0,0 @@
-# Kontrolní seznam vydání
-
-Tento kontrolní seznam použijte před označením nebo publikováním nové verze OmniRoute.
-
-## Verze a seznam změn
-
-1. Navýšit verzi `package.json` ( `xyz` ) ve větvi release.
-2. Přesunout poznámky k vydání z `## [Unreleased]` v `CHANGELOG.md` do sekce s datem vydání:
- - `## [x.y.z] — YYYY-MM-DD`
-3. Ponechte `## [Unreleased]` jako první sekci changelogu pro nadcházející práci.
-4. Ujistěte se, že nejnovější sekce semver v `CHANGELOG.md` je rovna verzi `package.json` .
-
-## Dokumentace API
-
-1. Aktualizace `docs/openapi.yaml` :
- - Soubor `info.version` se musí rovnat verzi `package.json` .
-2. Ověřte příklady koncových bodů, pokud se změnily smlouvy API.
-
-## Dokumentace k běhovému prostředí
-
-1. Projděte si `docs/ARCHITECTURE.md` , zda nedochází k posunu v úložišti/běhovém prostředí.
-2. Projděte si soubor `docs/TROUBLESHOOTING.md` , kde naleznete informace o proměnné prostředí a provozním posunu.
-3. Aktualizujte lokalizovanou dokumentaci, pokud se zdrojová dokumentace výrazně změnila.
-
-## Automatická kontrola
-
-Před otevřením PR spusťte lokálně ochranu synchronizace:
-
-```bash
-npm run check:docs-sync
-```
-
-CI také spouští tuto kontrolu v `.github/workflows/ci.yml` (úloha lint).
diff --git a/docs/i18n/cs/SECURITY.md b/docs/i18n/cs/SECURITY.md
index da9eece3fa..8aed7b6782 100644
--- a/docs/i18n/cs/SECURITY.md
+++ b/docs/i18n/cs/SECURITY.md
@@ -1,129 +1,138 @@
-# Bezpečnostní zásady
+# Security Policy (Čeština)
-## Hlášení zranitelností
-
-Pokud v OmniRoute objevíte bezpečnostní zranitelnost, nahlaste ji prosím zodpovědně:
-
-1. **NEOTVÍREJTE** veřejný problém na GitHubu
-2. Používejte [bezpečnostní doporučení GitHubu](https://github.com/diegosouzapw/OmniRoute/security/advisories/new)
-3. Zahrňte: popis, kroky reprodukce a potenciální dopad
-
-## Časová osa odezvy
-
-Fáze | Cíl
---- | ---
-Potvrzení | 48 hodin
-Triáž a posouzení | 5 pracovních dnů
-Vydání záplaty | 14 pracovních dnů (kritické)
-
-## Podporované verze
-
-Verze | Stav podpory
---- | ---
-1.0.x | ✅ Aktivní
-0.8.x | ✅ Bezpečnost
-< 0,8,0 | ❌ Nepodporováno
+🌐 **Languages:** 🇺🇸 [English](../../../SECURITY.md) · 🇪🇸 [es](../es/SECURITY.md) · 🇫🇷 [fr](../fr/SECURITY.md) · 🇩🇪 [de](../de/SECURITY.md) · 🇮🇹 [it](../it/SECURITY.md) · 🇷🇺 [ru](../ru/SECURITY.md) · 🇨🇳 [zh-CN](../zh-CN/SECURITY.md) · 🇯🇵 [ja](../ja/SECURITY.md) · 🇰🇷 [ko](../ko/SECURITY.md) · 🇸🇦 [ar](../ar/SECURITY.md) · 🇮🇳 [in](../in/SECURITY.md) · 🇹🇭 [th](../th/SECURITY.md) · 🇻🇳 [vi](../vi/SECURITY.md) · 🇮🇩 [id](../id/SECURITY.md) · 🇲🇾 [ms](../ms/SECURITY.md) · 🇳🇱 [nl](../nl/SECURITY.md) · 🇵🇱 [pl](../pl/SECURITY.md) · 🇸🇪 [sv](../sv/SECURITY.md) · 🇳🇴 [no](../no/SECURITY.md) · 🇩🇰 [da](../da/SECURITY.md) · 🇫🇮 [fi](../fi/SECURITY.md) · 🇵🇹 [pt](../pt/SECURITY.md) · 🇷🇴 [ro](../ro/SECURITY.md) · 🇭🇺 [hu](../hu/SECURITY.md) · 🇧🇬 [bg](../bg/SECURITY.md) · 🇸🇰 [sk](../sk/SECURITY.md) · 🇺🇦 [uk-UA](../uk-UA/SECURITY.md) · 🇮🇱 [he](../he/SECURITY.md) · 🇵🇭 [phi](../phi/SECURITY.md) · 🇧🇷 [pt-BR](../pt-BR/SECURITY.md) · 🇨🇿 [cs](../cs/SECURITY.md)
---
-## Bezpečnostní architektura
+## Reporting Vulnerabilities
-OmniRoute implementuje vícevrstvý bezpečnostní model:
+If you discover a security vulnerability in OmniRoute, please report it responsibly:
+
+1. **DO NOT** open a public GitHub issue
+2. Use [GitHub Security Advisories](https://github.com/diegosouzapw/OmniRoute/security/advisories/new)
+3. Include: description, reproduction steps, and potential impact
+
+## Response Timeline
+
+| Stage | Target |
+| ------------------- | --------------------------- |
+| Acknowledgment | 48 hours |
+| Triage & Assessment | 5 business days |
+| Patch Release | 14 business days (critical) |
+
+## Supported Versions
+
+| Version | Support Status |
+| ------- | -------------- |
+| 3.4.x | ✅ Active |
+| 3.0.x | ✅ Security |
+| < 3.0.0 | ❌ Unsupported |
+
+---
+
+## Security Architecture
+
+OmniRoute implements a multi-layered security model:
```
Request → CORS → API Key Auth → Prompt Injection Guard → Input Sanitizer → Rate Limiter → Circuit Breaker → Provider
```
-### 🔐 Ověřování a autorizace
+### 🔐 Authentication & Authorization
-Funkce | Implementace
---- | ---
-**Přihlášení do ovládacího panelu** | Ověřování na základě hesla s tokeny JWT (soubory cookie HttpOnly)
-**Autorizace klíče API** | Klíče podepsané HMAC s ověřením CRC
-**OAuth 2.0 + PKCE** | Bezpečné ověřování poskytovatelů (Claude, Codex, Gemini, Cursor atd.)
-**Obnovení tokenu** | Automatická aktualizace tokenu OAuth před vypršením platnosti
-**Bezpečné soubory cookie** | `AUTH_COOKIE_SECURE=true` pro prostředí HTTPS
+| Feature | Implementation |
+| -------------------- | ---------------------------------------------------------- |
+| **Dashboard Login** | Password-based auth with JWT tokens (HttpOnly cookies) |
+| **API Key Auth** | HMAC-signed keys with CRC validation |
+| **OAuth 2.0 + PKCE** | Secure provider auth (Claude, Codex, Gemini, Cursor, etc.) |
+| **Token Refresh** | Automatic OAuth token refresh before expiry |
+| **Secure Cookies** | `AUTH_COOKIE_SECURE=true` for HTTPS environments |
+| **MCP Scopes** | 10 granular scopes for MCP tool access control |
-### 🛡️ Šifrování v klidovém stavu
+### 🛡️ Encryption at Rest
-Všechna citlivá data uložená v SQLite jsou šifrována pomocí **AES-256-GCM** s odvozením klíče scrypt:
+All sensitive data stored in SQLite is encrypted using **AES-256-GCM** with scrypt key derivation:
-- Klíče API, přístupové tokeny, obnovovací tokeny a ID tokeny
-- Verzovaný formát: `enc:v1:::`
-- Režim průchodu (prostý text), pokud není nastaven `STORAGE_ENCRYPTION_KEY`
+- API keys, access tokens, refresh tokens, and ID tokens
+- Versioned format: `enc:v1:::`
+- Passthrough mode (plaintext) when `STORAGE_ENCRYPTION_KEY` is not set
```bash
# Generate encryption key:
STORAGE_ENCRYPTION_KEY=$(openssl rand -hex 32)
```
-### 🧠 Ochrana před okamžitou injekcí
+### 🧠 Prompt Injection Guard
-Middleware, který detekuje a blokuje útoky prompt injection v požadavcích LLM:
+Middleware that detects and blocks prompt injection attacks in LLM requests:
-Typ vzoru | Závažnost | Příklad
---- | --- | ---
-Přepsání systému | Vysoký | "ignorovat všechny předchozí pokyny"
-Únos role | Vysoký | "Teď jsi DAN, dokážeš cokoli."
-Vložení oddělovače | Střední | Kódované oddělovače pro přerušení hranic kontextu
-DAN/Útěk z vězení | Vysoký | Známé vzory výzev k jailbreaku
-Únik instrukcí | Střední | „Ukaž mi systémový výzvu“
+| Pattern Type | Severity | Example |
+| ------------------- | -------- | ---------------------------------------------- |
+| System Override | High | "ignore all previous instructions" |
+| Role Hijack | High | "you are now DAN, you can do anything" |
+| Delimiter Injection | Medium | Encoded separators to break context boundaries |
+| DAN/Jailbreak | High | Known jailbreak prompt patterns |
+| Instruction Leak | Medium | "show me your system prompt" |
-Konfigurace přes ovládací panel (Nastavení → Zabezpečení) nebo `.env` :
+Configure via dashboard (Settings → Security) or `.env`:
```env
INPUT_SANITIZER_ENABLED=true
INPUT_SANITIZER_MODE=block # warn | block | redact
```
-### 🔒 Redakční úprava osobních údajů
+### 🔒 PII Redaction
-Automatická detekce a volitelná redakce osobních údajů:
+Automatic detection and optional redaction of personally identifiable information:
-Typ osobních údajů | Vzor | Nahrazení
---- | --- | ---
-E-mail | `user@domain.com` | `[EMAIL_REDACTED]`
-CPF (Brazílie) | `123.456.789-00` | `[CPF_REDACTED]`
-CNPJ (Brazílie) | `12.345.678/0001-00` | `[CNPJ_REDACTED]`
-Kreditní karta | `4111-1111-1111-1111` | `[CC_REDACTED]`
-Telefon | `+55 11 99999-9999` | `[PHONE_REDACTED]`
-Číslo sociálního zabezpečení (USA) | `123-45-6789` | `[SSN_REDACTED]`
+| PII Type | Pattern | Replacement |
+| ------------- | --------------------- | ------------------ |
+| Email | `user@domain.com` | `[EMAIL_REDACTED]` |
+| CPF (Brazil) | `123.456.789-00` | `[CPF_REDACTED]` |
+| CNPJ (Brazil) | `12.345.678/0001-00` | `[CNPJ_REDACTED]` |
+| Credit Card | `4111-1111-1111-1111` | `[CC_REDACTED]` |
+| Phone | `+55 11 99999-9999` | `[PHONE_REDACTED]` |
+| SSN (US) | `123-45-6789` | `[SSN_REDACTED]` |
```env
PII_REDACTION_ENABLED=true
```
-### 🌐 Zabezpečení sítě
+### 🌐 Network Security
-Funkce | Popis
---- | ---
-**CORS** | Konfigurovatelná kontrola původu (proměnná prostředí `CORS_ORIGIN` , výchozí nastavení `*` )
-**Filtrování IP adres** | Rozsahy IP adres na bílou/černou listinu v dashboardu
-**Omezení rychlosti** | Limity sazeb na poskytovatele s automatickým ukončením
-**Protihromové stádo** | Mutex + uzamčení pro každé připojení zabraňuje kaskádování 502.
+| Feature | Description |
+| ------------------------ | ---------------------------------------------------------------- |
+| **CORS** | Configurable origin control (`CORS_ORIGIN` env var, default `*`) |
+| **IP Filtering** | Allowlist/blocklist IP ranges in dashboard |
+| **Rate Limiting** | Per-provider rate limits with automatic backoff |
+| **Anti-Thundering Herd** | Mutex + per-connection locking prevents cascading 502s |
+| **TLS Fingerprint** | Browser-like TLS fingerprint spoofing to reduce bot detection |
+| **CLI Fingerprint** | Per-provider header/body ordering to match native CLI signatures |
-### 🔌 Odolnost a dostupnost
+### 🔌 Resilience & Availability
-Funkce | Popis
---- | ---
-**Jistič** | 3 stavy (Zavřeno → Otevřeno → Polootevřeno) na poskytovatele, trvalé uložení v SQLite
-**Žádost o idempotenci** | 5sekundové okno pro odstranění duplicitních požadavků
-**Exponenciální odklon** | Automatické opakování s rostoucím zpožděním
-**Dashboard zdraví** | Monitorování stavu poskytovatele v reálném čase
+| Feature | Description |
+| ----------------------- | ------------------------------------------------------------------ |
+| **Circuit Breaker** | 3-state (Closed → Open → Half-Open) per provider, SQLite-persisted |
+| **Request Idempotency** | 5-second dedup window for duplicate requests |
+| **Exponential Backoff** | Automatic retry with increasing delays |
+| **Health Dashboard** | Real-time provider health monitoring |
-### 📋 Dodržování předpisů
+### 📋 Compliance
-Funkce | Popis
---- | ---
-**Uchovávání protokolů** | Automatické čištění po `LOG_RETENTION_DAYS`
-**Odhlášení bez ukládání protokolů** | Příznak `noLog` pro každý klíč API zakazuje protokolování požadavků.
-**Protokol auditu** | Administrativní akce sledované v tabulce `audit_log`
+| Feature | Description |
+| ------------------ | ----------------------------------------------------------- |
+| **Log Retention** | Automatic cleanup after `CALL_LOG_RETENTION_DAYS` |
+| **No-Log Opt-out** | Per API key `noLog` flag disables request logging |
+| **Audit Log** | Administrative actions tracked in `audit_log` table |
+| **MCP Audit** | SQLite-backed audit logging for all MCP tool calls |
+| **Zod Validation** | All API inputs validated with Zod v4 schemas at module load |
---
-## Požadované proměnné prostředí
+## Required Environment Variables
-Všechny tajné kódy musí být nastaveny před spuštěním serveru. Server **rychle selže** , pokud chybí nebo jsou slabé.
+All secrets must be set before starting the server. The server will **fail fast** if they are missing or weak.
```bash
# REQUIRED — server will not start without these:
@@ -134,17 +143,17 @@ API_KEY_SECRET=$(openssl rand -hex 32) # min 16 chars
STORAGE_ENCRYPTION_KEY=$(openssl rand -hex 32)
```
-Server aktivně odmítá známé slabé hodnoty, jako například `changeme` , `secret` nebo `password` .
+The server actively rejects known-weak values like `changeme`, `secret`, or `password`.
---
-## Zabezpečení Dockeru
+## Docker Security
-- Použití uživatele bez oprávnění root v produkčním prostředí
-- Připojte tajné kódy jako svazky jen pro čtení
-- Nikdy nekopírujte soubory `.env` do imagí Dockeru
-- Použití `.dockerignore` k vyloučení citlivých souborů
-- Nastavit `AUTH_COOKIE_SECURE=true` při připojení za HTTPS
+- Use non-root user in production
+- Mount secrets as read-only volumes
+- Never copy `.env` files into Docker images
+- Use `.dockerignore` to exclude sensitive files
+- Set `AUTH_COOKIE_SECURE=true` when behind HTTPS
```bash
docker run -d \
@@ -161,9 +170,10 @@ docker run -d \
---
-## Závislosti
+## Dependencies
-- Pravidelně spouštějte `npm audit`
-- Udržujte závislosti aktualizované
-- Projekt používá pro kontroly před commitem `husky` + `lint-staged`
-- CI pipeline spouští bezpečnostní pravidla ESLint při každém odeslání.
+- Run `npm audit` regularly
+- Keep dependencies updated
+- The project uses `husky` + `lint-staged` for pre-commit checks
+- CI pipeline runs ESLint security rules on every push
+- Provider constants validated at module load via Zod (`src/shared/validation/providerSchema.ts`)
diff --git a/docs/i18n/cs/TROUBLESHOOTING.md b/docs/i18n/cs/TROUBLESHOOTING.md
deleted file mode 100644
index 8463bf7909..0000000000
--- a/docs/i18n/cs/TROUBLESHOOTING.md
+++ /dev/null
@@ -1,254 +0,0 @@
-# Odstraňování problémů
-
-🌐 **Jazyky:** 🇺🇸 [angličtina](TROUBLESHOOTING.md) | 🇧🇷 [Português (Brazílie)](i18n/pt-BR/TROUBLESHOOTING.md) | 🇪🇸 [Español](i18n/es/TROUBLESHOOTING.md) | 🇫🇷 [Français](i18n/fr/TROUBLESHOOTING.md) | 🇮🇹 [Italiano](i18n/it/TROUBLESHOOTING.md) | 🇷🇺 [Русский](i18n/ru/TROUBLESHOOTING.md) | 🇨🇳[中文 (简体)](i18n/zh-CN/TROUBLESHOOTING.md) | 🇩🇪 [Deutsch](i18n/de/TROUBLESHOOTING.md) | 🇮🇳 [हिन्दी](i18n/in/TROUBLESHOOTING.md) | 🇹🇭 [ไทย](i18n/th/TROUBLESHOOTING.md) | 🇺🇦 [Українська](i18n/uk-UA/TROUBLESHOOTING.md) | 🇸🇦 [العربية](i18n/ar/TROUBLESHOOTING.md) | 🇯🇵[日本語](i18n/ja/TROUBLESHOOTING.md)| 🇻🇳 [Tiếng Việt](i18n/vi/TROUBLESHOOTING.md) | 🇧🇬 [Български](i18n/bg/TROUBLESHOOTING.md) | 🇩🇰 [Dánsko](i18n/da/TROUBLESHOOTING.md) | 🇫🇮 [Suomi](i18n/fi/TROUBLESHOOTING.md) | 🇮🇱 [עברית](i18n/he/TROUBLESHOOTING.md) | 🇭🇺 [maďarština](i18n/hu/TROUBLESHOOTING.md) | 🇮🇩 [Bahasa Indonésie](i18n/id/TROUBLESHOOTING.md) | 🇰🇷 [한국어](i18n/ko/TROUBLESHOOTING.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/TROUBLESHOOTING.md) | 🇳🇱 [Nizozemsko](i18n/nl/TROUBLESHOOTING.md) | 🇳🇴 [Norsk](i18n/no/TROUBLESHOOTING.md) | 🇵🇹 [Português (Portugalsko)](i18n/pt/TROUBLESHOOTING.md) | 🇷🇴 [Română](i18n/ro/TROUBLESHOOTING.md) | 🇵🇱 [Polski](i18n/pl/TROUBLESHOOTING.md) | 🇸🇰 [Slovenčina](i18n/sk/TROUBLESHOOTING.md) | 🇸🇪 [Svenska](i18n/sv/TROUBLESHOOTING.md) | 🇵🇭 [Filipínec](i18n/phi/TROUBLESHOOTING.md) | 🇨🇿 [Čeština](i18n/cs/TROUBLESHOOTING.md)
-
-Běžné problémy a řešení pro OmniRoute.
-
----
-
-## Rychlé opravy
-
-| Problém | Řešení |
-| ----------------------------------------- | --------------------------------------------------------------------------------- |
-| První přihlášení nefunguje | Nastavit `INITIAL_PASSWORD` v `.env` (bez pevně zakódovaného výchozího nastavení) |
-| Dashboard se otevírá na nesprávném portu | Nastavte `PORT=20128` a `NEXT_PUBLIC_BASE_URL=http://localhost:20128` |
-| Žádné protokoly požadavků v sekci `logs/` | Nastavte `ENABLE_REQUEST_LOGS=true` |
-| PŘÍSTUP: povolení zamítnuto | Nastavením `DATA_DIR=/path/to/writable/dir` přepíšete `~/.omniroute` |
-| Strategie směrování se neukládá | Aktualizace na v1.4.11+ (oprava schématu Zod pro perzistenci nastavení) |
-
----
-
-## Problémy s poskytovateli
-
-### "Jazykový model neposkytoval zprávy"
-
-**Příčina:** Vyčerpání kvóty poskytovatele.
-
-**Opravit:**
-
-1. Zkontrolujte sledovač kvót na řídicím panelu
-2. Použijte kombinaci se záložními úrovněmi
-3. Přepnout na levnější/bezplatnou úroveň
-
-### Omezení rychlosti
-
-**Příčina:** Vyčerpání kvóty předplatného.
-
-**Opravit:**
-
-- Přidat záložní variantu: `cc/claude-opus-4-6 → glm/glm-4.7 → if/kimi-k2-thinking`
-- Použijte GLM/MiniMax jako levnou zálohu
-
-### Platnost tokenu OAuth vypršela
-
-OmniRoute automaticky obnovuje tokeny. Pokud problémy přetrvávají:
-
-1. Ovládací panel → Poskytovatel → Znovu připojit
-2. Odstranění a opětovné přidání připojení poskytovatele
-
----
-
-## Problémy s cloudem
-
-### Chyby synchronizace s cloudem
-
-1. Ověřte, zda `BASE_URL` odkazuje na vaši spuštěnou instanci (např. `http://localhost:20128` )
-2. Ověřte, zda `CLOUD_URL` odkazuje na váš cloudový koncový bod (např. `https://omniroute.dev` ).
-3. Udržujte hodnoty `NEXT_PUBLIC_*` zarovnané s hodnotami na straně serveru.
-
-### Cloud `stream=false` Vrací 500
-
-**Příznak:** `Unexpected token 'd'...` na cloudovém koncovém bodu pro nestreamovaná volání.
-
-**Příčina:** Upstream vrací datovou část SSE, zatímco klient očekává JSON.
-
-**Řešení:** Pro přímá volání z cloudu použijte `stream=true` . Lokální běhové prostředí zahrnuje záložní SSE→JSON.
-
-### Cloud hlásí připojení, ale „neplatný klíč API“.
-
-1. Vytvořte nový klíč z lokálního dashboardu ( `/api/keys` )
-2. Spuštění synchronizace s cloudem: Povolit cloud → Synchronizovat nyní
-3. Staré/nesynchronizované klíče mohou v cloudu stále vracet `401`
-
----
-
-## Problémy s Dockerem
-
-### Nástroj CLI se zobrazuje jako nenainstalovaný
-
-1. Zkontrolujte běhová pole: `curl http://localhost:20128/api/cli-tools/runtime/codex | jq`
-2. Pro přenosný režim: použijte cílový soubor image `runner-cli` (dodávané CLI)
-3. Pro režim připojení hostitele: nastavte `CLI_EXTRA_PATHS` a připojte adresář hostitele bin jako pouze pro čtení.
-4. Pokud `installed=true` a `runnable=false` : binární soubor byl nalezen, ale kontrola stavu selhala.
-
-### Rychlé ověření za běhu
-
-```bash
-curl -s http://localhost:20128/api/cli-tools/codex-settings | jq '{installed,runnable,commandPath,runtimeMode,reason}'
-curl -s http://localhost:20128/api/cli-tools/claude-settings | jq '{installed,runnable,commandPath,runtimeMode,reason}'
-curl -s http://localhost:20128/api/cli-tools/openclaw-settings | jq '{installed,runnable,commandPath,runtimeMode,reason}'
-```
-
----
-
-## Problémy s náklady
-
-### Vysoké náklady
-
-1. Zkontrolujte statistiky využití v sekci Nástěnka → Využití
-2. Přepnout primární model na GLM/MiniMax
-3. Pro nekritické úlohy použijte bezplatnou úroveň (Gemini CLI, Qoder).
-4. Nastavení rozpočtů nákladů pro každý klíč API: Dashboard → API klíče → Rozpočet
-
----
-
-## Ladění
-
-### Povolit protokoly požadavků
-
-V souboru `.env` nastavte `ENABLE_REQUEST_LOGS=true` . Protokoly se zobrazují v adresáři `logs/` .
-
-### Zkontrolujte stav poskytovatele
-
-```bash
-# Health dashboard
-http://localhost:20128/dashboard/health
-
-# API health check
-curl http://localhost:20128/api/monitoring/health
-```
-
-### Runtimové úložiště
-
-- Hlavní stav: `${DATA_DIR}/storage.sqlite` (poskytovatelé, kombinace, aliasy, klíče, nastavení)
-- Použití: SQLite tabulky v `storage.sqlite` ( `usage_history` , `call_logs` , `proxy_logs` ) + volitelné `${DATA_DIR}/log.txt` a `${DATA_DIR}/call_logs/`
-- Záznamy požadavků: `/logs/...` (pokud `ENABLE_REQUEST_LOGS=true` )
-
----
-
-## Problémy s jističi
-
-### Poskytovatel uvízl ve stavu OPEN (OTEVŘENO)
-
-Pokud je jistič poskytovatele VYPNUTÝ, požadavky jsou blokovány, dokud neuplyne doba ochlazování.
-
-**Opravit:**
-
-1. Přejděte do **nabídky Ovládací panel → Nastavení → Odolnost**
-2. Zkontrolujte kartu jističe u dotčeného poskytovatele
-3. Kliknutím na **Obnovit vše** vynulujete všechny jističe nebo počkejte, až vyprší doba zpoždění.
-4. Před resetováním ověřte, zda je poskytovatel skutečně dostupný.
-
-### Poskytovatel neustále vypíná jistič
-
-Pokud poskytovatel opakovaně přechází do stavu OTEVŘENO:
-
-1. Zkontrolujte **v části Dashboard → Stav → Stav poskytovatele** vzorec selhání.
-2. Přejděte do **Nastavení → Odolnost → Profily poskytovatelů** a zvyšte prahovou hodnotu selhání.
-3. Zkontrolujte, zda poskytovatel změnil limity API nebo vyžaduje opětovné ověření.
-4. Zkontrolujte telemetrii latence – vysoká latence může způsobit selhání z důvodu časového limitu.
-
----
-
-## Problémy s přepisem zvuku
-
-### Chyba „Nepodporovaný model“
-
-- Ujistěte se, že používáte správný prefix: `deepgram/nova-3` nebo `assemblyai/best`
-- Ověřte, zda je poskytovatel připojen v **nabídce Dashboard → Poskytovatelé.**
-
-### Přepis vrací prázdný výsledek nebo selže
-
-- Zkontrolujte podporované zvukové formáty: `mp3` , `wav` , `m4a` , `flac` , `ogg` , `webm`
-- Ověřte, zda je velikost souboru v rámci limitů poskytovatele (obvykle < 25 MB)
-- Zkontrolujte platnost klíče API poskytovatele v kartě poskytovatele
-
----
-
-## Ladění překladače
-
-Pro ladění problémů s překladem formátu použijte **Dashboard → Translator** :
-
-| Režim | Kdy použít |
-| -------------------- | ---------------------------------------------------------------------------------------------------------- |
-| **Dětské hřiště** | Porovnejte vstupní/výstupní formáty vedle sebe – vložte neúspěšný požadavek a podívejte se, jak se přeloží |
-| **Tester chatu** | Odesílejte živé zprávy a kontrolujte kompletní datovou část požadavků/odpovědí včetně záhlaví |
-| **Zkušební stolice** | Spusťte dávkové testy napříč kombinacemi formátů a zjistěte, které překlady jsou poškozené. |
-| **Živý monitor** | Sledujte tok požadavků v reálném čase a zachyťte občasné problémy s překladem |
-
-### Běžné problémy s formátováním
-
-- **Štítky myšlení se nezobrazují** – Zkontrolujte, zda cílový poskytovatel podporuje myšlení a nastavení rozpočtu myšlení.
-- **Volání nástrojů se vynechávají** – Některé překlady formátů mohou odstranit nepodporovaná pole; ověřte v režimu Playground.
-- **Chybí systémová výzva** – Claude a Gemini zpracovávají systémové výzvy odlišně; zkontrolujte překlad výstupu
-- **SDK vrací nezpracovaný řetězec místo objektu** – Opraveno ve verzi 1.1.0: sanitizér odpovědí nyní odstraňuje nestandardní pole ( `x_groq` , `usage_breakdown` atd.), která způsobují selhání validace OpenAI SDK v Pydantic.
-- **GLM/ERNIE odmítá `system` roli** — Opraveno ve verzi 1.1.0: normalizátor rolí automaticky slučoval systémové zprávy s uživatelskými zprávami pro nekompatibilní modely.
-- **role `developer` nebyla rozpoznána** – Opraveno ve verzi 1.1.0: automaticky převedeno na `system` pro poskytovatele, kteří nepoužívají OpenAI
-- **`json_schema` nefunguje s Gemini** — Opraveno ve verzi 1.1.0: `response_format` se nyní převádí na `responseMimeType` + `responseSchema` z Gemini.
-
----
-
-## Nastavení odolnosti
-
-### Automatické omezení rychlosti se nespouští
-
-- Automatické omezení rychlosti se vztahuje pouze na poskytovatele klíčů API (ne na OAuth/předplatné)
-- Ověřte **Nastavení → Odolnost → Profily poskytovatelů** mají povoleno automatické omezení rychlosti
-- Zkontrolujte, zda poskytovatel vrací stavové kódy `429` nebo hlavičky `Retry-After`
-
-### Ladění exponenciálního poklesu
-
-Profily poskytovatelů podporují tato nastavení:
-
-- **Základní zpoždění** — Počáteční doba čekání po prvním selhání (výchozí: 1 s)
-- **Max. zpoždění** — Maximální doba čekání (výchozí: 30 s)
-- **Násobitel** — O kolik se má zvýšit zpoždění za každou po sobě jdoucí chybu (výchozí: 2x)
-
-### Stádo proti hromům
-
-Když se na poskytovatele s omezenou rychlostí odesílá mnoho souběžných požadavků, OmniRoute použije mutex + automatické omezení rychlosti k serializaci požadavků a zabránění kaskádovým selháním. Toto je automatické pro poskytovatele klíčů API.
-
----
-
-## Volitelná taxonomie selhání RAG / LLM (16 problémů)
-
-Někteří uživatelé OmniRoute umisťují bránu před RAG nebo agent stacky. V těchto nastaveních je běžné vidět zvláštní vzorec: OmniRoute vypadá v pořádku (poskytovatelé aktivní, profily směrování v pořádku, žádná upozornění na limity rychlosti), ale konečná odpověď je stále nesprávná.
-
-V praxi tyto incidenty obvykle pocházejí z následného RAG kanálu, nikoli ze samotné brány.
-
-Pokud chcete sdílenou slovní zásobu pro popis těchto selhání, můžete použít WFGY ProblemMap, externí textový zdroj s licencí MIT, který definuje šestnáct opakujících se vzorců selhání RAG / LLM. Na obecné úrovni zahrnuje:
-
-- drift vyhledávání a narušené hranice kontextu
-- prázdné nebo zastaralé indexy a vektorové úložiště
-- vkládání versus sémantický nesoulad
-- problémy s assembly promptu a kontextovým oknem
-- logický kolaps a přehnaně sebevědomé odpovědi
-- selhání dlouhého řetězce a koordinace agentů
-- paměť více agentů a posun rolí
-- problémy s nasazením a objednáváním bootstrapů
-
-Myšlenka je jednoduchá:
-
-1. Při vyšetřování špatné odpovědi zaznamenejte:
- - úkol a požadavek uživatele
- - Kombinace trasy nebo poskytovatele v OmniRoute
- - jakýkoli kontext RAG použitý v následných fázích (načtené dokumenty, volání nástrojů atd.)
-2. Namapujte incident na jedno nebo dvě čísla z WFGY ProblemMap ( `No.1` … `No.16` ).
-3. Uložte číslo do vlastního řídicího panelu, runbooku nebo sledovače incidentů vedle protokolů OmniRoute.
-4. Pro rozhodnutí, zda je potřeba změnit RAG stack, retriever nebo směrovací strategii, použijte odpovídající stránku WFGY.
-
-Plný text a konkrétní recepty naleznete zde (licence MIT, pouze text):
-
-[Soubor README pro mapu problémů WFGY](https://github.com/onestardao/WFGY/blob/main/ProblemMap/README.md)
-
-Tuto část můžete ignorovat, pokud za OmniRoute nespouštěte RAG ani agenty.
-
----
-
-## Stále v koncích?
-
-- **Problémy s GitHubem** : [github.com/diegosouzapw/OmniRoute/issues](https://github.com/diegosouzapw/OmniRoute/issues)
-- **Architektura** : Viz [`docs/ARCHITECTURE.md`](ARCHITECTURE.md) pro interní podrobnosti
-- **Referenční informace k API** : Všechny koncové body naleznete v [`docs/API_REFERENCE.md`](API_REFERENCE.md)
-- **Panel stavu** : Zkontrolujte **Panel stavu, kde** najdete stav systému v reálném čase.
-- **Překladač** : Použijte **Dashboard → Překladač** k ladění problémů s formátem
diff --git a/docs/i18n/cs/USER_GUIDE.md b/docs/i18n/cs/USER_GUIDE.md
deleted file mode 100644
index ed29de006f..0000000000
--- a/docs/i18n/cs/USER_GUIDE.md
+++ /dev/null
@@ -1,808 +0,0 @@
-# Uživatelská příručka
-
-🌐 **Jazyky:** 🇺🇸 [angličtina](USER_GUIDE.md) | 🇧🇷 [Português (Brazílie)](i18n/pt-BR/USER_GUIDE.md) | 🇪🇸 [Español](i18n/es/USER_GUIDE.md) | 🇫🇷 [Français](i18n/fr/USER_GUIDE.md) | 🇮🇹 [Italiano](i18n/it/USER_GUIDE.md) | 🇷🇺 [Русский](i18n/ru/USER_GUIDE.md) | 🇨🇳[中文 (简体)](i18n/zh-CN/USER_GUIDE.md) | 🇩🇪 [Deutsch](i18n/de/USER_GUIDE.md) | 🇮🇳 [हिन्दी](i18n/in/USER_GUIDE.md) | 🇹🇭 [ไทย](i18n/th/USER_GUIDE.md) | 🇺🇦 [Українська](i18n/uk-UA/USER_GUIDE.md) | 🇸🇦 [العربية](i18n/ar/USER_GUIDE.md) | 🇯🇵[日本語](i18n/ja/USER_GUIDE.md)| 🇻🇳 [Tiếng Việt](i18n/vi/USER_GUIDE.md) | 🇧🇬 [Български](i18n/bg/USER_GUIDE.md) | 🇩🇰 [Dánsko](i18n/da/USER_GUIDE.md) | 🇫🇮 [Suomi](i18n/fi/USER_GUIDE.md) | 🇮🇱 [עברית](i18n/he/USER_GUIDE.md) | 🇭🇺 [maďarština](i18n/hu/USER_GUIDE.md) | 🇮🇩 [Bahasa Indonésie](i18n/id/USER_GUIDE.md) | 🇰🇷 [한국어](i18n/ko/USER_GUIDE.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/USER_GUIDE.md) | 🇳🇱 [Nizozemsko](i18n/nl/USER_GUIDE.md) | 🇳🇴 [Norsk](i18n/no/USER_GUIDE.md) | 🇵🇹 [Português (Portugalsko)](i18n/pt/USER_GUIDE.md) | 🇷🇴 [Română](i18n/ro/USER_GUIDE.md) | 🇵🇱 [Polski](i18n/pl/USER_GUIDE.md) | 🇸🇰 [Slovenčina](i18n/sk/USER_GUIDE.md) | 🇸🇪 [Svenska](i18n/sv/USER_GUIDE.md) | 🇵🇭 [Filipínec](i18n/phi/USER_GUIDE.md) | 🇨🇿 [Čeština](i18n/cs/USER_GUIDE.md)
-
-Kompletní průvodce konfigurací poskytovatelů, vytvářením kombinací, integrací nástrojů CLI a nasazením OmniRoute.
-
----
-
-## Obsah
-
-- [Ceny v kostce](#-pricing-at-a-glance)
-- [Případy použití](#-use-cases)
-- [Nastavení poskytovatele](#-provider-setup)
-- [Integrace s rozhraním CLI](#-cli-integration)
-- [Nasazení](#-deployment)
-- [Dostupné modely](#-available-models)
-- [Pokročilé funkce](#-advanced-features)
-
----
-
-## 💰 Přehled cen
-
-| Úroveň | Poskytovatel | Náklady | Obnovení kvóty | Nejlepší pro |
-| ----------------- | ----------------- | ---------------- | ------------------- | -------------------------- |
-| **💳 PŘEDPLATNÉ** | Claude Code (pro) | 20 USD měsíc | 5h + týdně | Již přihlášené |
-| | Kodex (Plus/Pro) | 20–200 USD/měsíc | 5h + týdně | Uživatele OpenAI |
-| | Gemini CLI | **ZDARMA** | 180K/mo + 1K/den | Každého! |
-| | GitHub Copilot | 10–19 USD/měsíc | Měsíční | Uživatele GitHubu |
-| **🔑 KLÍČ API** | DeepSeek | Dle užití | Žádné | Laciné uvažování |
-| | Groq | Dle užití | Žádné | Ultrarychlá inference |
-| | xAI (Grok) | Dle užití | Žádné | Grok 4 uvažování |
-| | Mistral | Dle užití | Žádné | Modely hostované v EU |
-| | Perplexity | Dle užití | Žádné | Rozšířené vyhledávání |
-| | Together AI | Dle užití | Žádné | Open Source modely |
-| | Fireworks AI | Dle užití | Žádné | Rychlé FLUX obrázky |
-| | Cerebras | Dle užití | Žádné | Rychlost destičkového čipu |
-| | Cohere | Dle užití | Žádné | Command R+ RAG |
-| | NVIDIA NIM | Dle užití | Žádné | Podnikové modely |
-| **💰 LEVNÉ** | GLM-4.7 | $0.6/1M | Denně 10:00 | Levná záloha |
-| | MiniMax M2.1 | $0.2/1M | 5hodinové válcování | Nejlevnější varianta |
-| | Kimi K2 | 9 USD měsíc | 10M tokens/měsíc | Předvídatelné náklady |
-| **🆓 ZDARMA** | Qoder | $0 | Neomezený | 8 modelů zdarma |
-| | Qwen | $0 | Neomezený | 3 modely zdarma |
-| | Kiro | $0 | Neomezený | Claude zdarma |
-
-**💡 Pro Tip:** Začněte s kombinací Gemini CLI (180K zdarma/měsíc) + Qoder (neomezeně zdarma) = $0!
-
----
-
-## 🎯 Případy použití
-
-### Případ 1: „Mám předplatné Claude Pro“
-
-**Problém:** Kvóta vyprší, nevyužitá, limity rychlosti během náročného kódování
-
-```
-Combo: "maximize-claude"
- 1. cc/claude-opus-4-6 (use subscription fully)
- 2. glm/glm-4.7 (cheap backup when quota out)
- 3. if/kimi-k2-thinking (free emergency fallback)
-
-Monthly cost: $20 (subscription) + ~$5 (backup) = $25 total
-vs. $20 + hitting limits = frustration
-```
-
-### Případ 2: „Chci nulové náklady“
-
-**Problém:** Nemůžu si dovolit předplatné, potřebuji spolehlivé kódování s využitím umělé inteligence
-
-```
-Combo: "free-forever"
- 1. gc/gemini-3-flash (180K free/month)
- 2. if/kimi-k2-thinking (unlimited free)
- 3. qw/qwen3-coder-plus (unlimited free)
-
-Monthly cost: $0
-Quality: Production-ready models
-```
-
-### Případ 3: „Potřebuji kódování 24 hodin denně, 7 dní v týdnu, bez přerušení“
-
-**Problém:** Termíny, nemůžeme si dovolit prostoje
-
-```
-Combo: "always-on"
- 1. cc/claude-opus-4-6 (best quality)
- 2. cx/gpt-5.2-codex (second subscription)
- 3. glm/glm-4.7 (cheap, resets daily)
- 4. minimax/MiniMax-M2.1 (cheapest, 5h reset)
- 5. if/kimi-k2-thinking (free unlimited)
-
-Result: 5 layers of fallback = zero downtime
-Monthly cost: $20-200 (subscriptions) + $10-20 (backup)
-```
-
-### Případ 4: „Chci BEZPLATNOU AI v OpenClaw“
-
-**Problém:** Potřebujete asistenta s umělou inteligencí v aplikacích pro zasílání zpráv, zcela zdarma
-
-```
-Combo: "openclaw-free"
- 1. if/glm-4.7 (unlimited free)
- 2. if/minimax-m2.1 (unlimited free)
- 3. if/kimi-k2-thinking (unlimited free)
-
-Monthly cost: $0
-Access via: WhatsApp, Telegram, Slack, Discord, iMessage, Signal...
-```
-
----
-
-## 📖 Nastavení poskytovatele
-
-### 🔐 Poskytovatelé předplatného
-
-#### Claude Code (Pro/Max)
-
-```bash
-Dashboard → Providers → Connect Claude Code
-→ OAuth login → Auto token refresh
-→ 5-hour + weekly quota tracking
-
-Models:
- cc/claude-opus-4-6
- cc/claude-sonnet-4-5-20250929
- cc/claude-haiku-4-5-20251001
-```
-
-**Tip pro profesionály:** Pro složité úkoly používejte Opus, pro rychlost Sonnet. OmniRoute sleduje kvótu pro každý model!
-
-#### OpenAI Codex (Plus/Pro)
-
-```bash
-Dashboard → Providers → Connect Codex
-→ OAuth login (port 1455)
-→ 5-hour + weekly reset
-
-Models:
- cx/gpt-5.2-codex
- cx/gpt-5.1-codex-max
-```
-
-#### Gemini CLI (ZDARMA 180 000/měsíc!)
-
-```bash
-Dashboard → Providers → Connect Gemini CLI
-→ Google OAuth
-→ 180K completions/month + 1K/day
-
-Models:
- gc/gemini-3-flash-preview
- gc/gemini-2.5-pro
-```
-
-**Nejlepší hodnota:** Obrovská bezplatná úroveň! Použijte ji před placenými úrovněmi.
-
-#### GitHub Copilot
-
-```bash
-Dashboard → Providers → Connect GitHub
-→ OAuth via GitHub
-→ Monthly reset (1st of month)
-
-Models:
- gh/gpt-5
- gh/claude-4.5-sonnet
- gh/gemini-3-pro
-```
-
-### 💰 Levní poskytovatelé
-
-#### GLM-4.7 (Denní reset, 0,6 USD/1 milion)
-
-1. Registrace: [Zhipu AI](https://open.bigmodel.cn/)
-2. Získejte klíč API z kódovacího plánu
-3. Nástěnka → Přidat klíč API: Poskytovatel: `glm` , klíč API: `your-key`
-
-**Použití:** `glm/glm-4.7` — **Tip pro profesionály:** Coding Plan nabízí 3× kvótu za cenu 1/7! Resetovat denně v 10:00.
-
-#### MiniMax M2.1 (5h reset, 0,20 $/1 milion)
-
-1. Registrace: [MiniMax](https://www.minimax.io/)
-2. Získat API klíč → Dashboard → Přidat API klíč
-
-**Použití:** `minimax/MiniMax-M2.1` — **Tip pro profesionály:** Nejlevnější varianta pro dlouhý kontext (1 milion tokenů)!
-
-#### Kimi K2 (paušální poplatek 9 dolarů měsíčně)
-
-1. Odebírat: [Moonshot AI](https://platform.moonshot.ai/)
-2. Získat API klíč → Dashboard → Přidat API klíč
-
-**Použití:** `kimi/kimi-latest` — **Tip pro profesionály:** Fixní cena 9 $/měsíc za 10 milionů tokenů = efektivní náklady 0,90 $/1 milion!
-
-### 🆓 Poskytovatelé ZDARMA
-
-#### Qoder (8 modelů ZDARMA)
-
-```bash
-Dashboard → Connect Qoder → OAuth login → Unlimited usage
-
-Models: if/kimi-k2-thinking, if/qwen3-coder-plus, if/glm-4.7, if/minimax-m2, if/deepseek-r1
-```
-
-#### Qwen (3 modely ZDARMA)
-
-```bash
-Dashboard → Connect Qwen → Device code auth → Unlimited usage
-
-Models: qw/qwen3-coder-plus, qw/qwen3-coder-flash
-```
-
-#### Kiro (Claude ZDARMA)
-
-```bash
-Dashboard → Connect Kiro → AWS Builder ID or Google/GitHub → Unlimited
-
-Models: kr/claude-sonnet-4.5, kr/claude-haiku-4.5
-```
-
----
-
-## 🎨 Kombinace
-
-### Příklad 1: Maximalizace předplatného → Levné zálohování
-
-```
-Dashboard → Combos → Create New
-
-Name: premium-coding
-Models:
- 1. cc/claude-opus-4-6 (Subscription primary)
- 2. glm/glm-4.7 (Cheap backup, $0.6/1M)
- 3. minimax/MiniMax-M2.1 (Cheapest fallback, $0.20/1M)
-
-Use in CLI: premium-coding
-```
-
-### Příklad 2: Pouze zdarma (nulové náklady)
-
-```
-Name: free-combo
-Models:
- 1. gc/gemini-3-flash-preview (180K free/month)
- 2. if/kimi-k2-thinking (unlimited)
- 3. qw/qwen3-coder-plus (unlimited)
-
-Cost: $0 forever!
-```
-
----
-
-## 🔧 Integrace s rozhraním příkazového řádku
-
-### IDE kurzoru
-
-```
-Settings → Models → Advanced:
- OpenAI API Base URL: http://localhost:20128/v1
- OpenAI API Key: [from omniroute dashboard]
- Model: cc/claude-opus-4-6
-```
-
-### Claude Code
-
-Upravit `~/.claude/config.json` :
-
-```json
-{
- "anthropic_api_base": "http://localhost:20128/v1",
- "anthropic_api_key": "your-omniroute-api-key"
-}
-```
-
-### Codex CLI
-
-```bash
-export OPENAI_BASE_URL="http://localhost:20128"
-export OPENAI_API_KEY="your-omniroute-api-key"
-codex "your prompt"
-```
-
-### OpenClaw
-
-Upravit `~/.openclaw/openclaw.json` :
-
-```json
-{
- "agents": {
- "defaults": {
- "model": { "primary": "omniroute/if/glm-4.7" }
- }
- },
- "models": {
- "providers": {
- "omniroute": {
- "baseUrl": "http://localhost:20128/v1",
- "apiKey": "your-omniroute-api-key",
- "api": "openai-completions",
- "models": [{ "id": "if/glm-4.7", "name": "glm-4.7" }]
- }
- }
- }
-}
-```
-
-**Nebo použijte Dashboard:** CLI Tools → OpenClaw → Auto-config
-
-### Cline / Pokračovat / RooCode
-
-```
-Provider: OpenAI Compatible
-Base URL: http://localhost:20128/v1
-API Key: [from dashboard]
-Model: cc/claude-opus-4-6
-```
-
----
-
-## 🚀 Nasazení
-
-### Globální instalace npm (doporučeno)
-
-```bash
-npm install -g omniroute
-
-# Create config directory
-mkdir -p ~/.omniroute
-
-# Create .env file (see .env.example)
-cp .env.example ~/.omniroute/.env
-
-# Start server
-omniroute
-# Or with custom port:
-omniroute --port 3000
-```
-
-CLI automaticky načte `.env` z adresáře `~/.omniroute/.env` nebo `./.env` .
-
-### Nasazení VPS
-
-```bash
-git clone https://github.com/diegosouzapw/OmniRoute.git
-cd OmniRoute && npm install && npm run build
-
-export JWT_SECRET="your-secure-secret-change-this"
-export INITIAL_PASSWORD="your-password"
-export DATA_DIR="/var/lib/omniroute"
-export PORT="20128"
-export HOSTNAME="0.0.0.0"
-export NODE_ENV="production"
-export NEXT_PUBLIC_BASE_URL="http://localhost:20128"
-export API_KEY_SECRET="endpoint-proxy-api-key-secret"
-
-npm run start
-# Or: pm2 start npm --name omniroute -- start
-```
-
-### Nasazení PM2 (málo paměti)
-
-Pro servery s omezenou pamětí RAM použijte možnost omezení paměti:
-
-```bash
-# With 512MB limit (default)
-pm2 start npm --name omniroute -- start
-
-# Or with custom memory limit
-OMNIROUTE_MEMORY_MB=512 pm2 start npm --name omniroute -- start
-
-# Or using ecosystem.config.js
-pm2 start ecosystem.config.js
-```
-
-Vytvořte soubor `ecosystem.config.js` :
-
-```javascript
-module.exports = {
- apps: [
- {
- name: "omniroute",
- script: "npm",
- args: "start",
- env: {
- NODE_ENV: "production",
- OMNIROUTE_MEMORY_MB: "512",
- JWT_SECRET: "your-secret",
- INITIAL_PASSWORD: "your-password",
- },
- node_args: "--max-old-space-size=512",
- max_memory_restart: "300M",
- },
- ],
-};
-```
-
-### Přístavní dělník
-
-```bash
-# Build image (default = runner-cli with codex/claude/droid preinstalled)
-docker build -t omniroute:cli .
-
-# Portable mode (recommended)
-docker run -d --name omniroute -p 20128:20128 --env-file ./.env -v omniroute-data:/app/data omniroute:cli
-```
-
-Informace o režimu integrovaném s hostitelem s binárními soubory CLI naleznete v části Docker v hlavní dokumentaci.
-
-### Proměnné prostředí
-
-| Proměnná | Výchozí | Popis |
-| ------------------------- | ------------------------------------ | ------------------------------------------------------------------ |
-| `JWT_SECRET` | `omniroute-default-secret-change-me` | Tajný klíč podpisu JWT ( **změna v produkčním prostředí** ) |
-| `INITIAL_PASSWORD` | `123456` | První přihlašovací heslo |
-| `DATA_DIR` | `~/.omniroute` | Datový adresář (db, využití, protokoly) |
-| `PORT` | výchozí nastavení rámce | Servisní port ( `20128` v příkladech) |
-| `HOSTNAME` | výchozí nastavení rámce | Vázat hostitele (Docker má výchozí hodnotu `0.0.0.0` ) |
-| `NODE_ENV` | výchozí nastavení za běhu | Nastavení `production` pro nasazení |
-| `BASE_URL` | `http://localhost:20128` | Interní základní URL na straně serveru |
-| `CLOUD_URL` | `https://omniroute.dev` | Základní adresa URL koncového bodu synchronizace s cloudem |
-| `API_KEY_SECRET` | `endpoint-proxy-api-key-secret` | Tajný klíč HMAC pro generované klíče API |
-| `REQUIRE_API_KEY` | `false` | Vynutit klíč rozhraní Bearer API na `/v1/*` |
-| `ENABLE_REQUEST_LOGS` | `false` | Povoluje protokolování požadavků/odpovědí |
-| `AUTH_COOKIE_SECURE` | `false` | Vynutit soubor cookie `Secure` ověřování (za reverzní proxy HTTPS) |
-| `OMNIROUTE_MEMORY_MB` | `512` | Limit haldy Node.js v MB |
-| `PROMPT_CACHE_MAX_SIZE` | `50` | Maximální počet položek mezipaměti výzev |
-| `SEMANTIC_CACHE_MAX_SIZE` | `100` | Maximální počet položek sémantické mezipaměti |
-
-Úplný přehled proměnných prostředí naleznete v souboru [README](../README.md) .
-
----
-
-## 📊 Dostupné modely
-
-
-Zobrazit všechny dostupné modely
-
-
-**Claude Code ( `cc/` )** — Pro/Max: `cc/claude-opus-4-6` , `cc/claude-sonnet-4-5-20250929` , `cc/claude-haiku-4-5-20251001`
-
-**Codex ( `cx/` )** — Plus/Pro: `cx/gpt-5.2-codex` , `cx/gpt-5.1-codex-max`
-
-**Gemini CLI ( `gc/` )** — ZDARMA: `gc/gemini-3-flash-preview` , `gc/gemini-2.5-pro`
-
-**GitHub Copilot ( `gh/` )** : `gh/gpt-5` , `gh/claude-4.5-sonnet`
-
-**GLM ( `glm/` )** — 0,6 USD/1 milion: `glm/glm-4.7`
-
-**MiniMax ( `minimax/` )** — 0,2 USD/1 milion: `minimax/MiniMax-M2.1`
-
-**Qoder ( `if/` )** — ZDARMA: `if/kimi-k2-thinking` , `if/qwen3-coder-plus` , `if/deepseek-r1`
-
-**Qwen ( `qw/` )** — ZDARMA: `qw/qwen3-coder-plus` , `qw/qwen3-coder-flash`
-
-**Kiro ( `kr/` )** — ZDARMA: `kr/claude-sonnet-4.5` , `kr/claude-haiku-4.5`
-
-**DeepSeek ( `ds/` )** : `ds/deepseek-chat` , `ds/deepseek-reasoner`
-
-**Groq ( `groq/` )** : `groq/llama-3.3-70b-versatile` , `groq/llama-4-maverick-17b-128e-instruct`
-
-**xAI ( `xai/` )** : `xai/grok-4` , `xai/grok-4-0709-fast-reasoning` , `xai/grok-code-mini`
-
-**Mistral ( `mistral/` )** : `mistral/mistral-large-2501` , `mistral/codestral-2501`
-
-**Zmatek ( `pplx/` )** : `pplx/sonar-pro` , `pplx/sonar`
-
-**Společně AI ( `together/` )** : `together/meta-llama/Llama-3.3-70B-Instruct-Turbo`
-
-**Umělá inteligence pro ohňostroje ( `fireworks/` )** : `fireworks/accounts/fireworks/models/deepseek-v3p1`
-
-**Cerebras ( `cerebras/` )** : `cerebras/llama-3.3-70b`
-
-**Soudržnost ( `cohere/` )** : `cohere/command-r-plus-08-2024`
-
-**NVIDIA NIM ( `nvidia/` )** : `nvidia/nvidia/llama-3.3-70b-instruct`
-
----
-
-## 🧩 Pokročilé funkce
-
-### Vlastní modely
-
-Přidejte libovolné ID modelu k libovolnému poskytovateli bez čekání na aktualizaci aplikace:
-
-```bash
-# Via API
-curl -X POST http://localhost:20128/api/provider-models \
- -H "Content-Type: application/json" \
- -d '{"provider": "openai", "modelId": "gpt-4.5-preview", "modelName": "GPT-4.5 Preview"}'
-
-# List: curl http://localhost:20128/api/provider-models?provider=openai
-# Remove: curl -X DELETE "http://localhost:20128/api/provider-models?provider=openai&model=gpt-4.5-preview"
-```
-
-Nebo použijte Dashboard: **Poskytovatelé → [Poskytovatel] → Vlastní modely** .
-
-### Vyhrazené trasy poskytovatelů
-
-Směrování požadavků přímo ke konkrétnímu poskytovateli s validací modelu:
-
-```bash
-POST http://localhost:20128/v1/providers/openai/chat/completions
-POST http://localhost:20128/v1/providers/openai/embeddings
-POST http://localhost:20128/v1/providers/fireworks/images/generations
-```
-
-Pokud chybí prefix poskytovatele, automaticky se přidá. Neshodné modely vrátí chybu `400` .
-
-### Konfigurace síťového proxy serveru
-
-```bash
-# Set global proxy
-curl -X PUT http://localhost:20128/api/settings/proxy \
- -d '{"global": {"type":"http","host":"proxy.example.com","port":"8080"}}'
-
-# Per-provider proxy
-curl -X PUT http://localhost:20128/api/settings/proxy \
- -d '{"providers": {"openai": {"type":"socks5","host":"proxy.example.com","port":"1080"}}}'
-
-# Test proxy
-curl -X POST http://localhost:20128/api/settings/proxy/test \
- -d '{"proxy":{"type":"socks5","host":"proxy.example.com","port":"1080"}}'
-```
-
-**Priorita:** Specifická pro klíč → Specifická pro kombinaci → Specifická pro poskytovatele → Globální → Prostředí.
-
-### API katalogu modelů
-
-```bash
-curl http://localhost:20128/api/models/catalog
-```
-
-Vrátí modely seskupené podle poskytovatele s typy ( `chat` , `embedding` , `image` ).
-
-### Synchronizace s cloudem
-
-- Synchronizace poskytovatelů, kombinací a nastavení napříč zařízeními
-- Automatická synchronizace na pozadí s časovým limitem + rychlá ochrana proti selhání
-- V produkčním prostředí preferovat `BASE_URL` / `CLOUD_URL` na straně serveru
-
-### LLM Gateway Intelligence (fáze 9)
-
-- **Sémantická mezipaměť** — Automaticky ukládá do mezipaměti nestreamované odpovědi s teplotou 0 (obejde se pomocí `X-OmniRoute-No-Cache: true` )
-- **Request Idempotency** — Deduplikuje požadavky do 5 sekund pomocí hlavičky `Idempotency-Key` nebo `X-Request-Id`
-- **Sledování průběhu** — `event: progress` prostřednictvím záhlaví `X-OmniRoute-Progress: true`
-
----
-
-### Hřiště překladatelů
-
-Přístup přes **Dashboard → Translator** . Ladění a vizualizace toho, jak OmniRoute překládá požadavky API mezi poskytovateli.
-
-| Režim | Účel |
-| -------------------- | ------------------------------------------------------------------------------------------- |
-| **Dětské hřiště** | Vyberte zdrojový/cílový formát, vložte požadavek a okamžitě si prohlédněte přeložený výstup |
-| **Tester chatu** | Odesílejte zprávy živého chatu přes proxy a kontrolujte celý cyklus požadavku/odpovědi |
-| **Zkušební stolice** | Spusťte dávkové testy napříč různými kombinacemi formátů pro ověření správnosti překladu |
-| **Živý monitor** | Sledujte překlady v reálném čase, jak požadavky procházejí proxy serverem |
-
-**Případy použití:**
-
-- Ladění, proč selhává určitá kombinace klienta/poskytovatele
-- Ověřte, zda se tagy myšlení, volání nástrojů a systémové výzvy správně překládají.
-- Porovnejte rozdíly ve formátech OpenAI, Claude, Gemini a Responses API
-
----
-
-### Strategie směrování
-
-Konfigurace přes **Dashboard → Nastavení → Routing** .
-
-| Strategie | Popis |
-| ---------------------------- | ------------------------------------------------------------------------------------------------- |
-| **Nejprve vyplňte** | Používá účty podle priority – primární účet zpracovává všechny požadavky, dokud není k dispozici. |
-| **Round Robin** | Cykluje mezi všemi účty s nastavitelným trvalým limitem (výchozí: 3 volání na účet) |
-| **P2C (Síla dvou možností)** | Vybere 2 náhodné účty a nasměruje je k tomu zdravějšímu – vyvažuje zátěž s povědomím o zdraví |
-| **Náhodný** | Náhodně vybere účet pro každý požadavek pomocí Fisher-Yatesova náhodného výběru. |
-| **Nejméně používané** | Směruje k účtu s nejstarším časovým razítkem `lastUsedAt` a rovnoměrně rozděluje provoz. |
-| **Optimalizované náklady** | Směruje k účtu s nejnižší prioritou a optimalizuje pro poskytovatele s nejnižšími náklady. |
-
-#### Aliasy zástupných znaků modelů
-
-Vytvořte zástupné znaky pro přemapování názvů modelů:
-
-```
-Pattern: claude-sonnet-* → Target: cc/claude-sonnet-4-5-20250929
-Pattern: gpt-* → Target: gh/gpt-5.1-codex
-```
-
-Zástupné znaky podporují `*` (libovolný znak) a `?` (jeden znak).
-
-#### Záložní řetězce
-
-Definujte globální záložní řetězce, které platí pro všechny požadavky:
-
-```
-Chain: production-fallback
- 1. cc/claude-opus-4-6
- 2. gh/gpt-5.1-codex
- 3. glm/glm-4.7
-```
-
----
-
-### Odolnost a jističe
-
-Konfigurace přes **Dashboard → Settings → Resilience** .
-
-OmniRoute implementuje odolnost na úrovni poskytovatele se čtyřmi komponentami:
-
-1. **Profily poskytovatelů** – Konfigurace pro jednotlivé poskytovatele pro:
- - Práh selhání (počet selhání před otevřením)
- - Doba zchlazení
- - Citlivost detekce limitu frekvence
- - Exponenciální backoff parametry
-
-2. **Upravitelné limity rychlosti** – Výchozí nastavení na úrovni systému konfigurovatelná na řídicím panelu:
- - **Požadavky za minutu (RPM)** — Maximální počet požadavků za minutu na účet
- - **Minimální doba mezi požadavky** — Minimální mezera v milisekundách mezi požadavky
- - **Max. počet souběžných požadavků** — Maximální počet souběžných požadavků na účet
- - Klikněte na **Upravit** pro úpravu a poté **na Uložit** nebo **Zrušit** . Hodnoty se ukládají prostřednictvím rozhraní API pro odolnost.
-
-3. **Jistič** – Sleduje poruchy u jednotlivých poskytovatelů a automaticky rozpojuje obvod, když je dosaženo prahové hodnoty:
- - **ZAVŘENO** (v pořádku) – Požadavky probíhají normálně.
- - **OTEVŘENO** — Poskytovatel je dočasně zablokován po opakovaných selháních
- - **HALF_OPEN** — Testování, zda se poskytovatel zotavil
-
-4. **Zásady a uzamčené identifikátory** – Zobrazuje stav jističe a uzamčené identifikátory s možností vynuceného odemčení.
-
-5. **Automatická detekce limitu rychlosti** – Monitoruje záhlaví `429` a `Retry-After` , aby se proaktivně zabránilo dosažení limitů rychlosti poskytovatele.
-
-**Tip pro profesionály:** Pomocí tlačítka **Obnovit vše** vymažete všechny jističe a doby ochlazování, když se poskytovatel zotaví z výpadku.
-
----
-
-### Export / import databáze
-
-Správa záloh databáze se provádí v **nabídce Ovládací panel → Nastavení → Systém a úložiště** .
-
-| Akce | Popis |
-| ---------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------ |
-| **Exportovat databázi** | Stáhne aktuální databázi SQLite jako soubor `.sqlite` |
-| **Exportovat vše (.tar.gz)** | Stáhne kompletní zálohu včetně: databáze, nastavení, kombinací, připojení k poskytovatelům (bez přihlašovacích údajů) a metadat klíče API. |
-| **Importovat databázi** | Nahrajte soubor `.sqlite` , který nahradí aktuální databázi. Záloha před importem se vytvoří automaticky. |
-
-```bash
-# API: Export database
-curl -o backup.sqlite http://localhost:20128/api/db-backups/export
-
-# API: Export all (full archive)
-curl -o backup.tar.gz http://localhost:20128/api/db-backups/exportAll
-
-# API: Import database
-curl -X POST http://localhost:20128/api/db-backups/import \
- -F "file=@backup.sqlite"
-```
-
-**Ověření importu:** Importovaný soubor je ověřen z hlediska integrity (kontrola pragma SQLite), požadovaných tabulek ( `provider_connections` , `provider_nodes` , `combos` , `api_keys` ) a velikosti (max. 100 MB).
-
-**Případy použití:**
-
-- Migrace OmniRoute mezi počítači
-- Vytvořte externí zálohy pro zotavení po havárii
-- Sdílení konfigurací mezi členy týmu (exportovat vše → sdílet archiv)
-
----
-
-### Ovládací panel nastavení
-
-Stránka nastavení je pro snadnou navigaci uspořádána do 5 záložek:
-
-| Záložka | Obsah |
-| --------------------- | ---------------------------------------------------------------------------------------------------------------- |
-| **Zabezpečení** | Nastavení přihlášení/hesla, řízení přístupu k IP adrese, autorizace API pro `/models` a blokování poskytovatelů |
-| **Směrování** | Globální strategie směrování (6 možností), aliasy zástupných znaků, záložní řetězce, kombinované výchozí hodnoty |
-| **Odolnost** | Profily poskytovatelů, upravitelné limity sazeb, stav jističů, zásady a uzamčené identifikátory |
-| **Umělá inteligence** | Konfigurace rozpočtu promyšleného projektu, globální vkládání promptu do systému, statistiky mezipaměti promptu |
-| **Moderní** | Globální konfigurace proxy (HTTP/SOCKS5) |
-
----
-
-### Správa nákladů a rozpočtu
-
-Přístup přes **Dashboard → Náklady** .
-
-| Záložka | Účel |
-| ------------ | ----------------------------------------------------------------------------------------------------------- |
-| **Rozpočet** | Nastavte limity útrat pro každý klíč API s denními/týdenními/měsíčními rozpočty a sledováním v reálném čase |
-| **Ceny** | Zobrazení a úprava cenových položek modelu – cena za 1000 vstupních/výstupních tokenů na poskytovatele |
-
-```bash
-# API: Set a budget
-curl -X POST http://localhost:20128/api/usage/budget \
- -H "Content-Type: application/json" \
- -d '{"keyId": "key-123", "limit": 50.00, "period": "monthly"}'
-
-# API: Get current budget status
-curl http://localhost:20128/api/usage/budget
-```
-
-**Sledování nákladů:** Každý požadavek zaznamenává využití tokenů a vypočítává náklady pomocí ceníkové tabulky. Rozdělení si můžete prohlédnout v **sekci Dashboard → Využití** podle poskytovatele, modelu a klíče API.
-
----
-
-### Přepis zvuku
-
-OmniRoute podporuje přepis zvuku prostřednictvím koncového bodu kompatibilního s OpenAI:
-
-```bash
-POST /v1/audio/transcriptions
-Authorization: Bearer your-api-key
-Content-Type: multipart/form-data
-
-# Example with curl
-curl -X POST http://localhost:20128/v1/audio/transcriptions \
- -H "Authorization: Bearer your-api-key" \
- -F "file=@audio.mp3" \
- -F "model=deepgram/nova-3"
-```
-
-Dostupní poskytovatelé: **Deepgram** ( `deepgram/` ), **AssemblyAI** ( `assemblyai/` ).
-
-Podporované zvukové formáty: `mp3` , `wav` , `m4a` , `flac` , `ogg` , `webm` .
-
----
-
-### Strategie kombinovaného vyvažování
-
-Nastavte vyvažování jednotlivých kombinací v **nabídce Dashboard → Kombinace → Vytvořit/Upravit → Strategie** .
-
-| Strategie | Popis |
-| ------------------------------------- | ------------------------------------------------------------------------------------- |
-| **Round-Robin** | Postupně prochází modely |
-| **Přednost** | Vždy se pokusí o první model; vrací se pouze v případě chyby. |
-| **Náhodný** | Pro každý požadavek vybere náhodný model z komba |
-| **Vážené** | Trasy proporcionálně na základě přiřazených vah pro každý model |
-| **Nejméně používané** | Směruje k modelu s nejmenším počtem nedávných požadavků (používá kombinované metriky) |
-| **Optimalizované z hlediska nákladů** | Trasy k nejlevnějšímu dostupnému modelu (používá ceník) |
-
-Globální výchozí hodnoty kombinací lze nastavit v **nabídce Dashboard → Settings → Routing → Combo Defaults** .
-
----
-
-### Dashboard zdraví
-
-Přístup přes **Dashboard → Stav** . Přehled stavu systému v reálném čase se 6 kartami:
-
-| Karta | Co to ukazuje |
-| ------------------------ | ------------------------------------------------------------------ |
-| **Stav systému** | Doba provozuschopnosti, verze, využití paměti, datový adresář |
-| **Zdraví poskytovatelů** | Stav jističe podle dodavatele (Zapnuto/Vypnuto/Napůl vypnuto) |
-| **Limity sazeb** | Aktivní limit rychlosti cooldownů na účet se zbývajícím časem |
-| **Aktivní výluky** | Poskytovatelé dočasně blokovaní politikou uzamčení |
-| **Mezipaměť podpisů** | Statistiky mezipaměti pro deduplikaci (aktivní klíče, míra zásahů) |
-| **Telemetrie latence** | Agregace latence p50/p95/p99 na poskytovatele |
-
-**Tip pro profesionály:** Stránka Zdraví se automaticky obnovuje každých 10 sekund. Pomocí karty jističe můžete zjistit, kteří poskytovatelé mají problémy.
-
----
-
-## 🖥️ Desktopová aplikace (Electron)
-
-OmniRoute je k dispozici jako nativní desktopová aplikace pro Windows, macOS a Linux.
-
-### Instalace
-
-```bash
-# From the electron directory:
-cd electron
-npm install
-
-# Development mode (connect to running Next.js dev server):
-npm run dev
-
-# Production mode (uses standalone build):
-npm start
-```
-
-### Instalatéři budov
-
-```bash
-cd electron
-npm run build # Current platform
-npm run build:win # Windows (.exe NSIS)
-npm run build:mac # macOS (.dmg universal)
-npm run build:linux # Linux (.AppImage)
-```
-
-Výstup → `electron/dist-electron/`
-
-### Klíčové vlastnosti
-
-| Funkce | Popis |
-| ----------------------------- | -------------------------------------------------------------------- |
-| **Připravenost serveru** | Před zobrazením okna se dotazuje server (žádná prázdná obrazovka) |
-| **Systémový zásobník** | Minimalizovat do zásobníku, změnit port, ukončit menu v zásobníku |
-| **Správa přístavů** | Změna portu serveru z panelu úloh (automatické restartování serveru) |
-| **Zásady zabezpečení obsahu** | Omezující CSP prostřednictvím záhlaví relace |
-| **Jedna instance** | V daném okamžiku může běžet pouze jedna instance aplikace |
-| **Offline režim** | Dodávaný server Next.js funguje bez internetu |
-
-### Proměnné prostředí
-
-| Proměnná | Výchozí | Popis |
-| --------------------- | ------- | --------------------------------- |
-| `OMNIROUTE_PORT` | `20128` | Port serveru |
-| `OMNIROUTE_MEMORY_MB` | `512` | Limit haldy Node.js (64–16384 MB) |
-
-📖 Úplná dokumentace: [`electron/README.md`](../electron/README.md)
diff --git a/docs/i18n/cs/VM_DEPLOYMENT_GUIDE.md b/docs/i18n/cs/VM_DEPLOYMENT_GUIDE.md
deleted file mode 100644
index c33bb94069..0000000000
--- a/docs/i18n/cs/VM_DEPLOYMENT_GUIDE.md
+++ /dev/null
@@ -1,401 +0,0 @@
-# Průvodce nasazením OmniRoute na VM s Cloudflare
-
-🌐 **Jazyky:** 🇺🇸 [English](VM_DEPLOYMENT_GUIDE.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/VM_DEPLOYMENT_GUIDE.md) | 🇪🇸 [Español](i18n/es/VM_DEPLOYMENT_GUIDE.md) | 🇫🇷 [Français](i18n/fr/VM_DEPLOYMENT_GUIDE.md) | 🇮🇹 [Italiano](i18n/it/VM_DEPLOYMENT_GUIDE.md) | 🇷🇺 [Русский](i18n/ru/VM_DEPLOYMENT_GUIDE.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/VM_DEPLOYMENT_GUIDE.md) | 🇩🇪 [Deutsch](i18n/de/VM_DEPLOYMENT_GUIDE.md) | 🇮🇳 [हिन्दी](i18n/in/VM_DEPLOYMENT_GUIDE.md) | 🇹🇭 [ไทย](i18n/th/VM_DEPLOYMENT_GUIDE.md) | 🇺🇦 [Українська](i18n/uk-UA/VM_DEPLOYMENT_GUIDE.md) | 🇸🇦 [العربية](i18n/ar/VM_DEPLOYMENT_GUIDE.md) | 🇯🇵 [日本語](i18n/ja/VM_DEPLOYMENT_GUIDE.md) | 🇻🇳 [Tiếng Việt](i18n/vi/VM_DEPLOYMENT_GUIDE.md) | 🇧🇬 [Български](i18n/bg/VM_DEPLOYMENT_GUIDE.md) | 🇩🇰 [Dansk](i18n/da/VM_DEPLOYMENT_GUIDE.md) | 🇫🇮 [Suomi](i18n/fi/VM_DEPLOYMENT_GUIDE.md) | 🇮🇱 [עברית](i18n/he/VM_DEPLOYMENT_GUIDE.md) | 🇭🇺 [Magyar](i18n/hu/VM_DEPLOYMENT_GUIDE.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/VM_DEPLOYMENT_GUIDE.md) | 🇰🇷 [한국어](i18n/ko/VM_DEPLOYMENT_GUIDE.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/VM_DEPLOYMENT_GUIDE.md) | 🇳🇱 [Nederlands](i18n/nl/VM_DEPLOYMENT_GUIDE.md) | 🇳🇴 [Norsk](i18n/no/VM_DEPLOYMENT_GUIDE.md) | 🇵🇹 [Português (Portugal)](i18n/pt/VM_DEPLOYMENT_GUIDE.md) | 🇷🇴 [Română](i18n/ro/VM_DEPLOYMENT_GUIDE.md) | 🇵🇱 [Polski](i18n/pl/VM_DEPLOYMENT_GUIDE.md) | 🇸🇰 [Slovenčina](i18n/sk/VM_DEPLOYMENT_GUIDE.md) | 🇸🇪 [Svenska](i18n/sv/VM_DEPLOYMENT_GUIDE.md) | 🇵🇭 [Filipino](i18n/phi/VM_DEPLOYMENT_GUIDE.md) | 🇨🇿 [Čeština](i18n/cs/VM_DEPLOYMENT_GUIDE.md)
-
-Kompletní průvodce instalací a konfigurací OmniRoute na virtuálním stroji (VPS) se správou domény prostřednictvím Cloudflare.
-
----
-
-## Předpoklady
-
-| Položka | Minimální | Doporučeno |
-| ------------ | --------------------------- | ---------------- |
-| **Procesor** | 1 virtuální procesor | 2 vCPU |
-| **RAM** | 1 GB | 2 GB |
-| **Disk** | 10GB SSD | 25GB SSD |
-| **CPU** | Ubuntu 22.04 LTS | Ubuntu 24.04 LTS |
-| **Doména** | Zaregistrována v Cloudflare | — |
-| **Docker** | Docker Engine 24+ | Docker 27+ |
-
-**Testovaní poskytovatelé**: Akamai (Linode), DigitalOcean, Vultr, Hetzner, AWS Lightsail.
-
----
-
-## 1. Konfigurace virtuálního počítače
-
-### 1.1 Vytvořit ihned
-
-Žádný preferovaný poskytovatel VPS:
-
-- Vyberte si Ubuntu 24.04 LTS
-- Vyberte minimální plán (1 vCPU / 1 GB RAM)
-- Nastavte silné heslo pro root nebo konfiguraci SSH klíče
-- Poznamenejte si **veřejnou IP** (např.: `203.0.113.10`)
-
-### 1.2 Připojení přes SSH
-
-```bash
-ssh root@203.0.113.10
-```
-
-### 1.3 Aktualizace systému
-
-```bash
-apt update && apt upgrade -y
-```
-
-### 1.4 Instalace Dockeru
-
-```bash
-# Nainstalovat závislosti
-apt install -y ca-certificates curl gnupg
-
-# Přidat oficiální Docker repository
-install -m 0755 -d /etc/apt/keyrings
-curl -fsSL https://download.docker.com/linux/ubuntu/gpg | gpg --dearmor -o /etc/apt/keyrings/docker.gpg
-chmod a+r /etc/apt/keyrings/docker.gpg
-echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | tee /etc/apt/sources.list.d/docker.list > /dev/null
-apt update
-apt install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin
-```
-
-### 1.5 Instalace nginxu
-
-```bash
-apt install -y nginx
-```
-
-### 1.6 Konfigurace firewallu (UFW)
-
-```bash
-ufw default deny incoming
-ufw default allow outgoing
-ufw allow 22/tcp # SSH
-ufw allow 80/tcp # HTTP (redirect)
-ufw allow 443/tcp # HTTPS
-ufw enable
-```
-
-> **Tip**: Pro maximální zabezpečení omezte porty 80 a 443 pouze na IP Cloudflare. Viz sekce [Pokročilé zabezpečení](#pokrocilé-zabezpečení).
-
----
-
-## 2. Instalace OmniRoute
-
-### 2.1 Vytvořit konfigurační adresář
-
-```bash
-mkdir -p /opt/omniroute
-```
-
-### 2.2 Vytvořit soubor s proměnnými prostředí
-
-```bash
-cat > /opt/omniroute/.env << 'EOF'
-# === Bezpečnost ===
-JWT_SECRET=CHANGE-TO-A-UNIQUE-64-CHAR-SECRET-KEY
-INITIAL_PASSWORD=YourSecurePassword123!
-API_KEY_SECRET=REPLACE-WITH-ANOTHER-SECRET-KEY
-STORAGE_ENCRYPTION_KEY=REPLACE-WITH-THIRD-SECRET-KEY
-STORAGE_ENCRYPTION_KEY_VERSION=v1
-MACHINE_ID_SALT=CHANGE-TO-A-UNIQUE-SALT
-
-# === App ===
-PORT=20128
-NODE_ENV=production
-HOSTNAME=0.0.0.0
-DATA_DIR=/app/data
-STORAGE_DRIVER=sqlite
-ENABLE_REQUEST_LOGS=true
-AUTH_COOKIE_SECURE=false
-REQUIRE_API_KEY=false
-
-# === Doména (změňte na vaši doménu) ===
-BASE_URL=https://llms.vasedomena.com
-NEXT_PUBLIC_BASE_URL=https://llms.vasedomena.com
-
-# === Cloud Sync (opcional) ===
-# CLOUD_URL=https://cloud.omniroute.online
-# NEXT_PUBLIC_CLOUD_URL=https://cloud.omniroute.online
-EOF
-```
-
-> ⚠️ **DŮLEŽITÉ**: Vygenerujte jedinečné tajné klíče! Použijte `openssl rand -hex 32` pro každý klíč.
-
-### 2.3 Spuštění kontejneru
-
-```bash
-docker pull diegosouzapw/omniroute:latest
-
-docker run -d \
- --name omniroute \
- --restart unless-stopped \
- --env-file /opt/omniroute/.env \
- -p 20128:20128 \
- -v omniroute-data:/app/data \
- diegosouzapw/omniroute:latest
-```
-
-### 2.4 Verificar se está rodando
-
-```bash
-docker ps | grep omniroute
-docker logs omniroute --tail 20
-```
-
-Vývojový příklad: `[DB] SQLite database ready` a `listening on port 20128` .
-
----
-
-## 3. Konfigurace nginx (reverzní proxy)
-
-### 3.1 Vygenerovat SSL certifikát (Cloudflare Origin)
-
-Cloudflare nic neřeší:
-
-1. Používá **SSL/TLS → Origin Server**
-2. Klikněte na **Vytvořit certifikát**
-3. Ponechte výchozí nastavení (15 let, \*.vasedomena.com)
-4. Zkopírujte nebo zkopírujte **certifikát původu** a **soukromý klíč**
-
-```bash
-mkdir -p /etc/nginx/ssl
-
-# Vložit certifikát
-nano /etc/nginx/ssl/origin.crt
-
-# Colar a chave privada
-nano /etc/nginx/ssl/origin.key
-
-chmod 600 /etc/nginx/ssl/origin.key
-```
-
-### 3.2 Konfigurace nginxu
-
-```bash
-cat > /etc/nginx/sites-available/omniroute << 'NGINX'
-# Default server — bloqueia acesso direto por IP
-server {
- listen 80 default_server;
- listen [::]:80 default_server;
- listen 443 ssl default_server;
- listen [::]:443 ssl default_server;
- ssl_certificate /etc/nginx/ssl/origin.crt;
- ssl_certificate_key /etc/nginx/ssl/origin.key;
- server_name _;
- return 444;
-}
-
-# OmniRoute — HTTPS
-server {
- listen 443 ssl;
- listen [::]:443 ssl;
- server_name llms.vasedomena.com; # Změňte na vaši doménu
-
- ssl_certificate /etc/nginx/ssl/origin.crt;
- ssl_certificate_key /etc/nginx/ssl/origin.key;
- ssl_protocols TLSv1.2 TLSv1.3;
-
- client_max_body_size 100M;
-
- location / {
- proxy_pass http://127.0.0.1:20128;
- proxy_set_header Host $host;
- proxy_set_header X-Real-IP $remote_addr;
- proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
- proxy_set_header X-Forwarded-Proto $scheme;
-
- # WebSocket support
- proxy_http_version 1.1;
- proxy_set_header Upgrade $http_upgrade;
- proxy_set_header Connection "upgrade";
-
- # SSE (Server-Sent Events) — streaming AI responses
- proxy_buffering off;
- proxy_cache off;
- proxy_read_timeout 300s;
- proxy_send_timeout 300s;
- }
-}
-
-# HTTP → HTTPS redirect
-server {
- listen 80;
- listen [::]:80;
- server_name llms.vasedomena.com;
- return 301 https://$server_name$request_uri;
-}
-NGINX
-```
-
-### 3.3 Ativar a testování
-
-```bash
-# Remover config padrão
-rm -f /etc/nginx/sites-enabled/default
-
-# Ativar OmniRoute
-ln -sf /etc/nginx/sites-available/omniroute /etc/nginx/sites-enabled/omniroute
-
-# Testar e recarregar
-nginx -t && systemctl reload nginx
-```
-
----
-
-## 4. Konfigurace DNS v Cloudflare
-
-### 4.1 Další DNS registr
-
-V dashboardu Cloudflare → DNS:
-
-| Typ | Jméno | Obsah | Proxy |
-| --- | ------ | ----------------------------------------------- | -------- |
-| A | `llms` | `203.0.113.10` (IP adresa virtuálního počítače) | ✅ Proxy |
-
-### 4.2 Konfigurace SSL
-
-Em **SSL/TLS → Přehled** :
-
-- Režim: **Plný (Přísný)**
-
-V **SSL/TLS → Edge Certificates**:
-
-- Vždy používat HTTPS: ✅ Zapnuto
-- Minimální verze TLS: TLS 1.2
-- Automatické přepisování HTTPS: ✅ Zapnuto
-
-### 4.3 Testar
-
-```bash
-curl -sI https://llms.vasedomena.com/health
-# Deve retornar HTTP/2 200
-```
-
----
-
-## 5. Operace a údržba
-
-### Aktualizovat na novou verzi
-
-```bash
-docker pull diegosouzapw/omniroute:latest
-docker stop omniroute && docker rm omniroute
-docker run -d --name omniroute --restart unless-stopped \
- --env-file /opt/omniroute/.env \
- -p 20128:20128 \
- -v omniroute-data:/app/data \
- diegosouzapw/omniroute:latest
-```
-
-### Verzovní protokoly
-
-```bash
-docker logs -f omniroute # Živý stream
-docker logs omniroute --tail 50 # Últimas 50 linhas
-```
-
-### Ruční zálohování banky
-
-```bash
-# Kopírovat data z volume do hostitele
-docker cp omniroute:/app/data ./backup-$(date +%F)
-
-# Ou comprimir todo o volume
-docker run --rm -v omniroute-data:/data -v $(pwd):/backup \
- alpine tar czf /backup/omniroute-data-$(date +%F).tar.gz /data
-```
-
-### Obnovení zálohy
-
-```bash
-docker stop omniroute
-docker run --rm -v omniroute-data:/data -v $(pwd):/backup \
- alpine sh -c "rm -rf /data/* && tar xzf /backup/omniroute-data-YYYY-MM-DD.tar.gz -C /"
-docker start omniroute
-```
-
----
-
-## 6. Pokročilá bezpečnost
-
-### Omezte přístup k IP Cloudflare
-
-```bash
-cat > /etc/nginx/cloudflare-ips.conf << 'CF'
-# Cloudflare IPv4 ranges — aktualizovat pravidelně
-# https://www.cloudflare.com/ips-v4/
-set_real_ip_from 173.245.48.0/20;
-set_real_ip_from 103.21.244.0/22;
-set_real_ip_from 103.22.200.0/22;
-set_real_ip_from 103.31.4.0/22;
-set_real_ip_from 141.101.64.0/18;
-set_real_ip_from 108.162.192.0/18;
-set_real_ip_from 190.93.240.0/20;
-set_real_ip_from 188.114.96.0/20;
-set_real_ip_from 197.234.240.0/22;
-set_real_ip_from 198.41.128.0/17;
-set_real_ip_from 162.158.0.0/15;
-set_real_ip_from 104.16.0.0/13;
-set_real_ip_from 104.24.0.0/14;
-set_real_ip_from 172.64.0.0/13;
-set_real_ip_from 131.0.72.0/22;
-real_ip_header CF-Connecting-IP;
-CF
-```
-
-Přidat do `nginx.conf` do bloku `http {}`:
-
-```nginx
-include /etc/nginx/cloudflare-ips.conf;
-```
-
-### Nainstalujte fail2ban
-
-```bash
-apt install -y fail2ban
-systemctl enable fail2ban
-systemctl start fail2ban
-
-# Verificar status
-fail2ban-client status sshd
-```
-
-### Bloquear accesso direto na port do Docker
-
-```bash
-# Zamezit přímému externímu přístupu k portu 20128
-iptables -I DOCKER-USER -p tcp --dport 20128 -j DROP
-iptables -I DOCKER-USER -i lo -p tcp --dport 20128 -j ACCEPT
-
-# Persistir as regras
-apt install -y iptables-persistent
-netfilter-persistent save
-```
-
----
-
-## 7. Nasazení cloudového pracovníka (volitelné)
-
-Vzdálený přístup přes Cloudflare Workers (zde exponovat diretament VM):
-
-```bash
-# No repositório local
-cd omnirouteCloud
-npm install
-npx wrangler login
-npx wrangler deploy
-```
-
-Dokumenty jsou kompletní pro [omnirouteCloud/README.md](../omnirouteCloud/README.md) .
-
----
-
-## Přehled portů
-
-| Port | Služba | Přístup |
-| ----- | ----------- | ---------------------------------------- |
-| 22 | SSH | Veřejné (s fail2ban) |
-| 80 | nginx HTTP | Přesměrování → HTTPS |
-| 443 | nginx HTTPS | Prostřednictvím proxy serveru Cloudflare |
-| 20128 | OmniRoute | Někdy na localhostu (přes nginx) |
diff --git a/docs/i18n/cs/adr/0001-proxy-registry-limit-generalization.md b/docs/i18n/cs/adr/0001-proxy-registry-limit-generalization.md
deleted file mode 100644
index cb1ba57871..0000000000
--- a/docs/i18n/cs/adr/0001-proxy-registry-limit-generalization.md
+++ /dev/null
@@ -1,45 +0,0 @@
-# ADR-0001: Zobecnění registru proxy serverů + kontroly využití
-
-Datum: 17. 3. 2026 Stav: Přijato
-
-## Kontext
-
-OmniRoute je užitečný:
-
-- Přiřazení proxy na základě konfigurační mapy ( `global` , `providers` , `combos` , `keys` ).
-- Výběr s ohledem na kvóty poskytovatele khusus tertentu (zejména `codex` ).
-
-Mezera utama:
-
-- Proxy belum menjadi asset opakovaně použitelný jang bisa di-manage sebagai entitas (metadata, kde se používají, bezpečné smazání).
-- Zásady použití belum konsisten lintas provider.
-- Chybová smlouva API belum seragam untuk manajemen endpoint manajemen.
-
-## Rozhodnutí
-
-1. Tambah **Proxy Registry** sebegai domény baru di DB ( `proxy_registry` , `proxy_assignments` ).
-2. Stálá kompatibilita přiřazení lama (záložní lama `proxyConfig` ).
-3. Priority pakai runtime modulu Resolver:
- - účet -> poskytovatel -> globální (registr)
- - záložní ke legacy resolver jika registry belum ada přiřazení
-4. Výchozí registr výstupního seznamu Wajib redaction kredensial di.
-5. Standarkan error JSON unuk endpoint manajemen proxy agar konsisten dan punya `requestId` .
-
-## Důsledky
-
-Pozitivní:
-
-- Opakovaně použitelný proxy server.
-- Bezpečné odstranění bisa ditegakkan (409 saat masih dipakai).
-- Migrasi bertahap tanpa prolomení runtime změn.
-
-Negativní:
-
-- Ada dual-source sementara (registr + starší konfigurace) sampai migrasi selesai.
-- Ale přiřazení koncových bodů tambahan a pemetaan rozsah a rozsah.
-
-## Následná opatření
-
-- Poskytovatel uživatelského rozhraní Migrasi/účet umožňuje zadat nezpracovaný registr selektoru proxy serveru.
-- Telemetrie zdraví Tambah na proxy a upozornění.
-- Všeobecná kontrola používání ke poskytovateli lain melalui interface policy yang sama.
diff --git a/docs/i18n/cs/adr/0002-api-error-contract-management-endpoints.md b/docs/i18n/cs/adr/0002-api-error-contract-management-endpoints.md
deleted file mode 100644
index f3be181aa3..0000000000
--- a/docs/i18n/cs/adr/0002-api-error-contract-management-endpoints.md
+++ /dev/null
@@ -1,31 +0,0 @@
-# ADR-0002: Chybová smlouva pro koncové body správy
-
-Datum: 17. 3. 2026 Stav: Přijato
-
-## Rozhodnutí
-
-Koncové body správy (konfigurace proxy, registr proxy a přiřazení proxy) vracejí jednotné tělo chyby:
-
-```json
-{
- "error": {
- "message": "Human-readable summary",
- "type": "invalid_request | not_found | conflict | server_error",
- "details": {}
- },
- "requestId": "uuid"
-}
-```
-
-## Mapování stavu
-
-- 400: neplatný požadavek / selhání ověření
-- 404: zdroj nenalezen
-- 409: konflikt zdrojů (například proxy stále přiřazen)
-- 500: neočekávaná chyba serveru
-
-## Poznámky
-
-- `requestId` je povinný pro korelaci protokolů.
-- `details` je volitelné a používá se pouze pro bezpečné ověření detailů.
-- Citlivé tajné informace (přihlašovací údaje proxy, tokeny) se nikdy nesmí objevit ve `message` ani v `details` .
diff --git a/docs/i18n/cs/adr/0003-security-checklist-proxy-limits.md b/docs/i18n/cs/adr/0003-security-checklist-proxy-limits.md
deleted file mode 100644
index e6ac963c3a..0000000000
--- a/docs/i18n/cs/adr/0003-security-checklist-proxy-limits.md
+++ /dev/null
@@ -1,15 +0,0 @@
-# ADR-0003: Kontrolní seznam zabezpečení pro registr proxy a kontroly používání
-
-Datum: 17. 3. 2026 Stav: Přijato
-
-## Kontrolní seznam
-
-- Ověřte všechny datové části správy pomocí Zodu.
-- Odmítnout aktualizace chybně formátovaného přiřazení rozsahu se stavem 400.
-- Odmítnout smazání používané proxy se stavem 409, pokud to není vynuceno.
-- Ve výchozím nastavení nikdy nezobrazovat uživatelské jméno/heslo proxy v odpovědích seznamu.
-- Nikdy nezaznamenávejte nezpracované přihlašovací údaje ani hodnoty tokenů.
-- Udržujte chybové odpovědi bez interních trasování zásobníku.
-- Chraňte koncové body správy pomocí stávajících zásad middlewaru pro ověřování.
-- Auditovat mutující operace: vytvořit/aktualizovat/smazat/přiřadit/migraci.
-- Zajistěte, aby se resolver během přechodu vrátil k původní konfiguraci.
diff --git a/docs/i18n/cs/docs/A2A-SERVER.md b/docs/i18n/cs/docs/A2A-SERVER.md
new file mode 100644
index 0000000000..e8f673c33a
--- /dev/null
+++ b/docs/i18n/cs/docs/A2A-SERVER.md
@@ -0,0 +1,200 @@
+# OmniRoute A2A Server Documentation (Čeština)
+
+🌐 **Languages:** 🇺🇸 [English](../../../../docs/A2A-SERVER.md) · 🇪🇸 [es](../../es/docs/A2A-SERVER.md) · 🇫🇷 [fr](../../fr/docs/A2A-SERVER.md) · 🇩🇪 [de](../../de/docs/A2A-SERVER.md) · 🇮🇹 [it](../../it/docs/A2A-SERVER.md) · 🇷🇺 [ru](../../ru/docs/A2A-SERVER.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/A2A-SERVER.md) · 🇯🇵 [ja](../../ja/docs/A2A-SERVER.md) · 🇰🇷 [ko](../../ko/docs/A2A-SERVER.md) · 🇸🇦 [ar](../../ar/docs/A2A-SERVER.md) · 🇮🇳 [in](../../in/docs/A2A-SERVER.md) · 🇹🇭 [th](../../th/docs/A2A-SERVER.md) · 🇻🇳 [vi](../../vi/docs/A2A-SERVER.md) · 🇮🇩 [id](../../id/docs/A2A-SERVER.md) · 🇲🇾 [ms](../../ms/docs/A2A-SERVER.md) · 🇳🇱 [nl](../../nl/docs/A2A-SERVER.md) · 🇵🇱 [pl](../../pl/docs/A2A-SERVER.md) · 🇸🇪 [sv](../../sv/docs/A2A-SERVER.md) · 🇳🇴 [no](../../no/docs/A2A-SERVER.md) · 🇩🇰 [da](../../da/docs/A2A-SERVER.md) · 🇫🇮 [fi](../../fi/docs/A2A-SERVER.md) · 🇵🇹 [pt](../../pt/docs/A2A-SERVER.md) · 🇷🇴 [ro](../../ro/docs/A2A-SERVER.md) · 🇭🇺 [hu](../../hu/docs/A2A-SERVER.md) · 🇧🇬 [bg](../../bg/docs/A2A-SERVER.md) · 🇸🇰 [sk](../../sk/docs/A2A-SERVER.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/A2A-SERVER.md) · 🇮🇱 [he](../../he/docs/A2A-SERVER.md) · 🇵🇭 [phi](../../phi/docs/A2A-SERVER.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/A2A-SERVER.md) · 🇨🇿 [cs](../../cs/docs/A2A-SERVER.md)
+
+---
+
+> Agent-to-Agent Protocol v0.3 — OmniRoute as an intelligent routing agent
+
+## Agent Discovery
+
+```bash
+curl http://localhost:20128/.well-known/agent.json
+```
+
+Returns the Agent Card describing OmniRoute's capabilities, skills, and authentication requirements.
+
+---
+
+## Authentication
+
+All `/a2a` requests require an API key via the `Authorization` header:
+
+```
+Authorization: Bearer YOUR_OMNIROUTE_API_KEY
+```
+
+If no API key is configured on the server, authentication is bypassed.
+
+---
+
+## JSON-RPC 2.0 Methods
+
+### `message/send` — Synchronous Execution
+
+Sends a message to a skill and waits for the complete response.
+
+```bash
+curl -X POST http://localhost:20128/a2a \
+ -H "Content-Type: application/json" \
+ -H "Authorization: Bearer YOUR_KEY" \
+ -d '{
+ "jsonrpc": "2.0",
+ "id": "1",
+ "method": "message/send",
+ "params": {
+ "skill": "smart-routing",
+ "messages": [{"role": "user", "content": "Write a hello world in Python"}],
+ "metadata": {"model": "auto", "combo": "fast-coding"}
+ }
+ }'
+```
+
+**Response:**
+
+```json
+{
+ "jsonrpc": "2.0",
+ "id": "1",
+ "result": {
+ "task": { "id": "uuid", "state": "completed" },
+ "artifacts": [{ "type": "text", "content": "..." }],
+ "metadata": {
+ "routing_explanation": "Selected claude-sonnet via provider \"anthropic\" (latency: 1200ms, cost: $0.003)",
+ "cost_envelope": { "estimated": 0.005, "actual": 0.003, "currency": "USD" },
+ "resilience_trace": [
+ { "event": "primary_selected", "provider": "anthropic", "timestamp": "..." }
+ ],
+ "policy_verdict": { "allowed": true, "reason": "within budget and quota limits" }
+ }
+ }
+}
+```
+
+### `message/stream` — SSE Streaming
+
+Same as `message/send` but returns Server-Sent Events for real-time streaming.
+
+```bash
+curl -N -X POST http://localhost:20128/a2a \
+ -H "Content-Type: application/json" \
+ -H "Authorization: Bearer YOUR_KEY" \
+ -d '{
+ "jsonrpc": "2.0",
+ "id": "1",
+ "method": "message/stream",
+ "params": {
+ "skill": "smart-routing",
+ "messages": [{"role": "user", "content": "Explain quantum computing"}]
+ }
+ }'
+```
+
+**SSE Events:**
+
+```
+data: {"jsonrpc":"2.0","method":"message/stream","params":{"task":{"id":"...","state":"working"},"chunk":{"type":"text","content":"..."}}}
+
+: heartbeat 2026-03-03T17:00:00Z
+
+data: {"jsonrpc":"2.0","method":"message/stream","params":{"task":{"id":"...","state":"completed"},"metadata":{...}}}
+```
+
+### `tasks/get` — Query Task Status
+
+```bash
+curl -X POST http://localhost:20128/a2a \
+ -H "Content-Type: application/json" \
+ -H "Authorization: Bearer YOUR_KEY" \
+ -d '{"jsonrpc":"2.0","id":"2","method":"tasks/get","params":{"taskId":"TASK_UUID"}}'
+```
+
+### `tasks/cancel` — Cancel a Task
+
+```bash
+curl -X POST http://localhost:20128/a2a \
+ -H "Content-Type: application/json" \
+ -H "Authorization: Bearer YOUR_KEY" \
+ -d '{"jsonrpc":"2.0","id":"3","method":"tasks/cancel","params":{"taskId":"TASK_UUID"}}'
+```
+
+---
+
+## Available Skills
+
+| Skill | Description |
+| :----------------- | :------------------------------------------------------------------------------------------------------------------------------ |
+| `smart-routing` | Routes prompts through OmniRoute's intelligent pipeline. Returns response with routing explanation, cost, and resilience trace. |
+| `quota-management` | Answers natural-language queries about provider quotas, suggests free combos, and provides quota rankings. |
+
+---
+
+## Task Lifecycle
+
+```
+submitted → working → completed
+ → failed
+ → cancelled
+```
+
+- Tasks expire after 5 minutes (configurable)
+- Terminal states: `completed`, `failed`, `cancelled`
+- Event log tracks every state transition
+
+---
+
+## Error Codes
+
+| Code | Meaning |
+| :----- | :----------------------------- |
+| -32700 | Parse error (invalid JSON) |
+| -32600 | Invalid request / Unauthorized |
+| -32601 | Method or skill not found |
+| -32602 | Invalid params |
+| -32603 | Internal error |
+
+---
+
+## Integration Examples
+
+### Python (requests)
+
+```python
+import requests
+
+resp = requests.post("http://localhost:20128/a2a", json={
+ "jsonrpc": "2.0", "id": "1",
+ "method": "message/send",
+ "params": {
+ "skill": "smart-routing",
+ "messages": [{"role": "user", "content": "Hello"}]
+ }
+}, headers={"Authorization": "Bearer YOUR_KEY"})
+
+result = resp.json()["result"]
+print(result["artifacts"][0]["content"])
+print(result["metadata"]["routing_explanation"])
+```
+
+### TypeScript (fetch)
+
+```typescript
+const resp = await fetch("http://localhost:20128/a2a", {
+ method: "POST",
+ headers: {
+ "Content-Type": "application/json",
+ Authorization: "Bearer YOUR_KEY",
+ },
+ body: JSON.stringify({
+ jsonrpc: "2.0",
+ id: "1",
+ method: "message/send",
+ params: {
+ skill: "smart-routing",
+ messages: [{ role: "user", content: "Hello" }],
+ },
+ }),
+});
+const { result } = await resp.json();
+console.log(result.metadata.routing_explanation);
+```
diff --git a/docs/i18n/cs/docs/API_REFERENCE.md b/docs/i18n/cs/docs/API_REFERENCE.md
new file mode 100644
index 0000000000..b02cec2c81
--- /dev/null
+++ b/docs/i18n/cs/docs/API_REFERENCE.md
@@ -0,0 +1,465 @@
+# API Reference (Čeština)
+
+🌐 **Languages:** 🇺🇸 [English](../../../../docs/API_REFERENCE.md) · 🇪🇸 [es](../../es/docs/API_REFERENCE.md) · 🇫🇷 [fr](../../fr/docs/API_REFERENCE.md) · 🇩🇪 [de](../../de/docs/API_REFERENCE.md) · 🇮🇹 [it](../../it/docs/API_REFERENCE.md) · 🇷🇺 [ru](../../ru/docs/API_REFERENCE.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/API_REFERENCE.md) · 🇯🇵 [ja](../../ja/docs/API_REFERENCE.md) · 🇰🇷 [ko](../../ko/docs/API_REFERENCE.md) · 🇸🇦 [ar](../../ar/docs/API_REFERENCE.md) · 🇮🇳 [in](../../in/docs/API_REFERENCE.md) · 🇹🇭 [th](../../th/docs/API_REFERENCE.md) · 🇻🇳 [vi](../../vi/docs/API_REFERENCE.md) · 🇮🇩 [id](../../id/docs/API_REFERENCE.md) · 🇲🇾 [ms](../../ms/docs/API_REFERENCE.md) · 🇳🇱 [nl](../../nl/docs/API_REFERENCE.md) · 🇵🇱 [pl](../../pl/docs/API_REFERENCE.md) · 🇸🇪 [sv](../../sv/docs/API_REFERENCE.md) · 🇳🇴 [no](../../no/docs/API_REFERENCE.md) · 🇩🇰 [da](../../da/docs/API_REFERENCE.md) · 🇫🇮 [fi](../../fi/docs/API_REFERENCE.md) · 🇵🇹 [pt](../../pt/docs/API_REFERENCE.md) · 🇷🇴 [ro](../../ro/docs/API_REFERENCE.md) · 🇭🇺 [hu](../../hu/docs/API_REFERENCE.md) · 🇧🇬 [bg](../../bg/docs/API_REFERENCE.md) · 🇸🇰 [sk](../../sk/docs/API_REFERENCE.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/API_REFERENCE.md) · 🇮🇱 [he](../../he/docs/API_REFERENCE.md) · 🇵🇭 [phi](../../phi/docs/API_REFERENCE.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/API_REFERENCE.md) · 🇨🇿 [cs](../../cs/docs/API_REFERENCE.md)
+
+---
+
+Complete reference for all OmniRoute API endpoints.
+
+---
+
+## Table of Contents
+
+- [Chat Completions](#chat-completions)
+- [Embeddings](#embeddings)
+- [Image Generation](#image-generation)
+- [List Models](#list-models)
+- [Compatibility Endpoints](#compatibility-endpoints)
+- [Semantic Cache](#semantic-cache)
+- [Dashboard & Management](#dashboard--management)
+- [Request Processing](#request-processing)
+- [Authentication](#authentication)
+
+---
+
+## Chat Completions
+
+```bash
+POST /v1/chat/completions
+Authorization: Bearer your-api-key
+Content-Type: application/json
+
+{
+ "model": "cc/claude-opus-4-6",
+ "messages": [
+ {"role": "user", "content": "Write a function to..."}
+ ],
+ "stream": true
+}
+```
+
+### Custom Headers
+
+| Header | Direction | Description |
+| ------------------------ | --------- | ------------------------------------------------ |
+| `X-OmniRoute-No-Cache` | Request | Set to `true` to bypass cache |
+| `X-OmniRoute-Progress` | Request | Set to `true` for progress events |
+| `X-Session-Id` | Request | Sticky session key for external session affinity |
+| `x_session_id` | Request | Underscore variant also accepted (direct HTTP) |
+| `Idempotency-Key` | Request | Dedup key (5s window) |
+| `X-Request-Id` | Request | Alternative dedup key |
+| `X-OmniRoute-Cache` | Response | `HIT` or `MISS` (non-streaming) |
+| `X-OmniRoute-Idempotent` | Response | `true` if deduplicated |
+| `X-OmniRoute-Progress` | Response | `enabled` if progress tracking on |
+| `X-OmniRoute-Session-Id` | Response | Effective session ID used by OmniRoute |
+
+> Nginx note: if you rely on underscore headers (for example `x_session_id`), enable `underscores_in_headers on;`.
+
+---
+
+## Embeddings
+
+```bash
+POST /v1/embeddings
+Authorization: Bearer your-api-key
+Content-Type: application/json
+
+{
+ "model": "nebius/Qwen/Qwen3-Embedding-8B",
+ "input": "The food was delicious"
+}
+```
+
+Available providers: Nebius, OpenAI, Mistral, Together AI, Fireworks, NVIDIA.
+
+```bash
+# List all embedding models
+GET /v1/embeddings
+```
+
+---
+
+## Image Generation
+
+```bash
+POST /v1/images/generations
+Authorization: Bearer your-api-key
+Content-Type: application/json
+
+{
+ "model": "openai/dall-e-3",
+ "prompt": "A beautiful sunset over mountains",
+ "size": "1024x1024"
+}
+```
+
+Available providers: OpenAI (DALL-E), xAI (Grok Image), Together AI (FLUX), Fireworks AI.
+
+```bash
+# List all image models
+GET /v1/images/generations
+```
+
+---
+
+## List Models
+
+```bash
+GET /v1/models
+Authorization: Bearer your-api-key
+
+→ Returns all chat, embedding, and image models + combos in OpenAI format
+```
+
+---
+
+## Compatibility Endpoints
+
+| Method | Path | Format |
+| ------ | --------------------------- | ---------------------- |
+| POST | `/v1/chat/completions` | OpenAI |
+| POST | `/v1/messages` | Anthropic |
+| POST | `/v1/responses` | OpenAI Responses |
+| POST | `/v1/embeddings` | OpenAI |
+| POST | `/v1/images/generations` | OpenAI |
+| GET | `/v1/models` | OpenAI |
+| POST | `/v1/messages/count_tokens` | Anthropic |
+| GET | `/v1beta/models` | Gemini |
+| POST | `/v1beta/models/{...path}` | Gemini generateContent |
+| POST | `/v1/api/chat` | Ollama |
+
+### Dedicated Provider Routes
+
+```bash
+POST /v1/providers/{provider}/chat/completions
+POST /v1/providers/{provider}/embeddings
+POST /v1/providers/{provider}/images/generations
+```
+
+The provider prefix is auto-added if missing. Mismatched models return `400`.
+
+---
+
+## Semantic Cache
+
+```bash
+# Get cache stats
+GET /api/cache/stats
+
+# Clear all caches
+DELETE /api/cache/stats
+```
+
+Response example:
+
+```json
+{
+ "semanticCache": {
+ "memorySize": 42,
+ "memoryMaxSize": 500,
+ "dbSize": 128,
+ "hitRate": 0.65
+ },
+ "idempotency": {
+ "activeKeys": 3,
+ "windowMs": 5000
+ }
+}
+```
+
+---
+
+## Dashboard & Management
+
+### Authentication
+
+| Endpoint | Method | Description |
+| ----------------------------- | ------- | --------------------- |
+| `/api/auth/login` | POST | Login |
+| `/api/auth/logout` | POST | Logout |
+| `/api/settings/require-login` | GET/PUT | Toggle login required |
+
+### Provider Management
+
+| Endpoint | Method | Description |
+| ---------------------------- | --------------- | ------------------------ |
+| `/api/providers` | GET/POST | List / create providers |
+| `/api/providers/[id]` | GET/PUT/DELETE | Manage a provider |
+| `/api/providers/[id]/test` | POST | Test provider connection |
+| `/api/providers/[id]/models` | GET | List provider models |
+| `/api/providers/validate` | POST | Validate provider config |
+| `/api/provider-nodes*` | Various | Provider node management |
+| `/api/provider-models` | GET/POST/DELETE | Custom models |
+
+### OAuth Flows
+
+| Endpoint | Method | Description |
+| -------------------------------- | ------- | ----------------------- |
+| `/api/oauth/[provider]/[action]` | Various | Provider-specific OAuth |
+
+### Routing & Config
+
+| Endpoint | Method | Description |
+| --------------------- | -------- | ----------------------------- |
+| `/api/models/alias` | GET/POST | Model aliases |
+| `/api/models/catalog` | GET | All models by provider + type |
+| `/api/combos*` | Various | Combo management |
+| `/api/keys*` | Various | API key management |
+| `/api/pricing` | GET | Model pricing |
+
+### Usage & Analytics
+
+| Endpoint | Method | Description |
+| --------------------------- | ------ | -------------------- |
+| `/api/usage/history` | GET | Usage history |
+| `/api/usage/logs` | GET | Usage logs |
+| `/api/usage/request-logs` | GET | Request-level logs |
+| `/api/usage/[connectionId]` | GET | Per-connection usage |
+
+### Settings
+
+| Endpoint | Method | Description |
+| ------------------------------- | ------------- | ---------------------- |
+| `/api/settings` | GET/PUT/PATCH | General settings |
+| `/api/settings/proxy` | GET/PUT | Network proxy config |
+| `/api/settings/proxy/test` | POST | Test proxy connection |
+| `/api/settings/ip-filter` | GET/PUT | IP allowlist/blocklist |
+| `/api/settings/thinking-budget` | GET/PUT | Reasoning token budget |
+| `/api/settings/system-prompt` | GET/PUT | Global system prompt |
+
+### Monitoring
+
+| Endpoint | Method | Description |
+| ------------------------ | ---------- | ---------------------------------------------------------------------------------------------------- |
+| `/api/sessions` | GET | Active session tracking |
+| `/api/rate-limits` | GET | Per-account rate limits |
+| `/api/monitoring/health` | GET | Health check + provider summary (`catalogCount`, `configuredCount`, `activeCount`, `monitoredCount`) |
+| `/api/cache/stats` | GET/DELETE | Cache stats / clear |
+
+### Backup & Export/Import
+
+| Endpoint | Method | Description |
+| --------------------------- | ------ | --------------------------------------- |
+| `/api/db-backups` | GET | List available backups |
+| `/api/db-backups` | PUT | Create a manual backup |
+| `/api/db-backups` | POST | Restore from a specific backup |
+| `/api/db-backups/export` | GET | Download database as .sqlite file |
+| `/api/db-backups/import` | POST | Upload .sqlite file to replace database |
+| `/api/db-backups/exportAll` | GET | Download full backup as .tar.gz archive |
+
+### Cloud Sync
+
+| Endpoint | Method | Description |
+| ---------------------- | ------- | --------------------- |
+| `/api/sync/cloud` | Various | Cloud sync operations |
+| `/api/sync/initialize` | POST | Initialize sync |
+| `/api/cloud/*` | Various | Cloud management |
+
+### Tunnels
+
+| Endpoint | Method | Description |
+| -------------------------- | ------ | ----------------------------------------------------------------------- |
+| `/api/tunnels/cloudflared` | GET | Read Cloudflare Quick Tunnel install/runtime status for the dashboard |
+| `/api/tunnels/cloudflared` | POST | Enable or disable the Cloudflare Quick Tunnel (`action=enable/disable`) |
+
+### CLI Tools
+
+| Endpoint | Method | Description |
+| ---------------------------------- | ------ | ------------------- |
+| `/api/cli-tools/claude-settings` | GET | Claude CLI status |
+| `/api/cli-tools/codex-settings` | GET | Codex CLI status |
+| `/api/cli-tools/droid-settings` | GET | Droid CLI status |
+| `/api/cli-tools/openclaw-settings` | GET | OpenClaw CLI status |
+| `/api/cli-tools/runtime/[toolId]` | GET | Generic CLI runtime |
+
+CLI responses include: `installed`, `runnable`, `command`, `commandPath`, `runtimeMode`, `reason`.
+
+### ACP Agents
+
+| Endpoint | Method | Description |
+| ----------------- | ------ | -------------------------------------------------------- |
+| `/api/acp/agents` | GET | List all detected agents (built-in + custom) with status |
+| `/api/acp/agents` | POST | Add custom agent or refresh detection cache |
+| `/api/acp/agents` | DELETE | Remove a custom agent by `id` query param |
+
+GET response includes `agents[]` (id, name, binary, version, installed, protocol, isCustom) and `summary` (total, installed, notFound, builtIn, custom).
+
+### Resilience & Rate Limits
+
+| Endpoint | Method | Description |
+| ----------------------- | --------- | ------------------------------- |
+| `/api/resilience` | GET/PATCH | Get/update resilience profiles |
+| `/api/resilience/reset` | POST | Reset circuit breakers |
+| `/api/rate-limits` | GET | Per-account rate limit status |
+| `/api/rate-limit` | GET | Global rate limit configuration |
+
+### Evals
+
+| Endpoint | Method | Description |
+| ------------ | -------- | --------------------------------- |
+| `/api/evals` | GET/POST | List eval suites / run evaluation |
+
+### Policies
+
+| Endpoint | Method | Description |
+| --------------- | --------------- | ----------------------- |
+| `/api/policies` | GET/POST/DELETE | Manage routing policies |
+
+### Compliance
+
+| Endpoint | Method | Description |
+| --------------------------- | ------ | ----------------------------- |
+| `/api/compliance/audit-log` | GET | Compliance audit log (last N) |
+
+### v1beta (Gemini-Compatible)
+
+| Endpoint | Method | Description |
+| -------------------------- | ------ | --------------------------------- |
+| `/v1beta/models` | GET | List models in Gemini format |
+| `/v1beta/models/{...path}` | POST | Gemini `generateContent` endpoint |
+
+These endpoints mirror Gemini's API format for clients that expect native Gemini SDK compatibility.
+
+### Internal / System APIs
+
+| Endpoint | Method | Description |
+| --------------- | ------ | ---------------------------------------------------- |
+| `/api/init` | GET | Application initialization check (used on first run) |
+| `/api/tags` | GET | Ollama-compatible model tags (for Ollama clients) |
+| `/api/restart` | POST | Trigger graceful server restart |
+| `/api/shutdown` | POST | Trigger graceful server shutdown |
+
+> **Note:** These endpoints are used internally by the system or for Ollama client compatibility. They are not typically called by end users.
+
+---
+
+## Audio Transcription
+
+```bash
+POST /v1/audio/transcriptions
+Authorization: Bearer your-api-key
+Content-Type: multipart/form-data
+```
+
+Transcribe audio files using Deepgram or AssemblyAI.
+
+**Request:**
+
+```bash
+curl -X POST http://localhost:20128/v1/audio/transcriptions \
+ -H "Authorization: Bearer your-api-key" \
+ -F "file=@recording.mp3" \
+ -F "model=deepgram/nova-3"
+```
+
+**Response:**
+
+```json
+{
+ "text": "Hello, this is the transcribed audio content.",
+ "task": "transcribe",
+ "language": "en",
+ "duration": 12.5
+}
+```
+
+**Supported providers:** `deepgram/nova-3`, `assemblyai/best`.
+
+**Supported formats:** `mp3`, `wav`, `m4a`, `flac`, `ogg`, `webm`.
+
+---
+
+## Ollama Compatibility
+
+For clients that use Ollama's API format:
+
+```bash
+# Chat endpoint (Ollama format)
+POST /v1/api/chat
+
+# Model listing (Ollama format)
+GET /api/tags
+```
+
+Requests are automatically translated between Ollama and internal formats.
+
+---
+
+## Telemetry
+
+```bash
+# Get latency telemetry summary (p50/p95/p99 per provider)
+GET /api/telemetry/summary
+```
+
+**Response:**
+
+```json
+{
+ "providers": {
+ "claudeCode": { "p50": 245, "p95": 890, "p99": 1200, "count": 150 },
+ "github": { "p50": 180, "p95": 620, "p99": 950, "count": 320 }
+ }
+}
+```
+
+---
+
+## Budget
+
+```bash
+# Get budget status for all API keys
+GET /api/usage/budget
+
+# Set or update a budget
+POST /api/usage/budget
+Content-Type: application/json
+
+{
+ "keyId": "key-123",
+ "limit": 50.00,
+ "period": "monthly"
+}
+```
+
+---
+
+## Model Availability
+
+```bash
+# Get real-time model availability across all providers
+GET /api/models/availability
+
+# Check availability for a specific model
+POST /api/models/availability
+Content-Type: application/json
+
+{
+ "model": "claude-sonnet-4-5-20250929"
+}
+```
+
+---
+
+## Request Processing
+
+1. Client sends request to `/v1/*`
+2. Route handler calls `handleChat`, `handleEmbedding`, `handleAudioTranscription`, or `handleImageGeneration`
+3. Model is resolved (direct provider/model or alias/combo)
+4. Credentials selected from local DB with account availability filtering
+5. For chat: `handleChatCore` — format detection, translation, cache check, idempotency check
+6. Provider executor sends upstream request
+7. Response translated back to client format (chat) or returned as-is (embeddings/images/audio)
+8. Usage/logging recorded
+9. Fallback applies on errors according to combo rules
+
+Full architecture reference: [`ARCHITECTURE.md`](ARCHITECTURE.md)
+
+---
+
+## Authentication
+
+- Dashboard routes (`/dashboard/*`) use `auth_token` cookie
+- Login uses saved password hash; fallback to `INITIAL_PASSWORD`
+- `requireLogin` toggleable via `/api/settings/require-login`
+- `/v1/*` routes optionally require Bearer API key when `REQUIRE_API_KEY=true`
diff --git a/docs/i18n/cs/docs/ARCHITECTURE.md b/docs/i18n/cs/docs/ARCHITECTURE.md
new file mode 100644
index 0000000000..122e80eda2
--- /dev/null
+++ b/docs/i18n/cs/docs/ARCHITECTURE.md
@@ -0,0 +1,814 @@
+# OmniRoute Architecture (Čeština)
+
+🌐 **Languages:** 🇺🇸 [English](../../../../docs/ARCHITECTURE.md) · 🇪🇸 [es](../../es/docs/ARCHITECTURE.md) · 🇫🇷 [fr](../../fr/docs/ARCHITECTURE.md) · 🇩🇪 [de](../../de/docs/ARCHITECTURE.md) · 🇮🇹 [it](../../it/docs/ARCHITECTURE.md) · 🇷🇺 [ru](../../ru/docs/ARCHITECTURE.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/ARCHITECTURE.md) · 🇯🇵 [ja](../../ja/docs/ARCHITECTURE.md) · 🇰🇷 [ko](../../ko/docs/ARCHITECTURE.md) · 🇸🇦 [ar](../../ar/docs/ARCHITECTURE.md) · 🇮🇳 [in](../../in/docs/ARCHITECTURE.md) · 🇹🇭 [th](../../th/docs/ARCHITECTURE.md) · 🇻🇳 [vi](../../vi/docs/ARCHITECTURE.md) · 🇮🇩 [id](../../id/docs/ARCHITECTURE.md) · 🇲🇾 [ms](../../ms/docs/ARCHITECTURE.md) · 🇳🇱 [nl](../../nl/docs/ARCHITECTURE.md) · 🇵🇱 [pl](../../pl/docs/ARCHITECTURE.md) · 🇸🇪 [sv](../../sv/docs/ARCHITECTURE.md) · 🇳🇴 [no](../../no/docs/ARCHITECTURE.md) · 🇩🇰 [da](../../da/docs/ARCHITECTURE.md) · 🇫🇮 [fi](../../fi/docs/ARCHITECTURE.md) · 🇵🇹 [pt](../../pt/docs/ARCHITECTURE.md) · 🇷🇴 [ro](../../ro/docs/ARCHITECTURE.md) · 🇭🇺 [hu](../../hu/docs/ARCHITECTURE.md) · 🇧🇬 [bg](../../bg/docs/ARCHITECTURE.md) · 🇸🇰 [sk](../../sk/docs/ARCHITECTURE.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/ARCHITECTURE.md) · 🇮🇱 [he](../../he/docs/ARCHITECTURE.md) · 🇵🇭 [phi](../../phi/docs/ARCHITECTURE.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/ARCHITECTURE.md) · 🇨🇿 [cs](../../cs/docs/ARCHITECTURE.md)
+
+---
+
+_Last updated: 2026-03-28_
+
+## Executive Summary
+
+OmniRoute is a local AI routing gateway and dashboard built on Next.js.
+It provides a single OpenAI-compatible endpoint (`/v1/*`) and routes traffic across multiple upstream providers with translation, fallback, token refresh, and usage tracking.
+
+Core capabilities:
+
+- OpenAI-compatible API surface for CLI/tools (28 providers)
+- Request/response translation across provider formats
+- Model combo fallback (multi-model sequence)
+- Account-level fallback (multi-account per provider)
+- OAuth + API-key provider connection management
+- Embedding generation via `/v1/embeddings` (6 providers, 9 models)
+- Image generation via `/v1/images/generations` (4 providers, 9 models)
+- Think tag parsing (`...`) for reasoning models
+- Response sanitization for strict OpenAI SDK compatibility
+- Role normalization (developer→system, system→user) for cross-provider compatibility
+- Structured output conversion (json_schema → Gemini responseSchema)
+- Local persistence for providers, keys, aliases, combos, settings, pricing
+- Usage/cost tracking and request logging
+- Optional cloud sync for multi-device/state sync
+- IP allowlist/blocklist for API access control
+- Thinking budget management (passthrough/auto/custom/adaptive)
+- Global system prompt injection
+- Session tracking and fingerprinting
+- Per-account enhanced rate limiting with provider-specific profiles
+- Circuit breaker pattern for provider resilience
+- Anti-thundering herd protection with mutex locking
+- Signature-based request deduplication cache
+- Domain layer: model availability, cost rules, fallback policy, lockout policy
+- Domain state persistence (SQLite write-through cache for fallbacks, budgets, lockouts, circuit breakers)
+- Policy engine for centralized request evaluation (lockout → budget → fallback)
+- Request telemetry with p50/p95/p99 latency aggregation
+- Correlation ID (X-Request-Id) for end-to-end tracing
+- Compliance audit logging with opt-out per API key
+- Eval framework for LLM quality assurance
+- Resilience UI dashboard with real-time circuit breaker status
+- Modular OAuth providers (12 individual modules under `src/lib/oauth/providers/`)
+
+Primary runtime model:
+
+- Next.js app routes under `src/app/api/*` implement both dashboard APIs and compatibility APIs
+- A shared SSE/routing core in `src/sse/*` + `open-sse/*` handles provider execution, translation, streaming, fallback, and usage
+
+## Scope and Boundaries
+
+### In Scope
+
+- Local gateway runtime
+- Dashboard management APIs
+- Provider authentication and token refresh
+- Request translation and SSE streaming
+- Local state + usage persistence
+- Optional cloud sync orchestration
+
+### Out of Scope
+
+- Cloud service implementation behind `NEXT_PUBLIC_CLOUD_URL`
+- Provider SLA/control plane outside local process
+- External CLI binaries themselves (Claude CLI, Codex CLI, etc.)
+
+## Dashboard Surface (Current)
+
+Main pages under `src/app/(dashboard)/dashboard/`:
+
+- `/dashboard` — quick start + provider overview
+- `/dashboard/endpoint` — endpoint proxy + MCP + A2A + API endpoint tabs
+- `/dashboard/providers` — provider connections and credentials
+- `/dashboard/combos` — combo strategies, templates, model routing rules
+- `/dashboard/costs` — cost aggregation and pricing visibility
+- `/dashboard/analytics` — usage analytics and evaluations
+- `/dashboard/limits` — quota/rate controls
+- `/dashboard/cli-tools` — CLI onboarding, runtime detection, config generation
+- `/dashboard/agents` — detected ACP agents + custom agent registration
+- `/dashboard/media` — image/video/music playground
+- `/dashboard/search-tools` — search provider testing and history
+- `/dashboard/health` — uptime, circuit breakers, rate limits
+- `/dashboard/logs` — request/proxy/audit/console logs
+- `/dashboard/settings` — system settings tabs (general, routing, combo defaults, etc.)
+- `/dashboard/api-manager` — API key lifecycle and model permissions
+
+## High-Level System Context
+
+```mermaid
+flowchart LR
+ subgraph Clients[Developer Clients]
+ C1[Claude Code]
+ C2[Codex CLI]
+ C3[OpenClaw / Droid / Cline / Continue / Roo]
+ C4[Custom OpenAI-compatible clients]
+ BROWSER[Browser Dashboard]
+ end
+
+ subgraph Router[OmniRoute Local Process]
+ API[V1 Compatibility API\n/v1/*]
+ DASH[Dashboard + Management API\n/api/*]
+ CORE[SSE + Translation Core\nopen-sse + src/sse]
+ DB[(storage.sqlite)]
+ UDB[(usage tables + log artifacts)]
+ end
+
+ subgraph Upstreams[Upstream Providers]
+ P1[OAuth Providers\nClaude/Codex/Gemini/Qwen/Qoder/GitHub/Kiro/Cursor/Antigravity]
+ P2[API Key Providers\nOpenAI/Anthropic/OpenRouter/GLM/Kimi/MiniMax\nDeepSeek/Groq/xAI/Mistral/Perplexity\nTogether/Fireworks/Cerebras/Cohere/NVIDIA]
+ P3[Compatible Nodes\nOpenAI-compatible / Anthropic-compatible]
+ end
+
+ subgraph Cloud[Optional Cloud Sync]
+ CLOUD[Cloud Sync Endpoint\nNEXT_PUBLIC_CLOUD_URL]
+ end
+
+ C1 --> API
+ C2 --> API
+ C3 --> API
+ C4 --> API
+ BROWSER --> DASH
+
+ API --> CORE
+ DASH --> DB
+ CORE --> DB
+ CORE --> UDB
+
+ CORE --> P1
+ CORE --> P2
+ CORE --> P3
+
+ DASH --> CLOUD
+```
+
+## Core Runtime Components
+
+## 1) API and Routing Layer (Next.js App Routes)
+
+Main directories:
+
+- `src/app/api/v1/*` and `src/app/api/v1beta/*` for compatibility APIs
+- `src/app/api/*` for management/configuration APIs
+- Next rewrites in `next.config.mjs` map `/v1/*` to `/api/v1/*`
+
+Important compatibility routes:
+
+- `src/app/api/v1/chat/completions/route.ts`
+- `src/app/api/v1/messages/route.ts`
+- `src/app/api/v1/responses/route.ts`
+- `src/app/api/v1/models/route.ts` — includes custom models with `custom: true`
+- `src/app/api/v1/embeddings/route.ts` — embedding generation (6 providers)
+- `src/app/api/v1/images/generations/route.ts` — image generation (4+ providers incl. Antigravity/Nebius)
+- `src/app/api/v1/messages/count_tokens/route.ts`
+- `src/app/api/v1/providers/[provider]/chat/completions/route.ts` — dedicated per-provider chat
+- `src/app/api/v1/providers/[provider]/embeddings/route.ts` — dedicated per-provider embeddings
+- `src/app/api/v1/providers/[provider]/images/generations/route.ts` — dedicated per-provider images
+- `src/app/api/v1beta/models/route.ts`
+- `src/app/api/v1beta/models/[...path]/route.ts`
+
+Management domains:
+
+- Auth/settings: `src/app/api/auth/*`, `src/app/api/settings/*`
+- Providers/connections: `src/app/api/providers*`
+- Provider nodes: `src/app/api/provider-nodes*`
+- Custom models: `src/app/api/provider-models` (GET/POST/DELETE)
+- Model catalog: `src/app/api/models/route.ts` (GET)
+- Proxy config: `src/app/api/settings/proxy` (GET/PUT/DELETE) + `src/app/api/settings/proxy/test` (POST)
+- OAuth: `src/app/api/oauth/*`
+- Keys/aliases/combos/pricing: `src/app/api/keys*`, `src/app/api/models/alias`, `src/app/api/combos*`, `src/app/api/pricing`
+- Usage: `src/app/api/usage/*`
+- Sync/cloud: `src/app/api/sync/*`, `src/app/api/cloud/*`
+- CLI tooling helpers: `src/app/api/cli-tools/*`
+- IP filter: `src/app/api/settings/ip-filter` (GET/PUT)
+- Thinking budget: `src/app/api/settings/thinking-budget` (GET/PUT)
+- System prompt: `src/app/api/settings/system-prompt` (GET/PUT)
+- Sessions: `src/app/api/sessions` (GET)
+- Rate limits: `src/app/api/rate-limits` (GET)
+- Resilience: `src/app/api/resilience` (GET/PATCH) — provider profiles, circuit breaker, rate limit state
+- Resilience reset: `src/app/api/resilience/reset` (POST) — reset breakers + cooldowns
+- Cache stats: `src/app/api/cache/stats` (GET/DELETE)
+- Model availability: `src/app/api/models/availability` (GET/POST)
+- Telemetry: `src/app/api/telemetry/summary` (GET)
+- Budget: `src/app/api/usage/budget` (GET/POST)
+- Fallback chains: `src/app/api/fallback/chains` (GET/POST/DELETE)
+- Compliance audit: `src/app/api/compliance/audit-log` (GET)
+- Evals: `src/app/api/evals` (GET/POST), `src/app/api/evals/[suiteId]` (GET)
+- Policies: `src/app/api/policies` (GET/POST)
+
+## 2) SSE + Translation Core
+
+Main flow modules:
+
+- Entry: `src/sse/handlers/chat.ts`
+- Core orchestration: `open-sse/handlers/chatCore.ts`
+- Provider execution adapters: `open-sse/executors/*`
+- Format detection/provider config: `open-sse/services/provider.ts`
+- Model parse/resolve: `src/sse/services/model.ts`, `open-sse/services/model.ts`
+- Account fallback logic: `open-sse/services/accountFallback.ts`
+- Translation registry: `open-sse/translator/index.ts`
+- Stream transformations: `open-sse/utils/stream.ts`, `open-sse/utils/streamHandler.ts`
+- Usage extraction/normalization: `open-sse/utils/usageTracking.ts`
+- Think tag parser: `open-sse/utils/thinkTagParser.ts`
+- Embedding handler: `open-sse/handlers/embeddings.ts`
+- Embedding provider registry: `open-sse/config/embeddingRegistry.ts`
+- Image generation handler: `open-sse/handlers/imageGeneration.ts`
+- Image provider registry: `open-sse/config/imageRegistry.ts`
+- Response sanitization: `open-sse/handlers/responseSanitizer.ts`
+- Role normalization: `open-sse/services/roleNormalizer.ts`
+
+Services (business logic):
+
+- Account selection/scoring: `open-sse/services/accountSelector.ts`
+- Context lifecycle management: `open-sse/services/contextManager.ts`
+- IP filter enforcement: `open-sse/services/ipFilter.ts`
+- Session tracking: `open-sse/services/sessionManager.ts`
+- Request deduplication: `open-sse/services/signatureCache.ts`
+- System prompt injection: `open-sse/services/systemPrompt.ts`
+- Thinking budget management: `open-sse/services/thinkingBudget.ts`
+- Wildcard model routing: `open-sse/services/wildcardRouter.ts`
+- Rate limit management: `open-sse/services/rateLimitManager.ts`
+- Circuit breaker: `open-sse/services/circuitBreaker.ts`
+
+Domain layer modules:
+
+- Model availability: `src/lib/domain/modelAvailability.ts`
+- Cost rules/budgets: `src/lib/domain/costRules.ts`
+- Fallback policy: `src/lib/domain/fallbackPolicy.ts`
+- Combo resolver: `src/lib/domain/comboResolver.ts`
+- Lockout policy: `src/lib/domain/lockoutPolicy.ts`
+- Policy engine: `src/domain/policyEngine.ts` — centralized lockout → budget → fallback evaluation
+- Error codes catalog: `src/lib/domain/errorCodes.ts`
+- Request ID: `src/lib/domain/requestId.ts`
+- Fetch timeout: `src/lib/domain/fetchTimeout.ts`
+- Request telemetry: `src/lib/domain/requestTelemetry.ts`
+- Compliance/audit: `src/lib/domain/compliance/index.ts`
+- Eval runner: `src/lib/domain/evalRunner.ts`
+- Domain state persistence: `src/lib/db/domainState.ts` — SQLite CRUD for fallback chains, budgets, cost history, lockout state, circuit breakers
+
+OAuth provider modules (12 individual files under `src/lib/oauth/providers/`):
+
+- Registry index: `src/lib/oauth/providers/index.ts`
+- Individual providers: `claude.ts`, `codex.ts`, `gemini.ts`, `antigravity.ts`, `qoder.ts`, `qwen.ts`, `kimi-coding.ts`, `github.ts`, `kiro.ts`, `cursor.ts`, `kilocode.ts`, `cline.ts`
+- Thin wrapper: `src/lib/oauth/providers.ts` — re-exports from individual modules
+
+## 3) Persistence Layer
+
+Primary state DB (SQLite):
+
+- Core infra: `src/lib/db/core.ts` (better-sqlite3, migrations, WAL)
+- Re-export facade: `src/lib/localDb.ts` (thin compatibility layer for callers)
+- file: `${DATA_DIR}/storage.sqlite` (or `$XDG_CONFIG_HOME/omniroute/storage.sqlite` when set, else `~/.omniroute/storage.sqlite`)
+- entities (tables + KV namespaces): providerConnections, providerNodes, modelAliases, combos, apiKeys, settings, pricing, **customModels**, **proxyConfig**, **ipFilter**, **thinkingBudget**, **systemPrompt**
+
+Usage persistence:
+
+- facade: `src/lib/usageDb.ts` (decomposed modules in `src/lib/usage/*`)
+- SQLite tables in `storage.sqlite`: `usage_history`, `call_logs`, `proxy_logs`
+- optional file artifacts remain for compatibility/debug (`${DATA_DIR}/log.txt`, `${DATA_DIR}/call_logs/`, `/logs/...`)
+- legacy JSON files are migrated to SQLite by startup migrations when present
+
+Domain State DB (SQLite):
+
+- `src/lib/db/domainState.ts` — CRUD operations for domain state
+- Tables (created in `src/lib/db/core.ts`): `domain_fallback_chains`, `domain_budgets`, `domain_cost_history`, `domain_lockout_state`, `domain_circuit_breakers`
+- Write-through cache pattern: in-memory Maps are authoritative at runtime; mutations are written synchronously to SQLite; state is restored from DB on cold start
+
+## 4) Auth + Security Surfaces
+
+- Dashboard cookie auth: `src/proxy.ts`, `src/app/api/auth/login/route.ts`
+- API key generation/verification: `src/shared/utils/apiKey.ts`
+- Provider secrets persisted in `providerConnections` entries
+- Outbound proxy support via `open-sse/utils/proxyFetch.ts` (env vars) and `open-sse/utils/networkProxy.ts` (configurable per-provider or global)
+
+## 5) Cloud Sync
+
+- Scheduler init: `src/lib/initCloudSync.ts`, `src/shared/services/initializeCloudSync.ts`, `src/shared/services/modelSyncScheduler.ts`
+- Periodic task: `src/shared/services/cloudSyncScheduler.ts`
+- Periodic task: `src/shared/services/modelSyncScheduler.ts`
+- Control route: `src/app/api/sync/cloud/route.ts`
+
+## Request Lifecycle (`/v1/chat/completions`)
+
+```mermaid
+sequenceDiagram
+ autonumber
+ participant Client as CLI/SDK Client
+ participant Route as /api/v1/chat/completions
+ participant Chat as src/sse/handlers/chat
+ participant Core as open-sse/handlers/chatCore
+ participant Model as Model Resolver
+ participant Auth as Credential Selector
+ participant Exec as Provider Executor
+ participant Prov as Upstream Provider
+ participant Stream as Stream Translator
+ participant Usage as usageDb
+
+ Client->>Route: POST /v1/chat/completions
+ Route->>Chat: handleChat(request)
+ Chat->>Model: parse/resolve model or combo
+
+ alt Combo model
+ Chat->>Chat: iterate combo models (handleComboChat)
+ end
+
+ Chat->>Auth: getProviderCredentials(provider)
+ Auth-->>Chat: active account + tokens/api key
+
+ Chat->>Core: handleChatCore(body, modelInfo, credentials)
+ Core->>Core: detect source format
+ Core->>Core: translate request to target format
+ Core->>Exec: execute(provider, transformedBody)
+ Exec->>Prov: upstream API call
+ Prov-->>Exec: SSE/JSON response
+ Exec-->>Core: response + metadata
+
+ alt 401/403
+ Core->>Exec: refreshCredentials()
+ Exec-->>Core: updated tokens
+ Core->>Exec: retry request
+ end
+
+ Core->>Stream: translate/normalize stream to client format
+ Stream-->>Client: SSE chunks / JSON response
+
+ Stream->>Usage: extract usage + persist history/log
+```
+
+## Combo + Account Fallback Flow
+
+```mermaid
+flowchart TD
+ A[Incoming model string] --> B{Is combo name?}
+ B -- Yes --> C[Load combo models sequence]
+ B -- No --> D[Single model path]
+
+ C --> E[Try model N]
+ E --> F[Resolve provider/model]
+ D --> F
+
+ F --> G[Select account credentials]
+ G --> H{Credentials available?}
+ H -- No --> I[Return provider unavailable]
+ H -- Yes --> J[Execute request]
+
+ J --> K{Success?}
+ K -- Yes --> L[Return response]
+ K -- No --> M{Fallback-eligible error?}
+
+ M -- No --> N[Return error]
+ M -- Yes --> O[Mark account unavailable cooldown]
+ O --> P{Another account for provider?}
+ P -- Yes --> G
+ P -- No --> Q{In combo with next model?}
+ Q -- Yes --> E
+ Q -- No --> R[Return all unavailable]
+```
+
+Fallback decisions are driven by `open-sse/services/accountFallback.ts` using status codes and error-message heuristics. Combo routing adds one extra guard: provider-scoped 400s such as upstream content-block and role-validation failures are treated as model-local failures so later combo targets can still run.
+
+## OAuth Onboarding and Token Refresh Lifecycle
+
+```mermaid
+sequenceDiagram
+ autonumber
+ participant UI as Dashboard UI
+ participant OAuth as /api/oauth/[provider]/[action]
+ participant ProvAuth as Provider Auth Server
+ participant DB as localDb
+ participant Test as /api/providers/[id]/test
+ participant Exec as Provider Executor
+
+ UI->>OAuth: GET authorize or device-code
+ OAuth->>ProvAuth: create auth/device flow
+ ProvAuth-->>OAuth: auth URL or device code payload
+ OAuth-->>UI: flow data
+
+ UI->>OAuth: POST exchange or poll
+ OAuth->>ProvAuth: token exchange/poll
+ ProvAuth-->>OAuth: access/refresh tokens
+ OAuth->>DB: createProviderConnection(oauth data)
+ OAuth-->>UI: success + connection id
+
+ UI->>Test: POST /api/providers/[id]/test
+ Test->>Exec: validate credentials / optional refresh
+ Exec-->>Test: valid or refreshed token info
+ Test->>DB: update status/tokens/errors
+ Test-->>UI: validation result
+```
+
+Refresh during live traffic is executed inside `open-sse/handlers/chatCore.ts` via executor `refreshCredentials()`.
+
+## Cloud Sync Lifecycle (Enable / Sync / Disable)
+
+```mermaid
+sequenceDiagram
+ autonumber
+ participant UI as Endpoint Page UI
+ participant Sync as /api/sync/cloud
+ participant DB as localDb
+ participant Cloud as External Cloud Sync
+ participant Claude as ~/.claude/settings.json
+
+ UI->>Sync: POST action=enable
+ Sync->>DB: set cloudEnabled=true
+ Sync->>DB: ensure API key exists
+ Sync->>Cloud: POST /sync/{machineId} (providers/aliases/combos/keys)
+ Cloud-->>Sync: sync result
+ Sync->>Cloud: GET /{machineId}/v1/verify
+ Sync-->>UI: enabled + verification status
+
+ UI->>Sync: POST action=sync
+ Sync->>Cloud: POST /sync/{machineId}
+ Cloud-->>Sync: remote data
+ Sync->>DB: update newer local tokens/status
+ Sync-->>UI: synced
+
+ UI->>Sync: POST action=disable
+ Sync->>DB: set cloudEnabled=false
+ Sync->>Cloud: DELETE /sync/{machineId}
+ Sync->>Claude: switch ANTHROPIC_BASE_URL back to local (if needed)
+ Sync-->>UI: disabled
+```
+
+Periodic sync is triggered by `CloudSyncScheduler` when cloud is enabled.
+
+## Data Model and Storage Map
+
+```mermaid
+erDiagram
+ SETTINGS ||--o{ PROVIDER_CONNECTION : controls
+ PROVIDER_NODE ||--o{ PROVIDER_CONNECTION : backs_compatible_provider
+ PROVIDER_CONNECTION ||--o{ USAGE_ENTRY : emits_usage
+
+ SETTINGS {
+ boolean cloudEnabled
+ number stickyRoundRobinLimit
+ boolean requireLogin
+ string password_hash
+ string fallbackStrategy
+ json rateLimitDefaults
+ json providerProfiles
+ }
+
+ PROVIDER_CONNECTION {
+ string id
+ string provider
+ string authType
+ string name
+ number priority
+ boolean isActive
+ string apiKey
+ string accessToken
+ string refreshToken
+ string expiresAt
+ string testStatus
+ string lastError
+ string rateLimitedUntil
+ json providerSpecificData
+ }
+
+ PROVIDER_NODE {
+ string id
+ string type
+ string name
+ string prefix
+ string apiType
+ string baseUrl
+ }
+
+ MODEL_ALIAS {
+ string alias
+ string targetModel
+ }
+
+ COMBO {
+ string id
+ string name
+ string[] models
+ }
+
+ API_KEY {
+ string id
+ string name
+ string key
+ string machineId
+ }
+
+ USAGE_ENTRY {
+ string provider
+ string model
+ number prompt_tokens
+ number completion_tokens
+ string connectionId
+ string timestamp
+ }
+
+ CUSTOM_MODEL {
+ string id
+ string name
+ string providerId
+ }
+
+ PROXY_CONFIG {
+ string global
+ json providers
+ }
+
+ IP_FILTER {
+ string mode
+ string[] allowlist
+ string[] blocklist
+ }
+
+ THINKING_BUDGET {
+ string mode
+ number customBudget
+ string effortLevel
+ }
+
+ SYSTEM_PROMPT {
+ boolean enabled
+ string prompt
+ string position
+ }
+```
+
+Physical storage files:
+
+- primary runtime DB: `${DATA_DIR}/storage.sqlite`
+- request log lines: `${DATA_DIR}/log.txt` (compat/debug artifact)
+- structured call payload archives: `${DATA_DIR}/call_logs/`
+- optional translator/request debug sessions: `/logs/...`
+
+## Deployment Topology
+
+```mermaid
+flowchart LR
+ subgraph LocalHost[Developer Host]
+ CLI[CLI Tools]
+ Browser[Dashboard Browser]
+ end
+
+ subgraph ContainerOrProcess[OmniRoute Runtime]
+ Next[Next.js Server\nPORT=20128]
+ Core[SSE Core + Executors]
+ MainDB[(storage.sqlite)]
+ UsageDB[(usage tables + log artifacts)]
+ end
+
+ subgraph External[External Services]
+ Providers[AI Providers]
+ SyncCloud[Cloud Sync Service]
+ end
+
+ CLI --> Next
+ Browser --> Next
+ Next --> Core
+ Next --> MainDB
+ Core --> MainDB
+ Core --> UsageDB
+ Core --> Providers
+ Next --> SyncCloud
+```
+
+## Module Mapping (Decision-Critical)
+
+### Route and API Modules
+
+- `src/app/api/v1/*`, `src/app/api/v1beta/*`: compatibility APIs
+- `src/app/api/v1/providers/[provider]/*`: dedicated per-provider routes (chat, embeddings, images)
+- `src/app/api/providers*`: provider CRUD, validation, testing
+- `src/app/api/provider-nodes*`: custom compatible node management
+- `src/app/api/provider-models`: custom model management (CRUD)
+- `src/app/api/models/route.ts`: model catalog API (aliases + custom models)
+- `src/app/api/oauth/*`: OAuth/device-code flows
+- `src/app/api/keys*`: local API key lifecycle
+- `src/app/api/models/alias`: alias management
+- `src/app/api/combos*`: fallback combo management
+- `src/app/api/pricing`: pricing overrides for cost calculation
+- `src/app/api/settings/proxy`: proxy configuration (GET/PUT/DELETE)
+- `src/app/api/settings/proxy/test`: outbound proxy connectivity test (POST)
+- `src/app/api/usage/*`: usage and logs APIs
+- `src/app/api/sync/*` + `src/app/api/cloud/*`: cloud sync and cloud-facing helpers
+- `src/app/api/cli-tools/*`: local CLI config writers/checkers
+- `src/app/api/settings/ip-filter`: IP allowlist/blocklist (GET/PUT)
+- `src/app/api/settings/thinking-budget`: thinking token budget config (GET/PUT)
+- `src/app/api/settings/system-prompt`: global system prompt (GET/PUT)
+- `src/app/api/sessions`: active session listing (GET)
+- `src/app/api/rate-limits`: per-account rate limit status (GET)
+
+### Routing and Execution Core
+
+- `src/sse/handlers/chat.ts`: request parse, combo handling, account selection loop
+- `open-sse/handlers/chatCore.ts`: translation, executor dispatch, retry/refresh handling, stream setup
+- `open-sse/executors/*`: provider-specific network and format behavior
+
+### Translation Registry and Format Converters
+
+- `open-sse/translator/index.ts`: translator registry and orchestration
+- Request translators: `open-sse/translator/request/*`
+- Response translators: `open-sse/translator/response/*`
+- Format constants: `open-sse/translator/formats.ts`
+
+### Persistence
+
+- `src/lib/db/*`: persistent config/state and domain persistence on SQLite
+- `src/lib/localDb.ts`: compatibility re-export for DB modules
+- `src/lib/usageDb.ts`: usage history/call logs facade on top of SQLite tables
+
+## Provider Executor Coverage (Strategy Pattern)
+
+Each provider has a specialized executor extending `BaseExecutor` (in `open-sse/executors/base.ts`), which provides URL building, header construction, retry with exponential backoff, credential refresh hooks, and the `execute()` orchestration method.
+
+| Executor | Provider(s) | Special Handling |
+| --------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------ | -------------------------------------------------------------------- |
+| `DefaultExecutor` | OpenAI, Claude, Gemini, Qwen, Qoder, OpenRouter, GLM, Kimi, MiniMax, DeepSeek, Groq, xAI, Mistral, Perplexity, Together, Fireworks, Cerebras, Cohere, NVIDIA | Dynamic URL/header config per provider |
+| `AntigravityExecutor` | Google Antigravity | Custom project/session IDs, Retry-After parsing |
+| `CodexExecutor` | OpenAI Codex | Injects system instructions, forces reasoning effort |
+| `CursorExecutor` | Cursor IDE | ConnectRPC protocol, Protobuf encoding, request signing via checksum |
+| `GithubExecutor` | GitHub Copilot | Copilot token refresh, VSCode-mimicking headers |
+| `KiroExecutor` | AWS CodeWhisperer/Kiro | AWS EventStream binary format → SSE conversion |
+| `GeminiCLIExecutor` | Gemini CLI | Google OAuth token refresh cycle |
+
+All other providers (including custom compatible nodes) use the `DefaultExecutor`.
+
+## Provider Compatibility Matrix
+
+| Provider | Format | Auth | Stream | Non-Stream | Token Refresh | Usage API |
+| ---------------- | ---------------- | --------------------- | ---------------- | ---------- | ------------- | ------------------ |
+| Claude | claude | API Key / OAuth | ✅ | ✅ | ✅ | ⚠️ Admin only |
+| Gemini | gemini | API Key / OAuth | ✅ | ✅ | ✅ | ⚠️ Cloud Console |
+| Gemini CLI | gemini-cli | OAuth | ✅ | ✅ | ✅ | ⚠️ Cloud Console |
+| Antigravity | antigravity | OAuth | ✅ | ✅ | ✅ | ✅ Full quota API |
+| OpenAI | openai | API Key | ✅ | ✅ | ❌ | ❌ |
+| Codex | openai-responses | OAuth | ✅ forced | ❌ | ✅ | ✅ Rate limits |
+| GitHub Copilot | openai | OAuth + Copilot Token | ✅ | ✅ | ✅ | ✅ Quota snapshots |
+| Cursor | cursor | Custom checksum | ✅ | ✅ | ❌ | ❌ |
+| Kiro | kiro | AWS SSO OIDC | ✅ (EventStream) | ❌ | ✅ | ✅ Usage limits |
+| Qwen | openai | OAuth | ✅ | ✅ | ✅ | ⚠️ Per request |
+| Qoder | openai | OAuth (Basic) | ✅ | ✅ | ✅ | ⚠️ Per request |
+| OpenRouter | openai | API Key | ✅ | ✅ | ❌ | ❌ |
+| GLM/Kimi/MiniMax | claude | API Key | ✅ | ✅ | ❌ | ❌ |
+| DeepSeek | openai | API Key | ✅ | ✅ | ❌ | ❌ |
+| Groq | openai | API Key | ✅ | ✅ | ❌ | ❌ |
+| xAI (Grok) | openai | API Key | ✅ | ✅ | ❌ | ❌ |
+| Mistral | openai | API Key | ✅ | ✅ | ❌ | ❌ |
+| Perplexity | openai | API Key | ✅ | ✅ | ❌ | ❌ |
+| Together AI | openai | API Key | ✅ | ✅ | ❌ | ❌ |
+| Fireworks AI | openai | API Key | ✅ | ✅ | ❌ | ❌ |
+| Cerebras | openai | API Key | ✅ | ✅ | ❌ | ❌ |
+| Cohere | openai | API Key | ✅ | ✅ | ❌ | ❌ |
+| NVIDIA NIM | openai | API Key | ✅ | ✅ | ❌ | ❌ |
+
+## Format Translation Coverage
+
+Detected source formats include:
+
+- `openai`
+- `openai-responses`
+- `claude`
+- `gemini`
+
+Target formats include:
+
+- OpenAI chat/Responses
+- Claude
+- Gemini/Gemini-CLI/Antigravity envelope
+- Kiro
+- Cursor
+
+Translations use **OpenAI as the hub format** — all conversions go through OpenAI as intermediate:
+
+```
+Source Format → OpenAI (hub) → Target Format
+```
+
+Translations are selected dynamically based on source payload shape and provider target format.
+
+Additional processing layers in the translation pipeline:
+
+- **Response sanitization** — Strips non-standard fields from OpenAI-format responses (both streaming and non-streaming) to ensure strict SDK compliance
+- **Role normalization** — Converts `developer` → `system` for non-OpenAI targets; merges `system` → `user` for models that reject the system role (GLM, ERNIE)
+- **Think tag extraction** — Parses `...` blocks from content into `reasoning_content` field
+- **Structured output** — Converts OpenAI `response_format.json_schema` to Gemini's `responseMimeType` + `responseSchema`
+
+## Supported API Endpoints
+
+| Endpoint | Format | Handler |
+| -------------------------------------------------- | ------------------ | ------------------------------------------------------------------- |
+| `POST /v1/chat/completions` | OpenAI Chat | `src/sse/handlers/chat.ts` |
+| `POST /v1/messages` | Claude Messages | Same handler (auto-detected) |
+| `POST /v1/responses` | OpenAI Responses | `open-sse/handlers/responsesHandler.ts` |
+| `POST /v1/embeddings` | OpenAI Embeddings | `open-sse/handlers/embeddings.ts` |
+| `GET /v1/embeddings` | Model listing | API route |
+| `POST /v1/images/generations` | OpenAI Images | `open-sse/handlers/imageGeneration.ts` |
+| `GET /v1/images/generations` | Model listing | API route |
+| `POST /v1/providers/{provider}/chat/completions` | OpenAI Chat | Dedicated per-provider with model validation |
+| `POST /v1/providers/{provider}/embeddings` | OpenAI Embeddings | Dedicated per-provider with model validation |
+| `POST /v1/providers/{provider}/images/generations` | OpenAI Images | Dedicated per-provider with model validation |
+| `POST /v1/messages/count_tokens` | Claude Token Count | API route |
+| `GET /v1/models` | OpenAI Models list | API route (chat + embedding + image + custom models) |
+| `GET /api/models/catalog` | Catalog | All models grouped by provider + type |
+| `POST /v1beta/models/*:streamGenerateContent` | Gemini native | API route |
+| `GET/PUT/DELETE /api/settings/proxy` | Proxy Config | Network proxy configuration |
+| `POST /api/settings/proxy/test` | Proxy Connectivity | Proxy health/connectivity test endpoint |
+| `GET/POST/DELETE /api/provider-models` | Provider Models | Provider model metadata backing custom and managed available models |
+
+## Bypass Handler
+
+The bypass handler (`open-sse/utils/bypassHandler.ts`) intercepts known "throwaway" requests from Claude CLI — warmup pings, title extractions, and token counts — and returns a **fake response** without consuming upstream provider tokens. This is triggered only when `User-Agent` contains `claude-cli`.
+
+## Request Logger Pipeline
+
+The request logger (`open-sse/utils/requestLogger.ts`) provides a 7-stage debug logging pipeline, disabled by default, enabled via `ENABLE_REQUEST_LOGS=true`:
+
+```
+1_req_client.json → 2_req_source.json → 3_req_openai.json → 4_req_target.json
+→ 5_res_provider.txt → 6_res_openai.txt → 7_res_client.txt
+```
+
+Files are written to `/logs//` for each request session.
+
+## Failure Modes and Resilience
+
+## 1) Account/Provider Availability
+
+- provider account cooldown on transient/rate/auth errors
+- account fallback before failing request
+- combo model fallback when current model/provider path is exhausted
+
+## 2) Token Expiry
+
+- pre-check and refresh with retry for refreshable providers
+- 401/403 retry after refresh attempt in core path
+
+## 3) Stream Safety
+
+- disconnect-aware stream controller
+- translation stream with end-of-stream flush and `[DONE]` handling
+- usage estimation fallback when provider usage metadata is missing
+
+## 4) Cloud Sync Degradation
+
+- sync errors are surfaced but local runtime continues
+- scheduler has retry-capable logic, but periodic execution currently calls single-attempt sync by default
+
+## 5) Data Integrity
+
+- SQLite schema migrations and auto-upgrade hooks at startup
+- legacy JSON → SQLite migration compatibility path
+
+## Observability and Operational Signals
+
+Runtime visibility sources:
+
+- console logs from `src/sse/utils/logger.ts`
+- per-request usage aggregates in SQLite (`usage_history`, `call_logs`, `proxy_logs`)
+- four-stage detailed payload captures in SQLite (`request_detail_logs`) when `settings.detailed_logs_enabled=true`
+- textual request status log in `log.txt` (optional/compat)
+- optional deep request/translation logs under `logs/` when `ENABLE_REQUEST_LOGS=true`
+- dashboard usage endpoints (`/api/usage/*`) for UI consumption
+
+Detailed request payload capture stores up to four JSON payload stages per routed call:
+
+- raw request received from the client
+- translated request actually sent upstream
+- provider response reconstructed as JSON; streamed responses are compacted to the final summary plus stream metadata
+- final client response returned by OmniRoute; streamed responses are stored in the same compact summary form
+
+## Security-Sensitive Boundaries
+
+- JWT secret (`JWT_SECRET`) secures dashboard session cookie verification/signing
+- Initial password bootstrap (`INITIAL_PASSWORD`) should be explicitly configured for first-run provisioning
+- API key HMAC secret (`API_KEY_SECRET`) secures generated local API key format
+- Provider secrets (API keys/tokens) are persisted in local DB and should be protected at filesystem level
+- Cloud sync endpoints rely on API key auth + machine id semantics
+
+## Environment and Runtime Matrix
+
+Environment variables actively used by code:
+
+- App/auth: `JWT_SECRET`, `INITIAL_PASSWORD`
+- Storage: `DATA_DIR`
+- Compatible node behavior: `ALLOW_MULTI_CONNECTIONS_PER_COMPAT_NODE`
+- Optional storage base override (Linux/macOS when `DATA_DIR` unset): `XDG_CONFIG_HOME`
+- Security hashing: `API_KEY_SECRET`, `MACHINE_ID_SALT`
+- Logging: `ENABLE_REQUEST_LOGS`
+- Sync/cloud URLing: `NEXT_PUBLIC_BASE_URL`, `NEXT_PUBLIC_CLOUD_URL`
+- Outbound proxy: `HTTP_PROXY`, `HTTPS_PROXY`, `ALL_PROXY`, `NO_PROXY` and lowercase variants
+- SOCKS5 feature flags: `ENABLE_SOCKS5_PROXY`, `NEXT_PUBLIC_ENABLE_SOCKS5_PROXY`
+- Platform/runtime helpers (not app-specific config): `APPDATA`, `NODE_ENV`, `PORT`, `HOSTNAME`
+
+## Known Architectural Notes
+
+1. `usageDb` and `localDb` share the same base directory policy (`DATA_DIR` -> `XDG_CONFIG_HOME/omniroute` -> `~/.omniroute`) with legacy file migration.
+2. `/api/v1/route.ts` delegates to the same unified catalog builder used by `/api/v1/models` (`src/app/api/v1/models/catalog.ts`) to avoid semantic drift.
+3. Request logger writes full headers/body when enabled; treat log directory as sensitive.
+4. Cloud behavior depends on correct `NEXT_PUBLIC_BASE_URL` and cloud endpoint reachability.
+5. The `open-sse/` directory is published as the `@omniroute/open-sse` **npm workspace package**. Source code imports it via `@omniroute/open-sse/...` (resolved by Next.js `transpilePackages`). File paths in this document still use the directory name `open-sse/` for consistency.
+6. Charts in the dashboard use **Recharts** (SVG-based) for accessible, interactive analytics visualizations (model usage bar charts, provider breakdown tables with success rates).
+7. E2E tests use **Playwright** (`tests/e2e/`), run via `npm run test:e2e`. Unit tests use **Node.js test runner** (`tests/unit/`), run via `npm run test:unit`. Source code under `src/` is **TypeScript** (`.ts`/`.tsx`); the `open-sse/` workspace remains JavaScript (`.js`).
+8. Settings page is organized into 5 tabs: Security, Routing (6 global strategies: fill-first, round-robin, p2c, random, least-used, cost-optimized), Resilience (editable rate limits, circuit breaker, policies), AI (thinking budget, system prompt, prompt cache), Advanced (proxy).
+
+## Operational Verification Checklist
+
+- Build from source: `npm run build`
+- Build Docker image: `docker build -t omniroute .`
+- Start service and verify:
+- `GET /api/settings`
+- `GET /api/v1/models`
+- CLI target base URL should be `http://:20128/v1` when `PORT=20128`
diff --git a/docs/i18n/cs/docs/AUTO-COMBO.md b/docs/i18n/cs/docs/AUTO-COMBO.md
new file mode 100644
index 0000000000..87e38de265
--- /dev/null
+++ b/docs/i18n/cs/docs/AUTO-COMBO.md
@@ -0,0 +1,67 @@
+# OmniRoute Auto-Combo Engine (Čeština)
+
+🌐 **Languages:** 🇺🇸 [English](../../../../docs/AUTO-COMBO.md) · 🇪🇸 [es](../../es/docs/AUTO-COMBO.md) · 🇫🇷 [fr](../../fr/docs/AUTO-COMBO.md) · 🇩🇪 [de](../../de/docs/AUTO-COMBO.md) · 🇮🇹 [it](../../it/docs/AUTO-COMBO.md) · 🇷🇺 [ru](../../ru/docs/AUTO-COMBO.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/AUTO-COMBO.md) · 🇯🇵 [ja](../../ja/docs/AUTO-COMBO.md) · 🇰🇷 [ko](../../ko/docs/AUTO-COMBO.md) · 🇸🇦 [ar](../../ar/docs/AUTO-COMBO.md) · 🇮🇳 [in](../../in/docs/AUTO-COMBO.md) · 🇹🇭 [th](../../th/docs/AUTO-COMBO.md) · 🇻🇳 [vi](../../vi/docs/AUTO-COMBO.md) · 🇮🇩 [id](../../id/docs/AUTO-COMBO.md) · 🇲🇾 [ms](../../ms/docs/AUTO-COMBO.md) · 🇳🇱 [nl](../../nl/docs/AUTO-COMBO.md) · 🇵🇱 [pl](../../pl/docs/AUTO-COMBO.md) · 🇸🇪 [sv](../../sv/docs/AUTO-COMBO.md) · 🇳🇴 [no](../../no/docs/AUTO-COMBO.md) · 🇩🇰 [da](../../da/docs/AUTO-COMBO.md) · 🇫🇮 [fi](../../fi/docs/AUTO-COMBO.md) · 🇵🇹 [pt](../../pt/docs/AUTO-COMBO.md) · 🇷🇴 [ro](../../ro/docs/AUTO-COMBO.md) · 🇭🇺 [hu](../../hu/docs/AUTO-COMBO.md) · 🇧🇬 [bg](../../bg/docs/AUTO-COMBO.md) · 🇸🇰 [sk](../../sk/docs/AUTO-COMBO.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/AUTO-COMBO.md) · 🇮🇱 [he](../../he/docs/AUTO-COMBO.md) · 🇵🇭 [phi](../../phi/docs/AUTO-COMBO.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/AUTO-COMBO.md) · 🇨🇿 [cs](../../cs/docs/AUTO-COMBO.md)
+
+---
+
+> Self-managing model chains with adaptive scoring
+
+## How It Works
+
+The Auto-Combo Engine dynamically selects the best provider/model for each request using a **6-factor scoring function**:
+
+| Factor | Weight | Description |
+| :--------- | :----- | :---------------------------------------------- |
+| Quota | 0.20 | Remaining capacity [0..1] |
+| Health | 0.25 | Circuit breaker: CLOSED=1.0, HALF=0.5, OPEN=0.0 |
+| CostInv | 0.20 | Inverse cost (cheaper = higher score) |
+| LatencyInv | 0.15 | Inverse p95 latency (faster = higher) |
+| TaskFit | 0.10 | Model × task type fitness score |
+| Stability | 0.10 | Low variance in latency/errors |
+
+## Mode Packs
+
+| Pack | Focus | Key Weight |
+| :---------------------- | :----------- | :--------------- |
+| 🚀 **Ship Fast** | Speed | latencyInv: 0.35 |
+| 💰 **Cost Saver** | Economy | costInv: 0.40 |
+| 🎯 **Quality First** | Best model | taskFit: 0.40 |
+| 📡 **Offline Friendly** | Availability | quota: 0.40 |
+
+## Self-Healing
+
+- **Temporary exclusion**: Score < 0.2 → excluded for 5 min (progressive backoff, max 30 min)
+- **Circuit breaker awareness**: OPEN → auto-excluded; HALF_OPEN → probe requests
+- **Incident mode**: >50% OPEN → disable exploration, maximize stability
+- **Cooldown recovery**: After exclusion, first request is a "probe" with reduced timeout
+
+## Bandit Exploration
+
+5% of requests (configurable) are routed to random providers for exploration. Disabled in incident mode.
+
+## API
+
+```bash
+# Create auto-combo
+curl -X POST http://localhost:20128/api/combos/auto \
+ -H "Content-Type: application/json" \
+ -d '{"id":"my-auto","name":"Auto Coder","candidatePool":["anthropic","google","openai"],"modePack":"ship-fast"}'
+
+# List auto-combos
+curl http://localhost:20128/api/combos/auto
+```
+
+## Task Fitness
+
+30+ models scored across 6 task types (`coding`, `review`, `planning`, `analysis`, `debugging`, `documentation`). Supports wildcard patterns (e.g., `*-coder` → high coding score).
+
+## Files
+
+| File | Purpose |
+| :------------------------------------------- | :------------------------------------ |
+| `open-sse/services/autoCombo/scoring.ts` | Scoring function & pool normalization |
+| `open-sse/services/autoCombo/taskFitness.ts` | Model × task fitness lookup |
+| `open-sse/services/autoCombo/engine.ts` | Selection logic, bandit, budget cap |
+| `open-sse/services/autoCombo/selfHealing.ts` | Exclusion, probes, incident mode |
+| `open-sse/services/autoCombo/modePacks.ts` | 4 weight profiles |
+| `src/app/api/combos/auto/route.ts` | REST API |
diff --git a/docs/i18n/cs/docs/CLI-TOOLS.md b/docs/i18n/cs/docs/CLI-TOOLS.md
new file mode 100644
index 0000000000..4bc5c08051
--- /dev/null
+++ b/docs/i18n/cs/docs/CLI-TOOLS.md
@@ -0,0 +1,348 @@
+# CLI Tools Setup Guide — OmniRoute (Čeština)
+
+🌐 **Languages:** 🇺🇸 [English](../../../../docs/CLI-TOOLS.md) · 🇪🇸 [es](../../es/docs/CLI-TOOLS.md) · 🇫🇷 [fr](../../fr/docs/CLI-TOOLS.md) · 🇩🇪 [de](../../de/docs/CLI-TOOLS.md) · 🇮🇹 [it](../../it/docs/CLI-TOOLS.md) · 🇷🇺 [ru](../../ru/docs/CLI-TOOLS.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/CLI-TOOLS.md) · 🇯🇵 [ja](../../ja/docs/CLI-TOOLS.md) · 🇰🇷 [ko](../../ko/docs/CLI-TOOLS.md) · 🇸🇦 [ar](../../ar/docs/CLI-TOOLS.md) · 🇮🇳 [in](../../in/docs/CLI-TOOLS.md) · 🇹🇭 [th](../../th/docs/CLI-TOOLS.md) · 🇻🇳 [vi](../../vi/docs/CLI-TOOLS.md) · 🇮🇩 [id](../../id/docs/CLI-TOOLS.md) · 🇲🇾 [ms](../../ms/docs/CLI-TOOLS.md) · 🇳🇱 [nl](../../nl/docs/CLI-TOOLS.md) · 🇵🇱 [pl](../../pl/docs/CLI-TOOLS.md) · 🇸🇪 [sv](../../sv/docs/CLI-TOOLS.md) · 🇳🇴 [no](../../no/docs/CLI-TOOLS.md) · 🇩🇰 [da](../../da/docs/CLI-TOOLS.md) · 🇫🇮 [fi](../../fi/docs/CLI-TOOLS.md) · 🇵🇹 [pt](../../pt/docs/CLI-TOOLS.md) · 🇷🇴 [ro](../../ro/docs/CLI-TOOLS.md) · 🇭🇺 [hu](../../hu/docs/CLI-TOOLS.md) · 🇧🇬 [bg](../../bg/docs/CLI-TOOLS.md) · 🇸🇰 [sk](../../sk/docs/CLI-TOOLS.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/CLI-TOOLS.md) · 🇮🇱 [he](../../he/docs/CLI-TOOLS.md) · 🇵🇭 [phi](../../phi/docs/CLI-TOOLS.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/CLI-TOOLS.md) · 🇨🇿 [cs](../../cs/docs/CLI-TOOLS.md)
+
+---
+
+This guide explains how to install and configure all supported AI coding CLI tools
+to use **OmniRoute** as the unified backend, giving you centralized key management,
+cost tracking, model switching, and request logging across every tool.
+
+---
+
+## How It Works
+
+```
+Claude / Codex / OpenCode / Cline / KiloCode / Continue / Kiro / Cursor / Copilot
+ │
+ ▼ (all point to OmniRoute)
+ http://YOUR_SERVER:20128/v1
+ │
+ ▼ (OmniRoute routes to the right provider)
+ Anthropic / OpenAI / Gemini / DeepSeek / Groq / Mistral / ...
+```
+
+**Benefits:**
+
+- One API key to manage all tools
+- Cost tracking across all CLIs in the dashboard
+- Model switching without reconfiguring every tool
+- Works locally and on remote servers (VPS)
+
+---
+
+## Supported Tools (Dashboard Source of Truth)
+
+The dashboard cards in `/dashboard/cli-tools` are generated from `src/shared/constants/cliTools.ts`.
+Current list (v3.0.0-rc.16):
+
+| Tool | ID | Command | Setup Mode | Install Method |
+| ------------------ | ------------- | ---------- | ---------- | -------------- |
+| **Claude Code** | `claude` | `claude` | env | npm |
+| **OpenAI Codex** | `codex` | `codex` | custom | npm |
+| **Factory Droid** | `droid` | `droid` | custom | bundled/CLI |
+| **OpenClaw** | `openclaw` | `openclaw` | custom | bundled/CLI |
+| **Cursor** | `cursor` | app | guide | desktop app |
+| **Cline** | `cline` | `cline` | custom | npm |
+| **Kilo Code** | `kilo` | `kilocode` | custom | npm |
+| **Continue** | `continue` | extension | guide | VS Code |
+| **Antigravity** | `antigravity` | internal | mitm | OmniRoute |
+| **GitHub Copilot** | `copilot` | extension | custom | VS Code |
+| **OpenCode** | `opencode` | `opencode` | guide | npm |
+| **Kiro AI** | `kiro` | app/cli | mitm | desktop/CLI |
+
+### CLI fingerprint sync (Agents + Settings)
+
+`/dashboard/agents` and `Settings > CLI Fingerprint` use `src/shared/constants/cliCompatProviders.ts`.
+This keeps provider IDs aligned with CLI cards and legacy IDs.
+
+| CLI ID | Fingerprint Provider ID |
+| ---------------------------------------------------------------------------------------------------- | ----------------------- |
+| `kilo` | `kilocode` |
+| `copilot` | `github` |
+| `claude` / `codex` / `antigravity` / `kiro` / `cursor` / `cline` / `opencode` / `droid` / `openclaw` | same ID |
+
+Legacy IDs still accepted for compatibility: `copilot`, `kimi-coding`, `qwen`.
+
+---
+
+## Step 1 — Get an OmniRoute API Key
+
+1. Open the OmniRoute dashboard → **API Manager** (`/dashboard/api-manager`)
+2. Click **Create API Key**
+3. Give it a name (e.g. `cli-tools`) and select all permissions
+4. Copy the key — you'll need it for every CLI below
+
+> Your key looks like: `sk-xxxxxxxxxxxxxxxx-xxxxxxxxx`
+
+---
+
+## Step 2 — Install CLI Tools
+
+All npm-based tools require Node.js 18+:
+
+```bash
+# Claude Code (Anthropic)
+npm install -g @anthropic-ai/claude-code
+
+# OpenAI Codex
+npm install -g @openai/codex
+
+# OpenCode
+npm install -g opencode-ai
+
+# Cline
+npm install -g cline
+
+# KiloCode
+npm install -g kilocode
+
+# Kiro CLI (Amazon — requires curl + unzip)
+apt-get install -y unzip # on Debian/Ubuntu
+curl -fsSL https://cli.kiro.dev/install | bash
+export PATH="$HOME/.local/bin:$PATH" # add to ~/.bashrc
+```
+
+**Verify:**
+
+```bash
+claude --version # 2.x.x
+codex --version # 0.x.x
+opencode --version # x.x.x
+cline --version # 2.x.x
+kilocode --version # x.x.x (or: kilo --version)
+kiro-cli --version # 1.x.x
+```
+
+---
+
+## Step 3 — Set Global Environment Variables
+
+Add to `~/.bashrc` (or `~/.zshrc`), then run `source ~/.bashrc`:
+
+```bash
+# OmniRoute Universal Endpoint
+export OPENAI_BASE_URL="http://localhost:20128/v1"
+export OPENAI_API_KEY="sk-your-omniroute-key"
+export ANTHROPIC_BASE_URL="http://localhost:20128/v1"
+export ANTHROPIC_API_KEY="sk-your-omniroute-key"
+export GEMINI_BASE_URL="http://localhost:20128/v1"
+export GEMINI_API_KEY="sk-your-omniroute-key"
+```
+
+> For a **remote server** replace `localhost:20128` with the server IP or domain,
+> e.g. `http://192.168.0.15:20128`.
+
+---
+
+## Step 4 — Configure Each Tool
+
+### Claude Code
+
+```bash
+# Via CLI:
+claude config set --global api-base-url http://localhost:20128/v1
+
+# Or create ~/.claude/settings.json:
+mkdir -p ~/.claude && cat > ~/.claude/settings.json << EOF
+{
+ "apiBaseUrl": "http://localhost:20128/v1",
+ "apiKey": "sk-your-omniroute-key"
+}
+EOF
+```
+
+**Test:** `claude "say hello"`
+
+---
+
+### OpenAI Codex
+
+```bash
+mkdir -p ~/.codex && cat > ~/.codex/config.yaml << EOF
+model: auto
+apiKey: sk-your-omniroute-key
+apiBaseUrl: http://localhost:20128/v1
+EOF
+```
+
+**Test:** `codex "what is 2+2?"`
+
+---
+
+### OpenCode
+
+```bash
+mkdir -p ~/.config/opencode && cat > ~/.config/opencode/config.toml << EOF
+[provider.openai]
+base_url = "http://localhost:20128/v1"
+api_key = "sk-your-omniroute-key"
+EOF
+```
+
+**Test:** `opencode`
+
+---
+
+### Cline (CLI or VS Code)
+
+**CLI mode:**
+
+```bash
+mkdir -p ~/.cline/data && cat > ~/.cline/data/globalState.json << EOF
+{
+ "apiProvider": "openai",
+ "openAiBaseUrl": "http://localhost:20128/v1",
+ "openAiApiKey": "sk-your-omniroute-key"
+}
+EOF
+```
+
+**VS Code mode:**
+Cline extension settings → API Provider: `OpenAI Compatible` → Base URL: `http://localhost:20128/v1`
+
+Or use the OmniRoute dashboard → **CLI Tools → Cline → Apply Config**.
+
+---
+
+### KiloCode (CLI or VS Code)
+
+**CLI mode:**
+
+```bash
+kilocode --api-base http://localhost:20128/v1 --api-key sk-your-omniroute-key
+```
+
+**VS Code settings:**
+
+```json
+{
+ "kilo-code.openAiBaseUrl": "http://localhost:20128/v1",
+ "kilo-code.apiKey": "sk-your-omniroute-key"
+}
+```
+
+Or use the OmniRoute dashboard → **CLI Tools → KiloCode → Apply Config**.
+
+---
+
+### Continue (VS Code Extension)
+
+Edit `~/.continue/config.yaml`:
+
+```yaml
+models:
+ - name: OmniRoute
+ provider: openai
+ model: auto
+ apiBase: http://localhost:20128/v1
+ apiKey: sk-your-omniroute-key
+ default: true
+```
+
+Restart VS Code after editing.
+
+---
+
+### Kiro CLI (Amazon)
+
+```bash
+# Login to your AWS/Kiro account:
+kiro-cli login
+
+# The CLI uses its own auth — OmniRoute is not needed as backend for Kiro CLI itself.
+# Use kiro-cli alongside OmniRoute for other tools.
+kiro-cli status
+```
+
+---
+
+### Cursor (Desktop App)
+
+> **Note:** Cursor routes requests through its cloud. For OmniRoute integration,
+> enable **Cloud Endpoint** in OmniRoute Settings and use your public domain URL.
+
+Via GUI: **Settings → Models → OpenAI API Key**
+
+- Base URL: `https://your-domain.com/v1`
+- API Key: your OmniRoute key
+
+---
+
+## Dashboard Auto-Configuration
+
+The OmniRoute dashboard automates configuration for most tools:
+
+1. Go to `http://localhost:20128/dashboard/cli-tools`
+2. Expand any tool card
+3. Select your API key from the dropdown
+4. Click **Apply Config** (if tool is detected as installed)
+5. Or copy the generated config snippet manually
+
+---
+
+## Built-in Agents: Droid & OpenClaw
+
+**Droid** and **OpenClaw** are AI agents built directly into OmniRoute — no installation needed.
+They run as internal routes and use OmniRoute's model routing automatically.
+
+- Access: `http://localhost:20128/dashboard/agents`
+- Configure: same combos and providers as all other tools
+- No API key or CLI install required
+
+---
+
+## Available API Endpoints
+
+| Endpoint | Description | Use For |
+| -------------------------- | ----------------------------- | --------------------------- |
+| `/v1/chat/completions` | Standard chat (all providers) | All modern tools |
+| `/v1/responses` | Responses API (OpenAI format) | Codex, agentic workflows |
+| `/v1/completions` | Legacy text completions | Older tools using `prompt:` |
+| `/v1/embeddings` | Text embeddings | RAG, search |
+| `/v1/images/generations` | Image generation | DALL-E, Flux, etc. |
+| `/v1/audio/speech` | Text-to-speech | ElevenLabs, OpenAI TTS |
+| `/v1/audio/transcriptions` | Speech-to-text | Deepgram, AssemblyAI |
+
+---
+
+## Řešení problémů
+
+| Error | Cause | Fix |
+| ------------------------- | ----------------------- | ------------------------------------------ |
+| `Connection refused` | OmniRoute not running | `pm2 start omniroute` |
+| `401 Unauthorized` | Wrong API key | Check in `/dashboard/api-manager` |
+| `No combo configured` | No active routing combo | Set up in `/dashboard/combos` |
+| `invalid model` | Model not in catalog | Use `auto` or check `/dashboard/providers` |
+| CLI shows "not installed" | Binary not in PATH | Check `which ` |
+| `kiro-cli: not found` | Not in PATH | `export PATH="$HOME/.local/bin:$PATH"` |
+
+---
+
+## Quick Setup Script (One Command)
+
+```bash
+# Install all CLIs and configure for OmniRoute (replace with your key and server URL)
+OMNIROUTE_URL="http://localhost:20128/v1"
+OMNIROUTE_KEY="sk-your-omniroute-key"
+
+npm install -g @anthropic-ai/claude-code @openai/codex opencode-ai cline kilocode
+
+# Kiro CLI
+apt-get install -y unzip 2>/dev/null; curl -fsSL https://cli.kiro.dev/install | bash
+
+# Write configs
+mkdir -p ~/.claude ~/.codex ~/.config/opencode ~/.continue
+
+cat > ~/.claude/settings.json <<< "{\"apiBaseUrl\":\"$OMNIROUTE_URL\",\"apiKey\":\"$OMNIROUTE_KEY\"}"
+cat > ~/.codex/config.yaml <<< "model: auto\napiKey: $OMNIROUTE_KEY\napiBaseUrl: $OMNIROUTE_URL"
+cat >> ~/.bashrc << EOF
+export OPENAI_BASE_URL="$OMNIROUTE_URL"
+export OPENAI_API_KEY="$OMNIROUTE_KEY"
+export ANTHROPIC_BASE_URL="$OMNIROUTE_URL"
+export ANTHROPIC_API_KEY="$OMNIROUTE_KEY"
+EOF
+
+source ~/.bashrc
+echo "✅ All CLIs installed and configured for OmniRoute"
+```
diff --git a/docs/i18n/de/CODEBASE_DOCUMENTATION.md b/docs/i18n/cs/docs/CODEBASE_DOCUMENTATION.md
similarity index 91%
rename from docs/i18n/de/CODEBASE_DOCUMENTATION.md
rename to docs/i18n/cs/docs/CODEBASE_DOCUMENTATION.md
index e2d7950052..1be858fc65 100644
--- a/docs/i18n/de/CODEBASE_DOCUMENTATION.md
+++ b/docs/i18n/cs/docs/CODEBASE_DOCUMENTATION.md
@@ -1,11 +1,9 @@
-🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/CODEBASE_DOCUMENTATION.md) · 🇪🇸 [es](../es/CODEBASE_DOCUMENTATION.md) · 🇫🇷 [fr](../fr/CODEBASE_DOCUMENTATION.md) · 🇩🇪 [de](../de/CODEBASE_DOCUMENTATION.md) · 🇮🇹 [it](../it/CODEBASE_DOCUMENTATION.md) · 🇷🇺 [ru](../ru/CODEBASE_DOCUMENTATION.md) · 🇨🇳 [zh-CN](../zh-CN/CODEBASE_DOCUMENTATION.md) · 🇯🇵 [ja](../ja/CODEBASE_DOCUMENTATION.md) · 🇰🇷 [ko](../ko/CODEBASE_DOCUMENTATION.md) · 🇸🇦 [ar](../ar/CODEBASE_DOCUMENTATION.md) · 🇮🇳 [in](../in/CODEBASE_DOCUMENTATION.md) · 🇹🇭 [th](../th/CODEBASE_DOCUMENTATION.md) · 🇻🇳 [vi](../vi/CODEBASE_DOCUMENTATION.md) · 🇮🇩 [id](../id/CODEBASE_DOCUMENTATION.md) · 🇲🇾 [ms](../ms/CODEBASE_DOCUMENTATION.md) · 🇳🇱 [nl](../nl/CODEBASE_DOCUMENTATION.md) · 🇵🇱 [pl](../pl/CODEBASE_DOCUMENTATION.md) · 🇸🇪 [sv](../sv/CODEBASE_DOCUMENTATION.md) · 🇳🇴 [no](../no/CODEBASE_DOCUMENTATION.md) · 🇩🇰 [da](../da/CODEBASE_DOCUMENTATION.md) · 🇫🇮 [fi](../fi/CODEBASE_DOCUMENTATION.md) · 🇵🇹 [pt](../pt/CODEBASE_DOCUMENTATION.md) · 🇷🇴 [ro](../ro/CODEBASE_DOCUMENTATION.md) · 🇭🇺 [hu](../hu/CODEBASE_DOCUMENTATION.md) · 🇧🇬 [bg](../bg/CODEBASE_DOCUMENTATION.md) · 🇸🇰 [sk](../sk/CODEBASE_DOCUMENTATION.md) · 🇺🇦 [uk-UA](../uk-UA/CODEBASE_DOCUMENTATION.md) · 🇮🇱 [he](../he/CODEBASE_DOCUMENTATION.md) · 🇵🇭 [phi](../phi/CODEBASE_DOCUMENTATION.md)
+# omniroute — Codebase Documentation (Čeština)
+
+🌐 **Languages:** 🇺🇸 [English](../../../../docs/CODEBASE_DOCUMENTATION.md) · 🇪🇸 [es](../../es/docs/CODEBASE_DOCUMENTATION.md) · 🇫🇷 [fr](../../fr/docs/CODEBASE_DOCUMENTATION.md) · 🇩🇪 [de](../../de/docs/CODEBASE_DOCUMENTATION.md) · 🇮🇹 [it](../../it/docs/CODEBASE_DOCUMENTATION.md) · 🇷🇺 [ru](../../ru/docs/CODEBASE_DOCUMENTATION.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/CODEBASE_DOCUMENTATION.md) · 🇯🇵 [ja](../../ja/docs/CODEBASE_DOCUMENTATION.md) · 🇰🇷 [ko](../../ko/docs/CODEBASE_DOCUMENTATION.md) · 🇸🇦 [ar](../../ar/docs/CODEBASE_DOCUMENTATION.md) · 🇮🇳 [in](../../in/docs/CODEBASE_DOCUMENTATION.md) · 🇹🇭 [th](../../th/docs/CODEBASE_DOCUMENTATION.md) · 🇻🇳 [vi](../../vi/docs/CODEBASE_DOCUMENTATION.md) · 🇮🇩 [id](../../id/docs/CODEBASE_DOCUMENTATION.md) · 🇲🇾 [ms](../../ms/docs/CODEBASE_DOCUMENTATION.md) · 🇳🇱 [nl](../../nl/docs/CODEBASE_DOCUMENTATION.md) · 🇵🇱 [pl](../../pl/docs/CODEBASE_DOCUMENTATION.md) · 🇸🇪 [sv](../../sv/docs/CODEBASE_DOCUMENTATION.md) · 🇳🇴 [no](../../no/docs/CODEBASE_DOCUMENTATION.md) · 🇩🇰 [da](../../da/docs/CODEBASE_DOCUMENTATION.md) · 🇫🇮 [fi](../../fi/docs/CODEBASE_DOCUMENTATION.md) · 🇵🇹 [pt](../../pt/docs/CODEBASE_DOCUMENTATION.md) · 🇷🇴 [ro](../../ro/docs/CODEBASE_DOCUMENTATION.md) · 🇭🇺 [hu](../../hu/docs/CODEBASE_DOCUMENTATION.md) · 🇧🇬 [bg](../../bg/docs/CODEBASE_DOCUMENTATION.md) · 🇸🇰 [sk](../../sk/docs/CODEBASE_DOCUMENTATION.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/CODEBASE_DOCUMENTATION.md) · 🇮🇱 [he](../../he/docs/CODEBASE_DOCUMENTATION.md) · 🇵🇭 [phi](../../phi/docs/CODEBASE_DOCUMENTATION.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/CODEBASE_DOCUMENTATION.md) · 🇨🇿 [cs](../../cs/docs/CODEBASE_DOCUMENTATION.md)
---
-# omniroute — Codebase Documentation
-
-🌐 **Languages:** 🇺🇸 [English](CODEBASE_DOCUMENTATION.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/CODEBASE_DOCUMENTATION.md) | 🇪🇸 [Español](i18n/es/CODEBASE_DOCUMENTATION.md) | 🇫🇷 [Français](i18n/fr/CODEBASE_DOCUMENTATION.md) | 🇮🇹 [Italiano](i18n/it/CODEBASE_DOCUMENTATION.md) | 🇷🇺 [Русский](i18n/ru/CODEBASE_DOCUMENTATION.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/CODEBASE_DOCUMENTATION.md) | 🇩🇪 [Deutsch](i18n/de/CODEBASE_DOCUMENTATION.md) | 🇮🇳 [हिन्दी](i18n/in/CODEBASE_DOCUMENTATION.md) | 🇹🇭 [ไทย](i18n/th/CODEBASE_DOCUMENTATION.md) | 🇺🇦 [Українська](i18n/uk-UA/CODEBASE_DOCUMENTATION.md) | 🇸🇦 [العربية](i18n/ar/CODEBASE_DOCUMENTATION.md) | 🇯🇵 [日本語](i18n/ja/CODEBASE_DOCUMENTATION.md) | 🇻🇳 [Tiếng Việt](i18n/vi/CODEBASE_DOCUMENTATION.md) | 🇧🇬 [Български](i18n/bg/CODEBASE_DOCUMENTATION.md) | 🇩🇰 [Dansk](i18n/da/CODEBASE_DOCUMENTATION.md) | 🇫🇮 [Suomi](i18n/fi/CODEBASE_DOCUMENTATION.md) | 🇮🇱 [עברית](i18n/he/CODEBASE_DOCUMENTATION.md) | 🇭🇺 [Magyar](i18n/hu/CODEBASE_DOCUMENTATION.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/CODEBASE_DOCUMENTATION.md) | 🇰🇷 [한국어](i18n/ko/CODEBASE_DOCUMENTATION.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/CODEBASE_DOCUMENTATION.md) | 🇳🇱 [Nederlands](i18n/nl/CODEBASE_DOCUMENTATION.md) | 🇳🇴 [Norsk](i18n/no/CODEBASE_DOCUMENTATION.md) | 🇵🇹 [Português (Portugal)](i18n/pt/CODEBASE_DOCUMENTATION.md) | 🇷🇴 [Română](i18n/ro/CODEBASE_DOCUMENTATION.md) | 🇵🇱 [Polski](i18n/pl/CODEBASE_DOCUMENTATION.md) | 🇸🇰 [Slovenčina](i18n/sk/CODEBASE_DOCUMENTATION.md) | 🇸🇪 [Svenska](i18n/sv/CODEBASE_DOCUMENTATION.md) | 🇵🇭 [Filipino](i18n/phi/CODEBASE_DOCUMENTATION.md)
-
> A comprehensive, beginner-friendly guide to the **omniroute** multi-provider AI proxy router.
---
@@ -352,7 +350,7 @@ flowchart LR
The **format translation engine** using a self-registering plugin system.
-#### Architecture
+#### Architektura
```mermaid
graph TD
diff --git a/docs/i18n/cs/docs/COVERAGE_PLAN.md b/docs/i18n/cs/docs/COVERAGE_PLAN.md
new file mode 100644
index 0000000000..f1c783733d
--- /dev/null
+++ b/docs/i18n/cs/docs/COVERAGE_PLAN.md
@@ -0,0 +1,170 @@
+# Test Coverage Plan (Čeština)
+
+🌐 **Languages:** 🇺🇸 [English](../../../../docs/COVERAGE_PLAN.md) · 🇪🇸 [es](../../es/docs/COVERAGE_PLAN.md) · 🇫🇷 [fr](../../fr/docs/COVERAGE_PLAN.md) · 🇩🇪 [de](../../de/docs/COVERAGE_PLAN.md) · 🇮🇹 [it](../../it/docs/COVERAGE_PLAN.md) · 🇷🇺 [ru](../../ru/docs/COVERAGE_PLAN.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/COVERAGE_PLAN.md) · 🇯🇵 [ja](../../ja/docs/COVERAGE_PLAN.md) · 🇰🇷 [ko](../../ko/docs/COVERAGE_PLAN.md) · 🇸🇦 [ar](../../ar/docs/COVERAGE_PLAN.md) · 🇮🇳 [in](../../in/docs/COVERAGE_PLAN.md) · 🇹🇭 [th](../../th/docs/COVERAGE_PLAN.md) · 🇻🇳 [vi](../../vi/docs/COVERAGE_PLAN.md) · 🇮🇩 [id](../../id/docs/COVERAGE_PLAN.md) · 🇲🇾 [ms](../../ms/docs/COVERAGE_PLAN.md) · 🇳🇱 [nl](../../nl/docs/COVERAGE_PLAN.md) · 🇵🇱 [pl](../../pl/docs/COVERAGE_PLAN.md) · 🇸🇪 [sv](../../sv/docs/COVERAGE_PLAN.md) · 🇳🇴 [no](../../no/docs/COVERAGE_PLAN.md) · 🇩🇰 [da](../../da/docs/COVERAGE_PLAN.md) · 🇫🇮 [fi](../../fi/docs/COVERAGE_PLAN.md) · 🇵🇹 [pt](../../pt/docs/COVERAGE_PLAN.md) · 🇷🇴 [ro](../../ro/docs/COVERAGE_PLAN.md) · 🇭🇺 [hu](../../hu/docs/COVERAGE_PLAN.md) · 🇧🇬 [bg](../../bg/docs/COVERAGE_PLAN.md) · 🇸🇰 [sk](../../sk/docs/COVERAGE_PLAN.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/COVERAGE_PLAN.md) · 🇮🇱 [he](../../he/docs/COVERAGE_PLAN.md) · 🇵🇭 [phi](../../phi/docs/COVERAGE_PLAN.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/COVERAGE_PLAN.md) · 🇨🇿 [cs](../../cs/docs/COVERAGE_PLAN.md)
+
+---
+
+Last updated: 2026-03-28
+
+## Baseline
+
+There are multiple coverage numbers depending on how the report is computed. For planning, only one of them is useful.
+
+| Metric | Scope | Statements / Lines | Branches | Functions | Notes |
+| -------------------- | ----------------------------------------------------- | -----------------: | -------: | --------: | --------------------------------------------------- |
+| Legacy | Old `npm run test:coverage` | 79.42% | 75.15% | 67.94% | Inflated: counts test files and excludes `open-sse` |
+| Diagnostic | Source-only, excluding tests and excluding `open-sse` | 68.16% | 63.55% | 64.06% | Useful only to isolate `src/**` |
+| Recommended baseline | Source-only, excluding tests and including `open-sse` | 56.95% | 66.05% | 57.80% | This is the project-wide baseline to improve |
+
+The recommended baseline is the number to optimize against.
+
+## Rules
+
+- Coverage targets apply to source files, not to `tests/**`.
+- `open-sse/**` is part of the product and must remain in scope.
+- New code should not reduce coverage in touched areas.
+- Prefer testing behavior and branch outcomes over implementation details.
+- Prefer temp SQLite databases and small fixtures over broad mocks for `src/lib/db/**`.
+
+## Current command set
+
+- `npm run test:coverage`
+ - Main source coverage gate for the unit test suite
+ - Generates `text-summary`, `html`, `json-summary`, and `lcov`
+- `npm run coverage:report`
+ - Detailed file-by-file report from the latest run
+- `npm run test:coverage:legacy`
+ - Historical comparison only
+
+## Milestones
+
+| Phase | Target | Focus |
+| ------- | ---------------------: | ------------------------------------------------- |
+| Phase 1 | 60% statements / lines | Quick wins and low-risk utility coverage |
+| Phase 2 | 65% statements / lines | DB and route foundations |
+| Phase 3 | 70% statements / lines | Provider validation and usage analytics |
+| Phase 4 | 75% statements / lines | `open-sse` translators and helpers |
+| Phase 5 | 80% statements / lines | `open-sse` handlers and executor branches |
+| Phase 6 | 85% statements / lines | Harder edge cases, branch debt, regression suites |
+| Phase 7 | 90% statements / lines | Final sweep, gap closure, strict ratchet |
+
+Branches and functions should ratchet upward with each phase, but the primary hard target is statements / lines.
+
+## Priority hotspots
+
+These files or areas offer the best return for the next phases:
+
+1. `open-sse/handlers`
+ - `chatCore.ts` at 7.57%
+ - Overall directory at 29.07%
+2. `open-sse/translator/request`
+ - Overall directory at 36.39%
+ - Many translators are still near single-digit coverage
+3. `open-sse/translator/response`
+ - Overall directory at 8.07%
+4. `open-sse/executors`
+ - Overall directory at 36.62%
+5. `src/lib/db`
+ - `models.ts` at 20.66%
+ - `registeredKeys.ts` at 34.46%
+ - `modelComboMappings.ts` at 36.25%
+ - `settings.ts` at 46.40%
+ - `webhooks.ts` at 33.33%
+6. `src/lib/usage`
+ - `usageHistory.ts` at 21.12%
+ - `usageStats.ts` at 9.56%
+ - `costCalculator.ts` at 30.00%
+7. `src/lib/providers`
+ - `validation.ts` at 41.16%
+8. Low-risk utility and API files for early gains
+ - `src/shared/utils/upstreamError.ts`
+ - `src/shared/utils/apiAuth.ts`
+ - `src/lib/api/errorResponse.ts`
+ - `src/app/api/settings/require-login/route.ts`
+ - `src/app/api/providers/[id]/models/route.ts`
+
+## Execution checklist
+
+### Phase 1: 56.95% -> 60%
+
+- [x] Fix coverage metric so it reflects source code instead of test files
+- [x] Keep a legacy coverage script for comparison
+- [x] Record the baseline and hotspots in-repo
+- [ ] Add focused tests for low-risk utilities:
+ - `src/shared/utils/upstreamError.ts`
+ - `src/shared/utils/fetchTimeout.ts`
+ - `src/lib/api/errorResponse.ts`
+ - `src/shared/utils/apiAuth.ts`
+ - `src/lib/display/names.ts`
+- [ ] Add route tests for:
+ - `src/app/api/settings/require-login/route.ts`
+ - `src/app/api/providers/[id]/models/route.ts`
+
+### Phase 2: 60% -> 65%
+
+- [ ] Add DB-backed tests for:
+ - `src/lib/db/modelComboMappings.ts`
+ - `src/lib/db/settings.ts`
+ - `src/lib/db/registeredKeys.ts`
+- [ ] Cover branch behavior in:
+ - `src/lib/providers/validation.ts`
+ - `src/app/api/v1/embeddings/route.ts`
+ - `src/app/api/v1/moderations/route.ts`
+
+### Phase 3: 65% -> 70%
+
+- [ ] Add usage analytics tests for:
+ - `src/lib/usage/usageHistory.ts`
+ - `src/lib/usage/usageStats.ts`
+ - `src/lib/usage/costCalculator.ts`
+- [ ] Expand route coverage for proxy management and settings branches
+
+### Phase 4: 70% -> 75%
+
+- [ ] Cover translator helpers and central translation paths:
+ - `open-sse/translator/index.ts`
+ - `open-sse/translator/helpers/*`
+ - `open-sse/translator/request/*`
+ - `open-sse/translator/response/*`
+
+### Phase 5: 75% -> 80%
+
+- [ ] Add handler-level tests for:
+ - `open-sse/handlers/chatCore.ts`
+ - `open-sse/handlers/responsesHandler.js`
+ - `open-sse/handlers/imageGeneration.js`
+ - `open-sse/handlers/embeddings.js`
+- [ ] Add executor branch coverage for provider-specific auth, retries, and endpoint overrides
+
+### Phase 6: 80% -> 85%
+
+- [ ] Merge more edge-case suites into the main coverage path
+- [ ] Increase function coverage for DB modules with weak constructor/helper coverage
+- [ ] Close branch gaps in `settings.ts`, `registeredKeys.ts`, `validation.ts`, and translator helpers
+
+### Phase 7: 85% -> 90%
+
+- [ ] Treat the remaining low-coverage files as blockers
+- [ ] Add regression tests for every uncovered production bug fixed during the push to 90%
+- [ ] Raise the coverage gate in CI only after the local baseline is stable for at least two consecutive runs
+
+## Ratchet policy
+
+Update `npm run test:coverage` thresholds only after the project actually exceeds the next milestone with a comfortable buffer.
+
+Recommended ratchet sequence:
+
+1. 55/60/55
+2. 60/62/58
+3. 65/64/62
+4. 70/66/66
+5. 75/70/72
+6. 80/75/78
+7. 85/80/84
+8. 90/85/88
+
+Order is `statements-lines / branches / functions`.
+
+## Known gap
+
+The current coverage command measures the main Node unit suite and includes source reached from it, including `open-sse`. It does not yet merge Vitest coverage into a single unified report. That merge is worth doing later, but it is not a blocker for starting the 60% -> 80% climb.
diff --git a/docs/i18n/de/FEATURES.md b/docs/i18n/cs/docs/FEATURES.md
similarity index 75%
rename from docs/i18n/de/FEATURES.md
rename to docs/i18n/cs/docs/FEATURES.md
index c212d33261..7743ece44e 100644
--- a/docs/i18n/de/FEATURES.md
+++ b/docs/i18n/cs/docs/FEATURES.md
@@ -1,8 +1,6 @@
-# OmniRoute — Dashboard Features Gallery (Deutsch)
+# OmniRoute — Dashboard Features Gallery (Čeština)
-🌐 **Languages:** 🇺🇸 [English](../../../README.md) · 🇧🇷 [pt-BR](../pt-BR/README.md) · 🇪🇸 [es](../es/README.md) · 🇫🇷 [fr](../fr/README.md) · 🇩🇪 [de](../de/README.md) · 🇮🇹 [it](../it/README.md) · 🇷🇺 [ru](../ru/README.md) · 🇨🇳 [zh-CN](../zh-CN/README.md) · 🇯🇵 [ja](../ja/README.md) · 🇰🇷 [ko](../ko/README.md) · 🇸🇦 [ar](../ar/README.md) · 🇮🇳 [in](../in/README.md) · 🇹🇭 [th](../th/README.md) · 🇻🇳 [vi](../vi/README.md) · 🇮🇩 [id](../id/README.md) · 🇲🇾 [ms](../ms/README.md) · 🇳🇱 [nl](../nl/README.md) · 🇵🇱 [pl](../pl/README.md) · 🇸🇪 [sv](../sv/README.md) · 🇳🇴 [no](../no/README.md) · 🇩🇰 [da](../da/README.md) · 🇫🇮 [fi](../fi/README.md) · 🇵🇹 [pt](../pt/README.md) · 🇷🇴 [ro](../ro/README.md) · 🇭🇺 [hu](../hu/README.md) · 🇧🇬 [bg](../bg/README.md) · 🇸🇰 [sk](../sk/README.md) · 🇺🇦 [uk-UA](../uk-UA/README.md) · 🇮🇱 [he](../he/README.md) · 🇵🇭 [phi](../phi/README.md)
-
-> 🇺🇸 [English](../../../docs/FEATURES.md)
+🌐 **Languages:** 🇺🇸 [English](../../../../docs/FEATURES.md) · 🇪🇸 [es](../../es/docs/FEATURES.md) · 🇫🇷 [fr](../../fr/docs/FEATURES.md) · 🇩🇪 [de](../../de/docs/FEATURES.md) · 🇮🇹 [it](../../it/docs/FEATURES.md) · 🇷🇺 [ru](../../ru/docs/FEATURES.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/FEATURES.md) · 🇯🇵 [ja](../../ja/docs/FEATURES.md) · 🇰🇷 [ko](../../ko/docs/FEATURES.md) · 🇸🇦 [ar](../../ar/docs/FEATURES.md) · 🇮🇳 [in](../../in/docs/FEATURES.md) · 🇹🇭 [th](../../th/docs/FEATURES.md) · 🇻🇳 [vi](../../vi/docs/FEATURES.md) · 🇮🇩 [id](../../id/docs/FEATURES.md) · 🇲🇾 [ms](../../ms/docs/FEATURES.md) · 🇳🇱 [nl](../../nl/docs/FEATURES.md) · 🇵🇱 [pl](../../pl/docs/FEATURES.md) · 🇸🇪 [sv](../../sv/docs/FEATURES.md) · 🇳🇴 [no](../../no/docs/FEATURES.md) · 🇩🇰 [da](../../da/docs/FEATURES.md) · 🇫🇮 [fi](../../fi/docs/FEATURES.md) · 🇵🇹 [pt](../../pt/docs/FEATURES.md) · 🇷🇴 [ro](../../ro/docs/FEATURES.md) · 🇭🇺 [hu](../../hu/docs/FEATURES.md) · 🇧🇬 [bg](../../bg/docs/FEATURES.md) · 🇸🇰 [sk](../../sk/docs/FEATURES.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/FEATURES.md) · 🇮🇱 [he](../../he/docs/FEATURES.md) · 🇵🇭 [phi](../../phi/docs/FEATURES.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/FEATURES.md) · 🇨🇿 [cs](../../cs/docs/FEATURES.md)
---
@@ -70,8 +68,8 @@ Comprehensive settings panel with tabs:
- **Appearance** — Theme selector (dark/light/system), color theme presets and custom colors, health log visibility, sidebar item visibility controls
- **Security** — API endpoint protection, custom provider blocking, IP filtering, session info
- **Routing** — Model aliases, background task degradation
-- **Resilience** — Rate limit persistence, circuit breaker tuning
-- **Advanced** — Configuration overrides
+- **Resilience** — Rate limit persistence, circuit breaker tuning, auto-disable banned accounts, provider expiration monitoring
+- **Advanced** — Configuration overrides, configuration audit trail, fallback degradation mode

@@ -112,7 +110,7 @@ Real-time request logging with filtering by provider, model, account, and API ke
## 🌐 API Endpoint
-Your unified API endpoint with capability breakdown: Chat Completions, Responses API, Embeddings, Image Generation, Reranking, Audio Transcription, Text-to-Speech, Moderations, and registered API keys. Cloud proxy support for remote access.
+Your unified API endpoint with capability breakdown: Chat Completions, Responses API, Embeddings, Image Generation, Reranking, Audio Transcription, Text-to-Speech, Moderations, and registered API keys. Cloudflare Quick Tunnel integration and cloud proxy support for remote access.

diff --git a/docs/i18n/cs/docs/MCP-SERVER.md b/docs/i18n/cs/docs/MCP-SERVER.md
new file mode 100644
index 0000000000..ac766bad88
--- /dev/null
+++ b/docs/i18n/cs/docs/MCP-SERVER.md
@@ -0,0 +1,87 @@
+# OmniRoute MCP Server Documentation (Čeština)
+
+🌐 **Languages:** 🇺🇸 [English](../../../../docs/MCP-SERVER.md) · 🇪🇸 [es](../../es/docs/MCP-SERVER.md) · 🇫🇷 [fr](../../fr/docs/MCP-SERVER.md) · 🇩🇪 [de](../../de/docs/MCP-SERVER.md) · 🇮🇹 [it](../../it/docs/MCP-SERVER.md) · 🇷🇺 [ru](../../ru/docs/MCP-SERVER.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/MCP-SERVER.md) · 🇯🇵 [ja](../../ja/docs/MCP-SERVER.md) · 🇰🇷 [ko](../../ko/docs/MCP-SERVER.md) · 🇸🇦 [ar](../../ar/docs/MCP-SERVER.md) · 🇮🇳 [in](../../in/docs/MCP-SERVER.md) · 🇹🇭 [th](../../th/docs/MCP-SERVER.md) · 🇻🇳 [vi](../../vi/docs/MCP-SERVER.md) · 🇮🇩 [id](../../id/docs/MCP-SERVER.md) · 🇲🇾 [ms](../../ms/docs/MCP-SERVER.md) · 🇳🇱 [nl](../../nl/docs/MCP-SERVER.md) · 🇵🇱 [pl](../../pl/docs/MCP-SERVER.md) · 🇸🇪 [sv](../../sv/docs/MCP-SERVER.md) · 🇳🇴 [no](../../no/docs/MCP-SERVER.md) · 🇩🇰 [da](../../da/docs/MCP-SERVER.md) · 🇫🇮 [fi](../../fi/docs/MCP-SERVER.md) · 🇵🇹 [pt](../../pt/docs/MCP-SERVER.md) · 🇷🇴 [ro](../../ro/docs/MCP-SERVER.md) · 🇭🇺 [hu](../../hu/docs/MCP-SERVER.md) · 🇧🇬 [bg](../../bg/docs/MCP-SERVER.md) · 🇸🇰 [sk](../../sk/docs/MCP-SERVER.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/MCP-SERVER.md) · 🇮🇱 [he](../../he/docs/MCP-SERVER.md) · 🇵🇭 [phi](../../phi/docs/MCP-SERVER.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/MCP-SERVER.md) · 🇨🇿 [cs](../../cs/docs/MCP-SERVER.md)
+
+---
+
+> Model Context Protocol server with 16 intelligent tools
+
+## Instalace
+
+OmniRoute MCP is built-in. Start it with:
+
+```bash
+omniroute --mcp
+```
+
+Or via the open-sse transport:
+
+```bash
+# HTTP streamable transport (port 20130)
+omniroute --dev # MCP auto-starts on /mcp endpoint
+```
+
+## IDE Configuration
+
+See [IDE Configs](integrations/ide-configs.md) for Antigravity, Cursor, Copilot, and Claude Desktop setup.
+
+---
+
+## Essential Tools (8)
+
+| Tool | Description |
+| :------------------------------ | :--------------------------------------- |
+| `omniroute_get_health` | Gateway health, circuit breakers, uptime |
+| `omniroute_list_combos` | All configured combos with models |
+| `omniroute_get_combo_metrics` | Performance metrics for a specific combo |
+| `omniroute_switch_combo` | Switch active combo by ID/name |
+| `omniroute_check_quota` | Quota status per provider or all |
+| `omniroute_route_request` | Send a chat completion through OmniRoute |
+| `omniroute_cost_report` | Cost analytics for a time period |
+| `omniroute_list_models_catalog` | Full model catalog with capabilities |
+
+## Advanced Tools (8)
+
+| Tool | Description |
+| :--------------------------------- | :---------------------------------------------------------- |
+| `omniroute_simulate_route` | Dry-run routing simulation with fallback tree |
+| `omniroute_set_budget_guard` | Session budget with degrade/block/alert actions |
+| `omniroute_set_resilience_profile` | Apply conservative/balanced/aggressive preset |
+| `omniroute_test_combo` | Live-test all models in a combo via a real upstream request |
+| `omniroute_get_provider_metrics` | Detailed metrics for one provider |
+| `omniroute_best_combo_for_task` | Task-fitness recommendation with alternatives |
+| `omniroute_explain_route` | Explain a past routing decision |
+| `omniroute_get_session_snapshot` | Full session state: costs, tokens, errors |
+
+## Authentication
+
+MCP tools are authenticated via API key scopes. Each tool requires specific scopes:
+
+| Scope | Tools |
+| :------------- | :----------------------------------------------- |
+| `read:health` | get_health, get_provider_metrics |
+| `read:combos` | list_combos, get_combo_metrics |
+| `write:combos` | switch_combo |
+| `read:quota` | check_quota |
+| `write:route` | route_request, simulate_route, test_combo |
+| `read:usage` | cost_report, get_session_snapshot, explain_route |
+| `write:config` | set_budget_guard, set_resilience_profile |
+| `read:models` | list_models_catalog, best_combo_for_task |
+
+## Audit Logging
+
+Every tool call is logged to `mcp_tool_audit` with:
+
+- Tool name, arguments, result
+- Duration (ms), success/failure
+- API key hash, timestamp
+
+## Files
+
+| File | Purpose |
+| :------------------------------------------- | :------------------------------------------ |
+| `open-sse/mcp-server/server.ts` | MCP server creation + 16 tool registrations |
+| `open-sse/mcp-server/transport.ts` | Stdio + HTTP transport |
+| `open-sse/mcp-server/auth.ts` | API key + scope validation |
+| `open-sse/mcp-server/audit.ts` | Tool call audit logging |
+| `open-sse/mcp-server/tools/advancedTools.ts` | 8 advanced tool handlers |
diff --git a/docs/i18n/cs/docs/RELEASE_CHECKLIST.md b/docs/i18n/cs/docs/RELEASE_CHECKLIST.md
new file mode 100644
index 0000000000..59b4301828
--- /dev/null
+++ b/docs/i18n/cs/docs/RELEASE_CHECKLIST.md
@@ -0,0 +1,37 @@
+# Release Checklist (Čeština)
+
+🌐 **Languages:** 🇺🇸 [English](../../../../docs/RELEASE_CHECKLIST.md) · 🇪🇸 [es](../../es/docs/RELEASE_CHECKLIST.md) · 🇫🇷 [fr](../../fr/docs/RELEASE_CHECKLIST.md) · 🇩🇪 [de](../../de/docs/RELEASE_CHECKLIST.md) · 🇮🇹 [it](../../it/docs/RELEASE_CHECKLIST.md) · 🇷🇺 [ru](../../ru/docs/RELEASE_CHECKLIST.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/RELEASE_CHECKLIST.md) · 🇯🇵 [ja](../../ja/docs/RELEASE_CHECKLIST.md) · 🇰🇷 [ko](../../ko/docs/RELEASE_CHECKLIST.md) · 🇸🇦 [ar](../../ar/docs/RELEASE_CHECKLIST.md) · 🇮🇳 [in](../../in/docs/RELEASE_CHECKLIST.md) · 🇹🇭 [th](../../th/docs/RELEASE_CHECKLIST.md) · 🇻🇳 [vi](../../vi/docs/RELEASE_CHECKLIST.md) · 🇮🇩 [id](../../id/docs/RELEASE_CHECKLIST.md) · 🇲🇾 [ms](../../ms/docs/RELEASE_CHECKLIST.md) · 🇳🇱 [nl](../../nl/docs/RELEASE_CHECKLIST.md) · 🇵🇱 [pl](../../pl/docs/RELEASE_CHECKLIST.md) · 🇸🇪 [sv](../../sv/docs/RELEASE_CHECKLIST.md) · 🇳🇴 [no](../../no/docs/RELEASE_CHECKLIST.md) · 🇩🇰 [da](../../da/docs/RELEASE_CHECKLIST.md) · 🇫🇮 [fi](../../fi/docs/RELEASE_CHECKLIST.md) · 🇵🇹 [pt](../../pt/docs/RELEASE_CHECKLIST.md) · 🇷🇴 [ro](../../ro/docs/RELEASE_CHECKLIST.md) · 🇭🇺 [hu](../../hu/docs/RELEASE_CHECKLIST.md) · 🇧🇬 [bg](../../bg/docs/RELEASE_CHECKLIST.md) · 🇸🇰 [sk](../../sk/docs/RELEASE_CHECKLIST.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/RELEASE_CHECKLIST.md) · 🇮🇱 [he](../../he/docs/RELEASE_CHECKLIST.md) · 🇵🇭 [phi](../../phi/docs/RELEASE_CHECKLIST.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/RELEASE_CHECKLIST.md) · 🇨🇿 [cs](../../cs/docs/RELEASE_CHECKLIST.md)
+
+---
+
+Use this checklist before tagging or publishing a new OmniRoute release.
+
+## Version and Changelog
+
+1. Bump `package.json` version (`x.y.z`) in the release branch.
+2. Move release notes from `## [Unreleased]` in `CHANGELOG.md` to a dated section:
+ - `## [x.y.z] — YYYY-MM-DD`
+3. Keep `## [Unreleased]` as the first changelog section for upcoming work.
+4. Ensure the latest semver section in `CHANGELOG.md` equals `package.json` version.
+
+## API Docs
+
+1. Update `docs/openapi.yaml`:
+ - `info.version` must equal `package.json` version.
+2. Validate endpoint examples if API contracts changed.
+
+## Runtime Docs
+
+1. Review `docs/ARCHITECTURE.md` for storage/runtime drift.
+2. Review `docs/TROUBLESHOOTING.md` for env var and operational drift.
+3. Update localized docs if source docs changed significantly.
+
+## Automated Check
+
+Run the sync guard locally before opening PR:
+
+```bash
+npm run check:docs-sync
+```
+
+CI also runs this check in `.github/workflows/ci.yml` (lint job).
diff --git a/docs/i18n/de/TROUBLESHOOTING.md b/docs/i18n/cs/docs/TROUBLESHOOTING.md
similarity index 77%
rename from docs/i18n/de/TROUBLESHOOTING.md
rename to docs/i18n/cs/docs/TROUBLESHOOTING.md
index 63c148000a..3194e66812 100644
--- a/docs/i18n/de/TROUBLESHOOTING.md
+++ b/docs/i18n/cs/docs/TROUBLESHOOTING.md
@@ -1,11 +1,9 @@
-🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/TROUBLESHOOTING.md) · 🇪🇸 [es](../es/TROUBLESHOOTING.md) · 🇫🇷 [fr](../fr/TROUBLESHOOTING.md) · 🇩🇪 [de](../de/TROUBLESHOOTING.md) · 🇮🇹 [it](../it/TROUBLESHOOTING.md) · 🇷🇺 [ru](../ru/TROUBLESHOOTING.md) · 🇨🇳 [zh-CN](../zh-CN/TROUBLESHOOTING.md) · 🇯🇵 [ja](../ja/TROUBLESHOOTING.md) · 🇰🇷 [ko](../ko/TROUBLESHOOTING.md) · 🇸🇦 [ar](../ar/TROUBLESHOOTING.md) · 🇮🇳 [in](../in/TROUBLESHOOTING.md) · 🇹🇭 [th](../th/TROUBLESHOOTING.md) · 🇻🇳 [vi](../vi/TROUBLESHOOTING.md) · 🇮🇩 [id](../id/TROUBLESHOOTING.md) · 🇲🇾 [ms](../ms/TROUBLESHOOTING.md) · 🇳🇱 [nl](../nl/TROUBLESHOOTING.md) · 🇵🇱 [pl](../pl/TROUBLESHOOTING.md) · 🇸🇪 [sv](../sv/TROUBLESHOOTING.md) · 🇳🇴 [no](../no/TROUBLESHOOTING.md) · 🇩🇰 [da](../da/TROUBLESHOOTING.md) · 🇫🇮 [fi](../fi/TROUBLESHOOTING.md) · 🇵🇹 [pt](../pt/TROUBLESHOOTING.md) · 🇷🇴 [ro](../ro/TROUBLESHOOTING.md) · 🇭🇺 [hu](../hu/TROUBLESHOOTING.md) · 🇧🇬 [bg](../bg/TROUBLESHOOTING.md) · 🇸🇰 [sk](../sk/TROUBLESHOOTING.md) · 🇺🇦 [uk-UA](../uk-UA/TROUBLESHOOTING.md) · 🇮🇱 [he](../he/TROUBLESHOOTING.md) · 🇵🇭 [phi](../phi/TROUBLESHOOTING.md)
+# Troubleshooting (Čeština)
+
+🌐 **Languages:** 🇺🇸 [English](../../../../docs/TROUBLESHOOTING.md) · 🇪🇸 [es](../../es/docs/TROUBLESHOOTING.md) · 🇫🇷 [fr](../../fr/docs/TROUBLESHOOTING.md) · 🇩🇪 [de](../../de/docs/TROUBLESHOOTING.md) · 🇮🇹 [it](../../it/docs/TROUBLESHOOTING.md) · 🇷🇺 [ru](../../ru/docs/TROUBLESHOOTING.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/TROUBLESHOOTING.md) · 🇯🇵 [ja](../../ja/docs/TROUBLESHOOTING.md) · 🇰🇷 [ko](../../ko/docs/TROUBLESHOOTING.md) · 🇸🇦 [ar](../../ar/docs/TROUBLESHOOTING.md) · 🇮🇳 [in](../../in/docs/TROUBLESHOOTING.md) · 🇹🇭 [th](../../th/docs/TROUBLESHOOTING.md) · 🇻🇳 [vi](../../vi/docs/TROUBLESHOOTING.md) · 🇮🇩 [id](../../id/docs/TROUBLESHOOTING.md) · 🇲🇾 [ms](../../ms/docs/TROUBLESHOOTING.md) · 🇳🇱 [nl](../../nl/docs/TROUBLESHOOTING.md) · 🇵🇱 [pl](../../pl/docs/TROUBLESHOOTING.md) · 🇸🇪 [sv](../../sv/docs/TROUBLESHOOTING.md) · 🇳🇴 [no](../../no/docs/TROUBLESHOOTING.md) · 🇩🇰 [da](../../da/docs/TROUBLESHOOTING.md) · 🇫🇮 [fi](../../fi/docs/TROUBLESHOOTING.md) · 🇵🇹 [pt](../../pt/docs/TROUBLESHOOTING.md) · 🇷🇴 [ro](../../ro/docs/TROUBLESHOOTING.md) · 🇭🇺 [hu](../../hu/docs/TROUBLESHOOTING.md) · 🇧🇬 [bg](../../bg/docs/TROUBLESHOOTING.md) · 🇸🇰 [sk](../../sk/docs/TROUBLESHOOTING.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/TROUBLESHOOTING.md) · 🇮🇱 [he](../../he/docs/TROUBLESHOOTING.md) · 🇵🇭 [phi](../../phi/docs/TROUBLESHOOTING.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/TROUBLESHOOTING.md) · 🇨🇿 [cs](../../cs/docs/TROUBLESHOOTING.md)
---
-# Troubleshooting
-
-🌐 **Languages:** 🇺🇸 [English](TROUBLESHOOTING.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/TROUBLESHOOTING.md) | 🇪🇸 [Español](i18n/es/TROUBLESHOOTING.md) | 🇫🇷 [Français](i18n/fr/TROUBLESHOOTING.md) | 🇮🇹 [Italiano](i18n/it/TROUBLESHOOTING.md) | 🇷🇺 [Русский](i18n/ru/TROUBLESHOOTING.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/TROUBLESHOOTING.md) | 🇩🇪 [Deutsch](i18n/de/TROUBLESHOOTING.md) | 🇮🇳 [हिन्दी](i18n/in/TROUBLESHOOTING.md) | 🇹🇭 [ไทย](i18n/th/TROUBLESHOOTING.md) | 🇺🇦 [Українська](i18n/uk-UA/TROUBLESHOOTING.md) | 🇸🇦 [العربية](i18n/ar/TROUBLESHOOTING.md) | 🇯🇵 [日本語](i18n/ja/TROUBLESHOOTING.md) | 🇻🇳 [Tiếng Việt](i18n/vi/TROUBLESHOOTING.md) | 🇧🇬 [Български](i18n/bg/TROUBLESHOOTING.md) | 🇩🇰 [Dansk](i18n/da/TROUBLESHOOTING.md) | 🇫🇮 [Suomi](i18n/fi/TROUBLESHOOTING.md) | 🇮🇱 [עברית](i18n/he/TROUBLESHOOTING.md) | 🇭🇺 [Magyar](i18n/hu/TROUBLESHOOTING.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/TROUBLESHOOTING.md) | 🇰🇷 [한국어](i18n/ko/TROUBLESHOOTING.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/TROUBLESHOOTING.md) | 🇳🇱 [Nederlands](i18n/nl/TROUBLESHOOTING.md) | 🇳🇴 [Norsk](i18n/no/TROUBLESHOOTING.md) | 🇵🇹 [Português (Portugal)](i18n/pt/TROUBLESHOOTING.md) | 🇷🇴 [Română](i18n/ro/TROUBLESHOOTING.md) | 🇵🇱 [Polski](i18n/pl/TROUBLESHOOTING.md) | 🇸🇰 [Slovenčina](i18n/sk/TROUBLESHOOTING.md) | 🇸🇪 [Svenska](i18n/sv/TROUBLESHOOTING.md) | 🇵🇭 [Filipino](i18n/phi/TROUBLESHOOTING.md)
-
Common problems and solutions for OmniRoute.
---
diff --git a/docs/i18n/cs/docs/USER_GUIDE.md b/docs/i18n/cs/docs/USER_GUIDE.md
new file mode 100644
index 0000000000..d972e842de
--- /dev/null
+++ b/docs/i18n/cs/docs/USER_GUIDE.md
@@ -0,0 +1,944 @@
+# User Guide (Čeština)
+
+🌐 **Languages:** 🇺🇸 [English](../../../../docs/USER_GUIDE.md) · 🇪🇸 [es](../../es/docs/USER_GUIDE.md) · 🇫🇷 [fr](../../fr/docs/USER_GUIDE.md) · 🇩🇪 [de](../../de/docs/USER_GUIDE.md) · 🇮🇹 [it](../../it/docs/USER_GUIDE.md) · 🇷🇺 [ru](../../ru/docs/USER_GUIDE.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/USER_GUIDE.md) · 🇯🇵 [ja](../../ja/docs/USER_GUIDE.md) · 🇰🇷 [ko](../../ko/docs/USER_GUIDE.md) · 🇸🇦 [ar](../../ar/docs/USER_GUIDE.md) · 🇮🇳 [in](../../in/docs/USER_GUIDE.md) · 🇹🇭 [th](../../th/docs/USER_GUIDE.md) · 🇻🇳 [vi](../../vi/docs/USER_GUIDE.md) · 🇮🇩 [id](../../id/docs/USER_GUIDE.md) · 🇲🇾 [ms](../../ms/docs/USER_GUIDE.md) · 🇳🇱 [nl](../../nl/docs/USER_GUIDE.md) · 🇵🇱 [pl](../../pl/docs/USER_GUIDE.md) · 🇸🇪 [sv](../../sv/docs/USER_GUIDE.md) · 🇳🇴 [no](../../no/docs/USER_GUIDE.md) · 🇩🇰 [da](../../da/docs/USER_GUIDE.md) · 🇫🇮 [fi](../../fi/docs/USER_GUIDE.md) · 🇵🇹 [pt](../../pt/docs/USER_GUIDE.md) · 🇷🇴 [ro](../../ro/docs/USER_GUIDE.md) · 🇭🇺 [hu](../../hu/docs/USER_GUIDE.md) · 🇧🇬 [bg](../../bg/docs/USER_GUIDE.md) · 🇸🇰 [sk](../../sk/docs/USER_GUIDE.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/USER_GUIDE.md) · 🇮🇱 [he](../../he/docs/USER_GUIDE.md) · 🇵🇭 [phi](../../phi/docs/USER_GUIDE.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/USER_GUIDE.md) · 🇨🇿 [cs](../../cs/docs/USER_GUIDE.md)
+
+---
+
+Complete guide for configuring providers, creating combos, integrating CLI tools, and deploying OmniRoute.
+
+---
+
+## Table of Contents
+
+- [Pricing at a Glance](#-pricing-at-a-glance)
+- [Use Cases](#-use-cases)
+- [Provider Setup](#-provider-setup)
+- [CLI Integration](#-cli-integration)
+- [Deployment](#-deployment)
+- [Available Models](#-available-models)
+- [Advanced Features](#-advanced-features)
+
+---
+
+## 💰 Pricing at a Glance
+
+| Tier | Provider | Cost | Quota Reset | Best For |
+| ------------------- | ----------------- | ----------- | ---------------- | -------------------- |
+| **💳 SUBSCRIPTION** | Claude Code (Pro) | $20/mo | 5h + weekly | Already subscribed |
+| | Codex (Plus/Pro) | $20-200/mo | 5h + weekly | OpenAI users |
+| | Gemini CLI | **FREE** | 180K/mo + 1K/day | Everyone! |
+| | GitHub Copilot | $10-19/mo | Monthly | GitHub users |
+| **🔑 API KEY** | DeepSeek | Pay per use | None | Cheap reasoning |
+| | Groq | Pay per use | None | Ultra-fast inference |
+| | xAI (Grok) | Pay per use | None | Grok 4 reasoning |
+| | Mistral | Pay per use | None | EU-hosted models |
+| | Perplexity | Pay per use | None | Search-augmented |
+| | Together AI | Pay per use | None | Open-source models |
+| | Fireworks AI | Pay per use | None | Fast FLUX images |
+| | Cerebras | Pay per use | None | Wafer-scale speed |
+| | Cohere | Pay per use | None | Command R+ RAG |
+| | NVIDIA NIM | Pay per use | None | Enterprise models |
+| **💰 CHEAP** | GLM-4.7 | $0.6/1M | Daily 10AM | Budget backup |
+| | MiniMax M2.1 | $0.2/1M | 5-hour rolling | Cheapest option |
+| | Kimi K2 | $9/mo flat | 10M tokens/mo | Predictable cost |
+| **🆓 FREE** | Qoder | $0 | Unlimited | 8 models free |
+| | Qwen | $0 | Unlimited | 3 models free |
+| | Kiro | $0 | Unlimited | Claude free |
+
+**💡 Pro Tip:** Start with Gemini CLI (180K free/month) + Qoder (unlimited free) combo = $0 cost!
+
+---
+
+## 🎯 Use Cases
+
+### Case 1: "I have Claude Pro subscription"
+
+**Problem:** Quota expires unused, rate limits during heavy coding
+
+```
+Combo: "maximize-claude"
+ 1. cc/claude-opus-4-6 (use subscription fully)
+ 2. glm/glm-4.7 (cheap backup when quota out)
+ 3. if/kimi-k2-thinking (free emergency fallback)
+
+Monthly cost: $20 (subscription) + ~$5 (backup) = $25 total
+vs. $20 + hitting limits = frustration
+```
+
+### Case 2: "I want zero cost"
+
+**Problem:** Can't afford subscriptions, need reliable AI coding
+
+```
+Combo: "free-forever"
+ 1. gc/gemini-3-flash (180K free/month)
+ 2. if/kimi-k2-thinking (unlimited free)
+ 3. qw/qwen3-coder-plus (unlimited free)
+
+Monthly cost: $0
+Quality: Production-ready models
+```
+
+### Case 3: "I need 24/7 coding, no interruptions"
+
+**Problem:** Deadlines, can't afford downtime
+
+```
+Combo: "always-on"
+ 1. cc/claude-opus-4-6 (best quality)
+ 2. cx/gpt-5.2-codex (second subscription)
+ 3. glm/glm-4.7 (cheap, resets daily)
+ 4. minimax/MiniMax-M2.1 (cheapest, 5h reset)
+ 5. if/kimi-k2-thinking (free unlimited)
+
+Result: 5 layers of fallback = zero downtime
+Monthly cost: $20-200 (subscriptions) + $10-20 (backup)
+```
+
+### Case 4: "I want FREE AI in OpenClaw"
+
+**Problem:** Need AI assistant in messaging apps, completely free
+
+```
+Combo: "openclaw-free"
+ 1. if/glm-4.7 (unlimited free)
+ 2. if/minimax-m2.1 (unlimited free)
+ 3. if/kimi-k2-thinking (unlimited free)
+
+Monthly cost: $0
+Access via: WhatsApp, Telegram, Slack, Discord, iMessage, Signal...
+```
+
+---
+
+## 📖 Provider Setup
+
+### 🔐 Subscription Providers
+
+#### Claude Code (Pro/Max)
+
+```bash
+Dashboard → Providers → Connect Claude Code
+→ OAuth login → Auto token refresh
+→ 5-hour + weekly quota tracking
+
+Models:
+ cc/claude-opus-4-6
+ cc/claude-sonnet-4-5-20250929
+ cc/claude-haiku-4-5-20251001
+```
+
+**Pro Tip:** Use Opus for complex tasks, Sonnet for speed. OmniRoute tracks quota per model!
+
+#### OpenAI Codex (Plus/Pro)
+
+```bash
+Dashboard → Providers → Connect Codex
+→ OAuth login (port 1455)
+→ 5-hour + weekly reset
+
+Models:
+ cx/gpt-5.2-codex
+ cx/gpt-5.1-codex-max
+```
+
+#### Gemini CLI (FREE 180K/month!)
+
+```bash
+Dashboard → Providers → Connect Gemini CLI
+→ Google OAuth
+→ 180K completions/month + 1K/day
+
+Models:
+ gc/gemini-3-flash-preview
+ gc/gemini-2.5-pro
+```
+
+**Best Value:** Huge free tier! Use this before paid tiers.
+
+#### GitHub Copilot
+
+```bash
+Dashboard → Providers → Connect GitHub
+→ OAuth via GitHub
+→ Monthly reset (1st of month)
+
+Models:
+ gh/gpt-5
+ gh/claude-4.5-sonnet
+ gh/gemini-3-pro
+```
+
+### 💰 Cheap Providers
+
+#### GLM-4.7 (Daily reset, $0.6/1M)
+
+1. Sign up: [Zhipu AI](https://open.bigmodel.cn/)
+2. Get API key from Coding Plan
+3. Dashboard → Add API Key: Provider: `glm`, API Key: `your-key`
+
+**Use:** `glm/glm-4.7` — **Pro Tip:** Coding Plan offers 3× quota at 1/7 cost! Reset daily 10:00 AM.
+
+#### MiniMax M2.1 (5h reset, $0.20/1M)
+
+1. Sign up: [MiniMax](https://www.minimax.io/)
+2. Get API key → Dashboard → Add API Key
+
+**Use:** `minimax/MiniMax-M2.1` — **Pro Tip:** Cheapest option for long context (1M tokens)!
+
+#### Kimi K2 ($9/month flat)
+
+1. Subscribe: [Moonshot AI](https://platform.moonshot.ai/)
+2. Get API key → Dashboard → Add API Key
+
+**Use:** `kimi/kimi-latest` — **Pro Tip:** Fixed $9/month for 10M tokens = $0.90/1M effective cost!
+
+### 🆓 FREE Providers
+
+#### Qoder (8 FREE models)
+
+```bash
+Dashboard → Connect Qoder → OAuth login → Unlimited usage
+
+Models: if/kimi-k2-thinking, if/qwen3-coder-plus, if/glm-4.7, if/minimax-m2, if/deepseek-r1
+```
+
+#### Qwen (3 FREE models)
+
+```bash
+Dashboard → Connect Qwen → Device code auth → Unlimited usage
+
+Models: qw/qwen3-coder-plus, qw/qwen3-coder-flash
+```
+
+#### Kiro (Claude FREE)
+
+```bash
+Dashboard → Connect Kiro → AWS Builder ID or Google/GitHub → Unlimited
+
+Models: kr/claude-sonnet-4.5, kr/claude-haiku-4.5
+```
+
+---
+
+## 🎨 Combos
+
+### Example 1: Maximize Subscription → Cheap Backup
+
+```
+Dashboard → Combos → Create New
+
+Name: premium-coding
+Models:
+ 1. cc/claude-opus-4-6 (Subscription primary)
+ 2. glm/glm-4.7 (Cheap backup, $0.6/1M)
+ 3. minimax/MiniMax-M2.1 (Cheapest fallback, $0.20/1M)
+
+Use in CLI: premium-coding
+```
+
+### Example 2: Free-Only (Zero Cost)
+
+```
+Name: free-combo
+Models:
+ 1. gc/gemini-3-flash-preview (180K free/month)
+ 2. if/kimi-k2-thinking (unlimited)
+ 3. qw/qwen3-coder-plus (unlimited)
+
+Cost: $0 forever!
+```
+
+---
+
+## 🔧 CLI Integration
+
+### Cursor IDE
+
+```
+Settings → Models → Advanced:
+ OpenAI API Base URL: http://localhost:20128/v1
+ OpenAI API Key: [from omniroute dashboard]
+ Model: cc/claude-opus-4-6
+```
+
+### Claude Code
+
+Edit `~/.claude/config.json`:
+
+```json
+{
+ "anthropic_api_base": "http://localhost:20128/v1",
+ "anthropic_api_key": "your-omniroute-api-key"
+}
+```
+
+### Codex CLI
+
+```bash
+export OPENAI_BASE_URL="http://localhost:20128"
+export OPENAI_API_KEY="your-omniroute-api-key"
+codex "your prompt"
+```
+
+### OpenClaw
+
+Edit `~/.openclaw/openclaw.json`:
+
+```json
+{
+ "agents": {
+ "defaults": {
+ "model": { "primary": "omniroute/if/glm-4.7" }
+ }
+ },
+ "models": {
+ "providers": {
+ "omniroute": {
+ "baseUrl": "http://localhost:20128/v1",
+ "apiKey": "your-omniroute-api-key",
+ "api": "openai-completions",
+ "models": [{ "id": "if/glm-4.7", "name": "glm-4.7" }]
+ }
+ }
+ }
+}
+```
+
+**Or use Dashboard:** CLI Tools → OpenClaw → Auto-config
+
+### Cline / Continue / RooCode
+
+```
+Provider: OpenAI Compatible
+Base URL: http://localhost:20128/v1
+API Key: [from dashboard]
+Model: cc/claude-opus-4-6
+```
+
+---
+
+## Nasazení
+
+### Global npm install (Recommended)
+
+```bash
+npm install -g omniroute
+
+# Create config directory
+mkdir -p ~/.omniroute
+
+# Create .env file (see .env.example)
+cp .env.example ~/.omniroute/.env
+
+# Start server
+omniroute
+# Or with custom port:
+omniroute --port 3000
+```
+
+The CLI automatically loads `.env` from `~/.omniroute/.env` or `./.env`.
+
+### VPS Deployment
+
+```bash
+git clone https://github.com/diegosouzapw/OmniRoute.git
+cd OmniRoute && npm install && npm run build
+
+export JWT_SECRET="your-secure-secret-change-this"
+export INITIAL_PASSWORD="your-password"
+export DATA_DIR="/var/lib/omniroute"
+export PORT="20128"
+export HOSTNAME="0.0.0.0"
+export NODE_ENV="production"
+export NEXT_PUBLIC_BASE_URL="http://localhost:20128"
+export API_KEY_SECRET="endpoint-proxy-api-key-secret"
+
+npm run start
+# Or: pm2 start npm --name omniroute -- start
+```
+
+### PM2 Deployment (Low Memory)
+
+For servers with limited RAM, use the memory limit option:
+
+```bash
+# With 512MB limit (default)
+pm2 start npm --name omniroute -- start
+
+# Or with custom memory limit
+OMNIROUTE_MEMORY_MB=512 pm2 start npm --name omniroute -- start
+
+# Or using ecosystem.config.js
+pm2 start ecosystem.config.js
+```
+
+Create `ecosystem.config.js`:
+
+```javascript
+module.exports = {
+ apps: [
+ {
+ name: "omniroute",
+ script: "npm",
+ args: "start",
+ env: {
+ NODE_ENV: "production",
+ OMNIROUTE_MEMORY_MB: "512",
+ JWT_SECRET: "your-secret",
+ INITIAL_PASSWORD: "your-password",
+ },
+ node_args: "--max-old-space-size=512",
+ max_memory_restart: "300M",
+ },
+ ],
+};
+```
+
+### Docker
+
+```bash
+# Build image (default = runner-cli with codex/claude/droid preinstalled)
+docker build -t omniroute:cli .
+
+# Portable mode (recommended)
+docker run -d --name omniroute -p 20128:20128 --env-file ./.env -v omniroute-data:/app/data omniroute:cli
+```
+
+For host-integrated mode with CLI binaries, see the Docker section in the main docs.
+
+### Void Linux (xbps-src)
+
+Void Linux users can package and install OmniRoute natively using the `xbps-src` cross-compilation framework. This automates the Node.js standalone build along with the required `better-sqlite3` native bindings.
+
+
+View xbps-src template
+
+```bash
+# Template file for 'omniroute'
+pkgname=omniroute
+version=3.2.4
+revision=1
+hostmakedepends="nodejs python3 make"
+depends="openssl"
+short_desc="Universal AI gateway with smart routing for multiple LLM providers"
+maintainer="zenobit "
+license="MIT"
+homepage="https://github.com/diegosouzapw/OmniRoute"
+distfiles="https://github.com/diegosouzapw/OmniRoute/archive/refs/tags/v${version}.tar.gz"
+checksum=009400afee90a9f32599d8fe734145cfd84098140b7287990183dde45ae2245b
+system_accounts="_omniroute"
+omniroute_homedir="/var/lib/omniroute"
+export NODE_ENV=production
+export npm_config_engine_strict=false
+export npm_config_loglevel=error
+export npm_config_fund=false
+export npm_config_audit=false
+
+do_build() {
+ # Determine target CPU arch for node-gyp
+ local _gyp_arch
+ case "$XBPS_TARGET_MACHINE" in
+ aarch64*) _gyp_arch=arm64 ;;
+ armv7*|armv6*) _gyp_arch=arm ;;
+ i686*) _gyp_arch=ia32 ;;
+ *) _gyp_arch=x64 ;;
+ esac
+
+ # 1) Install all deps – skip scripts
+ NODE_ENV=development npm ci --ignore-scripts
+
+ # 2) Build the Next.js standalone bundle
+ npm run build
+
+ # 3) Copy static assets into standalone
+ cp -r .next/static .next/standalone/.next/static
+ [ -d public ] && cp -r public .next/standalone/public || true
+
+ # 4) Compile better-sqlite3 native binding
+ local _node_gyp=/usr/lib/node_modules/npm/node_modules/node-gyp/bin/node-gyp.js
+ (cd node_modules/better-sqlite3 && node "$_node_gyp" rebuild --arch="$_gyp_arch")
+
+ # 5) Place the compiled binding into the standalone bundle
+ local _bs3_release=.next/standalone/node_modules/better-sqlite3/build/Release
+ mkdir -p "$_bs3_release"
+ cp node_modules/better-sqlite3/build/Release/better_sqlite3.node "$_bs3_release/"
+
+ # 6) Remove arch-specific sharp bundles
+ rm -rf .next/standalone/node_modules/@img
+
+ # 7) Copy pino runtime deps omitted by Next.js static analysis:
+ for _mod in pino-abstract-transport split2 process-warning; do
+ cp -r "node_modules/$_mod" .next/standalone/node_modules/
+ done
+}
+
+do_check() {
+ npm run test:unit
+}
+
+do_install() {
+ vmkdir usr/lib/omniroute/.next
+ vcopy .next/standalone/. usr/lib/omniroute/.next/standalone
+
+ # Prevent removal of empty Next.js app router dirs by the post-install hook
+ for _d in \
+ .next/standalone/.next/server/app/dashboard \
+ .next/standalone/.next/server/app/dashboard/settings \
+ .next/standalone/.next/server/app/dashboard/providers; do
+ touch "${DESTDIR}/usr/lib/omniroute/${_d}/.keep"
+ done
+
+ cat > "${WRKDIR}/omniroute" <<'EOF'
+#!/bin/sh
+export PORT="${PORT:-20128}"
+export DATA_DIR="${DATA_DIR:-${XDG_DATA_HOME:-${HOME}/.local/share}/omniroute}"
+export LOG_TO_FILE="${LOG_TO_FILE:-false}"
+mkdir -p "${DATA_DIR}"
+exec node /usr/lib/omniroute/.next/standalone/server.js "$@"
+EOF
+ vbin "${WRKDIR}/omniroute"
+}
+
+post_install() {
+ vlicense LICENSE
+}
+```
+
+
+
+### Environment Variables
+
+| Variable | Default | Description |
+| ---------------------------- | ------------------------------------ | ------------------------------------------------------------------------------------------ |
+| `JWT_SECRET` | `omniroute-default-secret-change-me` | JWT signing secret (**change in production**) |
+| `INITIAL_PASSWORD` | `123456` | First login password |
+| `DATA_DIR` | `~/.omniroute` | Data directory (db, usage, logs) |
+| `PORT` | framework default | Service port (`20128` in examples) |
+| `HOSTNAME` | framework default | Bind host (Docker defaults to `0.0.0.0`) |
+| `NODE_ENV` | runtime default | Set `production` for deploy |
+| `BASE_URL` | `http://localhost:20128` | Server-side internal base URL |
+| `CLOUD_URL` | `https://omniroute.dev` | Cloud sync endpoint base URL |
+| `API_KEY_SECRET` | `endpoint-proxy-api-key-secret` | HMAC secret for generated API keys |
+| `REQUIRE_API_KEY` | `false` | Enforce Bearer API key on `/v1/*` |
+| `ALLOW_API_KEY_REVEAL` | `false` | Allow Api Manager to copy full API keys on demand |
+| `DISABLE_SQLITE_AUTO_BACKUP` | `false` | Disable automatic SQLite snapshots before writes/import/restore; manual backups still work |
+| `ENABLE_REQUEST_LOGS` | `false` | Enables request/response logs |
+| `AUTH_COOKIE_SECURE` | `false` | Force `Secure` auth cookie (behind HTTPS reverse proxy) |
+| `CLOUDFLARED_BIN` | unset | Use an existing `cloudflared` binary instead of managed download |
+| `OMNIROUTE_MEMORY_MB` | `512` | Node.js heap limit in MB |
+| `PROMPT_CACHE_MAX_SIZE` | `50` | Max prompt cache entries |
+| `SEMANTIC_CACHE_MAX_SIZE` | `100` | Max semantic cache entries |
+
+For the full environment variable reference, see the [README](../README.md).
+
+---
+
+## 📊 Available Models
+
+
+View all available models
+
+**Claude Code (`cc/`)** — Pro/Max: `cc/claude-opus-4-6`, `cc/claude-sonnet-4-5-20250929`, `cc/claude-haiku-4-5-20251001`
+
+**Codex (`cx/`)** — Plus/Pro: `cx/gpt-5.2-codex`, `cx/gpt-5.1-codex-max`
+
+**Gemini CLI (`gc/`)** — FREE: `gc/gemini-3-flash-preview`, `gc/gemini-2.5-pro`
+
+**GitHub Copilot (`gh/`)**: `gh/gpt-5`, `gh/claude-4.5-sonnet`
+
+**GLM (`glm/`)** — $0.6/1M: `glm/glm-4.7`
+
+**MiniMax (`minimax/`)** — $0.2/1M: `minimax/MiniMax-M2.1`
+
+**Qoder (`if/`)** — FREE: `if/kimi-k2-thinking`, `if/qwen3-coder-plus`, `if/deepseek-r1`
+
+**Qwen (`qw/`)** — FREE: `qw/qwen3-coder-plus`, `qw/qwen3-coder-flash`
+
+**Kiro (`kr/`)** — FREE: `kr/claude-sonnet-4.5`, `kr/claude-haiku-4.5`
+
+**DeepSeek (`ds/`)**: `ds/deepseek-chat`, `ds/deepseek-reasoner`
+
+**Groq (`groq/`)**: `groq/llama-3.3-70b-versatile`, `groq/llama-4-maverick-17b-128e-instruct`
+
+**xAI (`xai/`)**: `xai/grok-4`, `xai/grok-4-0709-fast-reasoning`, `xai/grok-code-mini`
+
+**Mistral (`mistral/`)**: `mistral/mistral-large-2501`, `mistral/codestral-2501`
+
+**Perplexity (`pplx/`)**: `pplx/sonar-pro`, `pplx/sonar`
+
+**Together AI (`together/`)**: `together/meta-llama/Llama-3.3-70B-Instruct-Turbo`
+
+**Fireworks AI (`fireworks/`)**: `fireworks/accounts/fireworks/models/deepseek-v3p1`
+
+**Cerebras (`cerebras/`)**: `cerebras/llama-3.3-70b`
+
+**Cohere (`cohere/`)**: `cohere/command-r-plus-08-2024`
+
+**NVIDIA NIM (`nvidia/`)**: `nvidia/nvidia/llama-3.3-70b-instruct`
+
+
+
+---
+
+## 🧩 Advanced Features
+
+### Custom Models
+
+Add any model ID to any provider without waiting for an app update:
+
+```bash
+# Via API
+curl -X POST http://localhost:20128/api/provider-models \
+ -H "Content-Type: application/json" \
+ -d '{"provider": "openai", "modelId": "gpt-4.5-preview", "modelName": "GPT-4.5 Preview"}'
+
+# List: curl http://localhost:20128/api/provider-models?provider=openai
+# Remove: curl -X DELETE "http://localhost:20128/api/provider-models?provider=openai&model=gpt-4.5-preview"
+```
+
+Or use Dashboard: **Providers → [Provider] → Custom Models**.
+
+Notes:
+
+- OpenRouter and OpenAI/Anthropic-compatible providers are managed from **Available Models** only. Manual add, import, and auto-sync all land in the same available-model list, so there is no separate Custom Models section for those providers.
+- The **Custom Models** section is intended for providers that do not expose managed available-model imports.
+
+### Dedicated Provider Routes
+
+Route requests directly to a specific provider with model validation:
+
+```bash
+POST http://localhost:20128/v1/providers/openai/chat/completions
+POST http://localhost:20128/v1/providers/openai/embeddings
+POST http://localhost:20128/v1/providers/fireworks/images/generations
+```
+
+The provider prefix is auto-added if missing. Mismatched models return `400`.
+
+### Network Proxy Configuration
+
+```bash
+# Set global proxy
+curl -X PUT http://localhost:20128/api/settings/proxy \
+ -d '{"global": {"type":"http","host":"proxy.example.com","port":"8080"}}'
+
+# Per-provider proxy
+curl -X PUT http://localhost:20128/api/settings/proxy \
+ -d '{"providers": {"openai": {"type":"socks5","host":"proxy.example.com","port":"1080"}}}'
+
+# Test proxy
+curl -X POST http://localhost:20128/api/settings/proxy/test \
+ -d '{"proxy":{"type":"socks5","host":"proxy.example.com","port":"1080"}}'
+```
+
+**Precedence:** Key-specific → Combo-specific → Provider-specific → Global → Environment.
+
+### Model Catalog API
+
+```bash
+curl http://localhost:20128/api/models/catalog
+```
+
+Returns models grouped by provider with types (`chat`, `embedding`, `image`).
+
+### Cloud Sync
+
+- Sync providers, combos, and settings across devices
+- Automatic background sync with timeout + fail-fast
+- Prefer server-side `BASE_URL`/`CLOUD_URL` in production
+
+### Cloudflare Quick Tunnel
+
+- Available in **Dashboard → Endpoints** for Docker and other self-hosted deployments
+- Creates a temporary `https://*.trycloudflare.com` URL that forwards to your current OpenAI-compatible `/v1` endpoint
+- First enable installs `cloudflared` only when needed; later restarts reuse the same managed binary
+- Tunnel URLs are ephemeral and change every time you stop/start the tunnel
+- Set `CLOUDFLARED_BIN` if you prefer using a preinstalled `cloudflared` binary instead of the managed download
+
+### LLM Gateway Intelligence (Phase 9)
+
+- **Semantic Cache** — Auto-caches non-streaming, temperature=0 responses (bypass with `X-OmniRoute-No-Cache: true`)
+- **Request Idempotency** — Deduplicates requests within 5s via `Idempotency-Key` or `X-Request-Id` header
+- **Progress Tracking** — Opt-in SSE `event: progress` events via `X-OmniRoute-Progress: true` header
+
+---
+
+### Translator Playground
+
+Access via **Dashboard → Translator**. Debug and visualize how OmniRoute translates API requests between providers.
+
+| Mode | Purpose |
+| ---------------- | -------------------------------------------------------------------------------------- |
+| **Playground** | Select source/target formats, paste a request, and see the translated output instantly |
+| **Chat Tester** | Send live chat messages through the proxy and inspect the full request/response cycle |
+| **Test Bench** | Run batch tests across multiple format combinations to verify translation correctness |
+| **Live Monitor** | Watch real-time translations as requests flow through the proxy |
+
+**Use cases:**
+
+- Debug why a specific client/provider combination fails
+- Verify that thinking tags, tool calls, and system prompts translate correctly
+- Compare format differences between OpenAI, Claude, Gemini, and Responses API formats
+
+---
+
+### Routing Strategies
+
+Configure via **Dashboard → Settings → Routing**.
+
+| Strategy | Description |
+| ------------------------------ | ------------------------------------------------------------------------------------------------ |
+| **Fill First** | Uses accounts in priority order — primary account handles all requests until unavailable |
+| **Round Robin** | Cycles through all accounts with a configurable sticky limit (default: 3 calls per account) |
+| **P2C (Power of Two Choices)** | Picks 2 random accounts and routes to the healthier one — balances load with awareness of health |
+| **Random** | Randomly selects an account for each request using Fisher-Yates shuffle |
+| **Least Used** | Routes to the account with the oldest `lastUsedAt` timestamp, distributing traffic evenly |
+| **Cost Optimized** | Routes to the account with the lowest priority value, optimizing for lowest-cost providers |
+
+#### External Sticky Session Header
+
+For external session affinity (for example, Claude Code/Codex agents behind reverse proxies), send:
+
+```http
+X-Session-Id: your-session-key
+```
+
+OmniRoute also accepts `x_session_id` and returns the effective session key in `X-OmniRoute-Session-Id`.
+
+If you use Nginx and send underscore-form headers, enable:
+
+```nginx
+underscores_in_headers on;
+```
+
+#### Wildcard Model Aliases
+
+Create wildcard patterns to remap model names:
+
+```
+Pattern: claude-sonnet-* → Target: cc/claude-sonnet-4-5-20250929
+Pattern: gpt-* → Target: gh/gpt-5.1-codex
+```
+
+Wildcards support `*` (any characters) and `?` (single character).
+
+#### Fallback Chains
+
+Define global fallback chains that apply across all requests:
+
+```
+Chain: production-fallback
+ 1. cc/claude-opus-4-6
+ 2. gh/gpt-5.1-codex
+ 3. glm/glm-4.7
+```
+
+---
+
+### Resilience & Circuit Breakers
+
+Configure via **Dashboard → Settings → Resilience**.
+
+OmniRoute implements provider-level resilience with four components:
+
+1. **Provider Profiles** — Per-provider configuration for:
+ - Failure threshold (how many failures before opening)
+ - Cooldown duration
+ - Rate limit detection sensitivity
+ - Exponential backoff parameters
+
+2. **Editable Rate Limits** — System-level defaults configurable in the dashboard:
+ - **Requests Per Minute (RPM)** — Maximum requests per minute per account
+ - **Min Time Between Requests** — Minimum gap in milliseconds between requests
+ - **Max Concurrent Requests** — Maximum simultaneous requests per account
+ - Click **Edit** to modify, then **Save** or **Cancel**. Values persist via the resilience API.
+
+3. **Circuit Breaker** — Tracks failures per provider and automatically opens the circuit when a threshold is reached:
+ - **CLOSED** (Healthy) — Requests flow normally
+ - **OPEN** — Provider is temporarily blocked after repeated failures
+ - **HALF_OPEN** — Testing if provider has recovered
+
+4. **Policies & Locked Identifiers** — Shows circuit breaker status and locked identifiers with force-unlock capability.
+
+5. **Rate Limit Auto-Detection** — Monitors `429` and `Retry-After` headers to proactively avoid hitting provider rate limits.
+
+**Pro Tip:** Use **Reset All** button to clear all circuit breakers and cooldowns when a provider recovers from an outage.
+
+---
+
+### Database Export / Import
+
+Manage database backups in **Dashboard → Settings → System & Storage**.
+
+| Action | Description |
+| ------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------- |
+| **Export Database** | Downloads the current SQLite database as a `.sqlite` file |
+| **Export All (.tar.gz)** | Downloads a full backup archive including: database, settings, combos, provider connections (no credentials), API key metadata |
+| **Import Database** | Upload a `.sqlite` file to replace the current database. A pre-import backup is automatically created unless `DISABLE_SQLITE_AUTO_BACKUP=true` |
+
+```bash
+# API: Export database
+curl -o backup.sqlite http://localhost:20128/api/db-backups/export
+
+# API: Export all (full archive)
+curl -o backup.tar.gz http://localhost:20128/api/db-backups/exportAll
+
+# API: Import database
+curl -X POST http://localhost:20128/api/db-backups/import \
+ -F "file=@backup.sqlite"
+```
+
+**Import Validation:** The imported file is validated for integrity (SQLite pragma check), required tables (`provider_connections`, `provider_nodes`, `combos`, `api_keys`), and size (max 100MB).
+
+**Use Cases:**
+
+- Migrate OmniRoute between machines
+- Create external backups for disaster recovery
+- Share configurations between team members (export all → share archive)
+
+---
+
+### Settings Dashboard
+
+The settings page is organized into 6 tabs for easy navigation:
+
+| Tab | Contents |
+| -------------- | ---------------------------------------------------------------------------------------------- |
+| **General** | System storage tools, appearance settings, theme controls, and per-item sidebar visibility |
+| **Security** | Login/Password settings, IP Access Control, API auth for `/models`, and Provider Blocking |
+| **Routing** | Global routing strategy (6 options), wildcard model aliases, fallback chains, combo defaults |
+| **Resilience** | Provider profiles, editable rate limits, circuit breaker status, policies & locked identifiers |
+| **AI** | Thinking budget configuration, global system prompt injection, prompt cache stats |
+| **Advanced** | Global proxy configuration (HTTP/SOCKS5) |
+
+---
+
+### Costs & Budget Management
+
+Access via **Dashboard → Costs**.
+
+| Tab | Purpose |
+| ----------- | ---------------------------------------------------------------------------------------- |
+| **Budget** | Set spending limits per API key with daily/weekly/monthly budgets and real-time tracking |
+| **Pricing** | View and edit model pricing entries — cost per 1K input/output tokens per provider |
+
+```bash
+# API: Set a budget
+curl -X POST http://localhost:20128/api/usage/budget \
+ -H "Content-Type: application/json" \
+ -d '{"keyId": "key-123", "limit": 50.00, "period": "monthly"}'
+
+# API: Get current budget status
+curl http://localhost:20128/api/usage/budget
+```
+
+**Cost Tracking:** Every request logs token usage and calculates cost using the pricing table. View breakdowns in **Dashboard → Usage** by provider, model, and API key.
+
+---
+
+### Audio Transcription
+
+OmniRoute supports audio transcription via the OpenAI-compatible endpoint:
+
+```bash
+POST /v1/audio/transcriptions
+Authorization: Bearer your-api-key
+Content-Type: multipart/form-data
+
+# Example with curl
+curl -X POST http://localhost:20128/v1/audio/transcriptions \
+ -H "Authorization: Bearer your-api-key" \
+ -F "file=@audio.mp3" \
+ -F "model=deepgram/nova-3"
+```
+
+Available providers: **Deepgram** (`deepgram/`), **AssemblyAI** (`assemblyai/`).
+
+Supported audio formats: `mp3`, `wav`, `m4a`, `flac`, `ogg`, `webm`.
+
+---
+
+### Combo Balancing Strategies
+
+Configure per-combo balancing in **Dashboard → Combos → Create/Edit → Strategy**.
+
+| Strategy | Description |
+| ------------------ | ------------------------------------------------------------------------ |
+| **Round-Robin** | Rotates through models sequentially |
+| **Priority** | Always tries the first model; falls back only on error |
+| **Random** | Picks a random model from the combo for each request |
+| **Weighted** | Routes proportionally based on assigned weights per model |
+| **Least-Used** | Routes to the model with the fewest recent requests (uses combo metrics) |
+| **Cost-Optimized** | Routes to the cheapest available model (uses pricing table) |
+
+Global combo defaults can be set in **Dashboard → Settings → Routing → Combo Defaults**.
+
+---
+
+### Health Dashboard
+
+Access via **Dashboard → Health**. Real-time system health overview with 6 cards:
+
+| Card | What It Shows |
+| --------------------- | ----------------------------------------------------------- |
+| **System Status** | Uptime, version, memory usage, data directory |
+| **Provider Health** | Per-provider circuit breaker state (Closed/Open/Half-Open) |
+| **Rate Limits** | Active rate limit cooldowns per account with remaining time |
+| **Active Lockouts** | Providers temporarily blocked by the lockout policy |
+| **Signature Cache** | Deduplication cache stats (active keys, hit rate) |
+| **Latency Telemetry** | p50/p95/p99 latency aggregation per provider |
+
+**Pro Tip:** The Health page auto-refreshes every 10 seconds. Use the circuit breaker card to identify which providers are experiencing issues.
+
+---
+
+## 🖥️ Desktop Application (Electron)
+
+OmniRoute is available as a native desktop application for Windows, macOS, and Linux.
+
+### Instalace
+
+```bash
+# From the electron directory:
+cd electron
+npm install
+
+# Development mode (connect to running Next.js dev server):
+npm run dev
+
+# Production mode (uses standalone build):
+npm start
+```
+
+### Building Installers
+
+```bash
+cd electron
+npm run build # Current platform
+npm run build:win # Windows (.exe NSIS)
+npm run build:mac # macOS (.dmg universal)
+npm run build:linux # Linux (.AppImage)
+```
+
+Output → `electron/dist-electron/`
+
+### Key Features
+
+| Feature | Description |
+| --------------------------- | ---------------------------------------------------- |
+| **Server Readiness** | Polls server before showing window (no blank screen) |
+| **System Tray** | Minimize to tray, change port, quit from tray menu |
+| **Port Management** | Change server port from tray (auto-restarts server) |
+| **Content Security Policy** | Restrictive CSP via session headers |
+| **Single Instance** | Only one app instance can run at a time |
+| **Offline Mode** | Bundled Next.js server works without internet |
+
+### Environment Variables
+
+| Variable | Default | Description |
+| --------------------- | ------- | -------------------------------- |
+| `OMNIROUTE_PORT` | `20128` | Server port |
+| `OMNIROUTE_MEMORY_MB` | `512` | Node.js heap limit (64–16384 MB) |
+
+📖 Full documentation: [`electron/README.md`](../electron/README.md)
diff --git a/docs/i18n/cs/docs/VM_DEPLOYMENT_GUIDE.md b/docs/i18n/cs/docs/VM_DEPLOYMENT_GUIDE.md
new file mode 100644
index 0000000000..ee8241396a
--- /dev/null
+++ b/docs/i18n/cs/docs/VM_DEPLOYMENT_GUIDE.md
@@ -0,0 +1,403 @@
+# OmniRoute — Deployment Guide on VM with Cloudflare (Čeština)
+
+🌐 **Languages:** 🇺🇸 [English](../../../../docs/VM_DEPLOYMENT_GUIDE.md) · 🇪🇸 [es](../../es/docs/VM_DEPLOYMENT_GUIDE.md) · 🇫🇷 [fr](../../fr/docs/VM_DEPLOYMENT_GUIDE.md) · 🇩🇪 [de](../../de/docs/VM_DEPLOYMENT_GUIDE.md) · 🇮🇹 [it](../../it/docs/VM_DEPLOYMENT_GUIDE.md) · 🇷🇺 [ru](../../ru/docs/VM_DEPLOYMENT_GUIDE.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/VM_DEPLOYMENT_GUIDE.md) · 🇯🇵 [ja](../../ja/docs/VM_DEPLOYMENT_GUIDE.md) · 🇰🇷 [ko](../../ko/docs/VM_DEPLOYMENT_GUIDE.md) · 🇸🇦 [ar](../../ar/docs/VM_DEPLOYMENT_GUIDE.md) · 🇮🇳 [in](../../in/docs/VM_DEPLOYMENT_GUIDE.md) · 🇹🇭 [th](../../th/docs/VM_DEPLOYMENT_GUIDE.md) · 🇻🇳 [vi](../../vi/docs/VM_DEPLOYMENT_GUIDE.md) · 🇮🇩 [id](../../id/docs/VM_DEPLOYMENT_GUIDE.md) · 🇲🇾 [ms](../../ms/docs/VM_DEPLOYMENT_GUIDE.md) · 🇳🇱 [nl](../../nl/docs/VM_DEPLOYMENT_GUIDE.md) · 🇵🇱 [pl](../../pl/docs/VM_DEPLOYMENT_GUIDE.md) · 🇸🇪 [sv](../../sv/docs/VM_DEPLOYMENT_GUIDE.md) · 🇳🇴 [no](../../no/docs/VM_DEPLOYMENT_GUIDE.md) · 🇩🇰 [da](../../da/docs/VM_DEPLOYMENT_GUIDE.md) · 🇫🇮 [fi](../../fi/docs/VM_DEPLOYMENT_GUIDE.md) · 🇵🇹 [pt](../../pt/docs/VM_DEPLOYMENT_GUIDE.md) · 🇷🇴 [ro](../../ro/docs/VM_DEPLOYMENT_GUIDE.md) · 🇭🇺 [hu](../../hu/docs/VM_DEPLOYMENT_GUIDE.md) · 🇧🇬 [bg](../../bg/docs/VM_DEPLOYMENT_GUIDE.md) · 🇸🇰 [sk](../../sk/docs/VM_DEPLOYMENT_GUIDE.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/VM_DEPLOYMENT_GUIDE.md) · 🇮🇱 [he](../../he/docs/VM_DEPLOYMENT_GUIDE.md) · 🇵🇭 [phi](../../phi/docs/VM_DEPLOYMENT_GUIDE.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/VM_DEPLOYMENT_GUIDE.md) · 🇨🇿 [cs](../../cs/docs/VM_DEPLOYMENT_GUIDE.md)
+
+---
+
+Complete guide to install and configure OmniRoute on a VM (VPS) with domain managed via Cloudflare.
+
+---
+
+## Prerequisites
+
+| Item | Minimum | Recommended |
+| ---------- | ------------------------ | ---------------- |
+| **CPU** | 1 vCPU | 2 vCPU |
+| **RAM** | 1 GB | 2 GB |
+| **Disk** | 10 GB SSD | 25 GB SSD |
+| **OS** | Ubuntu 22.04 LTS | Ubuntu 24.04 LTS |
+| **Domain** | Registered on Cloudflare | — |
+| **Docker** | Docker Engine 24+ | Docker 27+ |
+
+**Tested providers**: Akamai (Linode), DigitalOcean, Vultr, Hetzner, AWS Lightsail.
+
+---
+
+## 1. Configure the VM
+
+### 1.1 Create the instance
+
+On your preferred VPS provider:
+
+- Choose Ubuntu 24.04 LTS
+- Select the minimum plan (1 vCPU / 1 GB RAM)
+- Set a strong root password or configure SSH key
+- Note the **public IP** (e.g., `203.0.113.10`)
+
+### 1.2 Connect via SSH
+
+```bash
+ssh root@203.0.113.10
+```
+
+### 1.3 Update the system
+
+```bash
+apt update && apt upgrade -y
+```
+
+### 1.4 Install Docker
+
+```bash
+# Install dependencies
+apt install -y ca-certificates curl gnupg
+
+# Add official Docker repository
+install -m 0755 -d /etc/apt/keyrings
+curl -fsSL https://download.docker.com/linux/ubuntu/gpg | gpg --dearmor -o /etc/apt/keyrings/docker.gpg
+chmod a+r /etc/apt/keyrings/docker.gpg
+echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu $ (. /etc/os-release && echo “$VERSION_CODENAME”) stable" | tee /etc/apt/sources.list.d/docker.list > /dev/null
+apt update
+apt install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin
+```
+
+### 1.5 Install nginx
+
+```bash
+apt install -y nginx
+```
+
+### 1.6 Configure Firewall (UFW)
+
+```bash
+ufw default deny incoming
+ufw default allow outgoing
+ufw allow 22/tcp # SSH
+ufw allow 80/tcp # HTTP (redirect)
+ufw allow 443/tcp # HTTPS
+ufw enable
+```
+
+> **Tip**: For maximum security, restrict ports 80 and 443 to Cloudflare IPs only. See the [Advanced Security](#advanced-security) section.
+
+---
+
+## 2. Install OmniRoute
+
+### 2.1 Create configuration directory
+
+```bash
+mkdir -p /opt/omniroute
+```
+
+### 2.2 Create environment variables file
+
+```bash
+cat > /opt/omniroute/.env << ‘EOF’
+# === Security ===
+JWT_SECRET=CHANGE-TO-A-UNIQUE-64-CHAR-SECRET-KEY
+INITIAL_PASSWORD=YourSecurePassword123!
+API_KEY_SECRET=REPLACE-WITH-ANOTHER-SECRET-KEY
+STORAGE_ENCRYPTION_KEY=REPLACE-WITH-THIRD-SECRET-KEY
+STORAGE_ENCRYPTION_KEY_VERSION=v1
+MACHINE_ID_SALT=CHANGE-TO-A-UNIQUE-SALT
+
+# === App ===
+PORT=20128
+NODE_ENV=production
+HOSTNAME=0.0.0.0
+DATA_DIR=/app/data
+STORAGE_DRIVER=sqlite
+ENABLE_REQUEST_LOGS=true
+AUTH_COOKIE_SECURE=false
+REQUIRE_API_KEY=false
+
+# === Domain (change to your domain) ===
+BASE_URL=https://llms.seudominio.com
+NEXT_PUBLIC_BASE_URL=https://llms.seudominio.com
+
+# === Cloud Sync (optional) ===
+# CLOUD_URL=https://cloud.omniroute.online
+# NEXT_PUBLIC_CLOUD_URL=https://cloud.omniroute.online
+EOF
+```
+
+> ⚠️ **IMPORTANT**: Generate unique secret keys! Use `openssl rand -hex 32` for each key.
+
+### 2.3 Start the container
+
+```bash
+docker pull diegosouzapw/omniroute:latest
+
+docker run -d \
+ --name omniroute \
+ --restart unless-stopped \
+ --env-file /opt/omniroute/.env \
+ -p 20128:20128 \
+ -v omniroute-data:/app/data \
+ diegosouzapw/omniroute:latest
+```
+
+### 2.4 Verify that it is running
+
+```bash
+docker ps | grep omniroute
+docker logs omniroute --tail 20
+```
+
+It should display: `[DB] SQLite database ready` and `listening on port 20128`.
+
+---
+
+## 3. Configure nginx (Reverse Proxy)
+
+### 3.1 Generate SSL certificate (Cloudflare Origin)
+
+In the Cloudflare dashboard:
+
+1. Go to **SSL/TLS → Origin Server**
+2. Click **Create Certificate**
+3. Keep the defaults (15 years, \*.yourdomain.com)
+4. Copy the **Origin Certificate** and the **Private Key**
+
+```bash
+mkdir -p /etc/nginx/ssl
+
+# Paste the certificate
+nano /etc/nginx/ssl/origin.crt
+
+# Paste the private key
+nano /etc/nginx/ssl/origin.key
+
+chmod 600 /etc/nginx/ssl/origin.key
+```
+
+### 3.2 Nginx Configuration
+
+```bash
+cat > /etc/nginx/sites-available/omniroute << ‘NGINX’
+# Default server — blocks direct access via IP
+server {
+ listen 80 default_server;
+ listen [::]:80 default_server;
+ listen 443 ssl default_server;
+ listen [::]:443 ssl default_server;
+ ssl_certificate /etc/nginx/ssl/origin.crt;
+ ssl_certificate_key /etc/nginx/ssl/origin.key;
+ server_name _;
+ return 444;
+}
+
+# OmniRoute — HTTPS
+server {
+ listen 443 ssl;
+ listen [::]:443 ssl;
+ server_name llms.yourdomain.com; # Change to your domain
+
+ ssl_certificate /etc/nginx/ssl/origin.crt;
+ ssl_certificate_key /etc/nginx/ssl/origin.key;
+ ssl_protocols TLSv1.2 TLSv1.3;
+
+ client_max_body_size 100M;
+
+ location / {
+ proxy_pass http://127.0.0.1:20128;
+ proxy_set_header Host $host;
+ proxy_set_header X-Real-IP $remote_addr;
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
+ proxy_set_header X-Forwarded-Proto $scheme;
+
+ # WebSocket support
+ proxy_http_version 1.1;
+ proxy_set_header Upgrade $http_upgrade;
+ proxy_set_header Connection “upgrade”;
+
+ # SSE (Server-Sent Events) — streaming AI responses
+ proxy_buffering off;
+ proxy_cache off;
+ proxy_read_timeout 300s;
+ proxy_send_timeout 300s;
+ }
+}
+
+# HTTP → HTTPS redirect
+server {
+ listen 80;
+ listen [::]:80;
+ server_name llms.yourdomain.com;
+ return 301 https://$server_name$request_uri;
+}
+NGINX
+```
+
+### 3.3 Enable and Test
+
+```bash
+# Remove default configuration
+rm -f /etc/nginx/sites-enabled/default
+
+# Enable OmniRoute
+ln -sf /etc/nginx/sites-available/omniroute /etc/nginx/sites-enabled/omniroute
+
+# Test and reload
+nginx -t && systemctl reload nginx
+```
+
+---
+
+## 4. Configure Cloudflare DNS
+
+### 4.1 Add DNS record
+
+In the Cloudflare dashboard → DNS:
+
+| Type | Name | Content | Proxy |
+| ---- | ------ | ---------------------- | ---------- |
+| A | `llms` | `203.0.113.10` (VM IP) | ✅ Proxied |
+
+### 4.2 Configure SSL
+
+Under **SSL/TLS → Overview**:
+
+- Mode: **Full (Strict)**
+
+Under **SSL/TLS → Edge Certificates**:
+
+- Always Use HTTPS: ✅ On
+- Minimum TLS Version: TLS 1.2
+- Automatic HTTPS Rewrites: ✅ On
+
+### 4.3 Testing
+
+```bash
+curl -sI https://llms.seudominio.com/health
+# Should return HTTP/2 200
+```
+
+---
+
+## 5. Operations and Maintenance
+
+### Upgrade to a new version
+
+```bash
+docker pull diegosouzapw/omniroute:latest
+docker stop omniroute && docker rm omniroute
+docker run -d --name omniroute --restart unless-stopped \
+ --env-file /opt/omniroute/.env \
+ -p 20128:20128 \
+ -v omniroute-data:/app/data \
+ diegosouzapw/omniroute:latest
+```
+
+### View logs
+
+```bash
+docker logs -f omniroute # Real-time stream
+docker logs omniroute --tail 50 # Last 50 lines
+```
+
+### Manual database backup
+
+```bash
+# Copy data from the volume to the host
+docker cp omniroute:/app/data ./backup-$(date +%F)
+
+# Or compress the entire volume
+docker run --rm -v omniroute-data:/data -v $(pwd):/backup \
+ alpine tar czf /backup/omniroute-data-$(date +%F).tar.gz /data
+```
+
+### Restore from backup
+
+```bash
+docker stop omniroute
+docker run --rm -v omniroute-data:/data -v $(pwd):/backup \
+ alpine sh -c “rm -rf /data/* && tar xzf /backup/omniroute-data-YYYY-MM-DD.tar.gz -C /”
+docker start omniroute
+```
+
+---
+
+## 6. Advanced Security
+
+### Restrict nginx to Cloudflare IPs
+
+```bash
+cat > /etc/nginx/cloudflare-ips.conf << ‘CF’
+# Cloudflare IPv4 ranges — update periodically
+# https://www.cloudflare.com/ips-v4/
+set_real_ip_from 173.245.48.0/20;
+set_real_ip_from 103.21.244.0/22;
+set_real_ip_from 103.22.200.0/22;
+set_real_ip_from 103.31.4.0/22;
+set_real_ip_from 141.101.64.0/18;
+set_real_ip_from 108.162.192.0/18;
+set_real_ip_from 190.93.240.0/20;
+set_real_ip_from 188.114.96.0/20;
+set_real_ip_from 197.234.240.0/22;
+set_real_ip_from 198.41.128.0/17;
+set_real_ip_from 162.158.0.0/15;
+set_real_ip_from 104.16.0.0/13;
+set_real_ip_from 104.24.0.0/14;
+set_real_ip_from 172.64.0.0/13;
+set_real_ip_from 131.0.72.0/22;
+real_ip_header CF-Connecting-IP;
+CF
+```
+
+Add the following to `nginx.conf` inside the `http {}` block:
+
+```nginx
+include /etc/nginx/cloudflare-ips.conf;
+```
+
+### Install fail2ban
+
+```bash
+apt install -y fail2ban
+systemctl enable fail2ban
+systemctl start fail2ban
+
+# Check status
+fail2ban-client status sshd
+```
+
+### Block direct access to the Docker port
+
+```bash
+# Prevent direct external access to port 20128
+iptables -I DOCKER-USER -p tcp --dport 20128 -j DROP
+iptables -I DOCKER-USER -i lo -p tcp --dport 20128 -j ACCEPT
+
+# Persist the rules
+apt install -y iptables-persistent
+netfilter-persistent save
+```
+
+---
+
+## 7. Deploy to Cloudflare Workers (Optional)
+
+For remote access via Cloudflare Workers (without exposing the VM directly):
+
+```bash
+# In the local repository
+cd omnirouteCloud
+npm install
+npx wrangler login
+npx wrangler deploy
+```
+
+See the full documentation at [omnirouteCloud/README.md](../omnirouteCloud/README.md).
+
+---
+
+## Port Summary
+
+| Port | Service | Access |
+| ----- | ----------- | -------------------------- |
+| 22 | SSH | Public (with fail2ban) |
+| 80 | nginx HTTP | Redirect → HTTPS |
+| 443 | nginx HTTPS | Via Cloudflare Proxy |
+| 20128 | OmniRoute | Localhost only (via nginx) |
diff --git a/docs/i18n/cs/electron/README.md b/docs/i18n/cs/electron/README.md
deleted file mode 100644
index 28d3903ad3..0000000000
--- a/docs/i18n/cs/electron/README.md
+++ /dev/null
@@ -1,254 +0,0 @@
-# Aplikace OmniRoute Electron pro stolní počítače
-
-Tento adresář obsahuje obalovou aplikaci Electron pro desktopovou aplikaci OmniRoute.
-
-## Architektura (v1.6.4)
-
-```
-electron/
-├── main.js # Main process — window, tray, server lifecycle, CSP, IPC
-├── preload.js # Preload script — secure IPC bridge with disposer pattern
-├── package.json # Electron-specific dependencies & electron-builder config
-├── types.d.ts # TypeScript definitions (AppInfo, ServerStatus, ElectronAPI)
-└── assets/ # Application icons and resources
-
-src/shared/hooks/
-└── useElectron.ts # React hooks — useSyncExternalStore, zero re-renders
-```
-
-## Klíčová rozhodnutí o designu
-
-Rozhodnutí | Odůvodnění
---- | ---
-dotazování `waitForServer()` | Zabraňuje zobrazení prázdné obrazovky při studeném startu — před načtením se ozve `http://localhost:PORT`
-`stdio: 'pipe'` | Zachycuje stdout/stderr serveru pro logování + detekci připravenosti ( `inherit` )
-Vzor drtiče odpadu | `onServerStatus()` vrací `() => void` pro přesné vyčištění listeneru (ne `removeAllListeners` )
-`useSyncExternalStore` | Nulové renderování pro `useIsElectron()` — žádný cyklus `useState` + `useEffect`
-CSP prostřednictvím záhlaví relace | `Content-Security-Policy` omezuje `script-src` , `connect-src` atd. dle osvědčených postupů Electron.
-Podmíněný titulek pro platformu | `titleBarStyle: 'hiddenInset'` pouze v systému macOS; `default` ve Windows/Linuxu
-
-## Rozvoj
-
-### Předpoklady
-
-1. Nejprve sestavte aplikaci Next.js:
-
-```bash
-npm run build
-```
-
-1. Instalace závislostí Electronu:
-
-```bash
-cd electron
-npm install
-```
-
-### Spuštěno ve vývoji
-
-1. Spusťte vývojový server Next.js:
-
-```bash
-npm run dev
-```
-
-1. V jiném terminálu spusťte Electron:
-
-```bash
-cd electron
-npm run dev
-```
-
-### Spuštění v produkčním režimu
-
-1. Sestavení Next.js v samostatném režimu:
-
-```bash
-npm run build
-```
-
-1. Spuštění elektronu:
-
-```bash
-cd electron
-npm start
-```
-
-## Budova
-
-### Sestavení pro aktuální platformu
-
-```bash
-cd electron
-npm run build
-```
-
-### Vytvořte pro specifické platformy
-
-```bash
-# Windows
-npm run build:win
-
-# macOS (x64 + arm64)
-npm run build:mac
-
-# Linux
-npm run build:linux
-```
-
-## Výstup
-
-Vytvořené aplikace jsou umístěny v `dist-electron/` :
-
-- Windows: `.exe` instalační program (NSIS) + přenosný `.exe`
-- macOS: instalační soubor `.dmg` (Intel + Apple Silicon)
-- Linux: `.AppImage`
-
-## Instalace
-
-### macOS
-
-1. Stáhněte si nejnovější soubor `.dmg` ze stránky [Verze](https://github.com/diegosouzapw/OmniRoute/releases) .
-2. Otevřete soubor `.dmg` .
-3. Přetáhněte `OmniRoute.app` do složky Aplikace.
-4. Spustit z Aplikací.
-
-> ⚠️ **Poznámka:** Aplikace zatím není podepsána certifikátem Apple Developer. Pokud macOS aplikaci blokuje, spusťte:
->
-> ```bash
-> xattr -cr /Applications/OmniRoute.app
-> ```
->
-> Nebo klikněte pravým tlačítkem myši na aplikaci → Otevřít → Otevřít (pro obejití Gatekeeperu při prvním spuštění).
-
-### Windows
-
-**Instalační program (doporučeno):**
-
-1. Stáhněte si `OmniRoute.Setup.*.exe` z [Releases](https://github.com/diegosouzapw/OmniRoute/releases) .
-2. Spusťte instalační program.
-3. Spuštění z nabídky Start nebo zástupce na ploše.
-
-**Přenosné (bez instalace):**
-
-1. Stáhněte si soubor `OmniRoute.exe` ze [sekce Vydání](https://github.com/diegosouzapw/OmniRoute/releases) .
-2. Spouštět přímo z libovolné složky.
-
-### Linux
-
-1. Stáhněte si soubor `.AppImage` ze [sekce Releases](https://github.com/diegosouzapw/OmniRoute/releases) .
-2. Udělejte z něj spustitelný soubor:
- ```bash
- chmod +x OmniRoute-*.AppImage
- ```
-3. Běh:
- ```bash
- ./OmniRoute-*.AppImage
- ```
-
-## Funkce
-
-- **Připravenost serveru** – Před zobrazením okna čeká na kontrolu stavu
-- **Systémový zásobník** — Minimalizace do systémového zásobníku s rychlými akcemi (otevřít, změnit port, ukončit)
-- **Správa portů** — Změna portu z nabídky v systémové liště (server se automaticky restartuje)
-- **Ovládací prvky oken** — Vlastní minimalizace, maximalizace, zavření přes IPC
-- **Zásady zabezpečení obsahu** – Omezující CSP prostřednictvím záhlaví relací
-- **Offline podpora** — Samostatný server Next.js v balíčku
-- **Jedna instance** – V daném okamžiku může běžet pouze jedna instance aplikace.
-
-## Konfigurace
-
-### Proměnné prostředí
-
-Proměnná | Výchozí | Popis
---- | --- | ---
-`OMNIROUTE_PORT` | `20128` | Port serveru
-`OMNIROUTE_MEMORY_MB` | `512` | Limit haldy Node.js (64–16384 MB)
-`NODE_ENV` | `production` | Nastavit na `development` pro vývojářský režim
-
-### Vlastní ikona
-
-Umístěte ikony do `assets/` :
-
-- `icon.ico` — ikona Windows (256×256)
-- `icon.icns` — balíček ikon pro macOS
-- `icon.png` — Linux/obecné použití (512×512)
-- `tray-icon.png` — Ikona na systémové liště (16×16 nebo 32×32)
-
-## Kanály IPC
-
-### Vyvolání (Renderer → Hlavní, asynchronní)
-
-Kanál | Vrácení zboží | Popis
---- | --- | ---
-`get-app-info` | `AppInfo` | Název aplikace, verze, platforma, isDev, port
-`open-external` | `void` | Otevřít URL ve výchozím prohlížeči (pouze http/https)
-`get-data-dir` | `string` | Získat cestu k adresáři userData
-`restart-server` | `{ success }` | Zastavení + restart serveru (časový limit 5 s + SIGKILL)
-
-### Odeslat (Renderer → Hlavní, spustit a zapomenout)
-
-Kanál | Popis
---- | ---
-`window-minimize` | Minimalizovat okno
-`window-maximize` | Přepnout maximalizaci/obnovení
-`window-close` | Zavřít okno (minimalizovat do zásobníku)
-
-### Příjem (Hlavní → Renderer, události)
-
-Kanál | Užitečné zatížení | Vydáno, když
---- | --- | ---
-`server-status` | `ServerStatus` | Server se spouští, zastavuje, dochází k chybám nebo se restartuje
-`port-changed` | `number` | Změna portu přes menu zásobníku
-
-> **Poznámka** : Posluchače vracejí funkce pro přesné čištění. Viz hooky `useServerStatus` a `usePortChanged` .
-
-## Zabezpečení
-
-Funkce | Implementace
---- | ---
-Izolace kontextu | `contextIsolation: true` — renderer nemůže přistupovat k Node.js
-Integrace uzlů | `nodeIntegration: false` — v rendereru není `require()`
-Bílý seznam IPC | Názvy kanálů ověřené při předběžném načítání pomocí `safeInvoke` / `safeSend` / `safeOn`
-Ověření URL adresy | `shell.openExternal()` povoluje pouze protokoly `http:` / `https:`
-CSP | Záhlaví `Content-Security-Policy` nastavené pomocí `session.webRequest.onHeadersReceived`
-Zabezpečení webu | `webSecurity: true` – vynucena politika stejného původu
-
-## React Hooky
-
-Háček | Vrácení zboží | Popis
---- | --- | ---
-`useIsElectron()` | `boolean` | Detekce nulového renderování pomocí `useSyncExternalStore`
-`useElectronAppInfo()` | `{ appInfo, loading, error }` | Informace o aplikaci z hlavního procesu
-`useDataDir()` | `{ dataDir, loading, error }` | Adresář uživatelských dat
-`useWindowControls()` | `{ minimize, maximize, close }` | Akce ovládání oken
-`useOpenExternal()` | `{ openExternal }` | Otevřít URL adresy v prohlížeči
-`useServerControls()` | `{ restart, restarting }` | Řízení restartu serveru
-`useServerStatus(cb)` | Drtič odpadu | Poslouchejte události stavu serveru
-`usePortChanged(cb)` | Drtič odpadu | Poslouchejte události změny portu
-
-## Odstraňování problémů
-
-### Aplikace se nespustí
-
-1. Zkontrolujte, zda je port 20128 dostupný: `lsof -i :20128`
-2. Zkontrolujte protokoly konzole pro prefix `[Electron]`
-3. Ověřte, zda výstup sestavení existuje v souboru `.next/standalone`
-
-### Bílá obrazovka
-
-1. Ověření existence buildu Next.js – čekání na připravenost serveru maximálně 30 sekund
-2. Zkontrolujte výstup protokolů `[Server]` a `[Server:err]`
-3. Hledání porušení CSP v konzoli pro vývojáře
-
-### Selhání sestavení
-
-Ujistěte se, že máte nainstalované nástroje pro sestavení:
-
-- Windows: Nástroje pro sestavení ve Visual Studiu
-- macOS: Nástroje příkazového řádku Xcode
-- Linux: `build-essential` , `libsecret-1-dev`
-
-## Licence
-
-MIT
diff --git a/docs/i18n/cs/i18n/README.md b/docs/i18n/cs/i18n/README.md
deleted file mode 100644
index 5de17b4a03..0000000000
--- a/docs/i18n/cs/i18n/README.md
+++ /dev/null
@@ -1,26 +0,0 @@
-# Vícejazyčná dokumentace
-
-Tento adresář obsahuje strojově asistované překlady založené na anglické dokumentaci.
-
-- **API_REFERENCE.md** : 🇺🇸 [Česky](../API_REFERENCE.md) | 🇧🇷 [Português (Brazílie)](./pt-BR/API_REFERENCE.md) | 🇪🇸 [Español](./es/API_REFERENCE.md) | 🇫🇷 [Français](./fr/API_REFERENCE.md) | 🇮🇹 [Italiano](./it/API_REFERENCE.md) | 🇷🇺 [Русский](./ru/API_REFERENCE.md) | 🇨🇳[中文 (简体)](./zh-CN/API_REFERENCE.md) | 🇩🇪 [Deutsch](./de/API_REFERENCE.md) | 🇮🇳 [हिन्दी](./in/API_REFERENCE.md) | 🇹🇭 [ไทย](./th/API_REFERENCE.md) | 🇺🇦 [Українська](./uk-UA/API_REFERENCE.md) | 🇸🇦 [العربية](./ar/API_REFERENCE.md) | 🇯🇵[日本語](./ja/API_REFERENCE.md)| 🇻🇳 [Tiếng Việt](./vi/API_REFERENCE.md) | 🇧🇬 [Български](./bg/API_REFERENCE.md) | 🇩🇰 [Dánsko](./da/API_REFERENCE.md) | 🇫🇮 [Suomi](./fi/API_REFERENCE.md) | 🇮🇱 [עברית](./he/API_REFERENCE.md) | 🇭🇺 [maďarština](./hu/API_REFERENCE.md) | 🇮🇩 [Bahasa Indonésie](./id/API_REFERENCE.md) | 🇰🇷 [한국어](./ko/API_REFERENCE.md) | 🇲🇾 [Bahasa Melayu](./ms/API_REFERENCE.md) | 🇳🇱 [Nizozemsko](./nl/API_REFERENCE.md) | 🇳🇴 [Norsk](./no/API_REFERENCE.md) | 🇵🇹 [Português (Portugalsko)](./pt/API_REFERENCE.md) | 🇷🇴 [Română](./ro/API_REFERENCE.md) | 🇵🇱 [Polski](./pl/API_REFERENCE.md) | 🇸🇰 [Slovenčina](./sk/API_REFERENCE.md) | 🇸🇪 [Svenska](./sv/API_REFERENCE.md) | 🇵🇭 [Filipínec](./phi/API_REFERENCE.md) | 🇨🇿 [Čeština](./cs/API_REFERENCE.md)
-
-- **ARCHITECTURE.md** : 🇺🇸 [anglicky](../ARCHITECTURE.md) | 🇧🇷 [Português (Brazílie)](./pt-BR/ARCHITECTURE.md) | 🇪🇸 [Español](./es/ARCHITECTURE.md) | 🇫🇷 [Français](./fr/ARCHITECTURE.md) | 🇮🇹 [Italiano](./it/ARCHITECTURE.md) | 🇷🇺 [Русский](./ru/ARCHITECTURE.md) | 🇨🇳[中文 (简体)](./zh-CN/ARCHITECTURE.md) | 🇩🇪 [Deutsch](./de/ARCHITECTURE.md) | 🇮🇳 [हिन्दी](./in/ARCHITECTURE.md) | 🇹🇭 [ไทย](./th/ARCHITECTURE.md) | 🇺🇦 [Українська](./uk-UA/ARCHITECTURE.md) | 🇸🇦 [العربية](./ar/ARCHITECTURE.md) | 🇯🇵[日本語](./ja/ARCHITECTURE.md)| 🇻🇳 [Tiếng Việt](./vi/ARCHITECTURE.md) | 🇧🇬 [Български](./bg/ARCHITECTURE.md) | 🇩🇰 [Dánsko](./da/ARCHITECTURE.md) | 🇫🇮 [Suomi](./fi/ARCHITECTURE.md) | 🇮🇱 [עברית](./he/ARCHITECTURE.md) | 🇭🇺 [maďarština](./hu/ARCHITECTURE.md) | 🇮🇩 [Bahasa Indonésie](./id/ARCHITECTURE.md) | 🇰🇷 [한국어](./ko/ARCHITECTURE.md) | 🇲🇾 [Bahasa Melayu](./ms/ARCHITECTURE.md) | 🇳🇱 [Nizozemsko](./nl/ARCHITECTURE.md) | 🇳🇴 [Norsk](./no/ARCHITECTURE.md) | 🇵🇹 [Português (Portugalsko)](./pt/ARCHITECTURE.md) | 🇷🇴 [Română](./ro/ARCHITECTURE.md) | 🇵🇱 [Polski](./pl/ARCHITECTURE.md) | 🇸🇰 [Slovenčina](./sk/ARCHITECTURE.md) | 🇸🇪 [Svenska](./sv/ARCHITECTURE.md) | 🇵🇭 [Filipínec](./phi/ARCHITECTURE.md) | 🇨🇿 [Čeština](./cs/ARCHITECTURE.md)
-
-- **CODEBASE_DOCUMENTATION.md** : 🇺🇸 [anglicky](../CODEBASE_DOCUMENTATION.md) | 🇧🇷 [Português (Brazílie)](./pt-BR/CODEBASE_DOCUMENTATION.md) | 🇪🇸 [Español](./es/CODEBASE_DOCUMENTATION.md) | 🇫🇷 [Français](./fr/CODEBASE_DOCUMENTATION.md) | 🇮🇹 [Italiano](./it/CODEBASE_DOCUMENTATION.md) | 🇷🇺 [Русский](./ru/CODEBASE_DOCUMENTATION.md) | 🇨🇳[中文 (简体)](./zh-CN/CODEBASE_DOCUMENTATION.md) | 🇩🇪 [Deutsch](./de/CODEBASE_DOCUMENTATION.md) | 🇮🇳 [हिन्दी](./in/CODEBASE_DOCUMENTATION.md) | 🇹🇭 [ไทย](./th/CODEBASE_DOCUMENTATION.md) | 🇺🇦 [Українська](./uk-UA/CODEBASE_DOCUMENTATION.md) | 🇸🇦 [العربية](./ar/CODEBASE_DOCUMENTATION.md) | 🇯🇵[日本語](./ja/CODEBASE_DOCUMENTATION.md)| 🇻🇳 [Tiếng Việt](./vi/CODEBASE_DOCUMENTATION.md) | 🇧🇬 [Български](./bg/CODEBASE_DOCUMENTATION.md) | 🇩🇰 [Dánsko](./da/CODEBASE_DOCUMENTATION.md) | 🇫🇮 [Suomi](./fi/CODEBASE_DOCUMENTATION.md) | 🇮🇱 [עברית](./he/CODEBASE_DOCUMENTATION.md) | 🇭🇺 [maďarština](./hu/CODEBASE_DOCUMENTATION.md) | 🇮🇩 [Bahasa Indonésie](./id/CODEBASE_DOCUMENTATION.md) | 🇰🇷 [한국어](./ko/CODEBASE_DOCUMENTATION.md) | 🇲🇾 [Bahasa Melayu](./ms/CODEBASE_DOCUMENTATION.md) | 🇳🇱 [Nizozemsko](./nl/CODEBASE_DOCUMENTATION.md) | 🇳🇴 [Norsk](./no/CODEBASE_DOCUMENTATION.md) | 🇵🇹 [Português (Portugalsko)](./pt/CODEBASE_DOCUMENTATION.md) | 🇷🇴 [Română](./ro/CODEBASE_DOCUMENTATION.md) | 🇵🇱 [Polski](./pl/CODEBASE_DOCUMENTATION.md) | 🇸🇰 [Slovenčina](./sk/CODEBASE_DOCUMENTATION.md) | 🇸🇪 [Svenska](./sv/CODEBASE_DOCUMENTATION.md) | 🇵🇭 [Filipínec](./phi/CODEBASE_DOCUMENTATION.md) | 🇨🇿 [Čeština](./cs/CODEBASE_DOCUMENTATION.md)
-
-- **FEATURES.md** : 🇺🇸 [anglicky](../FEATURES.md) | 🇧🇷 [Português (Brazílie)](./pt-BR/FEATURES.md) | 🇪🇸 [Español](./es/FEATURES.md) | 🇫🇷 [Français](./fr/FEATURES.md) | 🇮🇹 [Italiano](./it/FEATURES.md) | 🇷🇺 [Русский](./ru/FEATURES.md) | 🇨🇳[中文 (简体)](./zh-CN/FEATURES.md) | 🇩🇪 [Deutsch](./de/FEATURES.md) | 🇮🇳 [हिन्दी](./in/FEATURES.md) | 🇹🇭 [ไทย](./th/FEATURES.md) | 🇺🇦 [Українська](./uk-UA/FEATURES.md) | 🇸🇦 [العربية](./ar/FEATURES.md) | 🇯🇵[日本語](./ja/FEATURES.md)| 🇻🇳 [Tiếng Việt](./vi/FEATURES.md) | 🇧🇬 [Български](./bg/FEATURES.md) | 🇩🇰 [Dánsko](./da/FEATURES.md) | 🇫🇮 [Suomi](./fi/FEATURES.md) | 🇮🇱 [עברית](./he/FEATURES.md) | 🇭🇺 [maďarština](./hu/FEATURES.md) | 🇮🇩 [Bahasa Indonésie](./id/FEATURES.md) | 🇰🇷 [한국어](./ko/FEATURES.md) | 🇲🇾 [Bahasa Melayu](./ms/FEATURES.md) | 🇳🇱 [Nizozemsko](./nl/FEATURES.md) | 🇳🇴 [Norsk](./no/FEATURES.md) | 🇵🇹 [Português (Portugalsko)](./pt/FEATURES.md) | 🇷🇴 [Română](./ro/FEATURES.md) | 🇵🇱 [Polski](./pl/FEATURES.md) | 🇸🇰 [Slovenčina](./sk/FEATURES.md) | 🇸🇪 [Svenska](./sv/FEATURES.md) | 🇵🇭 [Filipínec](./phi/FEATURES.md) | 🇨🇿 [Čeština](./cs/FEATURES.md)
-
-- **TOUBLESHOOTING.md** : 🇺🇸 [anglicky](../TROUBLESHOOTING.md) | 🇧🇷 [Português (Brazílie)](./pt-BR/TROUBLESHOOTING.md) | 🇪🇸 [Español](./es/TROUBLESHOOTING.md) | 🇫🇷 [Français](./fr/TROUBLESHOOTING.md) | 🇮🇹 [Italiano](./it/TROUBLESHOOTING.md) | 🇷🇺 [Русский](./ru/TROUBLESHOOTING.md) | 🇨🇳[中文 (简体)](./zh-CN/TROUBLESHOOTING.md) | 🇩🇪 [Deutsch](./de/TROUBLESHOOTING.md) | 🇮🇳 [हिन्दी](./in/TROUBLESHOOTING.md) | 🇹🇭 [ไทย](./th/TROUBLESHOOTING.md) | 🇺🇦 [Українська](./uk-UA/TROUBLESHOOTING.md) | 🇸🇦 [العربية](./ar/TROUBLESHOOTING.md) | 🇯🇵[日本語](./ja/TROUBLESHOOTING.md)| 🇻🇳 [Tiếng Việt](./vi/TROUBLESHOOTING.md) | 🇧🇬 [Български](./bg/TROUBLESHOOTING.md) | 🇩🇰 [Dánsko](./da/TROUBLESHOOTING.md) | 🇫🇮 [Suomi](./fi/TROUBLESHOOTING.md) | 🇮🇱 [עברית](./he/TROUBLESHOOTING.md) | 🇭🇺 [maďarština](./hu/TROUBLESHOOTING.md) | 🇮🇩 [Bahasa Indonésie](./id/TROUBLESHOOTING.md) | 🇰🇷 [한국어](./ko/TROUBLESHOOTING.md) | 🇲🇾 [Bahasa Melayu](./ms/TROUBLESHOOTING.md) | 🇳🇱 [Nizozemsko](./nl/TROUBLESHOOTING.md) | 🇳🇴 [Norsk](./no/TROUBLESHOOTING.md) | 🇵🇹 [Português (Portugalsko)](./pt/TROUBLESHOOTING.md) | 🇷🇴 [Română](./ro/TROUBLESHOOTING.md) | 🇵🇱 [Polski](./pl/TROUBLESHOOTING.md) | 🇸🇰 [Slovenčina](./sk/TROUBLESHOOTING.md) | 🇸🇪 [Svenska](./sv/TROUBLESHOOTING.md) | 🇵🇭 [Filipínec](./phi/TROUBLESHOOTING.md) | 🇨🇿 [Čeština](./cs/TROUBLESHOOTING.md)
-
-- **USER_GUIDE.md** : 🇺🇸 [anglicky](../USER_GUIDE.md) | 🇧🇷 [Português (Brazílie)](./pt-BR/USER_GUIDE.md) | 🇪🇸 [Español](./es/USER_GUIDE.md) | 🇫🇷 [Français](./fr/USER_GUIDE.md) | 🇮🇹 [Italiano](./it/USER_GUIDE.md) | 🇷🇺 [Русский](./ru/USER_GUIDE.md) | 🇨🇳[中文 (简体)](./zh-CN/USER_GUIDE.md) | 🇩🇪 [Deutsch](./de/USER_GUIDE.md) | 🇮🇳 [हिन्दी](./in/USER_GUIDE.md) | 🇹🇭 [ไทย](./th/USER_GUIDE.md) | 🇺🇦 [Українська](./uk-UA/USER_GUIDE.md) | 🇸🇦 [العربية](./ar/USER_GUIDE.md) | 🇯🇵[日本語](./ja/USER_GUIDE.md)| 🇻🇳 [Tiếng Việt](./vi/USER_GUIDE.md) | 🇧🇬 [Български](./bg/USER_GUIDE.md) | 🇩🇰 [Dánsko](./da/USER_GUIDE.md) | 🇫🇮 [Suomi](./fi/USER_GUIDE.md) | 🇮🇱 [עברית](./he/USER_GUIDE.md) | 🇭🇺 [maďarština](./hu/USER_GUIDE.md) | 🇮🇩 [Bahasa Indonésie](./id/USER_GUIDE.md) | 🇰🇷 [한국어](./ko/USER_GUIDE.md) | 🇲🇾 [Bahasa Melayu](./ms/USER_GUIDE.md) | 🇳🇱 [Nizozemsko](./nl/USER_GUIDE.md) | 🇳🇴 [Norsk](./no/USER_GUIDE.md) | 🇵🇹 [Português (Portugalsko)](./pt/USER_GUIDE.md) | 🇷🇴 [Română](./ro/USER_GUIDE.md) | 🇵🇱 [Polski](./pl/USER_GUIDE.md) | 🇸🇰 [Slovenčina](./sk/USER_GUIDE.md) | 🇸🇪 [Svenska](./sv/USER_GUIDE.md) | 🇵🇭 [Filipínec](./phi/USER_GUIDE.md) | 🇨🇿 [Čeština](./cs/USER_GUIDE.md)
-
-## Nedávná poznámka: Zásady limitů pro účty Codex
-
-Dokumentace nyní zahrnuje chování zásad kvót na úrovni účtu Codex:
-
-- Přepínání pro jednotlivé účty: `5h` a `Weekly` (ZAP/VYP).
-- Zásady prahových hodnot: povolené okno dosahující >=90 % označuje účet jako nezpůsobilý k výběru.
-- Automatická rotace: provoz se přesune na další způsobilý účet Codex.
-- Automatické opětovné použití: účet se opět stane způsobilým po úspěšném `resetAt` poskytovatele.
-
-Vygenerováno 26. února 2026.
diff --git a/docs/i18n/cs/open-sse/mcp-server/README.md b/docs/i18n/cs/open-sse/mcp-server/README.md
deleted file mode 100644
index cbf1561f19..0000000000
--- a/docs/i18n/cs/open-sse/mcp-server/README.md
+++ /dev/null
@@ -1,587 +0,0 @@
-# Server OmniRoute MCP
-
-> **Server protokolu modelového kontextu** , který zpřístupňuje inteligenci brány OmniRoute jako **16 nástrojů** pro agenty umělé inteligence.
-
-Server MCP umožňuje libovolnému agentovi umělé inteligence (Claude Desktop, Cursor, VS Code Copilot, vlastním agentům) programově **monitorovat, řídit a optimalizovat** bránu umělé inteligence OmniRoute.
-
----
-
-## Architektura
-
-```
-┌──────────────────────────────────────────────────────────────────┐
-│ AI Agent / IDE │
-│ (Claude Desktop, Cursor, VS Code, Custom) │
-└──────────────────────┬───────────────────────────────────────────┘
- │ MCP Protocol (stdio or HTTP)
- ▼
-┌──────────────────────────────────────────────────────────────────┐
-│ OmniRoute MCP Server │
-│ ┌──────────────┐ ┌─────────────────┐ ┌────────────────────┐ │
-│ │ Scope │ │ 16 MCP Tools │ │ Audit Logger │ │
-│ │ Enforcement │──│ (Phase 1 + 2) │──│ (SHA-256/SQLite) │ │
-│ └──────────────┘ └────────┬────────┘ └────────────────────┘ │
-└─────────────────────────────┼────────────────────────────────────┘
- │ HTTP (internal)
- ▼
-┌──────────────────────────────────────────────────────────────────┐
-│ OmniRoute Gateway (port 20128) │
-│ /v1/chat/completions /api/combos /api/usage ... │
-└──────────────────────────────────────────────────────────────────┘
-```
-
----
-
-## Rychlý start
-
-### 1. Proměnné prostředí
-
-```bash
-# Required: OmniRoute base URL
-export OMNIROUTE_BASE_URL="http://localhost:20128"
-
-# Optional: API key for authenticated access
-export OMNIROUTE_API_KEY="your-api-key"
-
-# Optional: Scope enforcement (default: disabled)
-export OMNIROUTE_MCP_ENFORCE_SCOPES="true"
-export OMNIROUTE_MCP_SCOPES="read:health,read:combos,read:quota,read:usage,read:models,execute:completions,write:combos,write:budget,write:resilience"
-```
-
-### 2. Transport stdio (integrace IDE)
-
-Přidejte do konfigurace klienta MCP:
-
-**Claude Desktop** ( `claude_desktop_config.json` ):
-
-```json
-{
- "mcpServers": {
- "omniroute": {
- "command": "node",
- "args": ["path/to/9router/open-sse/mcp-server/server.ts"],
- "env": {
- "OMNIROUTE_BASE_URL": "http://localhost:20128",
- "OMNIROUTE_API_KEY": "your-key"
- }
- }
- }
-}
-```
-
-**Cursor** ( `.cursor/mcp.json` ):
-
-```json
-{
- "mcpServers": {
- "omniroute": {
- "command": "npx",
- "args": ["tsx", "open-sse/mcp-server/server.ts"],
- "env": {
- "OMNIROUTE_BASE_URL": "http://localhost:20128"
- }
- }
- }
-}
-```
-
-**VS Code** ( `.vscode/settings.json` ):
-
-```json
-{
- "mcp": {
- "servers": {
- "omniroute": {
- "command": "npx",
- "args": ["tsx", "open-sse/mcp-server/server.ts"],
- "env": {
- "OMNIROUTE_BASE_URL": "http://localhost:20128"
- }
- }
- }
- }
-}
-```
-
-### 3. Spuštění přes CLI
-
-```bash
-# Direct start (stdio)
-npx tsx open-sse/mcp-server/server.ts
-
-# Or via OmniRoute CLI
-omniroute --mcp
-```
-
----
-
-## Referenční informace o nástrojích
-
-### Fáze 1: Základní nástroje (8)
-
-# | Nástroj | Rozsahy | Popis
---- | --- | --- | ---
-1 | `omniroute_get_health` | `read:health` | Stav brány, dostupnost, paměť, jističe, limity rychlosti, statistiky mezipaměti
-2 | `omniroute_list_combos` | `read:combos` | Vypsat všechny kombinace (modelové řetězce) se strategiemi a volitelnými metrikami
-3 | `omniroute_get_combo_metrics` | `read:combos` | Metriky výkonu pro konkrétní kombinaci
-4 | `omniroute_switch_combo` | `write:combos` | Aktivace nebo deaktivace komba pro směrování
-5 | `omniroute_check_quota` | `read:quota` | Zbývající kvóta API na poskytovatele se stavem tokenu
-6 | `omniroute_route_request` | `execute:completions` | Odeslat dokončení chatu pomocí inteligentního směrování
-7 | `omniroute_cost_report` | `read:usage` | Zpráva o nákladech podle období (relace/den/týden/měsíc) s rozpisem podle poskytovatele
-8 | `omniroute_list_models_catalog` | `read:models` | Seznam všech dostupných modelů od různých poskytovatelů s funkcemi a cenami
-
-### Fáze 2: Pokročilé nástroje (8)
-
-# | Nástroj | Rozsahy | Popis
---- | --- | --- | ---
-9 | `omniroute_simulate_route` | `read:health` , `read:combos` | Simulace trasy na dryru zobrazující záložní strom a odhadované náklady
-10 | `omniroute_set_budget_guard` | `write:budget` | Nastavit rozpočet relace s akcí při překročení: `degrade` , `block` nebo `alert`
-11 | `omniroute_set_resilience_profile` | `write:resilience` | Použijte profil odolnosti: `aggressive` , `balanced` nebo `conservative`
-12 | `omniroute_test_combo` | `execute:completions` , `read:combos` | Otestujte každého poskytovatele v kombinaci se skutečným výzvou a nahlaste latenci/náklady
-13 | `omniroute_get_provider_metrics` | `read:health` | Metriky pro jednotlivé poskytovatele s percentily latence (p50/p95/p99), jistič
-14 | `omniroute_best_combo_for_task` | `read:combos` , `read:health` | Doporučení kombinací podle typu úkolu s využitím umělé inteligence s omezeními rozpočtu/latence
-15 | `omniroute_explain_route` | `read:health` , `read:usage` | Vysvětlete, proč byl požadavek směrován k poskytovateli (faktory hodnocení, záložní metody)
-16 | `omniroute_get_session_snapshot` | `read:usage` | Snímek celého relace: náklady, tokeny, top modely, chyby, stav rozpočtu
-
----
-
-## Příklady klientů
-
-### Python — Kompletní pracovní postup agenta
-
-```python
-"""
-OmniRoute MCP Client — Python example using the mcp SDK.
-Install: pip install mcp
-"""
-import asyncio
-from mcp import ClientSession, StdioServerParameters
-from mcp.client.stdio import stdio_client
-
-async def main():
- server = StdioServerParameters(
- command="npx",
- args=["tsx", "open-sse/mcp-server/server.ts"],
- env={
- "OMNIROUTE_BASE_URL": "http://localhost:20128",
- "OMNIROUTE_API_KEY": "your-key",
- },
- )
-
- async with stdio_client(server) as (read, write):
- async with ClientSession(read, write) as session:
- await session.initialize()
-
- # 1. Check gateway health
- health = await session.call_tool("omniroute_get_health", {})
- print("Health:", health.content[0].text)
-
- # 2. List available combos with metrics
- combos = await session.call_tool("omniroute_list_combos", {
- "includeMetrics": True
- })
- print("Combos:", combos.content[0].text)
-
- # 3. Find the best combo for a coding task
- best = await session.call_tool("omniroute_best_combo_for_task", {
- "taskType": "coding",
- "budgetConstraint": 0.50,
- "latencyConstraint": 5000,
- })
- print("Best combo:", best.content[0].text)
-
- # 4. Set a session budget guard
- budget = await session.call_tool("omniroute_set_budget_guard", {
- "maxCost": 1.00,
- "action": "degrade",
- "degradeToTier": "cheap",
- })
- print("Budget guard:", budget.content[0].text)
-
- # 5. Route a request through intelligent pipeline
- response = await session.call_tool("omniroute_route_request", {
- "model": "claude-sonnet-4",
- "messages": [
- {"role": "user", "content": "Write a Python hello world"}
- ],
- "role": "coding",
- })
- print("Response:", response.content[0].text)
-
- # 6. Get the session snapshot
- snapshot = await session.call_tool("omniroute_get_session_snapshot", {})
- print("Session:", snapshot.content[0].text)
-
-asyncio.run(main())
-```
-
-### TypeScript — Programový agent
-
-```typescript
-import { Client } from "@modelcontextprotocol/sdk/client/index.js";
-import { StdioClientTransport } from "@modelcontextprotocol/sdk/client/stdio.js";
-
-async function main() {
- const transport = new StdioClientTransport({
- command: "npx",
- args: ["tsx", "open-sse/mcp-server/server.ts"],
- env: {
- OMNIROUTE_BASE_URL: "http://localhost:20128",
- OMNIROUTE_API_KEY: "your-key",
- },
- });
-
- const client = new Client({ name: "my-agent", version: "1.0.0" });
- await client.connect(transport);
-
- // Check quota before deciding which model to use
- const quota = await client.callTool({
- name: "omniroute_check_quota",
- arguments: { provider: "claude" },
- });
- console.log("Claude quota:", quota.content);
-
- // Simulate the route before actually calling
- const simulation = await client.callTool({
- name: "omniroute_simulate_route",
- arguments: {
- model: "claude-sonnet-4",
- promptTokenEstimate: 2000,
- },
- });
- console.log("Route simulation:", simulation.content);
-
- // Send the actual request
- const result = await client.callTool({
- name: "omniroute_route_request",
- arguments: {
- model: "claude-sonnet-4",
- messages: [{ role: "user", content: "Explain async/await" }],
- },
- });
- console.log("Result:", result.content);
-
- // Cost report
- const costs = await client.callTool({
- name: "omniroute_cost_report",
- arguments: { period: "session" },
- });
- console.log("Costs:", costs.content);
-
- await client.close();
-}
-
-main();
-```
-
-### Go — HTTP klient
-
-```go
-package main
-
-import (
- "bytes"
- "encoding/json"
- "fmt"
- "io"
- "net/http"
-)
-
-// Simplified direct-API approach (bypass MCP, hit OmniRoute APIs directly)
-// Useful if you don't need MCP protocol framing.
-
-func callTool(baseURL, tool string, args map[string]any) (string, error) {
- // MCP tools map to OmniRoute APIs:
- endpoints := map[string]string{
- "health": "/api/monitoring/health",
- "combos": "/api/combos",
- "quota": "/api/usage/quota",
- "models": "/v1/models",
- }
-
- url := baseURL + endpoints[tool]
- resp, err := http.Get(url)
- if err != nil {
- return "", err
- }
- defer resp.Body.Close()
- body, _ := io.ReadAll(resp.Body)
- return string(body), nil
-}
-
-func routeRequest(baseURL, model, prompt string) (string, error) {
- payload := map[string]any{
- "model": model,
- "messages": []map[string]string{
- {"role": "user", "content": prompt},
- },
- "stream": false,
- }
- data, _ := json.Marshal(payload)
-
- resp, err := http.Post(
- baseURL+"/v1/chat/completions",
- "application/json",
- bytes.NewReader(data),
- )
- if err != nil {
- return "", err
- }
- defer resp.Body.Close()
- body, _ := io.ReadAll(resp.Body)
- return string(body), nil
-}
-
-func main() {
- base := "http://localhost:20128"
-
- health, _ := callTool(base, "health", nil)
- fmt.Println("Health:", health)
-
- result, _ := routeRequest(base, "auto", "Hello from Go!")
- fmt.Println("Result:", result)
-}
-```
-
----
-
-## Případy použití
-
-### 🔄 Případ použití 1: Agent pro automatické ozdravování
-
-Agent, který monitoruje stav OmniRoute a automaticky přepíná kombinace, když se stav poskytovatelů zhorší.
-
-```python
-async def auto_healing_loop(session):
- """Monitor health and react to provider issues."""
- while True:
- # Check health
- health = await session.call_tool("omniroute_get_health", {})
- data = json.loads(health.content[0].text)
-
- # Find providers with open circuit breakers
- broken = [
- cb for cb in data["circuitBreakers"]
- if cb["state"] == "OPEN"
- ]
-
- if broken:
- # Switch to a different resilience profile
- await session.call_tool("omniroute_set_resilience_profile", {
- "profile": "conservative"
- })
-
- # Find best alternative combo
- best = await session.call_tool("omniroute_best_combo_for_task", {
- "taskType": "coding"
- })
- best_data = json.loads(best.content[0].text)
- combo_id = best_data["recommendedCombo"]["id"]
-
- # Activate it
- await session.call_tool("omniroute_switch_combo", {
- "comboId": combo_id, "active": True
- })
- print(f"⚠️ Auto-healed: switched to {combo_id}")
-
- await asyncio.sleep(30) # Check every 30 seconds
-```
-
-### 💰 Případ užití 2: Programovací agent s ohledem na rozpočet
-
-Agent, který sleduje náklady v reálném čase a při blížícím se vyčerpání rozpočtu přechází na levnější modely.
-
-```python
-async def budget_aware_coding(session, task: str, max_budget: float):
- """Complete a coding task within a budget."""
- # Set budget guard
- await session.call_tool("omniroute_set_budget_guard", {
- "maxCost": max_budget,
- "action": "degrade",
- "degradeToTier": "cheap",
- })
-
- # Simulate first to estimate cost
- sim = await session.call_tool("omniroute_simulate_route", {
- "model": "claude-sonnet-4",
- "promptTokenEstimate": len(task.split()) * 2,
- })
- sim_data = json.loads(sim.content[0].text)
- estimated_cost = sim_data["fallbackTree"]["bestCaseCost"]
- print(f"Estimated cost: ${estimated_cost:.4f}")
-
- # Send request
- result = await session.call_tool("omniroute_route_request", {
- "model": "claude-sonnet-4",
- "messages": [{"role": "user", "content": task}],
- "role": "coding",
- })
-
- # Check remaining budget
- snapshot = await session.call_tool("omniroute_get_session_snapshot", {})
- snap_data = json.loads(snapshot.content[0].text)
- print(f"Session cost: ${snap_data['costTotal']:.4f}")
- if snap_data.get("budgetGuard"):
- print(f"Budget remaining: ${snap_data['budgetGuard']['remaining']:.4f}")
-
- return json.loads(result.content[0].text)["response"]["content"]
-```
-
-### 🧪 Případ použití 3: Kombinovaný benchmarkingový agent
-
-Agent, který pravidelně porovnává všechna komba a hlásí nejrychlejší/nejlevnější.
-
-```python
-async def benchmark_combos(session):
- """Benchmark all enabled combos and rank them."""
- combos = await session.call_tool("omniroute_list_combos", {
- "includeMetrics": True,
- })
- combo_list = json.loads(combos.content[0].text)["combos"]
-
- results = []
- for combo in combo_list:
- if not combo["enabled"]:
- continue
-
- test = await session.call_tool("omniroute_test_combo", {
- "comboId": combo["id"],
- "testPrompt": "Return the number 42.",
- })
- test_data = json.loads(test.content[0].text)
- results.append({
- "combo": combo["name"],
- "fastest": test_data["summary"]["fastestProvider"],
- "cheapest": test_data["summary"]["cheapestProvider"],
- "success_rate": f'{test_data["summary"]["successful"]}/{test_data["summary"]["totalProviders"]}',
- })
-
- print("📊 Combo Benchmark Results:")
- for r in results:
- print(f" {r['combo']}: fastest={r['fastest']}, cheapest={r['cheapest']}, success={r['success_rate']}")
-```
-
-### 🔍 Případ použití 4: Agent pro ladění po smrti
-
-Agent, který vysvětluje, proč byl požadavek směrován ke konkrétnímu poskytovateli.
-
-```typescript
-async function debugRouting(client: Client, requestId: string) {
- // Explain the routing decision
- const explanation = await client.callTool({
- name: "omniroute_explain_route",
- arguments: { requestId },
- });
- const data = JSON.parse(explanation.content[0].text);
-
- console.log(`Request ${requestId}:`);
- console.log(` Provider: ${data.decision.providerSelected}`);
- console.log(` Model: ${data.decision.modelUsed}`);
- console.log(` Score: ${data.decision.score}`);
- console.log(` Factors:`);
- for (const factor of data.decision.factors) {
- console.log(` ${factor.name}: ${factor.value} (weight: ${factor.weight})`);
- }
- if (data.decision.fallbacksTriggered.length > 0) {
- console.log(` Fallbacks triggered:`);
- for (const fb of data.decision.fallbacksTriggered) {
- console.log(` ${fb.provider}: ${fb.reason}`);
- }
- }
-}
-```
-
-### 📋 Případ použití 5: Agent pro vyhledávání modelů
-
-Agent, který vyhledává nejlevnější modely pro danou funkci.
-
-```python
-async def find_cheapest_models(session, capability="chat"):
- """Find the cheapest available models for a capability."""
- catalog = await session.call_tool("omniroute_list_models_catalog", {
- "capability": capability,
- })
- models = json.loads(catalog.content[0].text)["models"]
-
- # Filter available models with pricing
- priced = [
- m for m in models
- if m["status"] == "available" and m.get("pricing")
- ]
- priced.sort(key=lambda m: m["pricing"]["inputPerMillion"] or float("inf"))
-
- print(f"💡 Cheapest {capability} models:")
- for m in priced[:5]:
- input_cost = m["pricing"]["inputPerMillion"] or 0
- output_cost = m["pricing"]["outputPerMillion"] or 0
- print(f" {m['id']} ({m['provider']}): ${input_cost}/M in, ${output_cost}/M out")
-```
-
----
-
-## Zabezpečení a vynucování rozsahu
-
-Server MCP podporuje **detailní vynucování rozsahu** pro prostředí s více klienty:
-
-Rozsah | Nástroje
---- | ---
-`read:health` | `get_health` , `simulate_route` , `get_provider_metrics` , `best_combo_for_task` , `explain_route`
-`read:combos` | `list_combos` , `get_combo_metrics` , `simulate_route` , `best_combo_for_task` , `test_combo`
-`read:quota` | `check_quota`
-`read:usage` | `cost_report` , `explain_route` , `get_session_snapshot`
-`read:models` | `list_models_catalog`
-`write:combos` | `switch_combo`
-`write:budget` | `set_budget_guard`
-`write:resilience` | `set_resilience_profile`
-`execute:completions` | `route_request` , `test_combo`
-
-**Rozsahy zástupných znaků:** Použijte `read:*` pro udělení všech rozsahů pro čtení nebo `*` pro plný přístup.
-
----
-
-## Protokolování auditu
-
-Každé volání nástroje je zaznamenáno do tabulky SQLite `mcp_tool_audit` :
-
-- **Vstup:** SHA-256 hash (nikdy neukládá nezpracované výzvy)
-- **Výstup:** Zkráceno na 200 znaků
-- **Metadata:** Název nástroje, doba trvání, úspěch/chyba, ID klíče API
-
-Přístup k auditním datům prostřednictvím:
-
-```typescript
-import { getRecentAuditEntries, getAuditStats } from "./audit";
-
-const entries = await getRecentAuditEntries(50);
-const stats = await getAuditStats();
-// stats: { totalCalls, successRate, avgDurationMs, topTools }
-```
-
----
-
-## Struktura souboru
-
-```
-mcp-server/
-├── server.ts # MCP server setup, essential tool handlers, entry point
-├── index.ts # Barrel export
-├── audit.ts # SQLite audit logger (SHA-256 input hashing)
-├── scopeEnforcement.ts # Fine-grained scope enforcement
-├── schemas/
-│ ├── tools.ts # Zod schemas for all 16 tools (input/output/scopes)
-│ ├── a2a.ts # A2A protocol types (Agent Card, Task, JSON-RPC)
-│ ├── audit.ts # Audit & routing decision types + hash helpers
-│ └── index.ts # Schema barrel export
-├── tools/
-│ └── advancedTools.ts # Phase 2 tool handlers (8 advanced tools)
-└── __tests__/
- ├── essentialTools.test.ts
- ├── advancedTools.test.ts
- └── a2aLifecycle.test.ts
-```
-
----
-
-## Licence
-
-Součást [OmniRoute](https://github.com/diegosouzapw/OmniRoute) — licence MIT.
diff --git a/docs/i18n/cs/src/lib/a2a/README.md b/docs/i18n/cs/src/lib/a2a/README.md
new file mode 100644
index 0000000000..a221082084
--- /dev/null
+++ b/docs/i18n/cs/src/lib/a2a/README.md
@@ -0,0 +1,752 @@
+# OmniRoute A2A Server (Čeština)
+
+🌐 **Languages:** 🇺🇸 [English](../../../../../../src/lib/a2a/README.md) · 🇪🇸 [es](../../../../es/src/lib/a2a/README.md) · 🇫🇷 [fr](../../../../fr/src/lib/a2a/README.md) · 🇩🇪 [de](../../../../de/src/lib/a2a/README.md) · 🇮🇹 [it](../../../../it/src/lib/a2a/README.md) · 🇷🇺 [ru](../../../../ru/src/lib/a2a/README.md) · 🇨🇳 [zh-CN](../../../../zh-CN/src/lib/a2a/README.md) · 🇯🇵 [ja](../../../../ja/src/lib/a2a/README.md) · 🇰🇷 [ko](../../../../ko/src/lib/a2a/README.md) · 🇸🇦 [ar](../../../../ar/src/lib/a2a/README.md) · 🇮🇳 [in](../../../../in/src/lib/a2a/README.md) · 🇹🇭 [th](../../../../th/src/lib/a2a/README.md) · 🇻🇳 [vi](../../../../vi/src/lib/a2a/README.md) · 🇮🇩 [id](../../../../id/src/lib/a2a/README.md) · 🇲🇾 [ms](../../../../ms/src/lib/a2a/README.md) · 🇳🇱 [nl](../../../../nl/src/lib/a2a/README.md) · 🇵🇱 [pl](../../../../pl/src/lib/a2a/README.md) · 🇸🇪 [sv](../../../../sv/src/lib/a2a/README.md) · 🇳🇴 [no](../../../../no/src/lib/a2a/README.md) · 🇩🇰 [da](../../../../da/src/lib/a2a/README.md) · 🇫🇮 [fi](../../../../fi/src/lib/a2a/README.md) · 🇵🇹 [pt](../../../../pt/src/lib/a2a/README.md) · 🇷🇴 [ro](../../../../ro/src/lib/a2a/README.md) · 🇭🇺 [hu](../../../../hu/src/lib/a2a/README.md) · 🇧🇬 [bg](../../../../bg/src/lib/a2a/README.md) · 🇸🇰 [sk](../../../../sk/src/lib/a2a/README.md) · 🇺🇦 [uk-UA](../../../../uk-UA/src/lib/a2a/README.md) · 🇮🇱 [he](../../../../he/src/lib/a2a/README.md) · 🇵🇭 [phi](../../../../phi/src/lib/a2a/README.md) · 🇧🇷 [pt-BR](../../../../pt-BR/src/lib/a2a/README.md) · 🇨🇿 [cs](../../../../cs/src/lib/a2a/README.md)
+
+---
+
+> **Agent-to-Agent Protocol v0.3** — Enables any AI agent to use OmniRoute as an intelligent routing agent via JSON-RPC 2.0.
+
+The A2A Server exposes OmniRoute as a **first-class agent** that other agents can discover, delegate tasks to, and collaborate with using the [A2A Protocol](https://google.github.io/A2A/).
+
+---
+
+## Architektura
+
+```
+┌──────────────────────────────────────────────────────────────────┐
+│ Orchestrator Agent │
+│ (LangChain, CrewAI, AutoGen, Custom Agent) │
+└──────────────────────┬───────────────────────────────────────────┘
+ │ 1. GET /.well-known/agent.json (discover)
+ │ 2. POST /a2a (JSON-RPC 2.0)
+ ▼
+┌──────────────────────────────────────────────────────────────────┐
+│ OmniRoute A2A Server │
+│ ┌────────────────┐ ┌────────────────┐ ┌───────────────────┐ │
+│ │ Task Manager │ │ Skill Engine │ │ SSE Streaming │ │
+│ │ (lifecycle) │──│ (registry) │──│ (real-time) │ │
+│ └────────────────┘ └────────┬───────┘ └───────────────────┘ │
+│ │ │
+│ Skills: │ │
+│ ├─ smart-routing ──────────┤ ┌────────────────────────────┐ │
+│ └─ quota-management ───────┘ │ Routing Decision Logger │ │
+│ └────────────────────────────┘ │
+└──────────────────────────────────────────────────────────────────┘
+ │
+ ▼ OmniRoute Gateway (internal)
+ /v1/chat/completions, /api/combos, /api/usage/quota
+```
+
+---
+
+## Rychlý start
+
+### Agent Discovery
+
+Every A2A-compatible agent exposes an **Agent Card** at `/.well-known/agent.json`:
+
+```bash
+curl http://localhost:20128/.well-known/agent.json
+```
+
+**Response:**
+
+```json
+{
+ "name": "OmniRoute",
+ "description": "Intelligent AI gateway with auto-routing across 50+ providers",
+ "url": "http://localhost:20128/a2a",
+ "version": "1.8.1",
+ "capabilities": {
+ "streaming": true,
+ "pushNotifications": false
+ },
+ "skills": [
+ {
+ "id": "smart-routing",
+ "name": "Smart Routing",
+ "description": "Routes prompts through OmniRoute intelligent pipeline",
+ "tags": ["routing", "llm", "multi-provider", "cost-optimization"],
+ "examples": [
+ "Write a hello world in Python",
+ "Explain quantum computing using the cheapest provider"
+ ]
+ },
+ {
+ "id": "quota-management",
+ "name": "Quota Management",
+ "description": "Natural-language queries about provider quotas",
+ "tags": ["quota", "analytics", "cost"],
+ "examples": [
+ "Which provider has the most quota remaining?",
+ "Suggest a free combo for coding"
+ ]
+ }
+ ],
+ "authentication": {
+ "schemes": ["bearer"],
+ "apiKeyHeader": "Authorization"
+ }
+}
+```
+
+---
+
+## JSON-RPC 2.0 Methods
+
+### `message/send` — Synchronous Execution
+
+Send a message to a skill and receive the complete response.
+
+```bash
+curl -X POST http://localhost:20128/a2a \
+ -H "Content-Type: application/json" \
+ -H "Authorization: Bearer YOUR_KEY" \
+ -d '{
+ "jsonrpc": "2.0",
+ "id": "1",
+ "method": "message/send",
+ "params": {
+ "skill": "smart-routing",
+ "messages": [{"role": "user", "content": "Write a Python hello world"}],
+ "metadata": {"model": "auto", "combo": "fast-coding"}
+ }
+ }'
+```
+
+**Response:**
+
+```json
+{
+ "jsonrpc": "2.0",
+ "id": "1",
+ "result": {
+ "task": { "id": "a1b2c3d4-...", "state": "completed" },
+ "artifacts": [{ "type": "text", "content": "print('Hello, World!')" }],
+ "metadata": {
+ "routing_explanation": "Selected claude-sonnet via provider \"anthropic\" (latency: 1200ms, cost: $0.0030)",
+ "cost_envelope": { "estimated": 0.005, "actual": 0.003, "currency": "USD" },
+ "resilience_trace": [
+ { "event": "primary_selected", "provider": "anthropic", "timestamp": "2026-03-04T..." }
+ ],
+ "policy_verdict": { "allowed": true, "reason": "within budget and quota limits" }
+ }
+ }
+}
+```
+
+### `message/stream` — SSE Streaming
+
+Same as `message/send` but returns Server-Sent Events for real-time streaming.
+
+```bash
+curl -N -X POST http://localhost:20128/a2a \
+ -H "Content-Type: application/json" \
+ -H "Authorization: Bearer YOUR_KEY" \
+ -d '{
+ "jsonrpc": "2.0",
+ "id": "1",
+ "method": "message/stream",
+ "params": {
+ "skill": "smart-routing",
+ "messages": [{"role": "user", "content": "Explain quantum computing"}]
+ }
+ }'
+```
+
+**SSE Events:**
+
+```
+data: {"jsonrpc":"2.0","method":"message/stream","params":{"task":{"id":"...","state":"working"},"chunk":{"type":"text","content":"Quantum computing..."}}}
+
+: heartbeat 2026-03-04T21:00:00Z
+
+data: {"jsonrpc":"2.0","method":"message/stream","params":{"task":{"id":"...","state":"completed"},"metadata":{...}}}
+```
+
+### `tasks/get` — Query Task Status
+
+```bash
+curl -X POST http://localhost:20128/a2a \
+ -H "Content-Type: application/json" \
+ -H "Authorization: Bearer YOUR_KEY" \
+ -d '{"jsonrpc":"2.0","id":"2","method":"tasks/get","params":{"taskId":"TASK_UUID"}}'
+```
+
+### `tasks/cancel` — Cancel a Running Task
+
+```bash
+curl -X POST http://localhost:20128/a2a \
+ -H "Content-Type: application/json" \
+ -H "Authorization: Bearer YOUR_KEY" \
+ -d '{"jsonrpc":"2.0","id":"3","method":"tasks/cancel","params":{"taskId":"TASK_UUID"}}'
+```
+
+---
+
+## Skills Reference
+
+### `smart-routing`
+
+Routes prompts through OmniRoute's intelligent pipeline with full observability.
+
+**Parameters (in `metadata`):**
+
+| Parameter | Type | Default | Description |
+| --------- | -------- | ------------ | ---------------------------------------------------------------------------------------- |
+| `model` | `string` | `"auto"` | Target model (e.g., `claude-sonnet-4`, `gpt-4o`, `auto`) |
+| `combo` | `string` | active combo | Specific combo to route through |
+| `budget` | `number` | none | Maximum cost in USD for this request |
+| `role` | `string` | none | Task role hint: `coding`, `review`, `planning`, `analysis`, `debugging`, `documentation` |
+
+**Returns:**
+
+| Field | Description |
+| ------------------------------ | --------------------------------------------------------- |
+| `artifacts[].content` | The LLM response text |
+| `metadata.routing_explanation` | Human-readable explanation of routing decision |
+| `metadata.cost_envelope` | Estimated vs actual cost with currency |
+| `metadata.resilience_trace` | Array of events (primary_selected, fallback_needed, etc.) |
+| `metadata.policy_verdict` | Whether the request was allowed and why |
+
+### `quota-management`
+
+Answers natural-language queries about provider quotas.
+
+**Query types (inferred from message content):**
+
+| Query Pattern | Response Type |
+| ---------------------------------------------- | -------------------------------------------------------- |
+| Contains `"ranking"`, `"most quota"`, `"best"` | Providers ranked by remaining quota |
+| Contains `"free"`, `"suggest"` | Lists free combos or suggests free-tier providers |
+| Default | Full quota summary with warnings for low-quota providers |
+
+---
+
+## Task Lifecycle
+
+```
+submitted ──→ working ──→ completed
+ ──→ failed
+ ──────────→ cancelled
+```
+
+| State | Description |
+| ----------- | ----------------------------------------------------- |
+| `submitted` | Task created, queued for execution |
+| `working` | Skill handler is executing |
+| `completed` | Execution succeeded, artifacts available |
+| `failed` | Execution failed or task expired (TTL: 5 min default) |
+| `cancelled` | Cancelled by client via `tasks/cancel` |
+
+- Terminal states: `completed`, `failed`, `cancelled` (no further transitions)
+- Expired tasks in `submitted` or `working` are auto-marked as `failed`
+- Tasks are garbage-collected after 2× TTL
+
+---
+
+## Client Examples
+
+### Python — Orchestrator Agent
+
+```python
+"""
+A2A Client — Python example.
+Discovers OmniRoute agent, sends a task, and processes the result.
+"""
+import requests
+import json
+
+BASE_URL = "http://localhost:20128"
+API_KEY = "your-api-key"
+HEADERS = {
+ "Content-Type": "application/json",
+ "Authorization": f"Bearer {API_KEY}",
+}
+
+# 1. Discover agent capabilities
+agent_card = requests.get(f"{BASE_URL}/.well-known/agent.json").json()
+print(f"Agent: {agent_card['name']} v{agent_card['version']}")
+print(f"Skills: {[s['id'] for s in agent_card['skills']]}")
+
+# 2. Send a smart-routing task
+response = requests.post(f"{BASE_URL}/a2a", headers=HEADERS, json={
+ "jsonrpc": "2.0",
+ "id": "task-1",
+ "method": "message/send",
+ "params": {
+ "skill": "smart-routing",
+ "messages": [{"role": "user", "content": "Write a Python quicksort implementation"}],
+ "metadata": {
+ "model": "auto",
+ "combo": "fast-coding",
+ "budget": 0.10,
+ }
+ }
+})
+result = response.json()["result"]
+print(f"\n📝 Response: {result['artifacts'][0]['content'][:200]}...")
+print(f"🔀 Routing: {result['metadata']['routing_explanation']}")
+print(f"💰 Cost: ${result['metadata']['cost_envelope']['actual']}")
+print(f"🛡️ Policy: {result['metadata']['policy_verdict']['reason']}")
+
+# 3. Query quota status
+quota_resp = requests.post(f"{BASE_URL}/a2a", headers=HEADERS, json={
+ "jsonrpc": "2.0",
+ "id": "task-2",
+ "method": "message/send",
+ "params": {
+ "skill": "quota-management",
+ "messages": [{"role": "user", "content": "Which provider has the most quota remaining?"}],
+ }
+})
+quota_result = quota_resp.json()["result"]
+print(f"\n📊 Quota: {quota_result['artifacts'][0]['content']}")
+```
+
+### TypeScript — Multi-Agent Orchestrator
+
+```typescript
+/**
+ * A2A Client — TypeScript example.
+ * Shows agent discovery, task delegation, and streaming.
+ */
+
+const BASE_URL = "http://localhost:20128";
+const API_KEY = "your-api-key";
+
+interface JsonRpcResponse {
+ jsonrpc: "2.0";
+ id: string | number;
+ result?: T;
+ error?: { code: number; message: string };
+}
+
+async function a2aCall(method: string, params: Record): Promise {
+ const resp = await fetch(`${BASE_URL}/a2a`, {
+ method: "POST",
+ headers: {
+ "Content-Type": "application/json",
+ Authorization: `Bearer ${API_KEY}`,
+ },
+ body: JSON.stringify({
+ jsonrpc: "2.0",
+ id: `${method}-${Date.now()}`,
+ method,
+ params,
+ }),
+ });
+ const json: JsonRpcResponse = await resp.json();
+ if (json.error) throw new Error(`[${json.error.code}] ${json.error.message}`);
+ return json.result!;
+}
+
+// ── Agent Discovery ──
+const agentCard = await fetch(`${BASE_URL}/.well-known/agent.json`).then((r) => r.json());
+console.log(`Connected to: ${agentCard.name} (${agentCard.skills.length} skills)`);
+
+// ── Smart Routing: Send a coding task ──
+const routingResult = await a2aCall("message/send", {
+ skill: "smart-routing",
+ messages: [{ role: "user", content: "Implement a Redis cache wrapper in TypeScript" }],
+ metadata: { model: "claude-sonnet-4", role: "coding" },
+});
+console.log("Response:", routingResult.artifacts[0].content);
+console.log("Provider:", routingResult.metadata.routing_explanation);
+
+// ── Quota Management: Find free alternatives ──
+const quotaResult = await a2aCall("message/send", {
+ skill: "quota-management",
+ messages: [{ role: "user", content: "Suggest free combos for documentation" }],
+});
+console.log("Free combos:", quotaResult.artifacts[0].content);
+
+// ── Streaming: Real-time response ──
+const streamResp = await fetch(`${BASE_URL}/a2a`, {
+ method: "POST",
+ headers: {
+ "Content-Type": "application/json",
+ Authorization: `Bearer ${API_KEY}`,
+ },
+ body: JSON.stringify({
+ jsonrpc: "2.0",
+ id: "stream-1",
+ method: "message/stream",
+ params: {
+ skill: "smart-routing",
+ messages: [{ role: "user", content: "Explain microservices architecture" }],
+ },
+ }),
+});
+
+const reader = streamResp.body!.getReader();
+const decoder = new TextDecoder();
+while (true) {
+ const { done, value } = await reader.read();
+ if (done) break;
+ const chunk = decoder.decode(value);
+ for (const line of chunk.split("\n")) {
+ if (line.startsWith("data: ")) {
+ const event = JSON.parse(line.slice(6));
+ if (event.params.chunk) {
+ process.stdout.write(event.params.chunk.content);
+ }
+ if (event.params.task.state === "completed") {
+ console.log("\n✅ Stream completed");
+ }
+ }
+ }
+}
+```
+
+### Python — LangChain A2A Integration
+
+```python
+"""
+LangChain integration — Use OmniRoute A2A as a custom LLM.
+"""
+from langchain.llms.base import BaseLLM
+from langchain.schema import LLMResult, Generation
+import requests
+from typing import List, Optional
+
+class OmniRouteA2A(BaseLLM):
+ base_url: str = "http://localhost:20128"
+ api_key: str = ""
+ model: str = "auto"
+ combo: Optional[str] = None
+
+ @property
+ def _llm_type(self) -> str:
+ return "omniroute-a2a"
+
+ def _call(self, prompt: str, stop: Optional[List[str]] = None, **kwargs) -> str:
+ response = requests.post(
+ f"{self.base_url}/a2a",
+ headers={
+ "Content-Type": "application/json",
+ "Authorization": f"Bearer {self.api_key}",
+ },
+ json={
+ "jsonrpc": "2.0",
+ "id": "langchain-1",
+ "method": "message/send",
+ "params": {
+ "skill": "smart-routing",
+ "messages": [{"role": "user", "content": prompt}],
+ "metadata": {
+ "model": self.model,
+ **({"combo": self.combo} if self.combo else {}),
+ },
+ },
+ },
+ )
+ result = response.json()["result"]
+ return result["artifacts"][0]["content"]
+
+ def _generate(self, prompts: List[str], stop=None, **kwargs) -> LLMResult:
+ return LLMResult(
+ generations=[[Generation(text=self._call(p, stop))] for p in prompts]
+ )
+
+# Usage
+llm = OmniRouteA2A(
+ base_url="http://localhost:20128",
+ api_key="your-key",
+ model="auto",
+ combo="fast-coding",
+)
+result = llm("Write a Python function to merge two sorted lists")
+print(result)
+```
+
+### Go — A2A Client
+
+```go
+package main
+
+import (
+ "bytes"
+ "encoding/json"
+ "fmt"
+ "io"
+ "net/http"
+)
+
+const baseURL = "http://localhost:20128"
+const apiKey = "your-api-key"
+
+type JsonRpcRequest struct {
+ Jsonrpc string `json:"jsonrpc"`
+ ID string `json:"id"`
+ Method string `json:"method"`
+ Params interface{} `json:"params"`
+}
+
+type JsonRpcResponse struct {
+ Jsonrpc string `json:"jsonrpc"`
+ ID string `json:"id"`
+ Result interface{} `json:"result"`
+ Error *struct {
+ Code int `json:"code"`
+ Message string `json:"message"`
+ } `json:"error"`
+}
+
+func a2aCall(method string, params interface{}) (*JsonRpcResponse, error) {
+ body, _ := json.Marshal(JsonRpcRequest{
+ Jsonrpc: "2.0",
+ ID: "go-1",
+ Method: method,
+ Params: params,
+ })
+
+ req, _ := http.NewRequest("POST", baseURL+"/a2a", bytes.NewReader(body))
+ req.Header.Set("Content-Type", "application/json")
+ req.Header.Set("Authorization", "Bearer "+apiKey)
+
+ resp, err := http.DefaultClient.Do(req)
+ if err != nil {
+ return nil, err
+ }
+ defer resp.Body.Close()
+ data, _ := io.ReadAll(resp.Body)
+
+ var result JsonRpcResponse
+ json.Unmarshal(data, &result)
+ return &result, nil
+}
+
+func main() {
+ // Discover agent
+ resp, _ := http.Get(baseURL + "/.well-known/agent.json")
+ defer resp.Body.Close()
+ body, _ := io.ReadAll(resp.Body)
+ fmt.Println("Agent Card:", string(body))
+
+ // Send smart-routing task
+ result, _ := a2aCall("message/send", map[string]interface{}{
+ "skill": "smart-routing",
+ "messages": []map[string]string{{"role": "user", "content": "Hello from Go!"}},
+ "metadata": map[string]interface{}{"model": "auto"},
+ })
+ out, _ := json.MarshalIndent(result.Result, "", " ")
+ fmt.Println("Result:", string(out))
+}
+```
+
+---
+
+## Use Cases
+
+### 🤖 Use Case 1: Multi-Agent Coding Pipeline
+
+An orchestrator agent delegates code generation to OmniRoute, then passes the output to a review agent.
+
+```python
+def coding_pipeline(task: str):
+ # Step 1: Generate code via OmniRoute A2A
+ code_result = a2a_send("smart-routing", [
+ {"role": "user", "content": f"Write production-quality code: {task}"}
+ ], metadata={"model": "auto", "role": "coding"})
+ code = code_result["artifacts"][0]["content"]
+
+ # Step 2: Review the code via OmniRoute A2A (different model)
+ review_result = a2a_send("smart-routing", [
+ {"role": "user", "content": f"Review this code for bugs and improvements:\n\n{code}"}
+ ], metadata={"model": "auto", "role": "review"})
+ review = review_result["artifacts"][0]["content"]
+
+ # Step 3: Check costs
+ print(f"Code cost: ${code_result['metadata']['cost_envelope']['actual']}")
+ print(f"Review cost: ${review_result['metadata']['cost_envelope']['actual']}")
+
+ return {"code": code, "review": review}
+```
+
+### 💡 Use Case 2: Quota-Aware Agent Swarm
+
+Multiple agents share quota through OmniRoute, using the quota skill to coordinate.
+
+```python
+async def quota_aware_agent(agent_name: str, task: str):
+ # Check quota before starting
+ quota = a2a_send("quota-management", [
+ {"role": "user", "content": "Which provider has the most quota remaining?"}
+ ])
+ print(f"[{agent_name}] {quota['artifacts'][0]['content']}")
+
+ # Send request with budget constraint
+ result = a2a_send("smart-routing", [
+ {"role": "user", "content": task}
+ ], metadata={"budget": 0.05})
+
+ policy = result["metadata"]["policy_verdict"]
+ if not policy["allowed"]:
+ print(f"[{agent_name}] ⚠️ Budget exceeded: {policy['reason']}")
+ # Fall back to free combo
+ quota = a2a_send("quota-management", [
+ {"role": "user", "content": "Suggest free combos"}
+ ])
+ print(f"[{agent_name}] Free alternatives: {quota['artifacts'][0]['content']}")
+
+ return result
+```
+
+### 📊 Use Case 3: Real-Time Streaming Dashboard
+
+A monitoring agent streams responses and displays progress in real-time.
+
+```typescript
+async function streamingDashboard(prompt: string) {
+ const response = await fetch(`${BASE_URL}/a2a`, {
+ method: "POST",
+ headers: { "Content-Type": "application/json", Authorization: `Bearer ${API_KEY}` },
+ body: JSON.stringify({
+ jsonrpc: "2.0",
+ id: "dash-1",
+ method: "message/stream",
+ params: { skill: "smart-routing", messages: [{ role: "user", content: prompt }] },
+ }),
+ });
+
+ let totalChunks = 0;
+ const reader = response.body!.getReader();
+ const decoder = new TextDecoder();
+
+ while (true) {
+ const { done, value } = await reader.read();
+ if (done) break;
+
+ for (const line of decoder.decode(value).split("\n")) {
+ if (line.startsWith("data: ")) {
+ const event = JSON.parse(line.slice(6));
+ const state = event.params.task.state;
+
+ if (state === "working" && event.params.chunk) {
+ totalChunks++;
+ process.stdout.write(
+ `\r[Chunk ${totalChunks}] ${event.params.chunk.content.slice(0, 50)}...`
+ );
+ }
+ if (state === "completed") {
+ const meta = event.params.metadata;
+ console.log(
+ `\n✅ Done | Cost: $${meta?.cost_envelope?.actual || 0} | Route: ${meta?.routing_explanation || "N/A"}`
+ );
+ }
+ if (state === "failed") {
+ console.error(`\n❌ Failed: ${event.params.metadata?.error}`);
+ }
+ }
+ }
+ }
+}
+```
+
+### 🔁 Use Case 4: Task Polling Pattern
+
+For long-running tasks, poll the task status instead of waiting synchronously.
+
+```python
+import time
+
+def poll_task(task_id: str, timeout: int = 60):
+ """Poll task status until completion or timeout."""
+ start = time.time()
+ while time.time() - start < timeout:
+ result = requests.post(f"{BASE_URL}/a2a", headers=HEADERS, json={
+ "jsonrpc": "2.0",
+ "id": "poll-1",
+ "method": "tasks/get",
+ "params": {"taskId": task_id},
+ }).json()
+
+ task = result["result"]["task"]
+ state = task["state"]
+ print(f" Task {task_id[:8]}... state={state}")
+
+ if state in ("completed", "failed", "cancelled"):
+ return task
+ time.sleep(2)
+
+ # Timeout — cancel the task
+ requests.post(f"{BASE_URL}/a2a", headers=HEADERS, json={
+ "jsonrpc": "2.0",
+ "id": "cancel-1",
+ "method": "tasks/cancel",
+ "params": {"taskId": task_id},
+ })
+ raise TimeoutError(f"Task {task_id} timed out after {timeout}s")
+```
+
+---
+
+## Error Codes
+
+| Code | Constant | Meaning |
+| ------ | ------------------------ | ---------------------------------------- |
+| -32700 | — | Parse error (invalid JSON) |
+| -32600 | `INVALID_REQUEST` | Invalid JSON-RPC request or unauthorized |
+| -32601 | `METHOD_NOT_FOUND` | Unknown method or skill |
+| -32602 | `INVALID_PARAMS` | Missing or invalid parameters |
+| -32603 | `INTERNAL_ERROR` | Skill execution failed |
+| -32001 | `TASK_NOT_FOUND` | Task ID not found |
+| -32002 | `TASK_ALREADY_COMPLETED` | Cannot modify a completed task |
+| -32003 | `UNAUTHORIZED` | Invalid or missing API key |
+| -32004 | `BUDGET_EXCEEDED` | Request exceeds configured budget |
+| -32005 | `PROVIDER_UNAVAILABLE` | No available providers |
+
+---
+
+## Authentication
+
+All `/a2a` requests require a Bearer token via the `Authorization` header:
+
+```
+Authorization: Bearer YOUR_OMNIROUTE_API_KEY
+```
+
+If no API key is configured on the server (`OMNIROUTE_API_KEY` is empty), authentication is bypassed.
+
+---
+
+## File Structure
+
+```
+src/lib/a2a/
+├── taskManager.ts # Task lifecycle (create/update/cancel/list), TTL, cleanup
+├── taskExecution.ts # Generic task executor with state management
+├── streaming.ts # SSE stream formatting, heartbeat, chunk/completion events
+├── routingLogger.ts # Routing decision logger (stats, history, retention)
+└── skills/
+ ├── smartRouting.ts # Smart routing skill (routes via /v1/chat/completions)
+ └── quotaManagement.ts # Quota management skill (natural-language quota queries)
+
+src/app/a2a/
+└── route.ts # Next.js API route handler (JSON-RPC 2.0 dispatch)
+
+open-sse/mcp-server/
+└── schemas/a2a.ts # Zod schemas (AgentCard, Task, JSON-RPC, SSE events)
+```
+
+---
+
+## Comparison: MCP vs A2A
+
+| Feature | MCP Server | A2A Server |
+| ----------------- | ---------------------------- | ------------------------------------------------- |
+| **Protocol** | Model Context Protocol | Agent-to-Agent Protocol v0.3 |
+| **Transport** | stdio / HTTP | HTTP (JSON-RPC 2.0) |
+| **Discovery** | Tool listing via MCP | `/.well-known/agent.json` |
+| **Granularity** | 16 individual tools | 2 high-level skills |
+| **Best for** | IDE agents (Cursor, VS Code) | Multi-agent systems (LangChain, CrewAI) |
+| **Streaming** | Not supported | SSE via `message/stream` |
+| **Task tracking** | No | Full lifecycle (submitted → completed) |
+| **Observability** | Audit log per tool call | Cost envelope + resilience trace + policy verdict |
+
+---
+
+## Licence
+
+Part of [OmniRoute](https://github.com/diegosouzapw/OmniRoute) — MIT License.
diff --git a/docs/i18n/da/CHANGELOG.md b/docs/i18n/da/CHANGELOG.md
index ea9a2c049c..bc247ceb7d 100644
--- a/docs/i18n/da/CHANGELOG.md
+++ b/docs/i18n/da/CHANGELOG.md
@@ -1,12 +1,92 @@
# Changelog (Dansk)
-🌐 **Languages:** 🇺🇸 [English](../../../CHANGELOG.md) · 🇪🇸 [es](../es/CHANGELOG.md) · 🇫🇷 [fr](../fr/CHANGELOG.md) · 🇩🇪 [de](../de/CHANGELOG.md) · 🇮🇹 [it](../it/CHANGELOG.md) · 🇷🇺 [ru](../ru/CHANGELOG.md) · 🇨🇳 [zh-CN](../zh-CN/CHANGELOG.md) · 🇯🇵 [ja](../ja/CHANGELOG.md) · 🇰🇷 [ko](../ko/CHANGELOG.md) · 🇸🇦 [ar](../ar/CHANGELOG.md) · 🇮🇳 [in](../in/CHANGELOG.md) · 🇹🇭 [th](../th/CHANGELOG.md) · 🇻🇳 [vi](../vi/CHANGELOG.md) · 🇮🇩 [id](../id/CHANGELOG.md) · 🇲🇾 [ms](../ms/CHANGELOG.md) · 🇳🇱 [nl](../nl/CHANGELOG.md) · 🇵🇱 [pl](../pl/CHANGELOG.md) · 🇸🇪 [sv](../sv/CHANGELOG.md) · 🇳🇴 [no](../no/CHANGELOG.md) · 🇩🇰 [da](../da/CHANGELOG.md) · 🇫🇮 [fi](../fi/CHANGELOG.md) · 🇵🇹 [pt](../pt/CHANGELOG.md) · 🇷🇴 [ro](../ro/CHANGELOG.md) · 🇭🇺 [hu](../hu/CHANGELOG.md) · 🇧🇬 [bg](../bg/CHANGELOG.md) · 🇸🇰 [sk](../sk/CHANGELOG.md) · 🇺🇦 [uk-UA](../uk-UA/CHANGELOG.md) · 🇮🇱 [he](../he/CHANGELOG.md) · 🇵🇭 [phi](../phi/CHANGELOG.md) · 🇧🇷 [pt-BR](../pt-BR/CHANGELOG.md)
+🌐 **Languages:** 🇺🇸 [English](../../../CHANGELOG.md) · 🇪🇸 [es](../es/CHANGELOG.md) · 🇫🇷 [fr](../fr/CHANGELOG.md) · 🇩🇪 [de](../de/CHANGELOG.md) · 🇮🇹 [it](../it/CHANGELOG.md) · 🇷🇺 [ru](../ru/CHANGELOG.md) · 🇨🇳 [zh-CN](../zh-CN/CHANGELOG.md) · 🇯🇵 [ja](../ja/CHANGELOG.md) · 🇰🇷 [ko](../ko/CHANGELOG.md) · 🇸🇦 [ar](../ar/CHANGELOG.md) · 🇮🇳 [in](../in/CHANGELOG.md) · 🇹🇭 [th](../th/CHANGELOG.md) · 🇻🇳 [vi](../vi/CHANGELOG.md) · 🇮🇩 [id](../id/CHANGELOG.md) · 🇲🇾 [ms](../ms/CHANGELOG.md) · 🇳🇱 [nl](../nl/CHANGELOG.md) · 🇵🇱 [pl](../pl/CHANGELOG.md) · 🇸🇪 [sv](../sv/CHANGELOG.md) · 🇳🇴 [no](../no/CHANGELOG.md) · 🇩🇰 [da](../da/CHANGELOG.md) · 🇫🇮 [fi](../fi/CHANGELOG.md) · 🇵🇹 [pt](../pt/CHANGELOG.md) · 🇷🇴 [ro](../ro/CHANGELOG.md) · 🇭🇺 [hu](../hu/CHANGELOG.md) · 🇧🇬 [bg](../bg/CHANGELOG.md) · 🇸🇰 [sk](../sk/CHANGELOG.md) · 🇺🇦 [uk-UA](../uk-UA/CHANGELOG.md) · 🇮🇱 [he](../he/CHANGELOG.md) · 🇵🇭 [phi](../phi/CHANGELOG.md) · 🇧🇷 [pt-BR](../pt-BR/CHANGELOG.md) · 🇨🇿 [cs](../cs/CHANGELOG.md)
---
-
## [Unreleased]
+### 🛠️ Maintenance
+
+- **AGENTS.md rewrite:** Condensed from 297→153 lines. Added build/lint/test commands (including single-test execution), code style guidelines (Prettier, TypeScript, ESLint, naming, imports, error handling, security), and trimmed verbose architecture tables for AI agent consumption.
+
+## [3.4.2] - 2026-04-01
+
+### 🐛 Bug Fixes
+
+- **CI Stabilization:** Fixed failing analytics/settings Playwright selectors and request assertions so GitHub Actions E2E runs pass reliably across localized UIs and switch-based controls.
+- **Deterministic Tests:** Removed date-sensitive quota fixtures from Copilot usage tests and aligned idempotency/model catalog tests with the merged runtime behavior.
+- **MCP Type Hardening:** Removed zero-budget explicit `any` regressions from the MCP server tool registration path, restoring the `check:any-budget:t11` workflow gate.
+
+### 🛠️ Maintenance
+
+- **Release Branch Integration:** Consolidated the active feature branches into `release/v3.4.2` on top of current `main` and validated the branch with lint, unit, coverage, build, and CI-mode E2E runs.
+
+## [3.4.1] - 2026-03-31
+
+> [!WARNING]
+> **BREAKING CHANGE: request logging, retention, and logging environment variables have been redesigned.**
+> On the first startup after upgrading, OmniRoute archives legacy request logs from `DATA_DIR/logs/`, legacy `DATA_DIR/call_logs/`, and `DATA_DIR/log.txt` into `DATA_DIR/log_archives/*.zip`, then removes the deprecated layout and switches to the new unified artifact format under `DATA_DIR/call_logs/`.
+
+### ✨ New Features
+
+- **.ENV Migration Utility:** Included `scripts/migrate-env.mjs` to seamlessly migrate `= 18 < 24 (recommended: 22 LTS)
+- **npm** 10+
+- **Git**
+
+### Clone & Install
+
+```bash
+git clone https://github.com/diegosouzapw/OmniRoute.git
+cd OmniRoute
+npm install
+```
+
+### Environment Variables
+
+```bash
+# Create your .env from the template
+cp .env.example .env
+
+# Generate required secrets
+echo "JWT_SECRET=$(openssl rand -base64 48)" >> .env
+echo "API_KEY_SECRET=$(openssl rand -hex 32)" >> .env
+```
+
+Key variables for development:
+
+| Variable | Development Default | Description |
+| ---------------------- | ------------------------ | --------------------- |
+| `PORT` | `20128` | Server port |
+| `NEXT_PUBLIC_BASE_URL` | `http://localhost:20128` | Base URL for frontend |
+| `JWT_SECRET` | (generate above) | JWT signing secret |
+| `INITIAL_PASSWORD` | `CHANGEME` | First login password |
+| `APP_LOG_LEVEL` | `info` | Log verbosity level |
+
+### Dashboard Settings
+
+The dashboard provides UI toggles for features that can also be configured via environment variables:
+
+| Setting Location | Toggle | Description |
+| ------------------- | ------------------ | ------------------------------ |
+| Settings → Advanced | Debug Mode | Enable debug request logs (UI) |
+| Settings → General | Sidebar Visibility | Show/hide sidebar sections |
+
+These settings are stored in the database and persist across restarts, overriding env var defaults when set.
+
+### Running Locally
+
+```bash
+# Development mode (hot reload)
+npm run dev
+
+# Production build
+npm run build
+npm run start
+
+# Common port configuration
+PORT=20128 NEXT_PUBLIC_BASE_URL=http://localhost:20128 npm run dev
+```
+
+Default URLs:
+
+- **Dashboard**: `http://localhost:20128/dashboard`
+- **API**: `http://localhost:20128/v1`
+
+---
+
+## Git Workflow
+
+> ⚠️ **NEVER commit directly to `main`.** Always use feature branches.
+
+```bash
+git checkout -b feat/your-feature-name
+# ... make changes ...
+git commit -m "feat: describe your change"
+git push -u origin feat/your-feature-name
+# Open a Pull Request on GitHub
+```
+
+### Branch Naming
+
+| Prefix | Purpose |
+| ----------- | ------------------------- |
+| `feat/` | New features |
+| `fix/` | Bug fixes |
+| `refactor/` | Code restructuring |
+| `docs/` | Documentation changes |
+| `test/` | Test additions/fixes |
+| `chore/` | Tooling, CI, dependencies |
+
+### Commit Messages
+
+Follow [Conventional Commits](https://www.conventionalcommits.org/):
+
+```
+feat: add circuit breaker for provider calls
+fix: resolve JWT secret validation edge case
+docs: update SECURITY.md with PII protection
+test: add observability unit tests
+refactor(db): consolidate rate limit tables
+```
+
+Scopes: `db`, `sse`, `oauth`, `dashboard`, `api`, `cli`, `docker`, `ci`, `mcp`, `a2a`, `memory`, `skills`.
+
+---
+
+## Running Tests
+
+```bash
+# All tests (unit + vitest + ecosystem + e2e)
+npm run test:all
+
+# Single test file (Node.js native test runner — most tests use this)
+node --import tsx/esm --test tests/unit/your-file.test.mjs
+
+# Vitest (MCP server, autoCombo, cache)
+npm run test:vitest
+
+# E2E tests (requires Playwright)
+npm run test:e2e
+
+# Protocol clients E2E (MCP transports, A2A)
+npm run test:protocols:e2e
+
+# Ecosystem compatibility tests
+npm run test:ecosystem
+
+# Coverage (55% min statements/lines/functions; 60% branches)
+npm run test:coverage
+npm run coverage:report
+
+# Lint + format check
+npm run lint
+npm run check
+```
+
+Coverage notes:
+
+- `npm run test:coverage` measures source coverage for the main unit test suite, excludes `tests/**`, and includes `open-sse/**`
+- `npm run coverage:report` prints the detailed file-by-file report from the latest coverage run
+- `npm run test:coverage:legacy` preserves the older metric for historical comparison
+- See `docs/COVERAGE_PLAN.md` for the phased coverage improvement roadmap
+
+Current test status: **122 unit test files** covering:
+
+- Provider translators and format conversion
+- Rate limiting, circuit breaker, and resilience
+- Semantic cache, idempotency, progress tracking
+- Database operations and schema (21 DB modules)
+- OAuth flows and authentication
+- API endpoint validation (Zod v4)
+- MCP server tools and scope enforcement
+- Memory and Skills systems
+
+---
+
+## Code Style
+
+- **ESLint** — Run `npm run lint` before committing
+- **Prettier** — Auto-formatted via `lint-staged` on commit (2 spaces, semicolons, double quotes, 100 char width, es5 trailing commas)
+- **TypeScript** — All `src/` code uses `.ts`/`.tsx`; `open-sse/` uses `.ts`/`.js`; document with TSDoc (`@param`, `@returns`, `@throws`)
+- **No `eval()`** — ESLint enforces `no-eval`, `no-implied-eval`, `no-new-func`
+- **Zod validation** — Use Zod v4 schemas for all API input validation
+- **Naming**: Files = camelCase/kebab-case, components = PascalCase, constants = UPPER_SNAKE
+
+---
+
+## Project Structure
+
+```
+src/ # TypeScript (.ts / .tsx)
+├── app/ # Next.js 16 App Router
+│ ├── (dashboard)/ # Dashboard pages (23 sections)
+│ ├── api/ # API routes (51 directories)
+│ └── login/ # Auth pages (.tsx)
+├── domain/ # Policy engine (policyEngine, comboResolver, costRules, etc.)
+├── lib/ # Core business logic (.ts)
+│ ├── a2a/ # Agent-to-Agent v0.3 protocol server
+│ ├── acp/ # Agent Communication Protocol registry
+│ ├── compliance/ # Compliance policy engine
+│ ├── db/ # SQLite database layer (21 modules + 16 migrations)
+│ ├── memory/ # Persistent conversational memory
+│ ├── oauth/ # OAuth providers, services, and utilities
+│ ├── skills/ # Extensible skill framework
+│ ├── usage/ # Usage tracking and cost calculation
+│ └── localDb.ts # Re-export layer only — never add logic here
+├── middleware/ # Request middleware (promptInjectionGuard)
+├── mitm/ # MITM proxy (cert, DNS, target routing)
+├── shared/
+│ ├── components/ # React components (.tsx)
+│ ├── constants/ # Provider definitions (60+), MCP scopes, routing strategies
+│ ├── utils/ # Circuit breaker, sanitizer, auth helpers
+│ └── validation/ # Zod v4 schemas
+└── sse/ # SSE proxy pipeline
+
+open-sse/ # @omniroute/open-sse workspace
+├── executors/ # 14 provider-specific request executors
+├── handlers/ # 11 request handlers (chat, responses, embeddings, images, etc.)
+├── mcp-server/ # MCP server (25 tools, 3 transports, 10 scopes)
+├── services/ # 36+ services (combo, autoCombo, rateLimitManager, etc.)
+├── translator/ # Format translators (OpenAI ↔ Claude ↔ Gemini ↔ Responses ↔ Ollama)
+├── transformer/ # Responses API transformer
+└── utils/ # 22 utility modules (stream, TLS, proxy, logging)
+
+electron/ # Electron desktop app (cross-platform)
+
+tests/
+├── unit/ # Node.js test runner (122 test files)
+├── integration/ # Integration tests
+├── e2e/ # Playwright tests
+├── security/ # Security tests
+├── translator/ # Translator-specific tests
+└── load/ # Load tests
+
+docs/ # Documentation
+├── ARCHITECTURE.md # System architecture
+├── API_REFERENCE.md # All endpoints
+├── USER_GUIDE.md # Provider setup, CLI integration
+├── TROUBLESHOOTING.md # Common issues
+├── MCP-SERVER.md # MCP server (25 tools)
+├── A2A-SERVER.md # A2A agent protocol
+├── AUTO-COMBO.md # Auto-combo engine
+├── CLI-TOOLS.md # CLI tools integration
+├── COVERAGE_PLAN.md # Test coverage improvement plan
+├── openapi.yaml # OpenAPI specification
+└── adr/ # Architecture Decision Records
+```
+
+---
+
+## Adding a New Provider
+
+### Step 1: Register Provider Constants
+
+Add to `src/shared/constants/providers.ts` — Zod-validated at module load.
+
+### Step 2: Add Executor (if custom logic needed)
+
+Create executor in `open-sse/executors/your-provider.ts` extending the base executor.
+
+### Step 3: Add Translator (if non-OpenAI format)
+
+Create request/response translators in `open-sse/translator/`.
+
+### Step 4: Add OAuth Config (if OAuth-based)
+
+Add OAuth credentials in `src/lib/oauth/constants/oauth.ts` and service in `src/lib/oauth/services/`.
+
+### Step 5: Register Models
+
+Add model definitions in `open-sse/config/providerRegistry.ts`.
+
+### Step 6: Add Tests
+
+Write unit tests in `tests/unit/` covering at minimum:
+
+- Provider registration
+- Request/response translation
+- Error handling
+
+---
+
+## Pull Request Checklist
+
+- [ ] Tests pass (`npm test`)
+- [ ] Linting passes (`npm run lint`)
+- [ ] Build succeeds (`npm run build`)
+- [ ] TypeScript types added for new public functions and interfaces
+- [ ] No hardcoded secrets or fallback values
+- [ ] All inputs validated with Zod schemas
+- [ ] CHANGELOG updated (if user-facing change)
+- [ ] Documentation updated (if applicable)
+
+---
+
+## Releasing
+
+Releases are managed via the `/generate-release` workflow. When a new GitHub Release is created, the package is **automatically published to npm** via GitHub Actions.
+
+---
+
+## Getting Help
+
+- **Architecture**: See [`docs/ARCHITECTURE.md`](docs/ARCHITECTURE.md)
+- **API Reference**: See [`docs/API_REFERENCE.md`](docs/API_REFERENCE.md)
+- **Issues**: [github.com/diegosouzapw/OmniRoute/issues](https://github.com/diegosouzapw/OmniRoute/issues)
+- **ADRs**: See `docs/adr/` for architectural decision records
diff --git a/docs/i18n/da/FEATURES.md b/docs/i18n/da/FEATURES.md
deleted file mode 100644
index 8714147c1e..0000000000
--- a/docs/i18n/da/FEATURES.md
+++ /dev/null
@@ -1,147 +0,0 @@
-# OmniRoute — Dashboard Features Gallery (Dansk)
-
-🌐 **Languages:** 🇺🇸 [English](../../../README.md) · 🇧🇷 [pt-BR](../pt-BR/README.md) · 🇪🇸 [es](../es/README.md) · 🇫🇷 [fr](../fr/README.md) · 🇩🇪 [de](../de/README.md) · 🇮🇹 [it](../it/README.md) · 🇷🇺 [ru](../ru/README.md) · 🇨🇳 [zh-CN](../zh-CN/README.md) · 🇯🇵 [ja](../ja/README.md) · 🇰🇷 [ko](../ko/README.md) · 🇸🇦 [ar](../ar/README.md) · 🇮🇳 [in](../in/README.md) · 🇹🇭 [th](../th/README.md) · 🇻🇳 [vi](../vi/README.md) · 🇮🇩 [id](../id/README.md) · 🇲🇾 [ms](../ms/README.md) · 🇳🇱 [nl](../nl/README.md) · 🇵🇱 [pl](../pl/README.md) · 🇸🇪 [sv](../sv/README.md) · 🇳🇴 [no](../no/README.md) · 🇩🇰 [da](../da/README.md) · 🇫🇮 [fi](../fi/README.md) · 🇵🇹 [pt](../pt/README.md) · 🇷🇴 [ro](../ro/README.md) · 🇭🇺 [hu](../hu/README.md) · 🇧🇬 [bg](../bg/README.md) · 🇸🇰 [sk](../sk/README.md) · 🇺🇦 [uk-UA](../uk-UA/README.md) · 🇮🇱 [he](../he/README.md) · 🇵🇭 [phi](../phi/README.md)
-
-> 🇺🇸 [English](../../../docs/FEATURES.md)
-
----
-
-Visual guide to every section of the OmniRoute dashboard.
-
----
-
-## 🔌 Providers
-
-Manage AI provider connections: OAuth providers (Claude Code, Codex, Gemini CLI), API key providers (Groq, DeepSeek, OpenRouter), and free providers (Qoder, Qwen, Kiro). Kiro accounts include credit balance tracking — remaining credits, total allowance, and renewal date visible in Dashboard → Usage.
-
-
-
----
-
-## 🎨 Combos
-
-Create model routing combos with 6 strategies: priority, weighted, round-robin, random, least-used, and cost-optimized. Each combo chains multiple models with automatic fallback and includes quick templates and readiness checks.
-
-
-
----
-
-## 📊 Analytics
-
-Comprehensive usage analytics with token consumption, cost estimates, activity heatmaps, weekly distribution charts, and per-provider breakdowns.
-
-
-
----
-
-## 🏥 System Health
-
-Real-time monitoring: uptime, memory, version, latency percentiles (p50/p95/p99), cache statistics, and provider circuit breaker states.
-
-
-
----
-
-## 🔧 Translator Playground
-
-Four modes for debugging API translations: **Playground** (format converter), **Chat Tester** (live requests), **Test Bench** (batch tests), and **Live Monitor** (real-time stream).
-
-
-
----
-
-## 🎮 Model Playground _(v2.0.9+)_
-
-Test any model directly from the dashboard. Select provider, model, and endpoint, write prompts with Monaco Editor, stream responses in real-time, abort mid-stream, and view timing metrics.
-
----
-
-## 🎨 Themes _(v2.0.5+)_
-
-Customizable color themes for the entire dashboard. Choose from 7 preset colors (Coral, Blue, Red, Green, Violet, Orange, Cyan) or create a custom theme by picking any hex color. Supports light, dark, and system mode.
-
----
-
-## ⚙️ Settings
-
-Comprehensive settings panel with tabs:
-
-- **General** — System storage, backup management (export/import database)
-- **Appearance** — Theme selector (dark/light/system), color theme presets and custom colors, health log visibility, sidebar item visibility controls
-- **Security** — API endpoint protection, custom provider blocking, IP filtering, session info
-- **Routing** — Model aliases, background task degradation
-- **Resilience** — Rate limit persistence, circuit breaker tuning
-- **Advanced** — Configuration overrides
-
-
-
----
-
-## 🔧 CLI Tools
-
-One-click configuration for AI coding tools: Claude Code, Codex CLI, Gemini CLI, OpenClaw, Kilo Code, Antigravity, Cline, Continue, Cursor, and Factory Droid. Features automated config apply/reset, connection profiles, and model mapping.
-
-
-
----
-
-## 🤖 CLI Agents _(v2.0.11+)_
-
-Dashboard for discovering and managing CLI agents. Shows a grid of 14 built-in agents (Codex, Claude, Goose, Gemini CLI, OpenClaw, Aider, OpenCode, Cline, Qwen Code, ForgeCode, Amazon Q, Open Interpreter, Cursor CLI, Warp) with:
-
-- **Installation status** — Installed / Not Found with version detection
-- **Protocol badges** — stdio, HTTP, etc.
-- **Custom agents** — Register any CLI tool via form (name, binary, version command, spawn args)
-- **CLI Fingerprint Matching** — Per-provider toggle to match native CLI request signatures, reducing ban risk while preserving proxy IP
-
----
-
-## 🖼️ Media _(v2.0.3+)_
-
-Generate images, videos, and music from the dashboard. Supports OpenAI, xAI, Together, Hyperbolic, SD WebUI, ComfyUI, AnimateDiff, Stable Audio Open, and MusicGen.
-
----
-
-## 📝 Request Logs
-
-Real-time request logging with filtering by provider, model, account, and API key. Shows status codes, token usage, latency, and response details.
-
-
-
----
-
-## 🌐 API Endpoint
-
-Your unified API endpoint with capability breakdown: Chat Completions, Responses API, Embeddings, Image Generation, Reranking, Audio Transcription, Text-to-Speech, Moderations, and registered API keys. Cloud proxy support for remote access.
-
-
-
----
-
-## 🔑 API Key Management
-
-Create, scope, and revoke API keys. Each key can be restricted to specific models/providers with full access or read-only permissions. Visual key management with usage tracking.
-
----
-
-## 📋 Audit Log
-
-Administrative action tracking with filtering by action type, actor, target, IP address, and timestamp. Full security event history.
-
----
-
-## 🖥️ Desktop Application
-
-Native Electron desktop app for Windows, macOS, and Linux. Run OmniRoute as a standalone application with system tray integration, offline support, auto-update, and one-click install.
-
-Key features:
-
-- Server readiness polling (no blank screen on cold start)
-- System tray with port management
-- Content Security Policy
-- Single-instance lock
-- Auto-update on restart
-- Platform-conditional UI (macOS traffic lights, Windows/Linux default titlebar)
-- Hardened Electron build packaging — symlinked `node_modules` in the standalone bundle is detected and rejected before packaging, preventing runtime dependency on the build machine (v2.5.5+)
-
-📖 See [`electron/README.md`](../electron/README.md) for full documentation.
diff --git a/docs/i18n/da/README.md b/docs/i18n/da/README.md
index c1f4b2f43a..84c2dba91a 100644
--- a/docs/i18n/da/README.md
+++ b/docs/i18n/da/README.md
@@ -1,13 +1,12 @@
# 🚀 OmniRoute — The Free AI Gateway (Dansk)
-🌐 **Languages:** 🇺🇸 [English](../../../README.md) · 🇪🇸 [es](../es/README.md) · 🇫🇷 [fr](../fr/README.md) · 🇩🇪 [de](../de/README.md) · 🇮🇹 [it](../it/README.md) · 🇷🇺 [ru](../ru/README.md) · 🇨🇳 [zh-CN](../zh-CN/README.md) · 🇯🇵 [ja](../ja/README.md) · 🇰🇷 [ko](../ko/README.md) · 🇸🇦 [ar](../ar/README.md) · 🇮🇳 [in](../in/README.md) · 🇹🇭 [th](../th/README.md) · 🇻🇳 [vi](../vi/README.md) · 🇮🇩 [id](../id/README.md) · 🇲🇾 [ms](../ms/README.md) · 🇳🇱 [nl](../nl/README.md) · 🇵🇱 [pl](../pl/README.md) · 🇸🇪 [sv](../sv/README.md) · 🇳🇴 [no](../no/README.md) · 🇩🇰 [da](../da/README.md) · 🇫🇮 [fi](../fi/README.md) · 🇵🇹 [pt](../pt/README.md) · 🇷🇴 [ro](../ro/README.md) · 🇭🇺 [hu](../hu/README.md) · 🇧🇬 [bg](../bg/README.md) · 🇸🇰 [sk](../sk/README.md) · 🇺🇦 [uk-UA](../uk-UA/README.md) · 🇮🇱 [he](../he/README.md) · 🇵🇭 [phi](../phi/README.md) · 🇧🇷 [pt-BR](../pt-BR/README.md)
+🌐 **Languages:** 🇺🇸 [English](../../../README.md) · 🇪🇸 [es](../es/README.md) · 🇫🇷 [fr](../fr/README.md) · 🇩🇪 [de](../de/README.md) · 🇮🇹 [it](../it/README.md) · 🇷🇺 [ru](../ru/README.md) · 🇨🇳 [zh-CN](../zh-CN/README.md) · 🇯🇵 [ja](../ja/README.md) · 🇰🇷 [ko](../ko/README.md) · 🇸🇦 [ar](../ar/README.md) · 🇮🇳 [in](../in/README.md) · 🇹🇭 [th](../th/README.md) · 🇻🇳 [vi](../vi/README.md) · 🇮🇩 [id](../id/README.md) · 🇲🇾 [ms](../ms/README.md) · 🇳🇱 [nl](../nl/README.md) · 🇵🇱 [pl](../pl/README.md) · 🇸🇪 [sv](../sv/README.md) · 🇳🇴 [no](../no/README.md) · 🇩🇰 [da](../da/README.md) · 🇫🇮 [fi](../fi/README.md) · 🇵🇹 [pt](../pt/README.md) · 🇷🇴 [ro](../ro/README.md) · 🇭🇺 [hu](../hu/README.md) · 🇧🇬 [bg](../bg/README.md) · 🇸🇰 [sk](../sk/README.md) · 🇺🇦 [uk-UA](../uk-UA/README.md) · 🇮🇱 [he](../he/README.md) · 🇵🇭 [phi](../phi/README.md) · 🇧🇷 [pt-BR](../pt-BR/README.md) · 🇨🇿 [cs](../cs/README.md)
---
-
### Never stop coding. Smart routing to **FREE & low-cost AI models** with automatic fallback.
-_Your universal API proxy — one endpoint, 67+ providers, zero downtime. Now with **MCP & A2A** agent orchestration._
+_Your universal API proxy — one endpoint, 60+ providers, zero downtime. Now with **MCP Server (25 tools)**, **A2A Protocol**, **Memory/Skills Systems** & **Electron Desktop App**._
**Chat Completions • Embeddings • Image Generation • Video • Music • Audio • Reranking • **Web Search** • MCP Server • A2A Protocol • 100% TypeScript**
@@ -47,15 +46,17 @@ _Your universal API proxy — one endpoint, 67+ providers, zero downtime. Now wi
> - `APP_LOG_FILE_PATH`
> - `APP_LOG_MAX_FILE_SIZE`
> - `APP_LOG_RETENTION_DAYS`
+> - `APP_LOG_MAX_FILES`
> - `APP_LOG_LEVEL`
> - `APP_LOG_FORMAT`
> - `CALL_LOG_RETENTION_DAYS`
+> - `CALL_LOG_MAX_ENTRIES`
>
> For release details and upgrade notes, see the [CHANGELOG](CHANGELOG.md).
---
-## 🆕 What's New in v3.0.0
+## 🆕 What's New
> **Upgrading from v2.9.5?** — See the [full CHANGELOG](CHANGELOG.md#300--2026-03-22-release-candidate--not-yet-merged-to-main) for all changes.
@@ -275,7 +276,7 @@ Developers pay $20–200/month for Claude Pro, Codex Pro, or GitHub Copilot. Eve
- **Smart 4-Tier Fallback** — If subscription quota runs out, automatically redirects to API Key → Cheap → Free with zero manual intervention
- **Real-Time Quota Tracking** — Shows token consumption in real-time with reset countdown (5h, daily, weekly)
- **Multi-Account Support** — Multiple accounts per provider with auto round-robin — when one runs out, switches to the next
-- **Custom Combos** — Customizable fallback chains with 6 balancing strategies (fill-first, round-robin, P2C, random, least-used, cost-optimized)
+- **Custom Combos** — Customizable fallback chains with 9 balancing strategies (priority, weighted, fill-first, round-robin, P2C, random, least-used, cost-optimized, strict-random)
- **Codex Business Quotas** — Business/Team workspace quota monitoring directly in the dashboard
@@ -287,7 +288,7 @@ OpenAI uses one format, Claude (Anthropic) uses another, Gemini yet another. If
**How OmniRoute solves it:**
-- **Unified Endpoint** — A single `http://localhost:20128/v1` serves as proxy for all 67+ providers
+- **Unified Endpoint** — A single `http://localhost:20128/v1` serves as proxy for all 60+ providers
- **Format Translation** — Automatic and transparent: OpenAI ↔ Claude ↔ Gemini ↔ Responses API
- **Response Sanitization** — Strips non-standard fields (`x_groq`, `usage_breakdown`, `service_tier`) that break OpenAI SDK v1.83+
- **Role Normalization** — Converts `developer` → `system` for non-OpenAI providers; `system` → `user` for GLM/ERNIE
@@ -373,7 +374,7 @@ Developers use Cursor, Claude Code, Codex CLI, OpenClaw, Gemini CLI, Kilo Code..
- **CLI Tools Dashboard** — Dedicated page with one-click setup for Claude Code, Codex CLI, OpenClaw, Kilo Code, Antigravity, Cline
- **GitHub Copilot Config Generator** — Generates `chatLanguageModels.json` for VS Code with bulk model selection
- **Onboarding Wizard** — Guided 4-step setup for first-time users
-- **One endpoint, all models** — Configure `http://localhost:20128/v1` once, access 67+ providers
+- **One endpoint, all models** — Configure `http://localhost:20128/v1` once, access 60+ providers
@@ -420,7 +421,7 @@ When a call fails, the dev doesn't know if it was a rate limit, expired token, w
- **SQLite Proxy Logs** — Persistent logs that survive server restarts
- **Translator Playground** — 4 debugging modes: Playground (format translation), Chat Tester (round-trip), Test Bench (batch), Live Monitor (real-time)
- **Request Telemetry** — p50/p95/p99 latency + X-Request-Id tracing
-- **File-Based Logging with Rotation** — Console interceptor captures everything to JSON log with size-based rotation
+- **File-Based Logging with Rotation** — App logs rotate by size, retention days, and archive count; call log artifacts rotate by retention days and file count
- **System Info Report** — `npm run system-info` generates `system-info.txt` with your full environment (Node version, OmniRoute version, OS, CLI tools, Docker/PM2 status). Attach it when reporting issues for instant triage.
@@ -515,7 +516,7 @@ Developers who want all responses in a specific language, with a specific tone,
- **System Prompt Injection** — Global prompt applied to all requests
- **Thinking Budget Validation** — Reasoning token allocation control per request (passthrough, auto, custom, adaptive)
-- **6 Routing Strategies** — Global strategies that determine how requests are distributed
+- **9 Routing Strategies** — Global strategies that determine how requests are distributed
- **Wildcard Router** — `provider/*` patterns route dynamically to any provider
- **Combo Enable/Disable Toggle** — Toggle combos directly from the dashboard
- **Provider Toggle** — Enable/disable all connections for a provider with one click
@@ -582,7 +583,7 @@ Different clients should have least-privilege access to tool categories.
**How OmniRoute solves it:**
-- 9 granular MCP scopes for controlled tool access
+- 10 granular MCP scopes for controlled tool access
- Scope enforcement and visibility in MCP management UI
- Safe default posture for operational tooling
@@ -1326,19 +1327,19 @@ OmniRoute v2.0 is built as an operational platform, not just a relay proxy.
### 🤖 Agent & Protocol Operations (v2.0)
-| Feature | What It Does |
-| ------------------------------------- | -------------------------------------------------------------------------------------------------- |
-| 🔧 **MCP Server (16 tools)** | IDE/agent tools via 3 transports: stdio, SSE (`/api/mcp/sse`), Streamable HTTP (`/api/mcp/stream`) |
-| 🤝 **A2A Server (JSON-RPC + SSE)** | Agent-to-agent task execution with sync and streaming flows |
-| 🧭 **Consolidated Endpoints Page** | Tabbed management page with Endpoint Proxy, MCP, A2A, and API Endpoints tabs |
-| 🎚️ **Service Enable/Disable Toggles** | ON/OFF switches for MCP and A2A with settings persistence (default: OFF) |
-| 🛰️ **MCP Runtime Heartbeat** | Real process status (pid, uptime, heartbeat age, transport, scope mode) |
-| 📋 **MCP Audit Trail** | Filterable audit logs with success/failure and key attribution |
-| 🔐 **MCP Scope Enforcement** | 9 granular scope permissions for controlled tool access |
-| 📡 **A2A Task Lifecycle Management** | List/filter tasks, inspect events/artifacts, cancel running tasks |
-| 📋 **Agent Card Discovery** | `/.well-known/agent.json` for client auto-discovery |
-| 🧪 **Protocol E2E Test Harness** | Real MCP SDK + A2A client flows in `test:protocols:e2e` |
-| ⚙️ **Operational Controls** | Switch combo, apply resilience profiles, reset breakers from one control surface |
+| Feature | What It Does |
+| ------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------- |
+| 🔧 **MCP Server (25 tools)** | IDE/agent tools via 3 transports: stdio, SSE (`/api/mcp/sse`), Streamable HTTP (`/api/mcp/stream`). 18 core + 3 memory + 4 skill tools |
+| 🤝 **A2A Server (JSON-RPC + SSE)** | Agent-to-agent task execution with sync and streaming flows |
+| 🧭 **Consolidated Endpoints Page** | Tabbed management page with Endpoint Proxy, MCP, A2A, and API Endpoints tabs |
+| 🎚️ **Service Enable/Disable Toggles** | ON/OFF switches for MCP and A2A with settings persistence (default: OFF) |
+| 🛰️ **MCP Runtime Heartbeat** | Real process status (pid, uptime, heartbeat age, transport, scope mode) |
+| 📋 **MCP Audit Trail** | Filterable audit logs with success/failure and key attribution |
+| 🔐 **MCP Scope Enforcement** | 10 granular scope permissions for controlled tool access |
+| 📡 **A2A Task Lifecycle Management** | List/filter tasks, inspect events/artifacts, cancel running tasks |
+| 📋 **Agent Card Discovery** | `/.well-known/agent.json` for client auto-discovery |
+| 🧪 **Protocol E2E Test Harness** | Real MCP SDK + A2A client flows in `test:protocols:e2e` |
+| ⚙️ **Operational Controls** | Switch combo, apply resilience profiles, reset breakers from one control surface |
### 🧠 Routing & Intelligence
@@ -1349,7 +1350,7 @@ OmniRoute v2.0 is built as an operational platform, not just a relay proxy.
| 🔄 **Format Translation** | OpenAI ↔ Claude ↔ Gemini ↔ Responses with schema-safe conversions |
| 👥 **Multi-Account Support** | Multiple accounts per provider with intelligent selection |
| 🔄 **Auto Token Refresh** | OAuth tokens refresh automatically with retry |
-| 🎨 **Custom Combos** | 6 balancing strategies + fallback chain control |
+| 🎨 **Custom Combos** | 9 balancing strategies + fallback chain control |
| 🌐 **Wildcard Router** | `provider/*` dynamic routing |
| 🧠 **Thinking Budget Controls** | Passthrough, auto, custom, and adaptive reasoning limits |
| 🔀 **Model Aliases** | Built-in + custom model aliasing and migration safety |
@@ -1950,6 +1951,7 @@ opencode
- Request artifacts are written to `DATA_DIR/call_logs/` as one JSON file per request
- Enable pipeline capture from Dashboard → Logs → Request Logs if you need detailed per-stage payloads
- Set `APP_LOG_TO_FILE=true` if you also want application console logs in `logs/application/app.log`
+- Adjust `APP_LOG_MAX_FILE_SIZE`, `APP_LOG_RETENTION_DAYS`, `APP_LOG_MAX_FILES`, and `CALL_LOG_MAX_ENTRIES` as needed
**Connection test shows "Invalid" for OpenAI-compatible providers**
diff --git a/docs/i18n/da/RELEASE_CHECKLIST.md b/docs/i18n/da/RELEASE_CHECKLIST.md
deleted file mode 100644
index 903e812c3f..0000000000
--- a/docs/i18n/da/RELEASE_CHECKLIST.md
+++ /dev/null
@@ -1,37 +0,0 @@
-🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/RELEASE_CHECKLIST.md) · 🇪🇸 [es](../es/RELEASE_CHECKLIST.md) · 🇫🇷 [fr](../fr/RELEASE_CHECKLIST.md) · 🇩🇪 [de](../de/RELEASE_CHECKLIST.md) · 🇮🇹 [it](../it/RELEASE_CHECKLIST.md) · 🇷🇺 [ru](../ru/RELEASE_CHECKLIST.md) · 🇨🇳 [zh-CN](../zh-CN/RELEASE_CHECKLIST.md) · 🇯🇵 [ja](../ja/RELEASE_CHECKLIST.md) · 🇰🇷 [ko](../ko/RELEASE_CHECKLIST.md) · 🇸🇦 [ar](../ar/RELEASE_CHECKLIST.md) · 🇮🇳 [in](../in/RELEASE_CHECKLIST.md) · 🇹🇭 [th](../th/RELEASE_CHECKLIST.md) · 🇻🇳 [vi](../vi/RELEASE_CHECKLIST.md) · 🇮🇩 [id](../id/RELEASE_CHECKLIST.md) · 🇲🇾 [ms](../ms/RELEASE_CHECKLIST.md) · 🇳🇱 [nl](../nl/RELEASE_CHECKLIST.md) · 🇵🇱 [pl](../pl/RELEASE_CHECKLIST.md) · 🇸🇪 [sv](../sv/RELEASE_CHECKLIST.md) · 🇳🇴 [no](../no/RELEASE_CHECKLIST.md) · 🇩🇰 [da](../da/RELEASE_CHECKLIST.md) · 🇫🇮 [fi](../fi/RELEASE_CHECKLIST.md) · 🇵🇹 [pt](../pt/RELEASE_CHECKLIST.md) · 🇷🇴 [ro](../ro/RELEASE_CHECKLIST.md) · 🇭🇺 [hu](../hu/RELEASE_CHECKLIST.md) · 🇧🇬 [bg](../bg/RELEASE_CHECKLIST.md) · 🇸🇰 [sk](../sk/RELEASE_CHECKLIST.md) · 🇺🇦 [uk-UA](../uk-UA/RELEASE_CHECKLIST.md) · 🇮🇱 [he](../he/RELEASE_CHECKLIST.md) · 🇵🇭 [phi](../phi/RELEASE_CHECKLIST.md)
-
----
-
-# Release Checklist
-
-Use this checklist before tagging or publishing a new OmniRoute release.
-
-## Version and Changelog
-
-1. Bump `package.json` version (`x.y.z`) in the release branch.
-2. Move release notes from `## [Unreleased]` in `CHANGELOG.md` to a dated section:
- - `## [x.y.z] — YYYY-MM-DD`
-3. Keep `## [Unreleased]` as the first changelog section for upcoming work.
-4. Ensure the latest semver section in `CHANGELOG.md` equals `package.json` version.
-
-## API Docs
-
-1. Update `docs/openapi.yaml`:
- - `info.version` must equal `package.json` version.
-2. Validate endpoint examples if API contracts changed.
-
-## Runtime Docs
-
-1. Review `docs/ARCHITECTURE.md` for storage/runtime drift.
-2. Review `docs/TROUBLESHOOTING.md` for env var and operational drift.
-3. Update localized docs if source docs changed significantly.
-
-## Automated Check
-
-Run the sync guard locally before opening PR:
-
-```bash
-npm run check:docs-sync
-```
-
-CI also runs this check in `.github/workflows/ci.yml` (lint job).
diff --git a/docs/i18n/da/SECURITY.md b/docs/i18n/da/SECURITY.md
new file mode 100644
index 0000000000..e1e7c83cea
--- /dev/null
+++ b/docs/i18n/da/SECURITY.md
@@ -0,0 +1,179 @@
+# Security Policy (Dansk)
+
+🌐 **Languages:** 🇺🇸 [English](../../../SECURITY.md) · 🇪🇸 [es](../es/SECURITY.md) · 🇫🇷 [fr](../fr/SECURITY.md) · 🇩🇪 [de](../de/SECURITY.md) · 🇮🇹 [it](../it/SECURITY.md) · 🇷🇺 [ru](../ru/SECURITY.md) · 🇨🇳 [zh-CN](../zh-CN/SECURITY.md) · 🇯🇵 [ja](../ja/SECURITY.md) · 🇰🇷 [ko](../ko/SECURITY.md) · 🇸🇦 [ar](../ar/SECURITY.md) · 🇮🇳 [in](../in/SECURITY.md) · 🇹🇭 [th](../th/SECURITY.md) · 🇻🇳 [vi](../vi/SECURITY.md) · 🇮🇩 [id](../id/SECURITY.md) · 🇲🇾 [ms](../ms/SECURITY.md) · 🇳🇱 [nl](../nl/SECURITY.md) · 🇵🇱 [pl](../pl/SECURITY.md) · 🇸🇪 [sv](../sv/SECURITY.md) · 🇳🇴 [no](../no/SECURITY.md) · 🇩🇰 [da](../da/SECURITY.md) · 🇫🇮 [fi](../fi/SECURITY.md) · 🇵🇹 [pt](../pt/SECURITY.md) · 🇷🇴 [ro](../ro/SECURITY.md) · 🇭🇺 [hu](../hu/SECURITY.md) · 🇧🇬 [bg](../bg/SECURITY.md) · 🇸🇰 [sk](../sk/SECURITY.md) · 🇺🇦 [uk-UA](../uk-UA/SECURITY.md) · 🇮🇱 [he](../he/SECURITY.md) · 🇵🇭 [phi](../phi/SECURITY.md) · 🇧🇷 [pt-BR](../pt-BR/SECURITY.md) · 🇨🇿 [cs](../cs/SECURITY.md)
+
+---
+
+## Reporting Vulnerabilities
+
+If you discover a security vulnerability in OmniRoute, please report it responsibly:
+
+1. **DO NOT** open a public GitHub issue
+2. Use [GitHub Security Advisories](https://github.com/diegosouzapw/OmniRoute/security/advisories/new)
+3. Include: description, reproduction steps, and potential impact
+
+## Response Timeline
+
+| Stage | Target |
+| ------------------- | --------------------------- |
+| Acknowledgment | 48 hours |
+| Triage & Assessment | 5 business days |
+| Patch Release | 14 business days (critical) |
+
+## Supported Versions
+
+| Version | Support Status |
+| ------- | -------------- |
+| 3.4.x | ✅ Active |
+| 3.0.x | ✅ Security |
+| < 3.0.0 | ❌ Unsupported |
+
+---
+
+## Security Architecture
+
+OmniRoute implements a multi-layered security model:
+
+```
+Request → CORS → API Key Auth → Prompt Injection Guard → Input Sanitizer → Rate Limiter → Circuit Breaker → Provider
+```
+
+### 🔐 Authentication & Authorization
+
+| Feature | Implementation |
+| -------------------- | ---------------------------------------------------------- |
+| **Dashboard Login** | Password-based auth with JWT tokens (HttpOnly cookies) |
+| **API Key Auth** | HMAC-signed keys with CRC validation |
+| **OAuth 2.0 + PKCE** | Secure provider auth (Claude, Codex, Gemini, Cursor, etc.) |
+| **Token Refresh** | Automatic OAuth token refresh before expiry |
+| **Secure Cookies** | `AUTH_COOKIE_SECURE=true` for HTTPS environments |
+| **MCP Scopes** | 10 granular scopes for MCP tool access control |
+
+### 🛡️ Encryption at Rest
+
+All sensitive data stored in SQLite is encrypted using **AES-256-GCM** with scrypt key derivation:
+
+- API keys, access tokens, refresh tokens, and ID tokens
+- Versioned format: `enc:v1:::`
+- Passthrough mode (plaintext) when `STORAGE_ENCRYPTION_KEY` is not set
+
+```bash
+# Generate encryption key:
+STORAGE_ENCRYPTION_KEY=$(openssl rand -hex 32)
+```
+
+### 🧠 Prompt Injection Guard
+
+Middleware that detects and blocks prompt injection attacks in LLM requests:
+
+| Pattern Type | Severity | Example |
+| ------------------- | -------- | ---------------------------------------------- |
+| System Override | High | "ignore all previous instructions" |
+| Role Hijack | High | "you are now DAN, you can do anything" |
+| Delimiter Injection | Medium | Encoded separators to break context boundaries |
+| DAN/Jailbreak | High | Known jailbreak prompt patterns |
+| Instruction Leak | Medium | "show me your system prompt" |
+
+Configure via dashboard (Settings → Security) or `.env`:
+
+```env
+INPUT_SANITIZER_ENABLED=true
+INPUT_SANITIZER_MODE=block # warn | block | redact
+```
+
+### 🔒 PII Redaction
+
+Automatic detection and optional redaction of personally identifiable information:
+
+| PII Type | Pattern | Replacement |
+| ------------- | --------------------- | ------------------ |
+| Email | `user@domain.com` | `[EMAIL_REDACTED]` |
+| CPF (Brazil) | `123.456.789-00` | `[CPF_REDACTED]` |
+| CNPJ (Brazil) | `12.345.678/0001-00` | `[CNPJ_REDACTED]` |
+| Credit Card | `4111-1111-1111-1111` | `[CC_REDACTED]` |
+| Phone | `+55 11 99999-9999` | `[PHONE_REDACTED]` |
+| SSN (US) | `123-45-6789` | `[SSN_REDACTED]` |
+
+```env
+PII_REDACTION_ENABLED=true
+```
+
+### 🌐 Network Security
+
+| Feature | Description |
+| ------------------------ | ---------------------------------------------------------------- |
+| **CORS** | Configurable origin control (`CORS_ORIGIN` env var, default `*`) |
+| **IP Filtering** | Allowlist/blocklist IP ranges in dashboard |
+| **Rate Limiting** | Per-provider rate limits with automatic backoff |
+| **Anti-Thundering Herd** | Mutex + per-connection locking prevents cascading 502s |
+| **TLS Fingerprint** | Browser-like TLS fingerprint spoofing to reduce bot detection |
+| **CLI Fingerprint** | Per-provider header/body ordering to match native CLI signatures |
+
+### 🔌 Resilience & Availability
+
+| Feature | Description |
+| ----------------------- | ------------------------------------------------------------------ |
+| **Circuit Breaker** | 3-state (Closed → Open → Half-Open) per provider, SQLite-persisted |
+| **Request Idempotency** | 5-second dedup window for duplicate requests |
+| **Exponential Backoff** | Automatic retry with increasing delays |
+| **Health Dashboard** | Real-time provider health monitoring |
+
+### 📋 Compliance
+
+| Feature | Description |
+| ------------------ | ----------------------------------------------------------- |
+| **Log Retention** | Automatic cleanup after `CALL_LOG_RETENTION_DAYS` |
+| **No-Log Opt-out** | Per API key `noLog` flag disables request logging |
+| **Audit Log** | Administrative actions tracked in `audit_log` table |
+| **MCP Audit** | SQLite-backed audit logging for all MCP tool calls |
+| **Zod Validation** | All API inputs validated with Zod v4 schemas at module load |
+
+---
+
+## Required Environment Variables
+
+All secrets must be set before starting the server. The server will **fail fast** if they are missing or weak.
+
+```bash
+# REQUIRED — server will not start without these:
+JWT_SECRET=$(openssl rand -base64 48) # min 32 chars
+API_KEY_SECRET=$(openssl rand -hex 32) # min 16 chars
+
+# RECOMMENDED — enables encryption at rest:
+STORAGE_ENCRYPTION_KEY=$(openssl rand -hex 32)
+```
+
+The server actively rejects known-weak values like `changeme`, `secret`, or `password`.
+
+---
+
+## Docker Security
+
+- Use non-root user in production
+- Mount secrets as read-only volumes
+- Never copy `.env` files into Docker images
+- Use `.dockerignore` to exclude sensitive files
+- Set `AUTH_COOKIE_SECURE=true` when behind HTTPS
+
+```bash
+docker run -d \
+ --name omniroute \
+ --restart unless-stopped \
+ --read-only \
+ -p 20128:20128 \
+ -v omniroute-data:/app/data \
+ -e JWT_SECRET="$(openssl rand -base64 48)" \
+ -e API_KEY_SECRET="$(openssl rand -hex 32)" \
+ -e STORAGE_ENCRYPTION_KEY="$(openssl rand -hex 32)" \
+ diegosouzapw/omniroute:latest
+```
+
+---
+
+## Dependencies
+
+- Run `npm audit` regularly
+- Keep dependencies updated
+- The project uses `husky` + `lint-staged` for pre-commit checks
+- CI pipeline runs ESLint security rules on every push
+- Provider constants validated at module load via Zod (`src/shared/validation/providerSchema.ts`)
diff --git a/docs/i18n/de/A2A-SERVER.md b/docs/i18n/da/docs/A2A-SERVER.md
similarity index 77%
rename from docs/i18n/de/A2A-SERVER.md
rename to docs/i18n/da/docs/A2A-SERVER.md
index 01531ff482..f850c3fc0b 100644
--- a/docs/i18n/de/A2A-SERVER.md
+++ b/docs/i18n/da/docs/A2A-SERVER.md
@@ -1,9 +1,9 @@
-🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/A2A-SERVER.md) · 🇪🇸 [es](../es/A2A-SERVER.md) · 🇫🇷 [fr](../fr/A2A-SERVER.md) · 🇩🇪 [de](../de/A2A-SERVER.md) · 🇮🇹 [it](../it/A2A-SERVER.md) · 🇷🇺 [ru](../ru/A2A-SERVER.md) · 🇨🇳 [zh-CN](../zh-CN/A2A-SERVER.md) · 🇯🇵 [ja](../ja/A2A-SERVER.md) · 🇰🇷 [ko](../ko/A2A-SERVER.md) · 🇸🇦 [ar](../ar/A2A-SERVER.md) · 🇮🇳 [in](../in/A2A-SERVER.md) · 🇹🇭 [th](../th/A2A-SERVER.md) · 🇻🇳 [vi](../vi/A2A-SERVER.md) · 🇮🇩 [id](../id/A2A-SERVER.md) · 🇲🇾 [ms](../ms/A2A-SERVER.md) · 🇳🇱 [nl](../nl/A2A-SERVER.md) · 🇵🇱 [pl](../pl/A2A-SERVER.md) · 🇸🇪 [sv](../sv/A2A-SERVER.md) · 🇳🇴 [no](../no/A2A-SERVER.md) · 🇩🇰 [da](../da/A2A-SERVER.md) · 🇫🇮 [fi](../fi/A2A-SERVER.md) · 🇵🇹 [pt](../pt/A2A-SERVER.md) · 🇷🇴 [ro](../ro/A2A-SERVER.md) · 🇭🇺 [hu](../hu/A2A-SERVER.md) · 🇧🇬 [bg](../bg/A2A-SERVER.md) · 🇸🇰 [sk](../sk/A2A-SERVER.md) · 🇺🇦 [uk-UA](../uk-UA/A2A-SERVER.md) · 🇮🇱 [he](../he/A2A-SERVER.md) · 🇵🇭 [phi](../phi/A2A-SERVER.md)
+# OmniRoute A2A Server Documentation (Dansk)
+
+🌐 **Languages:** 🇺🇸 [English](../../../../docs/A2A-SERVER.md) · 🇪🇸 [es](../../es/docs/A2A-SERVER.md) · 🇫🇷 [fr](../../fr/docs/A2A-SERVER.md) · 🇩🇪 [de](../../de/docs/A2A-SERVER.md) · 🇮🇹 [it](../../it/docs/A2A-SERVER.md) · 🇷🇺 [ru](../../ru/docs/A2A-SERVER.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/A2A-SERVER.md) · 🇯🇵 [ja](../../ja/docs/A2A-SERVER.md) · 🇰🇷 [ko](../../ko/docs/A2A-SERVER.md) · 🇸🇦 [ar](../../ar/docs/A2A-SERVER.md) · 🇮🇳 [in](../../in/docs/A2A-SERVER.md) · 🇹🇭 [th](../../th/docs/A2A-SERVER.md) · 🇻🇳 [vi](../../vi/docs/A2A-SERVER.md) · 🇮🇩 [id](../../id/docs/A2A-SERVER.md) · 🇲🇾 [ms](../../ms/docs/A2A-SERVER.md) · 🇳🇱 [nl](../../nl/docs/A2A-SERVER.md) · 🇵🇱 [pl](../../pl/docs/A2A-SERVER.md) · 🇸🇪 [sv](../../sv/docs/A2A-SERVER.md) · 🇳🇴 [no](../../no/docs/A2A-SERVER.md) · 🇩🇰 [da](../../da/docs/A2A-SERVER.md) · 🇫🇮 [fi](../../fi/docs/A2A-SERVER.md) · 🇵🇹 [pt](../../pt/docs/A2A-SERVER.md) · 🇷🇴 [ro](../../ro/docs/A2A-SERVER.md) · 🇭🇺 [hu](../../hu/docs/A2A-SERVER.md) · 🇧🇬 [bg](../../bg/docs/A2A-SERVER.md) · 🇸🇰 [sk](../../sk/docs/A2A-SERVER.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/A2A-SERVER.md) · 🇮🇱 [he](../../he/docs/A2A-SERVER.md) · 🇵🇭 [phi](../../phi/docs/A2A-SERVER.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/A2A-SERVER.md) · 🇨🇿 [cs](../../cs/docs/A2A-SERVER.md)
---
-# OmniRoute A2A Server Documentation
-
> Agent-to-Agent Protocol v0.3 — OmniRoute as an intelligent routing agent
## Agent Discovery
diff --git a/docs/i18n/ar/API_REFERENCE.md b/docs/i18n/da/docs/API_REFERENCE.md
similarity index 74%
rename from docs/i18n/ar/API_REFERENCE.md
rename to docs/i18n/da/docs/API_REFERENCE.md
index b878605221..69377fc6b7 100644
--- a/docs/i18n/ar/API_REFERENCE.md
+++ b/docs/i18n/da/docs/API_REFERENCE.md
@@ -1,11 +1,9 @@
-🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/API_REFERENCE.md) · 🇪🇸 [es](../es/API_REFERENCE.md) · 🇫🇷 [fr](../fr/API_REFERENCE.md) · 🇩🇪 [de](../de/API_REFERENCE.md) · 🇮🇹 [it](../it/API_REFERENCE.md) · 🇷🇺 [ru](../ru/API_REFERENCE.md) · 🇨🇳 [zh-CN](../zh-CN/API_REFERENCE.md) · 🇯🇵 [ja](../ja/API_REFERENCE.md) · 🇰🇷 [ko](../ko/API_REFERENCE.md) · 🇸🇦 [ar](../ar/API_REFERENCE.md) · 🇮🇳 [in](../in/API_REFERENCE.md) · 🇹🇭 [th](../th/API_REFERENCE.md) · 🇻🇳 [vi](../vi/API_REFERENCE.md) · 🇮🇩 [id](../id/API_REFERENCE.md) · 🇲🇾 [ms](../ms/API_REFERENCE.md) · 🇳🇱 [nl](../nl/API_REFERENCE.md) · 🇵🇱 [pl](../pl/API_REFERENCE.md) · 🇸🇪 [sv](../sv/API_REFERENCE.md) · 🇳🇴 [no](../no/API_REFERENCE.md) · 🇩🇰 [da](../da/API_REFERENCE.md) · 🇫🇮 [fi](../fi/API_REFERENCE.md) · 🇵🇹 [pt](../pt/API_REFERENCE.md) · 🇷🇴 [ro](../ro/API_REFERENCE.md) · 🇭🇺 [hu](../hu/API_REFERENCE.md) · 🇧🇬 [bg](../bg/API_REFERENCE.md) · 🇸🇰 [sk](../sk/API_REFERENCE.md) · 🇺🇦 [uk-UA](../uk-UA/API_REFERENCE.md) · 🇮🇱 [he](../he/API_REFERENCE.md) · 🇵🇭 [phi](../phi/API_REFERENCE.md)
+# API Reference (Dansk)
+
+🌐 **Languages:** 🇺🇸 [English](../../../../docs/API_REFERENCE.md) · 🇪🇸 [es](../../es/docs/API_REFERENCE.md) · 🇫🇷 [fr](../../fr/docs/API_REFERENCE.md) · 🇩🇪 [de](../../de/docs/API_REFERENCE.md) · 🇮🇹 [it](../../it/docs/API_REFERENCE.md) · 🇷🇺 [ru](../../ru/docs/API_REFERENCE.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/API_REFERENCE.md) · 🇯🇵 [ja](../../ja/docs/API_REFERENCE.md) · 🇰🇷 [ko](../../ko/docs/API_REFERENCE.md) · 🇸🇦 [ar](../../ar/docs/API_REFERENCE.md) · 🇮🇳 [in](../../in/docs/API_REFERENCE.md) · 🇹🇭 [th](../../th/docs/API_REFERENCE.md) · 🇻🇳 [vi](../../vi/docs/API_REFERENCE.md) · 🇮🇩 [id](../../id/docs/API_REFERENCE.md) · 🇲🇾 [ms](../../ms/docs/API_REFERENCE.md) · 🇳🇱 [nl](../../nl/docs/API_REFERENCE.md) · 🇵🇱 [pl](../../pl/docs/API_REFERENCE.md) · 🇸🇪 [sv](../../sv/docs/API_REFERENCE.md) · 🇳🇴 [no](../../no/docs/API_REFERENCE.md) · 🇩🇰 [da](../../da/docs/API_REFERENCE.md) · 🇫🇮 [fi](../../fi/docs/API_REFERENCE.md) · 🇵🇹 [pt](../../pt/docs/API_REFERENCE.md) · 🇷🇴 [ro](../../ro/docs/API_REFERENCE.md) · 🇭🇺 [hu](../../hu/docs/API_REFERENCE.md) · 🇧🇬 [bg](../../bg/docs/API_REFERENCE.md) · 🇸🇰 [sk](../../sk/docs/API_REFERENCE.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/API_REFERENCE.md) · 🇮🇱 [he](../../he/docs/API_REFERENCE.md) · 🇵🇭 [phi](../../phi/docs/API_REFERENCE.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/API_REFERENCE.md) · 🇨🇿 [cs](../../cs/docs/API_REFERENCE.md)
---
-# API Reference
-
-🌐 **Languages:** 🇺🇸 [English](API_REFERENCE.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/API_REFERENCE.md) | 🇪🇸 [Español](i18n/es/API_REFERENCE.md) | 🇫🇷 [Français](i18n/fr/API_REFERENCE.md) | 🇮🇹 [Italiano](i18n/it/API_REFERENCE.md) | 🇷🇺 [Русский](i18n/ru/API_REFERENCE.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/API_REFERENCE.md) | 🇩🇪 [Deutsch](i18n/de/API_REFERENCE.md) | 🇮🇳 [हिन्दी](i18n/in/API_REFERENCE.md) | 🇹🇭 [ไทย](i18n/th/API_REFERENCE.md) | 🇺🇦 [Українська](i18n/uk-UA/API_REFERENCE.md) | 🇸🇦 [العربية](i18n/ar/API_REFERENCE.md) | 🇯🇵 [日本語](i18n/ja/API_REFERENCE.md) | 🇻🇳 [Tiếng Việt](i18n/vi/API_REFERENCE.md) | 🇧🇬 [Български](i18n/bg/API_REFERENCE.md) | 🇩🇰 [Dansk](i18n/da/API_REFERENCE.md) | 🇫🇮 [Suomi](i18n/fi/API_REFERENCE.md) | 🇮🇱 [עברית](i18n/he/API_REFERENCE.md) | 🇭🇺 [Magyar](i18n/hu/API_REFERENCE.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/API_REFERENCE.md) | 🇰🇷 [한국어](i18n/ko/API_REFERENCE.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/API_REFERENCE.md) | 🇳🇱 [Nederlands](i18n/nl/API_REFERENCE.md) | 🇳🇴 [Norsk](i18n/no/API_REFERENCE.md) | 🇵🇹 [Português (Portugal)](i18n/pt/API_REFERENCE.md) | 🇷🇴 [Română](i18n/ro/API_REFERENCE.md) | 🇵🇱 [Polski](i18n/pl/API_REFERENCE.md) | 🇸🇰 [Slovenčina](i18n/sk/API_REFERENCE.md) | 🇸🇪 [Svenska](i18n/sv/API_REFERENCE.md) | 🇵🇭 [Filipino](i18n/phi/API_REFERENCE.md)
-
Complete reference for all OmniRoute API endpoints.
---
@@ -42,15 +40,20 @@ Content-Type: application/json
### Custom Headers
-| Header | Direction | Description |
-| ------------------------ | --------- | --------------------------------- |
-| `X-OmniRoute-No-Cache` | Request | Set to `true` to bypass cache |
-| `X-OmniRoute-Progress` | Request | Set to `true` for progress events |
-| `Idempotency-Key` | Request | Dedup key (5s window) |
-| `X-Request-Id` | Request | Alternative dedup key |
-| `X-OmniRoute-Cache` | Response | `HIT` or `MISS` (non-streaming) |
-| `X-OmniRoute-Idempotent` | Response | `true` if deduplicated |
-| `X-OmniRoute-Progress` | Response | `enabled` if progress tracking on |
+| Header | Direction | Description |
+| ------------------------ | --------- | ------------------------------------------------ |
+| `X-OmniRoute-No-Cache` | Request | Set to `true` to bypass cache |
+| `X-OmniRoute-Progress` | Request | Set to `true` for progress events |
+| `X-Session-Id` | Request | Sticky session key for external session affinity |
+| `x_session_id` | Request | Underscore variant also accepted (direct HTTP) |
+| `Idempotency-Key` | Request | Dedup key (5s window) |
+| `X-Request-Id` | Request | Alternative dedup key |
+| `X-OmniRoute-Cache` | Response | `HIT` or `MISS` (non-streaming) |
+| `X-OmniRoute-Idempotent` | Response | `true` if deduplicated |
+| `X-OmniRoute-Progress` | Response | `enabled` if progress tracking on |
+| `X-OmniRoute-Session-Id` | Response | Effective session ID used by OmniRoute |
+
+> Nginx note: if you rely on underscore headers (for example `x_session_id`), enable `underscores_in_headers on;`.
---
@@ -141,10 +144,10 @@ The provider prefix is auto-added if missing. Mismatched models return `400`.
```bash
# Get cache stats
-GET /api/cache
+GET /api/cache/stats
# Clear all caches
-DELETE /api/cache
+DELETE /api/cache/stats
```
Response example:
@@ -215,23 +218,23 @@ Response example:
### Settings
-| Endpoint | Method | Description |
-| ------------------------------- | ------- | ---------------------- |
-| `/api/settings` | GET/PUT | General settings |
-| `/api/settings/proxy` | GET/PUT | Network proxy config |
-| `/api/settings/proxy/test` | POST | Test proxy connection |
-| `/api/settings/ip-filter` | GET/PUT | IP allowlist/blocklist |
-| `/api/settings/thinking-budget` | GET/PUT | Reasoning token budget |
-| `/api/settings/system-prompt` | GET/PUT | Global system prompt |
+| Endpoint | Method | Description |
+| ------------------------------- | ------------- | ---------------------- |
+| `/api/settings` | GET/PUT/PATCH | General settings |
+| `/api/settings/proxy` | GET/PUT | Network proxy config |
+| `/api/settings/proxy/test` | POST | Test proxy connection |
+| `/api/settings/ip-filter` | GET/PUT | IP allowlist/blocklist |
+| `/api/settings/thinking-budget` | GET/PUT | Reasoning token budget |
+| `/api/settings/system-prompt` | GET/PUT | Global system prompt |
### Monitoring
-| Endpoint | Method | Description |
-| ------------------------ | ---------- | ----------------------- |
-| `/api/sessions` | GET | Active session tracking |
-| `/api/rate-limits` | GET | Per-account rate limits |
-| `/api/monitoring/health` | GET | Health check |
-| `/api/cache` | GET/DELETE | Cache stats / clear |
+| Endpoint | Method | Description |
+| ------------------------ | ---------- | ---------------------------------------------------------------------------------------------------- |
+| `/api/sessions` | GET | Active session tracking |
+| `/api/rate-limits` | GET | Per-account rate limits |
+| `/api/monitoring/health` | GET | Health check + provider summary (`catalogCount`, `configuredCount`, `activeCount`, `monitoredCount`) |
+| `/api/cache/stats` | GET/DELETE | Cache stats / clear |
### Backup & Export/Import
@@ -252,6 +255,13 @@ Response example:
| `/api/sync/initialize` | POST | Initialize sync |
| `/api/cloud/*` | Various | Cloud management |
+### Tunnels
+
+| Endpoint | Method | Description |
+| -------------------------- | ------ | ----------------------------------------------------------------------- |
+| `/api/tunnels/cloudflared` | GET | Read Cloudflare Quick Tunnel install/runtime status for the dashboard |
+| `/api/tunnels/cloudflared` | POST | Enable or disable the Cloudflare Quick Tunnel (`action=enable/disable`) |
+
### CLI Tools
| Endpoint | Method | Description |
@@ -276,12 +286,12 @@ GET response includes `agents[]` (id, name, binary, version, installed, protocol
### Resilience & Rate Limits
-| Endpoint | Method | Description |
-| ----------------------- | ------- | ------------------------------- |
-| `/api/resilience` | GET/PUT | Get/update resilience profiles |
-| `/api/resilience/reset` | POST | Reset circuit breakers |
-| `/api/rate-limits` | GET | Per-account rate limit status |
-| `/api/rate-limit` | GET | Global rate limit configuration |
+| Endpoint | Method | Description |
+| ----------------------- | --------- | ------------------------------- |
+| `/api/resilience` | GET/PATCH | Get/update resilience profiles |
+| `/api/resilience/reset` | POST | Reset circuit breakers |
+| `/api/rate-limits` | GET | Per-account rate limit status |
+| `/api/rate-limit` | GET | Global rate limit configuration |
### Evals
diff --git a/docs/i18n/ar/ARCHITECTURE.md b/docs/i18n/da/docs/ARCHITECTURE.md
similarity index 89%
rename from docs/i18n/ar/ARCHITECTURE.md
rename to docs/i18n/da/docs/ARCHITECTURE.md
index 4ea06a29f2..9812e24ae0 100644
--- a/docs/i18n/ar/ARCHITECTURE.md
+++ b/docs/i18n/da/docs/ARCHITECTURE.md
@@ -1,12 +1,10 @@
-🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/ARCHITECTURE.md) · 🇪🇸 [es](../es/ARCHITECTURE.md) · 🇫🇷 [fr](../fr/ARCHITECTURE.md) · 🇩🇪 [de](../de/ARCHITECTURE.md) · 🇮🇹 [it](../it/ARCHITECTURE.md) · 🇷🇺 [ru](../ru/ARCHITECTURE.md) · 🇨🇳 [zh-CN](../zh-CN/ARCHITECTURE.md) · 🇯🇵 [ja](../ja/ARCHITECTURE.md) · 🇰🇷 [ko](../ko/ARCHITECTURE.md) · 🇸🇦 [ar](../ar/ARCHITECTURE.md) · 🇮🇳 [in](../in/ARCHITECTURE.md) · 🇹🇭 [th](../th/ARCHITECTURE.md) · 🇻🇳 [vi](../vi/ARCHITECTURE.md) · 🇮🇩 [id](../id/ARCHITECTURE.md) · 🇲🇾 [ms](../ms/ARCHITECTURE.md) · 🇳🇱 [nl](../nl/ARCHITECTURE.md) · 🇵🇱 [pl](../pl/ARCHITECTURE.md) · 🇸🇪 [sv](../sv/ARCHITECTURE.md) · 🇳🇴 [no](../no/ARCHITECTURE.md) · 🇩🇰 [da](../da/ARCHITECTURE.md) · 🇫🇮 [fi](../fi/ARCHITECTURE.md) · 🇵🇹 [pt](../pt/ARCHITECTURE.md) · 🇷🇴 [ro](../ro/ARCHITECTURE.md) · 🇭🇺 [hu](../hu/ARCHITECTURE.md) · 🇧🇬 [bg](../bg/ARCHITECTURE.md) · 🇸🇰 [sk](../sk/ARCHITECTURE.md) · 🇺🇦 [uk-UA](../uk-UA/ARCHITECTURE.md) · 🇮🇱 [he](../he/ARCHITECTURE.md) · 🇵🇭 [phi](../phi/ARCHITECTURE.md)
+# OmniRoute Architecture (Dansk)
+
+🌐 **Languages:** 🇺🇸 [English](../../../../docs/ARCHITECTURE.md) · 🇪🇸 [es](../../es/docs/ARCHITECTURE.md) · 🇫🇷 [fr](../../fr/docs/ARCHITECTURE.md) · 🇩🇪 [de](../../de/docs/ARCHITECTURE.md) · 🇮🇹 [it](../../it/docs/ARCHITECTURE.md) · 🇷🇺 [ru](../../ru/docs/ARCHITECTURE.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/ARCHITECTURE.md) · 🇯🇵 [ja](../../ja/docs/ARCHITECTURE.md) · 🇰🇷 [ko](../../ko/docs/ARCHITECTURE.md) · 🇸🇦 [ar](../../ar/docs/ARCHITECTURE.md) · 🇮🇳 [in](../../in/docs/ARCHITECTURE.md) · 🇹🇭 [th](../../th/docs/ARCHITECTURE.md) · 🇻🇳 [vi](../../vi/docs/ARCHITECTURE.md) · 🇮🇩 [id](../../id/docs/ARCHITECTURE.md) · 🇲🇾 [ms](../../ms/docs/ARCHITECTURE.md) · 🇳🇱 [nl](../../nl/docs/ARCHITECTURE.md) · 🇵🇱 [pl](../../pl/docs/ARCHITECTURE.md) · 🇸🇪 [sv](../../sv/docs/ARCHITECTURE.md) · 🇳🇴 [no](../../no/docs/ARCHITECTURE.md) · 🇩🇰 [da](../../da/docs/ARCHITECTURE.md) · 🇫🇮 [fi](../../fi/docs/ARCHITECTURE.md) · 🇵🇹 [pt](../../pt/docs/ARCHITECTURE.md) · 🇷🇴 [ro](../../ro/docs/ARCHITECTURE.md) · 🇭🇺 [hu](../../hu/docs/ARCHITECTURE.md) · 🇧🇬 [bg](../../bg/docs/ARCHITECTURE.md) · 🇸🇰 [sk](../../sk/docs/ARCHITECTURE.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/ARCHITECTURE.md) · 🇮🇱 [he](../../he/docs/ARCHITECTURE.md) · 🇵🇭 [phi](../../phi/docs/ARCHITECTURE.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/ARCHITECTURE.md) · 🇨🇿 [cs](../../cs/docs/ARCHITECTURE.md)
---
-# OmniRoute Architecture
-
-🌐 **Languages:** 🇺🇸 [English](ARCHITECTURE.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/ARCHITECTURE.md) | 🇪🇸 [Español](i18n/es/ARCHITECTURE.md) | 🇫🇷 [Français](i18n/fr/ARCHITECTURE.md) | 🇮🇹 [Italiano](i18n/it/ARCHITECTURE.md) | 🇷🇺 [Русский](i18n/ru/ARCHITECTURE.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/ARCHITECTURE.md) | 🇩🇪 [Deutsch](i18n/de/ARCHITECTURE.md) | 🇮🇳 [हिन्दी](i18n/in/ARCHITECTURE.md) | 🇹🇭 [ไทย](i18n/th/ARCHITECTURE.md) | 🇺🇦 [Українська](i18n/uk-UA/ARCHITECTURE.md) | 🇸🇦 [العربية](i18n/ar/ARCHITECTURE.md) | 🇯🇵 [日本語](i18n/ja/ARCHITECTURE.md) | 🇻🇳 [Tiếng Việt](i18n/vi/ARCHITECTURE.md) | 🇧🇬 [Български](i18n/bg/ARCHITECTURE.md) | 🇩🇰 [Dansk](i18n/da/ARCHITECTURE.md) | 🇫🇮 [Suomi](i18n/fi/ARCHITECTURE.md) | 🇮🇱 [עברית](i18n/he/ARCHITECTURE.md) | 🇭🇺 [Magyar](i18n/hu/ARCHITECTURE.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/ARCHITECTURE.md) | 🇰🇷 [한국어](i18n/ko/ARCHITECTURE.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/ARCHITECTURE.md) | 🇳🇱 [Nederlands](i18n/nl/ARCHITECTURE.md) | 🇳🇴 [Norsk](i18n/no/ARCHITECTURE.md) | 🇵🇹 [Português (Portugal)](i18n/pt/ARCHITECTURE.md) | 🇷🇴 [Română](i18n/ro/ARCHITECTURE.md) | 🇵🇱 [Polski](i18n/pl/ARCHITECTURE.md) | 🇸🇰 [Slovenčina](i18n/sk/ARCHITECTURE.md) | 🇸🇪 [Svenska](i18n/sv/ARCHITECTURE.md) | 🇵🇭 [Filipino](i18n/phi/ARCHITECTURE.md)
-
-_Last updated: 2026-03-04_
+_Last updated: 2026-03-28_
## Executive Summary
@@ -69,6 +67,26 @@ Primary runtime model:
- Provider SLA/control plane outside local process
- External CLI binaries themselves (Claude CLI, Codex CLI, etc.)
+## Dashboard Surface (Current)
+
+Main pages under `src/app/(dashboard)/dashboard/`:
+
+- `/dashboard` — quick start + provider overview
+- `/dashboard/endpoint` — endpoint proxy + MCP + A2A + API endpoint tabs
+- `/dashboard/providers` — provider connections and credentials
+- `/dashboard/combos` — combo strategies, templates, model routing rules
+- `/dashboard/costs` — cost aggregation and pricing visibility
+- `/dashboard/analytics` — usage analytics and evaluations
+- `/dashboard/limits` — quota/rate controls
+- `/dashboard/cli-tools` — CLI onboarding, runtime detection, config generation
+- `/dashboard/agents` — detected ACP agents + custom agent registration
+- `/dashboard/media` — image/video/music playground
+- `/dashboard/search-tools` — search provider testing and history
+- `/dashboard/health` — uptime, circuit breakers, rate limits
+- `/dashboard/logs` — request/proxy/audit/console logs
+- `/dashboard/settings` — system settings tabs (general, routing, combo defaults, etc.)
+- `/dashboard/api-manager` — API key lifecycle and model permissions
+
## High-Level System Context
```mermaid
@@ -258,8 +276,9 @@ Domain State DB (SQLite):
## 5) Cloud Sync
-- Scheduler init: `src/lib/initCloudSync.ts`, `src/shared/services/initializeCloudSync.ts`
+- Scheduler init: `src/lib/initCloudSync.ts`, `src/shared/services/initializeCloudSync.ts`, `src/shared/services/modelSyncScheduler.ts`
- Periodic task: `src/shared/services/cloudSyncScheduler.ts`
+- Periodic task: `src/shared/services/modelSyncScheduler.ts`
- Control route: `src/app/api/sync/cloud/route.ts`
## Request Lifecycle (`/v1/chat/completions`)
@@ -339,7 +358,7 @@ flowchart TD
Q -- No --> R[Return all unavailable]
```
-Fallback decisions are driven by `open-sse/services/accountFallback.ts` using status codes and error-message heuristics.
+Fallback decisions are driven by `open-sse/services/accountFallback.ts` using status codes and error-message heuristics. Combo routing adds one extra guard: provider-scoped 400s such as upstream content-block and role-validation failures are treated as model-local failures so later combo targets can still run.
## OAuth Onboarding and Token Refresh Lifecycle
@@ -669,25 +688,25 @@ Additional processing layers in the translation pipeline:
## Supported API Endpoints
-| Endpoint | Format | Handler |
-| -------------------------------------------------- | ------------------ | ---------------------------------------------------- |
-| `POST /v1/chat/completions` | OpenAI Chat | `src/sse/handlers/chat.ts` |
-| `POST /v1/messages` | Claude Messages | Same handler (auto-detected) |
-| `POST /v1/responses` | OpenAI Responses | `open-sse/handlers/responsesHandler.ts` |
-| `POST /v1/embeddings` | OpenAI Embeddings | `open-sse/handlers/embeddings.ts` |
-| `GET /v1/embeddings` | Model listing | API route |
-| `POST /v1/images/generations` | OpenAI Images | `open-sse/handlers/imageGeneration.ts` |
-| `GET /v1/images/generations` | Model listing | API route |
-| `POST /v1/providers/{provider}/chat/completions` | OpenAI Chat | Dedicated per-provider with model validation |
-| `POST /v1/providers/{provider}/embeddings` | OpenAI Embeddings | Dedicated per-provider with model validation |
-| `POST /v1/providers/{provider}/images/generations` | OpenAI Images | Dedicated per-provider with model validation |
-| `POST /v1/messages/count_tokens` | Claude Token Count | API route |
-| `GET /v1/models` | OpenAI Models list | API route (chat + embedding + image + custom models) |
-| `GET /api/models/catalog` | Catalog | All models grouped by provider + type |
-| `POST /v1beta/models/*:streamGenerateContent` | Gemini native | API route |
-| `GET/PUT/DELETE /api/settings/proxy` | Proxy Config | Network proxy configuration |
-| `POST /api/settings/proxy/test` | Proxy Connectivity | Proxy health/connectivity test endpoint |
-| `GET/POST/DELETE /api/provider-models` | Custom Models | Custom model management per provider |
+| Endpoint | Format | Handler |
+| -------------------------------------------------- | ------------------ | ------------------------------------------------------------------- |
+| `POST /v1/chat/completions` | OpenAI Chat | `src/sse/handlers/chat.ts` |
+| `POST /v1/messages` | Claude Messages | Same handler (auto-detected) |
+| `POST /v1/responses` | OpenAI Responses | `open-sse/handlers/responsesHandler.ts` |
+| `POST /v1/embeddings` | OpenAI Embeddings | `open-sse/handlers/embeddings.ts` |
+| `GET /v1/embeddings` | Model listing | API route |
+| `POST /v1/images/generations` | OpenAI Images | `open-sse/handlers/imageGeneration.ts` |
+| `GET /v1/images/generations` | Model listing | API route |
+| `POST /v1/providers/{provider}/chat/completions` | OpenAI Chat | Dedicated per-provider with model validation |
+| `POST /v1/providers/{provider}/embeddings` | OpenAI Embeddings | Dedicated per-provider with model validation |
+| `POST /v1/providers/{provider}/images/generations` | OpenAI Images | Dedicated per-provider with model validation |
+| `POST /v1/messages/count_tokens` | Claude Token Count | API route |
+| `GET /v1/models` | OpenAI Models list | API route (chat + embedding + image + custom models) |
+| `GET /api/models/catalog` | Catalog | All models grouped by provider + type |
+| `POST /v1beta/models/*:streamGenerateContent` | Gemini native | API route |
+| `GET/PUT/DELETE /api/settings/proxy` | Proxy Config | Network proxy configuration |
+| `POST /api/settings/proxy/test` | Proxy Connectivity | Proxy health/connectivity test endpoint |
+| `GET/POST/DELETE /api/provider-models` | Provider Models | Provider model metadata backing custom and managed available models |
## Bypass Handler
@@ -739,10 +758,18 @@ Runtime visibility sources:
- console logs from `src/sse/utils/logger.ts`
- per-request usage aggregates in SQLite (`usage_history`, `call_logs`, `proxy_logs`)
+- four-stage detailed payload captures in SQLite (`request_detail_logs`) when `settings.detailed_logs_enabled=true`
- textual request status log in `log.txt` (optional/compat)
- optional deep request/translation logs under `logs/` when `ENABLE_REQUEST_LOGS=true`
- dashboard usage endpoints (`/api/usage/*`) for UI consumption
+Detailed request payload capture stores up to four JSON payload stages per routed call:
+
+- raw request received from the client
+- translated request actually sent upstream
+- provider response reconstructed as JSON; streamed responses are compacted to the final summary plus stream metadata
+- final client response returned by OmniRoute; streamed responses are stored in the same compact summary form
+
## Security-Sensitive Boundaries
- JWT secret (`JWT_SECRET`) secures dashboard session cookie verification/signing
diff --git a/docs/i18n/bg/AUTO-COMBO.md b/docs/i18n/da/docs/AUTO-COMBO.md
similarity index 65%
rename from docs/i18n/bg/AUTO-COMBO.md
rename to docs/i18n/da/docs/AUTO-COMBO.md
index 2166e41dff..257c960f41 100644
--- a/docs/i18n/bg/AUTO-COMBO.md
+++ b/docs/i18n/da/docs/AUTO-COMBO.md
@@ -1,9 +1,9 @@
-🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/AUTO-COMBO.md) · 🇪🇸 [es](../es/AUTO-COMBO.md) · 🇫🇷 [fr](../fr/AUTO-COMBO.md) · 🇩🇪 [de](../de/AUTO-COMBO.md) · 🇮🇹 [it](../it/AUTO-COMBO.md) · 🇷🇺 [ru](../ru/AUTO-COMBO.md) · 🇨🇳 [zh-CN](../zh-CN/AUTO-COMBO.md) · 🇯🇵 [ja](../ja/AUTO-COMBO.md) · 🇰🇷 [ko](../ko/AUTO-COMBO.md) · 🇸🇦 [ar](../ar/AUTO-COMBO.md) · 🇮🇳 [in](../in/AUTO-COMBO.md) · 🇹🇭 [th](../th/AUTO-COMBO.md) · 🇻🇳 [vi](../vi/AUTO-COMBO.md) · 🇮🇩 [id](../id/AUTO-COMBO.md) · 🇲🇾 [ms](../ms/AUTO-COMBO.md) · 🇳🇱 [nl](../nl/AUTO-COMBO.md) · 🇵🇱 [pl](../pl/AUTO-COMBO.md) · 🇸🇪 [sv](../sv/AUTO-COMBO.md) · 🇳🇴 [no](../no/AUTO-COMBO.md) · 🇩🇰 [da](../da/AUTO-COMBO.md) · 🇫🇮 [fi](../fi/AUTO-COMBO.md) · 🇵🇹 [pt](../pt/AUTO-COMBO.md) · 🇷🇴 [ro](../ro/AUTO-COMBO.md) · 🇭🇺 [hu](../hu/AUTO-COMBO.md) · 🇧🇬 [bg](../bg/AUTO-COMBO.md) · 🇸🇰 [sk](../sk/AUTO-COMBO.md) · 🇺🇦 [uk-UA](../uk-UA/AUTO-COMBO.md) · 🇮🇱 [he](../he/AUTO-COMBO.md) · 🇵🇭 [phi](../phi/AUTO-COMBO.md)
+# OmniRoute Auto-Combo Engine (Dansk)
+
+🌐 **Languages:** 🇺🇸 [English](../../../../docs/AUTO-COMBO.md) · 🇪🇸 [es](../../es/docs/AUTO-COMBO.md) · 🇫🇷 [fr](../../fr/docs/AUTO-COMBO.md) · 🇩🇪 [de](../../de/docs/AUTO-COMBO.md) · 🇮🇹 [it](../../it/docs/AUTO-COMBO.md) · 🇷🇺 [ru](../../ru/docs/AUTO-COMBO.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/AUTO-COMBO.md) · 🇯🇵 [ja](../../ja/docs/AUTO-COMBO.md) · 🇰🇷 [ko](../../ko/docs/AUTO-COMBO.md) · 🇸🇦 [ar](../../ar/docs/AUTO-COMBO.md) · 🇮🇳 [in](../../in/docs/AUTO-COMBO.md) · 🇹🇭 [th](../../th/docs/AUTO-COMBO.md) · 🇻🇳 [vi](../../vi/docs/AUTO-COMBO.md) · 🇮🇩 [id](../../id/docs/AUTO-COMBO.md) · 🇲🇾 [ms](../../ms/docs/AUTO-COMBO.md) · 🇳🇱 [nl](../../nl/docs/AUTO-COMBO.md) · 🇵🇱 [pl](../../pl/docs/AUTO-COMBO.md) · 🇸🇪 [sv](../../sv/docs/AUTO-COMBO.md) · 🇳🇴 [no](../../no/docs/AUTO-COMBO.md) · 🇩🇰 [da](../../da/docs/AUTO-COMBO.md) · 🇫🇮 [fi](../../fi/docs/AUTO-COMBO.md) · 🇵🇹 [pt](../../pt/docs/AUTO-COMBO.md) · 🇷🇴 [ro](../../ro/docs/AUTO-COMBO.md) · 🇭🇺 [hu](../../hu/docs/AUTO-COMBO.md) · 🇧🇬 [bg](../../bg/docs/AUTO-COMBO.md) · 🇸🇰 [sk](../../sk/docs/AUTO-COMBO.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/AUTO-COMBO.md) · 🇮🇱 [he](../../he/docs/AUTO-COMBO.md) · 🇵🇭 [phi](../../phi/docs/AUTO-COMBO.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/AUTO-COMBO.md) · 🇨🇿 [cs](../../cs/docs/AUTO-COMBO.md)
---
-# OmniRoute Auto-Combo Engine
-
> Self-managing model chains with adaptive scoring
## How It Works
diff --git a/docs/i18n/de/CLI-TOOLS.md b/docs/i18n/da/docs/CLI-TOOLS.md
similarity index 66%
rename from docs/i18n/de/CLI-TOOLS.md
rename to docs/i18n/da/docs/CLI-TOOLS.md
index 523fd2254d..b9946a5c32 100644
--- a/docs/i18n/de/CLI-TOOLS.md
+++ b/docs/i18n/da/docs/CLI-TOOLS.md
@@ -1,8 +1,8 @@
-🌐 **Languages:** 🇺🇸 [English](../../CLI-TOOLS.md) · 🇧🇷 [pt-BR](../pt-BR/CLI-TOOLS.md) · 🇪🇸 [es](../es/CLI-TOOLS.md) · 🇫🇷 [fr](../fr/CLI-TOOLS.md) · 🇩🇪 [de](../de/CLI-TOOLS.md) · 🇮🇹 [it](../it/CLI-TOOLS.md) · 🇷🇺 [ru](../ru/CLI-TOOLS.md) · 🇨🇳 [zh-CN](../zh-CN/CLI-TOOLS.md) · 🇯🇵 [ja](../ja/CLI-TOOLS.md) · 🇰🇷 [ko](../ko/CLI-TOOLS.md) · 🇸🇦 [ar](../ar/CLI-TOOLS.md)
+# CLI Tools Setup Guide — OmniRoute (Dansk)
-# CLI-Tools Einrichtungsanleitung — OmniRoute
+🌐 **Languages:** 🇺🇸 [English](../../../../docs/CLI-TOOLS.md) · 🇪🇸 [es](../../es/docs/CLI-TOOLS.md) · 🇫🇷 [fr](../../fr/docs/CLI-TOOLS.md) · 🇩🇪 [de](../../de/docs/CLI-TOOLS.md) · 🇮🇹 [it](../../it/docs/CLI-TOOLS.md) · 🇷🇺 [ru](../../ru/docs/CLI-TOOLS.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/CLI-TOOLS.md) · 🇯🇵 [ja](../../ja/docs/CLI-TOOLS.md) · 🇰🇷 [ko](../../ko/docs/CLI-TOOLS.md) · 🇸🇦 [ar](../../ar/docs/CLI-TOOLS.md) · 🇮🇳 [in](../../in/docs/CLI-TOOLS.md) · 🇹🇭 [th](../../th/docs/CLI-TOOLS.md) · 🇻🇳 [vi](../../vi/docs/CLI-TOOLS.md) · 🇮🇩 [id](../../id/docs/CLI-TOOLS.md) · 🇲🇾 [ms](../../ms/docs/CLI-TOOLS.md) · 🇳🇱 [nl](../../nl/docs/CLI-TOOLS.md) · 🇵🇱 [pl](../../pl/docs/CLI-TOOLS.md) · 🇸🇪 [sv](../../sv/docs/CLI-TOOLS.md) · 🇳🇴 [no](../../no/docs/CLI-TOOLS.md) · 🇩🇰 [da](../../da/docs/CLI-TOOLS.md) · 🇫🇮 [fi](../../fi/docs/CLI-TOOLS.md) · 🇵🇹 [pt](../../pt/docs/CLI-TOOLS.md) · 🇷🇴 [ro](../../ro/docs/CLI-TOOLS.md) · 🇭🇺 [hu](../../hu/docs/CLI-TOOLS.md) · 🇧🇬 [bg](../../bg/docs/CLI-TOOLS.md) · 🇸🇰 [sk](../../sk/docs/CLI-TOOLS.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/CLI-TOOLS.md) · 🇮🇱 [he](../../he/docs/CLI-TOOLS.md) · 🇵🇭 [phi](../../phi/docs/CLI-TOOLS.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/CLI-TOOLS.md) · 🇨🇿 [cs](../../cs/docs/CLI-TOOLS.md)
-Diese Anleitung erklärt, wie alle unterstützten AI-CLI-Tools installiert und konfiguriert werden, um **OmniRoute** als einheitlichen Backend zu verwenden.
+---
This guide explains how to install and configure all supported AI coding CLI tools
to use **OmniRoute** as the unified backend, giving you centralized key management,
@@ -13,7 +13,7 @@ cost tracking, model switching, and request logging across every tool.
## How It Works
```
-Claude / Codex / Gemini CLI / OpenCode / Cline / KiloCode / Continue / Kiro CLI
+Claude / Codex / OpenCode / Cline / KiloCode / Continue / Kiro / Cursor / Copilot
│
▼ (all point to OmniRoute)
http://YOUR_SERVER:20128/v1
@@ -31,21 +31,38 @@ Claude / Codex / Gemini CLI / OpenCode / Cline / KiloCode / Continue / Kiro CLI
---
-## Supported Tools
+## Supported Tools (Dashboard Source of Truth)
-| Tool | Command | Type | Install Method |
-| ---------------- | ------------------- | ----------------- | -------------- |
-| **Claude Code** | `claude` | CLI | npm |
-| **OpenAI Codex** | `codex` | CLI | npm |
-| **Gemini CLI** | `gemini` | CLI | npm |
-| **OpenCode** | `opencode` | CLI | npm |
-| **Cline** | `cline` | CLI + VS Code ext | npm |
-| **KiloCode** | `kilocode` / `kilo` | CLI + VS Code ext | npm |
-| **Continue** | guide-based | VS Code ext | VS Code |
-| **Kiro CLI** | `kiro-cli` | CLI | curl installer |
-| **Cursor** | `cursor` | Desktop app | Download |
-| **Droid** | web-based | Built-in agent | OmniRoute |
-| **OpenClaw** | web-based | Built-in agent | OmniRoute |
+The dashboard cards in `/dashboard/cli-tools` are generated from `src/shared/constants/cliTools.ts`.
+Current list (v3.0.0-rc.16):
+
+| Tool | ID | Command | Setup Mode | Install Method |
+| ------------------ | ------------- | ---------- | ---------- | -------------- |
+| **Claude Code** | `claude` | `claude` | env | npm |
+| **OpenAI Codex** | `codex` | `codex` | custom | npm |
+| **Factory Droid** | `droid` | `droid` | custom | bundled/CLI |
+| **OpenClaw** | `openclaw` | `openclaw` | custom | bundled/CLI |
+| **Cursor** | `cursor` | app | guide | desktop app |
+| **Cline** | `cline` | `cline` | custom | npm |
+| **Kilo Code** | `kilo` | `kilocode` | custom | npm |
+| **Continue** | `continue` | extension | guide | VS Code |
+| **Antigravity** | `antigravity` | internal | mitm | OmniRoute |
+| **GitHub Copilot** | `copilot` | extension | custom | VS Code |
+| **OpenCode** | `opencode` | `opencode` | guide | npm |
+| **Kiro AI** | `kiro` | app/cli | mitm | desktop/CLI |
+
+### CLI fingerprint sync (Agents + Settings)
+
+`/dashboard/agents` and `Settings > CLI Fingerprint` use `src/shared/constants/cliCompatProviders.ts`.
+This keeps provider IDs aligned with CLI cards and legacy IDs.
+
+| CLI ID | Fingerprint Provider ID |
+| ---------------------------------------------------------------------------------------------------- | ----------------------- |
+| `kilo` | `kilocode` |
+| `copilot` | `github` |
+| `claude` / `codex` / `antigravity` / `kiro` / `cursor` / `cline` / `opencode` / `droid` / `openclaw` | same ID |
+
+Legacy IDs still accepted for compatibility: `copilot`, `kimi-coding`, `qwen`.
---
@@ -71,9 +88,6 @@ npm install -g @anthropic-ai/claude-code
# OpenAI Codex
npm install -g @openai/codex
-# Gemini CLI (Google)
-npm install -g @google/gemini-cli
-
# OpenCode
npm install -g opencode-ai
@@ -81,7 +95,7 @@ npm install -g opencode-ai
npm install -g cline
# KiloCode
-npm install -g kilecode
+npm install -g kilocode
# Kiro CLI (Amazon — requires curl + unzip)
apt-get install -y unzip # on Debian/Ubuntu
@@ -94,7 +108,6 @@ export PATH="$HOME/.local/bin:$PATH" # add to ~/.bashrc
```bash
claude --version # 2.x.x
codex --version # 0.x.x
-gemini --version # 0.x.x
opencode --version # x.x.x
cline --version # 2.x.x
kilocode --version # x.x.x (or: kilo --version)
@@ -157,21 +170,6 @@ EOF
---
-### Gemini CLI
-
-```bash
-mkdir -p ~/.gemini && cat > ~/.gemini/settings.json << EOF
-{
- "apiKey": "sk-your-omniroute-key",
- "baseUrl": "http://localhost:20128/v1"
-}
-EOF
-```
-
-**Test:** `gemini "hello"`
-
----
-
### OpenCode
```bash
@@ -308,7 +306,7 @@ They run as internal routes and use OmniRoute's model routing automatically.
---
-## Troubleshooting
+## Fejlfinding
| Error | Cause | Fix |
| ------------------------- | ----------------------- | ------------------------------------------ |
@@ -328,17 +326,16 @@ They run as internal routes and use OmniRoute's model routing automatically.
OMNIROUTE_URL="http://localhost:20128/v1"
OMNIROUTE_KEY="sk-your-omniroute-key"
-npm install -g @anthropic-ai/claude-code @openai/codex @google/gemini-cli opencode-ai cline kilecode
+npm install -g @anthropic-ai/claude-code @openai/codex opencode-ai cline kilocode
# Kiro CLI
apt-get install -y unzip 2>/dev/null; curl -fsSL https://cli.kiro.dev/install | bash
# Write configs
-mkdir -p ~/.claude ~/.codex ~/.gemini ~/.config/opencode ~/.continue
+mkdir -p ~/.claude ~/.codex ~/.config/opencode ~/.continue
cat > ~/.claude/settings.json <<< "{\"apiBaseUrl\":\"$OMNIROUTE_URL\",\"apiKey\":\"$OMNIROUTE_KEY\"}"
cat > ~/.codex/config.yaml <<< "model: auto\napiKey: $OMNIROUTE_KEY\napiBaseUrl: $OMNIROUTE_URL"
-cat > ~/.gemini/settings.json <<< "{\"apiKey\":\"$OMNIROUTE_KEY\",\"baseUrl\":\"$OMNIROUTE_URL\"}"
cat >> ~/.bashrc << EOF
export OPENAI_BASE_URL="$OMNIROUTE_URL"
export OPENAI_API_KEY="$OMNIROUTE_KEY"
diff --git a/docs/i18n/da/docs/CODEBASE_DOCUMENTATION.md b/docs/i18n/da/docs/CODEBASE_DOCUMENTATION.md
new file mode 100644
index 0000000000..e513c901c1
--- /dev/null
+++ b/docs/i18n/da/docs/CODEBASE_DOCUMENTATION.md
@@ -0,0 +1,591 @@
+# omniroute — Codebase Documentation (Dansk)
+
+🌐 **Languages:** 🇺🇸 [English](../../../../docs/CODEBASE_DOCUMENTATION.md) · 🇪🇸 [es](../../es/docs/CODEBASE_DOCUMENTATION.md) · 🇫🇷 [fr](../../fr/docs/CODEBASE_DOCUMENTATION.md) · 🇩🇪 [de](../../de/docs/CODEBASE_DOCUMENTATION.md) · 🇮🇹 [it](../../it/docs/CODEBASE_DOCUMENTATION.md) · 🇷🇺 [ru](../../ru/docs/CODEBASE_DOCUMENTATION.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/CODEBASE_DOCUMENTATION.md) · 🇯🇵 [ja](../../ja/docs/CODEBASE_DOCUMENTATION.md) · 🇰🇷 [ko](../../ko/docs/CODEBASE_DOCUMENTATION.md) · 🇸🇦 [ar](../../ar/docs/CODEBASE_DOCUMENTATION.md) · 🇮🇳 [in](../../in/docs/CODEBASE_DOCUMENTATION.md) · 🇹🇭 [th](../../th/docs/CODEBASE_DOCUMENTATION.md) · 🇻🇳 [vi](../../vi/docs/CODEBASE_DOCUMENTATION.md) · 🇮🇩 [id](../../id/docs/CODEBASE_DOCUMENTATION.md) · 🇲🇾 [ms](../../ms/docs/CODEBASE_DOCUMENTATION.md) · 🇳🇱 [nl](../../nl/docs/CODEBASE_DOCUMENTATION.md) · 🇵🇱 [pl](../../pl/docs/CODEBASE_DOCUMENTATION.md) · 🇸🇪 [sv](../../sv/docs/CODEBASE_DOCUMENTATION.md) · 🇳🇴 [no](../../no/docs/CODEBASE_DOCUMENTATION.md) · 🇩🇰 [da](../../da/docs/CODEBASE_DOCUMENTATION.md) · 🇫🇮 [fi](../../fi/docs/CODEBASE_DOCUMENTATION.md) · 🇵🇹 [pt](../../pt/docs/CODEBASE_DOCUMENTATION.md) · 🇷🇴 [ro](../../ro/docs/CODEBASE_DOCUMENTATION.md) · 🇭🇺 [hu](../../hu/docs/CODEBASE_DOCUMENTATION.md) · 🇧🇬 [bg](../../bg/docs/CODEBASE_DOCUMENTATION.md) · 🇸🇰 [sk](../../sk/docs/CODEBASE_DOCUMENTATION.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/CODEBASE_DOCUMENTATION.md) · 🇮🇱 [he](../../he/docs/CODEBASE_DOCUMENTATION.md) · 🇵🇭 [phi](../../phi/docs/CODEBASE_DOCUMENTATION.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/CODEBASE_DOCUMENTATION.md) · 🇨🇿 [cs](../../cs/docs/CODEBASE_DOCUMENTATION.md)
+
+---
+
+> A comprehensive, beginner-friendly guide to the **omniroute** multi-provider AI proxy router.
+
+---
+
+## 1. What Is omniroute?
+
+omniroute is a **proxy router** that sits between AI clients (Claude CLI, Codex, Cursor IDE, etc.) and AI providers (Anthropic, Google, OpenAI, AWS, GitHub, etc.). It solves one big problem:
+
+> **Different AI clients speak different "languages" (API formats), and different AI providers expect different "languages" too.** omniroute translates between them automatically.
+
+Think of it like a universal translator at the United Nations — any delegate can speak any language, and the translator converts it for any other delegate.
+
+---
+
+## 2. Architecture Overview
+
+```mermaid
+graph LR
+ subgraph Clients
+ A[Claude CLI]
+ B[Codex]
+ C[Cursor IDE]
+ D[OpenAI-compatible]
+ end
+
+ subgraph omniroute
+ E[Handler Layer]
+ F[Translator Layer]
+ G[Executor Layer]
+ H[Services Layer]
+ end
+
+ subgraph Providers
+ I[Anthropic Claude]
+ J[Google Gemini]
+ K[OpenAI / Codex]
+ L[GitHub Copilot]
+ M[AWS Kiro]
+ N[Antigravity]
+ O[Cursor API]
+ end
+
+ A --> E
+ B --> E
+ C --> E
+ D --> E
+ E --> F
+ F --> G
+ G --> I
+ G --> J
+ G --> K
+ G --> L
+ G --> M
+ G --> N
+ G --> O
+ H -.-> E
+ H -.-> G
+```
+
+### Core Principle: Hub-and-Spoke Translation
+
+All format translation passes through **OpenAI format as the hub**:
+
+```
+Client Format → [OpenAI Hub] → Provider Format (request)
+Provider Format → [OpenAI Hub] → Client Format (response)
+```
+
+This means you only need **N translators** (one per format) instead of **N²** (every pair).
+
+---
+
+## 3. Project Structure
+
+```
+omniroute/
+├── open-sse/ ← Core proxy library (portable, framework-agnostic)
+│ ├── index.js ← Main entry point, exports everything
+│ ├── config/ ← Configuration & constants
+│ ├── executors/ ← Provider-specific request execution
+│ ├── handlers/ ← Request handling orchestration
+│ ├── services/ ← Business logic (auth, models, fallback, usage)
+│ ├── translator/ ← Format translation engine
+│ │ ├── request/ ← Request translators (8 files)
+│ │ ├── response/ ← Response translators (7 files)
+│ │ └── helpers/ ← Shared translation utilities (6 files)
+│ └── utils/ ← Utility functions
+├── src/ ← Application layer (Express/Worker runtime)
+│ ├── app/ ← Web UI, API routes, middleware
+│ ├── lib/ ← Database, auth, and shared library code
+│ ├── mitm/ ← Man-in-the-middle proxy utilities
+│ ├── models/ ← Database models
+│ ├── shared/ ← Shared utilities (wrappers around open-sse)
+│ ├── sse/ ← SSE endpoint handlers
+│ └── store/ ← State management
+├── data/ ← Runtime data (credentials, logs)
+│ └── provider-credentials.json (external credentials override, gitignored)
+└── tester/ ← Test utilities
+```
+
+---
+
+## 4. Module-by-Module Breakdown
+
+### 4.1 Config (`open-sse/config/`)
+
+The **single source of truth** for all provider configuration.
+
+| File | Purpose |
+| ----------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| `constants.ts` | `PROVIDERS` object with base URLs, OAuth credentials (defaults), headers, and default system prompts for every provider. Also defines `HTTP_STATUS`, `ERROR_TYPES`, `COOLDOWN_MS`, `BACKOFF_CONFIG`, and `SKIP_PATTERNS`. |
+| `credentialLoader.ts` | Loads external credentials from `data/provider-credentials.json` and merges them over the hardcoded defaults in `PROVIDERS`. Keeps secrets out of source control while maintaining backwards compatibility. |
+| `providerModels.ts` | Central model registry: maps provider aliases → model IDs. Functions like `getModels()`, `getProviderByAlias()`. |
+| `codexInstructions.ts` | System instructions injected into Codex requests (editing constraints, sandbox rules, approval policies). |
+| `defaultThinkingSignature.ts` | Default "thinking" signatures for Claude and Gemini models. |
+| `ollamaModels.ts` | Schema definition for local Ollama models (name, size, family, quantization). |
+
+#### Credential Loading Flow
+
+```mermaid
+flowchart TD
+ A["App starts"] --> B["constants.ts defines PROVIDERS\nwith hardcoded defaults"]
+ B --> C{"data/provider-credentials.json\nexists?"}
+ C -->|Yes| D["credentialLoader reads JSON"]
+ C -->|No| E["Use hardcoded defaults"]
+ D --> F{"For each provider in JSON"}
+ F --> G{"Provider exists\nin PROVIDERS?"}
+ G -->|No| H["Log warning, skip"]
+ G -->|Yes| I{"Value is object?"}
+ I -->|No| J["Log warning, skip"]
+ I -->|Yes| K["Merge clientId, clientSecret,\ntokenUrl, authUrl, refreshUrl"]
+ K --> F
+ H --> F
+ J --> F
+ F -->|Done| L["PROVIDERS ready with\nmerged credentials"]
+ E --> L
+```
+
+---
+
+### 4.2 Executors (`open-sse/executors/`)
+
+Executors encapsulate **provider-specific logic** using the **Strategy Pattern**. Each executor overrides base methods as needed.
+
+```mermaid
+classDiagram
+ class BaseExecutor {
+ +buildUrl(model, stream, options)
+ +buildHeaders(credentials, stream, body)
+ +transformRequest(body, model, stream, credentials)
+ +execute(url, options)
+ +shouldRetry(status, error)
+ +refreshCredentials(credentials, log)
+ }
+
+ class DefaultExecutor {
+ +refreshCredentials()
+ }
+
+ class AntigravityExecutor {
+ +buildUrl()
+ +buildHeaders()
+ +transformRequest()
+ +shouldRetry()
+ +refreshCredentials()
+ }
+
+ class CursorExecutor {
+ +buildUrl()
+ +buildHeaders()
+ +transformRequest()
+ +parseResponse()
+ +generateChecksum()
+ }
+
+ class KiroExecutor {
+ +buildUrl()
+ +buildHeaders()
+ +transformRequest()
+ +parseEventStream()
+ +refreshCredentials()
+ }
+
+ BaseExecutor <|-- DefaultExecutor
+ BaseExecutor <|-- AntigravityExecutor
+ BaseExecutor <|-- CursorExecutor
+ BaseExecutor <|-- KiroExecutor
+ BaseExecutor <|-- CodexExecutor
+ BaseExecutor <|-- GeminiCLIExecutor
+ BaseExecutor <|-- GithubExecutor
+```
+
+| Executor | Provider | Key Specializations |
+| ---------------- | ------------------------------------------ | ------------------------------------------------------------------------------------------------------------------- |
+| `base.ts` | — | Abstract base: URL building, headers, retry logic, credential refresh |
+| `default.ts` | Claude, Gemini, OpenAI, GLM, Kimi, MiniMax | Generic OAuth token refresh for standard providers |
+| `antigravity.ts` | Google Cloud Code | Project/session ID generation, multi-URL fallback, custom retry parsing from error messages ("reset after 2h7m23s") |
+| `cursor.ts` | Cursor IDE | **Most complex**: SHA-256 checksum auth, Protobuf request encoding, binary EventStream → SSE response parsing |
+| `codex.ts` | OpenAI Codex | Injects system instructions, manages thinking levels, removes unsupported parameters |
+| `gemini-cli.ts` | Google Gemini CLI | Custom URL building (`streamGenerateContent`), Google OAuth token refresh |
+| `github.ts` | GitHub Copilot | Dual token system (GitHub OAuth + Copilot token), VSCode header mimicking |
+| `kiro.ts` | AWS CodeWhisperer | AWS EventStream binary parsing, AMZN event frames, token estimation |
+| `index.ts` | — | Factory: maps provider name → executor class, with default fallback |
+
+---
+
+### 4.3 Handlers (`open-sse/handlers/`)
+
+The **orchestration layer** — coordinates translation, execution, streaming, and error handling.
+
+| File | Purpose |
+| --------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| `chatCore.ts` | **Central orchestrator** (~600 lines). Handles the complete request lifecycle: format detection → translation → executor dispatch → streaming/non-streaming response → token refresh → error handling → usage logging. |
+| `responsesHandler.ts` | Adapter for OpenAI's Responses API: converts Responses format → Chat Completions → sends to `chatCore` → converts SSE back to Responses format. |
+| `embeddings.ts` | Embedding generation handler: resolves embedding model → provider, dispatches to provider API, returns OpenAI-compatible embedding response. Supports 6+ providers. |
+| `imageGeneration.ts` | Image generation handler: resolves image model → provider, supports OpenAI-compatible, Gemini-image (Antigravity), and fallback (Nebius) modes. Returns base64 or URL images. |
+
+#### Request Lifecycle (chatCore.ts)
+
+```mermaid
+sequenceDiagram
+ participant Client
+ participant chatCore
+ participant Translator
+ participant Executor
+ participant Provider
+
+ Client->>chatCore: Request (any format)
+ chatCore->>chatCore: Detect source format
+ chatCore->>chatCore: Check bypass patterns
+ chatCore->>chatCore: Resolve model & provider
+ chatCore->>Translator: Translate request (source → OpenAI → target)
+ chatCore->>Executor: Get executor for provider
+ Executor->>Executor: Build URL, headers, transform request
+ Executor->>Executor: Refresh credentials if needed
+ Executor->>Provider: HTTP fetch (streaming or non-streaming)
+
+ alt Streaming
+ Provider-->>chatCore: SSE stream
+ chatCore->>chatCore: Pipe through SSE transform stream
+ Note over chatCore: Transform stream translates
each chunk: target → OpenAI → source
+ chatCore-->>Client: Translated SSE stream
+ else Non-streaming
+ Provider-->>chatCore: JSON response
+ chatCore->>Translator: Translate response
+ chatCore-->>Client: Translated JSON
+ end
+
+ alt Error (401, 429, 500...)
+ chatCore->>Executor: Retry with credential refresh
+ chatCore->>chatCore: Account fallback logic
+ end
+```
+
+---
+
+### 4.4 Services (`open-sse/services/`)
+
+Business logic that supports the handlers and executors.
+
+| File | Purpose |
+| -------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| `provider.ts` | **Format detection** (`detectFormat`): analyzes request body structure to identify Claude/OpenAI/Gemini/Antigravity/Responses formats (includes `max_tokens` heuristic for Claude). Also: URL building, header building, thinking config normalization. Supports `openai-compatible-*` and `anthropic-compatible-*` dynamic providers. |
+| `model.ts` | Model string parsing (`claude/model-name` → `{provider: "claude", model: "model-name"}`), alias resolution with collision detection, input sanitization (rejects path traversal/control chars), and model info resolution with async alias getter support. |
+| `accountFallback.ts` | Rate-limit handling: exponential backoff (1s → 2s → 4s → max 2min), account cooldown management, error classification (which errors trigger fallback vs. not). |
+| `tokenRefresh.ts` | OAuth token refresh for **every provider**: Google (Gemini, Antigravity), Claude, Codex, Qwen, Qoder, GitHub (OAuth + Copilot dual-token), Kiro (AWS SSO OIDC + Social Auth). Includes in-flight promise deduplication cache and retry with exponential backoff. |
+| `combo.ts` | **Combo models**: chains of fallback models. If model A fails with a fallback-eligible error, try model B, then C, etc. Returns actual upstream status codes. |
+| `usage.ts` | Fetches quota/usage data from provider APIs (GitHub Copilot quotas, Antigravity model quotas, Codex rate limits, Kiro usage breakdowns, Claude settings). |
+| `accountSelector.ts` | Smart account selection with scoring algorithm: considers priority, health status, round-robin position, and cooldown state to pick the optimal account for each request. |
+| `contextManager.ts` | Request context lifecycle management: creates and tracks per-request context objects with metadata (request ID, timestamps, provider info) for debugging and logging. |
+| `ipFilter.ts` | IP-based access control: supports allowlist and blocklist modes. Validates client IP against configured rules before processing API requests. |
+| `sessionManager.ts` | Session tracking with client fingerprinting: tracks active sessions using hashed client identifiers, monitors request counts, and provides session metrics. |
+| `signatureCache.ts` | Request signature-based deduplication cache: prevents duplicate requests by caching recent request signatures and returning cached responses for identical requests within a time window. |
+| `systemPrompt.ts` | Global system prompt injection: prepends or appends a configurable system prompt to all requests, with per-provider compatibility handling. |
+| `thinkingBudget.ts` | Reasoning token budget management: supports passthrough, auto (strip thinking config), custom (fixed budget), and adaptive (complexity-scaled) modes for controlling thinking/reasoning tokens. |
+| `wildcardRouter.ts` | Wildcard model pattern routing: resolves wildcard patterns (e.g., `*/claude-*`) to concrete provider/model pairs based on availability and priority. |
+
+#### Token Refresh Deduplication
+
+```mermaid
+sequenceDiagram
+ participant R1 as Request 1
+ participant R2 as Request 2
+ participant Cache as refreshPromiseCache
+ participant OAuth as OAuth Provider
+
+ R1->>Cache: getAccessToken("gemini", token)
+ Cache->>Cache: No in-flight promise
+ Cache->>OAuth: Start refresh
+ R2->>Cache: getAccessToken("gemini", token)
+ Cache->>Cache: Found in-flight promise
+ Cache-->>R2: Return existing promise
+ OAuth-->>Cache: New access token
+ Cache-->>R1: New access token
+ Cache-->>R2: Same access token (shared)
+ Cache->>Cache: Delete cache entry
+```
+
+#### Account Fallback State Machine
+
+```mermaid
+stateDiagram-v2
+ [*] --> Active
+ Active --> Error: Request fails (401/429/500)
+ Error --> Cooldown: Apply backoff
+ Cooldown --> Active: Cooldown expires
+ Active --> Active: Request succeeds (reset backoff)
+
+ state Error {
+ [*] --> ClassifyError
+ ClassifyError --> ShouldFallback: Rate limit / Auth / Transient
+ ClassifyError --> NoFallback: 400 Bad Request
+ }
+
+ state Cooldown {
+ [*] --> ExponentialBackoff
+ ExponentialBackoff: Level 0 = 1s
+ ExponentialBackoff: Level 1 = 2s
+ ExponentialBackoff: Level 2 = 4s
+ ExponentialBackoff: Max = 2min
+ }
+```
+
+#### Combo Model Chain
+
+```mermaid
+flowchart LR
+ A["Request with\ncombo model"] --> B["Model A"]
+ B -->|"2xx Success"| C["Return response"]
+ B -->|"429/401/500"| D{"Fallback\neligible?"}
+ D -->|Yes| E["Model B"]
+ D -->|No| F["Return error"]
+ E -->|"2xx Success"| C
+ E -->|"429/401/500"| G{"Fallback\neligible?"}
+ G -->|Yes| H["Model C"]
+ G -->|No| F
+ H -->|"2xx Success"| C
+ H -->|"Fail"| I["All failed →\nReturn last status"]
+```
+
+---
+
+### 4.5 Translator (`open-sse/translator/`)
+
+The **format translation engine** using a self-registering plugin system.
+
+#### Arkitektur
+
+```mermaid
+graph TD
+ subgraph "Request Translation"
+ A["Claude → OpenAI"]
+ B["Gemini → OpenAI"]
+ C["Antigravity → OpenAI"]
+ D["OpenAI Responses → OpenAI"]
+ E["OpenAI → Claude"]
+ F["OpenAI → Gemini"]
+ G["OpenAI → Kiro"]
+ H["OpenAI → Cursor"]
+ end
+
+ subgraph "Response Translation"
+ I["Claude → OpenAI"]
+ J["Gemini → OpenAI"]
+ K["Kiro → OpenAI"]
+ L["Cursor → OpenAI"]
+ M["OpenAI → Claude"]
+ N["OpenAI → Antigravity"]
+ O["OpenAI → Responses"]
+ end
+```
+
+| Directory | Files | Description |
+| ------------ | ------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| `request/` | 8 translators | Convert request bodies between formats. Each file self-registers via `register(from, to, fn)` on import. |
+| `response/` | 7 translators | Convert streaming response chunks between formats. Handles SSE event types, thinking blocks, tool calls. |
+| `helpers/` | 6 helpers | Shared utilities: `claudeHelper` (system prompt extraction, thinking config), `geminiHelper` (parts/contents mapping), `openaiHelper` (format filtering), `toolCallHelper` (ID generation, missing response injection), `maxTokensHelper`, `responsesApiHelper`. |
+| `index.ts` | — | Translation engine: `translateRequest()`, `translateResponse()`, state management, registry. |
+| `formats.ts` | — | Format constants: `OPENAI`, `CLAUDE`, `GEMINI`, `ANTIGRAVITY`, `KIRO`, `CURSOR`, `OPENAI_RESPONSES`. |
+
+#### Key Design: Self-Registering Plugins
+
+```javascript
+// Each translator file calls register() on import:
+import { register } from "../index.js";
+register("claude", "openai", translateClaudeToOpenAI);
+
+// The index.js imports all translator files, triggering registration:
+import "./request/claude-to-openai.js"; // ← self-registers
+```
+
+---
+
+### 4.6 Utils (`open-sse/utils/`)
+
+| File | Purpose |
+| ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
+| `error.ts` | Error response building (OpenAI-compatible format), upstream error parsing, Antigravity retry-time extraction from error messages, SSE error streaming. |
+| `stream.ts` | **SSE Transform Stream** — the core streaming pipeline. Two modes: `TRANSLATE` (full format translation) and `PASSTHROUGH` (normalize + extract usage). Handles chunk buffering, usage estimation, content length tracking. Per-stream encoder/decoder instances avoid shared state. |
+| `streamHelpers.ts` | Low-level SSE utilities: `parseSSELine` (whitespace-tolerant), `hasValuableContent` (filters empty chunks for OpenAI/Claude/Gemini), `fixInvalidId`, `formatSSE` (format-aware SSE serialization with `perf_metrics` cleanup). |
+| `usageTracking.ts` | Token usage extraction from any format (Claude/OpenAI/Gemini/Responses), estimation with separate tool/message char-per-token ratios, buffer addition (2000 tokens safety margin), format-specific field filtering, console logging with ANSI colors. |
+| `requestLogger.ts` | File-based request logging (opt-in via `ENABLE_REQUEST_LOGS=true`). Creates session folders with numbered files: `1_req_client.json` → `7_res_client.txt`. All I/O is async (fire-and-forget). Masks sensitive headers. |
+| `bypassHandler.ts` | Intercepts specific patterns from Claude CLI (title extraction, warmup, count) and returns fake responses without calling any provider. Supports both streaming and non-streaming. Intentionally limited to Claude CLI scope. |
+| `networkProxy.ts` | Resolves outbound proxy URL for a given provider with precedence: provider-specific config → global config → environment variables (`HTTPS_PROXY`/`HTTP_PROXY`/`ALL_PROXY`). Supports `NO_PROXY` exclusions. Caches config for 30s. |
+
+#### SSE Streaming Pipeline
+
+```mermaid
+flowchart TD
+ A["Provider SSE stream"] --> B["TextDecoder\n(per-stream instance)"]
+ B --> C["Buffer lines\n(split on newline)"]
+ C --> D["parseSSELine()\n(trim whitespace, parse JSON)"]
+ D --> E{"Mode?"}
+ E -->|TRANSLATE| F["translateResponse()\ntarget → OpenAI → source"]
+ E -->|PASSTHROUGH| G["fixInvalidId()\nnormalize chunk"]
+ F --> H["hasValuableContent()\nfilter empty chunks"]
+ G --> H
+ H -->|"Has content"| I["extractUsage()\ntrack token counts"]
+ H -->|"Empty"| J["Skip chunk"]
+ I --> K["formatSSE()\nserialize + clean perf_metrics"]
+ K --> L["TextEncoder\n(per-stream instance)"]
+ L --> M["Enqueue to\nclient stream"]
+
+ style A fill:#f9f,stroke:#333
+ style M fill:#9f9,stroke:#333
+```
+
+#### Request Logger Session Structure
+
+```
+logs/
+└── claude_gemini_claude-sonnet_20260208_143045/
+ ├── 1_req_client.json ← Raw client request
+ ├── 2_req_source.json ← After initial conversion
+ ├── 3_req_openai.json ← OpenAI intermediate format
+ ├── 4_req_target.json ← Final target format
+ ├── 5_res_provider.txt ← Provider SSE chunks (streaming)
+ ├── 5_res_provider.json ← Provider response (non-streaming)
+ ├── 6_res_openai.txt ← OpenAI intermediate chunks
+ ├── 7_res_client.txt ← Client-facing SSE chunks
+ └── 6_error.json ← Error details (if any)
+```
+
+---
+
+### 4.7 Application Layer (`src/`)
+
+| Directory | Purpose |
+| ------------- | ---------------------------------------------------------------------- |
+| `src/app/` | Web UI, API routes, Express middleware, OAuth callback handlers |
+| `src/lib/` | Database access (`localDb.ts`, `usageDb.ts`), authentication, shared |
+| `src/mitm/` | Man-in-the-middle proxy utilities for intercepting provider traffic |
+| `src/models/` | Database model definitions |
+| `src/shared/` | Wrappers around open-sse functions (provider, stream, error, etc.) |
+| `src/sse/` | SSE endpoint handlers that wire the open-sse library to Express routes |
+| `src/store/` | Application state management |
+
+#### Notable API Routes
+
+| Route | Methods | Purpose |
+| --------------------------------------------- | --------------- | ------------------------------------------------------------------------------------- |
+| `/api/provider-models` | GET/POST/DELETE | CRUD for custom models per provider |
+| `/api/models/catalog` | GET | Aggregated catalog of all models (chat, embedding, image, custom) grouped by provider |
+| `/api/settings/proxy` | GET/PUT/DELETE | Hierarchical outbound proxy configuration (`global/providers/combos/keys`) |
+| `/api/settings/proxy/test` | POST | Validates proxy connectivity and returns public IP/latency |
+| `/v1/providers/[provider]/chat/completions` | POST | Dedicated per-provider chat completions with model validation |
+| `/v1/providers/[provider]/embeddings` | POST | Dedicated per-provider embeddings with model validation |
+| `/v1/providers/[provider]/images/generations` | POST | Dedicated per-provider image generation with model validation |
+| `/api/settings/ip-filter` | GET/PUT | IP allowlist/blocklist management |
+| `/api/settings/thinking-budget` | GET/PUT | Reasoning token budget configuration (passthrough/auto/custom/adaptive) |
+| `/api/settings/system-prompt` | GET/PUT | Global system prompt injection for all requests |
+| `/api/sessions` | GET | Active session tracking and metrics |
+| `/api/rate-limits` | GET | Per-account rate limit status |
+
+---
+
+## 5. Key Design Patterns
+
+### 5.1 Hub-and-Spoke Translation
+
+All formats translate through **OpenAI format as the hub**. Adding a new provider only requires writing **one pair** of translators (to/from OpenAI), not N pairs.
+
+### 5.2 Executor Strategy Pattern
+
+Each provider has a dedicated executor class inheriting from `BaseExecutor`. The factory in `executors/index.ts` selects the right one at runtime.
+
+### 5.3 Self-Registering Plugin System
+
+Translator modules register themselves on import via `register()`. Adding a new translator is just creating a file and importing it.
+
+### 5.4 Account Fallback with Exponential Backoff
+
+When a provider returns 429/401/500, the system can switch to the next account, applying exponential cooldowns (1s → 2s → 4s → max 2min).
+
+### 5.5 Combo Model Chains
+
+A "combo" groups multiple `provider/model` strings. If the first fails, fallback to the next automatically.
+
+### 5.6 Stateful Streaming Translation
+
+Response translation maintains state across SSE chunks (thinking block tracking, tool call accumulation, content block indexing) via the `initState()` mechanism.
+
+### 5.7 Usage Safety Buffer
+
+A 2000-token buffer is added to reported usage to prevent clients from hitting context window limits due to overhead from system prompts and format translation.
+
+---
+
+## 6. Supported Formats
+
+| Format | Direction | Identifier |
+| ----------------------- | --------------- | ------------------ |
+| OpenAI Chat Completions | source + target | `openai` |
+| OpenAI Responses API | source + target | `openai-responses` |
+| Anthropic Claude | source + target | `claude` |
+| Google Gemini | source + target | `gemini` |
+| Google Gemini CLI | target only | `gemini-cli` |
+| Antigravity | source + target | `antigravity` |
+| AWS Kiro | target only | `kiro` |
+| Cursor | target only | `cursor` |
+
+---
+
+## 7. Supported Providers
+
+| Provider | Auth Method | Executor | Key Notes |
+| ------------------------ | ---------------------- | ----------- | --------------------------------------------- |
+| Anthropic Claude | API key or OAuth | Default | Uses `x-api-key` header |
+| Google Gemini | API key or OAuth | Default | Uses `x-goog-api-key` header |
+| Google Gemini CLI | OAuth | GeminiCLI | Uses `streamGenerateContent` endpoint |
+| Antigravity | OAuth | Antigravity | Multi-URL fallback, custom retry parsing |
+| OpenAI | API key | Default | Standard Bearer auth |
+| Codex | OAuth | Codex | Injects system instructions, manages thinking |
+| GitHub Copilot | OAuth + Copilot token | Github | Dual token, VSCode header mimicking |
+| Kiro (AWS) | AWS SSO OIDC or Social | Kiro | Binary EventStream parsing |
+| Cursor IDE | Checksum auth | Cursor | Protobuf encoding, SHA-256 checksums |
+| Qwen | OAuth | Default | Standard auth |
+| Qoder | OAuth (Basic + Bearer) | Default | Dual auth header |
+| OpenRouter | API key | Default | Standard Bearer auth |
+| GLM, Kimi, MiniMax | API key | Default | Claude-compatible, use `x-api-key` |
+| `openai-compatible-*` | API key | Default | Dynamic: any OpenAI-compatible endpoint |
+| `anthropic-compatible-*` | API key | Default | Dynamic: any Claude-compatible endpoint |
+
+---
+
+## 8. Data Flow Summary
+
+### Streaming Request
+
+```mermaid
+flowchart LR
+ A["Client"] --> B["detectFormat()"]
+ B --> C["translateRequest()\nsource → OpenAI → target"]
+ C --> D["Executor\nbuildUrl + buildHeaders"]
+ D --> E["fetch(providerURL)"]
+ E --> F["createSSEStream()\nTRANSLATE mode"]
+ F --> G["parseSSELine()"]
+ G --> H["translateResponse()\ntarget → OpenAI → source"]
+ H --> I["extractUsage()\n+ addBuffer"]
+ I --> J["formatSSE()"]
+ J --> K["Client receives\ntranslated SSE"]
+ K --> L["logUsage()\nsaveRequestUsage()"]
+```
+
+### Non-Streaming Request
+
+```mermaid
+flowchart LR
+ A["Client"] --> B["detectFormat()"]
+ B --> C["translateRequest()\nsource → OpenAI → target"]
+ C --> D["Executor.execute()"]
+ D --> E["translateResponse()\ntarget → OpenAI → source"]
+ E --> F["Return JSON\nresponse"]
+```
+
+### Bypass Flow (Claude CLI)
+
+```mermaid
+flowchart LR
+ A["Claude CLI request"] --> B{"Match bypass\npattern?"}
+ B -->|"Title/Warmup/Count"| C["Generate fake\nOpenAI response"]
+ B -->|"No match"| D["Normal flow"]
+ C --> E["Translate to\nsource format"]
+ E --> F["Return without\ncalling provider"]
+```
diff --git a/docs/i18n/da/docs/COVERAGE_PLAN.md b/docs/i18n/da/docs/COVERAGE_PLAN.md
new file mode 100644
index 0000000000..ecb6f0226f
--- /dev/null
+++ b/docs/i18n/da/docs/COVERAGE_PLAN.md
@@ -0,0 +1,170 @@
+# Test Coverage Plan (Dansk)
+
+🌐 **Languages:** 🇺🇸 [English](../../../../docs/COVERAGE_PLAN.md) · 🇪🇸 [es](../../es/docs/COVERAGE_PLAN.md) · 🇫🇷 [fr](../../fr/docs/COVERAGE_PLAN.md) · 🇩🇪 [de](../../de/docs/COVERAGE_PLAN.md) · 🇮🇹 [it](../../it/docs/COVERAGE_PLAN.md) · 🇷🇺 [ru](../../ru/docs/COVERAGE_PLAN.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/COVERAGE_PLAN.md) · 🇯🇵 [ja](../../ja/docs/COVERAGE_PLAN.md) · 🇰🇷 [ko](../../ko/docs/COVERAGE_PLAN.md) · 🇸🇦 [ar](../../ar/docs/COVERAGE_PLAN.md) · 🇮🇳 [in](../../in/docs/COVERAGE_PLAN.md) · 🇹🇭 [th](../../th/docs/COVERAGE_PLAN.md) · 🇻🇳 [vi](../../vi/docs/COVERAGE_PLAN.md) · 🇮🇩 [id](../../id/docs/COVERAGE_PLAN.md) · 🇲🇾 [ms](../../ms/docs/COVERAGE_PLAN.md) · 🇳🇱 [nl](../../nl/docs/COVERAGE_PLAN.md) · 🇵🇱 [pl](../../pl/docs/COVERAGE_PLAN.md) · 🇸🇪 [sv](../../sv/docs/COVERAGE_PLAN.md) · 🇳🇴 [no](../../no/docs/COVERAGE_PLAN.md) · 🇩🇰 [da](../../da/docs/COVERAGE_PLAN.md) · 🇫🇮 [fi](../../fi/docs/COVERAGE_PLAN.md) · 🇵🇹 [pt](../../pt/docs/COVERAGE_PLAN.md) · 🇷🇴 [ro](../../ro/docs/COVERAGE_PLAN.md) · 🇭🇺 [hu](../../hu/docs/COVERAGE_PLAN.md) · 🇧🇬 [bg](../../bg/docs/COVERAGE_PLAN.md) · 🇸🇰 [sk](../../sk/docs/COVERAGE_PLAN.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/COVERAGE_PLAN.md) · 🇮🇱 [he](../../he/docs/COVERAGE_PLAN.md) · 🇵🇭 [phi](../../phi/docs/COVERAGE_PLAN.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/COVERAGE_PLAN.md) · 🇨🇿 [cs](../../cs/docs/COVERAGE_PLAN.md)
+
+---
+
+Last updated: 2026-03-28
+
+## Baseline
+
+There are multiple coverage numbers depending on how the report is computed. For planning, only one of them is useful.
+
+| Metric | Scope | Statements / Lines | Branches | Functions | Notes |
+| -------------------- | ----------------------------------------------------- | -----------------: | -------: | --------: | --------------------------------------------------- |
+| Legacy | Old `npm run test:coverage` | 79.42% | 75.15% | 67.94% | Inflated: counts test files and excludes `open-sse` |
+| Diagnostic | Source-only, excluding tests and excluding `open-sse` | 68.16% | 63.55% | 64.06% | Useful only to isolate `src/**` |
+| Recommended baseline | Source-only, excluding tests and including `open-sse` | 56.95% | 66.05% | 57.80% | This is the project-wide baseline to improve |
+
+The recommended baseline is the number to optimize against.
+
+## Rules
+
+- Coverage targets apply to source files, not to `tests/**`.
+- `open-sse/**` is part of the product and must remain in scope.
+- New code should not reduce coverage in touched areas.
+- Prefer testing behavior and branch outcomes over implementation details.
+- Prefer temp SQLite databases and small fixtures over broad mocks for `src/lib/db/**`.
+
+## Current command set
+
+- `npm run test:coverage`
+ - Main source coverage gate for the unit test suite
+ - Generates `text-summary`, `html`, `json-summary`, and `lcov`
+- `npm run coverage:report`
+ - Detailed file-by-file report from the latest run
+- `npm run test:coverage:legacy`
+ - Historical comparison only
+
+## Milestones
+
+| Phase | Target | Focus |
+| ------- | ---------------------: | ------------------------------------------------- |
+| Phase 1 | 60% statements / lines | Quick wins and low-risk utility coverage |
+| Phase 2 | 65% statements / lines | DB and route foundations |
+| Phase 3 | 70% statements / lines | Provider validation and usage analytics |
+| Phase 4 | 75% statements / lines | `open-sse` translators and helpers |
+| Phase 5 | 80% statements / lines | `open-sse` handlers and executor branches |
+| Phase 6 | 85% statements / lines | Harder edge cases, branch debt, regression suites |
+| Phase 7 | 90% statements / lines | Final sweep, gap closure, strict ratchet |
+
+Branches and functions should ratchet upward with each phase, but the primary hard target is statements / lines.
+
+## Priority hotspots
+
+These files or areas offer the best return for the next phases:
+
+1. `open-sse/handlers`
+ - `chatCore.ts` at 7.57%
+ - Overall directory at 29.07%
+2. `open-sse/translator/request`
+ - Overall directory at 36.39%
+ - Many translators are still near single-digit coverage
+3. `open-sse/translator/response`
+ - Overall directory at 8.07%
+4. `open-sse/executors`
+ - Overall directory at 36.62%
+5. `src/lib/db`
+ - `models.ts` at 20.66%
+ - `registeredKeys.ts` at 34.46%
+ - `modelComboMappings.ts` at 36.25%
+ - `settings.ts` at 46.40%
+ - `webhooks.ts` at 33.33%
+6. `src/lib/usage`
+ - `usageHistory.ts` at 21.12%
+ - `usageStats.ts` at 9.56%
+ - `costCalculator.ts` at 30.00%
+7. `src/lib/providers`
+ - `validation.ts` at 41.16%
+8. Low-risk utility and API files for early gains
+ - `src/shared/utils/upstreamError.ts`
+ - `src/shared/utils/apiAuth.ts`
+ - `src/lib/api/errorResponse.ts`
+ - `src/app/api/settings/require-login/route.ts`
+ - `src/app/api/providers/[id]/models/route.ts`
+
+## Execution checklist
+
+### Phase 1: 56.95% -> 60%
+
+- [x] Fix coverage metric so it reflects source code instead of test files
+- [x] Keep a legacy coverage script for comparison
+- [x] Record the baseline and hotspots in-repo
+- [ ] Add focused tests for low-risk utilities:
+ - `src/shared/utils/upstreamError.ts`
+ - `src/shared/utils/fetchTimeout.ts`
+ - `src/lib/api/errorResponse.ts`
+ - `src/shared/utils/apiAuth.ts`
+ - `src/lib/display/names.ts`
+- [ ] Add route tests for:
+ - `src/app/api/settings/require-login/route.ts`
+ - `src/app/api/providers/[id]/models/route.ts`
+
+### Phase 2: 60% -> 65%
+
+- [ ] Add DB-backed tests for:
+ - `src/lib/db/modelComboMappings.ts`
+ - `src/lib/db/settings.ts`
+ - `src/lib/db/registeredKeys.ts`
+- [ ] Cover branch behavior in:
+ - `src/lib/providers/validation.ts`
+ - `src/app/api/v1/embeddings/route.ts`
+ - `src/app/api/v1/moderations/route.ts`
+
+### Phase 3: 65% -> 70%
+
+- [ ] Add usage analytics tests for:
+ - `src/lib/usage/usageHistory.ts`
+ - `src/lib/usage/usageStats.ts`
+ - `src/lib/usage/costCalculator.ts`
+- [ ] Expand route coverage for proxy management and settings branches
+
+### Phase 4: 70% -> 75%
+
+- [ ] Cover translator helpers and central translation paths:
+ - `open-sse/translator/index.ts`
+ - `open-sse/translator/helpers/*`
+ - `open-sse/translator/request/*`
+ - `open-sse/translator/response/*`
+
+### Phase 5: 75% -> 80%
+
+- [ ] Add handler-level tests for:
+ - `open-sse/handlers/chatCore.ts`
+ - `open-sse/handlers/responsesHandler.js`
+ - `open-sse/handlers/imageGeneration.js`
+ - `open-sse/handlers/embeddings.js`
+- [ ] Add executor branch coverage for provider-specific auth, retries, and endpoint overrides
+
+### Phase 6: 80% -> 85%
+
+- [ ] Merge more edge-case suites into the main coverage path
+- [ ] Increase function coverage for DB modules with weak constructor/helper coverage
+- [ ] Close branch gaps in `settings.ts`, `registeredKeys.ts`, `validation.ts`, and translator helpers
+
+### Phase 7: 85% -> 90%
+
+- [ ] Treat the remaining low-coverage files as blockers
+- [ ] Add regression tests for every uncovered production bug fixed during the push to 90%
+- [ ] Raise the coverage gate in CI only after the local baseline is stable for at least two consecutive runs
+
+## Ratchet policy
+
+Update `npm run test:coverage` thresholds only after the project actually exceeds the next milestone with a comfortable buffer.
+
+Recommended ratchet sequence:
+
+1. 55/60/55
+2. 60/62/58
+3. 65/64/62
+4. 70/66/66
+5. 75/70/72
+6. 80/75/78
+7. 85/80/84
+8. 90/85/88
+
+Order is `statements-lines / branches / functions`.
+
+## Known gap
+
+The current coverage command measures the main Node unit suite and includes source reached from it, including `open-sse`. It does not yet merge Vitest coverage into a single unified report. That merge is worth doing later, but it is not a blocker for starting the 60% -> 80% climb.
diff --git a/docs/i18n/da/docs/FEATURES.md b/docs/i18n/da/docs/FEATURES.md
index 9b2ad6f8c9..05da2ca10f 100644
--- a/docs/i18n/da/docs/FEATURES.md
+++ b/docs/i18n/da/docs/FEATURES.md
@@ -1,6 +1,6 @@
# OmniRoute — Dashboard Features Gallery (Dansk)
-🌐 **Languages:** 🇺🇸 [English](../../../../docs/FEATURES.md) · 🇪🇸 [es](../../es/docs/FEATURES.md) · 🇫🇷 [fr](../../fr/docs/FEATURES.md) · 🇩🇪 [de](../../de/docs/FEATURES.md) · 🇮🇹 [it](../../it/docs/FEATURES.md) · 🇷🇺 [ru](../../ru/docs/FEATURES.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/FEATURES.md) · 🇯🇵 [ja](../../ja/docs/FEATURES.md) · 🇰🇷 [ko](../../ko/docs/FEATURES.md) · 🇸🇦 [ar](../../ar/docs/FEATURES.md) · 🇮🇳 [in](../../in/docs/FEATURES.md) · 🇹🇭 [th](../../th/docs/FEATURES.md) · 🇻🇳 [vi](../../vi/docs/FEATURES.md) · 🇮🇩 [id](../../id/docs/FEATURES.md) · 🇲🇾 [ms](../../ms/docs/FEATURES.md) · 🇳🇱 [nl](../../nl/docs/FEATURES.md) · 🇵🇱 [pl](../../pl/docs/FEATURES.md) · 🇸🇪 [sv](../../sv/docs/FEATURES.md) · 🇳🇴 [no](../../no/docs/FEATURES.md) · 🇩🇰 [da](../../da/docs/FEATURES.md) · 🇫🇮 [fi](../../fi/docs/FEATURES.md) · 🇵🇹 [pt](../../pt/docs/FEATURES.md) · 🇷🇴 [ro](../../ro/docs/FEATURES.md) · 🇭🇺 [hu](../../hu/docs/FEATURES.md) · 🇧🇬 [bg](../../bg/docs/FEATURES.md) · 🇸🇰 [sk](../../sk/docs/FEATURES.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/FEATURES.md) · 🇮🇱 [he](../../he/docs/FEATURES.md) · 🇵🇭 [phi](../../phi/docs/FEATURES.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/FEATURES.md)
+🌐 **Languages:** 🇺🇸 [English](../../../../docs/FEATURES.md) · 🇪🇸 [es](../../es/docs/FEATURES.md) · 🇫🇷 [fr](../../fr/docs/FEATURES.md) · 🇩🇪 [de](../../de/docs/FEATURES.md) · 🇮🇹 [it](../../it/docs/FEATURES.md) · 🇷🇺 [ru](../../ru/docs/FEATURES.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/FEATURES.md) · 🇯🇵 [ja](../../ja/docs/FEATURES.md) · 🇰🇷 [ko](../../ko/docs/FEATURES.md) · 🇸🇦 [ar](../../ar/docs/FEATURES.md) · 🇮🇳 [in](../../in/docs/FEATURES.md) · 🇹🇭 [th](../../th/docs/FEATURES.md) · 🇻🇳 [vi](../../vi/docs/FEATURES.md) · 🇮🇩 [id](../../id/docs/FEATURES.md) · 🇲🇾 [ms](../../ms/docs/FEATURES.md) · 🇳🇱 [nl](../../nl/docs/FEATURES.md) · 🇵🇱 [pl](../../pl/docs/FEATURES.md) · 🇸🇪 [sv](../../sv/docs/FEATURES.md) · 🇳🇴 [no](../../no/docs/FEATURES.md) · 🇩🇰 [da](../../da/docs/FEATURES.md) · 🇫🇮 [fi](../../fi/docs/FEATURES.md) · 🇵🇹 [pt](../../pt/docs/FEATURES.md) · 🇷🇴 [ro](../../ro/docs/FEATURES.md) · 🇭🇺 [hu](../../hu/docs/FEATURES.md) · 🇧🇬 [bg](../../bg/docs/FEATURES.md) · 🇸🇰 [sk](../../sk/docs/FEATURES.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/FEATURES.md) · 🇮🇱 [he](../../he/docs/FEATURES.md) · 🇵🇭 [phi](../../phi/docs/FEATURES.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/FEATURES.md) · 🇨🇿 [cs](../../cs/docs/FEATURES.md)
---
@@ -10,7 +10,7 @@ Visual guide to every section of the OmniRoute dashboard.
## 🔌 Providers
-Manage AI provider connections: OAuth providers (Claude Code, Codex, Gemini CLI), API key providers (Groq, DeepSeek, OpenRouter), and free providers (iFlow, Qwen, Kiro). Kiro accounts include credit balance tracking — remaining credits, total allowance, and renewal date visible in Dashboard → Usage.
+Manage AI provider connections: OAuth providers (Claude Code, Codex, Gemini CLI), API key providers (Groq, DeepSeek, OpenRouter), and free providers (Qoder, Qwen, Kiro). Kiro accounts include credit balance tracking — remaining credits, total allowance, and renewal date visible in Dashboard → Usage.

diff --git a/docs/i18n/da/MCP-SERVER.md b/docs/i18n/da/docs/MCP-SERVER.md
similarity index 65%
rename from docs/i18n/da/MCP-SERVER.md
rename to docs/i18n/da/docs/MCP-SERVER.md
index 829acd30b1..5cad3f2a62 100644
--- a/docs/i18n/da/MCP-SERVER.md
+++ b/docs/i18n/da/docs/MCP-SERVER.md
@@ -1,12 +1,12 @@
-🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/MCP-SERVER.md) · 🇪🇸 [es](../es/MCP-SERVER.md) · 🇫🇷 [fr](../fr/MCP-SERVER.md) · 🇩🇪 [de](../de/MCP-SERVER.md) · 🇮🇹 [it](../it/MCP-SERVER.md) · 🇷🇺 [ru](../ru/MCP-SERVER.md) · 🇨🇳 [zh-CN](../zh-CN/MCP-SERVER.md) · 🇯🇵 [ja](../ja/MCP-SERVER.md) · 🇰🇷 [ko](../ko/MCP-SERVER.md) · 🇸🇦 [ar](../ar/MCP-SERVER.md) · 🇮🇳 [in](../in/MCP-SERVER.md) · 🇹🇭 [th](../th/MCP-SERVER.md) · 🇻🇳 [vi](../vi/MCP-SERVER.md) · 🇮🇩 [id](../id/MCP-SERVER.md) · 🇲🇾 [ms](../ms/MCP-SERVER.md) · 🇳🇱 [nl](../nl/MCP-SERVER.md) · 🇵🇱 [pl](../pl/MCP-SERVER.md) · 🇸🇪 [sv](../sv/MCP-SERVER.md) · 🇳🇴 [no](../no/MCP-SERVER.md) · 🇩🇰 [da](../da/MCP-SERVER.md) · 🇫🇮 [fi](../fi/MCP-SERVER.md) · 🇵🇹 [pt](../pt/MCP-SERVER.md) · 🇷🇴 [ro](../ro/MCP-SERVER.md) · 🇭🇺 [hu](../hu/MCP-SERVER.md) · 🇧🇬 [bg](../bg/MCP-SERVER.md) · 🇸🇰 [sk](../sk/MCP-SERVER.md) · 🇺🇦 [uk-UA](../uk-UA/MCP-SERVER.md) · 🇮🇱 [he](../he/MCP-SERVER.md) · 🇵🇭 [phi](../phi/MCP-SERVER.md)
+# OmniRoute MCP Server Documentation (Dansk)
+
+🌐 **Languages:** 🇺🇸 [English](../../../../docs/MCP-SERVER.md) · 🇪🇸 [es](../../es/docs/MCP-SERVER.md) · 🇫🇷 [fr](../../fr/docs/MCP-SERVER.md) · 🇩🇪 [de](../../de/docs/MCP-SERVER.md) · 🇮🇹 [it](../../it/docs/MCP-SERVER.md) · 🇷🇺 [ru](../../ru/docs/MCP-SERVER.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/MCP-SERVER.md) · 🇯🇵 [ja](../../ja/docs/MCP-SERVER.md) · 🇰🇷 [ko](../../ko/docs/MCP-SERVER.md) · 🇸🇦 [ar](../../ar/docs/MCP-SERVER.md) · 🇮🇳 [in](../../in/docs/MCP-SERVER.md) · 🇹🇭 [th](../../th/docs/MCP-SERVER.md) · 🇻🇳 [vi](../../vi/docs/MCP-SERVER.md) · 🇮🇩 [id](../../id/docs/MCP-SERVER.md) · 🇲🇾 [ms](../../ms/docs/MCP-SERVER.md) · 🇳🇱 [nl](../../nl/docs/MCP-SERVER.md) · 🇵🇱 [pl](../../pl/docs/MCP-SERVER.md) · 🇸🇪 [sv](../../sv/docs/MCP-SERVER.md) · 🇳🇴 [no](../../no/docs/MCP-SERVER.md) · 🇩🇰 [da](../../da/docs/MCP-SERVER.md) · 🇫🇮 [fi](../../fi/docs/MCP-SERVER.md) · 🇵🇹 [pt](../../pt/docs/MCP-SERVER.md) · 🇷🇴 [ro](../../ro/docs/MCP-SERVER.md) · 🇭🇺 [hu](../../hu/docs/MCP-SERVER.md) · 🇧🇬 [bg](../../bg/docs/MCP-SERVER.md) · 🇸🇰 [sk](../../sk/docs/MCP-SERVER.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/MCP-SERVER.md) · 🇮🇱 [he](../../he/docs/MCP-SERVER.md) · 🇵🇭 [phi](../../phi/docs/MCP-SERVER.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/MCP-SERVER.md) · 🇨🇿 [cs](../../cs/docs/MCP-SERVER.md)
---
-# OmniRoute MCP Server Documentation
-
> Model Context Protocol server with 16 intelligent tools
-## Installation
+## Installer
OmniRoute MCP is built-in. Start it with:
@@ -42,16 +42,16 @@ See [IDE Configs](integrations/ide-configs.md) for Antigravity, Cursor, Copilot,
## Advanced Tools (8)
-| Tool | Description |
-| :--------------------------------- | :---------------------------------------------- |
-| `omniroute_simulate_route` | Dry-run routing simulation with fallback tree |
-| `omniroute_set_budget_guard` | Session budget with degrade/block/alert actions |
-| `omniroute_set_resilience_profile` | Apply conservative/balanced/aggressive preset |
-| `omniroute_test_combo` | Live-test all models in a combo |
-| `omniroute_get_provider_metrics` | Detailed metrics for one provider |
-| `omniroute_best_combo_for_task` | Task-fitness recommendation with alternatives |
-| `omniroute_explain_route` | Explain a past routing decision |
-| `omniroute_get_session_snapshot` | Full session state: costs, tokens, errors |
+| Tool | Description |
+| :--------------------------------- | :---------------------------------------------------------- |
+| `omniroute_simulate_route` | Dry-run routing simulation with fallback tree |
+| `omniroute_set_budget_guard` | Session budget with degrade/block/alert actions |
+| `omniroute_set_resilience_profile` | Apply conservative/balanced/aggressive preset |
+| `omniroute_test_combo` | Live-test all models in a combo via a real upstream request |
+| `omniroute_get_provider_metrics` | Detailed metrics for one provider |
+| `omniroute_best_combo_for_task` | Task-fitness recommendation with alternatives |
+| `omniroute_explain_route` | Explain a past routing decision |
+| `omniroute_get_session_snapshot` | Full session state: costs, tokens, errors |
## Authentication
diff --git a/docs/i18n/da/docs/RELEASE_CHECKLIST.md b/docs/i18n/da/docs/RELEASE_CHECKLIST.md
new file mode 100644
index 0000000000..e47fc40eab
--- /dev/null
+++ b/docs/i18n/da/docs/RELEASE_CHECKLIST.md
@@ -0,0 +1,37 @@
+# Release Checklist (Dansk)
+
+🌐 **Languages:** 🇺🇸 [English](../../../../docs/RELEASE_CHECKLIST.md) · 🇪🇸 [es](../../es/docs/RELEASE_CHECKLIST.md) · 🇫🇷 [fr](../../fr/docs/RELEASE_CHECKLIST.md) · 🇩🇪 [de](../../de/docs/RELEASE_CHECKLIST.md) · 🇮🇹 [it](../../it/docs/RELEASE_CHECKLIST.md) · 🇷🇺 [ru](../../ru/docs/RELEASE_CHECKLIST.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/RELEASE_CHECKLIST.md) · 🇯🇵 [ja](../../ja/docs/RELEASE_CHECKLIST.md) · 🇰🇷 [ko](../../ko/docs/RELEASE_CHECKLIST.md) · 🇸🇦 [ar](../../ar/docs/RELEASE_CHECKLIST.md) · 🇮🇳 [in](../../in/docs/RELEASE_CHECKLIST.md) · 🇹🇭 [th](../../th/docs/RELEASE_CHECKLIST.md) · 🇻🇳 [vi](../../vi/docs/RELEASE_CHECKLIST.md) · 🇮🇩 [id](../../id/docs/RELEASE_CHECKLIST.md) · 🇲🇾 [ms](../../ms/docs/RELEASE_CHECKLIST.md) · 🇳🇱 [nl](../../nl/docs/RELEASE_CHECKLIST.md) · 🇵🇱 [pl](../../pl/docs/RELEASE_CHECKLIST.md) · 🇸🇪 [sv](../../sv/docs/RELEASE_CHECKLIST.md) · 🇳🇴 [no](../../no/docs/RELEASE_CHECKLIST.md) · 🇩🇰 [da](../../da/docs/RELEASE_CHECKLIST.md) · 🇫🇮 [fi](../../fi/docs/RELEASE_CHECKLIST.md) · 🇵🇹 [pt](../../pt/docs/RELEASE_CHECKLIST.md) · 🇷🇴 [ro](../../ro/docs/RELEASE_CHECKLIST.md) · 🇭🇺 [hu](../../hu/docs/RELEASE_CHECKLIST.md) · 🇧🇬 [bg](../../bg/docs/RELEASE_CHECKLIST.md) · 🇸🇰 [sk](../../sk/docs/RELEASE_CHECKLIST.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/RELEASE_CHECKLIST.md) · 🇮🇱 [he](../../he/docs/RELEASE_CHECKLIST.md) · 🇵🇭 [phi](../../phi/docs/RELEASE_CHECKLIST.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/RELEASE_CHECKLIST.md) · 🇨🇿 [cs](../../cs/docs/RELEASE_CHECKLIST.md)
+
+---
+
+Use this checklist before tagging or publishing a new OmniRoute release.
+
+## Version and Changelog
+
+1. Bump `package.json` version (`x.y.z`) in the release branch.
+2. Move release notes from `## [Unreleased]` in `CHANGELOG.md` to a dated section:
+ - `## [x.y.z] — YYYY-MM-DD`
+3. Keep `## [Unreleased]` as the first changelog section for upcoming work.
+4. Ensure the latest semver section in `CHANGELOG.md` equals `package.json` version.
+
+## API Docs
+
+1. Update `docs/openapi.yaml`:
+ - `info.version` must equal `package.json` version.
+2. Validate endpoint examples if API contracts changed.
+
+## Runtime Docs
+
+1. Review `docs/ARCHITECTURE.md` for storage/runtime drift.
+2. Review `docs/TROUBLESHOOTING.md` for env var and operational drift.
+3. Update localized docs if source docs changed significantly.
+
+## Automated Check
+
+Run the sync guard locally before opening PR:
+
+```bash
+npm run check:docs-sync
+```
+
+CI also runs this check in `.github/workflows/ci.yml` (lint job).
diff --git a/docs/i18n/ar/TROUBLESHOOTING.md b/docs/i18n/da/docs/TROUBLESHOOTING.md
similarity index 77%
rename from docs/i18n/ar/TROUBLESHOOTING.md
rename to docs/i18n/da/docs/TROUBLESHOOTING.md
index 63c148000a..d71db5edef 100644
--- a/docs/i18n/ar/TROUBLESHOOTING.md
+++ b/docs/i18n/da/docs/TROUBLESHOOTING.md
@@ -1,11 +1,9 @@
-🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/TROUBLESHOOTING.md) · 🇪🇸 [es](../es/TROUBLESHOOTING.md) · 🇫🇷 [fr](../fr/TROUBLESHOOTING.md) · 🇩🇪 [de](../de/TROUBLESHOOTING.md) · 🇮🇹 [it](../it/TROUBLESHOOTING.md) · 🇷🇺 [ru](../ru/TROUBLESHOOTING.md) · 🇨🇳 [zh-CN](../zh-CN/TROUBLESHOOTING.md) · 🇯🇵 [ja](../ja/TROUBLESHOOTING.md) · 🇰🇷 [ko](../ko/TROUBLESHOOTING.md) · 🇸🇦 [ar](../ar/TROUBLESHOOTING.md) · 🇮🇳 [in](../in/TROUBLESHOOTING.md) · 🇹🇭 [th](../th/TROUBLESHOOTING.md) · 🇻🇳 [vi](../vi/TROUBLESHOOTING.md) · 🇮🇩 [id](../id/TROUBLESHOOTING.md) · 🇲🇾 [ms](../ms/TROUBLESHOOTING.md) · 🇳🇱 [nl](../nl/TROUBLESHOOTING.md) · 🇵🇱 [pl](../pl/TROUBLESHOOTING.md) · 🇸🇪 [sv](../sv/TROUBLESHOOTING.md) · 🇳🇴 [no](../no/TROUBLESHOOTING.md) · 🇩🇰 [da](../da/TROUBLESHOOTING.md) · 🇫🇮 [fi](../fi/TROUBLESHOOTING.md) · 🇵🇹 [pt](../pt/TROUBLESHOOTING.md) · 🇷🇴 [ro](../ro/TROUBLESHOOTING.md) · 🇭🇺 [hu](../hu/TROUBLESHOOTING.md) · 🇧🇬 [bg](../bg/TROUBLESHOOTING.md) · 🇸🇰 [sk](../sk/TROUBLESHOOTING.md) · 🇺🇦 [uk-UA](../uk-UA/TROUBLESHOOTING.md) · 🇮🇱 [he](../he/TROUBLESHOOTING.md) · 🇵🇭 [phi](../phi/TROUBLESHOOTING.md)
+# Troubleshooting (Dansk)
+
+🌐 **Languages:** 🇺🇸 [English](../../../../docs/TROUBLESHOOTING.md) · 🇪🇸 [es](../../es/docs/TROUBLESHOOTING.md) · 🇫🇷 [fr](../../fr/docs/TROUBLESHOOTING.md) · 🇩🇪 [de](../../de/docs/TROUBLESHOOTING.md) · 🇮🇹 [it](../../it/docs/TROUBLESHOOTING.md) · 🇷🇺 [ru](../../ru/docs/TROUBLESHOOTING.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/TROUBLESHOOTING.md) · 🇯🇵 [ja](../../ja/docs/TROUBLESHOOTING.md) · 🇰🇷 [ko](../../ko/docs/TROUBLESHOOTING.md) · 🇸🇦 [ar](../../ar/docs/TROUBLESHOOTING.md) · 🇮🇳 [in](../../in/docs/TROUBLESHOOTING.md) · 🇹🇭 [th](../../th/docs/TROUBLESHOOTING.md) · 🇻🇳 [vi](../../vi/docs/TROUBLESHOOTING.md) · 🇮🇩 [id](../../id/docs/TROUBLESHOOTING.md) · 🇲🇾 [ms](../../ms/docs/TROUBLESHOOTING.md) · 🇳🇱 [nl](../../nl/docs/TROUBLESHOOTING.md) · 🇵🇱 [pl](../../pl/docs/TROUBLESHOOTING.md) · 🇸🇪 [sv](../../sv/docs/TROUBLESHOOTING.md) · 🇳🇴 [no](../../no/docs/TROUBLESHOOTING.md) · 🇩🇰 [da](../../da/docs/TROUBLESHOOTING.md) · 🇫🇮 [fi](../../fi/docs/TROUBLESHOOTING.md) · 🇵🇹 [pt](../../pt/docs/TROUBLESHOOTING.md) · 🇷🇴 [ro](../../ro/docs/TROUBLESHOOTING.md) · 🇭🇺 [hu](../../hu/docs/TROUBLESHOOTING.md) · 🇧🇬 [bg](../../bg/docs/TROUBLESHOOTING.md) · 🇸🇰 [sk](../../sk/docs/TROUBLESHOOTING.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/TROUBLESHOOTING.md) · 🇮🇱 [he](../../he/docs/TROUBLESHOOTING.md) · 🇵🇭 [phi](../../phi/docs/TROUBLESHOOTING.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/TROUBLESHOOTING.md) · 🇨🇿 [cs](../../cs/docs/TROUBLESHOOTING.md)
---
-# Troubleshooting
-
-🌐 **Languages:** 🇺🇸 [English](TROUBLESHOOTING.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/TROUBLESHOOTING.md) | 🇪🇸 [Español](i18n/es/TROUBLESHOOTING.md) | 🇫🇷 [Français](i18n/fr/TROUBLESHOOTING.md) | 🇮🇹 [Italiano](i18n/it/TROUBLESHOOTING.md) | 🇷🇺 [Русский](i18n/ru/TROUBLESHOOTING.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/TROUBLESHOOTING.md) | 🇩🇪 [Deutsch](i18n/de/TROUBLESHOOTING.md) | 🇮🇳 [हिन्दी](i18n/in/TROUBLESHOOTING.md) | 🇹🇭 [ไทย](i18n/th/TROUBLESHOOTING.md) | 🇺🇦 [Українська](i18n/uk-UA/TROUBLESHOOTING.md) | 🇸🇦 [العربية](i18n/ar/TROUBLESHOOTING.md) | 🇯🇵 [日本語](i18n/ja/TROUBLESHOOTING.md) | 🇻🇳 [Tiếng Việt](i18n/vi/TROUBLESHOOTING.md) | 🇧🇬 [Български](i18n/bg/TROUBLESHOOTING.md) | 🇩🇰 [Dansk](i18n/da/TROUBLESHOOTING.md) | 🇫🇮 [Suomi](i18n/fi/TROUBLESHOOTING.md) | 🇮🇱 [עברית](i18n/he/TROUBLESHOOTING.md) | 🇭🇺 [Magyar](i18n/hu/TROUBLESHOOTING.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/TROUBLESHOOTING.md) | 🇰🇷 [한국어](i18n/ko/TROUBLESHOOTING.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/TROUBLESHOOTING.md) | 🇳🇱 [Nederlands](i18n/nl/TROUBLESHOOTING.md) | 🇳🇴 [Norsk](i18n/no/TROUBLESHOOTING.md) | 🇵🇹 [Português (Portugal)](i18n/pt/TROUBLESHOOTING.md) | 🇷🇴 [Română](i18n/ro/TROUBLESHOOTING.md) | 🇵🇱 [Polski](i18n/pl/TROUBLESHOOTING.md) | 🇸🇰 [Slovenčina](i18n/sk/TROUBLESHOOTING.md) | 🇸🇪 [Svenska](i18n/sv/TROUBLESHOOTING.md) | 🇵🇭 [Filipino](i18n/phi/TROUBLESHOOTING.md)
-
Common problems and solutions for OmniRoute.
---
diff --git a/docs/i18n/da/USER_GUIDE.md b/docs/i18n/da/docs/USER_GUIDE.md
similarity index 82%
rename from docs/i18n/da/USER_GUIDE.md
rename to docs/i18n/da/docs/USER_GUIDE.md
index 7af0a60c9f..99a99aefb2 100644
--- a/docs/i18n/da/USER_GUIDE.md
+++ b/docs/i18n/da/docs/USER_GUIDE.md
@@ -1,8 +1,6 @@
# User Guide (Dansk)
-🌐 **Languages:** 🇺🇸 [English](../../USER_GUIDE.md) · 🇧🇷 [pt-BR](../pt-BR/USER_GUIDE.md) · 🇪🇸 [es](../es/USER_GUIDE.md) · 🇫🇷 [fr](../fr/USER_GUIDE.md) · 🇩🇪 [de](../de/USER_GUIDE.md) · 🇮🇹 [it](../it/USER_GUIDE.md) · 🇷🇺 [ru](../ru/USER_GUIDE.md) · 🇨🇳 [zh-CN](../zh-CN/USER_GUIDE.md) · 🇯🇵 [ja](../ja/USER_GUIDE.md) · 🇰🇷 [ko](../ko/USER_GUIDE.md) · 🇸🇦 [ar](../ar/USER_GUIDE.md) · 🇮🇳 [in](../in/USER_GUIDE.md) · 🇹🇭 [th](../th/USER_GUIDE.md) · 🇻🇳 [vi](../vi/USER_GUIDE.md) · 🇮🇩 [id](../id/USER_GUIDE.md) · 🇲🇾 [ms](../ms/USER_GUIDE.md) · 🇳🇱 [nl](../nl/USER_GUIDE.md) · 🇵🇱 [pl](../pl/USER_GUIDE.md) · 🇸🇪 [sv](../sv/USER_GUIDE.md) · 🇳🇴 [no](../no/USER_GUIDE.md) · 🇩🇰 [da](../da/USER_GUIDE.md) · 🇫🇮 [fi](../fi/USER_GUIDE.md) · 🇵🇹 [pt](../pt/USER_GUIDE.md) · 🇷🇴 [ro](../ro/USER_GUIDE.md) · 🇭🇺 [hu](../hu/USER_GUIDE.md) · 🇧🇬 [bg](../bg/USER_GUIDE.md) · 🇸🇰 [sk](../sk/USER_GUIDE.md) · 🇺🇦 [uk-UA](../uk-UA/USER_GUIDE.md) · 🇮🇱 [he](../he/USER_GUIDE.md) · 🇵🇭 [phi](../phi/USER_GUIDE.md)
-
-> 🇺🇸 [English](../../USER_GUIDE.md)
+🌐 **Languages:** 🇺🇸 [English](../../../../docs/USER_GUIDE.md) · 🇪🇸 [es](../../es/docs/USER_GUIDE.md) · 🇫🇷 [fr](../../fr/docs/USER_GUIDE.md) · 🇩🇪 [de](../../de/docs/USER_GUIDE.md) · 🇮🇹 [it](../../it/docs/USER_GUIDE.md) · 🇷🇺 [ru](../../ru/docs/USER_GUIDE.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/USER_GUIDE.md) · 🇯🇵 [ja](../../ja/docs/USER_GUIDE.md) · 🇰🇷 [ko](../../ko/docs/USER_GUIDE.md) · 🇸🇦 [ar](../../ar/docs/USER_GUIDE.md) · 🇮🇳 [in](../../in/docs/USER_GUIDE.md) · 🇹🇭 [th](../../th/docs/USER_GUIDE.md) · 🇻🇳 [vi](../../vi/docs/USER_GUIDE.md) · 🇮🇩 [id](../../id/docs/USER_GUIDE.md) · 🇲🇾 [ms](../../ms/docs/USER_GUIDE.md) · 🇳🇱 [nl](../../nl/docs/USER_GUIDE.md) · 🇵🇱 [pl](../../pl/docs/USER_GUIDE.md) · 🇸🇪 [sv](../../sv/docs/USER_GUIDE.md) · 🇳🇴 [no](../../no/docs/USER_GUIDE.md) · 🇩🇰 [da](../../da/docs/USER_GUIDE.md) · 🇫🇮 [fi](../../fi/docs/USER_GUIDE.md) · 🇵🇹 [pt](../../pt/docs/USER_GUIDE.md) · 🇷🇴 [ro](../../ro/docs/USER_GUIDE.md) · 🇭🇺 [hu](../../hu/docs/USER_GUIDE.md) · 🇧🇬 [bg](../../bg/docs/USER_GUIDE.md) · 🇸🇰 [sk](../../sk/docs/USER_GUIDE.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/USER_GUIDE.md) · 🇮🇱 [he](../../he/docs/USER_GUIDE.md) · 🇵🇭 [phi](../../phi/docs/USER_GUIDE.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/USER_GUIDE.md) · 🇨🇿 [cs](../../cs/docs/USER_GUIDE.md)
---
@@ -320,7 +318,7 @@ Model: cc/claude-opus-4-6
---
-## 🚀 Deployment
+## Udrulning
### Global npm install (Recommended)
@@ -511,23 +509,26 @@ post_install() {
### Environment Variables
-| Variable | Default | Description |
-| ------------------------- | ------------------------------------ | ------------------------------------------------------- |
-| `JWT_SECRET` | `omniroute-default-secret-change-me` | JWT signing secret (**change in production**) |
-| `INITIAL_PASSWORD` | `123456` | First login password |
-| `DATA_DIR` | `~/.omniroute` | Data directory (db, usage, logs) |
-| `PORT` | framework default | Service port (`20128` in examples) |
-| `HOSTNAME` | framework default | Bind host (Docker defaults to `0.0.0.0`) |
-| `NODE_ENV` | runtime default | Set `production` for deploy |
-| `BASE_URL` | `http://localhost:20128` | Server-side internal base URL |
-| `CLOUD_URL` | `https://omniroute.dev` | Cloud sync endpoint base URL |
-| `API_KEY_SECRET` | `endpoint-proxy-api-key-secret` | HMAC secret for generated API keys |
-| `REQUIRE_API_KEY` | `false` | Enforce Bearer API key on `/v1/*` |
-| `ENABLE_REQUEST_LOGS` | `false` | Enables request/response logs |
-| `AUTH_COOKIE_SECURE` | `false` | Force `Secure` auth cookie (behind HTTPS reverse proxy) |
-| `OMNIROUTE_MEMORY_MB` | `512` | Node.js heap limit in MB |
-| `PROMPT_CACHE_MAX_SIZE` | `50` | Max prompt cache entries |
-| `SEMANTIC_CACHE_MAX_SIZE` | `100` | Max semantic cache entries |
+| Variable | Default | Description |
+| ---------------------------- | ------------------------------------ | ------------------------------------------------------------------------------------------ |
+| `JWT_SECRET` | `omniroute-default-secret-change-me` | JWT signing secret (**change in production**) |
+| `INITIAL_PASSWORD` | `123456` | First login password |
+| `DATA_DIR` | `~/.omniroute` | Data directory (db, usage, logs) |
+| `PORT` | framework default | Service port (`20128` in examples) |
+| `HOSTNAME` | framework default | Bind host (Docker defaults to `0.0.0.0`) |
+| `NODE_ENV` | runtime default | Set `production` for deploy |
+| `BASE_URL` | `http://localhost:20128` | Server-side internal base URL |
+| `CLOUD_URL` | `https://omniroute.dev` | Cloud sync endpoint base URL |
+| `API_KEY_SECRET` | `endpoint-proxy-api-key-secret` | HMAC secret for generated API keys |
+| `REQUIRE_API_KEY` | `false` | Enforce Bearer API key on `/v1/*` |
+| `ALLOW_API_KEY_REVEAL` | `false` | Allow Api Manager to copy full API keys on demand |
+| `DISABLE_SQLITE_AUTO_BACKUP` | `false` | Disable automatic SQLite snapshots before writes/import/restore; manual backups still work |
+| `ENABLE_REQUEST_LOGS` | `false` | Enables request/response logs |
+| `AUTH_COOKIE_SECURE` | `false` | Force `Secure` auth cookie (behind HTTPS reverse proxy) |
+| `CLOUDFLARED_BIN` | unset | Use an existing `cloudflared` binary instead of managed download |
+| `OMNIROUTE_MEMORY_MB` | `512` | Node.js heap limit in MB |
+| `PROMPT_CACHE_MAX_SIZE` | `50` | Max prompt cache entries |
+| `SEMANTIC_CACHE_MAX_SIZE` | `100` | Max semantic cache entries |
For the full environment variable reference, see the [README](../README.md).
@@ -598,6 +599,11 @@ curl -X POST http://localhost:20128/api/provider-models \
Or use Dashboard: **Providers → [Provider] → Custom Models**.
+Notes:
+
+- OpenRouter and OpenAI/Anthropic-compatible providers are managed from **Available Models** only. Manual add, import, and auto-sync all land in the same available-model list, so there is no separate Custom Models section for those providers.
+- The **Custom Models** section is intended for providers that do not expose managed available-model imports.
+
### Dedicated Provider Routes
Route requests directly to a specific provider with model validation:
@@ -642,6 +648,14 @@ Returns models grouped by provider with types (`chat`, `embedding`, `image`).
- Automatic background sync with timeout + fail-fast
- Prefer server-side `BASE_URL`/`CLOUD_URL` in production
+### Cloudflare Quick Tunnel
+
+- Available in **Dashboard → Endpoints** for Docker and other self-hosted deployments
+- Creates a temporary `https://*.trycloudflare.com` URL that forwards to your current OpenAI-compatible `/v1` endpoint
+- First enable installs `cloudflared` only when needed; later restarts reuse the same managed binary
+- Tunnel URLs are ephemeral and change every time you stop/start the tunnel
+- Set `CLOUDFLARED_BIN` if you prefer using a preinstalled `cloudflared` binary instead of the managed download
+
### LLM Gateway Intelligence (Phase 9)
- **Semantic Cache** — Auto-caches non-streaming, temperature=0 responses (bypass with `X-OmniRoute-No-Cache: true`)
@@ -757,11 +771,11 @@ OmniRoute implements provider-level resilience with four components:
Manage database backups in **Dashboard → Settings → System & Storage**.
-| Action | Description |
-| ------------------------ | ------------------------------------------------------------------------------------------------------------------------------ |
-| **Export Database** | Downloads the current SQLite database as a `.sqlite` file |
-| **Export All (.tar.gz)** | Downloads a full backup archive including: database, settings, combos, provider connections (no credentials), API key metadata |
-| **Import Database** | Upload a `.sqlite` file to replace the current database. A pre-import backup is automatically created |
+| Action | Description |
+| ------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------- |
+| **Export Database** | Downloads the current SQLite database as a `.sqlite` file |
+| **Export All (.tar.gz)** | Downloads a full backup archive including: database, settings, combos, provider connections (no credentials), API key metadata |
+| **Import Database** | Upload a `.sqlite` file to replace the current database. A pre-import backup is automatically created unless `DISABLE_SQLITE_AUTO_BACKUP=true` |
```bash
# API: Export database
@@ -787,10 +801,11 @@ curl -X POST http://localhost:20128/api/db-backups/import \
### Settings Dashboard
-The settings page is organized into 5 tabs for easy navigation:
+The settings page is organized into 6 tabs for easy navigation:
| Tab | Contents |
| -------------- | ---------------------------------------------------------------------------------------------- |
+| **General** | System storage tools, appearance settings, theme controls, and per-item sidebar visibility |
| **Security** | Login/Password settings, IP Access Control, API auth for `/models`, and Provider Blocking |
| **Routing** | Global routing strategy (6 options), wildcard model aliases, fallback chains, combo defaults |
| **Resilience** | Provider profiles, editable rate limits, circuit breaker status, policies & locked identifiers |
diff --git a/docs/i18n/da/docs/VM_DEPLOYMENT_GUIDE.md b/docs/i18n/da/docs/VM_DEPLOYMENT_GUIDE.md
new file mode 100644
index 0000000000..28a7130f63
--- /dev/null
+++ b/docs/i18n/da/docs/VM_DEPLOYMENT_GUIDE.md
@@ -0,0 +1,403 @@
+# OmniRoute — Deployment Guide on VM with Cloudflare (Dansk)
+
+🌐 **Languages:** 🇺🇸 [English](../../../../docs/VM_DEPLOYMENT_GUIDE.md) · 🇪🇸 [es](../../es/docs/VM_DEPLOYMENT_GUIDE.md) · 🇫🇷 [fr](../../fr/docs/VM_DEPLOYMENT_GUIDE.md) · 🇩🇪 [de](../../de/docs/VM_DEPLOYMENT_GUIDE.md) · 🇮🇹 [it](../../it/docs/VM_DEPLOYMENT_GUIDE.md) · 🇷🇺 [ru](../../ru/docs/VM_DEPLOYMENT_GUIDE.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/VM_DEPLOYMENT_GUIDE.md) · 🇯🇵 [ja](../../ja/docs/VM_DEPLOYMENT_GUIDE.md) · 🇰🇷 [ko](../../ko/docs/VM_DEPLOYMENT_GUIDE.md) · 🇸🇦 [ar](../../ar/docs/VM_DEPLOYMENT_GUIDE.md) · 🇮🇳 [in](../../in/docs/VM_DEPLOYMENT_GUIDE.md) · 🇹🇭 [th](../../th/docs/VM_DEPLOYMENT_GUIDE.md) · 🇻🇳 [vi](../../vi/docs/VM_DEPLOYMENT_GUIDE.md) · 🇮🇩 [id](../../id/docs/VM_DEPLOYMENT_GUIDE.md) · 🇲🇾 [ms](../../ms/docs/VM_DEPLOYMENT_GUIDE.md) · 🇳🇱 [nl](../../nl/docs/VM_DEPLOYMENT_GUIDE.md) · 🇵🇱 [pl](../../pl/docs/VM_DEPLOYMENT_GUIDE.md) · 🇸🇪 [sv](../../sv/docs/VM_DEPLOYMENT_GUIDE.md) · 🇳🇴 [no](../../no/docs/VM_DEPLOYMENT_GUIDE.md) · 🇩🇰 [da](../../da/docs/VM_DEPLOYMENT_GUIDE.md) · 🇫🇮 [fi](../../fi/docs/VM_DEPLOYMENT_GUIDE.md) · 🇵🇹 [pt](../../pt/docs/VM_DEPLOYMENT_GUIDE.md) · 🇷🇴 [ro](../../ro/docs/VM_DEPLOYMENT_GUIDE.md) · 🇭🇺 [hu](../../hu/docs/VM_DEPLOYMENT_GUIDE.md) · 🇧🇬 [bg](../../bg/docs/VM_DEPLOYMENT_GUIDE.md) · 🇸🇰 [sk](../../sk/docs/VM_DEPLOYMENT_GUIDE.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/VM_DEPLOYMENT_GUIDE.md) · 🇮🇱 [he](../../he/docs/VM_DEPLOYMENT_GUIDE.md) · 🇵🇭 [phi](../../phi/docs/VM_DEPLOYMENT_GUIDE.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/VM_DEPLOYMENT_GUIDE.md) · 🇨🇿 [cs](../../cs/docs/VM_DEPLOYMENT_GUIDE.md)
+
+---
+
+Complete guide to install and configure OmniRoute on a VM (VPS) with domain managed via Cloudflare.
+
+---
+
+## Prerequisites
+
+| Item | Minimum | Recommended |
+| ---------- | ------------------------ | ---------------- |
+| **CPU** | 1 vCPU | 2 vCPU |
+| **RAM** | 1 GB | 2 GB |
+| **Disk** | 10 GB SSD | 25 GB SSD |
+| **OS** | Ubuntu 22.04 LTS | Ubuntu 24.04 LTS |
+| **Domain** | Registered on Cloudflare | — |
+| **Docker** | Docker Engine 24+ | Docker 27+ |
+
+**Tested providers**: Akamai (Linode), DigitalOcean, Vultr, Hetzner, AWS Lightsail.
+
+---
+
+## 1. Configure the VM
+
+### 1.1 Create the instance
+
+On your preferred VPS provider:
+
+- Choose Ubuntu 24.04 LTS
+- Select the minimum plan (1 vCPU / 1 GB RAM)
+- Set a strong root password or configure SSH key
+- Note the **public IP** (e.g., `203.0.113.10`)
+
+### 1.2 Connect via SSH
+
+```bash
+ssh root@203.0.113.10
+```
+
+### 1.3 Update the system
+
+```bash
+apt update && apt upgrade -y
+```
+
+### 1.4 Install Docker
+
+```bash
+# Install dependencies
+apt install -y ca-certificates curl gnupg
+
+# Add official Docker repository
+install -m 0755 -d /etc/apt/keyrings
+curl -fsSL https://download.docker.com/linux/ubuntu/gpg | gpg --dearmor -o /etc/apt/keyrings/docker.gpg
+chmod a+r /etc/apt/keyrings/docker.gpg
+echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu $ (. /etc/os-release && echo “$VERSION_CODENAME”) stable" | tee /etc/apt/sources.list.d/docker.list > /dev/null
+apt update
+apt install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin
+```
+
+### 1.5 Install nginx
+
+```bash
+apt install -y nginx
+```
+
+### 1.6 Configure Firewall (UFW)
+
+```bash
+ufw default deny incoming
+ufw default allow outgoing
+ufw allow 22/tcp # SSH
+ufw allow 80/tcp # HTTP (redirect)
+ufw allow 443/tcp # HTTPS
+ufw enable
+```
+
+> **Tip**: For maximum security, restrict ports 80 and 443 to Cloudflare IPs only. See the [Advanced Security](#advanced-security) section.
+
+---
+
+## 2. Install OmniRoute
+
+### 2.1 Create configuration directory
+
+```bash
+mkdir -p /opt/omniroute
+```
+
+### 2.2 Create environment variables file
+
+```bash
+cat > /opt/omniroute/.env << ‘EOF’
+# === Security ===
+JWT_SECRET=CHANGE-TO-A-UNIQUE-64-CHAR-SECRET-KEY
+INITIAL_PASSWORD=YourSecurePassword123!
+API_KEY_SECRET=REPLACE-WITH-ANOTHER-SECRET-KEY
+STORAGE_ENCRYPTION_KEY=REPLACE-WITH-THIRD-SECRET-KEY
+STORAGE_ENCRYPTION_KEY_VERSION=v1
+MACHINE_ID_SALT=CHANGE-TO-A-UNIQUE-SALT
+
+# === App ===
+PORT=20128
+NODE_ENV=production
+HOSTNAME=0.0.0.0
+DATA_DIR=/app/data
+STORAGE_DRIVER=sqlite
+ENABLE_REQUEST_LOGS=true
+AUTH_COOKIE_SECURE=false
+REQUIRE_API_KEY=false
+
+# === Domain (change to your domain) ===
+BASE_URL=https://llms.seudominio.com
+NEXT_PUBLIC_BASE_URL=https://llms.seudominio.com
+
+# === Cloud Sync (optional) ===
+# CLOUD_URL=https://cloud.omniroute.online
+# NEXT_PUBLIC_CLOUD_URL=https://cloud.omniroute.online
+EOF
+```
+
+> ⚠️ **IMPORTANT**: Generate unique secret keys! Use `openssl rand -hex 32` for each key.
+
+### 2.3 Start the container
+
+```bash
+docker pull diegosouzapw/omniroute:latest
+
+docker run -d \
+ --name omniroute \
+ --restart unless-stopped \
+ --env-file /opt/omniroute/.env \
+ -p 20128:20128 \
+ -v omniroute-data:/app/data \
+ diegosouzapw/omniroute:latest
+```
+
+### 2.4 Verify that it is running
+
+```bash
+docker ps | grep omniroute
+docker logs omniroute --tail 20
+```
+
+It should display: `[DB] SQLite database ready` and `listening on port 20128`.
+
+---
+
+## 3. Configure nginx (Reverse Proxy)
+
+### 3.1 Generate SSL certificate (Cloudflare Origin)
+
+In the Cloudflare dashboard:
+
+1. Go to **SSL/TLS → Origin Server**
+2. Click **Create Certificate**
+3. Keep the defaults (15 years, \*.yourdomain.com)
+4. Copy the **Origin Certificate** and the **Private Key**
+
+```bash
+mkdir -p /etc/nginx/ssl
+
+# Paste the certificate
+nano /etc/nginx/ssl/origin.crt
+
+# Paste the private key
+nano /etc/nginx/ssl/origin.key
+
+chmod 600 /etc/nginx/ssl/origin.key
+```
+
+### 3.2 Nginx Configuration
+
+```bash
+cat > /etc/nginx/sites-available/omniroute << ‘NGINX’
+# Default server — blocks direct access via IP
+server {
+ listen 80 default_server;
+ listen [::]:80 default_server;
+ listen 443 ssl default_server;
+ listen [::]:443 ssl default_server;
+ ssl_certificate /etc/nginx/ssl/origin.crt;
+ ssl_certificate_key /etc/nginx/ssl/origin.key;
+ server_name _;
+ return 444;
+}
+
+# OmniRoute — HTTPS
+server {
+ listen 443 ssl;
+ listen [::]:443 ssl;
+ server_name llms.yourdomain.com; # Change to your domain
+
+ ssl_certificate /etc/nginx/ssl/origin.crt;
+ ssl_certificate_key /etc/nginx/ssl/origin.key;
+ ssl_protocols TLSv1.2 TLSv1.3;
+
+ client_max_body_size 100M;
+
+ location / {
+ proxy_pass http://127.0.0.1:20128;
+ proxy_set_header Host $host;
+ proxy_set_header X-Real-IP $remote_addr;
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
+ proxy_set_header X-Forwarded-Proto $scheme;
+
+ # WebSocket support
+ proxy_http_version 1.1;
+ proxy_set_header Upgrade $http_upgrade;
+ proxy_set_header Connection “upgrade”;
+
+ # SSE (Server-Sent Events) — streaming AI responses
+ proxy_buffering off;
+ proxy_cache off;
+ proxy_read_timeout 300s;
+ proxy_send_timeout 300s;
+ }
+}
+
+# HTTP → HTTPS redirect
+server {
+ listen 80;
+ listen [::]:80;
+ server_name llms.yourdomain.com;
+ return 301 https://$server_name$request_uri;
+}
+NGINX
+```
+
+### 3.3 Enable and Test
+
+```bash
+# Remove default configuration
+rm -f /etc/nginx/sites-enabled/default
+
+# Enable OmniRoute
+ln -sf /etc/nginx/sites-available/omniroute /etc/nginx/sites-enabled/omniroute
+
+# Test and reload
+nginx -t && systemctl reload nginx
+```
+
+---
+
+## 4. Configure Cloudflare DNS
+
+### 4.1 Add DNS record
+
+In the Cloudflare dashboard → DNS:
+
+| Type | Name | Content | Proxy |
+| ---- | ------ | ---------------------- | ---------- |
+| A | `llms` | `203.0.113.10` (VM IP) | ✅ Proxied |
+
+### 4.2 Configure SSL
+
+Under **SSL/TLS → Overview**:
+
+- Mode: **Full (Strict)**
+
+Under **SSL/TLS → Edge Certificates**:
+
+- Always Use HTTPS: ✅ On
+- Minimum TLS Version: TLS 1.2
+- Automatic HTTPS Rewrites: ✅ On
+
+### 4.3 Testing
+
+```bash
+curl -sI https://llms.seudominio.com/health
+# Should return HTTP/2 200
+```
+
+---
+
+## 5. Operations and Maintenance
+
+### Upgrade to a new version
+
+```bash
+docker pull diegosouzapw/omniroute:latest
+docker stop omniroute && docker rm omniroute
+docker run -d --name omniroute --restart unless-stopped \
+ --env-file /opt/omniroute/.env \
+ -p 20128:20128 \
+ -v omniroute-data:/app/data \
+ diegosouzapw/omniroute:latest
+```
+
+### View logs
+
+```bash
+docker logs -f omniroute # Real-time stream
+docker logs omniroute --tail 50 # Last 50 lines
+```
+
+### Manual database backup
+
+```bash
+# Copy data from the volume to the host
+docker cp omniroute:/app/data ./backup-$(date +%F)
+
+# Or compress the entire volume
+docker run --rm -v omniroute-data:/data -v $(pwd):/backup \
+ alpine tar czf /backup/omniroute-data-$(date +%F).tar.gz /data
+```
+
+### Restore from backup
+
+```bash
+docker stop omniroute
+docker run --rm -v omniroute-data:/data -v $(pwd):/backup \
+ alpine sh -c “rm -rf /data/* && tar xzf /backup/omniroute-data-YYYY-MM-DD.tar.gz -C /”
+docker start omniroute
+```
+
+---
+
+## 6. Advanced Security
+
+### Restrict nginx to Cloudflare IPs
+
+```bash
+cat > /etc/nginx/cloudflare-ips.conf << ‘CF’
+# Cloudflare IPv4 ranges — update periodically
+# https://www.cloudflare.com/ips-v4/
+set_real_ip_from 173.245.48.0/20;
+set_real_ip_from 103.21.244.0/22;
+set_real_ip_from 103.22.200.0/22;
+set_real_ip_from 103.31.4.0/22;
+set_real_ip_from 141.101.64.0/18;
+set_real_ip_from 108.162.192.0/18;
+set_real_ip_from 190.93.240.0/20;
+set_real_ip_from 188.114.96.0/20;
+set_real_ip_from 197.234.240.0/22;
+set_real_ip_from 198.41.128.0/17;
+set_real_ip_from 162.158.0.0/15;
+set_real_ip_from 104.16.0.0/13;
+set_real_ip_from 104.24.0.0/14;
+set_real_ip_from 172.64.0.0/13;
+set_real_ip_from 131.0.72.0/22;
+real_ip_header CF-Connecting-IP;
+CF
+```
+
+Add the following to `nginx.conf` inside the `http {}` block:
+
+```nginx
+include /etc/nginx/cloudflare-ips.conf;
+```
+
+### Install fail2ban
+
+```bash
+apt install -y fail2ban
+systemctl enable fail2ban
+systemctl start fail2ban
+
+# Check status
+fail2ban-client status sshd
+```
+
+### Block direct access to the Docker port
+
+```bash
+# Prevent direct external access to port 20128
+iptables -I DOCKER-USER -p tcp --dport 20128 -j DROP
+iptables -I DOCKER-USER -i lo -p tcp --dport 20128 -j ACCEPT
+
+# Persist the rules
+apt install -y iptables-persistent
+netfilter-persistent save
+```
+
+---
+
+## 7. Deploy to Cloudflare Workers (Optional)
+
+For remote access via Cloudflare Workers (without exposing the VM directly):
+
+```bash
+# In the local repository
+cd omnirouteCloud
+npm install
+npx wrangler login
+npx wrangler deploy
+```
+
+See the full documentation at [omnirouteCloud/README.md](../omnirouteCloud/README.md).
+
+---
+
+## Port Summary
+
+| Port | Service | Access |
+| ----- | ----------- | -------------------------- |
+| 22 | SSH | Public (with fail2ban) |
+| 80 | nginx HTTP | Redirect → HTTPS |
+| 443 | nginx HTTPS | Via Cloudflare Proxy |
+| 20128 | OmniRoute | Localhost only (via nginx) |
diff --git a/docs/i18n/da/src/lib/a2a/README.md b/docs/i18n/da/src/lib/a2a/README.md
new file mode 100644
index 0000000000..5c5fee9245
--- /dev/null
+++ b/docs/i18n/da/src/lib/a2a/README.md
@@ -0,0 +1,752 @@
+# OmniRoute A2A Server (Dansk)
+
+🌐 **Languages:** 🇺🇸 [English](../../../../../../src/lib/a2a/README.md) · 🇪🇸 [es](../../../../es/src/lib/a2a/README.md) · 🇫🇷 [fr](../../../../fr/src/lib/a2a/README.md) · 🇩🇪 [de](../../../../de/src/lib/a2a/README.md) · 🇮🇹 [it](../../../../it/src/lib/a2a/README.md) · 🇷🇺 [ru](../../../../ru/src/lib/a2a/README.md) · 🇨🇳 [zh-CN](../../../../zh-CN/src/lib/a2a/README.md) · 🇯🇵 [ja](../../../../ja/src/lib/a2a/README.md) · 🇰🇷 [ko](../../../../ko/src/lib/a2a/README.md) · 🇸🇦 [ar](../../../../ar/src/lib/a2a/README.md) · 🇮🇳 [in](../../../../in/src/lib/a2a/README.md) · 🇹🇭 [th](../../../../th/src/lib/a2a/README.md) · 🇻🇳 [vi](../../../../vi/src/lib/a2a/README.md) · 🇮🇩 [id](../../../../id/src/lib/a2a/README.md) · 🇲🇾 [ms](../../../../ms/src/lib/a2a/README.md) · 🇳🇱 [nl](../../../../nl/src/lib/a2a/README.md) · 🇵🇱 [pl](../../../../pl/src/lib/a2a/README.md) · 🇸🇪 [sv](../../../../sv/src/lib/a2a/README.md) · 🇳🇴 [no](../../../../no/src/lib/a2a/README.md) · 🇩🇰 [da](../../../../da/src/lib/a2a/README.md) · 🇫🇮 [fi](../../../../fi/src/lib/a2a/README.md) · 🇵🇹 [pt](../../../../pt/src/lib/a2a/README.md) · 🇷🇴 [ro](../../../../ro/src/lib/a2a/README.md) · 🇭🇺 [hu](../../../../hu/src/lib/a2a/README.md) · 🇧🇬 [bg](../../../../bg/src/lib/a2a/README.md) · 🇸🇰 [sk](../../../../sk/src/lib/a2a/README.md) · 🇺🇦 [uk-UA](../../../../uk-UA/src/lib/a2a/README.md) · 🇮🇱 [he](../../../../he/src/lib/a2a/README.md) · 🇵🇭 [phi](../../../../phi/src/lib/a2a/README.md) · 🇧🇷 [pt-BR](../../../../pt-BR/src/lib/a2a/README.md) · 🇨🇿 [cs](../../../../cs/src/lib/a2a/README.md)
+
+---
+
+> **Agent-to-Agent Protocol v0.3** — Enables any AI agent to use OmniRoute as an intelligent routing agent via JSON-RPC 2.0.
+
+The A2A Server exposes OmniRoute as a **first-class agent** that other agents can discover, delegate tasks to, and collaborate with using the [A2A Protocol](https://google.github.io/A2A/).
+
+---
+
+## Arkitektur
+
+```
+┌──────────────────────────────────────────────────────────────────┐
+│ Orchestrator Agent │
+│ (LangChain, CrewAI, AutoGen, Custom Agent) │
+└──────────────────────┬───────────────────────────────────────────┘
+ │ 1. GET /.well-known/agent.json (discover)
+ │ 2. POST /a2a (JSON-RPC 2.0)
+ ▼
+┌──────────────────────────────────────────────────────────────────┐
+│ OmniRoute A2A Server │
+│ ┌────────────────┐ ┌────────────────┐ ┌───────────────────┐ │
+│ │ Task Manager │ │ Skill Engine │ │ SSE Streaming │ │
+│ │ (lifecycle) │──│ (registry) │──│ (real-time) │ │
+│ └────────────────┘ └────────┬───────┘ └───────────────────┘ │
+│ │ │
+│ Skills: │ │
+│ ├─ smart-routing ──────────┤ ┌────────────────────────────┐ │
+│ └─ quota-management ───────┘ │ Routing Decision Logger │ │
+│ └────────────────────────────┘ │
+└──────────────────────────────────────────────────────────────────┘
+ │
+ ▼ OmniRoute Gateway (internal)
+ /v1/chat/completions, /api/combos, /api/usage/quota
+```
+
+---
+
+## Kom hurtigt i gang
+
+### Agent Discovery
+
+Every A2A-compatible agent exposes an **Agent Card** at `/.well-known/agent.json`:
+
+```bash
+curl http://localhost:20128/.well-known/agent.json
+```
+
+**Response:**
+
+```json
+{
+ "name": "OmniRoute",
+ "description": "Intelligent AI gateway with auto-routing across 50+ providers",
+ "url": "http://localhost:20128/a2a",
+ "version": "1.8.1",
+ "capabilities": {
+ "streaming": true,
+ "pushNotifications": false
+ },
+ "skills": [
+ {
+ "id": "smart-routing",
+ "name": "Smart Routing",
+ "description": "Routes prompts through OmniRoute intelligent pipeline",
+ "tags": ["routing", "llm", "multi-provider", "cost-optimization"],
+ "examples": [
+ "Write a hello world in Python",
+ "Explain quantum computing using the cheapest provider"
+ ]
+ },
+ {
+ "id": "quota-management",
+ "name": "Quota Management",
+ "description": "Natural-language queries about provider quotas",
+ "tags": ["quota", "analytics", "cost"],
+ "examples": [
+ "Which provider has the most quota remaining?",
+ "Suggest a free combo for coding"
+ ]
+ }
+ ],
+ "authentication": {
+ "schemes": ["bearer"],
+ "apiKeyHeader": "Authorization"
+ }
+}
+```
+
+---
+
+## JSON-RPC 2.0 Methods
+
+### `message/send` — Synchronous Execution
+
+Send a message to a skill and receive the complete response.
+
+```bash
+curl -X POST http://localhost:20128/a2a \
+ -H "Content-Type: application/json" \
+ -H "Authorization: Bearer YOUR_KEY" \
+ -d '{
+ "jsonrpc": "2.0",
+ "id": "1",
+ "method": "message/send",
+ "params": {
+ "skill": "smart-routing",
+ "messages": [{"role": "user", "content": "Write a Python hello world"}],
+ "metadata": {"model": "auto", "combo": "fast-coding"}
+ }
+ }'
+```
+
+**Response:**
+
+```json
+{
+ "jsonrpc": "2.0",
+ "id": "1",
+ "result": {
+ "task": { "id": "a1b2c3d4-...", "state": "completed" },
+ "artifacts": [{ "type": "text", "content": "print('Hello, World!')" }],
+ "metadata": {
+ "routing_explanation": "Selected claude-sonnet via provider \"anthropic\" (latency: 1200ms, cost: $0.0030)",
+ "cost_envelope": { "estimated": 0.005, "actual": 0.003, "currency": "USD" },
+ "resilience_trace": [
+ { "event": "primary_selected", "provider": "anthropic", "timestamp": "2026-03-04T..." }
+ ],
+ "policy_verdict": { "allowed": true, "reason": "within budget and quota limits" }
+ }
+ }
+}
+```
+
+### `message/stream` — SSE Streaming
+
+Same as `message/send` but returns Server-Sent Events for real-time streaming.
+
+```bash
+curl -N -X POST http://localhost:20128/a2a \
+ -H "Content-Type: application/json" \
+ -H "Authorization: Bearer YOUR_KEY" \
+ -d '{
+ "jsonrpc": "2.0",
+ "id": "1",
+ "method": "message/stream",
+ "params": {
+ "skill": "smart-routing",
+ "messages": [{"role": "user", "content": "Explain quantum computing"}]
+ }
+ }'
+```
+
+**SSE Events:**
+
+```
+data: {"jsonrpc":"2.0","method":"message/stream","params":{"task":{"id":"...","state":"working"},"chunk":{"type":"text","content":"Quantum computing..."}}}
+
+: heartbeat 2026-03-04T21:00:00Z
+
+data: {"jsonrpc":"2.0","method":"message/stream","params":{"task":{"id":"...","state":"completed"},"metadata":{...}}}
+```
+
+### `tasks/get` — Query Task Status
+
+```bash
+curl -X POST http://localhost:20128/a2a \
+ -H "Content-Type: application/json" \
+ -H "Authorization: Bearer YOUR_KEY" \
+ -d '{"jsonrpc":"2.0","id":"2","method":"tasks/get","params":{"taskId":"TASK_UUID"}}'
+```
+
+### `tasks/cancel` — Cancel a Running Task
+
+```bash
+curl -X POST http://localhost:20128/a2a \
+ -H "Content-Type: application/json" \
+ -H "Authorization: Bearer YOUR_KEY" \
+ -d '{"jsonrpc":"2.0","id":"3","method":"tasks/cancel","params":{"taskId":"TASK_UUID"}}'
+```
+
+---
+
+## Skills Reference
+
+### `smart-routing`
+
+Routes prompts through OmniRoute's intelligent pipeline with full observability.
+
+**Parameters (in `metadata`):**
+
+| Parameter | Type | Default | Description |
+| --------- | -------- | ------------ | ---------------------------------------------------------------------------------------- |
+| `model` | `string` | `"auto"` | Target model (e.g., `claude-sonnet-4`, `gpt-4o`, `auto`) |
+| `combo` | `string` | active combo | Specific combo to route through |
+| `budget` | `number` | none | Maximum cost in USD for this request |
+| `role` | `string` | none | Task role hint: `coding`, `review`, `planning`, `analysis`, `debugging`, `documentation` |
+
+**Returns:**
+
+| Field | Description |
+| ------------------------------ | --------------------------------------------------------- |
+| `artifacts[].content` | The LLM response text |
+| `metadata.routing_explanation` | Human-readable explanation of routing decision |
+| `metadata.cost_envelope` | Estimated vs actual cost with currency |
+| `metadata.resilience_trace` | Array of events (primary_selected, fallback_needed, etc.) |
+| `metadata.policy_verdict` | Whether the request was allowed and why |
+
+### `quota-management`
+
+Answers natural-language queries about provider quotas.
+
+**Query types (inferred from message content):**
+
+| Query Pattern | Response Type |
+| ---------------------------------------------- | -------------------------------------------------------- |
+| Contains `"ranking"`, `"most quota"`, `"best"` | Providers ranked by remaining quota |
+| Contains `"free"`, `"suggest"` | Lists free combos or suggests free-tier providers |
+| Default | Full quota summary with warnings for low-quota providers |
+
+---
+
+## Task Lifecycle
+
+```
+submitted ──→ working ──→ completed
+ ──→ failed
+ ──────────→ cancelled
+```
+
+| State | Description |
+| ----------- | ----------------------------------------------------- |
+| `submitted` | Task created, queued for execution |
+| `working` | Skill handler is executing |
+| `completed` | Execution succeeded, artifacts available |
+| `failed` | Execution failed or task expired (TTL: 5 min default) |
+| `cancelled` | Cancelled by client via `tasks/cancel` |
+
+- Terminal states: `completed`, `failed`, `cancelled` (no further transitions)
+- Expired tasks in `submitted` or `working` are auto-marked as `failed`
+- Tasks are garbage-collected after 2× TTL
+
+---
+
+## Client Examples
+
+### Python — Orchestrator Agent
+
+```python
+"""
+A2A Client — Python example.
+Discovers OmniRoute agent, sends a task, and processes the result.
+"""
+import requests
+import json
+
+BASE_URL = "http://localhost:20128"
+API_KEY = "your-api-key"
+HEADERS = {
+ "Content-Type": "application/json",
+ "Authorization": f"Bearer {API_KEY}",
+}
+
+# 1. Discover agent capabilities
+agent_card = requests.get(f"{BASE_URL}/.well-known/agent.json").json()
+print(f"Agent: {agent_card['name']} v{agent_card['version']}")
+print(f"Skills: {[s['id'] for s in agent_card['skills']]}")
+
+# 2. Send a smart-routing task
+response = requests.post(f"{BASE_URL}/a2a", headers=HEADERS, json={
+ "jsonrpc": "2.0",
+ "id": "task-1",
+ "method": "message/send",
+ "params": {
+ "skill": "smart-routing",
+ "messages": [{"role": "user", "content": "Write a Python quicksort implementation"}],
+ "metadata": {
+ "model": "auto",
+ "combo": "fast-coding",
+ "budget": 0.10,
+ }
+ }
+})
+result = response.json()["result"]
+print(f"\n📝 Response: {result['artifacts'][0]['content'][:200]}...")
+print(f"🔀 Routing: {result['metadata']['routing_explanation']}")
+print(f"💰 Cost: ${result['metadata']['cost_envelope']['actual']}")
+print(f"🛡️ Policy: {result['metadata']['policy_verdict']['reason']}")
+
+# 3. Query quota status
+quota_resp = requests.post(f"{BASE_URL}/a2a", headers=HEADERS, json={
+ "jsonrpc": "2.0",
+ "id": "task-2",
+ "method": "message/send",
+ "params": {
+ "skill": "quota-management",
+ "messages": [{"role": "user", "content": "Which provider has the most quota remaining?"}],
+ }
+})
+quota_result = quota_resp.json()["result"]
+print(f"\n📊 Quota: {quota_result['artifacts'][0]['content']}")
+```
+
+### TypeScript — Multi-Agent Orchestrator
+
+```typescript
+/**
+ * A2A Client — TypeScript example.
+ * Shows agent discovery, task delegation, and streaming.
+ */
+
+const BASE_URL = "http://localhost:20128";
+const API_KEY = "your-api-key";
+
+interface JsonRpcResponse {
+ jsonrpc: "2.0";
+ id: string | number;
+ result?: T;
+ error?: { code: number; message: string };
+}
+
+async function a2aCall(method: string, params: Record): Promise {
+ const resp = await fetch(`${BASE_URL}/a2a`, {
+ method: "POST",
+ headers: {
+ "Content-Type": "application/json",
+ Authorization: `Bearer ${API_KEY}`,
+ },
+ body: JSON.stringify({
+ jsonrpc: "2.0",
+ id: `${method}-${Date.now()}`,
+ method,
+ params,
+ }),
+ });
+ const json: JsonRpcResponse = await resp.json();
+ if (json.error) throw new Error(`[${json.error.code}] ${json.error.message}`);
+ return json.result!;
+}
+
+// ── Agent Discovery ──
+const agentCard = await fetch(`${BASE_URL}/.well-known/agent.json`).then((r) => r.json());
+console.log(`Connected to: ${agentCard.name} (${agentCard.skills.length} skills)`);
+
+// ── Smart Routing: Send a coding task ──
+const routingResult = await a2aCall("message/send", {
+ skill: "smart-routing",
+ messages: [{ role: "user", content: "Implement a Redis cache wrapper in TypeScript" }],
+ metadata: { model: "claude-sonnet-4", role: "coding" },
+});
+console.log("Response:", routingResult.artifacts[0].content);
+console.log("Provider:", routingResult.metadata.routing_explanation);
+
+// ── Quota Management: Find free alternatives ──
+const quotaResult = await a2aCall("message/send", {
+ skill: "quota-management",
+ messages: [{ role: "user", content: "Suggest free combos for documentation" }],
+});
+console.log("Free combos:", quotaResult.artifacts[0].content);
+
+// ── Streaming: Real-time response ──
+const streamResp = await fetch(`${BASE_URL}/a2a`, {
+ method: "POST",
+ headers: {
+ "Content-Type": "application/json",
+ Authorization: `Bearer ${API_KEY}`,
+ },
+ body: JSON.stringify({
+ jsonrpc: "2.0",
+ id: "stream-1",
+ method: "message/stream",
+ params: {
+ skill: "smart-routing",
+ messages: [{ role: "user", content: "Explain microservices architecture" }],
+ },
+ }),
+});
+
+const reader = streamResp.body!.getReader();
+const decoder = new TextDecoder();
+while (true) {
+ const { done, value } = await reader.read();
+ if (done) break;
+ const chunk = decoder.decode(value);
+ for (const line of chunk.split("\n")) {
+ if (line.startsWith("data: ")) {
+ const event = JSON.parse(line.slice(6));
+ if (event.params.chunk) {
+ process.stdout.write(event.params.chunk.content);
+ }
+ if (event.params.task.state === "completed") {
+ console.log("\n✅ Stream completed");
+ }
+ }
+ }
+}
+```
+
+### Python — LangChain A2A Integration
+
+```python
+"""
+LangChain integration — Use OmniRoute A2A as a custom LLM.
+"""
+from langchain.llms.base import BaseLLM
+from langchain.schema import LLMResult, Generation
+import requests
+from typing import List, Optional
+
+class OmniRouteA2A(BaseLLM):
+ base_url: str = "http://localhost:20128"
+ api_key: str = ""
+ model: str = "auto"
+ combo: Optional[str] = None
+
+ @property
+ def _llm_type(self) -> str:
+ return "omniroute-a2a"
+
+ def _call(self, prompt: str, stop: Optional[List[str]] = None, **kwargs) -> str:
+ response = requests.post(
+ f"{self.base_url}/a2a",
+ headers={
+ "Content-Type": "application/json",
+ "Authorization": f"Bearer {self.api_key}",
+ },
+ json={
+ "jsonrpc": "2.0",
+ "id": "langchain-1",
+ "method": "message/send",
+ "params": {
+ "skill": "smart-routing",
+ "messages": [{"role": "user", "content": prompt}],
+ "metadata": {
+ "model": self.model,
+ **({"combo": self.combo} if self.combo else {}),
+ },
+ },
+ },
+ )
+ result = response.json()["result"]
+ return result["artifacts"][0]["content"]
+
+ def _generate(self, prompts: List[str], stop=None, **kwargs) -> LLMResult:
+ return LLMResult(
+ generations=[[Generation(text=self._call(p, stop))] for p in prompts]
+ )
+
+# Usage
+llm = OmniRouteA2A(
+ base_url="http://localhost:20128",
+ api_key="your-key",
+ model="auto",
+ combo="fast-coding",
+)
+result = llm("Write a Python function to merge two sorted lists")
+print(result)
+```
+
+### Go — A2A Client
+
+```go
+package main
+
+import (
+ "bytes"
+ "encoding/json"
+ "fmt"
+ "io"
+ "net/http"
+)
+
+const baseURL = "http://localhost:20128"
+const apiKey = "your-api-key"
+
+type JsonRpcRequest struct {
+ Jsonrpc string `json:"jsonrpc"`
+ ID string `json:"id"`
+ Method string `json:"method"`
+ Params interface{} `json:"params"`
+}
+
+type JsonRpcResponse struct {
+ Jsonrpc string `json:"jsonrpc"`
+ ID string `json:"id"`
+ Result interface{} `json:"result"`
+ Error *struct {
+ Code int `json:"code"`
+ Message string `json:"message"`
+ } `json:"error"`
+}
+
+func a2aCall(method string, params interface{}) (*JsonRpcResponse, error) {
+ body, _ := json.Marshal(JsonRpcRequest{
+ Jsonrpc: "2.0",
+ ID: "go-1",
+ Method: method,
+ Params: params,
+ })
+
+ req, _ := http.NewRequest("POST", baseURL+"/a2a", bytes.NewReader(body))
+ req.Header.Set("Content-Type", "application/json")
+ req.Header.Set("Authorization", "Bearer "+apiKey)
+
+ resp, err := http.DefaultClient.Do(req)
+ if err != nil {
+ return nil, err
+ }
+ defer resp.Body.Close()
+ data, _ := io.ReadAll(resp.Body)
+
+ var result JsonRpcResponse
+ json.Unmarshal(data, &result)
+ return &result, nil
+}
+
+func main() {
+ // Discover agent
+ resp, _ := http.Get(baseURL + "/.well-known/agent.json")
+ defer resp.Body.Close()
+ body, _ := io.ReadAll(resp.Body)
+ fmt.Println("Agent Card:", string(body))
+
+ // Send smart-routing task
+ result, _ := a2aCall("message/send", map[string]interface{}{
+ "skill": "smart-routing",
+ "messages": []map[string]string{{"role": "user", "content": "Hello from Go!"}},
+ "metadata": map[string]interface{}{"model": "auto"},
+ })
+ out, _ := json.MarshalIndent(result.Result, "", " ")
+ fmt.Println("Result:", string(out))
+}
+```
+
+---
+
+## Use Cases
+
+### 🤖 Use Case 1: Multi-Agent Coding Pipeline
+
+An orchestrator agent delegates code generation to OmniRoute, then passes the output to a review agent.
+
+```python
+def coding_pipeline(task: str):
+ # Step 1: Generate code via OmniRoute A2A
+ code_result = a2a_send("smart-routing", [
+ {"role": "user", "content": f"Write production-quality code: {task}"}
+ ], metadata={"model": "auto", "role": "coding"})
+ code = code_result["artifacts"][0]["content"]
+
+ # Step 2: Review the code via OmniRoute A2A (different model)
+ review_result = a2a_send("smart-routing", [
+ {"role": "user", "content": f"Review this code for bugs and improvements:\n\n{code}"}
+ ], metadata={"model": "auto", "role": "review"})
+ review = review_result["artifacts"][0]["content"]
+
+ # Step 3: Check costs
+ print(f"Code cost: ${code_result['metadata']['cost_envelope']['actual']}")
+ print(f"Review cost: ${review_result['metadata']['cost_envelope']['actual']}")
+
+ return {"code": code, "review": review}
+```
+
+### 💡 Use Case 2: Quota-Aware Agent Swarm
+
+Multiple agents share quota through OmniRoute, using the quota skill to coordinate.
+
+```python
+async def quota_aware_agent(agent_name: str, task: str):
+ # Check quota before starting
+ quota = a2a_send("quota-management", [
+ {"role": "user", "content": "Which provider has the most quota remaining?"}
+ ])
+ print(f"[{agent_name}] {quota['artifacts'][0]['content']}")
+
+ # Send request with budget constraint
+ result = a2a_send("smart-routing", [
+ {"role": "user", "content": task}
+ ], metadata={"budget": 0.05})
+
+ policy = result["metadata"]["policy_verdict"]
+ if not policy["allowed"]:
+ print(f"[{agent_name}] ⚠️ Budget exceeded: {policy['reason']}")
+ # Fall back to free combo
+ quota = a2a_send("quota-management", [
+ {"role": "user", "content": "Suggest free combos"}
+ ])
+ print(f"[{agent_name}] Free alternatives: {quota['artifacts'][0]['content']}")
+
+ return result
+```
+
+### 📊 Use Case 3: Real-Time Streaming Dashboard
+
+A monitoring agent streams responses and displays progress in real-time.
+
+```typescript
+async function streamingDashboard(prompt: string) {
+ const response = await fetch(`${BASE_URL}/a2a`, {
+ method: "POST",
+ headers: { "Content-Type": "application/json", Authorization: `Bearer ${API_KEY}` },
+ body: JSON.stringify({
+ jsonrpc: "2.0",
+ id: "dash-1",
+ method: "message/stream",
+ params: { skill: "smart-routing", messages: [{ role: "user", content: prompt }] },
+ }),
+ });
+
+ let totalChunks = 0;
+ const reader = response.body!.getReader();
+ const decoder = new TextDecoder();
+
+ while (true) {
+ const { done, value } = await reader.read();
+ if (done) break;
+
+ for (const line of decoder.decode(value).split("\n")) {
+ if (line.startsWith("data: ")) {
+ const event = JSON.parse(line.slice(6));
+ const state = event.params.task.state;
+
+ if (state === "working" && event.params.chunk) {
+ totalChunks++;
+ process.stdout.write(
+ `\r[Chunk ${totalChunks}] ${event.params.chunk.content.slice(0, 50)}...`
+ );
+ }
+ if (state === "completed") {
+ const meta = event.params.metadata;
+ console.log(
+ `\n✅ Done | Cost: $${meta?.cost_envelope?.actual || 0} | Route: ${meta?.routing_explanation || "N/A"}`
+ );
+ }
+ if (state === "failed") {
+ console.error(`\n❌ Failed: ${event.params.metadata?.error}`);
+ }
+ }
+ }
+ }
+}
+```
+
+### 🔁 Use Case 4: Task Polling Pattern
+
+For long-running tasks, poll the task status instead of waiting synchronously.
+
+```python
+import time
+
+def poll_task(task_id: str, timeout: int = 60):
+ """Poll task status until completion or timeout."""
+ start = time.time()
+ while time.time() - start < timeout:
+ result = requests.post(f"{BASE_URL}/a2a", headers=HEADERS, json={
+ "jsonrpc": "2.0",
+ "id": "poll-1",
+ "method": "tasks/get",
+ "params": {"taskId": task_id},
+ }).json()
+
+ task = result["result"]["task"]
+ state = task["state"]
+ print(f" Task {task_id[:8]}... state={state}")
+
+ if state in ("completed", "failed", "cancelled"):
+ return task
+ time.sleep(2)
+
+ # Timeout — cancel the task
+ requests.post(f"{BASE_URL}/a2a", headers=HEADERS, json={
+ "jsonrpc": "2.0",
+ "id": "cancel-1",
+ "method": "tasks/cancel",
+ "params": {"taskId": task_id},
+ })
+ raise TimeoutError(f"Task {task_id} timed out after {timeout}s")
+```
+
+---
+
+## Error Codes
+
+| Code | Constant | Meaning |
+| ------ | ------------------------ | ---------------------------------------- |
+| -32700 | — | Parse error (invalid JSON) |
+| -32600 | `INVALID_REQUEST` | Invalid JSON-RPC request or unauthorized |
+| -32601 | `METHOD_NOT_FOUND` | Unknown method or skill |
+| -32602 | `INVALID_PARAMS` | Missing or invalid parameters |
+| -32603 | `INTERNAL_ERROR` | Skill execution failed |
+| -32001 | `TASK_NOT_FOUND` | Task ID not found |
+| -32002 | `TASK_ALREADY_COMPLETED` | Cannot modify a completed task |
+| -32003 | `UNAUTHORIZED` | Invalid or missing API key |
+| -32004 | `BUDGET_EXCEEDED` | Request exceeds configured budget |
+| -32005 | `PROVIDER_UNAVAILABLE` | No available providers |
+
+---
+
+## Authentication
+
+All `/a2a` requests require a Bearer token via the `Authorization` header:
+
+```
+Authorization: Bearer YOUR_OMNIROUTE_API_KEY
+```
+
+If no API key is configured on the server (`OMNIROUTE_API_KEY` is empty), authentication is bypassed.
+
+---
+
+## File Structure
+
+```
+src/lib/a2a/
+├── taskManager.ts # Task lifecycle (create/update/cancel/list), TTL, cleanup
+├── taskExecution.ts # Generic task executor with state management
+├── streaming.ts # SSE stream formatting, heartbeat, chunk/completion events
+├── routingLogger.ts # Routing decision logger (stats, history, retention)
+└── skills/
+ ├── smartRouting.ts # Smart routing skill (routes via /v1/chat/completions)
+ └── quotaManagement.ts # Quota management skill (natural-language quota queries)
+
+src/app/a2a/
+└── route.ts # Next.js API route handler (JSON-RPC 2.0 dispatch)
+
+open-sse/mcp-server/
+└── schemas/a2a.ts # Zod schemas (AgentCard, Task, JSON-RPC, SSE events)
+```
+
+---
+
+## Comparison: MCP vs A2A
+
+| Feature | MCP Server | A2A Server |
+| ----------------- | ---------------------------- | ------------------------------------------------- |
+| **Protocol** | Model Context Protocol | Agent-to-Agent Protocol v0.3 |
+| **Transport** | stdio / HTTP | HTTP (JSON-RPC 2.0) |
+| **Discovery** | Tool listing via MCP | `/.well-known/agent.json` |
+| **Granularity** | 16 individual tools | 2 high-level skills |
+| **Best for** | IDE agents (Cursor, VS Code) | Multi-agent systems (LangChain, CrewAI) |
+| **Streaming** | Not supported | SSE via `message/stream` |
+| **Task tracking** | No | Full lifecycle (submitted → completed) |
+| **Observability** | Audit log per tool call | Cost envelope + resilience trace + policy verdict |
+
+---
+
+## Licens
+
+Part of [OmniRoute](https://github.com/diegosouzapw/OmniRoute) — MIT License.
diff --git a/docs/i18n/de/CHANGELOG.md b/docs/i18n/de/CHANGELOG.md
index 0dbc256214..ae7ea387c4 100644
--- a/docs/i18n/de/CHANGELOG.md
+++ b/docs/i18n/de/CHANGELOG.md
@@ -1,12 +1,92 @@
# Changelog (Deutsch)
-🌐 **Languages:** 🇺🇸 [English](../../../CHANGELOG.md) · 🇪🇸 [es](../es/CHANGELOG.md) · 🇫🇷 [fr](../fr/CHANGELOG.md) · 🇩🇪 [de](../de/CHANGELOG.md) · 🇮🇹 [it](../it/CHANGELOG.md) · 🇷🇺 [ru](../ru/CHANGELOG.md) · 🇨🇳 [zh-CN](../zh-CN/CHANGELOG.md) · 🇯🇵 [ja](../ja/CHANGELOG.md) · 🇰🇷 [ko](../ko/CHANGELOG.md) · 🇸🇦 [ar](../ar/CHANGELOG.md) · 🇮🇳 [in](../in/CHANGELOG.md) · 🇹🇭 [th](../th/CHANGELOG.md) · 🇻🇳 [vi](../vi/CHANGELOG.md) · 🇮🇩 [id](../id/CHANGELOG.md) · 🇲🇾 [ms](../ms/CHANGELOG.md) · 🇳🇱 [nl](../nl/CHANGELOG.md) · 🇵🇱 [pl](../pl/CHANGELOG.md) · 🇸🇪 [sv](../sv/CHANGELOG.md) · 🇳🇴 [no](../no/CHANGELOG.md) · 🇩🇰 [da](../da/CHANGELOG.md) · 🇫🇮 [fi](../fi/CHANGELOG.md) · 🇵🇹 [pt](../pt/CHANGELOG.md) · 🇷🇴 [ro](../ro/CHANGELOG.md) · 🇭🇺 [hu](../hu/CHANGELOG.md) · 🇧🇬 [bg](../bg/CHANGELOG.md) · 🇸🇰 [sk](../sk/CHANGELOG.md) · 🇺🇦 [uk-UA](../uk-UA/CHANGELOG.md) · 🇮🇱 [he](../he/CHANGELOG.md) · 🇵🇭 [phi](../phi/CHANGELOG.md) · 🇧🇷 [pt-BR](../pt-BR/CHANGELOG.md)
+🌐 **Languages:** 🇺🇸 [English](../../../CHANGELOG.md) · 🇪🇸 [es](../es/CHANGELOG.md) · 🇫🇷 [fr](../fr/CHANGELOG.md) · 🇩🇪 [de](../de/CHANGELOG.md) · 🇮🇹 [it](../it/CHANGELOG.md) · 🇷🇺 [ru](../ru/CHANGELOG.md) · 🇨🇳 [zh-CN](../zh-CN/CHANGELOG.md) · 🇯🇵 [ja](../ja/CHANGELOG.md) · 🇰🇷 [ko](../ko/CHANGELOG.md) · 🇸🇦 [ar](../ar/CHANGELOG.md) · 🇮🇳 [in](../in/CHANGELOG.md) · 🇹🇭 [th](../th/CHANGELOG.md) · 🇻🇳 [vi](../vi/CHANGELOG.md) · 🇮🇩 [id](../id/CHANGELOG.md) · 🇲🇾 [ms](../ms/CHANGELOG.md) · 🇳🇱 [nl](../nl/CHANGELOG.md) · 🇵🇱 [pl](../pl/CHANGELOG.md) · 🇸🇪 [sv](../sv/CHANGELOG.md) · 🇳🇴 [no](../no/CHANGELOG.md) · 🇩🇰 [da](../da/CHANGELOG.md) · 🇫🇮 [fi](../fi/CHANGELOG.md) · 🇵🇹 [pt](../pt/CHANGELOG.md) · 🇷🇴 [ro](../ro/CHANGELOG.md) · 🇭🇺 [hu](../hu/CHANGELOG.md) · 🇧🇬 [bg](../bg/CHANGELOG.md) · 🇸🇰 [sk](../sk/CHANGELOG.md) · 🇺🇦 [uk-UA](../uk-UA/CHANGELOG.md) · 🇮🇱 [he](../he/CHANGELOG.md) · 🇵🇭 [phi](../phi/CHANGELOG.md) · 🇧🇷 [pt-BR](../pt-BR/CHANGELOG.md) · 🇨🇿 [cs](../cs/CHANGELOG.md)
---
-
## [Unreleased]
+### 🛠️ Maintenance
+
+- **AGENTS.md rewrite:** Condensed from 297→153 lines. Added build/lint/test commands (including single-test execution), code style guidelines (Prettier, TypeScript, ESLint, naming, imports, error handling, security), and trimmed verbose architecture tables for AI agent consumption.
+
+## [3.4.2] - 2026-04-01
+
+### 🐛 Bug Fixes
+
+- **CI Stabilization:** Fixed failing analytics/settings Playwright selectors and request assertions so GitHub Actions E2E runs pass reliably across localized UIs and switch-based controls.
+- **Deterministic Tests:** Removed date-sensitive quota fixtures from Copilot usage tests and aligned idempotency/model catalog tests with the merged runtime behavior.
+- **MCP Type Hardening:** Removed zero-budget explicit `any` regressions from the MCP server tool registration path, restoring the `check:any-budget:t11` workflow gate.
+
+### 🛠️ Maintenance
+
+- **Release Branch Integration:** Consolidated the active feature branches into `release/v3.4.2` on top of current `main` and validated the branch with lint, unit, coverage, build, and CI-mode E2E runs.
+
+## [3.4.1] - 2026-03-31
+
+> [!WARNING]
+> **BREAKING CHANGE: request logging, retention, and logging environment variables have been redesigned.**
+> On the first startup after upgrading, OmniRoute archives legacy request logs from `DATA_DIR/logs/`, legacy `DATA_DIR/call_logs/`, and `DATA_DIR/log.txt` into `DATA_DIR/log_archives/*.zip`, then removes the deprecated layout and switches to the new unified artifact format under `DATA_DIR/call_logs/`.
+
+### ✨ New Features
+
+- **.ENV Migration Utility:** Included `scripts/migrate-env.mjs` to seamlessly migrate `= 18 < 24 (recommended: 22 LTS)
+- **npm** 10+
+- **Git**
+
+### Clone & Install
+
+```bash
+git clone https://github.com/diegosouzapw/OmniRoute.git
+cd OmniRoute
+npm install
+```
+
+### Environment Variables
+
+```bash
+# Create your .env from the template
+cp .env.example .env
+
+# Generate required secrets
+echo "JWT_SECRET=$(openssl rand -base64 48)" >> .env
+echo "API_KEY_SECRET=$(openssl rand -hex 32)" >> .env
+```
+
+Key variables for development:
+
+| Variable | Development Default | Description |
+| ---------------------- | ------------------------ | --------------------- |
+| `PORT` | `20128` | Server port |
+| `NEXT_PUBLIC_BASE_URL` | `http://localhost:20128` | Base URL for frontend |
+| `JWT_SECRET` | (generate above) | JWT signing secret |
+| `INITIAL_PASSWORD` | `CHANGEME` | First login password |
+| `APP_LOG_LEVEL` | `info` | Log verbosity level |
+
+### Dashboard Settings
+
+The dashboard provides UI toggles for features that can also be configured via environment variables:
+
+| Setting Location | Toggle | Description |
+| ------------------- | ------------------ | ------------------------------ |
+| Settings → Advanced | Debug Mode | Enable debug request logs (UI) |
+| Settings → General | Sidebar Visibility | Show/hide sidebar sections |
+
+These settings are stored in the database and persist across restarts, overriding env var defaults when set.
+
+### Running Locally
+
+```bash
+# Development mode (hot reload)
+npm run dev
+
+# Production build
+npm run build
+npm run start
+
+# Common port configuration
+PORT=20128 NEXT_PUBLIC_BASE_URL=http://localhost:20128 npm run dev
+```
+
+Default URLs:
+
+- **Dashboard**: `http://localhost:20128/dashboard`
+- **API**: `http://localhost:20128/v1`
+
+---
+
+## Git Workflow
+
+> ⚠️ **NEVER commit directly to `main`.** Always use feature branches.
+
+```bash
+git checkout -b feat/your-feature-name
+# ... make changes ...
+git commit -m "feat: describe your change"
+git push -u origin feat/your-feature-name
+# Open a Pull Request on GitHub
+```
+
+### Branch Naming
+
+| Prefix | Purpose |
+| ----------- | ------------------------- |
+| `feat/` | New features |
+| `fix/` | Bug fixes |
+| `refactor/` | Code restructuring |
+| `docs/` | Documentation changes |
+| `test/` | Test additions/fixes |
+| `chore/` | Tooling, CI, dependencies |
+
+### Commit Messages
+
+Follow [Conventional Commits](https://www.conventionalcommits.org/):
+
+```
+feat: add circuit breaker for provider calls
+fix: resolve JWT secret validation edge case
+docs: update SECURITY.md with PII protection
+test: add observability unit tests
+refactor(db): consolidate rate limit tables
+```
+
+Scopes: `db`, `sse`, `oauth`, `dashboard`, `api`, `cli`, `docker`, `ci`, `mcp`, `a2a`, `memory`, `skills`.
+
+---
+
+## Running Tests
+
+```bash
+# All tests (unit + vitest + ecosystem + e2e)
+npm run test:all
+
+# Single test file (Node.js native test runner — most tests use this)
+node --import tsx/esm --test tests/unit/your-file.test.mjs
+
+# Vitest (MCP server, autoCombo, cache)
+npm run test:vitest
+
+# E2E tests (requires Playwright)
+npm run test:e2e
+
+# Protocol clients E2E (MCP transports, A2A)
+npm run test:protocols:e2e
+
+# Ecosystem compatibility tests
+npm run test:ecosystem
+
+# Coverage (55% min statements/lines/functions; 60% branches)
+npm run test:coverage
+npm run coverage:report
+
+# Lint + format check
+npm run lint
+npm run check
+```
+
+Coverage notes:
+
+- `npm run test:coverage` measures source coverage for the main unit test suite, excludes `tests/**`, and includes `open-sse/**`
+- `npm run coverage:report` prints the detailed file-by-file report from the latest coverage run
+- `npm run test:coverage:legacy` preserves the older metric for historical comparison
+- See `docs/COVERAGE_PLAN.md` for the phased coverage improvement roadmap
+
+Current test status: **122 unit test files** covering:
+
+- Provider translators and format conversion
+- Rate limiting, circuit breaker, and resilience
+- Semantic cache, idempotency, progress tracking
+- Database operations and schema (21 DB modules)
+- OAuth flows and authentication
+- API endpoint validation (Zod v4)
+- MCP server tools and scope enforcement
+- Memory and Skills systems
+
+---
+
+## Code Style
+
+- **ESLint** — Run `npm run lint` before committing
+- **Prettier** — Auto-formatted via `lint-staged` on commit (2 spaces, semicolons, double quotes, 100 char width, es5 trailing commas)
+- **TypeScript** — All `src/` code uses `.ts`/`.tsx`; `open-sse/` uses `.ts`/`.js`; document with TSDoc (`@param`, `@returns`, `@throws`)
+- **No `eval()`** — ESLint enforces `no-eval`, `no-implied-eval`, `no-new-func`
+- **Zod validation** — Use Zod v4 schemas for all API input validation
+- **Naming**: Files = camelCase/kebab-case, components = PascalCase, constants = UPPER_SNAKE
+
+---
+
+## Project Structure
+
+```
+src/ # TypeScript (.ts / .tsx)
+├── app/ # Next.js 16 App Router
+│ ├── (dashboard)/ # Dashboard pages (23 sections)
+│ ├── api/ # API routes (51 directories)
+│ └── login/ # Auth pages (.tsx)
+├── domain/ # Policy engine (policyEngine, comboResolver, costRules, etc.)
+├── lib/ # Core business logic (.ts)
+│ ├── a2a/ # Agent-to-Agent v0.3 protocol server
+│ ├── acp/ # Agent Communication Protocol registry
+│ ├── compliance/ # Compliance policy engine
+│ ├── db/ # SQLite database layer (21 modules + 16 migrations)
+│ ├── memory/ # Persistent conversational memory
+│ ├── oauth/ # OAuth providers, services, and utilities
+│ ├── skills/ # Extensible skill framework
+│ ├── usage/ # Usage tracking and cost calculation
+│ └── localDb.ts # Re-export layer only — never add logic here
+├── middleware/ # Request middleware (promptInjectionGuard)
+├── mitm/ # MITM proxy (cert, DNS, target routing)
+├── shared/
+│ ├── components/ # React components (.tsx)
+│ ├── constants/ # Provider definitions (60+), MCP scopes, routing strategies
+│ ├── utils/ # Circuit breaker, sanitizer, auth helpers
+│ └── validation/ # Zod v4 schemas
+└── sse/ # SSE proxy pipeline
+
+open-sse/ # @omniroute/open-sse workspace
+├── executors/ # 14 provider-specific request executors
+├── handlers/ # 11 request handlers (chat, responses, embeddings, images, etc.)
+├── mcp-server/ # MCP server (25 tools, 3 transports, 10 scopes)
+├── services/ # 36+ services (combo, autoCombo, rateLimitManager, etc.)
+├── translator/ # Format translators (OpenAI ↔ Claude ↔ Gemini ↔ Responses ↔ Ollama)
+├── transformer/ # Responses API transformer
+└── utils/ # 22 utility modules (stream, TLS, proxy, logging)
+
+electron/ # Electron desktop app (cross-platform)
+
+tests/
+├── unit/ # Node.js test runner (122 test files)
+├── integration/ # Integration tests
+├── e2e/ # Playwright tests
+├── security/ # Security tests
+├── translator/ # Translator-specific tests
+└── load/ # Load tests
+
+docs/ # Documentation
+├── ARCHITECTURE.md # System architecture
+├── API_REFERENCE.md # All endpoints
+├── USER_GUIDE.md # Provider setup, CLI integration
+├── TROUBLESHOOTING.md # Common issues
+├── MCP-SERVER.md # MCP server (25 tools)
+├── A2A-SERVER.md # A2A agent protocol
+├── AUTO-COMBO.md # Auto-combo engine
+├── CLI-TOOLS.md # CLI tools integration
+├── COVERAGE_PLAN.md # Test coverage improvement plan
+├── openapi.yaml # OpenAPI specification
+└── adr/ # Architecture Decision Records
+```
+
+---
+
+## Adding a New Provider
+
+### Step 1: Register Provider Constants
+
+Add to `src/shared/constants/providers.ts` — Zod-validated at module load.
+
+### Step 2: Add Executor (if custom logic needed)
+
+Create executor in `open-sse/executors/your-provider.ts` extending the base executor.
+
+### Step 3: Add Translator (if non-OpenAI format)
+
+Create request/response translators in `open-sse/translator/`.
+
+### Step 4: Add OAuth Config (if OAuth-based)
+
+Add OAuth credentials in `src/lib/oauth/constants/oauth.ts` and service in `src/lib/oauth/services/`.
+
+### Step 5: Register Models
+
+Add model definitions in `open-sse/config/providerRegistry.ts`.
+
+### Step 6: Add Tests
+
+Write unit tests in `tests/unit/` covering at minimum:
+
+- Provider registration
+- Request/response translation
+- Error handling
+
+---
+
+## Pull Request Checklist
+
+- [ ] Tests pass (`npm test`)
+- [ ] Linting passes (`npm run lint`)
+- [ ] Build succeeds (`npm run build`)
+- [ ] TypeScript types added for new public functions and interfaces
+- [ ] No hardcoded secrets or fallback values
+- [ ] All inputs validated with Zod schemas
+- [ ] CHANGELOG updated (if user-facing change)
+- [ ] Documentation updated (if applicable)
+
+---
+
+## Releasing
+
+Releases are managed via the `/generate-release` workflow. When a new GitHub Release is created, the package is **automatically published to npm** via GitHub Actions.
+
+---
+
+## Getting Help
+
+- **Architecture**: See [`docs/ARCHITECTURE.md`](docs/ARCHITECTURE.md)
+- **API Reference**: See [`docs/API_REFERENCE.md`](docs/API_REFERENCE.md)
+- **Issues**: [github.com/diegosouzapw/OmniRoute/issues](https://github.com/diegosouzapw/OmniRoute/issues)
+- **ADRs**: See `docs/adr/` for architectural decision records
diff --git a/docs/i18n/de/README.md b/docs/i18n/de/README.md
index 63ff06475d..d6311e4947 100644
--- a/docs/i18n/de/README.md
+++ b/docs/i18n/de/README.md
@@ -1,13 +1,12 @@
# 🚀 OmniRoute — The Free AI Gateway (Deutsch)
-🌐 **Languages:** 🇺🇸 [English](../../../README.md) · 🇪🇸 [es](../es/README.md) · 🇫🇷 [fr](../fr/README.md) · 🇩🇪 [de](../de/README.md) · 🇮🇹 [it](../it/README.md) · 🇷🇺 [ru](../ru/README.md) · 🇨🇳 [zh-CN](../zh-CN/README.md) · 🇯🇵 [ja](../ja/README.md) · 🇰🇷 [ko](../ko/README.md) · 🇸🇦 [ar](../ar/README.md) · 🇮🇳 [in](../in/README.md) · 🇹🇭 [th](../th/README.md) · 🇻🇳 [vi](../vi/README.md) · 🇮🇩 [id](../id/README.md) · 🇲🇾 [ms](../ms/README.md) · 🇳🇱 [nl](../nl/README.md) · 🇵🇱 [pl](../pl/README.md) · 🇸🇪 [sv](../sv/README.md) · 🇳🇴 [no](../no/README.md) · 🇩🇰 [da](../da/README.md) · 🇫🇮 [fi](../fi/README.md) · 🇵🇹 [pt](../pt/README.md) · 🇷🇴 [ro](../ro/README.md) · 🇭🇺 [hu](../hu/README.md) · 🇧🇬 [bg](../bg/README.md) · 🇸🇰 [sk](../sk/README.md) · 🇺🇦 [uk-UA](../uk-UA/README.md) · 🇮🇱 [he](../he/README.md) · 🇵🇭 [phi](../phi/README.md) · 🇧🇷 [pt-BR](../pt-BR/README.md)
+🌐 **Languages:** 🇺🇸 [English](../../../README.md) · 🇪🇸 [es](../es/README.md) · 🇫🇷 [fr](../fr/README.md) · 🇩🇪 [de](../de/README.md) · 🇮🇹 [it](../it/README.md) · 🇷🇺 [ru](../ru/README.md) · 🇨🇳 [zh-CN](../zh-CN/README.md) · 🇯🇵 [ja](../ja/README.md) · 🇰🇷 [ko](../ko/README.md) · 🇸🇦 [ar](../ar/README.md) · 🇮🇳 [in](../in/README.md) · 🇹🇭 [th](../th/README.md) · 🇻🇳 [vi](../vi/README.md) · 🇮🇩 [id](../id/README.md) · 🇲🇾 [ms](../ms/README.md) · 🇳🇱 [nl](../nl/README.md) · 🇵🇱 [pl](../pl/README.md) · 🇸🇪 [sv](../sv/README.md) · 🇳🇴 [no](../no/README.md) · 🇩🇰 [da](../da/README.md) · 🇫🇮 [fi](../fi/README.md) · 🇵🇹 [pt](../pt/README.md) · 🇷🇴 [ro](../ro/README.md) · 🇭🇺 [hu](../hu/README.md) · 🇧🇬 [bg](../bg/README.md) · 🇸🇰 [sk](../sk/README.md) · 🇺🇦 [uk-UA](../uk-UA/README.md) · 🇮🇱 [he](../he/README.md) · 🇵🇭 [phi](../phi/README.md) · 🇧🇷 [pt-BR](../pt-BR/README.md) · 🇨🇿 [cs](../cs/README.md)
---
-
### Never stop coding. Smart routing to **FREE & low-cost AI models** with automatic fallback.
-_Your universal API proxy — one endpoint, 67+ providers, zero downtime. Now with **MCP & A2A** agent orchestration._
+_Your universal API proxy — one endpoint, 60+ providers, zero downtime. Now with **MCP Server (25 tools)**, **A2A Protocol**, **Memory/Skills Systems** & **Electron Desktop App**._
**Chat Completions • Embeddings • Image Generation • Video • Music • Audio • Reranking • **Web Search** • MCP Server • A2A Protocol • 100% TypeScript**
@@ -47,15 +46,17 @@ _Your universal API proxy — one endpoint, 67+ providers, zero downtime. Now wi
> - `APP_LOG_FILE_PATH`
> - `APP_LOG_MAX_FILE_SIZE`
> - `APP_LOG_RETENTION_DAYS`
+> - `APP_LOG_MAX_FILES`
> - `APP_LOG_LEVEL`
> - `APP_LOG_FORMAT`
> - `CALL_LOG_RETENTION_DAYS`
+> - `CALL_LOG_MAX_ENTRIES`
>
> For release details and upgrade notes, see the [CHANGELOG](CHANGELOG.md).
---
-## 🆕 What's New in v3.0.0
+## 🆕 What's New
> **Upgrading from v2.9.5?** — See the [full CHANGELOG](CHANGELOG.md#300--2026-03-22-release-candidate--not-yet-merged-to-main) for all changes.
@@ -275,7 +276,7 @@ Developers pay $20–200/month for Claude Pro, Codex Pro, or GitHub Copilot. Eve
- **Smart 4-Tier Fallback** — If subscription quota runs out, automatically redirects to API Key → Cheap → Free with zero manual intervention
- **Real-Time Quota Tracking** — Shows token consumption in real-time with reset countdown (5h, daily, weekly)
- **Multi-Account Support** — Multiple accounts per provider with auto round-robin — when one runs out, switches to the next
-- **Custom Combos** — Customizable fallback chains with 6 balancing strategies (fill-first, round-robin, P2C, random, least-used, cost-optimized)
+- **Custom Combos** — Customizable fallback chains with 9 balancing strategies (priority, weighted, fill-first, round-robin, P2C, random, least-used, cost-optimized, strict-random)
- **Codex Business Quotas** — Business/Team workspace quota monitoring directly in the dashboard
@@ -287,7 +288,7 @@ OpenAI uses one format, Claude (Anthropic) uses another, Gemini yet another. If
**How OmniRoute solves it:**
-- **Unified Endpoint** — A single `http://localhost:20128/v1` serves as proxy for all 67+ providers
+- **Unified Endpoint** — A single `http://localhost:20128/v1` serves as proxy for all 60+ providers
- **Format Translation** — Automatic and transparent: OpenAI ↔ Claude ↔ Gemini ↔ Responses API
- **Response Sanitization** — Strips non-standard fields (`x_groq`, `usage_breakdown`, `service_tier`) that break OpenAI SDK v1.83+
- **Role Normalization** — Converts `developer` → `system` for non-OpenAI providers; `system` → `user` for GLM/ERNIE
@@ -373,7 +374,7 @@ Developers use Cursor, Claude Code, Codex CLI, OpenClaw, Gemini CLI, Kilo Code..
- **CLI Tools Dashboard** — Dedicated page with one-click setup for Claude Code, Codex CLI, OpenClaw, Kilo Code, Antigravity, Cline
- **GitHub Copilot Config Generator** — Generates `chatLanguageModels.json` for VS Code with bulk model selection
- **Onboarding Wizard** — Guided 4-step setup for first-time users
-- **One endpoint, all models** — Configure `http://localhost:20128/v1` once, access 67+ providers
+- **One endpoint, all models** — Configure `http://localhost:20128/v1` once, access 60+ providers
@@ -420,7 +421,7 @@ When a call fails, the dev doesn't know if it was a rate limit, expired token, w
- **SQLite Proxy Logs** — Persistent logs that survive server restarts
- **Translator Playground** — 4 debugging modes: Playground (format translation), Chat Tester (round-trip), Test Bench (batch), Live Monitor (real-time)
- **Request Telemetry** — p50/p95/p99 latency + X-Request-Id tracing
-- **File-Based Logging with Rotation** — Console interceptor captures everything to JSON log with size-based rotation
+- **File-Based Logging with Rotation** — App logs rotate by size, retention days, and archive count; call log artifacts rotate by retention days and file count
- **System Info Report** — `npm run system-info` generates `system-info.txt` with your full environment (Node version, OmniRoute version, OS, CLI tools, Docker/PM2 status). Attach it when reporting issues for instant triage.
@@ -515,7 +516,7 @@ Developers who want all responses in a specific language, with a specific tone,
- **System Prompt Injection** — Global prompt applied to all requests
- **Thinking Budget Validation** — Reasoning token allocation control per request (passthrough, auto, custom, adaptive)
-- **6 Routing Strategies** — Global strategies that determine how requests are distributed
+- **9 Routing Strategies** — Global strategies that determine how requests are distributed
- **Wildcard Router** — `provider/*` patterns route dynamically to any provider
- **Combo Enable/Disable Toggle** — Toggle combos directly from the dashboard
- **Provider Toggle** — Enable/disable all connections for a provider with one click
@@ -582,7 +583,7 @@ Different clients should have least-privilege access to tool categories.
**How OmniRoute solves it:**
-- 9 granular MCP scopes for controlled tool access
+- 10 granular MCP scopes for controlled tool access
- Scope enforcement and visibility in MCP management UI
- Safe default posture for operational tooling
@@ -1326,19 +1327,19 @@ OmniRoute v2.0 is built as an operational platform, not just a relay proxy.
### 🤖 Agent & Protocol Operations (v2.0)
-| Feature | What It Does |
-| ------------------------------------- | -------------------------------------------------------------------------------------------------- |
-| 🔧 **MCP Server (16 tools)** | IDE/agent tools via 3 transports: stdio, SSE (`/api/mcp/sse`), Streamable HTTP (`/api/mcp/stream`) |
-| 🤝 **A2A Server (JSON-RPC + SSE)** | Agent-to-agent task execution with sync and streaming flows |
-| 🧭 **Consolidated Endpoints Page** | Tabbed management page with Endpoint Proxy, MCP, A2A, and API Endpoints tabs |
-| 🎚️ **Service Enable/Disable Toggles** | ON/OFF switches for MCP and A2A with settings persistence (default: OFF) |
-| 🛰️ **MCP Runtime Heartbeat** | Real process status (pid, uptime, heartbeat age, transport, scope mode) |
-| 📋 **MCP Audit Trail** | Filterable audit logs with success/failure and key attribution |
-| 🔐 **MCP Scope Enforcement** | 9 granular scope permissions for controlled tool access |
-| 📡 **A2A Task Lifecycle Management** | List/filter tasks, inspect events/artifacts, cancel running tasks |
-| 📋 **Agent Card Discovery** | `/.well-known/agent.json` for client auto-discovery |
-| 🧪 **Protocol E2E Test Harness** | Real MCP SDK + A2A client flows in `test:protocols:e2e` |
-| ⚙️ **Operational Controls** | Switch combo, apply resilience profiles, reset breakers from one control surface |
+| Feature | What It Does |
+| ------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------- |
+| 🔧 **MCP Server (25 tools)** | IDE/agent tools via 3 transports: stdio, SSE (`/api/mcp/sse`), Streamable HTTP (`/api/mcp/stream`). 18 core + 3 memory + 4 skill tools |
+| 🤝 **A2A Server (JSON-RPC + SSE)** | Agent-to-agent task execution with sync and streaming flows |
+| 🧭 **Consolidated Endpoints Page** | Tabbed management page with Endpoint Proxy, MCP, A2A, and API Endpoints tabs |
+| 🎚️ **Service Enable/Disable Toggles** | ON/OFF switches for MCP and A2A with settings persistence (default: OFF) |
+| 🛰️ **MCP Runtime Heartbeat** | Real process status (pid, uptime, heartbeat age, transport, scope mode) |
+| 📋 **MCP Audit Trail** | Filterable audit logs with success/failure and key attribution |
+| 🔐 **MCP Scope Enforcement** | 10 granular scope permissions for controlled tool access |
+| 📡 **A2A Task Lifecycle Management** | List/filter tasks, inspect events/artifacts, cancel running tasks |
+| 📋 **Agent Card Discovery** | `/.well-known/agent.json` for client auto-discovery |
+| 🧪 **Protocol E2E Test Harness** | Real MCP SDK + A2A client flows in `test:protocols:e2e` |
+| ⚙️ **Operational Controls** | Switch combo, apply resilience profiles, reset breakers from one control surface |
### 🧠 Routing & Intelligence
@@ -1349,7 +1350,7 @@ OmniRoute v2.0 is built as an operational platform, not just a relay proxy.
| 🔄 **Format Translation** | OpenAI ↔ Claude ↔ Gemini ↔ Responses with schema-safe conversions |
| 👥 **Multi-Account Support** | Multiple accounts per provider with intelligent selection |
| 🔄 **Auto Token Refresh** | OAuth tokens refresh automatically with retry |
-| 🎨 **Custom Combos** | 6 balancing strategies + fallback chain control |
+| 🎨 **Custom Combos** | 9 balancing strategies + fallback chain control |
| 🌐 **Wildcard Router** | `provider/*` dynamic routing |
| 🧠 **Thinking Budget Controls** | Passthrough, auto, custom, and adaptive reasoning limits |
| 🔀 **Model Aliases** | Built-in + custom model aliasing and migration safety |
@@ -1950,6 +1951,7 @@ opencode
- Request artifacts are written to `DATA_DIR/call_logs/` as one JSON file per request
- Enable pipeline capture from Dashboard → Logs → Request Logs if you need detailed per-stage payloads
- Set `APP_LOG_TO_FILE=true` if you also want application console logs in `logs/application/app.log`
+- Adjust `APP_LOG_MAX_FILE_SIZE`, `APP_LOG_RETENTION_DAYS`, `APP_LOG_MAX_FILES`, and `CALL_LOG_MAX_ENTRIES` as needed
**Connection test shows "Invalid" for OpenAI-compatible providers**
diff --git a/docs/i18n/de/RELEASE_CHECKLIST.md b/docs/i18n/de/RELEASE_CHECKLIST.md
deleted file mode 100644
index 903e812c3f..0000000000
--- a/docs/i18n/de/RELEASE_CHECKLIST.md
+++ /dev/null
@@ -1,37 +0,0 @@
-🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/RELEASE_CHECKLIST.md) · 🇪🇸 [es](../es/RELEASE_CHECKLIST.md) · 🇫🇷 [fr](../fr/RELEASE_CHECKLIST.md) · 🇩🇪 [de](../de/RELEASE_CHECKLIST.md) · 🇮🇹 [it](../it/RELEASE_CHECKLIST.md) · 🇷🇺 [ru](../ru/RELEASE_CHECKLIST.md) · 🇨🇳 [zh-CN](../zh-CN/RELEASE_CHECKLIST.md) · 🇯🇵 [ja](../ja/RELEASE_CHECKLIST.md) · 🇰🇷 [ko](../ko/RELEASE_CHECKLIST.md) · 🇸🇦 [ar](../ar/RELEASE_CHECKLIST.md) · 🇮🇳 [in](../in/RELEASE_CHECKLIST.md) · 🇹🇭 [th](../th/RELEASE_CHECKLIST.md) · 🇻🇳 [vi](../vi/RELEASE_CHECKLIST.md) · 🇮🇩 [id](../id/RELEASE_CHECKLIST.md) · 🇲🇾 [ms](../ms/RELEASE_CHECKLIST.md) · 🇳🇱 [nl](../nl/RELEASE_CHECKLIST.md) · 🇵🇱 [pl](../pl/RELEASE_CHECKLIST.md) · 🇸🇪 [sv](../sv/RELEASE_CHECKLIST.md) · 🇳🇴 [no](../no/RELEASE_CHECKLIST.md) · 🇩🇰 [da](../da/RELEASE_CHECKLIST.md) · 🇫🇮 [fi](../fi/RELEASE_CHECKLIST.md) · 🇵🇹 [pt](../pt/RELEASE_CHECKLIST.md) · 🇷🇴 [ro](../ro/RELEASE_CHECKLIST.md) · 🇭🇺 [hu](../hu/RELEASE_CHECKLIST.md) · 🇧🇬 [bg](../bg/RELEASE_CHECKLIST.md) · 🇸🇰 [sk](../sk/RELEASE_CHECKLIST.md) · 🇺🇦 [uk-UA](../uk-UA/RELEASE_CHECKLIST.md) · 🇮🇱 [he](../he/RELEASE_CHECKLIST.md) · 🇵🇭 [phi](../phi/RELEASE_CHECKLIST.md)
-
----
-
-# Release Checklist
-
-Use this checklist before tagging or publishing a new OmniRoute release.
-
-## Version and Changelog
-
-1. Bump `package.json` version (`x.y.z`) in the release branch.
-2. Move release notes from `## [Unreleased]` in `CHANGELOG.md` to a dated section:
- - `## [x.y.z] — YYYY-MM-DD`
-3. Keep `## [Unreleased]` as the first changelog section for upcoming work.
-4. Ensure the latest semver section in `CHANGELOG.md` equals `package.json` version.
-
-## API Docs
-
-1. Update `docs/openapi.yaml`:
- - `info.version` must equal `package.json` version.
-2. Validate endpoint examples if API contracts changed.
-
-## Runtime Docs
-
-1. Review `docs/ARCHITECTURE.md` for storage/runtime drift.
-2. Review `docs/TROUBLESHOOTING.md` for env var and operational drift.
-3. Update localized docs if source docs changed significantly.
-
-## Automated Check
-
-Run the sync guard locally before opening PR:
-
-```bash
-npm run check:docs-sync
-```
-
-CI also runs this check in `.github/workflows/ci.yml` (lint job).
diff --git a/docs/i18n/de/SECURITY.md b/docs/i18n/de/SECURITY.md
new file mode 100644
index 0000000000..8777153cde
--- /dev/null
+++ b/docs/i18n/de/SECURITY.md
@@ -0,0 +1,179 @@
+# Security Policy (Deutsch)
+
+🌐 **Languages:** 🇺🇸 [English](../../../SECURITY.md) · 🇪🇸 [es](../es/SECURITY.md) · 🇫🇷 [fr](../fr/SECURITY.md) · 🇩🇪 [de](../de/SECURITY.md) · 🇮🇹 [it](../it/SECURITY.md) · 🇷🇺 [ru](../ru/SECURITY.md) · 🇨🇳 [zh-CN](../zh-CN/SECURITY.md) · 🇯🇵 [ja](../ja/SECURITY.md) · 🇰🇷 [ko](../ko/SECURITY.md) · 🇸🇦 [ar](../ar/SECURITY.md) · 🇮🇳 [in](../in/SECURITY.md) · 🇹🇭 [th](../th/SECURITY.md) · 🇻🇳 [vi](../vi/SECURITY.md) · 🇮🇩 [id](../id/SECURITY.md) · 🇲🇾 [ms](../ms/SECURITY.md) · 🇳🇱 [nl](../nl/SECURITY.md) · 🇵🇱 [pl](../pl/SECURITY.md) · 🇸🇪 [sv](../sv/SECURITY.md) · 🇳🇴 [no](../no/SECURITY.md) · 🇩🇰 [da](../da/SECURITY.md) · 🇫🇮 [fi](../fi/SECURITY.md) · 🇵🇹 [pt](../pt/SECURITY.md) · 🇷🇴 [ro](../ro/SECURITY.md) · 🇭🇺 [hu](../hu/SECURITY.md) · 🇧🇬 [bg](../bg/SECURITY.md) · 🇸🇰 [sk](../sk/SECURITY.md) · 🇺🇦 [uk-UA](../uk-UA/SECURITY.md) · 🇮🇱 [he](../he/SECURITY.md) · 🇵🇭 [phi](../phi/SECURITY.md) · 🇧🇷 [pt-BR](../pt-BR/SECURITY.md) · 🇨🇿 [cs](../cs/SECURITY.md)
+
+---
+
+## Reporting Vulnerabilities
+
+If you discover a security vulnerability in OmniRoute, please report it responsibly:
+
+1. **DO NOT** open a public GitHub issue
+2. Use [GitHub Security Advisories](https://github.com/diegosouzapw/OmniRoute/security/advisories/new)
+3. Include: description, reproduction steps, and potential impact
+
+## Response Timeline
+
+| Stage | Target |
+| ------------------- | --------------------------- |
+| Acknowledgment | 48 hours |
+| Triage & Assessment | 5 business days |
+| Patch Release | 14 business days (critical) |
+
+## Supported Versions
+
+| Version | Support Status |
+| ------- | -------------- |
+| 3.4.x | ✅ Active |
+| 3.0.x | ✅ Security |
+| < 3.0.0 | ❌ Unsupported |
+
+---
+
+## Security Architecture
+
+OmniRoute implements a multi-layered security model:
+
+```
+Request → CORS → API Key Auth → Prompt Injection Guard → Input Sanitizer → Rate Limiter → Circuit Breaker → Provider
+```
+
+### 🔐 Authentication & Authorization
+
+| Feature | Implementation |
+| -------------------- | ---------------------------------------------------------- |
+| **Dashboard Login** | Password-based auth with JWT tokens (HttpOnly cookies) |
+| **API Key Auth** | HMAC-signed keys with CRC validation |
+| **OAuth 2.0 + PKCE** | Secure provider auth (Claude, Codex, Gemini, Cursor, etc.) |
+| **Token Refresh** | Automatic OAuth token refresh before expiry |
+| **Secure Cookies** | `AUTH_COOKIE_SECURE=true` for HTTPS environments |
+| **MCP Scopes** | 10 granular scopes for MCP tool access control |
+
+### 🛡️ Encryption at Rest
+
+All sensitive data stored in SQLite is encrypted using **AES-256-GCM** with scrypt key derivation:
+
+- API keys, access tokens, refresh tokens, and ID tokens
+- Versioned format: `enc:v1:::`
+- Passthrough mode (plaintext) when `STORAGE_ENCRYPTION_KEY` is not set
+
+```bash
+# Generate encryption key:
+STORAGE_ENCRYPTION_KEY=$(openssl rand -hex 32)
+```
+
+### 🧠 Prompt Injection Guard
+
+Middleware that detects and blocks prompt injection attacks in LLM requests:
+
+| Pattern Type | Severity | Example |
+| ------------------- | -------- | ---------------------------------------------- |
+| System Override | High | "ignore all previous instructions" |
+| Role Hijack | High | "you are now DAN, you can do anything" |
+| Delimiter Injection | Medium | Encoded separators to break context boundaries |
+| DAN/Jailbreak | High | Known jailbreak prompt patterns |
+| Instruction Leak | Medium | "show me your system prompt" |
+
+Configure via dashboard (Settings → Security) or `.env`:
+
+```env
+INPUT_SANITIZER_ENABLED=true
+INPUT_SANITIZER_MODE=block # warn | block | redact
+```
+
+### 🔒 PII Redaction
+
+Automatic detection and optional redaction of personally identifiable information:
+
+| PII Type | Pattern | Replacement |
+| ------------- | --------------------- | ------------------ |
+| Email | `user@domain.com` | `[EMAIL_REDACTED]` |
+| CPF (Brazil) | `123.456.789-00` | `[CPF_REDACTED]` |
+| CNPJ (Brazil) | `12.345.678/0001-00` | `[CNPJ_REDACTED]` |
+| Credit Card | `4111-1111-1111-1111` | `[CC_REDACTED]` |
+| Phone | `+55 11 99999-9999` | `[PHONE_REDACTED]` |
+| SSN (US) | `123-45-6789` | `[SSN_REDACTED]` |
+
+```env
+PII_REDACTION_ENABLED=true
+```
+
+### 🌐 Network Security
+
+| Feature | Description |
+| ------------------------ | ---------------------------------------------------------------- |
+| **CORS** | Configurable origin control (`CORS_ORIGIN` env var, default `*`) |
+| **IP Filtering** | Allowlist/blocklist IP ranges in dashboard |
+| **Rate Limiting** | Per-provider rate limits with automatic backoff |
+| **Anti-Thundering Herd** | Mutex + per-connection locking prevents cascading 502s |
+| **TLS Fingerprint** | Browser-like TLS fingerprint spoofing to reduce bot detection |
+| **CLI Fingerprint** | Per-provider header/body ordering to match native CLI signatures |
+
+### 🔌 Resilience & Availability
+
+| Feature | Description |
+| ----------------------- | ------------------------------------------------------------------ |
+| **Circuit Breaker** | 3-state (Closed → Open → Half-Open) per provider, SQLite-persisted |
+| **Request Idempotency** | 5-second dedup window for duplicate requests |
+| **Exponential Backoff** | Automatic retry with increasing delays |
+| **Health Dashboard** | Real-time provider health monitoring |
+
+### 📋 Compliance
+
+| Feature | Description |
+| ------------------ | ----------------------------------------------------------- |
+| **Log Retention** | Automatic cleanup after `CALL_LOG_RETENTION_DAYS` |
+| **No-Log Opt-out** | Per API key `noLog` flag disables request logging |
+| **Audit Log** | Administrative actions tracked in `audit_log` table |
+| **MCP Audit** | SQLite-backed audit logging for all MCP tool calls |
+| **Zod Validation** | All API inputs validated with Zod v4 schemas at module load |
+
+---
+
+## Required Environment Variables
+
+All secrets must be set before starting the server. The server will **fail fast** if they are missing or weak.
+
+```bash
+# REQUIRED — server will not start without these:
+JWT_SECRET=$(openssl rand -base64 48) # min 32 chars
+API_KEY_SECRET=$(openssl rand -hex 32) # min 16 chars
+
+# RECOMMENDED — enables encryption at rest:
+STORAGE_ENCRYPTION_KEY=$(openssl rand -hex 32)
+```
+
+The server actively rejects known-weak values like `changeme`, `secret`, or `password`.
+
+---
+
+## Docker Security
+
+- Use non-root user in production
+- Mount secrets as read-only volumes
+- Never copy `.env` files into Docker images
+- Use `.dockerignore` to exclude sensitive files
+- Set `AUTH_COOKIE_SECURE=true` when behind HTTPS
+
+```bash
+docker run -d \
+ --name omniroute \
+ --restart unless-stopped \
+ --read-only \
+ -p 20128:20128 \
+ -v omniroute-data:/app/data \
+ -e JWT_SECRET="$(openssl rand -base64 48)" \
+ -e API_KEY_SECRET="$(openssl rand -hex 32)" \
+ -e STORAGE_ENCRYPTION_KEY="$(openssl rand -hex 32)" \
+ diegosouzapw/omniroute:latest
+```
+
+---
+
+## Dependencies
+
+- Run `npm audit` regularly
+- Keep dependencies updated
+- The project uses `husky` + `lint-staged` for pre-commit checks
+- CI pipeline runs ESLint security rules on every push
+- Provider constants validated at module load via Zod (`src/shared/validation/providerSchema.ts`)
diff --git a/docs/i18n/de/VM_DEPLOYMENT_GUIDE.md b/docs/i18n/de/VM_DEPLOYMENT_GUIDE.md
deleted file mode 100644
index d9ebae328d..0000000000
--- a/docs/i18n/de/VM_DEPLOYMENT_GUIDE.md
+++ /dev/null
@@ -1,401 +0,0 @@
-# OmniRoute – Bereitstellungshandbuch auf VM mit Cloudflare
-
-🌐 **Languages:** 🇺🇸 [English](../../VM_DEPLOYMENT_GUIDE.md) | 🇧🇷 [Português (Brasil)](../pt-BR/VM_DEPLOYMENT_GUIDE.md) | 🇪🇸 [Español](../es/VM_DEPLOYMENT_GUIDE.md) | 🇫🇷 [Français](../fr/VM_DEPLOYMENT_GUIDE.md) | 🇮🇹 [Italiano](../it/VM_DEPLOYMENT_GUIDE.md) | 🇷🇺 [Русский](../ru/VM_DEPLOYMENT_GUIDE.md) | 🇨🇳 [中文 (简体)](../zh-CN/VM_DEPLOYMENT_GUIDE.md) | 🇩🇪 [Deutsch](../de/VM_DEPLOYMENT_GUIDE.md) | 🇮🇳 [हिन्दी](../in/VM_DEPLOYMENT_GUIDE.md) | 🇹🇭 [ไทย](../th/VM_DEPLOYMENT_GUIDE.md) | 🇺🇦 [Українська](../uk-UA/VM_DEPLOYMENT_GUIDE.md) | 🇸🇦 [العربية](../ar/VM_DEPLOYMENT_GUIDE.md) | 🇯🇵 [日本語](../ja/VM_DEPLOYMENT_GUIDE.md) | 🇻🇳 [Tiếng Việt](../vi/VM_DEPLOYMENT_GUIDE.md) | 🇧🇬 [Български](../bg/VM_DEPLOYMENT_GUIDE.md) | 🇩🇰 [Dansk](../da/VM_DEPLOYMENT_GUIDE.md) | 🇫🇮 [Suomi](../fi/VM_DEPLOYMENT_GUIDE.md) | 🇮🇱 [עברית](../he/VM_DEPLOYMENT_GUIDE.md) | 🇭🇺 [Magyar](../hu/VM_DEPLOYMENT_GUIDE.md) | 🇮🇩 [Bahasa Indonesia](../id/VM_DEPLOYMENT_GUIDE.md) | 🇰🇷 [한국어](../ko/VM_DEPLOYMENT_GUIDE.md) | 🇲🇾 [Bahasa Melayu](../ms/VM_DEPLOYMENT_GUIDE.md) | 🇳🇱 [Nederlands](../nl/VM_DEPLOYMENT_GUIDE.md) | 🇳🇴 [Norsk](../no/VM_DEPLOYMENT_GUIDE.md) | 🇵🇹 [Português (Portugal)](../pt/VM_DEPLOYMENT_GUIDE.md) | 🇷🇴 [Română](../ro/VM_DEPLOYMENT_GUIDE.md) | 🇵🇱 [Polski](../pl/VM_DEPLOYMENT_GUIDE.md) | 🇸🇰 [Slovenčina](../sk/VM_DEPLOYMENT_GUIDE.md) | 🇸🇪 [Svenska](../sv/VM_DEPLOYMENT_GUIDE.md) | 🇵🇭 [Filipino](../phi/VM_DEPLOYMENT_GUIDE.md) | 🇨🇿 [Čeština](../cs/VM_DEPLOYMENT_GUIDE.md)
-
-Vollständige Anleitung zur Installation und Konfiguration von OmniRoute auf einer VM (VPS) mit über Cloudflare verwalteter Domäne.
-
----
-
-## Voraussetzungen
-
-| Artikel | Minimum | Empfohlen |
-| ------------------ | -------------------------- | ---------------- |
-| **CPU** | 1 vCPU | 2 vCPU |
-| **RAM** | 1 GB | 2 GB |
-| **Festplatte** | 10 GB SSD | 25 GB SSD |
-| **Betriebssystem** | Ubuntu 22.04 LTS | Ubuntu 24.04 LTS |
-| **Domäne** | Registriert bei Cloudflare | — |
-| **Docker** | Docker Engine 24+ | Docker 27+ |
-
-**Getestete Anbieter**: Akamai (Linode), DigitalOcean, Vultr, Hetzner, AWS Lightsail.
-
----
-
-## 1. Konfigurieren Sie die VM
-
-### 1.1 Erstellen Sie die Instanz
-
-Bei Ihrem bevorzugten VPS-Anbieter:
-
-- Wählen Sie Ubuntu 24.04 LTS
-- Wählen Sie den Mindestplan (1 vCPU / 1 GB RAM)
-- Legen Sie ein sicheres Root-Passwort fest oder konfigurieren Sie den SSH-Schlüssel
-- Notieren Sie sich die **öffentliche IP** (z. B. `203.0.113.10`)
-
-### 1.2 Verbindung über SSH herstellen
-
-```bash
-ssh root@203.0.113.10
-```
-
-### 1.3 Aktualisieren Sie das System
-
-```bash
-apt update && apt upgrade -y
-```
-
-### 1.4 Docker installieren
-
-```bash
-# Install dependencies
-apt install -y ca-certificates curl gnupg
-
-# Add official Docker repository
-install -m 0755 -d /etc/apt/keyrings
-curl -fsSL https://download.docker.com/linux/ubuntu/gpg | gpg --dearmor -o /etc/apt/keyrings/docker.gpg
-chmod a+r /etc/apt/keyrings/docker.gpg
-echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu $ (. /etc/os-release && echo “$VERSION_CODENAME”) stable" | tee /etc/apt/sources.list.d/docker.list > /dev/null
-apt update
-apt install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin
-```
-
-### 1.5 Nginx installieren
-
-```bash
-apt install -y nginx
-```
-
-### 1.6 Firewall (UFW) konfigurieren
-
-```bash
-ufw default deny incoming
-ufw default allow outgoing
-ufw allow 22/tcp # SSH
-ufw allow 80/tcp # HTTP (redirect)
-ufw allow 443/tcp # HTTPS
-ufw enable
-```
-
-> **Tipp**: Für maximale Sicherheit beschränken Sie die Ports 80 und 443 nur auf Cloudflare-IPs. Siehe den Abschnitt [Advanced Security](#advanced-security).
-
----
-
-## 2. OmniRoute installieren
-
-### 2.1 Konfigurationsverzeichnis erstellen
-
-```bash
-mkdir -p /opt/omniroute
-```
-
-### 2.2 Umgebungsvariablendatei erstellen
-
-```bash
-cat > /opt/omniroute/.env << ‘EOF’
-# === Security ===
-JWT_SECRET=CHANGE-TO-A-UNIQUE-64-CHAR-SECRET-KEY
-INITIAL_PASSWORD=YourSecurePassword123!
-API_KEY_SECRET=REPLACE-WITH-ANOTHER-SECRET-KEY
-STORAGE_ENCRYPTION_KEY=REPLACE-WITH-THIRD-SECRET-KEY
-STORAGE_ENCRYPTION_KEY_VERSION=v1
-MACHINE_ID_SALT=CHANGE-TO-A-UNIQUE-SALT
-
-# === App ===
-PORT=20128
-NODE_ENV=production
-HOSTNAME=0.0.0.0
-DATA_DIR=/app/data
-STORAGE_DRIVER=sqlite
-ENABLE_REQUEST_LOGS=true
-AUTH_COOKIE_SECURE=false
-REQUIRE_API_KEY=false
-
-# === Domain (change to your domain) ===
-BASE_URL=https://llms.seudominio.com
-NEXT_PUBLIC_BASE_URL=https://llms.seudominio.com
-
-# === Cloud Sync (optional) ===
-# CLOUD_URL=https://cloud.omniroute.online
-# NEXT_PUBLIC_CLOUD_URL=https://cloud.omniroute.online
-EOF
-```
-
-> ⚠️ **WICHTIG**: Generieren Sie einzigartige geheime Schlüssel! Verwenden Sie `openssl rand -hex 32` für jeden Schlüssel.
-
-### 2.3 Starten Sie den Container
-
-```bash
-docker pull diegosouzapw/omniroute:latest
-
-docker run -d \
- --name omniroute \
- --restart unless-stopped \
- --env-file /opt/omniroute/.env \
- -p 20128:20128 \
- -v omniroute-data:/app/data \
- diegosouzapw/omniroute:latest
-```
-
-### 2.4 Stellen Sie sicher, dass es ausgeführt wird
-
-```bash
-docker ps | grep omniroute
-docker logs omniroute --tail 20
-```
-
-Es sollte Folgendes anzeigen: `[DB] SQLite database ready` und `listening on port 20128`.
-
----
-
-## 3. Nginx (Reverse Proxy) konfigurieren
-
-### 3.1 SSL-Zertifikat generieren (Cloudflare Origin)
-
-Im Cloudflare-Dashboard:
-
-1. Gehen Sie zu **SSL/TLS → Ursprungsserver**
-2. Klicken Sie auf **Zertifikat erstellen**
-3. Behalten Sie die Standardeinstellungen bei (15 Jahre, \*.yourdomain.com)
-4. Kopieren Sie das **Ursprungszertifikat** und den **Privaten Schlüssel**
-
-```bash
-mkdir -p /etc/nginx/ssl
-
-# Paste the certificate
-nano /etc/nginx/ssl/origin.crt
-
-# Paste the private key
-nano /etc/nginx/ssl/origin.key
-
-chmod 600 /etc/nginx/ssl/origin.key
-```
-
-### 3.2 Nginx-Konfiguration
-
-```bash
-cat > /etc/nginx/sites-available/omniroute << ‘NGINX’
-# Default server — blocks direct access via IP
-server {
- listen 80 default_server;
- listen [::]:80 default_server;
- listen 443 ssl default_server;
- listen [::]:443 ssl default_server;
- ssl_certificate /etc/nginx/ssl/origin.crt;
- ssl_certificate_key /etc/nginx/ssl/origin.key;
- server_name _;
- return 444;
-}
-
-# OmniRoute — HTTPS
-server {
- listen 443 ssl;
- listen [::]:443 ssl;
- server_name llms.yourdomain.com; # Change to your domain
-
- ssl_certificate /etc/nginx/ssl/origin.crt;
- ssl_certificate_key /etc/nginx/ssl/origin.key;
- ssl_protocols TLSv1.2 TLSv1.3;
-
- client_max_body_size 100M;
-
- location / {
- proxy_pass http://127.0.0.1:20128;
- proxy_set_header Host $host;
- proxy_set_header X-Real-IP $remote_addr;
- proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
- proxy_set_header X-Forwarded-Proto $scheme;
-
- # WebSocket support
- proxy_http_version 1.1;
- proxy_set_header Upgrade $http_upgrade;
- proxy_set_header Connection “upgrade”;
-
- # SSE (Server-Sent Events) — streaming AI responses
- proxy_buffering off;
- proxy_cache off;
- proxy_read_timeout 300s;
- proxy_send_timeout 300s;
- }
-}
-
-# HTTP → HTTPS redirect
-server {
- listen 80;
- listen [::]:80;
- server_name llms.yourdomain.com;
- return 301 https://$server_name$request_uri;
-}
-NGINX
-```
-
-### 3.3 Aktivieren und testen
-
-```bash
-# Remove default configuration
-rm -f /etc/nginx/sites-enabled/default
-
-# Enable OmniRoute
-ln -sf /etc/nginx/sites-available/omniroute /etc/nginx/sites-enabled/omniroute
-
-# Test and reload
-nginx -t && systemctl reload nginx
-```
-
----
-
-## 4. Konfigurieren Sie Cloudflare DNS
-
-### 4.1 DNS-Eintrag hinzufügen
-
-Im Cloudflare-Dashboard → DNS:
-
-| Geben Sie | ein Name | Inhalt | Proxy |
-| --------- | -------- | ---------------------- | -------- |
-| A | `llms` | `203.0.113.10` (VM-IP) | ✅ Proxy |
-
-### 4.2 SSL konfigurieren
-
-Unter **SSL/TLS → Übersicht**:
-
-- Modus: **Vollständig (Streng)**
-
-Unter **SSL/TLS → Edge-Zertifikate**:
-
-- Immer HTTPS verwenden: ✅ Ein
-- Mindest-TLS-Version: TLS 1.2
-- Automatische HTTPS-Rewrites: ✅ Ein
-
-### 4.3 Testen
-
-```bash
-curl -sI https://llms.seudominio.com/health
-# Should return HTTP/2 200
-```
-
----
-
-## 5. Betrieb und Wartung
-
-### Upgrade auf eine neue Version
-
-```bash
-docker pull diegosouzapw/omniroute:latest
-docker stop omniroute && docker rm omniroute
-docker run -d --name omniroute --restart unless-stopped \
- --env-file /opt/omniroute/.env \
- -p 20128:20128 \
- -v omniroute-data:/app/data \
- diegosouzapw/omniroute:latest
-```
-
-### Protokolle anzeigen
-
-```bash
-docker logs -f omniroute # Real-time stream
-docker logs omniroute --tail 50 # Last 50 lines
-```
-
-### Manuelle Datenbanksicherung
-
-```bash
-# Copy data from the volume to the host
-docker cp omniroute:/app/data ./backup-$(date +%F)
-
-# Or compress the entire volume
-docker run --rm -v omniroute-data:/data -v $(pwd):/backup \
- alpine tar czf /backup/omniroute-data-$(date +%F).tar.gz /data
-```
-
-### Aus Backup wiederherstellen
-
-```bash
-docker stop omniroute
-docker run --rm -v omniroute-data:/data -v $(pwd):/backup \
- alpine sh -c “rm -rf /data/* && tar xzf /backup/omniroute-data-YYYY-MM-DD.tar.gz -C /”
-docker start omniroute
-```
-
----
-
-## 6. Erweiterte Sicherheit
-
-### Nginx auf Cloudflare-IPs beschränken
-
-```bash
-cat > /etc/nginx/cloudflare-ips.conf << ‘CF’
-# Cloudflare IPv4 ranges — update periodically
-# https://www.cloudflare.com/ips-v4/
-set_real_ip_from 173.245.48.0/20;
-set_real_ip_from 103.21.244.0/22;
-set_real_ip_from 103.22.200.0/22;
-set_real_ip_from 103.31.4.0/22;
-set_real_ip_from 141.101.64.0/18;
-set_real_ip_from 108.162.192.0/18;
-set_real_ip_from 190.93.240.0/20;
-set_real_ip_from 188.114.96.0/20;
-set_real_ip_from 197.234.240.0/22;
-set_real_ip_from 198.41.128.0/17;
-set_real_ip_from 162.158.0.0/15;
-set_real_ip_from 104.16.0.0/13;
-set_real_ip_from 104.24.0.0/14;
-set_real_ip_from 172.64.0.0/13;
-set_real_ip_from 131.0.72.0/22;
-real_ip_header CF-Connecting-IP;
-CF
-```
-
-Fügen Sie Folgendes zu `nginx.conf` im Block `http {}` hinzu:
-
-```nginx
-include /etc/nginx/cloudflare-ips.conf;
-```
-
-### Fail2ban installieren
-
-```bash
-apt install -y fail2ban
-systemctl enable fail2ban
-systemctl start fail2ban
-
-# Check status
-fail2ban-client status sshd
-```
-
-### Blockieren Sie den direkten Zugriff auf den Docker-Port
-
-```bash
-# Prevent direct external access to port 20128
-iptables -I DOCKER-USER -p tcp --dport 20128 -j DROP
-iptables -I DOCKER-USER -i lo -p tcp --dport 20128 -j ACCEPT
-
-# Persist the rules
-apt install -y iptables-persistent
-netfilter-persistent save
-```
-
----
-
-## 7. Bereitstellung für Cloudflare-Worker (optional)
-
-Für den Fernzugriff über Cloudflare Workers (ohne die VM direkt verfügbar zu machen):
-
-```bash
-# In the local repository
-cd omnirouteCloud
-npm install
-npx wrangler login
-npx wrangler deploy
-```
-
-Die vollständige Dokumentation finden Sie unter [omnirouteCloud/README.md](../omnirouteCloud/README.md).
-
----
-
-## Portzusammenfassung
-
-| Hafen | Service | Zugriff |
-| ----- | ----------- | -------------------------- |
-| 22 | SSH | Öffentlich (mit fail2ban) |
-| 80 | nginx HTTP | Weiterleiten → HTTPS |
-| 443 | nginx HTTPS | Über Cloudflare-Proxy |
-| 20128 | OmniRoute | Nur Localhost (über Nginx) |
diff --git a/docs/i18n/de/docs/A2A-SERVER.md b/docs/i18n/de/docs/A2A-SERVER.md
new file mode 100644
index 0000000000..6eb01b9fca
--- /dev/null
+++ b/docs/i18n/de/docs/A2A-SERVER.md
@@ -0,0 +1,200 @@
+# OmniRoute A2A Server Documentation (Deutsch)
+
+🌐 **Languages:** 🇺🇸 [English](../../../../docs/A2A-SERVER.md) · 🇪🇸 [es](../../es/docs/A2A-SERVER.md) · 🇫🇷 [fr](../../fr/docs/A2A-SERVER.md) · 🇩🇪 [de](../../de/docs/A2A-SERVER.md) · 🇮🇹 [it](../../it/docs/A2A-SERVER.md) · 🇷🇺 [ru](../../ru/docs/A2A-SERVER.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/A2A-SERVER.md) · 🇯🇵 [ja](../../ja/docs/A2A-SERVER.md) · 🇰🇷 [ko](../../ko/docs/A2A-SERVER.md) · 🇸🇦 [ar](../../ar/docs/A2A-SERVER.md) · 🇮🇳 [in](../../in/docs/A2A-SERVER.md) · 🇹🇭 [th](../../th/docs/A2A-SERVER.md) · 🇻🇳 [vi](../../vi/docs/A2A-SERVER.md) · 🇮🇩 [id](../../id/docs/A2A-SERVER.md) · 🇲🇾 [ms](../../ms/docs/A2A-SERVER.md) · 🇳🇱 [nl](../../nl/docs/A2A-SERVER.md) · 🇵🇱 [pl](../../pl/docs/A2A-SERVER.md) · 🇸🇪 [sv](../../sv/docs/A2A-SERVER.md) · 🇳🇴 [no](../../no/docs/A2A-SERVER.md) · 🇩🇰 [da](../../da/docs/A2A-SERVER.md) · 🇫🇮 [fi](../../fi/docs/A2A-SERVER.md) · 🇵🇹 [pt](../../pt/docs/A2A-SERVER.md) · 🇷🇴 [ro](../../ro/docs/A2A-SERVER.md) · 🇭🇺 [hu](../../hu/docs/A2A-SERVER.md) · 🇧🇬 [bg](../../bg/docs/A2A-SERVER.md) · 🇸🇰 [sk](../../sk/docs/A2A-SERVER.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/A2A-SERVER.md) · 🇮🇱 [he](../../he/docs/A2A-SERVER.md) · 🇵🇭 [phi](../../phi/docs/A2A-SERVER.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/A2A-SERVER.md) · 🇨🇿 [cs](../../cs/docs/A2A-SERVER.md)
+
+---
+
+> Agent-to-Agent Protocol v0.3 — OmniRoute as an intelligent routing agent
+
+## Agent Discovery
+
+```bash
+curl http://localhost:20128/.well-known/agent.json
+```
+
+Returns the Agent Card describing OmniRoute's capabilities, skills, and authentication requirements.
+
+---
+
+## Authentication
+
+All `/a2a` requests require an API key via the `Authorization` header:
+
+```
+Authorization: Bearer YOUR_OMNIROUTE_API_KEY
+```
+
+If no API key is configured on the server, authentication is bypassed.
+
+---
+
+## JSON-RPC 2.0 Methods
+
+### `message/send` — Synchronous Execution
+
+Sends a message to a skill and waits for the complete response.
+
+```bash
+curl -X POST http://localhost:20128/a2a \
+ -H "Content-Type: application/json" \
+ -H "Authorization: Bearer YOUR_KEY" \
+ -d '{
+ "jsonrpc": "2.0",
+ "id": "1",
+ "method": "message/send",
+ "params": {
+ "skill": "smart-routing",
+ "messages": [{"role": "user", "content": "Write a hello world in Python"}],
+ "metadata": {"model": "auto", "combo": "fast-coding"}
+ }
+ }'
+```
+
+**Response:**
+
+```json
+{
+ "jsonrpc": "2.0",
+ "id": "1",
+ "result": {
+ "task": { "id": "uuid", "state": "completed" },
+ "artifacts": [{ "type": "text", "content": "..." }],
+ "metadata": {
+ "routing_explanation": "Selected claude-sonnet via provider \"anthropic\" (latency: 1200ms, cost: $0.003)",
+ "cost_envelope": { "estimated": 0.005, "actual": 0.003, "currency": "USD" },
+ "resilience_trace": [
+ { "event": "primary_selected", "provider": "anthropic", "timestamp": "..." }
+ ],
+ "policy_verdict": { "allowed": true, "reason": "within budget and quota limits" }
+ }
+ }
+}
+```
+
+### `message/stream` — SSE Streaming
+
+Same as `message/send` but returns Server-Sent Events for real-time streaming.
+
+```bash
+curl -N -X POST http://localhost:20128/a2a \
+ -H "Content-Type: application/json" \
+ -H "Authorization: Bearer YOUR_KEY" \
+ -d '{
+ "jsonrpc": "2.0",
+ "id": "1",
+ "method": "message/stream",
+ "params": {
+ "skill": "smart-routing",
+ "messages": [{"role": "user", "content": "Explain quantum computing"}]
+ }
+ }'
+```
+
+**SSE Events:**
+
+```
+data: {"jsonrpc":"2.0","method":"message/stream","params":{"task":{"id":"...","state":"working"},"chunk":{"type":"text","content":"..."}}}
+
+: heartbeat 2026-03-03T17:00:00Z
+
+data: {"jsonrpc":"2.0","method":"message/stream","params":{"task":{"id":"...","state":"completed"},"metadata":{...}}}
+```
+
+### `tasks/get` — Query Task Status
+
+```bash
+curl -X POST http://localhost:20128/a2a \
+ -H "Content-Type: application/json" \
+ -H "Authorization: Bearer YOUR_KEY" \
+ -d '{"jsonrpc":"2.0","id":"2","method":"tasks/get","params":{"taskId":"TASK_UUID"}}'
+```
+
+### `tasks/cancel` — Cancel a Task
+
+```bash
+curl -X POST http://localhost:20128/a2a \
+ -H "Content-Type: application/json" \
+ -H "Authorization: Bearer YOUR_KEY" \
+ -d '{"jsonrpc":"2.0","id":"3","method":"tasks/cancel","params":{"taskId":"TASK_UUID"}}'
+```
+
+---
+
+## Available Skills
+
+| Skill | Description |
+| :----------------- | :------------------------------------------------------------------------------------------------------------------------------ |
+| `smart-routing` | Routes prompts through OmniRoute's intelligent pipeline. Returns response with routing explanation, cost, and resilience trace. |
+| `quota-management` | Answers natural-language queries about provider quotas, suggests free combos, and provides quota rankings. |
+
+---
+
+## Task Lifecycle
+
+```
+submitted → working → completed
+ → failed
+ → cancelled
+```
+
+- Tasks expire after 5 minutes (configurable)
+- Terminal states: `completed`, `failed`, `cancelled`
+- Event log tracks every state transition
+
+---
+
+## Error Codes
+
+| Code | Meaning |
+| :----- | :----------------------------- |
+| -32700 | Parse error (invalid JSON) |
+| -32600 | Invalid request / Unauthorized |
+| -32601 | Method or skill not found |
+| -32602 | Invalid params |
+| -32603 | Internal error |
+
+---
+
+## Integration Examples
+
+### Python (requests)
+
+```python
+import requests
+
+resp = requests.post("http://localhost:20128/a2a", json={
+ "jsonrpc": "2.0", "id": "1",
+ "method": "message/send",
+ "params": {
+ "skill": "smart-routing",
+ "messages": [{"role": "user", "content": "Hello"}]
+ }
+}, headers={"Authorization": "Bearer YOUR_KEY"})
+
+result = resp.json()["result"]
+print(result["artifacts"][0]["content"])
+print(result["metadata"]["routing_explanation"])
+```
+
+### TypeScript (fetch)
+
+```typescript
+const resp = await fetch("http://localhost:20128/a2a", {
+ method: "POST",
+ headers: {
+ "Content-Type": "application/json",
+ Authorization: "Bearer YOUR_KEY",
+ },
+ body: JSON.stringify({
+ jsonrpc: "2.0",
+ id: "1",
+ method: "message/send",
+ params: {
+ skill: "smart-routing",
+ messages: [{ role: "user", content: "Hello" }],
+ },
+ }),
+});
+const { result } = await resp.json();
+console.log(result.metadata.routing_explanation);
+```
diff --git a/docs/i18n/de/docs/API_REFERENCE.md b/docs/i18n/de/docs/API_REFERENCE.md
new file mode 100644
index 0000000000..da1cbbde6e
--- /dev/null
+++ b/docs/i18n/de/docs/API_REFERENCE.md
@@ -0,0 +1,465 @@
+# API Reference (Deutsch)
+
+🌐 **Languages:** 🇺🇸 [English](../../../../docs/API_REFERENCE.md) · 🇪🇸 [es](../../es/docs/API_REFERENCE.md) · 🇫🇷 [fr](../../fr/docs/API_REFERENCE.md) · 🇩🇪 [de](../../de/docs/API_REFERENCE.md) · 🇮🇹 [it](../../it/docs/API_REFERENCE.md) · 🇷🇺 [ru](../../ru/docs/API_REFERENCE.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/API_REFERENCE.md) · 🇯🇵 [ja](../../ja/docs/API_REFERENCE.md) · 🇰🇷 [ko](../../ko/docs/API_REFERENCE.md) · 🇸🇦 [ar](../../ar/docs/API_REFERENCE.md) · 🇮🇳 [in](../../in/docs/API_REFERENCE.md) · 🇹🇭 [th](../../th/docs/API_REFERENCE.md) · 🇻🇳 [vi](../../vi/docs/API_REFERENCE.md) · 🇮🇩 [id](../../id/docs/API_REFERENCE.md) · 🇲🇾 [ms](../../ms/docs/API_REFERENCE.md) · 🇳🇱 [nl](../../nl/docs/API_REFERENCE.md) · 🇵🇱 [pl](../../pl/docs/API_REFERENCE.md) · 🇸🇪 [sv](../../sv/docs/API_REFERENCE.md) · 🇳🇴 [no](../../no/docs/API_REFERENCE.md) · 🇩🇰 [da](../../da/docs/API_REFERENCE.md) · 🇫🇮 [fi](../../fi/docs/API_REFERENCE.md) · 🇵🇹 [pt](../../pt/docs/API_REFERENCE.md) · 🇷🇴 [ro](../../ro/docs/API_REFERENCE.md) · 🇭🇺 [hu](../../hu/docs/API_REFERENCE.md) · 🇧🇬 [bg](../../bg/docs/API_REFERENCE.md) · 🇸🇰 [sk](../../sk/docs/API_REFERENCE.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/API_REFERENCE.md) · 🇮🇱 [he](../../he/docs/API_REFERENCE.md) · 🇵🇭 [phi](../../phi/docs/API_REFERENCE.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/API_REFERENCE.md) · 🇨🇿 [cs](../../cs/docs/API_REFERENCE.md)
+
+---
+
+Complete reference for all OmniRoute API endpoints.
+
+---
+
+## Table of Contents
+
+- [Chat Completions](#chat-completions)
+- [Embeddings](#embeddings)
+- [Image Generation](#image-generation)
+- [List Models](#list-models)
+- [Compatibility Endpoints](#compatibility-endpoints)
+- [Semantic Cache](#semantic-cache)
+- [Dashboard & Management](#dashboard--management)
+- [Request Processing](#request-processing)
+- [Authentication](#authentication)
+
+---
+
+## Chat Completions
+
+```bash
+POST /v1/chat/completions
+Authorization: Bearer your-api-key
+Content-Type: application/json
+
+{
+ "model": "cc/claude-opus-4-6",
+ "messages": [
+ {"role": "user", "content": "Write a function to..."}
+ ],
+ "stream": true
+}
+```
+
+### Custom Headers
+
+| Header | Direction | Description |
+| ------------------------ | --------- | ------------------------------------------------ |
+| `X-OmniRoute-No-Cache` | Request | Set to `true` to bypass cache |
+| `X-OmniRoute-Progress` | Request | Set to `true` for progress events |
+| `X-Session-Id` | Request | Sticky session key for external session affinity |
+| `x_session_id` | Request | Underscore variant also accepted (direct HTTP) |
+| `Idempotency-Key` | Request | Dedup key (5s window) |
+| `X-Request-Id` | Request | Alternative dedup key |
+| `X-OmniRoute-Cache` | Response | `HIT` or `MISS` (non-streaming) |
+| `X-OmniRoute-Idempotent` | Response | `true` if deduplicated |
+| `X-OmniRoute-Progress` | Response | `enabled` if progress tracking on |
+| `X-OmniRoute-Session-Id` | Response | Effective session ID used by OmniRoute |
+
+> Nginx note: if you rely on underscore headers (for example `x_session_id`), enable `underscores_in_headers on;`.
+
+---
+
+## Embeddings
+
+```bash
+POST /v1/embeddings
+Authorization: Bearer your-api-key
+Content-Type: application/json
+
+{
+ "model": "nebius/Qwen/Qwen3-Embedding-8B",
+ "input": "The food was delicious"
+}
+```
+
+Available providers: Nebius, OpenAI, Mistral, Together AI, Fireworks, NVIDIA.
+
+```bash
+# List all embedding models
+GET /v1/embeddings
+```
+
+---
+
+## Image Generation
+
+```bash
+POST /v1/images/generations
+Authorization: Bearer your-api-key
+Content-Type: application/json
+
+{
+ "model": "openai/dall-e-3",
+ "prompt": "A beautiful sunset over mountains",
+ "size": "1024x1024"
+}
+```
+
+Available providers: OpenAI (DALL-E), xAI (Grok Image), Together AI (FLUX), Fireworks AI.
+
+```bash
+# List all image models
+GET /v1/images/generations
+```
+
+---
+
+## List Models
+
+```bash
+GET /v1/models
+Authorization: Bearer your-api-key
+
+→ Returns all chat, embedding, and image models + combos in OpenAI format
+```
+
+---
+
+## Compatibility Endpoints
+
+| Method | Path | Format |
+| ------ | --------------------------- | ---------------------- |
+| POST | `/v1/chat/completions` | OpenAI |
+| POST | `/v1/messages` | Anthropic |
+| POST | `/v1/responses` | OpenAI Responses |
+| POST | `/v1/embeddings` | OpenAI |
+| POST | `/v1/images/generations` | OpenAI |
+| GET | `/v1/models` | OpenAI |
+| POST | `/v1/messages/count_tokens` | Anthropic |
+| GET | `/v1beta/models` | Gemini |
+| POST | `/v1beta/models/{...path}` | Gemini generateContent |
+| POST | `/v1/api/chat` | Ollama |
+
+### Dedicated Provider Routes
+
+```bash
+POST /v1/providers/{provider}/chat/completions
+POST /v1/providers/{provider}/embeddings
+POST /v1/providers/{provider}/images/generations
+```
+
+The provider prefix is auto-added if missing. Mismatched models return `400`.
+
+---
+
+## Semantic Cache
+
+```bash
+# Get cache stats
+GET /api/cache/stats
+
+# Clear all caches
+DELETE /api/cache/stats
+```
+
+Response example:
+
+```json
+{
+ "semanticCache": {
+ "memorySize": 42,
+ "memoryMaxSize": 500,
+ "dbSize": 128,
+ "hitRate": 0.65
+ },
+ "idempotency": {
+ "activeKeys": 3,
+ "windowMs": 5000
+ }
+}
+```
+
+---
+
+## Dashboard & Management
+
+### Authentication
+
+| Endpoint | Method | Description |
+| ----------------------------- | ------- | --------------------- |
+| `/api/auth/login` | POST | Login |
+| `/api/auth/logout` | POST | Logout |
+| `/api/settings/require-login` | GET/PUT | Toggle login required |
+
+### Provider Management
+
+| Endpoint | Method | Description |
+| ---------------------------- | --------------- | ------------------------ |
+| `/api/providers` | GET/POST | List / create providers |
+| `/api/providers/[id]` | GET/PUT/DELETE | Manage a provider |
+| `/api/providers/[id]/test` | POST | Test provider connection |
+| `/api/providers/[id]/models` | GET | List provider models |
+| `/api/providers/validate` | POST | Validate provider config |
+| `/api/provider-nodes*` | Various | Provider node management |
+| `/api/provider-models` | GET/POST/DELETE | Custom models |
+
+### OAuth Flows
+
+| Endpoint | Method | Description |
+| -------------------------------- | ------- | ----------------------- |
+| `/api/oauth/[provider]/[action]` | Various | Provider-specific OAuth |
+
+### Routing & Config
+
+| Endpoint | Method | Description |
+| --------------------- | -------- | ----------------------------- |
+| `/api/models/alias` | GET/POST | Model aliases |
+| `/api/models/catalog` | GET | All models by provider + type |
+| `/api/combos*` | Various | Combo management |
+| `/api/keys*` | Various | API key management |
+| `/api/pricing` | GET | Model pricing |
+
+### Usage & Analytics
+
+| Endpoint | Method | Description |
+| --------------------------- | ------ | -------------------- |
+| `/api/usage/history` | GET | Usage history |
+| `/api/usage/logs` | GET | Usage logs |
+| `/api/usage/request-logs` | GET | Request-level logs |
+| `/api/usage/[connectionId]` | GET | Per-connection usage |
+
+### Settings
+
+| Endpoint | Method | Description |
+| ------------------------------- | ------------- | ---------------------- |
+| `/api/settings` | GET/PUT/PATCH | General settings |
+| `/api/settings/proxy` | GET/PUT | Network proxy config |
+| `/api/settings/proxy/test` | POST | Test proxy connection |
+| `/api/settings/ip-filter` | GET/PUT | IP allowlist/blocklist |
+| `/api/settings/thinking-budget` | GET/PUT | Reasoning token budget |
+| `/api/settings/system-prompt` | GET/PUT | Global system prompt |
+
+### Monitoring
+
+| Endpoint | Method | Description |
+| ------------------------ | ---------- | ---------------------------------------------------------------------------------------------------- |
+| `/api/sessions` | GET | Active session tracking |
+| `/api/rate-limits` | GET | Per-account rate limits |
+| `/api/monitoring/health` | GET | Health check + provider summary (`catalogCount`, `configuredCount`, `activeCount`, `monitoredCount`) |
+| `/api/cache/stats` | GET/DELETE | Cache stats / clear |
+
+### Backup & Export/Import
+
+| Endpoint | Method | Description |
+| --------------------------- | ------ | --------------------------------------- |
+| `/api/db-backups` | GET | List available backups |
+| `/api/db-backups` | PUT | Create a manual backup |
+| `/api/db-backups` | POST | Restore from a specific backup |
+| `/api/db-backups/export` | GET | Download database as .sqlite file |
+| `/api/db-backups/import` | POST | Upload .sqlite file to replace database |
+| `/api/db-backups/exportAll` | GET | Download full backup as .tar.gz archive |
+
+### Cloud Sync
+
+| Endpoint | Method | Description |
+| ---------------------- | ------- | --------------------- |
+| `/api/sync/cloud` | Various | Cloud sync operations |
+| `/api/sync/initialize` | POST | Initialize sync |
+| `/api/cloud/*` | Various | Cloud management |
+
+### Tunnels
+
+| Endpoint | Method | Description |
+| -------------------------- | ------ | ----------------------------------------------------------------------- |
+| `/api/tunnels/cloudflared` | GET | Read Cloudflare Quick Tunnel install/runtime status for the dashboard |
+| `/api/tunnels/cloudflared` | POST | Enable or disable the Cloudflare Quick Tunnel (`action=enable/disable`) |
+
+### CLI Tools
+
+| Endpoint | Method | Description |
+| ---------------------------------- | ------ | ------------------- |
+| `/api/cli-tools/claude-settings` | GET | Claude CLI status |
+| `/api/cli-tools/codex-settings` | GET | Codex CLI status |
+| `/api/cli-tools/droid-settings` | GET | Droid CLI status |
+| `/api/cli-tools/openclaw-settings` | GET | OpenClaw CLI status |
+| `/api/cli-tools/runtime/[toolId]` | GET | Generic CLI runtime |
+
+CLI responses include: `installed`, `runnable`, `command`, `commandPath`, `runtimeMode`, `reason`.
+
+### ACP Agents
+
+| Endpoint | Method | Description |
+| ----------------- | ------ | -------------------------------------------------------- |
+| `/api/acp/agents` | GET | List all detected agents (built-in + custom) with status |
+| `/api/acp/agents` | POST | Add custom agent or refresh detection cache |
+| `/api/acp/agents` | DELETE | Remove a custom agent by `id` query param |
+
+GET response includes `agents[]` (id, name, binary, version, installed, protocol, isCustom) and `summary` (total, installed, notFound, builtIn, custom).
+
+### Resilience & Rate Limits
+
+| Endpoint | Method | Description |
+| ----------------------- | --------- | ------------------------------- |
+| `/api/resilience` | GET/PATCH | Get/update resilience profiles |
+| `/api/resilience/reset` | POST | Reset circuit breakers |
+| `/api/rate-limits` | GET | Per-account rate limit status |
+| `/api/rate-limit` | GET | Global rate limit configuration |
+
+### Evals
+
+| Endpoint | Method | Description |
+| ------------ | -------- | --------------------------------- |
+| `/api/evals` | GET/POST | List eval suites / run evaluation |
+
+### Policies
+
+| Endpoint | Method | Description |
+| --------------- | --------------- | ----------------------- |
+| `/api/policies` | GET/POST/DELETE | Manage routing policies |
+
+### Compliance
+
+| Endpoint | Method | Description |
+| --------------------------- | ------ | ----------------------------- |
+| `/api/compliance/audit-log` | GET | Compliance audit log (last N) |
+
+### v1beta (Gemini-Compatible)
+
+| Endpoint | Method | Description |
+| -------------------------- | ------ | --------------------------------- |
+| `/v1beta/models` | GET | List models in Gemini format |
+| `/v1beta/models/{...path}` | POST | Gemini `generateContent` endpoint |
+
+These endpoints mirror Gemini's API format for clients that expect native Gemini SDK compatibility.
+
+### Internal / System APIs
+
+| Endpoint | Method | Description |
+| --------------- | ------ | ---------------------------------------------------- |
+| `/api/init` | GET | Application initialization check (used on first run) |
+| `/api/tags` | GET | Ollama-compatible model tags (for Ollama clients) |
+| `/api/restart` | POST | Trigger graceful server restart |
+| `/api/shutdown` | POST | Trigger graceful server shutdown |
+
+> **Note:** These endpoints are used internally by the system or for Ollama client compatibility. They are not typically called by end users.
+
+---
+
+## Audio Transcription
+
+```bash
+POST /v1/audio/transcriptions
+Authorization: Bearer your-api-key
+Content-Type: multipart/form-data
+```
+
+Transcribe audio files using Deepgram or AssemblyAI.
+
+**Request:**
+
+```bash
+curl -X POST http://localhost:20128/v1/audio/transcriptions \
+ -H "Authorization: Bearer your-api-key" \
+ -F "file=@recording.mp3" \
+ -F "model=deepgram/nova-3"
+```
+
+**Response:**
+
+```json
+{
+ "text": "Hello, this is the transcribed audio content.",
+ "task": "transcribe",
+ "language": "en",
+ "duration": 12.5
+}
+```
+
+**Supported providers:** `deepgram/nova-3`, `assemblyai/best`.
+
+**Supported formats:** `mp3`, `wav`, `m4a`, `flac`, `ogg`, `webm`.
+
+---
+
+## Ollama Compatibility
+
+For clients that use Ollama's API format:
+
+```bash
+# Chat endpoint (Ollama format)
+POST /v1/api/chat
+
+# Model listing (Ollama format)
+GET /api/tags
+```
+
+Requests are automatically translated between Ollama and internal formats.
+
+---
+
+## Telemetry
+
+```bash
+# Get latency telemetry summary (p50/p95/p99 per provider)
+GET /api/telemetry/summary
+```
+
+**Response:**
+
+```json
+{
+ "providers": {
+ "claudeCode": { "p50": 245, "p95": 890, "p99": 1200, "count": 150 },
+ "github": { "p50": 180, "p95": 620, "p99": 950, "count": 320 }
+ }
+}
+```
+
+---
+
+## Budget
+
+```bash
+# Get budget status for all API keys
+GET /api/usage/budget
+
+# Set or update a budget
+POST /api/usage/budget
+Content-Type: application/json
+
+{
+ "keyId": "key-123",
+ "limit": 50.00,
+ "period": "monthly"
+}
+```
+
+---
+
+## Model Availability
+
+```bash
+# Get real-time model availability across all providers
+GET /api/models/availability
+
+# Check availability for a specific model
+POST /api/models/availability
+Content-Type: application/json
+
+{
+ "model": "claude-sonnet-4-5-20250929"
+}
+```
+
+---
+
+## Request Processing
+
+1. Client sends request to `/v1/*`
+2. Route handler calls `handleChat`, `handleEmbedding`, `handleAudioTranscription`, or `handleImageGeneration`
+3. Model is resolved (direct provider/model or alias/combo)
+4. Credentials selected from local DB with account availability filtering
+5. For chat: `handleChatCore` — format detection, translation, cache check, idempotency check
+6. Provider executor sends upstream request
+7. Response translated back to client format (chat) or returned as-is (embeddings/images/audio)
+8. Usage/logging recorded
+9. Fallback applies on errors according to combo rules
+
+Full architecture reference: [`ARCHITECTURE.md`](ARCHITECTURE.md)
+
+---
+
+## Authentication
+
+- Dashboard routes (`/dashboard/*`) use `auth_token` cookie
+- Login uses saved password hash; fallback to `INITIAL_PASSWORD`
+- `requireLogin` toggleable via `/api/settings/require-login`
+- `/v1/*` routes optionally require Bearer API key when `REQUIRE_API_KEY=true`
diff --git a/docs/i18n/de/docs/ARCHITECTURE.md b/docs/i18n/de/docs/ARCHITECTURE.md
new file mode 100644
index 0000000000..b46b692b63
--- /dev/null
+++ b/docs/i18n/de/docs/ARCHITECTURE.md
@@ -0,0 +1,814 @@
+# OmniRoute Architecture (Deutsch)
+
+🌐 **Languages:** 🇺🇸 [English](../../../../docs/ARCHITECTURE.md) · 🇪🇸 [es](../../es/docs/ARCHITECTURE.md) · 🇫🇷 [fr](../../fr/docs/ARCHITECTURE.md) · 🇩🇪 [de](../../de/docs/ARCHITECTURE.md) · 🇮🇹 [it](../../it/docs/ARCHITECTURE.md) · 🇷🇺 [ru](../../ru/docs/ARCHITECTURE.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/ARCHITECTURE.md) · 🇯🇵 [ja](../../ja/docs/ARCHITECTURE.md) · 🇰🇷 [ko](../../ko/docs/ARCHITECTURE.md) · 🇸🇦 [ar](../../ar/docs/ARCHITECTURE.md) · 🇮🇳 [in](../../in/docs/ARCHITECTURE.md) · 🇹🇭 [th](../../th/docs/ARCHITECTURE.md) · 🇻🇳 [vi](../../vi/docs/ARCHITECTURE.md) · 🇮🇩 [id](../../id/docs/ARCHITECTURE.md) · 🇲🇾 [ms](../../ms/docs/ARCHITECTURE.md) · 🇳🇱 [nl](../../nl/docs/ARCHITECTURE.md) · 🇵🇱 [pl](../../pl/docs/ARCHITECTURE.md) · 🇸🇪 [sv](../../sv/docs/ARCHITECTURE.md) · 🇳🇴 [no](../../no/docs/ARCHITECTURE.md) · 🇩🇰 [da](../../da/docs/ARCHITECTURE.md) · 🇫🇮 [fi](../../fi/docs/ARCHITECTURE.md) · 🇵🇹 [pt](../../pt/docs/ARCHITECTURE.md) · 🇷🇴 [ro](../../ro/docs/ARCHITECTURE.md) · 🇭🇺 [hu](../../hu/docs/ARCHITECTURE.md) · 🇧🇬 [bg](../../bg/docs/ARCHITECTURE.md) · 🇸🇰 [sk](../../sk/docs/ARCHITECTURE.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/ARCHITECTURE.md) · 🇮🇱 [he](../../he/docs/ARCHITECTURE.md) · 🇵🇭 [phi](../../phi/docs/ARCHITECTURE.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/ARCHITECTURE.md) · 🇨🇿 [cs](../../cs/docs/ARCHITECTURE.md)
+
+---
+
+_Last updated: 2026-03-28_
+
+## Executive Summary
+
+OmniRoute is a local AI routing gateway and dashboard built on Next.js.
+It provides a single OpenAI-compatible endpoint (`/v1/*`) and routes traffic across multiple upstream providers with translation, fallback, token refresh, and usage tracking.
+
+Core capabilities:
+
+- OpenAI-compatible API surface for CLI/tools (28 providers)
+- Request/response translation across provider formats
+- Model combo fallback (multi-model sequence)
+- Account-level fallback (multi-account per provider)
+- OAuth + API-key provider connection management
+- Embedding generation via `/v1/embeddings` (6 providers, 9 models)
+- Image generation via `/v1/images/generations` (4 providers, 9 models)
+- Think tag parsing (`...`) for reasoning models
+- Response sanitization for strict OpenAI SDK compatibility
+- Role normalization (developer→system, system→user) for cross-provider compatibility
+- Structured output conversion (json_schema → Gemini responseSchema)
+- Local persistence for providers, keys, aliases, combos, settings, pricing
+- Usage/cost tracking and request logging
+- Optional cloud sync for multi-device/state sync
+- IP allowlist/blocklist for API access control
+- Thinking budget management (passthrough/auto/custom/adaptive)
+- Global system prompt injection
+- Session tracking and fingerprinting
+- Per-account enhanced rate limiting with provider-specific profiles
+- Circuit breaker pattern for provider resilience
+- Anti-thundering herd protection with mutex locking
+- Signature-based request deduplication cache
+- Domain layer: model availability, cost rules, fallback policy, lockout policy
+- Domain state persistence (SQLite write-through cache for fallbacks, budgets, lockouts, circuit breakers)
+- Policy engine for centralized request evaluation (lockout → budget → fallback)
+- Request telemetry with p50/p95/p99 latency aggregation
+- Correlation ID (X-Request-Id) for end-to-end tracing
+- Compliance audit logging with opt-out per API key
+- Eval framework for LLM quality assurance
+- Resilience UI dashboard with real-time circuit breaker status
+- Modular OAuth providers (12 individual modules under `src/lib/oauth/providers/`)
+
+Primary runtime model:
+
+- Next.js app routes under `src/app/api/*` implement both dashboard APIs and compatibility APIs
+- A shared SSE/routing core in `src/sse/*` + `open-sse/*` handles provider execution, translation, streaming, fallback, and usage
+
+## Scope and Boundaries
+
+### In Scope
+
+- Local gateway runtime
+- Dashboard management APIs
+- Provider authentication and token refresh
+- Request translation and SSE streaming
+- Local state + usage persistence
+- Optional cloud sync orchestration
+
+### Out of Scope
+
+- Cloud service implementation behind `NEXT_PUBLIC_CLOUD_URL`
+- Provider SLA/control plane outside local process
+- External CLI binaries themselves (Claude CLI, Codex CLI, etc.)
+
+## Dashboard Surface (Current)
+
+Main pages under `src/app/(dashboard)/dashboard/`:
+
+- `/dashboard` — quick start + provider overview
+- `/dashboard/endpoint` — endpoint proxy + MCP + A2A + API endpoint tabs
+- `/dashboard/providers` — provider connections and credentials
+- `/dashboard/combos` — combo strategies, templates, model routing rules
+- `/dashboard/costs` — cost aggregation and pricing visibility
+- `/dashboard/analytics` — usage analytics and evaluations
+- `/dashboard/limits` — quota/rate controls
+- `/dashboard/cli-tools` — CLI onboarding, runtime detection, config generation
+- `/dashboard/agents` — detected ACP agents + custom agent registration
+- `/dashboard/media` — image/video/music playground
+- `/dashboard/search-tools` — search provider testing and history
+- `/dashboard/health` — uptime, circuit breakers, rate limits
+- `/dashboard/logs` — request/proxy/audit/console logs
+- `/dashboard/settings` — system settings tabs (general, routing, combo defaults, etc.)
+- `/dashboard/api-manager` — API key lifecycle and model permissions
+
+## High-Level System Context
+
+```mermaid
+flowchart LR
+ subgraph Clients[Developer Clients]
+ C1[Claude Code]
+ C2[Codex CLI]
+ C3[OpenClaw / Droid / Cline / Continue / Roo]
+ C4[Custom OpenAI-compatible clients]
+ BROWSER[Browser Dashboard]
+ end
+
+ subgraph Router[OmniRoute Local Process]
+ API[V1 Compatibility API\n/v1/*]
+ DASH[Dashboard + Management API\n/api/*]
+ CORE[SSE + Translation Core\nopen-sse + src/sse]
+ DB[(storage.sqlite)]
+ UDB[(usage tables + log artifacts)]
+ end
+
+ subgraph Upstreams[Upstream Providers]
+ P1[OAuth Providers\nClaude/Codex/Gemini/Qwen/Qoder/GitHub/Kiro/Cursor/Antigravity]
+ P2[API Key Providers\nOpenAI/Anthropic/OpenRouter/GLM/Kimi/MiniMax\nDeepSeek/Groq/xAI/Mistral/Perplexity\nTogether/Fireworks/Cerebras/Cohere/NVIDIA]
+ P3[Compatible Nodes\nOpenAI-compatible / Anthropic-compatible]
+ end
+
+ subgraph Cloud[Optional Cloud Sync]
+ CLOUD[Cloud Sync Endpoint\nNEXT_PUBLIC_CLOUD_URL]
+ end
+
+ C1 --> API
+ C2 --> API
+ C3 --> API
+ C4 --> API
+ BROWSER --> DASH
+
+ API --> CORE
+ DASH --> DB
+ CORE --> DB
+ CORE --> UDB
+
+ CORE --> P1
+ CORE --> P2
+ CORE --> P3
+
+ DASH --> CLOUD
+```
+
+## Core Runtime Components
+
+## 1) API and Routing Layer (Next.js App Routes)
+
+Main directories:
+
+- `src/app/api/v1/*` and `src/app/api/v1beta/*` for compatibility APIs
+- `src/app/api/*` for management/configuration APIs
+- Next rewrites in `next.config.mjs` map `/v1/*` to `/api/v1/*`
+
+Important compatibility routes:
+
+- `src/app/api/v1/chat/completions/route.ts`
+- `src/app/api/v1/messages/route.ts`
+- `src/app/api/v1/responses/route.ts`
+- `src/app/api/v1/models/route.ts` — includes custom models with `custom: true`
+- `src/app/api/v1/embeddings/route.ts` — embedding generation (6 providers)
+- `src/app/api/v1/images/generations/route.ts` — image generation (4+ providers incl. Antigravity/Nebius)
+- `src/app/api/v1/messages/count_tokens/route.ts`
+- `src/app/api/v1/providers/[provider]/chat/completions/route.ts` — dedicated per-provider chat
+- `src/app/api/v1/providers/[provider]/embeddings/route.ts` — dedicated per-provider embeddings
+- `src/app/api/v1/providers/[provider]/images/generations/route.ts` — dedicated per-provider images
+- `src/app/api/v1beta/models/route.ts`
+- `src/app/api/v1beta/models/[...path]/route.ts`
+
+Management domains:
+
+- Auth/settings: `src/app/api/auth/*`, `src/app/api/settings/*`
+- Providers/connections: `src/app/api/providers*`
+- Provider nodes: `src/app/api/provider-nodes*`
+- Custom models: `src/app/api/provider-models` (GET/POST/DELETE)
+- Model catalog: `src/app/api/models/route.ts` (GET)
+- Proxy config: `src/app/api/settings/proxy` (GET/PUT/DELETE) + `src/app/api/settings/proxy/test` (POST)
+- OAuth: `src/app/api/oauth/*`
+- Keys/aliases/combos/pricing: `src/app/api/keys*`, `src/app/api/models/alias`, `src/app/api/combos*`, `src/app/api/pricing`
+- Usage: `src/app/api/usage/*`
+- Sync/cloud: `src/app/api/sync/*`, `src/app/api/cloud/*`
+- CLI tooling helpers: `src/app/api/cli-tools/*`
+- IP filter: `src/app/api/settings/ip-filter` (GET/PUT)
+- Thinking budget: `src/app/api/settings/thinking-budget` (GET/PUT)
+- System prompt: `src/app/api/settings/system-prompt` (GET/PUT)
+- Sessions: `src/app/api/sessions` (GET)
+- Rate limits: `src/app/api/rate-limits` (GET)
+- Resilience: `src/app/api/resilience` (GET/PATCH) — provider profiles, circuit breaker, rate limit state
+- Resilience reset: `src/app/api/resilience/reset` (POST) — reset breakers + cooldowns
+- Cache stats: `src/app/api/cache/stats` (GET/DELETE)
+- Model availability: `src/app/api/models/availability` (GET/POST)
+- Telemetry: `src/app/api/telemetry/summary` (GET)
+- Budget: `src/app/api/usage/budget` (GET/POST)
+- Fallback chains: `src/app/api/fallback/chains` (GET/POST/DELETE)
+- Compliance audit: `src/app/api/compliance/audit-log` (GET)
+- Evals: `src/app/api/evals` (GET/POST), `src/app/api/evals/[suiteId]` (GET)
+- Policies: `src/app/api/policies` (GET/POST)
+
+## 2) SSE + Translation Core
+
+Main flow modules:
+
+- Entry: `src/sse/handlers/chat.ts`
+- Core orchestration: `open-sse/handlers/chatCore.ts`
+- Provider execution adapters: `open-sse/executors/*`
+- Format detection/provider config: `open-sse/services/provider.ts`
+- Model parse/resolve: `src/sse/services/model.ts`, `open-sse/services/model.ts`
+- Account fallback logic: `open-sse/services/accountFallback.ts`
+- Translation registry: `open-sse/translator/index.ts`
+- Stream transformations: `open-sse/utils/stream.ts`, `open-sse/utils/streamHandler.ts`
+- Usage extraction/normalization: `open-sse/utils/usageTracking.ts`
+- Think tag parser: `open-sse/utils/thinkTagParser.ts`
+- Embedding handler: `open-sse/handlers/embeddings.ts`
+- Embedding provider registry: `open-sse/config/embeddingRegistry.ts`
+- Image generation handler: `open-sse/handlers/imageGeneration.ts`
+- Image provider registry: `open-sse/config/imageRegistry.ts`
+- Response sanitization: `open-sse/handlers/responseSanitizer.ts`
+- Role normalization: `open-sse/services/roleNormalizer.ts`
+
+Services (business logic):
+
+- Account selection/scoring: `open-sse/services/accountSelector.ts`
+- Context lifecycle management: `open-sse/services/contextManager.ts`
+- IP filter enforcement: `open-sse/services/ipFilter.ts`
+- Session tracking: `open-sse/services/sessionManager.ts`
+- Request deduplication: `open-sse/services/signatureCache.ts`
+- System prompt injection: `open-sse/services/systemPrompt.ts`
+- Thinking budget management: `open-sse/services/thinkingBudget.ts`
+- Wildcard model routing: `open-sse/services/wildcardRouter.ts`
+- Rate limit management: `open-sse/services/rateLimitManager.ts`
+- Circuit breaker: `open-sse/services/circuitBreaker.ts`
+
+Domain layer modules:
+
+- Model availability: `src/lib/domain/modelAvailability.ts`
+- Cost rules/budgets: `src/lib/domain/costRules.ts`
+- Fallback policy: `src/lib/domain/fallbackPolicy.ts`
+- Combo resolver: `src/lib/domain/comboResolver.ts`
+- Lockout policy: `src/lib/domain/lockoutPolicy.ts`
+- Policy engine: `src/domain/policyEngine.ts` — centralized lockout → budget → fallback evaluation
+- Error codes catalog: `src/lib/domain/errorCodes.ts`
+- Request ID: `src/lib/domain/requestId.ts`
+- Fetch timeout: `src/lib/domain/fetchTimeout.ts`
+- Request telemetry: `src/lib/domain/requestTelemetry.ts`
+- Compliance/audit: `src/lib/domain/compliance/index.ts`
+- Eval runner: `src/lib/domain/evalRunner.ts`
+- Domain state persistence: `src/lib/db/domainState.ts` — SQLite CRUD for fallback chains, budgets, cost history, lockout state, circuit breakers
+
+OAuth provider modules (12 individual files under `src/lib/oauth/providers/`):
+
+- Registry index: `src/lib/oauth/providers/index.ts`
+- Individual providers: `claude.ts`, `codex.ts`, `gemini.ts`, `antigravity.ts`, `qoder.ts`, `qwen.ts`, `kimi-coding.ts`, `github.ts`, `kiro.ts`, `cursor.ts`, `kilocode.ts`, `cline.ts`
+- Thin wrapper: `src/lib/oauth/providers.ts` — re-exports from individual modules
+
+## 3) Persistence Layer
+
+Primary state DB (SQLite):
+
+- Core infra: `src/lib/db/core.ts` (better-sqlite3, migrations, WAL)
+- Re-export facade: `src/lib/localDb.ts` (thin compatibility layer for callers)
+- file: `${DATA_DIR}/storage.sqlite` (or `$XDG_CONFIG_HOME/omniroute/storage.sqlite` when set, else `~/.omniroute/storage.sqlite`)
+- entities (tables + KV namespaces): providerConnections, providerNodes, modelAliases, combos, apiKeys, settings, pricing, **customModels**, **proxyConfig**, **ipFilter**, **thinkingBudget**, **systemPrompt**
+
+Usage persistence:
+
+- facade: `src/lib/usageDb.ts` (decomposed modules in `src/lib/usage/*`)
+- SQLite tables in `storage.sqlite`: `usage_history`, `call_logs`, `proxy_logs`
+- optional file artifacts remain for compatibility/debug (`${DATA_DIR}/log.txt`, `${DATA_DIR}/call_logs/`, `/logs/...`)
+- legacy JSON files are migrated to SQLite by startup migrations when present
+
+Domain State DB (SQLite):
+
+- `src/lib/db/domainState.ts` — CRUD operations for domain state
+- Tables (created in `src/lib/db/core.ts`): `domain_fallback_chains`, `domain_budgets`, `domain_cost_history`, `domain_lockout_state`, `domain_circuit_breakers`
+- Write-through cache pattern: in-memory Maps are authoritative at runtime; mutations are written synchronously to SQLite; state is restored from DB on cold start
+
+## 4) Auth + Security Surfaces
+
+- Dashboard cookie auth: `src/proxy.ts`, `src/app/api/auth/login/route.ts`
+- API key generation/verification: `src/shared/utils/apiKey.ts`
+- Provider secrets persisted in `providerConnections` entries
+- Outbound proxy support via `open-sse/utils/proxyFetch.ts` (env vars) and `open-sse/utils/networkProxy.ts` (configurable per-provider or global)
+
+## 5) Cloud Sync
+
+- Scheduler init: `src/lib/initCloudSync.ts`, `src/shared/services/initializeCloudSync.ts`, `src/shared/services/modelSyncScheduler.ts`
+- Periodic task: `src/shared/services/cloudSyncScheduler.ts`
+- Periodic task: `src/shared/services/modelSyncScheduler.ts`
+- Control route: `src/app/api/sync/cloud/route.ts`
+
+## Request Lifecycle (`/v1/chat/completions`)
+
+```mermaid
+sequenceDiagram
+ autonumber
+ participant Client as CLI/SDK Client
+ participant Route as /api/v1/chat/completions
+ participant Chat as src/sse/handlers/chat
+ participant Core as open-sse/handlers/chatCore
+ participant Model as Model Resolver
+ participant Auth as Credential Selector
+ participant Exec as Provider Executor
+ participant Prov as Upstream Provider
+ participant Stream as Stream Translator
+ participant Usage as usageDb
+
+ Client->>Route: POST /v1/chat/completions
+ Route->>Chat: handleChat(request)
+ Chat->>Model: parse/resolve model or combo
+
+ alt Combo model
+ Chat->>Chat: iterate combo models (handleComboChat)
+ end
+
+ Chat->>Auth: getProviderCredentials(provider)
+ Auth-->>Chat: active account + tokens/api key
+
+ Chat->>Core: handleChatCore(body, modelInfo, credentials)
+ Core->>Core: detect source format
+ Core->>Core: translate request to target format
+ Core->>Exec: execute(provider, transformedBody)
+ Exec->>Prov: upstream API call
+ Prov-->>Exec: SSE/JSON response
+ Exec-->>Core: response + metadata
+
+ alt 401/403
+ Core->>Exec: refreshCredentials()
+ Exec-->>Core: updated tokens
+ Core->>Exec: retry request
+ end
+
+ Core->>Stream: translate/normalize stream to client format
+ Stream-->>Client: SSE chunks / JSON response
+
+ Stream->>Usage: extract usage + persist history/log
+```
+
+## Combo + Account Fallback Flow
+
+```mermaid
+flowchart TD
+ A[Incoming model string] --> B{Is combo name?}
+ B -- Yes --> C[Load combo models sequence]
+ B -- No --> D[Single model path]
+
+ C --> E[Try model N]
+ E --> F[Resolve provider/model]
+ D --> F
+
+ F --> G[Select account credentials]
+ G --> H{Credentials available?}
+ H -- No --> I[Return provider unavailable]
+ H -- Yes --> J[Execute request]
+
+ J --> K{Success?}
+ K -- Yes --> L[Return response]
+ K -- No --> M{Fallback-eligible error?}
+
+ M -- No --> N[Return error]
+ M -- Yes --> O[Mark account unavailable cooldown]
+ O --> P{Another account for provider?}
+ P -- Yes --> G
+ P -- No --> Q{In combo with next model?}
+ Q -- Yes --> E
+ Q -- No --> R[Return all unavailable]
+```
+
+Fallback decisions are driven by `open-sse/services/accountFallback.ts` using status codes and error-message heuristics. Combo routing adds one extra guard: provider-scoped 400s such as upstream content-block and role-validation failures are treated as model-local failures so later combo targets can still run.
+
+## OAuth Onboarding and Token Refresh Lifecycle
+
+```mermaid
+sequenceDiagram
+ autonumber
+ participant UI as Dashboard UI
+ participant OAuth as /api/oauth/[provider]/[action]
+ participant ProvAuth as Provider Auth Server
+ participant DB as localDb
+ participant Test as /api/providers/[id]/test
+ participant Exec as Provider Executor
+
+ UI->>OAuth: GET authorize or device-code
+ OAuth->>ProvAuth: create auth/device flow
+ ProvAuth-->>OAuth: auth URL or device code payload
+ OAuth-->>UI: flow data
+
+ UI->>OAuth: POST exchange or poll
+ OAuth->>ProvAuth: token exchange/poll
+ ProvAuth-->>OAuth: access/refresh tokens
+ OAuth->>DB: createProviderConnection(oauth data)
+ OAuth-->>UI: success + connection id
+
+ UI->>Test: POST /api/providers/[id]/test
+ Test->>Exec: validate credentials / optional refresh
+ Exec-->>Test: valid or refreshed token info
+ Test->>DB: update status/tokens/errors
+ Test-->>UI: validation result
+```
+
+Refresh during live traffic is executed inside `open-sse/handlers/chatCore.ts` via executor `refreshCredentials()`.
+
+## Cloud Sync Lifecycle (Enable / Sync / Disable)
+
+```mermaid
+sequenceDiagram
+ autonumber
+ participant UI as Endpoint Page UI
+ participant Sync as /api/sync/cloud
+ participant DB as localDb
+ participant Cloud as External Cloud Sync
+ participant Claude as ~/.claude/settings.json
+
+ UI->>Sync: POST action=enable
+ Sync->>DB: set cloudEnabled=true
+ Sync->>DB: ensure API key exists
+ Sync->>Cloud: POST /sync/{machineId} (providers/aliases/combos/keys)
+ Cloud-->>Sync: sync result
+ Sync->>Cloud: GET /{machineId}/v1/verify
+ Sync-->>UI: enabled + verification status
+
+ UI->>Sync: POST action=sync
+ Sync->>Cloud: POST /sync/{machineId}
+ Cloud-->>Sync: remote data
+ Sync->>DB: update newer local tokens/status
+ Sync-->>UI: synced
+
+ UI->>Sync: POST action=disable
+ Sync->>DB: set cloudEnabled=false
+ Sync->>Cloud: DELETE /sync/{machineId}
+ Sync->>Claude: switch ANTHROPIC_BASE_URL back to local (if needed)
+ Sync-->>UI: disabled
+```
+
+Periodic sync is triggered by `CloudSyncScheduler` when cloud is enabled.
+
+## Data Model and Storage Map
+
+```mermaid
+erDiagram
+ SETTINGS ||--o{ PROVIDER_CONNECTION : controls
+ PROVIDER_NODE ||--o{ PROVIDER_CONNECTION : backs_compatible_provider
+ PROVIDER_CONNECTION ||--o{ USAGE_ENTRY : emits_usage
+
+ SETTINGS {
+ boolean cloudEnabled
+ number stickyRoundRobinLimit
+ boolean requireLogin
+ string password_hash
+ string fallbackStrategy
+ json rateLimitDefaults
+ json providerProfiles
+ }
+
+ PROVIDER_CONNECTION {
+ string id
+ string provider
+ string authType
+ string name
+ number priority
+ boolean isActive
+ string apiKey
+ string accessToken
+ string refreshToken
+ string expiresAt
+ string testStatus
+ string lastError
+ string rateLimitedUntil
+ json providerSpecificData
+ }
+
+ PROVIDER_NODE {
+ string id
+ string type
+ string name
+ string prefix
+ string apiType
+ string baseUrl
+ }
+
+ MODEL_ALIAS {
+ string alias
+ string targetModel
+ }
+
+ COMBO {
+ string id
+ string name
+ string[] models
+ }
+
+ API_KEY {
+ string id
+ string name
+ string key
+ string machineId
+ }
+
+ USAGE_ENTRY {
+ string provider
+ string model
+ number prompt_tokens
+ number completion_tokens
+ string connectionId
+ string timestamp
+ }
+
+ CUSTOM_MODEL {
+ string id
+ string name
+ string providerId
+ }
+
+ PROXY_CONFIG {
+ string global
+ json providers
+ }
+
+ IP_FILTER {
+ string mode
+ string[] allowlist
+ string[] blocklist
+ }
+
+ THINKING_BUDGET {
+ string mode
+ number customBudget
+ string effortLevel
+ }
+
+ SYSTEM_PROMPT {
+ boolean enabled
+ string prompt
+ string position
+ }
+```
+
+Physical storage files:
+
+- primary runtime DB: `${DATA_DIR}/storage.sqlite`
+- request log lines: `${DATA_DIR}/log.txt` (compat/debug artifact)
+- structured call payload archives: `${DATA_DIR}/call_logs/`
+- optional translator/request debug sessions: `/logs/...`
+
+## Deployment Topology
+
+```mermaid
+flowchart LR
+ subgraph LocalHost[Developer Host]
+ CLI[CLI Tools]
+ Browser[Dashboard Browser]
+ end
+
+ subgraph ContainerOrProcess[OmniRoute Runtime]
+ Next[Next.js Server\nPORT=20128]
+ Core[SSE Core + Executors]
+ MainDB[(storage.sqlite)]
+ UsageDB[(usage tables + log artifacts)]
+ end
+
+ subgraph External[External Services]
+ Providers[AI Providers]
+ SyncCloud[Cloud Sync Service]
+ end
+
+ CLI --> Next
+ Browser --> Next
+ Next --> Core
+ Next --> MainDB
+ Core --> MainDB
+ Core --> UsageDB
+ Core --> Providers
+ Next --> SyncCloud
+```
+
+## Module Mapping (Decision-Critical)
+
+### Route and API Modules
+
+- `src/app/api/v1/*`, `src/app/api/v1beta/*`: compatibility APIs
+- `src/app/api/v1/providers/[provider]/*`: dedicated per-provider routes (chat, embeddings, images)
+- `src/app/api/providers*`: provider CRUD, validation, testing
+- `src/app/api/provider-nodes*`: custom compatible node management
+- `src/app/api/provider-models`: custom model management (CRUD)
+- `src/app/api/models/route.ts`: model catalog API (aliases + custom models)
+- `src/app/api/oauth/*`: OAuth/device-code flows
+- `src/app/api/keys*`: local API key lifecycle
+- `src/app/api/models/alias`: alias management
+- `src/app/api/combos*`: fallback combo management
+- `src/app/api/pricing`: pricing overrides for cost calculation
+- `src/app/api/settings/proxy`: proxy configuration (GET/PUT/DELETE)
+- `src/app/api/settings/proxy/test`: outbound proxy connectivity test (POST)
+- `src/app/api/usage/*`: usage and logs APIs
+- `src/app/api/sync/*` + `src/app/api/cloud/*`: cloud sync and cloud-facing helpers
+- `src/app/api/cli-tools/*`: local CLI config writers/checkers
+- `src/app/api/settings/ip-filter`: IP allowlist/blocklist (GET/PUT)
+- `src/app/api/settings/thinking-budget`: thinking token budget config (GET/PUT)
+- `src/app/api/settings/system-prompt`: global system prompt (GET/PUT)
+- `src/app/api/sessions`: active session listing (GET)
+- `src/app/api/rate-limits`: per-account rate limit status (GET)
+
+### Routing and Execution Core
+
+- `src/sse/handlers/chat.ts`: request parse, combo handling, account selection loop
+- `open-sse/handlers/chatCore.ts`: translation, executor dispatch, retry/refresh handling, stream setup
+- `open-sse/executors/*`: provider-specific network and format behavior
+
+### Translation Registry and Format Converters
+
+- `open-sse/translator/index.ts`: translator registry and orchestration
+- Request translators: `open-sse/translator/request/*`
+- Response translators: `open-sse/translator/response/*`
+- Format constants: `open-sse/translator/formats.ts`
+
+### Persistence
+
+- `src/lib/db/*`: persistent config/state and domain persistence on SQLite
+- `src/lib/localDb.ts`: compatibility re-export for DB modules
+- `src/lib/usageDb.ts`: usage history/call logs facade on top of SQLite tables
+
+## Provider Executor Coverage (Strategy Pattern)
+
+Each provider has a specialized executor extending `BaseExecutor` (in `open-sse/executors/base.ts`), which provides URL building, header construction, retry with exponential backoff, credential refresh hooks, and the `execute()` orchestration method.
+
+| Executor | Provider(s) | Special Handling |
+| --------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------ | -------------------------------------------------------------------- |
+| `DefaultExecutor` | OpenAI, Claude, Gemini, Qwen, Qoder, OpenRouter, GLM, Kimi, MiniMax, DeepSeek, Groq, xAI, Mistral, Perplexity, Together, Fireworks, Cerebras, Cohere, NVIDIA | Dynamic URL/header config per provider |
+| `AntigravityExecutor` | Google Antigravity | Custom project/session IDs, Retry-After parsing |
+| `CodexExecutor` | OpenAI Codex | Injects system instructions, forces reasoning effort |
+| `CursorExecutor` | Cursor IDE | ConnectRPC protocol, Protobuf encoding, request signing via checksum |
+| `GithubExecutor` | GitHub Copilot | Copilot token refresh, VSCode-mimicking headers |
+| `KiroExecutor` | AWS CodeWhisperer/Kiro | AWS EventStream binary format → SSE conversion |
+| `GeminiCLIExecutor` | Gemini CLI | Google OAuth token refresh cycle |
+
+All other providers (including custom compatible nodes) use the `DefaultExecutor`.
+
+## Provider Compatibility Matrix
+
+| Provider | Format | Auth | Stream | Non-Stream | Token Refresh | Usage API |
+| ---------------- | ---------------- | --------------------- | ---------------- | ---------- | ------------- | ------------------ |
+| Claude | claude | API Key / OAuth | ✅ | ✅ | ✅ | ⚠️ Admin only |
+| Gemini | gemini | API Key / OAuth | ✅ | ✅ | ✅ | ⚠️ Cloud Console |
+| Gemini CLI | gemini-cli | OAuth | ✅ | ✅ | ✅ | ⚠️ Cloud Console |
+| Antigravity | antigravity | OAuth | ✅ | ✅ | ✅ | ✅ Full quota API |
+| OpenAI | openai | API Key | ✅ | ✅ | ❌ | ❌ |
+| Codex | openai-responses | OAuth | ✅ forced | ❌ | ✅ | ✅ Rate limits |
+| GitHub Copilot | openai | OAuth + Copilot Token | ✅ | ✅ | ✅ | ✅ Quota snapshots |
+| Cursor | cursor | Custom checksum | ✅ | ✅ | ❌ | ❌ |
+| Kiro | kiro | AWS SSO OIDC | ✅ (EventStream) | ❌ | ✅ | ✅ Usage limits |
+| Qwen | openai | OAuth | ✅ | ✅ | ✅ | ⚠️ Per request |
+| Qoder | openai | OAuth (Basic) | ✅ | ✅ | ✅ | ⚠️ Per request |
+| OpenRouter | openai | API Key | ✅ | ✅ | ❌ | ❌ |
+| GLM/Kimi/MiniMax | claude | API Key | ✅ | ✅ | ❌ | ❌ |
+| DeepSeek | openai | API Key | ✅ | ✅ | ❌ | ❌ |
+| Groq | openai | API Key | ✅ | ✅ | ❌ | ❌ |
+| xAI (Grok) | openai | API Key | ✅ | ✅ | ❌ | ❌ |
+| Mistral | openai | API Key | ✅ | ✅ | ❌ | ❌ |
+| Perplexity | openai | API Key | ✅ | ✅ | ❌ | ❌ |
+| Together AI | openai | API Key | ✅ | ✅ | ❌ | ❌ |
+| Fireworks AI | openai | API Key | ✅ | ✅ | ❌ | ❌ |
+| Cerebras | openai | API Key | ✅ | ✅ | ❌ | ❌ |
+| Cohere | openai | API Key | ✅ | ✅ | ❌ | ❌ |
+| NVIDIA NIM | openai | API Key | ✅ | ✅ | ❌ | ❌ |
+
+## Format Translation Coverage
+
+Detected source formats include:
+
+- `openai`
+- `openai-responses`
+- `claude`
+- `gemini`
+
+Target formats include:
+
+- OpenAI chat/Responses
+- Claude
+- Gemini/Gemini-CLI/Antigravity envelope
+- Kiro
+- Cursor
+
+Translations use **OpenAI as the hub format** — all conversions go through OpenAI as intermediate:
+
+```
+Source Format → OpenAI (hub) → Target Format
+```
+
+Translations are selected dynamically based on source payload shape and provider target format.
+
+Additional processing layers in the translation pipeline:
+
+- **Response sanitization** — Strips non-standard fields from OpenAI-format responses (both streaming and non-streaming) to ensure strict SDK compliance
+- **Role normalization** — Converts `developer` → `system` for non-OpenAI targets; merges `system` → `user` for models that reject the system role (GLM, ERNIE)
+- **Think tag extraction** — Parses `...` blocks from content into `reasoning_content` field
+- **Structured output** — Converts OpenAI `response_format.json_schema` to Gemini's `responseMimeType` + `responseSchema`
+
+## Supported API Endpoints
+
+| Endpoint | Format | Handler |
+| -------------------------------------------------- | ------------------ | ------------------------------------------------------------------- |
+| `POST /v1/chat/completions` | OpenAI Chat | `src/sse/handlers/chat.ts` |
+| `POST /v1/messages` | Claude Messages | Same handler (auto-detected) |
+| `POST /v1/responses` | OpenAI Responses | `open-sse/handlers/responsesHandler.ts` |
+| `POST /v1/embeddings` | OpenAI Embeddings | `open-sse/handlers/embeddings.ts` |
+| `GET /v1/embeddings` | Model listing | API route |
+| `POST /v1/images/generations` | OpenAI Images | `open-sse/handlers/imageGeneration.ts` |
+| `GET /v1/images/generations` | Model listing | API route |
+| `POST /v1/providers/{provider}/chat/completions` | OpenAI Chat | Dedicated per-provider with model validation |
+| `POST /v1/providers/{provider}/embeddings` | OpenAI Embeddings | Dedicated per-provider with model validation |
+| `POST /v1/providers/{provider}/images/generations` | OpenAI Images | Dedicated per-provider with model validation |
+| `POST /v1/messages/count_tokens` | Claude Token Count | API route |
+| `GET /v1/models` | OpenAI Models list | API route (chat + embedding + image + custom models) |
+| `GET /api/models/catalog` | Catalog | All models grouped by provider + type |
+| `POST /v1beta/models/*:streamGenerateContent` | Gemini native | API route |
+| `GET/PUT/DELETE /api/settings/proxy` | Proxy Config | Network proxy configuration |
+| `POST /api/settings/proxy/test` | Proxy Connectivity | Proxy health/connectivity test endpoint |
+| `GET/POST/DELETE /api/provider-models` | Provider Models | Provider model metadata backing custom and managed available models |
+
+## Bypass Handler
+
+The bypass handler (`open-sse/utils/bypassHandler.ts`) intercepts known "throwaway" requests from Claude CLI — warmup pings, title extractions, and token counts — and returns a **fake response** without consuming upstream provider tokens. This is triggered only when `User-Agent` contains `claude-cli`.
+
+## Request Logger Pipeline
+
+The request logger (`open-sse/utils/requestLogger.ts`) provides a 7-stage debug logging pipeline, disabled by default, enabled via `ENABLE_REQUEST_LOGS=true`:
+
+```
+1_req_client.json → 2_req_source.json → 3_req_openai.json → 4_req_target.json
+→ 5_res_provider.txt → 6_res_openai.txt → 7_res_client.txt
+```
+
+Files are written to `/logs//` for each request session.
+
+## Failure Modes and Resilience
+
+## 1) Account/Provider Availability
+
+- provider account cooldown on transient/rate/auth errors
+- account fallback before failing request
+- combo model fallback when current model/provider path is exhausted
+
+## 2) Token Expiry
+
+- pre-check and refresh with retry for refreshable providers
+- 401/403 retry after refresh attempt in core path
+
+## 3) Stream Safety
+
+- disconnect-aware stream controller
+- translation stream with end-of-stream flush and `[DONE]` handling
+- usage estimation fallback when provider usage metadata is missing
+
+## 4) Cloud Sync Degradation
+
+- sync errors are surfaced but local runtime continues
+- scheduler has retry-capable logic, but periodic execution currently calls single-attempt sync by default
+
+## 5) Data Integrity
+
+- SQLite schema migrations and auto-upgrade hooks at startup
+- legacy JSON → SQLite migration compatibility path
+
+## Observability and Operational Signals
+
+Runtime visibility sources:
+
+- console logs from `src/sse/utils/logger.ts`
+- per-request usage aggregates in SQLite (`usage_history`, `call_logs`, `proxy_logs`)
+- four-stage detailed payload captures in SQLite (`request_detail_logs`) when `settings.detailed_logs_enabled=true`
+- textual request status log in `log.txt` (optional/compat)
+- optional deep request/translation logs under `logs/` when `ENABLE_REQUEST_LOGS=true`
+- dashboard usage endpoints (`/api/usage/*`) for UI consumption
+
+Detailed request payload capture stores up to four JSON payload stages per routed call:
+
+- raw request received from the client
+- translated request actually sent upstream
+- provider response reconstructed as JSON; streamed responses are compacted to the final summary plus stream metadata
+- final client response returned by OmniRoute; streamed responses are stored in the same compact summary form
+
+## Security-Sensitive Boundaries
+
+- JWT secret (`JWT_SECRET`) secures dashboard session cookie verification/signing
+- Initial password bootstrap (`INITIAL_PASSWORD`) should be explicitly configured for first-run provisioning
+- API key HMAC secret (`API_KEY_SECRET`) secures generated local API key format
+- Provider secrets (API keys/tokens) are persisted in local DB and should be protected at filesystem level
+- Cloud sync endpoints rely on API key auth + machine id semantics
+
+## Environment and Runtime Matrix
+
+Environment variables actively used by code:
+
+- App/auth: `JWT_SECRET`, `INITIAL_PASSWORD`
+- Storage: `DATA_DIR`
+- Compatible node behavior: `ALLOW_MULTI_CONNECTIONS_PER_COMPAT_NODE`
+- Optional storage base override (Linux/macOS when `DATA_DIR` unset): `XDG_CONFIG_HOME`
+- Security hashing: `API_KEY_SECRET`, `MACHINE_ID_SALT`
+- Logging: `ENABLE_REQUEST_LOGS`
+- Sync/cloud URLing: `NEXT_PUBLIC_BASE_URL`, `NEXT_PUBLIC_CLOUD_URL`
+- Outbound proxy: `HTTP_PROXY`, `HTTPS_PROXY`, `ALL_PROXY`, `NO_PROXY` and lowercase variants
+- SOCKS5 feature flags: `ENABLE_SOCKS5_PROXY`, `NEXT_PUBLIC_ENABLE_SOCKS5_PROXY`
+- Platform/runtime helpers (not app-specific config): `APPDATA`, `NODE_ENV`, `PORT`, `HOSTNAME`
+
+## Known Architectural Notes
+
+1. `usageDb` and `localDb` share the same base directory policy (`DATA_DIR` -> `XDG_CONFIG_HOME/omniroute` -> `~/.omniroute`) with legacy file migration.
+2. `/api/v1/route.ts` delegates to the same unified catalog builder used by `/api/v1/models` (`src/app/api/v1/models/catalog.ts`) to avoid semantic drift.
+3. Request logger writes full headers/body when enabled; treat log directory as sensitive.
+4. Cloud behavior depends on correct `NEXT_PUBLIC_BASE_URL` and cloud endpoint reachability.
+5. The `open-sse/` directory is published as the `@omniroute/open-sse` **npm workspace package**. Source code imports it via `@omniroute/open-sse/...` (resolved by Next.js `transpilePackages`). File paths in this document still use the directory name `open-sse/` for consistency.
+6. Charts in the dashboard use **Recharts** (SVG-based) for accessible, interactive analytics visualizations (model usage bar charts, provider breakdown tables with success rates).
+7. E2E tests use **Playwright** (`tests/e2e/`), run via `npm run test:e2e`. Unit tests use **Node.js test runner** (`tests/unit/`), run via `npm run test:unit`. Source code under `src/` is **TypeScript** (`.ts`/`.tsx`); the `open-sse/` workspace remains JavaScript (`.js`).
+8. Settings page is organized into 5 tabs: Security, Routing (6 global strategies: fill-first, round-robin, p2c, random, least-used, cost-optimized), Resilience (editable rate limits, circuit breaker, policies), AI (thinking budget, system prompt, prompt cache), Advanced (proxy).
+
+## Operational Verification Checklist
+
+- Build from source: `npm run build`
+- Build Docker image: `docker build -t omniroute .`
+- Start service and verify:
+- `GET /api/settings`
+- `GET /api/v1/models`
+- CLI target base URL should be `http://:20128/v1` when `PORT=20128`
diff --git a/docs/i18n/de/docs/AUTO-COMBO.md b/docs/i18n/de/docs/AUTO-COMBO.md
new file mode 100644
index 0000000000..d44b6de558
--- /dev/null
+++ b/docs/i18n/de/docs/AUTO-COMBO.md
@@ -0,0 +1,67 @@
+# OmniRoute Auto-Combo Engine (Deutsch)
+
+🌐 **Languages:** 🇺🇸 [English](../../../../docs/AUTO-COMBO.md) · 🇪🇸 [es](../../es/docs/AUTO-COMBO.md) · 🇫🇷 [fr](../../fr/docs/AUTO-COMBO.md) · 🇩🇪 [de](../../de/docs/AUTO-COMBO.md) · 🇮🇹 [it](../../it/docs/AUTO-COMBO.md) · 🇷🇺 [ru](../../ru/docs/AUTO-COMBO.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/AUTO-COMBO.md) · 🇯🇵 [ja](../../ja/docs/AUTO-COMBO.md) · 🇰🇷 [ko](../../ko/docs/AUTO-COMBO.md) · 🇸🇦 [ar](../../ar/docs/AUTO-COMBO.md) · 🇮🇳 [in](../../in/docs/AUTO-COMBO.md) · 🇹🇭 [th](../../th/docs/AUTO-COMBO.md) · 🇻🇳 [vi](../../vi/docs/AUTO-COMBO.md) · 🇮🇩 [id](../../id/docs/AUTO-COMBO.md) · 🇲🇾 [ms](../../ms/docs/AUTO-COMBO.md) · 🇳🇱 [nl](../../nl/docs/AUTO-COMBO.md) · 🇵🇱 [pl](../../pl/docs/AUTO-COMBO.md) · 🇸🇪 [sv](../../sv/docs/AUTO-COMBO.md) · 🇳🇴 [no](../../no/docs/AUTO-COMBO.md) · 🇩🇰 [da](../../da/docs/AUTO-COMBO.md) · 🇫🇮 [fi](../../fi/docs/AUTO-COMBO.md) · 🇵🇹 [pt](../../pt/docs/AUTO-COMBO.md) · 🇷🇴 [ro](../../ro/docs/AUTO-COMBO.md) · 🇭🇺 [hu](../../hu/docs/AUTO-COMBO.md) · 🇧🇬 [bg](../../bg/docs/AUTO-COMBO.md) · 🇸🇰 [sk](../../sk/docs/AUTO-COMBO.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/AUTO-COMBO.md) · 🇮🇱 [he](../../he/docs/AUTO-COMBO.md) · 🇵🇭 [phi](../../phi/docs/AUTO-COMBO.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/AUTO-COMBO.md) · 🇨🇿 [cs](../../cs/docs/AUTO-COMBO.md)
+
+---
+
+> Self-managing model chains with adaptive scoring
+
+## How It Works
+
+The Auto-Combo Engine dynamically selects the best provider/model for each request using a **6-factor scoring function**:
+
+| Factor | Weight | Description |
+| :--------- | :----- | :---------------------------------------------- |
+| Quota | 0.20 | Remaining capacity [0..1] |
+| Health | 0.25 | Circuit breaker: CLOSED=1.0, HALF=0.5, OPEN=0.0 |
+| CostInv | 0.20 | Inverse cost (cheaper = higher score) |
+| LatencyInv | 0.15 | Inverse p95 latency (faster = higher) |
+| TaskFit | 0.10 | Model × task type fitness score |
+| Stability | 0.10 | Low variance in latency/errors |
+
+## Mode Packs
+
+| Pack | Focus | Key Weight |
+| :---------------------- | :----------- | :--------------- |
+| 🚀 **Ship Fast** | Speed | latencyInv: 0.35 |
+| 💰 **Cost Saver** | Economy | costInv: 0.40 |
+| 🎯 **Quality First** | Best model | taskFit: 0.40 |
+| 📡 **Offline Friendly** | Availability | quota: 0.40 |
+
+## Self-Healing
+
+- **Temporary exclusion**: Score < 0.2 → excluded for 5 min (progressive backoff, max 30 min)
+- **Circuit breaker awareness**: OPEN → auto-excluded; HALF_OPEN → probe requests
+- **Incident mode**: >50% OPEN → disable exploration, maximize stability
+- **Cooldown recovery**: After exclusion, first request is a "probe" with reduced timeout
+
+## Bandit Exploration
+
+5% of requests (configurable) are routed to random providers for exploration. Disabled in incident mode.
+
+## API
+
+```bash
+# Create auto-combo
+curl -X POST http://localhost:20128/api/combos/auto \
+ -H "Content-Type: application/json" \
+ -d '{"id":"my-auto","name":"Auto Coder","candidatePool":["anthropic","google","openai"],"modePack":"ship-fast"}'
+
+# List auto-combos
+curl http://localhost:20128/api/combos/auto
+```
+
+## Task Fitness
+
+30+ models scored across 6 task types (`coding`, `review`, `planning`, `analysis`, `debugging`, `documentation`). Supports wildcard patterns (e.g., `*-coder` → high coding score).
+
+## Files
+
+| File | Purpose |
+| :------------------------------------------- | :------------------------------------ |
+| `open-sse/services/autoCombo/scoring.ts` | Scoring function & pool normalization |
+| `open-sse/services/autoCombo/taskFitness.ts` | Model × task fitness lookup |
+| `open-sse/services/autoCombo/engine.ts` | Selection logic, bandit, budget cap |
+| `open-sse/services/autoCombo/selfHealing.ts` | Exclusion, probes, incident mode |
+| `open-sse/services/autoCombo/modePacks.ts` | 4 weight profiles |
+| `src/app/api/combos/auto/route.ts` | REST API |
diff --git a/docs/i18n/de/docs/CLI-TOOLS.md b/docs/i18n/de/docs/CLI-TOOLS.md
new file mode 100644
index 0000000000..7427bf004d
--- /dev/null
+++ b/docs/i18n/de/docs/CLI-TOOLS.md
@@ -0,0 +1,348 @@
+# CLI Tools Setup Guide — OmniRoute (Deutsch)
+
+🌐 **Languages:** 🇺🇸 [English](../../../../docs/CLI-TOOLS.md) · 🇪🇸 [es](../../es/docs/CLI-TOOLS.md) · 🇫🇷 [fr](../../fr/docs/CLI-TOOLS.md) · 🇩🇪 [de](../../de/docs/CLI-TOOLS.md) · 🇮🇹 [it](../../it/docs/CLI-TOOLS.md) · 🇷🇺 [ru](../../ru/docs/CLI-TOOLS.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/CLI-TOOLS.md) · 🇯🇵 [ja](../../ja/docs/CLI-TOOLS.md) · 🇰🇷 [ko](../../ko/docs/CLI-TOOLS.md) · 🇸🇦 [ar](../../ar/docs/CLI-TOOLS.md) · 🇮🇳 [in](../../in/docs/CLI-TOOLS.md) · 🇹🇭 [th](../../th/docs/CLI-TOOLS.md) · 🇻🇳 [vi](../../vi/docs/CLI-TOOLS.md) · 🇮🇩 [id](../../id/docs/CLI-TOOLS.md) · 🇲🇾 [ms](../../ms/docs/CLI-TOOLS.md) · 🇳🇱 [nl](../../nl/docs/CLI-TOOLS.md) · 🇵🇱 [pl](../../pl/docs/CLI-TOOLS.md) · 🇸🇪 [sv](../../sv/docs/CLI-TOOLS.md) · 🇳🇴 [no](../../no/docs/CLI-TOOLS.md) · 🇩🇰 [da](../../da/docs/CLI-TOOLS.md) · 🇫🇮 [fi](../../fi/docs/CLI-TOOLS.md) · 🇵🇹 [pt](../../pt/docs/CLI-TOOLS.md) · 🇷🇴 [ro](../../ro/docs/CLI-TOOLS.md) · 🇭🇺 [hu](../../hu/docs/CLI-TOOLS.md) · 🇧🇬 [bg](../../bg/docs/CLI-TOOLS.md) · 🇸🇰 [sk](../../sk/docs/CLI-TOOLS.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/CLI-TOOLS.md) · 🇮🇱 [he](../../he/docs/CLI-TOOLS.md) · 🇵🇭 [phi](../../phi/docs/CLI-TOOLS.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/CLI-TOOLS.md) · 🇨🇿 [cs](../../cs/docs/CLI-TOOLS.md)
+
+---
+
+This guide explains how to install and configure all supported AI coding CLI tools
+to use **OmniRoute** as the unified backend, giving you centralized key management,
+cost tracking, model switching, and request logging across every tool.
+
+---
+
+## How It Works
+
+```
+Claude / Codex / OpenCode / Cline / KiloCode / Continue / Kiro / Cursor / Copilot
+ │
+ ▼ (all point to OmniRoute)
+ http://YOUR_SERVER:20128/v1
+ │
+ ▼ (OmniRoute routes to the right provider)
+ Anthropic / OpenAI / Gemini / DeepSeek / Groq / Mistral / ...
+```
+
+**Benefits:**
+
+- One API key to manage all tools
+- Cost tracking across all CLIs in the dashboard
+- Model switching without reconfiguring every tool
+- Works locally and on remote servers (VPS)
+
+---
+
+## Supported Tools (Dashboard Source of Truth)
+
+The dashboard cards in `/dashboard/cli-tools` are generated from `src/shared/constants/cliTools.ts`.
+Current list (v3.0.0-rc.16):
+
+| Tool | ID | Command | Setup Mode | Install Method |
+| ------------------ | ------------- | ---------- | ---------- | -------------- |
+| **Claude Code** | `claude` | `claude` | env | npm |
+| **OpenAI Codex** | `codex` | `codex` | custom | npm |
+| **Factory Droid** | `droid` | `droid` | custom | bundled/CLI |
+| **OpenClaw** | `openclaw` | `openclaw` | custom | bundled/CLI |
+| **Cursor** | `cursor` | app | guide | desktop app |
+| **Cline** | `cline` | `cline` | custom | npm |
+| **Kilo Code** | `kilo` | `kilocode` | custom | npm |
+| **Continue** | `continue` | extension | guide | VS Code |
+| **Antigravity** | `antigravity` | internal | mitm | OmniRoute |
+| **GitHub Copilot** | `copilot` | extension | custom | VS Code |
+| **OpenCode** | `opencode` | `opencode` | guide | npm |
+| **Kiro AI** | `kiro` | app/cli | mitm | desktop/CLI |
+
+### CLI fingerprint sync (Agents + Settings)
+
+`/dashboard/agents` and `Settings > CLI Fingerprint` use `src/shared/constants/cliCompatProviders.ts`.
+This keeps provider IDs aligned with CLI cards and legacy IDs.
+
+| CLI ID | Fingerprint Provider ID |
+| ---------------------------------------------------------------------------------------------------- | ----------------------- |
+| `kilo` | `kilocode` |
+| `copilot` | `github` |
+| `claude` / `codex` / `antigravity` / `kiro` / `cursor` / `cline` / `opencode` / `droid` / `openclaw` | same ID |
+
+Legacy IDs still accepted for compatibility: `copilot`, `kimi-coding`, `qwen`.
+
+---
+
+## Step 1 — Get an OmniRoute API Key
+
+1. Open the OmniRoute dashboard → **API Manager** (`/dashboard/api-manager`)
+2. Click **Create API Key**
+3. Give it a name (e.g. `cli-tools`) and select all permissions
+4. Copy the key — you'll need it for every CLI below
+
+> Your key looks like: `sk-xxxxxxxxxxxxxxxx-xxxxxxxxx`
+
+---
+
+## Step 2 — Install CLI Tools
+
+All npm-based tools require Node.js 18+:
+
+```bash
+# Claude Code (Anthropic)
+npm install -g @anthropic-ai/claude-code
+
+# OpenAI Codex
+npm install -g @openai/codex
+
+# OpenCode
+npm install -g opencode-ai
+
+# Cline
+npm install -g cline
+
+# KiloCode
+npm install -g kilocode
+
+# Kiro CLI (Amazon — requires curl + unzip)
+apt-get install -y unzip # on Debian/Ubuntu
+curl -fsSL https://cli.kiro.dev/install | bash
+export PATH="$HOME/.local/bin:$PATH" # add to ~/.bashrc
+```
+
+**Verify:**
+
+```bash
+claude --version # 2.x.x
+codex --version # 0.x.x
+opencode --version # x.x.x
+cline --version # 2.x.x
+kilocode --version # x.x.x (or: kilo --version)
+kiro-cli --version # 1.x.x
+```
+
+---
+
+## Step 3 — Set Global Environment Variables
+
+Add to `~/.bashrc` (or `~/.zshrc`), then run `source ~/.bashrc`:
+
+```bash
+# OmniRoute Universal Endpoint
+export OPENAI_BASE_URL="http://localhost:20128/v1"
+export OPENAI_API_KEY="sk-your-omniroute-key"
+export ANTHROPIC_BASE_URL="http://localhost:20128/v1"
+export ANTHROPIC_API_KEY="sk-your-omniroute-key"
+export GEMINI_BASE_URL="http://localhost:20128/v1"
+export GEMINI_API_KEY="sk-your-omniroute-key"
+```
+
+> For a **remote server** replace `localhost:20128` with the server IP or domain,
+> e.g. `http://192.168.0.15:20128`.
+
+---
+
+## Step 4 — Configure Each Tool
+
+### Claude Code
+
+```bash
+# Via CLI:
+claude config set --global api-base-url http://localhost:20128/v1
+
+# Or create ~/.claude/settings.json:
+mkdir -p ~/.claude && cat > ~/.claude/settings.json << EOF
+{
+ "apiBaseUrl": "http://localhost:20128/v1",
+ "apiKey": "sk-your-omniroute-key"
+}
+EOF
+```
+
+**Test:** `claude "say hello"`
+
+---
+
+### OpenAI Codex
+
+```bash
+mkdir -p ~/.codex && cat > ~/.codex/config.yaml << EOF
+model: auto
+apiKey: sk-your-omniroute-key
+apiBaseUrl: http://localhost:20128/v1
+EOF
+```
+
+**Test:** `codex "what is 2+2?"`
+
+---
+
+### OpenCode
+
+```bash
+mkdir -p ~/.config/opencode && cat > ~/.config/opencode/config.toml << EOF
+[provider.openai]
+base_url = "http://localhost:20128/v1"
+api_key = "sk-your-omniroute-key"
+EOF
+```
+
+**Test:** `opencode`
+
+---
+
+### Cline (CLI or VS Code)
+
+**CLI mode:**
+
+```bash
+mkdir -p ~/.cline/data && cat > ~/.cline/data/globalState.json << EOF
+{
+ "apiProvider": "openai",
+ "openAiBaseUrl": "http://localhost:20128/v1",
+ "openAiApiKey": "sk-your-omniroute-key"
+}
+EOF
+```
+
+**VS Code mode:**
+Cline extension settings → API Provider: `OpenAI Compatible` → Base URL: `http://localhost:20128/v1`
+
+Or use the OmniRoute dashboard → **CLI Tools → Cline → Apply Config**.
+
+---
+
+### KiloCode (CLI or VS Code)
+
+**CLI mode:**
+
+```bash
+kilocode --api-base http://localhost:20128/v1 --api-key sk-your-omniroute-key
+```
+
+**VS Code settings:**
+
+```json
+{
+ "kilo-code.openAiBaseUrl": "http://localhost:20128/v1",
+ "kilo-code.apiKey": "sk-your-omniroute-key"
+}
+```
+
+Or use the OmniRoute dashboard → **CLI Tools → KiloCode → Apply Config**.
+
+---
+
+### Continue (VS Code Extension)
+
+Edit `~/.continue/config.yaml`:
+
+```yaml
+models:
+ - name: OmniRoute
+ provider: openai
+ model: auto
+ apiBase: http://localhost:20128/v1
+ apiKey: sk-your-omniroute-key
+ default: true
+```
+
+Restart VS Code after editing.
+
+---
+
+### Kiro CLI (Amazon)
+
+```bash
+# Login to your AWS/Kiro account:
+kiro-cli login
+
+# The CLI uses its own auth — OmniRoute is not needed as backend for Kiro CLI itself.
+# Use kiro-cli alongside OmniRoute for other tools.
+kiro-cli status
+```
+
+---
+
+### Cursor (Desktop App)
+
+> **Note:** Cursor routes requests through its cloud. For OmniRoute integration,
+> enable **Cloud Endpoint** in OmniRoute Settings and use your public domain URL.
+
+Via GUI: **Settings → Models → OpenAI API Key**
+
+- Base URL: `https://your-domain.com/v1`
+- API Key: your OmniRoute key
+
+---
+
+## Dashboard Auto-Configuration
+
+The OmniRoute dashboard automates configuration for most tools:
+
+1. Go to `http://localhost:20128/dashboard/cli-tools`
+2. Expand any tool card
+3. Select your API key from the dropdown
+4. Click **Apply Config** (if tool is detected as installed)
+5. Or copy the generated config snippet manually
+
+---
+
+## Built-in Agents: Droid & OpenClaw
+
+**Droid** and **OpenClaw** are AI agents built directly into OmniRoute — no installation needed.
+They run as internal routes and use OmniRoute's model routing automatically.
+
+- Access: `http://localhost:20128/dashboard/agents`
+- Configure: same combos and providers as all other tools
+- No API key or CLI install required
+
+---
+
+## Available API Endpoints
+
+| Endpoint | Description | Use For |
+| -------------------------- | ----------------------------- | --------------------------- |
+| `/v1/chat/completions` | Standard chat (all providers) | All modern tools |
+| `/v1/responses` | Responses API (OpenAI format) | Codex, agentic workflows |
+| `/v1/completions` | Legacy text completions | Older tools using `prompt:` |
+| `/v1/embeddings` | Text embeddings | RAG, search |
+| `/v1/images/generations` | Image generation | DALL-E, Flux, etc. |
+| `/v1/audio/speech` | Text-to-speech | ElevenLabs, OpenAI TTS |
+| `/v1/audio/transcriptions` | Speech-to-text | Deepgram, AssemblyAI |
+
+---
+
+## Fehlerbehebung
+
+| Error | Cause | Fix |
+| ------------------------- | ----------------------- | ------------------------------------------ |
+| `Connection refused` | OmniRoute not running | `pm2 start omniroute` |
+| `401 Unauthorized` | Wrong API key | Check in `/dashboard/api-manager` |
+| `No combo configured` | No active routing combo | Set up in `/dashboard/combos` |
+| `invalid model` | Model not in catalog | Use `auto` or check `/dashboard/providers` |
+| CLI shows "not installed" | Binary not in PATH | Check `which ` |
+| `kiro-cli: not found` | Not in PATH | `export PATH="$HOME/.local/bin:$PATH"` |
+
+---
+
+## Quick Setup Script (One Command)
+
+```bash
+# Install all CLIs and configure for OmniRoute (replace with your key and server URL)
+OMNIROUTE_URL="http://localhost:20128/v1"
+OMNIROUTE_KEY="sk-your-omniroute-key"
+
+npm install -g @anthropic-ai/claude-code @openai/codex opencode-ai cline kilocode
+
+# Kiro CLI
+apt-get install -y unzip 2>/dev/null; curl -fsSL https://cli.kiro.dev/install | bash
+
+# Write configs
+mkdir -p ~/.claude ~/.codex ~/.config/opencode ~/.continue
+
+cat > ~/.claude/settings.json <<< "{\"apiBaseUrl\":\"$OMNIROUTE_URL\",\"apiKey\":\"$OMNIROUTE_KEY\"}"
+cat > ~/.codex/config.yaml <<< "model: auto\napiKey: $OMNIROUTE_KEY\napiBaseUrl: $OMNIROUTE_URL"
+cat >> ~/.bashrc << EOF
+export OPENAI_BASE_URL="$OMNIROUTE_URL"
+export OPENAI_API_KEY="$OMNIROUTE_KEY"
+export ANTHROPIC_BASE_URL="$OMNIROUTE_URL"
+export ANTHROPIC_API_KEY="$OMNIROUTE_KEY"
+EOF
+
+source ~/.bashrc
+echo "✅ All CLIs installed and configured for OmniRoute"
+```
diff --git a/docs/i18n/de/docs/CODEBASE_DOCUMENTATION.md b/docs/i18n/de/docs/CODEBASE_DOCUMENTATION.md
new file mode 100644
index 0000000000..3f0c42f791
--- /dev/null
+++ b/docs/i18n/de/docs/CODEBASE_DOCUMENTATION.md
@@ -0,0 +1,591 @@
+# omniroute — Codebase Documentation (Deutsch)
+
+🌐 **Languages:** 🇺🇸 [English](../../../../docs/CODEBASE_DOCUMENTATION.md) · 🇪🇸 [es](../../es/docs/CODEBASE_DOCUMENTATION.md) · 🇫🇷 [fr](../../fr/docs/CODEBASE_DOCUMENTATION.md) · 🇩🇪 [de](../../de/docs/CODEBASE_DOCUMENTATION.md) · 🇮🇹 [it](../../it/docs/CODEBASE_DOCUMENTATION.md) · 🇷🇺 [ru](../../ru/docs/CODEBASE_DOCUMENTATION.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/CODEBASE_DOCUMENTATION.md) · 🇯🇵 [ja](../../ja/docs/CODEBASE_DOCUMENTATION.md) · 🇰🇷 [ko](../../ko/docs/CODEBASE_DOCUMENTATION.md) · 🇸🇦 [ar](../../ar/docs/CODEBASE_DOCUMENTATION.md) · 🇮🇳 [in](../../in/docs/CODEBASE_DOCUMENTATION.md) · 🇹🇭 [th](../../th/docs/CODEBASE_DOCUMENTATION.md) · 🇻🇳 [vi](../../vi/docs/CODEBASE_DOCUMENTATION.md) · 🇮🇩 [id](../../id/docs/CODEBASE_DOCUMENTATION.md) · 🇲🇾 [ms](../../ms/docs/CODEBASE_DOCUMENTATION.md) · 🇳🇱 [nl](../../nl/docs/CODEBASE_DOCUMENTATION.md) · 🇵🇱 [pl](../../pl/docs/CODEBASE_DOCUMENTATION.md) · 🇸🇪 [sv](../../sv/docs/CODEBASE_DOCUMENTATION.md) · 🇳🇴 [no](../../no/docs/CODEBASE_DOCUMENTATION.md) · 🇩🇰 [da](../../da/docs/CODEBASE_DOCUMENTATION.md) · 🇫🇮 [fi](../../fi/docs/CODEBASE_DOCUMENTATION.md) · 🇵🇹 [pt](../../pt/docs/CODEBASE_DOCUMENTATION.md) · 🇷🇴 [ro](../../ro/docs/CODEBASE_DOCUMENTATION.md) · 🇭🇺 [hu](../../hu/docs/CODEBASE_DOCUMENTATION.md) · 🇧🇬 [bg](../../bg/docs/CODEBASE_DOCUMENTATION.md) · 🇸🇰 [sk](../../sk/docs/CODEBASE_DOCUMENTATION.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/CODEBASE_DOCUMENTATION.md) · 🇮🇱 [he](../../he/docs/CODEBASE_DOCUMENTATION.md) · 🇵🇭 [phi](../../phi/docs/CODEBASE_DOCUMENTATION.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/CODEBASE_DOCUMENTATION.md) · 🇨🇿 [cs](../../cs/docs/CODEBASE_DOCUMENTATION.md)
+
+---
+
+> A comprehensive, beginner-friendly guide to the **omniroute** multi-provider AI proxy router.
+
+---
+
+## 1. What Is omniroute?
+
+omniroute is a **proxy router** that sits between AI clients (Claude CLI, Codex, Cursor IDE, etc.) and AI providers (Anthropic, Google, OpenAI, AWS, GitHub, etc.). It solves one big problem:
+
+> **Different AI clients speak different "languages" (API formats), and different AI providers expect different "languages" too.** omniroute translates between them automatically.
+
+Think of it like a universal translator at the United Nations — any delegate can speak any language, and the translator converts it for any other delegate.
+
+---
+
+## 2. Architecture Overview
+
+```mermaid
+graph LR
+ subgraph Clients
+ A[Claude CLI]
+ B[Codex]
+ C[Cursor IDE]
+ D[OpenAI-compatible]
+ end
+
+ subgraph omniroute
+ E[Handler Layer]
+ F[Translator Layer]
+ G[Executor Layer]
+ H[Services Layer]
+ end
+
+ subgraph Providers
+ I[Anthropic Claude]
+ J[Google Gemini]
+ K[OpenAI / Codex]
+ L[GitHub Copilot]
+ M[AWS Kiro]
+ N[Antigravity]
+ O[Cursor API]
+ end
+
+ A --> E
+ B --> E
+ C --> E
+ D --> E
+ E --> F
+ F --> G
+ G --> I
+ G --> J
+ G --> K
+ G --> L
+ G --> M
+ G --> N
+ G --> O
+ H -.-> E
+ H -.-> G
+```
+
+### Core Principle: Hub-and-Spoke Translation
+
+All format translation passes through **OpenAI format as the hub**:
+
+```
+Client Format → [OpenAI Hub] → Provider Format (request)
+Provider Format → [OpenAI Hub] → Client Format (response)
+```
+
+This means you only need **N translators** (one per format) instead of **N²** (every pair).
+
+---
+
+## 3. Project Structure
+
+```
+omniroute/
+├── open-sse/ ← Core proxy library (portable, framework-agnostic)
+│ ├── index.js ← Main entry point, exports everything
+│ ├── config/ ← Configuration & constants
+│ ├── executors/ ← Provider-specific request execution
+│ ├── handlers/ ← Request handling orchestration
+│ ├── services/ ← Business logic (auth, models, fallback, usage)
+│ ├── translator/ ← Format translation engine
+│ │ ├── request/ ← Request translators (8 files)
+│ │ ├── response/ ← Response translators (7 files)
+│ │ └── helpers/ ← Shared translation utilities (6 files)
+│ └── utils/ ← Utility functions
+├── src/ ← Application layer (Express/Worker runtime)
+│ ├── app/ ← Web UI, API routes, middleware
+│ ├── lib/ ← Database, auth, and shared library code
+│ ├── mitm/ ← Man-in-the-middle proxy utilities
+│ ├── models/ ← Database models
+│ ├── shared/ ← Shared utilities (wrappers around open-sse)
+│ ├── sse/ ← SSE endpoint handlers
+│ └── store/ ← State management
+├── data/ ← Runtime data (credentials, logs)
+│ └── provider-credentials.json (external credentials override, gitignored)
+└── tester/ ← Test utilities
+```
+
+---
+
+## 4. Module-by-Module Breakdown
+
+### 4.1 Config (`open-sse/config/`)
+
+The **single source of truth** for all provider configuration.
+
+| File | Purpose |
+| ----------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| `constants.ts` | `PROVIDERS` object with base URLs, OAuth credentials (defaults), headers, and default system prompts for every provider. Also defines `HTTP_STATUS`, `ERROR_TYPES`, `COOLDOWN_MS`, `BACKOFF_CONFIG`, and `SKIP_PATTERNS`. |
+| `credentialLoader.ts` | Loads external credentials from `data/provider-credentials.json` and merges them over the hardcoded defaults in `PROVIDERS`. Keeps secrets out of source control while maintaining backwards compatibility. |
+| `providerModels.ts` | Central model registry: maps provider aliases → model IDs. Functions like `getModels()`, `getProviderByAlias()`. |
+| `codexInstructions.ts` | System instructions injected into Codex requests (editing constraints, sandbox rules, approval policies). |
+| `defaultThinkingSignature.ts` | Default "thinking" signatures for Claude and Gemini models. |
+| `ollamaModels.ts` | Schema definition for local Ollama models (name, size, family, quantization). |
+
+#### Credential Loading Flow
+
+```mermaid
+flowchart TD
+ A["App starts"] --> B["constants.ts defines PROVIDERS\nwith hardcoded defaults"]
+ B --> C{"data/provider-credentials.json\nexists?"}
+ C -->|Yes| D["credentialLoader reads JSON"]
+ C -->|No| E["Use hardcoded defaults"]
+ D --> F{"For each provider in JSON"}
+ F --> G{"Provider exists\nin PROVIDERS?"}
+ G -->|No| H["Log warning, skip"]
+ G -->|Yes| I{"Value is object?"}
+ I -->|No| J["Log warning, skip"]
+ I -->|Yes| K["Merge clientId, clientSecret,\ntokenUrl, authUrl, refreshUrl"]
+ K --> F
+ H --> F
+ J --> F
+ F -->|Done| L["PROVIDERS ready with\nmerged credentials"]
+ E --> L
+```
+
+---
+
+### 4.2 Executors (`open-sse/executors/`)
+
+Executors encapsulate **provider-specific logic** using the **Strategy Pattern**. Each executor overrides base methods as needed.
+
+```mermaid
+classDiagram
+ class BaseExecutor {
+ +buildUrl(model, stream, options)
+ +buildHeaders(credentials, stream, body)
+ +transformRequest(body, model, stream, credentials)
+ +execute(url, options)
+ +shouldRetry(status, error)
+ +refreshCredentials(credentials, log)
+ }
+
+ class DefaultExecutor {
+ +refreshCredentials()
+ }
+
+ class AntigravityExecutor {
+ +buildUrl()
+ +buildHeaders()
+ +transformRequest()
+ +shouldRetry()
+ +refreshCredentials()
+ }
+
+ class CursorExecutor {
+ +buildUrl()
+ +buildHeaders()
+ +transformRequest()
+ +parseResponse()
+ +generateChecksum()
+ }
+
+ class KiroExecutor {
+ +buildUrl()
+ +buildHeaders()
+ +transformRequest()
+ +parseEventStream()
+ +refreshCredentials()
+ }
+
+ BaseExecutor <|-- DefaultExecutor
+ BaseExecutor <|-- AntigravityExecutor
+ BaseExecutor <|-- CursorExecutor
+ BaseExecutor <|-- KiroExecutor
+ BaseExecutor <|-- CodexExecutor
+ BaseExecutor <|-- GeminiCLIExecutor
+ BaseExecutor <|-- GithubExecutor
+```
+
+| Executor | Provider | Key Specializations |
+| ---------------- | ------------------------------------------ | ------------------------------------------------------------------------------------------------------------------- |
+| `base.ts` | — | Abstract base: URL building, headers, retry logic, credential refresh |
+| `default.ts` | Claude, Gemini, OpenAI, GLM, Kimi, MiniMax | Generic OAuth token refresh for standard providers |
+| `antigravity.ts` | Google Cloud Code | Project/session ID generation, multi-URL fallback, custom retry parsing from error messages ("reset after 2h7m23s") |
+| `cursor.ts` | Cursor IDE | **Most complex**: SHA-256 checksum auth, Protobuf request encoding, binary EventStream → SSE response parsing |
+| `codex.ts` | OpenAI Codex | Injects system instructions, manages thinking levels, removes unsupported parameters |
+| `gemini-cli.ts` | Google Gemini CLI | Custom URL building (`streamGenerateContent`), Google OAuth token refresh |
+| `github.ts` | GitHub Copilot | Dual token system (GitHub OAuth + Copilot token), VSCode header mimicking |
+| `kiro.ts` | AWS CodeWhisperer | AWS EventStream binary parsing, AMZN event frames, token estimation |
+| `index.ts` | — | Factory: maps provider name → executor class, with default fallback |
+
+---
+
+### 4.3 Handlers (`open-sse/handlers/`)
+
+The **orchestration layer** — coordinates translation, execution, streaming, and error handling.
+
+| File | Purpose |
+| --------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| `chatCore.ts` | **Central orchestrator** (~600 lines). Handles the complete request lifecycle: format detection → translation → executor dispatch → streaming/non-streaming response → token refresh → error handling → usage logging. |
+| `responsesHandler.ts` | Adapter for OpenAI's Responses API: converts Responses format → Chat Completions → sends to `chatCore` → converts SSE back to Responses format. |
+| `embeddings.ts` | Embedding generation handler: resolves embedding model → provider, dispatches to provider API, returns OpenAI-compatible embedding response. Supports 6+ providers. |
+| `imageGeneration.ts` | Image generation handler: resolves image model → provider, supports OpenAI-compatible, Gemini-image (Antigravity), and fallback (Nebius) modes. Returns base64 or URL images. |
+
+#### Request Lifecycle (chatCore.ts)
+
+```mermaid
+sequenceDiagram
+ participant Client
+ participant chatCore
+ participant Translator
+ participant Executor
+ participant Provider
+
+ Client->>chatCore: Request (any format)
+ chatCore->>chatCore: Detect source format
+ chatCore->>chatCore: Check bypass patterns
+ chatCore->>chatCore: Resolve model & provider
+ chatCore->>Translator: Translate request (source → OpenAI → target)
+ chatCore->>Executor: Get executor for provider
+ Executor->>Executor: Build URL, headers, transform request
+ Executor->>Executor: Refresh credentials if needed
+ Executor->>Provider: HTTP fetch (streaming or non-streaming)
+
+ alt Streaming
+ Provider-->>chatCore: SSE stream
+ chatCore->>chatCore: Pipe through SSE transform stream
+ Note over chatCore: Transform stream translates
each chunk: target → OpenAI → source
+ chatCore-->>Client: Translated SSE stream
+ else Non-streaming
+ Provider-->>chatCore: JSON response
+ chatCore->>Translator: Translate response
+ chatCore-->>Client: Translated JSON
+ end
+
+ alt Error (401, 429, 500...)
+ chatCore->>Executor: Retry with credential refresh
+ chatCore->>chatCore: Account fallback logic
+ end
+```
+
+---
+
+### 4.4 Services (`open-sse/services/`)
+
+Business logic that supports the handlers and executors.
+
+| File | Purpose |
+| -------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| `provider.ts` | **Format detection** (`detectFormat`): analyzes request body structure to identify Claude/OpenAI/Gemini/Antigravity/Responses formats (includes `max_tokens` heuristic for Claude). Also: URL building, header building, thinking config normalization. Supports `openai-compatible-*` and `anthropic-compatible-*` dynamic providers. |
+| `model.ts` | Model string parsing (`claude/model-name` → `{provider: "claude", model: "model-name"}`), alias resolution with collision detection, input sanitization (rejects path traversal/control chars), and model info resolution with async alias getter support. |
+| `accountFallback.ts` | Rate-limit handling: exponential backoff (1s → 2s → 4s → max 2min), account cooldown management, error classification (which errors trigger fallback vs. not). |
+| `tokenRefresh.ts` | OAuth token refresh for **every provider**: Google (Gemini, Antigravity), Claude, Codex, Qwen, Qoder, GitHub (OAuth + Copilot dual-token), Kiro (AWS SSO OIDC + Social Auth). Includes in-flight promise deduplication cache and retry with exponential backoff. |
+| `combo.ts` | **Combo models**: chains of fallback models. If model A fails with a fallback-eligible error, try model B, then C, etc. Returns actual upstream status codes. |
+| `usage.ts` | Fetches quota/usage data from provider APIs (GitHub Copilot quotas, Antigravity model quotas, Codex rate limits, Kiro usage breakdowns, Claude settings). |
+| `accountSelector.ts` | Smart account selection with scoring algorithm: considers priority, health status, round-robin position, and cooldown state to pick the optimal account for each request. |
+| `contextManager.ts` | Request context lifecycle management: creates and tracks per-request context objects with metadata (request ID, timestamps, provider info) for debugging and logging. |
+| `ipFilter.ts` | IP-based access control: supports allowlist and blocklist modes. Validates client IP against configured rules before processing API requests. |
+| `sessionManager.ts` | Session tracking with client fingerprinting: tracks active sessions using hashed client identifiers, monitors request counts, and provides session metrics. |
+| `signatureCache.ts` | Request signature-based deduplication cache: prevents duplicate requests by caching recent request signatures and returning cached responses for identical requests within a time window. |
+| `systemPrompt.ts` | Global system prompt injection: prepends or appends a configurable system prompt to all requests, with per-provider compatibility handling. |
+| `thinkingBudget.ts` | Reasoning token budget management: supports passthrough, auto (strip thinking config), custom (fixed budget), and adaptive (complexity-scaled) modes for controlling thinking/reasoning tokens. |
+| `wildcardRouter.ts` | Wildcard model pattern routing: resolves wildcard patterns (e.g., `*/claude-*`) to concrete provider/model pairs based on availability and priority. |
+
+#### Token Refresh Deduplication
+
+```mermaid
+sequenceDiagram
+ participant R1 as Request 1
+ participant R2 as Request 2
+ participant Cache as refreshPromiseCache
+ participant OAuth as OAuth Provider
+
+ R1->>Cache: getAccessToken("gemini", token)
+ Cache->>Cache: No in-flight promise
+ Cache->>OAuth: Start refresh
+ R2->>Cache: getAccessToken("gemini", token)
+ Cache->>Cache: Found in-flight promise
+ Cache-->>R2: Return existing promise
+ OAuth-->>Cache: New access token
+ Cache-->>R1: New access token
+ Cache-->>R2: Same access token (shared)
+ Cache->>Cache: Delete cache entry
+```
+
+#### Account Fallback State Machine
+
+```mermaid
+stateDiagram-v2
+ [*] --> Active
+ Active --> Error: Request fails (401/429/500)
+ Error --> Cooldown: Apply backoff
+ Cooldown --> Active: Cooldown expires
+ Active --> Active: Request succeeds (reset backoff)
+
+ state Error {
+ [*] --> ClassifyError
+ ClassifyError --> ShouldFallback: Rate limit / Auth / Transient
+ ClassifyError --> NoFallback: 400 Bad Request
+ }
+
+ state Cooldown {
+ [*] --> ExponentialBackoff
+ ExponentialBackoff: Level 0 = 1s
+ ExponentialBackoff: Level 1 = 2s
+ ExponentialBackoff: Level 2 = 4s
+ ExponentialBackoff: Max = 2min
+ }
+```
+
+#### Combo Model Chain
+
+```mermaid
+flowchart LR
+ A["Request with\ncombo model"] --> B["Model A"]
+ B -->|"2xx Success"| C["Return response"]
+ B -->|"429/401/500"| D{"Fallback\neligible?"}
+ D -->|Yes| E["Model B"]
+ D -->|No| F["Return error"]
+ E -->|"2xx Success"| C
+ E -->|"429/401/500"| G{"Fallback\neligible?"}
+ G -->|Yes| H["Model C"]
+ G -->|No| F
+ H -->|"2xx Success"| C
+ H -->|"Fail"| I["All failed →\nReturn last status"]
+```
+
+---
+
+### 4.5 Translator (`open-sse/translator/`)
+
+The **format translation engine** using a self-registering plugin system.
+
+#### Architektur
+
+```mermaid
+graph TD
+ subgraph "Request Translation"
+ A["Claude → OpenAI"]
+ B["Gemini → OpenAI"]
+ C["Antigravity → OpenAI"]
+ D["OpenAI Responses → OpenAI"]
+ E["OpenAI → Claude"]
+ F["OpenAI → Gemini"]
+ G["OpenAI → Kiro"]
+ H["OpenAI → Cursor"]
+ end
+
+ subgraph "Response Translation"
+ I["Claude → OpenAI"]
+ J["Gemini → OpenAI"]
+ K["Kiro → OpenAI"]
+ L["Cursor → OpenAI"]
+ M["OpenAI → Claude"]
+ N["OpenAI → Antigravity"]
+ O["OpenAI → Responses"]
+ end
+```
+
+| Directory | Files | Description |
+| ------------ | ------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| `request/` | 8 translators | Convert request bodies between formats. Each file self-registers via `register(from, to, fn)` on import. |
+| `response/` | 7 translators | Convert streaming response chunks between formats. Handles SSE event types, thinking blocks, tool calls. |
+| `helpers/` | 6 helpers | Shared utilities: `claudeHelper` (system prompt extraction, thinking config), `geminiHelper` (parts/contents mapping), `openaiHelper` (format filtering), `toolCallHelper` (ID generation, missing response injection), `maxTokensHelper`, `responsesApiHelper`. |
+| `index.ts` | — | Translation engine: `translateRequest()`, `translateResponse()`, state management, registry. |
+| `formats.ts` | — | Format constants: `OPENAI`, `CLAUDE`, `GEMINI`, `ANTIGRAVITY`, `KIRO`, `CURSOR`, `OPENAI_RESPONSES`. |
+
+#### Key Design: Self-Registering Plugins
+
+```javascript
+// Each translator file calls register() on import:
+import { register } from "../index.js";
+register("claude", "openai", translateClaudeToOpenAI);
+
+// The index.js imports all translator files, triggering registration:
+import "./request/claude-to-openai.js"; // ← self-registers
+```
+
+---
+
+### 4.6 Utils (`open-sse/utils/`)
+
+| File | Purpose |
+| ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
+| `error.ts` | Error response building (OpenAI-compatible format), upstream error parsing, Antigravity retry-time extraction from error messages, SSE error streaming. |
+| `stream.ts` | **SSE Transform Stream** — the core streaming pipeline. Two modes: `TRANSLATE` (full format translation) and `PASSTHROUGH` (normalize + extract usage). Handles chunk buffering, usage estimation, content length tracking. Per-stream encoder/decoder instances avoid shared state. |
+| `streamHelpers.ts` | Low-level SSE utilities: `parseSSELine` (whitespace-tolerant), `hasValuableContent` (filters empty chunks for OpenAI/Claude/Gemini), `fixInvalidId`, `formatSSE` (format-aware SSE serialization with `perf_metrics` cleanup). |
+| `usageTracking.ts` | Token usage extraction from any format (Claude/OpenAI/Gemini/Responses), estimation with separate tool/message char-per-token ratios, buffer addition (2000 tokens safety margin), format-specific field filtering, console logging with ANSI colors. |
+| `requestLogger.ts` | File-based request logging (opt-in via `ENABLE_REQUEST_LOGS=true`). Creates session folders with numbered files: `1_req_client.json` → `7_res_client.txt`. All I/O is async (fire-and-forget). Masks sensitive headers. |
+| `bypassHandler.ts` | Intercepts specific patterns from Claude CLI (title extraction, warmup, count) and returns fake responses without calling any provider. Supports both streaming and non-streaming. Intentionally limited to Claude CLI scope. |
+| `networkProxy.ts` | Resolves outbound proxy URL for a given provider with precedence: provider-specific config → global config → environment variables (`HTTPS_PROXY`/`HTTP_PROXY`/`ALL_PROXY`). Supports `NO_PROXY` exclusions. Caches config for 30s. |
+
+#### SSE Streaming Pipeline
+
+```mermaid
+flowchart TD
+ A["Provider SSE stream"] --> B["TextDecoder\n(per-stream instance)"]
+ B --> C["Buffer lines\n(split on newline)"]
+ C --> D["parseSSELine()\n(trim whitespace, parse JSON)"]
+ D --> E{"Mode?"}
+ E -->|TRANSLATE| F["translateResponse()\ntarget → OpenAI → source"]
+ E -->|PASSTHROUGH| G["fixInvalidId()\nnormalize chunk"]
+ F --> H["hasValuableContent()\nfilter empty chunks"]
+ G --> H
+ H -->|"Has content"| I["extractUsage()\ntrack token counts"]
+ H -->|"Empty"| J["Skip chunk"]
+ I --> K["formatSSE()\nserialize + clean perf_metrics"]
+ K --> L["TextEncoder\n(per-stream instance)"]
+ L --> M["Enqueue to\nclient stream"]
+
+ style A fill:#f9f,stroke:#333
+ style M fill:#9f9,stroke:#333
+```
+
+#### Request Logger Session Structure
+
+```
+logs/
+└── claude_gemini_claude-sonnet_20260208_143045/
+ ├── 1_req_client.json ← Raw client request
+ ├── 2_req_source.json ← After initial conversion
+ ├── 3_req_openai.json ← OpenAI intermediate format
+ ├── 4_req_target.json ← Final target format
+ ├── 5_res_provider.txt ← Provider SSE chunks (streaming)
+ ├── 5_res_provider.json ← Provider response (non-streaming)
+ ├── 6_res_openai.txt ← OpenAI intermediate chunks
+ ├── 7_res_client.txt ← Client-facing SSE chunks
+ └── 6_error.json ← Error details (if any)
+```
+
+---
+
+### 4.7 Application Layer (`src/`)
+
+| Directory | Purpose |
+| ------------- | ---------------------------------------------------------------------- |
+| `src/app/` | Web UI, API routes, Express middleware, OAuth callback handlers |
+| `src/lib/` | Database access (`localDb.ts`, `usageDb.ts`), authentication, shared |
+| `src/mitm/` | Man-in-the-middle proxy utilities for intercepting provider traffic |
+| `src/models/` | Database model definitions |
+| `src/shared/` | Wrappers around open-sse functions (provider, stream, error, etc.) |
+| `src/sse/` | SSE endpoint handlers that wire the open-sse library to Express routes |
+| `src/store/` | Application state management |
+
+#### Notable API Routes
+
+| Route | Methods | Purpose |
+| --------------------------------------------- | --------------- | ------------------------------------------------------------------------------------- |
+| `/api/provider-models` | GET/POST/DELETE | CRUD for custom models per provider |
+| `/api/models/catalog` | GET | Aggregated catalog of all models (chat, embedding, image, custom) grouped by provider |
+| `/api/settings/proxy` | GET/PUT/DELETE | Hierarchical outbound proxy configuration (`global/providers/combos/keys`) |
+| `/api/settings/proxy/test` | POST | Validates proxy connectivity and returns public IP/latency |
+| `/v1/providers/[provider]/chat/completions` | POST | Dedicated per-provider chat completions with model validation |
+| `/v1/providers/[provider]/embeddings` | POST | Dedicated per-provider embeddings with model validation |
+| `/v1/providers/[provider]/images/generations` | POST | Dedicated per-provider image generation with model validation |
+| `/api/settings/ip-filter` | GET/PUT | IP allowlist/blocklist management |
+| `/api/settings/thinking-budget` | GET/PUT | Reasoning token budget configuration (passthrough/auto/custom/adaptive) |
+| `/api/settings/system-prompt` | GET/PUT | Global system prompt injection for all requests |
+| `/api/sessions` | GET | Active session tracking and metrics |
+| `/api/rate-limits` | GET | Per-account rate limit status |
+
+---
+
+## 5. Key Design Patterns
+
+### 5.1 Hub-and-Spoke Translation
+
+All formats translate through **OpenAI format as the hub**. Adding a new provider only requires writing **one pair** of translators (to/from OpenAI), not N pairs.
+
+### 5.2 Executor Strategy Pattern
+
+Each provider has a dedicated executor class inheriting from `BaseExecutor`. The factory in `executors/index.ts` selects the right one at runtime.
+
+### 5.3 Self-Registering Plugin System
+
+Translator modules register themselves on import via `register()`. Adding a new translator is just creating a file and importing it.
+
+### 5.4 Account Fallback with Exponential Backoff
+
+When a provider returns 429/401/500, the system can switch to the next account, applying exponential cooldowns (1s → 2s → 4s → max 2min).
+
+### 5.5 Combo Model Chains
+
+A "combo" groups multiple `provider/model` strings. If the first fails, fallback to the next automatically.
+
+### 5.6 Stateful Streaming Translation
+
+Response translation maintains state across SSE chunks (thinking block tracking, tool call accumulation, content block indexing) via the `initState()` mechanism.
+
+### 5.7 Usage Safety Buffer
+
+A 2000-token buffer is added to reported usage to prevent clients from hitting context window limits due to overhead from system prompts and format translation.
+
+---
+
+## 6. Supported Formats
+
+| Format | Direction | Identifier |
+| ----------------------- | --------------- | ------------------ |
+| OpenAI Chat Completions | source + target | `openai` |
+| OpenAI Responses API | source + target | `openai-responses` |
+| Anthropic Claude | source + target | `claude` |
+| Google Gemini | source + target | `gemini` |
+| Google Gemini CLI | target only | `gemini-cli` |
+| Antigravity | source + target | `antigravity` |
+| AWS Kiro | target only | `kiro` |
+| Cursor | target only | `cursor` |
+
+---
+
+## 7. Supported Providers
+
+| Provider | Auth Method | Executor | Key Notes |
+| ------------------------ | ---------------------- | ----------- | --------------------------------------------- |
+| Anthropic Claude | API key or OAuth | Default | Uses `x-api-key` header |
+| Google Gemini | API key or OAuth | Default | Uses `x-goog-api-key` header |
+| Google Gemini CLI | OAuth | GeminiCLI | Uses `streamGenerateContent` endpoint |
+| Antigravity | OAuth | Antigravity | Multi-URL fallback, custom retry parsing |
+| OpenAI | API key | Default | Standard Bearer auth |
+| Codex | OAuth | Codex | Injects system instructions, manages thinking |
+| GitHub Copilot | OAuth + Copilot token | Github | Dual token, VSCode header mimicking |
+| Kiro (AWS) | AWS SSO OIDC or Social | Kiro | Binary EventStream parsing |
+| Cursor IDE | Checksum auth | Cursor | Protobuf encoding, SHA-256 checksums |
+| Qwen | OAuth | Default | Standard auth |
+| Qoder | OAuth (Basic + Bearer) | Default | Dual auth header |
+| OpenRouter | API key | Default | Standard Bearer auth |
+| GLM, Kimi, MiniMax | API key | Default | Claude-compatible, use `x-api-key` |
+| `openai-compatible-*` | API key | Default | Dynamic: any OpenAI-compatible endpoint |
+| `anthropic-compatible-*` | API key | Default | Dynamic: any Claude-compatible endpoint |
+
+---
+
+## 8. Data Flow Summary
+
+### Streaming Request
+
+```mermaid
+flowchart LR
+ A["Client"] --> B["detectFormat()"]
+ B --> C["translateRequest()\nsource → OpenAI → target"]
+ C --> D["Executor\nbuildUrl + buildHeaders"]
+ D --> E["fetch(providerURL)"]
+ E --> F["createSSEStream()\nTRANSLATE mode"]
+ F --> G["parseSSELine()"]
+ G --> H["translateResponse()\ntarget → OpenAI → source"]
+ H --> I["extractUsage()\n+ addBuffer"]
+ I --> J["formatSSE()"]
+ J --> K["Client receives\ntranslated SSE"]
+ K --> L["logUsage()\nsaveRequestUsage()"]
+```
+
+### Non-Streaming Request
+
+```mermaid
+flowchart LR
+ A["Client"] --> B["detectFormat()"]
+ B --> C["translateRequest()\nsource → OpenAI → target"]
+ C --> D["Executor.execute()"]
+ D --> E["translateResponse()\ntarget → OpenAI → source"]
+ E --> F["Return JSON\nresponse"]
+```
+
+### Bypass Flow (Claude CLI)
+
+```mermaid
+flowchart LR
+ A["Claude CLI request"] --> B{"Match bypass\npattern?"}
+ B -->|"Title/Warmup/Count"| C["Generate fake\nOpenAI response"]
+ B -->|"No match"| D["Normal flow"]
+ C --> E["Translate to\nsource format"]
+ E --> F["Return without\ncalling provider"]
+```
diff --git a/docs/i18n/de/docs/COVERAGE_PLAN.md b/docs/i18n/de/docs/COVERAGE_PLAN.md
new file mode 100644
index 0000000000..5c994afb44
--- /dev/null
+++ b/docs/i18n/de/docs/COVERAGE_PLAN.md
@@ -0,0 +1,170 @@
+# Test Coverage Plan (Deutsch)
+
+🌐 **Languages:** 🇺🇸 [English](../../../../docs/COVERAGE_PLAN.md) · 🇪🇸 [es](../../es/docs/COVERAGE_PLAN.md) · 🇫🇷 [fr](../../fr/docs/COVERAGE_PLAN.md) · 🇩🇪 [de](../../de/docs/COVERAGE_PLAN.md) · 🇮🇹 [it](../../it/docs/COVERAGE_PLAN.md) · 🇷🇺 [ru](../../ru/docs/COVERAGE_PLAN.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/COVERAGE_PLAN.md) · 🇯🇵 [ja](../../ja/docs/COVERAGE_PLAN.md) · 🇰🇷 [ko](../../ko/docs/COVERAGE_PLAN.md) · 🇸🇦 [ar](../../ar/docs/COVERAGE_PLAN.md) · 🇮🇳 [in](../../in/docs/COVERAGE_PLAN.md) · 🇹🇭 [th](../../th/docs/COVERAGE_PLAN.md) · 🇻🇳 [vi](../../vi/docs/COVERAGE_PLAN.md) · 🇮🇩 [id](../../id/docs/COVERAGE_PLAN.md) · 🇲🇾 [ms](../../ms/docs/COVERAGE_PLAN.md) · 🇳🇱 [nl](../../nl/docs/COVERAGE_PLAN.md) · 🇵🇱 [pl](../../pl/docs/COVERAGE_PLAN.md) · 🇸🇪 [sv](../../sv/docs/COVERAGE_PLAN.md) · 🇳🇴 [no](../../no/docs/COVERAGE_PLAN.md) · 🇩🇰 [da](../../da/docs/COVERAGE_PLAN.md) · 🇫🇮 [fi](../../fi/docs/COVERAGE_PLAN.md) · 🇵🇹 [pt](../../pt/docs/COVERAGE_PLAN.md) · 🇷🇴 [ro](../../ro/docs/COVERAGE_PLAN.md) · 🇭🇺 [hu](../../hu/docs/COVERAGE_PLAN.md) · 🇧🇬 [bg](../../bg/docs/COVERAGE_PLAN.md) · 🇸🇰 [sk](../../sk/docs/COVERAGE_PLAN.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/COVERAGE_PLAN.md) · 🇮🇱 [he](../../he/docs/COVERAGE_PLAN.md) · 🇵🇭 [phi](../../phi/docs/COVERAGE_PLAN.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/COVERAGE_PLAN.md) · 🇨🇿 [cs](../../cs/docs/COVERAGE_PLAN.md)
+
+---
+
+Last updated: 2026-03-28
+
+## Baseline
+
+There are multiple coverage numbers depending on how the report is computed. For planning, only one of them is useful.
+
+| Metric | Scope | Statements / Lines | Branches | Functions | Notes |
+| -------------------- | ----------------------------------------------------- | -----------------: | -------: | --------: | --------------------------------------------------- |
+| Legacy | Old `npm run test:coverage` | 79.42% | 75.15% | 67.94% | Inflated: counts test files and excludes `open-sse` |
+| Diagnostic | Source-only, excluding tests and excluding `open-sse` | 68.16% | 63.55% | 64.06% | Useful only to isolate `src/**` |
+| Recommended baseline | Source-only, excluding tests and including `open-sse` | 56.95% | 66.05% | 57.80% | This is the project-wide baseline to improve |
+
+The recommended baseline is the number to optimize against.
+
+## Rules
+
+- Coverage targets apply to source files, not to `tests/**`.
+- `open-sse/**` is part of the product and must remain in scope.
+- New code should not reduce coverage in touched areas.
+- Prefer testing behavior and branch outcomes over implementation details.
+- Prefer temp SQLite databases and small fixtures over broad mocks for `src/lib/db/**`.
+
+## Current command set
+
+- `npm run test:coverage`
+ - Main source coverage gate for the unit test suite
+ - Generates `text-summary`, `html`, `json-summary`, and `lcov`
+- `npm run coverage:report`
+ - Detailed file-by-file report from the latest run
+- `npm run test:coverage:legacy`
+ - Historical comparison only
+
+## Milestones
+
+| Phase | Target | Focus |
+| ------- | ---------------------: | ------------------------------------------------- |
+| Phase 1 | 60% statements / lines | Quick wins and low-risk utility coverage |
+| Phase 2 | 65% statements / lines | DB and route foundations |
+| Phase 3 | 70% statements / lines | Provider validation and usage analytics |
+| Phase 4 | 75% statements / lines | `open-sse` translators and helpers |
+| Phase 5 | 80% statements / lines | `open-sse` handlers and executor branches |
+| Phase 6 | 85% statements / lines | Harder edge cases, branch debt, regression suites |
+| Phase 7 | 90% statements / lines | Final sweep, gap closure, strict ratchet |
+
+Branches and functions should ratchet upward with each phase, but the primary hard target is statements / lines.
+
+## Priority hotspots
+
+These files or areas offer the best return for the next phases:
+
+1. `open-sse/handlers`
+ - `chatCore.ts` at 7.57%
+ - Overall directory at 29.07%
+2. `open-sse/translator/request`
+ - Overall directory at 36.39%
+ - Many translators are still near single-digit coverage
+3. `open-sse/translator/response`
+ - Overall directory at 8.07%
+4. `open-sse/executors`
+ - Overall directory at 36.62%
+5. `src/lib/db`
+ - `models.ts` at 20.66%
+ - `registeredKeys.ts` at 34.46%
+ - `modelComboMappings.ts` at 36.25%
+ - `settings.ts` at 46.40%
+ - `webhooks.ts` at 33.33%
+6. `src/lib/usage`
+ - `usageHistory.ts` at 21.12%
+ - `usageStats.ts` at 9.56%
+ - `costCalculator.ts` at 30.00%
+7. `src/lib/providers`
+ - `validation.ts` at 41.16%
+8. Low-risk utility and API files for early gains
+ - `src/shared/utils/upstreamError.ts`
+ - `src/shared/utils/apiAuth.ts`
+ - `src/lib/api/errorResponse.ts`
+ - `src/app/api/settings/require-login/route.ts`
+ - `src/app/api/providers/[id]/models/route.ts`
+
+## Execution checklist
+
+### Phase 1: 56.95% -> 60%
+
+- [x] Fix coverage metric so it reflects source code instead of test files
+- [x] Keep a legacy coverage script for comparison
+- [x] Record the baseline and hotspots in-repo
+- [ ] Add focused tests for low-risk utilities:
+ - `src/shared/utils/upstreamError.ts`
+ - `src/shared/utils/fetchTimeout.ts`
+ - `src/lib/api/errorResponse.ts`
+ - `src/shared/utils/apiAuth.ts`
+ - `src/lib/display/names.ts`
+- [ ] Add route tests for:
+ - `src/app/api/settings/require-login/route.ts`
+ - `src/app/api/providers/[id]/models/route.ts`
+
+### Phase 2: 60% -> 65%
+
+- [ ] Add DB-backed tests for:
+ - `src/lib/db/modelComboMappings.ts`
+ - `src/lib/db/settings.ts`
+ - `src/lib/db/registeredKeys.ts`
+- [ ] Cover branch behavior in:
+ - `src/lib/providers/validation.ts`
+ - `src/app/api/v1/embeddings/route.ts`
+ - `src/app/api/v1/moderations/route.ts`
+
+### Phase 3: 65% -> 70%
+
+- [ ] Add usage analytics tests for:
+ - `src/lib/usage/usageHistory.ts`
+ - `src/lib/usage/usageStats.ts`
+ - `src/lib/usage/costCalculator.ts`
+- [ ] Expand route coverage for proxy management and settings branches
+
+### Phase 4: 70% -> 75%
+
+- [ ] Cover translator helpers and central translation paths:
+ - `open-sse/translator/index.ts`
+ - `open-sse/translator/helpers/*`
+ - `open-sse/translator/request/*`
+ - `open-sse/translator/response/*`
+
+### Phase 5: 75% -> 80%
+
+- [ ] Add handler-level tests for:
+ - `open-sse/handlers/chatCore.ts`
+ - `open-sse/handlers/responsesHandler.js`
+ - `open-sse/handlers/imageGeneration.js`
+ - `open-sse/handlers/embeddings.js`
+- [ ] Add executor branch coverage for provider-specific auth, retries, and endpoint overrides
+
+### Phase 6: 80% -> 85%
+
+- [ ] Merge more edge-case suites into the main coverage path
+- [ ] Increase function coverage for DB modules with weak constructor/helper coverage
+- [ ] Close branch gaps in `settings.ts`, `registeredKeys.ts`, `validation.ts`, and translator helpers
+
+### Phase 7: 85% -> 90%
+
+- [ ] Treat the remaining low-coverage files as blockers
+- [ ] Add regression tests for every uncovered production bug fixed during the push to 90%
+- [ ] Raise the coverage gate in CI only after the local baseline is stable for at least two consecutive runs
+
+## Ratchet policy
+
+Update `npm run test:coverage` thresholds only after the project actually exceeds the next milestone with a comfortable buffer.
+
+Recommended ratchet sequence:
+
+1. 55/60/55
+2. 60/62/58
+3. 65/64/62
+4. 70/66/66
+5. 75/70/72
+6. 80/75/78
+7. 85/80/84
+8. 90/85/88
+
+Order is `statements-lines / branches / functions`.
+
+## Known gap
+
+The current coverage command measures the main Node unit suite and includes source reached from it, including `open-sse`. It does not yet merge Vitest coverage into a single unified report. That merge is worth doing later, but it is not a blocker for starting the 60% -> 80% climb.
diff --git a/docs/i18n/de/docs/FEATURES.md b/docs/i18n/de/docs/FEATURES.md
index 72b1b15eba..31b04fba54 100644
--- a/docs/i18n/de/docs/FEATURES.md
+++ b/docs/i18n/de/docs/FEATURES.md
@@ -1,6 +1,6 @@
# OmniRoute — Dashboard Features Gallery (Deutsch)
-🌐 **Languages:** 🇺🇸 [English](../../../../docs/FEATURES.md) · 🇪🇸 [es](../../es/docs/FEATURES.md) · 🇫🇷 [fr](../../fr/docs/FEATURES.md) · 🇩🇪 [de](../../de/docs/FEATURES.md) · 🇮🇹 [it](../../it/docs/FEATURES.md) · 🇷🇺 [ru](../../ru/docs/FEATURES.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/FEATURES.md) · 🇯🇵 [ja](../../ja/docs/FEATURES.md) · 🇰🇷 [ko](../../ko/docs/FEATURES.md) · 🇸🇦 [ar](../../ar/docs/FEATURES.md) · 🇮🇳 [in](../../in/docs/FEATURES.md) · 🇹🇭 [th](../../th/docs/FEATURES.md) · 🇻🇳 [vi](../../vi/docs/FEATURES.md) · 🇮🇩 [id](../../id/docs/FEATURES.md) · 🇲🇾 [ms](../../ms/docs/FEATURES.md) · 🇳🇱 [nl](../../nl/docs/FEATURES.md) · 🇵🇱 [pl](../../pl/docs/FEATURES.md) · 🇸🇪 [sv](../../sv/docs/FEATURES.md) · 🇳🇴 [no](../../no/docs/FEATURES.md) · 🇩🇰 [da](../../da/docs/FEATURES.md) · 🇫🇮 [fi](../../fi/docs/FEATURES.md) · 🇵🇹 [pt](../../pt/docs/FEATURES.md) · 🇷🇴 [ro](../../ro/docs/FEATURES.md) · 🇭🇺 [hu](../../hu/docs/FEATURES.md) · 🇧🇬 [bg](../../bg/docs/FEATURES.md) · 🇸🇰 [sk](../../sk/docs/FEATURES.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/FEATURES.md) · 🇮🇱 [he](../../he/docs/FEATURES.md) · 🇵🇭 [phi](../../phi/docs/FEATURES.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/FEATURES.md)
+🌐 **Languages:** 🇺🇸 [English](../../../../docs/FEATURES.md) · 🇪🇸 [es](../../es/docs/FEATURES.md) · 🇫🇷 [fr](../../fr/docs/FEATURES.md) · 🇩🇪 [de](../../de/docs/FEATURES.md) · 🇮🇹 [it](../../it/docs/FEATURES.md) · 🇷🇺 [ru](../../ru/docs/FEATURES.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/FEATURES.md) · 🇯🇵 [ja](../../ja/docs/FEATURES.md) · 🇰🇷 [ko](../../ko/docs/FEATURES.md) · 🇸🇦 [ar](../../ar/docs/FEATURES.md) · 🇮🇳 [in](../../in/docs/FEATURES.md) · 🇹🇭 [th](../../th/docs/FEATURES.md) · 🇻🇳 [vi](../../vi/docs/FEATURES.md) · 🇮🇩 [id](../../id/docs/FEATURES.md) · 🇲🇾 [ms](../../ms/docs/FEATURES.md) · 🇳🇱 [nl](../../nl/docs/FEATURES.md) · 🇵🇱 [pl](../../pl/docs/FEATURES.md) · 🇸🇪 [sv](../../sv/docs/FEATURES.md) · 🇳🇴 [no](../../no/docs/FEATURES.md) · 🇩🇰 [da](../../da/docs/FEATURES.md) · 🇫🇮 [fi](../../fi/docs/FEATURES.md) · 🇵🇹 [pt](../../pt/docs/FEATURES.md) · 🇷🇴 [ro](../../ro/docs/FEATURES.md) · 🇭🇺 [hu](../../hu/docs/FEATURES.md) · 🇧🇬 [bg](../../bg/docs/FEATURES.md) · 🇸🇰 [sk](../../sk/docs/FEATURES.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/FEATURES.md) · 🇮🇱 [he](../../he/docs/FEATURES.md) · 🇵🇭 [phi](../../phi/docs/FEATURES.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/FEATURES.md) · 🇨🇿 [cs](../../cs/docs/FEATURES.md)
---
@@ -10,7 +10,7 @@ Visual guide to every section of the OmniRoute dashboard.
## 🔌 Providers
-Manage AI provider connections: OAuth providers (Claude Code, Codex, Gemini CLI), API key providers (Groq, DeepSeek, OpenRouter), and free providers (iFlow, Qwen, Kiro). Kiro accounts include credit balance tracking — remaining credits, total allowance, and renewal date visible in Dashboard → Usage.
+Manage AI provider connections: OAuth providers (Claude Code, Codex, Gemini CLI), API key providers (Groq, DeepSeek, OpenRouter), and free providers (Qoder, Qwen, Kiro). Kiro accounts include credit balance tracking — remaining credits, total allowance, and renewal date visible in Dashboard → Usage.

diff --git a/docs/i18n/de/docs/MCP-SERVER.md b/docs/i18n/de/docs/MCP-SERVER.md
new file mode 100644
index 0000000000..73e478960f
--- /dev/null
+++ b/docs/i18n/de/docs/MCP-SERVER.md
@@ -0,0 +1,87 @@
+# OmniRoute MCP Server Documentation (Deutsch)
+
+🌐 **Languages:** 🇺🇸 [English](../../../../docs/MCP-SERVER.md) · 🇪🇸 [es](../../es/docs/MCP-SERVER.md) · 🇫🇷 [fr](../../fr/docs/MCP-SERVER.md) · 🇩🇪 [de](../../de/docs/MCP-SERVER.md) · 🇮🇹 [it](../../it/docs/MCP-SERVER.md) · 🇷🇺 [ru](../../ru/docs/MCP-SERVER.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/MCP-SERVER.md) · 🇯🇵 [ja](../../ja/docs/MCP-SERVER.md) · 🇰🇷 [ko](../../ko/docs/MCP-SERVER.md) · 🇸🇦 [ar](../../ar/docs/MCP-SERVER.md) · 🇮🇳 [in](../../in/docs/MCP-SERVER.md) · 🇹🇭 [th](../../th/docs/MCP-SERVER.md) · 🇻🇳 [vi](../../vi/docs/MCP-SERVER.md) · 🇮🇩 [id](../../id/docs/MCP-SERVER.md) · 🇲🇾 [ms](../../ms/docs/MCP-SERVER.md) · 🇳🇱 [nl](../../nl/docs/MCP-SERVER.md) · 🇵🇱 [pl](../../pl/docs/MCP-SERVER.md) · 🇸🇪 [sv](../../sv/docs/MCP-SERVER.md) · 🇳🇴 [no](../../no/docs/MCP-SERVER.md) · 🇩🇰 [da](../../da/docs/MCP-SERVER.md) · 🇫🇮 [fi](../../fi/docs/MCP-SERVER.md) · 🇵🇹 [pt](../../pt/docs/MCP-SERVER.md) · 🇷🇴 [ro](../../ro/docs/MCP-SERVER.md) · 🇭🇺 [hu](../../hu/docs/MCP-SERVER.md) · 🇧🇬 [bg](../../bg/docs/MCP-SERVER.md) · 🇸🇰 [sk](../../sk/docs/MCP-SERVER.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/MCP-SERVER.md) · 🇮🇱 [he](../../he/docs/MCP-SERVER.md) · 🇵🇭 [phi](../../phi/docs/MCP-SERVER.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/MCP-SERVER.md) · 🇨🇿 [cs](../../cs/docs/MCP-SERVER.md)
+
+---
+
+> Model Context Protocol server with 16 intelligent tools
+
+## Installieren
+
+OmniRoute MCP is built-in. Start it with:
+
+```bash
+omniroute --mcp
+```
+
+Or via the open-sse transport:
+
+```bash
+# HTTP streamable transport (port 20130)
+omniroute --dev # MCP auto-starts on /mcp endpoint
+```
+
+## IDE Configuration
+
+See [IDE Configs](integrations/ide-configs.md) for Antigravity, Cursor, Copilot, and Claude Desktop setup.
+
+---
+
+## Essential Tools (8)
+
+| Tool | Description |
+| :------------------------------ | :--------------------------------------- |
+| `omniroute_get_health` | Gateway health, circuit breakers, uptime |
+| `omniroute_list_combos` | All configured combos with models |
+| `omniroute_get_combo_metrics` | Performance metrics for a specific combo |
+| `omniroute_switch_combo` | Switch active combo by ID/name |
+| `omniroute_check_quota` | Quota status per provider or all |
+| `omniroute_route_request` | Send a chat completion through OmniRoute |
+| `omniroute_cost_report` | Cost analytics for a time period |
+| `omniroute_list_models_catalog` | Full model catalog with capabilities |
+
+## Advanced Tools (8)
+
+| Tool | Description |
+| :--------------------------------- | :---------------------------------------------------------- |
+| `omniroute_simulate_route` | Dry-run routing simulation with fallback tree |
+| `omniroute_set_budget_guard` | Session budget with degrade/block/alert actions |
+| `omniroute_set_resilience_profile` | Apply conservative/balanced/aggressive preset |
+| `omniroute_test_combo` | Live-test all models in a combo via a real upstream request |
+| `omniroute_get_provider_metrics` | Detailed metrics for one provider |
+| `omniroute_best_combo_for_task` | Task-fitness recommendation with alternatives |
+| `omniroute_explain_route` | Explain a past routing decision |
+| `omniroute_get_session_snapshot` | Full session state: costs, tokens, errors |
+
+## Authentication
+
+MCP tools are authenticated via API key scopes. Each tool requires specific scopes:
+
+| Scope | Tools |
+| :------------- | :----------------------------------------------- |
+| `read:health` | get_health, get_provider_metrics |
+| `read:combos` | list_combos, get_combo_metrics |
+| `write:combos` | switch_combo |
+| `read:quota` | check_quota |
+| `write:route` | route_request, simulate_route, test_combo |
+| `read:usage` | cost_report, get_session_snapshot, explain_route |
+| `write:config` | set_budget_guard, set_resilience_profile |
+| `read:models` | list_models_catalog, best_combo_for_task |
+
+## Audit Logging
+
+Every tool call is logged to `mcp_tool_audit` with:
+
+- Tool name, arguments, result
+- Duration (ms), success/failure
+- API key hash, timestamp
+
+## Files
+
+| File | Purpose |
+| :------------------------------------------- | :------------------------------------------ |
+| `open-sse/mcp-server/server.ts` | MCP server creation + 16 tool registrations |
+| `open-sse/mcp-server/transport.ts` | Stdio + HTTP transport |
+| `open-sse/mcp-server/auth.ts` | API key + scope validation |
+| `open-sse/mcp-server/audit.ts` | Tool call audit logging |
+| `open-sse/mcp-server/tools/advancedTools.ts` | 8 advanced tool handlers |
diff --git a/docs/i18n/de/docs/RELEASE_CHECKLIST.md b/docs/i18n/de/docs/RELEASE_CHECKLIST.md
new file mode 100644
index 0000000000..1b7db4cafa
--- /dev/null
+++ b/docs/i18n/de/docs/RELEASE_CHECKLIST.md
@@ -0,0 +1,37 @@
+# Release Checklist (Deutsch)
+
+🌐 **Languages:** 🇺🇸 [English](../../../../docs/RELEASE_CHECKLIST.md) · 🇪🇸 [es](../../es/docs/RELEASE_CHECKLIST.md) · 🇫🇷 [fr](../../fr/docs/RELEASE_CHECKLIST.md) · 🇩🇪 [de](../../de/docs/RELEASE_CHECKLIST.md) · 🇮🇹 [it](../../it/docs/RELEASE_CHECKLIST.md) · 🇷🇺 [ru](../../ru/docs/RELEASE_CHECKLIST.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/RELEASE_CHECKLIST.md) · 🇯🇵 [ja](../../ja/docs/RELEASE_CHECKLIST.md) · 🇰🇷 [ko](../../ko/docs/RELEASE_CHECKLIST.md) · 🇸🇦 [ar](../../ar/docs/RELEASE_CHECKLIST.md) · 🇮🇳 [in](../../in/docs/RELEASE_CHECKLIST.md) · 🇹🇭 [th](../../th/docs/RELEASE_CHECKLIST.md) · 🇻🇳 [vi](../../vi/docs/RELEASE_CHECKLIST.md) · 🇮🇩 [id](../../id/docs/RELEASE_CHECKLIST.md) · 🇲🇾 [ms](../../ms/docs/RELEASE_CHECKLIST.md) · 🇳🇱 [nl](../../nl/docs/RELEASE_CHECKLIST.md) · 🇵🇱 [pl](../../pl/docs/RELEASE_CHECKLIST.md) · 🇸🇪 [sv](../../sv/docs/RELEASE_CHECKLIST.md) · 🇳🇴 [no](../../no/docs/RELEASE_CHECKLIST.md) · 🇩🇰 [da](../../da/docs/RELEASE_CHECKLIST.md) · 🇫🇮 [fi](../../fi/docs/RELEASE_CHECKLIST.md) · 🇵🇹 [pt](../../pt/docs/RELEASE_CHECKLIST.md) · 🇷🇴 [ro](../../ro/docs/RELEASE_CHECKLIST.md) · 🇭🇺 [hu](../../hu/docs/RELEASE_CHECKLIST.md) · 🇧🇬 [bg](../../bg/docs/RELEASE_CHECKLIST.md) · 🇸🇰 [sk](../../sk/docs/RELEASE_CHECKLIST.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/RELEASE_CHECKLIST.md) · 🇮🇱 [he](../../he/docs/RELEASE_CHECKLIST.md) · 🇵🇭 [phi](../../phi/docs/RELEASE_CHECKLIST.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/RELEASE_CHECKLIST.md) · 🇨🇿 [cs](../../cs/docs/RELEASE_CHECKLIST.md)
+
+---
+
+Use this checklist before tagging or publishing a new OmniRoute release.
+
+## Version and Changelog
+
+1. Bump `package.json` version (`x.y.z`) in the release branch.
+2. Move release notes from `## [Unreleased]` in `CHANGELOG.md` to a dated section:
+ - `## [x.y.z] — YYYY-MM-DD`
+3. Keep `## [Unreleased]` as the first changelog section for upcoming work.
+4. Ensure the latest semver section in `CHANGELOG.md` equals `package.json` version.
+
+## API Docs
+
+1. Update `docs/openapi.yaml`:
+ - `info.version` must equal `package.json` version.
+2. Validate endpoint examples if API contracts changed.
+
+## Runtime Docs
+
+1. Review `docs/ARCHITECTURE.md` for storage/runtime drift.
+2. Review `docs/TROUBLESHOOTING.md` for env var and operational drift.
+3. Update localized docs if source docs changed significantly.
+
+## Automated Check
+
+Run the sync guard locally before opening PR:
+
+```bash
+npm run check:docs-sync
+```
+
+CI also runs this check in `.github/workflows/ci.yml` (lint job).
diff --git a/docs/i18n/de/docs/TROUBLESHOOTING.md b/docs/i18n/de/docs/TROUBLESHOOTING.md
new file mode 100644
index 0000000000..02ab03bcf8
--- /dev/null
+++ b/docs/i18n/de/docs/TROUBLESHOOTING.md
@@ -0,0 +1,256 @@
+# Troubleshooting (Deutsch)
+
+🌐 **Languages:** 🇺🇸 [English](../../../../docs/TROUBLESHOOTING.md) · 🇪🇸 [es](../../es/docs/TROUBLESHOOTING.md) · 🇫🇷 [fr](../../fr/docs/TROUBLESHOOTING.md) · 🇩🇪 [de](../../de/docs/TROUBLESHOOTING.md) · 🇮🇹 [it](../../it/docs/TROUBLESHOOTING.md) · 🇷🇺 [ru](../../ru/docs/TROUBLESHOOTING.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/TROUBLESHOOTING.md) · 🇯🇵 [ja](../../ja/docs/TROUBLESHOOTING.md) · 🇰🇷 [ko](../../ko/docs/TROUBLESHOOTING.md) · 🇸🇦 [ar](../../ar/docs/TROUBLESHOOTING.md) · 🇮🇳 [in](../../in/docs/TROUBLESHOOTING.md) · 🇹🇭 [th](../../th/docs/TROUBLESHOOTING.md) · 🇻🇳 [vi](../../vi/docs/TROUBLESHOOTING.md) · 🇮🇩 [id](../../id/docs/TROUBLESHOOTING.md) · 🇲🇾 [ms](../../ms/docs/TROUBLESHOOTING.md) · 🇳🇱 [nl](../../nl/docs/TROUBLESHOOTING.md) · 🇵🇱 [pl](../../pl/docs/TROUBLESHOOTING.md) · 🇸🇪 [sv](../../sv/docs/TROUBLESHOOTING.md) · 🇳🇴 [no](../../no/docs/TROUBLESHOOTING.md) · 🇩🇰 [da](../../da/docs/TROUBLESHOOTING.md) · 🇫🇮 [fi](../../fi/docs/TROUBLESHOOTING.md) · 🇵🇹 [pt](../../pt/docs/TROUBLESHOOTING.md) · 🇷🇴 [ro](../../ro/docs/TROUBLESHOOTING.md) · 🇭🇺 [hu](../../hu/docs/TROUBLESHOOTING.md) · 🇧🇬 [bg](../../bg/docs/TROUBLESHOOTING.md) · 🇸🇰 [sk](../../sk/docs/TROUBLESHOOTING.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/TROUBLESHOOTING.md) · 🇮🇱 [he](../../he/docs/TROUBLESHOOTING.md) · 🇵🇭 [phi](../../phi/docs/TROUBLESHOOTING.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/TROUBLESHOOTING.md) · 🇨🇿 [cs](../../cs/docs/TROUBLESHOOTING.md)
+
+---
+
+Common problems and solutions for OmniRoute.
+
+---
+
+## Quick Fixes
+
+| Problem | Solution |
+| ----------------------------- | ------------------------------------------------------------------ |
+| First login not working | Set `INITIAL_PASSWORD` in `.env` (no hardcoded default) |
+| Dashboard opens on wrong port | Set `PORT=20128` and `NEXT_PUBLIC_BASE_URL=http://localhost:20128` |
+| No request logs under `logs/` | Set `ENABLE_REQUEST_LOGS=true` |
+| EACCES: permission denied | Set `DATA_DIR=/path/to/writable/dir` to override `~/.omniroute` |
+| Routing strategy not saving | Update to v1.4.11+ (Zod schema fix for settings persistence) |
+
+---
+
+## Provider Issues
+
+### "Language model did not provide messages"
+
+**Cause:** Provider quota exhausted.
+
+**Fix:**
+
+1. Check dashboard quota tracker
+2. Use a combo with fallback tiers
+3. Switch to cheaper/free tier
+
+### Rate Limiting
+
+**Cause:** Subscription quota exhausted.
+
+**Fix:**
+
+- Add fallback: `cc/claude-opus-4-6 → glm/glm-4.7 → if/kimi-k2-thinking`
+- Use GLM/MiniMax as cheap backup
+
+### OAuth Token Expired
+
+OmniRoute auto-refreshes tokens. If issues persist:
+
+1. Dashboard → Provider → Reconnect
+2. Delete and re-add the provider connection
+
+---
+
+## Cloud Issues
+
+### Cloud Sync Errors
+
+1. Verify `BASE_URL` points to your running instance (e.g., `http://localhost:20128`)
+2. Verify `CLOUD_URL` points to your cloud endpoint (e.g., `https://omniroute.dev`)
+3. Keep `NEXT_PUBLIC_*` values aligned with server-side values
+
+### Cloud `stream=false` Returns 500
+
+**Symptom:** `Unexpected token 'd'...` on cloud endpoint for non-streaming calls.
+
+**Cause:** Upstream returns SSE payload while client expects JSON.
+
+**Workaround:** Use `stream=true` for cloud direct calls. Local runtime includes SSE→JSON fallback.
+
+### Cloud Says Connected but "Invalid API key"
+
+1. Create a fresh key from local dashboard (`/api/keys`)
+2. Run cloud sync: Enable Cloud → Sync Now
+3. Old/non-synced keys can still return `401` on cloud
+
+---
+
+## Docker Issues
+
+### CLI Tool Shows Not Installed
+
+1. Check runtime fields: `curl http://localhost:20128/api/cli-tools/runtime/codex | jq`
+2. For portable mode: use image target `runner-cli` (bundled CLIs)
+3. For host mount mode: set `CLI_EXTRA_PATHS` and mount host bin directory as read-only
+4. If `installed=true` and `runnable=false`: binary was found but failed healthcheck
+
+### Quick Runtime Validation
+
+```bash
+curl -s http://localhost:20128/api/cli-tools/codex-settings | jq '{installed,runnable,commandPath,runtimeMode,reason}'
+curl -s http://localhost:20128/api/cli-tools/claude-settings | jq '{installed,runnable,commandPath,runtimeMode,reason}'
+curl -s http://localhost:20128/api/cli-tools/openclaw-settings | jq '{installed,runnable,commandPath,runtimeMode,reason}'
+```
+
+---
+
+## Cost Issues
+
+### High Costs
+
+1. Check usage stats in Dashboard → Usage
+2. Switch primary model to GLM/MiniMax
+3. Use free tier (Gemini CLI, Qoder) for non-critical tasks
+4. Set cost budgets per API key: Dashboard → API Keys → Budget
+
+---
+
+## Debugging
+
+### Enable Request Logs
+
+Set `ENABLE_REQUEST_LOGS=true` in your `.env` file. Logs appear under `logs/` directory.
+
+### Check Provider Health
+
+```bash
+# Health dashboard
+http://localhost:20128/dashboard/health
+
+# API health check
+curl http://localhost:20128/api/monitoring/health
+```
+
+### Runtime Storage
+
+- Main state: `${DATA_DIR}/storage.sqlite` (providers, combos, aliases, keys, settings)
+- Usage: SQLite tables in `storage.sqlite` (`usage_history`, `call_logs`, `proxy_logs`) + optional `${DATA_DIR}/log.txt` and `${DATA_DIR}/call_logs/`
+- Request logs: `/logs/...` (when `ENABLE_REQUEST_LOGS=true`)
+
+---
+
+## Circuit Breaker Issues
+
+### Provider stuck in OPEN state
+
+When a provider's circuit breaker is OPEN, requests are blocked until the cooldown expires.
+
+**Fix:**
+
+1. Go to **Dashboard → Settings → Resilience**
+2. Check the circuit breaker card for the affected provider
+3. Click **Reset All** to clear all breakers, or wait for the cooldown to expire
+4. Verify the provider is actually available before resetting
+
+### Provider keeps tripping the circuit breaker
+
+If a provider repeatedly enters OPEN state:
+
+1. Check **Dashboard → Health → Provider Health** for the failure pattern
+2. Go to **Settings → Resilience → Provider Profiles** and increase the failure threshold
+3. Check if the provider has changed API limits or requires re-authentication
+4. Review latency telemetry — high latency may cause timeout-based failures
+
+---
+
+## Audio Transcription Issues
+
+### "Unsupported model" error
+
+- Ensure you're using the correct prefix: `deepgram/nova-3` or `assemblyai/best`
+- Verify the provider is connected in **Dashboard → Providers**
+
+### Transcription returns empty or fails
+
+- Check supported audio formats: `mp3`, `wav`, `m4a`, `flac`, `ogg`, `webm`
+- Verify file size is within provider limits (typically < 25MB)
+- Check provider API key validity in the provider card
+
+---
+
+## Translator Debugging
+
+Use **Dashboard → Translator** to debug format translation issues:
+
+| Mode | When to Use |
+| ---------------- | -------------------------------------------------------------------------------------------- |
+| **Playground** | Compare input/output formats side by side — paste a failing request to see how it translates |
+| **Chat Tester** | Send live messages and inspect the full request/response payload including headers |
+| **Test Bench** | Run batch tests across format combinations to find which translations are broken |
+| **Live Monitor** | Watch real-time request flow to catch intermittent translation issues |
+
+### Common format issues
+
+- **Thinking tags not appearing** — Check if the target provider supports thinking and the thinking budget setting
+- **Tool calls dropping** — Some format translations may strip unsupported fields; verify in Playground mode
+- **System prompt missing** — Claude and Gemini handle system prompts differently; check translation output
+- **SDK returns raw string instead of object** — Fixed in v1.1.0: response sanitizer now strips non-standard fields (`x_groq`, `usage_breakdown`, etc.) that cause OpenAI SDK Pydantic validation failures
+- **GLM/ERNIE rejects `system` role** — Fixed in v1.1.0: role normalizer automatically merges system messages into user messages for incompatible models
+- **`developer` role not recognized** — Fixed in v1.1.0: automatically converted to `system` for non-OpenAI providers
+- **`json_schema` not working with Gemini** — Fixed in v1.1.0: `response_format` is now converted to Gemini's `responseMimeType` + `responseSchema`
+
+---
+
+## Resilience Settings
+
+### Auto rate-limit not triggering
+
+- Auto rate-limit only applies to API key providers (not OAuth/subscription)
+- Verify **Settings → Resilience → Provider Profiles** has auto-rate-limit enabled
+- Check if the provider returns `429` status codes or `Retry-After` headers
+
+### Tuning exponential backoff
+
+Provider profiles support these settings:
+
+- **Base delay** — Initial wait time after first failure (default: 1s)
+- **Max delay** — Maximum wait time cap (default: 30s)
+- **Multiplier** — How much to increase delay per consecutive failure (default: 2x)
+
+### Anti-thundering herd
+
+When many concurrent requests hit a rate-limited provider, OmniRoute uses mutex + auto rate-limiting to serialize requests and prevent cascading failures. This is automatic for API key providers.
+
+---
+
+## Optional RAG / LLM failure taxonomy (16 problems)
+
+Some OmniRoute users place the gateway in front of RAG or agent stacks. In those setups it is common to see a strange pattern: OmniRoute looks healthy (providers up, routing profiles ok, no rate limit alerts) but the final answer is still wrong.
+
+In practice these incidents usually come from the downstream RAG pipeline, not from the gateway itself.
+
+If you want a shared vocabulary to describe those failures you can use the WFGY ProblemMap, an external MIT license text resource that defines sixteen recurring RAG / LLM failure patterns. At a high level it covers:
+
+- retrieval drift and broken context boundaries
+- empty or stale indexes and vector stores
+- embedding versus semantic mismatch
+- prompt assembly and context window issues
+- logic collapse and overconfident answers
+- long chain and agent coordination failures
+- multi agent memory and role drift
+- deployment and bootstrap ordering problems
+
+The idea is simple:
+
+1. When you investigate a bad response, capture:
+ - user task and request
+ - route or provider combo in OmniRoute
+ - any RAG context used downstream (retrieved documents, tool calls, etc)
+2. Map the incident to one or two WFGY ProblemMap numbers (`No.1` … `No.16`).
+3. Store the number in your own dashboard, runbook, or incident tracker next to the OmniRoute logs.
+4. Use the corresponding WFGY page to decide whether you need to change your RAG stack, retriever, or routing strategy.
+
+Full text and concrete recipes live here (MIT license, text only):
+
+[WFGY ProblemMap README](https://github.com/onestardao/WFGY/blob/main/ProblemMap/README.md)
+
+You can ignore this section if you do not run RAG or agent pipelines behind OmniRoute.
+
+---
+
+## Still Stuck?
+
+- **GitHub Issues**: [github.com/diegosouzapw/OmniRoute/issues](https://github.com/diegosouzapw/OmniRoute/issues)
+- **Architecture**: See [`docs/ARCHITECTURE.md`](ARCHITECTURE.md) for internal details
+- **API Reference**: See [`docs/API_REFERENCE.md`](API_REFERENCE.md) for all endpoints
+- **Health Dashboard**: Check **Dashboard → Health** for real-time system status
+- **Translator**: Use **Dashboard → Translator** to debug format issues
diff --git a/docs/i18n/de/USER_GUIDE.md b/docs/i18n/de/docs/USER_GUIDE.md
similarity index 82%
rename from docs/i18n/de/USER_GUIDE.md
rename to docs/i18n/de/docs/USER_GUIDE.md
index 2e6793c4c4..0280efc638 100644
--- a/docs/i18n/de/USER_GUIDE.md
+++ b/docs/i18n/de/docs/USER_GUIDE.md
@@ -1,8 +1,6 @@
# User Guide (Deutsch)
-🌐 **Languages:** 🇺🇸 [English](../../USER_GUIDE.md) · 🇧🇷 [pt-BR](../pt-BR/USER_GUIDE.md) · 🇪🇸 [es](../es/USER_GUIDE.md) · 🇫🇷 [fr](../fr/USER_GUIDE.md) · 🇩🇪 [de](../de/USER_GUIDE.md) · 🇮🇹 [it](../it/USER_GUIDE.md) · 🇷🇺 [ru](../ru/USER_GUIDE.md) · 🇨🇳 [zh-CN](../zh-CN/USER_GUIDE.md) · 🇯🇵 [ja](../ja/USER_GUIDE.md) · 🇰🇷 [ko](../ko/USER_GUIDE.md) · 🇸🇦 [ar](../ar/USER_GUIDE.md) · 🇮🇳 [in](../in/USER_GUIDE.md) · 🇹🇭 [th](../th/USER_GUIDE.md) · 🇻🇳 [vi](../vi/USER_GUIDE.md) · 🇮🇩 [id](../id/USER_GUIDE.md) · 🇲🇾 [ms](../ms/USER_GUIDE.md) · 🇳🇱 [nl](../nl/USER_GUIDE.md) · 🇵🇱 [pl](../pl/USER_GUIDE.md) · 🇸🇪 [sv](../sv/USER_GUIDE.md) · 🇳🇴 [no](../no/USER_GUIDE.md) · 🇩🇰 [da](../da/USER_GUIDE.md) · 🇫🇮 [fi](../fi/USER_GUIDE.md) · 🇵🇹 [pt](../pt/USER_GUIDE.md) · 🇷🇴 [ro](../ro/USER_GUIDE.md) · 🇭🇺 [hu](../hu/USER_GUIDE.md) · 🇧🇬 [bg](../bg/USER_GUIDE.md) · 🇸🇰 [sk](../sk/USER_GUIDE.md) · 🇺🇦 [uk-UA](../uk-UA/USER_GUIDE.md) · 🇮🇱 [he](../he/USER_GUIDE.md) · 🇵🇭 [phi](../phi/USER_GUIDE.md)
-
-> 🇺🇸 [English](../../USER_GUIDE.md)
+🌐 **Languages:** 🇺🇸 [English](../../../../docs/USER_GUIDE.md) · 🇪🇸 [es](../../es/docs/USER_GUIDE.md) · 🇫🇷 [fr](../../fr/docs/USER_GUIDE.md) · 🇩🇪 [de](../../de/docs/USER_GUIDE.md) · 🇮🇹 [it](../../it/docs/USER_GUIDE.md) · 🇷🇺 [ru](../../ru/docs/USER_GUIDE.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/USER_GUIDE.md) · 🇯🇵 [ja](../../ja/docs/USER_GUIDE.md) · 🇰🇷 [ko](../../ko/docs/USER_GUIDE.md) · 🇸🇦 [ar](../../ar/docs/USER_GUIDE.md) · 🇮🇳 [in](../../in/docs/USER_GUIDE.md) · 🇹🇭 [th](../../th/docs/USER_GUIDE.md) · 🇻🇳 [vi](../../vi/docs/USER_GUIDE.md) · 🇮🇩 [id](../../id/docs/USER_GUIDE.md) · 🇲🇾 [ms](../../ms/docs/USER_GUIDE.md) · 🇳🇱 [nl](../../nl/docs/USER_GUIDE.md) · 🇵🇱 [pl](../../pl/docs/USER_GUIDE.md) · 🇸🇪 [sv](../../sv/docs/USER_GUIDE.md) · 🇳🇴 [no](../../no/docs/USER_GUIDE.md) · 🇩🇰 [da](../../da/docs/USER_GUIDE.md) · 🇫🇮 [fi](../../fi/docs/USER_GUIDE.md) · 🇵🇹 [pt](../../pt/docs/USER_GUIDE.md) · 🇷🇴 [ro](../../ro/docs/USER_GUIDE.md) · 🇭🇺 [hu](../../hu/docs/USER_GUIDE.md) · 🇧🇬 [bg](../../bg/docs/USER_GUIDE.md) · 🇸🇰 [sk](../../sk/docs/USER_GUIDE.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/USER_GUIDE.md) · 🇮🇱 [he](../../he/docs/USER_GUIDE.md) · 🇵🇭 [phi](../../phi/docs/USER_GUIDE.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/USER_GUIDE.md) · 🇨🇿 [cs](../../cs/docs/USER_GUIDE.md)
---
@@ -320,7 +318,7 @@ Model: cc/claude-opus-4-6
---
-## 🚀 Deployment
+## Bereitstellung
### Global npm install (Recommended)
@@ -511,23 +509,26 @@ post_install() {
### Environment Variables
-| Variable | Default | Description |
-| ------------------------- | ------------------------------------ | ------------------------------------------------------- |
-| `JWT_SECRET` | `omniroute-default-secret-change-me` | JWT signing secret (**change in production**) |
-| `INITIAL_PASSWORD` | `123456` | First login password |
-| `DATA_DIR` | `~/.omniroute` | Data directory (db, usage, logs) |
-| `PORT` | framework default | Service port (`20128` in examples) |
-| `HOSTNAME` | framework default | Bind host (Docker defaults to `0.0.0.0`) |
-| `NODE_ENV` | runtime default | Set `production` for deploy |
-| `BASE_URL` | `http://localhost:20128` | Server-side internal base URL |
-| `CLOUD_URL` | `https://omniroute.dev` | Cloud sync endpoint base URL |
-| `API_KEY_SECRET` | `endpoint-proxy-api-key-secret` | HMAC secret for generated API keys |
-| `REQUIRE_API_KEY` | `false` | Enforce Bearer API key on `/v1/*` |
-| `ENABLE_REQUEST_LOGS` | `false` | Enables request/response logs |
-| `AUTH_COOKIE_SECURE` | `false` | Force `Secure` auth cookie (behind HTTPS reverse proxy) |
-| `OMNIROUTE_MEMORY_MB` | `512` | Node.js heap limit in MB |
-| `PROMPT_CACHE_MAX_SIZE` | `50` | Max prompt cache entries |
-| `SEMANTIC_CACHE_MAX_SIZE` | `100` | Max semantic cache entries |
+| Variable | Default | Description |
+| ---------------------------- | ------------------------------------ | ------------------------------------------------------------------------------------------ |
+| `JWT_SECRET` | `omniroute-default-secret-change-me` | JWT signing secret (**change in production**) |
+| `INITIAL_PASSWORD` | `123456` | First login password |
+| `DATA_DIR` | `~/.omniroute` | Data directory (db, usage, logs) |
+| `PORT` | framework default | Service port (`20128` in examples) |
+| `HOSTNAME` | framework default | Bind host (Docker defaults to `0.0.0.0`) |
+| `NODE_ENV` | runtime default | Set `production` for deploy |
+| `BASE_URL` | `http://localhost:20128` | Server-side internal base URL |
+| `CLOUD_URL` | `https://omniroute.dev` | Cloud sync endpoint base URL |
+| `API_KEY_SECRET` | `endpoint-proxy-api-key-secret` | HMAC secret for generated API keys |
+| `REQUIRE_API_KEY` | `false` | Enforce Bearer API key on `/v1/*` |
+| `ALLOW_API_KEY_REVEAL` | `false` | Allow Api Manager to copy full API keys on demand |
+| `DISABLE_SQLITE_AUTO_BACKUP` | `false` | Disable automatic SQLite snapshots before writes/import/restore; manual backups still work |
+| `ENABLE_REQUEST_LOGS` | `false` | Enables request/response logs |
+| `AUTH_COOKIE_SECURE` | `false` | Force `Secure` auth cookie (behind HTTPS reverse proxy) |
+| `CLOUDFLARED_BIN` | unset | Use an existing `cloudflared` binary instead of managed download |
+| `OMNIROUTE_MEMORY_MB` | `512` | Node.js heap limit in MB |
+| `PROMPT_CACHE_MAX_SIZE` | `50` | Max prompt cache entries |
+| `SEMANTIC_CACHE_MAX_SIZE` | `100` | Max semantic cache entries |
For the full environment variable reference, see the [README](../README.md).
@@ -598,6 +599,11 @@ curl -X POST http://localhost:20128/api/provider-models \
Or use Dashboard: **Providers → [Provider] → Custom Models**.
+Notes:
+
+- OpenRouter and OpenAI/Anthropic-compatible providers are managed from **Available Models** only. Manual add, import, and auto-sync all land in the same available-model list, so there is no separate Custom Models section for those providers.
+- The **Custom Models** section is intended for providers that do not expose managed available-model imports.
+
### Dedicated Provider Routes
Route requests directly to a specific provider with model validation:
@@ -642,6 +648,14 @@ Returns models grouped by provider with types (`chat`, `embedding`, `image`).
- Automatic background sync with timeout + fail-fast
- Prefer server-side `BASE_URL`/`CLOUD_URL` in production
+### Cloudflare Quick Tunnel
+
+- Available in **Dashboard → Endpoints** for Docker and other self-hosted deployments
+- Creates a temporary `https://*.trycloudflare.com` URL that forwards to your current OpenAI-compatible `/v1` endpoint
+- First enable installs `cloudflared` only when needed; later restarts reuse the same managed binary
+- Tunnel URLs are ephemeral and change every time you stop/start the tunnel
+- Set `CLOUDFLARED_BIN` if you prefer using a preinstalled `cloudflared` binary instead of the managed download
+
### LLM Gateway Intelligence (Phase 9)
- **Semantic Cache** — Auto-caches non-streaming, temperature=0 responses (bypass with `X-OmniRoute-No-Cache: true`)
@@ -757,11 +771,11 @@ OmniRoute implements provider-level resilience with four components:
Manage database backups in **Dashboard → Settings → System & Storage**.
-| Action | Description |
-| ------------------------ | ------------------------------------------------------------------------------------------------------------------------------ |
-| **Export Database** | Downloads the current SQLite database as a `.sqlite` file |
-| **Export All (.tar.gz)** | Downloads a full backup archive including: database, settings, combos, provider connections (no credentials), API key metadata |
-| **Import Database** | Upload a `.sqlite` file to replace the current database. A pre-import backup is automatically created |
+| Action | Description |
+| ------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------- |
+| **Export Database** | Downloads the current SQLite database as a `.sqlite` file |
+| **Export All (.tar.gz)** | Downloads a full backup archive including: database, settings, combos, provider connections (no credentials), API key metadata |
+| **Import Database** | Upload a `.sqlite` file to replace the current database. A pre-import backup is automatically created unless `DISABLE_SQLITE_AUTO_BACKUP=true` |
```bash
# API: Export database
@@ -787,10 +801,11 @@ curl -X POST http://localhost:20128/api/db-backups/import \
### Settings Dashboard
-The settings page is organized into 5 tabs for easy navigation:
+The settings page is organized into 6 tabs for easy navigation:
| Tab | Contents |
| -------------- | ---------------------------------------------------------------------------------------------- |
+| **General** | System storage tools, appearance settings, theme controls, and per-item sidebar visibility |
| **Security** | Login/Password settings, IP Access Control, API auth for `/models`, and Provider Blocking |
| **Routing** | Global routing strategy (6 options), wildcard model aliases, fallback chains, combo defaults |
| **Resilience** | Provider profiles, editable rate limits, circuit breaker status, policies & locked identifiers |
diff --git a/docs/i18n/de/docs/VM_DEPLOYMENT_GUIDE.md b/docs/i18n/de/docs/VM_DEPLOYMENT_GUIDE.md
new file mode 100644
index 0000000000..158a27774b
--- /dev/null
+++ b/docs/i18n/de/docs/VM_DEPLOYMENT_GUIDE.md
@@ -0,0 +1,403 @@
+# OmniRoute — Deployment Guide on VM with Cloudflare (Deutsch)
+
+🌐 **Languages:** 🇺🇸 [English](../../../../docs/VM_DEPLOYMENT_GUIDE.md) · 🇪🇸 [es](../../es/docs/VM_DEPLOYMENT_GUIDE.md) · 🇫🇷 [fr](../../fr/docs/VM_DEPLOYMENT_GUIDE.md) · 🇩🇪 [de](../../de/docs/VM_DEPLOYMENT_GUIDE.md) · 🇮🇹 [it](../../it/docs/VM_DEPLOYMENT_GUIDE.md) · 🇷🇺 [ru](../../ru/docs/VM_DEPLOYMENT_GUIDE.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/VM_DEPLOYMENT_GUIDE.md) · 🇯🇵 [ja](../../ja/docs/VM_DEPLOYMENT_GUIDE.md) · 🇰🇷 [ko](../../ko/docs/VM_DEPLOYMENT_GUIDE.md) · 🇸🇦 [ar](../../ar/docs/VM_DEPLOYMENT_GUIDE.md) · 🇮🇳 [in](../../in/docs/VM_DEPLOYMENT_GUIDE.md) · 🇹🇭 [th](../../th/docs/VM_DEPLOYMENT_GUIDE.md) · 🇻🇳 [vi](../../vi/docs/VM_DEPLOYMENT_GUIDE.md) · 🇮🇩 [id](../../id/docs/VM_DEPLOYMENT_GUIDE.md) · 🇲🇾 [ms](../../ms/docs/VM_DEPLOYMENT_GUIDE.md) · 🇳🇱 [nl](../../nl/docs/VM_DEPLOYMENT_GUIDE.md) · 🇵🇱 [pl](../../pl/docs/VM_DEPLOYMENT_GUIDE.md) · 🇸🇪 [sv](../../sv/docs/VM_DEPLOYMENT_GUIDE.md) · 🇳🇴 [no](../../no/docs/VM_DEPLOYMENT_GUIDE.md) · 🇩🇰 [da](../../da/docs/VM_DEPLOYMENT_GUIDE.md) · 🇫🇮 [fi](../../fi/docs/VM_DEPLOYMENT_GUIDE.md) · 🇵🇹 [pt](../../pt/docs/VM_DEPLOYMENT_GUIDE.md) · 🇷🇴 [ro](../../ro/docs/VM_DEPLOYMENT_GUIDE.md) · 🇭🇺 [hu](../../hu/docs/VM_DEPLOYMENT_GUIDE.md) · 🇧🇬 [bg](../../bg/docs/VM_DEPLOYMENT_GUIDE.md) · 🇸🇰 [sk](../../sk/docs/VM_DEPLOYMENT_GUIDE.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/VM_DEPLOYMENT_GUIDE.md) · 🇮🇱 [he](../../he/docs/VM_DEPLOYMENT_GUIDE.md) · 🇵🇭 [phi](../../phi/docs/VM_DEPLOYMENT_GUIDE.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/VM_DEPLOYMENT_GUIDE.md) · 🇨🇿 [cs](../../cs/docs/VM_DEPLOYMENT_GUIDE.md)
+
+---
+
+Complete guide to install and configure OmniRoute on a VM (VPS) with domain managed via Cloudflare.
+
+---
+
+## Prerequisites
+
+| Item | Minimum | Recommended |
+| ---------- | ------------------------ | ---------------- |
+| **CPU** | 1 vCPU | 2 vCPU |
+| **RAM** | 1 GB | 2 GB |
+| **Disk** | 10 GB SSD | 25 GB SSD |
+| **OS** | Ubuntu 22.04 LTS | Ubuntu 24.04 LTS |
+| **Domain** | Registered on Cloudflare | — |
+| **Docker** | Docker Engine 24+ | Docker 27+ |
+
+**Tested providers**: Akamai (Linode), DigitalOcean, Vultr, Hetzner, AWS Lightsail.
+
+---
+
+## 1. Configure the VM
+
+### 1.1 Create the instance
+
+On your preferred VPS provider:
+
+- Choose Ubuntu 24.04 LTS
+- Select the minimum plan (1 vCPU / 1 GB RAM)
+- Set a strong root password or configure SSH key
+- Note the **public IP** (e.g., `203.0.113.10`)
+
+### 1.2 Connect via SSH
+
+```bash
+ssh root@203.0.113.10
+```
+
+### 1.3 Update the system
+
+```bash
+apt update && apt upgrade -y
+```
+
+### 1.4 Install Docker
+
+```bash
+# Install dependencies
+apt install -y ca-certificates curl gnupg
+
+# Add official Docker repository
+install -m 0755 -d /etc/apt/keyrings
+curl -fsSL https://download.docker.com/linux/ubuntu/gpg | gpg --dearmor -o /etc/apt/keyrings/docker.gpg
+chmod a+r /etc/apt/keyrings/docker.gpg
+echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu $ (. /etc/os-release && echo “$VERSION_CODENAME”) stable" | tee /etc/apt/sources.list.d/docker.list > /dev/null
+apt update
+apt install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin
+```
+
+### 1.5 Install nginx
+
+```bash
+apt install -y nginx
+```
+
+### 1.6 Configure Firewall (UFW)
+
+```bash
+ufw default deny incoming
+ufw default allow outgoing
+ufw allow 22/tcp # SSH
+ufw allow 80/tcp # HTTP (redirect)
+ufw allow 443/tcp # HTTPS
+ufw enable
+```
+
+> **Tip**: For maximum security, restrict ports 80 and 443 to Cloudflare IPs only. See the [Advanced Security](#advanced-security) section.
+
+---
+
+## 2. Install OmniRoute
+
+### 2.1 Create configuration directory
+
+```bash
+mkdir -p /opt/omniroute
+```
+
+### 2.2 Create environment variables file
+
+```bash
+cat > /opt/omniroute/.env << ‘EOF’
+# === Security ===
+JWT_SECRET=CHANGE-TO-A-UNIQUE-64-CHAR-SECRET-KEY
+INITIAL_PASSWORD=YourSecurePassword123!
+API_KEY_SECRET=REPLACE-WITH-ANOTHER-SECRET-KEY
+STORAGE_ENCRYPTION_KEY=REPLACE-WITH-THIRD-SECRET-KEY
+STORAGE_ENCRYPTION_KEY_VERSION=v1
+MACHINE_ID_SALT=CHANGE-TO-A-UNIQUE-SALT
+
+# === App ===
+PORT=20128
+NODE_ENV=production
+HOSTNAME=0.0.0.0
+DATA_DIR=/app/data
+STORAGE_DRIVER=sqlite
+ENABLE_REQUEST_LOGS=true
+AUTH_COOKIE_SECURE=false
+REQUIRE_API_KEY=false
+
+# === Domain (change to your domain) ===
+BASE_URL=https://llms.seudominio.com
+NEXT_PUBLIC_BASE_URL=https://llms.seudominio.com
+
+# === Cloud Sync (optional) ===
+# CLOUD_URL=https://cloud.omniroute.online
+# NEXT_PUBLIC_CLOUD_URL=https://cloud.omniroute.online
+EOF
+```
+
+> ⚠️ **IMPORTANT**: Generate unique secret keys! Use `openssl rand -hex 32` for each key.
+
+### 2.3 Start the container
+
+```bash
+docker pull diegosouzapw/omniroute:latest
+
+docker run -d \
+ --name omniroute \
+ --restart unless-stopped \
+ --env-file /opt/omniroute/.env \
+ -p 20128:20128 \
+ -v omniroute-data:/app/data \
+ diegosouzapw/omniroute:latest
+```
+
+### 2.4 Verify that it is running
+
+```bash
+docker ps | grep omniroute
+docker logs omniroute --tail 20
+```
+
+It should display: `[DB] SQLite database ready` and `listening on port 20128`.
+
+---
+
+## 3. Configure nginx (Reverse Proxy)
+
+### 3.1 Generate SSL certificate (Cloudflare Origin)
+
+In the Cloudflare dashboard:
+
+1. Go to **SSL/TLS → Origin Server**
+2. Click **Create Certificate**
+3. Keep the defaults (15 years, \*.yourdomain.com)
+4. Copy the **Origin Certificate** and the **Private Key**
+
+```bash
+mkdir -p /etc/nginx/ssl
+
+# Paste the certificate
+nano /etc/nginx/ssl/origin.crt
+
+# Paste the private key
+nano /etc/nginx/ssl/origin.key
+
+chmod 600 /etc/nginx/ssl/origin.key
+```
+
+### 3.2 Nginx Configuration
+
+```bash
+cat > /etc/nginx/sites-available/omniroute << ‘NGINX’
+# Default server — blocks direct access via IP
+server {
+ listen 80 default_server;
+ listen [::]:80 default_server;
+ listen 443 ssl default_server;
+ listen [::]:443 ssl default_server;
+ ssl_certificate /etc/nginx/ssl/origin.crt;
+ ssl_certificate_key /etc/nginx/ssl/origin.key;
+ server_name _;
+ return 444;
+}
+
+# OmniRoute — HTTPS
+server {
+ listen 443 ssl;
+ listen [::]:443 ssl;
+ server_name llms.yourdomain.com; # Change to your domain
+
+ ssl_certificate /etc/nginx/ssl/origin.crt;
+ ssl_certificate_key /etc/nginx/ssl/origin.key;
+ ssl_protocols TLSv1.2 TLSv1.3;
+
+ client_max_body_size 100M;
+
+ location / {
+ proxy_pass http://127.0.0.1:20128;
+ proxy_set_header Host $host;
+ proxy_set_header X-Real-IP $remote_addr;
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
+ proxy_set_header X-Forwarded-Proto $scheme;
+
+ # WebSocket support
+ proxy_http_version 1.1;
+ proxy_set_header Upgrade $http_upgrade;
+ proxy_set_header Connection “upgrade”;
+
+ # SSE (Server-Sent Events) — streaming AI responses
+ proxy_buffering off;
+ proxy_cache off;
+ proxy_read_timeout 300s;
+ proxy_send_timeout 300s;
+ }
+}
+
+# HTTP → HTTPS redirect
+server {
+ listen 80;
+ listen [::]:80;
+ server_name llms.yourdomain.com;
+ return 301 https://$server_name$request_uri;
+}
+NGINX
+```
+
+### 3.3 Enable and Test
+
+```bash
+# Remove default configuration
+rm -f /etc/nginx/sites-enabled/default
+
+# Enable OmniRoute
+ln -sf /etc/nginx/sites-available/omniroute /etc/nginx/sites-enabled/omniroute
+
+# Test and reload
+nginx -t && systemctl reload nginx
+```
+
+---
+
+## 4. Configure Cloudflare DNS
+
+### 4.1 Add DNS record
+
+In the Cloudflare dashboard → DNS:
+
+| Type | Name | Content | Proxy |
+| ---- | ------ | ---------------------- | ---------- |
+| A | `llms` | `203.0.113.10` (VM IP) | ✅ Proxied |
+
+### 4.2 Configure SSL
+
+Under **SSL/TLS → Overview**:
+
+- Mode: **Full (Strict)**
+
+Under **SSL/TLS → Edge Certificates**:
+
+- Always Use HTTPS: ✅ On
+- Minimum TLS Version: TLS 1.2
+- Automatic HTTPS Rewrites: ✅ On
+
+### 4.3 Testing
+
+```bash
+curl -sI https://llms.seudominio.com/health
+# Should return HTTP/2 200
+```
+
+---
+
+## 5. Operations and Maintenance
+
+### Upgrade to a new version
+
+```bash
+docker pull diegosouzapw/omniroute:latest
+docker stop omniroute && docker rm omniroute
+docker run -d --name omniroute --restart unless-stopped \
+ --env-file /opt/omniroute/.env \
+ -p 20128:20128 \
+ -v omniroute-data:/app/data \
+ diegosouzapw/omniroute:latest
+```
+
+### View logs
+
+```bash
+docker logs -f omniroute # Real-time stream
+docker logs omniroute --tail 50 # Last 50 lines
+```
+
+### Manual database backup
+
+```bash
+# Copy data from the volume to the host
+docker cp omniroute:/app/data ./backup-$(date +%F)
+
+# Or compress the entire volume
+docker run --rm -v omniroute-data:/data -v $(pwd):/backup \
+ alpine tar czf /backup/omniroute-data-$(date +%F).tar.gz /data
+```
+
+### Restore from backup
+
+```bash
+docker stop omniroute
+docker run --rm -v omniroute-data:/data -v $(pwd):/backup \
+ alpine sh -c “rm -rf /data/* && tar xzf /backup/omniroute-data-YYYY-MM-DD.tar.gz -C /”
+docker start omniroute
+```
+
+---
+
+## 6. Advanced Security
+
+### Restrict nginx to Cloudflare IPs
+
+```bash
+cat > /etc/nginx/cloudflare-ips.conf << ‘CF’
+# Cloudflare IPv4 ranges — update periodically
+# https://www.cloudflare.com/ips-v4/
+set_real_ip_from 173.245.48.0/20;
+set_real_ip_from 103.21.244.0/22;
+set_real_ip_from 103.22.200.0/22;
+set_real_ip_from 103.31.4.0/22;
+set_real_ip_from 141.101.64.0/18;
+set_real_ip_from 108.162.192.0/18;
+set_real_ip_from 190.93.240.0/20;
+set_real_ip_from 188.114.96.0/20;
+set_real_ip_from 197.234.240.0/22;
+set_real_ip_from 198.41.128.0/17;
+set_real_ip_from 162.158.0.0/15;
+set_real_ip_from 104.16.0.0/13;
+set_real_ip_from 104.24.0.0/14;
+set_real_ip_from 172.64.0.0/13;
+set_real_ip_from 131.0.72.0/22;
+real_ip_header CF-Connecting-IP;
+CF
+```
+
+Add the following to `nginx.conf` inside the `http {}` block:
+
+```nginx
+include /etc/nginx/cloudflare-ips.conf;
+```
+
+### Install fail2ban
+
+```bash
+apt install -y fail2ban
+systemctl enable fail2ban
+systemctl start fail2ban
+
+# Check status
+fail2ban-client status sshd
+```
+
+### Block direct access to the Docker port
+
+```bash
+# Prevent direct external access to port 20128
+iptables -I DOCKER-USER -p tcp --dport 20128 -j DROP
+iptables -I DOCKER-USER -i lo -p tcp --dport 20128 -j ACCEPT
+
+# Persist the rules
+apt install -y iptables-persistent
+netfilter-persistent save
+```
+
+---
+
+## 7. Deploy to Cloudflare Workers (Optional)
+
+For remote access via Cloudflare Workers (without exposing the VM directly):
+
+```bash
+# In the local repository
+cd omnirouteCloud
+npm install
+npx wrangler login
+npx wrangler deploy
+```
+
+See the full documentation at [omnirouteCloud/README.md](../omnirouteCloud/README.md).
+
+---
+
+## Port Summary
+
+| Port | Service | Access |
+| ----- | ----------- | -------------------------- |
+| 22 | SSH | Public (with fail2ban) |
+| 80 | nginx HTTP | Redirect → HTTPS |
+| 443 | nginx HTTPS | Via Cloudflare Proxy |
+| 20128 | OmniRoute | Localhost only (via nginx) |
diff --git a/docs/i18n/de/src/lib/a2a/README.md b/docs/i18n/de/src/lib/a2a/README.md
new file mode 100644
index 0000000000..4946f4b98b
--- /dev/null
+++ b/docs/i18n/de/src/lib/a2a/README.md
@@ -0,0 +1,752 @@
+# OmniRoute A2A Server (Deutsch)
+
+🌐 **Languages:** 🇺🇸 [English](../../../../../../src/lib/a2a/README.md) · 🇪🇸 [es](../../../../es/src/lib/a2a/README.md) · 🇫🇷 [fr](../../../../fr/src/lib/a2a/README.md) · 🇩🇪 [de](../../../../de/src/lib/a2a/README.md) · 🇮🇹 [it](../../../../it/src/lib/a2a/README.md) · 🇷🇺 [ru](../../../../ru/src/lib/a2a/README.md) · 🇨🇳 [zh-CN](../../../../zh-CN/src/lib/a2a/README.md) · 🇯🇵 [ja](../../../../ja/src/lib/a2a/README.md) · 🇰🇷 [ko](../../../../ko/src/lib/a2a/README.md) · 🇸🇦 [ar](../../../../ar/src/lib/a2a/README.md) · 🇮🇳 [in](../../../../in/src/lib/a2a/README.md) · 🇹🇭 [th](../../../../th/src/lib/a2a/README.md) · 🇻🇳 [vi](../../../../vi/src/lib/a2a/README.md) · 🇮🇩 [id](../../../../id/src/lib/a2a/README.md) · 🇲🇾 [ms](../../../../ms/src/lib/a2a/README.md) · 🇳🇱 [nl](../../../../nl/src/lib/a2a/README.md) · 🇵🇱 [pl](../../../../pl/src/lib/a2a/README.md) · 🇸🇪 [sv](../../../../sv/src/lib/a2a/README.md) · 🇳🇴 [no](../../../../no/src/lib/a2a/README.md) · 🇩🇰 [da](../../../../da/src/lib/a2a/README.md) · 🇫🇮 [fi](../../../../fi/src/lib/a2a/README.md) · 🇵🇹 [pt](../../../../pt/src/lib/a2a/README.md) · 🇷🇴 [ro](../../../../ro/src/lib/a2a/README.md) · 🇭🇺 [hu](../../../../hu/src/lib/a2a/README.md) · 🇧🇬 [bg](../../../../bg/src/lib/a2a/README.md) · 🇸🇰 [sk](../../../../sk/src/lib/a2a/README.md) · 🇺🇦 [uk-UA](../../../../uk-UA/src/lib/a2a/README.md) · 🇮🇱 [he](../../../../he/src/lib/a2a/README.md) · 🇵🇭 [phi](../../../../phi/src/lib/a2a/README.md) · 🇧🇷 [pt-BR](../../../../pt-BR/src/lib/a2a/README.md) · 🇨🇿 [cs](../../../../cs/src/lib/a2a/README.md)
+
+---
+
+> **Agent-to-Agent Protocol v0.3** — Enables any AI agent to use OmniRoute as an intelligent routing agent via JSON-RPC 2.0.
+
+The A2A Server exposes OmniRoute as a **first-class agent** that other agents can discover, delegate tasks to, and collaborate with using the [A2A Protocol](https://google.github.io/A2A/).
+
+---
+
+## Architektur
+
+```
+┌──────────────────────────────────────────────────────────────────┐
+│ Orchestrator Agent │
+│ (LangChain, CrewAI, AutoGen, Custom Agent) │
+└──────────────────────┬───────────────────────────────────────────┘
+ │ 1. GET /.well-known/agent.json (discover)
+ │ 2. POST /a2a (JSON-RPC 2.0)
+ ▼
+┌──────────────────────────────────────────────────────────────────┐
+│ OmniRoute A2A Server │
+│ ┌────────────────┐ ┌────────────────┐ ┌───────────────────┐ │
+│ │ Task Manager │ │ Skill Engine │ │ SSE Streaming │ │
+│ │ (lifecycle) │──│ (registry) │──│ (real-time) │ │
+│ └────────────────┘ └────────┬───────┘ └───────────────────┘ │
+│ │ │
+│ Skills: │ │
+│ ├─ smart-routing ──────────┤ ┌────────────────────────────┐ │
+│ └─ quota-management ───────┘ │ Routing Decision Logger │ │
+│ └────────────────────────────┘ │
+└──────────────────────────────────────────────────────────────────┘
+ │
+ ▼ OmniRoute Gateway (internal)
+ /v1/chat/completions, /api/combos, /api/usage/quota
+```
+
+---
+
+## Schnellstart
+
+### Agent Discovery
+
+Every A2A-compatible agent exposes an **Agent Card** at `/.well-known/agent.json`:
+
+```bash
+curl http://localhost:20128/.well-known/agent.json
+```
+
+**Response:**
+
+```json
+{
+ "name": "OmniRoute",
+ "description": "Intelligent AI gateway with auto-routing across 50+ providers",
+ "url": "http://localhost:20128/a2a",
+ "version": "1.8.1",
+ "capabilities": {
+ "streaming": true,
+ "pushNotifications": false
+ },
+ "skills": [
+ {
+ "id": "smart-routing",
+ "name": "Smart Routing",
+ "description": "Routes prompts through OmniRoute intelligent pipeline",
+ "tags": ["routing", "llm", "multi-provider", "cost-optimization"],
+ "examples": [
+ "Write a hello world in Python",
+ "Explain quantum computing using the cheapest provider"
+ ]
+ },
+ {
+ "id": "quota-management",
+ "name": "Quota Management",
+ "description": "Natural-language queries about provider quotas",
+ "tags": ["quota", "analytics", "cost"],
+ "examples": [
+ "Which provider has the most quota remaining?",
+ "Suggest a free combo for coding"
+ ]
+ }
+ ],
+ "authentication": {
+ "schemes": ["bearer"],
+ "apiKeyHeader": "Authorization"
+ }
+}
+```
+
+---
+
+## JSON-RPC 2.0 Methods
+
+### `message/send` — Synchronous Execution
+
+Send a message to a skill and receive the complete response.
+
+```bash
+curl -X POST http://localhost:20128/a2a \
+ -H "Content-Type: application/json" \
+ -H "Authorization: Bearer YOUR_KEY" \
+ -d '{
+ "jsonrpc": "2.0",
+ "id": "1",
+ "method": "message/send",
+ "params": {
+ "skill": "smart-routing",
+ "messages": [{"role": "user", "content": "Write a Python hello world"}],
+ "metadata": {"model": "auto", "combo": "fast-coding"}
+ }
+ }'
+```
+
+**Response:**
+
+```json
+{
+ "jsonrpc": "2.0",
+ "id": "1",
+ "result": {
+ "task": { "id": "a1b2c3d4-...", "state": "completed" },
+ "artifacts": [{ "type": "text", "content": "print('Hello, World!')" }],
+ "metadata": {
+ "routing_explanation": "Selected claude-sonnet via provider \"anthropic\" (latency: 1200ms, cost: $0.0030)",
+ "cost_envelope": { "estimated": 0.005, "actual": 0.003, "currency": "USD" },
+ "resilience_trace": [
+ { "event": "primary_selected", "provider": "anthropic", "timestamp": "2026-03-04T..." }
+ ],
+ "policy_verdict": { "allowed": true, "reason": "within budget and quota limits" }
+ }
+ }
+}
+```
+
+### `message/stream` — SSE Streaming
+
+Same as `message/send` but returns Server-Sent Events for real-time streaming.
+
+```bash
+curl -N -X POST http://localhost:20128/a2a \
+ -H "Content-Type: application/json" \
+ -H "Authorization: Bearer YOUR_KEY" \
+ -d '{
+ "jsonrpc": "2.0",
+ "id": "1",
+ "method": "message/stream",
+ "params": {
+ "skill": "smart-routing",
+ "messages": [{"role": "user", "content": "Explain quantum computing"}]
+ }
+ }'
+```
+
+**SSE Events:**
+
+```
+data: {"jsonrpc":"2.0","method":"message/stream","params":{"task":{"id":"...","state":"working"},"chunk":{"type":"text","content":"Quantum computing..."}}}
+
+: heartbeat 2026-03-04T21:00:00Z
+
+data: {"jsonrpc":"2.0","method":"message/stream","params":{"task":{"id":"...","state":"completed"},"metadata":{...}}}
+```
+
+### `tasks/get` — Query Task Status
+
+```bash
+curl -X POST http://localhost:20128/a2a \
+ -H "Content-Type: application/json" \
+ -H "Authorization: Bearer YOUR_KEY" \
+ -d '{"jsonrpc":"2.0","id":"2","method":"tasks/get","params":{"taskId":"TASK_UUID"}}'
+```
+
+### `tasks/cancel` — Cancel a Running Task
+
+```bash
+curl -X POST http://localhost:20128/a2a \
+ -H "Content-Type: application/json" \
+ -H "Authorization: Bearer YOUR_KEY" \
+ -d '{"jsonrpc":"2.0","id":"3","method":"tasks/cancel","params":{"taskId":"TASK_UUID"}}'
+```
+
+---
+
+## Skills Reference
+
+### `smart-routing`
+
+Routes prompts through OmniRoute's intelligent pipeline with full observability.
+
+**Parameters (in `metadata`):**
+
+| Parameter | Type | Default | Description |
+| --------- | -------- | ------------ | ---------------------------------------------------------------------------------------- |
+| `model` | `string` | `"auto"` | Target model (e.g., `claude-sonnet-4`, `gpt-4o`, `auto`) |
+| `combo` | `string` | active combo | Specific combo to route through |
+| `budget` | `number` | none | Maximum cost in USD for this request |
+| `role` | `string` | none | Task role hint: `coding`, `review`, `planning`, `analysis`, `debugging`, `documentation` |
+
+**Returns:**
+
+| Field | Description |
+| ------------------------------ | --------------------------------------------------------- |
+| `artifacts[].content` | The LLM response text |
+| `metadata.routing_explanation` | Human-readable explanation of routing decision |
+| `metadata.cost_envelope` | Estimated vs actual cost with currency |
+| `metadata.resilience_trace` | Array of events (primary_selected, fallback_needed, etc.) |
+| `metadata.policy_verdict` | Whether the request was allowed and why |
+
+### `quota-management`
+
+Answers natural-language queries about provider quotas.
+
+**Query types (inferred from message content):**
+
+| Query Pattern | Response Type |
+| ---------------------------------------------- | -------------------------------------------------------- |
+| Contains `"ranking"`, `"most quota"`, `"best"` | Providers ranked by remaining quota |
+| Contains `"free"`, `"suggest"` | Lists free combos or suggests free-tier providers |
+| Default | Full quota summary with warnings for low-quota providers |
+
+---
+
+## Task Lifecycle
+
+```
+submitted ──→ working ──→ completed
+ ──→ failed
+ ──────────→ cancelled
+```
+
+| State | Description |
+| ----------- | ----------------------------------------------------- |
+| `submitted` | Task created, queued for execution |
+| `working` | Skill handler is executing |
+| `completed` | Execution succeeded, artifacts available |
+| `failed` | Execution failed or task expired (TTL: 5 min default) |
+| `cancelled` | Cancelled by client via `tasks/cancel` |
+
+- Terminal states: `completed`, `failed`, `cancelled` (no further transitions)
+- Expired tasks in `submitted` or `working` are auto-marked as `failed`
+- Tasks are garbage-collected after 2× TTL
+
+---
+
+## Client Examples
+
+### Python — Orchestrator Agent
+
+```python
+"""
+A2A Client — Python example.
+Discovers OmniRoute agent, sends a task, and processes the result.
+"""
+import requests
+import json
+
+BASE_URL = "http://localhost:20128"
+API_KEY = "your-api-key"
+HEADERS = {
+ "Content-Type": "application/json",
+ "Authorization": f"Bearer {API_KEY}",
+}
+
+# 1. Discover agent capabilities
+agent_card = requests.get(f"{BASE_URL}/.well-known/agent.json").json()
+print(f"Agent: {agent_card['name']} v{agent_card['version']}")
+print(f"Skills: {[s['id'] for s in agent_card['skills']]}")
+
+# 2. Send a smart-routing task
+response = requests.post(f"{BASE_URL}/a2a", headers=HEADERS, json={
+ "jsonrpc": "2.0",
+ "id": "task-1",
+ "method": "message/send",
+ "params": {
+ "skill": "smart-routing",
+ "messages": [{"role": "user", "content": "Write a Python quicksort implementation"}],
+ "metadata": {
+ "model": "auto",
+ "combo": "fast-coding",
+ "budget": 0.10,
+ }
+ }
+})
+result = response.json()["result"]
+print(f"\n📝 Response: {result['artifacts'][0]['content'][:200]}...")
+print(f"🔀 Routing: {result['metadata']['routing_explanation']}")
+print(f"💰 Cost: ${result['metadata']['cost_envelope']['actual']}")
+print(f"🛡️ Policy: {result['metadata']['policy_verdict']['reason']}")
+
+# 3. Query quota status
+quota_resp = requests.post(f"{BASE_URL}/a2a", headers=HEADERS, json={
+ "jsonrpc": "2.0",
+ "id": "task-2",
+ "method": "message/send",
+ "params": {
+ "skill": "quota-management",
+ "messages": [{"role": "user", "content": "Which provider has the most quota remaining?"}],
+ }
+})
+quota_result = quota_resp.json()["result"]
+print(f"\n📊 Quota: {quota_result['artifacts'][0]['content']}")
+```
+
+### TypeScript — Multi-Agent Orchestrator
+
+```typescript
+/**
+ * A2A Client — TypeScript example.
+ * Shows agent discovery, task delegation, and streaming.
+ */
+
+const BASE_URL = "http://localhost:20128";
+const API_KEY = "your-api-key";
+
+interface JsonRpcResponse {
+ jsonrpc: "2.0";
+ id: string | number;
+ result?: T;
+ error?: { code: number; message: string };
+}
+
+async function a2aCall(method: string, params: Record): Promise {
+ const resp = await fetch(`${BASE_URL}/a2a`, {
+ method: "POST",
+ headers: {
+ "Content-Type": "application/json",
+ Authorization: `Bearer ${API_KEY}`,
+ },
+ body: JSON.stringify({
+ jsonrpc: "2.0",
+ id: `${method}-${Date.now()}`,
+ method,
+ params,
+ }),
+ });
+ const json: JsonRpcResponse = await resp.json();
+ if (json.error) throw new Error(`[${json.error.code}] ${json.error.message}`);
+ return json.result!;
+}
+
+// ── Agent Discovery ──
+const agentCard = await fetch(`${BASE_URL}/.well-known/agent.json`).then((r) => r.json());
+console.log(`Connected to: ${agentCard.name} (${agentCard.skills.length} skills)`);
+
+// ── Smart Routing: Send a coding task ──
+const routingResult = await a2aCall("message/send", {
+ skill: "smart-routing",
+ messages: [{ role: "user", content: "Implement a Redis cache wrapper in TypeScript" }],
+ metadata: { model: "claude-sonnet-4", role: "coding" },
+});
+console.log("Response:", routingResult.artifacts[0].content);
+console.log("Provider:", routingResult.metadata.routing_explanation);
+
+// ── Quota Management: Find free alternatives ──
+const quotaResult = await a2aCall("message/send", {
+ skill: "quota-management",
+ messages: [{ role: "user", content: "Suggest free combos for documentation" }],
+});
+console.log("Free combos:", quotaResult.artifacts[0].content);
+
+// ── Streaming: Real-time response ──
+const streamResp = await fetch(`${BASE_URL}/a2a`, {
+ method: "POST",
+ headers: {
+ "Content-Type": "application/json",
+ Authorization: `Bearer ${API_KEY}`,
+ },
+ body: JSON.stringify({
+ jsonrpc: "2.0",
+ id: "stream-1",
+ method: "message/stream",
+ params: {
+ skill: "smart-routing",
+ messages: [{ role: "user", content: "Explain microservices architecture" }],
+ },
+ }),
+});
+
+const reader = streamResp.body!.getReader();
+const decoder = new TextDecoder();
+while (true) {
+ const { done, value } = await reader.read();
+ if (done) break;
+ const chunk = decoder.decode(value);
+ for (const line of chunk.split("\n")) {
+ if (line.startsWith("data: ")) {
+ const event = JSON.parse(line.slice(6));
+ if (event.params.chunk) {
+ process.stdout.write(event.params.chunk.content);
+ }
+ if (event.params.task.state === "completed") {
+ console.log("\n✅ Stream completed");
+ }
+ }
+ }
+}
+```
+
+### Python — LangChain A2A Integration
+
+```python
+"""
+LangChain integration — Use OmniRoute A2A as a custom LLM.
+"""
+from langchain.llms.base import BaseLLM
+from langchain.schema import LLMResult, Generation
+import requests
+from typing import List, Optional
+
+class OmniRouteA2A(BaseLLM):
+ base_url: str = "http://localhost:20128"
+ api_key: str = ""
+ model: str = "auto"
+ combo: Optional[str] = None
+
+ @property
+ def _llm_type(self) -> str:
+ return "omniroute-a2a"
+
+ def _call(self, prompt: str, stop: Optional[List[str]] = None, **kwargs) -> str:
+ response = requests.post(
+ f"{self.base_url}/a2a",
+ headers={
+ "Content-Type": "application/json",
+ "Authorization": f"Bearer {self.api_key}",
+ },
+ json={
+ "jsonrpc": "2.0",
+ "id": "langchain-1",
+ "method": "message/send",
+ "params": {
+ "skill": "smart-routing",
+ "messages": [{"role": "user", "content": prompt}],
+ "metadata": {
+ "model": self.model,
+ **({"combo": self.combo} if self.combo else {}),
+ },
+ },
+ },
+ )
+ result = response.json()["result"]
+ return result["artifacts"][0]["content"]
+
+ def _generate(self, prompts: List[str], stop=None, **kwargs) -> LLMResult:
+ return LLMResult(
+ generations=[[Generation(text=self._call(p, stop))] for p in prompts]
+ )
+
+# Usage
+llm = OmniRouteA2A(
+ base_url="http://localhost:20128",
+ api_key="your-key",
+ model="auto",
+ combo="fast-coding",
+)
+result = llm("Write a Python function to merge two sorted lists")
+print(result)
+```
+
+### Go — A2A Client
+
+```go
+package main
+
+import (
+ "bytes"
+ "encoding/json"
+ "fmt"
+ "io"
+ "net/http"
+)
+
+const baseURL = "http://localhost:20128"
+const apiKey = "your-api-key"
+
+type JsonRpcRequest struct {
+ Jsonrpc string `json:"jsonrpc"`
+ ID string `json:"id"`
+ Method string `json:"method"`
+ Params interface{} `json:"params"`
+}
+
+type JsonRpcResponse struct {
+ Jsonrpc string `json:"jsonrpc"`
+ ID string `json:"id"`
+ Result interface{} `json:"result"`
+ Error *struct {
+ Code int `json:"code"`
+ Message string `json:"message"`
+ } `json:"error"`
+}
+
+func a2aCall(method string, params interface{}) (*JsonRpcResponse, error) {
+ body, _ := json.Marshal(JsonRpcRequest{
+ Jsonrpc: "2.0",
+ ID: "go-1",
+ Method: method,
+ Params: params,
+ })
+
+ req, _ := http.NewRequest("POST", baseURL+"/a2a", bytes.NewReader(body))
+ req.Header.Set("Content-Type", "application/json")
+ req.Header.Set("Authorization", "Bearer "+apiKey)
+
+ resp, err := http.DefaultClient.Do(req)
+ if err != nil {
+ return nil, err
+ }
+ defer resp.Body.Close()
+ data, _ := io.ReadAll(resp.Body)
+
+ var result JsonRpcResponse
+ json.Unmarshal(data, &result)
+ return &result, nil
+}
+
+func main() {
+ // Discover agent
+ resp, _ := http.Get(baseURL + "/.well-known/agent.json")
+ defer resp.Body.Close()
+ body, _ := io.ReadAll(resp.Body)
+ fmt.Println("Agent Card:", string(body))
+
+ // Send smart-routing task
+ result, _ := a2aCall("message/send", map[string]interface{}{
+ "skill": "smart-routing",
+ "messages": []map[string]string{{"role": "user", "content": "Hello from Go!"}},
+ "metadata": map[string]interface{}{"model": "auto"},
+ })
+ out, _ := json.MarshalIndent(result.Result, "", " ")
+ fmt.Println("Result:", string(out))
+}
+```
+
+---
+
+## Use Cases
+
+### 🤖 Use Case 1: Multi-Agent Coding Pipeline
+
+An orchestrator agent delegates code generation to OmniRoute, then passes the output to a review agent.
+
+```python
+def coding_pipeline(task: str):
+ # Step 1: Generate code via OmniRoute A2A
+ code_result = a2a_send("smart-routing", [
+ {"role": "user", "content": f"Write production-quality code: {task}"}
+ ], metadata={"model": "auto", "role": "coding"})
+ code = code_result["artifacts"][0]["content"]
+
+ # Step 2: Review the code via OmniRoute A2A (different model)
+ review_result = a2a_send("smart-routing", [
+ {"role": "user", "content": f"Review this code for bugs and improvements:\n\n{code}"}
+ ], metadata={"model": "auto", "role": "review"})
+ review = review_result["artifacts"][0]["content"]
+
+ # Step 3: Check costs
+ print(f"Code cost: ${code_result['metadata']['cost_envelope']['actual']}")
+ print(f"Review cost: ${review_result['metadata']['cost_envelope']['actual']}")
+
+ return {"code": code, "review": review}
+```
+
+### 💡 Use Case 2: Quota-Aware Agent Swarm
+
+Multiple agents share quota through OmniRoute, using the quota skill to coordinate.
+
+```python
+async def quota_aware_agent(agent_name: str, task: str):
+ # Check quota before starting
+ quota = a2a_send("quota-management", [
+ {"role": "user", "content": "Which provider has the most quota remaining?"}
+ ])
+ print(f"[{agent_name}] {quota['artifacts'][0]['content']}")
+
+ # Send request with budget constraint
+ result = a2a_send("smart-routing", [
+ {"role": "user", "content": task}
+ ], metadata={"budget": 0.05})
+
+ policy = result["metadata"]["policy_verdict"]
+ if not policy["allowed"]:
+ print(f"[{agent_name}] ⚠️ Budget exceeded: {policy['reason']}")
+ # Fall back to free combo
+ quota = a2a_send("quota-management", [
+ {"role": "user", "content": "Suggest free combos"}
+ ])
+ print(f"[{agent_name}] Free alternatives: {quota['artifacts'][0]['content']}")
+
+ return result
+```
+
+### 📊 Use Case 3: Real-Time Streaming Dashboard
+
+A monitoring agent streams responses and displays progress in real-time.
+
+```typescript
+async function streamingDashboard(prompt: string) {
+ const response = await fetch(`${BASE_URL}/a2a`, {
+ method: "POST",
+ headers: { "Content-Type": "application/json", Authorization: `Bearer ${API_KEY}` },
+ body: JSON.stringify({
+ jsonrpc: "2.0",
+ id: "dash-1",
+ method: "message/stream",
+ params: { skill: "smart-routing", messages: [{ role: "user", content: prompt }] },
+ }),
+ });
+
+ let totalChunks = 0;
+ const reader = response.body!.getReader();
+ const decoder = new TextDecoder();
+
+ while (true) {
+ const { done, value } = await reader.read();
+ if (done) break;
+
+ for (const line of decoder.decode(value).split("\n")) {
+ if (line.startsWith("data: ")) {
+ const event = JSON.parse(line.slice(6));
+ const state = event.params.task.state;
+
+ if (state === "working" && event.params.chunk) {
+ totalChunks++;
+ process.stdout.write(
+ `\r[Chunk ${totalChunks}] ${event.params.chunk.content.slice(0, 50)}...`
+ );
+ }
+ if (state === "completed") {
+ const meta = event.params.metadata;
+ console.log(
+ `\n✅ Done | Cost: $${meta?.cost_envelope?.actual || 0} | Route: ${meta?.routing_explanation || "N/A"}`
+ );
+ }
+ if (state === "failed") {
+ console.error(`\n❌ Failed: ${event.params.metadata?.error}`);
+ }
+ }
+ }
+ }
+}
+```
+
+### 🔁 Use Case 4: Task Polling Pattern
+
+For long-running tasks, poll the task status instead of waiting synchronously.
+
+```python
+import time
+
+def poll_task(task_id: str, timeout: int = 60):
+ """Poll task status until completion or timeout."""
+ start = time.time()
+ while time.time() - start < timeout:
+ result = requests.post(f"{BASE_URL}/a2a", headers=HEADERS, json={
+ "jsonrpc": "2.0",
+ "id": "poll-1",
+ "method": "tasks/get",
+ "params": {"taskId": task_id},
+ }).json()
+
+ task = result["result"]["task"]
+ state = task["state"]
+ print(f" Task {task_id[:8]}... state={state}")
+
+ if state in ("completed", "failed", "cancelled"):
+ return task
+ time.sleep(2)
+
+ # Timeout — cancel the task
+ requests.post(f"{BASE_URL}/a2a", headers=HEADERS, json={
+ "jsonrpc": "2.0",
+ "id": "cancel-1",
+ "method": "tasks/cancel",
+ "params": {"taskId": task_id},
+ })
+ raise TimeoutError(f"Task {task_id} timed out after {timeout}s")
+```
+
+---
+
+## Error Codes
+
+| Code | Constant | Meaning |
+| ------ | ------------------------ | ---------------------------------------- |
+| -32700 | — | Parse error (invalid JSON) |
+| -32600 | `INVALID_REQUEST` | Invalid JSON-RPC request or unauthorized |
+| -32601 | `METHOD_NOT_FOUND` | Unknown method or skill |
+| -32602 | `INVALID_PARAMS` | Missing or invalid parameters |
+| -32603 | `INTERNAL_ERROR` | Skill execution failed |
+| -32001 | `TASK_NOT_FOUND` | Task ID not found |
+| -32002 | `TASK_ALREADY_COMPLETED` | Cannot modify a completed task |
+| -32003 | `UNAUTHORIZED` | Invalid or missing API key |
+| -32004 | `BUDGET_EXCEEDED` | Request exceeds configured budget |
+| -32005 | `PROVIDER_UNAVAILABLE` | No available providers |
+
+---
+
+## Authentication
+
+All `/a2a` requests require a Bearer token via the `Authorization` header:
+
+```
+Authorization: Bearer YOUR_OMNIROUTE_API_KEY
+```
+
+If no API key is configured on the server (`OMNIROUTE_API_KEY` is empty), authentication is bypassed.
+
+---
+
+## File Structure
+
+```
+src/lib/a2a/
+├── taskManager.ts # Task lifecycle (create/update/cancel/list), TTL, cleanup
+├── taskExecution.ts # Generic task executor with state management
+├── streaming.ts # SSE stream formatting, heartbeat, chunk/completion events
+├── routingLogger.ts # Routing decision logger (stats, history, retention)
+└── skills/
+ ├── smartRouting.ts # Smart routing skill (routes via /v1/chat/completions)
+ └── quotaManagement.ts # Quota management skill (natural-language quota queries)
+
+src/app/a2a/
+└── route.ts # Next.js API route handler (JSON-RPC 2.0 dispatch)
+
+open-sse/mcp-server/
+└── schemas/a2a.ts # Zod schemas (AgentCard, Task, JSON-RPC, SSE events)
+```
+
+---
+
+## Comparison: MCP vs A2A
+
+| Feature | MCP Server | A2A Server |
+| ----------------- | ---------------------------- | ------------------------------------------------- |
+| **Protocol** | Model Context Protocol | Agent-to-Agent Protocol v0.3 |
+| **Transport** | stdio / HTTP | HTTP (JSON-RPC 2.0) |
+| **Discovery** | Tool listing via MCP | `/.well-known/agent.json` |
+| **Granularity** | 16 individual tools | 2 high-level skills |
+| **Best for** | IDE agents (Cursor, VS Code) | Multi-agent systems (LangChain, CrewAI) |
+| **Streaming** | Not supported | SSE via `message/stream` |
+| **Task tracking** | No | Full lifecycle (submitted → completed) |
+| **Observability** | Audit log per tool call | Cost envelope + resilience trace + policy verdict |
+
+---
+
+## Lizenz
+
+Part of [OmniRoute](https://github.com/diegosouzapw/OmniRoute) — MIT License.
diff --git a/docs/i18n/es/A2A-SERVER.md b/docs/i18n/es/A2A-SERVER.md
deleted file mode 100644
index 01531ff482..0000000000
--- a/docs/i18n/es/A2A-SERVER.md
+++ /dev/null
@@ -1,200 +0,0 @@
-🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/A2A-SERVER.md) · 🇪🇸 [es](../es/A2A-SERVER.md) · 🇫🇷 [fr](../fr/A2A-SERVER.md) · 🇩🇪 [de](../de/A2A-SERVER.md) · 🇮🇹 [it](../it/A2A-SERVER.md) · 🇷🇺 [ru](../ru/A2A-SERVER.md) · 🇨🇳 [zh-CN](../zh-CN/A2A-SERVER.md) · 🇯🇵 [ja](../ja/A2A-SERVER.md) · 🇰🇷 [ko](../ko/A2A-SERVER.md) · 🇸🇦 [ar](../ar/A2A-SERVER.md) · 🇮🇳 [in](../in/A2A-SERVER.md) · 🇹🇭 [th](../th/A2A-SERVER.md) · 🇻🇳 [vi](../vi/A2A-SERVER.md) · 🇮🇩 [id](../id/A2A-SERVER.md) · 🇲🇾 [ms](../ms/A2A-SERVER.md) · 🇳🇱 [nl](../nl/A2A-SERVER.md) · 🇵🇱 [pl](../pl/A2A-SERVER.md) · 🇸🇪 [sv](../sv/A2A-SERVER.md) · 🇳🇴 [no](../no/A2A-SERVER.md) · 🇩🇰 [da](../da/A2A-SERVER.md) · 🇫🇮 [fi](../fi/A2A-SERVER.md) · 🇵🇹 [pt](../pt/A2A-SERVER.md) · 🇷🇴 [ro](../ro/A2A-SERVER.md) · 🇭🇺 [hu](../hu/A2A-SERVER.md) · 🇧🇬 [bg](../bg/A2A-SERVER.md) · 🇸🇰 [sk](../sk/A2A-SERVER.md) · 🇺🇦 [uk-UA](../uk-UA/A2A-SERVER.md) · 🇮🇱 [he](../he/A2A-SERVER.md) · 🇵🇭 [phi](../phi/A2A-SERVER.md)
-
----
-
-# OmniRoute A2A Server Documentation
-
-> Agent-to-Agent Protocol v0.3 — OmniRoute as an intelligent routing agent
-
-## Agent Discovery
-
-```bash
-curl http://localhost:20128/.well-known/agent.json
-```
-
-Returns the Agent Card describing OmniRoute's capabilities, skills, and authentication requirements.
-
----
-
-## Authentication
-
-All `/a2a` requests require an API key via the `Authorization` header:
-
-```
-Authorization: Bearer YOUR_OMNIROUTE_API_KEY
-```
-
-If no API key is configured on the server, authentication is bypassed.
-
----
-
-## JSON-RPC 2.0 Methods
-
-### `message/send` — Synchronous Execution
-
-Sends a message to a skill and waits for the complete response.
-
-```bash
-curl -X POST http://localhost:20128/a2a \
- -H "Content-Type: application/json" \
- -H "Authorization: Bearer YOUR_KEY" \
- -d '{
- "jsonrpc": "2.0",
- "id": "1",
- "method": "message/send",
- "params": {
- "skill": "smart-routing",
- "messages": [{"role": "user", "content": "Write a hello world in Python"}],
- "metadata": {"model": "auto", "combo": "fast-coding"}
- }
- }'
-```
-
-**Response:**
-
-```json
-{
- "jsonrpc": "2.0",
- "id": "1",
- "result": {
- "task": { "id": "uuid", "state": "completed" },
- "artifacts": [{ "type": "text", "content": "..." }],
- "metadata": {
- "routing_explanation": "Selected claude-sonnet via provider \"anthropic\" (latency: 1200ms, cost: $0.003)",
- "cost_envelope": { "estimated": 0.005, "actual": 0.003, "currency": "USD" },
- "resilience_trace": [
- { "event": "primary_selected", "provider": "anthropic", "timestamp": "..." }
- ],
- "policy_verdict": { "allowed": true, "reason": "within budget and quota limits" }
- }
- }
-}
-```
-
-### `message/stream` — SSE Streaming
-
-Same as `message/send` but returns Server-Sent Events for real-time streaming.
-
-```bash
-curl -N -X POST http://localhost:20128/a2a \
- -H "Content-Type: application/json" \
- -H "Authorization: Bearer YOUR_KEY" \
- -d '{
- "jsonrpc": "2.0",
- "id": "1",
- "method": "message/stream",
- "params": {
- "skill": "smart-routing",
- "messages": [{"role": "user", "content": "Explain quantum computing"}]
- }
- }'
-```
-
-**SSE Events:**
-
-```
-data: {"jsonrpc":"2.0","method":"message/stream","params":{"task":{"id":"...","state":"working"},"chunk":{"type":"text","content":"..."}}}
-
-: heartbeat 2026-03-03T17:00:00Z
-
-data: {"jsonrpc":"2.0","method":"message/stream","params":{"task":{"id":"...","state":"completed"},"metadata":{...}}}
-```
-
-### `tasks/get` — Query Task Status
-
-```bash
-curl -X POST http://localhost:20128/a2a \
- -H "Content-Type: application/json" \
- -H "Authorization: Bearer YOUR_KEY" \
- -d '{"jsonrpc":"2.0","id":"2","method":"tasks/get","params":{"taskId":"TASK_UUID"}}'
-```
-
-### `tasks/cancel` — Cancel a Task
-
-```bash
-curl -X POST http://localhost:20128/a2a \
- -H "Content-Type: application/json" \
- -H "Authorization: Bearer YOUR_KEY" \
- -d '{"jsonrpc":"2.0","id":"3","method":"tasks/cancel","params":{"taskId":"TASK_UUID"}}'
-```
-
----
-
-## Available Skills
-
-| Skill | Description |
-| :----------------- | :------------------------------------------------------------------------------------------------------------------------------ |
-| `smart-routing` | Routes prompts through OmniRoute's intelligent pipeline. Returns response with routing explanation, cost, and resilience trace. |
-| `quota-management` | Answers natural-language queries about provider quotas, suggests free combos, and provides quota rankings. |
-
----
-
-## Task Lifecycle
-
-```
-submitted → working → completed
- → failed
- → cancelled
-```
-
-- Tasks expire after 5 minutes (configurable)
-- Terminal states: `completed`, `failed`, `cancelled`
-- Event log tracks every state transition
-
----
-
-## Error Codes
-
-| Code | Meaning |
-| :----- | :----------------------------- |
-| -32700 | Parse error (invalid JSON) |
-| -32600 | Invalid request / Unauthorized |
-| -32601 | Method or skill not found |
-| -32602 | Invalid params |
-| -32603 | Internal error |
-
----
-
-## Integration Examples
-
-### Python (requests)
-
-```python
-import requests
-
-resp = requests.post("http://localhost:20128/a2a", json={
- "jsonrpc": "2.0", "id": "1",
- "method": "message/send",
- "params": {
- "skill": "smart-routing",
- "messages": [{"role": "user", "content": "Hello"}]
- }
-}, headers={"Authorization": "Bearer YOUR_KEY"})
-
-result = resp.json()["result"]
-print(result["artifacts"][0]["content"])
-print(result["metadata"]["routing_explanation"])
-```
-
-### TypeScript (fetch)
-
-```typescript
-const resp = await fetch("http://localhost:20128/a2a", {
- method: "POST",
- headers: {
- "Content-Type": "application/json",
- Authorization: "Bearer YOUR_KEY",
- },
- body: JSON.stringify({
- jsonrpc: "2.0",
- id: "1",
- method: "message/send",
- params: {
- skill: "smart-routing",
- messages: [{ role: "user", content: "Hello" }],
- },
- }),
-});
-const { result } = await resp.json();
-console.log(result.metadata.routing_explanation);
-```
diff --git a/docs/i18n/es/API_REFERENCE.md b/docs/i18n/es/API_REFERENCE.md
deleted file mode 100644
index b878605221..0000000000
--- a/docs/i18n/es/API_REFERENCE.md
+++ /dev/null
@@ -1,455 +0,0 @@
-🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/API_REFERENCE.md) · 🇪🇸 [es](../es/API_REFERENCE.md) · 🇫🇷 [fr](../fr/API_REFERENCE.md) · 🇩🇪 [de](../de/API_REFERENCE.md) · 🇮🇹 [it](../it/API_REFERENCE.md) · 🇷🇺 [ru](../ru/API_REFERENCE.md) · 🇨🇳 [zh-CN](../zh-CN/API_REFERENCE.md) · 🇯🇵 [ja](../ja/API_REFERENCE.md) · 🇰🇷 [ko](../ko/API_REFERENCE.md) · 🇸🇦 [ar](../ar/API_REFERENCE.md) · 🇮🇳 [in](../in/API_REFERENCE.md) · 🇹🇭 [th](../th/API_REFERENCE.md) · 🇻🇳 [vi](../vi/API_REFERENCE.md) · 🇮🇩 [id](../id/API_REFERENCE.md) · 🇲🇾 [ms](../ms/API_REFERENCE.md) · 🇳🇱 [nl](../nl/API_REFERENCE.md) · 🇵🇱 [pl](../pl/API_REFERENCE.md) · 🇸🇪 [sv](../sv/API_REFERENCE.md) · 🇳🇴 [no](../no/API_REFERENCE.md) · 🇩🇰 [da](../da/API_REFERENCE.md) · 🇫🇮 [fi](../fi/API_REFERENCE.md) · 🇵🇹 [pt](../pt/API_REFERENCE.md) · 🇷🇴 [ro](../ro/API_REFERENCE.md) · 🇭🇺 [hu](../hu/API_REFERENCE.md) · 🇧🇬 [bg](../bg/API_REFERENCE.md) · 🇸🇰 [sk](../sk/API_REFERENCE.md) · 🇺🇦 [uk-UA](../uk-UA/API_REFERENCE.md) · 🇮🇱 [he](../he/API_REFERENCE.md) · 🇵🇭 [phi](../phi/API_REFERENCE.md)
-
----
-
-# API Reference
-
-🌐 **Languages:** 🇺🇸 [English](API_REFERENCE.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/API_REFERENCE.md) | 🇪🇸 [Español](i18n/es/API_REFERENCE.md) | 🇫🇷 [Français](i18n/fr/API_REFERENCE.md) | 🇮🇹 [Italiano](i18n/it/API_REFERENCE.md) | 🇷🇺 [Русский](i18n/ru/API_REFERENCE.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/API_REFERENCE.md) | 🇩🇪 [Deutsch](i18n/de/API_REFERENCE.md) | 🇮🇳 [हिन्दी](i18n/in/API_REFERENCE.md) | 🇹🇭 [ไทย](i18n/th/API_REFERENCE.md) | 🇺🇦 [Українська](i18n/uk-UA/API_REFERENCE.md) | 🇸🇦 [العربية](i18n/ar/API_REFERENCE.md) | 🇯🇵 [日本語](i18n/ja/API_REFERENCE.md) | 🇻🇳 [Tiếng Việt](i18n/vi/API_REFERENCE.md) | 🇧🇬 [Български](i18n/bg/API_REFERENCE.md) | 🇩🇰 [Dansk](i18n/da/API_REFERENCE.md) | 🇫🇮 [Suomi](i18n/fi/API_REFERENCE.md) | 🇮🇱 [עברית](i18n/he/API_REFERENCE.md) | 🇭🇺 [Magyar](i18n/hu/API_REFERENCE.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/API_REFERENCE.md) | 🇰🇷 [한국어](i18n/ko/API_REFERENCE.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/API_REFERENCE.md) | 🇳🇱 [Nederlands](i18n/nl/API_REFERENCE.md) | 🇳🇴 [Norsk](i18n/no/API_REFERENCE.md) | 🇵🇹 [Português (Portugal)](i18n/pt/API_REFERENCE.md) | 🇷🇴 [Română](i18n/ro/API_REFERENCE.md) | 🇵🇱 [Polski](i18n/pl/API_REFERENCE.md) | 🇸🇰 [Slovenčina](i18n/sk/API_REFERENCE.md) | 🇸🇪 [Svenska](i18n/sv/API_REFERENCE.md) | 🇵🇭 [Filipino](i18n/phi/API_REFERENCE.md)
-
-Complete reference for all OmniRoute API endpoints.
-
----
-
-## Table of Contents
-
-- [Chat Completions](#chat-completions)
-- [Embeddings](#embeddings)
-- [Image Generation](#image-generation)
-- [List Models](#list-models)
-- [Compatibility Endpoints](#compatibility-endpoints)
-- [Semantic Cache](#semantic-cache)
-- [Dashboard & Management](#dashboard--management)
-- [Request Processing](#request-processing)
-- [Authentication](#authentication)
-
----
-
-## Chat Completions
-
-```bash
-POST /v1/chat/completions
-Authorization: Bearer your-api-key
-Content-Type: application/json
-
-{
- "model": "cc/claude-opus-4-6",
- "messages": [
- {"role": "user", "content": "Write a function to..."}
- ],
- "stream": true
-}
-```
-
-### Custom Headers
-
-| Header | Direction | Description |
-| ------------------------ | --------- | --------------------------------- |
-| `X-OmniRoute-No-Cache` | Request | Set to `true` to bypass cache |
-| `X-OmniRoute-Progress` | Request | Set to `true` for progress events |
-| `Idempotency-Key` | Request | Dedup key (5s window) |
-| `X-Request-Id` | Request | Alternative dedup key |
-| `X-OmniRoute-Cache` | Response | `HIT` or `MISS` (non-streaming) |
-| `X-OmniRoute-Idempotent` | Response | `true` if deduplicated |
-| `X-OmniRoute-Progress` | Response | `enabled` if progress tracking on |
-
----
-
-## Embeddings
-
-```bash
-POST /v1/embeddings
-Authorization: Bearer your-api-key
-Content-Type: application/json
-
-{
- "model": "nebius/Qwen/Qwen3-Embedding-8B",
- "input": "The food was delicious"
-}
-```
-
-Available providers: Nebius, OpenAI, Mistral, Together AI, Fireworks, NVIDIA.
-
-```bash
-# List all embedding models
-GET /v1/embeddings
-```
-
----
-
-## Image Generation
-
-```bash
-POST /v1/images/generations
-Authorization: Bearer your-api-key
-Content-Type: application/json
-
-{
- "model": "openai/dall-e-3",
- "prompt": "A beautiful sunset over mountains",
- "size": "1024x1024"
-}
-```
-
-Available providers: OpenAI (DALL-E), xAI (Grok Image), Together AI (FLUX), Fireworks AI.
-
-```bash
-# List all image models
-GET /v1/images/generations
-```
-
----
-
-## List Models
-
-```bash
-GET /v1/models
-Authorization: Bearer your-api-key
-
-→ Returns all chat, embedding, and image models + combos in OpenAI format
-```
-
----
-
-## Compatibility Endpoints
-
-| Method | Path | Format |
-| ------ | --------------------------- | ---------------------- |
-| POST | `/v1/chat/completions` | OpenAI |
-| POST | `/v1/messages` | Anthropic |
-| POST | `/v1/responses` | OpenAI Responses |
-| POST | `/v1/embeddings` | OpenAI |
-| POST | `/v1/images/generations` | OpenAI |
-| GET | `/v1/models` | OpenAI |
-| POST | `/v1/messages/count_tokens` | Anthropic |
-| GET | `/v1beta/models` | Gemini |
-| POST | `/v1beta/models/{...path}` | Gemini generateContent |
-| POST | `/v1/api/chat` | Ollama |
-
-### Dedicated Provider Routes
-
-```bash
-POST /v1/providers/{provider}/chat/completions
-POST /v1/providers/{provider}/embeddings
-POST /v1/providers/{provider}/images/generations
-```
-
-The provider prefix is auto-added if missing. Mismatched models return `400`.
-
----
-
-## Semantic Cache
-
-```bash
-# Get cache stats
-GET /api/cache
-
-# Clear all caches
-DELETE /api/cache
-```
-
-Response example:
-
-```json
-{
- "semanticCache": {
- "memorySize": 42,
- "memoryMaxSize": 500,
- "dbSize": 128,
- "hitRate": 0.65
- },
- "idempotency": {
- "activeKeys": 3,
- "windowMs": 5000
- }
-}
-```
-
----
-
-## Dashboard & Management
-
-### Authentication
-
-| Endpoint | Method | Description |
-| ----------------------------- | ------- | --------------------- |
-| `/api/auth/login` | POST | Login |
-| `/api/auth/logout` | POST | Logout |
-| `/api/settings/require-login` | GET/PUT | Toggle login required |
-
-### Provider Management
-
-| Endpoint | Method | Description |
-| ---------------------------- | --------------- | ------------------------ |
-| `/api/providers` | GET/POST | List / create providers |
-| `/api/providers/[id]` | GET/PUT/DELETE | Manage a provider |
-| `/api/providers/[id]/test` | POST | Test provider connection |
-| `/api/providers/[id]/models` | GET | List provider models |
-| `/api/providers/validate` | POST | Validate provider config |
-| `/api/provider-nodes*` | Various | Provider node management |
-| `/api/provider-models` | GET/POST/DELETE | Custom models |
-
-### OAuth Flows
-
-| Endpoint | Method | Description |
-| -------------------------------- | ------- | ----------------------- |
-| `/api/oauth/[provider]/[action]` | Various | Provider-specific OAuth |
-
-### Routing & Config
-
-| Endpoint | Method | Description |
-| --------------------- | -------- | ----------------------------- |
-| `/api/models/alias` | GET/POST | Model aliases |
-| `/api/models/catalog` | GET | All models by provider + type |
-| `/api/combos*` | Various | Combo management |
-| `/api/keys*` | Various | API key management |
-| `/api/pricing` | GET | Model pricing |
-
-### Usage & Analytics
-
-| Endpoint | Method | Description |
-| --------------------------- | ------ | -------------------- |
-| `/api/usage/history` | GET | Usage history |
-| `/api/usage/logs` | GET | Usage logs |
-| `/api/usage/request-logs` | GET | Request-level logs |
-| `/api/usage/[connectionId]` | GET | Per-connection usage |
-
-### Settings
-
-| Endpoint | Method | Description |
-| ------------------------------- | ------- | ---------------------- |
-| `/api/settings` | GET/PUT | General settings |
-| `/api/settings/proxy` | GET/PUT | Network proxy config |
-| `/api/settings/proxy/test` | POST | Test proxy connection |
-| `/api/settings/ip-filter` | GET/PUT | IP allowlist/blocklist |
-| `/api/settings/thinking-budget` | GET/PUT | Reasoning token budget |
-| `/api/settings/system-prompt` | GET/PUT | Global system prompt |
-
-### Monitoring
-
-| Endpoint | Method | Description |
-| ------------------------ | ---------- | ----------------------- |
-| `/api/sessions` | GET | Active session tracking |
-| `/api/rate-limits` | GET | Per-account rate limits |
-| `/api/monitoring/health` | GET | Health check |
-| `/api/cache` | GET/DELETE | Cache stats / clear |
-
-### Backup & Export/Import
-
-| Endpoint | Method | Description |
-| --------------------------- | ------ | --------------------------------------- |
-| `/api/db-backups` | GET | List available backups |
-| `/api/db-backups` | PUT | Create a manual backup |
-| `/api/db-backups` | POST | Restore from a specific backup |
-| `/api/db-backups/export` | GET | Download database as .sqlite file |
-| `/api/db-backups/import` | POST | Upload .sqlite file to replace database |
-| `/api/db-backups/exportAll` | GET | Download full backup as .tar.gz archive |
-
-### Cloud Sync
-
-| Endpoint | Method | Description |
-| ---------------------- | ------- | --------------------- |
-| `/api/sync/cloud` | Various | Cloud sync operations |
-| `/api/sync/initialize` | POST | Initialize sync |
-| `/api/cloud/*` | Various | Cloud management |
-
-### CLI Tools
-
-| Endpoint | Method | Description |
-| ---------------------------------- | ------ | ------------------- |
-| `/api/cli-tools/claude-settings` | GET | Claude CLI status |
-| `/api/cli-tools/codex-settings` | GET | Codex CLI status |
-| `/api/cli-tools/droid-settings` | GET | Droid CLI status |
-| `/api/cli-tools/openclaw-settings` | GET | OpenClaw CLI status |
-| `/api/cli-tools/runtime/[toolId]` | GET | Generic CLI runtime |
-
-CLI responses include: `installed`, `runnable`, `command`, `commandPath`, `runtimeMode`, `reason`.
-
-### ACP Agents
-
-| Endpoint | Method | Description |
-| ----------------- | ------ | -------------------------------------------------------- |
-| `/api/acp/agents` | GET | List all detected agents (built-in + custom) with status |
-| `/api/acp/agents` | POST | Add custom agent or refresh detection cache |
-| `/api/acp/agents` | DELETE | Remove a custom agent by `id` query param |
-
-GET response includes `agents[]` (id, name, binary, version, installed, protocol, isCustom) and `summary` (total, installed, notFound, builtIn, custom).
-
-### Resilience & Rate Limits
-
-| Endpoint | Method | Description |
-| ----------------------- | ------- | ------------------------------- |
-| `/api/resilience` | GET/PUT | Get/update resilience profiles |
-| `/api/resilience/reset` | POST | Reset circuit breakers |
-| `/api/rate-limits` | GET | Per-account rate limit status |
-| `/api/rate-limit` | GET | Global rate limit configuration |
-
-### Evals
-
-| Endpoint | Method | Description |
-| ------------ | -------- | --------------------------------- |
-| `/api/evals` | GET/POST | List eval suites / run evaluation |
-
-### Policies
-
-| Endpoint | Method | Description |
-| --------------- | --------------- | ----------------------- |
-| `/api/policies` | GET/POST/DELETE | Manage routing policies |
-
-### Compliance
-
-| Endpoint | Method | Description |
-| --------------------------- | ------ | ----------------------------- |
-| `/api/compliance/audit-log` | GET | Compliance audit log (last N) |
-
-### v1beta (Gemini-Compatible)
-
-| Endpoint | Method | Description |
-| -------------------------- | ------ | --------------------------------- |
-| `/v1beta/models` | GET | List models in Gemini format |
-| `/v1beta/models/{...path}` | POST | Gemini `generateContent` endpoint |
-
-These endpoints mirror Gemini's API format for clients that expect native Gemini SDK compatibility.
-
-### Internal / System APIs
-
-| Endpoint | Method | Description |
-| --------------- | ------ | ---------------------------------------------------- |
-| `/api/init` | GET | Application initialization check (used on first run) |
-| `/api/tags` | GET | Ollama-compatible model tags (for Ollama clients) |
-| `/api/restart` | POST | Trigger graceful server restart |
-| `/api/shutdown` | POST | Trigger graceful server shutdown |
-
-> **Note:** These endpoints are used internally by the system or for Ollama client compatibility. They are not typically called by end users.
-
----
-
-## Audio Transcription
-
-```bash
-POST /v1/audio/transcriptions
-Authorization: Bearer your-api-key
-Content-Type: multipart/form-data
-```
-
-Transcribe audio files using Deepgram or AssemblyAI.
-
-**Request:**
-
-```bash
-curl -X POST http://localhost:20128/v1/audio/transcriptions \
- -H "Authorization: Bearer your-api-key" \
- -F "file=@recording.mp3" \
- -F "model=deepgram/nova-3"
-```
-
-**Response:**
-
-```json
-{
- "text": "Hello, this is the transcribed audio content.",
- "task": "transcribe",
- "language": "en",
- "duration": 12.5
-}
-```
-
-**Supported providers:** `deepgram/nova-3`, `assemblyai/best`.
-
-**Supported formats:** `mp3`, `wav`, `m4a`, `flac`, `ogg`, `webm`.
-
----
-
-## Ollama Compatibility
-
-For clients that use Ollama's API format:
-
-```bash
-# Chat endpoint (Ollama format)
-POST /v1/api/chat
-
-# Model listing (Ollama format)
-GET /api/tags
-```
-
-Requests are automatically translated between Ollama and internal formats.
-
----
-
-## Telemetry
-
-```bash
-# Get latency telemetry summary (p50/p95/p99 per provider)
-GET /api/telemetry/summary
-```
-
-**Response:**
-
-```json
-{
- "providers": {
- "claudeCode": { "p50": 245, "p95": 890, "p99": 1200, "count": 150 },
- "github": { "p50": 180, "p95": 620, "p99": 950, "count": 320 }
- }
-}
-```
-
----
-
-## Budget
-
-```bash
-# Get budget status for all API keys
-GET /api/usage/budget
-
-# Set or update a budget
-POST /api/usage/budget
-Content-Type: application/json
-
-{
- "keyId": "key-123",
- "limit": 50.00,
- "period": "monthly"
-}
-```
-
----
-
-## Model Availability
-
-```bash
-# Get real-time model availability across all providers
-GET /api/models/availability
-
-# Check availability for a specific model
-POST /api/models/availability
-Content-Type: application/json
-
-{
- "model": "claude-sonnet-4-5-20250929"
-}
-```
-
----
-
-## Request Processing
-
-1. Client sends request to `/v1/*`
-2. Route handler calls `handleChat`, `handleEmbedding`, `handleAudioTranscription`, or `handleImageGeneration`
-3. Model is resolved (direct provider/model or alias/combo)
-4. Credentials selected from local DB with account availability filtering
-5. For chat: `handleChatCore` — format detection, translation, cache check, idempotency check
-6. Provider executor sends upstream request
-7. Response translated back to client format (chat) or returned as-is (embeddings/images/audio)
-8. Usage/logging recorded
-9. Fallback applies on errors according to combo rules
-
-Full architecture reference: [`ARCHITECTURE.md`](ARCHITECTURE.md)
-
----
-
-## Authentication
-
-- Dashboard routes (`/dashboard/*`) use `auth_token` cookie
-- Login uses saved password hash; fallback to `INITIAL_PASSWORD`
-- `requireLogin` toggleable via `/api/settings/require-login`
-- `/v1/*` routes optionally require Bearer API key when `REQUIRE_API_KEY=true`
diff --git a/docs/i18n/es/ARCHITECTURE.md b/docs/i18n/es/ARCHITECTURE.md
deleted file mode 100644
index 4ea06a29f2..0000000000
--- a/docs/i18n/es/ARCHITECTURE.md
+++ /dev/null
@@ -1,787 +0,0 @@
-🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/ARCHITECTURE.md) · 🇪🇸 [es](../es/ARCHITECTURE.md) · 🇫🇷 [fr](../fr/ARCHITECTURE.md) · 🇩🇪 [de](../de/ARCHITECTURE.md) · 🇮🇹 [it](../it/ARCHITECTURE.md) · 🇷🇺 [ru](../ru/ARCHITECTURE.md) · 🇨🇳 [zh-CN](../zh-CN/ARCHITECTURE.md) · 🇯🇵 [ja](../ja/ARCHITECTURE.md) · 🇰🇷 [ko](../ko/ARCHITECTURE.md) · 🇸🇦 [ar](../ar/ARCHITECTURE.md) · 🇮🇳 [in](../in/ARCHITECTURE.md) · 🇹🇭 [th](../th/ARCHITECTURE.md) · 🇻🇳 [vi](../vi/ARCHITECTURE.md) · 🇮🇩 [id](../id/ARCHITECTURE.md) · 🇲🇾 [ms](../ms/ARCHITECTURE.md) · 🇳🇱 [nl](../nl/ARCHITECTURE.md) · 🇵🇱 [pl](../pl/ARCHITECTURE.md) · 🇸🇪 [sv](../sv/ARCHITECTURE.md) · 🇳🇴 [no](../no/ARCHITECTURE.md) · 🇩🇰 [da](../da/ARCHITECTURE.md) · 🇫🇮 [fi](../fi/ARCHITECTURE.md) · 🇵🇹 [pt](../pt/ARCHITECTURE.md) · 🇷🇴 [ro](../ro/ARCHITECTURE.md) · 🇭🇺 [hu](../hu/ARCHITECTURE.md) · 🇧🇬 [bg](../bg/ARCHITECTURE.md) · 🇸🇰 [sk](../sk/ARCHITECTURE.md) · 🇺🇦 [uk-UA](../uk-UA/ARCHITECTURE.md) · 🇮🇱 [he](../he/ARCHITECTURE.md) · 🇵🇭 [phi](../phi/ARCHITECTURE.md)
-
----
-
-# OmniRoute Architecture
-
-🌐 **Languages:** 🇺🇸 [English](ARCHITECTURE.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/ARCHITECTURE.md) | 🇪🇸 [Español](i18n/es/ARCHITECTURE.md) | 🇫🇷 [Français](i18n/fr/ARCHITECTURE.md) | 🇮🇹 [Italiano](i18n/it/ARCHITECTURE.md) | 🇷🇺 [Русский](i18n/ru/ARCHITECTURE.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/ARCHITECTURE.md) | 🇩🇪 [Deutsch](i18n/de/ARCHITECTURE.md) | 🇮🇳 [हिन्दी](i18n/in/ARCHITECTURE.md) | 🇹🇭 [ไทย](i18n/th/ARCHITECTURE.md) | 🇺🇦 [Українська](i18n/uk-UA/ARCHITECTURE.md) | 🇸🇦 [العربية](i18n/ar/ARCHITECTURE.md) | 🇯🇵 [日本語](i18n/ja/ARCHITECTURE.md) | 🇻🇳 [Tiếng Việt](i18n/vi/ARCHITECTURE.md) | 🇧🇬 [Български](i18n/bg/ARCHITECTURE.md) | 🇩🇰 [Dansk](i18n/da/ARCHITECTURE.md) | 🇫🇮 [Suomi](i18n/fi/ARCHITECTURE.md) | 🇮🇱 [עברית](i18n/he/ARCHITECTURE.md) | 🇭🇺 [Magyar](i18n/hu/ARCHITECTURE.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/ARCHITECTURE.md) | 🇰🇷 [한국어](i18n/ko/ARCHITECTURE.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/ARCHITECTURE.md) | 🇳🇱 [Nederlands](i18n/nl/ARCHITECTURE.md) | 🇳🇴 [Norsk](i18n/no/ARCHITECTURE.md) | 🇵🇹 [Português (Portugal)](i18n/pt/ARCHITECTURE.md) | 🇷🇴 [Română](i18n/ro/ARCHITECTURE.md) | 🇵🇱 [Polski](i18n/pl/ARCHITECTURE.md) | 🇸🇰 [Slovenčina](i18n/sk/ARCHITECTURE.md) | 🇸🇪 [Svenska](i18n/sv/ARCHITECTURE.md) | 🇵🇭 [Filipino](i18n/phi/ARCHITECTURE.md)
-
-_Last updated: 2026-03-04_
-
-## Executive Summary
-
-OmniRoute is a local AI routing gateway and dashboard built on Next.js.
-It provides a single OpenAI-compatible endpoint (`/v1/*`) and routes traffic across multiple upstream providers with translation, fallback, token refresh, and usage tracking.
-
-Core capabilities:
-
-- OpenAI-compatible API surface for CLI/tools (28 providers)
-- Request/response translation across provider formats
-- Model combo fallback (multi-model sequence)
-- Account-level fallback (multi-account per provider)
-- OAuth + API-key provider connection management
-- Embedding generation via `/v1/embeddings` (6 providers, 9 models)
-- Image generation via `/v1/images/generations` (4 providers, 9 models)
-- Think tag parsing (`...`) for reasoning models
-- Response sanitization for strict OpenAI SDK compatibility
-- Role normalization (developer→system, system→user) for cross-provider compatibility
-- Structured output conversion (json_schema → Gemini responseSchema)
-- Local persistence for providers, keys, aliases, combos, settings, pricing
-- Usage/cost tracking and request logging
-- Optional cloud sync for multi-device/state sync
-- IP allowlist/blocklist for API access control
-- Thinking budget management (passthrough/auto/custom/adaptive)
-- Global system prompt injection
-- Session tracking and fingerprinting
-- Per-account enhanced rate limiting with provider-specific profiles
-- Circuit breaker pattern for provider resilience
-- Anti-thundering herd protection with mutex locking
-- Signature-based request deduplication cache
-- Domain layer: model availability, cost rules, fallback policy, lockout policy
-- Domain state persistence (SQLite write-through cache for fallbacks, budgets, lockouts, circuit breakers)
-- Policy engine for centralized request evaluation (lockout → budget → fallback)
-- Request telemetry with p50/p95/p99 latency aggregation
-- Correlation ID (X-Request-Id) for end-to-end tracing
-- Compliance audit logging with opt-out per API key
-- Eval framework for LLM quality assurance
-- Resilience UI dashboard with real-time circuit breaker status
-- Modular OAuth providers (12 individual modules under `src/lib/oauth/providers/`)
-
-Primary runtime model:
-
-- Next.js app routes under `src/app/api/*` implement both dashboard APIs and compatibility APIs
-- A shared SSE/routing core in `src/sse/*` + `open-sse/*` handles provider execution, translation, streaming, fallback, and usage
-
-## Scope and Boundaries
-
-### In Scope
-
-- Local gateway runtime
-- Dashboard management APIs
-- Provider authentication and token refresh
-- Request translation and SSE streaming
-- Local state + usage persistence
-- Optional cloud sync orchestration
-
-### Out of Scope
-
-- Cloud service implementation behind `NEXT_PUBLIC_CLOUD_URL`
-- Provider SLA/control plane outside local process
-- External CLI binaries themselves (Claude CLI, Codex CLI, etc.)
-
-## High-Level System Context
-
-```mermaid
-flowchart LR
- subgraph Clients[Developer Clients]
- C1[Claude Code]
- C2[Codex CLI]
- C3[OpenClaw / Droid / Cline / Continue / Roo]
- C4[Custom OpenAI-compatible clients]
- BROWSER[Browser Dashboard]
- end
-
- subgraph Router[OmniRoute Local Process]
- API[V1 Compatibility API\n/v1/*]
- DASH[Dashboard + Management API\n/api/*]
- CORE[SSE + Translation Core\nopen-sse + src/sse]
- DB[(storage.sqlite)]
- UDB[(usage tables + log artifacts)]
- end
-
- subgraph Upstreams[Upstream Providers]
- P1[OAuth Providers\nClaude/Codex/Gemini/Qwen/Qoder/GitHub/Kiro/Cursor/Antigravity]
- P2[API Key Providers\nOpenAI/Anthropic/OpenRouter/GLM/Kimi/MiniMax\nDeepSeek/Groq/xAI/Mistral/Perplexity\nTogether/Fireworks/Cerebras/Cohere/NVIDIA]
- P3[Compatible Nodes\nOpenAI-compatible / Anthropic-compatible]
- end
-
- subgraph Cloud[Optional Cloud Sync]
- CLOUD[Cloud Sync Endpoint\nNEXT_PUBLIC_CLOUD_URL]
- end
-
- C1 --> API
- C2 --> API
- C3 --> API
- C4 --> API
- BROWSER --> DASH
-
- API --> CORE
- DASH --> DB
- CORE --> DB
- CORE --> UDB
-
- CORE --> P1
- CORE --> P2
- CORE --> P3
-
- DASH --> CLOUD
-```
-
-## Core Runtime Components
-
-## 1) API and Routing Layer (Next.js App Routes)
-
-Main directories:
-
-- `src/app/api/v1/*` and `src/app/api/v1beta/*` for compatibility APIs
-- `src/app/api/*` for management/configuration APIs
-- Next rewrites in `next.config.mjs` map `/v1/*` to `/api/v1/*`
-
-Important compatibility routes:
-
-- `src/app/api/v1/chat/completions/route.ts`
-- `src/app/api/v1/messages/route.ts`
-- `src/app/api/v1/responses/route.ts`
-- `src/app/api/v1/models/route.ts` — includes custom models with `custom: true`
-- `src/app/api/v1/embeddings/route.ts` — embedding generation (6 providers)
-- `src/app/api/v1/images/generations/route.ts` — image generation (4+ providers incl. Antigravity/Nebius)
-- `src/app/api/v1/messages/count_tokens/route.ts`
-- `src/app/api/v1/providers/[provider]/chat/completions/route.ts` — dedicated per-provider chat
-- `src/app/api/v1/providers/[provider]/embeddings/route.ts` — dedicated per-provider embeddings
-- `src/app/api/v1/providers/[provider]/images/generations/route.ts` — dedicated per-provider images
-- `src/app/api/v1beta/models/route.ts`
-- `src/app/api/v1beta/models/[...path]/route.ts`
-
-Management domains:
-
-- Auth/settings: `src/app/api/auth/*`, `src/app/api/settings/*`
-- Providers/connections: `src/app/api/providers*`
-- Provider nodes: `src/app/api/provider-nodes*`
-- Custom models: `src/app/api/provider-models` (GET/POST/DELETE)
-- Model catalog: `src/app/api/models/route.ts` (GET)
-- Proxy config: `src/app/api/settings/proxy` (GET/PUT/DELETE) + `src/app/api/settings/proxy/test` (POST)
-- OAuth: `src/app/api/oauth/*`
-- Keys/aliases/combos/pricing: `src/app/api/keys*`, `src/app/api/models/alias`, `src/app/api/combos*`, `src/app/api/pricing`
-- Usage: `src/app/api/usage/*`
-- Sync/cloud: `src/app/api/sync/*`, `src/app/api/cloud/*`
-- CLI tooling helpers: `src/app/api/cli-tools/*`
-- IP filter: `src/app/api/settings/ip-filter` (GET/PUT)
-- Thinking budget: `src/app/api/settings/thinking-budget` (GET/PUT)
-- System prompt: `src/app/api/settings/system-prompt` (GET/PUT)
-- Sessions: `src/app/api/sessions` (GET)
-- Rate limits: `src/app/api/rate-limits` (GET)
-- Resilience: `src/app/api/resilience` (GET/PATCH) — provider profiles, circuit breaker, rate limit state
-- Resilience reset: `src/app/api/resilience/reset` (POST) — reset breakers + cooldowns
-- Cache stats: `src/app/api/cache/stats` (GET/DELETE)
-- Model availability: `src/app/api/models/availability` (GET/POST)
-- Telemetry: `src/app/api/telemetry/summary` (GET)
-- Budget: `src/app/api/usage/budget` (GET/POST)
-- Fallback chains: `src/app/api/fallback/chains` (GET/POST/DELETE)
-- Compliance audit: `src/app/api/compliance/audit-log` (GET)
-- Evals: `src/app/api/evals` (GET/POST), `src/app/api/evals/[suiteId]` (GET)
-- Policies: `src/app/api/policies` (GET/POST)
-
-## 2) SSE + Translation Core
-
-Main flow modules:
-
-- Entry: `src/sse/handlers/chat.ts`
-- Core orchestration: `open-sse/handlers/chatCore.ts`
-- Provider execution adapters: `open-sse/executors/*`
-- Format detection/provider config: `open-sse/services/provider.ts`
-- Model parse/resolve: `src/sse/services/model.ts`, `open-sse/services/model.ts`
-- Account fallback logic: `open-sse/services/accountFallback.ts`
-- Translation registry: `open-sse/translator/index.ts`
-- Stream transformations: `open-sse/utils/stream.ts`, `open-sse/utils/streamHandler.ts`
-- Usage extraction/normalization: `open-sse/utils/usageTracking.ts`
-- Think tag parser: `open-sse/utils/thinkTagParser.ts`
-- Embedding handler: `open-sse/handlers/embeddings.ts`
-- Embedding provider registry: `open-sse/config/embeddingRegistry.ts`
-- Image generation handler: `open-sse/handlers/imageGeneration.ts`
-- Image provider registry: `open-sse/config/imageRegistry.ts`
-- Response sanitization: `open-sse/handlers/responseSanitizer.ts`
-- Role normalization: `open-sse/services/roleNormalizer.ts`
-
-Services (business logic):
-
-- Account selection/scoring: `open-sse/services/accountSelector.ts`
-- Context lifecycle management: `open-sse/services/contextManager.ts`
-- IP filter enforcement: `open-sse/services/ipFilter.ts`
-- Session tracking: `open-sse/services/sessionManager.ts`
-- Request deduplication: `open-sse/services/signatureCache.ts`
-- System prompt injection: `open-sse/services/systemPrompt.ts`
-- Thinking budget management: `open-sse/services/thinkingBudget.ts`
-- Wildcard model routing: `open-sse/services/wildcardRouter.ts`
-- Rate limit management: `open-sse/services/rateLimitManager.ts`
-- Circuit breaker: `open-sse/services/circuitBreaker.ts`
-
-Domain layer modules:
-
-- Model availability: `src/lib/domain/modelAvailability.ts`
-- Cost rules/budgets: `src/lib/domain/costRules.ts`
-- Fallback policy: `src/lib/domain/fallbackPolicy.ts`
-- Combo resolver: `src/lib/domain/comboResolver.ts`
-- Lockout policy: `src/lib/domain/lockoutPolicy.ts`
-- Policy engine: `src/domain/policyEngine.ts` — centralized lockout → budget → fallback evaluation
-- Error codes catalog: `src/lib/domain/errorCodes.ts`
-- Request ID: `src/lib/domain/requestId.ts`
-- Fetch timeout: `src/lib/domain/fetchTimeout.ts`
-- Request telemetry: `src/lib/domain/requestTelemetry.ts`
-- Compliance/audit: `src/lib/domain/compliance/index.ts`
-- Eval runner: `src/lib/domain/evalRunner.ts`
-- Domain state persistence: `src/lib/db/domainState.ts` — SQLite CRUD for fallback chains, budgets, cost history, lockout state, circuit breakers
-
-OAuth provider modules (12 individual files under `src/lib/oauth/providers/`):
-
-- Registry index: `src/lib/oauth/providers/index.ts`
-- Individual providers: `claude.ts`, `codex.ts`, `gemini.ts`, `antigravity.ts`, `qoder.ts`, `qwen.ts`, `kimi-coding.ts`, `github.ts`, `kiro.ts`, `cursor.ts`, `kilocode.ts`, `cline.ts`
-- Thin wrapper: `src/lib/oauth/providers.ts` — re-exports from individual modules
-
-## 3) Persistence Layer
-
-Primary state DB (SQLite):
-
-- Core infra: `src/lib/db/core.ts` (better-sqlite3, migrations, WAL)
-- Re-export facade: `src/lib/localDb.ts` (thin compatibility layer for callers)
-- file: `${DATA_DIR}/storage.sqlite` (or `$XDG_CONFIG_HOME/omniroute/storage.sqlite` when set, else `~/.omniroute/storage.sqlite`)
-- entities (tables + KV namespaces): providerConnections, providerNodes, modelAliases, combos, apiKeys, settings, pricing, **customModels**, **proxyConfig**, **ipFilter**, **thinkingBudget**, **systemPrompt**
-
-Usage persistence:
-
-- facade: `src/lib/usageDb.ts` (decomposed modules in `src/lib/usage/*`)
-- SQLite tables in `storage.sqlite`: `usage_history`, `call_logs`, `proxy_logs`
-- optional file artifacts remain for compatibility/debug (`${DATA_DIR}/log.txt`, `${DATA_DIR}/call_logs/`, `/logs/...`)
-- legacy JSON files are migrated to SQLite by startup migrations when present
-
-Domain State DB (SQLite):
-
-- `src/lib/db/domainState.ts` — CRUD operations for domain state
-- Tables (created in `src/lib/db/core.ts`): `domain_fallback_chains`, `domain_budgets`, `domain_cost_history`, `domain_lockout_state`, `domain_circuit_breakers`
-- Write-through cache pattern: in-memory Maps are authoritative at runtime; mutations are written synchronously to SQLite; state is restored from DB on cold start
-
-## 4) Auth + Security Surfaces
-
-- Dashboard cookie auth: `src/proxy.ts`, `src/app/api/auth/login/route.ts`
-- API key generation/verification: `src/shared/utils/apiKey.ts`
-- Provider secrets persisted in `providerConnections` entries
-- Outbound proxy support via `open-sse/utils/proxyFetch.ts` (env vars) and `open-sse/utils/networkProxy.ts` (configurable per-provider or global)
-
-## 5) Cloud Sync
-
-- Scheduler init: `src/lib/initCloudSync.ts`, `src/shared/services/initializeCloudSync.ts`
-- Periodic task: `src/shared/services/cloudSyncScheduler.ts`
-- Control route: `src/app/api/sync/cloud/route.ts`
-
-## Request Lifecycle (`/v1/chat/completions`)
-
-```mermaid
-sequenceDiagram
- autonumber
- participant Client as CLI/SDK Client
- participant Route as /api/v1/chat/completions
- participant Chat as src/sse/handlers/chat
- participant Core as open-sse/handlers/chatCore
- participant Model as Model Resolver
- participant Auth as Credential Selector
- participant Exec as Provider Executor
- participant Prov as Upstream Provider
- participant Stream as Stream Translator
- participant Usage as usageDb
-
- Client->>Route: POST /v1/chat/completions
- Route->>Chat: handleChat(request)
- Chat->>Model: parse/resolve model or combo
-
- alt Combo model
- Chat->>Chat: iterate combo models (handleComboChat)
- end
-
- Chat->>Auth: getProviderCredentials(provider)
- Auth-->>Chat: active account + tokens/api key
-
- Chat->>Core: handleChatCore(body, modelInfo, credentials)
- Core->>Core: detect source format
- Core->>Core: translate request to target format
- Core->>Exec: execute(provider, transformedBody)
- Exec->>Prov: upstream API call
- Prov-->>Exec: SSE/JSON response
- Exec-->>Core: response + metadata
-
- alt 401/403
- Core->>Exec: refreshCredentials()
- Exec-->>Core: updated tokens
- Core->>Exec: retry request
- end
-
- Core->>Stream: translate/normalize stream to client format
- Stream-->>Client: SSE chunks / JSON response
-
- Stream->>Usage: extract usage + persist history/log
-```
-
-## Combo + Account Fallback Flow
-
-```mermaid
-flowchart TD
- A[Incoming model string] --> B{Is combo name?}
- B -- Yes --> C[Load combo models sequence]
- B -- No --> D[Single model path]
-
- C --> E[Try model N]
- E --> F[Resolve provider/model]
- D --> F
-
- F --> G[Select account credentials]
- G --> H{Credentials available?}
- H -- No --> I[Return provider unavailable]
- H -- Yes --> J[Execute request]
-
- J --> K{Success?}
- K -- Yes --> L[Return response]
- K -- No --> M{Fallback-eligible error?}
-
- M -- No --> N[Return error]
- M -- Yes --> O[Mark account unavailable cooldown]
- O --> P{Another account for provider?}
- P -- Yes --> G
- P -- No --> Q{In combo with next model?}
- Q -- Yes --> E
- Q -- No --> R[Return all unavailable]
-```
-
-Fallback decisions are driven by `open-sse/services/accountFallback.ts` using status codes and error-message heuristics.
-
-## OAuth Onboarding and Token Refresh Lifecycle
-
-```mermaid
-sequenceDiagram
- autonumber
- participant UI as Dashboard UI
- participant OAuth as /api/oauth/[provider]/[action]
- participant ProvAuth as Provider Auth Server
- participant DB as localDb
- participant Test as /api/providers/[id]/test
- participant Exec as Provider Executor
-
- UI->>OAuth: GET authorize or device-code
- OAuth->>ProvAuth: create auth/device flow
- ProvAuth-->>OAuth: auth URL or device code payload
- OAuth-->>UI: flow data
-
- UI->>OAuth: POST exchange or poll
- OAuth->>ProvAuth: token exchange/poll
- ProvAuth-->>OAuth: access/refresh tokens
- OAuth->>DB: createProviderConnection(oauth data)
- OAuth-->>UI: success + connection id
-
- UI->>Test: POST /api/providers/[id]/test
- Test->>Exec: validate credentials / optional refresh
- Exec-->>Test: valid or refreshed token info
- Test->>DB: update status/tokens/errors
- Test-->>UI: validation result
-```
-
-Refresh during live traffic is executed inside `open-sse/handlers/chatCore.ts` via executor `refreshCredentials()`.
-
-## Cloud Sync Lifecycle (Enable / Sync / Disable)
-
-```mermaid
-sequenceDiagram
- autonumber
- participant UI as Endpoint Page UI
- participant Sync as /api/sync/cloud
- participant DB as localDb
- participant Cloud as External Cloud Sync
- participant Claude as ~/.claude/settings.json
-
- UI->>Sync: POST action=enable
- Sync->>DB: set cloudEnabled=true
- Sync->>DB: ensure API key exists
- Sync->>Cloud: POST /sync/{machineId} (providers/aliases/combos/keys)
- Cloud-->>Sync: sync result
- Sync->>Cloud: GET /{machineId}/v1/verify
- Sync-->>UI: enabled + verification status
-
- UI->>Sync: POST action=sync
- Sync->>Cloud: POST /sync/{machineId}
- Cloud-->>Sync: remote data
- Sync->>DB: update newer local tokens/status
- Sync-->>UI: synced
-
- UI->>Sync: POST action=disable
- Sync->>DB: set cloudEnabled=false
- Sync->>Cloud: DELETE /sync/{machineId}
- Sync->>Claude: switch ANTHROPIC_BASE_URL back to local (if needed)
- Sync-->>UI: disabled
-```
-
-Periodic sync is triggered by `CloudSyncScheduler` when cloud is enabled.
-
-## Data Model and Storage Map
-
-```mermaid
-erDiagram
- SETTINGS ||--o{ PROVIDER_CONNECTION : controls
- PROVIDER_NODE ||--o{ PROVIDER_CONNECTION : backs_compatible_provider
- PROVIDER_CONNECTION ||--o{ USAGE_ENTRY : emits_usage
-
- SETTINGS {
- boolean cloudEnabled
- number stickyRoundRobinLimit
- boolean requireLogin
- string password_hash
- string fallbackStrategy
- json rateLimitDefaults
- json providerProfiles
- }
-
- PROVIDER_CONNECTION {
- string id
- string provider
- string authType
- string name
- number priority
- boolean isActive
- string apiKey
- string accessToken
- string refreshToken
- string expiresAt
- string testStatus
- string lastError
- string rateLimitedUntil
- json providerSpecificData
- }
-
- PROVIDER_NODE {
- string id
- string type
- string name
- string prefix
- string apiType
- string baseUrl
- }
-
- MODEL_ALIAS {
- string alias
- string targetModel
- }
-
- COMBO {
- string id
- string name
- string[] models
- }
-
- API_KEY {
- string id
- string name
- string key
- string machineId
- }
-
- USAGE_ENTRY {
- string provider
- string model
- number prompt_tokens
- number completion_tokens
- string connectionId
- string timestamp
- }
-
- CUSTOM_MODEL {
- string id
- string name
- string providerId
- }
-
- PROXY_CONFIG {
- string global
- json providers
- }
-
- IP_FILTER {
- string mode
- string[] allowlist
- string[] blocklist
- }
-
- THINKING_BUDGET {
- string mode
- number customBudget
- string effortLevel
- }
-
- SYSTEM_PROMPT {
- boolean enabled
- string prompt
- string position
- }
-```
-
-Physical storage files:
-
-- primary runtime DB: `${DATA_DIR}/storage.sqlite`
-- request log lines: `${DATA_DIR}/log.txt` (compat/debug artifact)
-- structured call payload archives: `${DATA_DIR}/call_logs/`
-- optional translator/request debug sessions: `/logs/...`
-
-## Deployment Topology
-
-```mermaid
-flowchart LR
- subgraph LocalHost[Developer Host]
- CLI[CLI Tools]
- Browser[Dashboard Browser]
- end
-
- subgraph ContainerOrProcess[OmniRoute Runtime]
- Next[Next.js Server\nPORT=20128]
- Core[SSE Core + Executors]
- MainDB[(storage.sqlite)]
- UsageDB[(usage tables + log artifacts)]
- end
-
- subgraph External[External Services]
- Providers[AI Providers]
- SyncCloud[Cloud Sync Service]
- end
-
- CLI --> Next
- Browser --> Next
- Next --> Core
- Next --> MainDB
- Core --> MainDB
- Core --> UsageDB
- Core --> Providers
- Next --> SyncCloud
-```
-
-## Module Mapping (Decision-Critical)
-
-### Route and API Modules
-
-- `src/app/api/v1/*`, `src/app/api/v1beta/*`: compatibility APIs
-- `src/app/api/v1/providers/[provider]/*`: dedicated per-provider routes (chat, embeddings, images)
-- `src/app/api/providers*`: provider CRUD, validation, testing
-- `src/app/api/provider-nodes*`: custom compatible node management
-- `src/app/api/provider-models`: custom model management (CRUD)
-- `src/app/api/models/route.ts`: model catalog API (aliases + custom models)
-- `src/app/api/oauth/*`: OAuth/device-code flows
-- `src/app/api/keys*`: local API key lifecycle
-- `src/app/api/models/alias`: alias management
-- `src/app/api/combos*`: fallback combo management
-- `src/app/api/pricing`: pricing overrides for cost calculation
-- `src/app/api/settings/proxy`: proxy configuration (GET/PUT/DELETE)
-- `src/app/api/settings/proxy/test`: outbound proxy connectivity test (POST)
-- `src/app/api/usage/*`: usage and logs APIs
-- `src/app/api/sync/*` + `src/app/api/cloud/*`: cloud sync and cloud-facing helpers
-- `src/app/api/cli-tools/*`: local CLI config writers/checkers
-- `src/app/api/settings/ip-filter`: IP allowlist/blocklist (GET/PUT)
-- `src/app/api/settings/thinking-budget`: thinking token budget config (GET/PUT)
-- `src/app/api/settings/system-prompt`: global system prompt (GET/PUT)
-- `src/app/api/sessions`: active session listing (GET)
-- `src/app/api/rate-limits`: per-account rate limit status (GET)
-
-### Routing and Execution Core
-
-- `src/sse/handlers/chat.ts`: request parse, combo handling, account selection loop
-- `open-sse/handlers/chatCore.ts`: translation, executor dispatch, retry/refresh handling, stream setup
-- `open-sse/executors/*`: provider-specific network and format behavior
-
-### Translation Registry and Format Converters
-
-- `open-sse/translator/index.ts`: translator registry and orchestration
-- Request translators: `open-sse/translator/request/*`
-- Response translators: `open-sse/translator/response/*`
-- Format constants: `open-sse/translator/formats.ts`
-
-### Persistence
-
-- `src/lib/db/*`: persistent config/state and domain persistence on SQLite
-- `src/lib/localDb.ts`: compatibility re-export for DB modules
-- `src/lib/usageDb.ts`: usage history/call logs facade on top of SQLite tables
-
-## Provider Executor Coverage (Strategy Pattern)
-
-Each provider has a specialized executor extending `BaseExecutor` (in `open-sse/executors/base.ts`), which provides URL building, header construction, retry with exponential backoff, credential refresh hooks, and the `execute()` orchestration method.
-
-| Executor | Provider(s) | Special Handling |
-| --------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------ | -------------------------------------------------------------------- |
-| `DefaultExecutor` | OpenAI, Claude, Gemini, Qwen, Qoder, OpenRouter, GLM, Kimi, MiniMax, DeepSeek, Groq, xAI, Mistral, Perplexity, Together, Fireworks, Cerebras, Cohere, NVIDIA | Dynamic URL/header config per provider |
-| `AntigravityExecutor` | Google Antigravity | Custom project/session IDs, Retry-After parsing |
-| `CodexExecutor` | OpenAI Codex | Injects system instructions, forces reasoning effort |
-| `CursorExecutor` | Cursor IDE | ConnectRPC protocol, Protobuf encoding, request signing via checksum |
-| `GithubExecutor` | GitHub Copilot | Copilot token refresh, VSCode-mimicking headers |
-| `KiroExecutor` | AWS CodeWhisperer/Kiro | AWS EventStream binary format → SSE conversion |
-| `GeminiCLIExecutor` | Gemini CLI | Google OAuth token refresh cycle |
-
-All other providers (including custom compatible nodes) use the `DefaultExecutor`.
-
-## Provider Compatibility Matrix
-
-| Provider | Format | Auth | Stream | Non-Stream | Token Refresh | Usage API |
-| ---------------- | ---------------- | --------------------- | ---------------- | ---------- | ------------- | ------------------ |
-| Claude | claude | API Key / OAuth | ✅ | ✅ | ✅ | ⚠️ Admin only |
-| Gemini | gemini | API Key / OAuth | ✅ | ✅ | ✅ | ⚠️ Cloud Console |
-| Gemini CLI | gemini-cli | OAuth | ✅ | ✅ | ✅ | ⚠️ Cloud Console |
-| Antigravity | antigravity | OAuth | ✅ | ✅ | ✅ | ✅ Full quota API |
-| OpenAI | openai | API Key | ✅ | ✅ | ❌ | ❌ |
-| Codex | openai-responses | OAuth | ✅ forced | ❌ | ✅ | ✅ Rate limits |
-| GitHub Copilot | openai | OAuth + Copilot Token | ✅ | ✅ | ✅ | ✅ Quota snapshots |
-| Cursor | cursor | Custom checksum | ✅ | ✅ | ❌ | ❌ |
-| Kiro | kiro | AWS SSO OIDC | ✅ (EventStream) | ❌ | ✅ | ✅ Usage limits |
-| Qwen | openai | OAuth | ✅ | ✅ | ✅ | ⚠️ Per request |
-| Qoder | openai | OAuth (Basic) | ✅ | ✅ | ✅ | ⚠️ Per request |
-| OpenRouter | openai | API Key | ✅ | ✅ | ❌ | ❌ |
-| GLM/Kimi/MiniMax | claude | API Key | ✅ | ✅ | ❌ | ❌ |
-| DeepSeek | openai | API Key | ✅ | ✅ | ❌ | ❌ |
-| Groq | openai | API Key | ✅ | ✅ | ❌ | ❌ |
-| xAI (Grok) | openai | API Key | ✅ | ✅ | ❌ | ❌ |
-| Mistral | openai | API Key | ✅ | ✅ | ❌ | ❌ |
-| Perplexity | openai | API Key | ✅ | ✅ | ❌ | ❌ |
-| Together AI | openai | API Key | ✅ | ✅ | ❌ | ❌ |
-| Fireworks AI | openai | API Key | ✅ | ✅ | ❌ | ❌ |
-| Cerebras | openai | API Key | ✅ | ✅ | ❌ | ❌ |
-| Cohere | openai | API Key | ✅ | ✅ | ❌ | ❌ |
-| NVIDIA NIM | openai | API Key | ✅ | ✅ | ❌ | ❌ |
-
-## Format Translation Coverage
-
-Detected source formats include:
-
-- `openai`
-- `openai-responses`
-- `claude`
-- `gemini`
-
-Target formats include:
-
-- OpenAI chat/Responses
-- Claude
-- Gemini/Gemini-CLI/Antigravity envelope
-- Kiro
-- Cursor
-
-Translations use **OpenAI as the hub format** — all conversions go through OpenAI as intermediate:
-
-```
-Source Format → OpenAI (hub) → Target Format
-```
-
-Translations are selected dynamically based on source payload shape and provider target format.
-
-Additional processing layers in the translation pipeline:
-
-- **Response sanitization** — Strips non-standard fields from OpenAI-format responses (both streaming and non-streaming) to ensure strict SDK compliance
-- **Role normalization** — Converts `developer` → `system` for non-OpenAI targets; merges `system` → `user` for models that reject the system role (GLM, ERNIE)
-- **Think tag extraction** — Parses `...` blocks from content into `reasoning_content` field
-- **Structured output** — Converts OpenAI `response_format.json_schema` to Gemini's `responseMimeType` + `responseSchema`
-
-## Supported API Endpoints
-
-| Endpoint | Format | Handler |
-| -------------------------------------------------- | ------------------ | ---------------------------------------------------- |
-| `POST /v1/chat/completions` | OpenAI Chat | `src/sse/handlers/chat.ts` |
-| `POST /v1/messages` | Claude Messages | Same handler (auto-detected) |
-| `POST /v1/responses` | OpenAI Responses | `open-sse/handlers/responsesHandler.ts` |
-| `POST /v1/embeddings` | OpenAI Embeddings | `open-sse/handlers/embeddings.ts` |
-| `GET /v1/embeddings` | Model listing | API route |
-| `POST /v1/images/generations` | OpenAI Images | `open-sse/handlers/imageGeneration.ts` |
-| `GET /v1/images/generations` | Model listing | API route |
-| `POST /v1/providers/{provider}/chat/completions` | OpenAI Chat | Dedicated per-provider with model validation |
-| `POST /v1/providers/{provider}/embeddings` | OpenAI Embeddings | Dedicated per-provider with model validation |
-| `POST /v1/providers/{provider}/images/generations` | OpenAI Images | Dedicated per-provider with model validation |
-| `POST /v1/messages/count_tokens` | Claude Token Count | API route |
-| `GET /v1/models` | OpenAI Models list | API route (chat + embedding + image + custom models) |
-| `GET /api/models/catalog` | Catalog | All models grouped by provider + type |
-| `POST /v1beta/models/*:streamGenerateContent` | Gemini native | API route |
-| `GET/PUT/DELETE /api/settings/proxy` | Proxy Config | Network proxy configuration |
-| `POST /api/settings/proxy/test` | Proxy Connectivity | Proxy health/connectivity test endpoint |
-| `GET/POST/DELETE /api/provider-models` | Custom Models | Custom model management per provider |
-
-## Bypass Handler
-
-The bypass handler (`open-sse/utils/bypassHandler.ts`) intercepts known "throwaway" requests from Claude CLI — warmup pings, title extractions, and token counts — and returns a **fake response** without consuming upstream provider tokens. This is triggered only when `User-Agent` contains `claude-cli`.
-
-## Request Logger Pipeline
-
-The request logger (`open-sse/utils/requestLogger.ts`) provides a 7-stage debug logging pipeline, disabled by default, enabled via `ENABLE_REQUEST_LOGS=true`:
-
-```
-1_req_client.json → 2_req_source.json → 3_req_openai.json → 4_req_target.json
-→ 5_res_provider.txt → 6_res_openai.txt → 7_res_client.txt
-```
-
-Files are written to `/logs//` for each request session.
-
-## Failure Modes and Resilience
-
-## 1) Account/Provider Availability
-
-- provider account cooldown on transient/rate/auth errors
-- account fallback before failing request
-- combo model fallback when current model/provider path is exhausted
-
-## 2) Token Expiry
-
-- pre-check and refresh with retry for refreshable providers
-- 401/403 retry after refresh attempt in core path
-
-## 3) Stream Safety
-
-- disconnect-aware stream controller
-- translation stream with end-of-stream flush and `[DONE]` handling
-- usage estimation fallback when provider usage metadata is missing
-
-## 4) Cloud Sync Degradation
-
-- sync errors are surfaced but local runtime continues
-- scheduler has retry-capable logic, but periodic execution currently calls single-attempt sync by default
-
-## 5) Data Integrity
-
-- SQLite schema migrations and auto-upgrade hooks at startup
-- legacy JSON → SQLite migration compatibility path
-
-## Observability and Operational Signals
-
-Runtime visibility sources:
-
-- console logs from `src/sse/utils/logger.ts`
-- per-request usage aggregates in SQLite (`usage_history`, `call_logs`, `proxy_logs`)
-- textual request status log in `log.txt` (optional/compat)
-- optional deep request/translation logs under `logs/` when `ENABLE_REQUEST_LOGS=true`
-- dashboard usage endpoints (`/api/usage/*`) for UI consumption
-
-## Security-Sensitive Boundaries
-
-- JWT secret (`JWT_SECRET`) secures dashboard session cookie verification/signing
-- Initial password bootstrap (`INITIAL_PASSWORD`) should be explicitly configured for first-run provisioning
-- API key HMAC secret (`API_KEY_SECRET`) secures generated local API key format
-- Provider secrets (API keys/tokens) are persisted in local DB and should be protected at filesystem level
-- Cloud sync endpoints rely on API key auth + machine id semantics
-
-## Environment and Runtime Matrix
-
-Environment variables actively used by code:
-
-- App/auth: `JWT_SECRET`, `INITIAL_PASSWORD`
-- Storage: `DATA_DIR`
-- Compatible node behavior: `ALLOW_MULTI_CONNECTIONS_PER_COMPAT_NODE`
-- Optional storage base override (Linux/macOS when `DATA_DIR` unset): `XDG_CONFIG_HOME`
-- Security hashing: `API_KEY_SECRET`, `MACHINE_ID_SALT`
-- Logging: `ENABLE_REQUEST_LOGS`
-- Sync/cloud URLing: `NEXT_PUBLIC_BASE_URL`, `NEXT_PUBLIC_CLOUD_URL`
-- Outbound proxy: `HTTP_PROXY`, `HTTPS_PROXY`, `ALL_PROXY`, `NO_PROXY` and lowercase variants
-- SOCKS5 feature flags: `ENABLE_SOCKS5_PROXY`, `NEXT_PUBLIC_ENABLE_SOCKS5_PROXY`
-- Platform/runtime helpers (not app-specific config): `APPDATA`, `NODE_ENV`, `PORT`, `HOSTNAME`
-
-## Known Architectural Notes
-
-1. `usageDb` and `localDb` share the same base directory policy (`DATA_DIR` -> `XDG_CONFIG_HOME/omniroute` -> `~/.omniroute`) with legacy file migration.
-2. `/api/v1/route.ts` delegates to the same unified catalog builder used by `/api/v1/models` (`src/app/api/v1/models/catalog.ts`) to avoid semantic drift.
-3. Request logger writes full headers/body when enabled; treat log directory as sensitive.
-4. Cloud behavior depends on correct `NEXT_PUBLIC_BASE_URL` and cloud endpoint reachability.
-5. The `open-sse/` directory is published as the `@omniroute/open-sse` **npm workspace package**. Source code imports it via `@omniroute/open-sse/...` (resolved by Next.js `transpilePackages`). File paths in this document still use the directory name `open-sse/` for consistency.
-6. Charts in the dashboard use **Recharts** (SVG-based) for accessible, interactive analytics visualizations (model usage bar charts, provider breakdown tables with success rates).
-7. E2E tests use **Playwright** (`tests/e2e/`), run via `npm run test:e2e`. Unit tests use **Node.js test runner** (`tests/unit/`), run via `npm run test:unit`. Source code under `src/` is **TypeScript** (`.ts`/`.tsx`); the `open-sse/` workspace remains JavaScript (`.js`).
-8. Settings page is organized into 5 tabs: Security, Routing (6 global strategies: fill-first, round-robin, p2c, random, least-used, cost-optimized), Resilience (editable rate limits, circuit breaker, policies), AI (thinking budget, system prompt, prompt cache), Advanced (proxy).
-
-## Operational Verification Checklist
-
-- Build from source: `npm run build`
-- Build Docker image: `docker build -t omniroute .`
-- Start service and verify:
-- `GET /api/settings`
-- `GET /api/v1/models`
-- CLI target base URL should be `http://:20128/v1` when `PORT=20128`
diff --git a/docs/i18n/es/AUTO-COMBO.md b/docs/i18n/es/AUTO-COMBO.md
deleted file mode 100644
index 2166e41dff..0000000000
--- a/docs/i18n/es/AUTO-COMBO.md
+++ /dev/null
@@ -1,67 +0,0 @@
-🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/AUTO-COMBO.md) · 🇪🇸 [es](../es/AUTO-COMBO.md) · 🇫🇷 [fr](../fr/AUTO-COMBO.md) · 🇩🇪 [de](../de/AUTO-COMBO.md) · 🇮🇹 [it](../it/AUTO-COMBO.md) · 🇷🇺 [ru](../ru/AUTO-COMBO.md) · 🇨🇳 [zh-CN](../zh-CN/AUTO-COMBO.md) · 🇯🇵 [ja](../ja/AUTO-COMBO.md) · 🇰🇷 [ko](../ko/AUTO-COMBO.md) · 🇸🇦 [ar](../ar/AUTO-COMBO.md) · 🇮🇳 [in](../in/AUTO-COMBO.md) · 🇹🇭 [th](../th/AUTO-COMBO.md) · 🇻🇳 [vi](../vi/AUTO-COMBO.md) · 🇮🇩 [id](../id/AUTO-COMBO.md) · 🇲🇾 [ms](../ms/AUTO-COMBO.md) · 🇳🇱 [nl](../nl/AUTO-COMBO.md) · 🇵🇱 [pl](../pl/AUTO-COMBO.md) · 🇸🇪 [sv](../sv/AUTO-COMBO.md) · 🇳🇴 [no](../no/AUTO-COMBO.md) · 🇩🇰 [da](../da/AUTO-COMBO.md) · 🇫🇮 [fi](../fi/AUTO-COMBO.md) · 🇵🇹 [pt](../pt/AUTO-COMBO.md) · 🇷🇴 [ro](../ro/AUTO-COMBO.md) · 🇭🇺 [hu](../hu/AUTO-COMBO.md) · 🇧🇬 [bg](../bg/AUTO-COMBO.md) · 🇸🇰 [sk](../sk/AUTO-COMBO.md) · 🇺🇦 [uk-UA](../uk-UA/AUTO-COMBO.md) · 🇮🇱 [he](../he/AUTO-COMBO.md) · 🇵🇭 [phi](../phi/AUTO-COMBO.md)
-
----
-
-# OmniRoute Auto-Combo Engine
-
-> Self-managing model chains with adaptive scoring
-
-## How It Works
-
-The Auto-Combo Engine dynamically selects the best provider/model for each request using a **6-factor scoring function**:
-
-| Factor | Weight | Description |
-| :--------- | :----- | :---------------------------------------------- |
-| Quota | 0.20 | Remaining capacity [0..1] |
-| Health | 0.25 | Circuit breaker: CLOSED=1.0, HALF=0.5, OPEN=0.0 |
-| CostInv | 0.20 | Inverse cost (cheaper = higher score) |
-| LatencyInv | 0.15 | Inverse p95 latency (faster = higher) |
-| TaskFit | 0.10 | Model × task type fitness score |
-| Stability | 0.10 | Low variance in latency/errors |
-
-## Mode Packs
-
-| Pack | Focus | Key Weight |
-| :---------------------- | :----------- | :--------------- |
-| 🚀 **Ship Fast** | Speed | latencyInv: 0.35 |
-| 💰 **Cost Saver** | Economy | costInv: 0.40 |
-| 🎯 **Quality First** | Best model | taskFit: 0.40 |
-| 📡 **Offline Friendly** | Availability | quota: 0.40 |
-
-## Self-Healing
-
-- **Temporary exclusion**: Score < 0.2 → excluded for 5 min (progressive backoff, max 30 min)
-- **Circuit breaker awareness**: OPEN → auto-excluded; HALF_OPEN → probe requests
-- **Incident mode**: >50% OPEN → disable exploration, maximize stability
-- **Cooldown recovery**: After exclusion, first request is a "probe" with reduced timeout
-
-## Bandit Exploration
-
-5% of requests (configurable) are routed to random providers for exploration. Disabled in incident mode.
-
-## API
-
-```bash
-# Create auto-combo
-curl -X POST http://localhost:20128/api/combos/auto \
- -H "Content-Type: application/json" \
- -d '{"id":"my-auto","name":"Auto Coder","candidatePool":["anthropic","google","openai"],"modePack":"ship-fast"}'
-
-# List auto-combos
-curl http://localhost:20128/api/combos/auto
-```
-
-## Task Fitness
-
-30+ models scored across 6 task types (`coding`, `review`, `planning`, `analysis`, `debugging`, `documentation`). Supports wildcard patterns (e.g., `*-coder` → high coding score).
-
-## Files
-
-| File | Purpose |
-| :------------------------------------------- | :------------------------------------ |
-| `open-sse/services/autoCombo/scoring.ts` | Scoring function & pool normalization |
-| `open-sse/services/autoCombo/taskFitness.ts` | Model × task fitness lookup |
-| `open-sse/services/autoCombo/engine.ts` | Selection logic, bandit, budget cap |
-| `open-sse/services/autoCombo/selfHealing.ts` | Exclusion, probes, incident mode |
-| `open-sse/services/autoCombo/modePacks.ts` | 4 weight profiles |
-| `src/app/api/combos/auto/route.ts` | REST API |
diff --git a/docs/i18n/es/CHANGELOG.md b/docs/i18n/es/CHANGELOG.md
index eb4136c683..9e8c1dfb8b 100644
--- a/docs/i18n/es/CHANGELOG.md
+++ b/docs/i18n/es/CHANGELOG.md
@@ -1,12 +1,92 @@
# Changelog (Español)
-🌐 **Languages:** 🇺🇸 [English](../../../CHANGELOG.md) · 🇪🇸 [es](../es/CHANGELOG.md) · 🇫🇷 [fr](../fr/CHANGELOG.md) · 🇩🇪 [de](../de/CHANGELOG.md) · 🇮🇹 [it](../it/CHANGELOG.md) · 🇷🇺 [ru](../ru/CHANGELOG.md) · 🇨🇳 [zh-CN](../zh-CN/CHANGELOG.md) · 🇯🇵 [ja](../ja/CHANGELOG.md) · 🇰🇷 [ko](../ko/CHANGELOG.md) · 🇸🇦 [ar](../ar/CHANGELOG.md) · 🇮🇳 [in](../in/CHANGELOG.md) · 🇹🇭 [th](../th/CHANGELOG.md) · 🇻🇳 [vi](../vi/CHANGELOG.md) · 🇮🇩 [id](../id/CHANGELOG.md) · 🇲🇾 [ms](../ms/CHANGELOG.md) · 🇳🇱 [nl](../nl/CHANGELOG.md) · 🇵🇱 [pl](../pl/CHANGELOG.md) · 🇸🇪 [sv](../sv/CHANGELOG.md) · 🇳🇴 [no](../no/CHANGELOG.md) · 🇩🇰 [da](../da/CHANGELOG.md) · 🇫🇮 [fi](../fi/CHANGELOG.md) · 🇵🇹 [pt](../pt/CHANGELOG.md) · 🇷🇴 [ro](../ro/CHANGELOG.md) · 🇭🇺 [hu](../hu/CHANGELOG.md) · 🇧🇬 [bg](../bg/CHANGELOG.md) · 🇸🇰 [sk](../sk/CHANGELOG.md) · 🇺🇦 [uk-UA](../uk-UA/CHANGELOG.md) · 🇮🇱 [he](../he/CHANGELOG.md) · 🇵🇭 [phi](../phi/CHANGELOG.md) · 🇧🇷 [pt-BR](../pt-BR/CHANGELOG.md)
+🌐 **Languages:** 🇺🇸 [English](../../../CHANGELOG.md) · 🇪🇸 [es](../es/CHANGELOG.md) · 🇫🇷 [fr](../fr/CHANGELOG.md) · 🇩🇪 [de](../de/CHANGELOG.md) · 🇮🇹 [it](../it/CHANGELOG.md) · 🇷🇺 [ru](../ru/CHANGELOG.md) · 🇨🇳 [zh-CN](../zh-CN/CHANGELOG.md) · 🇯🇵 [ja](../ja/CHANGELOG.md) · 🇰🇷 [ko](../ko/CHANGELOG.md) · 🇸🇦 [ar](../ar/CHANGELOG.md) · 🇮🇳 [in](../in/CHANGELOG.md) · 🇹🇭 [th](../th/CHANGELOG.md) · 🇻🇳 [vi](../vi/CHANGELOG.md) · 🇮🇩 [id](../id/CHANGELOG.md) · 🇲🇾 [ms](../ms/CHANGELOG.md) · 🇳🇱 [nl](../nl/CHANGELOG.md) · 🇵🇱 [pl](../pl/CHANGELOG.md) · 🇸🇪 [sv](../sv/CHANGELOG.md) · 🇳🇴 [no](../no/CHANGELOG.md) · 🇩🇰 [da](../da/CHANGELOG.md) · 🇫🇮 [fi](../fi/CHANGELOG.md) · 🇵🇹 [pt](../pt/CHANGELOG.md) · 🇷🇴 [ro](../ro/CHANGELOG.md) · 🇭🇺 [hu](../hu/CHANGELOG.md) · 🇧🇬 [bg](../bg/CHANGELOG.md) · 🇸🇰 [sk](../sk/CHANGELOG.md) · 🇺🇦 [uk-UA](../uk-UA/CHANGELOG.md) · 🇮🇱 [he](../he/CHANGELOG.md) · 🇵🇭 [phi](../phi/CHANGELOG.md) · 🇧🇷 [pt-BR](../pt-BR/CHANGELOG.md) · 🇨🇿 [cs](../cs/CHANGELOG.md)
---
-
## [Unreleased]
+### 🛠️ Maintenance
+
+- **AGENTS.md rewrite:** Condensed from 297→153 lines. Added build/lint/test commands (including single-test execution), code style guidelines (Prettier, TypeScript, ESLint, naming, imports, error handling, security), and trimmed verbose architecture tables for AI agent consumption.
+
+## [3.4.2] - 2026-04-01
+
+### 🐛 Bug Fixes
+
+- **CI Stabilization:** Fixed failing analytics/settings Playwright selectors and request assertions so GitHub Actions E2E runs pass reliably across localized UIs and switch-based controls.
+- **Deterministic Tests:** Removed date-sensitive quota fixtures from Copilot usage tests and aligned idempotency/model catalog tests with the merged runtime behavior.
+- **MCP Type Hardening:** Removed zero-budget explicit `any` regressions from the MCP server tool registration path, restoring the `check:any-budget:t11` workflow gate.
+
+### 🛠️ Maintenance
+
+- **Release Branch Integration:** Consolidated the active feature branches into `release/v3.4.2` on top of current `main` and validated the branch with lint, unit, coverage, build, and CI-mode E2E runs.
+
+## [3.4.1] - 2026-03-31
+
+> [!WARNING]
+> **BREAKING CHANGE: request logging, retention, and logging environment variables have been redesigned.**
+> On the first startup after upgrading, OmniRoute archives legacy request logs from `DATA_DIR/logs/`, legacy `DATA_DIR/call_logs/`, and `DATA_DIR/log.txt` into `DATA_DIR/log_archives/*.zip`, then removes the deprecated layout and switches to the new unified artifact format under `DATA_DIR/call_logs/`.
+
+### ✨ New Features
+
+- **.ENV Migration Utility:** Included `scripts/migrate-env.mjs` to seamlessly migrate ` Your key looks like: `sk-xxxxxxxxxxxxxxxx-xxxxxxxxx`
-
----
-
-## Step 2 — Install CLI Tools
-
-All npm-based tools require Node.js 18+:
-
-```bash
-# Claude Code (Anthropic)
-npm install -g @anthropic-ai/claude-code
-
-# OpenAI Codex
-npm install -g @openai/codex
-
-# Gemini CLI (Google)
-npm install -g @google/gemini-cli
-
-# OpenCode
-npm install -g opencode-ai
-
-# Cline
-npm install -g cline
-
-# KiloCode
-npm install -g kilecode
-
-# Kiro CLI (Amazon — requires curl + unzip)
-apt-get install -y unzip # on Debian/Ubuntu
-curl -fsSL https://cli.kiro.dev/install | bash
-export PATH="$HOME/.local/bin:$PATH" # add to ~/.bashrc
-```
-
-**Verify:**
-
-```bash
-claude --version # 2.x.x
-codex --version # 0.x.x
-gemini --version # 0.x.x
-opencode --version # x.x.x
-cline --version # 2.x.x
-kilocode --version # x.x.x (or: kilo --version)
-kiro-cli --version # 1.x.x
-```
-
----
-
-## Step 3 — Set Global Environment Variables
-
-Add to `~/.bashrc` (or `~/.zshrc`), then run `source ~/.bashrc`:
-
-```bash
-# OmniRoute Universal Endpoint
-export OPENAI_BASE_URL="http://localhost:20128/v1"
-export OPENAI_API_KEY="sk-your-omniroute-key"
-export ANTHROPIC_BASE_URL="http://localhost:20128/v1"
-export ANTHROPIC_API_KEY="sk-your-omniroute-key"
-export GEMINI_BASE_URL="http://localhost:20128/v1"
-export GEMINI_API_KEY="sk-your-omniroute-key"
-```
-
-> For a **remote server** replace `localhost:20128` with the server IP or domain,
-> e.g. `http://192.168.0.15:20128`.
-
----
-
-## Step 4 — Configure Each Tool
-
-### Claude Code
-
-```bash
-# Via CLI:
-claude config set --global api-base-url http://localhost:20128/v1
-
-# Or create ~/.claude/settings.json:
-mkdir -p ~/.claude && cat > ~/.claude/settings.json << EOF
-{
- "apiBaseUrl": "http://localhost:20128/v1",
- "apiKey": "sk-your-omniroute-key"
-}
-EOF
-```
-
-**Test:** `claude "say hello"`
-
----
-
-### OpenAI Codex
-
-```bash
-mkdir -p ~/.codex && cat > ~/.codex/config.yaml << EOF
-model: auto
-apiKey: sk-your-omniroute-key
-apiBaseUrl: http://localhost:20128/v1
-EOF
-```
-
-**Test:** `codex "what is 2+2?"`
-
----
-
-### Gemini CLI
-
-```bash
-mkdir -p ~/.gemini && cat > ~/.gemini/settings.json << EOF
-{
- "apiKey": "sk-your-omniroute-key",
- "baseUrl": "http://localhost:20128/v1"
-}
-EOF
-```
-
-**Test:** `gemini "hello"`
-
----
-
-### OpenCode
-
-```bash
-mkdir -p ~/.config/opencode && cat > ~/.config/opencode/config.toml << EOF
-[provider.openai]
-base_url = "http://localhost:20128/v1"
-api_key = "sk-your-omniroute-key"
-EOF
-```
-
-**Test:** `opencode`
-
----
-
-### Cline (CLI or VS Code)
-
-**CLI mode:**
-
-```bash
-mkdir -p ~/.cline/data && cat > ~/.cline/data/globalState.json << EOF
-{
- "apiProvider": "openai",
- "openAiBaseUrl": "http://localhost:20128/v1",
- "openAiApiKey": "sk-your-omniroute-key"
-}
-EOF
-```
-
-**VS Code mode:**
-Cline extension settings → API Provider: `OpenAI Compatible` → Base URL: `http://localhost:20128/v1`
-
-Or use the OmniRoute dashboard → **CLI Tools → Cline → Apply Config**.
-
----
-
-### KiloCode (CLI or VS Code)
-
-**CLI mode:**
-
-```bash
-kilocode --api-base http://localhost:20128/v1 --api-key sk-your-omniroute-key
-```
-
-**VS Code settings:**
-
-```json
-{
- "kilo-code.openAiBaseUrl": "http://localhost:20128/v1",
- "kilo-code.apiKey": "sk-your-omniroute-key"
-}
-```
-
-Or use the OmniRoute dashboard → **CLI Tools → KiloCode → Apply Config**.
-
----
-
-### Continue (VS Code Extension)
-
-Edit `~/.continue/config.yaml`:
-
-```yaml
-models:
- - name: OmniRoute
- provider: openai
- model: auto
- apiBase: http://localhost:20128/v1
- apiKey: sk-your-omniroute-key
- default: true
-```
-
-Restart VS Code after editing.
-
----
-
-### Kiro CLI (Amazon)
-
-```bash
-# Login to your AWS/Kiro account:
-kiro-cli login
-
-# The CLI uses its own auth — OmniRoute is not needed as backend for Kiro CLI itself.
-# Use kiro-cli alongside OmniRoute for other tools.
-kiro-cli status
-```
-
----
-
-### Cursor (Desktop App)
-
-> **Note:** Cursor routes requests through its cloud. For OmniRoute integration,
-> enable **Cloud Endpoint** in OmniRoute Settings and use your public domain URL.
-
-Via GUI: **Settings → Models → OpenAI API Key**
-
-- Base URL: `https://your-domain.com/v1`
-- API Key: your OmniRoute key
-
----
-
-## Dashboard Auto-Configuration
-
-The OmniRoute dashboard automates configuration for most tools:
-
-1. Go to `http://localhost:20128/dashboard/cli-tools`
-2. Expand any tool card
-3. Select your API key from the dropdown
-4. Click **Apply Config** (if tool is detected as installed)
-5. Or copy the generated config snippet manually
-
----
-
-## Built-in Agents: Droid & OpenClaw
-
-**Droid** and **OpenClaw** are AI agents built directly into OmniRoute — no installation needed.
-They run as internal routes and use OmniRoute's model routing automatically.
-
-- Access: `http://localhost:20128/dashboard/agents`
-- Configure: same combos and providers as all other tools
-- No API key or CLI install required
-
----
-
-## Available API Endpoints
-
-| Endpoint | Description | Use For |
-| -------------------------- | ----------------------------- | --------------------------- |
-| `/v1/chat/completions` | Standard chat (all providers) | All modern tools |
-| `/v1/responses` | Responses API (OpenAI format) | Codex, agentic workflows |
-| `/v1/completions` | Legacy text completions | Older tools using `prompt:` |
-| `/v1/embeddings` | Text embeddings | RAG, search |
-| `/v1/images/generations` | Image generation | DALL-E, Flux, etc. |
-| `/v1/audio/speech` | Text-to-speech | ElevenLabs, OpenAI TTS |
-| `/v1/audio/transcriptions` | Speech-to-text | Deepgram, AssemblyAI |
-
----
-
-## Troubleshooting
-
-| Error | Cause | Fix |
-| ------------------------- | ----------------------- | ------------------------------------------ |
-| `Connection refused` | OmniRoute not running | `pm2 start omniroute` |
-| `401 Unauthorized` | Wrong API key | Check in `/dashboard/api-manager` |
-| `No combo configured` | No active routing combo | Set up in `/dashboard/combos` |
-| `invalid model` | Model not in catalog | Use `auto` or check `/dashboard/providers` |
-| CLI shows "not installed" | Binary not in PATH | Check `which ` |
-| `kiro-cli: not found` | Not in PATH | `export PATH="$HOME/.local/bin:$PATH"` |
-
----
-
-## Quick Setup Script (One Command)
-
-```bash
-# Install all CLIs and configure for OmniRoute (replace with your key and server URL)
-OMNIROUTE_URL="http://localhost:20128/v1"
-OMNIROUTE_KEY="sk-your-omniroute-key"
-
-npm install -g @anthropic-ai/claude-code @openai/codex @google/gemini-cli opencode-ai cline kilecode
-
-# Kiro CLI
-apt-get install -y unzip 2>/dev/null; curl -fsSL https://cli.kiro.dev/install | bash
-
-# Write configs
-mkdir -p ~/.claude ~/.codex ~/.gemini ~/.config/opencode ~/.continue
-
-cat > ~/.claude/settings.json <<< "{\"apiBaseUrl\":\"$OMNIROUTE_URL\",\"apiKey\":\"$OMNIROUTE_KEY\"}"
-cat > ~/.codex/config.yaml <<< "model: auto\napiKey: $OMNIROUTE_KEY\napiBaseUrl: $OMNIROUTE_URL"
-cat > ~/.gemini/settings.json <<< "{\"apiKey\":\"$OMNIROUTE_KEY\",\"baseUrl\":\"$OMNIROUTE_URL\"}"
-cat >> ~/.bashrc << EOF
-export OPENAI_BASE_URL="$OMNIROUTE_URL"
-export OPENAI_API_KEY="$OMNIROUTE_KEY"
-export ANTHROPIC_BASE_URL="$OMNIROUTE_URL"
-export ANTHROPIC_API_KEY="$OMNIROUTE_KEY"
-EOF
-
-source ~/.bashrc
-echo "✅ All CLIs installed and configured for OmniRoute"
-```
diff --git a/docs/i18n/es/CODEBASE_DOCUMENTATION.md b/docs/i18n/es/CODEBASE_DOCUMENTATION.md
deleted file mode 100644
index e2d7950052..0000000000
--- a/docs/i18n/es/CODEBASE_DOCUMENTATION.md
+++ /dev/null
@@ -1,593 +0,0 @@
-🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/CODEBASE_DOCUMENTATION.md) · 🇪🇸 [es](../es/CODEBASE_DOCUMENTATION.md) · 🇫🇷 [fr](../fr/CODEBASE_DOCUMENTATION.md) · 🇩🇪 [de](../de/CODEBASE_DOCUMENTATION.md) · 🇮🇹 [it](../it/CODEBASE_DOCUMENTATION.md) · 🇷🇺 [ru](../ru/CODEBASE_DOCUMENTATION.md) · 🇨🇳 [zh-CN](../zh-CN/CODEBASE_DOCUMENTATION.md) · 🇯🇵 [ja](../ja/CODEBASE_DOCUMENTATION.md) · 🇰🇷 [ko](../ko/CODEBASE_DOCUMENTATION.md) · 🇸🇦 [ar](../ar/CODEBASE_DOCUMENTATION.md) · 🇮🇳 [in](../in/CODEBASE_DOCUMENTATION.md) · 🇹🇭 [th](../th/CODEBASE_DOCUMENTATION.md) · 🇻🇳 [vi](../vi/CODEBASE_DOCUMENTATION.md) · 🇮🇩 [id](../id/CODEBASE_DOCUMENTATION.md) · 🇲🇾 [ms](../ms/CODEBASE_DOCUMENTATION.md) · 🇳🇱 [nl](../nl/CODEBASE_DOCUMENTATION.md) · 🇵🇱 [pl](../pl/CODEBASE_DOCUMENTATION.md) · 🇸🇪 [sv](../sv/CODEBASE_DOCUMENTATION.md) · 🇳🇴 [no](../no/CODEBASE_DOCUMENTATION.md) · 🇩🇰 [da](../da/CODEBASE_DOCUMENTATION.md) · 🇫🇮 [fi](../fi/CODEBASE_DOCUMENTATION.md) · 🇵🇹 [pt](../pt/CODEBASE_DOCUMENTATION.md) · 🇷🇴 [ro](../ro/CODEBASE_DOCUMENTATION.md) · 🇭🇺 [hu](../hu/CODEBASE_DOCUMENTATION.md) · 🇧🇬 [bg](../bg/CODEBASE_DOCUMENTATION.md) · 🇸🇰 [sk](../sk/CODEBASE_DOCUMENTATION.md) · 🇺🇦 [uk-UA](../uk-UA/CODEBASE_DOCUMENTATION.md) · 🇮🇱 [he](../he/CODEBASE_DOCUMENTATION.md) · 🇵🇭 [phi](../phi/CODEBASE_DOCUMENTATION.md)
-
----
-
-# omniroute — Codebase Documentation
-
-🌐 **Languages:** 🇺🇸 [English](CODEBASE_DOCUMENTATION.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/CODEBASE_DOCUMENTATION.md) | 🇪🇸 [Español](i18n/es/CODEBASE_DOCUMENTATION.md) | 🇫🇷 [Français](i18n/fr/CODEBASE_DOCUMENTATION.md) | 🇮🇹 [Italiano](i18n/it/CODEBASE_DOCUMENTATION.md) | 🇷🇺 [Русский](i18n/ru/CODEBASE_DOCUMENTATION.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/CODEBASE_DOCUMENTATION.md) | 🇩🇪 [Deutsch](i18n/de/CODEBASE_DOCUMENTATION.md) | 🇮🇳 [हिन्दी](i18n/in/CODEBASE_DOCUMENTATION.md) | 🇹🇭 [ไทย](i18n/th/CODEBASE_DOCUMENTATION.md) | 🇺🇦 [Українська](i18n/uk-UA/CODEBASE_DOCUMENTATION.md) | 🇸🇦 [العربية](i18n/ar/CODEBASE_DOCUMENTATION.md) | 🇯🇵 [日本語](i18n/ja/CODEBASE_DOCUMENTATION.md) | 🇻🇳 [Tiếng Việt](i18n/vi/CODEBASE_DOCUMENTATION.md) | 🇧🇬 [Български](i18n/bg/CODEBASE_DOCUMENTATION.md) | 🇩🇰 [Dansk](i18n/da/CODEBASE_DOCUMENTATION.md) | 🇫🇮 [Suomi](i18n/fi/CODEBASE_DOCUMENTATION.md) | 🇮🇱 [עברית](i18n/he/CODEBASE_DOCUMENTATION.md) | 🇭🇺 [Magyar](i18n/hu/CODEBASE_DOCUMENTATION.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/CODEBASE_DOCUMENTATION.md) | 🇰🇷 [한국어](i18n/ko/CODEBASE_DOCUMENTATION.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/CODEBASE_DOCUMENTATION.md) | 🇳🇱 [Nederlands](i18n/nl/CODEBASE_DOCUMENTATION.md) | 🇳🇴 [Norsk](i18n/no/CODEBASE_DOCUMENTATION.md) | 🇵🇹 [Português (Portugal)](i18n/pt/CODEBASE_DOCUMENTATION.md) | 🇷🇴 [Română](i18n/ro/CODEBASE_DOCUMENTATION.md) | 🇵🇱 [Polski](i18n/pl/CODEBASE_DOCUMENTATION.md) | 🇸🇰 [Slovenčina](i18n/sk/CODEBASE_DOCUMENTATION.md) | 🇸🇪 [Svenska](i18n/sv/CODEBASE_DOCUMENTATION.md) | 🇵🇭 [Filipino](i18n/phi/CODEBASE_DOCUMENTATION.md)
-
-> A comprehensive, beginner-friendly guide to the **omniroute** multi-provider AI proxy router.
-
----
-
-## 1. What Is omniroute?
-
-omniroute is a **proxy router** that sits between AI clients (Claude CLI, Codex, Cursor IDE, etc.) and AI providers (Anthropic, Google, OpenAI, AWS, GitHub, etc.). It solves one big problem:
-
-> **Different AI clients speak different "languages" (API formats), and different AI providers expect different "languages" too.** omniroute translates between them automatically.
-
-Think of it like a universal translator at the United Nations — any delegate can speak any language, and the translator converts it for any other delegate.
-
----
-
-## 2. Architecture Overview
-
-```mermaid
-graph LR
- subgraph Clients
- A[Claude CLI]
- B[Codex]
- C[Cursor IDE]
- D[OpenAI-compatible]
- end
-
- subgraph omniroute
- E[Handler Layer]
- F[Translator Layer]
- G[Executor Layer]
- H[Services Layer]
- end
-
- subgraph Providers
- I[Anthropic Claude]
- J[Google Gemini]
- K[OpenAI / Codex]
- L[GitHub Copilot]
- M[AWS Kiro]
- N[Antigravity]
- O[Cursor API]
- end
-
- A --> E
- B --> E
- C --> E
- D --> E
- E --> F
- F --> G
- G --> I
- G --> J
- G --> K
- G --> L
- G --> M
- G --> N
- G --> O
- H -.-> E
- H -.-> G
-```
-
-### Core Principle: Hub-and-Spoke Translation
-
-All format translation passes through **OpenAI format as the hub**:
-
-```
-Client Format → [OpenAI Hub] → Provider Format (request)
-Provider Format → [OpenAI Hub] → Client Format (response)
-```
-
-This means you only need **N translators** (one per format) instead of **N²** (every pair).
-
----
-
-## 3. Project Structure
-
-```
-omniroute/
-├── open-sse/ ← Core proxy library (portable, framework-agnostic)
-│ ├── index.js ← Main entry point, exports everything
-│ ├── config/ ← Configuration & constants
-│ ├── executors/ ← Provider-specific request execution
-│ ├── handlers/ ← Request handling orchestration
-│ ├── services/ ← Business logic (auth, models, fallback, usage)
-│ ├── translator/ ← Format translation engine
-│ │ ├── request/ ← Request translators (8 files)
-│ │ ├── response/ ← Response translators (7 files)
-│ │ └── helpers/ ← Shared translation utilities (6 files)
-│ └── utils/ ← Utility functions
-├── src/ ← Application layer (Express/Worker runtime)
-│ ├── app/ ← Web UI, API routes, middleware
-│ ├── lib/ ← Database, auth, and shared library code
-│ ├── mitm/ ← Man-in-the-middle proxy utilities
-│ ├── models/ ← Database models
-│ ├── shared/ ← Shared utilities (wrappers around open-sse)
-│ ├── sse/ ← SSE endpoint handlers
-│ └── store/ ← State management
-├── data/ ← Runtime data (credentials, logs)
-│ └── provider-credentials.json (external credentials override, gitignored)
-└── tester/ ← Test utilities
-```
-
----
-
-## 4. Module-by-Module Breakdown
-
-### 4.1 Config (`open-sse/config/`)
-
-The **single source of truth** for all provider configuration.
-
-| File | Purpose |
-| ----------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| `constants.ts` | `PROVIDERS` object with base URLs, OAuth credentials (defaults), headers, and default system prompts for every provider. Also defines `HTTP_STATUS`, `ERROR_TYPES`, `COOLDOWN_MS`, `BACKOFF_CONFIG`, and `SKIP_PATTERNS`. |
-| `credentialLoader.ts` | Loads external credentials from `data/provider-credentials.json` and merges them over the hardcoded defaults in `PROVIDERS`. Keeps secrets out of source control while maintaining backwards compatibility. |
-| `providerModels.ts` | Central model registry: maps provider aliases → model IDs. Functions like `getModels()`, `getProviderByAlias()`. |
-| `codexInstructions.ts` | System instructions injected into Codex requests (editing constraints, sandbox rules, approval policies). |
-| `defaultThinkingSignature.ts` | Default "thinking" signatures for Claude and Gemini models. |
-| `ollamaModels.ts` | Schema definition for local Ollama models (name, size, family, quantization). |
-
-#### Credential Loading Flow
-
-```mermaid
-flowchart TD
- A["App starts"] --> B["constants.ts defines PROVIDERS\nwith hardcoded defaults"]
- B --> C{"data/provider-credentials.json\nexists?"}
- C -->|Yes| D["credentialLoader reads JSON"]
- C -->|No| E["Use hardcoded defaults"]
- D --> F{"For each provider in JSON"}
- F --> G{"Provider exists\nin PROVIDERS?"}
- G -->|No| H["Log warning, skip"]
- G -->|Yes| I{"Value is object?"}
- I -->|No| J["Log warning, skip"]
- I -->|Yes| K["Merge clientId, clientSecret,\ntokenUrl, authUrl, refreshUrl"]
- K --> F
- H --> F
- J --> F
- F -->|Done| L["PROVIDERS ready with\nmerged credentials"]
- E --> L
-```
-
----
-
-### 4.2 Executors (`open-sse/executors/`)
-
-Executors encapsulate **provider-specific logic** using the **Strategy Pattern**. Each executor overrides base methods as needed.
-
-```mermaid
-classDiagram
- class BaseExecutor {
- +buildUrl(model, stream, options)
- +buildHeaders(credentials, stream, body)
- +transformRequest(body, model, stream, credentials)
- +execute(url, options)
- +shouldRetry(status, error)
- +refreshCredentials(credentials, log)
- }
-
- class DefaultExecutor {
- +refreshCredentials()
- }
-
- class AntigravityExecutor {
- +buildUrl()
- +buildHeaders()
- +transformRequest()
- +shouldRetry()
- +refreshCredentials()
- }
-
- class CursorExecutor {
- +buildUrl()
- +buildHeaders()
- +transformRequest()
- +parseResponse()
- +generateChecksum()
- }
-
- class KiroExecutor {
- +buildUrl()
- +buildHeaders()
- +transformRequest()
- +parseEventStream()
- +refreshCredentials()
- }
-
- BaseExecutor <|-- DefaultExecutor
- BaseExecutor <|-- AntigravityExecutor
- BaseExecutor <|-- CursorExecutor
- BaseExecutor <|-- KiroExecutor
- BaseExecutor <|-- CodexExecutor
- BaseExecutor <|-- GeminiCLIExecutor
- BaseExecutor <|-- GithubExecutor
-```
-
-| Executor | Provider | Key Specializations |
-| ---------------- | ------------------------------------------ | ------------------------------------------------------------------------------------------------------------------- |
-| `base.ts` | — | Abstract base: URL building, headers, retry logic, credential refresh |
-| `default.ts` | Claude, Gemini, OpenAI, GLM, Kimi, MiniMax | Generic OAuth token refresh for standard providers |
-| `antigravity.ts` | Google Cloud Code | Project/session ID generation, multi-URL fallback, custom retry parsing from error messages ("reset after 2h7m23s") |
-| `cursor.ts` | Cursor IDE | **Most complex**: SHA-256 checksum auth, Protobuf request encoding, binary EventStream → SSE response parsing |
-| `codex.ts` | OpenAI Codex | Injects system instructions, manages thinking levels, removes unsupported parameters |
-| `gemini-cli.ts` | Google Gemini CLI | Custom URL building (`streamGenerateContent`), Google OAuth token refresh |
-| `github.ts` | GitHub Copilot | Dual token system (GitHub OAuth + Copilot token), VSCode header mimicking |
-| `kiro.ts` | AWS CodeWhisperer | AWS EventStream binary parsing, AMZN event frames, token estimation |
-| `index.ts` | — | Factory: maps provider name → executor class, with default fallback |
-
----
-
-### 4.3 Handlers (`open-sse/handlers/`)
-
-The **orchestration layer** — coordinates translation, execution, streaming, and error handling.
-
-| File | Purpose |
-| --------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| `chatCore.ts` | **Central orchestrator** (~600 lines). Handles the complete request lifecycle: format detection → translation → executor dispatch → streaming/non-streaming response → token refresh → error handling → usage logging. |
-| `responsesHandler.ts` | Adapter for OpenAI's Responses API: converts Responses format → Chat Completions → sends to `chatCore` → converts SSE back to Responses format. |
-| `embeddings.ts` | Embedding generation handler: resolves embedding model → provider, dispatches to provider API, returns OpenAI-compatible embedding response. Supports 6+ providers. |
-| `imageGeneration.ts` | Image generation handler: resolves image model → provider, supports OpenAI-compatible, Gemini-image (Antigravity), and fallback (Nebius) modes. Returns base64 or URL images. |
-
-#### Request Lifecycle (chatCore.ts)
-
-```mermaid
-sequenceDiagram
- participant Client
- participant chatCore
- participant Translator
- participant Executor
- participant Provider
-
- Client->>chatCore: Request (any format)
- chatCore->>chatCore: Detect source format
- chatCore->>chatCore: Check bypass patterns
- chatCore->>chatCore: Resolve model & provider
- chatCore->>Translator: Translate request (source → OpenAI → target)
- chatCore->>Executor: Get executor for provider
- Executor->>Executor: Build URL, headers, transform request
- Executor->>Executor: Refresh credentials if needed
- Executor->>Provider: HTTP fetch (streaming or non-streaming)
-
- alt Streaming
- Provider-->>chatCore: SSE stream
- chatCore->>chatCore: Pipe through SSE transform stream
- Note over chatCore: Transform stream translates
each chunk: target → OpenAI → source
- chatCore-->>Client: Translated SSE stream
- else Non-streaming
- Provider-->>chatCore: JSON response
- chatCore->>Translator: Translate response
- chatCore-->>Client: Translated JSON
- end
-
- alt Error (401, 429, 500...)
- chatCore->>Executor: Retry with credential refresh
- chatCore->>chatCore: Account fallback logic
- end
-```
-
----
-
-### 4.4 Services (`open-sse/services/`)
-
-Business logic that supports the handlers and executors.
-
-| File | Purpose |
-| -------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| `provider.ts` | **Format detection** (`detectFormat`): analyzes request body structure to identify Claude/OpenAI/Gemini/Antigravity/Responses formats (includes `max_tokens` heuristic for Claude). Also: URL building, header building, thinking config normalization. Supports `openai-compatible-*` and `anthropic-compatible-*` dynamic providers. |
-| `model.ts` | Model string parsing (`claude/model-name` → `{provider: "claude", model: "model-name"}`), alias resolution with collision detection, input sanitization (rejects path traversal/control chars), and model info resolution with async alias getter support. |
-| `accountFallback.ts` | Rate-limit handling: exponential backoff (1s → 2s → 4s → max 2min), account cooldown management, error classification (which errors trigger fallback vs. not). |
-| `tokenRefresh.ts` | OAuth token refresh for **every provider**: Google (Gemini, Antigravity), Claude, Codex, Qwen, Qoder, GitHub (OAuth + Copilot dual-token), Kiro (AWS SSO OIDC + Social Auth). Includes in-flight promise deduplication cache and retry with exponential backoff. |
-| `combo.ts` | **Combo models**: chains of fallback models. If model A fails with a fallback-eligible error, try model B, then C, etc. Returns actual upstream status codes. |
-| `usage.ts` | Fetches quota/usage data from provider APIs (GitHub Copilot quotas, Antigravity model quotas, Codex rate limits, Kiro usage breakdowns, Claude settings). |
-| `accountSelector.ts` | Smart account selection with scoring algorithm: considers priority, health status, round-robin position, and cooldown state to pick the optimal account for each request. |
-| `contextManager.ts` | Request context lifecycle management: creates and tracks per-request context objects with metadata (request ID, timestamps, provider info) for debugging and logging. |
-| `ipFilter.ts` | IP-based access control: supports allowlist and blocklist modes. Validates client IP against configured rules before processing API requests. |
-| `sessionManager.ts` | Session tracking with client fingerprinting: tracks active sessions using hashed client identifiers, monitors request counts, and provides session metrics. |
-| `signatureCache.ts` | Request signature-based deduplication cache: prevents duplicate requests by caching recent request signatures and returning cached responses for identical requests within a time window. |
-| `systemPrompt.ts` | Global system prompt injection: prepends or appends a configurable system prompt to all requests, with per-provider compatibility handling. |
-| `thinkingBudget.ts` | Reasoning token budget management: supports passthrough, auto (strip thinking config), custom (fixed budget), and adaptive (complexity-scaled) modes for controlling thinking/reasoning tokens. |
-| `wildcardRouter.ts` | Wildcard model pattern routing: resolves wildcard patterns (e.g., `*/claude-*`) to concrete provider/model pairs based on availability and priority. |
-
-#### Token Refresh Deduplication
-
-```mermaid
-sequenceDiagram
- participant R1 as Request 1
- participant R2 as Request 2
- participant Cache as refreshPromiseCache
- participant OAuth as OAuth Provider
-
- R1->>Cache: getAccessToken("gemini", token)
- Cache->>Cache: No in-flight promise
- Cache->>OAuth: Start refresh
- R2->>Cache: getAccessToken("gemini", token)
- Cache->>Cache: Found in-flight promise
- Cache-->>R2: Return existing promise
- OAuth-->>Cache: New access token
- Cache-->>R1: New access token
- Cache-->>R2: Same access token (shared)
- Cache->>Cache: Delete cache entry
-```
-
-#### Account Fallback State Machine
-
-```mermaid
-stateDiagram-v2
- [*] --> Active
- Active --> Error: Request fails (401/429/500)
- Error --> Cooldown: Apply backoff
- Cooldown --> Active: Cooldown expires
- Active --> Active: Request succeeds (reset backoff)
-
- state Error {
- [*] --> ClassifyError
- ClassifyError --> ShouldFallback: Rate limit / Auth / Transient
- ClassifyError --> NoFallback: 400 Bad Request
- }
-
- state Cooldown {
- [*] --> ExponentialBackoff
- ExponentialBackoff: Level 0 = 1s
- ExponentialBackoff: Level 1 = 2s
- ExponentialBackoff: Level 2 = 4s
- ExponentialBackoff: Max = 2min
- }
-```
-
-#### Combo Model Chain
-
-```mermaid
-flowchart LR
- A["Request with\ncombo model"] --> B["Model A"]
- B -->|"2xx Success"| C["Return response"]
- B -->|"429/401/500"| D{"Fallback\neligible?"}
- D -->|Yes| E["Model B"]
- D -->|No| F["Return error"]
- E -->|"2xx Success"| C
- E -->|"429/401/500"| G{"Fallback\neligible?"}
- G -->|Yes| H["Model C"]
- G -->|No| F
- H -->|"2xx Success"| C
- H -->|"Fail"| I["All failed →\nReturn last status"]
-```
-
----
-
-### 4.5 Translator (`open-sse/translator/`)
-
-The **format translation engine** using a self-registering plugin system.
-
-#### Architecture
-
-```mermaid
-graph TD
- subgraph "Request Translation"
- A["Claude → OpenAI"]
- B["Gemini → OpenAI"]
- C["Antigravity → OpenAI"]
- D["OpenAI Responses → OpenAI"]
- E["OpenAI → Claude"]
- F["OpenAI → Gemini"]
- G["OpenAI → Kiro"]
- H["OpenAI → Cursor"]
- end
-
- subgraph "Response Translation"
- I["Claude → OpenAI"]
- J["Gemini → OpenAI"]
- K["Kiro → OpenAI"]
- L["Cursor → OpenAI"]
- M["OpenAI → Claude"]
- N["OpenAI → Antigravity"]
- O["OpenAI → Responses"]
- end
-```
-
-| Directory | Files | Description |
-| ------------ | ------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| `request/` | 8 translators | Convert request bodies between formats. Each file self-registers via `register(from, to, fn)` on import. |
-| `response/` | 7 translators | Convert streaming response chunks between formats. Handles SSE event types, thinking blocks, tool calls. |
-| `helpers/` | 6 helpers | Shared utilities: `claudeHelper` (system prompt extraction, thinking config), `geminiHelper` (parts/contents mapping), `openaiHelper` (format filtering), `toolCallHelper` (ID generation, missing response injection), `maxTokensHelper`, `responsesApiHelper`. |
-| `index.ts` | — | Translation engine: `translateRequest()`, `translateResponse()`, state management, registry. |
-| `formats.ts` | — | Format constants: `OPENAI`, `CLAUDE`, `GEMINI`, `ANTIGRAVITY`, `KIRO`, `CURSOR`, `OPENAI_RESPONSES`. |
-
-#### Key Design: Self-Registering Plugins
-
-```javascript
-// Each translator file calls register() on import:
-import { register } from "../index.js";
-register("claude", "openai", translateClaudeToOpenAI);
-
-// The index.js imports all translator files, triggering registration:
-import "./request/claude-to-openai.js"; // ← self-registers
-```
-
----
-
-### 4.6 Utils (`open-sse/utils/`)
-
-| File | Purpose |
-| ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
-| `error.ts` | Error response building (OpenAI-compatible format), upstream error parsing, Antigravity retry-time extraction from error messages, SSE error streaming. |
-| `stream.ts` | **SSE Transform Stream** — the core streaming pipeline. Two modes: `TRANSLATE` (full format translation) and `PASSTHROUGH` (normalize + extract usage). Handles chunk buffering, usage estimation, content length tracking. Per-stream encoder/decoder instances avoid shared state. |
-| `streamHelpers.ts` | Low-level SSE utilities: `parseSSELine` (whitespace-tolerant), `hasValuableContent` (filters empty chunks for OpenAI/Claude/Gemini), `fixInvalidId`, `formatSSE` (format-aware SSE serialization with `perf_metrics` cleanup). |
-| `usageTracking.ts` | Token usage extraction from any format (Claude/OpenAI/Gemini/Responses), estimation with separate tool/message char-per-token ratios, buffer addition (2000 tokens safety margin), format-specific field filtering, console logging with ANSI colors. |
-| `requestLogger.ts` | File-based request logging (opt-in via `ENABLE_REQUEST_LOGS=true`). Creates session folders with numbered files: `1_req_client.json` → `7_res_client.txt`. All I/O is async (fire-and-forget). Masks sensitive headers. |
-| `bypassHandler.ts` | Intercepts specific patterns from Claude CLI (title extraction, warmup, count) and returns fake responses without calling any provider. Supports both streaming and non-streaming. Intentionally limited to Claude CLI scope. |
-| `networkProxy.ts` | Resolves outbound proxy URL for a given provider with precedence: provider-specific config → global config → environment variables (`HTTPS_PROXY`/`HTTP_PROXY`/`ALL_PROXY`). Supports `NO_PROXY` exclusions. Caches config for 30s. |
-
-#### SSE Streaming Pipeline
-
-```mermaid
-flowchart TD
- A["Provider SSE stream"] --> B["TextDecoder\n(per-stream instance)"]
- B --> C["Buffer lines\n(split on newline)"]
- C --> D["parseSSELine()\n(trim whitespace, parse JSON)"]
- D --> E{"Mode?"}
- E -->|TRANSLATE| F["translateResponse()\ntarget → OpenAI → source"]
- E -->|PASSTHROUGH| G["fixInvalidId()\nnormalize chunk"]
- F --> H["hasValuableContent()\nfilter empty chunks"]
- G --> H
- H -->|"Has content"| I["extractUsage()\ntrack token counts"]
- H -->|"Empty"| J["Skip chunk"]
- I --> K["formatSSE()\nserialize + clean perf_metrics"]
- K --> L["TextEncoder\n(per-stream instance)"]
- L --> M["Enqueue to\nclient stream"]
-
- style A fill:#f9f,stroke:#333
- style M fill:#9f9,stroke:#333
-```
-
-#### Request Logger Session Structure
-
-```
-logs/
-└── claude_gemini_claude-sonnet_20260208_143045/
- ├── 1_req_client.json ← Raw client request
- ├── 2_req_source.json ← After initial conversion
- ├── 3_req_openai.json ← OpenAI intermediate format
- ├── 4_req_target.json ← Final target format
- ├── 5_res_provider.txt ← Provider SSE chunks (streaming)
- ├── 5_res_provider.json ← Provider response (non-streaming)
- ├── 6_res_openai.txt ← OpenAI intermediate chunks
- ├── 7_res_client.txt ← Client-facing SSE chunks
- └── 6_error.json ← Error details (if any)
-```
-
----
-
-### 4.7 Application Layer (`src/`)
-
-| Directory | Purpose |
-| ------------- | ---------------------------------------------------------------------- |
-| `src/app/` | Web UI, API routes, Express middleware, OAuth callback handlers |
-| `src/lib/` | Database access (`localDb.ts`, `usageDb.ts`), authentication, shared |
-| `src/mitm/` | Man-in-the-middle proxy utilities for intercepting provider traffic |
-| `src/models/` | Database model definitions |
-| `src/shared/` | Wrappers around open-sse functions (provider, stream, error, etc.) |
-| `src/sse/` | SSE endpoint handlers that wire the open-sse library to Express routes |
-| `src/store/` | Application state management |
-
-#### Notable API Routes
-
-| Route | Methods | Purpose |
-| --------------------------------------------- | --------------- | ------------------------------------------------------------------------------------- |
-| `/api/provider-models` | GET/POST/DELETE | CRUD for custom models per provider |
-| `/api/models/catalog` | GET | Aggregated catalog of all models (chat, embedding, image, custom) grouped by provider |
-| `/api/settings/proxy` | GET/PUT/DELETE | Hierarchical outbound proxy configuration (`global/providers/combos/keys`) |
-| `/api/settings/proxy/test` | POST | Validates proxy connectivity and returns public IP/latency |
-| `/v1/providers/[provider]/chat/completions` | POST | Dedicated per-provider chat completions with model validation |
-| `/v1/providers/[provider]/embeddings` | POST | Dedicated per-provider embeddings with model validation |
-| `/v1/providers/[provider]/images/generations` | POST | Dedicated per-provider image generation with model validation |
-| `/api/settings/ip-filter` | GET/PUT | IP allowlist/blocklist management |
-| `/api/settings/thinking-budget` | GET/PUT | Reasoning token budget configuration (passthrough/auto/custom/adaptive) |
-| `/api/settings/system-prompt` | GET/PUT | Global system prompt injection for all requests |
-| `/api/sessions` | GET | Active session tracking and metrics |
-| `/api/rate-limits` | GET | Per-account rate limit status |
-
----
-
-## 5. Key Design Patterns
-
-### 5.1 Hub-and-Spoke Translation
-
-All formats translate through **OpenAI format as the hub**. Adding a new provider only requires writing **one pair** of translators (to/from OpenAI), not N pairs.
-
-### 5.2 Executor Strategy Pattern
-
-Each provider has a dedicated executor class inheriting from `BaseExecutor`. The factory in `executors/index.ts` selects the right one at runtime.
-
-### 5.3 Self-Registering Plugin System
-
-Translator modules register themselves on import via `register()`. Adding a new translator is just creating a file and importing it.
-
-### 5.4 Account Fallback with Exponential Backoff
-
-When a provider returns 429/401/500, the system can switch to the next account, applying exponential cooldowns (1s → 2s → 4s → max 2min).
-
-### 5.5 Combo Model Chains
-
-A "combo" groups multiple `provider/model` strings. If the first fails, fallback to the next automatically.
-
-### 5.6 Stateful Streaming Translation
-
-Response translation maintains state across SSE chunks (thinking block tracking, tool call accumulation, content block indexing) via the `initState()` mechanism.
-
-### 5.7 Usage Safety Buffer
-
-A 2000-token buffer is added to reported usage to prevent clients from hitting context window limits due to overhead from system prompts and format translation.
-
----
-
-## 6. Supported Formats
-
-| Format | Direction | Identifier |
-| ----------------------- | --------------- | ------------------ |
-| OpenAI Chat Completions | source + target | `openai` |
-| OpenAI Responses API | source + target | `openai-responses` |
-| Anthropic Claude | source + target | `claude` |
-| Google Gemini | source + target | `gemini` |
-| Google Gemini CLI | target only | `gemini-cli` |
-| Antigravity | source + target | `antigravity` |
-| AWS Kiro | target only | `kiro` |
-| Cursor | target only | `cursor` |
-
----
-
-## 7. Supported Providers
-
-| Provider | Auth Method | Executor | Key Notes |
-| ------------------------ | ---------------------- | ----------- | --------------------------------------------- |
-| Anthropic Claude | API key or OAuth | Default | Uses `x-api-key` header |
-| Google Gemini | API key or OAuth | Default | Uses `x-goog-api-key` header |
-| Google Gemini CLI | OAuth | GeminiCLI | Uses `streamGenerateContent` endpoint |
-| Antigravity | OAuth | Antigravity | Multi-URL fallback, custom retry parsing |
-| OpenAI | API key | Default | Standard Bearer auth |
-| Codex | OAuth | Codex | Injects system instructions, manages thinking |
-| GitHub Copilot | OAuth + Copilot token | Github | Dual token, VSCode header mimicking |
-| Kiro (AWS) | AWS SSO OIDC or Social | Kiro | Binary EventStream parsing |
-| Cursor IDE | Checksum auth | Cursor | Protobuf encoding, SHA-256 checksums |
-| Qwen | OAuth | Default | Standard auth |
-| Qoder | OAuth (Basic + Bearer) | Default | Dual auth header |
-| OpenRouter | API key | Default | Standard Bearer auth |
-| GLM, Kimi, MiniMax | API key | Default | Claude-compatible, use `x-api-key` |
-| `openai-compatible-*` | API key | Default | Dynamic: any OpenAI-compatible endpoint |
-| `anthropic-compatible-*` | API key | Default | Dynamic: any Claude-compatible endpoint |
-
----
-
-## 8. Data Flow Summary
-
-### Streaming Request
-
-```mermaid
-flowchart LR
- A["Client"] --> B["detectFormat()"]
- B --> C["translateRequest()\nsource → OpenAI → target"]
- C --> D["Executor\nbuildUrl + buildHeaders"]
- D --> E["fetch(providerURL)"]
- E --> F["createSSEStream()\nTRANSLATE mode"]
- F --> G["parseSSELine()"]
- G --> H["translateResponse()\ntarget → OpenAI → source"]
- H --> I["extractUsage()\n+ addBuffer"]
- I --> J["formatSSE()"]
- J --> K["Client receives\ntranslated SSE"]
- K --> L["logUsage()\nsaveRequestUsage()"]
-```
-
-### Non-Streaming Request
-
-```mermaid
-flowchart LR
- A["Client"] --> B["detectFormat()"]
- B --> C["translateRequest()\nsource → OpenAI → target"]
- C --> D["Executor.execute()"]
- D --> E["translateResponse()\ntarget → OpenAI → source"]
- E --> F["Return JSON\nresponse"]
-```
-
-### Bypass Flow (Claude CLI)
-
-```mermaid
-flowchart LR
- A["Claude CLI request"] --> B{"Match bypass\npattern?"}
- B -->|"Title/Warmup/Count"| C["Generate fake\nOpenAI response"]
- B -->|"No match"| D["Normal flow"]
- C --> E["Translate to\nsource format"]
- E --> F["Return without\ncalling provider"]
-```
diff --git a/docs/i18n/es/CONTRIBUTING.md b/docs/i18n/es/CONTRIBUTING.md
new file mode 100644
index 0000000000..579e24e47a
--- /dev/null
+++ b/docs/i18n/es/CONTRIBUTING.md
@@ -0,0 +1,299 @@
+# Contributing to OmniRoute (Español)
+
+🌐 **Languages:** 🇺🇸 [English](../../../CONTRIBUTING.md) · 🇪🇸 [es](../es/CONTRIBUTING.md) · 🇫🇷 [fr](../fr/CONTRIBUTING.md) · 🇩🇪 [de](../de/CONTRIBUTING.md) · 🇮🇹 [it](../it/CONTRIBUTING.md) · 🇷🇺 [ru](../ru/CONTRIBUTING.md) · 🇨🇳 [zh-CN](../zh-CN/CONTRIBUTING.md) · 🇯🇵 [ja](../ja/CONTRIBUTING.md) · 🇰🇷 [ko](../ko/CONTRIBUTING.md) · 🇸🇦 [ar](../ar/CONTRIBUTING.md) · 🇮🇳 [in](../in/CONTRIBUTING.md) · 🇹🇭 [th](../th/CONTRIBUTING.md) · 🇻🇳 [vi](../vi/CONTRIBUTING.md) · 🇮🇩 [id](../id/CONTRIBUTING.md) · 🇲🇾 [ms](../ms/CONTRIBUTING.md) · 🇳🇱 [nl](../nl/CONTRIBUTING.md) · 🇵🇱 [pl](../pl/CONTRIBUTING.md) · 🇸🇪 [sv](../sv/CONTRIBUTING.md) · 🇳🇴 [no](../no/CONTRIBUTING.md) · 🇩🇰 [da](../da/CONTRIBUTING.md) · 🇫🇮 [fi](../fi/CONTRIBUTING.md) · 🇵🇹 [pt](../pt/CONTRIBUTING.md) · 🇷🇴 [ro](../ro/CONTRIBUTING.md) · 🇭🇺 [hu](../hu/CONTRIBUTING.md) · 🇧🇬 [bg](../bg/CONTRIBUTING.md) · 🇸🇰 [sk](../sk/CONTRIBUTING.md) · 🇺🇦 [uk-UA](../uk-UA/CONTRIBUTING.md) · 🇮🇱 [he](../he/CONTRIBUTING.md) · 🇵🇭 [phi](../phi/CONTRIBUTING.md) · 🇧🇷 [pt-BR](../pt-BR/CONTRIBUTING.md) · 🇨🇿 [cs](../cs/CONTRIBUTING.md)
+
+---
+
+Thank you for your interest in contributing! This guide covers everything you need to get started.
+
+---
+
+## Development Setup
+
+### Prerequisites
+
+- **Node.js** >= 18 < 24 (recommended: 22 LTS)
+- **npm** 10+
+- **Git**
+
+### Clone & Install
+
+```bash
+git clone https://github.com/diegosouzapw/OmniRoute.git
+cd OmniRoute
+npm install
+```
+
+### Environment Variables
+
+```bash
+# Create your .env from the template
+cp .env.example .env
+
+# Generate required secrets
+echo "JWT_SECRET=$(openssl rand -base64 48)" >> .env
+echo "API_KEY_SECRET=$(openssl rand -hex 32)" >> .env
+```
+
+Key variables for development:
+
+| Variable | Development Default | Description |
+| ---------------------- | ------------------------ | --------------------- |
+| `PORT` | `20128` | Server port |
+| `NEXT_PUBLIC_BASE_URL` | `http://localhost:20128` | Base URL for frontend |
+| `JWT_SECRET` | (generate above) | JWT signing secret |
+| `INITIAL_PASSWORD` | `CHANGEME` | First login password |
+| `APP_LOG_LEVEL` | `info` | Log verbosity level |
+
+### Dashboard Settings
+
+The dashboard provides UI toggles for features that can also be configured via environment variables:
+
+| Setting Location | Toggle | Description |
+| ------------------- | ------------------ | ------------------------------ |
+| Settings → Advanced | Debug Mode | Enable debug request logs (UI) |
+| Settings → General | Sidebar Visibility | Show/hide sidebar sections |
+
+These settings are stored in the database and persist across restarts, overriding env var defaults when set.
+
+### Running Locally
+
+```bash
+# Development mode (hot reload)
+npm run dev
+
+# Production build
+npm run build
+npm run start
+
+# Common port configuration
+PORT=20128 NEXT_PUBLIC_BASE_URL=http://localhost:20128 npm run dev
+```
+
+Default URLs:
+
+- **Dashboard**: `http://localhost:20128/dashboard`
+- **API**: `http://localhost:20128/v1`
+
+---
+
+## Git Workflow
+
+> ⚠️ **NEVER commit directly to `main`.** Always use feature branches.
+
+```bash
+git checkout -b feat/your-feature-name
+# ... make changes ...
+git commit -m "feat: describe your change"
+git push -u origin feat/your-feature-name
+# Open a Pull Request on GitHub
+```
+
+### Branch Naming
+
+| Prefix | Purpose |
+| ----------- | ------------------------- |
+| `feat/` | New features |
+| `fix/` | Bug fixes |
+| `refactor/` | Code restructuring |
+| `docs/` | Documentation changes |
+| `test/` | Test additions/fixes |
+| `chore/` | Tooling, CI, dependencies |
+
+### Commit Messages
+
+Follow [Conventional Commits](https://www.conventionalcommits.org/):
+
+```
+feat: add circuit breaker for provider calls
+fix: resolve JWT secret validation edge case
+docs: update SECURITY.md with PII protection
+test: add observability unit tests
+refactor(db): consolidate rate limit tables
+```
+
+Scopes: `db`, `sse`, `oauth`, `dashboard`, `api`, `cli`, `docker`, `ci`, `mcp`, `a2a`, `memory`, `skills`.
+
+---
+
+## Running Tests
+
+```bash
+# All tests (unit + vitest + ecosystem + e2e)
+npm run test:all
+
+# Single test file (Node.js native test runner — most tests use this)
+node --import tsx/esm --test tests/unit/your-file.test.mjs
+
+# Vitest (MCP server, autoCombo, cache)
+npm run test:vitest
+
+# E2E tests (requires Playwright)
+npm run test:e2e
+
+# Protocol clients E2E (MCP transports, A2A)
+npm run test:protocols:e2e
+
+# Ecosystem compatibility tests
+npm run test:ecosystem
+
+# Coverage (55% min statements/lines/functions; 60% branches)
+npm run test:coverage
+npm run coverage:report
+
+# Lint + format check
+npm run lint
+npm run check
+```
+
+Coverage notes:
+
+- `npm run test:coverage` measures source coverage for the main unit test suite, excludes `tests/**`, and includes `open-sse/**`
+- `npm run coverage:report` prints the detailed file-by-file report from the latest coverage run
+- `npm run test:coverage:legacy` preserves the older metric for historical comparison
+- See `docs/COVERAGE_PLAN.md` for the phased coverage improvement roadmap
+
+Current test status: **122 unit test files** covering:
+
+- Provider translators and format conversion
+- Rate limiting, circuit breaker, and resilience
+- Semantic cache, idempotency, progress tracking
+- Database operations and schema (21 DB modules)
+- OAuth flows and authentication
+- API endpoint validation (Zod v4)
+- MCP server tools and scope enforcement
+- Memory and Skills systems
+
+---
+
+## Code Style
+
+- **ESLint** — Run `npm run lint` before committing
+- **Prettier** — Auto-formatted via `lint-staged` on commit (2 spaces, semicolons, double quotes, 100 char width, es5 trailing commas)
+- **TypeScript** — All `src/` code uses `.ts`/`.tsx`; `open-sse/` uses `.ts`/`.js`; document with TSDoc (`@param`, `@returns`, `@throws`)
+- **No `eval()`** — ESLint enforces `no-eval`, `no-implied-eval`, `no-new-func`
+- **Zod validation** — Use Zod v4 schemas for all API input validation
+- **Naming**: Files = camelCase/kebab-case, components = PascalCase, constants = UPPER_SNAKE
+
+---
+
+## Project Structure
+
+```
+src/ # TypeScript (.ts / .tsx)
+├── app/ # Next.js 16 App Router
+│ ├── (dashboard)/ # Dashboard pages (23 sections)
+│ ├── api/ # API routes (51 directories)
+│ └── login/ # Auth pages (.tsx)
+├── domain/ # Policy engine (policyEngine, comboResolver, costRules, etc.)
+├── lib/ # Core business logic (.ts)
+│ ├── a2a/ # Agent-to-Agent v0.3 protocol server
+│ ├── acp/ # Agent Communication Protocol registry
+│ ├── compliance/ # Compliance policy engine
+│ ├── db/ # SQLite database layer (21 modules + 16 migrations)
+│ ├── memory/ # Persistent conversational memory
+│ ├── oauth/ # OAuth providers, services, and utilities
+│ ├── skills/ # Extensible skill framework
+│ ├── usage/ # Usage tracking and cost calculation
+│ └── localDb.ts # Re-export layer only — never add logic here
+├── middleware/ # Request middleware (promptInjectionGuard)
+├── mitm/ # MITM proxy (cert, DNS, target routing)
+├── shared/
+│ ├── components/ # React components (.tsx)
+│ ├── constants/ # Provider definitions (60+), MCP scopes, routing strategies
+│ ├── utils/ # Circuit breaker, sanitizer, auth helpers
+│ └── validation/ # Zod v4 schemas
+└── sse/ # SSE proxy pipeline
+
+open-sse/ # @omniroute/open-sse workspace
+├── executors/ # 14 provider-specific request executors
+├── handlers/ # 11 request handlers (chat, responses, embeddings, images, etc.)
+├── mcp-server/ # MCP server (25 tools, 3 transports, 10 scopes)
+├── services/ # 36+ services (combo, autoCombo, rateLimitManager, etc.)
+├── translator/ # Format translators (OpenAI ↔ Claude ↔ Gemini ↔ Responses ↔ Ollama)
+├── transformer/ # Responses API transformer
+└── utils/ # 22 utility modules (stream, TLS, proxy, logging)
+
+electron/ # Electron desktop app (cross-platform)
+
+tests/
+├── unit/ # Node.js test runner (122 test files)
+├── integration/ # Integration tests
+├── e2e/ # Playwright tests
+├── security/ # Security tests
+├── translator/ # Translator-specific tests
+└── load/ # Load tests
+
+docs/ # Documentation
+├── ARCHITECTURE.md # System architecture
+├── API_REFERENCE.md # All endpoints
+├── USER_GUIDE.md # Provider setup, CLI integration
+├── TROUBLESHOOTING.md # Common issues
+├── MCP-SERVER.md # MCP server (25 tools)
+├── A2A-SERVER.md # A2A agent protocol
+├── AUTO-COMBO.md # Auto-combo engine
+├── CLI-TOOLS.md # CLI tools integration
+├── COVERAGE_PLAN.md # Test coverage improvement plan
+├── openapi.yaml # OpenAPI specification
+└── adr/ # Architecture Decision Records
+```
+
+---
+
+## Adding a New Provider
+
+### Step 1: Register Provider Constants
+
+Add to `src/shared/constants/providers.ts` — Zod-validated at module load.
+
+### Step 2: Add Executor (if custom logic needed)
+
+Create executor in `open-sse/executors/your-provider.ts` extending the base executor.
+
+### Step 3: Add Translator (if non-OpenAI format)
+
+Create request/response translators in `open-sse/translator/`.
+
+### Step 4: Add OAuth Config (if OAuth-based)
+
+Add OAuth credentials in `src/lib/oauth/constants/oauth.ts` and service in `src/lib/oauth/services/`.
+
+### Step 5: Register Models
+
+Add model definitions in `open-sse/config/providerRegistry.ts`.
+
+### Step 6: Add Tests
+
+Write unit tests in `tests/unit/` covering at minimum:
+
+- Provider registration
+- Request/response translation
+- Error handling
+
+---
+
+## Pull Request Checklist
+
+- [ ] Tests pass (`npm test`)
+- [ ] Linting passes (`npm run lint`)
+- [ ] Build succeeds (`npm run build`)
+- [ ] TypeScript types added for new public functions and interfaces
+- [ ] No hardcoded secrets or fallback values
+- [ ] All inputs validated with Zod schemas
+- [ ] CHANGELOG updated (if user-facing change)
+- [ ] Documentation updated (if applicable)
+
+---
+
+## Releasing
+
+Releases are managed via the `/generate-release` workflow. When a new GitHub Release is created, the package is **automatically published to npm** via GitHub Actions.
+
+---
+
+## Getting Help
+
+- **Architecture**: See [`docs/ARCHITECTURE.md`](docs/ARCHITECTURE.md)
+- **API Reference**: See [`docs/API_REFERENCE.md`](docs/API_REFERENCE.md)
+- **Issues**: [github.com/diegosouzapw/OmniRoute/issues](https://github.com/diegosouzapw/OmniRoute/issues)
+- **ADRs**: See `docs/adr/` for architectural decision records
diff --git a/docs/i18n/es/FEATURES.md b/docs/i18n/es/FEATURES.md
deleted file mode 100644
index f648fe35d9..0000000000
--- a/docs/i18n/es/FEATURES.md
+++ /dev/null
@@ -1,147 +0,0 @@
-# OmniRoute — Dashboard Features Gallery (Español)
-
-🌐 **Languages:** 🇺🇸 [English](../../../README.md) · 🇧🇷 [pt-BR](../pt-BR/README.md) · 🇪🇸 [es](../es/README.md) · 🇫🇷 [fr](../fr/README.md) · 🇩🇪 [de](../de/README.md) · 🇮🇹 [it](../it/README.md) · 🇷🇺 [ru](../ru/README.md) · 🇨🇳 [zh-CN](../zh-CN/README.md) · 🇯🇵 [ja](../ja/README.md) · 🇰🇷 [ko](../ko/README.md) · 🇸🇦 [ar](../ar/README.md) · 🇮🇳 [in](../in/README.md) · 🇹🇭 [th](../th/README.md) · 🇻🇳 [vi](../vi/README.md) · 🇮🇩 [id](../id/README.md) · 🇲🇾 [ms](../ms/README.md) · 🇳🇱 [nl](../nl/README.md) · 🇵🇱 [pl](../pl/README.md) · 🇸🇪 [sv](../sv/README.md) · 🇳🇴 [no](../no/README.md) · 🇩🇰 [da](../da/README.md) · 🇫🇮 [fi](../fi/README.md) · 🇵🇹 [pt](../pt/README.md) · 🇷🇴 [ro](../ro/README.md) · 🇭🇺 [hu](../hu/README.md) · 🇧🇬 [bg](../bg/README.md) · 🇸🇰 [sk](../sk/README.md) · 🇺🇦 [uk-UA](../uk-UA/README.md) · 🇮🇱 [he](../he/README.md) · 🇵🇭 [phi](../phi/README.md)
-
-> 🇺🇸 [English](../../../docs/FEATURES.md)
-
----
-
-Visual guide to every section of the OmniRoute dashboard.
-
----
-
-## 🔌 Providers
-
-Manage AI provider connections: OAuth providers (Claude Code, Codex, Gemini CLI), API key providers (Groq, DeepSeek, OpenRouter), and free providers (Qoder, Qwen, Kiro). Kiro accounts include credit balance tracking — remaining credits, total allowance, and renewal date visible in Dashboard → Usage.
-
-
-
----
-
-## 🎨 Combos
-
-Create model routing combos with 6 strategies: priority, weighted, round-robin, random, least-used, and cost-optimized. Each combo chains multiple models with automatic fallback and includes quick templates and readiness checks.
-
-
-
----
-
-## 📊 Analytics
-
-Comprehensive usage analytics with token consumption, cost estimates, activity heatmaps, weekly distribution charts, and per-provider breakdowns.
-
-
-
----
-
-## 🏥 System Health
-
-Real-time monitoring: uptime, memory, version, latency percentiles (p50/p95/p99), cache statistics, and provider circuit breaker states.
-
-
-
----
-
-## 🔧 Translator Playground
-
-Four modes for debugging API translations: **Playground** (format converter), **Chat Tester** (live requests), **Test Bench** (batch tests), and **Live Monitor** (real-time stream).
-
-
-
----
-
-## 🎮 Model Playground _(v2.0.9+)_
-
-Test any model directly from the dashboard. Select provider, model, and endpoint, write prompts with Monaco Editor, stream responses in real-time, abort mid-stream, and view timing metrics.
-
----
-
-## 🎨 Themes _(v2.0.5+)_
-
-Customizable color themes for the entire dashboard. Choose from 7 preset colors (Coral, Blue, Red, Green, Violet, Orange, Cyan) or create a custom theme by picking any hex color. Supports light, dark, and system mode.
-
----
-
-## ⚙️ Settings
-
-Comprehensive settings panel with tabs:
-
-- **General** — System storage, backup management (export/import database)
-- **Appearance** — Theme selector (dark/light/system), color theme presets and custom colors, health log visibility, sidebar item visibility controls
-- **Security** — API endpoint protection, custom provider blocking, IP filtering, session info
-- **Routing** — Model aliases, background task degradation
-- **Resilience** — Rate limit persistence, circuit breaker tuning
-- **Advanced** — Configuration overrides
-
-
-
----
-
-## 🔧 CLI Tools
-
-One-click configuration for AI coding tools: Claude Code, Codex CLI, Gemini CLI, OpenClaw, Kilo Code, Antigravity, Cline, Continue, Cursor, and Factory Droid. Features automated config apply/reset, connection profiles, and model mapping.
-
-
-
----
-
-## 🤖 CLI Agents _(v2.0.11+)_
-
-Dashboard for discovering and managing CLI agents. Shows a grid of 14 built-in agents (Codex, Claude, Goose, Gemini CLI, OpenClaw, Aider, OpenCode, Cline, Qwen Code, ForgeCode, Amazon Q, Open Interpreter, Cursor CLI, Warp) with:
-
-- **Installation status** — Installed / Not Found with version detection
-- **Protocol badges** — stdio, HTTP, etc.
-- **Custom agents** — Register any CLI tool via form (name, binary, version command, spawn args)
-- **CLI Fingerprint Matching** — Per-provider toggle to match native CLI request signatures, reducing ban risk while preserving proxy IP
-
----
-
-## 🖼️ Media _(v2.0.3+)_
-
-Generate images, videos, and music from the dashboard. Supports OpenAI, xAI, Together, Hyperbolic, SD WebUI, ComfyUI, AnimateDiff, Stable Audio Open, and MusicGen.
-
----
-
-## 📝 Request Logs
-
-Real-time request logging with filtering by provider, model, account, and API key. Shows status codes, token usage, latency, and response details.
-
-
-
----
-
-## 🌐 API Endpoint
-
-Your unified API endpoint with capability breakdown: Chat Completions, Responses API, Embeddings, Image Generation, Reranking, Audio Transcription, Text-to-Speech, Moderations, and registered API keys. Cloud proxy support for remote access.
-
-
-
----
-
-## 🔑 API Key Management
-
-Create, scope, and revoke API keys. Each key can be restricted to specific models/providers with full access or read-only permissions. Visual key management with usage tracking.
-
----
-
-## 📋 Audit Log
-
-Administrative action tracking with filtering by action type, actor, target, IP address, and timestamp. Full security event history.
-
----
-
-## 🖥️ Desktop Application
-
-Native Electron desktop app for Windows, macOS, and Linux. Run OmniRoute as a standalone application with system tray integration, offline support, auto-update, and one-click install.
-
-Key features:
-
-- Server readiness polling (no blank screen on cold start)
-- System tray with port management
-- Content Security Policy
-- Single-instance lock
-- Auto-update on restart
-- Platform-conditional UI (macOS traffic lights, Windows/Linux default titlebar)
-- Hardened Electron build packaging — symlinked `node_modules` in the standalone bundle is detected and rejected before packaging, preventing runtime dependency on the build machine (v2.5.5+)
-
-📖 See [`electron/README.md`](../electron/README.md) for full documentation.
diff --git a/docs/i18n/es/MCP-SERVER.md b/docs/i18n/es/MCP-SERVER.md
deleted file mode 100644
index 829acd30b1..0000000000
--- a/docs/i18n/es/MCP-SERVER.md
+++ /dev/null
@@ -1,87 +0,0 @@
-🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/MCP-SERVER.md) · 🇪🇸 [es](../es/MCP-SERVER.md) · 🇫🇷 [fr](../fr/MCP-SERVER.md) · 🇩🇪 [de](../de/MCP-SERVER.md) · 🇮🇹 [it](../it/MCP-SERVER.md) · 🇷🇺 [ru](../ru/MCP-SERVER.md) · 🇨🇳 [zh-CN](../zh-CN/MCP-SERVER.md) · 🇯🇵 [ja](../ja/MCP-SERVER.md) · 🇰🇷 [ko](../ko/MCP-SERVER.md) · 🇸🇦 [ar](../ar/MCP-SERVER.md) · 🇮🇳 [in](../in/MCP-SERVER.md) · 🇹🇭 [th](../th/MCP-SERVER.md) · 🇻🇳 [vi](../vi/MCP-SERVER.md) · 🇮🇩 [id](../id/MCP-SERVER.md) · 🇲🇾 [ms](../ms/MCP-SERVER.md) · 🇳🇱 [nl](../nl/MCP-SERVER.md) · 🇵🇱 [pl](../pl/MCP-SERVER.md) · 🇸🇪 [sv](../sv/MCP-SERVER.md) · 🇳🇴 [no](../no/MCP-SERVER.md) · 🇩🇰 [da](../da/MCP-SERVER.md) · 🇫🇮 [fi](../fi/MCP-SERVER.md) · 🇵🇹 [pt](../pt/MCP-SERVER.md) · 🇷🇴 [ro](../ro/MCP-SERVER.md) · 🇭🇺 [hu](../hu/MCP-SERVER.md) · 🇧🇬 [bg](../bg/MCP-SERVER.md) · 🇸🇰 [sk](../sk/MCP-SERVER.md) · 🇺🇦 [uk-UA](../uk-UA/MCP-SERVER.md) · 🇮🇱 [he](../he/MCP-SERVER.md) · 🇵🇭 [phi](../phi/MCP-SERVER.md)
-
----
-
-# OmniRoute MCP Server Documentation
-
-> Model Context Protocol server with 16 intelligent tools
-
-## Installation
-
-OmniRoute MCP is built-in. Start it with:
-
-```bash
-omniroute --mcp
-```
-
-Or via the open-sse transport:
-
-```bash
-# HTTP streamable transport (port 20130)
-omniroute --dev # MCP auto-starts on /mcp endpoint
-```
-
-## IDE Configuration
-
-See [IDE Configs](integrations/ide-configs.md) for Antigravity, Cursor, Copilot, and Claude Desktop setup.
-
----
-
-## Essential Tools (8)
-
-| Tool | Description |
-| :------------------------------ | :--------------------------------------- |
-| `omniroute_get_health` | Gateway health, circuit breakers, uptime |
-| `omniroute_list_combos` | All configured combos with models |
-| `omniroute_get_combo_metrics` | Performance metrics for a specific combo |
-| `omniroute_switch_combo` | Switch active combo by ID/name |
-| `omniroute_check_quota` | Quota status per provider or all |
-| `omniroute_route_request` | Send a chat completion through OmniRoute |
-| `omniroute_cost_report` | Cost analytics for a time period |
-| `omniroute_list_models_catalog` | Full model catalog with capabilities |
-
-## Advanced Tools (8)
-
-| Tool | Description |
-| :--------------------------------- | :---------------------------------------------- |
-| `omniroute_simulate_route` | Dry-run routing simulation with fallback tree |
-| `omniroute_set_budget_guard` | Session budget with degrade/block/alert actions |
-| `omniroute_set_resilience_profile` | Apply conservative/balanced/aggressive preset |
-| `omniroute_test_combo` | Live-test all models in a combo |
-| `omniroute_get_provider_metrics` | Detailed metrics for one provider |
-| `omniroute_best_combo_for_task` | Task-fitness recommendation with alternatives |
-| `omniroute_explain_route` | Explain a past routing decision |
-| `omniroute_get_session_snapshot` | Full session state: costs, tokens, errors |
-
-## Authentication
-
-MCP tools are authenticated via API key scopes. Each tool requires specific scopes:
-
-| Scope | Tools |
-| :------------- | :----------------------------------------------- |
-| `read:health` | get_health, get_provider_metrics |
-| `read:combos` | list_combos, get_combo_metrics |
-| `write:combos` | switch_combo |
-| `read:quota` | check_quota |
-| `write:route` | route_request, simulate_route, test_combo |
-| `read:usage` | cost_report, get_session_snapshot, explain_route |
-| `write:config` | set_budget_guard, set_resilience_profile |
-| `read:models` | list_models_catalog, best_combo_for_task |
-
-## Audit Logging
-
-Every tool call is logged to `mcp_tool_audit` with:
-
-- Tool name, arguments, result
-- Duration (ms), success/failure
-- API key hash, timestamp
-
-## Files
-
-| File | Purpose |
-| :------------------------------------------- | :------------------------------------------ |
-| `open-sse/mcp-server/server.ts` | MCP server creation + 16 tool registrations |
-| `open-sse/mcp-server/transport.ts` | Stdio + HTTP transport |
-| `open-sse/mcp-server/auth.ts` | API key + scope validation |
-| `open-sse/mcp-server/audit.ts` | Tool call audit logging |
-| `open-sse/mcp-server/tools/advancedTools.ts` | 8 advanced tool handlers |
diff --git a/docs/i18n/es/README.md b/docs/i18n/es/README.md
index 4f9491f187..c58dcde5e1 100644
--- a/docs/i18n/es/README.md
+++ b/docs/i18n/es/README.md
@@ -1,13 +1,12 @@
# 🚀 OmniRoute — The Free AI Gateway (Español)
-🌐 **Languages:** 🇺🇸 [English](../../../README.md) · 🇪🇸 [es](../es/README.md) · 🇫🇷 [fr](../fr/README.md) · 🇩🇪 [de](../de/README.md) · 🇮🇹 [it](../it/README.md) · 🇷🇺 [ru](../ru/README.md) · 🇨🇳 [zh-CN](../zh-CN/README.md) · 🇯🇵 [ja](../ja/README.md) · 🇰🇷 [ko](../ko/README.md) · 🇸🇦 [ar](../ar/README.md) · 🇮🇳 [in](../in/README.md) · 🇹🇭 [th](../th/README.md) · 🇻🇳 [vi](../vi/README.md) · 🇮🇩 [id](../id/README.md) · 🇲🇾 [ms](../ms/README.md) · 🇳🇱 [nl](../nl/README.md) · 🇵🇱 [pl](../pl/README.md) · 🇸🇪 [sv](../sv/README.md) · 🇳🇴 [no](../no/README.md) · 🇩🇰 [da](../da/README.md) · 🇫🇮 [fi](../fi/README.md) · 🇵🇹 [pt](../pt/README.md) · 🇷🇴 [ro](../ro/README.md) · 🇭🇺 [hu](../hu/README.md) · 🇧🇬 [bg](../bg/README.md) · 🇸🇰 [sk](../sk/README.md) · 🇺🇦 [uk-UA](../uk-UA/README.md) · 🇮🇱 [he](../he/README.md) · 🇵🇭 [phi](../phi/README.md) · 🇧🇷 [pt-BR](../pt-BR/README.md)
+🌐 **Languages:** 🇺🇸 [English](../../../README.md) · 🇪🇸 [es](../es/README.md) · 🇫🇷 [fr](../fr/README.md) · 🇩🇪 [de](../de/README.md) · 🇮🇹 [it](../it/README.md) · 🇷🇺 [ru](../ru/README.md) · 🇨🇳 [zh-CN](../zh-CN/README.md) · 🇯🇵 [ja](../ja/README.md) · 🇰🇷 [ko](../ko/README.md) · 🇸🇦 [ar](../ar/README.md) · 🇮🇳 [in](../in/README.md) · 🇹🇭 [th](../th/README.md) · 🇻🇳 [vi](../vi/README.md) · 🇮🇩 [id](../id/README.md) · 🇲🇾 [ms](../ms/README.md) · 🇳🇱 [nl](../nl/README.md) · 🇵🇱 [pl](../pl/README.md) · 🇸🇪 [sv](../sv/README.md) · 🇳🇴 [no](../no/README.md) · 🇩🇰 [da](../da/README.md) · 🇫🇮 [fi](../fi/README.md) · 🇵🇹 [pt](../pt/README.md) · 🇷🇴 [ro](../ro/README.md) · 🇭🇺 [hu](../hu/README.md) · 🇧🇬 [bg](../bg/README.md) · 🇸🇰 [sk](../sk/README.md) · 🇺🇦 [uk-UA](../uk-UA/README.md) · 🇮🇱 [he](../he/README.md) · 🇵🇭 [phi](../phi/README.md) · 🇧🇷 [pt-BR](../pt-BR/README.md) · 🇨🇿 [cs](../cs/README.md)
---
-
### Never stop coding. Smart routing to **FREE & low-cost AI models** with automatic fallback.
-_Your universal API proxy — one endpoint, 67+ providers, zero downtime. Now with **MCP & A2A** agent orchestration._
+_Your universal API proxy — one endpoint, 60+ providers, zero downtime. Now with **MCP Server (25 tools)**, **A2A Protocol**, **Memory/Skills Systems** & **Electron Desktop App**._
**Chat Completions • Embeddings • Image Generation • Video • Music • Audio • Reranking • **Web Search** • MCP Server • A2A Protocol • 100% TypeScript**
@@ -47,15 +46,17 @@ _Your universal API proxy — one endpoint, 67+ providers, zero downtime. Now wi
> - `APP_LOG_FILE_PATH`
> - `APP_LOG_MAX_FILE_SIZE`
> - `APP_LOG_RETENTION_DAYS`
+> - `APP_LOG_MAX_FILES`
> - `APP_LOG_LEVEL`
> - `APP_LOG_FORMAT`
> - `CALL_LOG_RETENTION_DAYS`
+> - `CALL_LOG_MAX_ENTRIES`
>
> For release details and upgrade notes, see the [CHANGELOG](CHANGELOG.md).
---
-## 🆕 What's New in v3.0.0
+## 🆕 What's New
> **Upgrading from v2.9.5?** — See the [full CHANGELOG](CHANGELOG.md#300--2026-03-22-release-candidate--not-yet-merged-to-main) for all changes.
@@ -275,7 +276,7 @@ Developers pay $20–200/month for Claude Pro, Codex Pro, or GitHub Copilot. Eve
- **Smart 4-Tier Fallback** — If subscription quota runs out, automatically redirects to API Key → Cheap → Free with zero manual intervention
- **Real-Time Quota Tracking** — Shows token consumption in real-time with reset countdown (5h, daily, weekly)
- **Multi-Account Support** — Multiple accounts per provider with auto round-robin — when one runs out, switches to the next
-- **Custom Combos** — Customizable fallback chains with 6 balancing strategies (fill-first, round-robin, P2C, random, least-used, cost-optimized)
+- **Custom Combos** — Customizable fallback chains with 9 balancing strategies (priority, weighted, fill-first, round-robin, P2C, random, least-used, cost-optimized, strict-random)
- **Codex Business Quotas** — Business/Team workspace quota monitoring directly in the dashboard
@@ -287,7 +288,7 @@ OpenAI uses one format, Claude (Anthropic) uses another, Gemini yet another. If
**How OmniRoute solves it:**
-- **Unified Endpoint** — A single `http://localhost:20128/v1` serves as proxy for all 67+ providers
+- **Unified Endpoint** — A single `http://localhost:20128/v1` serves as proxy for all 60+ providers
- **Format Translation** — Automatic and transparent: OpenAI ↔ Claude ↔ Gemini ↔ Responses API
- **Response Sanitization** — Strips non-standard fields (`x_groq`, `usage_breakdown`, `service_tier`) that break OpenAI SDK v1.83+
- **Role Normalization** — Converts `developer` → `system` for non-OpenAI providers; `system` → `user` for GLM/ERNIE
@@ -373,7 +374,7 @@ Developers use Cursor, Claude Code, Codex CLI, OpenClaw, Gemini CLI, Kilo Code..
- **CLI Tools Dashboard** — Dedicated page with one-click setup for Claude Code, Codex CLI, OpenClaw, Kilo Code, Antigravity, Cline
- **GitHub Copilot Config Generator** — Generates `chatLanguageModels.json` for VS Code with bulk model selection
- **Onboarding Wizard** — Guided 4-step setup for first-time users
-- **One endpoint, all models** — Configure `http://localhost:20128/v1` once, access 67+ providers
+- **One endpoint, all models** — Configure `http://localhost:20128/v1` once, access 60+ providers
@@ -420,7 +421,7 @@ When a call fails, the dev doesn't know if it was a rate limit, expired token, w
- **SQLite Proxy Logs** — Persistent logs that survive server restarts
- **Translator Playground** — 4 debugging modes: Playground (format translation), Chat Tester (round-trip), Test Bench (batch), Live Monitor (real-time)
- **Request Telemetry** — p50/p95/p99 latency + X-Request-Id tracing
-- **File-Based Logging with Rotation** — Console interceptor captures everything to JSON log with size-based rotation
+- **File-Based Logging with Rotation** — App logs rotate by size, retention days, and archive count; call log artifacts rotate by retention days and file count
- **System Info Report** — `npm run system-info` generates `system-info.txt` with your full environment (Node version, OmniRoute version, OS, CLI tools, Docker/PM2 status). Attach it when reporting issues for instant triage.
@@ -515,7 +516,7 @@ Developers who want all responses in a specific language, with a specific tone,
- **System Prompt Injection** — Global prompt applied to all requests
- **Thinking Budget Validation** — Reasoning token allocation control per request (passthrough, auto, custom, adaptive)
-- **6 Routing Strategies** — Global strategies that determine how requests are distributed
+- **9 Routing Strategies** — Global strategies that determine how requests are distributed
- **Wildcard Router** — `provider/*` patterns route dynamically to any provider
- **Combo Enable/Disable Toggle** — Toggle combos directly from the dashboard
- **Provider Toggle** — Enable/disable all connections for a provider with one click
@@ -582,7 +583,7 @@ Different clients should have least-privilege access to tool categories.
**How OmniRoute solves it:**
-- 9 granular MCP scopes for controlled tool access
+- 10 granular MCP scopes for controlled tool access
- Scope enforcement and visibility in MCP management UI
- Safe default posture for operational tooling
@@ -1326,19 +1327,19 @@ OmniRoute v2.0 is built as an operational platform, not just a relay proxy.
### 🤖 Agent & Protocol Operations (v2.0)
-| Feature | What It Does |
-| ------------------------------------- | -------------------------------------------------------------------------------------------------- |
-| 🔧 **MCP Server (16 tools)** | IDE/agent tools via 3 transports: stdio, SSE (`/api/mcp/sse`), Streamable HTTP (`/api/mcp/stream`) |
-| 🤝 **A2A Server (JSON-RPC + SSE)** | Agent-to-agent task execution with sync and streaming flows |
-| 🧭 **Consolidated Endpoints Page** | Tabbed management page with Endpoint Proxy, MCP, A2A, and API Endpoints tabs |
-| 🎚️ **Service Enable/Disable Toggles** | ON/OFF switches for MCP and A2A with settings persistence (default: OFF) |
-| 🛰️ **MCP Runtime Heartbeat** | Real process status (pid, uptime, heartbeat age, transport, scope mode) |
-| 📋 **MCP Audit Trail** | Filterable audit logs with success/failure and key attribution |
-| 🔐 **MCP Scope Enforcement** | 9 granular scope permissions for controlled tool access |
-| 📡 **A2A Task Lifecycle Management** | List/filter tasks, inspect events/artifacts, cancel running tasks |
-| 📋 **Agent Card Discovery** | `/.well-known/agent.json` for client auto-discovery |
-| 🧪 **Protocol E2E Test Harness** | Real MCP SDK + A2A client flows in `test:protocols:e2e` |
-| ⚙️ **Operational Controls** | Switch combo, apply resilience profiles, reset breakers from one control surface |
+| Feature | What It Does |
+| ------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------- |
+| 🔧 **MCP Server (25 tools)** | IDE/agent tools via 3 transports: stdio, SSE (`/api/mcp/sse`), Streamable HTTP (`/api/mcp/stream`). 18 core + 3 memory + 4 skill tools |
+| 🤝 **A2A Server (JSON-RPC + SSE)** | Agent-to-agent task execution with sync and streaming flows |
+| 🧭 **Consolidated Endpoints Page** | Tabbed management page with Endpoint Proxy, MCP, A2A, and API Endpoints tabs |
+| 🎚️ **Service Enable/Disable Toggles** | ON/OFF switches for MCP and A2A with settings persistence (default: OFF) |
+| 🛰️ **MCP Runtime Heartbeat** | Real process status (pid, uptime, heartbeat age, transport, scope mode) |
+| 📋 **MCP Audit Trail** | Filterable audit logs with success/failure and key attribution |
+| 🔐 **MCP Scope Enforcement** | 10 granular scope permissions for controlled tool access |
+| 📡 **A2A Task Lifecycle Management** | List/filter tasks, inspect events/artifacts, cancel running tasks |
+| 📋 **Agent Card Discovery** | `/.well-known/agent.json` for client auto-discovery |
+| 🧪 **Protocol E2E Test Harness** | Real MCP SDK + A2A client flows in `test:protocols:e2e` |
+| ⚙️ **Operational Controls** | Switch combo, apply resilience profiles, reset breakers from one control surface |
### 🧠 Routing & Intelligence
@@ -1349,7 +1350,7 @@ OmniRoute v2.0 is built as an operational platform, not just a relay proxy.
| 🔄 **Format Translation** | OpenAI ↔ Claude ↔ Gemini ↔ Responses with schema-safe conversions |
| 👥 **Multi-Account Support** | Multiple accounts per provider with intelligent selection |
| 🔄 **Auto Token Refresh** | OAuth tokens refresh automatically with retry |
-| 🎨 **Custom Combos** | 6 balancing strategies + fallback chain control |
+| 🎨 **Custom Combos** | 9 balancing strategies + fallback chain control |
| 🌐 **Wildcard Router** | `provider/*` dynamic routing |
| 🧠 **Thinking Budget Controls** | Passthrough, auto, custom, and adaptive reasoning limits |
| 🔀 **Model Aliases** | Built-in + custom model aliasing and migration safety |
@@ -1950,6 +1951,7 @@ opencode
- Request artifacts are written to `DATA_DIR/call_logs/` as one JSON file per request
- Enable pipeline capture from Dashboard → Logs → Request Logs if you need detailed per-stage payloads
- Set `APP_LOG_TO_FILE=true` if you also want application console logs in `logs/application/app.log`
+- Adjust `APP_LOG_MAX_FILE_SIZE`, `APP_LOG_RETENTION_DAYS`, `APP_LOG_MAX_FILES`, and `CALL_LOG_MAX_ENTRIES` as needed
**Connection test shows "Invalid" for OpenAI-compatible providers**
diff --git a/docs/i18n/es/RELEASE_CHECKLIST.md b/docs/i18n/es/RELEASE_CHECKLIST.md
deleted file mode 100644
index 903e812c3f..0000000000
--- a/docs/i18n/es/RELEASE_CHECKLIST.md
+++ /dev/null
@@ -1,37 +0,0 @@
-🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/RELEASE_CHECKLIST.md) · 🇪🇸 [es](../es/RELEASE_CHECKLIST.md) · 🇫🇷 [fr](../fr/RELEASE_CHECKLIST.md) · 🇩🇪 [de](../de/RELEASE_CHECKLIST.md) · 🇮🇹 [it](../it/RELEASE_CHECKLIST.md) · 🇷🇺 [ru](../ru/RELEASE_CHECKLIST.md) · 🇨🇳 [zh-CN](../zh-CN/RELEASE_CHECKLIST.md) · 🇯🇵 [ja](../ja/RELEASE_CHECKLIST.md) · 🇰🇷 [ko](../ko/RELEASE_CHECKLIST.md) · 🇸🇦 [ar](../ar/RELEASE_CHECKLIST.md) · 🇮🇳 [in](../in/RELEASE_CHECKLIST.md) · 🇹🇭 [th](../th/RELEASE_CHECKLIST.md) · 🇻🇳 [vi](../vi/RELEASE_CHECKLIST.md) · 🇮🇩 [id](../id/RELEASE_CHECKLIST.md) · 🇲🇾 [ms](../ms/RELEASE_CHECKLIST.md) · 🇳🇱 [nl](../nl/RELEASE_CHECKLIST.md) · 🇵🇱 [pl](../pl/RELEASE_CHECKLIST.md) · 🇸🇪 [sv](../sv/RELEASE_CHECKLIST.md) · 🇳🇴 [no](../no/RELEASE_CHECKLIST.md) · 🇩🇰 [da](../da/RELEASE_CHECKLIST.md) · 🇫🇮 [fi](../fi/RELEASE_CHECKLIST.md) · 🇵🇹 [pt](../pt/RELEASE_CHECKLIST.md) · 🇷🇴 [ro](../ro/RELEASE_CHECKLIST.md) · 🇭🇺 [hu](../hu/RELEASE_CHECKLIST.md) · 🇧🇬 [bg](../bg/RELEASE_CHECKLIST.md) · 🇸🇰 [sk](../sk/RELEASE_CHECKLIST.md) · 🇺🇦 [uk-UA](../uk-UA/RELEASE_CHECKLIST.md) · 🇮🇱 [he](../he/RELEASE_CHECKLIST.md) · 🇵🇭 [phi](../phi/RELEASE_CHECKLIST.md)
-
----
-
-# Release Checklist
-
-Use this checklist before tagging or publishing a new OmniRoute release.
-
-## Version and Changelog
-
-1. Bump `package.json` version (`x.y.z`) in the release branch.
-2. Move release notes from `## [Unreleased]` in `CHANGELOG.md` to a dated section:
- - `## [x.y.z] — YYYY-MM-DD`
-3. Keep `## [Unreleased]` as the first changelog section for upcoming work.
-4. Ensure the latest semver section in `CHANGELOG.md` equals `package.json` version.
-
-## API Docs
-
-1. Update `docs/openapi.yaml`:
- - `info.version` must equal `package.json` version.
-2. Validate endpoint examples if API contracts changed.
-
-## Runtime Docs
-
-1. Review `docs/ARCHITECTURE.md` for storage/runtime drift.
-2. Review `docs/TROUBLESHOOTING.md` for env var and operational drift.
-3. Update localized docs if source docs changed significantly.
-
-## Automated Check
-
-Run the sync guard locally before opening PR:
-
-```bash
-npm run check:docs-sync
-```
-
-CI also runs this check in `.github/workflows/ci.yml` (lint job).
diff --git a/docs/i18n/es/SECURITY.md b/docs/i18n/es/SECURITY.md
new file mode 100644
index 0000000000..6e78dbc9b5
--- /dev/null
+++ b/docs/i18n/es/SECURITY.md
@@ -0,0 +1,179 @@
+# Security Policy (Español)
+
+🌐 **Languages:** 🇺🇸 [English](../../../SECURITY.md) · 🇪🇸 [es](../es/SECURITY.md) · 🇫🇷 [fr](../fr/SECURITY.md) · 🇩🇪 [de](../de/SECURITY.md) · 🇮🇹 [it](../it/SECURITY.md) · 🇷🇺 [ru](../ru/SECURITY.md) · 🇨🇳 [zh-CN](../zh-CN/SECURITY.md) · 🇯🇵 [ja](../ja/SECURITY.md) · 🇰🇷 [ko](../ko/SECURITY.md) · 🇸🇦 [ar](../ar/SECURITY.md) · 🇮🇳 [in](../in/SECURITY.md) · 🇹🇭 [th](../th/SECURITY.md) · 🇻🇳 [vi](../vi/SECURITY.md) · 🇮🇩 [id](../id/SECURITY.md) · 🇲🇾 [ms](../ms/SECURITY.md) · 🇳🇱 [nl](../nl/SECURITY.md) · 🇵🇱 [pl](../pl/SECURITY.md) · 🇸🇪 [sv](../sv/SECURITY.md) · 🇳🇴 [no](../no/SECURITY.md) · 🇩🇰 [da](../da/SECURITY.md) · 🇫🇮 [fi](../fi/SECURITY.md) · 🇵🇹 [pt](../pt/SECURITY.md) · 🇷🇴 [ro](../ro/SECURITY.md) · 🇭🇺 [hu](../hu/SECURITY.md) · 🇧🇬 [bg](../bg/SECURITY.md) · 🇸🇰 [sk](../sk/SECURITY.md) · 🇺🇦 [uk-UA](../uk-UA/SECURITY.md) · 🇮🇱 [he](../he/SECURITY.md) · 🇵🇭 [phi](../phi/SECURITY.md) · 🇧🇷 [pt-BR](../pt-BR/SECURITY.md) · 🇨🇿 [cs](../cs/SECURITY.md)
+
+---
+
+## Reporting Vulnerabilities
+
+If you discover a security vulnerability in OmniRoute, please report it responsibly:
+
+1. **DO NOT** open a public GitHub issue
+2. Use [GitHub Security Advisories](https://github.com/diegosouzapw/OmniRoute/security/advisories/new)
+3. Include: description, reproduction steps, and potential impact
+
+## Response Timeline
+
+| Stage | Target |
+| ------------------- | --------------------------- |
+| Acknowledgment | 48 hours |
+| Triage & Assessment | 5 business days |
+| Patch Release | 14 business days (critical) |
+
+## Supported Versions
+
+| Version | Support Status |
+| ------- | -------------- |
+| 3.4.x | ✅ Active |
+| 3.0.x | ✅ Security |
+| < 3.0.0 | ❌ Unsupported |
+
+---
+
+## Security Architecture
+
+OmniRoute implements a multi-layered security model:
+
+```
+Request → CORS → API Key Auth → Prompt Injection Guard → Input Sanitizer → Rate Limiter → Circuit Breaker → Provider
+```
+
+### 🔐 Authentication & Authorization
+
+| Feature | Implementation |
+| -------------------- | ---------------------------------------------------------- |
+| **Dashboard Login** | Password-based auth with JWT tokens (HttpOnly cookies) |
+| **API Key Auth** | HMAC-signed keys with CRC validation |
+| **OAuth 2.0 + PKCE** | Secure provider auth (Claude, Codex, Gemini, Cursor, etc.) |
+| **Token Refresh** | Automatic OAuth token refresh before expiry |
+| **Secure Cookies** | `AUTH_COOKIE_SECURE=true` for HTTPS environments |
+| **MCP Scopes** | 10 granular scopes for MCP tool access control |
+
+### 🛡️ Encryption at Rest
+
+All sensitive data stored in SQLite is encrypted using **AES-256-GCM** with scrypt key derivation:
+
+- API keys, access tokens, refresh tokens, and ID tokens
+- Versioned format: `enc:v1:::`
+- Passthrough mode (plaintext) when `STORAGE_ENCRYPTION_KEY` is not set
+
+```bash
+# Generate encryption key:
+STORAGE_ENCRYPTION_KEY=$(openssl rand -hex 32)
+```
+
+### 🧠 Prompt Injection Guard
+
+Middleware that detects and blocks prompt injection attacks in LLM requests:
+
+| Pattern Type | Severity | Example |
+| ------------------- | -------- | ---------------------------------------------- |
+| System Override | High | "ignore all previous instructions" |
+| Role Hijack | High | "you are now DAN, you can do anything" |
+| Delimiter Injection | Medium | Encoded separators to break context boundaries |
+| DAN/Jailbreak | High | Known jailbreak prompt patterns |
+| Instruction Leak | Medium | "show me your system prompt" |
+
+Configure via dashboard (Settings → Security) or `.env`:
+
+```env
+INPUT_SANITIZER_ENABLED=true
+INPUT_SANITIZER_MODE=block # warn | block | redact
+```
+
+### 🔒 PII Redaction
+
+Automatic detection and optional redaction of personally identifiable information:
+
+| PII Type | Pattern | Replacement |
+| ------------- | --------------------- | ------------------ |
+| Email | `user@domain.com` | `[EMAIL_REDACTED]` |
+| CPF (Brazil) | `123.456.789-00` | `[CPF_REDACTED]` |
+| CNPJ (Brazil) | `12.345.678/0001-00` | `[CNPJ_REDACTED]` |
+| Credit Card | `4111-1111-1111-1111` | `[CC_REDACTED]` |
+| Phone | `+55 11 99999-9999` | `[PHONE_REDACTED]` |
+| SSN (US) | `123-45-6789` | `[SSN_REDACTED]` |
+
+```env
+PII_REDACTION_ENABLED=true
+```
+
+### 🌐 Network Security
+
+| Feature | Description |
+| ------------------------ | ---------------------------------------------------------------- |
+| **CORS** | Configurable origin control (`CORS_ORIGIN` env var, default `*`) |
+| **IP Filtering** | Allowlist/blocklist IP ranges in dashboard |
+| **Rate Limiting** | Per-provider rate limits with automatic backoff |
+| **Anti-Thundering Herd** | Mutex + per-connection locking prevents cascading 502s |
+| **TLS Fingerprint** | Browser-like TLS fingerprint spoofing to reduce bot detection |
+| **CLI Fingerprint** | Per-provider header/body ordering to match native CLI signatures |
+
+### 🔌 Resilience & Availability
+
+| Feature | Description |
+| ----------------------- | ------------------------------------------------------------------ |
+| **Circuit Breaker** | 3-state (Closed → Open → Half-Open) per provider, SQLite-persisted |
+| **Request Idempotency** | 5-second dedup window for duplicate requests |
+| **Exponential Backoff** | Automatic retry with increasing delays |
+| **Health Dashboard** | Real-time provider health monitoring |
+
+### 📋 Compliance
+
+| Feature | Description |
+| ------------------ | ----------------------------------------------------------- |
+| **Log Retention** | Automatic cleanup after `CALL_LOG_RETENTION_DAYS` |
+| **No-Log Opt-out** | Per API key `noLog` flag disables request logging |
+| **Audit Log** | Administrative actions tracked in `audit_log` table |
+| **MCP Audit** | SQLite-backed audit logging for all MCP tool calls |
+| **Zod Validation** | All API inputs validated with Zod v4 schemas at module load |
+
+---
+
+## Required Environment Variables
+
+All secrets must be set before starting the server. The server will **fail fast** if they are missing or weak.
+
+```bash
+# REQUIRED — server will not start without these:
+JWT_SECRET=$(openssl rand -base64 48) # min 32 chars
+API_KEY_SECRET=$(openssl rand -hex 32) # min 16 chars
+
+# RECOMMENDED — enables encryption at rest:
+STORAGE_ENCRYPTION_KEY=$(openssl rand -hex 32)
+```
+
+The server actively rejects known-weak values like `changeme`, `secret`, or `password`.
+
+---
+
+## Docker Security
+
+- Use non-root user in production
+- Mount secrets as read-only volumes
+- Never copy `.env` files into Docker images
+- Use `.dockerignore` to exclude sensitive files
+- Set `AUTH_COOKIE_SECURE=true` when behind HTTPS
+
+```bash
+docker run -d \
+ --name omniroute \
+ --restart unless-stopped \
+ --read-only \
+ -p 20128:20128 \
+ -v omniroute-data:/app/data \
+ -e JWT_SECRET="$(openssl rand -base64 48)" \
+ -e API_KEY_SECRET="$(openssl rand -hex 32)" \
+ -e STORAGE_ENCRYPTION_KEY="$(openssl rand -hex 32)" \
+ diegosouzapw/omniroute:latest
+```
+
+---
+
+## Dependencies
+
+- Run `npm audit` regularly
+- Keep dependencies updated
+- The project uses `husky` + `lint-staged` for pre-commit checks
+- CI pipeline runs ESLint security rules on every push
+- Provider constants validated at module load via Zod (`src/shared/validation/providerSchema.ts`)
diff --git a/docs/i18n/es/TROUBLESHOOTING.md b/docs/i18n/es/TROUBLESHOOTING.md
deleted file mode 100644
index 63c148000a..0000000000
--- a/docs/i18n/es/TROUBLESHOOTING.md
+++ /dev/null
@@ -1,258 +0,0 @@
-🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/TROUBLESHOOTING.md) · 🇪🇸 [es](../es/TROUBLESHOOTING.md) · 🇫🇷 [fr](../fr/TROUBLESHOOTING.md) · 🇩🇪 [de](../de/TROUBLESHOOTING.md) · 🇮🇹 [it](../it/TROUBLESHOOTING.md) · 🇷🇺 [ru](../ru/TROUBLESHOOTING.md) · 🇨🇳 [zh-CN](../zh-CN/TROUBLESHOOTING.md) · 🇯🇵 [ja](../ja/TROUBLESHOOTING.md) · 🇰🇷 [ko](../ko/TROUBLESHOOTING.md) · 🇸🇦 [ar](../ar/TROUBLESHOOTING.md) · 🇮🇳 [in](../in/TROUBLESHOOTING.md) · 🇹🇭 [th](../th/TROUBLESHOOTING.md) · 🇻🇳 [vi](../vi/TROUBLESHOOTING.md) · 🇮🇩 [id](../id/TROUBLESHOOTING.md) · 🇲🇾 [ms](../ms/TROUBLESHOOTING.md) · 🇳🇱 [nl](../nl/TROUBLESHOOTING.md) · 🇵🇱 [pl](../pl/TROUBLESHOOTING.md) · 🇸🇪 [sv](../sv/TROUBLESHOOTING.md) · 🇳🇴 [no](../no/TROUBLESHOOTING.md) · 🇩🇰 [da](../da/TROUBLESHOOTING.md) · 🇫🇮 [fi](../fi/TROUBLESHOOTING.md) · 🇵🇹 [pt](../pt/TROUBLESHOOTING.md) · 🇷🇴 [ro](../ro/TROUBLESHOOTING.md) · 🇭🇺 [hu](../hu/TROUBLESHOOTING.md) · 🇧🇬 [bg](../bg/TROUBLESHOOTING.md) · 🇸🇰 [sk](../sk/TROUBLESHOOTING.md) · 🇺🇦 [uk-UA](../uk-UA/TROUBLESHOOTING.md) · 🇮🇱 [he](../he/TROUBLESHOOTING.md) · 🇵🇭 [phi](../phi/TROUBLESHOOTING.md)
-
----
-
-# Troubleshooting
-
-🌐 **Languages:** 🇺🇸 [English](TROUBLESHOOTING.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/TROUBLESHOOTING.md) | 🇪🇸 [Español](i18n/es/TROUBLESHOOTING.md) | 🇫🇷 [Français](i18n/fr/TROUBLESHOOTING.md) | 🇮🇹 [Italiano](i18n/it/TROUBLESHOOTING.md) | 🇷🇺 [Русский](i18n/ru/TROUBLESHOOTING.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/TROUBLESHOOTING.md) | 🇩🇪 [Deutsch](i18n/de/TROUBLESHOOTING.md) | 🇮🇳 [हिन्दी](i18n/in/TROUBLESHOOTING.md) | 🇹🇭 [ไทย](i18n/th/TROUBLESHOOTING.md) | 🇺🇦 [Українська](i18n/uk-UA/TROUBLESHOOTING.md) | 🇸🇦 [العربية](i18n/ar/TROUBLESHOOTING.md) | 🇯🇵 [日本語](i18n/ja/TROUBLESHOOTING.md) | 🇻🇳 [Tiếng Việt](i18n/vi/TROUBLESHOOTING.md) | 🇧🇬 [Български](i18n/bg/TROUBLESHOOTING.md) | 🇩🇰 [Dansk](i18n/da/TROUBLESHOOTING.md) | 🇫🇮 [Suomi](i18n/fi/TROUBLESHOOTING.md) | 🇮🇱 [עברית](i18n/he/TROUBLESHOOTING.md) | 🇭🇺 [Magyar](i18n/hu/TROUBLESHOOTING.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/TROUBLESHOOTING.md) | 🇰🇷 [한국어](i18n/ko/TROUBLESHOOTING.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/TROUBLESHOOTING.md) | 🇳🇱 [Nederlands](i18n/nl/TROUBLESHOOTING.md) | 🇳🇴 [Norsk](i18n/no/TROUBLESHOOTING.md) | 🇵🇹 [Português (Portugal)](i18n/pt/TROUBLESHOOTING.md) | 🇷🇴 [Română](i18n/ro/TROUBLESHOOTING.md) | 🇵🇱 [Polski](i18n/pl/TROUBLESHOOTING.md) | 🇸🇰 [Slovenčina](i18n/sk/TROUBLESHOOTING.md) | 🇸🇪 [Svenska](i18n/sv/TROUBLESHOOTING.md) | 🇵🇭 [Filipino](i18n/phi/TROUBLESHOOTING.md)
-
-Common problems and solutions for OmniRoute.
-
----
-
-## Quick Fixes
-
-| Problem | Solution |
-| ----------------------------- | ------------------------------------------------------------------ |
-| First login not working | Set `INITIAL_PASSWORD` in `.env` (no hardcoded default) |
-| Dashboard opens on wrong port | Set `PORT=20128` and `NEXT_PUBLIC_BASE_URL=http://localhost:20128` |
-| No request logs under `logs/` | Set `ENABLE_REQUEST_LOGS=true` |
-| EACCES: permission denied | Set `DATA_DIR=/path/to/writable/dir` to override `~/.omniroute` |
-| Routing strategy not saving | Update to v1.4.11+ (Zod schema fix for settings persistence) |
-
----
-
-## Provider Issues
-
-### "Language model did not provide messages"
-
-**Cause:** Provider quota exhausted.
-
-**Fix:**
-
-1. Check dashboard quota tracker
-2. Use a combo with fallback tiers
-3. Switch to cheaper/free tier
-
-### Rate Limiting
-
-**Cause:** Subscription quota exhausted.
-
-**Fix:**
-
-- Add fallback: `cc/claude-opus-4-6 → glm/glm-4.7 → if/kimi-k2-thinking`
-- Use GLM/MiniMax as cheap backup
-
-### OAuth Token Expired
-
-OmniRoute auto-refreshes tokens. If issues persist:
-
-1. Dashboard → Provider → Reconnect
-2. Delete and re-add the provider connection
-
----
-
-## Cloud Issues
-
-### Cloud Sync Errors
-
-1. Verify `BASE_URL` points to your running instance (e.g., `http://localhost:20128`)
-2. Verify `CLOUD_URL` points to your cloud endpoint (e.g., `https://omniroute.dev`)
-3. Keep `NEXT_PUBLIC_*` values aligned with server-side values
-
-### Cloud `stream=false` Returns 500
-
-**Symptom:** `Unexpected token 'd'...` on cloud endpoint for non-streaming calls.
-
-**Cause:** Upstream returns SSE payload while client expects JSON.
-
-**Workaround:** Use `stream=true` for cloud direct calls. Local runtime includes SSE→JSON fallback.
-
-### Cloud Says Connected but "Invalid API key"
-
-1. Create a fresh key from local dashboard (`/api/keys`)
-2. Run cloud sync: Enable Cloud → Sync Now
-3. Old/non-synced keys can still return `401` on cloud
-
----
-
-## Docker Issues
-
-### CLI Tool Shows Not Installed
-
-1. Check runtime fields: `curl http://localhost:20128/api/cli-tools/runtime/codex | jq`
-2. For portable mode: use image target `runner-cli` (bundled CLIs)
-3. For host mount mode: set `CLI_EXTRA_PATHS` and mount host bin directory as read-only
-4. If `installed=true` and `runnable=false`: binary was found but failed healthcheck
-
-### Quick Runtime Validation
-
-```bash
-curl -s http://localhost:20128/api/cli-tools/codex-settings | jq '{installed,runnable,commandPath,runtimeMode,reason}'
-curl -s http://localhost:20128/api/cli-tools/claude-settings | jq '{installed,runnable,commandPath,runtimeMode,reason}'
-curl -s http://localhost:20128/api/cli-tools/openclaw-settings | jq '{installed,runnable,commandPath,runtimeMode,reason}'
-```
-
----
-
-## Cost Issues
-
-### High Costs
-
-1. Check usage stats in Dashboard → Usage
-2. Switch primary model to GLM/MiniMax
-3. Use free tier (Gemini CLI, Qoder) for non-critical tasks
-4. Set cost budgets per API key: Dashboard → API Keys → Budget
-
----
-
-## Debugging
-
-### Enable Request Logs
-
-Set `ENABLE_REQUEST_LOGS=true` in your `.env` file. Logs appear under `logs/` directory.
-
-### Check Provider Health
-
-```bash
-# Health dashboard
-http://localhost:20128/dashboard/health
-
-# API health check
-curl http://localhost:20128/api/monitoring/health
-```
-
-### Runtime Storage
-
-- Main state: `${DATA_DIR}/storage.sqlite` (providers, combos, aliases, keys, settings)
-- Usage: SQLite tables in `storage.sqlite` (`usage_history`, `call_logs`, `proxy_logs`) + optional `${DATA_DIR}/log.txt` and `${DATA_DIR}/call_logs/`
-- Request logs: `/logs/...` (when `ENABLE_REQUEST_LOGS=true`)
-
----
-
-## Circuit Breaker Issues
-
-### Provider stuck in OPEN state
-
-When a provider's circuit breaker is OPEN, requests are blocked until the cooldown expires.
-
-**Fix:**
-
-1. Go to **Dashboard → Settings → Resilience**
-2. Check the circuit breaker card for the affected provider
-3. Click **Reset All** to clear all breakers, or wait for the cooldown to expire
-4. Verify the provider is actually available before resetting
-
-### Provider keeps tripping the circuit breaker
-
-If a provider repeatedly enters OPEN state:
-
-1. Check **Dashboard → Health → Provider Health** for the failure pattern
-2. Go to **Settings → Resilience → Provider Profiles** and increase the failure threshold
-3. Check if the provider has changed API limits or requires re-authentication
-4. Review latency telemetry — high latency may cause timeout-based failures
-
----
-
-## Audio Transcription Issues
-
-### "Unsupported model" error
-
-- Ensure you're using the correct prefix: `deepgram/nova-3` or `assemblyai/best`
-- Verify the provider is connected in **Dashboard → Providers**
-
-### Transcription returns empty or fails
-
-- Check supported audio formats: `mp3`, `wav`, `m4a`, `flac`, `ogg`, `webm`
-- Verify file size is within provider limits (typically < 25MB)
-- Check provider API key validity in the provider card
-
----
-
-## Translator Debugging
-
-Use **Dashboard → Translator** to debug format translation issues:
-
-| Mode | When to Use |
-| ---------------- | -------------------------------------------------------------------------------------------- |
-| **Playground** | Compare input/output formats side by side — paste a failing request to see how it translates |
-| **Chat Tester** | Send live messages and inspect the full request/response payload including headers |
-| **Test Bench** | Run batch tests across format combinations to find which translations are broken |
-| **Live Monitor** | Watch real-time request flow to catch intermittent translation issues |
-
-### Common format issues
-
-- **Thinking tags not appearing** — Check if the target provider supports thinking and the thinking budget setting
-- **Tool calls dropping** — Some format translations may strip unsupported fields; verify in Playground mode
-- **System prompt missing** — Claude and Gemini handle system prompts differently; check translation output
-- **SDK returns raw string instead of object** — Fixed in v1.1.0: response sanitizer now strips non-standard fields (`x_groq`, `usage_breakdown`, etc.) that cause OpenAI SDK Pydantic validation failures
-- **GLM/ERNIE rejects `system` role** — Fixed in v1.1.0: role normalizer automatically merges system messages into user messages for incompatible models
-- **`developer` role not recognized** — Fixed in v1.1.0: automatically converted to `system` for non-OpenAI providers
-- **`json_schema` not working with Gemini** — Fixed in v1.1.0: `response_format` is now converted to Gemini's `responseMimeType` + `responseSchema`
-
----
-
-## Resilience Settings
-
-### Auto rate-limit not triggering
-
-- Auto rate-limit only applies to API key providers (not OAuth/subscription)
-- Verify **Settings → Resilience → Provider Profiles** has auto-rate-limit enabled
-- Check if the provider returns `429` status codes or `Retry-After` headers
-
-### Tuning exponential backoff
-
-Provider profiles support these settings:
-
-- **Base delay** — Initial wait time after first failure (default: 1s)
-- **Max delay** — Maximum wait time cap (default: 30s)
-- **Multiplier** — How much to increase delay per consecutive failure (default: 2x)
-
-### Anti-thundering herd
-
-When many concurrent requests hit a rate-limited provider, OmniRoute uses mutex + auto rate-limiting to serialize requests and prevent cascading failures. This is automatic for API key providers.
-
----
-
-## Optional RAG / LLM failure taxonomy (16 problems)
-
-Some OmniRoute users place the gateway in front of RAG or agent stacks. In those setups it is common to see a strange pattern: OmniRoute looks healthy (providers up, routing profiles ok, no rate limit alerts) but the final answer is still wrong.
-
-In practice these incidents usually come from the downstream RAG pipeline, not from the gateway itself.
-
-If you want a shared vocabulary to describe those failures you can use the WFGY ProblemMap, an external MIT license text resource that defines sixteen recurring RAG / LLM failure patterns. At a high level it covers:
-
-- retrieval drift and broken context boundaries
-- empty or stale indexes and vector stores
-- embedding versus semantic mismatch
-- prompt assembly and context window issues
-- logic collapse and overconfident answers
-- long chain and agent coordination failures
-- multi agent memory and role drift
-- deployment and bootstrap ordering problems
-
-The idea is simple:
-
-1. When you investigate a bad response, capture:
- - user task and request
- - route or provider combo in OmniRoute
- - any RAG context used downstream (retrieved documents, tool calls, etc)
-2. Map the incident to one or two WFGY ProblemMap numbers (`No.1` … `No.16`).
-3. Store the number in your own dashboard, runbook, or incident tracker next to the OmniRoute logs.
-4. Use the corresponding WFGY page to decide whether you need to change your RAG stack, retriever, or routing strategy.
-
-Full text and concrete recipes live here (MIT license, text only):
-
-[WFGY ProblemMap README](https://github.com/onestardao/WFGY/blob/main/ProblemMap/README.md)
-
-You can ignore this section if you do not run RAG or agent pipelines behind OmniRoute.
-
----
-
-## Still Stuck?
-
-- **GitHub Issues**: [github.com/diegosouzapw/OmniRoute/issues](https://github.com/diegosouzapw/OmniRoute/issues)
-- **Architecture**: See [`docs/ARCHITECTURE.md`](ARCHITECTURE.md) for internal details
-- **API Reference**: See [`docs/API_REFERENCE.md`](API_REFERENCE.md) for all endpoints
-- **Health Dashboard**: Check **Dashboard → Health** for real-time system status
-- **Translator**: Use **Dashboard → Translator** to debug format issues
diff --git a/docs/i18n/es/VM_DEPLOYMENT_GUIDE.md b/docs/i18n/es/VM_DEPLOYMENT_GUIDE.md
deleted file mode 100644
index aef093802e..0000000000
--- a/docs/i18n/es/VM_DEPLOYMENT_GUIDE.md
+++ /dev/null
@@ -1,401 +0,0 @@
-# OmniRoute: Guía de implementación en VM con Cloudflare
-
-🌐 **Languages:** 🇺🇸 [English](../../VM_DEPLOYMENT_GUIDE.md) | 🇧🇷 [Português (Brasil)](../pt-BR/VM_DEPLOYMENT_GUIDE.md) | 🇪🇸 [Español](../es/VM_DEPLOYMENT_GUIDE.md) | 🇫🇷 [Français](../fr/VM_DEPLOYMENT_GUIDE.md) | 🇮🇹 [Italiano](../it/VM_DEPLOYMENT_GUIDE.md) | 🇷🇺 [Русский](../ru/VM_DEPLOYMENT_GUIDE.md) | 🇨🇳 [中文 (简体)](../zh-CN/VM_DEPLOYMENT_GUIDE.md) | 🇩🇪 [Deutsch](../de/VM_DEPLOYMENT_GUIDE.md) | 🇮🇳 [हिन्दी](../in/VM_DEPLOYMENT_GUIDE.md) | 🇹🇭 [ไทย](../th/VM_DEPLOYMENT_GUIDE.md) | 🇺🇦 [Українська](../uk-UA/VM_DEPLOYMENT_GUIDE.md) | 🇸🇦 [العربية](../ar/VM_DEPLOYMENT_GUIDE.md) | 🇯🇵 [日本語](../ja/VM_DEPLOYMENT_GUIDE.md) | 🇻🇳 [Tiếng Việt](../vi/VM_DEPLOYMENT_GUIDE.md) | 🇧🇬 [Български](../bg/VM_DEPLOYMENT_GUIDE.md) | 🇩🇰 [Dansk](../da/VM_DEPLOYMENT_GUIDE.md) | 🇫🇮 [Suomi](../fi/VM_DEPLOYMENT_GUIDE.md) | 🇮🇱 [עברית](../he/VM_DEPLOYMENT_GUIDE.md) | 🇭🇺 [Magyar](../hu/VM_DEPLOYMENT_GUIDE.md) | 🇮🇩 [Bahasa Indonesia](../id/VM_DEPLOYMENT_GUIDE.md) | 🇰🇷 [한국어](../ko/VM_DEPLOYMENT_GUIDE.md) | 🇲🇾 [Bahasa Melayu](../ms/VM_DEPLOYMENT_GUIDE.md) | 🇳🇱 [Nederlands](../nl/VM_DEPLOYMENT_GUIDE.md) | 🇳🇴 [Norsk](../no/VM_DEPLOYMENT_GUIDE.md) | 🇵🇹 [Português (Portugal)](../pt/VM_DEPLOYMENT_GUIDE.md) | 🇷🇴 [Română](../ro/VM_DEPLOYMENT_GUIDE.md) | 🇵🇱 [Polski](../pl/VM_DEPLOYMENT_GUIDE.md) | 🇸🇰 [Slovenčina](../sk/VM_DEPLOYMENT_GUIDE.md) | 🇸🇪 [Svenska](../sv/VM_DEPLOYMENT_GUIDE.md) | 🇵🇭 [Filipino](../phi/VM_DEPLOYMENT_GUIDE.md) | 🇨🇿 [Čeština](../cs/VM_DEPLOYMENT_GUIDE.md)
-
-Guía completa para instalar y configurar OmniRoute en una VM (VPS) con dominio administrado vía Cloudflare.
-
----
-
-## Requisitos previos
-
-| Artículo | Mínimo | Recomendado |
-| -------------- | ------------------------ | --------------------- |
-| **procesador** | 1 CPU virtual | 2 CPU virtuales |
-| **RAM** | 1 GB | 2 GB |
-| **Disco** | SSD de 10 GB | SSD de 25 GB |
-| **SO** | Ubuntu 22.04 LTS | Ubuntu 24.04 LTS |
-| **Dominio** | Registrado en Cloudflare | — |
-| **Acoplador** | Motor Docker 24+ | Ventana acoplable 27+ |
-
-**Proveedores probados**: Akamai (Linode), DigitalOcean, Vultr, Hetzner, AWS Lightsail.
-
----
-
-## 1. Configurar la máquina virtual
-
-### 1.1 Crear la instancia
-
-En su proveedor VPS preferido:
-
-- Elija Ubuntu 24.04 LTS
-- Seleccione el plan mínimo (1 vCPU / 1 GB de RAM)
-- Establezca una contraseña de root segura o configure la clave SSH
-- Tenga en cuenta la **IP pública** (por ejemplo, `203.0.113.10`)
-
-### 1.2 Conectarse vía SSH
-
-```bash
-ssh root@203.0.113.10
-```
-
-### 1.3 Actualizar el sistema
-
-```bash
-apt update && apt upgrade -y
-```
-
-### 1.4 Instalar Docker
-
-```bash
-# Install dependencies
-apt install -y ca-certificates curl gnupg
-
-# Add official Docker repository
-install -m 0755 -d /etc/apt/keyrings
-curl -fsSL https://download.docker.com/linux/ubuntu/gpg | gpg --dearmor -o /etc/apt/keyrings/docker.gpg
-chmod a+r /etc/apt/keyrings/docker.gpg
-echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu $ (. /etc/os-release && echo “$VERSION_CODENAME”) stable" | tee /etc/apt/sources.list.d/docker.list > /dev/null
-apt update
-apt install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin
-```
-
-### 1.5 Instalar nginx
-
-```bash
-apt install -y nginx
-```
-
-### 1.6 Configurar el cortafuegos (UFW)
-
-```bash
-ufw default deny incoming
-ufw default allow outgoing
-ufw allow 22/tcp # SSH
-ufw allow 80/tcp # HTTP (redirect)
-ufw allow 443/tcp # HTTPS
-ufw enable
-```
-
-> **Consejo**: Para máxima seguridad, restrinja los puertos 80 y 443 solo a las IP de Cloudflare. Consulte la sección [Advanced Security](#advanced-security).
-
----
-
-## 2. Instalar OmniRoute
-
-### 2.1 Crear directorio de configuración
-
-```bash
-mkdir -p /opt/omniroute
-```
-
-### 2.2 Crear archivo de variables de entorno
-
-```bash
-cat > /opt/omniroute/.env << ‘EOF’
-# === Security ===
-JWT_SECRET=CHANGE-TO-A-UNIQUE-64-CHAR-SECRET-KEY
-INITIAL_PASSWORD=YourSecurePassword123!
-API_KEY_SECRET=REPLACE-WITH-ANOTHER-SECRET-KEY
-STORAGE_ENCRYPTION_KEY=REPLACE-WITH-THIRD-SECRET-KEY
-STORAGE_ENCRYPTION_KEY_VERSION=v1
-MACHINE_ID_SALT=CHANGE-TO-A-UNIQUE-SALT
-
-# === App ===
-PORT=20128
-NODE_ENV=production
-HOSTNAME=0.0.0.0
-DATA_DIR=/app/data
-STORAGE_DRIVER=sqlite
-ENABLE_REQUEST_LOGS=true
-AUTH_COOKIE_SECURE=false
-REQUIRE_API_KEY=false
-
-# === Domain (change to your domain) ===
-BASE_URL=https://llms.seudominio.com
-NEXT_PUBLIC_BASE_URL=https://llms.seudominio.com
-
-# === Cloud Sync (optional) ===
-# CLOUD_URL=https://cloud.omniroute.online
-# NEXT_PUBLIC_CLOUD_URL=https://cloud.omniroute.online
-EOF
-```
-
-> ⚠️ **IMPORTANTE**: ¡Genera claves secretas únicas! Utilice `openssl rand -hex 32` para cada clave.
-
-### 2.3 Iniciar el contenedor
-
-```bash
-docker pull diegosouzapw/omniroute:latest
-
-docker run -d \
- --name omniroute \
- --restart unless-stopped \
- --env-file /opt/omniroute/.env \
- -p 20128:20128 \
- -v omniroute-data:/app/data \
- diegosouzapw/omniroute:latest
-```
-
-### 2.4 Verificar que esté funcionando
-
-```bash
-docker ps | grep omniroute
-docker logs omniroute --tail 20
-```
-
-Debería mostrar: `[DB] SQLite database ready` y `listening on port 20128`.
-
----
-
-## 3. Configurar nginx (Proxy inverso)
-
-### 3.1 Generar certificado SSL (Origen Cloudflare)
-
-En el panel de Cloudflare:
-
-1. Vaya a **SSL/TLS → Servidor de origen**
-2. Haga clic en **Crear certificado**
-3. Mantenga los valores predeterminados (15 años, \*.sudominio.com)
-4. Copie el **Certificado de Origen** y la **Clave Privada**
-
-```bash
-mkdir -p /etc/nginx/ssl
-
-# Paste the certificate
-nano /etc/nginx/ssl/origin.crt
-
-# Paste the private key
-nano /etc/nginx/ssl/origin.key
-
-chmod 600 /etc/nginx/ssl/origin.key
-```
-
-### 3.2 Configuración de Nginx
-
-```bash
-cat > /etc/nginx/sites-available/omniroute << ‘NGINX’
-# Default server — blocks direct access via IP
-server {
- listen 80 default_server;
- listen [::]:80 default_server;
- listen 443 ssl default_server;
- listen [::]:443 ssl default_server;
- ssl_certificate /etc/nginx/ssl/origin.crt;
- ssl_certificate_key /etc/nginx/ssl/origin.key;
- server_name _;
- return 444;
-}
-
-# OmniRoute — HTTPS
-server {
- listen 443 ssl;
- listen [::]:443 ssl;
- server_name llms.yourdomain.com; # Change to your domain
-
- ssl_certificate /etc/nginx/ssl/origin.crt;
- ssl_certificate_key /etc/nginx/ssl/origin.key;
- ssl_protocols TLSv1.2 TLSv1.3;
-
- client_max_body_size 100M;
-
- location / {
- proxy_pass http://127.0.0.1:20128;
- proxy_set_header Host $host;
- proxy_set_header X-Real-IP $remote_addr;
- proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
- proxy_set_header X-Forwarded-Proto $scheme;
-
- # WebSocket support
- proxy_http_version 1.1;
- proxy_set_header Upgrade $http_upgrade;
- proxy_set_header Connection “upgrade”;
-
- # SSE (Server-Sent Events) — streaming AI responses
- proxy_buffering off;
- proxy_cache off;
- proxy_read_timeout 300s;
- proxy_send_timeout 300s;
- }
-}
-
-# HTTP → HTTPS redirect
-server {
- listen 80;
- listen [::]:80;
- server_name llms.yourdomain.com;
- return 301 https://$server_name$request_uri;
-}
-NGINX
-```
-
-### 3.3 Habilitar y probar
-
-```bash
-# Remove default configuration
-rm -f /etc/nginx/sites-enabled/default
-
-# Enable OmniRoute
-ln -sf /etc/nginx/sites-available/omniroute /etc/nginx/sites-enabled/omniroute
-
-# Test and reload
-nginx -t && systemctl reload nginx
-```
-
----
-
-## 4. Configurar DNS de Cloudflare
-
-### 4.1 Agregar registro DNS
-
-En el panel de Cloudflare → DNS:
-
-| Tipo | Nombre | Contenido | Apoderado |
-| ---- | ------ | ----------------------------------------- | ------------ |
-| Un | `llms` | `203.0.113.10` (IP de la máquina virtual) | ✅ Apoderado |
-
-### 4.2 Configurar SSL
-
-En **SSL/TLS → Descripción general**:
-
-- Modo: **Completo (Estricto)**
-
-En **SSL/TLS → Certificados perimetrales**:
-
-- Utilice siempre HTTPS: ✅ Activado
-- Versión mínima de TLS: TLS 1.2
-- Reescrituras HTTPS automáticas: ✅ Activado
-
-### 4.3 Pruebas
-
-```bash
-curl -sI https://llms.seudominio.com/health
-# Should return HTTP/2 200
-```
-
----
-
-## 5. Operaciones y Mantenimiento
-
-### Actualizar a una nueva versión
-
-```bash
-docker pull diegosouzapw/omniroute:latest
-docker stop omniroute && docker rm omniroute
-docker run -d --name omniroute --restart unless-stopped \
- --env-file /opt/omniroute/.env \
- -p 20128:20128 \
- -v omniroute-data:/app/data \
- diegosouzapw/omniroute:latest
-```
-
-### Ver registros
-
-```bash
-docker logs -f omniroute # Real-time stream
-docker logs omniroute --tail 50 # Last 50 lines
-```
-
-### Copia de seguridad manual de la base de datos
-
-```bash
-# Copy data from the volume to the host
-docker cp omniroute:/app/data ./backup-$(date +%F)
-
-# Or compress the entire volume
-docker run --rm -v omniroute-data:/data -v $(pwd):/backup \
- alpine tar czf /backup/omniroute-data-$(date +%F).tar.gz /data
-```
-
-### Restaurar desde copia de seguridad
-
-```bash
-docker stop omniroute
-docker run --rm -v omniroute-data:/data -v $(pwd):/backup \
- alpine sh -c “rm -rf /data/* && tar xzf /backup/omniroute-data-YYYY-MM-DD.tar.gz -C /”
-docker start omniroute
-```
-
----
-
-## 6. Seguridad avanzada
-
-### Restringir nginx a las IP de Cloudflare
-
-```bash
-cat > /etc/nginx/cloudflare-ips.conf << ‘CF’
-# Cloudflare IPv4 ranges — update periodically
-# https://www.cloudflare.com/ips-v4/
-set_real_ip_from 173.245.48.0/20;
-set_real_ip_from 103.21.244.0/22;
-set_real_ip_from 103.22.200.0/22;
-set_real_ip_from 103.31.4.0/22;
-set_real_ip_from 141.101.64.0/18;
-set_real_ip_from 108.162.192.0/18;
-set_real_ip_from 190.93.240.0/20;
-set_real_ip_from 188.114.96.0/20;
-set_real_ip_from 197.234.240.0/22;
-set_real_ip_from 198.41.128.0/17;
-set_real_ip_from 162.158.0.0/15;
-set_real_ip_from 104.16.0.0/13;
-set_real_ip_from 104.24.0.0/14;
-set_real_ip_from 172.64.0.0/13;
-set_real_ip_from 131.0.72.0/22;
-real_ip_header CF-Connecting-IP;
-CF
-```
-
-Agregue lo siguiente a `nginx.conf` dentro del bloque `http {}`:
-
-```nginx
-include /etc/nginx/cloudflare-ips.conf;
-```
-
-### Instalar fail2ban
-
-```bash
-apt install -y fail2ban
-systemctl enable fail2ban
-systemctl start fail2ban
-
-# Check status
-fail2ban-client status sshd
-```
-
-### Bloquear el acceso directo al puerto Docker
-
-```bash
-# Prevent direct external access to port 20128
-iptables -I DOCKER-USER -p tcp --dport 20128 -j DROP
-iptables -I DOCKER-USER -i lo -p tcp --dport 20128 -j ACCEPT
-
-# Persist the rules
-apt install -y iptables-persistent
-netfilter-persistent save
-```
-
----
-
-## 7. Implementación para trabajadores de Cloudflare (opcional)
-
-Para acceso remoto a través de Cloudflare Workers (sin exponer la VM directamente):
-
-```bash
-# In the local repository
-cd omnirouteCloud
-npm install
-npx wrangler login
-npx wrangler deploy
-```
-
-Consulte la documentación completa en [omnirouteCloud/README.md](../omnirouteCloud/README.md).
-
----
-
-## Resumen de puerto
-
-| Puerto | Servicio | Acceso |
-| ------ | ----------- | ---------------------------------- |
-| 22 | SSH | Público (con fail2ban) |
-| 80 | nginxHTTP | Redirigir → HTTPS |
-| 443 | nginx HTTPS | A través del proxy de Cloudflare |
-| 20128 | OmniRuta | Solo localhost (a través de nginx) |
diff --git a/docs/i18n/es/docs/A2A-SERVER.md b/docs/i18n/es/docs/A2A-SERVER.md
new file mode 100644
index 0000000000..f3dd07d543
--- /dev/null
+++ b/docs/i18n/es/docs/A2A-SERVER.md
@@ -0,0 +1,200 @@
+# OmniRoute A2A Server Documentation (Español)
+
+🌐 **Languages:** 🇺🇸 [English](../../../../docs/A2A-SERVER.md) · 🇪🇸 [es](../../es/docs/A2A-SERVER.md) · 🇫🇷 [fr](../../fr/docs/A2A-SERVER.md) · 🇩🇪 [de](../../de/docs/A2A-SERVER.md) · 🇮🇹 [it](../../it/docs/A2A-SERVER.md) · 🇷🇺 [ru](../../ru/docs/A2A-SERVER.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/A2A-SERVER.md) · 🇯🇵 [ja](../../ja/docs/A2A-SERVER.md) · 🇰🇷 [ko](../../ko/docs/A2A-SERVER.md) · 🇸🇦 [ar](../../ar/docs/A2A-SERVER.md) · 🇮🇳 [in](../../in/docs/A2A-SERVER.md) · 🇹🇭 [th](../../th/docs/A2A-SERVER.md) · 🇻🇳 [vi](../../vi/docs/A2A-SERVER.md) · 🇮🇩 [id](../../id/docs/A2A-SERVER.md) · 🇲🇾 [ms](../../ms/docs/A2A-SERVER.md) · 🇳🇱 [nl](../../nl/docs/A2A-SERVER.md) · 🇵🇱 [pl](../../pl/docs/A2A-SERVER.md) · 🇸🇪 [sv](../../sv/docs/A2A-SERVER.md) · 🇳🇴 [no](../../no/docs/A2A-SERVER.md) · 🇩🇰 [da](../../da/docs/A2A-SERVER.md) · 🇫🇮 [fi](../../fi/docs/A2A-SERVER.md) · 🇵🇹 [pt](../../pt/docs/A2A-SERVER.md) · 🇷🇴 [ro](../../ro/docs/A2A-SERVER.md) · 🇭🇺 [hu](../../hu/docs/A2A-SERVER.md) · 🇧🇬 [bg](../../bg/docs/A2A-SERVER.md) · 🇸🇰 [sk](../../sk/docs/A2A-SERVER.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/A2A-SERVER.md) · 🇮🇱 [he](../../he/docs/A2A-SERVER.md) · 🇵🇭 [phi](../../phi/docs/A2A-SERVER.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/A2A-SERVER.md) · 🇨🇿 [cs](../../cs/docs/A2A-SERVER.md)
+
+---
+
+> Agent-to-Agent Protocol v0.3 — OmniRoute as an intelligent routing agent
+
+## Agent Discovery
+
+```bash
+curl http://localhost:20128/.well-known/agent.json
+```
+
+Returns the Agent Card describing OmniRoute's capabilities, skills, and authentication requirements.
+
+---
+
+## Authentication
+
+All `/a2a` requests require an API key via the `Authorization` header:
+
+```
+Authorization: Bearer YOUR_OMNIROUTE_API_KEY
+```
+
+If no API key is configured on the server, authentication is bypassed.
+
+---
+
+## JSON-RPC 2.0 Methods
+
+### `message/send` — Synchronous Execution
+
+Sends a message to a skill and waits for the complete response.
+
+```bash
+curl -X POST http://localhost:20128/a2a \
+ -H "Content-Type: application/json" \
+ -H "Authorization: Bearer YOUR_KEY" \
+ -d '{
+ "jsonrpc": "2.0",
+ "id": "1",
+ "method": "message/send",
+ "params": {
+ "skill": "smart-routing",
+ "messages": [{"role": "user", "content": "Write a hello world in Python"}],
+ "metadata": {"model": "auto", "combo": "fast-coding"}
+ }
+ }'
+```
+
+**Response:**
+
+```json
+{
+ "jsonrpc": "2.0",
+ "id": "1",
+ "result": {
+ "task": { "id": "uuid", "state": "completed" },
+ "artifacts": [{ "type": "text", "content": "..." }],
+ "metadata": {
+ "routing_explanation": "Selected claude-sonnet via provider \"anthropic\" (latency: 1200ms, cost: $0.003)",
+ "cost_envelope": { "estimated": 0.005, "actual": 0.003, "currency": "USD" },
+ "resilience_trace": [
+ { "event": "primary_selected", "provider": "anthropic", "timestamp": "..." }
+ ],
+ "policy_verdict": { "allowed": true, "reason": "within budget and quota limits" }
+ }
+ }
+}
+```
+
+### `message/stream` — SSE Streaming
+
+Same as `message/send` but returns Server-Sent Events for real-time streaming.
+
+```bash
+curl -N -X POST http://localhost:20128/a2a \
+ -H "Content-Type: application/json" \
+ -H "Authorization: Bearer YOUR_KEY" \
+ -d '{
+ "jsonrpc": "2.0",
+ "id": "1",
+ "method": "message/stream",
+ "params": {
+ "skill": "smart-routing",
+ "messages": [{"role": "user", "content": "Explain quantum computing"}]
+ }
+ }'
+```
+
+**SSE Events:**
+
+```
+data: {"jsonrpc":"2.0","method":"message/stream","params":{"task":{"id":"...","state":"working"},"chunk":{"type":"text","content":"..."}}}
+
+: heartbeat 2026-03-03T17:00:00Z
+
+data: {"jsonrpc":"2.0","method":"message/stream","params":{"task":{"id":"...","state":"completed"},"metadata":{...}}}
+```
+
+### `tasks/get` — Query Task Status
+
+```bash
+curl -X POST http://localhost:20128/a2a \
+ -H "Content-Type: application/json" \
+ -H "Authorization: Bearer YOUR_KEY" \
+ -d '{"jsonrpc":"2.0","id":"2","method":"tasks/get","params":{"taskId":"TASK_UUID"}}'
+```
+
+### `tasks/cancel` — Cancel a Task
+
+```bash
+curl -X POST http://localhost:20128/a2a \
+ -H "Content-Type: application/json" \
+ -H "Authorization: Bearer YOUR_KEY" \
+ -d '{"jsonrpc":"2.0","id":"3","method":"tasks/cancel","params":{"taskId":"TASK_UUID"}}'
+```
+
+---
+
+## Available Skills
+
+| Skill | Description |
+| :----------------- | :------------------------------------------------------------------------------------------------------------------------------ |
+| `smart-routing` | Routes prompts through OmniRoute's intelligent pipeline. Returns response with routing explanation, cost, and resilience trace. |
+| `quota-management` | Answers natural-language queries about provider quotas, suggests free combos, and provides quota rankings. |
+
+---
+
+## Task Lifecycle
+
+```
+submitted → working → completed
+ → failed
+ → cancelled
+```
+
+- Tasks expire after 5 minutes (configurable)
+- Terminal states: `completed`, `failed`, `cancelled`
+- Event log tracks every state transition
+
+---
+
+## Error Codes
+
+| Code | Meaning |
+| :----- | :----------------------------- |
+| -32700 | Parse error (invalid JSON) |
+| -32600 | Invalid request / Unauthorized |
+| -32601 | Method or skill not found |
+| -32602 | Invalid params |
+| -32603 | Internal error |
+
+---
+
+## Integration Examples
+
+### Python (requests)
+
+```python
+import requests
+
+resp = requests.post("http://localhost:20128/a2a", json={
+ "jsonrpc": "2.0", "id": "1",
+ "method": "message/send",
+ "params": {
+ "skill": "smart-routing",
+ "messages": [{"role": "user", "content": "Hello"}]
+ }
+}, headers={"Authorization": "Bearer YOUR_KEY"})
+
+result = resp.json()["result"]
+print(result["artifacts"][0]["content"])
+print(result["metadata"]["routing_explanation"])
+```
+
+### TypeScript (fetch)
+
+```typescript
+const resp = await fetch("http://localhost:20128/a2a", {
+ method: "POST",
+ headers: {
+ "Content-Type": "application/json",
+ Authorization: "Bearer YOUR_KEY",
+ },
+ body: JSON.stringify({
+ jsonrpc: "2.0",
+ id: "1",
+ method: "message/send",
+ params: {
+ skill: "smart-routing",
+ messages: [{ role: "user", content: "Hello" }],
+ },
+ }),
+});
+const { result } = await resp.json();
+console.log(result.metadata.routing_explanation);
+```
diff --git a/docs/i18n/es/docs/API_REFERENCE.md b/docs/i18n/es/docs/API_REFERENCE.md
new file mode 100644
index 0000000000..7e10627f3e
--- /dev/null
+++ b/docs/i18n/es/docs/API_REFERENCE.md
@@ -0,0 +1,465 @@
+# API Reference (Español)
+
+🌐 **Languages:** 🇺🇸 [English](../../../../docs/API_REFERENCE.md) · 🇪🇸 [es](../../es/docs/API_REFERENCE.md) · 🇫🇷 [fr](../../fr/docs/API_REFERENCE.md) · 🇩🇪 [de](../../de/docs/API_REFERENCE.md) · 🇮🇹 [it](../../it/docs/API_REFERENCE.md) · 🇷🇺 [ru](../../ru/docs/API_REFERENCE.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/API_REFERENCE.md) · 🇯🇵 [ja](../../ja/docs/API_REFERENCE.md) · 🇰🇷 [ko](../../ko/docs/API_REFERENCE.md) · 🇸🇦 [ar](../../ar/docs/API_REFERENCE.md) · 🇮🇳 [in](../../in/docs/API_REFERENCE.md) · 🇹🇭 [th](../../th/docs/API_REFERENCE.md) · 🇻🇳 [vi](../../vi/docs/API_REFERENCE.md) · 🇮🇩 [id](../../id/docs/API_REFERENCE.md) · 🇲🇾 [ms](../../ms/docs/API_REFERENCE.md) · 🇳🇱 [nl](../../nl/docs/API_REFERENCE.md) · 🇵🇱 [pl](../../pl/docs/API_REFERENCE.md) · 🇸🇪 [sv](../../sv/docs/API_REFERENCE.md) · 🇳🇴 [no](../../no/docs/API_REFERENCE.md) · 🇩🇰 [da](../../da/docs/API_REFERENCE.md) · 🇫🇮 [fi](../../fi/docs/API_REFERENCE.md) · 🇵🇹 [pt](../../pt/docs/API_REFERENCE.md) · 🇷🇴 [ro](../../ro/docs/API_REFERENCE.md) · 🇭🇺 [hu](../../hu/docs/API_REFERENCE.md) · 🇧🇬 [bg](../../bg/docs/API_REFERENCE.md) · 🇸🇰 [sk](../../sk/docs/API_REFERENCE.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/API_REFERENCE.md) · 🇮🇱 [he](../../he/docs/API_REFERENCE.md) · 🇵🇭 [phi](../../phi/docs/API_REFERENCE.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/API_REFERENCE.md) · 🇨🇿 [cs](../../cs/docs/API_REFERENCE.md)
+
+---
+
+Complete reference for all OmniRoute API endpoints.
+
+---
+
+## Table of Contents
+
+- [Chat Completions](#chat-completions)
+- [Embeddings](#embeddings)
+- [Image Generation](#image-generation)
+- [List Models](#list-models)
+- [Compatibility Endpoints](#compatibility-endpoints)
+- [Semantic Cache](#semantic-cache)
+- [Dashboard & Management](#dashboard--management)
+- [Request Processing](#request-processing)
+- [Authentication](#authentication)
+
+---
+
+## Chat Completions
+
+```bash
+POST /v1/chat/completions
+Authorization: Bearer your-api-key
+Content-Type: application/json
+
+{
+ "model": "cc/claude-opus-4-6",
+ "messages": [
+ {"role": "user", "content": "Write a function to..."}
+ ],
+ "stream": true
+}
+```
+
+### Custom Headers
+
+| Header | Direction | Description |
+| ------------------------ | --------- | ------------------------------------------------ |
+| `X-OmniRoute-No-Cache` | Request | Set to `true` to bypass cache |
+| `X-OmniRoute-Progress` | Request | Set to `true` for progress events |
+| `X-Session-Id` | Request | Sticky session key for external session affinity |
+| `x_session_id` | Request | Underscore variant also accepted (direct HTTP) |
+| `Idempotency-Key` | Request | Dedup key (5s window) |
+| `X-Request-Id` | Request | Alternative dedup key |
+| `X-OmniRoute-Cache` | Response | `HIT` or `MISS` (non-streaming) |
+| `X-OmniRoute-Idempotent` | Response | `true` if deduplicated |
+| `X-OmniRoute-Progress` | Response | `enabled` if progress tracking on |
+| `X-OmniRoute-Session-Id` | Response | Effective session ID used by OmniRoute |
+
+> Nginx note: if you rely on underscore headers (for example `x_session_id`), enable `underscores_in_headers on;`.
+
+---
+
+## Embeddings
+
+```bash
+POST /v1/embeddings
+Authorization: Bearer your-api-key
+Content-Type: application/json
+
+{
+ "model": "nebius/Qwen/Qwen3-Embedding-8B",
+ "input": "The food was delicious"
+}
+```
+
+Available providers: Nebius, OpenAI, Mistral, Together AI, Fireworks, NVIDIA.
+
+```bash
+# List all embedding models
+GET /v1/embeddings
+```
+
+---
+
+## Image Generation
+
+```bash
+POST /v1/images/generations
+Authorization: Bearer your-api-key
+Content-Type: application/json
+
+{
+ "model": "openai/dall-e-3",
+ "prompt": "A beautiful sunset over mountains",
+ "size": "1024x1024"
+}
+```
+
+Available providers: OpenAI (DALL-E), xAI (Grok Image), Together AI (FLUX), Fireworks AI.
+
+```bash
+# List all image models
+GET /v1/images/generations
+```
+
+---
+
+## List Models
+
+```bash
+GET /v1/models
+Authorization: Bearer your-api-key
+
+→ Returns all chat, embedding, and image models + combos in OpenAI format
+```
+
+---
+
+## Compatibility Endpoints
+
+| Method | Path | Format |
+| ------ | --------------------------- | ---------------------- |
+| POST | `/v1/chat/completions` | OpenAI |
+| POST | `/v1/messages` | Anthropic |
+| POST | `/v1/responses` | OpenAI Responses |
+| POST | `/v1/embeddings` | OpenAI |
+| POST | `/v1/images/generations` | OpenAI |
+| GET | `/v1/models` | OpenAI |
+| POST | `/v1/messages/count_tokens` | Anthropic |
+| GET | `/v1beta/models` | Gemini |
+| POST | `/v1beta/models/{...path}` | Gemini generateContent |
+| POST | `/v1/api/chat` | Ollama |
+
+### Dedicated Provider Routes
+
+```bash
+POST /v1/providers/{provider}/chat/completions
+POST /v1/providers/{provider}/embeddings
+POST /v1/providers/{provider}/images/generations
+```
+
+The provider prefix is auto-added if missing. Mismatched models return `400`.
+
+---
+
+## Semantic Cache
+
+```bash
+# Get cache stats
+GET /api/cache/stats
+
+# Clear all caches
+DELETE /api/cache/stats
+```
+
+Response example:
+
+```json
+{
+ "semanticCache": {
+ "memorySize": 42,
+ "memoryMaxSize": 500,
+ "dbSize": 128,
+ "hitRate": 0.65
+ },
+ "idempotency": {
+ "activeKeys": 3,
+ "windowMs": 5000
+ }
+}
+```
+
+---
+
+## Dashboard & Management
+
+### Authentication
+
+| Endpoint | Method | Description |
+| ----------------------------- | ------- | --------------------- |
+| `/api/auth/login` | POST | Login |
+| `/api/auth/logout` | POST | Logout |
+| `/api/settings/require-login` | GET/PUT | Toggle login required |
+
+### Provider Management
+
+| Endpoint | Method | Description |
+| ---------------------------- | --------------- | ------------------------ |
+| `/api/providers` | GET/POST | List / create providers |
+| `/api/providers/[id]` | GET/PUT/DELETE | Manage a provider |
+| `/api/providers/[id]/test` | POST | Test provider connection |
+| `/api/providers/[id]/models` | GET | List provider models |
+| `/api/providers/validate` | POST | Validate provider config |
+| `/api/provider-nodes*` | Various | Provider node management |
+| `/api/provider-models` | GET/POST/DELETE | Custom models |
+
+### OAuth Flows
+
+| Endpoint | Method | Description |
+| -------------------------------- | ------- | ----------------------- |
+| `/api/oauth/[provider]/[action]` | Various | Provider-specific OAuth |
+
+### Routing & Config
+
+| Endpoint | Method | Description |
+| --------------------- | -------- | ----------------------------- |
+| `/api/models/alias` | GET/POST | Model aliases |
+| `/api/models/catalog` | GET | All models by provider + type |
+| `/api/combos*` | Various | Combo management |
+| `/api/keys*` | Various | API key management |
+| `/api/pricing` | GET | Model pricing |
+
+### Usage & Analytics
+
+| Endpoint | Method | Description |
+| --------------------------- | ------ | -------------------- |
+| `/api/usage/history` | GET | Usage history |
+| `/api/usage/logs` | GET | Usage logs |
+| `/api/usage/request-logs` | GET | Request-level logs |
+| `/api/usage/[connectionId]` | GET | Per-connection usage |
+
+### Settings
+
+| Endpoint | Method | Description |
+| ------------------------------- | ------------- | ---------------------- |
+| `/api/settings` | GET/PUT/PATCH | General settings |
+| `/api/settings/proxy` | GET/PUT | Network proxy config |
+| `/api/settings/proxy/test` | POST | Test proxy connection |
+| `/api/settings/ip-filter` | GET/PUT | IP allowlist/blocklist |
+| `/api/settings/thinking-budget` | GET/PUT | Reasoning token budget |
+| `/api/settings/system-prompt` | GET/PUT | Global system prompt |
+
+### Monitoring
+
+| Endpoint | Method | Description |
+| ------------------------ | ---------- | ---------------------------------------------------------------------------------------------------- |
+| `/api/sessions` | GET | Active session tracking |
+| `/api/rate-limits` | GET | Per-account rate limits |
+| `/api/monitoring/health` | GET | Health check + provider summary (`catalogCount`, `configuredCount`, `activeCount`, `monitoredCount`) |
+| `/api/cache/stats` | GET/DELETE | Cache stats / clear |
+
+### Backup & Export/Import
+
+| Endpoint | Method | Description |
+| --------------------------- | ------ | --------------------------------------- |
+| `/api/db-backups` | GET | List available backups |
+| `/api/db-backups` | PUT | Create a manual backup |
+| `/api/db-backups` | POST | Restore from a specific backup |
+| `/api/db-backups/export` | GET | Download database as .sqlite file |
+| `/api/db-backups/import` | POST | Upload .sqlite file to replace database |
+| `/api/db-backups/exportAll` | GET | Download full backup as .tar.gz archive |
+
+### Cloud Sync
+
+| Endpoint | Method | Description |
+| ---------------------- | ------- | --------------------- |
+| `/api/sync/cloud` | Various | Cloud sync operations |
+| `/api/sync/initialize` | POST | Initialize sync |
+| `/api/cloud/*` | Various | Cloud management |
+
+### Tunnels
+
+| Endpoint | Method | Description |
+| -------------------------- | ------ | ----------------------------------------------------------------------- |
+| `/api/tunnels/cloudflared` | GET | Read Cloudflare Quick Tunnel install/runtime status for the dashboard |
+| `/api/tunnels/cloudflared` | POST | Enable or disable the Cloudflare Quick Tunnel (`action=enable/disable`) |
+
+### CLI Tools
+
+| Endpoint | Method | Description |
+| ---------------------------------- | ------ | ------------------- |
+| `/api/cli-tools/claude-settings` | GET | Claude CLI status |
+| `/api/cli-tools/codex-settings` | GET | Codex CLI status |
+| `/api/cli-tools/droid-settings` | GET | Droid CLI status |
+| `/api/cli-tools/openclaw-settings` | GET | OpenClaw CLI status |
+| `/api/cli-tools/runtime/[toolId]` | GET | Generic CLI runtime |
+
+CLI responses include: `installed`, `runnable`, `command`, `commandPath`, `runtimeMode`, `reason`.
+
+### ACP Agents
+
+| Endpoint | Method | Description |
+| ----------------- | ------ | -------------------------------------------------------- |
+| `/api/acp/agents` | GET | List all detected agents (built-in + custom) with status |
+| `/api/acp/agents` | POST | Add custom agent or refresh detection cache |
+| `/api/acp/agents` | DELETE | Remove a custom agent by `id` query param |
+
+GET response includes `agents[]` (id, name, binary, version, installed, protocol, isCustom) and `summary` (total, installed, notFound, builtIn, custom).
+
+### Resilience & Rate Limits
+
+| Endpoint | Method | Description |
+| ----------------------- | --------- | ------------------------------- |
+| `/api/resilience` | GET/PATCH | Get/update resilience profiles |
+| `/api/resilience/reset` | POST | Reset circuit breakers |
+| `/api/rate-limits` | GET | Per-account rate limit status |
+| `/api/rate-limit` | GET | Global rate limit configuration |
+
+### Evals
+
+| Endpoint | Method | Description |
+| ------------ | -------- | --------------------------------- |
+| `/api/evals` | GET/POST | List eval suites / run evaluation |
+
+### Policies
+
+| Endpoint | Method | Description |
+| --------------- | --------------- | ----------------------- |
+| `/api/policies` | GET/POST/DELETE | Manage routing policies |
+
+### Compliance
+
+| Endpoint | Method | Description |
+| --------------------------- | ------ | ----------------------------- |
+| `/api/compliance/audit-log` | GET | Compliance audit log (last N) |
+
+### v1beta (Gemini-Compatible)
+
+| Endpoint | Method | Description |
+| -------------------------- | ------ | --------------------------------- |
+| `/v1beta/models` | GET | List models in Gemini format |
+| `/v1beta/models/{...path}` | POST | Gemini `generateContent` endpoint |
+
+These endpoints mirror Gemini's API format for clients that expect native Gemini SDK compatibility.
+
+### Internal / System APIs
+
+| Endpoint | Method | Description |
+| --------------- | ------ | ---------------------------------------------------- |
+| `/api/init` | GET | Application initialization check (used on first run) |
+| `/api/tags` | GET | Ollama-compatible model tags (for Ollama clients) |
+| `/api/restart` | POST | Trigger graceful server restart |
+| `/api/shutdown` | POST | Trigger graceful server shutdown |
+
+> **Note:** These endpoints are used internally by the system or for Ollama client compatibility. They are not typically called by end users.
+
+---
+
+## Audio Transcription
+
+```bash
+POST /v1/audio/transcriptions
+Authorization: Bearer your-api-key
+Content-Type: multipart/form-data
+```
+
+Transcribe audio files using Deepgram or AssemblyAI.
+
+**Request:**
+
+```bash
+curl -X POST http://localhost:20128/v1/audio/transcriptions \
+ -H "Authorization: Bearer your-api-key" \
+ -F "file=@recording.mp3" \
+ -F "model=deepgram/nova-3"
+```
+
+**Response:**
+
+```json
+{
+ "text": "Hello, this is the transcribed audio content.",
+ "task": "transcribe",
+ "language": "en",
+ "duration": 12.5
+}
+```
+
+**Supported providers:** `deepgram/nova-3`, `assemblyai/best`.
+
+**Supported formats:** `mp3`, `wav`, `m4a`, `flac`, `ogg`, `webm`.
+
+---
+
+## Ollama Compatibility
+
+For clients that use Ollama's API format:
+
+```bash
+# Chat endpoint (Ollama format)
+POST /v1/api/chat
+
+# Model listing (Ollama format)
+GET /api/tags
+```
+
+Requests are automatically translated between Ollama and internal formats.
+
+---
+
+## Telemetry
+
+```bash
+# Get latency telemetry summary (p50/p95/p99 per provider)
+GET /api/telemetry/summary
+```
+
+**Response:**
+
+```json
+{
+ "providers": {
+ "claudeCode": { "p50": 245, "p95": 890, "p99": 1200, "count": 150 },
+ "github": { "p50": 180, "p95": 620, "p99": 950, "count": 320 }
+ }
+}
+```
+
+---
+
+## Budget
+
+```bash
+# Get budget status for all API keys
+GET /api/usage/budget
+
+# Set or update a budget
+POST /api/usage/budget
+Content-Type: application/json
+
+{
+ "keyId": "key-123",
+ "limit": 50.00,
+ "period": "monthly"
+}
+```
+
+---
+
+## Model Availability
+
+```bash
+# Get real-time model availability across all providers
+GET /api/models/availability
+
+# Check availability for a specific model
+POST /api/models/availability
+Content-Type: application/json
+
+{
+ "model": "claude-sonnet-4-5-20250929"
+}
+```
+
+---
+
+## Request Processing
+
+1. Client sends request to `/v1/*`
+2. Route handler calls `handleChat`, `handleEmbedding`, `handleAudioTranscription`, or `handleImageGeneration`
+3. Model is resolved (direct provider/model or alias/combo)
+4. Credentials selected from local DB with account availability filtering
+5. For chat: `handleChatCore` — format detection, translation, cache check, idempotency check
+6. Provider executor sends upstream request
+7. Response translated back to client format (chat) or returned as-is (embeddings/images/audio)
+8. Usage/logging recorded
+9. Fallback applies on errors according to combo rules
+
+Full architecture reference: [`ARCHITECTURE.md`](ARCHITECTURE.md)
+
+---
+
+## Authentication
+
+- Dashboard routes (`/dashboard/*`) use `auth_token` cookie
+- Login uses saved password hash; fallback to `INITIAL_PASSWORD`
+- `requireLogin` toggleable via `/api/settings/require-login`
+- `/v1/*` routes optionally require Bearer API key when `REQUIRE_API_KEY=true`
diff --git a/docs/i18n/es/docs/ARCHITECTURE.md b/docs/i18n/es/docs/ARCHITECTURE.md
new file mode 100644
index 0000000000..ff05a4f0ef
--- /dev/null
+++ b/docs/i18n/es/docs/ARCHITECTURE.md
@@ -0,0 +1,814 @@
+# OmniRoute Architecture (Español)
+
+🌐 **Languages:** 🇺🇸 [English](../../../../docs/ARCHITECTURE.md) · 🇪🇸 [es](../../es/docs/ARCHITECTURE.md) · 🇫🇷 [fr](../../fr/docs/ARCHITECTURE.md) · 🇩🇪 [de](../../de/docs/ARCHITECTURE.md) · 🇮🇹 [it](../../it/docs/ARCHITECTURE.md) · 🇷🇺 [ru](../../ru/docs/ARCHITECTURE.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/ARCHITECTURE.md) · 🇯🇵 [ja](../../ja/docs/ARCHITECTURE.md) · 🇰🇷 [ko](../../ko/docs/ARCHITECTURE.md) · 🇸🇦 [ar](../../ar/docs/ARCHITECTURE.md) · 🇮🇳 [in](../../in/docs/ARCHITECTURE.md) · 🇹🇭 [th](../../th/docs/ARCHITECTURE.md) · 🇻🇳 [vi](../../vi/docs/ARCHITECTURE.md) · 🇮🇩 [id](../../id/docs/ARCHITECTURE.md) · 🇲🇾 [ms](../../ms/docs/ARCHITECTURE.md) · 🇳🇱 [nl](../../nl/docs/ARCHITECTURE.md) · 🇵🇱 [pl](../../pl/docs/ARCHITECTURE.md) · 🇸🇪 [sv](../../sv/docs/ARCHITECTURE.md) · 🇳🇴 [no](../../no/docs/ARCHITECTURE.md) · 🇩🇰 [da](../../da/docs/ARCHITECTURE.md) · 🇫🇮 [fi](../../fi/docs/ARCHITECTURE.md) · 🇵🇹 [pt](../../pt/docs/ARCHITECTURE.md) · 🇷🇴 [ro](../../ro/docs/ARCHITECTURE.md) · 🇭🇺 [hu](../../hu/docs/ARCHITECTURE.md) · 🇧🇬 [bg](../../bg/docs/ARCHITECTURE.md) · 🇸🇰 [sk](../../sk/docs/ARCHITECTURE.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/ARCHITECTURE.md) · 🇮🇱 [he](../../he/docs/ARCHITECTURE.md) · 🇵🇭 [phi](../../phi/docs/ARCHITECTURE.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/ARCHITECTURE.md) · 🇨🇿 [cs](../../cs/docs/ARCHITECTURE.md)
+
+---
+
+_Last updated: 2026-03-28_
+
+## Executive Summary
+
+OmniRoute is a local AI routing gateway and dashboard built on Next.js.
+It provides a single OpenAI-compatible endpoint (`/v1/*`) and routes traffic across multiple upstream providers with translation, fallback, token refresh, and usage tracking.
+
+Core capabilities:
+
+- OpenAI-compatible API surface for CLI/tools (28 providers)
+- Request/response translation across provider formats
+- Model combo fallback (multi-model sequence)
+- Account-level fallback (multi-account per provider)
+- OAuth + API-key provider connection management
+- Embedding generation via `/v1/embeddings` (6 providers, 9 models)
+- Image generation via `/v1/images/generations` (4 providers, 9 models)
+- Think tag parsing (`...`) for reasoning models
+- Response sanitization for strict OpenAI SDK compatibility
+- Role normalization (developer→system, system→user) for cross-provider compatibility
+- Structured output conversion (json_schema → Gemini responseSchema)
+- Local persistence for providers, keys, aliases, combos, settings, pricing
+- Usage/cost tracking and request logging
+- Optional cloud sync for multi-device/state sync
+- IP allowlist/blocklist for API access control
+- Thinking budget management (passthrough/auto/custom/adaptive)
+- Global system prompt injection
+- Session tracking and fingerprinting
+- Per-account enhanced rate limiting with provider-specific profiles
+- Circuit breaker pattern for provider resilience
+- Anti-thundering herd protection with mutex locking
+- Signature-based request deduplication cache
+- Domain layer: model availability, cost rules, fallback policy, lockout policy
+- Domain state persistence (SQLite write-through cache for fallbacks, budgets, lockouts, circuit breakers)
+- Policy engine for centralized request evaluation (lockout → budget → fallback)
+- Request telemetry with p50/p95/p99 latency aggregation
+- Correlation ID (X-Request-Id) for end-to-end tracing
+- Compliance audit logging with opt-out per API key
+- Eval framework for LLM quality assurance
+- Resilience UI dashboard with real-time circuit breaker status
+- Modular OAuth providers (12 individual modules under `src/lib/oauth/providers/`)
+
+Primary runtime model:
+
+- Next.js app routes under `src/app/api/*` implement both dashboard APIs and compatibility APIs
+- A shared SSE/routing core in `src/sse/*` + `open-sse/*` handles provider execution, translation, streaming, fallback, and usage
+
+## Scope and Boundaries
+
+### In Scope
+
+- Local gateway runtime
+- Dashboard management APIs
+- Provider authentication and token refresh
+- Request translation and SSE streaming
+- Local state + usage persistence
+- Optional cloud sync orchestration
+
+### Out of Scope
+
+- Cloud service implementation behind `NEXT_PUBLIC_CLOUD_URL`
+- Provider SLA/control plane outside local process
+- External CLI binaries themselves (Claude CLI, Codex CLI, etc.)
+
+## Dashboard Surface (Current)
+
+Main pages under `src/app/(dashboard)/dashboard/`:
+
+- `/dashboard` — quick start + provider overview
+- `/dashboard/endpoint` — endpoint proxy + MCP + A2A + API endpoint tabs
+- `/dashboard/providers` — provider connections and credentials
+- `/dashboard/combos` — combo strategies, templates, model routing rules
+- `/dashboard/costs` — cost aggregation and pricing visibility
+- `/dashboard/analytics` — usage analytics and evaluations
+- `/dashboard/limits` — quota/rate controls
+- `/dashboard/cli-tools` — CLI onboarding, runtime detection, config generation
+- `/dashboard/agents` — detected ACP agents + custom agent registration
+- `/dashboard/media` — image/video/music playground
+- `/dashboard/search-tools` — search provider testing and history
+- `/dashboard/health` — uptime, circuit breakers, rate limits
+- `/dashboard/logs` — request/proxy/audit/console logs
+- `/dashboard/settings` — system settings tabs (general, routing, combo defaults, etc.)
+- `/dashboard/api-manager` — API key lifecycle and model permissions
+
+## High-Level System Context
+
+```mermaid
+flowchart LR
+ subgraph Clients[Developer Clients]
+ C1[Claude Code]
+ C2[Codex CLI]
+ C3[OpenClaw / Droid / Cline / Continue / Roo]
+ C4[Custom OpenAI-compatible clients]
+ BROWSER[Browser Dashboard]
+ end
+
+ subgraph Router[OmniRoute Local Process]
+ API[V1 Compatibility API\n/v1/*]
+ DASH[Dashboard + Management API\n/api/*]
+ CORE[SSE + Translation Core\nopen-sse + src/sse]
+ DB[(storage.sqlite)]
+ UDB[(usage tables + log artifacts)]
+ end
+
+ subgraph Upstreams[Upstream Providers]
+ P1[OAuth Providers\nClaude/Codex/Gemini/Qwen/Qoder/GitHub/Kiro/Cursor/Antigravity]
+ P2[API Key Providers\nOpenAI/Anthropic/OpenRouter/GLM/Kimi/MiniMax\nDeepSeek/Groq/xAI/Mistral/Perplexity\nTogether/Fireworks/Cerebras/Cohere/NVIDIA]
+ P3[Compatible Nodes\nOpenAI-compatible / Anthropic-compatible]
+ end
+
+ subgraph Cloud[Optional Cloud Sync]
+ CLOUD[Cloud Sync Endpoint\nNEXT_PUBLIC_CLOUD_URL]
+ end
+
+ C1 --> API
+ C2 --> API
+ C3 --> API
+ C4 --> API
+ BROWSER --> DASH
+
+ API --> CORE
+ DASH --> DB
+ CORE --> DB
+ CORE --> UDB
+
+ CORE --> P1
+ CORE --> P2
+ CORE --> P3
+
+ DASH --> CLOUD
+```
+
+## Core Runtime Components
+
+## 1) API and Routing Layer (Next.js App Routes)
+
+Main directories:
+
+- `src/app/api/v1/*` and `src/app/api/v1beta/*` for compatibility APIs
+- `src/app/api/*` for management/configuration APIs
+- Next rewrites in `next.config.mjs` map `/v1/*` to `/api/v1/*`
+
+Important compatibility routes:
+
+- `src/app/api/v1/chat/completions/route.ts`
+- `src/app/api/v1/messages/route.ts`
+- `src/app/api/v1/responses/route.ts`
+- `src/app/api/v1/models/route.ts` — includes custom models with `custom: true`
+- `src/app/api/v1/embeddings/route.ts` — embedding generation (6 providers)
+- `src/app/api/v1/images/generations/route.ts` — image generation (4+ providers incl. Antigravity/Nebius)
+- `src/app/api/v1/messages/count_tokens/route.ts`
+- `src/app/api/v1/providers/[provider]/chat/completions/route.ts` — dedicated per-provider chat
+- `src/app/api/v1/providers/[provider]/embeddings/route.ts` — dedicated per-provider embeddings
+- `src/app/api/v1/providers/[provider]/images/generations/route.ts` — dedicated per-provider images
+- `src/app/api/v1beta/models/route.ts`
+- `src/app/api/v1beta/models/[...path]/route.ts`
+
+Management domains:
+
+- Auth/settings: `src/app/api/auth/*`, `src/app/api/settings/*`
+- Providers/connections: `src/app/api/providers*`
+- Provider nodes: `src/app/api/provider-nodes*`
+- Custom models: `src/app/api/provider-models` (GET/POST/DELETE)
+- Model catalog: `src/app/api/models/route.ts` (GET)
+- Proxy config: `src/app/api/settings/proxy` (GET/PUT/DELETE) + `src/app/api/settings/proxy/test` (POST)
+- OAuth: `src/app/api/oauth/*`
+- Keys/aliases/combos/pricing: `src/app/api/keys*`, `src/app/api/models/alias`, `src/app/api/combos*`, `src/app/api/pricing`
+- Usage: `src/app/api/usage/*`
+- Sync/cloud: `src/app/api/sync/*`, `src/app/api/cloud/*`
+- CLI tooling helpers: `src/app/api/cli-tools/*`
+- IP filter: `src/app/api/settings/ip-filter` (GET/PUT)
+- Thinking budget: `src/app/api/settings/thinking-budget` (GET/PUT)
+- System prompt: `src/app/api/settings/system-prompt` (GET/PUT)
+- Sessions: `src/app/api/sessions` (GET)
+- Rate limits: `src/app/api/rate-limits` (GET)
+- Resilience: `src/app/api/resilience` (GET/PATCH) — provider profiles, circuit breaker, rate limit state
+- Resilience reset: `src/app/api/resilience/reset` (POST) — reset breakers + cooldowns
+- Cache stats: `src/app/api/cache/stats` (GET/DELETE)
+- Model availability: `src/app/api/models/availability` (GET/POST)
+- Telemetry: `src/app/api/telemetry/summary` (GET)
+- Budget: `src/app/api/usage/budget` (GET/POST)
+- Fallback chains: `src/app/api/fallback/chains` (GET/POST/DELETE)
+- Compliance audit: `src/app/api/compliance/audit-log` (GET)
+- Evals: `src/app/api/evals` (GET/POST), `src/app/api/evals/[suiteId]` (GET)
+- Policies: `src/app/api/policies` (GET/POST)
+
+## 2) SSE + Translation Core
+
+Main flow modules:
+
+- Entry: `src/sse/handlers/chat.ts`
+- Core orchestration: `open-sse/handlers/chatCore.ts`
+- Provider execution adapters: `open-sse/executors/*`
+- Format detection/provider config: `open-sse/services/provider.ts`
+- Model parse/resolve: `src/sse/services/model.ts`, `open-sse/services/model.ts`
+- Account fallback logic: `open-sse/services/accountFallback.ts`
+- Translation registry: `open-sse/translator/index.ts`
+- Stream transformations: `open-sse/utils/stream.ts`, `open-sse/utils/streamHandler.ts`
+- Usage extraction/normalization: `open-sse/utils/usageTracking.ts`
+- Think tag parser: `open-sse/utils/thinkTagParser.ts`
+- Embedding handler: `open-sse/handlers/embeddings.ts`
+- Embedding provider registry: `open-sse/config/embeddingRegistry.ts`
+- Image generation handler: `open-sse/handlers/imageGeneration.ts`
+- Image provider registry: `open-sse/config/imageRegistry.ts`
+- Response sanitization: `open-sse/handlers/responseSanitizer.ts`
+- Role normalization: `open-sse/services/roleNormalizer.ts`
+
+Services (business logic):
+
+- Account selection/scoring: `open-sse/services/accountSelector.ts`
+- Context lifecycle management: `open-sse/services/contextManager.ts`
+- IP filter enforcement: `open-sse/services/ipFilter.ts`
+- Session tracking: `open-sse/services/sessionManager.ts`
+- Request deduplication: `open-sse/services/signatureCache.ts`
+- System prompt injection: `open-sse/services/systemPrompt.ts`
+- Thinking budget management: `open-sse/services/thinkingBudget.ts`
+- Wildcard model routing: `open-sse/services/wildcardRouter.ts`
+- Rate limit management: `open-sse/services/rateLimitManager.ts`
+- Circuit breaker: `open-sse/services/circuitBreaker.ts`
+
+Domain layer modules:
+
+- Model availability: `src/lib/domain/modelAvailability.ts`
+- Cost rules/budgets: `src/lib/domain/costRules.ts`
+- Fallback policy: `src/lib/domain/fallbackPolicy.ts`
+- Combo resolver: `src/lib/domain/comboResolver.ts`
+- Lockout policy: `src/lib/domain/lockoutPolicy.ts`
+- Policy engine: `src/domain/policyEngine.ts` — centralized lockout → budget → fallback evaluation
+- Error codes catalog: `src/lib/domain/errorCodes.ts`
+- Request ID: `src/lib/domain/requestId.ts`
+- Fetch timeout: `src/lib/domain/fetchTimeout.ts`
+- Request telemetry: `src/lib/domain/requestTelemetry.ts`
+- Compliance/audit: `src/lib/domain/compliance/index.ts`
+- Eval runner: `src/lib/domain/evalRunner.ts`
+- Domain state persistence: `src/lib/db/domainState.ts` — SQLite CRUD for fallback chains, budgets, cost history, lockout state, circuit breakers
+
+OAuth provider modules (12 individual files under `src/lib/oauth/providers/`):
+
+- Registry index: `src/lib/oauth/providers/index.ts`
+- Individual providers: `claude.ts`, `codex.ts`, `gemini.ts`, `antigravity.ts`, `qoder.ts`, `qwen.ts`, `kimi-coding.ts`, `github.ts`, `kiro.ts`, `cursor.ts`, `kilocode.ts`, `cline.ts`
+- Thin wrapper: `src/lib/oauth/providers.ts` — re-exports from individual modules
+
+## 3) Persistence Layer
+
+Primary state DB (SQLite):
+
+- Core infra: `src/lib/db/core.ts` (better-sqlite3, migrations, WAL)
+- Re-export facade: `src/lib/localDb.ts` (thin compatibility layer for callers)
+- file: `${DATA_DIR}/storage.sqlite` (or `$XDG_CONFIG_HOME/omniroute/storage.sqlite` when set, else `~/.omniroute/storage.sqlite`)
+- entities (tables + KV namespaces): providerConnections, providerNodes, modelAliases, combos, apiKeys, settings, pricing, **customModels**, **proxyConfig**, **ipFilter**, **thinkingBudget**, **systemPrompt**
+
+Usage persistence:
+
+- facade: `src/lib/usageDb.ts` (decomposed modules in `src/lib/usage/*`)
+- SQLite tables in `storage.sqlite`: `usage_history`, `call_logs`, `proxy_logs`
+- optional file artifacts remain for compatibility/debug (`${DATA_DIR}/log.txt`, `${DATA_DIR}/call_logs/`, `/logs/...`)
+- legacy JSON files are migrated to SQLite by startup migrations when present
+
+Domain State DB (SQLite):
+
+- `src/lib/db/domainState.ts` — CRUD operations for domain state
+- Tables (created in `src/lib/db/core.ts`): `domain_fallback_chains`, `domain_budgets`, `domain_cost_history`, `domain_lockout_state`, `domain_circuit_breakers`
+- Write-through cache pattern: in-memory Maps are authoritative at runtime; mutations are written synchronously to SQLite; state is restored from DB on cold start
+
+## 4) Auth + Security Surfaces
+
+- Dashboard cookie auth: `src/proxy.ts`, `src/app/api/auth/login/route.ts`
+- API key generation/verification: `src/shared/utils/apiKey.ts`
+- Provider secrets persisted in `providerConnections` entries
+- Outbound proxy support via `open-sse/utils/proxyFetch.ts` (env vars) and `open-sse/utils/networkProxy.ts` (configurable per-provider or global)
+
+## 5) Cloud Sync
+
+- Scheduler init: `src/lib/initCloudSync.ts`, `src/shared/services/initializeCloudSync.ts`, `src/shared/services/modelSyncScheduler.ts`
+- Periodic task: `src/shared/services/cloudSyncScheduler.ts`
+- Periodic task: `src/shared/services/modelSyncScheduler.ts`
+- Control route: `src/app/api/sync/cloud/route.ts`
+
+## Request Lifecycle (`/v1/chat/completions`)
+
+```mermaid
+sequenceDiagram
+ autonumber
+ participant Client as CLI/SDK Client
+ participant Route as /api/v1/chat/completions
+ participant Chat as src/sse/handlers/chat
+ participant Core as open-sse/handlers/chatCore
+ participant Model as Model Resolver
+ participant Auth as Credential Selector
+ participant Exec as Provider Executor
+ participant Prov as Upstream Provider
+ participant Stream as Stream Translator
+ participant Usage as usageDb
+
+ Client->>Route: POST /v1/chat/completions
+ Route->>Chat: handleChat(request)
+ Chat->>Model: parse/resolve model or combo
+
+ alt Combo model
+ Chat->>Chat: iterate combo models (handleComboChat)
+ end
+
+ Chat->>Auth: getProviderCredentials(provider)
+ Auth-->>Chat: active account + tokens/api key
+
+ Chat->>Core: handleChatCore(body, modelInfo, credentials)
+ Core->>Core: detect source format
+ Core->>Core: translate request to target format
+ Core->>Exec: execute(provider, transformedBody)
+ Exec->>Prov: upstream API call
+ Prov-->>Exec: SSE/JSON response
+ Exec-->>Core: response + metadata
+
+ alt 401/403
+ Core->>Exec: refreshCredentials()
+ Exec-->>Core: updated tokens
+ Core->>Exec: retry request
+ end
+
+ Core->>Stream: translate/normalize stream to client format
+ Stream-->>Client: SSE chunks / JSON response
+
+ Stream->>Usage: extract usage + persist history/log
+```
+
+## Combo + Account Fallback Flow
+
+```mermaid
+flowchart TD
+ A[Incoming model string] --> B{Is combo name?}
+ B -- Yes --> C[Load combo models sequence]
+ B -- No --> D[Single model path]
+
+ C --> E[Try model N]
+ E --> F[Resolve provider/model]
+ D --> F
+
+ F --> G[Select account credentials]
+ G --> H{Credentials available?}
+ H -- No --> I[Return provider unavailable]
+ H -- Yes --> J[Execute request]
+
+ J --> K{Success?}
+ K -- Yes --> L[Return response]
+ K -- No --> M{Fallback-eligible error?}
+
+ M -- No --> N[Return error]
+ M -- Yes --> O[Mark account unavailable cooldown]
+ O --> P{Another account for provider?}
+ P -- Yes --> G
+ P -- No --> Q{In combo with next model?}
+ Q -- Yes --> E
+ Q -- No --> R[Return all unavailable]
+```
+
+Fallback decisions are driven by `open-sse/services/accountFallback.ts` using status codes and error-message heuristics. Combo routing adds one extra guard: provider-scoped 400s such as upstream content-block and role-validation failures are treated as model-local failures so later combo targets can still run.
+
+## OAuth Onboarding and Token Refresh Lifecycle
+
+```mermaid
+sequenceDiagram
+ autonumber
+ participant UI as Dashboard UI
+ participant OAuth as /api/oauth/[provider]/[action]
+ participant ProvAuth as Provider Auth Server
+ participant DB as localDb
+ participant Test as /api/providers/[id]/test
+ participant Exec as Provider Executor
+
+ UI->>OAuth: GET authorize or device-code
+ OAuth->>ProvAuth: create auth/device flow
+ ProvAuth-->>OAuth: auth URL or device code payload
+ OAuth-->>UI: flow data
+
+ UI->>OAuth: POST exchange or poll
+ OAuth->>ProvAuth: token exchange/poll
+ ProvAuth-->>OAuth: access/refresh tokens
+ OAuth->>DB: createProviderConnection(oauth data)
+ OAuth-->>UI: success + connection id
+
+ UI->>Test: POST /api/providers/[id]/test
+ Test->>Exec: validate credentials / optional refresh
+ Exec-->>Test: valid or refreshed token info
+ Test->>DB: update status/tokens/errors
+ Test-->>UI: validation result
+```
+
+Refresh during live traffic is executed inside `open-sse/handlers/chatCore.ts` via executor `refreshCredentials()`.
+
+## Cloud Sync Lifecycle (Enable / Sync / Disable)
+
+```mermaid
+sequenceDiagram
+ autonumber
+ participant UI as Endpoint Page UI
+ participant Sync as /api/sync/cloud
+ participant DB as localDb
+ participant Cloud as External Cloud Sync
+ participant Claude as ~/.claude/settings.json
+
+ UI->>Sync: POST action=enable
+ Sync->>DB: set cloudEnabled=true
+ Sync->>DB: ensure API key exists
+ Sync->>Cloud: POST /sync/{machineId} (providers/aliases/combos/keys)
+ Cloud-->>Sync: sync result
+ Sync->>Cloud: GET /{machineId}/v1/verify
+ Sync-->>UI: enabled + verification status
+
+ UI->>Sync: POST action=sync
+ Sync->>Cloud: POST /sync/{machineId}
+ Cloud-->>Sync: remote data
+ Sync->>DB: update newer local tokens/status
+ Sync-->>UI: synced
+
+ UI->>Sync: POST action=disable
+ Sync->>DB: set cloudEnabled=false
+ Sync->>Cloud: DELETE /sync/{machineId}
+ Sync->>Claude: switch ANTHROPIC_BASE_URL back to local (if needed)
+ Sync-->>UI: disabled
+```
+
+Periodic sync is triggered by `CloudSyncScheduler` when cloud is enabled.
+
+## Data Model and Storage Map
+
+```mermaid
+erDiagram
+ SETTINGS ||--o{ PROVIDER_CONNECTION : controls
+ PROVIDER_NODE ||--o{ PROVIDER_CONNECTION : backs_compatible_provider
+ PROVIDER_CONNECTION ||--o{ USAGE_ENTRY : emits_usage
+
+ SETTINGS {
+ boolean cloudEnabled
+ number stickyRoundRobinLimit
+ boolean requireLogin
+ string password_hash
+ string fallbackStrategy
+ json rateLimitDefaults
+ json providerProfiles
+ }
+
+ PROVIDER_CONNECTION {
+ string id
+ string provider
+ string authType
+ string name
+ number priority
+ boolean isActive
+ string apiKey
+ string accessToken
+ string refreshToken
+ string expiresAt
+ string testStatus
+ string lastError
+ string rateLimitedUntil
+ json providerSpecificData
+ }
+
+ PROVIDER_NODE {
+ string id
+ string type
+ string name
+ string prefix
+ string apiType
+ string baseUrl
+ }
+
+ MODEL_ALIAS {
+ string alias
+ string targetModel
+ }
+
+ COMBO {
+ string id
+ string name
+ string[] models
+ }
+
+ API_KEY {
+ string id
+ string name
+ string key
+ string machineId
+ }
+
+ USAGE_ENTRY {
+ string provider
+ string model
+ number prompt_tokens
+ number completion_tokens
+ string connectionId
+ string timestamp
+ }
+
+ CUSTOM_MODEL {
+ string id
+ string name
+ string providerId
+ }
+
+ PROXY_CONFIG {
+ string global
+ json providers
+ }
+
+ IP_FILTER {
+ string mode
+ string[] allowlist
+ string[] blocklist
+ }
+
+ THINKING_BUDGET {
+ string mode
+ number customBudget
+ string effortLevel
+ }
+
+ SYSTEM_PROMPT {
+ boolean enabled
+ string prompt
+ string position
+ }
+```
+
+Physical storage files:
+
+- primary runtime DB: `${DATA_DIR}/storage.sqlite`
+- request log lines: `${DATA_DIR}/log.txt` (compat/debug artifact)
+- structured call payload archives: `${DATA_DIR}/call_logs/`
+- optional translator/request debug sessions: `/logs/...`
+
+## Deployment Topology
+
+```mermaid
+flowchart LR
+ subgraph LocalHost[Developer Host]
+ CLI[CLI Tools]
+ Browser[Dashboard Browser]
+ end
+
+ subgraph ContainerOrProcess[OmniRoute Runtime]
+ Next[Next.js Server\nPORT=20128]
+ Core[SSE Core + Executors]
+ MainDB[(storage.sqlite)]
+ UsageDB[(usage tables + log artifacts)]
+ end
+
+ subgraph External[External Services]
+ Providers[AI Providers]
+ SyncCloud[Cloud Sync Service]
+ end
+
+ CLI --> Next
+ Browser --> Next
+ Next --> Core
+ Next --> MainDB
+ Core --> MainDB
+ Core --> UsageDB
+ Core --> Providers
+ Next --> SyncCloud
+```
+
+## Module Mapping (Decision-Critical)
+
+### Route and API Modules
+
+- `src/app/api/v1/*`, `src/app/api/v1beta/*`: compatibility APIs
+- `src/app/api/v1/providers/[provider]/*`: dedicated per-provider routes (chat, embeddings, images)
+- `src/app/api/providers*`: provider CRUD, validation, testing
+- `src/app/api/provider-nodes*`: custom compatible node management
+- `src/app/api/provider-models`: custom model management (CRUD)
+- `src/app/api/models/route.ts`: model catalog API (aliases + custom models)
+- `src/app/api/oauth/*`: OAuth/device-code flows
+- `src/app/api/keys*`: local API key lifecycle
+- `src/app/api/models/alias`: alias management
+- `src/app/api/combos*`: fallback combo management
+- `src/app/api/pricing`: pricing overrides for cost calculation
+- `src/app/api/settings/proxy`: proxy configuration (GET/PUT/DELETE)
+- `src/app/api/settings/proxy/test`: outbound proxy connectivity test (POST)
+- `src/app/api/usage/*`: usage and logs APIs
+- `src/app/api/sync/*` + `src/app/api/cloud/*`: cloud sync and cloud-facing helpers
+- `src/app/api/cli-tools/*`: local CLI config writers/checkers
+- `src/app/api/settings/ip-filter`: IP allowlist/blocklist (GET/PUT)
+- `src/app/api/settings/thinking-budget`: thinking token budget config (GET/PUT)
+- `src/app/api/settings/system-prompt`: global system prompt (GET/PUT)
+- `src/app/api/sessions`: active session listing (GET)
+- `src/app/api/rate-limits`: per-account rate limit status (GET)
+
+### Routing and Execution Core
+
+- `src/sse/handlers/chat.ts`: request parse, combo handling, account selection loop
+- `open-sse/handlers/chatCore.ts`: translation, executor dispatch, retry/refresh handling, stream setup
+- `open-sse/executors/*`: provider-specific network and format behavior
+
+### Translation Registry and Format Converters
+
+- `open-sse/translator/index.ts`: translator registry and orchestration
+- Request translators: `open-sse/translator/request/*`
+- Response translators: `open-sse/translator/response/*`
+- Format constants: `open-sse/translator/formats.ts`
+
+### Persistence
+
+- `src/lib/db/*`: persistent config/state and domain persistence on SQLite
+- `src/lib/localDb.ts`: compatibility re-export for DB modules
+- `src/lib/usageDb.ts`: usage history/call logs facade on top of SQLite tables
+
+## Provider Executor Coverage (Strategy Pattern)
+
+Each provider has a specialized executor extending `BaseExecutor` (in `open-sse/executors/base.ts`), which provides URL building, header construction, retry with exponential backoff, credential refresh hooks, and the `execute()` orchestration method.
+
+| Executor | Provider(s) | Special Handling |
+| --------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------ | -------------------------------------------------------------------- |
+| `DefaultExecutor` | OpenAI, Claude, Gemini, Qwen, Qoder, OpenRouter, GLM, Kimi, MiniMax, DeepSeek, Groq, xAI, Mistral, Perplexity, Together, Fireworks, Cerebras, Cohere, NVIDIA | Dynamic URL/header config per provider |
+| `AntigravityExecutor` | Google Antigravity | Custom project/session IDs, Retry-After parsing |
+| `CodexExecutor` | OpenAI Codex | Injects system instructions, forces reasoning effort |
+| `CursorExecutor` | Cursor IDE | ConnectRPC protocol, Protobuf encoding, request signing via checksum |
+| `GithubExecutor` | GitHub Copilot | Copilot token refresh, VSCode-mimicking headers |
+| `KiroExecutor` | AWS CodeWhisperer/Kiro | AWS EventStream binary format → SSE conversion |
+| `GeminiCLIExecutor` | Gemini CLI | Google OAuth token refresh cycle |
+
+All other providers (including custom compatible nodes) use the `DefaultExecutor`.
+
+## Provider Compatibility Matrix
+
+| Provider | Format | Auth | Stream | Non-Stream | Token Refresh | Usage API |
+| ---------------- | ---------------- | --------------------- | ---------------- | ---------- | ------------- | ------------------ |
+| Claude | claude | API Key / OAuth | ✅ | ✅ | ✅ | ⚠️ Admin only |
+| Gemini | gemini | API Key / OAuth | ✅ | ✅ | ✅ | ⚠️ Cloud Console |
+| Gemini CLI | gemini-cli | OAuth | ✅ | ✅ | ✅ | ⚠️ Cloud Console |
+| Antigravity | antigravity | OAuth | ✅ | ✅ | ✅ | ✅ Full quota API |
+| OpenAI | openai | API Key | ✅ | ✅ | ❌ | ❌ |
+| Codex | openai-responses | OAuth | ✅ forced | ❌ | ✅ | ✅ Rate limits |
+| GitHub Copilot | openai | OAuth + Copilot Token | ✅ | ✅ | ✅ | ✅ Quota snapshots |
+| Cursor | cursor | Custom checksum | ✅ | ✅ | ❌ | ❌ |
+| Kiro | kiro | AWS SSO OIDC | ✅ (EventStream) | ❌ | ✅ | ✅ Usage limits |
+| Qwen | openai | OAuth | ✅ | ✅ | ✅ | ⚠️ Per request |
+| Qoder | openai | OAuth (Basic) | ✅ | ✅ | ✅ | ⚠️ Per request |
+| OpenRouter | openai | API Key | ✅ | ✅ | ❌ | ❌ |
+| GLM/Kimi/MiniMax | claude | API Key | ✅ | ✅ | ❌ | ❌ |
+| DeepSeek | openai | API Key | ✅ | ✅ | ❌ | ❌ |
+| Groq | openai | API Key | ✅ | ✅ | ❌ | ❌ |
+| xAI (Grok) | openai | API Key | ✅ | ✅ | ❌ | ❌ |
+| Mistral | openai | API Key | ✅ | ✅ | ❌ | ❌ |
+| Perplexity | openai | API Key | ✅ | ✅ | ❌ | ❌ |
+| Together AI | openai | API Key | ✅ | ✅ | ❌ | ❌ |
+| Fireworks AI | openai | API Key | ✅ | ✅ | ❌ | ❌ |
+| Cerebras | openai | API Key | ✅ | ✅ | ❌ | ❌ |
+| Cohere | openai | API Key | ✅ | ✅ | ❌ | ❌ |
+| NVIDIA NIM | openai | API Key | ✅ | ✅ | ❌ | ❌ |
+
+## Format Translation Coverage
+
+Detected source formats include:
+
+- `openai`
+- `openai-responses`
+- `claude`
+- `gemini`
+
+Target formats include:
+
+- OpenAI chat/Responses
+- Claude
+- Gemini/Gemini-CLI/Antigravity envelope
+- Kiro
+- Cursor
+
+Translations use **OpenAI as the hub format** — all conversions go through OpenAI as intermediate:
+
+```
+Source Format → OpenAI (hub) → Target Format
+```
+
+Translations are selected dynamically based on source payload shape and provider target format.
+
+Additional processing layers in the translation pipeline:
+
+- **Response sanitization** — Strips non-standard fields from OpenAI-format responses (both streaming and non-streaming) to ensure strict SDK compliance
+- **Role normalization** — Converts `developer` → `system` for non-OpenAI targets; merges `system` → `user` for models that reject the system role (GLM, ERNIE)
+- **Think tag extraction** — Parses `...` blocks from content into `reasoning_content` field
+- **Structured output** — Converts OpenAI `response_format.json_schema` to Gemini's `responseMimeType` + `responseSchema`
+
+## Supported API Endpoints
+
+| Endpoint | Format | Handler |
+| -------------------------------------------------- | ------------------ | ------------------------------------------------------------------- |
+| `POST /v1/chat/completions` | OpenAI Chat | `src/sse/handlers/chat.ts` |
+| `POST /v1/messages` | Claude Messages | Same handler (auto-detected) |
+| `POST /v1/responses` | OpenAI Responses | `open-sse/handlers/responsesHandler.ts` |
+| `POST /v1/embeddings` | OpenAI Embeddings | `open-sse/handlers/embeddings.ts` |
+| `GET /v1/embeddings` | Model listing | API route |
+| `POST /v1/images/generations` | OpenAI Images | `open-sse/handlers/imageGeneration.ts` |
+| `GET /v1/images/generations` | Model listing | API route |
+| `POST /v1/providers/{provider}/chat/completions` | OpenAI Chat | Dedicated per-provider with model validation |
+| `POST /v1/providers/{provider}/embeddings` | OpenAI Embeddings | Dedicated per-provider with model validation |
+| `POST /v1/providers/{provider}/images/generations` | OpenAI Images | Dedicated per-provider with model validation |
+| `POST /v1/messages/count_tokens` | Claude Token Count | API route |
+| `GET /v1/models` | OpenAI Models list | API route (chat + embedding + image + custom models) |
+| `GET /api/models/catalog` | Catalog | All models grouped by provider + type |
+| `POST /v1beta/models/*:streamGenerateContent` | Gemini native | API route |
+| `GET/PUT/DELETE /api/settings/proxy` | Proxy Config | Network proxy configuration |
+| `POST /api/settings/proxy/test` | Proxy Connectivity | Proxy health/connectivity test endpoint |
+| `GET/POST/DELETE /api/provider-models` | Provider Models | Provider model metadata backing custom and managed available models |
+
+## Bypass Handler
+
+The bypass handler (`open-sse/utils/bypassHandler.ts`) intercepts known "throwaway" requests from Claude CLI — warmup pings, title extractions, and token counts — and returns a **fake response** without consuming upstream provider tokens. This is triggered only when `User-Agent` contains `claude-cli`.
+
+## Request Logger Pipeline
+
+The request logger (`open-sse/utils/requestLogger.ts`) provides a 7-stage debug logging pipeline, disabled by default, enabled via `ENABLE_REQUEST_LOGS=true`:
+
+```
+1_req_client.json → 2_req_source.json → 3_req_openai.json → 4_req_target.json
+→ 5_res_provider.txt → 6_res_openai.txt → 7_res_client.txt
+```
+
+Files are written to `/logs//` for each request session.
+
+## Failure Modes and Resilience
+
+## 1) Account/Provider Availability
+
+- provider account cooldown on transient/rate/auth errors
+- account fallback before failing request
+- combo model fallback when current model/provider path is exhausted
+
+## 2) Token Expiry
+
+- pre-check and refresh with retry for refreshable providers
+- 401/403 retry after refresh attempt in core path
+
+## 3) Stream Safety
+
+- disconnect-aware stream controller
+- translation stream with end-of-stream flush and `[DONE]` handling
+- usage estimation fallback when provider usage metadata is missing
+
+## 4) Cloud Sync Degradation
+
+- sync errors are surfaced but local runtime continues
+- scheduler has retry-capable logic, but periodic execution currently calls single-attempt sync by default
+
+## 5) Data Integrity
+
+- SQLite schema migrations and auto-upgrade hooks at startup
+- legacy JSON → SQLite migration compatibility path
+
+## Observability and Operational Signals
+
+Runtime visibility sources:
+
+- console logs from `src/sse/utils/logger.ts`
+- per-request usage aggregates in SQLite (`usage_history`, `call_logs`, `proxy_logs`)
+- four-stage detailed payload captures in SQLite (`request_detail_logs`) when `settings.detailed_logs_enabled=true`
+- textual request status log in `log.txt` (optional/compat)
+- optional deep request/translation logs under `logs/` when `ENABLE_REQUEST_LOGS=true`
+- dashboard usage endpoints (`/api/usage/*`) for UI consumption
+
+Detailed request payload capture stores up to four JSON payload stages per routed call:
+
+- raw request received from the client
+- translated request actually sent upstream
+- provider response reconstructed as JSON; streamed responses are compacted to the final summary plus stream metadata
+- final client response returned by OmniRoute; streamed responses are stored in the same compact summary form
+
+## Security-Sensitive Boundaries
+
+- JWT secret (`JWT_SECRET`) secures dashboard session cookie verification/signing
+- Initial password bootstrap (`INITIAL_PASSWORD`) should be explicitly configured for first-run provisioning
+- API key HMAC secret (`API_KEY_SECRET`) secures generated local API key format
+- Provider secrets (API keys/tokens) are persisted in local DB and should be protected at filesystem level
+- Cloud sync endpoints rely on API key auth + machine id semantics
+
+## Environment and Runtime Matrix
+
+Environment variables actively used by code:
+
+- App/auth: `JWT_SECRET`, `INITIAL_PASSWORD`
+- Storage: `DATA_DIR`
+- Compatible node behavior: `ALLOW_MULTI_CONNECTIONS_PER_COMPAT_NODE`
+- Optional storage base override (Linux/macOS when `DATA_DIR` unset): `XDG_CONFIG_HOME`
+- Security hashing: `API_KEY_SECRET`, `MACHINE_ID_SALT`
+- Logging: `ENABLE_REQUEST_LOGS`
+- Sync/cloud URLing: `NEXT_PUBLIC_BASE_URL`, `NEXT_PUBLIC_CLOUD_URL`
+- Outbound proxy: `HTTP_PROXY`, `HTTPS_PROXY`, `ALL_PROXY`, `NO_PROXY` and lowercase variants
+- SOCKS5 feature flags: `ENABLE_SOCKS5_PROXY`, `NEXT_PUBLIC_ENABLE_SOCKS5_PROXY`
+- Platform/runtime helpers (not app-specific config): `APPDATA`, `NODE_ENV`, `PORT`, `HOSTNAME`
+
+## Known Architectural Notes
+
+1. `usageDb` and `localDb` share the same base directory policy (`DATA_DIR` -> `XDG_CONFIG_HOME/omniroute` -> `~/.omniroute`) with legacy file migration.
+2. `/api/v1/route.ts` delegates to the same unified catalog builder used by `/api/v1/models` (`src/app/api/v1/models/catalog.ts`) to avoid semantic drift.
+3. Request logger writes full headers/body when enabled; treat log directory as sensitive.
+4. Cloud behavior depends on correct `NEXT_PUBLIC_BASE_URL` and cloud endpoint reachability.
+5. The `open-sse/` directory is published as the `@omniroute/open-sse` **npm workspace package**. Source code imports it via `@omniroute/open-sse/...` (resolved by Next.js `transpilePackages`). File paths in this document still use the directory name `open-sse/` for consistency.
+6. Charts in the dashboard use **Recharts** (SVG-based) for accessible, interactive analytics visualizations (model usage bar charts, provider breakdown tables with success rates).
+7. E2E tests use **Playwright** (`tests/e2e/`), run via `npm run test:e2e`. Unit tests use **Node.js test runner** (`tests/unit/`), run via `npm run test:unit`. Source code under `src/` is **TypeScript** (`.ts`/`.tsx`); the `open-sse/` workspace remains JavaScript (`.js`).
+8. Settings page is organized into 5 tabs: Security, Routing (6 global strategies: fill-first, round-robin, p2c, random, least-used, cost-optimized), Resilience (editable rate limits, circuit breaker, policies), AI (thinking budget, system prompt, prompt cache), Advanced (proxy).
+
+## Operational Verification Checklist
+
+- Build from source: `npm run build`
+- Build Docker image: `docker build -t omniroute .`
+- Start service and verify:
+- `GET /api/settings`
+- `GET /api/v1/models`
+- CLI target base URL should be `http://:20128/v1` when `PORT=20128`
diff --git a/docs/i18n/es/docs/AUTO-COMBO.md b/docs/i18n/es/docs/AUTO-COMBO.md
new file mode 100644
index 0000000000..24ba8b36ad
--- /dev/null
+++ b/docs/i18n/es/docs/AUTO-COMBO.md
@@ -0,0 +1,67 @@
+# OmniRoute Auto-Combo Engine (Español)
+
+🌐 **Languages:** 🇺🇸 [English](../../../../docs/AUTO-COMBO.md) · 🇪🇸 [es](../../es/docs/AUTO-COMBO.md) · 🇫🇷 [fr](../../fr/docs/AUTO-COMBO.md) · 🇩🇪 [de](../../de/docs/AUTO-COMBO.md) · 🇮🇹 [it](../../it/docs/AUTO-COMBO.md) · 🇷🇺 [ru](../../ru/docs/AUTO-COMBO.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/AUTO-COMBO.md) · 🇯🇵 [ja](../../ja/docs/AUTO-COMBO.md) · 🇰🇷 [ko](../../ko/docs/AUTO-COMBO.md) · 🇸🇦 [ar](../../ar/docs/AUTO-COMBO.md) · 🇮🇳 [in](../../in/docs/AUTO-COMBO.md) · 🇹🇭 [th](../../th/docs/AUTO-COMBO.md) · 🇻🇳 [vi](../../vi/docs/AUTO-COMBO.md) · 🇮🇩 [id](../../id/docs/AUTO-COMBO.md) · 🇲🇾 [ms](../../ms/docs/AUTO-COMBO.md) · 🇳🇱 [nl](../../nl/docs/AUTO-COMBO.md) · 🇵🇱 [pl](../../pl/docs/AUTO-COMBO.md) · 🇸🇪 [sv](../../sv/docs/AUTO-COMBO.md) · 🇳🇴 [no](../../no/docs/AUTO-COMBO.md) · 🇩🇰 [da](../../da/docs/AUTO-COMBO.md) · 🇫🇮 [fi](../../fi/docs/AUTO-COMBO.md) · 🇵🇹 [pt](../../pt/docs/AUTO-COMBO.md) · 🇷🇴 [ro](../../ro/docs/AUTO-COMBO.md) · 🇭🇺 [hu](../../hu/docs/AUTO-COMBO.md) · 🇧🇬 [bg](../../bg/docs/AUTO-COMBO.md) · 🇸🇰 [sk](../../sk/docs/AUTO-COMBO.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/AUTO-COMBO.md) · 🇮🇱 [he](../../he/docs/AUTO-COMBO.md) · 🇵🇭 [phi](../../phi/docs/AUTO-COMBO.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/AUTO-COMBO.md) · 🇨🇿 [cs](../../cs/docs/AUTO-COMBO.md)
+
+---
+
+> Self-managing model chains with adaptive scoring
+
+## How It Works
+
+The Auto-Combo Engine dynamically selects the best provider/model for each request using a **6-factor scoring function**:
+
+| Factor | Weight | Description |
+| :--------- | :----- | :---------------------------------------------- |
+| Quota | 0.20 | Remaining capacity [0..1] |
+| Health | 0.25 | Circuit breaker: CLOSED=1.0, HALF=0.5, OPEN=0.0 |
+| CostInv | 0.20 | Inverse cost (cheaper = higher score) |
+| LatencyInv | 0.15 | Inverse p95 latency (faster = higher) |
+| TaskFit | 0.10 | Model × task type fitness score |
+| Stability | 0.10 | Low variance in latency/errors |
+
+## Mode Packs
+
+| Pack | Focus | Key Weight |
+| :---------------------- | :----------- | :--------------- |
+| 🚀 **Ship Fast** | Speed | latencyInv: 0.35 |
+| 💰 **Cost Saver** | Economy | costInv: 0.40 |
+| 🎯 **Quality First** | Best model | taskFit: 0.40 |
+| 📡 **Offline Friendly** | Availability | quota: 0.40 |
+
+## Self-Healing
+
+- **Temporary exclusion**: Score < 0.2 → excluded for 5 min (progressive backoff, max 30 min)
+- **Circuit breaker awareness**: OPEN → auto-excluded; HALF_OPEN → probe requests
+- **Incident mode**: >50% OPEN → disable exploration, maximize stability
+- **Cooldown recovery**: After exclusion, first request is a "probe" with reduced timeout
+
+## Bandit Exploration
+
+5% of requests (configurable) are routed to random providers for exploration. Disabled in incident mode.
+
+## API
+
+```bash
+# Create auto-combo
+curl -X POST http://localhost:20128/api/combos/auto \
+ -H "Content-Type: application/json" \
+ -d '{"id":"my-auto","name":"Auto Coder","candidatePool":["anthropic","google","openai"],"modePack":"ship-fast"}'
+
+# List auto-combos
+curl http://localhost:20128/api/combos/auto
+```
+
+## Task Fitness
+
+30+ models scored across 6 task types (`coding`, `review`, `planning`, `analysis`, `debugging`, `documentation`). Supports wildcard patterns (e.g., `*-coder` → high coding score).
+
+## Files
+
+| File | Purpose |
+| :------------------------------------------- | :------------------------------------ |
+| `open-sse/services/autoCombo/scoring.ts` | Scoring function & pool normalization |
+| `open-sse/services/autoCombo/taskFitness.ts` | Model × task fitness lookup |
+| `open-sse/services/autoCombo/engine.ts` | Selection logic, bandit, budget cap |
+| `open-sse/services/autoCombo/selfHealing.ts` | Exclusion, probes, incident mode |
+| `open-sse/services/autoCombo/modePacks.ts` | 4 weight profiles |
+| `src/app/api/combos/auto/route.ts` | REST API |
diff --git a/docs/i18n/es/docs/CLI-TOOLS.md b/docs/i18n/es/docs/CLI-TOOLS.md
new file mode 100644
index 0000000000..885a3a6614
--- /dev/null
+++ b/docs/i18n/es/docs/CLI-TOOLS.md
@@ -0,0 +1,348 @@
+# CLI Tools Setup Guide — OmniRoute (Español)
+
+🌐 **Languages:** 🇺🇸 [English](../../../../docs/CLI-TOOLS.md) · 🇪🇸 [es](../../es/docs/CLI-TOOLS.md) · 🇫🇷 [fr](../../fr/docs/CLI-TOOLS.md) · 🇩🇪 [de](../../de/docs/CLI-TOOLS.md) · 🇮🇹 [it](../../it/docs/CLI-TOOLS.md) · 🇷🇺 [ru](../../ru/docs/CLI-TOOLS.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/CLI-TOOLS.md) · 🇯🇵 [ja](../../ja/docs/CLI-TOOLS.md) · 🇰🇷 [ko](../../ko/docs/CLI-TOOLS.md) · 🇸🇦 [ar](../../ar/docs/CLI-TOOLS.md) · 🇮🇳 [in](../../in/docs/CLI-TOOLS.md) · 🇹🇭 [th](../../th/docs/CLI-TOOLS.md) · 🇻🇳 [vi](../../vi/docs/CLI-TOOLS.md) · 🇮🇩 [id](../../id/docs/CLI-TOOLS.md) · 🇲🇾 [ms](../../ms/docs/CLI-TOOLS.md) · 🇳🇱 [nl](../../nl/docs/CLI-TOOLS.md) · 🇵🇱 [pl](../../pl/docs/CLI-TOOLS.md) · 🇸🇪 [sv](../../sv/docs/CLI-TOOLS.md) · 🇳🇴 [no](../../no/docs/CLI-TOOLS.md) · 🇩🇰 [da](../../da/docs/CLI-TOOLS.md) · 🇫🇮 [fi](../../fi/docs/CLI-TOOLS.md) · 🇵🇹 [pt](../../pt/docs/CLI-TOOLS.md) · 🇷🇴 [ro](../../ro/docs/CLI-TOOLS.md) · 🇭🇺 [hu](../../hu/docs/CLI-TOOLS.md) · 🇧🇬 [bg](../../bg/docs/CLI-TOOLS.md) · 🇸🇰 [sk](../../sk/docs/CLI-TOOLS.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/CLI-TOOLS.md) · 🇮🇱 [he](../../he/docs/CLI-TOOLS.md) · 🇵🇭 [phi](../../phi/docs/CLI-TOOLS.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/CLI-TOOLS.md) · 🇨🇿 [cs](../../cs/docs/CLI-TOOLS.md)
+
+---
+
+This guide explains how to install and configure all supported AI coding CLI tools
+to use **OmniRoute** as the unified backend, giving you centralized key management,
+cost tracking, model switching, and request logging across every tool.
+
+---
+
+## How It Works
+
+```
+Claude / Codex / OpenCode / Cline / KiloCode / Continue / Kiro / Cursor / Copilot
+ │
+ ▼ (all point to OmniRoute)
+ http://YOUR_SERVER:20128/v1
+ │
+ ▼ (OmniRoute routes to the right provider)
+ Anthropic / OpenAI / Gemini / DeepSeek / Groq / Mistral / ...
+```
+
+**Benefits:**
+
+- One API key to manage all tools
+- Cost tracking across all CLIs in the dashboard
+- Model switching without reconfiguring every tool
+- Works locally and on remote servers (VPS)
+
+---
+
+## Supported Tools (Dashboard Source of Truth)
+
+The dashboard cards in `/dashboard/cli-tools` are generated from `src/shared/constants/cliTools.ts`.
+Current list (v3.0.0-rc.16):
+
+| Tool | ID | Command | Setup Mode | Install Method |
+| ------------------ | ------------- | ---------- | ---------- | -------------- |
+| **Claude Code** | `claude` | `claude` | env | npm |
+| **OpenAI Codex** | `codex` | `codex` | custom | npm |
+| **Factory Droid** | `droid` | `droid` | custom | bundled/CLI |
+| **OpenClaw** | `openclaw` | `openclaw` | custom | bundled/CLI |
+| **Cursor** | `cursor` | app | guide | desktop app |
+| **Cline** | `cline` | `cline` | custom | npm |
+| **Kilo Code** | `kilo` | `kilocode` | custom | npm |
+| **Continue** | `continue` | extension | guide | VS Code |
+| **Antigravity** | `antigravity` | internal | mitm | OmniRoute |
+| **GitHub Copilot** | `copilot` | extension | custom | VS Code |
+| **OpenCode** | `opencode` | `opencode` | guide | npm |
+| **Kiro AI** | `kiro` | app/cli | mitm | desktop/CLI |
+
+### CLI fingerprint sync (Agents + Settings)
+
+`/dashboard/agents` and `Settings > CLI Fingerprint` use `src/shared/constants/cliCompatProviders.ts`.
+This keeps provider IDs aligned with CLI cards and legacy IDs.
+
+| CLI ID | Fingerprint Provider ID |
+| ---------------------------------------------------------------------------------------------------- | ----------------------- |
+| `kilo` | `kilocode` |
+| `copilot` | `github` |
+| `claude` / `codex` / `antigravity` / `kiro` / `cursor` / `cline` / `opencode` / `droid` / `openclaw` | same ID |
+
+Legacy IDs still accepted for compatibility: `copilot`, `kimi-coding`, `qwen`.
+
+---
+
+## Step 1 — Get an OmniRoute API Key
+
+1. Open the OmniRoute dashboard → **API Manager** (`/dashboard/api-manager`)
+2. Click **Create API Key**
+3. Give it a name (e.g. `cli-tools`) and select all permissions
+4. Copy the key — you'll need it for every CLI below
+
+> Your key looks like: `sk-xxxxxxxxxxxxxxxx-xxxxxxxxx`
+
+---
+
+## Step 2 — Install CLI Tools
+
+All npm-based tools require Node.js 18+:
+
+```bash
+# Claude Code (Anthropic)
+npm install -g @anthropic-ai/claude-code
+
+# OpenAI Codex
+npm install -g @openai/codex
+
+# OpenCode
+npm install -g opencode-ai
+
+# Cline
+npm install -g cline
+
+# KiloCode
+npm install -g kilocode
+
+# Kiro CLI (Amazon — requires curl + unzip)
+apt-get install -y unzip # on Debian/Ubuntu
+curl -fsSL https://cli.kiro.dev/install | bash
+export PATH="$HOME/.local/bin:$PATH" # add to ~/.bashrc
+```
+
+**Verify:**
+
+```bash
+claude --version # 2.x.x
+codex --version # 0.x.x
+opencode --version # x.x.x
+cline --version # 2.x.x
+kilocode --version # x.x.x (or: kilo --version)
+kiro-cli --version # 1.x.x
+```
+
+---
+
+## Step 3 — Set Global Environment Variables
+
+Add to `~/.bashrc` (or `~/.zshrc`), then run `source ~/.bashrc`:
+
+```bash
+# OmniRoute Universal Endpoint
+export OPENAI_BASE_URL="http://localhost:20128/v1"
+export OPENAI_API_KEY="sk-your-omniroute-key"
+export ANTHROPIC_BASE_URL="http://localhost:20128/v1"
+export ANTHROPIC_API_KEY="sk-your-omniroute-key"
+export GEMINI_BASE_URL="http://localhost:20128/v1"
+export GEMINI_API_KEY="sk-your-omniroute-key"
+```
+
+> For a **remote server** replace `localhost:20128` with the server IP or domain,
+> e.g. `http://192.168.0.15:20128`.
+
+---
+
+## Step 4 — Configure Each Tool
+
+### Claude Code
+
+```bash
+# Via CLI:
+claude config set --global api-base-url http://localhost:20128/v1
+
+# Or create ~/.claude/settings.json:
+mkdir -p ~/.claude && cat > ~/.claude/settings.json << EOF
+{
+ "apiBaseUrl": "http://localhost:20128/v1",
+ "apiKey": "sk-your-omniroute-key"
+}
+EOF
+```
+
+**Test:** `claude "say hello"`
+
+---
+
+### OpenAI Codex
+
+```bash
+mkdir -p ~/.codex && cat > ~/.codex/config.yaml << EOF
+model: auto
+apiKey: sk-your-omniroute-key
+apiBaseUrl: http://localhost:20128/v1
+EOF
+```
+
+**Test:** `codex "what is 2+2?"`
+
+---
+
+### OpenCode
+
+```bash
+mkdir -p ~/.config/opencode && cat > ~/.config/opencode/config.toml << EOF
+[provider.openai]
+base_url = "http://localhost:20128/v1"
+api_key = "sk-your-omniroute-key"
+EOF
+```
+
+**Test:** `opencode`
+
+---
+
+### Cline (CLI or VS Code)
+
+**CLI mode:**
+
+```bash
+mkdir -p ~/.cline/data && cat > ~/.cline/data/globalState.json << EOF
+{
+ "apiProvider": "openai",
+ "openAiBaseUrl": "http://localhost:20128/v1",
+ "openAiApiKey": "sk-your-omniroute-key"
+}
+EOF
+```
+
+**VS Code mode:**
+Cline extension settings → API Provider: `OpenAI Compatible` → Base URL: `http://localhost:20128/v1`
+
+Or use the OmniRoute dashboard → **CLI Tools → Cline → Apply Config**.
+
+---
+
+### KiloCode (CLI or VS Code)
+
+**CLI mode:**
+
+```bash
+kilocode --api-base http://localhost:20128/v1 --api-key sk-your-omniroute-key
+```
+
+**VS Code settings:**
+
+```json
+{
+ "kilo-code.openAiBaseUrl": "http://localhost:20128/v1",
+ "kilo-code.apiKey": "sk-your-omniroute-key"
+}
+```
+
+Or use the OmniRoute dashboard → **CLI Tools → KiloCode → Apply Config**.
+
+---
+
+### Continue (VS Code Extension)
+
+Edit `~/.continue/config.yaml`:
+
+```yaml
+models:
+ - name: OmniRoute
+ provider: openai
+ model: auto
+ apiBase: http://localhost:20128/v1
+ apiKey: sk-your-omniroute-key
+ default: true
+```
+
+Restart VS Code after editing.
+
+---
+
+### Kiro CLI (Amazon)
+
+```bash
+# Login to your AWS/Kiro account:
+kiro-cli login
+
+# The CLI uses its own auth — OmniRoute is not needed as backend for Kiro CLI itself.
+# Use kiro-cli alongside OmniRoute for other tools.
+kiro-cli status
+```
+
+---
+
+### Cursor (Desktop App)
+
+> **Note:** Cursor routes requests through its cloud. For OmniRoute integration,
+> enable **Cloud Endpoint** in OmniRoute Settings and use your public domain URL.
+
+Via GUI: **Settings → Models → OpenAI API Key**
+
+- Base URL: `https://your-domain.com/v1`
+- API Key: your OmniRoute key
+
+---
+
+## Dashboard Auto-Configuration
+
+The OmniRoute dashboard automates configuration for most tools:
+
+1. Go to `http://localhost:20128/dashboard/cli-tools`
+2. Expand any tool card
+3. Select your API key from the dropdown
+4. Click **Apply Config** (if tool is detected as installed)
+5. Or copy the generated config snippet manually
+
+---
+
+## Built-in Agents: Droid & OpenClaw
+
+**Droid** and **OpenClaw** are AI agents built directly into OmniRoute — no installation needed.
+They run as internal routes and use OmniRoute's model routing automatically.
+
+- Access: `http://localhost:20128/dashboard/agents`
+- Configure: same combos and providers as all other tools
+- No API key or CLI install required
+
+---
+
+## Available API Endpoints
+
+| Endpoint | Description | Use For |
+| -------------------------- | ----------------------------- | --------------------------- |
+| `/v1/chat/completions` | Standard chat (all providers) | All modern tools |
+| `/v1/responses` | Responses API (OpenAI format) | Codex, agentic workflows |
+| `/v1/completions` | Legacy text completions | Older tools using `prompt:` |
+| `/v1/embeddings` | Text embeddings | RAG, search |
+| `/v1/images/generations` | Image generation | DALL-E, Flux, etc. |
+| `/v1/audio/speech` | Text-to-speech | ElevenLabs, OpenAI TTS |
+| `/v1/audio/transcriptions` | Speech-to-text | Deepgram, AssemblyAI |
+
+---
+
+## Solución de Problemas
+
+| Error | Cause | Fix |
+| ------------------------- | ----------------------- | ------------------------------------------ |
+| `Connection refused` | OmniRoute not running | `pm2 start omniroute` |
+| `401 Unauthorized` | Wrong API key | Check in `/dashboard/api-manager` |
+| `No combo configured` | No active routing combo | Set up in `/dashboard/combos` |
+| `invalid model` | Model not in catalog | Use `auto` or check `/dashboard/providers` |
+| CLI shows "not installed" | Binary not in PATH | Check `which ` |
+| `kiro-cli: not found` | Not in PATH | `export PATH="$HOME/.local/bin:$PATH"` |
+
+---
+
+## Quick Setup Script (One Command)
+
+```bash
+# Install all CLIs and configure for OmniRoute (replace with your key and server URL)
+OMNIROUTE_URL="http://localhost:20128/v1"
+OMNIROUTE_KEY="sk-your-omniroute-key"
+
+npm install -g @anthropic-ai/claude-code @openai/codex opencode-ai cline kilocode
+
+# Kiro CLI
+apt-get install -y unzip 2>/dev/null; curl -fsSL https://cli.kiro.dev/install | bash
+
+# Write configs
+mkdir -p ~/.claude ~/.codex ~/.config/opencode ~/.continue
+
+cat > ~/.claude/settings.json <<< "{\"apiBaseUrl\":\"$OMNIROUTE_URL\",\"apiKey\":\"$OMNIROUTE_KEY\"}"
+cat > ~/.codex/config.yaml <<< "model: auto\napiKey: $OMNIROUTE_KEY\napiBaseUrl: $OMNIROUTE_URL"
+cat >> ~/.bashrc << EOF
+export OPENAI_BASE_URL="$OMNIROUTE_URL"
+export OPENAI_API_KEY="$OMNIROUTE_KEY"
+export ANTHROPIC_BASE_URL="$OMNIROUTE_URL"
+export ANTHROPIC_API_KEY="$OMNIROUTE_KEY"
+EOF
+
+source ~/.bashrc
+echo "✅ All CLIs installed and configured for OmniRoute"
+```
diff --git a/docs/i18n/es/docs/CODEBASE_DOCUMENTATION.md b/docs/i18n/es/docs/CODEBASE_DOCUMENTATION.md
new file mode 100644
index 0000000000..16356b1ed7
--- /dev/null
+++ b/docs/i18n/es/docs/CODEBASE_DOCUMENTATION.md
@@ -0,0 +1,591 @@
+# omniroute — Codebase Documentation (Español)
+
+🌐 **Languages:** 🇺🇸 [English](../../../../docs/CODEBASE_DOCUMENTATION.md) · 🇪🇸 [es](../../es/docs/CODEBASE_DOCUMENTATION.md) · 🇫🇷 [fr](../../fr/docs/CODEBASE_DOCUMENTATION.md) · 🇩🇪 [de](../../de/docs/CODEBASE_DOCUMENTATION.md) · 🇮🇹 [it](../../it/docs/CODEBASE_DOCUMENTATION.md) · 🇷🇺 [ru](../../ru/docs/CODEBASE_DOCUMENTATION.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/CODEBASE_DOCUMENTATION.md) · 🇯🇵 [ja](../../ja/docs/CODEBASE_DOCUMENTATION.md) · 🇰🇷 [ko](../../ko/docs/CODEBASE_DOCUMENTATION.md) · 🇸🇦 [ar](../../ar/docs/CODEBASE_DOCUMENTATION.md) · 🇮🇳 [in](../../in/docs/CODEBASE_DOCUMENTATION.md) · 🇹🇭 [th](../../th/docs/CODEBASE_DOCUMENTATION.md) · 🇻🇳 [vi](../../vi/docs/CODEBASE_DOCUMENTATION.md) · 🇮🇩 [id](../../id/docs/CODEBASE_DOCUMENTATION.md) · 🇲🇾 [ms](../../ms/docs/CODEBASE_DOCUMENTATION.md) · 🇳🇱 [nl](../../nl/docs/CODEBASE_DOCUMENTATION.md) · 🇵🇱 [pl](../../pl/docs/CODEBASE_DOCUMENTATION.md) · 🇸🇪 [sv](../../sv/docs/CODEBASE_DOCUMENTATION.md) · 🇳🇴 [no](../../no/docs/CODEBASE_DOCUMENTATION.md) · 🇩🇰 [da](../../da/docs/CODEBASE_DOCUMENTATION.md) · 🇫🇮 [fi](../../fi/docs/CODEBASE_DOCUMENTATION.md) · 🇵🇹 [pt](../../pt/docs/CODEBASE_DOCUMENTATION.md) · 🇷🇴 [ro](../../ro/docs/CODEBASE_DOCUMENTATION.md) · 🇭🇺 [hu](../../hu/docs/CODEBASE_DOCUMENTATION.md) · 🇧🇬 [bg](../../bg/docs/CODEBASE_DOCUMENTATION.md) · 🇸🇰 [sk](../../sk/docs/CODEBASE_DOCUMENTATION.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/CODEBASE_DOCUMENTATION.md) · 🇮🇱 [he](../../he/docs/CODEBASE_DOCUMENTATION.md) · 🇵🇭 [phi](../../phi/docs/CODEBASE_DOCUMENTATION.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/CODEBASE_DOCUMENTATION.md) · 🇨🇿 [cs](../../cs/docs/CODEBASE_DOCUMENTATION.md)
+
+---
+
+> A comprehensive, beginner-friendly guide to the **omniroute** multi-provider AI proxy router.
+
+---
+
+## 1. What Is omniroute?
+
+omniroute is a **proxy router** that sits between AI clients (Claude CLI, Codex, Cursor IDE, etc.) and AI providers (Anthropic, Google, OpenAI, AWS, GitHub, etc.). It solves one big problem:
+
+> **Different AI clients speak different "languages" (API formats), and different AI providers expect different "languages" too.** omniroute translates between them automatically.
+
+Think of it like a universal translator at the United Nations — any delegate can speak any language, and the translator converts it for any other delegate.
+
+---
+
+## 2. Architecture Overview
+
+```mermaid
+graph LR
+ subgraph Clients
+ A[Claude CLI]
+ B[Codex]
+ C[Cursor IDE]
+ D[OpenAI-compatible]
+ end
+
+ subgraph omniroute
+ E[Handler Layer]
+ F[Translator Layer]
+ G[Executor Layer]
+ H[Services Layer]
+ end
+
+ subgraph Providers
+ I[Anthropic Claude]
+ J[Google Gemini]
+ K[OpenAI / Codex]
+ L[GitHub Copilot]
+ M[AWS Kiro]
+ N[Antigravity]
+ O[Cursor API]
+ end
+
+ A --> E
+ B --> E
+ C --> E
+ D --> E
+ E --> F
+ F --> G
+ G --> I
+ G --> J
+ G --> K
+ G --> L
+ G --> M
+ G --> N
+ G --> O
+ H -.-> E
+ H -.-> G
+```
+
+### Core Principle: Hub-and-Spoke Translation
+
+All format translation passes through **OpenAI format as the hub**:
+
+```
+Client Format → [OpenAI Hub] → Provider Format (request)
+Provider Format → [OpenAI Hub] → Client Format (response)
+```
+
+This means you only need **N translators** (one per format) instead of **N²** (every pair).
+
+---
+
+## 3. Project Structure
+
+```
+omniroute/
+├── open-sse/ ← Core proxy library (portable, framework-agnostic)
+│ ├── index.js ← Main entry point, exports everything
+│ ├── config/ ← Configuration & constants
+│ ├── executors/ ← Provider-specific request execution
+│ ├── handlers/ ← Request handling orchestration
+│ ├── services/ ← Business logic (auth, models, fallback, usage)
+│ ├── translator/ ← Format translation engine
+│ │ ├── request/ ← Request translators (8 files)
+│ │ ├── response/ ← Response translators (7 files)
+│ │ └── helpers/ ← Shared translation utilities (6 files)
+│ └── utils/ ← Utility functions
+├── src/ ← Application layer (Express/Worker runtime)
+│ ├── app/ ← Web UI, API routes, middleware
+│ ├── lib/ ← Database, auth, and shared library code
+│ ├── mitm/ ← Man-in-the-middle proxy utilities
+│ ├── models/ ← Database models
+│ ├── shared/ ← Shared utilities (wrappers around open-sse)
+│ ├── sse/ ← SSE endpoint handlers
+│ └── store/ ← State management
+├── data/ ← Runtime data (credentials, logs)
+│ └── provider-credentials.json (external credentials override, gitignored)
+└── tester/ ← Test utilities
+```
+
+---
+
+## 4. Module-by-Module Breakdown
+
+### 4.1 Config (`open-sse/config/`)
+
+The **single source of truth** for all provider configuration.
+
+| File | Purpose |
+| ----------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| `constants.ts` | `PROVIDERS` object with base URLs, OAuth credentials (defaults), headers, and default system prompts for every provider. Also defines `HTTP_STATUS`, `ERROR_TYPES`, `COOLDOWN_MS`, `BACKOFF_CONFIG`, and `SKIP_PATTERNS`. |
+| `credentialLoader.ts` | Loads external credentials from `data/provider-credentials.json` and merges them over the hardcoded defaults in `PROVIDERS`. Keeps secrets out of source control while maintaining backwards compatibility. |
+| `providerModels.ts` | Central model registry: maps provider aliases → model IDs. Functions like `getModels()`, `getProviderByAlias()`. |
+| `codexInstructions.ts` | System instructions injected into Codex requests (editing constraints, sandbox rules, approval policies). |
+| `defaultThinkingSignature.ts` | Default "thinking" signatures for Claude and Gemini models. |
+| `ollamaModels.ts` | Schema definition for local Ollama models (name, size, family, quantization). |
+
+#### Credential Loading Flow
+
+```mermaid
+flowchart TD
+ A["App starts"] --> B["constants.ts defines PROVIDERS\nwith hardcoded defaults"]
+ B --> C{"data/provider-credentials.json\nexists?"}
+ C -->|Yes| D["credentialLoader reads JSON"]
+ C -->|No| E["Use hardcoded defaults"]
+ D --> F{"For each provider in JSON"}
+ F --> G{"Provider exists\nin PROVIDERS?"}
+ G -->|No| H["Log warning, skip"]
+ G -->|Yes| I{"Value is object?"}
+ I -->|No| J["Log warning, skip"]
+ I -->|Yes| K["Merge clientId, clientSecret,\ntokenUrl, authUrl, refreshUrl"]
+ K --> F
+ H --> F
+ J --> F
+ F -->|Done| L["PROVIDERS ready with\nmerged credentials"]
+ E --> L
+```
+
+---
+
+### 4.2 Executors (`open-sse/executors/`)
+
+Executors encapsulate **provider-specific logic** using the **Strategy Pattern**. Each executor overrides base methods as needed.
+
+```mermaid
+classDiagram
+ class BaseExecutor {
+ +buildUrl(model, stream, options)
+ +buildHeaders(credentials, stream, body)
+ +transformRequest(body, model, stream, credentials)
+ +execute(url, options)
+ +shouldRetry(status, error)
+ +refreshCredentials(credentials, log)
+ }
+
+ class DefaultExecutor {
+ +refreshCredentials()
+ }
+
+ class AntigravityExecutor {
+ +buildUrl()
+ +buildHeaders()
+ +transformRequest()
+ +shouldRetry()
+ +refreshCredentials()
+ }
+
+ class CursorExecutor {
+ +buildUrl()
+ +buildHeaders()
+ +transformRequest()
+ +parseResponse()
+ +generateChecksum()
+ }
+
+ class KiroExecutor {
+ +buildUrl()
+ +buildHeaders()
+ +transformRequest()
+ +parseEventStream()
+ +refreshCredentials()
+ }
+
+ BaseExecutor <|-- DefaultExecutor
+ BaseExecutor <|-- AntigravityExecutor
+ BaseExecutor <|-- CursorExecutor
+ BaseExecutor <|-- KiroExecutor
+ BaseExecutor <|-- CodexExecutor
+ BaseExecutor <|-- GeminiCLIExecutor
+ BaseExecutor <|-- GithubExecutor
+```
+
+| Executor | Provider | Key Specializations |
+| ---------------- | ------------------------------------------ | ------------------------------------------------------------------------------------------------------------------- |
+| `base.ts` | — | Abstract base: URL building, headers, retry logic, credential refresh |
+| `default.ts` | Claude, Gemini, OpenAI, GLM, Kimi, MiniMax | Generic OAuth token refresh for standard providers |
+| `antigravity.ts` | Google Cloud Code | Project/session ID generation, multi-URL fallback, custom retry parsing from error messages ("reset after 2h7m23s") |
+| `cursor.ts` | Cursor IDE | **Most complex**: SHA-256 checksum auth, Protobuf request encoding, binary EventStream → SSE response parsing |
+| `codex.ts` | OpenAI Codex | Injects system instructions, manages thinking levels, removes unsupported parameters |
+| `gemini-cli.ts` | Google Gemini CLI | Custom URL building (`streamGenerateContent`), Google OAuth token refresh |
+| `github.ts` | GitHub Copilot | Dual token system (GitHub OAuth + Copilot token), VSCode header mimicking |
+| `kiro.ts` | AWS CodeWhisperer | AWS EventStream binary parsing, AMZN event frames, token estimation |
+| `index.ts` | — | Factory: maps provider name → executor class, with default fallback |
+
+---
+
+### 4.3 Handlers (`open-sse/handlers/`)
+
+The **orchestration layer** — coordinates translation, execution, streaming, and error handling.
+
+| File | Purpose |
+| --------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| `chatCore.ts` | **Central orchestrator** (~600 lines). Handles the complete request lifecycle: format detection → translation → executor dispatch → streaming/non-streaming response → token refresh → error handling → usage logging. |
+| `responsesHandler.ts` | Adapter for OpenAI's Responses API: converts Responses format → Chat Completions → sends to `chatCore` → converts SSE back to Responses format. |
+| `embeddings.ts` | Embedding generation handler: resolves embedding model → provider, dispatches to provider API, returns OpenAI-compatible embedding response. Supports 6+ providers. |
+| `imageGeneration.ts` | Image generation handler: resolves image model → provider, supports OpenAI-compatible, Gemini-image (Antigravity), and fallback (Nebius) modes. Returns base64 or URL images. |
+
+#### Request Lifecycle (chatCore.ts)
+
+```mermaid
+sequenceDiagram
+ participant Client
+ participant chatCore
+ participant Translator
+ participant Executor
+ participant Provider
+
+ Client->>chatCore: Request (any format)
+ chatCore->>chatCore: Detect source format
+ chatCore->>chatCore: Check bypass patterns
+ chatCore->>chatCore: Resolve model & provider
+ chatCore->>Translator: Translate request (source → OpenAI → target)
+ chatCore->>Executor: Get executor for provider
+ Executor->>Executor: Build URL, headers, transform request
+ Executor->>Executor: Refresh credentials if needed
+ Executor->>Provider: HTTP fetch (streaming or non-streaming)
+
+ alt Streaming
+ Provider-->>chatCore: SSE stream
+ chatCore->>chatCore: Pipe through SSE transform stream
+ Note over chatCore: Transform stream translates
each chunk: target → OpenAI → source
+ chatCore-->>Client: Translated SSE stream
+ else Non-streaming
+ Provider-->>chatCore: JSON response
+ chatCore->>Translator: Translate response
+ chatCore-->>Client: Translated JSON
+ end
+
+ alt Error (401, 429, 500...)
+ chatCore->>Executor: Retry with credential refresh
+ chatCore->>chatCore: Account fallback logic
+ end
+```
+
+---
+
+### 4.4 Services (`open-sse/services/`)
+
+Business logic that supports the handlers and executors.
+
+| File | Purpose |
+| -------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| `provider.ts` | **Format detection** (`detectFormat`): analyzes request body structure to identify Claude/OpenAI/Gemini/Antigravity/Responses formats (includes `max_tokens` heuristic for Claude). Also: URL building, header building, thinking config normalization. Supports `openai-compatible-*` and `anthropic-compatible-*` dynamic providers. |
+| `model.ts` | Model string parsing (`claude/model-name` → `{provider: "claude", model: "model-name"}`), alias resolution with collision detection, input sanitization (rejects path traversal/control chars), and model info resolution with async alias getter support. |
+| `accountFallback.ts` | Rate-limit handling: exponential backoff (1s → 2s → 4s → max 2min), account cooldown management, error classification (which errors trigger fallback vs. not). |
+| `tokenRefresh.ts` | OAuth token refresh for **every provider**: Google (Gemini, Antigravity), Claude, Codex, Qwen, Qoder, GitHub (OAuth + Copilot dual-token), Kiro (AWS SSO OIDC + Social Auth). Includes in-flight promise deduplication cache and retry with exponential backoff. |
+| `combo.ts` | **Combo models**: chains of fallback models. If model A fails with a fallback-eligible error, try model B, then C, etc. Returns actual upstream status codes. |
+| `usage.ts` | Fetches quota/usage data from provider APIs (GitHub Copilot quotas, Antigravity model quotas, Codex rate limits, Kiro usage breakdowns, Claude settings). |
+| `accountSelector.ts` | Smart account selection with scoring algorithm: considers priority, health status, round-robin position, and cooldown state to pick the optimal account for each request. |
+| `contextManager.ts` | Request context lifecycle management: creates and tracks per-request context objects with metadata (request ID, timestamps, provider info) for debugging and logging. |
+| `ipFilter.ts` | IP-based access control: supports allowlist and blocklist modes. Validates client IP against configured rules before processing API requests. |
+| `sessionManager.ts` | Session tracking with client fingerprinting: tracks active sessions using hashed client identifiers, monitors request counts, and provides session metrics. |
+| `signatureCache.ts` | Request signature-based deduplication cache: prevents duplicate requests by caching recent request signatures and returning cached responses for identical requests within a time window. |
+| `systemPrompt.ts` | Global system prompt injection: prepends or appends a configurable system prompt to all requests, with per-provider compatibility handling. |
+| `thinkingBudget.ts` | Reasoning token budget management: supports passthrough, auto (strip thinking config), custom (fixed budget), and adaptive (complexity-scaled) modes for controlling thinking/reasoning tokens. |
+| `wildcardRouter.ts` | Wildcard model pattern routing: resolves wildcard patterns (e.g., `*/claude-*`) to concrete provider/model pairs based on availability and priority. |
+
+#### Token Refresh Deduplication
+
+```mermaid
+sequenceDiagram
+ participant R1 as Request 1
+ participant R2 as Request 2
+ participant Cache as refreshPromiseCache
+ participant OAuth as OAuth Provider
+
+ R1->>Cache: getAccessToken("gemini", token)
+ Cache->>Cache: No in-flight promise
+ Cache->>OAuth: Start refresh
+ R2->>Cache: getAccessToken("gemini", token)
+ Cache->>Cache: Found in-flight promise
+ Cache-->>R2: Return existing promise
+ OAuth-->>Cache: New access token
+ Cache-->>R1: New access token
+ Cache-->>R2: Same access token (shared)
+ Cache->>Cache: Delete cache entry
+```
+
+#### Account Fallback State Machine
+
+```mermaid
+stateDiagram-v2
+ [*] --> Active
+ Active --> Error: Request fails (401/429/500)
+ Error --> Cooldown: Apply backoff
+ Cooldown --> Active: Cooldown expires
+ Active --> Active: Request succeeds (reset backoff)
+
+ state Error {
+ [*] --> ClassifyError
+ ClassifyError --> ShouldFallback: Rate limit / Auth / Transient
+ ClassifyError --> NoFallback: 400 Bad Request
+ }
+
+ state Cooldown {
+ [*] --> ExponentialBackoff
+ ExponentialBackoff: Level 0 = 1s
+ ExponentialBackoff: Level 1 = 2s
+ ExponentialBackoff: Level 2 = 4s
+ ExponentialBackoff: Max = 2min
+ }
+```
+
+#### Combo Model Chain
+
+```mermaid
+flowchart LR
+ A["Request with\ncombo model"] --> B["Model A"]
+ B -->|"2xx Success"| C["Return response"]
+ B -->|"429/401/500"| D{"Fallback\neligible?"}
+ D -->|Yes| E["Model B"]
+ D -->|No| F["Return error"]
+ E -->|"2xx Success"| C
+ E -->|"429/401/500"| G{"Fallback\neligible?"}
+ G -->|Yes| H["Model C"]
+ G -->|No| F
+ H -->|"2xx Success"| C
+ H -->|"Fail"| I["All failed →\nReturn last status"]
+```
+
+---
+
+### 4.5 Translator (`open-sse/translator/`)
+
+The **format translation engine** using a self-registering plugin system.
+
+#### Arquitectura
+
+```mermaid
+graph TD
+ subgraph "Request Translation"
+ A["Claude → OpenAI"]
+ B["Gemini → OpenAI"]
+ C["Antigravity → OpenAI"]
+ D["OpenAI Responses → OpenAI"]
+ E["OpenAI → Claude"]
+ F["OpenAI → Gemini"]
+ G["OpenAI → Kiro"]
+ H["OpenAI → Cursor"]
+ end
+
+ subgraph "Response Translation"
+ I["Claude → OpenAI"]
+ J["Gemini → OpenAI"]
+ K["Kiro → OpenAI"]
+ L["Cursor → OpenAI"]
+ M["OpenAI → Claude"]
+ N["OpenAI → Antigravity"]
+ O["OpenAI → Responses"]
+ end
+```
+
+| Directory | Files | Description |
+| ------------ | ------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| `request/` | 8 translators | Convert request bodies between formats. Each file self-registers via `register(from, to, fn)` on import. |
+| `response/` | 7 translators | Convert streaming response chunks between formats. Handles SSE event types, thinking blocks, tool calls. |
+| `helpers/` | 6 helpers | Shared utilities: `claudeHelper` (system prompt extraction, thinking config), `geminiHelper` (parts/contents mapping), `openaiHelper` (format filtering), `toolCallHelper` (ID generation, missing response injection), `maxTokensHelper`, `responsesApiHelper`. |
+| `index.ts` | — | Translation engine: `translateRequest()`, `translateResponse()`, state management, registry. |
+| `formats.ts` | — | Format constants: `OPENAI`, `CLAUDE`, `GEMINI`, `ANTIGRAVITY`, `KIRO`, `CURSOR`, `OPENAI_RESPONSES`. |
+
+#### Key Design: Self-Registering Plugins
+
+```javascript
+// Each translator file calls register() on import:
+import { register } from "../index.js";
+register("claude", "openai", translateClaudeToOpenAI);
+
+// The index.js imports all translator files, triggering registration:
+import "./request/claude-to-openai.js"; // ← self-registers
+```
+
+---
+
+### 4.6 Utils (`open-sse/utils/`)
+
+| File | Purpose |
+| ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
+| `error.ts` | Error response building (OpenAI-compatible format), upstream error parsing, Antigravity retry-time extraction from error messages, SSE error streaming. |
+| `stream.ts` | **SSE Transform Stream** — the core streaming pipeline. Two modes: `TRANSLATE` (full format translation) and `PASSTHROUGH` (normalize + extract usage). Handles chunk buffering, usage estimation, content length tracking. Per-stream encoder/decoder instances avoid shared state. |
+| `streamHelpers.ts` | Low-level SSE utilities: `parseSSELine` (whitespace-tolerant), `hasValuableContent` (filters empty chunks for OpenAI/Claude/Gemini), `fixInvalidId`, `formatSSE` (format-aware SSE serialization with `perf_metrics` cleanup). |
+| `usageTracking.ts` | Token usage extraction from any format (Claude/OpenAI/Gemini/Responses), estimation with separate tool/message char-per-token ratios, buffer addition (2000 tokens safety margin), format-specific field filtering, console logging with ANSI colors. |
+| `requestLogger.ts` | File-based request logging (opt-in via `ENABLE_REQUEST_LOGS=true`). Creates session folders with numbered files: `1_req_client.json` → `7_res_client.txt`. All I/O is async (fire-and-forget). Masks sensitive headers. |
+| `bypassHandler.ts` | Intercepts specific patterns from Claude CLI (title extraction, warmup, count) and returns fake responses without calling any provider. Supports both streaming and non-streaming. Intentionally limited to Claude CLI scope. |
+| `networkProxy.ts` | Resolves outbound proxy URL for a given provider with precedence: provider-specific config → global config → environment variables (`HTTPS_PROXY`/`HTTP_PROXY`/`ALL_PROXY`). Supports `NO_PROXY` exclusions. Caches config for 30s. |
+
+#### SSE Streaming Pipeline
+
+```mermaid
+flowchart TD
+ A["Provider SSE stream"] --> B["TextDecoder\n(per-stream instance)"]
+ B --> C["Buffer lines\n(split on newline)"]
+ C --> D["parseSSELine()\n(trim whitespace, parse JSON)"]
+ D --> E{"Mode?"}
+ E -->|TRANSLATE| F["translateResponse()\ntarget → OpenAI → source"]
+ E -->|PASSTHROUGH| G["fixInvalidId()\nnormalize chunk"]
+ F --> H["hasValuableContent()\nfilter empty chunks"]
+ G --> H
+ H -->|"Has content"| I["extractUsage()\ntrack token counts"]
+ H -->|"Empty"| J["Skip chunk"]
+ I --> K["formatSSE()\nserialize + clean perf_metrics"]
+ K --> L["TextEncoder\n(per-stream instance)"]
+ L --> M["Enqueue to\nclient stream"]
+
+ style A fill:#f9f,stroke:#333
+ style M fill:#9f9,stroke:#333
+```
+
+#### Request Logger Session Structure
+
+```
+logs/
+└── claude_gemini_claude-sonnet_20260208_143045/
+ ├── 1_req_client.json ← Raw client request
+ ├── 2_req_source.json ← After initial conversion
+ ├── 3_req_openai.json ← OpenAI intermediate format
+ ├── 4_req_target.json ← Final target format
+ ├── 5_res_provider.txt ← Provider SSE chunks (streaming)
+ ├── 5_res_provider.json ← Provider response (non-streaming)
+ ├── 6_res_openai.txt ← OpenAI intermediate chunks
+ ├── 7_res_client.txt ← Client-facing SSE chunks
+ └── 6_error.json ← Error details (if any)
+```
+
+---
+
+### 4.7 Application Layer (`src/`)
+
+| Directory | Purpose |
+| ------------- | ---------------------------------------------------------------------- |
+| `src/app/` | Web UI, API routes, Express middleware, OAuth callback handlers |
+| `src/lib/` | Database access (`localDb.ts`, `usageDb.ts`), authentication, shared |
+| `src/mitm/` | Man-in-the-middle proxy utilities for intercepting provider traffic |
+| `src/models/` | Database model definitions |
+| `src/shared/` | Wrappers around open-sse functions (provider, stream, error, etc.) |
+| `src/sse/` | SSE endpoint handlers that wire the open-sse library to Express routes |
+| `src/store/` | Application state management |
+
+#### Notable API Routes
+
+| Route | Methods | Purpose |
+| --------------------------------------------- | --------------- | ------------------------------------------------------------------------------------- |
+| `/api/provider-models` | GET/POST/DELETE | CRUD for custom models per provider |
+| `/api/models/catalog` | GET | Aggregated catalog of all models (chat, embedding, image, custom) grouped by provider |
+| `/api/settings/proxy` | GET/PUT/DELETE | Hierarchical outbound proxy configuration (`global/providers/combos/keys`) |
+| `/api/settings/proxy/test` | POST | Validates proxy connectivity and returns public IP/latency |
+| `/v1/providers/[provider]/chat/completions` | POST | Dedicated per-provider chat completions with model validation |
+| `/v1/providers/[provider]/embeddings` | POST | Dedicated per-provider embeddings with model validation |
+| `/v1/providers/[provider]/images/generations` | POST | Dedicated per-provider image generation with model validation |
+| `/api/settings/ip-filter` | GET/PUT | IP allowlist/blocklist management |
+| `/api/settings/thinking-budget` | GET/PUT | Reasoning token budget configuration (passthrough/auto/custom/adaptive) |
+| `/api/settings/system-prompt` | GET/PUT | Global system prompt injection for all requests |
+| `/api/sessions` | GET | Active session tracking and metrics |
+| `/api/rate-limits` | GET | Per-account rate limit status |
+
+---
+
+## 5. Key Design Patterns
+
+### 5.1 Hub-and-Spoke Translation
+
+All formats translate through **OpenAI format as the hub**. Adding a new provider only requires writing **one pair** of translators (to/from OpenAI), not N pairs.
+
+### 5.2 Executor Strategy Pattern
+
+Each provider has a dedicated executor class inheriting from `BaseExecutor`. The factory in `executors/index.ts` selects the right one at runtime.
+
+### 5.3 Self-Registering Plugin System
+
+Translator modules register themselves on import via `register()`. Adding a new translator is just creating a file and importing it.
+
+### 5.4 Account Fallback with Exponential Backoff
+
+When a provider returns 429/401/500, the system can switch to the next account, applying exponential cooldowns (1s → 2s → 4s → max 2min).
+
+### 5.5 Combo Model Chains
+
+A "combo" groups multiple `provider/model` strings. If the first fails, fallback to the next automatically.
+
+### 5.6 Stateful Streaming Translation
+
+Response translation maintains state across SSE chunks (thinking block tracking, tool call accumulation, content block indexing) via the `initState()` mechanism.
+
+### 5.7 Usage Safety Buffer
+
+A 2000-token buffer is added to reported usage to prevent clients from hitting context window limits due to overhead from system prompts and format translation.
+
+---
+
+## 6. Supported Formats
+
+| Format | Direction | Identifier |
+| ----------------------- | --------------- | ------------------ |
+| OpenAI Chat Completions | source + target | `openai` |
+| OpenAI Responses API | source + target | `openai-responses` |
+| Anthropic Claude | source + target | `claude` |
+| Google Gemini | source + target | `gemini` |
+| Google Gemini CLI | target only | `gemini-cli` |
+| Antigravity | source + target | `antigravity` |
+| AWS Kiro | target only | `kiro` |
+| Cursor | target only | `cursor` |
+
+---
+
+## 7. Supported Providers
+
+| Provider | Auth Method | Executor | Key Notes |
+| ------------------------ | ---------------------- | ----------- | --------------------------------------------- |
+| Anthropic Claude | API key or OAuth | Default | Uses `x-api-key` header |
+| Google Gemini | API key or OAuth | Default | Uses `x-goog-api-key` header |
+| Google Gemini CLI | OAuth | GeminiCLI | Uses `streamGenerateContent` endpoint |
+| Antigravity | OAuth | Antigravity | Multi-URL fallback, custom retry parsing |
+| OpenAI | API key | Default | Standard Bearer auth |
+| Codex | OAuth | Codex | Injects system instructions, manages thinking |
+| GitHub Copilot | OAuth + Copilot token | Github | Dual token, VSCode header mimicking |
+| Kiro (AWS) | AWS SSO OIDC or Social | Kiro | Binary EventStream parsing |
+| Cursor IDE | Checksum auth | Cursor | Protobuf encoding, SHA-256 checksums |
+| Qwen | OAuth | Default | Standard auth |
+| Qoder | OAuth (Basic + Bearer) | Default | Dual auth header |
+| OpenRouter | API key | Default | Standard Bearer auth |
+| GLM, Kimi, MiniMax | API key | Default | Claude-compatible, use `x-api-key` |
+| `openai-compatible-*` | API key | Default | Dynamic: any OpenAI-compatible endpoint |
+| `anthropic-compatible-*` | API key | Default | Dynamic: any Claude-compatible endpoint |
+
+---
+
+## 8. Data Flow Summary
+
+### Streaming Request
+
+```mermaid
+flowchart LR
+ A["Client"] --> B["detectFormat()"]
+ B --> C["translateRequest()\nsource → OpenAI → target"]
+ C --> D["Executor\nbuildUrl + buildHeaders"]
+ D --> E["fetch(providerURL)"]
+ E --> F["createSSEStream()\nTRANSLATE mode"]
+ F --> G["parseSSELine()"]
+ G --> H["translateResponse()\ntarget → OpenAI → source"]
+ H --> I["extractUsage()\n+ addBuffer"]
+ I --> J["formatSSE()"]
+ J --> K["Client receives\ntranslated SSE"]
+ K --> L["logUsage()\nsaveRequestUsage()"]
+```
+
+### Non-Streaming Request
+
+```mermaid
+flowchart LR
+ A["Client"] --> B["detectFormat()"]
+ B --> C["translateRequest()\nsource → OpenAI → target"]
+ C --> D["Executor.execute()"]
+ D --> E["translateResponse()\ntarget → OpenAI → source"]
+ E --> F["Return JSON\nresponse"]
+```
+
+### Bypass Flow (Claude CLI)
+
+```mermaid
+flowchart LR
+ A["Claude CLI request"] --> B{"Match bypass\npattern?"}
+ B -->|"Title/Warmup/Count"| C["Generate fake\nOpenAI response"]
+ B -->|"No match"| D["Normal flow"]
+ C --> E["Translate to\nsource format"]
+ E --> F["Return without\ncalling provider"]
+```
diff --git a/docs/i18n/es/docs/COVERAGE_PLAN.md b/docs/i18n/es/docs/COVERAGE_PLAN.md
new file mode 100644
index 0000000000..21babefd0c
--- /dev/null
+++ b/docs/i18n/es/docs/COVERAGE_PLAN.md
@@ -0,0 +1,170 @@
+# Test Coverage Plan (Español)
+
+🌐 **Languages:** 🇺🇸 [English](../../../../docs/COVERAGE_PLAN.md) · 🇪🇸 [es](../../es/docs/COVERAGE_PLAN.md) · 🇫🇷 [fr](../../fr/docs/COVERAGE_PLAN.md) · 🇩🇪 [de](../../de/docs/COVERAGE_PLAN.md) · 🇮🇹 [it](../../it/docs/COVERAGE_PLAN.md) · 🇷🇺 [ru](../../ru/docs/COVERAGE_PLAN.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/COVERAGE_PLAN.md) · 🇯🇵 [ja](../../ja/docs/COVERAGE_PLAN.md) · 🇰🇷 [ko](../../ko/docs/COVERAGE_PLAN.md) · 🇸🇦 [ar](../../ar/docs/COVERAGE_PLAN.md) · 🇮🇳 [in](../../in/docs/COVERAGE_PLAN.md) · 🇹🇭 [th](../../th/docs/COVERAGE_PLAN.md) · 🇻🇳 [vi](../../vi/docs/COVERAGE_PLAN.md) · 🇮🇩 [id](../../id/docs/COVERAGE_PLAN.md) · 🇲🇾 [ms](../../ms/docs/COVERAGE_PLAN.md) · 🇳🇱 [nl](../../nl/docs/COVERAGE_PLAN.md) · 🇵🇱 [pl](../../pl/docs/COVERAGE_PLAN.md) · 🇸🇪 [sv](../../sv/docs/COVERAGE_PLAN.md) · 🇳🇴 [no](../../no/docs/COVERAGE_PLAN.md) · 🇩🇰 [da](../../da/docs/COVERAGE_PLAN.md) · 🇫🇮 [fi](../../fi/docs/COVERAGE_PLAN.md) · 🇵🇹 [pt](../../pt/docs/COVERAGE_PLAN.md) · 🇷🇴 [ro](../../ro/docs/COVERAGE_PLAN.md) · 🇭🇺 [hu](../../hu/docs/COVERAGE_PLAN.md) · 🇧🇬 [bg](../../bg/docs/COVERAGE_PLAN.md) · 🇸🇰 [sk](../../sk/docs/COVERAGE_PLAN.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/COVERAGE_PLAN.md) · 🇮🇱 [he](../../he/docs/COVERAGE_PLAN.md) · 🇵🇭 [phi](../../phi/docs/COVERAGE_PLAN.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/COVERAGE_PLAN.md) · 🇨🇿 [cs](../../cs/docs/COVERAGE_PLAN.md)
+
+---
+
+Last updated: 2026-03-28
+
+## Baseline
+
+There are multiple coverage numbers depending on how the report is computed. For planning, only one of them is useful.
+
+| Metric | Scope | Statements / Lines | Branches | Functions | Notes |
+| -------------------- | ----------------------------------------------------- | -----------------: | -------: | --------: | --------------------------------------------------- |
+| Legacy | Old `npm run test:coverage` | 79.42% | 75.15% | 67.94% | Inflated: counts test files and excludes `open-sse` |
+| Diagnostic | Source-only, excluding tests and excluding `open-sse` | 68.16% | 63.55% | 64.06% | Useful only to isolate `src/**` |
+| Recommended baseline | Source-only, excluding tests and including `open-sse` | 56.95% | 66.05% | 57.80% | This is the project-wide baseline to improve |
+
+The recommended baseline is the number to optimize against.
+
+## Rules
+
+- Coverage targets apply to source files, not to `tests/**`.
+- `open-sse/**` is part of the product and must remain in scope.
+- New code should not reduce coverage in touched areas.
+- Prefer testing behavior and branch outcomes over implementation details.
+- Prefer temp SQLite databases and small fixtures over broad mocks for `src/lib/db/**`.
+
+## Current command set
+
+- `npm run test:coverage`
+ - Main source coverage gate for the unit test suite
+ - Generates `text-summary`, `html`, `json-summary`, and `lcov`
+- `npm run coverage:report`
+ - Detailed file-by-file report from the latest run
+- `npm run test:coverage:legacy`
+ - Historical comparison only
+
+## Milestones
+
+| Phase | Target | Focus |
+| ------- | ---------------------: | ------------------------------------------------- |
+| Phase 1 | 60% statements / lines | Quick wins and low-risk utility coverage |
+| Phase 2 | 65% statements / lines | DB and route foundations |
+| Phase 3 | 70% statements / lines | Provider validation and usage analytics |
+| Phase 4 | 75% statements / lines | `open-sse` translators and helpers |
+| Phase 5 | 80% statements / lines | `open-sse` handlers and executor branches |
+| Phase 6 | 85% statements / lines | Harder edge cases, branch debt, regression suites |
+| Phase 7 | 90% statements / lines | Final sweep, gap closure, strict ratchet |
+
+Branches and functions should ratchet upward with each phase, but the primary hard target is statements / lines.
+
+## Priority hotspots
+
+These files or areas offer the best return for the next phases:
+
+1. `open-sse/handlers`
+ - `chatCore.ts` at 7.57%
+ - Overall directory at 29.07%
+2. `open-sse/translator/request`
+ - Overall directory at 36.39%
+ - Many translators are still near single-digit coverage
+3. `open-sse/translator/response`
+ - Overall directory at 8.07%
+4. `open-sse/executors`
+ - Overall directory at 36.62%
+5. `src/lib/db`
+ - `models.ts` at 20.66%
+ - `registeredKeys.ts` at 34.46%
+ - `modelComboMappings.ts` at 36.25%
+ - `settings.ts` at 46.40%
+ - `webhooks.ts` at 33.33%
+6. `src/lib/usage`
+ - `usageHistory.ts` at 21.12%
+ - `usageStats.ts` at 9.56%
+ - `costCalculator.ts` at 30.00%
+7. `src/lib/providers`
+ - `validation.ts` at 41.16%
+8. Low-risk utility and API files for early gains
+ - `src/shared/utils/upstreamError.ts`
+ - `src/shared/utils/apiAuth.ts`
+ - `src/lib/api/errorResponse.ts`
+ - `src/app/api/settings/require-login/route.ts`
+ - `src/app/api/providers/[id]/models/route.ts`
+
+## Execution checklist
+
+### Phase 1: 56.95% -> 60%
+
+- [x] Fix coverage metric so it reflects source code instead of test files
+- [x] Keep a legacy coverage script for comparison
+- [x] Record the baseline and hotspots in-repo
+- [ ] Add focused tests for low-risk utilities:
+ - `src/shared/utils/upstreamError.ts`
+ - `src/shared/utils/fetchTimeout.ts`
+ - `src/lib/api/errorResponse.ts`
+ - `src/shared/utils/apiAuth.ts`
+ - `src/lib/display/names.ts`
+- [ ] Add route tests for:
+ - `src/app/api/settings/require-login/route.ts`
+ - `src/app/api/providers/[id]/models/route.ts`
+
+### Phase 2: 60% -> 65%
+
+- [ ] Add DB-backed tests for:
+ - `src/lib/db/modelComboMappings.ts`
+ - `src/lib/db/settings.ts`
+ - `src/lib/db/registeredKeys.ts`
+- [ ] Cover branch behavior in:
+ - `src/lib/providers/validation.ts`
+ - `src/app/api/v1/embeddings/route.ts`
+ - `src/app/api/v1/moderations/route.ts`
+
+### Phase 3: 65% -> 70%
+
+- [ ] Add usage analytics tests for:
+ - `src/lib/usage/usageHistory.ts`
+ - `src/lib/usage/usageStats.ts`
+ - `src/lib/usage/costCalculator.ts`
+- [ ] Expand route coverage for proxy management and settings branches
+
+### Phase 4: 70% -> 75%
+
+- [ ] Cover translator helpers and central translation paths:
+ - `open-sse/translator/index.ts`
+ - `open-sse/translator/helpers/*`
+ - `open-sse/translator/request/*`
+ - `open-sse/translator/response/*`
+
+### Phase 5: 75% -> 80%
+
+- [ ] Add handler-level tests for:
+ - `open-sse/handlers/chatCore.ts`
+ - `open-sse/handlers/responsesHandler.js`
+ - `open-sse/handlers/imageGeneration.js`
+ - `open-sse/handlers/embeddings.js`
+- [ ] Add executor branch coverage for provider-specific auth, retries, and endpoint overrides
+
+### Phase 6: 80% -> 85%
+
+- [ ] Merge more edge-case suites into the main coverage path
+- [ ] Increase function coverage for DB modules with weak constructor/helper coverage
+- [ ] Close branch gaps in `settings.ts`, `registeredKeys.ts`, `validation.ts`, and translator helpers
+
+### Phase 7: 85% -> 90%
+
+- [ ] Treat the remaining low-coverage files as blockers
+- [ ] Add regression tests for every uncovered production bug fixed during the push to 90%
+- [ ] Raise the coverage gate in CI only after the local baseline is stable for at least two consecutive runs
+
+## Ratchet policy
+
+Update `npm run test:coverage` thresholds only after the project actually exceeds the next milestone with a comfortable buffer.
+
+Recommended ratchet sequence:
+
+1. 55/60/55
+2. 60/62/58
+3. 65/64/62
+4. 70/66/66
+5. 75/70/72
+6. 80/75/78
+7. 85/80/84
+8. 90/85/88
+
+Order is `statements-lines / branches / functions`.
+
+## Known gap
+
+The current coverage command measures the main Node unit suite and includes source reached from it, including `open-sse`. It does not yet merge Vitest coverage into a single unified report. That merge is worth doing later, but it is not a blocker for starting the 60% -> 80% climb.
diff --git a/docs/i18n/es/docs/FEATURES.md b/docs/i18n/es/docs/FEATURES.md
index 4d8f9bcc3a..88fb1e7670 100644
--- a/docs/i18n/es/docs/FEATURES.md
+++ b/docs/i18n/es/docs/FEATURES.md
@@ -1,6 +1,6 @@
# OmniRoute — Dashboard Features Gallery (Español)
-🌐 **Languages:** 🇺🇸 [English](../../../../docs/FEATURES.md) · 🇪🇸 [es](../../es/docs/FEATURES.md) · 🇫🇷 [fr](../../fr/docs/FEATURES.md) · 🇩🇪 [de](../../de/docs/FEATURES.md) · 🇮🇹 [it](../../it/docs/FEATURES.md) · 🇷🇺 [ru](../../ru/docs/FEATURES.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/FEATURES.md) · 🇯🇵 [ja](../../ja/docs/FEATURES.md) · 🇰🇷 [ko](../../ko/docs/FEATURES.md) · 🇸🇦 [ar](../../ar/docs/FEATURES.md) · 🇮🇳 [in](../../in/docs/FEATURES.md) · 🇹🇭 [th](../../th/docs/FEATURES.md) · 🇻🇳 [vi](../../vi/docs/FEATURES.md) · 🇮🇩 [id](../../id/docs/FEATURES.md) · 🇲🇾 [ms](../../ms/docs/FEATURES.md) · 🇳🇱 [nl](../../nl/docs/FEATURES.md) · 🇵🇱 [pl](../../pl/docs/FEATURES.md) · 🇸🇪 [sv](../../sv/docs/FEATURES.md) · 🇳🇴 [no](../../no/docs/FEATURES.md) · 🇩🇰 [da](../../da/docs/FEATURES.md) · 🇫🇮 [fi](../../fi/docs/FEATURES.md) · 🇵🇹 [pt](../../pt/docs/FEATURES.md) · 🇷🇴 [ro](../../ro/docs/FEATURES.md) · 🇭🇺 [hu](../../hu/docs/FEATURES.md) · 🇧🇬 [bg](../../bg/docs/FEATURES.md) · 🇸🇰 [sk](../../sk/docs/FEATURES.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/FEATURES.md) · 🇮🇱 [he](../../he/docs/FEATURES.md) · 🇵🇭 [phi](../../phi/docs/FEATURES.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/FEATURES.md)
+🌐 **Languages:** 🇺🇸 [English](../../../../docs/FEATURES.md) · 🇪🇸 [es](../../es/docs/FEATURES.md) · 🇫🇷 [fr](../../fr/docs/FEATURES.md) · 🇩🇪 [de](../../de/docs/FEATURES.md) · 🇮🇹 [it](../../it/docs/FEATURES.md) · 🇷🇺 [ru](../../ru/docs/FEATURES.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/FEATURES.md) · 🇯🇵 [ja](../../ja/docs/FEATURES.md) · 🇰🇷 [ko](../../ko/docs/FEATURES.md) · 🇸🇦 [ar](../../ar/docs/FEATURES.md) · 🇮🇳 [in](../../in/docs/FEATURES.md) · 🇹🇭 [th](../../th/docs/FEATURES.md) · 🇻🇳 [vi](../../vi/docs/FEATURES.md) · 🇮🇩 [id](../../id/docs/FEATURES.md) · 🇲🇾 [ms](../../ms/docs/FEATURES.md) · 🇳🇱 [nl](../../nl/docs/FEATURES.md) · 🇵🇱 [pl](../../pl/docs/FEATURES.md) · 🇸🇪 [sv](../../sv/docs/FEATURES.md) · 🇳🇴 [no](../../no/docs/FEATURES.md) · 🇩🇰 [da](../../da/docs/FEATURES.md) · 🇫🇮 [fi](../../fi/docs/FEATURES.md) · 🇵🇹 [pt](../../pt/docs/FEATURES.md) · 🇷🇴 [ro](../../ro/docs/FEATURES.md) · 🇭🇺 [hu](../../hu/docs/FEATURES.md) · 🇧🇬 [bg](../../bg/docs/FEATURES.md) · 🇸🇰 [sk](../../sk/docs/FEATURES.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/FEATURES.md) · 🇮🇱 [he](../../he/docs/FEATURES.md) · 🇵🇭 [phi](../../phi/docs/FEATURES.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/FEATURES.md) · 🇨🇿 [cs](../../cs/docs/FEATURES.md)
---
@@ -10,7 +10,7 @@ Visual guide to every section of the OmniRoute dashboard.
## 🔌 Providers
-Manage AI provider connections: OAuth providers (Claude Code, Codex, Gemini CLI), API key providers (Groq, DeepSeek, OpenRouter), and free providers (iFlow, Qwen, Kiro). Kiro accounts include credit balance tracking — remaining credits, total allowance, and renewal date visible in Dashboard → Usage.
+Manage AI provider connections: OAuth providers (Claude Code, Codex, Gemini CLI), API key providers (Groq, DeepSeek, OpenRouter), and free providers (Qoder, Qwen, Kiro). Kiro accounts include credit balance tracking — remaining credits, total allowance, and renewal date visible in Dashboard → Usage.

diff --git a/docs/i18n/es/docs/MCP-SERVER.md b/docs/i18n/es/docs/MCP-SERVER.md
new file mode 100644
index 0000000000..822bdf14eb
--- /dev/null
+++ b/docs/i18n/es/docs/MCP-SERVER.md
@@ -0,0 +1,87 @@
+# OmniRoute MCP Server Documentation (Español)
+
+🌐 **Languages:** 🇺🇸 [English](../../../../docs/MCP-SERVER.md) · 🇪🇸 [es](../../es/docs/MCP-SERVER.md) · 🇫🇷 [fr](../../fr/docs/MCP-SERVER.md) · 🇩🇪 [de](../../de/docs/MCP-SERVER.md) · 🇮🇹 [it](../../it/docs/MCP-SERVER.md) · 🇷🇺 [ru](../../ru/docs/MCP-SERVER.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/MCP-SERVER.md) · 🇯🇵 [ja](../../ja/docs/MCP-SERVER.md) · 🇰🇷 [ko](../../ko/docs/MCP-SERVER.md) · 🇸🇦 [ar](../../ar/docs/MCP-SERVER.md) · 🇮🇳 [in](../../in/docs/MCP-SERVER.md) · 🇹🇭 [th](../../th/docs/MCP-SERVER.md) · 🇻🇳 [vi](../../vi/docs/MCP-SERVER.md) · 🇮🇩 [id](../../id/docs/MCP-SERVER.md) · 🇲🇾 [ms](../../ms/docs/MCP-SERVER.md) · 🇳🇱 [nl](../../nl/docs/MCP-SERVER.md) · 🇵🇱 [pl](../../pl/docs/MCP-SERVER.md) · 🇸🇪 [sv](../../sv/docs/MCP-SERVER.md) · 🇳🇴 [no](../../no/docs/MCP-SERVER.md) · 🇩🇰 [da](../../da/docs/MCP-SERVER.md) · 🇫🇮 [fi](../../fi/docs/MCP-SERVER.md) · 🇵🇹 [pt](../../pt/docs/MCP-SERVER.md) · 🇷🇴 [ro](../../ro/docs/MCP-SERVER.md) · 🇭🇺 [hu](../../hu/docs/MCP-SERVER.md) · 🇧🇬 [bg](../../bg/docs/MCP-SERVER.md) · 🇸🇰 [sk](../../sk/docs/MCP-SERVER.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/MCP-SERVER.md) · 🇮🇱 [he](../../he/docs/MCP-SERVER.md) · 🇵🇭 [phi](../../phi/docs/MCP-SERVER.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/MCP-SERVER.md) · 🇨🇿 [cs](../../cs/docs/MCP-SERVER.md)
+
+---
+
+> Model Context Protocol server with 16 intelligent tools
+
+## Instalar
+
+OmniRoute MCP is built-in. Start it with:
+
+```bash
+omniroute --mcp
+```
+
+Or via the open-sse transport:
+
+```bash
+# HTTP streamable transport (port 20130)
+omniroute --dev # MCP auto-starts on /mcp endpoint
+```
+
+## IDE Configuration
+
+See [IDE Configs](integrations/ide-configs.md) for Antigravity, Cursor, Copilot, and Claude Desktop setup.
+
+---
+
+## Essential Tools (8)
+
+| Tool | Description |
+| :------------------------------ | :--------------------------------------- |
+| `omniroute_get_health` | Gateway health, circuit breakers, uptime |
+| `omniroute_list_combos` | All configured combos with models |
+| `omniroute_get_combo_metrics` | Performance metrics for a specific combo |
+| `omniroute_switch_combo` | Switch active combo by ID/name |
+| `omniroute_check_quota` | Quota status per provider or all |
+| `omniroute_route_request` | Send a chat completion through OmniRoute |
+| `omniroute_cost_report` | Cost analytics for a time period |
+| `omniroute_list_models_catalog` | Full model catalog with capabilities |
+
+## Advanced Tools (8)
+
+| Tool | Description |
+| :--------------------------------- | :---------------------------------------------------------- |
+| `omniroute_simulate_route` | Dry-run routing simulation with fallback tree |
+| `omniroute_set_budget_guard` | Session budget with degrade/block/alert actions |
+| `omniroute_set_resilience_profile` | Apply conservative/balanced/aggressive preset |
+| `omniroute_test_combo` | Live-test all models in a combo via a real upstream request |
+| `omniroute_get_provider_metrics` | Detailed metrics for one provider |
+| `omniroute_best_combo_for_task` | Task-fitness recommendation with alternatives |
+| `omniroute_explain_route` | Explain a past routing decision |
+| `omniroute_get_session_snapshot` | Full session state: costs, tokens, errors |
+
+## Authentication
+
+MCP tools are authenticated via API key scopes. Each tool requires specific scopes:
+
+| Scope | Tools |
+| :------------- | :----------------------------------------------- |
+| `read:health` | get_health, get_provider_metrics |
+| `read:combos` | list_combos, get_combo_metrics |
+| `write:combos` | switch_combo |
+| `read:quota` | check_quota |
+| `write:route` | route_request, simulate_route, test_combo |
+| `read:usage` | cost_report, get_session_snapshot, explain_route |
+| `write:config` | set_budget_guard, set_resilience_profile |
+| `read:models` | list_models_catalog, best_combo_for_task |
+
+## Audit Logging
+
+Every tool call is logged to `mcp_tool_audit` with:
+
+- Tool name, arguments, result
+- Duration (ms), success/failure
+- API key hash, timestamp
+
+## Files
+
+| File | Purpose |
+| :------------------------------------------- | :------------------------------------------ |
+| `open-sse/mcp-server/server.ts` | MCP server creation + 16 tool registrations |
+| `open-sse/mcp-server/transport.ts` | Stdio + HTTP transport |
+| `open-sse/mcp-server/auth.ts` | API key + scope validation |
+| `open-sse/mcp-server/audit.ts` | Tool call audit logging |
+| `open-sse/mcp-server/tools/advancedTools.ts` | 8 advanced tool handlers |
diff --git a/docs/i18n/es/docs/RELEASE_CHECKLIST.md b/docs/i18n/es/docs/RELEASE_CHECKLIST.md
new file mode 100644
index 0000000000..d0964eabda
--- /dev/null
+++ b/docs/i18n/es/docs/RELEASE_CHECKLIST.md
@@ -0,0 +1,37 @@
+# Release Checklist (Español)
+
+🌐 **Languages:** 🇺🇸 [English](../../../../docs/RELEASE_CHECKLIST.md) · 🇪🇸 [es](../../es/docs/RELEASE_CHECKLIST.md) · 🇫🇷 [fr](../../fr/docs/RELEASE_CHECKLIST.md) · 🇩🇪 [de](../../de/docs/RELEASE_CHECKLIST.md) · 🇮🇹 [it](../../it/docs/RELEASE_CHECKLIST.md) · 🇷🇺 [ru](../../ru/docs/RELEASE_CHECKLIST.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/RELEASE_CHECKLIST.md) · 🇯🇵 [ja](../../ja/docs/RELEASE_CHECKLIST.md) · 🇰🇷 [ko](../../ko/docs/RELEASE_CHECKLIST.md) · 🇸🇦 [ar](../../ar/docs/RELEASE_CHECKLIST.md) · 🇮🇳 [in](../../in/docs/RELEASE_CHECKLIST.md) · 🇹🇭 [th](../../th/docs/RELEASE_CHECKLIST.md) · 🇻🇳 [vi](../../vi/docs/RELEASE_CHECKLIST.md) · 🇮🇩 [id](../../id/docs/RELEASE_CHECKLIST.md) · 🇲🇾 [ms](../../ms/docs/RELEASE_CHECKLIST.md) · 🇳🇱 [nl](../../nl/docs/RELEASE_CHECKLIST.md) · 🇵🇱 [pl](../../pl/docs/RELEASE_CHECKLIST.md) · 🇸🇪 [sv](../../sv/docs/RELEASE_CHECKLIST.md) · 🇳🇴 [no](../../no/docs/RELEASE_CHECKLIST.md) · 🇩🇰 [da](../../da/docs/RELEASE_CHECKLIST.md) · 🇫🇮 [fi](../../fi/docs/RELEASE_CHECKLIST.md) · 🇵🇹 [pt](../../pt/docs/RELEASE_CHECKLIST.md) · 🇷🇴 [ro](../../ro/docs/RELEASE_CHECKLIST.md) · 🇭🇺 [hu](../../hu/docs/RELEASE_CHECKLIST.md) · 🇧🇬 [bg](../../bg/docs/RELEASE_CHECKLIST.md) · 🇸🇰 [sk](../../sk/docs/RELEASE_CHECKLIST.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/RELEASE_CHECKLIST.md) · 🇮🇱 [he](../../he/docs/RELEASE_CHECKLIST.md) · 🇵🇭 [phi](../../phi/docs/RELEASE_CHECKLIST.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/RELEASE_CHECKLIST.md) · 🇨🇿 [cs](../../cs/docs/RELEASE_CHECKLIST.md)
+
+---
+
+Use this checklist before tagging or publishing a new OmniRoute release.
+
+## Version and Changelog
+
+1. Bump `package.json` version (`x.y.z`) in the release branch.
+2. Move release notes from `## [Unreleased]` in `CHANGELOG.md` to a dated section:
+ - `## [x.y.z] — YYYY-MM-DD`
+3. Keep `## [Unreleased]` as the first changelog section for upcoming work.
+4. Ensure the latest semver section in `CHANGELOG.md` equals `package.json` version.
+
+## API Docs
+
+1. Update `docs/openapi.yaml`:
+ - `info.version` must equal `package.json` version.
+2. Validate endpoint examples if API contracts changed.
+
+## Runtime Docs
+
+1. Review `docs/ARCHITECTURE.md` for storage/runtime drift.
+2. Review `docs/TROUBLESHOOTING.md` for env var and operational drift.
+3. Update localized docs if source docs changed significantly.
+
+## Automated Check
+
+Run the sync guard locally before opening PR:
+
+```bash
+npm run check:docs-sync
+```
+
+CI also runs this check in `.github/workflows/ci.yml` (lint job).
diff --git a/docs/i18n/es/docs/TROUBLESHOOTING.md b/docs/i18n/es/docs/TROUBLESHOOTING.md
new file mode 100644
index 0000000000..6ec65ff780
--- /dev/null
+++ b/docs/i18n/es/docs/TROUBLESHOOTING.md
@@ -0,0 +1,256 @@
+# Troubleshooting (Español)
+
+🌐 **Languages:** 🇺🇸 [English](../../../../docs/TROUBLESHOOTING.md) · 🇪🇸 [es](../../es/docs/TROUBLESHOOTING.md) · 🇫🇷 [fr](../../fr/docs/TROUBLESHOOTING.md) · 🇩🇪 [de](../../de/docs/TROUBLESHOOTING.md) · 🇮🇹 [it](../../it/docs/TROUBLESHOOTING.md) · 🇷🇺 [ru](../../ru/docs/TROUBLESHOOTING.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/TROUBLESHOOTING.md) · 🇯🇵 [ja](../../ja/docs/TROUBLESHOOTING.md) · 🇰🇷 [ko](../../ko/docs/TROUBLESHOOTING.md) · 🇸🇦 [ar](../../ar/docs/TROUBLESHOOTING.md) · 🇮🇳 [in](../../in/docs/TROUBLESHOOTING.md) · 🇹🇭 [th](../../th/docs/TROUBLESHOOTING.md) · 🇻🇳 [vi](../../vi/docs/TROUBLESHOOTING.md) · 🇮🇩 [id](../../id/docs/TROUBLESHOOTING.md) · 🇲🇾 [ms](../../ms/docs/TROUBLESHOOTING.md) · 🇳🇱 [nl](../../nl/docs/TROUBLESHOOTING.md) · 🇵🇱 [pl](../../pl/docs/TROUBLESHOOTING.md) · 🇸🇪 [sv](../../sv/docs/TROUBLESHOOTING.md) · 🇳🇴 [no](../../no/docs/TROUBLESHOOTING.md) · 🇩🇰 [da](../../da/docs/TROUBLESHOOTING.md) · 🇫🇮 [fi](../../fi/docs/TROUBLESHOOTING.md) · 🇵🇹 [pt](../../pt/docs/TROUBLESHOOTING.md) · 🇷🇴 [ro](../../ro/docs/TROUBLESHOOTING.md) · 🇭🇺 [hu](../../hu/docs/TROUBLESHOOTING.md) · 🇧🇬 [bg](../../bg/docs/TROUBLESHOOTING.md) · 🇸🇰 [sk](../../sk/docs/TROUBLESHOOTING.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/TROUBLESHOOTING.md) · 🇮🇱 [he](../../he/docs/TROUBLESHOOTING.md) · 🇵🇭 [phi](../../phi/docs/TROUBLESHOOTING.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/TROUBLESHOOTING.md) · 🇨🇿 [cs](../../cs/docs/TROUBLESHOOTING.md)
+
+---
+
+Common problems and solutions for OmniRoute.
+
+---
+
+## Quick Fixes
+
+| Problem | Solution |
+| ----------------------------- | ------------------------------------------------------------------ |
+| First login not working | Set `INITIAL_PASSWORD` in `.env` (no hardcoded default) |
+| Dashboard opens on wrong port | Set `PORT=20128` and `NEXT_PUBLIC_BASE_URL=http://localhost:20128` |
+| No request logs under `logs/` | Set `ENABLE_REQUEST_LOGS=true` |
+| EACCES: permission denied | Set `DATA_DIR=/path/to/writable/dir` to override `~/.omniroute` |
+| Routing strategy not saving | Update to v1.4.11+ (Zod schema fix for settings persistence) |
+
+---
+
+## Provider Issues
+
+### "Language model did not provide messages"
+
+**Cause:** Provider quota exhausted.
+
+**Fix:**
+
+1. Check dashboard quota tracker
+2. Use a combo with fallback tiers
+3. Switch to cheaper/free tier
+
+### Rate Limiting
+
+**Cause:** Subscription quota exhausted.
+
+**Fix:**
+
+- Add fallback: `cc/claude-opus-4-6 → glm/glm-4.7 → if/kimi-k2-thinking`
+- Use GLM/MiniMax as cheap backup
+
+### OAuth Token Expired
+
+OmniRoute auto-refreshes tokens. If issues persist:
+
+1. Dashboard → Provider → Reconnect
+2. Delete and re-add the provider connection
+
+---
+
+## Cloud Issues
+
+### Cloud Sync Errors
+
+1. Verify `BASE_URL` points to your running instance (e.g., `http://localhost:20128`)
+2. Verify `CLOUD_URL` points to your cloud endpoint (e.g., `https://omniroute.dev`)
+3. Keep `NEXT_PUBLIC_*` values aligned with server-side values
+
+### Cloud `stream=false` Returns 500
+
+**Symptom:** `Unexpected token 'd'...` on cloud endpoint for non-streaming calls.
+
+**Cause:** Upstream returns SSE payload while client expects JSON.
+
+**Workaround:** Use `stream=true` for cloud direct calls. Local runtime includes SSE→JSON fallback.
+
+### Cloud Says Connected but "Invalid API key"
+
+1. Create a fresh key from local dashboard (`/api/keys`)
+2. Run cloud sync: Enable Cloud → Sync Now
+3. Old/non-synced keys can still return `401` on cloud
+
+---
+
+## Docker Issues
+
+### CLI Tool Shows Not Installed
+
+1. Check runtime fields: `curl http://localhost:20128/api/cli-tools/runtime/codex | jq`
+2. For portable mode: use image target `runner-cli` (bundled CLIs)
+3. For host mount mode: set `CLI_EXTRA_PATHS` and mount host bin directory as read-only
+4. If `installed=true` and `runnable=false`: binary was found but failed healthcheck
+
+### Quick Runtime Validation
+
+```bash
+curl -s http://localhost:20128/api/cli-tools/codex-settings | jq '{installed,runnable,commandPath,runtimeMode,reason}'
+curl -s http://localhost:20128/api/cli-tools/claude-settings | jq '{installed,runnable,commandPath,runtimeMode,reason}'
+curl -s http://localhost:20128/api/cli-tools/openclaw-settings | jq '{installed,runnable,commandPath,runtimeMode,reason}'
+```
+
+---
+
+## Cost Issues
+
+### High Costs
+
+1. Check usage stats in Dashboard → Usage
+2. Switch primary model to GLM/MiniMax
+3. Use free tier (Gemini CLI, Qoder) for non-critical tasks
+4. Set cost budgets per API key: Dashboard → API Keys → Budget
+
+---
+
+## Debugging
+
+### Enable Request Logs
+
+Set `ENABLE_REQUEST_LOGS=true` in your `.env` file. Logs appear under `logs/` directory.
+
+### Check Provider Health
+
+```bash
+# Health dashboard
+http://localhost:20128/dashboard/health
+
+# API health check
+curl http://localhost:20128/api/monitoring/health
+```
+
+### Runtime Storage
+
+- Main state: `${DATA_DIR}/storage.sqlite` (providers, combos, aliases, keys, settings)
+- Usage: SQLite tables in `storage.sqlite` (`usage_history`, `call_logs`, `proxy_logs`) + optional `${DATA_DIR}/log.txt` and `${DATA_DIR}/call_logs/`
+- Request logs: `/logs/...` (when `ENABLE_REQUEST_LOGS=true`)
+
+---
+
+## Circuit Breaker Issues
+
+### Provider stuck in OPEN state
+
+When a provider's circuit breaker is OPEN, requests are blocked until the cooldown expires.
+
+**Fix:**
+
+1. Go to **Dashboard → Settings → Resilience**
+2. Check the circuit breaker card for the affected provider
+3. Click **Reset All** to clear all breakers, or wait for the cooldown to expire
+4. Verify the provider is actually available before resetting
+
+### Provider keeps tripping the circuit breaker
+
+If a provider repeatedly enters OPEN state:
+
+1. Check **Dashboard → Health → Provider Health** for the failure pattern
+2. Go to **Settings → Resilience → Provider Profiles** and increase the failure threshold
+3. Check if the provider has changed API limits or requires re-authentication
+4. Review latency telemetry — high latency may cause timeout-based failures
+
+---
+
+## Audio Transcription Issues
+
+### "Unsupported model" error
+
+- Ensure you're using the correct prefix: `deepgram/nova-3` or `assemblyai/best`
+- Verify the provider is connected in **Dashboard → Providers**
+
+### Transcription returns empty or fails
+
+- Check supported audio formats: `mp3`, `wav`, `m4a`, `flac`, `ogg`, `webm`
+- Verify file size is within provider limits (typically < 25MB)
+- Check provider API key validity in the provider card
+
+---
+
+## Translator Debugging
+
+Use **Dashboard → Translator** to debug format translation issues:
+
+| Mode | When to Use |
+| ---------------- | -------------------------------------------------------------------------------------------- |
+| **Playground** | Compare input/output formats side by side — paste a failing request to see how it translates |
+| **Chat Tester** | Send live messages and inspect the full request/response payload including headers |
+| **Test Bench** | Run batch tests across format combinations to find which translations are broken |
+| **Live Monitor** | Watch real-time request flow to catch intermittent translation issues |
+
+### Common format issues
+
+- **Thinking tags not appearing** — Check if the target provider supports thinking and the thinking budget setting
+- **Tool calls dropping** — Some format translations may strip unsupported fields; verify in Playground mode
+- **System prompt missing** — Claude and Gemini handle system prompts differently; check translation output
+- **SDK returns raw string instead of object** — Fixed in v1.1.0: response sanitizer now strips non-standard fields (`x_groq`, `usage_breakdown`, etc.) that cause OpenAI SDK Pydantic validation failures
+- **GLM/ERNIE rejects `system` role** — Fixed in v1.1.0: role normalizer automatically merges system messages into user messages for incompatible models
+- **`developer` role not recognized** — Fixed in v1.1.0: automatically converted to `system` for non-OpenAI providers
+- **`json_schema` not working with Gemini** — Fixed in v1.1.0: `response_format` is now converted to Gemini's `responseMimeType` + `responseSchema`
+
+---
+
+## Resilience Settings
+
+### Auto rate-limit not triggering
+
+- Auto rate-limit only applies to API key providers (not OAuth/subscription)
+- Verify **Settings → Resilience → Provider Profiles** has auto-rate-limit enabled
+- Check if the provider returns `429` status codes or `Retry-After` headers
+
+### Tuning exponential backoff
+
+Provider profiles support these settings:
+
+- **Base delay** — Initial wait time after first failure (default: 1s)
+- **Max delay** — Maximum wait time cap (default: 30s)
+- **Multiplier** — How much to increase delay per consecutive failure (default: 2x)
+
+### Anti-thundering herd
+
+When many concurrent requests hit a rate-limited provider, OmniRoute uses mutex + auto rate-limiting to serialize requests and prevent cascading failures. This is automatic for API key providers.
+
+---
+
+## Optional RAG / LLM failure taxonomy (16 problems)
+
+Some OmniRoute users place the gateway in front of RAG or agent stacks. In those setups it is common to see a strange pattern: OmniRoute looks healthy (providers up, routing profiles ok, no rate limit alerts) but the final answer is still wrong.
+
+In practice these incidents usually come from the downstream RAG pipeline, not from the gateway itself.
+
+If you want a shared vocabulary to describe those failures you can use the WFGY ProblemMap, an external MIT license text resource that defines sixteen recurring RAG / LLM failure patterns. At a high level it covers:
+
+- retrieval drift and broken context boundaries
+- empty or stale indexes and vector stores
+- embedding versus semantic mismatch
+- prompt assembly and context window issues
+- logic collapse and overconfident answers
+- long chain and agent coordination failures
+- multi agent memory and role drift
+- deployment and bootstrap ordering problems
+
+The idea is simple:
+
+1. When you investigate a bad response, capture:
+ - user task and request
+ - route or provider combo in OmniRoute
+ - any RAG context used downstream (retrieved documents, tool calls, etc)
+2. Map the incident to one or two WFGY ProblemMap numbers (`No.1` … `No.16`).
+3. Store the number in your own dashboard, runbook, or incident tracker next to the OmniRoute logs.
+4. Use the corresponding WFGY page to decide whether you need to change your RAG stack, retriever, or routing strategy.
+
+Full text and concrete recipes live here (MIT license, text only):
+
+[WFGY ProblemMap README](https://github.com/onestardao/WFGY/blob/main/ProblemMap/README.md)
+
+You can ignore this section if you do not run RAG or agent pipelines behind OmniRoute.
+
+---
+
+## Still Stuck?
+
+- **GitHub Issues**: [github.com/diegosouzapw/OmniRoute/issues](https://github.com/diegosouzapw/OmniRoute/issues)
+- **Architecture**: See [`docs/ARCHITECTURE.md`](ARCHITECTURE.md) for internal details
+- **API Reference**: See [`docs/API_REFERENCE.md`](API_REFERENCE.md) for all endpoints
+- **Health Dashboard**: Check **Dashboard → Health** for real-time system status
+- **Translator**: Use **Dashboard → Translator** to debug format issues
diff --git a/docs/i18n/es/USER_GUIDE.md b/docs/i18n/es/docs/USER_GUIDE.md
similarity index 82%
rename from docs/i18n/es/USER_GUIDE.md
rename to docs/i18n/es/docs/USER_GUIDE.md
index 89023b75bb..668cae9c29 100644
--- a/docs/i18n/es/USER_GUIDE.md
+++ b/docs/i18n/es/docs/USER_GUIDE.md
@@ -1,8 +1,6 @@
# User Guide (Español)
-🌐 **Languages:** 🇺🇸 [English](../../USER_GUIDE.md) · 🇧🇷 [pt-BR](../pt-BR/USER_GUIDE.md) · 🇪🇸 [es](../es/USER_GUIDE.md) · 🇫🇷 [fr](../fr/USER_GUIDE.md) · 🇩🇪 [de](../de/USER_GUIDE.md) · 🇮🇹 [it](../it/USER_GUIDE.md) · 🇷🇺 [ru](../ru/USER_GUIDE.md) · 🇨🇳 [zh-CN](../zh-CN/USER_GUIDE.md) · 🇯🇵 [ja](../ja/USER_GUIDE.md) · 🇰🇷 [ko](../ko/USER_GUIDE.md) · 🇸🇦 [ar](../ar/USER_GUIDE.md) · 🇮🇳 [in](../in/USER_GUIDE.md) · 🇹🇭 [th](../th/USER_GUIDE.md) · 🇻🇳 [vi](../vi/USER_GUIDE.md) · 🇮🇩 [id](../id/USER_GUIDE.md) · 🇲🇾 [ms](../ms/USER_GUIDE.md) · 🇳🇱 [nl](../nl/USER_GUIDE.md) · 🇵🇱 [pl](../pl/USER_GUIDE.md) · 🇸🇪 [sv](../sv/USER_GUIDE.md) · 🇳🇴 [no](../no/USER_GUIDE.md) · 🇩🇰 [da](../da/USER_GUIDE.md) · 🇫🇮 [fi](../fi/USER_GUIDE.md) · 🇵🇹 [pt](../pt/USER_GUIDE.md) · 🇷🇴 [ro](../ro/USER_GUIDE.md) · 🇭🇺 [hu](../hu/USER_GUIDE.md) · 🇧🇬 [bg](../bg/USER_GUIDE.md) · 🇸🇰 [sk](../sk/USER_GUIDE.md) · 🇺🇦 [uk-UA](../uk-UA/USER_GUIDE.md) · 🇮🇱 [he](../he/USER_GUIDE.md) · 🇵🇭 [phi](../phi/USER_GUIDE.md)
-
-> 🇺🇸 [English](../../USER_GUIDE.md)
+🌐 **Languages:** 🇺🇸 [English](../../../../docs/USER_GUIDE.md) · 🇪🇸 [es](../../es/docs/USER_GUIDE.md) · 🇫🇷 [fr](../../fr/docs/USER_GUIDE.md) · 🇩🇪 [de](../../de/docs/USER_GUIDE.md) · 🇮🇹 [it](../../it/docs/USER_GUIDE.md) · 🇷🇺 [ru](../../ru/docs/USER_GUIDE.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/USER_GUIDE.md) · 🇯🇵 [ja](../../ja/docs/USER_GUIDE.md) · 🇰🇷 [ko](../../ko/docs/USER_GUIDE.md) · 🇸🇦 [ar](../../ar/docs/USER_GUIDE.md) · 🇮🇳 [in](../../in/docs/USER_GUIDE.md) · 🇹🇭 [th](../../th/docs/USER_GUIDE.md) · 🇻🇳 [vi](../../vi/docs/USER_GUIDE.md) · 🇮🇩 [id](../../id/docs/USER_GUIDE.md) · 🇲🇾 [ms](../../ms/docs/USER_GUIDE.md) · 🇳🇱 [nl](../../nl/docs/USER_GUIDE.md) · 🇵🇱 [pl](../../pl/docs/USER_GUIDE.md) · 🇸🇪 [sv](../../sv/docs/USER_GUIDE.md) · 🇳🇴 [no](../../no/docs/USER_GUIDE.md) · 🇩🇰 [da](../../da/docs/USER_GUIDE.md) · 🇫🇮 [fi](../../fi/docs/USER_GUIDE.md) · 🇵🇹 [pt](../../pt/docs/USER_GUIDE.md) · 🇷🇴 [ro](../../ro/docs/USER_GUIDE.md) · 🇭🇺 [hu](../../hu/docs/USER_GUIDE.md) · 🇧🇬 [bg](../../bg/docs/USER_GUIDE.md) · 🇸🇰 [sk](../../sk/docs/USER_GUIDE.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/USER_GUIDE.md) · 🇮🇱 [he](../../he/docs/USER_GUIDE.md) · 🇵🇭 [phi](../../phi/docs/USER_GUIDE.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/USER_GUIDE.md) · 🇨🇿 [cs](../../cs/docs/USER_GUIDE.md)
---
@@ -320,7 +318,7 @@ Model: cc/claude-opus-4-6
---
-## 🚀 Deployment
+## Despliegue
### Global npm install (Recommended)
@@ -511,23 +509,26 @@ post_install() {
### Environment Variables
-| Variable | Default | Description |
-| ------------------------- | ------------------------------------ | ------------------------------------------------------- |
-| `JWT_SECRET` | `omniroute-default-secret-change-me` | JWT signing secret (**change in production**) |
-| `INITIAL_PASSWORD` | `123456` | First login password |
-| `DATA_DIR` | `~/.omniroute` | Data directory (db, usage, logs) |
-| `PORT` | framework default | Service port (`20128` in examples) |
-| `HOSTNAME` | framework default | Bind host (Docker defaults to `0.0.0.0`) |
-| `NODE_ENV` | runtime default | Set `production` for deploy |
-| `BASE_URL` | `http://localhost:20128` | Server-side internal base URL |
-| `CLOUD_URL` | `https://omniroute.dev` | Cloud sync endpoint base URL |
-| `API_KEY_SECRET` | `endpoint-proxy-api-key-secret` | HMAC secret for generated API keys |
-| `REQUIRE_API_KEY` | `false` | Enforce Bearer API key on `/v1/*` |
-| `ENABLE_REQUEST_LOGS` | `false` | Enables request/response logs |
-| `AUTH_COOKIE_SECURE` | `false` | Force `Secure` auth cookie (behind HTTPS reverse proxy) |
-| `OMNIROUTE_MEMORY_MB` | `512` | Node.js heap limit in MB |
-| `PROMPT_CACHE_MAX_SIZE` | `50` | Max prompt cache entries |
-| `SEMANTIC_CACHE_MAX_SIZE` | `100` | Max semantic cache entries |
+| Variable | Default | Description |
+| ---------------------------- | ------------------------------------ | ------------------------------------------------------------------------------------------ |
+| `JWT_SECRET` | `omniroute-default-secret-change-me` | JWT signing secret (**change in production**) |
+| `INITIAL_PASSWORD` | `123456` | First login password |
+| `DATA_DIR` | `~/.omniroute` | Data directory (db, usage, logs) |
+| `PORT` | framework default | Service port (`20128` in examples) |
+| `HOSTNAME` | framework default | Bind host (Docker defaults to `0.0.0.0`) |
+| `NODE_ENV` | runtime default | Set `production` for deploy |
+| `BASE_URL` | `http://localhost:20128` | Server-side internal base URL |
+| `CLOUD_URL` | `https://omniroute.dev` | Cloud sync endpoint base URL |
+| `API_KEY_SECRET` | `endpoint-proxy-api-key-secret` | HMAC secret for generated API keys |
+| `REQUIRE_API_KEY` | `false` | Enforce Bearer API key on `/v1/*` |
+| `ALLOW_API_KEY_REVEAL` | `false` | Allow Api Manager to copy full API keys on demand |
+| `DISABLE_SQLITE_AUTO_BACKUP` | `false` | Disable automatic SQLite snapshots before writes/import/restore; manual backups still work |
+| `ENABLE_REQUEST_LOGS` | `false` | Enables request/response logs |
+| `AUTH_COOKIE_SECURE` | `false` | Force `Secure` auth cookie (behind HTTPS reverse proxy) |
+| `CLOUDFLARED_BIN` | unset | Use an existing `cloudflared` binary instead of managed download |
+| `OMNIROUTE_MEMORY_MB` | `512` | Node.js heap limit in MB |
+| `PROMPT_CACHE_MAX_SIZE` | `50` | Max prompt cache entries |
+| `SEMANTIC_CACHE_MAX_SIZE` | `100` | Max semantic cache entries |
For the full environment variable reference, see the [README](../README.md).
@@ -598,6 +599,11 @@ curl -X POST http://localhost:20128/api/provider-models \
Or use Dashboard: **Providers → [Provider] → Custom Models**.
+Notes:
+
+- OpenRouter and OpenAI/Anthropic-compatible providers are managed from **Available Models** only. Manual add, import, and auto-sync all land in the same available-model list, so there is no separate Custom Models section for those providers.
+- The **Custom Models** section is intended for providers that do not expose managed available-model imports.
+
### Dedicated Provider Routes
Route requests directly to a specific provider with model validation:
@@ -642,6 +648,14 @@ Returns models grouped by provider with types (`chat`, `embedding`, `image`).
- Automatic background sync with timeout + fail-fast
- Prefer server-side `BASE_URL`/`CLOUD_URL` in production
+### Cloudflare Quick Tunnel
+
+- Available in **Dashboard → Endpoints** for Docker and other self-hosted deployments
+- Creates a temporary `https://*.trycloudflare.com` URL that forwards to your current OpenAI-compatible `/v1` endpoint
+- First enable installs `cloudflared` only when needed; later restarts reuse the same managed binary
+- Tunnel URLs are ephemeral and change every time you stop/start the tunnel
+- Set `CLOUDFLARED_BIN` if you prefer using a preinstalled `cloudflared` binary instead of the managed download
+
### LLM Gateway Intelligence (Phase 9)
- **Semantic Cache** — Auto-caches non-streaming, temperature=0 responses (bypass with `X-OmniRoute-No-Cache: true`)
@@ -757,11 +771,11 @@ OmniRoute implements provider-level resilience with four components:
Manage database backups in **Dashboard → Settings → System & Storage**.
-| Action | Description |
-| ------------------------ | ------------------------------------------------------------------------------------------------------------------------------ |
-| **Export Database** | Downloads the current SQLite database as a `.sqlite` file |
-| **Export All (.tar.gz)** | Downloads a full backup archive including: database, settings, combos, provider connections (no credentials), API key metadata |
-| **Import Database** | Upload a `.sqlite` file to replace the current database. A pre-import backup is automatically created |
+| Action | Description |
+| ------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------- |
+| **Export Database** | Downloads the current SQLite database as a `.sqlite` file |
+| **Export All (.tar.gz)** | Downloads a full backup archive including: database, settings, combos, provider connections (no credentials), API key metadata |
+| **Import Database** | Upload a `.sqlite` file to replace the current database. A pre-import backup is automatically created unless `DISABLE_SQLITE_AUTO_BACKUP=true` |
```bash
# API: Export database
@@ -787,10 +801,11 @@ curl -X POST http://localhost:20128/api/db-backups/import \
### Settings Dashboard
-The settings page is organized into 5 tabs for easy navigation:
+The settings page is organized into 6 tabs for easy navigation:
| Tab | Contents |
| -------------- | ---------------------------------------------------------------------------------------------- |
+| **General** | System storage tools, appearance settings, theme controls, and per-item sidebar visibility |
| **Security** | Login/Password settings, IP Access Control, API auth for `/models`, and Provider Blocking |
| **Routing** | Global routing strategy (6 options), wildcard model aliases, fallback chains, combo defaults |
| **Resilience** | Provider profiles, editable rate limits, circuit breaker status, policies & locked identifiers |
diff --git a/docs/i18n/no/VM_DEPLOYMENT_GUIDE.md b/docs/i18n/es/docs/VM_DEPLOYMENT_GUIDE.md
similarity index 58%
rename from docs/i18n/no/VM_DEPLOYMENT_GUIDE.md
rename to docs/i18n/es/docs/VM_DEPLOYMENT_GUIDE.md
index a4067dc9ce..a6e66d22a8 100644
--- a/docs/i18n/no/VM_DEPLOYMENT_GUIDE.md
+++ b/docs/i18n/es/docs/VM_DEPLOYMENT_GUIDE.md
@@ -1,50 +1,52 @@
-# OmniRoute — Implementeringsveiledning på VM med Cloudflare
+# OmniRoute — Deployment Guide on VM with Cloudflare (Español)
-🌐 **Languages:** 🇺🇸 [English](../../VM_DEPLOYMENT_GUIDE.md) | 🇧🇷 [Português (Brasil)](../pt-BR/VM_DEPLOYMENT_GUIDE.md) | 🇪🇸 [Español](../es/VM_DEPLOYMENT_GUIDE.md) | 🇫🇷 [Français](../fr/VM_DEPLOYMENT_GUIDE.md) | 🇮🇹 [Italiano](../it/VM_DEPLOYMENT_GUIDE.md) | 🇷🇺 [Русский](../ru/VM_DEPLOYMENT_GUIDE.md) | 🇨🇳 [中文 (简体)](../zh-CN/VM_DEPLOYMENT_GUIDE.md) | 🇩🇪 [Deutsch](../de/VM_DEPLOYMENT_GUIDE.md) | 🇮🇳 [हिन्दी](../in/VM_DEPLOYMENT_GUIDE.md) | 🇹🇭 [ไทย](../th/VM_DEPLOYMENT_GUIDE.md) | 🇺🇦 [Українська](../uk-UA/VM_DEPLOYMENT_GUIDE.md) | 🇸🇦 [العربية](../ar/VM_DEPLOYMENT_GUIDE.md) | 🇯🇵 [日本語](../ja/VM_DEPLOYMENT_GUIDE.md) | 🇻🇳 [Tiếng Việt](../vi/VM_DEPLOYMENT_GUIDE.md) | 🇧🇬 [Български](../bg/VM_DEPLOYMENT_GUIDE.md) | 🇩🇰 [Dansk](../da/VM_DEPLOYMENT_GUIDE.md) | 🇫🇮 [Suomi](../fi/VM_DEPLOYMENT_GUIDE.md) | 🇮🇱 [עברית](../he/VM_DEPLOYMENT_GUIDE.md) | 🇭🇺 [Magyar](../hu/VM_DEPLOYMENT_GUIDE.md) | 🇮🇩 [Bahasa Indonesia](../id/VM_DEPLOYMENT_GUIDE.md) | 🇰🇷 [한국어](../ko/VM_DEPLOYMENT_GUIDE.md) | 🇲🇾 [Bahasa Melayu](../ms/VM_DEPLOYMENT_GUIDE.md) | 🇳🇱 [Nederlands](../nl/VM_DEPLOYMENT_GUIDE.md) | 🇳🇴 [Norsk](../no/VM_DEPLOYMENT_GUIDE.md) | 🇵🇹 [Português (Portugal)](../pt/VM_DEPLOYMENT_GUIDE.md) | 🇷🇴 [Română](../ro/VM_DEPLOYMENT_GUIDE.md) | 🇵🇱 [Polski](../pl/VM_DEPLOYMENT_GUIDE.md) | 🇸🇰 [Slovenčina](../sk/VM_DEPLOYMENT_GUIDE.md) | 🇸🇪 [Svenska](../sv/VM_DEPLOYMENT_GUIDE.md) | 🇵🇭 [Filipino](../phi/VM_DEPLOYMENT_GUIDE.md) | 🇨🇿 [Čeština](../cs/VM_DEPLOYMENT_GUIDE.md)
-
-Komplett veiledning for å installere og konfigurere OmniRoute på en VM (VPS) med domene administrert via Cloudflare.
+🌐 **Languages:** 🇺🇸 [English](../../../../docs/VM_DEPLOYMENT_GUIDE.md) · 🇪🇸 [es](../../es/docs/VM_DEPLOYMENT_GUIDE.md) · 🇫🇷 [fr](../../fr/docs/VM_DEPLOYMENT_GUIDE.md) · 🇩🇪 [de](../../de/docs/VM_DEPLOYMENT_GUIDE.md) · 🇮🇹 [it](../../it/docs/VM_DEPLOYMENT_GUIDE.md) · 🇷🇺 [ru](../../ru/docs/VM_DEPLOYMENT_GUIDE.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/VM_DEPLOYMENT_GUIDE.md) · 🇯🇵 [ja](../../ja/docs/VM_DEPLOYMENT_GUIDE.md) · 🇰🇷 [ko](../../ko/docs/VM_DEPLOYMENT_GUIDE.md) · 🇸🇦 [ar](../../ar/docs/VM_DEPLOYMENT_GUIDE.md) · 🇮🇳 [in](../../in/docs/VM_DEPLOYMENT_GUIDE.md) · 🇹🇭 [th](../../th/docs/VM_DEPLOYMENT_GUIDE.md) · 🇻🇳 [vi](../../vi/docs/VM_DEPLOYMENT_GUIDE.md) · 🇮🇩 [id](../../id/docs/VM_DEPLOYMENT_GUIDE.md) · 🇲🇾 [ms](../../ms/docs/VM_DEPLOYMENT_GUIDE.md) · 🇳🇱 [nl](../../nl/docs/VM_DEPLOYMENT_GUIDE.md) · 🇵🇱 [pl](../../pl/docs/VM_DEPLOYMENT_GUIDE.md) · 🇸🇪 [sv](../../sv/docs/VM_DEPLOYMENT_GUIDE.md) · 🇳🇴 [no](../../no/docs/VM_DEPLOYMENT_GUIDE.md) · 🇩🇰 [da](../../da/docs/VM_DEPLOYMENT_GUIDE.md) · 🇫🇮 [fi](../../fi/docs/VM_DEPLOYMENT_GUIDE.md) · 🇵🇹 [pt](../../pt/docs/VM_DEPLOYMENT_GUIDE.md) · 🇷🇴 [ro](../../ro/docs/VM_DEPLOYMENT_GUIDE.md) · 🇭🇺 [hu](../../hu/docs/VM_DEPLOYMENT_GUIDE.md) · 🇧🇬 [bg](../../bg/docs/VM_DEPLOYMENT_GUIDE.md) · 🇸🇰 [sk](../../sk/docs/VM_DEPLOYMENT_GUIDE.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/VM_DEPLOYMENT_GUIDE.md) · 🇮🇱 [he](../../he/docs/VM_DEPLOYMENT_GUIDE.md) · 🇵🇭 [phi](../../phi/docs/VM_DEPLOYMENT_GUIDE.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/VM_DEPLOYMENT_GUIDE.md) · 🇨🇿 [cs](../../cs/docs/VM_DEPLOYMENT_GUIDE.md)
---
-## Forutsetninger
+Complete guide to install and configure OmniRoute on a VM (VPS) with domain managed via Cloudflare.
-| Vare | Minimum | Anbefalt |
+---
+
+## Prerequisites
+
+| Item | Minimum | Recommended |
| ---------- | ------------------------ | ---------------- |
| **CPU** | 1 vCPU | 2 vCPU |
| **RAM** | 1 GB | 2 GB |
| **Disk** | 10 GB SSD | 25 GB SSD |
| **OS** | Ubuntu 22.04 LTS | Ubuntu 24.04 LTS |
-| **Domene** | Registrert på Cloudflare | — |
-| **Dokker** | Docker Engine 24+ | Docker 27+ |
+| **Domain** | Registered on Cloudflare | — |
+| **Docker** | Docker Engine 24+ | Docker 27+ |
-**Testede leverandører**: Akamai (Linode), DigitalOcean, Vultr, Hetzner, AWS Lightsail.
+**Tested providers**: Akamai (Linode), DigitalOcean, Vultr, Hetzner, AWS Lightsail.
---
-## 1. Konfigurer VM
+## 1. Configure the VM
-### 1.1 Opprett forekomsten
+### 1.1 Create the instance
-På din foretrukne VPS-leverandør:
+On your preferred VPS provider:
-- Velg Ubuntu 24.04 LTS
-- Velg minimumsplanen (1 vCPU / 1 GB RAM)
-- Angi et sterkt root-passord eller konfigurer SSH-nøkkel
- – Legg merke til **offentlig IP** (f.eks. `203.0.113.10`)
+- Choose Ubuntu 24.04 LTS
+- Select the minimum plan (1 vCPU / 1 GB RAM)
+- Set a strong root password or configure SSH key
+- Note the **public IP** (e.g., `203.0.113.10`)
-### 1.2 Koble til via SSH
+### 1.2 Connect via SSH
```bash
ssh root@203.0.113.10
```
-### 1.3 Oppdater systemet
+### 1.3 Update the system
```bash
apt update && apt upgrade -y
```
-### 1.4 Installer Docker
+### 1.4 Install Docker
```bash
# Install dependencies
@@ -59,13 +61,13 @@ apt update
apt install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin
```
-### 1.5 Installer nginx
+### 1.5 Install nginx
```bash
apt install -y nginx
```
-### 1.6 Konfigurer brannmur (UFW)
+### 1.6 Configure Firewall (UFW)
```bash
ufw default deny incoming
@@ -76,19 +78,19 @@ ufw allow 443/tcp # HTTPS
ufw enable
```
-> **Tips**: For maksimal sikkerhet, begrense portene 80 og 443 til bare Cloudflare IP-er. Se avsnittet [Advanced Security](#advanced-security).
+> **Tip**: For maximum security, restrict ports 80 and 443 to Cloudflare IPs only. See the [Advanced Security](#advanced-security) section.
---
-## 2. Installer OmniRoute
+## 2. Install OmniRoute
-### 2.1 Opprett konfigurasjonskatalog
+### 2.1 Create configuration directory
```bash
mkdir -p /opt/omniroute
```
-### 2.2 Lag miljøvariabler-fil
+### 2.2 Create environment variables file
```bash
cat > /opt/omniroute/.env << ‘EOF’
@@ -120,9 +122,9 @@ NEXT_PUBLIC_BASE_URL=https://llms.seudominio.com
EOF
```
-> ⚠️ **VIKTIG**: Generer unike hemmelige nøkler! Bruk `openssl rand -hex 32` for hver nøkkel.
+> ⚠️ **IMPORTANT**: Generate unique secret keys! Use `openssl rand -hex 32` for each key.
-### 2.3 Start beholderen
+### 2.3 Start the container
```bash
docker pull diegosouzapw/omniroute:latest
@@ -136,27 +138,27 @@ docker run -d \
diegosouzapw/omniroute:latest
```
-### 2.4 Bekreft at den kjører
+### 2.4 Verify that it is running
```bash
docker ps | grep omniroute
docker logs omniroute --tail 20
```
-Den skal vise: `[DB] SQLite database ready` og `listening on port 20128`.
+It should display: `[DB] SQLite database ready` and `listening on port 20128`.
---
-## 3. Konfigurer nginx (omvendt proxy)
+## 3. Configure nginx (Reverse Proxy)
-### 3.1 Generer SSL-sertifikat (Cloudflare Origin)
+### 3.1 Generate SSL certificate (Cloudflare Origin)
-I Cloudflare-dashbordet:
+In the Cloudflare dashboard:
-1. Gå til **SSL/TLS → Origin Server**
-2. Klikk på **Opprett sertifikat**
-3. Behold standardinnstillingene (15 år, \*.dittdomene.com)
-4. Kopier **opprinnelsessertifikatet** og **privatnøkkelen**
+1. Go to **SSL/TLS → Origin Server**
+2. Click **Create Certificate**
+3. Keep the defaults (15 years, \*.yourdomain.com)
+4. Copy the **Origin Certificate** and the **Private Key**
```bash
mkdir -p /etc/nginx/ssl
@@ -170,7 +172,7 @@ nano /etc/nginx/ssl/origin.key
chmod 600 /etc/nginx/ssl/origin.key
```
-### 3.2 Nginx-konfigurasjon
+### 3.2 Nginx Configuration
```bash
cat > /etc/nginx/sites-available/omniroute << ‘NGINX’
@@ -228,7 +230,7 @@ server {
NGINX
```
-### 3.3 Aktiver og test
+### 3.3 Enable and Test
```bash
# Remove default configuration
@@ -243,27 +245,27 @@ nginx -t && systemctl reload nginx
---
-## 4. Konfigurer Cloudflare DNS
+## 4. Configure Cloudflare DNS
-### 4.1 Legg til DNS-post
+### 4.1 Add DNS record
-I Cloudflare-dashbordet → DNS:
+In the Cloudflare dashboard → DNS:
-| Skriv inn | Navn | Innhold | Fullmakt |
-| --------- | ------ | ---------------------- | ----------- |
-| A | `llms` | `203.0.113.10` (VM IP) | ✅ Fullmakt |
+| Type | Name | Content | Proxy |
+| ---- | ------ | ---------------------- | ---------- |
+| A | `llms` | `203.0.113.10` (VM IP) | ✅ Proxied |
-### 4.2 Konfigurer SSL
+### 4.2 Configure SSL
-Under **SSL/TLS → Oversikt**:
+Under **SSL/TLS → Overview**:
-- Modus: **Full (Streng)**
+- Mode: **Full (Strict)**
Under **SSL/TLS → Edge Certificates**:
-- Bruk alltid HTTPS: ✅ På
-- Minimum TLS-versjon: TLS 1.2
-- Automatiske HTTPS-omskrivinger: ✅ På
+- Always Use HTTPS: ✅ On
+- Minimum TLS Version: TLS 1.2
+- Automatic HTTPS Rewrites: ✅ On
### 4.3 Testing
@@ -274,9 +276,9 @@ curl -sI https://llms.seudominio.com/health
---
-## 5. Drift og vedlikehold
+## 5. Operations and Maintenance
-### Oppgrader til en ny versjon
+### Upgrade to a new version
```bash
docker pull diegosouzapw/omniroute:latest
@@ -288,14 +290,14 @@ docker run -d --name omniroute --restart unless-stopped \
diegosouzapw/omniroute:latest
```
-### Vis logger
+### View logs
```bash
docker logs -f omniroute # Real-time stream
docker logs omniroute --tail 50 # Last 50 lines
```
-### Manuell sikkerhetskopiering av database
+### Manual database backup
```bash
# Copy data from the volume to the host
@@ -306,7 +308,7 @@ docker run --rm -v omniroute-data:/data -v $(pwd):/backup \
alpine tar czf /backup/omniroute-data-$(date +%F).tar.gz /data
```
-### Gjenopprett fra sikkerhetskopi
+### Restore from backup
```bash
docker stop omniroute
@@ -317,9 +319,9 @@ docker start omniroute
---
-## 6. Avansert sikkerhet
+## 6. Advanced Security
-### Begrens nginx til Cloudflare IP-er
+### Restrict nginx to Cloudflare IPs
```bash
cat > /etc/nginx/cloudflare-ips.conf << ‘CF’
@@ -344,13 +346,13 @@ real_ip_header CF-Connecting-IP;
CF
```
-Legg til følgende til `nginx.conf` inne i `http {}`-blokken:
+Add the following to `nginx.conf` inside the `http {}` block:
```nginx
include /etc/nginx/cloudflare-ips.conf;
```
-### Installer fail2ban
+### Install fail2ban
```bash
apt install -y fail2ban
@@ -361,7 +363,7 @@ systemctl start fail2ban
fail2ban-client status sshd
```
-### Blokker direkte tilgang til Docker-porten
+### Block direct access to the Docker port
```bash
# Prevent direct external access to port 20128
@@ -375,9 +377,9 @@ netfilter-persistent save
---
-## 7. Distribuer til Cloudflare-arbeidere (valgfritt)
+## 7. Deploy to Cloudflare Workers (Optional)
-For ekstern tilgang via Cloudflare Workers (uten å eksponere VM direkte):
+For remote access via Cloudflare Workers (without exposing the VM directly):
```bash
# In the local repository
@@ -387,15 +389,15 @@ npx wrangler login
npx wrangler deploy
```
-Se hele dokumentasjonen på [omnirouteCloud/README.md](../omnirouteCloud/README.md).
+See the full documentation at [omnirouteCloud/README.md](../omnirouteCloud/README.md).
---
-## Portsammendrag
+## Port Summary
-| Port | Service | Tilgang |
+| Port | Service | Access |
| ----- | ----------- | -------------------------- |
-| 22 | SSH | Offentlig (med fail2ban) |
-| 80 | nginx HTTP | Omdirigere → HTTPS |
+| 22 | SSH | Public (with fail2ban) |
+| 80 | nginx HTTP | Redirect → HTTPS |
| 443 | nginx HTTPS | Via Cloudflare Proxy |
-| 20128 | OmniRoute | Kun lokal vert (via nginx) |
+| 20128 | OmniRoute | Localhost only (via nginx) |
diff --git a/docs/i18n/es/src/lib/a2a/README.md b/docs/i18n/es/src/lib/a2a/README.md
new file mode 100644
index 0000000000..07dfb276ed
--- /dev/null
+++ b/docs/i18n/es/src/lib/a2a/README.md
@@ -0,0 +1,752 @@
+# OmniRoute A2A Server (Español)
+
+🌐 **Languages:** 🇺🇸 [English](../../../../../../src/lib/a2a/README.md) · 🇪🇸 [es](../../../../es/src/lib/a2a/README.md) · 🇫🇷 [fr](../../../../fr/src/lib/a2a/README.md) · 🇩🇪 [de](../../../../de/src/lib/a2a/README.md) · 🇮🇹 [it](../../../../it/src/lib/a2a/README.md) · 🇷🇺 [ru](../../../../ru/src/lib/a2a/README.md) · 🇨🇳 [zh-CN](../../../../zh-CN/src/lib/a2a/README.md) · 🇯🇵 [ja](../../../../ja/src/lib/a2a/README.md) · 🇰🇷 [ko](../../../../ko/src/lib/a2a/README.md) · 🇸🇦 [ar](../../../../ar/src/lib/a2a/README.md) · 🇮🇳 [in](../../../../in/src/lib/a2a/README.md) · 🇹🇭 [th](../../../../th/src/lib/a2a/README.md) · 🇻🇳 [vi](../../../../vi/src/lib/a2a/README.md) · 🇮🇩 [id](../../../../id/src/lib/a2a/README.md) · 🇲🇾 [ms](../../../../ms/src/lib/a2a/README.md) · 🇳🇱 [nl](../../../../nl/src/lib/a2a/README.md) · 🇵🇱 [pl](../../../../pl/src/lib/a2a/README.md) · 🇸🇪 [sv](../../../../sv/src/lib/a2a/README.md) · 🇳🇴 [no](../../../../no/src/lib/a2a/README.md) · 🇩🇰 [da](../../../../da/src/lib/a2a/README.md) · 🇫🇮 [fi](../../../../fi/src/lib/a2a/README.md) · 🇵🇹 [pt](../../../../pt/src/lib/a2a/README.md) · 🇷🇴 [ro](../../../../ro/src/lib/a2a/README.md) · 🇭🇺 [hu](../../../../hu/src/lib/a2a/README.md) · 🇧🇬 [bg](../../../../bg/src/lib/a2a/README.md) · 🇸🇰 [sk](../../../../sk/src/lib/a2a/README.md) · 🇺🇦 [uk-UA](../../../../uk-UA/src/lib/a2a/README.md) · 🇮🇱 [he](../../../../he/src/lib/a2a/README.md) · 🇵🇭 [phi](../../../../phi/src/lib/a2a/README.md) · 🇧🇷 [pt-BR](../../../../pt-BR/src/lib/a2a/README.md) · 🇨🇿 [cs](../../../../cs/src/lib/a2a/README.md)
+
+---
+
+> **Agent-to-Agent Protocol v0.3** — Enables any AI agent to use OmniRoute as an intelligent routing agent via JSON-RPC 2.0.
+
+The A2A Server exposes OmniRoute as a **first-class agent** that other agents can discover, delegate tasks to, and collaborate with using the [A2A Protocol](https://google.github.io/A2A/).
+
+---
+
+## Arquitectura
+
+```
+┌──────────────────────────────────────────────────────────────────┐
+│ Orchestrator Agent │
+│ (LangChain, CrewAI, AutoGen, Custom Agent) │
+└──────────────────────┬───────────────────────────────────────────┘
+ │ 1. GET /.well-known/agent.json (discover)
+ │ 2. POST /a2a (JSON-RPC 2.0)
+ ▼
+┌──────────────────────────────────────────────────────────────────┐
+│ OmniRoute A2A Server │
+│ ┌────────────────┐ ┌────────────────┐ ┌───────────────────┐ │
+│ │ Task Manager │ │ Skill Engine │ │ SSE Streaming │ │
+│ │ (lifecycle) │──│ (registry) │──│ (real-time) │ │
+│ └────────────────┘ └────────┬───────┘ └───────────────────┘ │
+│ │ │
+│ Skills: │ │
+│ ├─ smart-routing ──────────┤ ┌────────────────────────────┐ │
+│ └─ quota-management ───────┘ │ Routing Decision Logger │ │
+│ └────────────────────────────┘ │
+└──────────────────────────────────────────────────────────────────┘
+ │
+ ▼ OmniRoute Gateway (internal)
+ /v1/chat/completions, /api/combos, /api/usage/quota
+```
+
+---
+
+## Inicio Rápido
+
+### Agent Discovery
+
+Every A2A-compatible agent exposes an **Agent Card** at `/.well-known/agent.json`:
+
+```bash
+curl http://localhost:20128/.well-known/agent.json
+```
+
+**Response:**
+
+```json
+{
+ "name": "OmniRoute",
+ "description": "Intelligent AI gateway with auto-routing across 50+ providers",
+ "url": "http://localhost:20128/a2a",
+ "version": "1.8.1",
+ "capabilities": {
+ "streaming": true,
+ "pushNotifications": false
+ },
+ "skills": [
+ {
+ "id": "smart-routing",
+ "name": "Smart Routing",
+ "description": "Routes prompts through OmniRoute intelligent pipeline",
+ "tags": ["routing", "llm", "multi-provider", "cost-optimization"],
+ "examples": [
+ "Write a hello world in Python",
+ "Explain quantum computing using the cheapest provider"
+ ]
+ },
+ {
+ "id": "quota-management",
+ "name": "Quota Management",
+ "description": "Natural-language queries about provider quotas",
+ "tags": ["quota", "analytics", "cost"],
+ "examples": [
+ "Which provider has the most quota remaining?",
+ "Suggest a free combo for coding"
+ ]
+ }
+ ],
+ "authentication": {
+ "schemes": ["bearer"],
+ "apiKeyHeader": "Authorization"
+ }
+}
+```
+
+---
+
+## JSON-RPC 2.0 Methods
+
+### `message/send` — Synchronous Execution
+
+Send a message to a skill and receive the complete response.
+
+```bash
+curl -X POST http://localhost:20128/a2a \
+ -H "Content-Type: application/json" \
+ -H "Authorization: Bearer YOUR_KEY" \
+ -d '{
+ "jsonrpc": "2.0",
+ "id": "1",
+ "method": "message/send",
+ "params": {
+ "skill": "smart-routing",
+ "messages": [{"role": "user", "content": "Write a Python hello world"}],
+ "metadata": {"model": "auto", "combo": "fast-coding"}
+ }
+ }'
+```
+
+**Response:**
+
+```json
+{
+ "jsonrpc": "2.0",
+ "id": "1",
+ "result": {
+ "task": { "id": "a1b2c3d4-...", "state": "completed" },
+ "artifacts": [{ "type": "text", "content": "print('Hello, World!')" }],
+ "metadata": {
+ "routing_explanation": "Selected claude-sonnet via provider \"anthropic\" (latency: 1200ms, cost: $0.0030)",
+ "cost_envelope": { "estimated": 0.005, "actual": 0.003, "currency": "USD" },
+ "resilience_trace": [
+ { "event": "primary_selected", "provider": "anthropic", "timestamp": "2026-03-04T..." }
+ ],
+ "policy_verdict": { "allowed": true, "reason": "within budget and quota limits" }
+ }
+ }
+}
+```
+
+### `message/stream` — SSE Streaming
+
+Same as `message/send` but returns Server-Sent Events for real-time streaming.
+
+```bash
+curl -N -X POST http://localhost:20128/a2a \
+ -H "Content-Type: application/json" \
+ -H "Authorization: Bearer YOUR_KEY" \
+ -d '{
+ "jsonrpc": "2.0",
+ "id": "1",
+ "method": "message/stream",
+ "params": {
+ "skill": "smart-routing",
+ "messages": [{"role": "user", "content": "Explain quantum computing"}]
+ }
+ }'
+```
+
+**SSE Events:**
+
+```
+data: {"jsonrpc":"2.0","method":"message/stream","params":{"task":{"id":"...","state":"working"},"chunk":{"type":"text","content":"Quantum computing..."}}}
+
+: heartbeat 2026-03-04T21:00:00Z
+
+data: {"jsonrpc":"2.0","method":"message/stream","params":{"task":{"id":"...","state":"completed"},"metadata":{...}}}
+```
+
+### `tasks/get` — Query Task Status
+
+```bash
+curl -X POST http://localhost:20128/a2a \
+ -H "Content-Type: application/json" \
+ -H "Authorization: Bearer YOUR_KEY" \
+ -d '{"jsonrpc":"2.0","id":"2","method":"tasks/get","params":{"taskId":"TASK_UUID"}}'
+```
+
+### `tasks/cancel` — Cancel a Running Task
+
+```bash
+curl -X POST http://localhost:20128/a2a \
+ -H "Content-Type: application/json" \
+ -H "Authorization: Bearer YOUR_KEY" \
+ -d '{"jsonrpc":"2.0","id":"3","method":"tasks/cancel","params":{"taskId":"TASK_UUID"}}'
+```
+
+---
+
+## Skills Reference
+
+### `smart-routing`
+
+Routes prompts through OmniRoute's intelligent pipeline with full observability.
+
+**Parameters (in `metadata`):**
+
+| Parameter | Type | Default | Description |
+| --------- | -------- | ------------ | ---------------------------------------------------------------------------------------- |
+| `model` | `string` | `"auto"` | Target model (e.g., `claude-sonnet-4`, `gpt-4o`, `auto`) |
+| `combo` | `string` | active combo | Specific combo to route through |
+| `budget` | `number` | none | Maximum cost in USD for this request |
+| `role` | `string` | none | Task role hint: `coding`, `review`, `planning`, `analysis`, `debugging`, `documentation` |
+
+**Returns:**
+
+| Field | Description |
+| ------------------------------ | --------------------------------------------------------- |
+| `artifacts[].content` | The LLM response text |
+| `metadata.routing_explanation` | Human-readable explanation of routing decision |
+| `metadata.cost_envelope` | Estimated vs actual cost with currency |
+| `metadata.resilience_trace` | Array of events (primary_selected, fallback_needed, etc.) |
+| `metadata.policy_verdict` | Whether the request was allowed and why |
+
+### `quota-management`
+
+Answers natural-language queries about provider quotas.
+
+**Query types (inferred from message content):**
+
+| Query Pattern | Response Type |
+| ---------------------------------------------- | -------------------------------------------------------- |
+| Contains `"ranking"`, `"most quota"`, `"best"` | Providers ranked by remaining quota |
+| Contains `"free"`, `"suggest"` | Lists free combos or suggests free-tier providers |
+| Default | Full quota summary with warnings for low-quota providers |
+
+---
+
+## Task Lifecycle
+
+```
+submitted ──→ working ──→ completed
+ ──→ failed
+ ──────────→ cancelled
+```
+
+| State | Description |
+| ----------- | ----------------------------------------------------- |
+| `submitted` | Task created, queued for execution |
+| `working` | Skill handler is executing |
+| `completed` | Execution succeeded, artifacts available |
+| `failed` | Execution failed or task expired (TTL: 5 min default) |
+| `cancelled` | Cancelled by client via `tasks/cancel` |
+
+- Terminal states: `completed`, `failed`, `cancelled` (no further transitions)
+- Expired tasks in `submitted` or `working` are auto-marked as `failed`
+- Tasks are garbage-collected after 2× TTL
+
+---
+
+## Client Examples
+
+### Python — Orchestrator Agent
+
+```python
+"""
+A2A Client — Python example.
+Discovers OmniRoute agent, sends a task, and processes the result.
+"""
+import requests
+import json
+
+BASE_URL = "http://localhost:20128"
+API_KEY = "your-api-key"
+HEADERS = {
+ "Content-Type": "application/json",
+ "Authorization": f"Bearer {API_KEY}",
+}
+
+# 1. Discover agent capabilities
+agent_card = requests.get(f"{BASE_URL}/.well-known/agent.json").json()
+print(f"Agent: {agent_card['name']} v{agent_card['version']}")
+print(f"Skills: {[s['id'] for s in agent_card['skills']]}")
+
+# 2. Send a smart-routing task
+response = requests.post(f"{BASE_URL}/a2a", headers=HEADERS, json={
+ "jsonrpc": "2.0",
+ "id": "task-1",
+ "method": "message/send",
+ "params": {
+ "skill": "smart-routing",
+ "messages": [{"role": "user", "content": "Write a Python quicksort implementation"}],
+ "metadata": {
+ "model": "auto",
+ "combo": "fast-coding",
+ "budget": 0.10,
+ }
+ }
+})
+result = response.json()["result"]
+print(f"\n📝 Response: {result['artifacts'][0]['content'][:200]}...")
+print(f"🔀 Routing: {result['metadata']['routing_explanation']}")
+print(f"💰 Cost: ${result['metadata']['cost_envelope']['actual']}")
+print(f"🛡️ Policy: {result['metadata']['policy_verdict']['reason']}")
+
+# 3. Query quota status
+quota_resp = requests.post(f"{BASE_URL}/a2a", headers=HEADERS, json={
+ "jsonrpc": "2.0",
+ "id": "task-2",
+ "method": "message/send",
+ "params": {
+ "skill": "quota-management",
+ "messages": [{"role": "user", "content": "Which provider has the most quota remaining?"}],
+ }
+})
+quota_result = quota_resp.json()["result"]
+print(f"\n📊 Quota: {quota_result['artifacts'][0]['content']}")
+```
+
+### TypeScript — Multi-Agent Orchestrator
+
+```typescript
+/**
+ * A2A Client — TypeScript example.
+ * Shows agent discovery, task delegation, and streaming.
+ */
+
+const BASE_URL = "http://localhost:20128";
+const API_KEY = "your-api-key";
+
+interface JsonRpcResponse {
+ jsonrpc: "2.0";
+ id: string | number;
+ result?: T;
+ error?: { code: number; message: string };
+}
+
+async function a2aCall(method: string, params: Record): Promise {
+ const resp = await fetch(`${BASE_URL}/a2a`, {
+ method: "POST",
+ headers: {
+ "Content-Type": "application/json",
+ Authorization: `Bearer ${API_KEY}`,
+ },
+ body: JSON.stringify({
+ jsonrpc: "2.0",
+ id: `${method}-${Date.now()}`,
+ method,
+ params,
+ }),
+ });
+ const json: JsonRpcResponse = await resp.json();
+ if (json.error) throw new Error(`[${json.error.code}] ${json.error.message}`);
+ return json.result!;
+}
+
+// ── Agent Discovery ──
+const agentCard = await fetch(`${BASE_URL}/.well-known/agent.json`).then((r) => r.json());
+console.log(`Connected to: ${agentCard.name} (${agentCard.skills.length} skills)`);
+
+// ── Smart Routing: Send a coding task ──
+const routingResult = await a2aCall("message/send", {
+ skill: "smart-routing",
+ messages: [{ role: "user", content: "Implement a Redis cache wrapper in TypeScript" }],
+ metadata: { model: "claude-sonnet-4", role: "coding" },
+});
+console.log("Response:", routingResult.artifacts[0].content);
+console.log("Provider:", routingResult.metadata.routing_explanation);
+
+// ── Quota Management: Find free alternatives ──
+const quotaResult = await a2aCall("message/send", {
+ skill: "quota-management",
+ messages: [{ role: "user", content: "Suggest free combos for documentation" }],
+});
+console.log("Free combos:", quotaResult.artifacts[0].content);
+
+// ── Streaming: Real-time response ──
+const streamResp = await fetch(`${BASE_URL}/a2a`, {
+ method: "POST",
+ headers: {
+ "Content-Type": "application/json",
+ Authorization: `Bearer ${API_KEY}`,
+ },
+ body: JSON.stringify({
+ jsonrpc: "2.0",
+ id: "stream-1",
+ method: "message/stream",
+ params: {
+ skill: "smart-routing",
+ messages: [{ role: "user", content: "Explain microservices architecture" }],
+ },
+ }),
+});
+
+const reader = streamResp.body!.getReader();
+const decoder = new TextDecoder();
+while (true) {
+ const { done, value } = await reader.read();
+ if (done) break;
+ const chunk = decoder.decode(value);
+ for (const line of chunk.split("\n")) {
+ if (line.startsWith("data: ")) {
+ const event = JSON.parse(line.slice(6));
+ if (event.params.chunk) {
+ process.stdout.write(event.params.chunk.content);
+ }
+ if (event.params.task.state === "completed") {
+ console.log("\n✅ Stream completed");
+ }
+ }
+ }
+}
+```
+
+### Python — LangChain A2A Integration
+
+```python
+"""
+LangChain integration — Use OmniRoute A2A as a custom LLM.
+"""
+from langchain.llms.base import BaseLLM
+from langchain.schema import LLMResult, Generation
+import requests
+from typing import List, Optional
+
+class OmniRouteA2A(BaseLLM):
+ base_url: str = "http://localhost:20128"
+ api_key: str = ""
+ model: str = "auto"
+ combo: Optional[str] = None
+
+ @property
+ def _llm_type(self) -> str:
+ return "omniroute-a2a"
+
+ def _call(self, prompt: str, stop: Optional[List[str]] = None, **kwargs) -> str:
+ response = requests.post(
+ f"{self.base_url}/a2a",
+ headers={
+ "Content-Type": "application/json",
+ "Authorization": f"Bearer {self.api_key}",
+ },
+ json={
+ "jsonrpc": "2.0",
+ "id": "langchain-1",
+ "method": "message/send",
+ "params": {
+ "skill": "smart-routing",
+ "messages": [{"role": "user", "content": prompt}],
+ "metadata": {
+ "model": self.model,
+ **({"combo": self.combo} if self.combo else {}),
+ },
+ },
+ },
+ )
+ result = response.json()["result"]
+ return result["artifacts"][0]["content"]
+
+ def _generate(self, prompts: List[str], stop=None, **kwargs) -> LLMResult:
+ return LLMResult(
+ generations=[[Generation(text=self._call(p, stop))] for p in prompts]
+ )
+
+# Usage
+llm = OmniRouteA2A(
+ base_url="http://localhost:20128",
+ api_key="your-key",
+ model="auto",
+ combo="fast-coding",
+)
+result = llm("Write a Python function to merge two sorted lists")
+print(result)
+```
+
+### Go — A2A Client
+
+```go
+package main
+
+import (
+ "bytes"
+ "encoding/json"
+ "fmt"
+ "io"
+ "net/http"
+)
+
+const baseURL = "http://localhost:20128"
+const apiKey = "your-api-key"
+
+type JsonRpcRequest struct {
+ Jsonrpc string `json:"jsonrpc"`
+ ID string `json:"id"`
+ Method string `json:"method"`
+ Params interface{} `json:"params"`
+}
+
+type JsonRpcResponse struct {
+ Jsonrpc string `json:"jsonrpc"`
+ ID string `json:"id"`
+ Result interface{} `json:"result"`
+ Error *struct {
+ Code int `json:"code"`
+ Message string `json:"message"`
+ } `json:"error"`
+}
+
+func a2aCall(method string, params interface{}) (*JsonRpcResponse, error) {
+ body, _ := json.Marshal(JsonRpcRequest{
+ Jsonrpc: "2.0",
+ ID: "go-1",
+ Method: method,
+ Params: params,
+ })
+
+ req, _ := http.NewRequest("POST", baseURL+"/a2a", bytes.NewReader(body))
+ req.Header.Set("Content-Type", "application/json")
+ req.Header.Set("Authorization", "Bearer "+apiKey)
+
+ resp, err := http.DefaultClient.Do(req)
+ if err != nil {
+ return nil, err
+ }
+ defer resp.Body.Close()
+ data, _ := io.ReadAll(resp.Body)
+
+ var result JsonRpcResponse
+ json.Unmarshal(data, &result)
+ return &result, nil
+}
+
+func main() {
+ // Discover agent
+ resp, _ := http.Get(baseURL + "/.well-known/agent.json")
+ defer resp.Body.Close()
+ body, _ := io.ReadAll(resp.Body)
+ fmt.Println("Agent Card:", string(body))
+
+ // Send smart-routing task
+ result, _ := a2aCall("message/send", map[string]interface{}{
+ "skill": "smart-routing",
+ "messages": []map[string]string{{"role": "user", "content": "Hello from Go!"}},
+ "metadata": map[string]interface{}{"model": "auto"},
+ })
+ out, _ := json.MarshalIndent(result.Result, "", " ")
+ fmt.Println("Result:", string(out))
+}
+```
+
+---
+
+## Use Cases
+
+### 🤖 Use Case 1: Multi-Agent Coding Pipeline
+
+An orchestrator agent delegates code generation to OmniRoute, then passes the output to a review agent.
+
+```python
+def coding_pipeline(task: str):
+ # Step 1: Generate code via OmniRoute A2A
+ code_result = a2a_send("smart-routing", [
+ {"role": "user", "content": f"Write production-quality code: {task}"}
+ ], metadata={"model": "auto", "role": "coding"})
+ code = code_result["artifacts"][0]["content"]
+
+ # Step 2: Review the code via OmniRoute A2A (different model)
+ review_result = a2a_send("smart-routing", [
+ {"role": "user", "content": f"Review this code for bugs and improvements:\n\n{code}"}
+ ], metadata={"model": "auto", "role": "review"})
+ review = review_result["artifacts"][0]["content"]
+
+ # Step 3: Check costs
+ print(f"Code cost: ${code_result['metadata']['cost_envelope']['actual']}")
+ print(f"Review cost: ${review_result['metadata']['cost_envelope']['actual']}")
+
+ return {"code": code, "review": review}
+```
+
+### 💡 Use Case 2: Quota-Aware Agent Swarm
+
+Multiple agents share quota through OmniRoute, using the quota skill to coordinate.
+
+```python
+async def quota_aware_agent(agent_name: str, task: str):
+ # Check quota before starting
+ quota = a2a_send("quota-management", [
+ {"role": "user", "content": "Which provider has the most quota remaining?"}
+ ])
+ print(f"[{agent_name}] {quota['artifacts'][0]['content']}")
+
+ # Send request with budget constraint
+ result = a2a_send("smart-routing", [
+ {"role": "user", "content": task}
+ ], metadata={"budget": 0.05})
+
+ policy = result["metadata"]["policy_verdict"]
+ if not policy["allowed"]:
+ print(f"[{agent_name}] ⚠️ Budget exceeded: {policy['reason']}")
+ # Fall back to free combo
+ quota = a2a_send("quota-management", [
+ {"role": "user", "content": "Suggest free combos"}
+ ])
+ print(f"[{agent_name}] Free alternatives: {quota['artifacts'][0]['content']}")
+
+ return result
+```
+
+### 📊 Use Case 3: Real-Time Streaming Dashboard
+
+A monitoring agent streams responses and displays progress in real-time.
+
+```typescript
+async function streamingDashboard(prompt: string) {
+ const response = await fetch(`${BASE_URL}/a2a`, {
+ method: "POST",
+ headers: { "Content-Type": "application/json", Authorization: `Bearer ${API_KEY}` },
+ body: JSON.stringify({
+ jsonrpc: "2.0",
+ id: "dash-1",
+ method: "message/stream",
+ params: { skill: "smart-routing", messages: [{ role: "user", content: prompt }] },
+ }),
+ });
+
+ let totalChunks = 0;
+ const reader = response.body!.getReader();
+ const decoder = new TextDecoder();
+
+ while (true) {
+ const { done, value } = await reader.read();
+ if (done) break;
+
+ for (const line of decoder.decode(value).split("\n")) {
+ if (line.startsWith("data: ")) {
+ const event = JSON.parse(line.slice(6));
+ const state = event.params.task.state;
+
+ if (state === "working" && event.params.chunk) {
+ totalChunks++;
+ process.stdout.write(
+ `\r[Chunk ${totalChunks}] ${event.params.chunk.content.slice(0, 50)}...`
+ );
+ }
+ if (state === "completed") {
+ const meta = event.params.metadata;
+ console.log(
+ `\n✅ Done | Cost: $${meta?.cost_envelope?.actual || 0} | Route: ${meta?.routing_explanation || "N/A"}`
+ );
+ }
+ if (state === "failed") {
+ console.error(`\n❌ Failed: ${event.params.metadata?.error}`);
+ }
+ }
+ }
+ }
+}
+```
+
+### 🔁 Use Case 4: Task Polling Pattern
+
+For long-running tasks, poll the task status instead of waiting synchronously.
+
+```python
+import time
+
+def poll_task(task_id: str, timeout: int = 60):
+ """Poll task status until completion or timeout."""
+ start = time.time()
+ while time.time() - start < timeout:
+ result = requests.post(f"{BASE_URL}/a2a", headers=HEADERS, json={
+ "jsonrpc": "2.0",
+ "id": "poll-1",
+ "method": "tasks/get",
+ "params": {"taskId": task_id},
+ }).json()
+
+ task = result["result"]["task"]
+ state = task["state"]
+ print(f" Task {task_id[:8]}... state={state}")
+
+ if state in ("completed", "failed", "cancelled"):
+ return task
+ time.sleep(2)
+
+ # Timeout — cancel the task
+ requests.post(f"{BASE_URL}/a2a", headers=HEADERS, json={
+ "jsonrpc": "2.0",
+ "id": "cancel-1",
+ "method": "tasks/cancel",
+ "params": {"taskId": task_id},
+ })
+ raise TimeoutError(f"Task {task_id} timed out after {timeout}s")
+```
+
+---
+
+## Error Codes
+
+| Code | Constant | Meaning |
+| ------ | ------------------------ | ---------------------------------------- |
+| -32700 | — | Parse error (invalid JSON) |
+| -32600 | `INVALID_REQUEST` | Invalid JSON-RPC request or unauthorized |
+| -32601 | `METHOD_NOT_FOUND` | Unknown method or skill |
+| -32602 | `INVALID_PARAMS` | Missing or invalid parameters |
+| -32603 | `INTERNAL_ERROR` | Skill execution failed |
+| -32001 | `TASK_NOT_FOUND` | Task ID not found |
+| -32002 | `TASK_ALREADY_COMPLETED` | Cannot modify a completed task |
+| -32003 | `UNAUTHORIZED` | Invalid or missing API key |
+| -32004 | `BUDGET_EXCEEDED` | Request exceeds configured budget |
+| -32005 | `PROVIDER_UNAVAILABLE` | No available providers |
+
+---
+
+## Authentication
+
+All `/a2a` requests require a Bearer token via the `Authorization` header:
+
+```
+Authorization: Bearer YOUR_OMNIROUTE_API_KEY
+```
+
+If no API key is configured on the server (`OMNIROUTE_API_KEY` is empty), authentication is bypassed.
+
+---
+
+## File Structure
+
+```
+src/lib/a2a/
+├── taskManager.ts # Task lifecycle (create/update/cancel/list), TTL, cleanup
+├── taskExecution.ts # Generic task executor with state management
+├── streaming.ts # SSE stream formatting, heartbeat, chunk/completion events
+├── routingLogger.ts # Routing decision logger (stats, history, retention)
+└── skills/
+ ├── smartRouting.ts # Smart routing skill (routes via /v1/chat/completions)
+ └── quotaManagement.ts # Quota management skill (natural-language quota queries)
+
+src/app/a2a/
+└── route.ts # Next.js API route handler (JSON-RPC 2.0 dispatch)
+
+open-sse/mcp-server/
+└── schemas/a2a.ts # Zod schemas (AgentCard, Task, JSON-RPC, SSE events)
+```
+
+---
+
+## Comparison: MCP vs A2A
+
+| Feature | MCP Server | A2A Server |
+| ----------------- | ---------------------------- | ------------------------------------------------- |
+| **Protocol** | Model Context Protocol | Agent-to-Agent Protocol v0.3 |
+| **Transport** | stdio / HTTP | HTTP (JSON-RPC 2.0) |
+| **Discovery** | Tool listing via MCP | `/.well-known/agent.json` |
+| **Granularity** | 16 individual tools | 2 high-level skills |
+| **Best for** | IDE agents (Cursor, VS Code) | Multi-agent systems (LangChain, CrewAI) |
+| **Streaming** | Not supported | SSE via `message/stream` |
+| **Task tracking** | No | Full lifecycle (submitted → completed) |
+| **Observability** | Audit log per tool call | Cost envelope + resilience trace + policy verdict |
+
+---
+
+## Licencia
+
+Part of [OmniRoute](https://github.com/diegosouzapw/OmniRoute) — MIT License.
diff --git a/docs/i18n/fi/A2A-SERVER.md b/docs/i18n/fi/A2A-SERVER.md
deleted file mode 100644
index 01531ff482..0000000000
--- a/docs/i18n/fi/A2A-SERVER.md
+++ /dev/null
@@ -1,200 +0,0 @@
-🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/A2A-SERVER.md) · 🇪🇸 [es](../es/A2A-SERVER.md) · 🇫🇷 [fr](../fr/A2A-SERVER.md) · 🇩🇪 [de](../de/A2A-SERVER.md) · 🇮🇹 [it](../it/A2A-SERVER.md) · 🇷🇺 [ru](../ru/A2A-SERVER.md) · 🇨🇳 [zh-CN](../zh-CN/A2A-SERVER.md) · 🇯🇵 [ja](../ja/A2A-SERVER.md) · 🇰🇷 [ko](../ko/A2A-SERVER.md) · 🇸🇦 [ar](../ar/A2A-SERVER.md) · 🇮🇳 [in](../in/A2A-SERVER.md) · 🇹🇭 [th](../th/A2A-SERVER.md) · 🇻🇳 [vi](../vi/A2A-SERVER.md) · 🇮🇩 [id](../id/A2A-SERVER.md) · 🇲🇾 [ms](../ms/A2A-SERVER.md) · 🇳🇱 [nl](../nl/A2A-SERVER.md) · 🇵🇱 [pl](../pl/A2A-SERVER.md) · 🇸🇪 [sv](../sv/A2A-SERVER.md) · 🇳🇴 [no](../no/A2A-SERVER.md) · 🇩🇰 [da](../da/A2A-SERVER.md) · 🇫🇮 [fi](../fi/A2A-SERVER.md) · 🇵🇹 [pt](../pt/A2A-SERVER.md) · 🇷🇴 [ro](../ro/A2A-SERVER.md) · 🇭🇺 [hu](../hu/A2A-SERVER.md) · 🇧🇬 [bg](../bg/A2A-SERVER.md) · 🇸🇰 [sk](../sk/A2A-SERVER.md) · 🇺🇦 [uk-UA](../uk-UA/A2A-SERVER.md) · 🇮🇱 [he](../he/A2A-SERVER.md) · 🇵🇭 [phi](../phi/A2A-SERVER.md)
-
----
-
-# OmniRoute A2A Server Documentation
-
-> Agent-to-Agent Protocol v0.3 — OmniRoute as an intelligent routing agent
-
-## Agent Discovery
-
-```bash
-curl http://localhost:20128/.well-known/agent.json
-```
-
-Returns the Agent Card describing OmniRoute's capabilities, skills, and authentication requirements.
-
----
-
-## Authentication
-
-All `/a2a` requests require an API key via the `Authorization` header:
-
-```
-Authorization: Bearer YOUR_OMNIROUTE_API_KEY
-```
-
-If no API key is configured on the server, authentication is bypassed.
-
----
-
-## JSON-RPC 2.0 Methods
-
-### `message/send` — Synchronous Execution
-
-Sends a message to a skill and waits for the complete response.
-
-```bash
-curl -X POST http://localhost:20128/a2a \
- -H "Content-Type: application/json" \
- -H "Authorization: Bearer YOUR_KEY" \
- -d '{
- "jsonrpc": "2.0",
- "id": "1",
- "method": "message/send",
- "params": {
- "skill": "smart-routing",
- "messages": [{"role": "user", "content": "Write a hello world in Python"}],
- "metadata": {"model": "auto", "combo": "fast-coding"}
- }
- }'
-```
-
-**Response:**
-
-```json
-{
- "jsonrpc": "2.0",
- "id": "1",
- "result": {
- "task": { "id": "uuid", "state": "completed" },
- "artifacts": [{ "type": "text", "content": "..." }],
- "metadata": {
- "routing_explanation": "Selected claude-sonnet via provider \"anthropic\" (latency: 1200ms, cost: $0.003)",
- "cost_envelope": { "estimated": 0.005, "actual": 0.003, "currency": "USD" },
- "resilience_trace": [
- { "event": "primary_selected", "provider": "anthropic", "timestamp": "..." }
- ],
- "policy_verdict": { "allowed": true, "reason": "within budget and quota limits" }
- }
- }
-}
-```
-
-### `message/stream` — SSE Streaming
-
-Same as `message/send` but returns Server-Sent Events for real-time streaming.
-
-```bash
-curl -N -X POST http://localhost:20128/a2a \
- -H "Content-Type: application/json" \
- -H "Authorization: Bearer YOUR_KEY" \
- -d '{
- "jsonrpc": "2.0",
- "id": "1",
- "method": "message/stream",
- "params": {
- "skill": "smart-routing",
- "messages": [{"role": "user", "content": "Explain quantum computing"}]
- }
- }'
-```
-
-**SSE Events:**
-
-```
-data: {"jsonrpc":"2.0","method":"message/stream","params":{"task":{"id":"...","state":"working"},"chunk":{"type":"text","content":"..."}}}
-
-: heartbeat 2026-03-03T17:00:00Z
-
-data: {"jsonrpc":"2.0","method":"message/stream","params":{"task":{"id":"...","state":"completed"},"metadata":{...}}}
-```
-
-### `tasks/get` — Query Task Status
-
-```bash
-curl -X POST http://localhost:20128/a2a \
- -H "Content-Type: application/json" \
- -H "Authorization: Bearer YOUR_KEY" \
- -d '{"jsonrpc":"2.0","id":"2","method":"tasks/get","params":{"taskId":"TASK_UUID"}}'
-```
-
-### `tasks/cancel` — Cancel a Task
-
-```bash
-curl -X POST http://localhost:20128/a2a \
- -H "Content-Type: application/json" \
- -H "Authorization: Bearer YOUR_KEY" \
- -d '{"jsonrpc":"2.0","id":"3","method":"tasks/cancel","params":{"taskId":"TASK_UUID"}}'
-```
-
----
-
-## Available Skills
-
-| Skill | Description |
-| :----------------- | :------------------------------------------------------------------------------------------------------------------------------ |
-| `smart-routing` | Routes prompts through OmniRoute's intelligent pipeline. Returns response with routing explanation, cost, and resilience trace. |
-| `quota-management` | Answers natural-language queries about provider quotas, suggests free combos, and provides quota rankings. |
-
----
-
-## Task Lifecycle
-
-```
-submitted → working → completed
- → failed
- → cancelled
-```
-
-- Tasks expire after 5 minutes (configurable)
-- Terminal states: `completed`, `failed`, `cancelled`
-- Event log tracks every state transition
-
----
-
-## Error Codes
-
-| Code | Meaning |
-| :----- | :----------------------------- |
-| -32700 | Parse error (invalid JSON) |
-| -32600 | Invalid request / Unauthorized |
-| -32601 | Method or skill not found |
-| -32602 | Invalid params |
-| -32603 | Internal error |
-
----
-
-## Integration Examples
-
-### Python (requests)
-
-```python
-import requests
-
-resp = requests.post("http://localhost:20128/a2a", json={
- "jsonrpc": "2.0", "id": "1",
- "method": "message/send",
- "params": {
- "skill": "smart-routing",
- "messages": [{"role": "user", "content": "Hello"}]
- }
-}, headers={"Authorization": "Bearer YOUR_KEY"})
-
-result = resp.json()["result"]
-print(result["artifacts"][0]["content"])
-print(result["metadata"]["routing_explanation"])
-```
-
-### TypeScript (fetch)
-
-```typescript
-const resp = await fetch("http://localhost:20128/a2a", {
- method: "POST",
- headers: {
- "Content-Type": "application/json",
- Authorization: "Bearer YOUR_KEY",
- },
- body: JSON.stringify({
- jsonrpc: "2.0",
- id: "1",
- method: "message/send",
- params: {
- skill: "smart-routing",
- messages: [{ role: "user", content: "Hello" }],
- },
- }),
-});
-const { result } = await resp.json();
-console.log(result.metadata.routing_explanation);
-```
diff --git a/docs/i18n/fi/API_REFERENCE.md b/docs/i18n/fi/API_REFERENCE.md
deleted file mode 100644
index b878605221..0000000000
--- a/docs/i18n/fi/API_REFERENCE.md
+++ /dev/null
@@ -1,455 +0,0 @@
-🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/API_REFERENCE.md) · 🇪🇸 [es](../es/API_REFERENCE.md) · 🇫🇷 [fr](../fr/API_REFERENCE.md) · 🇩🇪 [de](../de/API_REFERENCE.md) · 🇮🇹 [it](../it/API_REFERENCE.md) · 🇷🇺 [ru](../ru/API_REFERENCE.md) · 🇨🇳 [zh-CN](../zh-CN/API_REFERENCE.md) · 🇯🇵 [ja](../ja/API_REFERENCE.md) · 🇰🇷 [ko](../ko/API_REFERENCE.md) · 🇸🇦 [ar](../ar/API_REFERENCE.md) · 🇮🇳 [in](../in/API_REFERENCE.md) · 🇹🇭 [th](../th/API_REFERENCE.md) · 🇻🇳 [vi](../vi/API_REFERENCE.md) · 🇮🇩 [id](../id/API_REFERENCE.md) · 🇲🇾 [ms](../ms/API_REFERENCE.md) · 🇳🇱 [nl](../nl/API_REFERENCE.md) · 🇵🇱 [pl](../pl/API_REFERENCE.md) · 🇸🇪 [sv](../sv/API_REFERENCE.md) · 🇳🇴 [no](../no/API_REFERENCE.md) · 🇩🇰 [da](../da/API_REFERENCE.md) · 🇫🇮 [fi](../fi/API_REFERENCE.md) · 🇵🇹 [pt](../pt/API_REFERENCE.md) · 🇷🇴 [ro](../ro/API_REFERENCE.md) · 🇭🇺 [hu](../hu/API_REFERENCE.md) · 🇧🇬 [bg](../bg/API_REFERENCE.md) · 🇸🇰 [sk](../sk/API_REFERENCE.md) · 🇺🇦 [uk-UA](../uk-UA/API_REFERENCE.md) · 🇮🇱 [he](../he/API_REFERENCE.md) · 🇵🇭 [phi](../phi/API_REFERENCE.md)
-
----
-
-# API Reference
-
-🌐 **Languages:** 🇺🇸 [English](API_REFERENCE.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/API_REFERENCE.md) | 🇪🇸 [Español](i18n/es/API_REFERENCE.md) | 🇫🇷 [Français](i18n/fr/API_REFERENCE.md) | 🇮🇹 [Italiano](i18n/it/API_REFERENCE.md) | 🇷🇺 [Русский](i18n/ru/API_REFERENCE.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/API_REFERENCE.md) | 🇩🇪 [Deutsch](i18n/de/API_REFERENCE.md) | 🇮🇳 [हिन्दी](i18n/in/API_REFERENCE.md) | 🇹🇭 [ไทย](i18n/th/API_REFERENCE.md) | 🇺🇦 [Українська](i18n/uk-UA/API_REFERENCE.md) | 🇸🇦 [العربية](i18n/ar/API_REFERENCE.md) | 🇯🇵 [日本語](i18n/ja/API_REFERENCE.md) | 🇻🇳 [Tiếng Việt](i18n/vi/API_REFERENCE.md) | 🇧🇬 [Български](i18n/bg/API_REFERENCE.md) | 🇩🇰 [Dansk](i18n/da/API_REFERENCE.md) | 🇫🇮 [Suomi](i18n/fi/API_REFERENCE.md) | 🇮🇱 [עברית](i18n/he/API_REFERENCE.md) | 🇭🇺 [Magyar](i18n/hu/API_REFERENCE.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/API_REFERENCE.md) | 🇰🇷 [한국어](i18n/ko/API_REFERENCE.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/API_REFERENCE.md) | 🇳🇱 [Nederlands](i18n/nl/API_REFERENCE.md) | 🇳🇴 [Norsk](i18n/no/API_REFERENCE.md) | 🇵🇹 [Português (Portugal)](i18n/pt/API_REFERENCE.md) | 🇷🇴 [Română](i18n/ro/API_REFERENCE.md) | 🇵🇱 [Polski](i18n/pl/API_REFERENCE.md) | 🇸🇰 [Slovenčina](i18n/sk/API_REFERENCE.md) | 🇸🇪 [Svenska](i18n/sv/API_REFERENCE.md) | 🇵🇭 [Filipino](i18n/phi/API_REFERENCE.md)
-
-Complete reference for all OmniRoute API endpoints.
-
----
-
-## Table of Contents
-
-- [Chat Completions](#chat-completions)
-- [Embeddings](#embeddings)
-- [Image Generation](#image-generation)
-- [List Models](#list-models)
-- [Compatibility Endpoints](#compatibility-endpoints)
-- [Semantic Cache](#semantic-cache)
-- [Dashboard & Management](#dashboard--management)
-- [Request Processing](#request-processing)
-- [Authentication](#authentication)
-
----
-
-## Chat Completions
-
-```bash
-POST /v1/chat/completions
-Authorization: Bearer your-api-key
-Content-Type: application/json
-
-{
- "model": "cc/claude-opus-4-6",
- "messages": [
- {"role": "user", "content": "Write a function to..."}
- ],
- "stream": true
-}
-```
-
-### Custom Headers
-
-| Header | Direction | Description |
-| ------------------------ | --------- | --------------------------------- |
-| `X-OmniRoute-No-Cache` | Request | Set to `true` to bypass cache |
-| `X-OmniRoute-Progress` | Request | Set to `true` for progress events |
-| `Idempotency-Key` | Request | Dedup key (5s window) |
-| `X-Request-Id` | Request | Alternative dedup key |
-| `X-OmniRoute-Cache` | Response | `HIT` or `MISS` (non-streaming) |
-| `X-OmniRoute-Idempotent` | Response | `true` if deduplicated |
-| `X-OmniRoute-Progress` | Response | `enabled` if progress tracking on |
-
----
-
-## Embeddings
-
-```bash
-POST /v1/embeddings
-Authorization: Bearer your-api-key
-Content-Type: application/json
-
-{
- "model": "nebius/Qwen/Qwen3-Embedding-8B",
- "input": "The food was delicious"
-}
-```
-
-Available providers: Nebius, OpenAI, Mistral, Together AI, Fireworks, NVIDIA.
-
-```bash
-# List all embedding models
-GET /v1/embeddings
-```
-
----
-
-## Image Generation
-
-```bash
-POST /v1/images/generations
-Authorization: Bearer your-api-key
-Content-Type: application/json
-
-{
- "model": "openai/dall-e-3",
- "prompt": "A beautiful sunset over mountains",
- "size": "1024x1024"
-}
-```
-
-Available providers: OpenAI (DALL-E), xAI (Grok Image), Together AI (FLUX), Fireworks AI.
-
-```bash
-# List all image models
-GET /v1/images/generations
-```
-
----
-
-## List Models
-
-```bash
-GET /v1/models
-Authorization: Bearer your-api-key
-
-→ Returns all chat, embedding, and image models + combos in OpenAI format
-```
-
----
-
-## Compatibility Endpoints
-
-| Method | Path | Format |
-| ------ | --------------------------- | ---------------------- |
-| POST | `/v1/chat/completions` | OpenAI |
-| POST | `/v1/messages` | Anthropic |
-| POST | `/v1/responses` | OpenAI Responses |
-| POST | `/v1/embeddings` | OpenAI |
-| POST | `/v1/images/generations` | OpenAI |
-| GET | `/v1/models` | OpenAI |
-| POST | `/v1/messages/count_tokens` | Anthropic |
-| GET | `/v1beta/models` | Gemini |
-| POST | `/v1beta/models/{...path}` | Gemini generateContent |
-| POST | `/v1/api/chat` | Ollama |
-
-### Dedicated Provider Routes
-
-```bash
-POST /v1/providers/{provider}/chat/completions
-POST /v1/providers/{provider}/embeddings
-POST /v1/providers/{provider}/images/generations
-```
-
-The provider prefix is auto-added if missing. Mismatched models return `400`.
-
----
-
-## Semantic Cache
-
-```bash
-# Get cache stats
-GET /api/cache
-
-# Clear all caches
-DELETE /api/cache
-```
-
-Response example:
-
-```json
-{
- "semanticCache": {
- "memorySize": 42,
- "memoryMaxSize": 500,
- "dbSize": 128,
- "hitRate": 0.65
- },
- "idempotency": {
- "activeKeys": 3,
- "windowMs": 5000
- }
-}
-```
-
----
-
-## Dashboard & Management
-
-### Authentication
-
-| Endpoint | Method | Description |
-| ----------------------------- | ------- | --------------------- |
-| `/api/auth/login` | POST | Login |
-| `/api/auth/logout` | POST | Logout |
-| `/api/settings/require-login` | GET/PUT | Toggle login required |
-
-### Provider Management
-
-| Endpoint | Method | Description |
-| ---------------------------- | --------------- | ------------------------ |
-| `/api/providers` | GET/POST | List / create providers |
-| `/api/providers/[id]` | GET/PUT/DELETE | Manage a provider |
-| `/api/providers/[id]/test` | POST | Test provider connection |
-| `/api/providers/[id]/models` | GET | List provider models |
-| `/api/providers/validate` | POST | Validate provider config |
-| `/api/provider-nodes*` | Various | Provider node management |
-| `/api/provider-models` | GET/POST/DELETE | Custom models |
-
-### OAuth Flows
-
-| Endpoint | Method | Description |
-| -------------------------------- | ------- | ----------------------- |
-| `/api/oauth/[provider]/[action]` | Various | Provider-specific OAuth |
-
-### Routing & Config
-
-| Endpoint | Method | Description |
-| --------------------- | -------- | ----------------------------- |
-| `/api/models/alias` | GET/POST | Model aliases |
-| `/api/models/catalog` | GET | All models by provider + type |
-| `/api/combos*` | Various | Combo management |
-| `/api/keys*` | Various | API key management |
-| `/api/pricing` | GET | Model pricing |
-
-### Usage & Analytics
-
-| Endpoint | Method | Description |
-| --------------------------- | ------ | -------------------- |
-| `/api/usage/history` | GET | Usage history |
-| `/api/usage/logs` | GET | Usage logs |
-| `/api/usage/request-logs` | GET | Request-level logs |
-| `/api/usage/[connectionId]` | GET | Per-connection usage |
-
-### Settings
-
-| Endpoint | Method | Description |
-| ------------------------------- | ------- | ---------------------- |
-| `/api/settings` | GET/PUT | General settings |
-| `/api/settings/proxy` | GET/PUT | Network proxy config |
-| `/api/settings/proxy/test` | POST | Test proxy connection |
-| `/api/settings/ip-filter` | GET/PUT | IP allowlist/blocklist |
-| `/api/settings/thinking-budget` | GET/PUT | Reasoning token budget |
-| `/api/settings/system-prompt` | GET/PUT | Global system prompt |
-
-### Monitoring
-
-| Endpoint | Method | Description |
-| ------------------------ | ---------- | ----------------------- |
-| `/api/sessions` | GET | Active session tracking |
-| `/api/rate-limits` | GET | Per-account rate limits |
-| `/api/monitoring/health` | GET | Health check |
-| `/api/cache` | GET/DELETE | Cache stats / clear |
-
-### Backup & Export/Import
-
-| Endpoint | Method | Description |
-| --------------------------- | ------ | --------------------------------------- |
-| `/api/db-backups` | GET | List available backups |
-| `/api/db-backups` | PUT | Create a manual backup |
-| `/api/db-backups` | POST | Restore from a specific backup |
-| `/api/db-backups/export` | GET | Download database as .sqlite file |
-| `/api/db-backups/import` | POST | Upload .sqlite file to replace database |
-| `/api/db-backups/exportAll` | GET | Download full backup as .tar.gz archive |
-
-### Cloud Sync
-
-| Endpoint | Method | Description |
-| ---------------------- | ------- | --------------------- |
-| `/api/sync/cloud` | Various | Cloud sync operations |
-| `/api/sync/initialize` | POST | Initialize sync |
-| `/api/cloud/*` | Various | Cloud management |
-
-### CLI Tools
-
-| Endpoint | Method | Description |
-| ---------------------------------- | ------ | ------------------- |
-| `/api/cli-tools/claude-settings` | GET | Claude CLI status |
-| `/api/cli-tools/codex-settings` | GET | Codex CLI status |
-| `/api/cli-tools/droid-settings` | GET | Droid CLI status |
-| `/api/cli-tools/openclaw-settings` | GET | OpenClaw CLI status |
-| `/api/cli-tools/runtime/[toolId]` | GET | Generic CLI runtime |
-
-CLI responses include: `installed`, `runnable`, `command`, `commandPath`, `runtimeMode`, `reason`.
-
-### ACP Agents
-
-| Endpoint | Method | Description |
-| ----------------- | ------ | -------------------------------------------------------- |
-| `/api/acp/agents` | GET | List all detected agents (built-in + custom) with status |
-| `/api/acp/agents` | POST | Add custom agent or refresh detection cache |
-| `/api/acp/agents` | DELETE | Remove a custom agent by `id` query param |
-
-GET response includes `agents[]` (id, name, binary, version, installed, protocol, isCustom) and `summary` (total, installed, notFound, builtIn, custom).
-
-### Resilience & Rate Limits
-
-| Endpoint | Method | Description |
-| ----------------------- | ------- | ------------------------------- |
-| `/api/resilience` | GET/PUT | Get/update resilience profiles |
-| `/api/resilience/reset` | POST | Reset circuit breakers |
-| `/api/rate-limits` | GET | Per-account rate limit status |
-| `/api/rate-limit` | GET | Global rate limit configuration |
-
-### Evals
-
-| Endpoint | Method | Description |
-| ------------ | -------- | --------------------------------- |
-| `/api/evals` | GET/POST | List eval suites / run evaluation |
-
-### Policies
-
-| Endpoint | Method | Description |
-| --------------- | --------------- | ----------------------- |
-| `/api/policies` | GET/POST/DELETE | Manage routing policies |
-
-### Compliance
-
-| Endpoint | Method | Description |
-| --------------------------- | ------ | ----------------------------- |
-| `/api/compliance/audit-log` | GET | Compliance audit log (last N) |
-
-### v1beta (Gemini-Compatible)
-
-| Endpoint | Method | Description |
-| -------------------------- | ------ | --------------------------------- |
-| `/v1beta/models` | GET | List models in Gemini format |
-| `/v1beta/models/{...path}` | POST | Gemini `generateContent` endpoint |
-
-These endpoints mirror Gemini's API format for clients that expect native Gemini SDK compatibility.
-
-### Internal / System APIs
-
-| Endpoint | Method | Description |
-| --------------- | ------ | ---------------------------------------------------- |
-| `/api/init` | GET | Application initialization check (used on first run) |
-| `/api/tags` | GET | Ollama-compatible model tags (for Ollama clients) |
-| `/api/restart` | POST | Trigger graceful server restart |
-| `/api/shutdown` | POST | Trigger graceful server shutdown |
-
-> **Note:** These endpoints are used internally by the system or for Ollama client compatibility. They are not typically called by end users.
-
----
-
-## Audio Transcription
-
-```bash
-POST /v1/audio/transcriptions
-Authorization: Bearer your-api-key
-Content-Type: multipart/form-data
-```
-
-Transcribe audio files using Deepgram or AssemblyAI.
-
-**Request:**
-
-```bash
-curl -X POST http://localhost:20128/v1/audio/transcriptions \
- -H "Authorization: Bearer your-api-key" \
- -F "file=@recording.mp3" \
- -F "model=deepgram/nova-3"
-```
-
-**Response:**
-
-```json
-{
- "text": "Hello, this is the transcribed audio content.",
- "task": "transcribe",
- "language": "en",
- "duration": 12.5
-}
-```
-
-**Supported providers:** `deepgram/nova-3`, `assemblyai/best`.
-
-**Supported formats:** `mp3`, `wav`, `m4a`, `flac`, `ogg`, `webm`.
-
----
-
-## Ollama Compatibility
-
-For clients that use Ollama's API format:
-
-```bash
-# Chat endpoint (Ollama format)
-POST /v1/api/chat
-
-# Model listing (Ollama format)
-GET /api/tags
-```
-
-Requests are automatically translated between Ollama and internal formats.
-
----
-
-## Telemetry
-
-```bash
-# Get latency telemetry summary (p50/p95/p99 per provider)
-GET /api/telemetry/summary
-```
-
-**Response:**
-
-```json
-{
- "providers": {
- "claudeCode": { "p50": 245, "p95": 890, "p99": 1200, "count": 150 },
- "github": { "p50": 180, "p95": 620, "p99": 950, "count": 320 }
- }
-}
-```
-
----
-
-## Budget
-
-```bash
-# Get budget status for all API keys
-GET /api/usage/budget
-
-# Set or update a budget
-POST /api/usage/budget
-Content-Type: application/json
-
-{
- "keyId": "key-123",
- "limit": 50.00,
- "period": "monthly"
-}
-```
-
----
-
-## Model Availability
-
-```bash
-# Get real-time model availability across all providers
-GET /api/models/availability
-
-# Check availability for a specific model
-POST /api/models/availability
-Content-Type: application/json
-
-{
- "model": "claude-sonnet-4-5-20250929"
-}
-```
-
----
-
-## Request Processing
-
-1. Client sends request to `/v1/*`
-2. Route handler calls `handleChat`, `handleEmbedding`, `handleAudioTranscription`, or `handleImageGeneration`
-3. Model is resolved (direct provider/model or alias/combo)
-4. Credentials selected from local DB with account availability filtering
-5. For chat: `handleChatCore` — format detection, translation, cache check, idempotency check
-6. Provider executor sends upstream request
-7. Response translated back to client format (chat) or returned as-is (embeddings/images/audio)
-8. Usage/logging recorded
-9. Fallback applies on errors according to combo rules
-
-Full architecture reference: [`ARCHITECTURE.md`](ARCHITECTURE.md)
-
----
-
-## Authentication
-
-- Dashboard routes (`/dashboard/*`) use `auth_token` cookie
-- Login uses saved password hash; fallback to `INITIAL_PASSWORD`
-- `requireLogin` toggleable via `/api/settings/require-login`
-- `/v1/*` routes optionally require Bearer API key when `REQUIRE_API_KEY=true`
diff --git a/docs/i18n/fi/ARCHITECTURE.md b/docs/i18n/fi/ARCHITECTURE.md
deleted file mode 100644
index 4ea06a29f2..0000000000
--- a/docs/i18n/fi/ARCHITECTURE.md
+++ /dev/null
@@ -1,787 +0,0 @@
-🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/ARCHITECTURE.md) · 🇪🇸 [es](../es/ARCHITECTURE.md) · 🇫🇷 [fr](../fr/ARCHITECTURE.md) · 🇩🇪 [de](../de/ARCHITECTURE.md) · 🇮🇹 [it](../it/ARCHITECTURE.md) · 🇷🇺 [ru](../ru/ARCHITECTURE.md) · 🇨🇳 [zh-CN](../zh-CN/ARCHITECTURE.md) · 🇯🇵 [ja](../ja/ARCHITECTURE.md) · 🇰🇷 [ko](../ko/ARCHITECTURE.md) · 🇸🇦 [ar](../ar/ARCHITECTURE.md) · 🇮🇳 [in](../in/ARCHITECTURE.md) · 🇹🇭 [th](../th/ARCHITECTURE.md) · 🇻🇳 [vi](../vi/ARCHITECTURE.md) · 🇮🇩 [id](../id/ARCHITECTURE.md) · 🇲🇾 [ms](../ms/ARCHITECTURE.md) · 🇳🇱 [nl](../nl/ARCHITECTURE.md) · 🇵🇱 [pl](../pl/ARCHITECTURE.md) · 🇸🇪 [sv](../sv/ARCHITECTURE.md) · 🇳🇴 [no](../no/ARCHITECTURE.md) · 🇩🇰 [da](../da/ARCHITECTURE.md) · 🇫🇮 [fi](../fi/ARCHITECTURE.md) · 🇵🇹 [pt](../pt/ARCHITECTURE.md) · 🇷🇴 [ro](../ro/ARCHITECTURE.md) · 🇭🇺 [hu](../hu/ARCHITECTURE.md) · 🇧🇬 [bg](../bg/ARCHITECTURE.md) · 🇸🇰 [sk](../sk/ARCHITECTURE.md) · 🇺🇦 [uk-UA](../uk-UA/ARCHITECTURE.md) · 🇮🇱 [he](../he/ARCHITECTURE.md) · 🇵🇭 [phi](../phi/ARCHITECTURE.md)
-
----
-
-# OmniRoute Architecture
-
-🌐 **Languages:** 🇺🇸 [English](ARCHITECTURE.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/ARCHITECTURE.md) | 🇪🇸 [Español](i18n/es/ARCHITECTURE.md) | 🇫🇷 [Français](i18n/fr/ARCHITECTURE.md) | 🇮🇹 [Italiano](i18n/it/ARCHITECTURE.md) | 🇷🇺 [Русский](i18n/ru/ARCHITECTURE.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/ARCHITECTURE.md) | 🇩🇪 [Deutsch](i18n/de/ARCHITECTURE.md) | 🇮🇳 [हिन्दी](i18n/in/ARCHITECTURE.md) | 🇹🇭 [ไทย](i18n/th/ARCHITECTURE.md) | 🇺🇦 [Українська](i18n/uk-UA/ARCHITECTURE.md) | 🇸🇦 [العربية](i18n/ar/ARCHITECTURE.md) | 🇯🇵 [日本語](i18n/ja/ARCHITECTURE.md) | 🇻🇳 [Tiếng Việt](i18n/vi/ARCHITECTURE.md) | 🇧🇬 [Български](i18n/bg/ARCHITECTURE.md) | 🇩🇰 [Dansk](i18n/da/ARCHITECTURE.md) | 🇫🇮 [Suomi](i18n/fi/ARCHITECTURE.md) | 🇮🇱 [עברית](i18n/he/ARCHITECTURE.md) | 🇭🇺 [Magyar](i18n/hu/ARCHITECTURE.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/ARCHITECTURE.md) | 🇰🇷 [한국어](i18n/ko/ARCHITECTURE.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/ARCHITECTURE.md) | 🇳🇱 [Nederlands](i18n/nl/ARCHITECTURE.md) | 🇳🇴 [Norsk](i18n/no/ARCHITECTURE.md) | 🇵🇹 [Português (Portugal)](i18n/pt/ARCHITECTURE.md) | 🇷🇴 [Română](i18n/ro/ARCHITECTURE.md) | 🇵🇱 [Polski](i18n/pl/ARCHITECTURE.md) | 🇸🇰 [Slovenčina](i18n/sk/ARCHITECTURE.md) | 🇸🇪 [Svenska](i18n/sv/ARCHITECTURE.md) | 🇵🇭 [Filipino](i18n/phi/ARCHITECTURE.md)
-
-_Last updated: 2026-03-04_
-
-## Executive Summary
-
-OmniRoute is a local AI routing gateway and dashboard built on Next.js.
-It provides a single OpenAI-compatible endpoint (`/v1/*`) and routes traffic across multiple upstream providers with translation, fallback, token refresh, and usage tracking.
-
-Core capabilities:
-
-- OpenAI-compatible API surface for CLI/tools (28 providers)
-- Request/response translation across provider formats
-- Model combo fallback (multi-model sequence)
-- Account-level fallback (multi-account per provider)
-- OAuth + API-key provider connection management
-- Embedding generation via `/v1/embeddings` (6 providers, 9 models)
-- Image generation via `/v1/images/generations` (4 providers, 9 models)
-- Think tag parsing (`...`) for reasoning models
-- Response sanitization for strict OpenAI SDK compatibility
-- Role normalization (developer→system, system→user) for cross-provider compatibility
-- Structured output conversion (json_schema → Gemini responseSchema)
-- Local persistence for providers, keys, aliases, combos, settings, pricing
-- Usage/cost tracking and request logging
-- Optional cloud sync for multi-device/state sync
-- IP allowlist/blocklist for API access control
-- Thinking budget management (passthrough/auto/custom/adaptive)
-- Global system prompt injection
-- Session tracking and fingerprinting
-- Per-account enhanced rate limiting with provider-specific profiles
-- Circuit breaker pattern for provider resilience
-- Anti-thundering herd protection with mutex locking
-- Signature-based request deduplication cache
-- Domain layer: model availability, cost rules, fallback policy, lockout policy
-- Domain state persistence (SQLite write-through cache for fallbacks, budgets, lockouts, circuit breakers)
-- Policy engine for centralized request evaluation (lockout → budget → fallback)
-- Request telemetry with p50/p95/p99 latency aggregation
-- Correlation ID (X-Request-Id) for end-to-end tracing
-- Compliance audit logging with opt-out per API key
-- Eval framework for LLM quality assurance
-- Resilience UI dashboard with real-time circuit breaker status
-- Modular OAuth providers (12 individual modules under `src/lib/oauth/providers/`)
-
-Primary runtime model:
-
-- Next.js app routes under `src/app/api/*` implement both dashboard APIs and compatibility APIs
-- A shared SSE/routing core in `src/sse/*` + `open-sse/*` handles provider execution, translation, streaming, fallback, and usage
-
-## Scope and Boundaries
-
-### In Scope
-
-- Local gateway runtime
-- Dashboard management APIs
-- Provider authentication and token refresh
-- Request translation and SSE streaming
-- Local state + usage persistence
-- Optional cloud sync orchestration
-
-### Out of Scope
-
-- Cloud service implementation behind `NEXT_PUBLIC_CLOUD_URL`
-- Provider SLA/control plane outside local process
-- External CLI binaries themselves (Claude CLI, Codex CLI, etc.)
-
-## High-Level System Context
-
-```mermaid
-flowchart LR
- subgraph Clients[Developer Clients]
- C1[Claude Code]
- C2[Codex CLI]
- C3[OpenClaw / Droid / Cline / Continue / Roo]
- C4[Custom OpenAI-compatible clients]
- BROWSER[Browser Dashboard]
- end
-
- subgraph Router[OmniRoute Local Process]
- API[V1 Compatibility API\n/v1/*]
- DASH[Dashboard + Management API\n/api/*]
- CORE[SSE + Translation Core\nopen-sse + src/sse]
- DB[(storage.sqlite)]
- UDB[(usage tables + log artifacts)]
- end
-
- subgraph Upstreams[Upstream Providers]
- P1[OAuth Providers\nClaude/Codex/Gemini/Qwen/Qoder/GitHub/Kiro/Cursor/Antigravity]
- P2[API Key Providers\nOpenAI/Anthropic/OpenRouter/GLM/Kimi/MiniMax\nDeepSeek/Groq/xAI/Mistral/Perplexity\nTogether/Fireworks/Cerebras/Cohere/NVIDIA]
- P3[Compatible Nodes\nOpenAI-compatible / Anthropic-compatible]
- end
-
- subgraph Cloud[Optional Cloud Sync]
- CLOUD[Cloud Sync Endpoint\nNEXT_PUBLIC_CLOUD_URL]
- end
-
- C1 --> API
- C2 --> API
- C3 --> API
- C4 --> API
- BROWSER --> DASH
-
- API --> CORE
- DASH --> DB
- CORE --> DB
- CORE --> UDB
-
- CORE --> P1
- CORE --> P2
- CORE --> P3
-
- DASH --> CLOUD
-```
-
-## Core Runtime Components
-
-## 1) API and Routing Layer (Next.js App Routes)
-
-Main directories:
-
-- `src/app/api/v1/*` and `src/app/api/v1beta/*` for compatibility APIs
-- `src/app/api/*` for management/configuration APIs
-- Next rewrites in `next.config.mjs` map `/v1/*` to `/api/v1/*`
-
-Important compatibility routes:
-
-- `src/app/api/v1/chat/completions/route.ts`
-- `src/app/api/v1/messages/route.ts`
-- `src/app/api/v1/responses/route.ts`
-- `src/app/api/v1/models/route.ts` — includes custom models with `custom: true`
-- `src/app/api/v1/embeddings/route.ts` — embedding generation (6 providers)
-- `src/app/api/v1/images/generations/route.ts` — image generation (4+ providers incl. Antigravity/Nebius)
-- `src/app/api/v1/messages/count_tokens/route.ts`
-- `src/app/api/v1/providers/[provider]/chat/completions/route.ts` — dedicated per-provider chat
-- `src/app/api/v1/providers/[provider]/embeddings/route.ts` — dedicated per-provider embeddings
-- `src/app/api/v1/providers/[provider]/images/generations/route.ts` — dedicated per-provider images
-- `src/app/api/v1beta/models/route.ts`
-- `src/app/api/v1beta/models/[...path]/route.ts`
-
-Management domains:
-
-- Auth/settings: `src/app/api/auth/*`, `src/app/api/settings/*`
-- Providers/connections: `src/app/api/providers*`
-- Provider nodes: `src/app/api/provider-nodes*`
-- Custom models: `src/app/api/provider-models` (GET/POST/DELETE)
-- Model catalog: `src/app/api/models/route.ts` (GET)
-- Proxy config: `src/app/api/settings/proxy` (GET/PUT/DELETE) + `src/app/api/settings/proxy/test` (POST)
-- OAuth: `src/app/api/oauth/*`
-- Keys/aliases/combos/pricing: `src/app/api/keys*`, `src/app/api/models/alias`, `src/app/api/combos*`, `src/app/api/pricing`
-- Usage: `src/app/api/usage/*`
-- Sync/cloud: `src/app/api/sync/*`, `src/app/api/cloud/*`
-- CLI tooling helpers: `src/app/api/cli-tools/*`
-- IP filter: `src/app/api/settings/ip-filter` (GET/PUT)
-- Thinking budget: `src/app/api/settings/thinking-budget` (GET/PUT)
-- System prompt: `src/app/api/settings/system-prompt` (GET/PUT)
-- Sessions: `src/app/api/sessions` (GET)
-- Rate limits: `src/app/api/rate-limits` (GET)
-- Resilience: `src/app/api/resilience` (GET/PATCH) — provider profiles, circuit breaker, rate limit state
-- Resilience reset: `src/app/api/resilience/reset` (POST) — reset breakers + cooldowns
-- Cache stats: `src/app/api/cache/stats` (GET/DELETE)
-- Model availability: `src/app/api/models/availability` (GET/POST)
-- Telemetry: `src/app/api/telemetry/summary` (GET)
-- Budget: `src/app/api/usage/budget` (GET/POST)
-- Fallback chains: `src/app/api/fallback/chains` (GET/POST/DELETE)
-- Compliance audit: `src/app/api/compliance/audit-log` (GET)
-- Evals: `src/app/api/evals` (GET/POST), `src/app/api/evals/[suiteId]` (GET)
-- Policies: `src/app/api/policies` (GET/POST)
-
-## 2) SSE + Translation Core
-
-Main flow modules:
-
-- Entry: `src/sse/handlers/chat.ts`
-- Core orchestration: `open-sse/handlers/chatCore.ts`
-- Provider execution adapters: `open-sse/executors/*`
-- Format detection/provider config: `open-sse/services/provider.ts`
-- Model parse/resolve: `src/sse/services/model.ts`, `open-sse/services/model.ts`
-- Account fallback logic: `open-sse/services/accountFallback.ts`
-- Translation registry: `open-sse/translator/index.ts`
-- Stream transformations: `open-sse/utils/stream.ts`, `open-sse/utils/streamHandler.ts`
-- Usage extraction/normalization: `open-sse/utils/usageTracking.ts`
-- Think tag parser: `open-sse/utils/thinkTagParser.ts`
-- Embedding handler: `open-sse/handlers/embeddings.ts`
-- Embedding provider registry: `open-sse/config/embeddingRegistry.ts`
-- Image generation handler: `open-sse/handlers/imageGeneration.ts`
-- Image provider registry: `open-sse/config/imageRegistry.ts`
-- Response sanitization: `open-sse/handlers/responseSanitizer.ts`
-- Role normalization: `open-sse/services/roleNormalizer.ts`
-
-Services (business logic):
-
-- Account selection/scoring: `open-sse/services/accountSelector.ts`
-- Context lifecycle management: `open-sse/services/contextManager.ts`
-- IP filter enforcement: `open-sse/services/ipFilter.ts`
-- Session tracking: `open-sse/services/sessionManager.ts`
-- Request deduplication: `open-sse/services/signatureCache.ts`
-- System prompt injection: `open-sse/services/systemPrompt.ts`
-- Thinking budget management: `open-sse/services/thinkingBudget.ts`
-- Wildcard model routing: `open-sse/services/wildcardRouter.ts`
-- Rate limit management: `open-sse/services/rateLimitManager.ts`
-- Circuit breaker: `open-sse/services/circuitBreaker.ts`
-
-Domain layer modules:
-
-- Model availability: `src/lib/domain/modelAvailability.ts`
-- Cost rules/budgets: `src/lib/domain/costRules.ts`
-- Fallback policy: `src/lib/domain/fallbackPolicy.ts`
-- Combo resolver: `src/lib/domain/comboResolver.ts`
-- Lockout policy: `src/lib/domain/lockoutPolicy.ts`
-- Policy engine: `src/domain/policyEngine.ts` — centralized lockout → budget → fallback evaluation
-- Error codes catalog: `src/lib/domain/errorCodes.ts`
-- Request ID: `src/lib/domain/requestId.ts`
-- Fetch timeout: `src/lib/domain/fetchTimeout.ts`
-- Request telemetry: `src/lib/domain/requestTelemetry.ts`
-- Compliance/audit: `src/lib/domain/compliance/index.ts`
-- Eval runner: `src/lib/domain/evalRunner.ts`
-- Domain state persistence: `src/lib/db/domainState.ts` — SQLite CRUD for fallback chains, budgets, cost history, lockout state, circuit breakers
-
-OAuth provider modules (12 individual files under `src/lib/oauth/providers/`):
-
-- Registry index: `src/lib/oauth/providers/index.ts`
-- Individual providers: `claude.ts`, `codex.ts`, `gemini.ts`, `antigravity.ts`, `qoder.ts`, `qwen.ts`, `kimi-coding.ts`, `github.ts`, `kiro.ts`, `cursor.ts`, `kilocode.ts`, `cline.ts`
-- Thin wrapper: `src/lib/oauth/providers.ts` — re-exports from individual modules
-
-## 3) Persistence Layer
-
-Primary state DB (SQLite):
-
-- Core infra: `src/lib/db/core.ts` (better-sqlite3, migrations, WAL)
-- Re-export facade: `src/lib/localDb.ts` (thin compatibility layer for callers)
-- file: `${DATA_DIR}/storage.sqlite` (or `$XDG_CONFIG_HOME/omniroute/storage.sqlite` when set, else `~/.omniroute/storage.sqlite`)
-- entities (tables + KV namespaces): providerConnections, providerNodes, modelAliases, combos, apiKeys, settings, pricing, **customModels**, **proxyConfig**, **ipFilter**, **thinkingBudget**, **systemPrompt**
-
-Usage persistence:
-
-- facade: `src/lib/usageDb.ts` (decomposed modules in `src/lib/usage/*`)
-- SQLite tables in `storage.sqlite`: `usage_history`, `call_logs`, `proxy_logs`
-- optional file artifacts remain for compatibility/debug (`${DATA_DIR}/log.txt`, `${DATA_DIR}/call_logs/`, `/logs/...`)
-- legacy JSON files are migrated to SQLite by startup migrations when present
-
-Domain State DB (SQLite):
-
-- `src/lib/db/domainState.ts` — CRUD operations for domain state
-- Tables (created in `src/lib/db/core.ts`): `domain_fallback_chains`, `domain_budgets`, `domain_cost_history`, `domain_lockout_state`, `domain_circuit_breakers`
-- Write-through cache pattern: in-memory Maps are authoritative at runtime; mutations are written synchronously to SQLite; state is restored from DB on cold start
-
-## 4) Auth + Security Surfaces
-
-- Dashboard cookie auth: `src/proxy.ts`, `src/app/api/auth/login/route.ts`
-- API key generation/verification: `src/shared/utils/apiKey.ts`
-- Provider secrets persisted in `providerConnections` entries
-- Outbound proxy support via `open-sse/utils/proxyFetch.ts` (env vars) and `open-sse/utils/networkProxy.ts` (configurable per-provider or global)
-
-## 5) Cloud Sync
-
-- Scheduler init: `src/lib/initCloudSync.ts`, `src/shared/services/initializeCloudSync.ts`
-- Periodic task: `src/shared/services/cloudSyncScheduler.ts`
-- Control route: `src/app/api/sync/cloud/route.ts`
-
-## Request Lifecycle (`/v1/chat/completions`)
-
-```mermaid
-sequenceDiagram
- autonumber
- participant Client as CLI/SDK Client
- participant Route as /api/v1/chat/completions
- participant Chat as src/sse/handlers/chat
- participant Core as open-sse/handlers/chatCore
- participant Model as Model Resolver
- participant Auth as Credential Selector
- participant Exec as Provider Executor
- participant Prov as Upstream Provider
- participant Stream as Stream Translator
- participant Usage as usageDb
-
- Client->>Route: POST /v1/chat/completions
- Route->>Chat: handleChat(request)
- Chat->>Model: parse/resolve model or combo
-
- alt Combo model
- Chat->>Chat: iterate combo models (handleComboChat)
- end
-
- Chat->>Auth: getProviderCredentials(provider)
- Auth-->>Chat: active account + tokens/api key
-
- Chat->>Core: handleChatCore(body, modelInfo, credentials)
- Core->>Core: detect source format
- Core->>Core: translate request to target format
- Core->>Exec: execute(provider, transformedBody)
- Exec->>Prov: upstream API call
- Prov-->>Exec: SSE/JSON response
- Exec-->>Core: response + metadata
-
- alt 401/403
- Core->>Exec: refreshCredentials()
- Exec-->>Core: updated tokens
- Core->>Exec: retry request
- end
-
- Core->>Stream: translate/normalize stream to client format
- Stream-->>Client: SSE chunks / JSON response
-
- Stream->>Usage: extract usage + persist history/log
-```
-
-## Combo + Account Fallback Flow
-
-```mermaid
-flowchart TD
- A[Incoming model string] --> B{Is combo name?}
- B -- Yes --> C[Load combo models sequence]
- B -- No --> D[Single model path]
-
- C --> E[Try model N]
- E --> F[Resolve provider/model]
- D --> F
-
- F --> G[Select account credentials]
- G --> H{Credentials available?}
- H -- No --> I[Return provider unavailable]
- H -- Yes --> J[Execute request]
-
- J --> K{Success?}
- K -- Yes --> L[Return response]
- K -- No --> M{Fallback-eligible error?}
-
- M -- No --> N[Return error]
- M -- Yes --> O[Mark account unavailable cooldown]
- O --> P{Another account for provider?}
- P -- Yes --> G
- P -- No --> Q{In combo with next model?}
- Q -- Yes --> E
- Q -- No --> R[Return all unavailable]
-```
-
-Fallback decisions are driven by `open-sse/services/accountFallback.ts` using status codes and error-message heuristics.
-
-## OAuth Onboarding and Token Refresh Lifecycle
-
-```mermaid
-sequenceDiagram
- autonumber
- participant UI as Dashboard UI
- participant OAuth as /api/oauth/[provider]/[action]
- participant ProvAuth as Provider Auth Server
- participant DB as localDb
- participant Test as /api/providers/[id]/test
- participant Exec as Provider Executor
-
- UI->>OAuth: GET authorize or device-code
- OAuth->>ProvAuth: create auth/device flow
- ProvAuth-->>OAuth: auth URL or device code payload
- OAuth-->>UI: flow data
-
- UI->>OAuth: POST exchange or poll
- OAuth->>ProvAuth: token exchange/poll
- ProvAuth-->>OAuth: access/refresh tokens
- OAuth->>DB: createProviderConnection(oauth data)
- OAuth-->>UI: success + connection id
-
- UI->>Test: POST /api/providers/[id]/test
- Test->>Exec: validate credentials / optional refresh
- Exec-->>Test: valid or refreshed token info
- Test->>DB: update status/tokens/errors
- Test-->>UI: validation result
-```
-
-Refresh during live traffic is executed inside `open-sse/handlers/chatCore.ts` via executor `refreshCredentials()`.
-
-## Cloud Sync Lifecycle (Enable / Sync / Disable)
-
-```mermaid
-sequenceDiagram
- autonumber
- participant UI as Endpoint Page UI
- participant Sync as /api/sync/cloud
- participant DB as localDb
- participant Cloud as External Cloud Sync
- participant Claude as ~/.claude/settings.json
-
- UI->>Sync: POST action=enable
- Sync->>DB: set cloudEnabled=true
- Sync->>DB: ensure API key exists
- Sync->>Cloud: POST /sync/{machineId} (providers/aliases/combos/keys)
- Cloud-->>Sync: sync result
- Sync->>Cloud: GET /{machineId}/v1/verify
- Sync-->>UI: enabled + verification status
-
- UI->>Sync: POST action=sync
- Sync->>Cloud: POST /sync/{machineId}
- Cloud-->>Sync: remote data
- Sync->>DB: update newer local tokens/status
- Sync-->>UI: synced
-
- UI->>Sync: POST action=disable
- Sync->>DB: set cloudEnabled=false
- Sync->>Cloud: DELETE /sync/{machineId}
- Sync->>Claude: switch ANTHROPIC_BASE_URL back to local (if needed)
- Sync-->>UI: disabled
-```
-
-Periodic sync is triggered by `CloudSyncScheduler` when cloud is enabled.
-
-## Data Model and Storage Map
-
-```mermaid
-erDiagram
- SETTINGS ||--o{ PROVIDER_CONNECTION : controls
- PROVIDER_NODE ||--o{ PROVIDER_CONNECTION : backs_compatible_provider
- PROVIDER_CONNECTION ||--o{ USAGE_ENTRY : emits_usage
-
- SETTINGS {
- boolean cloudEnabled
- number stickyRoundRobinLimit
- boolean requireLogin
- string password_hash
- string fallbackStrategy
- json rateLimitDefaults
- json providerProfiles
- }
-
- PROVIDER_CONNECTION {
- string id
- string provider
- string authType
- string name
- number priority
- boolean isActive
- string apiKey
- string accessToken
- string refreshToken
- string expiresAt
- string testStatus
- string lastError
- string rateLimitedUntil
- json providerSpecificData
- }
-
- PROVIDER_NODE {
- string id
- string type
- string name
- string prefix
- string apiType
- string baseUrl
- }
-
- MODEL_ALIAS {
- string alias
- string targetModel
- }
-
- COMBO {
- string id
- string name
- string[] models
- }
-
- API_KEY {
- string id
- string name
- string key
- string machineId
- }
-
- USAGE_ENTRY {
- string provider
- string model
- number prompt_tokens
- number completion_tokens
- string connectionId
- string timestamp
- }
-
- CUSTOM_MODEL {
- string id
- string name
- string providerId
- }
-
- PROXY_CONFIG {
- string global
- json providers
- }
-
- IP_FILTER {
- string mode
- string[] allowlist
- string[] blocklist
- }
-
- THINKING_BUDGET {
- string mode
- number customBudget
- string effortLevel
- }
-
- SYSTEM_PROMPT {
- boolean enabled
- string prompt
- string position
- }
-```
-
-Physical storage files:
-
-- primary runtime DB: `${DATA_DIR}/storage.sqlite`
-- request log lines: `${DATA_DIR}/log.txt` (compat/debug artifact)
-- structured call payload archives: `${DATA_DIR}/call_logs/`
-- optional translator/request debug sessions: `/logs/...`
-
-## Deployment Topology
-
-```mermaid
-flowchart LR
- subgraph LocalHost[Developer Host]
- CLI[CLI Tools]
- Browser[Dashboard Browser]
- end
-
- subgraph ContainerOrProcess[OmniRoute Runtime]
- Next[Next.js Server\nPORT=20128]
- Core[SSE Core + Executors]
- MainDB[(storage.sqlite)]
- UsageDB[(usage tables + log artifacts)]
- end
-
- subgraph External[External Services]
- Providers[AI Providers]
- SyncCloud[Cloud Sync Service]
- end
-
- CLI --> Next
- Browser --> Next
- Next --> Core
- Next --> MainDB
- Core --> MainDB
- Core --> UsageDB
- Core --> Providers
- Next --> SyncCloud
-```
-
-## Module Mapping (Decision-Critical)
-
-### Route and API Modules
-
-- `src/app/api/v1/*`, `src/app/api/v1beta/*`: compatibility APIs
-- `src/app/api/v1/providers/[provider]/*`: dedicated per-provider routes (chat, embeddings, images)
-- `src/app/api/providers*`: provider CRUD, validation, testing
-- `src/app/api/provider-nodes*`: custom compatible node management
-- `src/app/api/provider-models`: custom model management (CRUD)
-- `src/app/api/models/route.ts`: model catalog API (aliases + custom models)
-- `src/app/api/oauth/*`: OAuth/device-code flows
-- `src/app/api/keys*`: local API key lifecycle
-- `src/app/api/models/alias`: alias management
-- `src/app/api/combos*`: fallback combo management
-- `src/app/api/pricing`: pricing overrides for cost calculation
-- `src/app/api/settings/proxy`: proxy configuration (GET/PUT/DELETE)
-- `src/app/api/settings/proxy/test`: outbound proxy connectivity test (POST)
-- `src/app/api/usage/*`: usage and logs APIs
-- `src/app/api/sync/*` + `src/app/api/cloud/*`: cloud sync and cloud-facing helpers
-- `src/app/api/cli-tools/*`: local CLI config writers/checkers
-- `src/app/api/settings/ip-filter`: IP allowlist/blocklist (GET/PUT)
-- `src/app/api/settings/thinking-budget`: thinking token budget config (GET/PUT)
-- `src/app/api/settings/system-prompt`: global system prompt (GET/PUT)
-- `src/app/api/sessions`: active session listing (GET)
-- `src/app/api/rate-limits`: per-account rate limit status (GET)
-
-### Routing and Execution Core
-
-- `src/sse/handlers/chat.ts`: request parse, combo handling, account selection loop
-- `open-sse/handlers/chatCore.ts`: translation, executor dispatch, retry/refresh handling, stream setup
-- `open-sse/executors/*`: provider-specific network and format behavior
-
-### Translation Registry and Format Converters
-
-- `open-sse/translator/index.ts`: translator registry and orchestration
-- Request translators: `open-sse/translator/request/*`
-- Response translators: `open-sse/translator/response/*`
-- Format constants: `open-sse/translator/formats.ts`
-
-### Persistence
-
-- `src/lib/db/*`: persistent config/state and domain persistence on SQLite
-- `src/lib/localDb.ts`: compatibility re-export for DB modules
-- `src/lib/usageDb.ts`: usage history/call logs facade on top of SQLite tables
-
-## Provider Executor Coverage (Strategy Pattern)
-
-Each provider has a specialized executor extending `BaseExecutor` (in `open-sse/executors/base.ts`), which provides URL building, header construction, retry with exponential backoff, credential refresh hooks, and the `execute()` orchestration method.
-
-| Executor | Provider(s) | Special Handling |
-| --------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------ | -------------------------------------------------------------------- |
-| `DefaultExecutor` | OpenAI, Claude, Gemini, Qwen, Qoder, OpenRouter, GLM, Kimi, MiniMax, DeepSeek, Groq, xAI, Mistral, Perplexity, Together, Fireworks, Cerebras, Cohere, NVIDIA | Dynamic URL/header config per provider |
-| `AntigravityExecutor` | Google Antigravity | Custom project/session IDs, Retry-After parsing |
-| `CodexExecutor` | OpenAI Codex | Injects system instructions, forces reasoning effort |
-| `CursorExecutor` | Cursor IDE | ConnectRPC protocol, Protobuf encoding, request signing via checksum |
-| `GithubExecutor` | GitHub Copilot | Copilot token refresh, VSCode-mimicking headers |
-| `KiroExecutor` | AWS CodeWhisperer/Kiro | AWS EventStream binary format → SSE conversion |
-| `GeminiCLIExecutor` | Gemini CLI | Google OAuth token refresh cycle |
-
-All other providers (including custom compatible nodes) use the `DefaultExecutor`.
-
-## Provider Compatibility Matrix
-
-| Provider | Format | Auth | Stream | Non-Stream | Token Refresh | Usage API |
-| ---------------- | ---------------- | --------------------- | ---------------- | ---------- | ------------- | ------------------ |
-| Claude | claude | API Key / OAuth | ✅ | ✅ | ✅ | ⚠️ Admin only |
-| Gemini | gemini | API Key / OAuth | ✅ | ✅ | ✅ | ⚠️ Cloud Console |
-| Gemini CLI | gemini-cli | OAuth | ✅ | ✅ | ✅ | ⚠️ Cloud Console |
-| Antigravity | antigravity | OAuth | ✅ | ✅ | ✅ | ✅ Full quota API |
-| OpenAI | openai | API Key | ✅ | ✅ | ❌ | ❌ |
-| Codex | openai-responses | OAuth | ✅ forced | ❌ | ✅ | ✅ Rate limits |
-| GitHub Copilot | openai | OAuth + Copilot Token | ✅ | ✅ | ✅ | ✅ Quota snapshots |
-| Cursor | cursor | Custom checksum | ✅ | ✅ | ❌ | ❌ |
-| Kiro | kiro | AWS SSO OIDC | ✅ (EventStream) | ❌ | ✅ | ✅ Usage limits |
-| Qwen | openai | OAuth | ✅ | ✅ | ✅ | ⚠️ Per request |
-| Qoder | openai | OAuth (Basic) | ✅ | ✅ | ✅ | ⚠️ Per request |
-| OpenRouter | openai | API Key | ✅ | ✅ | ❌ | ❌ |
-| GLM/Kimi/MiniMax | claude | API Key | ✅ | ✅ | ❌ | ❌ |
-| DeepSeek | openai | API Key | ✅ | ✅ | ❌ | ❌ |
-| Groq | openai | API Key | ✅ | ✅ | ❌ | ❌ |
-| xAI (Grok) | openai | API Key | ✅ | ✅ | ❌ | ❌ |
-| Mistral | openai | API Key | ✅ | ✅ | ❌ | ❌ |
-| Perplexity | openai | API Key | ✅ | ✅ | ❌ | ❌ |
-| Together AI | openai | API Key | ✅ | ✅ | ❌ | ❌ |
-| Fireworks AI | openai | API Key | ✅ | ✅ | ❌ | ❌ |
-| Cerebras | openai | API Key | ✅ | ✅ | ❌ | ❌ |
-| Cohere | openai | API Key | ✅ | ✅ | ❌ | ❌ |
-| NVIDIA NIM | openai | API Key | ✅ | ✅ | ❌ | ❌ |
-
-## Format Translation Coverage
-
-Detected source formats include:
-
-- `openai`
-- `openai-responses`
-- `claude`
-- `gemini`
-
-Target formats include:
-
-- OpenAI chat/Responses
-- Claude
-- Gemini/Gemini-CLI/Antigravity envelope
-- Kiro
-- Cursor
-
-Translations use **OpenAI as the hub format** — all conversions go through OpenAI as intermediate:
-
-```
-Source Format → OpenAI (hub) → Target Format
-```
-
-Translations are selected dynamically based on source payload shape and provider target format.
-
-Additional processing layers in the translation pipeline:
-
-- **Response sanitization** — Strips non-standard fields from OpenAI-format responses (both streaming and non-streaming) to ensure strict SDK compliance
-- **Role normalization** — Converts `developer` → `system` for non-OpenAI targets; merges `system` → `user` for models that reject the system role (GLM, ERNIE)
-- **Think tag extraction** — Parses `...` blocks from content into `reasoning_content` field
-- **Structured output** — Converts OpenAI `response_format.json_schema` to Gemini's `responseMimeType` + `responseSchema`
-
-## Supported API Endpoints
-
-| Endpoint | Format | Handler |
-| -------------------------------------------------- | ------------------ | ---------------------------------------------------- |
-| `POST /v1/chat/completions` | OpenAI Chat | `src/sse/handlers/chat.ts` |
-| `POST /v1/messages` | Claude Messages | Same handler (auto-detected) |
-| `POST /v1/responses` | OpenAI Responses | `open-sse/handlers/responsesHandler.ts` |
-| `POST /v1/embeddings` | OpenAI Embeddings | `open-sse/handlers/embeddings.ts` |
-| `GET /v1/embeddings` | Model listing | API route |
-| `POST /v1/images/generations` | OpenAI Images | `open-sse/handlers/imageGeneration.ts` |
-| `GET /v1/images/generations` | Model listing | API route |
-| `POST /v1/providers/{provider}/chat/completions` | OpenAI Chat | Dedicated per-provider with model validation |
-| `POST /v1/providers/{provider}/embeddings` | OpenAI Embeddings | Dedicated per-provider with model validation |
-| `POST /v1/providers/{provider}/images/generations` | OpenAI Images | Dedicated per-provider with model validation |
-| `POST /v1/messages/count_tokens` | Claude Token Count | API route |
-| `GET /v1/models` | OpenAI Models list | API route (chat + embedding + image + custom models) |
-| `GET /api/models/catalog` | Catalog | All models grouped by provider + type |
-| `POST /v1beta/models/*:streamGenerateContent` | Gemini native | API route |
-| `GET/PUT/DELETE /api/settings/proxy` | Proxy Config | Network proxy configuration |
-| `POST /api/settings/proxy/test` | Proxy Connectivity | Proxy health/connectivity test endpoint |
-| `GET/POST/DELETE /api/provider-models` | Custom Models | Custom model management per provider |
-
-## Bypass Handler
-
-The bypass handler (`open-sse/utils/bypassHandler.ts`) intercepts known "throwaway" requests from Claude CLI — warmup pings, title extractions, and token counts — and returns a **fake response** without consuming upstream provider tokens. This is triggered only when `User-Agent` contains `claude-cli`.
-
-## Request Logger Pipeline
-
-The request logger (`open-sse/utils/requestLogger.ts`) provides a 7-stage debug logging pipeline, disabled by default, enabled via `ENABLE_REQUEST_LOGS=true`:
-
-```
-1_req_client.json → 2_req_source.json → 3_req_openai.json → 4_req_target.json
-→ 5_res_provider.txt → 6_res_openai.txt → 7_res_client.txt
-```
-
-Files are written to `/logs//` for each request session.
-
-## Failure Modes and Resilience
-
-## 1) Account/Provider Availability
-
-- provider account cooldown on transient/rate/auth errors
-- account fallback before failing request
-- combo model fallback when current model/provider path is exhausted
-
-## 2) Token Expiry
-
-- pre-check and refresh with retry for refreshable providers
-- 401/403 retry after refresh attempt in core path
-
-## 3) Stream Safety
-
-- disconnect-aware stream controller
-- translation stream with end-of-stream flush and `[DONE]` handling
-- usage estimation fallback when provider usage metadata is missing
-
-## 4) Cloud Sync Degradation
-
-- sync errors are surfaced but local runtime continues
-- scheduler has retry-capable logic, but periodic execution currently calls single-attempt sync by default
-
-## 5) Data Integrity
-
-- SQLite schema migrations and auto-upgrade hooks at startup
-- legacy JSON → SQLite migration compatibility path
-
-## Observability and Operational Signals
-
-Runtime visibility sources:
-
-- console logs from `src/sse/utils/logger.ts`
-- per-request usage aggregates in SQLite (`usage_history`, `call_logs`, `proxy_logs`)
-- textual request status log in `log.txt` (optional/compat)
-- optional deep request/translation logs under `logs/` when `ENABLE_REQUEST_LOGS=true`
-- dashboard usage endpoints (`/api/usage/*`) for UI consumption
-
-## Security-Sensitive Boundaries
-
-- JWT secret (`JWT_SECRET`) secures dashboard session cookie verification/signing
-- Initial password bootstrap (`INITIAL_PASSWORD`) should be explicitly configured for first-run provisioning
-- API key HMAC secret (`API_KEY_SECRET`) secures generated local API key format
-- Provider secrets (API keys/tokens) are persisted in local DB and should be protected at filesystem level
-- Cloud sync endpoints rely on API key auth + machine id semantics
-
-## Environment and Runtime Matrix
-
-Environment variables actively used by code:
-
-- App/auth: `JWT_SECRET`, `INITIAL_PASSWORD`
-- Storage: `DATA_DIR`
-- Compatible node behavior: `ALLOW_MULTI_CONNECTIONS_PER_COMPAT_NODE`
-- Optional storage base override (Linux/macOS when `DATA_DIR` unset): `XDG_CONFIG_HOME`
-- Security hashing: `API_KEY_SECRET`, `MACHINE_ID_SALT`
-- Logging: `ENABLE_REQUEST_LOGS`
-- Sync/cloud URLing: `NEXT_PUBLIC_BASE_URL`, `NEXT_PUBLIC_CLOUD_URL`
-- Outbound proxy: `HTTP_PROXY`, `HTTPS_PROXY`, `ALL_PROXY`, `NO_PROXY` and lowercase variants
-- SOCKS5 feature flags: `ENABLE_SOCKS5_PROXY`, `NEXT_PUBLIC_ENABLE_SOCKS5_PROXY`
-- Platform/runtime helpers (not app-specific config): `APPDATA`, `NODE_ENV`, `PORT`, `HOSTNAME`
-
-## Known Architectural Notes
-
-1. `usageDb` and `localDb` share the same base directory policy (`DATA_DIR` -> `XDG_CONFIG_HOME/omniroute` -> `~/.omniroute`) with legacy file migration.
-2. `/api/v1/route.ts` delegates to the same unified catalog builder used by `/api/v1/models` (`src/app/api/v1/models/catalog.ts`) to avoid semantic drift.
-3. Request logger writes full headers/body when enabled; treat log directory as sensitive.
-4. Cloud behavior depends on correct `NEXT_PUBLIC_BASE_URL` and cloud endpoint reachability.
-5. The `open-sse/` directory is published as the `@omniroute/open-sse` **npm workspace package**. Source code imports it via `@omniroute/open-sse/...` (resolved by Next.js `transpilePackages`). File paths in this document still use the directory name `open-sse/` for consistency.
-6. Charts in the dashboard use **Recharts** (SVG-based) for accessible, interactive analytics visualizations (model usage bar charts, provider breakdown tables with success rates).
-7. E2E tests use **Playwright** (`tests/e2e/`), run via `npm run test:e2e`. Unit tests use **Node.js test runner** (`tests/unit/`), run via `npm run test:unit`. Source code under `src/` is **TypeScript** (`.ts`/`.tsx`); the `open-sse/` workspace remains JavaScript (`.js`).
-8. Settings page is organized into 5 tabs: Security, Routing (6 global strategies: fill-first, round-robin, p2c, random, least-used, cost-optimized), Resilience (editable rate limits, circuit breaker, policies), AI (thinking budget, system prompt, prompt cache), Advanced (proxy).
-
-## Operational Verification Checklist
-
-- Build from source: `npm run build`
-- Build Docker image: `docker build -t omniroute .`
-- Start service and verify:
-- `GET /api/settings`
-- `GET /api/v1/models`
-- CLI target base URL should be `http://:20128/v1` when `PORT=20128`
diff --git a/docs/i18n/fi/AUTO-COMBO.md b/docs/i18n/fi/AUTO-COMBO.md
deleted file mode 100644
index 2166e41dff..0000000000
--- a/docs/i18n/fi/AUTO-COMBO.md
+++ /dev/null
@@ -1,67 +0,0 @@
-🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/AUTO-COMBO.md) · 🇪🇸 [es](../es/AUTO-COMBO.md) · 🇫🇷 [fr](../fr/AUTO-COMBO.md) · 🇩🇪 [de](../de/AUTO-COMBO.md) · 🇮🇹 [it](../it/AUTO-COMBO.md) · 🇷🇺 [ru](../ru/AUTO-COMBO.md) · 🇨🇳 [zh-CN](../zh-CN/AUTO-COMBO.md) · 🇯🇵 [ja](../ja/AUTO-COMBO.md) · 🇰🇷 [ko](../ko/AUTO-COMBO.md) · 🇸🇦 [ar](../ar/AUTO-COMBO.md) · 🇮🇳 [in](../in/AUTO-COMBO.md) · 🇹🇭 [th](../th/AUTO-COMBO.md) · 🇻🇳 [vi](../vi/AUTO-COMBO.md) · 🇮🇩 [id](../id/AUTO-COMBO.md) · 🇲🇾 [ms](../ms/AUTO-COMBO.md) · 🇳🇱 [nl](../nl/AUTO-COMBO.md) · 🇵🇱 [pl](../pl/AUTO-COMBO.md) · 🇸🇪 [sv](../sv/AUTO-COMBO.md) · 🇳🇴 [no](../no/AUTO-COMBO.md) · 🇩🇰 [da](../da/AUTO-COMBO.md) · 🇫🇮 [fi](../fi/AUTO-COMBO.md) · 🇵🇹 [pt](../pt/AUTO-COMBO.md) · 🇷🇴 [ro](../ro/AUTO-COMBO.md) · 🇭🇺 [hu](../hu/AUTO-COMBO.md) · 🇧🇬 [bg](../bg/AUTO-COMBO.md) · 🇸🇰 [sk](../sk/AUTO-COMBO.md) · 🇺🇦 [uk-UA](../uk-UA/AUTO-COMBO.md) · 🇮🇱 [he](../he/AUTO-COMBO.md) · 🇵🇭 [phi](../phi/AUTO-COMBO.md)
-
----
-
-# OmniRoute Auto-Combo Engine
-
-> Self-managing model chains with adaptive scoring
-
-## How It Works
-
-The Auto-Combo Engine dynamically selects the best provider/model for each request using a **6-factor scoring function**:
-
-| Factor | Weight | Description |
-| :--------- | :----- | :---------------------------------------------- |
-| Quota | 0.20 | Remaining capacity [0..1] |
-| Health | 0.25 | Circuit breaker: CLOSED=1.0, HALF=0.5, OPEN=0.0 |
-| CostInv | 0.20 | Inverse cost (cheaper = higher score) |
-| LatencyInv | 0.15 | Inverse p95 latency (faster = higher) |
-| TaskFit | 0.10 | Model × task type fitness score |
-| Stability | 0.10 | Low variance in latency/errors |
-
-## Mode Packs
-
-| Pack | Focus | Key Weight |
-| :---------------------- | :----------- | :--------------- |
-| 🚀 **Ship Fast** | Speed | latencyInv: 0.35 |
-| 💰 **Cost Saver** | Economy | costInv: 0.40 |
-| 🎯 **Quality First** | Best model | taskFit: 0.40 |
-| 📡 **Offline Friendly** | Availability | quota: 0.40 |
-
-## Self-Healing
-
-- **Temporary exclusion**: Score < 0.2 → excluded for 5 min (progressive backoff, max 30 min)
-- **Circuit breaker awareness**: OPEN → auto-excluded; HALF_OPEN → probe requests
-- **Incident mode**: >50% OPEN → disable exploration, maximize stability
-- **Cooldown recovery**: After exclusion, first request is a "probe" with reduced timeout
-
-## Bandit Exploration
-
-5% of requests (configurable) are routed to random providers for exploration. Disabled in incident mode.
-
-## API
-
-```bash
-# Create auto-combo
-curl -X POST http://localhost:20128/api/combos/auto \
- -H "Content-Type: application/json" \
- -d '{"id":"my-auto","name":"Auto Coder","candidatePool":["anthropic","google","openai"],"modePack":"ship-fast"}'
-
-# List auto-combos
-curl http://localhost:20128/api/combos/auto
-```
-
-## Task Fitness
-
-30+ models scored across 6 task types (`coding`, `review`, `planning`, `analysis`, `debugging`, `documentation`). Supports wildcard patterns (e.g., `*-coder` → high coding score).
-
-## Files
-
-| File | Purpose |
-| :------------------------------------------- | :------------------------------------ |
-| `open-sse/services/autoCombo/scoring.ts` | Scoring function & pool normalization |
-| `open-sse/services/autoCombo/taskFitness.ts` | Model × task fitness lookup |
-| `open-sse/services/autoCombo/engine.ts` | Selection logic, bandit, budget cap |
-| `open-sse/services/autoCombo/selfHealing.ts` | Exclusion, probes, incident mode |
-| `open-sse/services/autoCombo/modePacks.ts` | 4 weight profiles |
-| `src/app/api/combos/auto/route.ts` | REST API |
diff --git a/docs/i18n/fi/CHANGELOG.md b/docs/i18n/fi/CHANGELOG.md
index 5aa4367d18..852d728046 100644
--- a/docs/i18n/fi/CHANGELOG.md
+++ b/docs/i18n/fi/CHANGELOG.md
@@ -1,12 +1,92 @@
# Changelog (Suomi)
-🌐 **Languages:** 🇺🇸 [English](../../../CHANGELOG.md) · 🇪🇸 [es](../es/CHANGELOG.md) · 🇫🇷 [fr](../fr/CHANGELOG.md) · 🇩🇪 [de](../de/CHANGELOG.md) · 🇮🇹 [it](../it/CHANGELOG.md) · 🇷🇺 [ru](../ru/CHANGELOG.md) · 🇨🇳 [zh-CN](../zh-CN/CHANGELOG.md) · 🇯🇵 [ja](../ja/CHANGELOG.md) · 🇰🇷 [ko](../ko/CHANGELOG.md) · 🇸🇦 [ar](../ar/CHANGELOG.md) · 🇮🇳 [in](../in/CHANGELOG.md) · 🇹🇭 [th](../th/CHANGELOG.md) · 🇻🇳 [vi](../vi/CHANGELOG.md) · 🇮🇩 [id](../id/CHANGELOG.md) · 🇲🇾 [ms](../ms/CHANGELOG.md) · 🇳🇱 [nl](../nl/CHANGELOG.md) · 🇵🇱 [pl](../pl/CHANGELOG.md) · 🇸🇪 [sv](../sv/CHANGELOG.md) · 🇳🇴 [no](../no/CHANGELOG.md) · 🇩🇰 [da](../da/CHANGELOG.md) · 🇫🇮 [fi](../fi/CHANGELOG.md) · 🇵🇹 [pt](../pt/CHANGELOG.md) · 🇷🇴 [ro](../ro/CHANGELOG.md) · 🇭🇺 [hu](../hu/CHANGELOG.md) · 🇧🇬 [bg](../bg/CHANGELOG.md) · 🇸🇰 [sk](../sk/CHANGELOG.md) · 🇺🇦 [uk-UA](../uk-UA/CHANGELOG.md) · 🇮🇱 [he](../he/CHANGELOG.md) · 🇵🇭 [phi](../phi/CHANGELOG.md) · 🇧🇷 [pt-BR](../pt-BR/CHANGELOG.md)
+🌐 **Languages:** 🇺🇸 [English](../../../CHANGELOG.md) · 🇪🇸 [es](../es/CHANGELOG.md) · 🇫🇷 [fr](../fr/CHANGELOG.md) · 🇩🇪 [de](../de/CHANGELOG.md) · 🇮🇹 [it](../it/CHANGELOG.md) · 🇷🇺 [ru](../ru/CHANGELOG.md) · 🇨🇳 [zh-CN](../zh-CN/CHANGELOG.md) · 🇯🇵 [ja](../ja/CHANGELOG.md) · 🇰🇷 [ko](../ko/CHANGELOG.md) · 🇸🇦 [ar](../ar/CHANGELOG.md) · 🇮🇳 [in](../in/CHANGELOG.md) · 🇹🇭 [th](../th/CHANGELOG.md) · 🇻🇳 [vi](../vi/CHANGELOG.md) · 🇮🇩 [id](../id/CHANGELOG.md) · 🇲🇾 [ms](../ms/CHANGELOG.md) · 🇳🇱 [nl](../nl/CHANGELOG.md) · 🇵🇱 [pl](../pl/CHANGELOG.md) · 🇸🇪 [sv](../sv/CHANGELOG.md) · 🇳🇴 [no](../no/CHANGELOG.md) · 🇩🇰 [da](../da/CHANGELOG.md) · 🇫🇮 [fi](../fi/CHANGELOG.md) · 🇵🇹 [pt](../pt/CHANGELOG.md) · 🇷🇴 [ro](../ro/CHANGELOG.md) · 🇭🇺 [hu](../hu/CHANGELOG.md) · 🇧🇬 [bg](../bg/CHANGELOG.md) · 🇸🇰 [sk](../sk/CHANGELOG.md) · 🇺🇦 [uk-UA](../uk-UA/CHANGELOG.md) · 🇮🇱 [he](../he/CHANGELOG.md) · 🇵🇭 [phi](../phi/CHANGELOG.md) · 🇧🇷 [pt-BR](../pt-BR/CHANGELOG.md) · 🇨🇿 [cs](../cs/CHANGELOG.md)
---
-
## [Unreleased]
+### 🛠️ Maintenance
+
+- **AGENTS.md rewrite:** Condensed from 297→153 lines. Added build/lint/test commands (including single-test execution), code style guidelines (Prettier, TypeScript, ESLint, naming, imports, error handling, security), and trimmed verbose architecture tables for AI agent consumption.
+
+## [3.4.2] - 2026-04-01
+
+### 🐛 Bug Fixes
+
+- **CI Stabilization:** Fixed failing analytics/settings Playwright selectors and request assertions so GitHub Actions E2E runs pass reliably across localized UIs and switch-based controls.
+- **Deterministic Tests:** Removed date-sensitive quota fixtures from Copilot usage tests and aligned idempotency/model catalog tests with the merged runtime behavior.
+- **MCP Type Hardening:** Removed zero-budget explicit `any` regressions from the MCP server tool registration path, restoring the `check:any-budget:t11` workflow gate.
+
+### 🛠️ Maintenance
+
+- **Release Branch Integration:** Consolidated the active feature branches into `release/v3.4.2` on top of current `main` and validated the branch with lint, unit, coverage, build, and CI-mode E2E runs.
+
+## [3.4.1] - 2026-03-31
+
+> [!WARNING]
+> **BREAKING CHANGE: request logging, retention, and logging environment variables have been redesigned.**
+> On the first startup after upgrading, OmniRoute archives legacy request logs from `DATA_DIR/logs/`, legacy `DATA_DIR/call_logs/`, and `DATA_DIR/log.txt` into `DATA_DIR/log_archives/*.zip`, then removes the deprecated layout and switches to the new unified artifact format under `DATA_DIR/call_logs/`.
+
+### ✨ New Features
+
+- **.ENV Migration Utility:** Included `scripts/migrate-env.mjs` to seamlessly migrate ` Your key looks like: `sk-xxxxxxxxxxxxxxxx-xxxxxxxxx`
-
----
-
-## Step 2 — Install CLI Tools
-
-All npm-based tools require Node.js 18+:
-
-```bash
-# Claude Code (Anthropic)
-npm install -g @anthropic-ai/claude-code
-
-# OpenAI Codex
-npm install -g @openai/codex
-
-# Gemini CLI (Google)
-npm install -g @google/gemini-cli
-
-# OpenCode
-npm install -g opencode-ai
-
-# Cline
-npm install -g cline
-
-# KiloCode
-npm install -g kilecode
-
-# Kiro CLI (Amazon — requires curl + unzip)
-apt-get install -y unzip # on Debian/Ubuntu
-curl -fsSL https://cli.kiro.dev/install | bash
-export PATH="$HOME/.local/bin:$PATH" # add to ~/.bashrc
-```
-
-**Verify:**
-
-```bash
-claude --version # 2.x.x
-codex --version # 0.x.x
-gemini --version # 0.x.x
-opencode --version # x.x.x
-cline --version # 2.x.x
-kilocode --version # x.x.x (or: kilo --version)
-kiro-cli --version # 1.x.x
-```
-
----
-
-## Step 3 — Set Global Environment Variables
-
-Add to `~/.bashrc` (or `~/.zshrc`), then run `source ~/.bashrc`:
-
-```bash
-# OmniRoute Universal Endpoint
-export OPENAI_BASE_URL="http://localhost:20128/v1"
-export OPENAI_API_KEY="sk-your-omniroute-key"
-export ANTHROPIC_BASE_URL="http://localhost:20128/v1"
-export ANTHROPIC_API_KEY="sk-your-omniroute-key"
-export GEMINI_BASE_URL="http://localhost:20128/v1"
-export GEMINI_API_KEY="sk-your-omniroute-key"
-```
-
-> For a **remote server** replace `localhost:20128` with the server IP or domain,
-> e.g. `http://192.168.0.15:20128`.
-
----
-
-## Step 4 — Configure Each Tool
-
-### Claude Code
-
-```bash
-# Via CLI:
-claude config set --global api-base-url http://localhost:20128/v1
-
-# Or create ~/.claude/settings.json:
-mkdir -p ~/.claude && cat > ~/.claude/settings.json << EOF
-{
- "apiBaseUrl": "http://localhost:20128/v1",
- "apiKey": "sk-your-omniroute-key"
-}
-EOF
-```
-
-**Test:** `claude "say hello"`
-
----
-
-### OpenAI Codex
-
-```bash
-mkdir -p ~/.codex && cat > ~/.codex/config.yaml << EOF
-model: auto
-apiKey: sk-your-omniroute-key
-apiBaseUrl: http://localhost:20128/v1
-EOF
-```
-
-**Test:** `codex "what is 2+2?"`
-
----
-
-### Gemini CLI
-
-```bash
-mkdir -p ~/.gemini && cat > ~/.gemini/settings.json << EOF
-{
- "apiKey": "sk-your-omniroute-key",
- "baseUrl": "http://localhost:20128/v1"
-}
-EOF
-```
-
-**Test:** `gemini "hello"`
-
----
-
-### OpenCode
-
-```bash
-mkdir -p ~/.config/opencode && cat > ~/.config/opencode/config.toml << EOF
-[provider.openai]
-base_url = "http://localhost:20128/v1"
-api_key = "sk-your-omniroute-key"
-EOF
-```
-
-**Test:** `opencode`
-
----
-
-### Cline (CLI or VS Code)
-
-**CLI mode:**
-
-```bash
-mkdir -p ~/.cline/data && cat > ~/.cline/data/globalState.json << EOF
-{
- "apiProvider": "openai",
- "openAiBaseUrl": "http://localhost:20128/v1",
- "openAiApiKey": "sk-your-omniroute-key"
-}
-EOF
-```
-
-**VS Code mode:**
-Cline extension settings → API Provider: `OpenAI Compatible` → Base URL: `http://localhost:20128/v1`
-
-Or use the OmniRoute dashboard → **CLI Tools → Cline → Apply Config**.
-
----
-
-### KiloCode (CLI or VS Code)
-
-**CLI mode:**
-
-```bash
-kilocode --api-base http://localhost:20128/v1 --api-key sk-your-omniroute-key
-```
-
-**VS Code settings:**
-
-```json
-{
- "kilo-code.openAiBaseUrl": "http://localhost:20128/v1",
- "kilo-code.apiKey": "sk-your-omniroute-key"
-}
-```
-
-Or use the OmniRoute dashboard → **CLI Tools → KiloCode → Apply Config**.
-
----
-
-### Continue (VS Code Extension)
-
-Edit `~/.continue/config.yaml`:
-
-```yaml
-models:
- - name: OmniRoute
- provider: openai
- model: auto
- apiBase: http://localhost:20128/v1
- apiKey: sk-your-omniroute-key
- default: true
-```
-
-Restart VS Code after editing.
-
----
-
-### Kiro CLI (Amazon)
-
-```bash
-# Login to your AWS/Kiro account:
-kiro-cli login
-
-# The CLI uses its own auth — OmniRoute is not needed as backend for Kiro CLI itself.
-# Use kiro-cli alongside OmniRoute for other tools.
-kiro-cli status
-```
-
----
-
-### Cursor (Desktop App)
-
-> **Note:** Cursor routes requests through its cloud. For OmniRoute integration,
-> enable **Cloud Endpoint** in OmniRoute Settings and use your public domain URL.
-
-Via GUI: **Settings → Models → OpenAI API Key**
-
-- Base URL: `https://your-domain.com/v1`
-- API Key: your OmniRoute key
-
----
-
-## Dashboard Auto-Configuration
-
-The OmniRoute dashboard automates configuration for most tools:
-
-1. Go to `http://localhost:20128/dashboard/cli-tools`
-2. Expand any tool card
-3. Select your API key from the dropdown
-4. Click **Apply Config** (if tool is detected as installed)
-5. Or copy the generated config snippet manually
-
----
-
-## Built-in Agents: Droid & OpenClaw
-
-**Droid** and **OpenClaw** are AI agents built directly into OmniRoute — no installation needed.
-They run as internal routes and use OmniRoute's model routing automatically.
-
-- Access: `http://localhost:20128/dashboard/agents`
-- Configure: same combos and providers as all other tools
-- No API key or CLI install required
-
----
-
-## Available API Endpoints
-
-| Endpoint | Description | Use For |
-| -------------------------- | ----------------------------- | --------------------------- |
-| `/v1/chat/completions` | Standard chat (all providers) | All modern tools |
-| `/v1/responses` | Responses API (OpenAI format) | Codex, agentic workflows |
-| `/v1/completions` | Legacy text completions | Older tools using `prompt:` |
-| `/v1/embeddings` | Text embeddings | RAG, search |
-| `/v1/images/generations` | Image generation | DALL-E, Flux, etc. |
-| `/v1/audio/speech` | Text-to-speech | ElevenLabs, OpenAI TTS |
-| `/v1/audio/transcriptions` | Speech-to-text | Deepgram, AssemblyAI |
-
----
-
-## Troubleshooting
-
-| Error | Cause | Fix |
-| ------------------------- | ----------------------- | ------------------------------------------ |
-| `Connection refused` | OmniRoute not running | `pm2 start omniroute` |
-| `401 Unauthorized` | Wrong API key | Check in `/dashboard/api-manager` |
-| `No combo configured` | No active routing combo | Set up in `/dashboard/combos` |
-| `invalid model` | Model not in catalog | Use `auto` or check `/dashboard/providers` |
-| CLI shows "not installed" | Binary not in PATH | Check `which ` |
-| `kiro-cli: not found` | Not in PATH | `export PATH="$HOME/.local/bin:$PATH"` |
-
----
-
-## Quick Setup Script (One Command)
-
-```bash
-# Install all CLIs and configure for OmniRoute (replace with your key and server URL)
-OMNIROUTE_URL="http://localhost:20128/v1"
-OMNIROUTE_KEY="sk-your-omniroute-key"
-
-npm install -g @anthropic-ai/claude-code @openai/codex @google/gemini-cli opencode-ai cline kilecode
-
-# Kiro CLI
-apt-get install -y unzip 2>/dev/null; curl -fsSL https://cli.kiro.dev/install | bash
-
-# Write configs
-mkdir -p ~/.claude ~/.codex ~/.gemini ~/.config/opencode ~/.continue
-
-cat > ~/.claude/settings.json <<< "{\"apiBaseUrl\":\"$OMNIROUTE_URL\",\"apiKey\":\"$OMNIROUTE_KEY\"}"
-cat > ~/.codex/config.yaml <<< "model: auto\napiKey: $OMNIROUTE_KEY\napiBaseUrl: $OMNIROUTE_URL"
-cat > ~/.gemini/settings.json <<< "{\"apiKey\":\"$OMNIROUTE_KEY\",\"baseUrl\":\"$OMNIROUTE_URL\"}"
-cat >> ~/.bashrc << EOF
-export OPENAI_BASE_URL="$OMNIROUTE_URL"
-export OPENAI_API_KEY="$OMNIROUTE_KEY"
-export ANTHROPIC_BASE_URL="$OMNIROUTE_URL"
-export ANTHROPIC_API_KEY="$OMNIROUTE_KEY"
-EOF
-
-source ~/.bashrc
-echo "✅ All CLIs installed and configured for OmniRoute"
-```
diff --git a/docs/i18n/fi/CODEBASE_DOCUMENTATION.md b/docs/i18n/fi/CODEBASE_DOCUMENTATION.md
deleted file mode 100644
index e2d7950052..0000000000
--- a/docs/i18n/fi/CODEBASE_DOCUMENTATION.md
+++ /dev/null
@@ -1,593 +0,0 @@
-🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/CODEBASE_DOCUMENTATION.md) · 🇪🇸 [es](../es/CODEBASE_DOCUMENTATION.md) · 🇫🇷 [fr](../fr/CODEBASE_DOCUMENTATION.md) · 🇩🇪 [de](../de/CODEBASE_DOCUMENTATION.md) · 🇮🇹 [it](../it/CODEBASE_DOCUMENTATION.md) · 🇷🇺 [ru](../ru/CODEBASE_DOCUMENTATION.md) · 🇨🇳 [zh-CN](../zh-CN/CODEBASE_DOCUMENTATION.md) · 🇯🇵 [ja](../ja/CODEBASE_DOCUMENTATION.md) · 🇰🇷 [ko](../ko/CODEBASE_DOCUMENTATION.md) · 🇸🇦 [ar](../ar/CODEBASE_DOCUMENTATION.md) · 🇮🇳 [in](../in/CODEBASE_DOCUMENTATION.md) · 🇹🇭 [th](../th/CODEBASE_DOCUMENTATION.md) · 🇻🇳 [vi](../vi/CODEBASE_DOCUMENTATION.md) · 🇮🇩 [id](../id/CODEBASE_DOCUMENTATION.md) · 🇲🇾 [ms](../ms/CODEBASE_DOCUMENTATION.md) · 🇳🇱 [nl](../nl/CODEBASE_DOCUMENTATION.md) · 🇵🇱 [pl](../pl/CODEBASE_DOCUMENTATION.md) · 🇸🇪 [sv](../sv/CODEBASE_DOCUMENTATION.md) · 🇳🇴 [no](../no/CODEBASE_DOCUMENTATION.md) · 🇩🇰 [da](../da/CODEBASE_DOCUMENTATION.md) · 🇫🇮 [fi](../fi/CODEBASE_DOCUMENTATION.md) · 🇵🇹 [pt](../pt/CODEBASE_DOCUMENTATION.md) · 🇷🇴 [ro](../ro/CODEBASE_DOCUMENTATION.md) · 🇭🇺 [hu](../hu/CODEBASE_DOCUMENTATION.md) · 🇧🇬 [bg](../bg/CODEBASE_DOCUMENTATION.md) · 🇸🇰 [sk](../sk/CODEBASE_DOCUMENTATION.md) · 🇺🇦 [uk-UA](../uk-UA/CODEBASE_DOCUMENTATION.md) · 🇮🇱 [he](../he/CODEBASE_DOCUMENTATION.md) · 🇵🇭 [phi](../phi/CODEBASE_DOCUMENTATION.md)
-
----
-
-# omniroute — Codebase Documentation
-
-🌐 **Languages:** 🇺🇸 [English](CODEBASE_DOCUMENTATION.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/CODEBASE_DOCUMENTATION.md) | 🇪🇸 [Español](i18n/es/CODEBASE_DOCUMENTATION.md) | 🇫🇷 [Français](i18n/fr/CODEBASE_DOCUMENTATION.md) | 🇮🇹 [Italiano](i18n/it/CODEBASE_DOCUMENTATION.md) | 🇷🇺 [Русский](i18n/ru/CODEBASE_DOCUMENTATION.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/CODEBASE_DOCUMENTATION.md) | 🇩🇪 [Deutsch](i18n/de/CODEBASE_DOCUMENTATION.md) | 🇮🇳 [हिन्दी](i18n/in/CODEBASE_DOCUMENTATION.md) | 🇹🇭 [ไทย](i18n/th/CODEBASE_DOCUMENTATION.md) | 🇺🇦 [Українська](i18n/uk-UA/CODEBASE_DOCUMENTATION.md) | 🇸🇦 [العربية](i18n/ar/CODEBASE_DOCUMENTATION.md) | 🇯🇵 [日本語](i18n/ja/CODEBASE_DOCUMENTATION.md) | 🇻🇳 [Tiếng Việt](i18n/vi/CODEBASE_DOCUMENTATION.md) | 🇧🇬 [Български](i18n/bg/CODEBASE_DOCUMENTATION.md) | 🇩🇰 [Dansk](i18n/da/CODEBASE_DOCUMENTATION.md) | 🇫🇮 [Suomi](i18n/fi/CODEBASE_DOCUMENTATION.md) | 🇮🇱 [עברית](i18n/he/CODEBASE_DOCUMENTATION.md) | 🇭🇺 [Magyar](i18n/hu/CODEBASE_DOCUMENTATION.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/CODEBASE_DOCUMENTATION.md) | 🇰🇷 [한국어](i18n/ko/CODEBASE_DOCUMENTATION.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/CODEBASE_DOCUMENTATION.md) | 🇳🇱 [Nederlands](i18n/nl/CODEBASE_DOCUMENTATION.md) | 🇳🇴 [Norsk](i18n/no/CODEBASE_DOCUMENTATION.md) | 🇵🇹 [Português (Portugal)](i18n/pt/CODEBASE_DOCUMENTATION.md) | 🇷🇴 [Română](i18n/ro/CODEBASE_DOCUMENTATION.md) | 🇵🇱 [Polski](i18n/pl/CODEBASE_DOCUMENTATION.md) | 🇸🇰 [Slovenčina](i18n/sk/CODEBASE_DOCUMENTATION.md) | 🇸🇪 [Svenska](i18n/sv/CODEBASE_DOCUMENTATION.md) | 🇵🇭 [Filipino](i18n/phi/CODEBASE_DOCUMENTATION.md)
-
-> A comprehensive, beginner-friendly guide to the **omniroute** multi-provider AI proxy router.
-
----
-
-## 1. What Is omniroute?
-
-omniroute is a **proxy router** that sits between AI clients (Claude CLI, Codex, Cursor IDE, etc.) and AI providers (Anthropic, Google, OpenAI, AWS, GitHub, etc.). It solves one big problem:
-
-> **Different AI clients speak different "languages" (API formats), and different AI providers expect different "languages" too.** omniroute translates between them automatically.
-
-Think of it like a universal translator at the United Nations — any delegate can speak any language, and the translator converts it for any other delegate.
-
----
-
-## 2. Architecture Overview
-
-```mermaid
-graph LR
- subgraph Clients
- A[Claude CLI]
- B[Codex]
- C[Cursor IDE]
- D[OpenAI-compatible]
- end
-
- subgraph omniroute
- E[Handler Layer]
- F[Translator Layer]
- G[Executor Layer]
- H[Services Layer]
- end
-
- subgraph Providers
- I[Anthropic Claude]
- J[Google Gemini]
- K[OpenAI / Codex]
- L[GitHub Copilot]
- M[AWS Kiro]
- N[Antigravity]
- O[Cursor API]
- end
-
- A --> E
- B --> E
- C --> E
- D --> E
- E --> F
- F --> G
- G --> I
- G --> J
- G --> K
- G --> L
- G --> M
- G --> N
- G --> O
- H -.-> E
- H -.-> G
-```
-
-### Core Principle: Hub-and-Spoke Translation
-
-All format translation passes through **OpenAI format as the hub**:
-
-```
-Client Format → [OpenAI Hub] → Provider Format (request)
-Provider Format → [OpenAI Hub] → Client Format (response)
-```
-
-This means you only need **N translators** (one per format) instead of **N²** (every pair).
-
----
-
-## 3. Project Structure
-
-```
-omniroute/
-├── open-sse/ ← Core proxy library (portable, framework-agnostic)
-│ ├── index.js ← Main entry point, exports everything
-│ ├── config/ ← Configuration & constants
-│ ├── executors/ ← Provider-specific request execution
-│ ├── handlers/ ← Request handling orchestration
-│ ├── services/ ← Business logic (auth, models, fallback, usage)
-│ ├── translator/ ← Format translation engine
-│ │ ├── request/ ← Request translators (8 files)
-│ │ ├── response/ ← Response translators (7 files)
-│ │ └── helpers/ ← Shared translation utilities (6 files)
-│ └── utils/ ← Utility functions
-├── src/ ← Application layer (Express/Worker runtime)
-│ ├── app/ ← Web UI, API routes, middleware
-│ ├── lib/ ← Database, auth, and shared library code
-│ ├── mitm/ ← Man-in-the-middle proxy utilities
-│ ├── models/ ← Database models
-│ ├── shared/ ← Shared utilities (wrappers around open-sse)
-│ ├── sse/ ← SSE endpoint handlers
-│ └── store/ ← State management
-├── data/ ← Runtime data (credentials, logs)
-│ └── provider-credentials.json (external credentials override, gitignored)
-└── tester/ ← Test utilities
-```
-
----
-
-## 4. Module-by-Module Breakdown
-
-### 4.1 Config (`open-sse/config/`)
-
-The **single source of truth** for all provider configuration.
-
-| File | Purpose |
-| ----------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| `constants.ts` | `PROVIDERS` object with base URLs, OAuth credentials (defaults), headers, and default system prompts for every provider. Also defines `HTTP_STATUS`, `ERROR_TYPES`, `COOLDOWN_MS`, `BACKOFF_CONFIG`, and `SKIP_PATTERNS`. |
-| `credentialLoader.ts` | Loads external credentials from `data/provider-credentials.json` and merges them over the hardcoded defaults in `PROVIDERS`. Keeps secrets out of source control while maintaining backwards compatibility. |
-| `providerModels.ts` | Central model registry: maps provider aliases → model IDs. Functions like `getModels()`, `getProviderByAlias()`. |
-| `codexInstructions.ts` | System instructions injected into Codex requests (editing constraints, sandbox rules, approval policies). |
-| `defaultThinkingSignature.ts` | Default "thinking" signatures for Claude and Gemini models. |
-| `ollamaModels.ts` | Schema definition for local Ollama models (name, size, family, quantization). |
-
-#### Credential Loading Flow
-
-```mermaid
-flowchart TD
- A["App starts"] --> B["constants.ts defines PROVIDERS\nwith hardcoded defaults"]
- B --> C{"data/provider-credentials.json\nexists?"}
- C -->|Yes| D["credentialLoader reads JSON"]
- C -->|No| E["Use hardcoded defaults"]
- D --> F{"For each provider in JSON"}
- F --> G{"Provider exists\nin PROVIDERS?"}
- G -->|No| H["Log warning, skip"]
- G -->|Yes| I{"Value is object?"}
- I -->|No| J["Log warning, skip"]
- I -->|Yes| K["Merge clientId, clientSecret,\ntokenUrl, authUrl, refreshUrl"]
- K --> F
- H --> F
- J --> F
- F -->|Done| L["PROVIDERS ready with\nmerged credentials"]
- E --> L
-```
-
----
-
-### 4.2 Executors (`open-sse/executors/`)
-
-Executors encapsulate **provider-specific logic** using the **Strategy Pattern**. Each executor overrides base methods as needed.
-
-```mermaid
-classDiagram
- class BaseExecutor {
- +buildUrl(model, stream, options)
- +buildHeaders(credentials, stream, body)
- +transformRequest(body, model, stream, credentials)
- +execute(url, options)
- +shouldRetry(status, error)
- +refreshCredentials(credentials, log)
- }
-
- class DefaultExecutor {
- +refreshCredentials()
- }
-
- class AntigravityExecutor {
- +buildUrl()
- +buildHeaders()
- +transformRequest()
- +shouldRetry()
- +refreshCredentials()
- }
-
- class CursorExecutor {
- +buildUrl()
- +buildHeaders()
- +transformRequest()
- +parseResponse()
- +generateChecksum()
- }
-
- class KiroExecutor {
- +buildUrl()
- +buildHeaders()
- +transformRequest()
- +parseEventStream()
- +refreshCredentials()
- }
-
- BaseExecutor <|-- DefaultExecutor
- BaseExecutor <|-- AntigravityExecutor
- BaseExecutor <|-- CursorExecutor
- BaseExecutor <|-- KiroExecutor
- BaseExecutor <|-- CodexExecutor
- BaseExecutor <|-- GeminiCLIExecutor
- BaseExecutor <|-- GithubExecutor
-```
-
-| Executor | Provider | Key Specializations |
-| ---------------- | ------------------------------------------ | ------------------------------------------------------------------------------------------------------------------- |
-| `base.ts` | — | Abstract base: URL building, headers, retry logic, credential refresh |
-| `default.ts` | Claude, Gemini, OpenAI, GLM, Kimi, MiniMax | Generic OAuth token refresh for standard providers |
-| `antigravity.ts` | Google Cloud Code | Project/session ID generation, multi-URL fallback, custom retry parsing from error messages ("reset after 2h7m23s") |
-| `cursor.ts` | Cursor IDE | **Most complex**: SHA-256 checksum auth, Protobuf request encoding, binary EventStream → SSE response parsing |
-| `codex.ts` | OpenAI Codex | Injects system instructions, manages thinking levels, removes unsupported parameters |
-| `gemini-cli.ts` | Google Gemini CLI | Custom URL building (`streamGenerateContent`), Google OAuth token refresh |
-| `github.ts` | GitHub Copilot | Dual token system (GitHub OAuth + Copilot token), VSCode header mimicking |
-| `kiro.ts` | AWS CodeWhisperer | AWS EventStream binary parsing, AMZN event frames, token estimation |
-| `index.ts` | — | Factory: maps provider name → executor class, with default fallback |
-
----
-
-### 4.3 Handlers (`open-sse/handlers/`)
-
-The **orchestration layer** — coordinates translation, execution, streaming, and error handling.
-
-| File | Purpose |
-| --------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| `chatCore.ts` | **Central orchestrator** (~600 lines). Handles the complete request lifecycle: format detection → translation → executor dispatch → streaming/non-streaming response → token refresh → error handling → usage logging. |
-| `responsesHandler.ts` | Adapter for OpenAI's Responses API: converts Responses format → Chat Completions → sends to `chatCore` → converts SSE back to Responses format. |
-| `embeddings.ts` | Embedding generation handler: resolves embedding model → provider, dispatches to provider API, returns OpenAI-compatible embedding response. Supports 6+ providers. |
-| `imageGeneration.ts` | Image generation handler: resolves image model → provider, supports OpenAI-compatible, Gemini-image (Antigravity), and fallback (Nebius) modes. Returns base64 or URL images. |
-
-#### Request Lifecycle (chatCore.ts)
-
-```mermaid
-sequenceDiagram
- participant Client
- participant chatCore
- participant Translator
- participant Executor
- participant Provider
-
- Client->>chatCore: Request (any format)
- chatCore->>chatCore: Detect source format
- chatCore->>chatCore: Check bypass patterns
- chatCore->>chatCore: Resolve model & provider
- chatCore->>Translator: Translate request (source → OpenAI → target)
- chatCore->>Executor: Get executor for provider
- Executor->>Executor: Build URL, headers, transform request
- Executor->>Executor: Refresh credentials if needed
- Executor->>Provider: HTTP fetch (streaming or non-streaming)
-
- alt Streaming
- Provider-->>chatCore: SSE stream
- chatCore->>chatCore: Pipe through SSE transform stream
- Note over chatCore: Transform stream translates
each chunk: target → OpenAI → source
- chatCore-->>Client: Translated SSE stream
- else Non-streaming
- Provider-->>chatCore: JSON response
- chatCore->>Translator: Translate response
- chatCore-->>Client: Translated JSON
- end
-
- alt Error (401, 429, 500...)
- chatCore->>Executor: Retry with credential refresh
- chatCore->>chatCore: Account fallback logic
- end
-```
-
----
-
-### 4.4 Services (`open-sse/services/`)
-
-Business logic that supports the handlers and executors.
-
-| File | Purpose |
-| -------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| `provider.ts` | **Format detection** (`detectFormat`): analyzes request body structure to identify Claude/OpenAI/Gemini/Antigravity/Responses formats (includes `max_tokens` heuristic for Claude). Also: URL building, header building, thinking config normalization. Supports `openai-compatible-*` and `anthropic-compatible-*` dynamic providers. |
-| `model.ts` | Model string parsing (`claude/model-name` → `{provider: "claude", model: "model-name"}`), alias resolution with collision detection, input sanitization (rejects path traversal/control chars), and model info resolution with async alias getter support. |
-| `accountFallback.ts` | Rate-limit handling: exponential backoff (1s → 2s → 4s → max 2min), account cooldown management, error classification (which errors trigger fallback vs. not). |
-| `tokenRefresh.ts` | OAuth token refresh for **every provider**: Google (Gemini, Antigravity), Claude, Codex, Qwen, Qoder, GitHub (OAuth + Copilot dual-token), Kiro (AWS SSO OIDC + Social Auth). Includes in-flight promise deduplication cache and retry with exponential backoff. |
-| `combo.ts` | **Combo models**: chains of fallback models. If model A fails with a fallback-eligible error, try model B, then C, etc. Returns actual upstream status codes. |
-| `usage.ts` | Fetches quota/usage data from provider APIs (GitHub Copilot quotas, Antigravity model quotas, Codex rate limits, Kiro usage breakdowns, Claude settings). |
-| `accountSelector.ts` | Smart account selection with scoring algorithm: considers priority, health status, round-robin position, and cooldown state to pick the optimal account for each request. |
-| `contextManager.ts` | Request context lifecycle management: creates and tracks per-request context objects with metadata (request ID, timestamps, provider info) for debugging and logging. |
-| `ipFilter.ts` | IP-based access control: supports allowlist and blocklist modes. Validates client IP against configured rules before processing API requests. |
-| `sessionManager.ts` | Session tracking with client fingerprinting: tracks active sessions using hashed client identifiers, monitors request counts, and provides session metrics. |
-| `signatureCache.ts` | Request signature-based deduplication cache: prevents duplicate requests by caching recent request signatures and returning cached responses for identical requests within a time window. |
-| `systemPrompt.ts` | Global system prompt injection: prepends or appends a configurable system prompt to all requests, with per-provider compatibility handling. |
-| `thinkingBudget.ts` | Reasoning token budget management: supports passthrough, auto (strip thinking config), custom (fixed budget), and adaptive (complexity-scaled) modes for controlling thinking/reasoning tokens. |
-| `wildcardRouter.ts` | Wildcard model pattern routing: resolves wildcard patterns (e.g., `*/claude-*`) to concrete provider/model pairs based on availability and priority. |
-
-#### Token Refresh Deduplication
-
-```mermaid
-sequenceDiagram
- participant R1 as Request 1
- participant R2 as Request 2
- participant Cache as refreshPromiseCache
- participant OAuth as OAuth Provider
-
- R1->>Cache: getAccessToken("gemini", token)
- Cache->>Cache: No in-flight promise
- Cache->>OAuth: Start refresh
- R2->>Cache: getAccessToken("gemini", token)
- Cache->>Cache: Found in-flight promise
- Cache-->>R2: Return existing promise
- OAuth-->>Cache: New access token
- Cache-->>R1: New access token
- Cache-->>R2: Same access token (shared)
- Cache->>Cache: Delete cache entry
-```
-
-#### Account Fallback State Machine
-
-```mermaid
-stateDiagram-v2
- [*] --> Active
- Active --> Error: Request fails (401/429/500)
- Error --> Cooldown: Apply backoff
- Cooldown --> Active: Cooldown expires
- Active --> Active: Request succeeds (reset backoff)
-
- state Error {
- [*] --> ClassifyError
- ClassifyError --> ShouldFallback: Rate limit / Auth / Transient
- ClassifyError --> NoFallback: 400 Bad Request
- }
-
- state Cooldown {
- [*] --> ExponentialBackoff
- ExponentialBackoff: Level 0 = 1s
- ExponentialBackoff: Level 1 = 2s
- ExponentialBackoff: Level 2 = 4s
- ExponentialBackoff: Max = 2min
- }
-```
-
-#### Combo Model Chain
-
-```mermaid
-flowchart LR
- A["Request with\ncombo model"] --> B["Model A"]
- B -->|"2xx Success"| C["Return response"]
- B -->|"429/401/500"| D{"Fallback\neligible?"}
- D -->|Yes| E["Model B"]
- D -->|No| F["Return error"]
- E -->|"2xx Success"| C
- E -->|"429/401/500"| G{"Fallback\neligible?"}
- G -->|Yes| H["Model C"]
- G -->|No| F
- H -->|"2xx Success"| C
- H -->|"Fail"| I["All failed →\nReturn last status"]
-```
-
----
-
-### 4.5 Translator (`open-sse/translator/`)
-
-The **format translation engine** using a self-registering plugin system.
-
-#### Architecture
-
-```mermaid
-graph TD
- subgraph "Request Translation"
- A["Claude → OpenAI"]
- B["Gemini → OpenAI"]
- C["Antigravity → OpenAI"]
- D["OpenAI Responses → OpenAI"]
- E["OpenAI → Claude"]
- F["OpenAI → Gemini"]
- G["OpenAI → Kiro"]
- H["OpenAI → Cursor"]
- end
-
- subgraph "Response Translation"
- I["Claude → OpenAI"]
- J["Gemini → OpenAI"]
- K["Kiro → OpenAI"]
- L["Cursor → OpenAI"]
- M["OpenAI → Claude"]
- N["OpenAI → Antigravity"]
- O["OpenAI → Responses"]
- end
-```
-
-| Directory | Files | Description |
-| ------------ | ------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| `request/` | 8 translators | Convert request bodies between formats. Each file self-registers via `register(from, to, fn)` on import. |
-| `response/` | 7 translators | Convert streaming response chunks between formats. Handles SSE event types, thinking blocks, tool calls. |
-| `helpers/` | 6 helpers | Shared utilities: `claudeHelper` (system prompt extraction, thinking config), `geminiHelper` (parts/contents mapping), `openaiHelper` (format filtering), `toolCallHelper` (ID generation, missing response injection), `maxTokensHelper`, `responsesApiHelper`. |
-| `index.ts` | — | Translation engine: `translateRequest()`, `translateResponse()`, state management, registry. |
-| `formats.ts` | — | Format constants: `OPENAI`, `CLAUDE`, `GEMINI`, `ANTIGRAVITY`, `KIRO`, `CURSOR`, `OPENAI_RESPONSES`. |
-
-#### Key Design: Self-Registering Plugins
-
-```javascript
-// Each translator file calls register() on import:
-import { register } from "../index.js";
-register("claude", "openai", translateClaudeToOpenAI);
-
-// The index.js imports all translator files, triggering registration:
-import "./request/claude-to-openai.js"; // ← self-registers
-```
-
----
-
-### 4.6 Utils (`open-sse/utils/`)
-
-| File | Purpose |
-| ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
-| `error.ts` | Error response building (OpenAI-compatible format), upstream error parsing, Antigravity retry-time extraction from error messages, SSE error streaming. |
-| `stream.ts` | **SSE Transform Stream** — the core streaming pipeline. Two modes: `TRANSLATE` (full format translation) and `PASSTHROUGH` (normalize + extract usage). Handles chunk buffering, usage estimation, content length tracking. Per-stream encoder/decoder instances avoid shared state. |
-| `streamHelpers.ts` | Low-level SSE utilities: `parseSSELine` (whitespace-tolerant), `hasValuableContent` (filters empty chunks for OpenAI/Claude/Gemini), `fixInvalidId`, `formatSSE` (format-aware SSE serialization with `perf_metrics` cleanup). |
-| `usageTracking.ts` | Token usage extraction from any format (Claude/OpenAI/Gemini/Responses), estimation with separate tool/message char-per-token ratios, buffer addition (2000 tokens safety margin), format-specific field filtering, console logging with ANSI colors. |
-| `requestLogger.ts` | File-based request logging (opt-in via `ENABLE_REQUEST_LOGS=true`). Creates session folders with numbered files: `1_req_client.json` → `7_res_client.txt`. All I/O is async (fire-and-forget). Masks sensitive headers. |
-| `bypassHandler.ts` | Intercepts specific patterns from Claude CLI (title extraction, warmup, count) and returns fake responses without calling any provider. Supports both streaming and non-streaming. Intentionally limited to Claude CLI scope. |
-| `networkProxy.ts` | Resolves outbound proxy URL for a given provider with precedence: provider-specific config → global config → environment variables (`HTTPS_PROXY`/`HTTP_PROXY`/`ALL_PROXY`). Supports `NO_PROXY` exclusions. Caches config for 30s. |
-
-#### SSE Streaming Pipeline
-
-```mermaid
-flowchart TD
- A["Provider SSE stream"] --> B["TextDecoder\n(per-stream instance)"]
- B --> C["Buffer lines\n(split on newline)"]
- C --> D["parseSSELine()\n(trim whitespace, parse JSON)"]
- D --> E{"Mode?"}
- E -->|TRANSLATE| F["translateResponse()\ntarget → OpenAI → source"]
- E -->|PASSTHROUGH| G["fixInvalidId()\nnormalize chunk"]
- F --> H["hasValuableContent()\nfilter empty chunks"]
- G --> H
- H -->|"Has content"| I["extractUsage()\ntrack token counts"]
- H -->|"Empty"| J["Skip chunk"]
- I --> K["formatSSE()\nserialize + clean perf_metrics"]
- K --> L["TextEncoder\n(per-stream instance)"]
- L --> M["Enqueue to\nclient stream"]
-
- style A fill:#f9f,stroke:#333
- style M fill:#9f9,stroke:#333
-```
-
-#### Request Logger Session Structure
-
-```
-logs/
-└── claude_gemini_claude-sonnet_20260208_143045/
- ├── 1_req_client.json ← Raw client request
- ├── 2_req_source.json ← After initial conversion
- ├── 3_req_openai.json ← OpenAI intermediate format
- ├── 4_req_target.json ← Final target format
- ├── 5_res_provider.txt ← Provider SSE chunks (streaming)
- ├── 5_res_provider.json ← Provider response (non-streaming)
- ├── 6_res_openai.txt ← OpenAI intermediate chunks
- ├── 7_res_client.txt ← Client-facing SSE chunks
- └── 6_error.json ← Error details (if any)
-```
-
----
-
-### 4.7 Application Layer (`src/`)
-
-| Directory | Purpose |
-| ------------- | ---------------------------------------------------------------------- |
-| `src/app/` | Web UI, API routes, Express middleware, OAuth callback handlers |
-| `src/lib/` | Database access (`localDb.ts`, `usageDb.ts`), authentication, shared |
-| `src/mitm/` | Man-in-the-middle proxy utilities for intercepting provider traffic |
-| `src/models/` | Database model definitions |
-| `src/shared/` | Wrappers around open-sse functions (provider, stream, error, etc.) |
-| `src/sse/` | SSE endpoint handlers that wire the open-sse library to Express routes |
-| `src/store/` | Application state management |
-
-#### Notable API Routes
-
-| Route | Methods | Purpose |
-| --------------------------------------------- | --------------- | ------------------------------------------------------------------------------------- |
-| `/api/provider-models` | GET/POST/DELETE | CRUD for custom models per provider |
-| `/api/models/catalog` | GET | Aggregated catalog of all models (chat, embedding, image, custom) grouped by provider |
-| `/api/settings/proxy` | GET/PUT/DELETE | Hierarchical outbound proxy configuration (`global/providers/combos/keys`) |
-| `/api/settings/proxy/test` | POST | Validates proxy connectivity and returns public IP/latency |
-| `/v1/providers/[provider]/chat/completions` | POST | Dedicated per-provider chat completions with model validation |
-| `/v1/providers/[provider]/embeddings` | POST | Dedicated per-provider embeddings with model validation |
-| `/v1/providers/[provider]/images/generations` | POST | Dedicated per-provider image generation with model validation |
-| `/api/settings/ip-filter` | GET/PUT | IP allowlist/blocklist management |
-| `/api/settings/thinking-budget` | GET/PUT | Reasoning token budget configuration (passthrough/auto/custom/adaptive) |
-| `/api/settings/system-prompt` | GET/PUT | Global system prompt injection for all requests |
-| `/api/sessions` | GET | Active session tracking and metrics |
-| `/api/rate-limits` | GET | Per-account rate limit status |
-
----
-
-## 5. Key Design Patterns
-
-### 5.1 Hub-and-Spoke Translation
-
-All formats translate through **OpenAI format as the hub**. Adding a new provider only requires writing **one pair** of translators (to/from OpenAI), not N pairs.
-
-### 5.2 Executor Strategy Pattern
-
-Each provider has a dedicated executor class inheriting from `BaseExecutor`. The factory in `executors/index.ts` selects the right one at runtime.
-
-### 5.3 Self-Registering Plugin System
-
-Translator modules register themselves on import via `register()`. Adding a new translator is just creating a file and importing it.
-
-### 5.4 Account Fallback with Exponential Backoff
-
-When a provider returns 429/401/500, the system can switch to the next account, applying exponential cooldowns (1s → 2s → 4s → max 2min).
-
-### 5.5 Combo Model Chains
-
-A "combo" groups multiple `provider/model` strings. If the first fails, fallback to the next automatically.
-
-### 5.6 Stateful Streaming Translation
-
-Response translation maintains state across SSE chunks (thinking block tracking, tool call accumulation, content block indexing) via the `initState()` mechanism.
-
-### 5.7 Usage Safety Buffer
-
-A 2000-token buffer is added to reported usage to prevent clients from hitting context window limits due to overhead from system prompts and format translation.
-
----
-
-## 6. Supported Formats
-
-| Format | Direction | Identifier |
-| ----------------------- | --------------- | ------------------ |
-| OpenAI Chat Completions | source + target | `openai` |
-| OpenAI Responses API | source + target | `openai-responses` |
-| Anthropic Claude | source + target | `claude` |
-| Google Gemini | source + target | `gemini` |
-| Google Gemini CLI | target only | `gemini-cli` |
-| Antigravity | source + target | `antigravity` |
-| AWS Kiro | target only | `kiro` |
-| Cursor | target only | `cursor` |
-
----
-
-## 7. Supported Providers
-
-| Provider | Auth Method | Executor | Key Notes |
-| ------------------------ | ---------------------- | ----------- | --------------------------------------------- |
-| Anthropic Claude | API key or OAuth | Default | Uses `x-api-key` header |
-| Google Gemini | API key or OAuth | Default | Uses `x-goog-api-key` header |
-| Google Gemini CLI | OAuth | GeminiCLI | Uses `streamGenerateContent` endpoint |
-| Antigravity | OAuth | Antigravity | Multi-URL fallback, custom retry parsing |
-| OpenAI | API key | Default | Standard Bearer auth |
-| Codex | OAuth | Codex | Injects system instructions, manages thinking |
-| GitHub Copilot | OAuth + Copilot token | Github | Dual token, VSCode header mimicking |
-| Kiro (AWS) | AWS SSO OIDC or Social | Kiro | Binary EventStream parsing |
-| Cursor IDE | Checksum auth | Cursor | Protobuf encoding, SHA-256 checksums |
-| Qwen | OAuth | Default | Standard auth |
-| Qoder | OAuth (Basic + Bearer) | Default | Dual auth header |
-| OpenRouter | API key | Default | Standard Bearer auth |
-| GLM, Kimi, MiniMax | API key | Default | Claude-compatible, use `x-api-key` |
-| `openai-compatible-*` | API key | Default | Dynamic: any OpenAI-compatible endpoint |
-| `anthropic-compatible-*` | API key | Default | Dynamic: any Claude-compatible endpoint |
-
----
-
-## 8. Data Flow Summary
-
-### Streaming Request
-
-```mermaid
-flowchart LR
- A["Client"] --> B["detectFormat()"]
- B --> C["translateRequest()\nsource → OpenAI → target"]
- C --> D["Executor\nbuildUrl + buildHeaders"]
- D --> E["fetch(providerURL)"]
- E --> F["createSSEStream()\nTRANSLATE mode"]
- F --> G["parseSSELine()"]
- G --> H["translateResponse()\ntarget → OpenAI → source"]
- H --> I["extractUsage()\n+ addBuffer"]
- I --> J["formatSSE()"]
- J --> K["Client receives\ntranslated SSE"]
- K --> L["logUsage()\nsaveRequestUsage()"]
-```
-
-### Non-Streaming Request
-
-```mermaid
-flowchart LR
- A["Client"] --> B["detectFormat()"]
- B --> C["translateRequest()\nsource → OpenAI → target"]
- C --> D["Executor.execute()"]
- D --> E["translateResponse()\ntarget → OpenAI → source"]
- E --> F["Return JSON\nresponse"]
-```
-
-### Bypass Flow (Claude CLI)
-
-```mermaid
-flowchart LR
- A["Claude CLI request"] --> B{"Match bypass\npattern?"}
- B -->|"Title/Warmup/Count"| C["Generate fake\nOpenAI response"]
- B -->|"No match"| D["Normal flow"]
- C --> E["Translate to\nsource format"]
- E --> F["Return without\ncalling provider"]
-```
diff --git a/docs/i18n/fi/CONTRIBUTING.md b/docs/i18n/fi/CONTRIBUTING.md
new file mode 100644
index 0000000000..993c124278
--- /dev/null
+++ b/docs/i18n/fi/CONTRIBUTING.md
@@ -0,0 +1,299 @@
+# Contributing to OmniRoute (Suomi)
+
+🌐 **Languages:** 🇺🇸 [English](../../../CONTRIBUTING.md) · 🇪🇸 [es](../es/CONTRIBUTING.md) · 🇫🇷 [fr](../fr/CONTRIBUTING.md) · 🇩🇪 [de](../de/CONTRIBUTING.md) · 🇮🇹 [it](../it/CONTRIBUTING.md) · 🇷🇺 [ru](../ru/CONTRIBUTING.md) · 🇨🇳 [zh-CN](../zh-CN/CONTRIBUTING.md) · 🇯🇵 [ja](../ja/CONTRIBUTING.md) · 🇰🇷 [ko](../ko/CONTRIBUTING.md) · 🇸🇦 [ar](../ar/CONTRIBUTING.md) · 🇮🇳 [in](../in/CONTRIBUTING.md) · 🇹🇭 [th](../th/CONTRIBUTING.md) · 🇻🇳 [vi](../vi/CONTRIBUTING.md) · 🇮🇩 [id](../id/CONTRIBUTING.md) · 🇲🇾 [ms](../ms/CONTRIBUTING.md) · 🇳🇱 [nl](../nl/CONTRIBUTING.md) · 🇵🇱 [pl](../pl/CONTRIBUTING.md) · 🇸🇪 [sv](../sv/CONTRIBUTING.md) · 🇳🇴 [no](../no/CONTRIBUTING.md) · 🇩🇰 [da](../da/CONTRIBUTING.md) · 🇫🇮 [fi](../fi/CONTRIBUTING.md) · 🇵🇹 [pt](../pt/CONTRIBUTING.md) · 🇷🇴 [ro](../ro/CONTRIBUTING.md) · 🇭🇺 [hu](../hu/CONTRIBUTING.md) · 🇧🇬 [bg](../bg/CONTRIBUTING.md) · 🇸🇰 [sk](../sk/CONTRIBUTING.md) · 🇺🇦 [uk-UA](../uk-UA/CONTRIBUTING.md) · 🇮🇱 [he](../he/CONTRIBUTING.md) · 🇵🇭 [phi](../phi/CONTRIBUTING.md) · 🇧🇷 [pt-BR](../pt-BR/CONTRIBUTING.md) · 🇨🇿 [cs](../cs/CONTRIBUTING.md)
+
+---
+
+Thank you for your interest in contributing! This guide covers everything you need to get started.
+
+---
+
+## Development Setup
+
+### Prerequisites
+
+- **Node.js** >= 18 < 24 (recommended: 22 LTS)
+- **npm** 10+
+- **Git**
+
+### Clone & Install
+
+```bash
+git clone https://github.com/diegosouzapw/OmniRoute.git
+cd OmniRoute
+npm install
+```
+
+### Environment Variables
+
+```bash
+# Create your .env from the template
+cp .env.example .env
+
+# Generate required secrets
+echo "JWT_SECRET=$(openssl rand -base64 48)" >> .env
+echo "API_KEY_SECRET=$(openssl rand -hex 32)" >> .env
+```
+
+Key variables for development:
+
+| Variable | Development Default | Description |
+| ---------------------- | ------------------------ | --------------------- |
+| `PORT` | `20128` | Server port |
+| `NEXT_PUBLIC_BASE_URL` | `http://localhost:20128` | Base URL for frontend |
+| `JWT_SECRET` | (generate above) | JWT signing secret |
+| `INITIAL_PASSWORD` | `CHANGEME` | First login password |
+| `APP_LOG_LEVEL` | `info` | Log verbosity level |
+
+### Dashboard Settings
+
+The dashboard provides UI toggles for features that can also be configured via environment variables:
+
+| Setting Location | Toggle | Description |
+| ------------------- | ------------------ | ------------------------------ |
+| Settings → Advanced | Debug Mode | Enable debug request logs (UI) |
+| Settings → General | Sidebar Visibility | Show/hide sidebar sections |
+
+These settings are stored in the database and persist across restarts, overriding env var defaults when set.
+
+### Running Locally
+
+```bash
+# Development mode (hot reload)
+npm run dev
+
+# Production build
+npm run build
+npm run start
+
+# Common port configuration
+PORT=20128 NEXT_PUBLIC_BASE_URL=http://localhost:20128 npm run dev
+```
+
+Default URLs:
+
+- **Dashboard**: `http://localhost:20128/dashboard`
+- **API**: `http://localhost:20128/v1`
+
+---
+
+## Git Workflow
+
+> ⚠️ **NEVER commit directly to `main`.** Always use feature branches.
+
+```bash
+git checkout -b feat/your-feature-name
+# ... make changes ...
+git commit -m "feat: describe your change"
+git push -u origin feat/your-feature-name
+# Open a Pull Request on GitHub
+```
+
+### Branch Naming
+
+| Prefix | Purpose |
+| ----------- | ------------------------- |
+| `feat/` | New features |
+| `fix/` | Bug fixes |
+| `refactor/` | Code restructuring |
+| `docs/` | Documentation changes |
+| `test/` | Test additions/fixes |
+| `chore/` | Tooling, CI, dependencies |
+
+### Commit Messages
+
+Follow [Conventional Commits](https://www.conventionalcommits.org/):
+
+```
+feat: add circuit breaker for provider calls
+fix: resolve JWT secret validation edge case
+docs: update SECURITY.md with PII protection
+test: add observability unit tests
+refactor(db): consolidate rate limit tables
+```
+
+Scopes: `db`, `sse`, `oauth`, `dashboard`, `api`, `cli`, `docker`, `ci`, `mcp`, `a2a`, `memory`, `skills`.
+
+---
+
+## Running Tests
+
+```bash
+# All tests (unit + vitest + ecosystem + e2e)
+npm run test:all
+
+# Single test file (Node.js native test runner — most tests use this)
+node --import tsx/esm --test tests/unit/your-file.test.mjs
+
+# Vitest (MCP server, autoCombo, cache)
+npm run test:vitest
+
+# E2E tests (requires Playwright)
+npm run test:e2e
+
+# Protocol clients E2E (MCP transports, A2A)
+npm run test:protocols:e2e
+
+# Ecosystem compatibility tests
+npm run test:ecosystem
+
+# Coverage (55% min statements/lines/functions; 60% branches)
+npm run test:coverage
+npm run coverage:report
+
+# Lint + format check
+npm run lint
+npm run check
+```
+
+Coverage notes:
+
+- `npm run test:coverage` measures source coverage for the main unit test suite, excludes `tests/**`, and includes `open-sse/**`
+- `npm run coverage:report` prints the detailed file-by-file report from the latest coverage run
+- `npm run test:coverage:legacy` preserves the older metric for historical comparison
+- See `docs/COVERAGE_PLAN.md` for the phased coverage improvement roadmap
+
+Current test status: **122 unit test files** covering:
+
+- Provider translators and format conversion
+- Rate limiting, circuit breaker, and resilience
+- Semantic cache, idempotency, progress tracking
+- Database operations and schema (21 DB modules)
+- OAuth flows and authentication
+- API endpoint validation (Zod v4)
+- MCP server tools and scope enforcement
+- Memory and Skills systems
+
+---
+
+## Code Style
+
+- **ESLint** — Run `npm run lint` before committing
+- **Prettier** — Auto-formatted via `lint-staged` on commit (2 spaces, semicolons, double quotes, 100 char width, es5 trailing commas)
+- **TypeScript** — All `src/` code uses `.ts`/`.tsx`; `open-sse/` uses `.ts`/`.js`; document with TSDoc (`@param`, `@returns`, `@throws`)
+- **No `eval()`** — ESLint enforces `no-eval`, `no-implied-eval`, `no-new-func`
+- **Zod validation** — Use Zod v4 schemas for all API input validation
+- **Naming**: Files = camelCase/kebab-case, components = PascalCase, constants = UPPER_SNAKE
+
+---
+
+## Project Structure
+
+```
+src/ # TypeScript (.ts / .tsx)
+├── app/ # Next.js 16 App Router
+│ ├── (dashboard)/ # Dashboard pages (23 sections)
+│ ├── api/ # API routes (51 directories)
+│ └── login/ # Auth pages (.tsx)
+├── domain/ # Policy engine (policyEngine, comboResolver, costRules, etc.)
+├── lib/ # Core business logic (.ts)
+│ ├── a2a/ # Agent-to-Agent v0.3 protocol server
+│ ├── acp/ # Agent Communication Protocol registry
+│ ├── compliance/ # Compliance policy engine
+│ ├── db/ # SQLite database layer (21 modules + 16 migrations)
+│ ├── memory/ # Persistent conversational memory
+│ ├── oauth/ # OAuth providers, services, and utilities
+│ ├── skills/ # Extensible skill framework
+│ ├── usage/ # Usage tracking and cost calculation
+│ └── localDb.ts # Re-export layer only — never add logic here
+├── middleware/ # Request middleware (promptInjectionGuard)
+├── mitm/ # MITM proxy (cert, DNS, target routing)
+├── shared/
+│ ├── components/ # React components (.tsx)
+│ ├── constants/ # Provider definitions (60+), MCP scopes, routing strategies
+│ ├── utils/ # Circuit breaker, sanitizer, auth helpers
+│ └── validation/ # Zod v4 schemas
+└── sse/ # SSE proxy pipeline
+
+open-sse/ # @omniroute/open-sse workspace
+├── executors/ # 14 provider-specific request executors
+├── handlers/ # 11 request handlers (chat, responses, embeddings, images, etc.)
+├── mcp-server/ # MCP server (25 tools, 3 transports, 10 scopes)
+├── services/ # 36+ services (combo, autoCombo, rateLimitManager, etc.)
+├── translator/ # Format translators (OpenAI ↔ Claude ↔ Gemini ↔ Responses ↔ Ollama)
+├── transformer/ # Responses API transformer
+└── utils/ # 22 utility modules (stream, TLS, proxy, logging)
+
+electron/ # Electron desktop app (cross-platform)
+
+tests/
+├── unit/ # Node.js test runner (122 test files)
+├── integration/ # Integration tests
+├── e2e/ # Playwright tests
+├── security/ # Security tests
+├── translator/ # Translator-specific tests
+└── load/ # Load tests
+
+docs/ # Documentation
+├── ARCHITECTURE.md # System architecture
+├── API_REFERENCE.md # All endpoints
+├── USER_GUIDE.md # Provider setup, CLI integration
+├── TROUBLESHOOTING.md # Common issues
+├── MCP-SERVER.md # MCP server (25 tools)
+├── A2A-SERVER.md # A2A agent protocol
+├── AUTO-COMBO.md # Auto-combo engine
+├── CLI-TOOLS.md # CLI tools integration
+├── COVERAGE_PLAN.md # Test coverage improvement plan
+├── openapi.yaml # OpenAPI specification
+└── adr/ # Architecture Decision Records
+```
+
+---
+
+## Adding a New Provider
+
+### Step 1: Register Provider Constants
+
+Add to `src/shared/constants/providers.ts` — Zod-validated at module load.
+
+### Step 2: Add Executor (if custom logic needed)
+
+Create executor in `open-sse/executors/your-provider.ts` extending the base executor.
+
+### Step 3: Add Translator (if non-OpenAI format)
+
+Create request/response translators in `open-sse/translator/`.
+
+### Step 4: Add OAuth Config (if OAuth-based)
+
+Add OAuth credentials in `src/lib/oauth/constants/oauth.ts` and service in `src/lib/oauth/services/`.
+
+### Step 5: Register Models
+
+Add model definitions in `open-sse/config/providerRegistry.ts`.
+
+### Step 6: Add Tests
+
+Write unit tests in `tests/unit/` covering at minimum:
+
+- Provider registration
+- Request/response translation
+- Error handling
+
+---
+
+## Pull Request Checklist
+
+- [ ] Tests pass (`npm test`)
+- [ ] Linting passes (`npm run lint`)
+- [ ] Build succeeds (`npm run build`)
+- [ ] TypeScript types added for new public functions and interfaces
+- [ ] No hardcoded secrets or fallback values
+- [ ] All inputs validated with Zod schemas
+- [ ] CHANGELOG updated (if user-facing change)
+- [ ] Documentation updated (if applicable)
+
+---
+
+## Releasing
+
+Releases are managed via the `/generate-release` workflow. When a new GitHub Release is created, the package is **automatically published to npm** via GitHub Actions.
+
+---
+
+## Getting Help
+
+- **Architecture**: See [`docs/ARCHITECTURE.md`](docs/ARCHITECTURE.md)
+- **API Reference**: See [`docs/API_REFERENCE.md`](docs/API_REFERENCE.md)
+- **Issues**: [github.com/diegosouzapw/OmniRoute/issues](https://github.com/diegosouzapw/OmniRoute/issues)
+- **ADRs**: See `docs/adr/` for architectural decision records
diff --git a/docs/i18n/fi/FEATURES.md b/docs/i18n/fi/FEATURES.md
deleted file mode 100644
index 564e8059c9..0000000000
--- a/docs/i18n/fi/FEATURES.md
+++ /dev/null
@@ -1,147 +0,0 @@
-# OmniRoute — Dashboard Features Gallery (Suomi)
-
-🌐 **Languages:** 🇺🇸 [English](../../../README.md) · 🇧🇷 [pt-BR](../pt-BR/README.md) · 🇪🇸 [es](../es/README.md) · 🇫🇷 [fr](../fr/README.md) · 🇩🇪 [de](../de/README.md) · 🇮🇹 [it](../it/README.md) · 🇷🇺 [ru](../ru/README.md) · 🇨🇳 [zh-CN](../zh-CN/README.md) · 🇯🇵 [ja](../ja/README.md) · 🇰🇷 [ko](../ko/README.md) · 🇸🇦 [ar](../ar/README.md) · 🇮🇳 [in](../in/README.md) · 🇹🇭 [th](../th/README.md) · 🇻🇳 [vi](../vi/README.md) · 🇮🇩 [id](../id/README.md) · 🇲🇾 [ms](../ms/README.md) · 🇳🇱 [nl](../nl/README.md) · 🇵🇱 [pl](../pl/README.md) · 🇸🇪 [sv](../sv/README.md) · 🇳🇴 [no](../no/README.md) · 🇩🇰 [da](../da/README.md) · 🇫🇮 [fi](../fi/README.md) · 🇵🇹 [pt](../pt/README.md) · 🇷🇴 [ro](../ro/README.md) · 🇭🇺 [hu](../hu/README.md) · 🇧🇬 [bg](../bg/README.md) · 🇸🇰 [sk](../sk/README.md) · 🇺🇦 [uk-UA](../uk-UA/README.md) · 🇮🇱 [he](../he/README.md) · 🇵🇭 [phi](../phi/README.md)
-
-> 🇺🇸 [English](../../../docs/FEATURES.md)
-
----
-
-Visual guide to every section of the OmniRoute dashboard.
-
----
-
-## 🔌 Providers
-
-Manage AI provider connections: OAuth providers (Claude Code, Codex, Gemini CLI), API key providers (Groq, DeepSeek, OpenRouter), and free providers (Qoder, Qwen, Kiro). Kiro accounts include credit balance tracking — remaining credits, total allowance, and renewal date visible in Dashboard → Usage.
-
-
-
----
-
-## 🎨 Combos
-
-Create model routing combos with 6 strategies: priority, weighted, round-robin, random, least-used, and cost-optimized. Each combo chains multiple models with automatic fallback and includes quick templates and readiness checks.
-
-
-
----
-
-## 📊 Analytics
-
-Comprehensive usage analytics with token consumption, cost estimates, activity heatmaps, weekly distribution charts, and per-provider breakdowns.
-
-
-
----
-
-## 🏥 System Health
-
-Real-time monitoring: uptime, memory, version, latency percentiles (p50/p95/p99), cache statistics, and provider circuit breaker states.
-
-
-
----
-
-## 🔧 Translator Playground
-
-Four modes for debugging API translations: **Playground** (format converter), **Chat Tester** (live requests), **Test Bench** (batch tests), and **Live Monitor** (real-time stream).
-
-
-
----
-
-## 🎮 Model Playground _(v2.0.9+)_
-
-Test any model directly from the dashboard. Select provider, model, and endpoint, write prompts with Monaco Editor, stream responses in real-time, abort mid-stream, and view timing metrics.
-
----
-
-## 🎨 Themes _(v2.0.5+)_
-
-Customizable color themes for the entire dashboard. Choose from 7 preset colors (Coral, Blue, Red, Green, Violet, Orange, Cyan) or create a custom theme by picking any hex color. Supports light, dark, and system mode.
-
----
-
-## ⚙️ Settings
-
-Comprehensive settings panel with tabs:
-
-- **General** — System storage, backup management (export/import database)
-- **Appearance** — Theme selector (dark/light/system), color theme presets and custom colors, health log visibility, sidebar item visibility controls
-- **Security** — API endpoint protection, custom provider blocking, IP filtering, session info
-- **Routing** — Model aliases, background task degradation
-- **Resilience** — Rate limit persistence, circuit breaker tuning
-- **Advanced** — Configuration overrides
-
-
-
----
-
-## 🔧 CLI Tools
-
-One-click configuration for AI coding tools: Claude Code, Codex CLI, Gemini CLI, OpenClaw, Kilo Code, Antigravity, Cline, Continue, Cursor, and Factory Droid. Features automated config apply/reset, connection profiles, and model mapping.
-
-
-
----
-
-## 🤖 CLI Agents _(v2.0.11+)_
-
-Dashboard for discovering and managing CLI agents. Shows a grid of 14 built-in agents (Codex, Claude, Goose, Gemini CLI, OpenClaw, Aider, OpenCode, Cline, Qwen Code, ForgeCode, Amazon Q, Open Interpreter, Cursor CLI, Warp) with:
-
-- **Installation status** — Installed / Not Found with version detection
-- **Protocol badges** — stdio, HTTP, etc.
-- **Custom agents** — Register any CLI tool via form (name, binary, version command, spawn args)
-- **CLI Fingerprint Matching** — Per-provider toggle to match native CLI request signatures, reducing ban risk while preserving proxy IP
-
----
-
-## 🖼️ Media _(v2.0.3+)_
-
-Generate images, videos, and music from the dashboard. Supports OpenAI, xAI, Together, Hyperbolic, SD WebUI, ComfyUI, AnimateDiff, Stable Audio Open, and MusicGen.
-
----
-
-## 📝 Request Logs
-
-Real-time request logging with filtering by provider, model, account, and API key. Shows status codes, token usage, latency, and response details.
-
-
-
----
-
-## 🌐 API Endpoint
-
-Your unified API endpoint with capability breakdown: Chat Completions, Responses API, Embeddings, Image Generation, Reranking, Audio Transcription, Text-to-Speech, Moderations, and registered API keys. Cloud proxy support for remote access.
-
-
-
----
-
-## 🔑 API Key Management
-
-Create, scope, and revoke API keys. Each key can be restricted to specific models/providers with full access or read-only permissions. Visual key management with usage tracking.
-
----
-
-## 📋 Audit Log
-
-Administrative action tracking with filtering by action type, actor, target, IP address, and timestamp. Full security event history.
-
----
-
-## 🖥️ Desktop Application
-
-Native Electron desktop app for Windows, macOS, and Linux. Run OmniRoute as a standalone application with system tray integration, offline support, auto-update, and one-click install.
-
-Key features:
-
-- Server readiness polling (no blank screen on cold start)
-- System tray with port management
-- Content Security Policy
-- Single-instance lock
-- Auto-update on restart
-- Platform-conditional UI (macOS traffic lights, Windows/Linux default titlebar)
-- Hardened Electron build packaging — symlinked `node_modules` in the standalone bundle is detected and rejected before packaging, preventing runtime dependency on the build machine (v2.5.5+)
-
-📖 See [`electron/README.md`](../electron/README.md) for full documentation.
diff --git a/docs/i18n/fi/MCP-SERVER.md b/docs/i18n/fi/MCP-SERVER.md
deleted file mode 100644
index 829acd30b1..0000000000
--- a/docs/i18n/fi/MCP-SERVER.md
+++ /dev/null
@@ -1,87 +0,0 @@
-🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/MCP-SERVER.md) · 🇪🇸 [es](../es/MCP-SERVER.md) · 🇫🇷 [fr](../fr/MCP-SERVER.md) · 🇩🇪 [de](../de/MCP-SERVER.md) · 🇮🇹 [it](../it/MCP-SERVER.md) · 🇷🇺 [ru](../ru/MCP-SERVER.md) · 🇨🇳 [zh-CN](../zh-CN/MCP-SERVER.md) · 🇯🇵 [ja](../ja/MCP-SERVER.md) · 🇰🇷 [ko](../ko/MCP-SERVER.md) · 🇸🇦 [ar](../ar/MCP-SERVER.md) · 🇮🇳 [in](../in/MCP-SERVER.md) · 🇹🇭 [th](../th/MCP-SERVER.md) · 🇻🇳 [vi](../vi/MCP-SERVER.md) · 🇮🇩 [id](../id/MCP-SERVER.md) · 🇲🇾 [ms](../ms/MCP-SERVER.md) · 🇳🇱 [nl](../nl/MCP-SERVER.md) · 🇵🇱 [pl](../pl/MCP-SERVER.md) · 🇸🇪 [sv](../sv/MCP-SERVER.md) · 🇳🇴 [no](../no/MCP-SERVER.md) · 🇩🇰 [da](../da/MCP-SERVER.md) · 🇫🇮 [fi](../fi/MCP-SERVER.md) · 🇵🇹 [pt](../pt/MCP-SERVER.md) · 🇷🇴 [ro](../ro/MCP-SERVER.md) · 🇭🇺 [hu](../hu/MCP-SERVER.md) · 🇧🇬 [bg](../bg/MCP-SERVER.md) · 🇸🇰 [sk](../sk/MCP-SERVER.md) · 🇺🇦 [uk-UA](../uk-UA/MCP-SERVER.md) · 🇮🇱 [he](../he/MCP-SERVER.md) · 🇵🇭 [phi](../phi/MCP-SERVER.md)
-
----
-
-# OmniRoute MCP Server Documentation
-
-> Model Context Protocol server with 16 intelligent tools
-
-## Installation
-
-OmniRoute MCP is built-in. Start it with:
-
-```bash
-omniroute --mcp
-```
-
-Or via the open-sse transport:
-
-```bash
-# HTTP streamable transport (port 20130)
-omniroute --dev # MCP auto-starts on /mcp endpoint
-```
-
-## IDE Configuration
-
-See [IDE Configs](integrations/ide-configs.md) for Antigravity, Cursor, Copilot, and Claude Desktop setup.
-
----
-
-## Essential Tools (8)
-
-| Tool | Description |
-| :------------------------------ | :--------------------------------------- |
-| `omniroute_get_health` | Gateway health, circuit breakers, uptime |
-| `omniroute_list_combos` | All configured combos with models |
-| `omniroute_get_combo_metrics` | Performance metrics for a specific combo |
-| `omniroute_switch_combo` | Switch active combo by ID/name |
-| `omniroute_check_quota` | Quota status per provider or all |
-| `omniroute_route_request` | Send a chat completion through OmniRoute |
-| `omniroute_cost_report` | Cost analytics for a time period |
-| `omniroute_list_models_catalog` | Full model catalog with capabilities |
-
-## Advanced Tools (8)
-
-| Tool | Description |
-| :--------------------------------- | :---------------------------------------------- |
-| `omniroute_simulate_route` | Dry-run routing simulation with fallback tree |
-| `omniroute_set_budget_guard` | Session budget with degrade/block/alert actions |
-| `omniroute_set_resilience_profile` | Apply conservative/balanced/aggressive preset |
-| `omniroute_test_combo` | Live-test all models in a combo |
-| `omniroute_get_provider_metrics` | Detailed metrics for one provider |
-| `omniroute_best_combo_for_task` | Task-fitness recommendation with alternatives |
-| `omniroute_explain_route` | Explain a past routing decision |
-| `omniroute_get_session_snapshot` | Full session state: costs, tokens, errors |
-
-## Authentication
-
-MCP tools are authenticated via API key scopes. Each tool requires specific scopes:
-
-| Scope | Tools |
-| :------------- | :----------------------------------------------- |
-| `read:health` | get_health, get_provider_metrics |
-| `read:combos` | list_combos, get_combo_metrics |
-| `write:combos` | switch_combo |
-| `read:quota` | check_quota |
-| `write:route` | route_request, simulate_route, test_combo |
-| `read:usage` | cost_report, get_session_snapshot, explain_route |
-| `write:config` | set_budget_guard, set_resilience_profile |
-| `read:models` | list_models_catalog, best_combo_for_task |
-
-## Audit Logging
-
-Every tool call is logged to `mcp_tool_audit` with:
-
-- Tool name, arguments, result
-- Duration (ms), success/failure
-- API key hash, timestamp
-
-## Files
-
-| File | Purpose |
-| :------------------------------------------- | :------------------------------------------ |
-| `open-sse/mcp-server/server.ts` | MCP server creation + 16 tool registrations |
-| `open-sse/mcp-server/transport.ts` | Stdio + HTTP transport |
-| `open-sse/mcp-server/auth.ts` | API key + scope validation |
-| `open-sse/mcp-server/audit.ts` | Tool call audit logging |
-| `open-sse/mcp-server/tools/advancedTools.ts` | 8 advanced tool handlers |
diff --git a/docs/i18n/fi/README.md b/docs/i18n/fi/README.md
index b199ab0db7..3478a21b3a 100644
--- a/docs/i18n/fi/README.md
+++ b/docs/i18n/fi/README.md
@@ -1,13 +1,12 @@
# 🚀 OmniRoute — The Free AI Gateway (Suomi)
-🌐 **Languages:** 🇺🇸 [English](../../../README.md) · 🇪🇸 [es](../es/README.md) · 🇫🇷 [fr](../fr/README.md) · 🇩🇪 [de](../de/README.md) · 🇮🇹 [it](../it/README.md) · 🇷🇺 [ru](../ru/README.md) · 🇨🇳 [zh-CN](../zh-CN/README.md) · 🇯🇵 [ja](../ja/README.md) · 🇰🇷 [ko](../ko/README.md) · 🇸🇦 [ar](../ar/README.md) · 🇮🇳 [in](../in/README.md) · 🇹🇭 [th](../th/README.md) · 🇻🇳 [vi](../vi/README.md) · 🇮🇩 [id](../id/README.md) · 🇲🇾 [ms](../ms/README.md) · 🇳🇱 [nl](../nl/README.md) · 🇵🇱 [pl](../pl/README.md) · 🇸🇪 [sv](../sv/README.md) · 🇳🇴 [no](../no/README.md) · 🇩🇰 [da](../da/README.md) · 🇫🇮 [fi](../fi/README.md) · 🇵🇹 [pt](../pt/README.md) · 🇷🇴 [ro](../ro/README.md) · 🇭🇺 [hu](../hu/README.md) · 🇧🇬 [bg](../bg/README.md) · 🇸🇰 [sk](../sk/README.md) · 🇺🇦 [uk-UA](../uk-UA/README.md) · 🇮🇱 [he](../he/README.md) · 🇵🇭 [phi](../phi/README.md) · 🇧🇷 [pt-BR](../pt-BR/README.md)
+🌐 **Languages:** 🇺🇸 [English](../../../README.md) · 🇪🇸 [es](../es/README.md) · 🇫🇷 [fr](../fr/README.md) · 🇩🇪 [de](../de/README.md) · 🇮🇹 [it](../it/README.md) · 🇷🇺 [ru](../ru/README.md) · 🇨🇳 [zh-CN](../zh-CN/README.md) · 🇯🇵 [ja](../ja/README.md) · 🇰🇷 [ko](../ko/README.md) · 🇸🇦 [ar](../ar/README.md) · 🇮🇳 [in](../in/README.md) · 🇹🇭 [th](../th/README.md) · 🇻🇳 [vi](../vi/README.md) · 🇮🇩 [id](../id/README.md) · 🇲🇾 [ms](../ms/README.md) · 🇳🇱 [nl](../nl/README.md) · 🇵🇱 [pl](../pl/README.md) · 🇸🇪 [sv](../sv/README.md) · 🇳🇴 [no](../no/README.md) · 🇩🇰 [da](../da/README.md) · 🇫🇮 [fi](../fi/README.md) · 🇵🇹 [pt](../pt/README.md) · 🇷🇴 [ro](../ro/README.md) · 🇭🇺 [hu](../hu/README.md) · 🇧🇬 [bg](../bg/README.md) · 🇸🇰 [sk](../sk/README.md) · 🇺🇦 [uk-UA](../uk-UA/README.md) · 🇮🇱 [he](../he/README.md) · 🇵🇭 [phi](../phi/README.md) · 🇧🇷 [pt-BR](../pt-BR/README.md) · 🇨🇿 [cs](../cs/README.md)
---
-
### Never stop coding. Smart routing to **FREE & low-cost AI models** with automatic fallback.
-_Your universal API proxy — one endpoint, 67+ providers, zero downtime. Now with **MCP & A2A** agent orchestration._
+_Your universal API proxy — one endpoint, 60+ providers, zero downtime. Now with **MCP Server (25 tools)**, **A2A Protocol**, **Memory/Skills Systems** & **Electron Desktop App**._
**Chat Completions • Embeddings • Image Generation • Video • Music • Audio • Reranking • **Web Search** • MCP Server • A2A Protocol • 100% TypeScript**
@@ -47,15 +46,17 @@ _Your universal API proxy — one endpoint, 67+ providers, zero downtime. Now wi
> - `APP_LOG_FILE_PATH`
> - `APP_LOG_MAX_FILE_SIZE`
> - `APP_LOG_RETENTION_DAYS`
+> - `APP_LOG_MAX_FILES`
> - `APP_LOG_LEVEL`
> - `APP_LOG_FORMAT`
> - `CALL_LOG_RETENTION_DAYS`
+> - `CALL_LOG_MAX_ENTRIES`
>
> For release details and upgrade notes, see the [CHANGELOG](CHANGELOG.md).
---
-## 🆕 What's New in v3.0.0
+## 🆕 What's New
> **Upgrading from v2.9.5?** — See the [full CHANGELOG](CHANGELOG.md#300--2026-03-22-release-candidate--not-yet-merged-to-main) for all changes.
@@ -275,7 +276,7 @@ Developers pay $20–200/month for Claude Pro, Codex Pro, or GitHub Copilot. Eve
- **Smart 4-Tier Fallback** — If subscription quota runs out, automatically redirects to API Key → Cheap → Free with zero manual intervention
- **Real-Time Quota Tracking** — Shows token consumption in real-time with reset countdown (5h, daily, weekly)
- **Multi-Account Support** — Multiple accounts per provider with auto round-robin — when one runs out, switches to the next
-- **Custom Combos** — Customizable fallback chains with 6 balancing strategies (fill-first, round-robin, P2C, random, least-used, cost-optimized)
+- **Custom Combos** — Customizable fallback chains with 9 balancing strategies (priority, weighted, fill-first, round-robin, P2C, random, least-used, cost-optimized, strict-random)
- **Codex Business Quotas** — Business/Team workspace quota monitoring directly in the dashboard
@@ -287,7 +288,7 @@ OpenAI uses one format, Claude (Anthropic) uses another, Gemini yet another. If
**How OmniRoute solves it:**
-- **Unified Endpoint** — A single `http://localhost:20128/v1` serves as proxy for all 67+ providers
+- **Unified Endpoint** — A single `http://localhost:20128/v1` serves as proxy for all 60+ providers
- **Format Translation** — Automatic and transparent: OpenAI ↔ Claude ↔ Gemini ↔ Responses API
- **Response Sanitization** — Strips non-standard fields (`x_groq`, `usage_breakdown`, `service_tier`) that break OpenAI SDK v1.83+
- **Role Normalization** — Converts `developer` → `system` for non-OpenAI providers; `system` → `user` for GLM/ERNIE
@@ -373,7 +374,7 @@ Developers use Cursor, Claude Code, Codex CLI, OpenClaw, Gemini CLI, Kilo Code..
- **CLI Tools Dashboard** — Dedicated page with one-click setup for Claude Code, Codex CLI, OpenClaw, Kilo Code, Antigravity, Cline
- **GitHub Copilot Config Generator** — Generates `chatLanguageModels.json` for VS Code with bulk model selection
- **Onboarding Wizard** — Guided 4-step setup for first-time users
-- **One endpoint, all models** — Configure `http://localhost:20128/v1` once, access 67+ providers
+- **One endpoint, all models** — Configure `http://localhost:20128/v1` once, access 60+ providers
@@ -420,7 +421,7 @@ When a call fails, the dev doesn't know if it was a rate limit, expired token, w
- **SQLite Proxy Logs** — Persistent logs that survive server restarts
- **Translator Playground** — 4 debugging modes: Playground (format translation), Chat Tester (round-trip), Test Bench (batch), Live Monitor (real-time)
- **Request Telemetry** — p50/p95/p99 latency + X-Request-Id tracing
-- **File-Based Logging with Rotation** — Console interceptor captures everything to JSON log with size-based rotation
+- **File-Based Logging with Rotation** — App logs rotate by size, retention days, and archive count; call log artifacts rotate by retention days and file count
- **System Info Report** — `npm run system-info` generates `system-info.txt` with your full environment (Node version, OmniRoute version, OS, CLI tools, Docker/PM2 status). Attach it when reporting issues for instant triage.
@@ -515,7 +516,7 @@ Developers who want all responses in a specific language, with a specific tone,
- **System Prompt Injection** — Global prompt applied to all requests
- **Thinking Budget Validation** — Reasoning token allocation control per request (passthrough, auto, custom, adaptive)
-- **6 Routing Strategies** — Global strategies that determine how requests are distributed
+- **9 Routing Strategies** — Global strategies that determine how requests are distributed
- **Wildcard Router** — `provider/*` patterns route dynamically to any provider
- **Combo Enable/Disable Toggle** — Toggle combos directly from the dashboard
- **Provider Toggle** — Enable/disable all connections for a provider with one click
@@ -582,7 +583,7 @@ Different clients should have least-privilege access to tool categories.
**How OmniRoute solves it:**
-- 9 granular MCP scopes for controlled tool access
+- 10 granular MCP scopes for controlled tool access
- Scope enforcement and visibility in MCP management UI
- Safe default posture for operational tooling
@@ -1326,19 +1327,19 @@ OmniRoute v2.0 is built as an operational platform, not just a relay proxy.
### 🤖 Agent & Protocol Operations (v2.0)
-| Feature | What It Does |
-| ------------------------------------- | -------------------------------------------------------------------------------------------------- |
-| 🔧 **MCP Server (16 tools)** | IDE/agent tools via 3 transports: stdio, SSE (`/api/mcp/sse`), Streamable HTTP (`/api/mcp/stream`) |
-| 🤝 **A2A Server (JSON-RPC + SSE)** | Agent-to-agent task execution with sync and streaming flows |
-| 🧭 **Consolidated Endpoints Page** | Tabbed management page with Endpoint Proxy, MCP, A2A, and API Endpoints tabs |
-| 🎚️ **Service Enable/Disable Toggles** | ON/OFF switches for MCP and A2A with settings persistence (default: OFF) |
-| 🛰️ **MCP Runtime Heartbeat** | Real process status (pid, uptime, heartbeat age, transport, scope mode) |
-| 📋 **MCP Audit Trail** | Filterable audit logs with success/failure and key attribution |
-| 🔐 **MCP Scope Enforcement** | 9 granular scope permissions for controlled tool access |
-| 📡 **A2A Task Lifecycle Management** | List/filter tasks, inspect events/artifacts, cancel running tasks |
-| 📋 **Agent Card Discovery** | `/.well-known/agent.json` for client auto-discovery |
-| 🧪 **Protocol E2E Test Harness** | Real MCP SDK + A2A client flows in `test:protocols:e2e` |
-| ⚙️ **Operational Controls** | Switch combo, apply resilience profiles, reset breakers from one control surface |
+| Feature | What It Does |
+| ------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------- |
+| 🔧 **MCP Server (25 tools)** | IDE/agent tools via 3 transports: stdio, SSE (`/api/mcp/sse`), Streamable HTTP (`/api/mcp/stream`). 18 core + 3 memory + 4 skill tools |
+| 🤝 **A2A Server (JSON-RPC + SSE)** | Agent-to-agent task execution with sync and streaming flows |
+| 🧭 **Consolidated Endpoints Page** | Tabbed management page with Endpoint Proxy, MCP, A2A, and API Endpoints tabs |
+| 🎚️ **Service Enable/Disable Toggles** | ON/OFF switches for MCP and A2A with settings persistence (default: OFF) |
+| 🛰️ **MCP Runtime Heartbeat** | Real process status (pid, uptime, heartbeat age, transport, scope mode) |
+| 📋 **MCP Audit Trail** | Filterable audit logs with success/failure and key attribution |
+| 🔐 **MCP Scope Enforcement** | 10 granular scope permissions for controlled tool access |
+| 📡 **A2A Task Lifecycle Management** | List/filter tasks, inspect events/artifacts, cancel running tasks |
+| 📋 **Agent Card Discovery** | `/.well-known/agent.json` for client auto-discovery |
+| 🧪 **Protocol E2E Test Harness** | Real MCP SDK + A2A client flows in `test:protocols:e2e` |
+| ⚙️ **Operational Controls** | Switch combo, apply resilience profiles, reset breakers from one control surface |
### 🧠 Routing & Intelligence
@@ -1349,7 +1350,7 @@ OmniRoute v2.0 is built as an operational platform, not just a relay proxy.
| 🔄 **Format Translation** | OpenAI ↔ Claude ↔ Gemini ↔ Responses with schema-safe conversions |
| 👥 **Multi-Account Support** | Multiple accounts per provider with intelligent selection |
| 🔄 **Auto Token Refresh** | OAuth tokens refresh automatically with retry |
-| 🎨 **Custom Combos** | 6 balancing strategies + fallback chain control |
+| 🎨 **Custom Combos** | 9 balancing strategies + fallback chain control |
| 🌐 **Wildcard Router** | `provider/*` dynamic routing |
| 🧠 **Thinking Budget Controls** | Passthrough, auto, custom, and adaptive reasoning limits |
| 🔀 **Model Aliases** | Built-in + custom model aliasing and migration safety |
@@ -1950,6 +1951,7 @@ opencode
- Request artifacts are written to `DATA_DIR/call_logs/` as one JSON file per request
- Enable pipeline capture from Dashboard → Logs → Request Logs if you need detailed per-stage payloads
- Set `APP_LOG_TO_FILE=true` if you also want application console logs in `logs/application/app.log`
+- Adjust `APP_LOG_MAX_FILE_SIZE`, `APP_LOG_RETENTION_DAYS`, `APP_LOG_MAX_FILES`, and `CALL_LOG_MAX_ENTRIES` as needed
**Connection test shows "Invalid" for OpenAI-compatible providers**
diff --git a/docs/i18n/fi/RELEASE_CHECKLIST.md b/docs/i18n/fi/RELEASE_CHECKLIST.md
deleted file mode 100644
index 903e812c3f..0000000000
--- a/docs/i18n/fi/RELEASE_CHECKLIST.md
+++ /dev/null
@@ -1,37 +0,0 @@
-🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/RELEASE_CHECKLIST.md) · 🇪🇸 [es](../es/RELEASE_CHECKLIST.md) · 🇫🇷 [fr](../fr/RELEASE_CHECKLIST.md) · 🇩🇪 [de](../de/RELEASE_CHECKLIST.md) · 🇮🇹 [it](../it/RELEASE_CHECKLIST.md) · 🇷🇺 [ru](../ru/RELEASE_CHECKLIST.md) · 🇨🇳 [zh-CN](../zh-CN/RELEASE_CHECKLIST.md) · 🇯🇵 [ja](../ja/RELEASE_CHECKLIST.md) · 🇰🇷 [ko](../ko/RELEASE_CHECKLIST.md) · 🇸🇦 [ar](../ar/RELEASE_CHECKLIST.md) · 🇮🇳 [in](../in/RELEASE_CHECKLIST.md) · 🇹🇭 [th](../th/RELEASE_CHECKLIST.md) · 🇻🇳 [vi](../vi/RELEASE_CHECKLIST.md) · 🇮🇩 [id](../id/RELEASE_CHECKLIST.md) · 🇲🇾 [ms](../ms/RELEASE_CHECKLIST.md) · 🇳🇱 [nl](../nl/RELEASE_CHECKLIST.md) · 🇵🇱 [pl](../pl/RELEASE_CHECKLIST.md) · 🇸🇪 [sv](../sv/RELEASE_CHECKLIST.md) · 🇳🇴 [no](../no/RELEASE_CHECKLIST.md) · 🇩🇰 [da](../da/RELEASE_CHECKLIST.md) · 🇫🇮 [fi](../fi/RELEASE_CHECKLIST.md) · 🇵🇹 [pt](../pt/RELEASE_CHECKLIST.md) · 🇷🇴 [ro](../ro/RELEASE_CHECKLIST.md) · 🇭🇺 [hu](../hu/RELEASE_CHECKLIST.md) · 🇧🇬 [bg](../bg/RELEASE_CHECKLIST.md) · 🇸🇰 [sk](../sk/RELEASE_CHECKLIST.md) · 🇺🇦 [uk-UA](../uk-UA/RELEASE_CHECKLIST.md) · 🇮🇱 [he](../he/RELEASE_CHECKLIST.md) · 🇵🇭 [phi](../phi/RELEASE_CHECKLIST.md)
-
----
-
-# Release Checklist
-
-Use this checklist before tagging or publishing a new OmniRoute release.
-
-## Version and Changelog
-
-1. Bump `package.json` version (`x.y.z`) in the release branch.
-2. Move release notes from `## [Unreleased]` in `CHANGELOG.md` to a dated section:
- - `## [x.y.z] — YYYY-MM-DD`
-3. Keep `## [Unreleased]` as the first changelog section for upcoming work.
-4. Ensure the latest semver section in `CHANGELOG.md` equals `package.json` version.
-
-## API Docs
-
-1. Update `docs/openapi.yaml`:
- - `info.version` must equal `package.json` version.
-2. Validate endpoint examples if API contracts changed.
-
-## Runtime Docs
-
-1. Review `docs/ARCHITECTURE.md` for storage/runtime drift.
-2. Review `docs/TROUBLESHOOTING.md` for env var and operational drift.
-3. Update localized docs if source docs changed significantly.
-
-## Automated Check
-
-Run the sync guard locally before opening PR:
-
-```bash
-npm run check:docs-sync
-```
-
-CI also runs this check in `.github/workflows/ci.yml` (lint job).
diff --git a/docs/i18n/fi/SECURITY.md b/docs/i18n/fi/SECURITY.md
new file mode 100644
index 0000000000..74b366c597
--- /dev/null
+++ b/docs/i18n/fi/SECURITY.md
@@ -0,0 +1,179 @@
+# Security Policy (Suomi)
+
+🌐 **Languages:** 🇺🇸 [English](../../../SECURITY.md) · 🇪🇸 [es](../es/SECURITY.md) · 🇫🇷 [fr](../fr/SECURITY.md) · 🇩🇪 [de](../de/SECURITY.md) · 🇮🇹 [it](../it/SECURITY.md) · 🇷🇺 [ru](../ru/SECURITY.md) · 🇨🇳 [zh-CN](../zh-CN/SECURITY.md) · 🇯🇵 [ja](../ja/SECURITY.md) · 🇰🇷 [ko](../ko/SECURITY.md) · 🇸🇦 [ar](../ar/SECURITY.md) · 🇮🇳 [in](../in/SECURITY.md) · 🇹🇭 [th](../th/SECURITY.md) · 🇻🇳 [vi](../vi/SECURITY.md) · 🇮🇩 [id](../id/SECURITY.md) · 🇲🇾 [ms](../ms/SECURITY.md) · 🇳🇱 [nl](../nl/SECURITY.md) · 🇵🇱 [pl](../pl/SECURITY.md) · 🇸🇪 [sv](../sv/SECURITY.md) · 🇳🇴 [no](../no/SECURITY.md) · 🇩🇰 [da](../da/SECURITY.md) · 🇫🇮 [fi](../fi/SECURITY.md) · 🇵🇹 [pt](../pt/SECURITY.md) · 🇷🇴 [ro](../ro/SECURITY.md) · 🇭🇺 [hu](../hu/SECURITY.md) · 🇧🇬 [bg](../bg/SECURITY.md) · 🇸🇰 [sk](../sk/SECURITY.md) · 🇺🇦 [uk-UA](../uk-UA/SECURITY.md) · 🇮🇱 [he](../he/SECURITY.md) · 🇵🇭 [phi](../phi/SECURITY.md) · 🇧🇷 [pt-BR](../pt-BR/SECURITY.md) · 🇨🇿 [cs](../cs/SECURITY.md)
+
+---
+
+## Reporting Vulnerabilities
+
+If you discover a security vulnerability in OmniRoute, please report it responsibly:
+
+1. **DO NOT** open a public GitHub issue
+2. Use [GitHub Security Advisories](https://github.com/diegosouzapw/OmniRoute/security/advisories/new)
+3. Include: description, reproduction steps, and potential impact
+
+## Response Timeline
+
+| Stage | Target |
+| ------------------- | --------------------------- |
+| Acknowledgment | 48 hours |
+| Triage & Assessment | 5 business days |
+| Patch Release | 14 business days (critical) |
+
+## Supported Versions
+
+| Version | Support Status |
+| ------- | -------------- |
+| 3.4.x | ✅ Active |
+| 3.0.x | ✅ Security |
+| < 3.0.0 | ❌ Unsupported |
+
+---
+
+## Security Architecture
+
+OmniRoute implements a multi-layered security model:
+
+```
+Request → CORS → API Key Auth → Prompt Injection Guard → Input Sanitizer → Rate Limiter → Circuit Breaker → Provider
+```
+
+### 🔐 Authentication & Authorization
+
+| Feature | Implementation |
+| -------------------- | ---------------------------------------------------------- |
+| **Dashboard Login** | Password-based auth with JWT tokens (HttpOnly cookies) |
+| **API Key Auth** | HMAC-signed keys with CRC validation |
+| **OAuth 2.0 + PKCE** | Secure provider auth (Claude, Codex, Gemini, Cursor, etc.) |
+| **Token Refresh** | Automatic OAuth token refresh before expiry |
+| **Secure Cookies** | `AUTH_COOKIE_SECURE=true` for HTTPS environments |
+| **MCP Scopes** | 10 granular scopes for MCP tool access control |
+
+### 🛡️ Encryption at Rest
+
+All sensitive data stored in SQLite is encrypted using **AES-256-GCM** with scrypt key derivation:
+
+- API keys, access tokens, refresh tokens, and ID tokens
+- Versioned format: `enc:v1:::`
+- Passthrough mode (plaintext) when `STORAGE_ENCRYPTION_KEY` is not set
+
+```bash
+# Generate encryption key:
+STORAGE_ENCRYPTION_KEY=$(openssl rand -hex 32)
+```
+
+### 🧠 Prompt Injection Guard
+
+Middleware that detects and blocks prompt injection attacks in LLM requests:
+
+| Pattern Type | Severity | Example |
+| ------------------- | -------- | ---------------------------------------------- |
+| System Override | High | "ignore all previous instructions" |
+| Role Hijack | High | "you are now DAN, you can do anything" |
+| Delimiter Injection | Medium | Encoded separators to break context boundaries |
+| DAN/Jailbreak | High | Known jailbreak prompt patterns |
+| Instruction Leak | Medium | "show me your system prompt" |
+
+Configure via dashboard (Settings → Security) or `.env`:
+
+```env
+INPUT_SANITIZER_ENABLED=true
+INPUT_SANITIZER_MODE=block # warn | block | redact
+```
+
+### 🔒 PII Redaction
+
+Automatic detection and optional redaction of personally identifiable information:
+
+| PII Type | Pattern | Replacement |
+| ------------- | --------------------- | ------------------ |
+| Email | `user@domain.com` | `[EMAIL_REDACTED]` |
+| CPF (Brazil) | `123.456.789-00` | `[CPF_REDACTED]` |
+| CNPJ (Brazil) | `12.345.678/0001-00` | `[CNPJ_REDACTED]` |
+| Credit Card | `4111-1111-1111-1111` | `[CC_REDACTED]` |
+| Phone | `+55 11 99999-9999` | `[PHONE_REDACTED]` |
+| SSN (US) | `123-45-6789` | `[SSN_REDACTED]` |
+
+```env
+PII_REDACTION_ENABLED=true
+```
+
+### 🌐 Network Security
+
+| Feature | Description |
+| ------------------------ | ---------------------------------------------------------------- |
+| **CORS** | Configurable origin control (`CORS_ORIGIN` env var, default `*`) |
+| **IP Filtering** | Allowlist/blocklist IP ranges in dashboard |
+| **Rate Limiting** | Per-provider rate limits with automatic backoff |
+| **Anti-Thundering Herd** | Mutex + per-connection locking prevents cascading 502s |
+| **TLS Fingerprint** | Browser-like TLS fingerprint spoofing to reduce bot detection |
+| **CLI Fingerprint** | Per-provider header/body ordering to match native CLI signatures |
+
+### 🔌 Resilience & Availability
+
+| Feature | Description |
+| ----------------------- | ------------------------------------------------------------------ |
+| **Circuit Breaker** | 3-state (Closed → Open → Half-Open) per provider, SQLite-persisted |
+| **Request Idempotency** | 5-second dedup window for duplicate requests |
+| **Exponential Backoff** | Automatic retry with increasing delays |
+| **Health Dashboard** | Real-time provider health monitoring |
+
+### 📋 Compliance
+
+| Feature | Description |
+| ------------------ | ----------------------------------------------------------- |
+| **Log Retention** | Automatic cleanup after `CALL_LOG_RETENTION_DAYS` |
+| **No-Log Opt-out** | Per API key `noLog` flag disables request logging |
+| **Audit Log** | Administrative actions tracked in `audit_log` table |
+| **MCP Audit** | SQLite-backed audit logging for all MCP tool calls |
+| **Zod Validation** | All API inputs validated with Zod v4 schemas at module load |
+
+---
+
+## Required Environment Variables
+
+All secrets must be set before starting the server. The server will **fail fast** if they are missing or weak.
+
+```bash
+# REQUIRED — server will not start without these:
+JWT_SECRET=$(openssl rand -base64 48) # min 32 chars
+API_KEY_SECRET=$(openssl rand -hex 32) # min 16 chars
+
+# RECOMMENDED — enables encryption at rest:
+STORAGE_ENCRYPTION_KEY=$(openssl rand -hex 32)
+```
+
+The server actively rejects known-weak values like `changeme`, `secret`, or `password`.
+
+---
+
+## Docker Security
+
+- Use non-root user in production
+- Mount secrets as read-only volumes
+- Never copy `.env` files into Docker images
+- Use `.dockerignore` to exclude sensitive files
+- Set `AUTH_COOKIE_SECURE=true` when behind HTTPS
+
+```bash
+docker run -d \
+ --name omniroute \
+ --restart unless-stopped \
+ --read-only \
+ -p 20128:20128 \
+ -v omniroute-data:/app/data \
+ -e JWT_SECRET="$(openssl rand -base64 48)" \
+ -e API_KEY_SECRET="$(openssl rand -hex 32)" \
+ -e STORAGE_ENCRYPTION_KEY="$(openssl rand -hex 32)" \
+ diegosouzapw/omniroute:latest
+```
+
+---
+
+## Dependencies
+
+- Run `npm audit` regularly
+- Keep dependencies updated
+- The project uses `husky` + `lint-staged` for pre-commit checks
+- CI pipeline runs ESLint security rules on every push
+- Provider constants validated at module load via Zod (`src/shared/validation/providerSchema.ts`)
diff --git a/docs/i18n/fi/TROUBLESHOOTING.md b/docs/i18n/fi/TROUBLESHOOTING.md
deleted file mode 100644
index 63c148000a..0000000000
--- a/docs/i18n/fi/TROUBLESHOOTING.md
+++ /dev/null
@@ -1,258 +0,0 @@
-🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/TROUBLESHOOTING.md) · 🇪🇸 [es](../es/TROUBLESHOOTING.md) · 🇫🇷 [fr](../fr/TROUBLESHOOTING.md) · 🇩🇪 [de](../de/TROUBLESHOOTING.md) · 🇮🇹 [it](../it/TROUBLESHOOTING.md) · 🇷🇺 [ru](../ru/TROUBLESHOOTING.md) · 🇨🇳 [zh-CN](../zh-CN/TROUBLESHOOTING.md) · 🇯🇵 [ja](../ja/TROUBLESHOOTING.md) · 🇰🇷 [ko](../ko/TROUBLESHOOTING.md) · 🇸🇦 [ar](../ar/TROUBLESHOOTING.md) · 🇮🇳 [in](../in/TROUBLESHOOTING.md) · 🇹🇭 [th](../th/TROUBLESHOOTING.md) · 🇻🇳 [vi](../vi/TROUBLESHOOTING.md) · 🇮🇩 [id](../id/TROUBLESHOOTING.md) · 🇲🇾 [ms](../ms/TROUBLESHOOTING.md) · 🇳🇱 [nl](../nl/TROUBLESHOOTING.md) · 🇵🇱 [pl](../pl/TROUBLESHOOTING.md) · 🇸🇪 [sv](../sv/TROUBLESHOOTING.md) · 🇳🇴 [no](../no/TROUBLESHOOTING.md) · 🇩🇰 [da](../da/TROUBLESHOOTING.md) · 🇫🇮 [fi](../fi/TROUBLESHOOTING.md) · 🇵🇹 [pt](../pt/TROUBLESHOOTING.md) · 🇷🇴 [ro](../ro/TROUBLESHOOTING.md) · 🇭🇺 [hu](../hu/TROUBLESHOOTING.md) · 🇧🇬 [bg](../bg/TROUBLESHOOTING.md) · 🇸🇰 [sk](../sk/TROUBLESHOOTING.md) · 🇺🇦 [uk-UA](../uk-UA/TROUBLESHOOTING.md) · 🇮🇱 [he](../he/TROUBLESHOOTING.md) · 🇵🇭 [phi](../phi/TROUBLESHOOTING.md)
-
----
-
-# Troubleshooting
-
-🌐 **Languages:** 🇺🇸 [English](TROUBLESHOOTING.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/TROUBLESHOOTING.md) | 🇪🇸 [Español](i18n/es/TROUBLESHOOTING.md) | 🇫🇷 [Français](i18n/fr/TROUBLESHOOTING.md) | 🇮🇹 [Italiano](i18n/it/TROUBLESHOOTING.md) | 🇷🇺 [Русский](i18n/ru/TROUBLESHOOTING.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/TROUBLESHOOTING.md) | 🇩🇪 [Deutsch](i18n/de/TROUBLESHOOTING.md) | 🇮🇳 [हिन्दी](i18n/in/TROUBLESHOOTING.md) | 🇹🇭 [ไทย](i18n/th/TROUBLESHOOTING.md) | 🇺🇦 [Українська](i18n/uk-UA/TROUBLESHOOTING.md) | 🇸🇦 [العربية](i18n/ar/TROUBLESHOOTING.md) | 🇯🇵 [日本語](i18n/ja/TROUBLESHOOTING.md) | 🇻🇳 [Tiếng Việt](i18n/vi/TROUBLESHOOTING.md) | 🇧🇬 [Български](i18n/bg/TROUBLESHOOTING.md) | 🇩🇰 [Dansk](i18n/da/TROUBLESHOOTING.md) | 🇫🇮 [Suomi](i18n/fi/TROUBLESHOOTING.md) | 🇮🇱 [עברית](i18n/he/TROUBLESHOOTING.md) | 🇭🇺 [Magyar](i18n/hu/TROUBLESHOOTING.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/TROUBLESHOOTING.md) | 🇰🇷 [한국어](i18n/ko/TROUBLESHOOTING.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/TROUBLESHOOTING.md) | 🇳🇱 [Nederlands](i18n/nl/TROUBLESHOOTING.md) | 🇳🇴 [Norsk](i18n/no/TROUBLESHOOTING.md) | 🇵🇹 [Português (Portugal)](i18n/pt/TROUBLESHOOTING.md) | 🇷🇴 [Română](i18n/ro/TROUBLESHOOTING.md) | 🇵🇱 [Polski](i18n/pl/TROUBLESHOOTING.md) | 🇸🇰 [Slovenčina](i18n/sk/TROUBLESHOOTING.md) | 🇸🇪 [Svenska](i18n/sv/TROUBLESHOOTING.md) | 🇵🇭 [Filipino](i18n/phi/TROUBLESHOOTING.md)
-
-Common problems and solutions for OmniRoute.
-
----
-
-## Quick Fixes
-
-| Problem | Solution |
-| ----------------------------- | ------------------------------------------------------------------ |
-| First login not working | Set `INITIAL_PASSWORD` in `.env` (no hardcoded default) |
-| Dashboard opens on wrong port | Set `PORT=20128` and `NEXT_PUBLIC_BASE_URL=http://localhost:20128` |
-| No request logs under `logs/` | Set `ENABLE_REQUEST_LOGS=true` |
-| EACCES: permission denied | Set `DATA_DIR=/path/to/writable/dir` to override `~/.omniroute` |
-| Routing strategy not saving | Update to v1.4.11+ (Zod schema fix for settings persistence) |
-
----
-
-## Provider Issues
-
-### "Language model did not provide messages"
-
-**Cause:** Provider quota exhausted.
-
-**Fix:**
-
-1. Check dashboard quota tracker
-2. Use a combo with fallback tiers
-3. Switch to cheaper/free tier
-
-### Rate Limiting
-
-**Cause:** Subscription quota exhausted.
-
-**Fix:**
-
-- Add fallback: `cc/claude-opus-4-6 → glm/glm-4.7 → if/kimi-k2-thinking`
-- Use GLM/MiniMax as cheap backup
-
-### OAuth Token Expired
-
-OmniRoute auto-refreshes tokens. If issues persist:
-
-1. Dashboard → Provider → Reconnect
-2. Delete and re-add the provider connection
-
----
-
-## Cloud Issues
-
-### Cloud Sync Errors
-
-1. Verify `BASE_URL` points to your running instance (e.g., `http://localhost:20128`)
-2. Verify `CLOUD_URL` points to your cloud endpoint (e.g., `https://omniroute.dev`)
-3. Keep `NEXT_PUBLIC_*` values aligned with server-side values
-
-### Cloud `stream=false` Returns 500
-
-**Symptom:** `Unexpected token 'd'...` on cloud endpoint for non-streaming calls.
-
-**Cause:** Upstream returns SSE payload while client expects JSON.
-
-**Workaround:** Use `stream=true` for cloud direct calls. Local runtime includes SSE→JSON fallback.
-
-### Cloud Says Connected but "Invalid API key"
-
-1. Create a fresh key from local dashboard (`/api/keys`)
-2. Run cloud sync: Enable Cloud → Sync Now
-3. Old/non-synced keys can still return `401` on cloud
-
----
-
-## Docker Issues
-
-### CLI Tool Shows Not Installed
-
-1. Check runtime fields: `curl http://localhost:20128/api/cli-tools/runtime/codex | jq`
-2. For portable mode: use image target `runner-cli` (bundled CLIs)
-3. For host mount mode: set `CLI_EXTRA_PATHS` and mount host bin directory as read-only
-4. If `installed=true` and `runnable=false`: binary was found but failed healthcheck
-
-### Quick Runtime Validation
-
-```bash
-curl -s http://localhost:20128/api/cli-tools/codex-settings | jq '{installed,runnable,commandPath,runtimeMode,reason}'
-curl -s http://localhost:20128/api/cli-tools/claude-settings | jq '{installed,runnable,commandPath,runtimeMode,reason}'
-curl -s http://localhost:20128/api/cli-tools/openclaw-settings | jq '{installed,runnable,commandPath,runtimeMode,reason}'
-```
-
----
-
-## Cost Issues
-
-### High Costs
-
-1. Check usage stats in Dashboard → Usage
-2. Switch primary model to GLM/MiniMax
-3. Use free tier (Gemini CLI, Qoder) for non-critical tasks
-4. Set cost budgets per API key: Dashboard → API Keys → Budget
-
----
-
-## Debugging
-
-### Enable Request Logs
-
-Set `ENABLE_REQUEST_LOGS=true` in your `.env` file. Logs appear under `logs/` directory.
-
-### Check Provider Health
-
-```bash
-# Health dashboard
-http://localhost:20128/dashboard/health
-
-# API health check
-curl http://localhost:20128/api/monitoring/health
-```
-
-### Runtime Storage
-
-- Main state: `${DATA_DIR}/storage.sqlite` (providers, combos, aliases, keys, settings)
-- Usage: SQLite tables in `storage.sqlite` (`usage_history`, `call_logs`, `proxy_logs`) + optional `${DATA_DIR}/log.txt` and `${DATA_DIR}/call_logs/`
-- Request logs: `/logs/...` (when `ENABLE_REQUEST_LOGS=true`)
-
----
-
-## Circuit Breaker Issues
-
-### Provider stuck in OPEN state
-
-When a provider's circuit breaker is OPEN, requests are blocked until the cooldown expires.
-
-**Fix:**
-
-1. Go to **Dashboard → Settings → Resilience**
-2. Check the circuit breaker card for the affected provider
-3. Click **Reset All** to clear all breakers, or wait for the cooldown to expire
-4. Verify the provider is actually available before resetting
-
-### Provider keeps tripping the circuit breaker
-
-If a provider repeatedly enters OPEN state:
-
-1. Check **Dashboard → Health → Provider Health** for the failure pattern
-2. Go to **Settings → Resilience → Provider Profiles** and increase the failure threshold
-3. Check if the provider has changed API limits or requires re-authentication
-4. Review latency telemetry — high latency may cause timeout-based failures
-
----
-
-## Audio Transcription Issues
-
-### "Unsupported model" error
-
-- Ensure you're using the correct prefix: `deepgram/nova-3` or `assemblyai/best`
-- Verify the provider is connected in **Dashboard → Providers**
-
-### Transcription returns empty or fails
-
-- Check supported audio formats: `mp3`, `wav`, `m4a`, `flac`, `ogg`, `webm`
-- Verify file size is within provider limits (typically < 25MB)
-- Check provider API key validity in the provider card
-
----
-
-## Translator Debugging
-
-Use **Dashboard → Translator** to debug format translation issues:
-
-| Mode | When to Use |
-| ---------------- | -------------------------------------------------------------------------------------------- |
-| **Playground** | Compare input/output formats side by side — paste a failing request to see how it translates |
-| **Chat Tester** | Send live messages and inspect the full request/response payload including headers |
-| **Test Bench** | Run batch tests across format combinations to find which translations are broken |
-| **Live Monitor** | Watch real-time request flow to catch intermittent translation issues |
-
-### Common format issues
-
-- **Thinking tags not appearing** — Check if the target provider supports thinking and the thinking budget setting
-- **Tool calls dropping** — Some format translations may strip unsupported fields; verify in Playground mode
-- **System prompt missing** — Claude and Gemini handle system prompts differently; check translation output
-- **SDK returns raw string instead of object** — Fixed in v1.1.0: response sanitizer now strips non-standard fields (`x_groq`, `usage_breakdown`, etc.) that cause OpenAI SDK Pydantic validation failures
-- **GLM/ERNIE rejects `system` role** — Fixed in v1.1.0: role normalizer automatically merges system messages into user messages for incompatible models
-- **`developer` role not recognized** — Fixed in v1.1.0: automatically converted to `system` for non-OpenAI providers
-- **`json_schema` not working with Gemini** — Fixed in v1.1.0: `response_format` is now converted to Gemini's `responseMimeType` + `responseSchema`
-
----
-
-## Resilience Settings
-
-### Auto rate-limit not triggering
-
-- Auto rate-limit only applies to API key providers (not OAuth/subscription)
-- Verify **Settings → Resilience → Provider Profiles** has auto-rate-limit enabled
-- Check if the provider returns `429` status codes or `Retry-After` headers
-
-### Tuning exponential backoff
-
-Provider profiles support these settings:
-
-- **Base delay** — Initial wait time after first failure (default: 1s)
-- **Max delay** — Maximum wait time cap (default: 30s)
-- **Multiplier** — How much to increase delay per consecutive failure (default: 2x)
-
-### Anti-thundering herd
-
-When many concurrent requests hit a rate-limited provider, OmniRoute uses mutex + auto rate-limiting to serialize requests and prevent cascading failures. This is automatic for API key providers.
-
----
-
-## Optional RAG / LLM failure taxonomy (16 problems)
-
-Some OmniRoute users place the gateway in front of RAG or agent stacks. In those setups it is common to see a strange pattern: OmniRoute looks healthy (providers up, routing profiles ok, no rate limit alerts) but the final answer is still wrong.
-
-In practice these incidents usually come from the downstream RAG pipeline, not from the gateway itself.
-
-If you want a shared vocabulary to describe those failures you can use the WFGY ProblemMap, an external MIT license text resource that defines sixteen recurring RAG / LLM failure patterns. At a high level it covers:
-
-- retrieval drift and broken context boundaries
-- empty or stale indexes and vector stores
-- embedding versus semantic mismatch
-- prompt assembly and context window issues
-- logic collapse and overconfident answers
-- long chain and agent coordination failures
-- multi agent memory and role drift
-- deployment and bootstrap ordering problems
-
-The idea is simple:
-
-1. When you investigate a bad response, capture:
- - user task and request
- - route or provider combo in OmniRoute
- - any RAG context used downstream (retrieved documents, tool calls, etc)
-2. Map the incident to one or two WFGY ProblemMap numbers (`No.1` … `No.16`).
-3. Store the number in your own dashboard, runbook, or incident tracker next to the OmniRoute logs.
-4. Use the corresponding WFGY page to decide whether you need to change your RAG stack, retriever, or routing strategy.
-
-Full text and concrete recipes live here (MIT license, text only):
-
-[WFGY ProblemMap README](https://github.com/onestardao/WFGY/blob/main/ProblemMap/README.md)
-
-You can ignore this section if you do not run RAG or agent pipelines behind OmniRoute.
-
----
-
-## Still Stuck?
-
-- **GitHub Issues**: [github.com/diegosouzapw/OmniRoute/issues](https://github.com/diegosouzapw/OmniRoute/issues)
-- **Architecture**: See [`docs/ARCHITECTURE.md`](ARCHITECTURE.md) for internal details
-- **API Reference**: See [`docs/API_REFERENCE.md`](API_REFERENCE.md) for all endpoints
-- **Health Dashboard**: Check **Dashboard → Health** for real-time system status
-- **Translator**: Use **Dashboard → Translator** to debug format issues
diff --git a/docs/i18n/fi/VM_DEPLOYMENT_GUIDE.md b/docs/i18n/fi/VM_DEPLOYMENT_GUIDE.md
deleted file mode 100644
index 924077cc35..0000000000
--- a/docs/i18n/fi/VM_DEPLOYMENT_GUIDE.md
+++ /dev/null
@@ -1,401 +0,0 @@
-# OmniRoute — Käyttöönottoopas VM:ssä Cloudflaren kanssa
-
-🌐 **Languages:** 🇺🇸 [English](../../VM_DEPLOYMENT_GUIDE.md) | 🇧🇷 [Português (Brasil)](../pt-BR/VM_DEPLOYMENT_GUIDE.md) | 🇪🇸 [Español](../es/VM_DEPLOYMENT_GUIDE.md) | 🇫🇷 [Français](../fr/VM_DEPLOYMENT_GUIDE.md) | 🇮🇹 [Italiano](../it/VM_DEPLOYMENT_GUIDE.md) | 🇷🇺 [Русский](../ru/VM_DEPLOYMENT_GUIDE.md) | 🇨🇳 [中文 (简体)](../zh-CN/VM_DEPLOYMENT_GUIDE.md) | 🇩🇪 [Deutsch](../de/VM_DEPLOYMENT_GUIDE.md) | 🇮🇳 [हिन्दी](../in/VM_DEPLOYMENT_GUIDE.md) | 🇹🇭 [ไทย](../th/VM_DEPLOYMENT_GUIDE.md) | 🇺🇦 [Українська](../uk-UA/VM_DEPLOYMENT_GUIDE.md) | 🇸🇦 [العربية](../ar/VM_DEPLOYMENT_GUIDE.md) | 🇯🇵 [日本語](../ja/VM_DEPLOYMENT_GUIDE.md) | 🇻🇳 [Tiếng Việt](../vi/VM_DEPLOYMENT_GUIDE.md) | 🇧🇬 [Български](../bg/VM_DEPLOYMENT_GUIDE.md) | 🇩🇰 [Dansk](../da/VM_DEPLOYMENT_GUIDE.md) | 🇫🇮 [Suomi](../fi/VM_DEPLOYMENT_GUIDE.md) | 🇮🇱 [עברית](../he/VM_DEPLOYMENT_GUIDE.md) | 🇭🇺 [Magyar](../hu/VM_DEPLOYMENT_GUIDE.md) | 🇮🇩 [Bahasa Indonesia](../id/VM_DEPLOYMENT_GUIDE.md) | 🇰🇷 [한국어](../ko/VM_DEPLOYMENT_GUIDE.md) | 🇲🇾 [Bahasa Melayu](../ms/VM_DEPLOYMENT_GUIDE.md) | 🇳🇱 [Nederlands](../nl/VM_DEPLOYMENT_GUIDE.md) | 🇳🇴 [Norsk](../no/VM_DEPLOYMENT_GUIDE.md) | 🇵🇹 [Português (Portugal)](../pt/VM_DEPLOYMENT_GUIDE.md) | 🇷🇴 [Română](../ro/VM_DEPLOYMENT_GUIDE.md) | 🇵🇱 [Polski](../pl/VM_DEPLOYMENT_GUIDE.md) | 🇸🇰 [Slovenčina](../sk/VM_DEPLOYMENT_GUIDE.md) | 🇸🇪 [Svenska](../sv/VM_DEPLOYMENT_GUIDE.md) | 🇵🇭 [Filipino](../phi/VM_DEPLOYMENT_GUIDE.md) | 🇨🇿 [Čeština](../cs/VM_DEPLOYMENT_GUIDE.md)
-
-Täydellinen opas OmniRouten asentamiseen ja määrittämiseen VM:lle (VPS), jonka toimialuetta hallitaan Cloudflaren kautta.
-
----
-
-## Edellytykset
-
-| Tuote | Minimi | Suositeltava |
-| ----------- | ------------------------- | ---------------- |
-| **CPU** | 1 vCPU | 2 vCPU |
-| **RAM** | 1 Gt | 2 Gt |
-| **Levy** | 10 Gt SSD | 25 Gt SSD |
-| **OS** | Ubuntu 22.04 LTS | Ubuntu 24.04 LTS |
-| **Domain** | Rekisteröity Cloudflareen | — |
-| **Dokkeri** | Docker Engine 24+ | Docker 27+ |
-
-**Testatut palveluntarjoajat**: Akamai (Linode), DigitalOcean, Vultr, Hetzner, AWS Lightsail.
-
----
-
-## 1. Määritä virtuaalikone
-
-### 1.1 Luo ilmentymä
-
-Valitsemallasi VPS-palveluntarjoajalla:
-
-- Valitse Ubuntu 24.04 LTS
-- Valitse vähimmäissuunnitelma (1 vCPU / 1 Gt RAM)
-- Aseta vahva root-salasana tai määritä SSH-avain
-- Huomaa **julkinen IP** (esim. `203.0.113.10`)
-
-### 1.2 Yhdistä SSH:n kautta
-
-```bash
-ssh root@203.0.113.10
-```
-
-### 1.3 Päivitä järjestelmä
-
-```bash
-apt update && apt upgrade -y
-```
-
-### 1.4 Asenna Docker
-
-```bash
-# Install dependencies
-apt install -y ca-certificates curl gnupg
-
-# Add official Docker repository
-install -m 0755 -d /etc/apt/keyrings
-curl -fsSL https://download.docker.com/linux/ubuntu/gpg | gpg --dearmor -o /etc/apt/keyrings/docker.gpg
-chmod a+r /etc/apt/keyrings/docker.gpg
-echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu $ (. /etc/os-release && echo “$VERSION_CODENAME”) stable" | tee /etc/apt/sources.list.d/docker.list > /dev/null
-apt update
-apt install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin
-```
-
-### 1.5 Asenna nginx
-
-```bash
-apt install -y nginx
-```
-
-### 1.6 Määritä palomuuri (UFW)
-
-```bash
-ufw default deny incoming
-ufw default allow outgoing
-ufw allow 22/tcp # SSH
-ufw allow 80/tcp # HTTP (redirect)
-ufw allow 443/tcp # HTTPS
-ufw enable
-```
-
-> **Vinkki**: Maksimaalista turvallisuutta varten rajaa portit 80 ja 443 vain Cloudflaren IP-osoitteisiin. Katso osio [Advanced Security](#advanced-security).
-
----
-
-## 2. Asenna OmniRoute
-
-### 2.1 Luo asetushakemisto
-
-```bash
-mkdir -p /opt/omniroute
-```
-
-### 2.2 Luo ympäristömuuttujatiedosto
-
-```bash
-cat > /opt/omniroute/.env << ‘EOF’
-# === Security ===
-JWT_SECRET=CHANGE-TO-A-UNIQUE-64-CHAR-SECRET-KEY
-INITIAL_PASSWORD=YourSecurePassword123!
-API_KEY_SECRET=REPLACE-WITH-ANOTHER-SECRET-KEY
-STORAGE_ENCRYPTION_KEY=REPLACE-WITH-THIRD-SECRET-KEY
-STORAGE_ENCRYPTION_KEY_VERSION=v1
-MACHINE_ID_SALT=CHANGE-TO-A-UNIQUE-SALT
-
-# === App ===
-PORT=20128
-NODE_ENV=production
-HOSTNAME=0.0.0.0
-DATA_DIR=/app/data
-STORAGE_DRIVER=sqlite
-ENABLE_REQUEST_LOGS=true
-AUTH_COOKIE_SECURE=false
-REQUIRE_API_KEY=false
-
-# === Domain (change to your domain) ===
-BASE_URL=https://llms.seudominio.com
-NEXT_PUBLIC_BASE_URL=https://llms.seudominio.com
-
-# === Cloud Sync (optional) ===
-# CLOUD_URL=https://cloud.omniroute.online
-# NEXT_PUBLIC_CLOUD_URL=https://cloud.omniroute.online
-EOF
-```
-
-> ⚠️ **TÄRKEÄÄ**: Luo ainutlaatuisia salaisia avaimia! Käytä `openssl rand -hex 32` jokaiselle avaimelle.
-
-### 2.3 Käynnistä kontti
-
-```bash
-docker pull diegosouzapw/omniroute:latest
-
-docker run -d \
- --name omniroute \
- --restart unless-stopped \
- --env-file /opt/omniroute/.env \
- -p 20128:20128 \
- -v omniroute-data:/app/data \
- diegosouzapw/omniroute:latest
-```
-
-### 2.4 Varmista, että se on käynnissä
-
-```bash
-docker ps | grep omniroute
-docker logs omniroute --tail 20
-```
-
-Sen pitäisi näyttää: `[DB] SQLite database ready` ja `listening on port 20128`.
-
----
-
-## 3. Määritä nginx (käänteinen välityspalvelin)
-
-### 3.1 Luo SSL-varmenne (Cloudflare Origin)
-
-Cloudflare-hallintapaneelissa:
-
-1. Siirry kohtaan **SSL/TLS → Origin Server**
-2. Napsauta **Luo varmenne**
-3. Säilytä oletusasetukset (15 vuotta, \*.omaverkkotunnus.com)
-4. Kopioi **alkuperätodistus** ja **yksityinen avain**
-
-```bash
-mkdir -p /etc/nginx/ssl
-
-# Paste the certificate
-nano /etc/nginx/ssl/origin.crt
-
-# Paste the private key
-nano /etc/nginx/ssl/origin.key
-
-chmod 600 /etc/nginx/ssl/origin.key
-```
-
-### 3.2 Nginx-kokoonpano
-
-```bash
-cat > /etc/nginx/sites-available/omniroute << ‘NGINX’
-# Default server — blocks direct access via IP
-server {
- listen 80 default_server;
- listen [::]:80 default_server;
- listen 443 ssl default_server;
- listen [::]:443 ssl default_server;
- ssl_certificate /etc/nginx/ssl/origin.crt;
- ssl_certificate_key /etc/nginx/ssl/origin.key;
- server_name _;
- return 444;
-}
-
-# OmniRoute — HTTPS
-server {
- listen 443 ssl;
- listen [::]:443 ssl;
- server_name llms.yourdomain.com; # Change to your domain
-
- ssl_certificate /etc/nginx/ssl/origin.crt;
- ssl_certificate_key /etc/nginx/ssl/origin.key;
- ssl_protocols TLSv1.2 TLSv1.3;
-
- client_max_body_size 100M;
-
- location / {
- proxy_pass http://127.0.0.1:20128;
- proxy_set_header Host $host;
- proxy_set_header X-Real-IP $remote_addr;
- proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
- proxy_set_header X-Forwarded-Proto $scheme;
-
- # WebSocket support
- proxy_http_version 1.1;
- proxy_set_header Upgrade $http_upgrade;
- proxy_set_header Connection “upgrade”;
-
- # SSE (Server-Sent Events) — streaming AI responses
- proxy_buffering off;
- proxy_cache off;
- proxy_read_timeout 300s;
- proxy_send_timeout 300s;
- }
-}
-
-# HTTP → HTTPS redirect
-server {
- listen 80;
- listen [::]:80;
- server_name llms.yourdomain.com;
- return 301 https://$server_name$request_uri;
-}
-NGINX
-```
-
-### 3.3 Ota käyttöön ja testaa
-
-```bash
-# Remove default configuration
-rm -f /etc/nginx/sites-enabled/default
-
-# Enable OmniRoute
-ln -sf /etc/nginx/sites-available/omniroute /etc/nginx/sites-enabled/omniroute
-
-# Test and reload
-nginx -t && systemctl reload nginx
-```
-
----
-
-## 4. Määritä Cloudflare DNS
-
-### 4.1 Lisää DNS-tietue
-
-Cloudflaren kojelaudassa → DNS:
-
-| Tyyppi | Nimi | Sisältö | Välityspalvelin |
-| ------ | ------ | ---------------------- | ------------------ |
-| A | `llms` | `203.0.113.10` (VM IP) | ✅ Välityspalvelin |
-
-### 4.2 Määritä SSL
-
-Kohdassa **SSL/TLS → Yleiskatsaus**:
-
-- Tila: **Täysi (tiukka)**
-
-Alle **SSL/TLS → Edge-sertifikaatit**:
-
-- Käytä aina HTTPS:ää: ✅ Käytössä
-- TLS:n vähimmäisversio: TLS 1.2
-- Automaattiset HTTPS-uudelleenkirjoitukset: ✅ Käytössä
-
-### 4.3 Testaus
-
-```bash
-curl -sI https://llms.seudominio.com/health
-# Should return HTTP/2 200
-```
-
----
-
-## 5. Käyttö ja huolto
-
-### Päivitä uuteen versioon
-
-```bash
-docker pull diegosouzapw/omniroute:latest
-docker stop omniroute && docker rm omniroute
-docker run -d --name omniroute --restart unless-stopped \
- --env-file /opt/omniroute/.env \
- -p 20128:20128 \
- -v omniroute-data:/app/data \
- diegosouzapw/omniroute:latest
-```
-
-### Näytä lokit
-
-```bash
-docker logs -f omniroute # Real-time stream
-docker logs omniroute --tail 50 # Last 50 lines
-```
-
-### Manuaalinen tietokannan varmuuskopiointi
-
-```bash
-# Copy data from the volume to the host
-docker cp omniroute:/app/data ./backup-$(date +%F)
-
-# Or compress the entire volume
-docker run --rm -v omniroute-data:/data -v $(pwd):/backup \
- alpine tar czf /backup/omniroute-data-$(date +%F).tar.gz /data
-```
-
-### Palauta varmuuskopiosta
-
-```bash
-docker stop omniroute
-docker run --rm -v omniroute-data:/data -v $(pwd):/backup \
- alpine sh -c “rm -rf /data/* && tar xzf /backup/omniroute-data-YYYY-MM-DD.tar.gz -C /”
-docker start omniroute
-```
-
----
-
-## 6. Lisäsuojaus
-
-### Rajoita nginx Cloudflaren IP-osoitteisiin
-
-```bash
-cat > /etc/nginx/cloudflare-ips.conf << ‘CF’
-# Cloudflare IPv4 ranges — update periodically
-# https://www.cloudflare.com/ips-v4/
-set_real_ip_from 173.245.48.0/20;
-set_real_ip_from 103.21.244.0/22;
-set_real_ip_from 103.22.200.0/22;
-set_real_ip_from 103.31.4.0/22;
-set_real_ip_from 141.101.64.0/18;
-set_real_ip_from 108.162.192.0/18;
-set_real_ip_from 190.93.240.0/20;
-set_real_ip_from 188.114.96.0/20;
-set_real_ip_from 197.234.240.0/22;
-set_real_ip_from 198.41.128.0/17;
-set_real_ip_from 162.158.0.0/15;
-set_real_ip_from 104.16.0.0/13;
-set_real_ip_from 104.24.0.0/14;
-set_real_ip_from 172.64.0.0/13;
-set_real_ip_from 131.0.72.0/22;
-real_ip_header CF-Connecting-IP;
-CF
-```
-
-Lisää seuraava `nginx.conf` -lohkoon `http {}`:
-
-```nginx
-include /etc/nginx/cloudflare-ips.conf;
-```
-
-### Asenna fail2ban
-
-```bash
-apt install -y fail2ban
-systemctl enable fail2ban
-systemctl start fail2ban
-
-# Check status
-fail2ban-client status sshd
-```
-
-### Estä suora pääsy Docker-porttiin
-
-```bash
-# Prevent direct external access to port 20128
-iptables -I DOCKER-USER -p tcp --dport 20128 -j DROP
-iptables -I DOCKER-USER -i lo -p tcp --dport 20128 -j ACCEPT
-
-# Persist the rules
-apt install -y iptables-persistent
-netfilter-persistent save
-```
-
----
-
-## 7. Ota käyttöön Cloudflare-työntekijöille (valinnainen)
-
-Etäkäyttö Cloudflare Workersin kautta (paljastamatta virtuaalikonetta suoraan):
-
-```bash
-# In the local repository
-cd omnirouteCloud
-npm install
-npx wrangler login
-npx wrangler deploy
-```
-
-Katso koko dokumentaatio osoitteessa [omnirouteCloud/README.md](../omnirouteCloud/README.md).
-
----
-
-## Portin yhteenveto
-
-| Portti | Palvelu | Pääsy |
-| ------ | ----------- | ----------------------------------- |
-| 22 | SSH | Julkinen (fail2banin kanssa) |
-| 80 | nginx HTTP | Uudelleenohjaus → HTTPS |
-| 443 | nginx HTTPS | Cloudflare-välityspalvelimen kautta |
-| 20128 | OmniRoute | Vain Localhost (nginxin kautta) |
diff --git a/docs/i18n/ar/A2A-SERVER.md b/docs/i18n/fi/docs/A2A-SERVER.md
similarity index 77%
rename from docs/i18n/ar/A2A-SERVER.md
rename to docs/i18n/fi/docs/A2A-SERVER.md
index 01531ff482..4787d889f2 100644
--- a/docs/i18n/ar/A2A-SERVER.md
+++ b/docs/i18n/fi/docs/A2A-SERVER.md
@@ -1,9 +1,9 @@
-🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/A2A-SERVER.md) · 🇪🇸 [es](../es/A2A-SERVER.md) · 🇫🇷 [fr](../fr/A2A-SERVER.md) · 🇩🇪 [de](../de/A2A-SERVER.md) · 🇮🇹 [it](../it/A2A-SERVER.md) · 🇷🇺 [ru](../ru/A2A-SERVER.md) · 🇨🇳 [zh-CN](../zh-CN/A2A-SERVER.md) · 🇯🇵 [ja](../ja/A2A-SERVER.md) · 🇰🇷 [ko](../ko/A2A-SERVER.md) · 🇸🇦 [ar](../ar/A2A-SERVER.md) · 🇮🇳 [in](../in/A2A-SERVER.md) · 🇹🇭 [th](../th/A2A-SERVER.md) · 🇻🇳 [vi](../vi/A2A-SERVER.md) · 🇮🇩 [id](../id/A2A-SERVER.md) · 🇲🇾 [ms](../ms/A2A-SERVER.md) · 🇳🇱 [nl](../nl/A2A-SERVER.md) · 🇵🇱 [pl](../pl/A2A-SERVER.md) · 🇸🇪 [sv](../sv/A2A-SERVER.md) · 🇳🇴 [no](../no/A2A-SERVER.md) · 🇩🇰 [da](../da/A2A-SERVER.md) · 🇫🇮 [fi](../fi/A2A-SERVER.md) · 🇵🇹 [pt](../pt/A2A-SERVER.md) · 🇷🇴 [ro](../ro/A2A-SERVER.md) · 🇭🇺 [hu](../hu/A2A-SERVER.md) · 🇧🇬 [bg](../bg/A2A-SERVER.md) · 🇸🇰 [sk](../sk/A2A-SERVER.md) · 🇺🇦 [uk-UA](../uk-UA/A2A-SERVER.md) · 🇮🇱 [he](../he/A2A-SERVER.md) · 🇵🇭 [phi](../phi/A2A-SERVER.md)
+# OmniRoute A2A Server Documentation (Suomi)
+
+🌐 **Languages:** 🇺🇸 [English](../../../../docs/A2A-SERVER.md) · 🇪🇸 [es](../../es/docs/A2A-SERVER.md) · 🇫🇷 [fr](../../fr/docs/A2A-SERVER.md) · 🇩🇪 [de](../../de/docs/A2A-SERVER.md) · 🇮🇹 [it](../../it/docs/A2A-SERVER.md) · 🇷🇺 [ru](../../ru/docs/A2A-SERVER.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/A2A-SERVER.md) · 🇯🇵 [ja](../../ja/docs/A2A-SERVER.md) · 🇰🇷 [ko](../../ko/docs/A2A-SERVER.md) · 🇸🇦 [ar](../../ar/docs/A2A-SERVER.md) · 🇮🇳 [in](../../in/docs/A2A-SERVER.md) · 🇹🇭 [th](../../th/docs/A2A-SERVER.md) · 🇻🇳 [vi](../../vi/docs/A2A-SERVER.md) · 🇮🇩 [id](../../id/docs/A2A-SERVER.md) · 🇲🇾 [ms](../../ms/docs/A2A-SERVER.md) · 🇳🇱 [nl](../../nl/docs/A2A-SERVER.md) · 🇵🇱 [pl](../../pl/docs/A2A-SERVER.md) · 🇸🇪 [sv](../../sv/docs/A2A-SERVER.md) · 🇳🇴 [no](../../no/docs/A2A-SERVER.md) · 🇩🇰 [da](../../da/docs/A2A-SERVER.md) · 🇫🇮 [fi](../../fi/docs/A2A-SERVER.md) · 🇵🇹 [pt](../../pt/docs/A2A-SERVER.md) · 🇷🇴 [ro](../../ro/docs/A2A-SERVER.md) · 🇭🇺 [hu](../../hu/docs/A2A-SERVER.md) · 🇧🇬 [bg](../../bg/docs/A2A-SERVER.md) · 🇸🇰 [sk](../../sk/docs/A2A-SERVER.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/A2A-SERVER.md) · 🇮🇱 [he](../../he/docs/A2A-SERVER.md) · 🇵🇭 [phi](../../phi/docs/A2A-SERVER.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/A2A-SERVER.md) · 🇨🇿 [cs](../../cs/docs/A2A-SERVER.md)
---
-# OmniRoute A2A Server Documentation
-
> Agent-to-Agent Protocol v0.3 — OmniRoute as an intelligent routing agent
## Agent Discovery
diff --git a/docs/i18n/bg/API_REFERENCE.md b/docs/i18n/fi/docs/API_REFERENCE.md
similarity index 74%
rename from docs/i18n/bg/API_REFERENCE.md
rename to docs/i18n/fi/docs/API_REFERENCE.md
index b878605221..b78cf27fd0 100644
--- a/docs/i18n/bg/API_REFERENCE.md
+++ b/docs/i18n/fi/docs/API_REFERENCE.md
@@ -1,11 +1,9 @@
-🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/API_REFERENCE.md) · 🇪🇸 [es](../es/API_REFERENCE.md) · 🇫🇷 [fr](../fr/API_REFERENCE.md) · 🇩🇪 [de](../de/API_REFERENCE.md) · 🇮🇹 [it](../it/API_REFERENCE.md) · 🇷🇺 [ru](../ru/API_REFERENCE.md) · 🇨🇳 [zh-CN](../zh-CN/API_REFERENCE.md) · 🇯🇵 [ja](../ja/API_REFERENCE.md) · 🇰🇷 [ko](../ko/API_REFERENCE.md) · 🇸🇦 [ar](../ar/API_REFERENCE.md) · 🇮🇳 [in](../in/API_REFERENCE.md) · 🇹🇭 [th](../th/API_REFERENCE.md) · 🇻🇳 [vi](../vi/API_REFERENCE.md) · 🇮🇩 [id](../id/API_REFERENCE.md) · 🇲🇾 [ms](../ms/API_REFERENCE.md) · 🇳🇱 [nl](../nl/API_REFERENCE.md) · 🇵🇱 [pl](../pl/API_REFERENCE.md) · 🇸🇪 [sv](../sv/API_REFERENCE.md) · 🇳🇴 [no](../no/API_REFERENCE.md) · 🇩🇰 [da](../da/API_REFERENCE.md) · 🇫🇮 [fi](../fi/API_REFERENCE.md) · 🇵🇹 [pt](../pt/API_REFERENCE.md) · 🇷🇴 [ro](../ro/API_REFERENCE.md) · 🇭🇺 [hu](../hu/API_REFERENCE.md) · 🇧🇬 [bg](../bg/API_REFERENCE.md) · 🇸🇰 [sk](../sk/API_REFERENCE.md) · 🇺🇦 [uk-UA](../uk-UA/API_REFERENCE.md) · 🇮🇱 [he](../he/API_REFERENCE.md) · 🇵🇭 [phi](../phi/API_REFERENCE.md)
+# API Reference (Suomi)
+
+🌐 **Languages:** 🇺🇸 [English](../../../../docs/API_REFERENCE.md) · 🇪🇸 [es](../../es/docs/API_REFERENCE.md) · 🇫🇷 [fr](../../fr/docs/API_REFERENCE.md) · 🇩🇪 [de](../../de/docs/API_REFERENCE.md) · 🇮🇹 [it](../../it/docs/API_REFERENCE.md) · 🇷🇺 [ru](../../ru/docs/API_REFERENCE.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/API_REFERENCE.md) · 🇯🇵 [ja](../../ja/docs/API_REFERENCE.md) · 🇰🇷 [ko](../../ko/docs/API_REFERENCE.md) · 🇸🇦 [ar](../../ar/docs/API_REFERENCE.md) · 🇮🇳 [in](../../in/docs/API_REFERENCE.md) · 🇹🇭 [th](../../th/docs/API_REFERENCE.md) · 🇻🇳 [vi](../../vi/docs/API_REFERENCE.md) · 🇮🇩 [id](../../id/docs/API_REFERENCE.md) · 🇲🇾 [ms](../../ms/docs/API_REFERENCE.md) · 🇳🇱 [nl](../../nl/docs/API_REFERENCE.md) · 🇵🇱 [pl](../../pl/docs/API_REFERENCE.md) · 🇸🇪 [sv](../../sv/docs/API_REFERENCE.md) · 🇳🇴 [no](../../no/docs/API_REFERENCE.md) · 🇩🇰 [da](../../da/docs/API_REFERENCE.md) · 🇫🇮 [fi](../../fi/docs/API_REFERENCE.md) · 🇵🇹 [pt](../../pt/docs/API_REFERENCE.md) · 🇷🇴 [ro](../../ro/docs/API_REFERENCE.md) · 🇭🇺 [hu](../../hu/docs/API_REFERENCE.md) · 🇧🇬 [bg](../../bg/docs/API_REFERENCE.md) · 🇸🇰 [sk](../../sk/docs/API_REFERENCE.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/API_REFERENCE.md) · 🇮🇱 [he](../../he/docs/API_REFERENCE.md) · 🇵🇭 [phi](../../phi/docs/API_REFERENCE.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/API_REFERENCE.md) · 🇨🇿 [cs](../../cs/docs/API_REFERENCE.md)
---
-# API Reference
-
-🌐 **Languages:** 🇺🇸 [English](API_REFERENCE.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/API_REFERENCE.md) | 🇪🇸 [Español](i18n/es/API_REFERENCE.md) | 🇫🇷 [Français](i18n/fr/API_REFERENCE.md) | 🇮🇹 [Italiano](i18n/it/API_REFERENCE.md) | 🇷🇺 [Русский](i18n/ru/API_REFERENCE.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/API_REFERENCE.md) | 🇩🇪 [Deutsch](i18n/de/API_REFERENCE.md) | 🇮🇳 [हिन्दी](i18n/in/API_REFERENCE.md) | 🇹🇭 [ไทย](i18n/th/API_REFERENCE.md) | 🇺🇦 [Українська](i18n/uk-UA/API_REFERENCE.md) | 🇸🇦 [العربية](i18n/ar/API_REFERENCE.md) | 🇯🇵 [日本語](i18n/ja/API_REFERENCE.md) | 🇻🇳 [Tiếng Việt](i18n/vi/API_REFERENCE.md) | 🇧🇬 [Български](i18n/bg/API_REFERENCE.md) | 🇩🇰 [Dansk](i18n/da/API_REFERENCE.md) | 🇫🇮 [Suomi](i18n/fi/API_REFERENCE.md) | 🇮🇱 [עברית](i18n/he/API_REFERENCE.md) | 🇭🇺 [Magyar](i18n/hu/API_REFERENCE.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/API_REFERENCE.md) | 🇰🇷 [한국어](i18n/ko/API_REFERENCE.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/API_REFERENCE.md) | 🇳🇱 [Nederlands](i18n/nl/API_REFERENCE.md) | 🇳🇴 [Norsk](i18n/no/API_REFERENCE.md) | 🇵🇹 [Português (Portugal)](i18n/pt/API_REFERENCE.md) | 🇷🇴 [Română](i18n/ro/API_REFERENCE.md) | 🇵🇱 [Polski](i18n/pl/API_REFERENCE.md) | 🇸🇰 [Slovenčina](i18n/sk/API_REFERENCE.md) | 🇸🇪 [Svenska](i18n/sv/API_REFERENCE.md) | 🇵🇭 [Filipino](i18n/phi/API_REFERENCE.md)
-
Complete reference for all OmniRoute API endpoints.
---
@@ -42,15 +40,20 @@ Content-Type: application/json
### Custom Headers
-| Header | Direction | Description |
-| ------------------------ | --------- | --------------------------------- |
-| `X-OmniRoute-No-Cache` | Request | Set to `true` to bypass cache |
-| `X-OmniRoute-Progress` | Request | Set to `true` for progress events |
-| `Idempotency-Key` | Request | Dedup key (5s window) |
-| `X-Request-Id` | Request | Alternative dedup key |
-| `X-OmniRoute-Cache` | Response | `HIT` or `MISS` (non-streaming) |
-| `X-OmniRoute-Idempotent` | Response | `true` if deduplicated |
-| `X-OmniRoute-Progress` | Response | `enabled` if progress tracking on |
+| Header | Direction | Description |
+| ------------------------ | --------- | ------------------------------------------------ |
+| `X-OmniRoute-No-Cache` | Request | Set to `true` to bypass cache |
+| `X-OmniRoute-Progress` | Request | Set to `true` for progress events |
+| `X-Session-Id` | Request | Sticky session key for external session affinity |
+| `x_session_id` | Request | Underscore variant also accepted (direct HTTP) |
+| `Idempotency-Key` | Request | Dedup key (5s window) |
+| `X-Request-Id` | Request | Alternative dedup key |
+| `X-OmniRoute-Cache` | Response | `HIT` or `MISS` (non-streaming) |
+| `X-OmniRoute-Idempotent` | Response | `true` if deduplicated |
+| `X-OmniRoute-Progress` | Response | `enabled` if progress tracking on |
+| `X-OmniRoute-Session-Id` | Response | Effective session ID used by OmniRoute |
+
+> Nginx note: if you rely on underscore headers (for example `x_session_id`), enable `underscores_in_headers on;`.
---
@@ -141,10 +144,10 @@ The provider prefix is auto-added if missing. Mismatched models return `400`.
```bash
# Get cache stats
-GET /api/cache
+GET /api/cache/stats
# Clear all caches
-DELETE /api/cache
+DELETE /api/cache/stats
```
Response example:
@@ -215,23 +218,23 @@ Response example:
### Settings
-| Endpoint | Method | Description |
-| ------------------------------- | ------- | ---------------------- |
-| `/api/settings` | GET/PUT | General settings |
-| `/api/settings/proxy` | GET/PUT | Network proxy config |
-| `/api/settings/proxy/test` | POST | Test proxy connection |
-| `/api/settings/ip-filter` | GET/PUT | IP allowlist/blocklist |
-| `/api/settings/thinking-budget` | GET/PUT | Reasoning token budget |
-| `/api/settings/system-prompt` | GET/PUT | Global system prompt |
+| Endpoint | Method | Description |
+| ------------------------------- | ------------- | ---------------------- |
+| `/api/settings` | GET/PUT/PATCH | General settings |
+| `/api/settings/proxy` | GET/PUT | Network proxy config |
+| `/api/settings/proxy/test` | POST | Test proxy connection |
+| `/api/settings/ip-filter` | GET/PUT | IP allowlist/blocklist |
+| `/api/settings/thinking-budget` | GET/PUT | Reasoning token budget |
+| `/api/settings/system-prompt` | GET/PUT | Global system prompt |
### Monitoring
-| Endpoint | Method | Description |
-| ------------------------ | ---------- | ----------------------- |
-| `/api/sessions` | GET | Active session tracking |
-| `/api/rate-limits` | GET | Per-account rate limits |
-| `/api/monitoring/health` | GET | Health check |
-| `/api/cache` | GET/DELETE | Cache stats / clear |
+| Endpoint | Method | Description |
+| ------------------------ | ---------- | ---------------------------------------------------------------------------------------------------- |
+| `/api/sessions` | GET | Active session tracking |
+| `/api/rate-limits` | GET | Per-account rate limits |
+| `/api/monitoring/health` | GET | Health check + provider summary (`catalogCount`, `configuredCount`, `activeCount`, `monitoredCount`) |
+| `/api/cache/stats` | GET/DELETE | Cache stats / clear |
### Backup & Export/Import
@@ -252,6 +255,13 @@ Response example:
| `/api/sync/initialize` | POST | Initialize sync |
| `/api/cloud/*` | Various | Cloud management |
+### Tunnels
+
+| Endpoint | Method | Description |
+| -------------------------- | ------ | ----------------------------------------------------------------------- |
+| `/api/tunnels/cloudflared` | GET | Read Cloudflare Quick Tunnel install/runtime status for the dashboard |
+| `/api/tunnels/cloudflared` | POST | Enable or disable the Cloudflare Quick Tunnel (`action=enable/disable`) |
+
### CLI Tools
| Endpoint | Method | Description |
@@ -276,12 +286,12 @@ GET response includes `agents[]` (id, name, binary, version, installed, protocol
### Resilience & Rate Limits
-| Endpoint | Method | Description |
-| ----------------------- | ------- | ------------------------------- |
-| `/api/resilience` | GET/PUT | Get/update resilience profiles |
-| `/api/resilience/reset` | POST | Reset circuit breakers |
-| `/api/rate-limits` | GET | Per-account rate limit status |
-| `/api/rate-limit` | GET | Global rate limit configuration |
+| Endpoint | Method | Description |
+| ----------------------- | --------- | ------------------------------- |
+| `/api/resilience` | GET/PATCH | Get/update resilience profiles |
+| `/api/resilience/reset` | POST | Reset circuit breakers |
+| `/api/rate-limits` | GET | Per-account rate limit status |
+| `/api/rate-limit` | GET | Global rate limit configuration |
### Evals
diff --git a/docs/i18n/de/ARCHITECTURE.md b/docs/i18n/fi/docs/ARCHITECTURE.md
similarity index 89%
rename from docs/i18n/de/ARCHITECTURE.md
rename to docs/i18n/fi/docs/ARCHITECTURE.md
index 4ea06a29f2..9be954d4a1 100644
--- a/docs/i18n/de/ARCHITECTURE.md
+++ b/docs/i18n/fi/docs/ARCHITECTURE.md
@@ -1,12 +1,10 @@
-🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/ARCHITECTURE.md) · 🇪🇸 [es](../es/ARCHITECTURE.md) · 🇫🇷 [fr](../fr/ARCHITECTURE.md) · 🇩🇪 [de](../de/ARCHITECTURE.md) · 🇮🇹 [it](../it/ARCHITECTURE.md) · 🇷🇺 [ru](../ru/ARCHITECTURE.md) · 🇨🇳 [zh-CN](../zh-CN/ARCHITECTURE.md) · 🇯🇵 [ja](../ja/ARCHITECTURE.md) · 🇰🇷 [ko](../ko/ARCHITECTURE.md) · 🇸🇦 [ar](../ar/ARCHITECTURE.md) · 🇮🇳 [in](../in/ARCHITECTURE.md) · 🇹🇭 [th](../th/ARCHITECTURE.md) · 🇻🇳 [vi](../vi/ARCHITECTURE.md) · 🇮🇩 [id](../id/ARCHITECTURE.md) · 🇲🇾 [ms](../ms/ARCHITECTURE.md) · 🇳🇱 [nl](../nl/ARCHITECTURE.md) · 🇵🇱 [pl](../pl/ARCHITECTURE.md) · 🇸🇪 [sv](../sv/ARCHITECTURE.md) · 🇳🇴 [no](../no/ARCHITECTURE.md) · 🇩🇰 [da](../da/ARCHITECTURE.md) · 🇫🇮 [fi](../fi/ARCHITECTURE.md) · 🇵🇹 [pt](../pt/ARCHITECTURE.md) · 🇷🇴 [ro](../ro/ARCHITECTURE.md) · 🇭🇺 [hu](../hu/ARCHITECTURE.md) · 🇧🇬 [bg](../bg/ARCHITECTURE.md) · 🇸🇰 [sk](../sk/ARCHITECTURE.md) · 🇺🇦 [uk-UA](../uk-UA/ARCHITECTURE.md) · 🇮🇱 [he](../he/ARCHITECTURE.md) · 🇵🇭 [phi](../phi/ARCHITECTURE.md)
+# OmniRoute Architecture (Suomi)
+
+🌐 **Languages:** 🇺🇸 [English](../../../../docs/ARCHITECTURE.md) · 🇪🇸 [es](../../es/docs/ARCHITECTURE.md) · 🇫🇷 [fr](../../fr/docs/ARCHITECTURE.md) · 🇩🇪 [de](../../de/docs/ARCHITECTURE.md) · 🇮🇹 [it](../../it/docs/ARCHITECTURE.md) · 🇷🇺 [ru](../../ru/docs/ARCHITECTURE.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/ARCHITECTURE.md) · 🇯🇵 [ja](../../ja/docs/ARCHITECTURE.md) · 🇰🇷 [ko](../../ko/docs/ARCHITECTURE.md) · 🇸🇦 [ar](../../ar/docs/ARCHITECTURE.md) · 🇮🇳 [in](../../in/docs/ARCHITECTURE.md) · 🇹🇭 [th](../../th/docs/ARCHITECTURE.md) · 🇻🇳 [vi](../../vi/docs/ARCHITECTURE.md) · 🇮🇩 [id](../../id/docs/ARCHITECTURE.md) · 🇲🇾 [ms](../../ms/docs/ARCHITECTURE.md) · 🇳🇱 [nl](../../nl/docs/ARCHITECTURE.md) · 🇵🇱 [pl](../../pl/docs/ARCHITECTURE.md) · 🇸🇪 [sv](../../sv/docs/ARCHITECTURE.md) · 🇳🇴 [no](../../no/docs/ARCHITECTURE.md) · 🇩🇰 [da](../../da/docs/ARCHITECTURE.md) · 🇫🇮 [fi](../../fi/docs/ARCHITECTURE.md) · 🇵🇹 [pt](../../pt/docs/ARCHITECTURE.md) · 🇷🇴 [ro](../../ro/docs/ARCHITECTURE.md) · 🇭🇺 [hu](../../hu/docs/ARCHITECTURE.md) · 🇧🇬 [bg](../../bg/docs/ARCHITECTURE.md) · 🇸🇰 [sk](../../sk/docs/ARCHITECTURE.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/ARCHITECTURE.md) · 🇮🇱 [he](../../he/docs/ARCHITECTURE.md) · 🇵🇭 [phi](../../phi/docs/ARCHITECTURE.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/ARCHITECTURE.md) · 🇨🇿 [cs](../../cs/docs/ARCHITECTURE.md)
---
-# OmniRoute Architecture
-
-🌐 **Languages:** 🇺🇸 [English](ARCHITECTURE.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/ARCHITECTURE.md) | 🇪🇸 [Español](i18n/es/ARCHITECTURE.md) | 🇫🇷 [Français](i18n/fr/ARCHITECTURE.md) | 🇮🇹 [Italiano](i18n/it/ARCHITECTURE.md) | 🇷🇺 [Русский](i18n/ru/ARCHITECTURE.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/ARCHITECTURE.md) | 🇩🇪 [Deutsch](i18n/de/ARCHITECTURE.md) | 🇮🇳 [हिन्दी](i18n/in/ARCHITECTURE.md) | 🇹🇭 [ไทย](i18n/th/ARCHITECTURE.md) | 🇺🇦 [Українська](i18n/uk-UA/ARCHITECTURE.md) | 🇸🇦 [العربية](i18n/ar/ARCHITECTURE.md) | 🇯🇵 [日本語](i18n/ja/ARCHITECTURE.md) | 🇻🇳 [Tiếng Việt](i18n/vi/ARCHITECTURE.md) | 🇧🇬 [Български](i18n/bg/ARCHITECTURE.md) | 🇩🇰 [Dansk](i18n/da/ARCHITECTURE.md) | 🇫🇮 [Suomi](i18n/fi/ARCHITECTURE.md) | 🇮🇱 [עברית](i18n/he/ARCHITECTURE.md) | 🇭🇺 [Magyar](i18n/hu/ARCHITECTURE.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/ARCHITECTURE.md) | 🇰🇷 [한국어](i18n/ko/ARCHITECTURE.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/ARCHITECTURE.md) | 🇳🇱 [Nederlands](i18n/nl/ARCHITECTURE.md) | 🇳🇴 [Norsk](i18n/no/ARCHITECTURE.md) | 🇵🇹 [Português (Portugal)](i18n/pt/ARCHITECTURE.md) | 🇷🇴 [Română](i18n/ro/ARCHITECTURE.md) | 🇵🇱 [Polski](i18n/pl/ARCHITECTURE.md) | 🇸🇰 [Slovenčina](i18n/sk/ARCHITECTURE.md) | 🇸🇪 [Svenska](i18n/sv/ARCHITECTURE.md) | 🇵🇭 [Filipino](i18n/phi/ARCHITECTURE.md)
-
-_Last updated: 2026-03-04_
+_Last updated: 2026-03-28_
## Executive Summary
@@ -69,6 +67,26 @@ Primary runtime model:
- Provider SLA/control plane outside local process
- External CLI binaries themselves (Claude CLI, Codex CLI, etc.)
+## Dashboard Surface (Current)
+
+Main pages under `src/app/(dashboard)/dashboard/`:
+
+- `/dashboard` — quick start + provider overview
+- `/dashboard/endpoint` — endpoint proxy + MCP + A2A + API endpoint tabs
+- `/dashboard/providers` — provider connections and credentials
+- `/dashboard/combos` — combo strategies, templates, model routing rules
+- `/dashboard/costs` — cost aggregation and pricing visibility
+- `/dashboard/analytics` — usage analytics and evaluations
+- `/dashboard/limits` — quota/rate controls
+- `/dashboard/cli-tools` — CLI onboarding, runtime detection, config generation
+- `/dashboard/agents` — detected ACP agents + custom agent registration
+- `/dashboard/media` — image/video/music playground
+- `/dashboard/search-tools` — search provider testing and history
+- `/dashboard/health` — uptime, circuit breakers, rate limits
+- `/dashboard/logs` — request/proxy/audit/console logs
+- `/dashboard/settings` — system settings tabs (general, routing, combo defaults, etc.)
+- `/dashboard/api-manager` — API key lifecycle and model permissions
+
## High-Level System Context
```mermaid
@@ -258,8 +276,9 @@ Domain State DB (SQLite):
## 5) Cloud Sync
-- Scheduler init: `src/lib/initCloudSync.ts`, `src/shared/services/initializeCloudSync.ts`
+- Scheduler init: `src/lib/initCloudSync.ts`, `src/shared/services/initializeCloudSync.ts`, `src/shared/services/modelSyncScheduler.ts`
- Periodic task: `src/shared/services/cloudSyncScheduler.ts`
+- Periodic task: `src/shared/services/modelSyncScheduler.ts`
- Control route: `src/app/api/sync/cloud/route.ts`
## Request Lifecycle (`/v1/chat/completions`)
@@ -339,7 +358,7 @@ flowchart TD
Q -- No --> R[Return all unavailable]
```
-Fallback decisions are driven by `open-sse/services/accountFallback.ts` using status codes and error-message heuristics.
+Fallback decisions are driven by `open-sse/services/accountFallback.ts` using status codes and error-message heuristics. Combo routing adds one extra guard: provider-scoped 400s such as upstream content-block and role-validation failures are treated as model-local failures so later combo targets can still run.
## OAuth Onboarding and Token Refresh Lifecycle
@@ -669,25 +688,25 @@ Additional processing layers in the translation pipeline:
## Supported API Endpoints
-| Endpoint | Format | Handler |
-| -------------------------------------------------- | ------------------ | ---------------------------------------------------- |
-| `POST /v1/chat/completions` | OpenAI Chat | `src/sse/handlers/chat.ts` |
-| `POST /v1/messages` | Claude Messages | Same handler (auto-detected) |
-| `POST /v1/responses` | OpenAI Responses | `open-sse/handlers/responsesHandler.ts` |
-| `POST /v1/embeddings` | OpenAI Embeddings | `open-sse/handlers/embeddings.ts` |
-| `GET /v1/embeddings` | Model listing | API route |
-| `POST /v1/images/generations` | OpenAI Images | `open-sse/handlers/imageGeneration.ts` |
-| `GET /v1/images/generations` | Model listing | API route |
-| `POST /v1/providers/{provider}/chat/completions` | OpenAI Chat | Dedicated per-provider with model validation |
-| `POST /v1/providers/{provider}/embeddings` | OpenAI Embeddings | Dedicated per-provider with model validation |
-| `POST /v1/providers/{provider}/images/generations` | OpenAI Images | Dedicated per-provider with model validation |
-| `POST /v1/messages/count_tokens` | Claude Token Count | API route |
-| `GET /v1/models` | OpenAI Models list | API route (chat + embedding + image + custom models) |
-| `GET /api/models/catalog` | Catalog | All models grouped by provider + type |
-| `POST /v1beta/models/*:streamGenerateContent` | Gemini native | API route |
-| `GET/PUT/DELETE /api/settings/proxy` | Proxy Config | Network proxy configuration |
-| `POST /api/settings/proxy/test` | Proxy Connectivity | Proxy health/connectivity test endpoint |
-| `GET/POST/DELETE /api/provider-models` | Custom Models | Custom model management per provider |
+| Endpoint | Format | Handler |
+| -------------------------------------------------- | ------------------ | ------------------------------------------------------------------- |
+| `POST /v1/chat/completions` | OpenAI Chat | `src/sse/handlers/chat.ts` |
+| `POST /v1/messages` | Claude Messages | Same handler (auto-detected) |
+| `POST /v1/responses` | OpenAI Responses | `open-sse/handlers/responsesHandler.ts` |
+| `POST /v1/embeddings` | OpenAI Embeddings | `open-sse/handlers/embeddings.ts` |
+| `GET /v1/embeddings` | Model listing | API route |
+| `POST /v1/images/generations` | OpenAI Images | `open-sse/handlers/imageGeneration.ts` |
+| `GET /v1/images/generations` | Model listing | API route |
+| `POST /v1/providers/{provider}/chat/completions` | OpenAI Chat | Dedicated per-provider with model validation |
+| `POST /v1/providers/{provider}/embeddings` | OpenAI Embeddings | Dedicated per-provider with model validation |
+| `POST /v1/providers/{provider}/images/generations` | OpenAI Images | Dedicated per-provider with model validation |
+| `POST /v1/messages/count_tokens` | Claude Token Count | API route |
+| `GET /v1/models` | OpenAI Models list | API route (chat + embedding + image + custom models) |
+| `GET /api/models/catalog` | Catalog | All models grouped by provider + type |
+| `POST /v1beta/models/*:streamGenerateContent` | Gemini native | API route |
+| `GET/PUT/DELETE /api/settings/proxy` | Proxy Config | Network proxy configuration |
+| `POST /api/settings/proxy/test` | Proxy Connectivity | Proxy health/connectivity test endpoint |
+| `GET/POST/DELETE /api/provider-models` | Provider Models | Provider model metadata backing custom and managed available models |
## Bypass Handler
@@ -739,10 +758,18 @@ Runtime visibility sources:
- console logs from `src/sse/utils/logger.ts`
- per-request usage aggregates in SQLite (`usage_history`, `call_logs`, `proxy_logs`)
+- four-stage detailed payload captures in SQLite (`request_detail_logs`) when `settings.detailed_logs_enabled=true`
- textual request status log in `log.txt` (optional/compat)
- optional deep request/translation logs under `logs/` when `ENABLE_REQUEST_LOGS=true`
- dashboard usage endpoints (`/api/usage/*`) for UI consumption
+Detailed request payload capture stores up to four JSON payload stages per routed call:
+
+- raw request received from the client
+- translated request actually sent upstream
+- provider response reconstructed as JSON; streamed responses are compacted to the final summary plus stream metadata
+- final client response returned by OmniRoute; streamed responses are stored in the same compact summary form
+
## Security-Sensitive Boundaries
- JWT secret (`JWT_SECRET`) secures dashboard session cookie verification/signing
diff --git a/docs/i18n/de/AUTO-COMBO.md b/docs/i18n/fi/docs/AUTO-COMBO.md
similarity index 65%
rename from docs/i18n/de/AUTO-COMBO.md
rename to docs/i18n/fi/docs/AUTO-COMBO.md
index 2166e41dff..f2c5cfedb7 100644
--- a/docs/i18n/de/AUTO-COMBO.md
+++ b/docs/i18n/fi/docs/AUTO-COMBO.md
@@ -1,9 +1,9 @@
-🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/AUTO-COMBO.md) · 🇪🇸 [es](../es/AUTO-COMBO.md) · 🇫🇷 [fr](../fr/AUTO-COMBO.md) · 🇩🇪 [de](../de/AUTO-COMBO.md) · 🇮🇹 [it](../it/AUTO-COMBO.md) · 🇷🇺 [ru](../ru/AUTO-COMBO.md) · 🇨🇳 [zh-CN](../zh-CN/AUTO-COMBO.md) · 🇯🇵 [ja](../ja/AUTO-COMBO.md) · 🇰🇷 [ko](../ko/AUTO-COMBO.md) · 🇸🇦 [ar](../ar/AUTO-COMBO.md) · 🇮🇳 [in](../in/AUTO-COMBO.md) · 🇹🇭 [th](../th/AUTO-COMBO.md) · 🇻🇳 [vi](../vi/AUTO-COMBO.md) · 🇮🇩 [id](../id/AUTO-COMBO.md) · 🇲🇾 [ms](../ms/AUTO-COMBO.md) · 🇳🇱 [nl](../nl/AUTO-COMBO.md) · 🇵🇱 [pl](../pl/AUTO-COMBO.md) · 🇸🇪 [sv](../sv/AUTO-COMBO.md) · 🇳🇴 [no](../no/AUTO-COMBO.md) · 🇩🇰 [da](../da/AUTO-COMBO.md) · 🇫🇮 [fi](../fi/AUTO-COMBO.md) · 🇵🇹 [pt](../pt/AUTO-COMBO.md) · 🇷🇴 [ro](../ro/AUTO-COMBO.md) · 🇭🇺 [hu](../hu/AUTO-COMBO.md) · 🇧🇬 [bg](../bg/AUTO-COMBO.md) · 🇸🇰 [sk](../sk/AUTO-COMBO.md) · 🇺🇦 [uk-UA](../uk-UA/AUTO-COMBO.md) · 🇮🇱 [he](../he/AUTO-COMBO.md) · 🇵🇭 [phi](../phi/AUTO-COMBO.md)
+# OmniRoute Auto-Combo Engine (Suomi)
+
+🌐 **Languages:** 🇺🇸 [English](../../../../docs/AUTO-COMBO.md) · 🇪🇸 [es](../../es/docs/AUTO-COMBO.md) · 🇫🇷 [fr](../../fr/docs/AUTO-COMBO.md) · 🇩🇪 [de](../../de/docs/AUTO-COMBO.md) · 🇮🇹 [it](../../it/docs/AUTO-COMBO.md) · 🇷🇺 [ru](../../ru/docs/AUTO-COMBO.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/AUTO-COMBO.md) · 🇯🇵 [ja](../../ja/docs/AUTO-COMBO.md) · 🇰🇷 [ko](../../ko/docs/AUTO-COMBO.md) · 🇸🇦 [ar](../../ar/docs/AUTO-COMBO.md) · 🇮🇳 [in](../../in/docs/AUTO-COMBO.md) · 🇹🇭 [th](../../th/docs/AUTO-COMBO.md) · 🇻🇳 [vi](../../vi/docs/AUTO-COMBO.md) · 🇮🇩 [id](../../id/docs/AUTO-COMBO.md) · 🇲🇾 [ms](../../ms/docs/AUTO-COMBO.md) · 🇳🇱 [nl](../../nl/docs/AUTO-COMBO.md) · 🇵🇱 [pl](../../pl/docs/AUTO-COMBO.md) · 🇸🇪 [sv](../../sv/docs/AUTO-COMBO.md) · 🇳🇴 [no](../../no/docs/AUTO-COMBO.md) · 🇩🇰 [da](../../da/docs/AUTO-COMBO.md) · 🇫🇮 [fi](../../fi/docs/AUTO-COMBO.md) · 🇵🇹 [pt](../../pt/docs/AUTO-COMBO.md) · 🇷🇴 [ro](../../ro/docs/AUTO-COMBO.md) · 🇭🇺 [hu](../../hu/docs/AUTO-COMBO.md) · 🇧🇬 [bg](../../bg/docs/AUTO-COMBO.md) · 🇸🇰 [sk](../../sk/docs/AUTO-COMBO.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/AUTO-COMBO.md) · 🇮🇱 [he](../../he/docs/AUTO-COMBO.md) · 🇵🇭 [phi](../../phi/docs/AUTO-COMBO.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/AUTO-COMBO.md) · 🇨🇿 [cs](../../cs/docs/AUTO-COMBO.md)
---
-# OmniRoute Auto-Combo Engine
-
> Self-managing model chains with adaptive scoring
## How It Works
diff --git a/docs/i18n/fi/docs/CLI-TOOLS.md b/docs/i18n/fi/docs/CLI-TOOLS.md
new file mode 100644
index 0000000000..c44a72bd3c
--- /dev/null
+++ b/docs/i18n/fi/docs/CLI-TOOLS.md
@@ -0,0 +1,348 @@
+# CLI Tools Setup Guide — OmniRoute (Suomi)
+
+🌐 **Languages:** 🇺🇸 [English](../../../../docs/CLI-TOOLS.md) · 🇪🇸 [es](../../es/docs/CLI-TOOLS.md) · 🇫🇷 [fr](../../fr/docs/CLI-TOOLS.md) · 🇩🇪 [de](../../de/docs/CLI-TOOLS.md) · 🇮🇹 [it](../../it/docs/CLI-TOOLS.md) · 🇷🇺 [ru](../../ru/docs/CLI-TOOLS.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/CLI-TOOLS.md) · 🇯🇵 [ja](../../ja/docs/CLI-TOOLS.md) · 🇰🇷 [ko](../../ko/docs/CLI-TOOLS.md) · 🇸🇦 [ar](../../ar/docs/CLI-TOOLS.md) · 🇮🇳 [in](../../in/docs/CLI-TOOLS.md) · 🇹🇭 [th](../../th/docs/CLI-TOOLS.md) · 🇻🇳 [vi](../../vi/docs/CLI-TOOLS.md) · 🇮🇩 [id](../../id/docs/CLI-TOOLS.md) · 🇲🇾 [ms](../../ms/docs/CLI-TOOLS.md) · 🇳🇱 [nl](../../nl/docs/CLI-TOOLS.md) · 🇵🇱 [pl](../../pl/docs/CLI-TOOLS.md) · 🇸🇪 [sv](../../sv/docs/CLI-TOOLS.md) · 🇳🇴 [no](../../no/docs/CLI-TOOLS.md) · 🇩🇰 [da](../../da/docs/CLI-TOOLS.md) · 🇫🇮 [fi](../../fi/docs/CLI-TOOLS.md) · 🇵🇹 [pt](../../pt/docs/CLI-TOOLS.md) · 🇷🇴 [ro](../../ro/docs/CLI-TOOLS.md) · 🇭🇺 [hu](../../hu/docs/CLI-TOOLS.md) · 🇧🇬 [bg](../../bg/docs/CLI-TOOLS.md) · 🇸🇰 [sk](../../sk/docs/CLI-TOOLS.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/CLI-TOOLS.md) · 🇮🇱 [he](../../he/docs/CLI-TOOLS.md) · 🇵🇭 [phi](../../phi/docs/CLI-TOOLS.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/CLI-TOOLS.md) · 🇨🇿 [cs](../../cs/docs/CLI-TOOLS.md)
+
+---
+
+This guide explains how to install and configure all supported AI coding CLI tools
+to use **OmniRoute** as the unified backend, giving you centralized key management,
+cost tracking, model switching, and request logging across every tool.
+
+---
+
+## How It Works
+
+```
+Claude / Codex / OpenCode / Cline / KiloCode / Continue / Kiro / Cursor / Copilot
+ │
+ ▼ (all point to OmniRoute)
+ http://YOUR_SERVER:20128/v1
+ │
+ ▼ (OmniRoute routes to the right provider)
+ Anthropic / OpenAI / Gemini / DeepSeek / Groq / Mistral / ...
+```
+
+**Benefits:**
+
+- One API key to manage all tools
+- Cost tracking across all CLIs in the dashboard
+- Model switching without reconfiguring every tool
+- Works locally and on remote servers (VPS)
+
+---
+
+## Supported Tools (Dashboard Source of Truth)
+
+The dashboard cards in `/dashboard/cli-tools` are generated from `src/shared/constants/cliTools.ts`.
+Current list (v3.0.0-rc.16):
+
+| Tool | ID | Command | Setup Mode | Install Method |
+| ------------------ | ------------- | ---------- | ---------- | -------------- |
+| **Claude Code** | `claude` | `claude` | env | npm |
+| **OpenAI Codex** | `codex` | `codex` | custom | npm |
+| **Factory Droid** | `droid` | `droid` | custom | bundled/CLI |
+| **OpenClaw** | `openclaw` | `openclaw` | custom | bundled/CLI |
+| **Cursor** | `cursor` | app | guide | desktop app |
+| **Cline** | `cline` | `cline` | custom | npm |
+| **Kilo Code** | `kilo` | `kilocode` | custom | npm |
+| **Continue** | `continue` | extension | guide | VS Code |
+| **Antigravity** | `antigravity` | internal | mitm | OmniRoute |
+| **GitHub Copilot** | `copilot` | extension | custom | VS Code |
+| **OpenCode** | `opencode` | `opencode` | guide | npm |
+| **Kiro AI** | `kiro` | app/cli | mitm | desktop/CLI |
+
+### CLI fingerprint sync (Agents + Settings)
+
+`/dashboard/agents` and `Settings > CLI Fingerprint` use `src/shared/constants/cliCompatProviders.ts`.
+This keeps provider IDs aligned with CLI cards and legacy IDs.
+
+| CLI ID | Fingerprint Provider ID |
+| ---------------------------------------------------------------------------------------------------- | ----------------------- |
+| `kilo` | `kilocode` |
+| `copilot` | `github` |
+| `claude` / `codex` / `antigravity` / `kiro` / `cursor` / `cline` / `opencode` / `droid` / `openclaw` | same ID |
+
+Legacy IDs still accepted for compatibility: `copilot`, `kimi-coding`, `qwen`.
+
+---
+
+## Step 1 — Get an OmniRoute API Key
+
+1. Open the OmniRoute dashboard → **API Manager** (`/dashboard/api-manager`)
+2. Click **Create API Key**
+3. Give it a name (e.g. `cli-tools`) and select all permissions
+4. Copy the key — you'll need it for every CLI below
+
+> Your key looks like: `sk-xxxxxxxxxxxxxxxx-xxxxxxxxx`
+
+---
+
+## Step 2 — Install CLI Tools
+
+All npm-based tools require Node.js 18+:
+
+```bash
+# Claude Code (Anthropic)
+npm install -g @anthropic-ai/claude-code
+
+# OpenAI Codex
+npm install -g @openai/codex
+
+# OpenCode
+npm install -g opencode-ai
+
+# Cline
+npm install -g cline
+
+# KiloCode
+npm install -g kilocode
+
+# Kiro CLI (Amazon — requires curl + unzip)
+apt-get install -y unzip # on Debian/Ubuntu
+curl -fsSL https://cli.kiro.dev/install | bash
+export PATH="$HOME/.local/bin:$PATH" # add to ~/.bashrc
+```
+
+**Verify:**
+
+```bash
+claude --version # 2.x.x
+codex --version # 0.x.x
+opencode --version # x.x.x
+cline --version # 2.x.x
+kilocode --version # x.x.x (or: kilo --version)
+kiro-cli --version # 1.x.x
+```
+
+---
+
+## Step 3 — Set Global Environment Variables
+
+Add to `~/.bashrc` (or `~/.zshrc`), then run `source ~/.bashrc`:
+
+```bash
+# OmniRoute Universal Endpoint
+export OPENAI_BASE_URL="http://localhost:20128/v1"
+export OPENAI_API_KEY="sk-your-omniroute-key"
+export ANTHROPIC_BASE_URL="http://localhost:20128/v1"
+export ANTHROPIC_API_KEY="sk-your-omniroute-key"
+export GEMINI_BASE_URL="http://localhost:20128/v1"
+export GEMINI_API_KEY="sk-your-omniroute-key"
+```
+
+> For a **remote server** replace `localhost:20128` with the server IP or domain,
+> e.g. `http://192.168.0.15:20128`.
+
+---
+
+## Step 4 — Configure Each Tool
+
+### Claude Code
+
+```bash
+# Via CLI:
+claude config set --global api-base-url http://localhost:20128/v1
+
+# Or create ~/.claude/settings.json:
+mkdir -p ~/.claude && cat > ~/.claude/settings.json << EOF
+{
+ "apiBaseUrl": "http://localhost:20128/v1",
+ "apiKey": "sk-your-omniroute-key"
+}
+EOF
+```
+
+**Test:** `claude "say hello"`
+
+---
+
+### OpenAI Codex
+
+```bash
+mkdir -p ~/.codex && cat > ~/.codex/config.yaml << EOF
+model: auto
+apiKey: sk-your-omniroute-key
+apiBaseUrl: http://localhost:20128/v1
+EOF
+```
+
+**Test:** `codex "what is 2+2?"`
+
+---
+
+### OpenCode
+
+```bash
+mkdir -p ~/.config/opencode && cat > ~/.config/opencode/config.toml << EOF
+[provider.openai]
+base_url = "http://localhost:20128/v1"
+api_key = "sk-your-omniroute-key"
+EOF
+```
+
+**Test:** `opencode`
+
+---
+
+### Cline (CLI or VS Code)
+
+**CLI mode:**
+
+```bash
+mkdir -p ~/.cline/data && cat > ~/.cline/data/globalState.json << EOF
+{
+ "apiProvider": "openai",
+ "openAiBaseUrl": "http://localhost:20128/v1",
+ "openAiApiKey": "sk-your-omniroute-key"
+}
+EOF
+```
+
+**VS Code mode:**
+Cline extension settings → API Provider: `OpenAI Compatible` → Base URL: `http://localhost:20128/v1`
+
+Or use the OmniRoute dashboard → **CLI Tools → Cline → Apply Config**.
+
+---
+
+### KiloCode (CLI or VS Code)
+
+**CLI mode:**
+
+```bash
+kilocode --api-base http://localhost:20128/v1 --api-key sk-your-omniroute-key
+```
+
+**VS Code settings:**
+
+```json
+{
+ "kilo-code.openAiBaseUrl": "http://localhost:20128/v1",
+ "kilo-code.apiKey": "sk-your-omniroute-key"
+}
+```
+
+Or use the OmniRoute dashboard → **CLI Tools → KiloCode → Apply Config**.
+
+---
+
+### Continue (VS Code Extension)
+
+Edit `~/.continue/config.yaml`:
+
+```yaml
+models:
+ - name: OmniRoute
+ provider: openai
+ model: auto
+ apiBase: http://localhost:20128/v1
+ apiKey: sk-your-omniroute-key
+ default: true
+```
+
+Restart VS Code after editing.
+
+---
+
+### Kiro CLI (Amazon)
+
+```bash
+# Login to your AWS/Kiro account:
+kiro-cli login
+
+# The CLI uses its own auth — OmniRoute is not needed as backend for Kiro CLI itself.
+# Use kiro-cli alongside OmniRoute for other tools.
+kiro-cli status
+```
+
+---
+
+### Cursor (Desktop App)
+
+> **Note:** Cursor routes requests through its cloud. For OmniRoute integration,
+> enable **Cloud Endpoint** in OmniRoute Settings and use your public domain URL.
+
+Via GUI: **Settings → Models → OpenAI API Key**
+
+- Base URL: `https://your-domain.com/v1`
+- API Key: your OmniRoute key
+
+---
+
+## Dashboard Auto-Configuration
+
+The OmniRoute dashboard automates configuration for most tools:
+
+1. Go to `http://localhost:20128/dashboard/cli-tools`
+2. Expand any tool card
+3. Select your API key from the dropdown
+4. Click **Apply Config** (if tool is detected as installed)
+5. Or copy the generated config snippet manually
+
+---
+
+## Built-in Agents: Droid & OpenClaw
+
+**Droid** and **OpenClaw** are AI agents built directly into OmniRoute — no installation needed.
+They run as internal routes and use OmniRoute's model routing automatically.
+
+- Access: `http://localhost:20128/dashboard/agents`
+- Configure: same combos and providers as all other tools
+- No API key or CLI install required
+
+---
+
+## Available API Endpoints
+
+| Endpoint | Description | Use For |
+| -------------------------- | ----------------------------- | --------------------------- |
+| `/v1/chat/completions` | Standard chat (all providers) | All modern tools |
+| `/v1/responses` | Responses API (OpenAI format) | Codex, agentic workflows |
+| `/v1/completions` | Legacy text completions | Older tools using `prompt:` |
+| `/v1/embeddings` | Text embeddings | RAG, search |
+| `/v1/images/generations` | Image generation | DALL-E, Flux, etc. |
+| `/v1/audio/speech` | Text-to-speech | ElevenLabs, OpenAI TTS |
+| `/v1/audio/transcriptions` | Speech-to-text | Deepgram, AssemblyAI |
+
+---
+
+## Vianmääritys
+
+| Error | Cause | Fix |
+| ------------------------- | ----------------------- | ------------------------------------------ |
+| `Connection refused` | OmniRoute not running | `pm2 start omniroute` |
+| `401 Unauthorized` | Wrong API key | Check in `/dashboard/api-manager` |
+| `No combo configured` | No active routing combo | Set up in `/dashboard/combos` |
+| `invalid model` | Model not in catalog | Use `auto` or check `/dashboard/providers` |
+| CLI shows "not installed" | Binary not in PATH | Check `which ` |
+| `kiro-cli: not found` | Not in PATH | `export PATH="$HOME/.local/bin:$PATH"` |
+
+---
+
+## Quick Setup Script (One Command)
+
+```bash
+# Install all CLIs and configure for OmniRoute (replace with your key and server URL)
+OMNIROUTE_URL="http://localhost:20128/v1"
+OMNIROUTE_KEY="sk-your-omniroute-key"
+
+npm install -g @anthropic-ai/claude-code @openai/codex opencode-ai cline kilocode
+
+# Kiro CLI
+apt-get install -y unzip 2>/dev/null; curl -fsSL https://cli.kiro.dev/install | bash
+
+# Write configs
+mkdir -p ~/.claude ~/.codex ~/.config/opencode ~/.continue
+
+cat > ~/.claude/settings.json <<< "{\"apiBaseUrl\":\"$OMNIROUTE_URL\",\"apiKey\":\"$OMNIROUTE_KEY\"}"
+cat > ~/.codex/config.yaml <<< "model: auto\napiKey: $OMNIROUTE_KEY\napiBaseUrl: $OMNIROUTE_URL"
+cat >> ~/.bashrc << EOF
+export OPENAI_BASE_URL="$OMNIROUTE_URL"
+export OPENAI_API_KEY="$OMNIROUTE_KEY"
+export ANTHROPIC_BASE_URL="$OMNIROUTE_URL"
+export ANTHROPIC_API_KEY="$OMNIROUTE_KEY"
+EOF
+
+source ~/.bashrc
+echo "✅ All CLIs installed and configured for OmniRoute"
+```
diff --git a/docs/i18n/fi/docs/CODEBASE_DOCUMENTATION.md b/docs/i18n/fi/docs/CODEBASE_DOCUMENTATION.md
new file mode 100644
index 0000000000..d39141da9b
--- /dev/null
+++ b/docs/i18n/fi/docs/CODEBASE_DOCUMENTATION.md
@@ -0,0 +1,591 @@
+# omniroute — Codebase Documentation (Suomi)
+
+🌐 **Languages:** 🇺🇸 [English](../../../../docs/CODEBASE_DOCUMENTATION.md) · 🇪🇸 [es](../../es/docs/CODEBASE_DOCUMENTATION.md) · 🇫🇷 [fr](../../fr/docs/CODEBASE_DOCUMENTATION.md) · 🇩🇪 [de](../../de/docs/CODEBASE_DOCUMENTATION.md) · 🇮🇹 [it](../../it/docs/CODEBASE_DOCUMENTATION.md) · 🇷🇺 [ru](../../ru/docs/CODEBASE_DOCUMENTATION.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/CODEBASE_DOCUMENTATION.md) · 🇯🇵 [ja](../../ja/docs/CODEBASE_DOCUMENTATION.md) · 🇰🇷 [ko](../../ko/docs/CODEBASE_DOCUMENTATION.md) · 🇸🇦 [ar](../../ar/docs/CODEBASE_DOCUMENTATION.md) · 🇮🇳 [in](../../in/docs/CODEBASE_DOCUMENTATION.md) · 🇹🇭 [th](../../th/docs/CODEBASE_DOCUMENTATION.md) · 🇻🇳 [vi](../../vi/docs/CODEBASE_DOCUMENTATION.md) · 🇮🇩 [id](../../id/docs/CODEBASE_DOCUMENTATION.md) · 🇲🇾 [ms](../../ms/docs/CODEBASE_DOCUMENTATION.md) · 🇳🇱 [nl](../../nl/docs/CODEBASE_DOCUMENTATION.md) · 🇵🇱 [pl](../../pl/docs/CODEBASE_DOCUMENTATION.md) · 🇸🇪 [sv](../../sv/docs/CODEBASE_DOCUMENTATION.md) · 🇳🇴 [no](../../no/docs/CODEBASE_DOCUMENTATION.md) · 🇩🇰 [da](../../da/docs/CODEBASE_DOCUMENTATION.md) · 🇫🇮 [fi](../../fi/docs/CODEBASE_DOCUMENTATION.md) · 🇵🇹 [pt](../../pt/docs/CODEBASE_DOCUMENTATION.md) · 🇷🇴 [ro](../../ro/docs/CODEBASE_DOCUMENTATION.md) · 🇭🇺 [hu](../../hu/docs/CODEBASE_DOCUMENTATION.md) · 🇧🇬 [bg](../../bg/docs/CODEBASE_DOCUMENTATION.md) · 🇸🇰 [sk](../../sk/docs/CODEBASE_DOCUMENTATION.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/CODEBASE_DOCUMENTATION.md) · 🇮🇱 [he](../../he/docs/CODEBASE_DOCUMENTATION.md) · 🇵🇭 [phi](../../phi/docs/CODEBASE_DOCUMENTATION.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/CODEBASE_DOCUMENTATION.md) · 🇨🇿 [cs](../../cs/docs/CODEBASE_DOCUMENTATION.md)
+
+---
+
+> A comprehensive, beginner-friendly guide to the **omniroute** multi-provider AI proxy router.
+
+---
+
+## 1. What Is omniroute?
+
+omniroute is a **proxy router** that sits between AI clients (Claude CLI, Codex, Cursor IDE, etc.) and AI providers (Anthropic, Google, OpenAI, AWS, GitHub, etc.). It solves one big problem:
+
+> **Different AI clients speak different "languages" (API formats), and different AI providers expect different "languages" too.** omniroute translates between them automatically.
+
+Think of it like a universal translator at the United Nations — any delegate can speak any language, and the translator converts it for any other delegate.
+
+---
+
+## 2. Architecture Overview
+
+```mermaid
+graph LR
+ subgraph Clients
+ A[Claude CLI]
+ B[Codex]
+ C[Cursor IDE]
+ D[OpenAI-compatible]
+ end
+
+ subgraph omniroute
+ E[Handler Layer]
+ F[Translator Layer]
+ G[Executor Layer]
+ H[Services Layer]
+ end
+
+ subgraph Providers
+ I[Anthropic Claude]
+ J[Google Gemini]
+ K[OpenAI / Codex]
+ L[GitHub Copilot]
+ M[AWS Kiro]
+ N[Antigravity]
+ O[Cursor API]
+ end
+
+ A --> E
+ B --> E
+ C --> E
+ D --> E
+ E --> F
+ F --> G
+ G --> I
+ G --> J
+ G --> K
+ G --> L
+ G --> M
+ G --> N
+ G --> O
+ H -.-> E
+ H -.-> G
+```
+
+### Core Principle: Hub-and-Spoke Translation
+
+All format translation passes through **OpenAI format as the hub**:
+
+```
+Client Format → [OpenAI Hub] → Provider Format (request)
+Provider Format → [OpenAI Hub] → Client Format (response)
+```
+
+This means you only need **N translators** (one per format) instead of **N²** (every pair).
+
+---
+
+## 3. Project Structure
+
+```
+omniroute/
+├── open-sse/ ← Core proxy library (portable, framework-agnostic)
+│ ├── index.js ← Main entry point, exports everything
+│ ├── config/ ← Configuration & constants
+│ ├── executors/ ← Provider-specific request execution
+│ ├── handlers/ ← Request handling orchestration
+│ ├── services/ ← Business logic (auth, models, fallback, usage)
+│ ├── translator/ ← Format translation engine
+│ │ ├── request/ ← Request translators (8 files)
+│ │ ├── response/ ← Response translators (7 files)
+│ │ └── helpers/ ← Shared translation utilities (6 files)
+│ └── utils/ ← Utility functions
+├── src/ ← Application layer (Express/Worker runtime)
+│ ├── app/ ← Web UI, API routes, middleware
+│ ├── lib/ ← Database, auth, and shared library code
+│ ├── mitm/ ← Man-in-the-middle proxy utilities
+│ ├── models/ ← Database models
+│ ├── shared/ ← Shared utilities (wrappers around open-sse)
+│ ├── sse/ ← SSE endpoint handlers
+│ └── store/ ← State management
+├── data/ ← Runtime data (credentials, logs)
+│ └── provider-credentials.json (external credentials override, gitignored)
+└── tester/ ← Test utilities
+```
+
+---
+
+## 4. Module-by-Module Breakdown
+
+### 4.1 Config (`open-sse/config/`)
+
+The **single source of truth** for all provider configuration.
+
+| File | Purpose |
+| ----------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| `constants.ts` | `PROVIDERS` object with base URLs, OAuth credentials (defaults), headers, and default system prompts for every provider. Also defines `HTTP_STATUS`, `ERROR_TYPES`, `COOLDOWN_MS`, `BACKOFF_CONFIG`, and `SKIP_PATTERNS`. |
+| `credentialLoader.ts` | Loads external credentials from `data/provider-credentials.json` and merges them over the hardcoded defaults in `PROVIDERS`. Keeps secrets out of source control while maintaining backwards compatibility. |
+| `providerModels.ts` | Central model registry: maps provider aliases → model IDs. Functions like `getModels()`, `getProviderByAlias()`. |
+| `codexInstructions.ts` | System instructions injected into Codex requests (editing constraints, sandbox rules, approval policies). |
+| `defaultThinkingSignature.ts` | Default "thinking" signatures for Claude and Gemini models. |
+| `ollamaModels.ts` | Schema definition for local Ollama models (name, size, family, quantization). |
+
+#### Credential Loading Flow
+
+```mermaid
+flowchart TD
+ A["App starts"] --> B["constants.ts defines PROVIDERS\nwith hardcoded defaults"]
+ B --> C{"data/provider-credentials.json\nexists?"}
+ C -->|Yes| D["credentialLoader reads JSON"]
+ C -->|No| E["Use hardcoded defaults"]
+ D --> F{"For each provider in JSON"}
+ F --> G{"Provider exists\nin PROVIDERS?"}
+ G -->|No| H["Log warning, skip"]
+ G -->|Yes| I{"Value is object?"}
+ I -->|No| J["Log warning, skip"]
+ I -->|Yes| K["Merge clientId, clientSecret,\ntokenUrl, authUrl, refreshUrl"]
+ K --> F
+ H --> F
+ J --> F
+ F -->|Done| L["PROVIDERS ready with\nmerged credentials"]
+ E --> L
+```
+
+---
+
+### 4.2 Executors (`open-sse/executors/`)
+
+Executors encapsulate **provider-specific logic** using the **Strategy Pattern**. Each executor overrides base methods as needed.
+
+```mermaid
+classDiagram
+ class BaseExecutor {
+ +buildUrl(model, stream, options)
+ +buildHeaders(credentials, stream, body)
+ +transformRequest(body, model, stream, credentials)
+ +execute(url, options)
+ +shouldRetry(status, error)
+ +refreshCredentials(credentials, log)
+ }
+
+ class DefaultExecutor {
+ +refreshCredentials()
+ }
+
+ class AntigravityExecutor {
+ +buildUrl()
+ +buildHeaders()
+ +transformRequest()
+ +shouldRetry()
+ +refreshCredentials()
+ }
+
+ class CursorExecutor {
+ +buildUrl()
+ +buildHeaders()
+ +transformRequest()
+ +parseResponse()
+ +generateChecksum()
+ }
+
+ class KiroExecutor {
+ +buildUrl()
+ +buildHeaders()
+ +transformRequest()
+ +parseEventStream()
+ +refreshCredentials()
+ }
+
+ BaseExecutor <|-- DefaultExecutor
+ BaseExecutor <|-- AntigravityExecutor
+ BaseExecutor <|-- CursorExecutor
+ BaseExecutor <|-- KiroExecutor
+ BaseExecutor <|-- CodexExecutor
+ BaseExecutor <|-- GeminiCLIExecutor
+ BaseExecutor <|-- GithubExecutor
+```
+
+| Executor | Provider | Key Specializations |
+| ---------------- | ------------------------------------------ | ------------------------------------------------------------------------------------------------------------------- |
+| `base.ts` | — | Abstract base: URL building, headers, retry logic, credential refresh |
+| `default.ts` | Claude, Gemini, OpenAI, GLM, Kimi, MiniMax | Generic OAuth token refresh for standard providers |
+| `antigravity.ts` | Google Cloud Code | Project/session ID generation, multi-URL fallback, custom retry parsing from error messages ("reset after 2h7m23s") |
+| `cursor.ts` | Cursor IDE | **Most complex**: SHA-256 checksum auth, Protobuf request encoding, binary EventStream → SSE response parsing |
+| `codex.ts` | OpenAI Codex | Injects system instructions, manages thinking levels, removes unsupported parameters |
+| `gemini-cli.ts` | Google Gemini CLI | Custom URL building (`streamGenerateContent`), Google OAuth token refresh |
+| `github.ts` | GitHub Copilot | Dual token system (GitHub OAuth + Copilot token), VSCode header mimicking |
+| `kiro.ts` | AWS CodeWhisperer | AWS EventStream binary parsing, AMZN event frames, token estimation |
+| `index.ts` | — | Factory: maps provider name → executor class, with default fallback |
+
+---
+
+### 4.3 Handlers (`open-sse/handlers/`)
+
+The **orchestration layer** — coordinates translation, execution, streaming, and error handling.
+
+| File | Purpose |
+| --------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| `chatCore.ts` | **Central orchestrator** (~600 lines). Handles the complete request lifecycle: format detection → translation → executor dispatch → streaming/non-streaming response → token refresh → error handling → usage logging. |
+| `responsesHandler.ts` | Adapter for OpenAI's Responses API: converts Responses format → Chat Completions → sends to `chatCore` → converts SSE back to Responses format. |
+| `embeddings.ts` | Embedding generation handler: resolves embedding model → provider, dispatches to provider API, returns OpenAI-compatible embedding response. Supports 6+ providers. |
+| `imageGeneration.ts` | Image generation handler: resolves image model → provider, supports OpenAI-compatible, Gemini-image (Antigravity), and fallback (Nebius) modes. Returns base64 or URL images. |
+
+#### Request Lifecycle (chatCore.ts)
+
+```mermaid
+sequenceDiagram
+ participant Client
+ participant chatCore
+ participant Translator
+ participant Executor
+ participant Provider
+
+ Client->>chatCore: Request (any format)
+ chatCore->>chatCore: Detect source format
+ chatCore->>chatCore: Check bypass patterns
+ chatCore->>chatCore: Resolve model & provider
+ chatCore->>Translator: Translate request (source → OpenAI → target)
+ chatCore->>Executor: Get executor for provider
+ Executor->>Executor: Build URL, headers, transform request
+ Executor->>Executor: Refresh credentials if needed
+ Executor->>Provider: HTTP fetch (streaming or non-streaming)
+
+ alt Streaming
+ Provider-->>chatCore: SSE stream
+ chatCore->>chatCore: Pipe through SSE transform stream
+ Note over chatCore: Transform stream translates
each chunk: target → OpenAI → source
+ chatCore-->>Client: Translated SSE stream
+ else Non-streaming
+ Provider-->>chatCore: JSON response
+ chatCore->>Translator: Translate response
+ chatCore-->>Client: Translated JSON
+ end
+
+ alt Error (401, 429, 500...)
+ chatCore->>Executor: Retry with credential refresh
+ chatCore->>chatCore: Account fallback logic
+ end
+```
+
+---
+
+### 4.4 Services (`open-sse/services/`)
+
+Business logic that supports the handlers and executors.
+
+| File | Purpose |
+| -------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| `provider.ts` | **Format detection** (`detectFormat`): analyzes request body structure to identify Claude/OpenAI/Gemini/Antigravity/Responses formats (includes `max_tokens` heuristic for Claude). Also: URL building, header building, thinking config normalization. Supports `openai-compatible-*` and `anthropic-compatible-*` dynamic providers. |
+| `model.ts` | Model string parsing (`claude/model-name` → `{provider: "claude", model: "model-name"}`), alias resolution with collision detection, input sanitization (rejects path traversal/control chars), and model info resolution with async alias getter support. |
+| `accountFallback.ts` | Rate-limit handling: exponential backoff (1s → 2s → 4s → max 2min), account cooldown management, error classification (which errors trigger fallback vs. not). |
+| `tokenRefresh.ts` | OAuth token refresh for **every provider**: Google (Gemini, Antigravity), Claude, Codex, Qwen, Qoder, GitHub (OAuth + Copilot dual-token), Kiro (AWS SSO OIDC + Social Auth). Includes in-flight promise deduplication cache and retry with exponential backoff. |
+| `combo.ts` | **Combo models**: chains of fallback models. If model A fails with a fallback-eligible error, try model B, then C, etc. Returns actual upstream status codes. |
+| `usage.ts` | Fetches quota/usage data from provider APIs (GitHub Copilot quotas, Antigravity model quotas, Codex rate limits, Kiro usage breakdowns, Claude settings). |
+| `accountSelector.ts` | Smart account selection with scoring algorithm: considers priority, health status, round-robin position, and cooldown state to pick the optimal account for each request. |
+| `contextManager.ts` | Request context lifecycle management: creates and tracks per-request context objects with metadata (request ID, timestamps, provider info) for debugging and logging. |
+| `ipFilter.ts` | IP-based access control: supports allowlist and blocklist modes. Validates client IP against configured rules before processing API requests. |
+| `sessionManager.ts` | Session tracking with client fingerprinting: tracks active sessions using hashed client identifiers, monitors request counts, and provides session metrics. |
+| `signatureCache.ts` | Request signature-based deduplication cache: prevents duplicate requests by caching recent request signatures and returning cached responses for identical requests within a time window. |
+| `systemPrompt.ts` | Global system prompt injection: prepends or appends a configurable system prompt to all requests, with per-provider compatibility handling. |
+| `thinkingBudget.ts` | Reasoning token budget management: supports passthrough, auto (strip thinking config), custom (fixed budget), and adaptive (complexity-scaled) modes for controlling thinking/reasoning tokens. |
+| `wildcardRouter.ts` | Wildcard model pattern routing: resolves wildcard patterns (e.g., `*/claude-*`) to concrete provider/model pairs based on availability and priority. |
+
+#### Token Refresh Deduplication
+
+```mermaid
+sequenceDiagram
+ participant R1 as Request 1
+ participant R2 as Request 2
+ participant Cache as refreshPromiseCache
+ participant OAuth as OAuth Provider
+
+ R1->>Cache: getAccessToken("gemini", token)
+ Cache->>Cache: No in-flight promise
+ Cache->>OAuth: Start refresh
+ R2->>Cache: getAccessToken("gemini", token)
+ Cache->>Cache: Found in-flight promise
+ Cache-->>R2: Return existing promise
+ OAuth-->>Cache: New access token
+ Cache-->>R1: New access token
+ Cache-->>R2: Same access token (shared)
+ Cache->>Cache: Delete cache entry
+```
+
+#### Account Fallback State Machine
+
+```mermaid
+stateDiagram-v2
+ [*] --> Active
+ Active --> Error: Request fails (401/429/500)
+ Error --> Cooldown: Apply backoff
+ Cooldown --> Active: Cooldown expires
+ Active --> Active: Request succeeds (reset backoff)
+
+ state Error {
+ [*] --> ClassifyError
+ ClassifyError --> ShouldFallback: Rate limit / Auth / Transient
+ ClassifyError --> NoFallback: 400 Bad Request
+ }
+
+ state Cooldown {
+ [*] --> ExponentialBackoff
+ ExponentialBackoff: Level 0 = 1s
+ ExponentialBackoff: Level 1 = 2s
+ ExponentialBackoff: Level 2 = 4s
+ ExponentialBackoff: Max = 2min
+ }
+```
+
+#### Combo Model Chain
+
+```mermaid
+flowchart LR
+ A["Request with\ncombo model"] --> B["Model A"]
+ B -->|"2xx Success"| C["Return response"]
+ B -->|"429/401/500"| D{"Fallback\neligible?"}
+ D -->|Yes| E["Model B"]
+ D -->|No| F["Return error"]
+ E -->|"2xx Success"| C
+ E -->|"429/401/500"| G{"Fallback\neligible?"}
+ G -->|Yes| H["Model C"]
+ G -->|No| F
+ H -->|"2xx Success"| C
+ H -->|"Fail"| I["All failed →\nReturn last status"]
+```
+
+---
+
+### 4.5 Translator (`open-sse/translator/`)
+
+The **format translation engine** using a self-registering plugin system.
+
+#### Arkkitehtuuri
+
+```mermaid
+graph TD
+ subgraph "Request Translation"
+ A["Claude → OpenAI"]
+ B["Gemini → OpenAI"]
+ C["Antigravity → OpenAI"]
+ D["OpenAI Responses → OpenAI"]
+ E["OpenAI → Claude"]
+ F["OpenAI → Gemini"]
+ G["OpenAI → Kiro"]
+ H["OpenAI → Cursor"]
+ end
+
+ subgraph "Response Translation"
+ I["Claude → OpenAI"]
+ J["Gemini → OpenAI"]
+ K["Kiro → OpenAI"]
+ L["Cursor → OpenAI"]
+ M["OpenAI → Claude"]
+ N["OpenAI → Antigravity"]
+ O["OpenAI → Responses"]
+ end
+```
+
+| Directory | Files | Description |
+| ------------ | ------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| `request/` | 8 translators | Convert request bodies between formats. Each file self-registers via `register(from, to, fn)` on import. |
+| `response/` | 7 translators | Convert streaming response chunks between formats. Handles SSE event types, thinking blocks, tool calls. |
+| `helpers/` | 6 helpers | Shared utilities: `claudeHelper` (system prompt extraction, thinking config), `geminiHelper` (parts/contents mapping), `openaiHelper` (format filtering), `toolCallHelper` (ID generation, missing response injection), `maxTokensHelper`, `responsesApiHelper`. |
+| `index.ts` | — | Translation engine: `translateRequest()`, `translateResponse()`, state management, registry. |
+| `formats.ts` | — | Format constants: `OPENAI`, `CLAUDE`, `GEMINI`, `ANTIGRAVITY`, `KIRO`, `CURSOR`, `OPENAI_RESPONSES`. |
+
+#### Key Design: Self-Registering Plugins
+
+```javascript
+// Each translator file calls register() on import:
+import { register } from "../index.js";
+register("claude", "openai", translateClaudeToOpenAI);
+
+// The index.js imports all translator files, triggering registration:
+import "./request/claude-to-openai.js"; // ← self-registers
+```
+
+---
+
+### 4.6 Utils (`open-sse/utils/`)
+
+| File | Purpose |
+| ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
+| `error.ts` | Error response building (OpenAI-compatible format), upstream error parsing, Antigravity retry-time extraction from error messages, SSE error streaming. |
+| `stream.ts` | **SSE Transform Stream** — the core streaming pipeline. Two modes: `TRANSLATE` (full format translation) and `PASSTHROUGH` (normalize + extract usage). Handles chunk buffering, usage estimation, content length tracking. Per-stream encoder/decoder instances avoid shared state. |
+| `streamHelpers.ts` | Low-level SSE utilities: `parseSSELine` (whitespace-tolerant), `hasValuableContent` (filters empty chunks for OpenAI/Claude/Gemini), `fixInvalidId`, `formatSSE` (format-aware SSE serialization with `perf_metrics` cleanup). |
+| `usageTracking.ts` | Token usage extraction from any format (Claude/OpenAI/Gemini/Responses), estimation with separate tool/message char-per-token ratios, buffer addition (2000 tokens safety margin), format-specific field filtering, console logging with ANSI colors. |
+| `requestLogger.ts` | File-based request logging (opt-in via `ENABLE_REQUEST_LOGS=true`). Creates session folders with numbered files: `1_req_client.json` → `7_res_client.txt`. All I/O is async (fire-and-forget). Masks sensitive headers. |
+| `bypassHandler.ts` | Intercepts specific patterns from Claude CLI (title extraction, warmup, count) and returns fake responses without calling any provider. Supports both streaming and non-streaming. Intentionally limited to Claude CLI scope. |
+| `networkProxy.ts` | Resolves outbound proxy URL for a given provider with precedence: provider-specific config → global config → environment variables (`HTTPS_PROXY`/`HTTP_PROXY`/`ALL_PROXY`). Supports `NO_PROXY` exclusions. Caches config for 30s. |
+
+#### SSE Streaming Pipeline
+
+```mermaid
+flowchart TD
+ A["Provider SSE stream"] --> B["TextDecoder\n(per-stream instance)"]
+ B --> C["Buffer lines\n(split on newline)"]
+ C --> D["parseSSELine()\n(trim whitespace, parse JSON)"]
+ D --> E{"Mode?"}
+ E -->|TRANSLATE| F["translateResponse()\ntarget → OpenAI → source"]
+ E -->|PASSTHROUGH| G["fixInvalidId()\nnormalize chunk"]
+ F --> H["hasValuableContent()\nfilter empty chunks"]
+ G --> H
+ H -->|"Has content"| I["extractUsage()\ntrack token counts"]
+ H -->|"Empty"| J["Skip chunk"]
+ I --> K["formatSSE()\nserialize + clean perf_metrics"]
+ K --> L["TextEncoder\n(per-stream instance)"]
+ L --> M["Enqueue to\nclient stream"]
+
+ style A fill:#f9f,stroke:#333
+ style M fill:#9f9,stroke:#333
+```
+
+#### Request Logger Session Structure
+
+```
+logs/
+└── claude_gemini_claude-sonnet_20260208_143045/
+ ├── 1_req_client.json ← Raw client request
+ ├── 2_req_source.json ← After initial conversion
+ ├── 3_req_openai.json ← OpenAI intermediate format
+ ├── 4_req_target.json ← Final target format
+ ├── 5_res_provider.txt ← Provider SSE chunks (streaming)
+ ├── 5_res_provider.json ← Provider response (non-streaming)
+ ├── 6_res_openai.txt ← OpenAI intermediate chunks
+ ├── 7_res_client.txt ← Client-facing SSE chunks
+ └── 6_error.json ← Error details (if any)
+```
+
+---
+
+### 4.7 Application Layer (`src/`)
+
+| Directory | Purpose |
+| ------------- | ---------------------------------------------------------------------- |
+| `src/app/` | Web UI, API routes, Express middleware, OAuth callback handlers |
+| `src/lib/` | Database access (`localDb.ts`, `usageDb.ts`), authentication, shared |
+| `src/mitm/` | Man-in-the-middle proxy utilities for intercepting provider traffic |
+| `src/models/` | Database model definitions |
+| `src/shared/` | Wrappers around open-sse functions (provider, stream, error, etc.) |
+| `src/sse/` | SSE endpoint handlers that wire the open-sse library to Express routes |
+| `src/store/` | Application state management |
+
+#### Notable API Routes
+
+| Route | Methods | Purpose |
+| --------------------------------------------- | --------------- | ------------------------------------------------------------------------------------- |
+| `/api/provider-models` | GET/POST/DELETE | CRUD for custom models per provider |
+| `/api/models/catalog` | GET | Aggregated catalog of all models (chat, embedding, image, custom) grouped by provider |
+| `/api/settings/proxy` | GET/PUT/DELETE | Hierarchical outbound proxy configuration (`global/providers/combos/keys`) |
+| `/api/settings/proxy/test` | POST | Validates proxy connectivity and returns public IP/latency |
+| `/v1/providers/[provider]/chat/completions` | POST | Dedicated per-provider chat completions with model validation |
+| `/v1/providers/[provider]/embeddings` | POST | Dedicated per-provider embeddings with model validation |
+| `/v1/providers/[provider]/images/generations` | POST | Dedicated per-provider image generation with model validation |
+| `/api/settings/ip-filter` | GET/PUT | IP allowlist/blocklist management |
+| `/api/settings/thinking-budget` | GET/PUT | Reasoning token budget configuration (passthrough/auto/custom/adaptive) |
+| `/api/settings/system-prompt` | GET/PUT | Global system prompt injection for all requests |
+| `/api/sessions` | GET | Active session tracking and metrics |
+| `/api/rate-limits` | GET | Per-account rate limit status |
+
+---
+
+## 5. Key Design Patterns
+
+### 5.1 Hub-and-Spoke Translation
+
+All formats translate through **OpenAI format as the hub**. Adding a new provider only requires writing **one pair** of translators (to/from OpenAI), not N pairs.
+
+### 5.2 Executor Strategy Pattern
+
+Each provider has a dedicated executor class inheriting from `BaseExecutor`. The factory in `executors/index.ts` selects the right one at runtime.
+
+### 5.3 Self-Registering Plugin System
+
+Translator modules register themselves on import via `register()`. Adding a new translator is just creating a file and importing it.
+
+### 5.4 Account Fallback with Exponential Backoff
+
+When a provider returns 429/401/500, the system can switch to the next account, applying exponential cooldowns (1s → 2s → 4s → max 2min).
+
+### 5.5 Combo Model Chains
+
+A "combo" groups multiple `provider/model` strings. If the first fails, fallback to the next automatically.
+
+### 5.6 Stateful Streaming Translation
+
+Response translation maintains state across SSE chunks (thinking block tracking, tool call accumulation, content block indexing) via the `initState()` mechanism.
+
+### 5.7 Usage Safety Buffer
+
+A 2000-token buffer is added to reported usage to prevent clients from hitting context window limits due to overhead from system prompts and format translation.
+
+---
+
+## 6. Supported Formats
+
+| Format | Direction | Identifier |
+| ----------------------- | --------------- | ------------------ |
+| OpenAI Chat Completions | source + target | `openai` |
+| OpenAI Responses API | source + target | `openai-responses` |
+| Anthropic Claude | source + target | `claude` |
+| Google Gemini | source + target | `gemini` |
+| Google Gemini CLI | target only | `gemini-cli` |
+| Antigravity | source + target | `antigravity` |
+| AWS Kiro | target only | `kiro` |
+| Cursor | target only | `cursor` |
+
+---
+
+## 7. Supported Providers
+
+| Provider | Auth Method | Executor | Key Notes |
+| ------------------------ | ---------------------- | ----------- | --------------------------------------------- |
+| Anthropic Claude | API key or OAuth | Default | Uses `x-api-key` header |
+| Google Gemini | API key or OAuth | Default | Uses `x-goog-api-key` header |
+| Google Gemini CLI | OAuth | GeminiCLI | Uses `streamGenerateContent` endpoint |
+| Antigravity | OAuth | Antigravity | Multi-URL fallback, custom retry parsing |
+| OpenAI | API key | Default | Standard Bearer auth |
+| Codex | OAuth | Codex | Injects system instructions, manages thinking |
+| GitHub Copilot | OAuth + Copilot token | Github | Dual token, VSCode header mimicking |
+| Kiro (AWS) | AWS SSO OIDC or Social | Kiro | Binary EventStream parsing |
+| Cursor IDE | Checksum auth | Cursor | Protobuf encoding, SHA-256 checksums |
+| Qwen | OAuth | Default | Standard auth |
+| Qoder | OAuth (Basic + Bearer) | Default | Dual auth header |
+| OpenRouter | API key | Default | Standard Bearer auth |
+| GLM, Kimi, MiniMax | API key | Default | Claude-compatible, use `x-api-key` |
+| `openai-compatible-*` | API key | Default | Dynamic: any OpenAI-compatible endpoint |
+| `anthropic-compatible-*` | API key | Default | Dynamic: any Claude-compatible endpoint |
+
+---
+
+## 8. Data Flow Summary
+
+### Streaming Request
+
+```mermaid
+flowchart LR
+ A["Client"] --> B["detectFormat()"]
+ B --> C["translateRequest()\nsource → OpenAI → target"]
+ C --> D["Executor\nbuildUrl + buildHeaders"]
+ D --> E["fetch(providerURL)"]
+ E --> F["createSSEStream()\nTRANSLATE mode"]
+ F --> G["parseSSELine()"]
+ G --> H["translateResponse()\ntarget → OpenAI → source"]
+ H --> I["extractUsage()\n+ addBuffer"]
+ I --> J["formatSSE()"]
+ J --> K["Client receives\ntranslated SSE"]
+ K --> L["logUsage()\nsaveRequestUsage()"]
+```
+
+### Non-Streaming Request
+
+```mermaid
+flowchart LR
+ A["Client"] --> B["detectFormat()"]
+ B --> C["translateRequest()\nsource → OpenAI → target"]
+ C --> D["Executor.execute()"]
+ D --> E["translateResponse()\ntarget → OpenAI → source"]
+ E --> F["Return JSON\nresponse"]
+```
+
+### Bypass Flow (Claude CLI)
+
+```mermaid
+flowchart LR
+ A["Claude CLI request"] --> B{"Match bypass\npattern?"}
+ B -->|"Title/Warmup/Count"| C["Generate fake\nOpenAI response"]
+ B -->|"No match"| D["Normal flow"]
+ C --> E["Translate to\nsource format"]
+ E --> F["Return without\ncalling provider"]
+```
diff --git a/docs/i18n/fi/docs/COVERAGE_PLAN.md b/docs/i18n/fi/docs/COVERAGE_PLAN.md
new file mode 100644
index 0000000000..0cdd6d4213
--- /dev/null
+++ b/docs/i18n/fi/docs/COVERAGE_PLAN.md
@@ -0,0 +1,170 @@
+# Test Coverage Plan (Suomi)
+
+🌐 **Languages:** 🇺🇸 [English](../../../../docs/COVERAGE_PLAN.md) · 🇪🇸 [es](../../es/docs/COVERAGE_PLAN.md) · 🇫🇷 [fr](../../fr/docs/COVERAGE_PLAN.md) · 🇩🇪 [de](../../de/docs/COVERAGE_PLAN.md) · 🇮🇹 [it](../../it/docs/COVERAGE_PLAN.md) · 🇷🇺 [ru](../../ru/docs/COVERAGE_PLAN.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/COVERAGE_PLAN.md) · 🇯🇵 [ja](../../ja/docs/COVERAGE_PLAN.md) · 🇰🇷 [ko](../../ko/docs/COVERAGE_PLAN.md) · 🇸🇦 [ar](../../ar/docs/COVERAGE_PLAN.md) · 🇮🇳 [in](../../in/docs/COVERAGE_PLAN.md) · 🇹🇭 [th](../../th/docs/COVERAGE_PLAN.md) · 🇻🇳 [vi](../../vi/docs/COVERAGE_PLAN.md) · 🇮🇩 [id](../../id/docs/COVERAGE_PLAN.md) · 🇲🇾 [ms](../../ms/docs/COVERAGE_PLAN.md) · 🇳🇱 [nl](../../nl/docs/COVERAGE_PLAN.md) · 🇵🇱 [pl](../../pl/docs/COVERAGE_PLAN.md) · 🇸🇪 [sv](../../sv/docs/COVERAGE_PLAN.md) · 🇳🇴 [no](../../no/docs/COVERAGE_PLAN.md) · 🇩🇰 [da](../../da/docs/COVERAGE_PLAN.md) · 🇫🇮 [fi](../../fi/docs/COVERAGE_PLAN.md) · 🇵🇹 [pt](../../pt/docs/COVERAGE_PLAN.md) · 🇷🇴 [ro](../../ro/docs/COVERAGE_PLAN.md) · 🇭🇺 [hu](../../hu/docs/COVERAGE_PLAN.md) · 🇧🇬 [bg](../../bg/docs/COVERAGE_PLAN.md) · 🇸🇰 [sk](../../sk/docs/COVERAGE_PLAN.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/COVERAGE_PLAN.md) · 🇮🇱 [he](../../he/docs/COVERAGE_PLAN.md) · 🇵🇭 [phi](../../phi/docs/COVERAGE_PLAN.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/COVERAGE_PLAN.md) · 🇨🇿 [cs](../../cs/docs/COVERAGE_PLAN.md)
+
+---
+
+Last updated: 2026-03-28
+
+## Baseline
+
+There are multiple coverage numbers depending on how the report is computed. For planning, only one of them is useful.
+
+| Metric | Scope | Statements / Lines | Branches | Functions | Notes |
+| -------------------- | ----------------------------------------------------- | -----------------: | -------: | --------: | --------------------------------------------------- |
+| Legacy | Old `npm run test:coverage` | 79.42% | 75.15% | 67.94% | Inflated: counts test files and excludes `open-sse` |
+| Diagnostic | Source-only, excluding tests and excluding `open-sse` | 68.16% | 63.55% | 64.06% | Useful only to isolate `src/**` |
+| Recommended baseline | Source-only, excluding tests and including `open-sse` | 56.95% | 66.05% | 57.80% | This is the project-wide baseline to improve |
+
+The recommended baseline is the number to optimize against.
+
+## Rules
+
+- Coverage targets apply to source files, not to `tests/**`.
+- `open-sse/**` is part of the product and must remain in scope.
+- New code should not reduce coverage in touched areas.
+- Prefer testing behavior and branch outcomes over implementation details.
+- Prefer temp SQLite databases and small fixtures over broad mocks for `src/lib/db/**`.
+
+## Current command set
+
+- `npm run test:coverage`
+ - Main source coverage gate for the unit test suite
+ - Generates `text-summary`, `html`, `json-summary`, and `lcov`
+- `npm run coverage:report`
+ - Detailed file-by-file report from the latest run
+- `npm run test:coverage:legacy`
+ - Historical comparison only
+
+## Milestones
+
+| Phase | Target | Focus |
+| ------- | ---------------------: | ------------------------------------------------- |
+| Phase 1 | 60% statements / lines | Quick wins and low-risk utility coverage |
+| Phase 2 | 65% statements / lines | DB and route foundations |
+| Phase 3 | 70% statements / lines | Provider validation and usage analytics |
+| Phase 4 | 75% statements / lines | `open-sse` translators and helpers |
+| Phase 5 | 80% statements / lines | `open-sse` handlers and executor branches |
+| Phase 6 | 85% statements / lines | Harder edge cases, branch debt, regression suites |
+| Phase 7 | 90% statements / lines | Final sweep, gap closure, strict ratchet |
+
+Branches and functions should ratchet upward with each phase, but the primary hard target is statements / lines.
+
+## Priority hotspots
+
+These files or areas offer the best return for the next phases:
+
+1. `open-sse/handlers`
+ - `chatCore.ts` at 7.57%
+ - Overall directory at 29.07%
+2. `open-sse/translator/request`
+ - Overall directory at 36.39%
+ - Many translators are still near single-digit coverage
+3. `open-sse/translator/response`
+ - Overall directory at 8.07%
+4. `open-sse/executors`
+ - Overall directory at 36.62%
+5. `src/lib/db`
+ - `models.ts` at 20.66%
+ - `registeredKeys.ts` at 34.46%
+ - `modelComboMappings.ts` at 36.25%
+ - `settings.ts` at 46.40%
+ - `webhooks.ts` at 33.33%
+6. `src/lib/usage`
+ - `usageHistory.ts` at 21.12%
+ - `usageStats.ts` at 9.56%
+ - `costCalculator.ts` at 30.00%
+7. `src/lib/providers`
+ - `validation.ts` at 41.16%
+8. Low-risk utility and API files for early gains
+ - `src/shared/utils/upstreamError.ts`
+ - `src/shared/utils/apiAuth.ts`
+ - `src/lib/api/errorResponse.ts`
+ - `src/app/api/settings/require-login/route.ts`
+ - `src/app/api/providers/[id]/models/route.ts`
+
+## Execution checklist
+
+### Phase 1: 56.95% -> 60%
+
+- [x] Fix coverage metric so it reflects source code instead of test files
+- [x] Keep a legacy coverage script for comparison
+- [x] Record the baseline and hotspots in-repo
+- [ ] Add focused tests for low-risk utilities:
+ - `src/shared/utils/upstreamError.ts`
+ - `src/shared/utils/fetchTimeout.ts`
+ - `src/lib/api/errorResponse.ts`
+ - `src/shared/utils/apiAuth.ts`
+ - `src/lib/display/names.ts`
+- [ ] Add route tests for:
+ - `src/app/api/settings/require-login/route.ts`
+ - `src/app/api/providers/[id]/models/route.ts`
+
+### Phase 2: 60% -> 65%
+
+- [ ] Add DB-backed tests for:
+ - `src/lib/db/modelComboMappings.ts`
+ - `src/lib/db/settings.ts`
+ - `src/lib/db/registeredKeys.ts`
+- [ ] Cover branch behavior in:
+ - `src/lib/providers/validation.ts`
+ - `src/app/api/v1/embeddings/route.ts`
+ - `src/app/api/v1/moderations/route.ts`
+
+### Phase 3: 65% -> 70%
+
+- [ ] Add usage analytics tests for:
+ - `src/lib/usage/usageHistory.ts`
+ - `src/lib/usage/usageStats.ts`
+ - `src/lib/usage/costCalculator.ts`
+- [ ] Expand route coverage for proxy management and settings branches
+
+### Phase 4: 70% -> 75%
+
+- [ ] Cover translator helpers and central translation paths:
+ - `open-sse/translator/index.ts`
+ - `open-sse/translator/helpers/*`
+ - `open-sse/translator/request/*`
+ - `open-sse/translator/response/*`
+
+### Phase 5: 75% -> 80%
+
+- [ ] Add handler-level tests for:
+ - `open-sse/handlers/chatCore.ts`
+ - `open-sse/handlers/responsesHandler.js`
+ - `open-sse/handlers/imageGeneration.js`
+ - `open-sse/handlers/embeddings.js`
+- [ ] Add executor branch coverage for provider-specific auth, retries, and endpoint overrides
+
+### Phase 6: 80% -> 85%
+
+- [ ] Merge more edge-case suites into the main coverage path
+- [ ] Increase function coverage for DB modules with weak constructor/helper coverage
+- [ ] Close branch gaps in `settings.ts`, `registeredKeys.ts`, `validation.ts`, and translator helpers
+
+### Phase 7: 85% -> 90%
+
+- [ ] Treat the remaining low-coverage files as blockers
+- [ ] Add regression tests for every uncovered production bug fixed during the push to 90%
+- [ ] Raise the coverage gate in CI only after the local baseline is stable for at least two consecutive runs
+
+## Ratchet policy
+
+Update `npm run test:coverage` thresholds only after the project actually exceeds the next milestone with a comfortable buffer.
+
+Recommended ratchet sequence:
+
+1. 55/60/55
+2. 60/62/58
+3. 65/64/62
+4. 70/66/66
+5. 75/70/72
+6. 80/75/78
+7. 85/80/84
+8. 90/85/88
+
+Order is `statements-lines / branches / functions`.
+
+## Known gap
+
+The current coverage command measures the main Node unit suite and includes source reached from it, including `open-sse`. It does not yet merge Vitest coverage into a single unified report. That merge is worth doing later, but it is not a blocker for starting the 60% -> 80% climb.
diff --git a/docs/i18n/fi/docs/FEATURES.md b/docs/i18n/fi/docs/FEATURES.md
index 1acc4488ff..6d6dcbbd73 100644
--- a/docs/i18n/fi/docs/FEATURES.md
+++ b/docs/i18n/fi/docs/FEATURES.md
@@ -1,6 +1,6 @@
# OmniRoute — Dashboard Features Gallery (Suomi)
-🌐 **Languages:** 🇺🇸 [English](../../../../docs/FEATURES.md) · 🇪🇸 [es](../../es/docs/FEATURES.md) · 🇫🇷 [fr](../../fr/docs/FEATURES.md) · 🇩🇪 [de](../../de/docs/FEATURES.md) · 🇮🇹 [it](../../it/docs/FEATURES.md) · 🇷🇺 [ru](../../ru/docs/FEATURES.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/FEATURES.md) · 🇯🇵 [ja](../../ja/docs/FEATURES.md) · 🇰🇷 [ko](../../ko/docs/FEATURES.md) · 🇸🇦 [ar](../../ar/docs/FEATURES.md) · 🇮🇳 [in](../../in/docs/FEATURES.md) · 🇹🇭 [th](../../th/docs/FEATURES.md) · 🇻🇳 [vi](../../vi/docs/FEATURES.md) · 🇮🇩 [id](../../id/docs/FEATURES.md) · 🇲🇾 [ms](../../ms/docs/FEATURES.md) · 🇳🇱 [nl](../../nl/docs/FEATURES.md) · 🇵🇱 [pl](../../pl/docs/FEATURES.md) · 🇸🇪 [sv](../../sv/docs/FEATURES.md) · 🇳🇴 [no](../../no/docs/FEATURES.md) · 🇩🇰 [da](../../da/docs/FEATURES.md) · 🇫🇮 [fi](../../fi/docs/FEATURES.md) · 🇵🇹 [pt](../../pt/docs/FEATURES.md) · 🇷🇴 [ro](../../ro/docs/FEATURES.md) · 🇭🇺 [hu](../../hu/docs/FEATURES.md) · 🇧🇬 [bg](../../bg/docs/FEATURES.md) · 🇸🇰 [sk](../../sk/docs/FEATURES.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/FEATURES.md) · 🇮🇱 [he](../../he/docs/FEATURES.md) · 🇵🇭 [phi](../../phi/docs/FEATURES.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/FEATURES.md)
+🌐 **Languages:** 🇺🇸 [English](../../../../docs/FEATURES.md) · 🇪🇸 [es](../../es/docs/FEATURES.md) · 🇫🇷 [fr](../../fr/docs/FEATURES.md) · 🇩🇪 [de](../../de/docs/FEATURES.md) · 🇮🇹 [it](../../it/docs/FEATURES.md) · 🇷🇺 [ru](../../ru/docs/FEATURES.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/FEATURES.md) · 🇯🇵 [ja](../../ja/docs/FEATURES.md) · 🇰🇷 [ko](../../ko/docs/FEATURES.md) · 🇸🇦 [ar](../../ar/docs/FEATURES.md) · 🇮🇳 [in](../../in/docs/FEATURES.md) · 🇹🇭 [th](../../th/docs/FEATURES.md) · 🇻🇳 [vi](../../vi/docs/FEATURES.md) · 🇮🇩 [id](../../id/docs/FEATURES.md) · 🇲🇾 [ms](../../ms/docs/FEATURES.md) · 🇳🇱 [nl](../../nl/docs/FEATURES.md) · 🇵🇱 [pl](../../pl/docs/FEATURES.md) · 🇸🇪 [sv](../../sv/docs/FEATURES.md) · 🇳🇴 [no](../../no/docs/FEATURES.md) · 🇩🇰 [da](../../da/docs/FEATURES.md) · 🇫🇮 [fi](../../fi/docs/FEATURES.md) · 🇵🇹 [pt](../../pt/docs/FEATURES.md) · 🇷🇴 [ro](../../ro/docs/FEATURES.md) · 🇭🇺 [hu](../../hu/docs/FEATURES.md) · 🇧🇬 [bg](../../bg/docs/FEATURES.md) · 🇸🇰 [sk](../../sk/docs/FEATURES.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/FEATURES.md) · 🇮🇱 [he](../../he/docs/FEATURES.md) · 🇵🇭 [phi](../../phi/docs/FEATURES.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/FEATURES.md) · 🇨🇿 [cs](../../cs/docs/FEATURES.md)
---
@@ -10,7 +10,7 @@ Visual guide to every section of the OmniRoute dashboard.
## 🔌 Providers
-Manage AI provider connections: OAuth providers (Claude Code, Codex, Gemini CLI), API key providers (Groq, DeepSeek, OpenRouter), and free providers (iFlow, Qwen, Kiro). Kiro accounts include credit balance tracking — remaining credits, total allowance, and renewal date visible in Dashboard → Usage.
+Manage AI provider connections: OAuth providers (Claude Code, Codex, Gemini CLI), API key providers (Groq, DeepSeek, OpenRouter), and free providers (Qoder, Qwen, Kiro). Kiro accounts include credit balance tracking — remaining credits, total allowance, and renewal date visible in Dashboard → Usage.

diff --git a/docs/i18n/ar/MCP-SERVER.md b/docs/i18n/fi/docs/MCP-SERVER.md
similarity index 65%
rename from docs/i18n/ar/MCP-SERVER.md
rename to docs/i18n/fi/docs/MCP-SERVER.md
index 829acd30b1..d2c249eb8d 100644
--- a/docs/i18n/ar/MCP-SERVER.md
+++ b/docs/i18n/fi/docs/MCP-SERVER.md
@@ -1,12 +1,12 @@
-🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/MCP-SERVER.md) · 🇪🇸 [es](../es/MCP-SERVER.md) · 🇫🇷 [fr](../fr/MCP-SERVER.md) · 🇩🇪 [de](../de/MCP-SERVER.md) · 🇮🇹 [it](../it/MCP-SERVER.md) · 🇷🇺 [ru](../ru/MCP-SERVER.md) · 🇨🇳 [zh-CN](../zh-CN/MCP-SERVER.md) · 🇯🇵 [ja](../ja/MCP-SERVER.md) · 🇰🇷 [ko](../ko/MCP-SERVER.md) · 🇸🇦 [ar](../ar/MCP-SERVER.md) · 🇮🇳 [in](../in/MCP-SERVER.md) · 🇹🇭 [th](../th/MCP-SERVER.md) · 🇻🇳 [vi](../vi/MCP-SERVER.md) · 🇮🇩 [id](../id/MCP-SERVER.md) · 🇲🇾 [ms](../ms/MCP-SERVER.md) · 🇳🇱 [nl](../nl/MCP-SERVER.md) · 🇵🇱 [pl](../pl/MCP-SERVER.md) · 🇸🇪 [sv](../sv/MCP-SERVER.md) · 🇳🇴 [no](../no/MCP-SERVER.md) · 🇩🇰 [da](../da/MCP-SERVER.md) · 🇫🇮 [fi](../fi/MCP-SERVER.md) · 🇵🇹 [pt](../pt/MCP-SERVER.md) · 🇷🇴 [ro](../ro/MCP-SERVER.md) · 🇭🇺 [hu](../hu/MCP-SERVER.md) · 🇧🇬 [bg](../bg/MCP-SERVER.md) · 🇸🇰 [sk](../sk/MCP-SERVER.md) · 🇺🇦 [uk-UA](../uk-UA/MCP-SERVER.md) · 🇮🇱 [he](../he/MCP-SERVER.md) · 🇵🇭 [phi](../phi/MCP-SERVER.md)
+# OmniRoute MCP Server Documentation (Suomi)
+
+🌐 **Languages:** 🇺🇸 [English](../../../../docs/MCP-SERVER.md) · 🇪🇸 [es](../../es/docs/MCP-SERVER.md) · 🇫🇷 [fr](../../fr/docs/MCP-SERVER.md) · 🇩🇪 [de](../../de/docs/MCP-SERVER.md) · 🇮🇹 [it](../../it/docs/MCP-SERVER.md) · 🇷🇺 [ru](../../ru/docs/MCP-SERVER.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/MCP-SERVER.md) · 🇯🇵 [ja](../../ja/docs/MCP-SERVER.md) · 🇰🇷 [ko](../../ko/docs/MCP-SERVER.md) · 🇸🇦 [ar](../../ar/docs/MCP-SERVER.md) · 🇮🇳 [in](../../in/docs/MCP-SERVER.md) · 🇹🇭 [th](../../th/docs/MCP-SERVER.md) · 🇻🇳 [vi](../../vi/docs/MCP-SERVER.md) · 🇮🇩 [id](../../id/docs/MCP-SERVER.md) · 🇲🇾 [ms](../../ms/docs/MCP-SERVER.md) · 🇳🇱 [nl](../../nl/docs/MCP-SERVER.md) · 🇵🇱 [pl](../../pl/docs/MCP-SERVER.md) · 🇸🇪 [sv](../../sv/docs/MCP-SERVER.md) · 🇳🇴 [no](../../no/docs/MCP-SERVER.md) · 🇩🇰 [da](../../da/docs/MCP-SERVER.md) · 🇫🇮 [fi](../../fi/docs/MCP-SERVER.md) · 🇵🇹 [pt](../../pt/docs/MCP-SERVER.md) · 🇷🇴 [ro](../../ro/docs/MCP-SERVER.md) · 🇭🇺 [hu](../../hu/docs/MCP-SERVER.md) · 🇧🇬 [bg](../../bg/docs/MCP-SERVER.md) · 🇸🇰 [sk](../../sk/docs/MCP-SERVER.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/MCP-SERVER.md) · 🇮🇱 [he](../../he/docs/MCP-SERVER.md) · 🇵🇭 [phi](../../phi/docs/MCP-SERVER.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/MCP-SERVER.md) · 🇨🇿 [cs](../../cs/docs/MCP-SERVER.md)
---
-# OmniRoute MCP Server Documentation
-
> Model Context Protocol server with 16 intelligent tools
-## Installation
+## Asenna
OmniRoute MCP is built-in. Start it with:
@@ -42,16 +42,16 @@ See [IDE Configs](integrations/ide-configs.md) for Antigravity, Cursor, Copilot,
## Advanced Tools (8)
-| Tool | Description |
-| :--------------------------------- | :---------------------------------------------- |
-| `omniroute_simulate_route` | Dry-run routing simulation with fallback tree |
-| `omniroute_set_budget_guard` | Session budget with degrade/block/alert actions |
-| `omniroute_set_resilience_profile` | Apply conservative/balanced/aggressive preset |
-| `omniroute_test_combo` | Live-test all models in a combo |
-| `omniroute_get_provider_metrics` | Detailed metrics for one provider |
-| `omniroute_best_combo_for_task` | Task-fitness recommendation with alternatives |
-| `omniroute_explain_route` | Explain a past routing decision |
-| `omniroute_get_session_snapshot` | Full session state: costs, tokens, errors |
+| Tool | Description |
+| :--------------------------------- | :---------------------------------------------------------- |
+| `omniroute_simulate_route` | Dry-run routing simulation with fallback tree |
+| `omniroute_set_budget_guard` | Session budget with degrade/block/alert actions |
+| `omniroute_set_resilience_profile` | Apply conservative/balanced/aggressive preset |
+| `omniroute_test_combo` | Live-test all models in a combo via a real upstream request |
+| `omniroute_get_provider_metrics` | Detailed metrics for one provider |
+| `omniroute_best_combo_for_task` | Task-fitness recommendation with alternatives |
+| `omniroute_explain_route` | Explain a past routing decision |
+| `omniroute_get_session_snapshot` | Full session state: costs, tokens, errors |
## Authentication
diff --git a/docs/i18n/fi/docs/RELEASE_CHECKLIST.md b/docs/i18n/fi/docs/RELEASE_CHECKLIST.md
new file mode 100644
index 0000000000..2001c28287
--- /dev/null
+++ b/docs/i18n/fi/docs/RELEASE_CHECKLIST.md
@@ -0,0 +1,37 @@
+# Release Checklist (Suomi)
+
+🌐 **Languages:** 🇺🇸 [English](../../../../docs/RELEASE_CHECKLIST.md) · 🇪🇸 [es](../../es/docs/RELEASE_CHECKLIST.md) · 🇫🇷 [fr](../../fr/docs/RELEASE_CHECKLIST.md) · 🇩🇪 [de](../../de/docs/RELEASE_CHECKLIST.md) · 🇮🇹 [it](../../it/docs/RELEASE_CHECKLIST.md) · 🇷🇺 [ru](../../ru/docs/RELEASE_CHECKLIST.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/RELEASE_CHECKLIST.md) · 🇯🇵 [ja](../../ja/docs/RELEASE_CHECKLIST.md) · 🇰🇷 [ko](../../ko/docs/RELEASE_CHECKLIST.md) · 🇸🇦 [ar](../../ar/docs/RELEASE_CHECKLIST.md) · 🇮🇳 [in](../../in/docs/RELEASE_CHECKLIST.md) · 🇹🇭 [th](../../th/docs/RELEASE_CHECKLIST.md) · 🇻🇳 [vi](../../vi/docs/RELEASE_CHECKLIST.md) · 🇮🇩 [id](../../id/docs/RELEASE_CHECKLIST.md) · 🇲🇾 [ms](../../ms/docs/RELEASE_CHECKLIST.md) · 🇳🇱 [nl](../../nl/docs/RELEASE_CHECKLIST.md) · 🇵🇱 [pl](../../pl/docs/RELEASE_CHECKLIST.md) · 🇸🇪 [sv](../../sv/docs/RELEASE_CHECKLIST.md) · 🇳🇴 [no](../../no/docs/RELEASE_CHECKLIST.md) · 🇩🇰 [da](../../da/docs/RELEASE_CHECKLIST.md) · 🇫🇮 [fi](../../fi/docs/RELEASE_CHECKLIST.md) · 🇵🇹 [pt](../../pt/docs/RELEASE_CHECKLIST.md) · 🇷🇴 [ro](../../ro/docs/RELEASE_CHECKLIST.md) · 🇭🇺 [hu](../../hu/docs/RELEASE_CHECKLIST.md) · 🇧🇬 [bg](../../bg/docs/RELEASE_CHECKLIST.md) · 🇸🇰 [sk](../../sk/docs/RELEASE_CHECKLIST.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/RELEASE_CHECKLIST.md) · 🇮🇱 [he](../../he/docs/RELEASE_CHECKLIST.md) · 🇵🇭 [phi](../../phi/docs/RELEASE_CHECKLIST.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/RELEASE_CHECKLIST.md) · 🇨🇿 [cs](../../cs/docs/RELEASE_CHECKLIST.md)
+
+---
+
+Use this checklist before tagging or publishing a new OmniRoute release.
+
+## Version and Changelog
+
+1. Bump `package.json` version (`x.y.z`) in the release branch.
+2. Move release notes from `## [Unreleased]` in `CHANGELOG.md` to a dated section:
+ - `## [x.y.z] — YYYY-MM-DD`
+3. Keep `## [Unreleased]` as the first changelog section for upcoming work.
+4. Ensure the latest semver section in `CHANGELOG.md` equals `package.json` version.
+
+## API Docs
+
+1. Update `docs/openapi.yaml`:
+ - `info.version` must equal `package.json` version.
+2. Validate endpoint examples if API contracts changed.
+
+## Runtime Docs
+
+1. Review `docs/ARCHITECTURE.md` for storage/runtime drift.
+2. Review `docs/TROUBLESHOOTING.md` for env var and operational drift.
+3. Update localized docs if source docs changed significantly.
+
+## Automated Check
+
+Run the sync guard locally before opening PR:
+
+```bash
+npm run check:docs-sync
+```
+
+CI also runs this check in `.github/workflows/ci.yml` (lint job).
diff --git a/docs/i18n/fi/docs/TROUBLESHOOTING.md b/docs/i18n/fi/docs/TROUBLESHOOTING.md
new file mode 100644
index 0000000000..696f624823
--- /dev/null
+++ b/docs/i18n/fi/docs/TROUBLESHOOTING.md
@@ -0,0 +1,256 @@
+# Troubleshooting (Suomi)
+
+🌐 **Languages:** 🇺🇸 [English](../../../../docs/TROUBLESHOOTING.md) · 🇪🇸 [es](../../es/docs/TROUBLESHOOTING.md) · 🇫🇷 [fr](../../fr/docs/TROUBLESHOOTING.md) · 🇩🇪 [de](../../de/docs/TROUBLESHOOTING.md) · 🇮🇹 [it](../../it/docs/TROUBLESHOOTING.md) · 🇷🇺 [ru](../../ru/docs/TROUBLESHOOTING.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/TROUBLESHOOTING.md) · 🇯🇵 [ja](../../ja/docs/TROUBLESHOOTING.md) · 🇰🇷 [ko](../../ko/docs/TROUBLESHOOTING.md) · 🇸🇦 [ar](../../ar/docs/TROUBLESHOOTING.md) · 🇮🇳 [in](../../in/docs/TROUBLESHOOTING.md) · 🇹🇭 [th](../../th/docs/TROUBLESHOOTING.md) · 🇻🇳 [vi](../../vi/docs/TROUBLESHOOTING.md) · 🇮🇩 [id](../../id/docs/TROUBLESHOOTING.md) · 🇲🇾 [ms](../../ms/docs/TROUBLESHOOTING.md) · 🇳🇱 [nl](../../nl/docs/TROUBLESHOOTING.md) · 🇵🇱 [pl](../../pl/docs/TROUBLESHOOTING.md) · 🇸🇪 [sv](../../sv/docs/TROUBLESHOOTING.md) · 🇳🇴 [no](../../no/docs/TROUBLESHOOTING.md) · 🇩🇰 [da](../../da/docs/TROUBLESHOOTING.md) · 🇫🇮 [fi](../../fi/docs/TROUBLESHOOTING.md) · 🇵🇹 [pt](../../pt/docs/TROUBLESHOOTING.md) · 🇷🇴 [ro](../../ro/docs/TROUBLESHOOTING.md) · 🇭🇺 [hu](../../hu/docs/TROUBLESHOOTING.md) · 🇧🇬 [bg](../../bg/docs/TROUBLESHOOTING.md) · 🇸🇰 [sk](../../sk/docs/TROUBLESHOOTING.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/TROUBLESHOOTING.md) · 🇮🇱 [he](../../he/docs/TROUBLESHOOTING.md) · 🇵🇭 [phi](../../phi/docs/TROUBLESHOOTING.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/TROUBLESHOOTING.md) · 🇨🇿 [cs](../../cs/docs/TROUBLESHOOTING.md)
+
+---
+
+Common problems and solutions for OmniRoute.
+
+---
+
+## Quick Fixes
+
+| Problem | Solution |
+| ----------------------------- | ------------------------------------------------------------------ |
+| First login not working | Set `INITIAL_PASSWORD` in `.env` (no hardcoded default) |
+| Dashboard opens on wrong port | Set `PORT=20128` and `NEXT_PUBLIC_BASE_URL=http://localhost:20128` |
+| No request logs under `logs/` | Set `ENABLE_REQUEST_LOGS=true` |
+| EACCES: permission denied | Set `DATA_DIR=/path/to/writable/dir` to override `~/.omniroute` |
+| Routing strategy not saving | Update to v1.4.11+ (Zod schema fix for settings persistence) |
+
+---
+
+## Provider Issues
+
+### "Language model did not provide messages"
+
+**Cause:** Provider quota exhausted.
+
+**Fix:**
+
+1. Check dashboard quota tracker
+2. Use a combo with fallback tiers
+3. Switch to cheaper/free tier
+
+### Rate Limiting
+
+**Cause:** Subscription quota exhausted.
+
+**Fix:**
+
+- Add fallback: `cc/claude-opus-4-6 → glm/glm-4.7 → if/kimi-k2-thinking`
+- Use GLM/MiniMax as cheap backup
+
+### OAuth Token Expired
+
+OmniRoute auto-refreshes tokens. If issues persist:
+
+1. Dashboard → Provider → Reconnect
+2. Delete and re-add the provider connection
+
+---
+
+## Cloud Issues
+
+### Cloud Sync Errors
+
+1. Verify `BASE_URL` points to your running instance (e.g., `http://localhost:20128`)
+2. Verify `CLOUD_URL` points to your cloud endpoint (e.g., `https://omniroute.dev`)
+3. Keep `NEXT_PUBLIC_*` values aligned with server-side values
+
+### Cloud `stream=false` Returns 500
+
+**Symptom:** `Unexpected token 'd'...` on cloud endpoint for non-streaming calls.
+
+**Cause:** Upstream returns SSE payload while client expects JSON.
+
+**Workaround:** Use `stream=true` for cloud direct calls. Local runtime includes SSE→JSON fallback.
+
+### Cloud Says Connected but "Invalid API key"
+
+1. Create a fresh key from local dashboard (`/api/keys`)
+2. Run cloud sync: Enable Cloud → Sync Now
+3. Old/non-synced keys can still return `401` on cloud
+
+---
+
+## Docker Issues
+
+### CLI Tool Shows Not Installed
+
+1. Check runtime fields: `curl http://localhost:20128/api/cli-tools/runtime/codex | jq`
+2. For portable mode: use image target `runner-cli` (bundled CLIs)
+3. For host mount mode: set `CLI_EXTRA_PATHS` and mount host bin directory as read-only
+4. If `installed=true` and `runnable=false`: binary was found but failed healthcheck
+
+### Quick Runtime Validation
+
+```bash
+curl -s http://localhost:20128/api/cli-tools/codex-settings | jq '{installed,runnable,commandPath,runtimeMode,reason}'
+curl -s http://localhost:20128/api/cli-tools/claude-settings | jq '{installed,runnable,commandPath,runtimeMode,reason}'
+curl -s http://localhost:20128/api/cli-tools/openclaw-settings | jq '{installed,runnable,commandPath,runtimeMode,reason}'
+```
+
+---
+
+## Cost Issues
+
+### High Costs
+
+1. Check usage stats in Dashboard → Usage
+2. Switch primary model to GLM/MiniMax
+3. Use free tier (Gemini CLI, Qoder) for non-critical tasks
+4. Set cost budgets per API key: Dashboard → API Keys → Budget
+
+---
+
+## Debugging
+
+### Enable Request Logs
+
+Set `ENABLE_REQUEST_LOGS=true` in your `.env` file. Logs appear under `logs/` directory.
+
+### Check Provider Health
+
+```bash
+# Health dashboard
+http://localhost:20128/dashboard/health
+
+# API health check
+curl http://localhost:20128/api/monitoring/health
+```
+
+### Runtime Storage
+
+- Main state: `${DATA_DIR}/storage.sqlite` (providers, combos, aliases, keys, settings)
+- Usage: SQLite tables in `storage.sqlite` (`usage_history`, `call_logs`, `proxy_logs`) + optional `${DATA_DIR}/log.txt` and `${DATA_DIR}/call_logs/`
+- Request logs: `/logs/...` (when `ENABLE_REQUEST_LOGS=true`)
+
+---
+
+## Circuit Breaker Issues
+
+### Provider stuck in OPEN state
+
+When a provider's circuit breaker is OPEN, requests are blocked until the cooldown expires.
+
+**Fix:**
+
+1. Go to **Dashboard → Settings → Resilience**
+2. Check the circuit breaker card for the affected provider
+3. Click **Reset All** to clear all breakers, or wait for the cooldown to expire
+4. Verify the provider is actually available before resetting
+
+### Provider keeps tripping the circuit breaker
+
+If a provider repeatedly enters OPEN state:
+
+1. Check **Dashboard → Health → Provider Health** for the failure pattern
+2. Go to **Settings → Resilience → Provider Profiles** and increase the failure threshold
+3. Check if the provider has changed API limits or requires re-authentication
+4. Review latency telemetry — high latency may cause timeout-based failures
+
+---
+
+## Audio Transcription Issues
+
+### "Unsupported model" error
+
+- Ensure you're using the correct prefix: `deepgram/nova-3` or `assemblyai/best`
+- Verify the provider is connected in **Dashboard → Providers**
+
+### Transcription returns empty or fails
+
+- Check supported audio formats: `mp3`, `wav`, `m4a`, `flac`, `ogg`, `webm`
+- Verify file size is within provider limits (typically < 25MB)
+- Check provider API key validity in the provider card
+
+---
+
+## Translator Debugging
+
+Use **Dashboard → Translator** to debug format translation issues:
+
+| Mode | When to Use |
+| ---------------- | -------------------------------------------------------------------------------------------- |
+| **Playground** | Compare input/output formats side by side — paste a failing request to see how it translates |
+| **Chat Tester** | Send live messages and inspect the full request/response payload including headers |
+| **Test Bench** | Run batch tests across format combinations to find which translations are broken |
+| **Live Monitor** | Watch real-time request flow to catch intermittent translation issues |
+
+### Common format issues
+
+- **Thinking tags not appearing** — Check if the target provider supports thinking and the thinking budget setting
+- **Tool calls dropping** — Some format translations may strip unsupported fields; verify in Playground mode
+- **System prompt missing** — Claude and Gemini handle system prompts differently; check translation output
+- **SDK returns raw string instead of object** — Fixed in v1.1.0: response sanitizer now strips non-standard fields (`x_groq`, `usage_breakdown`, etc.) that cause OpenAI SDK Pydantic validation failures
+- **GLM/ERNIE rejects `system` role** — Fixed in v1.1.0: role normalizer automatically merges system messages into user messages for incompatible models
+- **`developer` role not recognized** — Fixed in v1.1.0: automatically converted to `system` for non-OpenAI providers
+- **`json_schema` not working with Gemini** — Fixed in v1.1.0: `response_format` is now converted to Gemini's `responseMimeType` + `responseSchema`
+
+---
+
+## Resilience Settings
+
+### Auto rate-limit not triggering
+
+- Auto rate-limit only applies to API key providers (not OAuth/subscription)
+- Verify **Settings → Resilience → Provider Profiles** has auto-rate-limit enabled
+- Check if the provider returns `429` status codes or `Retry-After` headers
+
+### Tuning exponential backoff
+
+Provider profiles support these settings:
+
+- **Base delay** — Initial wait time after first failure (default: 1s)
+- **Max delay** — Maximum wait time cap (default: 30s)
+- **Multiplier** — How much to increase delay per consecutive failure (default: 2x)
+
+### Anti-thundering herd
+
+When many concurrent requests hit a rate-limited provider, OmniRoute uses mutex + auto rate-limiting to serialize requests and prevent cascading failures. This is automatic for API key providers.
+
+---
+
+## Optional RAG / LLM failure taxonomy (16 problems)
+
+Some OmniRoute users place the gateway in front of RAG or agent stacks. In those setups it is common to see a strange pattern: OmniRoute looks healthy (providers up, routing profiles ok, no rate limit alerts) but the final answer is still wrong.
+
+In practice these incidents usually come from the downstream RAG pipeline, not from the gateway itself.
+
+If you want a shared vocabulary to describe those failures you can use the WFGY ProblemMap, an external MIT license text resource that defines sixteen recurring RAG / LLM failure patterns. At a high level it covers:
+
+- retrieval drift and broken context boundaries
+- empty or stale indexes and vector stores
+- embedding versus semantic mismatch
+- prompt assembly and context window issues
+- logic collapse and overconfident answers
+- long chain and agent coordination failures
+- multi agent memory and role drift
+- deployment and bootstrap ordering problems
+
+The idea is simple:
+
+1. When you investigate a bad response, capture:
+ - user task and request
+ - route or provider combo in OmniRoute
+ - any RAG context used downstream (retrieved documents, tool calls, etc)
+2. Map the incident to one or two WFGY ProblemMap numbers (`No.1` … `No.16`).
+3. Store the number in your own dashboard, runbook, or incident tracker next to the OmniRoute logs.
+4. Use the corresponding WFGY page to decide whether you need to change your RAG stack, retriever, or routing strategy.
+
+Full text and concrete recipes live here (MIT license, text only):
+
+[WFGY ProblemMap README](https://github.com/onestardao/WFGY/blob/main/ProblemMap/README.md)
+
+You can ignore this section if you do not run RAG or agent pipelines behind OmniRoute.
+
+---
+
+## Still Stuck?
+
+- **GitHub Issues**: [github.com/diegosouzapw/OmniRoute/issues](https://github.com/diegosouzapw/OmniRoute/issues)
+- **Architecture**: See [`docs/ARCHITECTURE.md`](ARCHITECTURE.md) for internal details
+- **API Reference**: See [`docs/API_REFERENCE.md`](API_REFERENCE.md) for all endpoints
+- **Health Dashboard**: Check **Dashboard → Health** for real-time system status
+- **Translator**: Use **Dashboard → Translator** to debug format issues
diff --git a/docs/i18n/fi/USER_GUIDE.md b/docs/i18n/fi/docs/USER_GUIDE.md
similarity index 82%
rename from docs/i18n/fi/USER_GUIDE.md
rename to docs/i18n/fi/docs/USER_GUIDE.md
index 92bcd5e191..30508224f1 100644
--- a/docs/i18n/fi/USER_GUIDE.md
+++ b/docs/i18n/fi/docs/USER_GUIDE.md
@@ -1,8 +1,6 @@
# User Guide (Suomi)
-🌐 **Languages:** 🇺🇸 [English](../../USER_GUIDE.md) · 🇧🇷 [pt-BR](../pt-BR/USER_GUIDE.md) · 🇪🇸 [es](../es/USER_GUIDE.md) · 🇫🇷 [fr](../fr/USER_GUIDE.md) · 🇩🇪 [de](../de/USER_GUIDE.md) · 🇮🇹 [it](../it/USER_GUIDE.md) · 🇷🇺 [ru](../ru/USER_GUIDE.md) · 🇨🇳 [zh-CN](../zh-CN/USER_GUIDE.md) · 🇯🇵 [ja](../ja/USER_GUIDE.md) · 🇰🇷 [ko](../ko/USER_GUIDE.md) · 🇸🇦 [ar](../ar/USER_GUIDE.md) · 🇮🇳 [in](../in/USER_GUIDE.md) · 🇹🇭 [th](../th/USER_GUIDE.md) · 🇻🇳 [vi](../vi/USER_GUIDE.md) · 🇮🇩 [id](../id/USER_GUIDE.md) · 🇲🇾 [ms](../ms/USER_GUIDE.md) · 🇳🇱 [nl](../nl/USER_GUIDE.md) · 🇵🇱 [pl](../pl/USER_GUIDE.md) · 🇸🇪 [sv](../sv/USER_GUIDE.md) · 🇳🇴 [no](../no/USER_GUIDE.md) · 🇩🇰 [da](../da/USER_GUIDE.md) · 🇫🇮 [fi](../fi/USER_GUIDE.md) · 🇵🇹 [pt](../pt/USER_GUIDE.md) · 🇷🇴 [ro](../ro/USER_GUIDE.md) · 🇭🇺 [hu](../hu/USER_GUIDE.md) · 🇧🇬 [bg](../bg/USER_GUIDE.md) · 🇸🇰 [sk](../sk/USER_GUIDE.md) · 🇺🇦 [uk-UA](../uk-UA/USER_GUIDE.md) · 🇮🇱 [he](../he/USER_GUIDE.md) · 🇵🇭 [phi](../phi/USER_GUIDE.md)
-
-> 🇺🇸 [English](../../USER_GUIDE.md)
+🌐 **Languages:** 🇺🇸 [English](../../../../docs/USER_GUIDE.md) · 🇪🇸 [es](../../es/docs/USER_GUIDE.md) · 🇫🇷 [fr](../../fr/docs/USER_GUIDE.md) · 🇩🇪 [de](../../de/docs/USER_GUIDE.md) · 🇮🇹 [it](../../it/docs/USER_GUIDE.md) · 🇷🇺 [ru](../../ru/docs/USER_GUIDE.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/USER_GUIDE.md) · 🇯🇵 [ja](../../ja/docs/USER_GUIDE.md) · 🇰🇷 [ko](../../ko/docs/USER_GUIDE.md) · 🇸🇦 [ar](../../ar/docs/USER_GUIDE.md) · 🇮🇳 [in](../../in/docs/USER_GUIDE.md) · 🇹🇭 [th](../../th/docs/USER_GUIDE.md) · 🇻🇳 [vi](../../vi/docs/USER_GUIDE.md) · 🇮🇩 [id](../../id/docs/USER_GUIDE.md) · 🇲🇾 [ms](../../ms/docs/USER_GUIDE.md) · 🇳🇱 [nl](../../nl/docs/USER_GUIDE.md) · 🇵🇱 [pl](../../pl/docs/USER_GUIDE.md) · 🇸🇪 [sv](../../sv/docs/USER_GUIDE.md) · 🇳🇴 [no](../../no/docs/USER_GUIDE.md) · 🇩🇰 [da](../../da/docs/USER_GUIDE.md) · 🇫🇮 [fi](../../fi/docs/USER_GUIDE.md) · 🇵🇹 [pt](../../pt/docs/USER_GUIDE.md) · 🇷🇴 [ro](../../ro/docs/USER_GUIDE.md) · 🇭🇺 [hu](../../hu/docs/USER_GUIDE.md) · 🇧🇬 [bg](../../bg/docs/USER_GUIDE.md) · 🇸🇰 [sk](../../sk/docs/USER_GUIDE.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/USER_GUIDE.md) · 🇮🇱 [he](../../he/docs/USER_GUIDE.md) · 🇵🇭 [phi](../../phi/docs/USER_GUIDE.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/USER_GUIDE.md) · 🇨🇿 [cs](../../cs/docs/USER_GUIDE.md)
---
@@ -320,7 +318,7 @@ Model: cc/claude-opus-4-6
---
-## 🚀 Deployment
+## Käyttöönotto
### Global npm install (Recommended)
@@ -511,23 +509,26 @@ post_install() {
### Environment Variables
-| Variable | Default | Description |
-| ------------------------- | ------------------------------------ | ------------------------------------------------------- |
-| `JWT_SECRET` | `omniroute-default-secret-change-me` | JWT signing secret (**change in production**) |
-| `INITIAL_PASSWORD` | `123456` | First login password |
-| `DATA_DIR` | `~/.omniroute` | Data directory (db, usage, logs) |
-| `PORT` | framework default | Service port (`20128` in examples) |
-| `HOSTNAME` | framework default | Bind host (Docker defaults to `0.0.0.0`) |
-| `NODE_ENV` | runtime default | Set `production` for deploy |
-| `BASE_URL` | `http://localhost:20128` | Server-side internal base URL |
-| `CLOUD_URL` | `https://omniroute.dev` | Cloud sync endpoint base URL |
-| `API_KEY_SECRET` | `endpoint-proxy-api-key-secret` | HMAC secret for generated API keys |
-| `REQUIRE_API_KEY` | `false` | Enforce Bearer API key on `/v1/*` |
-| `ENABLE_REQUEST_LOGS` | `false` | Enables request/response logs |
-| `AUTH_COOKIE_SECURE` | `false` | Force `Secure` auth cookie (behind HTTPS reverse proxy) |
-| `OMNIROUTE_MEMORY_MB` | `512` | Node.js heap limit in MB |
-| `PROMPT_CACHE_MAX_SIZE` | `50` | Max prompt cache entries |
-| `SEMANTIC_CACHE_MAX_SIZE` | `100` | Max semantic cache entries |
+| Variable | Default | Description |
+| ---------------------------- | ------------------------------------ | ------------------------------------------------------------------------------------------ |
+| `JWT_SECRET` | `omniroute-default-secret-change-me` | JWT signing secret (**change in production**) |
+| `INITIAL_PASSWORD` | `123456` | First login password |
+| `DATA_DIR` | `~/.omniroute` | Data directory (db, usage, logs) |
+| `PORT` | framework default | Service port (`20128` in examples) |
+| `HOSTNAME` | framework default | Bind host (Docker defaults to `0.0.0.0`) |
+| `NODE_ENV` | runtime default | Set `production` for deploy |
+| `BASE_URL` | `http://localhost:20128` | Server-side internal base URL |
+| `CLOUD_URL` | `https://omniroute.dev` | Cloud sync endpoint base URL |
+| `API_KEY_SECRET` | `endpoint-proxy-api-key-secret` | HMAC secret for generated API keys |
+| `REQUIRE_API_KEY` | `false` | Enforce Bearer API key on `/v1/*` |
+| `ALLOW_API_KEY_REVEAL` | `false` | Allow Api Manager to copy full API keys on demand |
+| `DISABLE_SQLITE_AUTO_BACKUP` | `false` | Disable automatic SQLite snapshots before writes/import/restore; manual backups still work |
+| `ENABLE_REQUEST_LOGS` | `false` | Enables request/response logs |
+| `AUTH_COOKIE_SECURE` | `false` | Force `Secure` auth cookie (behind HTTPS reverse proxy) |
+| `CLOUDFLARED_BIN` | unset | Use an existing `cloudflared` binary instead of managed download |
+| `OMNIROUTE_MEMORY_MB` | `512` | Node.js heap limit in MB |
+| `PROMPT_CACHE_MAX_SIZE` | `50` | Max prompt cache entries |
+| `SEMANTIC_CACHE_MAX_SIZE` | `100` | Max semantic cache entries |
For the full environment variable reference, see the [README](../README.md).
@@ -598,6 +599,11 @@ curl -X POST http://localhost:20128/api/provider-models \
Or use Dashboard: **Providers → [Provider] → Custom Models**.
+Notes:
+
+- OpenRouter and OpenAI/Anthropic-compatible providers are managed from **Available Models** only. Manual add, import, and auto-sync all land in the same available-model list, so there is no separate Custom Models section for those providers.
+- The **Custom Models** section is intended for providers that do not expose managed available-model imports.
+
### Dedicated Provider Routes
Route requests directly to a specific provider with model validation:
@@ -642,6 +648,14 @@ Returns models grouped by provider with types (`chat`, `embedding`, `image`).
- Automatic background sync with timeout + fail-fast
- Prefer server-side `BASE_URL`/`CLOUD_URL` in production
+### Cloudflare Quick Tunnel
+
+- Available in **Dashboard → Endpoints** for Docker and other self-hosted deployments
+- Creates a temporary `https://*.trycloudflare.com` URL that forwards to your current OpenAI-compatible `/v1` endpoint
+- First enable installs `cloudflared` only when needed; later restarts reuse the same managed binary
+- Tunnel URLs are ephemeral and change every time you stop/start the tunnel
+- Set `CLOUDFLARED_BIN` if you prefer using a preinstalled `cloudflared` binary instead of the managed download
+
### LLM Gateway Intelligence (Phase 9)
- **Semantic Cache** — Auto-caches non-streaming, temperature=0 responses (bypass with `X-OmniRoute-No-Cache: true`)
@@ -757,11 +771,11 @@ OmniRoute implements provider-level resilience with four components:
Manage database backups in **Dashboard → Settings → System & Storage**.
-| Action | Description |
-| ------------------------ | ------------------------------------------------------------------------------------------------------------------------------ |
-| **Export Database** | Downloads the current SQLite database as a `.sqlite` file |
-| **Export All (.tar.gz)** | Downloads a full backup archive including: database, settings, combos, provider connections (no credentials), API key metadata |
-| **Import Database** | Upload a `.sqlite` file to replace the current database. A pre-import backup is automatically created |
+| Action | Description |
+| ------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------- |
+| **Export Database** | Downloads the current SQLite database as a `.sqlite` file |
+| **Export All (.tar.gz)** | Downloads a full backup archive including: database, settings, combos, provider connections (no credentials), API key metadata |
+| **Import Database** | Upload a `.sqlite` file to replace the current database. A pre-import backup is automatically created unless `DISABLE_SQLITE_AUTO_BACKUP=true` |
```bash
# API: Export database
@@ -787,10 +801,11 @@ curl -X POST http://localhost:20128/api/db-backups/import \
### Settings Dashboard
-The settings page is organized into 5 tabs for easy navigation:
+The settings page is organized into 6 tabs for easy navigation:
| Tab | Contents |
| -------------- | ---------------------------------------------------------------------------------------------- |
+| **General** | System storage tools, appearance settings, theme controls, and per-item sidebar visibility |
| **Security** | Login/Password settings, IP Access Control, API auth for `/models`, and Provider Blocking |
| **Routing** | Global routing strategy (6 options), wildcard model aliases, fallback chains, combo defaults |
| **Resilience** | Provider profiles, editable rate limits, circuit breaker status, policies & locked identifiers |
diff --git a/docs/i18n/fi/docs/VM_DEPLOYMENT_GUIDE.md b/docs/i18n/fi/docs/VM_DEPLOYMENT_GUIDE.md
new file mode 100644
index 0000000000..2662210f72
--- /dev/null
+++ b/docs/i18n/fi/docs/VM_DEPLOYMENT_GUIDE.md
@@ -0,0 +1,403 @@
+# OmniRoute — Deployment Guide on VM with Cloudflare (Suomi)
+
+🌐 **Languages:** 🇺🇸 [English](../../../../docs/VM_DEPLOYMENT_GUIDE.md) · 🇪🇸 [es](../../es/docs/VM_DEPLOYMENT_GUIDE.md) · 🇫🇷 [fr](../../fr/docs/VM_DEPLOYMENT_GUIDE.md) · 🇩🇪 [de](../../de/docs/VM_DEPLOYMENT_GUIDE.md) · 🇮🇹 [it](../../it/docs/VM_DEPLOYMENT_GUIDE.md) · 🇷🇺 [ru](../../ru/docs/VM_DEPLOYMENT_GUIDE.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/VM_DEPLOYMENT_GUIDE.md) · 🇯🇵 [ja](../../ja/docs/VM_DEPLOYMENT_GUIDE.md) · 🇰🇷 [ko](../../ko/docs/VM_DEPLOYMENT_GUIDE.md) · 🇸🇦 [ar](../../ar/docs/VM_DEPLOYMENT_GUIDE.md) · 🇮🇳 [in](../../in/docs/VM_DEPLOYMENT_GUIDE.md) · 🇹🇭 [th](../../th/docs/VM_DEPLOYMENT_GUIDE.md) · 🇻🇳 [vi](../../vi/docs/VM_DEPLOYMENT_GUIDE.md) · 🇮🇩 [id](../../id/docs/VM_DEPLOYMENT_GUIDE.md) · 🇲🇾 [ms](../../ms/docs/VM_DEPLOYMENT_GUIDE.md) · 🇳🇱 [nl](../../nl/docs/VM_DEPLOYMENT_GUIDE.md) · 🇵🇱 [pl](../../pl/docs/VM_DEPLOYMENT_GUIDE.md) · 🇸🇪 [sv](../../sv/docs/VM_DEPLOYMENT_GUIDE.md) · 🇳🇴 [no](../../no/docs/VM_DEPLOYMENT_GUIDE.md) · 🇩🇰 [da](../../da/docs/VM_DEPLOYMENT_GUIDE.md) · 🇫🇮 [fi](../../fi/docs/VM_DEPLOYMENT_GUIDE.md) · 🇵🇹 [pt](../../pt/docs/VM_DEPLOYMENT_GUIDE.md) · 🇷🇴 [ro](../../ro/docs/VM_DEPLOYMENT_GUIDE.md) · 🇭🇺 [hu](../../hu/docs/VM_DEPLOYMENT_GUIDE.md) · 🇧🇬 [bg](../../bg/docs/VM_DEPLOYMENT_GUIDE.md) · 🇸🇰 [sk](../../sk/docs/VM_DEPLOYMENT_GUIDE.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/VM_DEPLOYMENT_GUIDE.md) · 🇮🇱 [he](../../he/docs/VM_DEPLOYMENT_GUIDE.md) · 🇵🇭 [phi](../../phi/docs/VM_DEPLOYMENT_GUIDE.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/VM_DEPLOYMENT_GUIDE.md) · 🇨🇿 [cs](../../cs/docs/VM_DEPLOYMENT_GUIDE.md)
+
+---
+
+Complete guide to install and configure OmniRoute on a VM (VPS) with domain managed via Cloudflare.
+
+---
+
+## Prerequisites
+
+| Item | Minimum | Recommended |
+| ---------- | ------------------------ | ---------------- |
+| **CPU** | 1 vCPU | 2 vCPU |
+| **RAM** | 1 GB | 2 GB |
+| **Disk** | 10 GB SSD | 25 GB SSD |
+| **OS** | Ubuntu 22.04 LTS | Ubuntu 24.04 LTS |
+| **Domain** | Registered on Cloudflare | — |
+| **Docker** | Docker Engine 24+ | Docker 27+ |
+
+**Tested providers**: Akamai (Linode), DigitalOcean, Vultr, Hetzner, AWS Lightsail.
+
+---
+
+## 1. Configure the VM
+
+### 1.1 Create the instance
+
+On your preferred VPS provider:
+
+- Choose Ubuntu 24.04 LTS
+- Select the minimum plan (1 vCPU / 1 GB RAM)
+- Set a strong root password or configure SSH key
+- Note the **public IP** (e.g., `203.0.113.10`)
+
+### 1.2 Connect via SSH
+
+```bash
+ssh root@203.0.113.10
+```
+
+### 1.3 Update the system
+
+```bash
+apt update && apt upgrade -y
+```
+
+### 1.4 Install Docker
+
+```bash
+# Install dependencies
+apt install -y ca-certificates curl gnupg
+
+# Add official Docker repository
+install -m 0755 -d /etc/apt/keyrings
+curl -fsSL https://download.docker.com/linux/ubuntu/gpg | gpg --dearmor -o /etc/apt/keyrings/docker.gpg
+chmod a+r /etc/apt/keyrings/docker.gpg
+echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu $ (. /etc/os-release && echo “$VERSION_CODENAME”) stable" | tee /etc/apt/sources.list.d/docker.list > /dev/null
+apt update
+apt install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin
+```
+
+### 1.5 Install nginx
+
+```bash
+apt install -y nginx
+```
+
+### 1.6 Configure Firewall (UFW)
+
+```bash
+ufw default deny incoming
+ufw default allow outgoing
+ufw allow 22/tcp # SSH
+ufw allow 80/tcp # HTTP (redirect)
+ufw allow 443/tcp # HTTPS
+ufw enable
+```
+
+> **Tip**: For maximum security, restrict ports 80 and 443 to Cloudflare IPs only. See the [Advanced Security](#advanced-security) section.
+
+---
+
+## 2. Install OmniRoute
+
+### 2.1 Create configuration directory
+
+```bash
+mkdir -p /opt/omniroute
+```
+
+### 2.2 Create environment variables file
+
+```bash
+cat > /opt/omniroute/.env << ‘EOF’
+# === Security ===
+JWT_SECRET=CHANGE-TO-A-UNIQUE-64-CHAR-SECRET-KEY
+INITIAL_PASSWORD=YourSecurePassword123!
+API_KEY_SECRET=REPLACE-WITH-ANOTHER-SECRET-KEY
+STORAGE_ENCRYPTION_KEY=REPLACE-WITH-THIRD-SECRET-KEY
+STORAGE_ENCRYPTION_KEY_VERSION=v1
+MACHINE_ID_SALT=CHANGE-TO-A-UNIQUE-SALT
+
+# === App ===
+PORT=20128
+NODE_ENV=production
+HOSTNAME=0.0.0.0
+DATA_DIR=/app/data
+STORAGE_DRIVER=sqlite
+ENABLE_REQUEST_LOGS=true
+AUTH_COOKIE_SECURE=false
+REQUIRE_API_KEY=false
+
+# === Domain (change to your domain) ===
+BASE_URL=https://llms.seudominio.com
+NEXT_PUBLIC_BASE_URL=https://llms.seudominio.com
+
+# === Cloud Sync (optional) ===
+# CLOUD_URL=https://cloud.omniroute.online
+# NEXT_PUBLIC_CLOUD_URL=https://cloud.omniroute.online
+EOF
+```
+
+> ⚠️ **IMPORTANT**: Generate unique secret keys! Use `openssl rand -hex 32` for each key.
+
+### 2.3 Start the container
+
+```bash
+docker pull diegosouzapw/omniroute:latest
+
+docker run -d \
+ --name omniroute \
+ --restart unless-stopped \
+ --env-file /opt/omniroute/.env \
+ -p 20128:20128 \
+ -v omniroute-data:/app/data \
+ diegosouzapw/omniroute:latest
+```
+
+### 2.4 Verify that it is running
+
+```bash
+docker ps | grep omniroute
+docker logs omniroute --tail 20
+```
+
+It should display: `[DB] SQLite database ready` and `listening on port 20128`.
+
+---
+
+## 3. Configure nginx (Reverse Proxy)
+
+### 3.1 Generate SSL certificate (Cloudflare Origin)
+
+In the Cloudflare dashboard:
+
+1. Go to **SSL/TLS → Origin Server**
+2. Click **Create Certificate**
+3. Keep the defaults (15 years, \*.yourdomain.com)
+4. Copy the **Origin Certificate** and the **Private Key**
+
+```bash
+mkdir -p /etc/nginx/ssl
+
+# Paste the certificate
+nano /etc/nginx/ssl/origin.crt
+
+# Paste the private key
+nano /etc/nginx/ssl/origin.key
+
+chmod 600 /etc/nginx/ssl/origin.key
+```
+
+### 3.2 Nginx Configuration
+
+```bash
+cat > /etc/nginx/sites-available/omniroute << ‘NGINX’
+# Default server — blocks direct access via IP
+server {
+ listen 80 default_server;
+ listen [::]:80 default_server;
+ listen 443 ssl default_server;
+ listen [::]:443 ssl default_server;
+ ssl_certificate /etc/nginx/ssl/origin.crt;
+ ssl_certificate_key /etc/nginx/ssl/origin.key;
+ server_name _;
+ return 444;
+}
+
+# OmniRoute — HTTPS
+server {
+ listen 443 ssl;
+ listen [::]:443 ssl;
+ server_name llms.yourdomain.com; # Change to your domain
+
+ ssl_certificate /etc/nginx/ssl/origin.crt;
+ ssl_certificate_key /etc/nginx/ssl/origin.key;
+ ssl_protocols TLSv1.2 TLSv1.3;
+
+ client_max_body_size 100M;
+
+ location / {
+ proxy_pass http://127.0.0.1:20128;
+ proxy_set_header Host $host;
+ proxy_set_header X-Real-IP $remote_addr;
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
+ proxy_set_header X-Forwarded-Proto $scheme;
+
+ # WebSocket support
+ proxy_http_version 1.1;
+ proxy_set_header Upgrade $http_upgrade;
+ proxy_set_header Connection “upgrade”;
+
+ # SSE (Server-Sent Events) — streaming AI responses
+ proxy_buffering off;
+ proxy_cache off;
+ proxy_read_timeout 300s;
+ proxy_send_timeout 300s;
+ }
+}
+
+# HTTP → HTTPS redirect
+server {
+ listen 80;
+ listen [::]:80;
+ server_name llms.yourdomain.com;
+ return 301 https://$server_name$request_uri;
+}
+NGINX
+```
+
+### 3.3 Enable and Test
+
+```bash
+# Remove default configuration
+rm -f /etc/nginx/sites-enabled/default
+
+# Enable OmniRoute
+ln -sf /etc/nginx/sites-available/omniroute /etc/nginx/sites-enabled/omniroute
+
+# Test and reload
+nginx -t && systemctl reload nginx
+```
+
+---
+
+## 4. Configure Cloudflare DNS
+
+### 4.1 Add DNS record
+
+In the Cloudflare dashboard → DNS:
+
+| Type | Name | Content | Proxy |
+| ---- | ------ | ---------------------- | ---------- |
+| A | `llms` | `203.0.113.10` (VM IP) | ✅ Proxied |
+
+### 4.2 Configure SSL
+
+Under **SSL/TLS → Overview**:
+
+- Mode: **Full (Strict)**
+
+Under **SSL/TLS → Edge Certificates**:
+
+- Always Use HTTPS: ✅ On
+- Minimum TLS Version: TLS 1.2
+- Automatic HTTPS Rewrites: ✅ On
+
+### 4.3 Testing
+
+```bash
+curl -sI https://llms.seudominio.com/health
+# Should return HTTP/2 200
+```
+
+---
+
+## 5. Operations and Maintenance
+
+### Upgrade to a new version
+
+```bash
+docker pull diegosouzapw/omniroute:latest
+docker stop omniroute && docker rm omniroute
+docker run -d --name omniroute --restart unless-stopped \
+ --env-file /opt/omniroute/.env \
+ -p 20128:20128 \
+ -v omniroute-data:/app/data \
+ diegosouzapw/omniroute:latest
+```
+
+### View logs
+
+```bash
+docker logs -f omniroute # Real-time stream
+docker logs omniroute --tail 50 # Last 50 lines
+```
+
+### Manual database backup
+
+```bash
+# Copy data from the volume to the host
+docker cp omniroute:/app/data ./backup-$(date +%F)
+
+# Or compress the entire volume
+docker run --rm -v omniroute-data:/data -v $(pwd):/backup \
+ alpine tar czf /backup/omniroute-data-$(date +%F).tar.gz /data
+```
+
+### Restore from backup
+
+```bash
+docker stop omniroute
+docker run --rm -v omniroute-data:/data -v $(pwd):/backup \
+ alpine sh -c “rm -rf /data/* && tar xzf /backup/omniroute-data-YYYY-MM-DD.tar.gz -C /”
+docker start omniroute
+```
+
+---
+
+## 6. Advanced Security
+
+### Restrict nginx to Cloudflare IPs
+
+```bash
+cat > /etc/nginx/cloudflare-ips.conf << ‘CF’
+# Cloudflare IPv4 ranges — update periodically
+# https://www.cloudflare.com/ips-v4/
+set_real_ip_from 173.245.48.0/20;
+set_real_ip_from 103.21.244.0/22;
+set_real_ip_from 103.22.200.0/22;
+set_real_ip_from 103.31.4.0/22;
+set_real_ip_from 141.101.64.0/18;
+set_real_ip_from 108.162.192.0/18;
+set_real_ip_from 190.93.240.0/20;
+set_real_ip_from 188.114.96.0/20;
+set_real_ip_from 197.234.240.0/22;
+set_real_ip_from 198.41.128.0/17;
+set_real_ip_from 162.158.0.0/15;
+set_real_ip_from 104.16.0.0/13;
+set_real_ip_from 104.24.0.0/14;
+set_real_ip_from 172.64.0.0/13;
+set_real_ip_from 131.0.72.0/22;
+real_ip_header CF-Connecting-IP;
+CF
+```
+
+Add the following to `nginx.conf` inside the `http {}` block:
+
+```nginx
+include /etc/nginx/cloudflare-ips.conf;
+```
+
+### Install fail2ban
+
+```bash
+apt install -y fail2ban
+systemctl enable fail2ban
+systemctl start fail2ban
+
+# Check status
+fail2ban-client status sshd
+```
+
+### Block direct access to the Docker port
+
+```bash
+# Prevent direct external access to port 20128
+iptables -I DOCKER-USER -p tcp --dport 20128 -j DROP
+iptables -I DOCKER-USER -i lo -p tcp --dport 20128 -j ACCEPT
+
+# Persist the rules
+apt install -y iptables-persistent
+netfilter-persistent save
+```
+
+---
+
+## 7. Deploy to Cloudflare Workers (Optional)
+
+For remote access via Cloudflare Workers (without exposing the VM directly):
+
+```bash
+# In the local repository
+cd omnirouteCloud
+npm install
+npx wrangler login
+npx wrangler deploy
+```
+
+See the full documentation at [omnirouteCloud/README.md](../omnirouteCloud/README.md).
+
+---
+
+## Port Summary
+
+| Port | Service | Access |
+| ----- | ----------- | -------------------------- |
+| 22 | SSH | Public (with fail2ban) |
+| 80 | nginx HTTP | Redirect → HTTPS |
+| 443 | nginx HTTPS | Via Cloudflare Proxy |
+| 20128 | OmniRoute | Localhost only (via nginx) |
diff --git a/docs/i18n/fi/src/lib/a2a/README.md b/docs/i18n/fi/src/lib/a2a/README.md
new file mode 100644
index 0000000000..7287dc4172
--- /dev/null
+++ b/docs/i18n/fi/src/lib/a2a/README.md
@@ -0,0 +1,752 @@
+# OmniRoute A2A Server (Suomi)
+
+🌐 **Languages:** 🇺🇸 [English](../../../../../../src/lib/a2a/README.md) · 🇪🇸 [es](../../../../es/src/lib/a2a/README.md) · 🇫🇷 [fr](../../../../fr/src/lib/a2a/README.md) · 🇩🇪 [de](../../../../de/src/lib/a2a/README.md) · 🇮🇹 [it](../../../../it/src/lib/a2a/README.md) · 🇷🇺 [ru](../../../../ru/src/lib/a2a/README.md) · 🇨🇳 [zh-CN](../../../../zh-CN/src/lib/a2a/README.md) · 🇯🇵 [ja](../../../../ja/src/lib/a2a/README.md) · 🇰🇷 [ko](../../../../ko/src/lib/a2a/README.md) · 🇸🇦 [ar](../../../../ar/src/lib/a2a/README.md) · 🇮🇳 [in](../../../../in/src/lib/a2a/README.md) · 🇹🇭 [th](../../../../th/src/lib/a2a/README.md) · 🇻🇳 [vi](../../../../vi/src/lib/a2a/README.md) · 🇮🇩 [id](../../../../id/src/lib/a2a/README.md) · 🇲🇾 [ms](../../../../ms/src/lib/a2a/README.md) · 🇳🇱 [nl](../../../../nl/src/lib/a2a/README.md) · 🇵🇱 [pl](../../../../pl/src/lib/a2a/README.md) · 🇸🇪 [sv](../../../../sv/src/lib/a2a/README.md) · 🇳🇴 [no](../../../../no/src/lib/a2a/README.md) · 🇩🇰 [da](../../../../da/src/lib/a2a/README.md) · 🇫🇮 [fi](../../../../fi/src/lib/a2a/README.md) · 🇵🇹 [pt](../../../../pt/src/lib/a2a/README.md) · 🇷🇴 [ro](../../../../ro/src/lib/a2a/README.md) · 🇭🇺 [hu](../../../../hu/src/lib/a2a/README.md) · 🇧🇬 [bg](../../../../bg/src/lib/a2a/README.md) · 🇸🇰 [sk](../../../../sk/src/lib/a2a/README.md) · 🇺🇦 [uk-UA](../../../../uk-UA/src/lib/a2a/README.md) · 🇮🇱 [he](../../../../he/src/lib/a2a/README.md) · 🇵🇭 [phi](../../../../phi/src/lib/a2a/README.md) · 🇧🇷 [pt-BR](../../../../pt-BR/src/lib/a2a/README.md) · 🇨🇿 [cs](../../../../cs/src/lib/a2a/README.md)
+
+---
+
+> **Agent-to-Agent Protocol v0.3** — Enables any AI agent to use OmniRoute as an intelligent routing agent via JSON-RPC 2.0.
+
+The A2A Server exposes OmniRoute as a **first-class agent** that other agents can discover, delegate tasks to, and collaborate with using the [A2A Protocol](https://google.github.io/A2A/).
+
+---
+
+## Arkkitehtuuri
+
+```
+┌──────────────────────────────────────────────────────────────────┐
+│ Orchestrator Agent │
+│ (LangChain, CrewAI, AutoGen, Custom Agent) │
+└──────────────────────┬───────────────────────────────────────────┘
+ │ 1. GET /.well-known/agent.json (discover)
+ │ 2. POST /a2a (JSON-RPC 2.0)
+ ▼
+┌──────────────────────────────────────────────────────────────────┐
+│ OmniRoute A2A Server │
+│ ┌────────────────┐ ┌────────────────┐ ┌───────────────────┐ │
+│ │ Task Manager │ │ Skill Engine │ │ SSE Streaming │ │
+│ │ (lifecycle) │──│ (registry) │──│ (real-time) │ │
+│ └────────────────┘ └────────┬───────┘ └───────────────────┘ │
+│ │ │
+│ Skills: │ │
+│ ├─ smart-routing ──────────┤ ┌────────────────────────────┐ │
+│ └─ quota-management ───────┘ │ Routing Decision Logger │ │
+│ └────────────────────────────┘ │
+└──────────────────────────────────────────────────────────────────┘
+ │
+ ▼ OmniRoute Gateway (internal)
+ /v1/chat/completions, /api/combos, /api/usage/quota
+```
+
+---
+
+## Pikakäynnistys
+
+### Agent Discovery
+
+Every A2A-compatible agent exposes an **Agent Card** at `/.well-known/agent.json`:
+
+```bash
+curl http://localhost:20128/.well-known/agent.json
+```
+
+**Response:**
+
+```json
+{
+ "name": "OmniRoute",
+ "description": "Intelligent AI gateway with auto-routing across 50+ providers",
+ "url": "http://localhost:20128/a2a",
+ "version": "1.8.1",
+ "capabilities": {
+ "streaming": true,
+ "pushNotifications": false
+ },
+ "skills": [
+ {
+ "id": "smart-routing",
+ "name": "Smart Routing",
+ "description": "Routes prompts through OmniRoute intelligent pipeline",
+ "tags": ["routing", "llm", "multi-provider", "cost-optimization"],
+ "examples": [
+ "Write a hello world in Python",
+ "Explain quantum computing using the cheapest provider"
+ ]
+ },
+ {
+ "id": "quota-management",
+ "name": "Quota Management",
+ "description": "Natural-language queries about provider quotas",
+ "tags": ["quota", "analytics", "cost"],
+ "examples": [
+ "Which provider has the most quota remaining?",
+ "Suggest a free combo for coding"
+ ]
+ }
+ ],
+ "authentication": {
+ "schemes": ["bearer"],
+ "apiKeyHeader": "Authorization"
+ }
+}
+```
+
+---
+
+## JSON-RPC 2.0 Methods
+
+### `message/send` — Synchronous Execution
+
+Send a message to a skill and receive the complete response.
+
+```bash
+curl -X POST http://localhost:20128/a2a \
+ -H "Content-Type: application/json" \
+ -H "Authorization: Bearer YOUR_KEY" \
+ -d '{
+ "jsonrpc": "2.0",
+ "id": "1",
+ "method": "message/send",
+ "params": {
+ "skill": "smart-routing",
+ "messages": [{"role": "user", "content": "Write a Python hello world"}],
+ "metadata": {"model": "auto", "combo": "fast-coding"}
+ }
+ }'
+```
+
+**Response:**
+
+```json
+{
+ "jsonrpc": "2.0",
+ "id": "1",
+ "result": {
+ "task": { "id": "a1b2c3d4-...", "state": "completed" },
+ "artifacts": [{ "type": "text", "content": "print('Hello, World!')" }],
+ "metadata": {
+ "routing_explanation": "Selected claude-sonnet via provider \"anthropic\" (latency: 1200ms, cost: $0.0030)",
+ "cost_envelope": { "estimated": 0.005, "actual": 0.003, "currency": "USD" },
+ "resilience_trace": [
+ { "event": "primary_selected", "provider": "anthropic", "timestamp": "2026-03-04T..." }
+ ],
+ "policy_verdict": { "allowed": true, "reason": "within budget and quota limits" }
+ }
+ }
+}
+```
+
+### `message/stream` — SSE Streaming
+
+Same as `message/send` but returns Server-Sent Events for real-time streaming.
+
+```bash
+curl -N -X POST http://localhost:20128/a2a \
+ -H "Content-Type: application/json" \
+ -H "Authorization: Bearer YOUR_KEY" \
+ -d '{
+ "jsonrpc": "2.0",
+ "id": "1",
+ "method": "message/stream",
+ "params": {
+ "skill": "smart-routing",
+ "messages": [{"role": "user", "content": "Explain quantum computing"}]
+ }
+ }'
+```
+
+**SSE Events:**
+
+```
+data: {"jsonrpc":"2.0","method":"message/stream","params":{"task":{"id":"...","state":"working"},"chunk":{"type":"text","content":"Quantum computing..."}}}
+
+: heartbeat 2026-03-04T21:00:00Z
+
+data: {"jsonrpc":"2.0","method":"message/stream","params":{"task":{"id":"...","state":"completed"},"metadata":{...}}}
+```
+
+### `tasks/get` — Query Task Status
+
+```bash
+curl -X POST http://localhost:20128/a2a \
+ -H "Content-Type: application/json" \
+ -H "Authorization: Bearer YOUR_KEY" \
+ -d '{"jsonrpc":"2.0","id":"2","method":"tasks/get","params":{"taskId":"TASK_UUID"}}'
+```
+
+### `tasks/cancel` — Cancel a Running Task
+
+```bash
+curl -X POST http://localhost:20128/a2a \
+ -H "Content-Type: application/json" \
+ -H "Authorization: Bearer YOUR_KEY" \
+ -d '{"jsonrpc":"2.0","id":"3","method":"tasks/cancel","params":{"taskId":"TASK_UUID"}}'
+```
+
+---
+
+## Skills Reference
+
+### `smart-routing`
+
+Routes prompts through OmniRoute's intelligent pipeline with full observability.
+
+**Parameters (in `metadata`):**
+
+| Parameter | Type | Default | Description |
+| --------- | -------- | ------------ | ---------------------------------------------------------------------------------------- |
+| `model` | `string` | `"auto"` | Target model (e.g., `claude-sonnet-4`, `gpt-4o`, `auto`) |
+| `combo` | `string` | active combo | Specific combo to route through |
+| `budget` | `number` | none | Maximum cost in USD for this request |
+| `role` | `string` | none | Task role hint: `coding`, `review`, `planning`, `analysis`, `debugging`, `documentation` |
+
+**Returns:**
+
+| Field | Description |
+| ------------------------------ | --------------------------------------------------------- |
+| `artifacts[].content` | The LLM response text |
+| `metadata.routing_explanation` | Human-readable explanation of routing decision |
+| `metadata.cost_envelope` | Estimated vs actual cost with currency |
+| `metadata.resilience_trace` | Array of events (primary_selected, fallback_needed, etc.) |
+| `metadata.policy_verdict` | Whether the request was allowed and why |
+
+### `quota-management`
+
+Answers natural-language queries about provider quotas.
+
+**Query types (inferred from message content):**
+
+| Query Pattern | Response Type |
+| ---------------------------------------------- | -------------------------------------------------------- |
+| Contains `"ranking"`, `"most quota"`, `"best"` | Providers ranked by remaining quota |
+| Contains `"free"`, `"suggest"` | Lists free combos or suggests free-tier providers |
+| Default | Full quota summary with warnings for low-quota providers |
+
+---
+
+## Task Lifecycle
+
+```
+submitted ──→ working ──→ completed
+ ──→ failed
+ ──────────→ cancelled
+```
+
+| State | Description |
+| ----------- | ----------------------------------------------------- |
+| `submitted` | Task created, queued for execution |
+| `working` | Skill handler is executing |
+| `completed` | Execution succeeded, artifacts available |
+| `failed` | Execution failed or task expired (TTL: 5 min default) |
+| `cancelled` | Cancelled by client via `tasks/cancel` |
+
+- Terminal states: `completed`, `failed`, `cancelled` (no further transitions)
+- Expired tasks in `submitted` or `working` are auto-marked as `failed`
+- Tasks are garbage-collected after 2× TTL
+
+---
+
+## Client Examples
+
+### Python — Orchestrator Agent
+
+```python
+"""
+A2A Client — Python example.
+Discovers OmniRoute agent, sends a task, and processes the result.
+"""
+import requests
+import json
+
+BASE_URL = "http://localhost:20128"
+API_KEY = "your-api-key"
+HEADERS = {
+ "Content-Type": "application/json",
+ "Authorization": f"Bearer {API_KEY}",
+}
+
+# 1. Discover agent capabilities
+agent_card = requests.get(f"{BASE_URL}/.well-known/agent.json").json()
+print(f"Agent: {agent_card['name']} v{agent_card['version']}")
+print(f"Skills: {[s['id'] for s in agent_card['skills']]}")
+
+# 2. Send a smart-routing task
+response = requests.post(f"{BASE_URL}/a2a", headers=HEADERS, json={
+ "jsonrpc": "2.0",
+ "id": "task-1",
+ "method": "message/send",
+ "params": {
+ "skill": "smart-routing",
+ "messages": [{"role": "user", "content": "Write a Python quicksort implementation"}],
+ "metadata": {
+ "model": "auto",
+ "combo": "fast-coding",
+ "budget": 0.10,
+ }
+ }
+})
+result = response.json()["result"]
+print(f"\n📝 Response: {result['artifacts'][0]['content'][:200]}...")
+print(f"🔀 Routing: {result['metadata']['routing_explanation']}")
+print(f"💰 Cost: ${result['metadata']['cost_envelope']['actual']}")
+print(f"🛡️ Policy: {result['metadata']['policy_verdict']['reason']}")
+
+# 3. Query quota status
+quota_resp = requests.post(f"{BASE_URL}/a2a", headers=HEADERS, json={
+ "jsonrpc": "2.0",
+ "id": "task-2",
+ "method": "message/send",
+ "params": {
+ "skill": "quota-management",
+ "messages": [{"role": "user", "content": "Which provider has the most quota remaining?"}],
+ }
+})
+quota_result = quota_resp.json()["result"]
+print(f"\n📊 Quota: {quota_result['artifacts'][0]['content']}")
+```
+
+### TypeScript — Multi-Agent Orchestrator
+
+```typescript
+/**
+ * A2A Client — TypeScript example.
+ * Shows agent discovery, task delegation, and streaming.
+ */
+
+const BASE_URL = "http://localhost:20128";
+const API_KEY = "your-api-key";
+
+interface JsonRpcResponse {
+ jsonrpc: "2.0";
+ id: string | number;
+ result?: T;
+ error?: { code: number; message: string };
+}
+
+async function a2aCall(method: string, params: Record): Promise {
+ const resp = await fetch(`${BASE_URL}/a2a`, {
+ method: "POST",
+ headers: {
+ "Content-Type": "application/json",
+ Authorization: `Bearer ${API_KEY}`,
+ },
+ body: JSON.stringify({
+ jsonrpc: "2.0",
+ id: `${method}-${Date.now()}`,
+ method,
+ params,
+ }),
+ });
+ const json: JsonRpcResponse = await resp.json();
+ if (json.error) throw new Error(`[${json.error.code}] ${json.error.message}`);
+ return json.result!;
+}
+
+// ── Agent Discovery ──
+const agentCard = await fetch(`${BASE_URL}/.well-known/agent.json`).then((r) => r.json());
+console.log(`Connected to: ${agentCard.name} (${agentCard.skills.length} skills)`);
+
+// ── Smart Routing: Send a coding task ──
+const routingResult = await a2aCall("message/send", {
+ skill: "smart-routing",
+ messages: [{ role: "user", content: "Implement a Redis cache wrapper in TypeScript" }],
+ metadata: { model: "claude-sonnet-4", role: "coding" },
+});
+console.log("Response:", routingResult.artifacts[0].content);
+console.log("Provider:", routingResult.metadata.routing_explanation);
+
+// ── Quota Management: Find free alternatives ──
+const quotaResult = await a2aCall("message/send", {
+ skill: "quota-management",
+ messages: [{ role: "user", content: "Suggest free combos for documentation" }],
+});
+console.log("Free combos:", quotaResult.artifacts[0].content);
+
+// ── Streaming: Real-time response ──
+const streamResp = await fetch(`${BASE_URL}/a2a`, {
+ method: "POST",
+ headers: {
+ "Content-Type": "application/json",
+ Authorization: `Bearer ${API_KEY}`,
+ },
+ body: JSON.stringify({
+ jsonrpc: "2.0",
+ id: "stream-1",
+ method: "message/stream",
+ params: {
+ skill: "smart-routing",
+ messages: [{ role: "user", content: "Explain microservices architecture" }],
+ },
+ }),
+});
+
+const reader = streamResp.body!.getReader();
+const decoder = new TextDecoder();
+while (true) {
+ const { done, value } = await reader.read();
+ if (done) break;
+ const chunk = decoder.decode(value);
+ for (const line of chunk.split("\n")) {
+ if (line.startsWith("data: ")) {
+ const event = JSON.parse(line.slice(6));
+ if (event.params.chunk) {
+ process.stdout.write(event.params.chunk.content);
+ }
+ if (event.params.task.state === "completed") {
+ console.log("\n✅ Stream completed");
+ }
+ }
+ }
+}
+```
+
+### Python — LangChain A2A Integration
+
+```python
+"""
+LangChain integration — Use OmniRoute A2A as a custom LLM.
+"""
+from langchain.llms.base import BaseLLM
+from langchain.schema import LLMResult, Generation
+import requests
+from typing import List, Optional
+
+class OmniRouteA2A(BaseLLM):
+ base_url: str = "http://localhost:20128"
+ api_key: str = ""
+ model: str = "auto"
+ combo: Optional[str] = None
+
+ @property
+ def _llm_type(self) -> str:
+ return "omniroute-a2a"
+
+ def _call(self, prompt: str, stop: Optional[List[str]] = None, **kwargs) -> str:
+ response = requests.post(
+ f"{self.base_url}/a2a",
+ headers={
+ "Content-Type": "application/json",
+ "Authorization": f"Bearer {self.api_key}",
+ },
+ json={
+ "jsonrpc": "2.0",
+ "id": "langchain-1",
+ "method": "message/send",
+ "params": {
+ "skill": "smart-routing",
+ "messages": [{"role": "user", "content": prompt}],
+ "metadata": {
+ "model": self.model,
+ **({"combo": self.combo} if self.combo else {}),
+ },
+ },
+ },
+ )
+ result = response.json()["result"]
+ return result["artifacts"][0]["content"]
+
+ def _generate(self, prompts: List[str], stop=None, **kwargs) -> LLMResult:
+ return LLMResult(
+ generations=[[Generation(text=self._call(p, stop))] for p in prompts]
+ )
+
+# Usage
+llm = OmniRouteA2A(
+ base_url="http://localhost:20128",
+ api_key="your-key",
+ model="auto",
+ combo="fast-coding",
+)
+result = llm("Write a Python function to merge two sorted lists")
+print(result)
+```
+
+### Go — A2A Client
+
+```go
+package main
+
+import (
+ "bytes"
+ "encoding/json"
+ "fmt"
+ "io"
+ "net/http"
+)
+
+const baseURL = "http://localhost:20128"
+const apiKey = "your-api-key"
+
+type JsonRpcRequest struct {
+ Jsonrpc string `json:"jsonrpc"`
+ ID string `json:"id"`
+ Method string `json:"method"`
+ Params interface{} `json:"params"`
+}
+
+type JsonRpcResponse struct {
+ Jsonrpc string `json:"jsonrpc"`
+ ID string `json:"id"`
+ Result interface{} `json:"result"`
+ Error *struct {
+ Code int `json:"code"`
+ Message string `json:"message"`
+ } `json:"error"`
+}
+
+func a2aCall(method string, params interface{}) (*JsonRpcResponse, error) {
+ body, _ := json.Marshal(JsonRpcRequest{
+ Jsonrpc: "2.0",
+ ID: "go-1",
+ Method: method,
+ Params: params,
+ })
+
+ req, _ := http.NewRequest("POST", baseURL+"/a2a", bytes.NewReader(body))
+ req.Header.Set("Content-Type", "application/json")
+ req.Header.Set("Authorization", "Bearer "+apiKey)
+
+ resp, err := http.DefaultClient.Do(req)
+ if err != nil {
+ return nil, err
+ }
+ defer resp.Body.Close()
+ data, _ := io.ReadAll(resp.Body)
+
+ var result JsonRpcResponse
+ json.Unmarshal(data, &result)
+ return &result, nil
+}
+
+func main() {
+ // Discover agent
+ resp, _ := http.Get(baseURL + "/.well-known/agent.json")
+ defer resp.Body.Close()
+ body, _ := io.ReadAll(resp.Body)
+ fmt.Println("Agent Card:", string(body))
+
+ // Send smart-routing task
+ result, _ := a2aCall("message/send", map[string]interface{}{
+ "skill": "smart-routing",
+ "messages": []map[string]string{{"role": "user", "content": "Hello from Go!"}},
+ "metadata": map[string]interface{}{"model": "auto"},
+ })
+ out, _ := json.MarshalIndent(result.Result, "", " ")
+ fmt.Println("Result:", string(out))
+}
+```
+
+---
+
+## Use Cases
+
+### 🤖 Use Case 1: Multi-Agent Coding Pipeline
+
+An orchestrator agent delegates code generation to OmniRoute, then passes the output to a review agent.
+
+```python
+def coding_pipeline(task: str):
+ # Step 1: Generate code via OmniRoute A2A
+ code_result = a2a_send("smart-routing", [
+ {"role": "user", "content": f"Write production-quality code: {task}"}
+ ], metadata={"model": "auto", "role": "coding"})
+ code = code_result["artifacts"][0]["content"]
+
+ # Step 2: Review the code via OmniRoute A2A (different model)
+ review_result = a2a_send("smart-routing", [
+ {"role": "user", "content": f"Review this code for bugs and improvements:\n\n{code}"}
+ ], metadata={"model": "auto", "role": "review"})
+ review = review_result["artifacts"][0]["content"]
+
+ # Step 3: Check costs
+ print(f"Code cost: ${code_result['metadata']['cost_envelope']['actual']}")
+ print(f"Review cost: ${review_result['metadata']['cost_envelope']['actual']}")
+
+ return {"code": code, "review": review}
+```
+
+### 💡 Use Case 2: Quota-Aware Agent Swarm
+
+Multiple agents share quota through OmniRoute, using the quota skill to coordinate.
+
+```python
+async def quota_aware_agent(agent_name: str, task: str):
+ # Check quota before starting
+ quota = a2a_send("quota-management", [
+ {"role": "user", "content": "Which provider has the most quota remaining?"}
+ ])
+ print(f"[{agent_name}] {quota['artifacts'][0]['content']}")
+
+ # Send request with budget constraint
+ result = a2a_send("smart-routing", [
+ {"role": "user", "content": task}
+ ], metadata={"budget": 0.05})
+
+ policy = result["metadata"]["policy_verdict"]
+ if not policy["allowed"]:
+ print(f"[{agent_name}] ⚠️ Budget exceeded: {policy['reason']}")
+ # Fall back to free combo
+ quota = a2a_send("quota-management", [
+ {"role": "user", "content": "Suggest free combos"}
+ ])
+ print(f"[{agent_name}] Free alternatives: {quota['artifacts'][0]['content']}")
+
+ return result
+```
+
+### 📊 Use Case 3: Real-Time Streaming Dashboard
+
+A monitoring agent streams responses and displays progress in real-time.
+
+```typescript
+async function streamingDashboard(prompt: string) {
+ const response = await fetch(`${BASE_URL}/a2a`, {
+ method: "POST",
+ headers: { "Content-Type": "application/json", Authorization: `Bearer ${API_KEY}` },
+ body: JSON.stringify({
+ jsonrpc: "2.0",
+ id: "dash-1",
+ method: "message/stream",
+ params: { skill: "smart-routing", messages: [{ role: "user", content: prompt }] },
+ }),
+ });
+
+ let totalChunks = 0;
+ const reader = response.body!.getReader();
+ const decoder = new TextDecoder();
+
+ while (true) {
+ const { done, value } = await reader.read();
+ if (done) break;
+
+ for (const line of decoder.decode(value).split("\n")) {
+ if (line.startsWith("data: ")) {
+ const event = JSON.parse(line.slice(6));
+ const state = event.params.task.state;
+
+ if (state === "working" && event.params.chunk) {
+ totalChunks++;
+ process.stdout.write(
+ `\r[Chunk ${totalChunks}] ${event.params.chunk.content.slice(0, 50)}...`
+ );
+ }
+ if (state === "completed") {
+ const meta = event.params.metadata;
+ console.log(
+ `\n✅ Done | Cost: $${meta?.cost_envelope?.actual || 0} | Route: ${meta?.routing_explanation || "N/A"}`
+ );
+ }
+ if (state === "failed") {
+ console.error(`\n❌ Failed: ${event.params.metadata?.error}`);
+ }
+ }
+ }
+ }
+}
+```
+
+### 🔁 Use Case 4: Task Polling Pattern
+
+For long-running tasks, poll the task status instead of waiting synchronously.
+
+```python
+import time
+
+def poll_task(task_id: str, timeout: int = 60):
+ """Poll task status until completion or timeout."""
+ start = time.time()
+ while time.time() - start < timeout:
+ result = requests.post(f"{BASE_URL}/a2a", headers=HEADERS, json={
+ "jsonrpc": "2.0",
+ "id": "poll-1",
+ "method": "tasks/get",
+ "params": {"taskId": task_id},
+ }).json()
+
+ task = result["result"]["task"]
+ state = task["state"]
+ print(f" Task {task_id[:8]}... state={state}")
+
+ if state in ("completed", "failed", "cancelled"):
+ return task
+ time.sleep(2)
+
+ # Timeout — cancel the task
+ requests.post(f"{BASE_URL}/a2a", headers=HEADERS, json={
+ "jsonrpc": "2.0",
+ "id": "cancel-1",
+ "method": "tasks/cancel",
+ "params": {"taskId": task_id},
+ })
+ raise TimeoutError(f"Task {task_id} timed out after {timeout}s")
+```
+
+---
+
+## Error Codes
+
+| Code | Constant | Meaning |
+| ------ | ------------------------ | ---------------------------------------- |
+| -32700 | — | Parse error (invalid JSON) |
+| -32600 | `INVALID_REQUEST` | Invalid JSON-RPC request or unauthorized |
+| -32601 | `METHOD_NOT_FOUND` | Unknown method or skill |
+| -32602 | `INVALID_PARAMS` | Missing or invalid parameters |
+| -32603 | `INTERNAL_ERROR` | Skill execution failed |
+| -32001 | `TASK_NOT_FOUND` | Task ID not found |
+| -32002 | `TASK_ALREADY_COMPLETED` | Cannot modify a completed task |
+| -32003 | `UNAUTHORIZED` | Invalid or missing API key |
+| -32004 | `BUDGET_EXCEEDED` | Request exceeds configured budget |
+| -32005 | `PROVIDER_UNAVAILABLE` | No available providers |
+
+---
+
+## Authentication
+
+All `/a2a` requests require a Bearer token via the `Authorization` header:
+
+```
+Authorization: Bearer YOUR_OMNIROUTE_API_KEY
+```
+
+If no API key is configured on the server (`OMNIROUTE_API_KEY` is empty), authentication is bypassed.
+
+---
+
+## File Structure
+
+```
+src/lib/a2a/
+├── taskManager.ts # Task lifecycle (create/update/cancel/list), TTL, cleanup
+├── taskExecution.ts # Generic task executor with state management
+├── streaming.ts # SSE stream formatting, heartbeat, chunk/completion events
+├── routingLogger.ts # Routing decision logger (stats, history, retention)
+└── skills/
+ ├── smartRouting.ts # Smart routing skill (routes via /v1/chat/completions)
+ └── quotaManagement.ts # Quota management skill (natural-language quota queries)
+
+src/app/a2a/
+└── route.ts # Next.js API route handler (JSON-RPC 2.0 dispatch)
+
+open-sse/mcp-server/
+└── schemas/a2a.ts # Zod schemas (AgentCard, Task, JSON-RPC, SSE events)
+```
+
+---
+
+## Comparison: MCP vs A2A
+
+| Feature | MCP Server | A2A Server |
+| ----------------- | ---------------------------- | ------------------------------------------------- |
+| **Protocol** | Model Context Protocol | Agent-to-Agent Protocol v0.3 |
+| **Transport** | stdio / HTTP | HTTP (JSON-RPC 2.0) |
+| **Discovery** | Tool listing via MCP | `/.well-known/agent.json` |
+| **Granularity** | 16 individual tools | 2 high-level skills |
+| **Best for** | IDE agents (Cursor, VS Code) | Multi-agent systems (LangChain, CrewAI) |
+| **Streaming** | Not supported | SSE via `message/stream` |
+| **Task tracking** | No | Full lifecycle (submitted → completed) |
+| **Observability** | Audit log per tool call | Cost envelope + resilience trace + policy verdict |
+
+---
+
+## Lisenssi
+
+Part of [OmniRoute](https://github.com/diegosouzapw/OmniRoute) — MIT License.
diff --git a/docs/i18n/fr/A2A-SERVER.md b/docs/i18n/fr/A2A-SERVER.md
deleted file mode 100644
index 01531ff482..0000000000
--- a/docs/i18n/fr/A2A-SERVER.md
+++ /dev/null
@@ -1,200 +0,0 @@
-🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/A2A-SERVER.md) · 🇪🇸 [es](../es/A2A-SERVER.md) · 🇫🇷 [fr](../fr/A2A-SERVER.md) · 🇩🇪 [de](../de/A2A-SERVER.md) · 🇮🇹 [it](../it/A2A-SERVER.md) · 🇷🇺 [ru](../ru/A2A-SERVER.md) · 🇨🇳 [zh-CN](../zh-CN/A2A-SERVER.md) · 🇯🇵 [ja](../ja/A2A-SERVER.md) · 🇰🇷 [ko](../ko/A2A-SERVER.md) · 🇸🇦 [ar](../ar/A2A-SERVER.md) · 🇮🇳 [in](../in/A2A-SERVER.md) · 🇹🇭 [th](../th/A2A-SERVER.md) · 🇻🇳 [vi](../vi/A2A-SERVER.md) · 🇮🇩 [id](../id/A2A-SERVER.md) · 🇲🇾 [ms](../ms/A2A-SERVER.md) · 🇳🇱 [nl](../nl/A2A-SERVER.md) · 🇵🇱 [pl](../pl/A2A-SERVER.md) · 🇸🇪 [sv](../sv/A2A-SERVER.md) · 🇳🇴 [no](../no/A2A-SERVER.md) · 🇩🇰 [da](../da/A2A-SERVER.md) · 🇫🇮 [fi](../fi/A2A-SERVER.md) · 🇵🇹 [pt](../pt/A2A-SERVER.md) · 🇷🇴 [ro](../ro/A2A-SERVER.md) · 🇭🇺 [hu](../hu/A2A-SERVER.md) · 🇧🇬 [bg](../bg/A2A-SERVER.md) · 🇸🇰 [sk](../sk/A2A-SERVER.md) · 🇺🇦 [uk-UA](../uk-UA/A2A-SERVER.md) · 🇮🇱 [he](../he/A2A-SERVER.md) · 🇵🇭 [phi](../phi/A2A-SERVER.md)
-
----
-
-# OmniRoute A2A Server Documentation
-
-> Agent-to-Agent Protocol v0.3 — OmniRoute as an intelligent routing agent
-
-## Agent Discovery
-
-```bash
-curl http://localhost:20128/.well-known/agent.json
-```
-
-Returns the Agent Card describing OmniRoute's capabilities, skills, and authentication requirements.
-
----
-
-## Authentication
-
-All `/a2a` requests require an API key via the `Authorization` header:
-
-```
-Authorization: Bearer YOUR_OMNIROUTE_API_KEY
-```
-
-If no API key is configured on the server, authentication is bypassed.
-
----
-
-## JSON-RPC 2.0 Methods
-
-### `message/send` — Synchronous Execution
-
-Sends a message to a skill and waits for the complete response.
-
-```bash
-curl -X POST http://localhost:20128/a2a \
- -H "Content-Type: application/json" \
- -H "Authorization: Bearer YOUR_KEY" \
- -d '{
- "jsonrpc": "2.0",
- "id": "1",
- "method": "message/send",
- "params": {
- "skill": "smart-routing",
- "messages": [{"role": "user", "content": "Write a hello world in Python"}],
- "metadata": {"model": "auto", "combo": "fast-coding"}
- }
- }'
-```
-
-**Response:**
-
-```json
-{
- "jsonrpc": "2.0",
- "id": "1",
- "result": {
- "task": { "id": "uuid", "state": "completed" },
- "artifacts": [{ "type": "text", "content": "..." }],
- "metadata": {
- "routing_explanation": "Selected claude-sonnet via provider \"anthropic\" (latency: 1200ms, cost: $0.003)",
- "cost_envelope": { "estimated": 0.005, "actual": 0.003, "currency": "USD" },
- "resilience_trace": [
- { "event": "primary_selected", "provider": "anthropic", "timestamp": "..." }
- ],
- "policy_verdict": { "allowed": true, "reason": "within budget and quota limits" }
- }
- }
-}
-```
-
-### `message/stream` — SSE Streaming
-
-Same as `message/send` but returns Server-Sent Events for real-time streaming.
-
-```bash
-curl -N -X POST http://localhost:20128/a2a \
- -H "Content-Type: application/json" \
- -H "Authorization: Bearer YOUR_KEY" \
- -d '{
- "jsonrpc": "2.0",
- "id": "1",
- "method": "message/stream",
- "params": {
- "skill": "smart-routing",
- "messages": [{"role": "user", "content": "Explain quantum computing"}]
- }
- }'
-```
-
-**SSE Events:**
-
-```
-data: {"jsonrpc":"2.0","method":"message/stream","params":{"task":{"id":"...","state":"working"},"chunk":{"type":"text","content":"..."}}}
-
-: heartbeat 2026-03-03T17:00:00Z
-
-data: {"jsonrpc":"2.0","method":"message/stream","params":{"task":{"id":"...","state":"completed"},"metadata":{...}}}
-```
-
-### `tasks/get` — Query Task Status
-
-```bash
-curl -X POST http://localhost:20128/a2a \
- -H "Content-Type: application/json" \
- -H "Authorization: Bearer YOUR_KEY" \
- -d '{"jsonrpc":"2.0","id":"2","method":"tasks/get","params":{"taskId":"TASK_UUID"}}'
-```
-
-### `tasks/cancel` — Cancel a Task
-
-```bash
-curl -X POST http://localhost:20128/a2a \
- -H "Content-Type: application/json" \
- -H "Authorization: Bearer YOUR_KEY" \
- -d '{"jsonrpc":"2.0","id":"3","method":"tasks/cancel","params":{"taskId":"TASK_UUID"}}'
-```
-
----
-
-## Available Skills
-
-| Skill | Description |
-| :----------------- | :------------------------------------------------------------------------------------------------------------------------------ |
-| `smart-routing` | Routes prompts through OmniRoute's intelligent pipeline. Returns response with routing explanation, cost, and resilience trace. |
-| `quota-management` | Answers natural-language queries about provider quotas, suggests free combos, and provides quota rankings. |
-
----
-
-## Task Lifecycle
-
-```
-submitted → working → completed
- → failed
- → cancelled
-```
-
-- Tasks expire after 5 minutes (configurable)
-- Terminal states: `completed`, `failed`, `cancelled`
-- Event log tracks every state transition
-
----
-
-## Error Codes
-
-| Code | Meaning |
-| :----- | :----------------------------- |
-| -32700 | Parse error (invalid JSON) |
-| -32600 | Invalid request / Unauthorized |
-| -32601 | Method or skill not found |
-| -32602 | Invalid params |
-| -32603 | Internal error |
-
----
-
-## Integration Examples
-
-### Python (requests)
-
-```python
-import requests
-
-resp = requests.post("http://localhost:20128/a2a", json={
- "jsonrpc": "2.0", "id": "1",
- "method": "message/send",
- "params": {
- "skill": "smart-routing",
- "messages": [{"role": "user", "content": "Hello"}]
- }
-}, headers={"Authorization": "Bearer YOUR_KEY"})
-
-result = resp.json()["result"]
-print(result["artifacts"][0]["content"])
-print(result["metadata"]["routing_explanation"])
-```
-
-### TypeScript (fetch)
-
-```typescript
-const resp = await fetch("http://localhost:20128/a2a", {
- method: "POST",
- headers: {
- "Content-Type": "application/json",
- Authorization: "Bearer YOUR_KEY",
- },
- body: JSON.stringify({
- jsonrpc: "2.0",
- id: "1",
- method: "message/send",
- params: {
- skill: "smart-routing",
- messages: [{ role: "user", content: "Hello" }],
- },
- }),
-});
-const { result } = await resp.json();
-console.log(result.metadata.routing_explanation);
-```
diff --git a/docs/i18n/fr/API_REFERENCE.md b/docs/i18n/fr/API_REFERENCE.md
deleted file mode 100644
index b878605221..0000000000
--- a/docs/i18n/fr/API_REFERENCE.md
+++ /dev/null
@@ -1,455 +0,0 @@
-🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/API_REFERENCE.md) · 🇪🇸 [es](../es/API_REFERENCE.md) · 🇫🇷 [fr](../fr/API_REFERENCE.md) · 🇩🇪 [de](../de/API_REFERENCE.md) · 🇮🇹 [it](../it/API_REFERENCE.md) · 🇷🇺 [ru](../ru/API_REFERENCE.md) · 🇨🇳 [zh-CN](../zh-CN/API_REFERENCE.md) · 🇯🇵 [ja](../ja/API_REFERENCE.md) · 🇰🇷 [ko](../ko/API_REFERENCE.md) · 🇸🇦 [ar](../ar/API_REFERENCE.md) · 🇮🇳 [in](../in/API_REFERENCE.md) · 🇹🇭 [th](../th/API_REFERENCE.md) · 🇻🇳 [vi](../vi/API_REFERENCE.md) · 🇮🇩 [id](../id/API_REFERENCE.md) · 🇲🇾 [ms](../ms/API_REFERENCE.md) · 🇳🇱 [nl](../nl/API_REFERENCE.md) · 🇵🇱 [pl](../pl/API_REFERENCE.md) · 🇸🇪 [sv](../sv/API_REFERENCE.md) · 🇳🇴 [no](../no/API_REFERENCE.md) · 🇩🇰 [da](../da/API_REFERENCE.md) · 🇫🇮 [fi](../fi/API_REFERENCE.md) · 🇵🇹 [pt](../pt/API_REFERENCE.md) · 🇷🇴 [ro](../ro/API_REFERENCE.md) · 🇭🇺 [hu](../hu/API_REFERENCE.md) · 🇧🇬 [bg](../bg/API_REFERENCE.md) · 🇸🇰 [sk](../sk/API_REFERENCE.md) · 🇺🇦 [uk-UA](../uk-UA/API_REFERENCE.md) · 🇮🇱 [he](../he/API_REFERENCE.md) · 🇵🇭 [phi](../phi/API_REFERENCE.md)
-
----
-
-# API Reference
-
-🌐 **Languages:** 🇺🇸 [English](API_REFERENCE.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/API_REFERENCE.md) | 🇪🇸 [Español](i18n/es/API_REFERENCE.md) | 🇫🇷 [Français](i18n/fr/API_REFERENCE.md) | 🇮🇹 [Italiano](i18n/it/API_REFERENCE.md) | 🇷🇺 [Русский](i18n/ru/API_REFERENCE.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/API_REFERENCE.md) | 🇩🇪 [Deutsch](i18n/de/API_REFERENCE.md) | 🇮🇳 [हिन्दी](i18n/in/API_REFERENCE.md) | 🇹🇭 [ไทย](i18n/th/API_REFERENCE.md) | 🇺🇦 [Українська](i18n/uk-UA/API_REFERENCE.md) | 🇸🇦 [العربية](i18n/ar/API_REFERENCE.md) | 🇯🇵 [日本語](i18n/ja/API_REFERENCE.md) | 🇻🇳 [Tiếng Việt](i18n/vi/API_REFERENCE.md) | 🇧🇬 [Български](i18n/bg/API_REFERENCE.md) | 🇩🇰 [Dansk](i18n/da/API_REFERENCE.md) | 🇫🇮 [Suomi](i18n/fi/API_REFERENCE.md) | 🇮🇱 [עברית](i18n/he/API_REFERENCE.md) | 🇭🇺 [Magyar](i18n/hu/API_REFERENCE.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/API_REFERENCE.md) | 🇰🇷 [한국어](i18n/ko/API_REFERENCE.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/API_REFERENCE.md) | 🇳🇱 [Nederlands](i18n/nl/API_REFERENCE.md) | 🇳🇴 [Norsk](i18n/no/API_REFERENCE.md) | 🇵🇹 [Português (Portugal)](i18n/pt/API_REFERENCE.md) | 🇷🇴 [Română](i18n/ro/API_REFERENCE.md) | 🇵🇱 [Polski](i18n/pl/API_REFERENCE.md) | 🇸🇰 [Slovenčina](i18n/sk/API_REFERENCE.md) | 🇸🇪 [Svenska](i18n/sv/API_REFERENCE.md) | 🇵🇭 [Filipino](i18n/phi/API_REFERENCE.md)
-
-Complete reference for all OmniRoute API endpoints.
-
----
-
-## Table of Contents
-
-- [Chat Completions](#chat-completions)
-- [Embeddings](#embeddings)
-- [Image Generation](#image-generation)
-- [List Models](#list-models)
-- [Compatibility Endpoints](#compatibility-endpoints)
-- [Semantic Cache](#semantic-cache)
-- [Dashboard & Management](#dashboard--management)
-- [Request Processing](#request-processing)
-- [Authentication](#authentication)
-
----
-
-## Chat Completions
-
-```bash
-POST /v1/chat/completions
-Authorization: Bearer your-api-key
-Content-Type: application/json
-
-{
- "model": "cc/claude-opus-4-6",
- "messages": [
- {"role": "user", "content": "Write a function to..."}
- ],
- "stream": true
-}
-```
-
-### Custom Headers
-
-| Header | Direction | Description |
-| ------------------------ | --------- | --------------------------------- |
-| `X-OmniRoute-No-Cache` | Request | Set to `true` to bypass cache |
-| `X-OmniRoute-Progress` | Request | Set to `true` for progress events |
-| `Idempotency-Key` | Request | Dedup key (5s window) |
-| `X-Request-Id` | Request | Alternative dedup key |
-| `X-OmniRoute-Cache` | Response | `HIT` or `MISS` (non-streaming) |
-| `X-OmniRoute-Idempotent` | Response | `true` if deduplicated |
-| `X-OmniRoute-Progress` | Response | `enabled` if progress tracking on |
-
----
-
-## Embeddings
-
-```bash
-POST /v1/embeddings
-Authorization: Bearer your-api-key
-Content-Type: application/json
-
-{
- "model": "nebius/Qwen/Qwen3-Embedding-8B",
- "input": "The food was delicious"
-}
-```
-
-Available providers: Nebius, OpenAI, Mistral, Together AI, Fireworks, NVIDIA.
-
-```bash
-# List all embedding models
-GET /v1/embeddings
-```
-
----
-
-## Image Generation
-
-```bash
-POST /v1/images/generations
-Authorization: Bearer your-api-key
-Content-Type: application/json
-
-{
- "model": "openai/dall-e-3",
- "prompt": "A beautiful sunset over mountains",
- "size": "1024x1024"
-}
-```
-
-Available providers: OpenAI (DALL-E), xAI (Grok Image), Together AI (FLUX), Fireworks AI.
-
-```bash
-# List all image models
-GET /v1/images/generations
-```
-
----
-
-## List Models
-
-```bash
-GET /v1/models
-Authorization: Bearer your-api-key
-
-→ Returns all chat, embedding, and image models + combos in OpenAI format
-```
-
----
-
-## Compatibility Endpoints
-
-| Method | Path | Format |
-| ------ | --------------------------- | ---------------------- |
-| POST | `/v1/chat/completions` | OpenAI |
-| POST | `/v1/messages` | Anthropic |
-| POST | `/v1/responses` | OpenAI Responses |
-| POST | `/v1/embeddings` | OpenAI |
-| POST | `/v1/images/generations` | OpenAI |
-| GET | `/v1/models` | OpenAI |
-| POST | `/v1/messages/count_tokens` | Anthropic |
-| GET | `/v1beta/models` | Gemini |
-| POST | `/v1beta/models/{...path}` | Gemini generateContent |
-| POST | `/v1/api/chat` | Ollama |
-
-### Dedicated Provider Routes
-
-```bash
-POST /v1/providers/{provider}/chat/completions
-POST /v1/providers/{provider}/embeddings
-POST /v1/providers/{provider}/images/generations
-```
-
-The provider prefix is auto-added if missing. Mismatched models return `400`.
-
----
-
-## Semantic Cache
-
-```bash
-# Get cache stats
-GET /api/cache
-
-# Clear all caches
-DELETE /api/cache
-```
-
-Response example:
-
-```json
-{
- "semanticCache": {
- "memorySize": 42,
- "memoryMaxSize": 500,
- "dbSize": 128,
- "hitRate": 0.65
- },
- "idempotency": {
- "activeKeys": 3,
- "windowMs": 5000
- }
-}
-```
-
----
-
-## Dashboard & Management
-
-### Authentication
-
-| Endpoint | Method | Description |
-| ----------------------------- | ------- | --------------------- |
-| `/api/auth/login` | POST | Login |
-| `/api/auth/logout` | POST | Logout |
-| `/api/settings/require-login` | GET/PUT | Toggle login required |
-
-### Provider Management
-
-| Endpoint | Method | Description |
-| ---------------------------- | --------------- | ------------------------ |
-| `/api/providers` | GET/POST | List / create providers |
-| `/api/providers/[id]` | GET/PUT/DELETE | Manage a provider |
-| `/api/providers/[id]/test` | POST | Test provider connection |
-| `/api/providers/[id]/models` | GET | List provider models |
-| `/api/providers/validate` | POST | Validate provider config |
-| `/api/provider-nodes*` | Various | Provider node management |
-| `/api/provider-models` | GET/POST/DELETE | Custom models |
-
-### OAuth Flows
-
-| Endpoint | Method | Description |
-| -------------------------------- | ------- | ----------------------- |
-| `/api/oauth/[provider]/[action]` | Various | Provider-specific OAuth |
-
-### Routing & Config
-
-| Endpoint | Method | Description |
-| --------------------- | -------- | ----------------------------- |
-| `/api/models/alias` | GET/POST | Model aliases |
-| `/api/models/catalog` | GET | All models by provider + type |
-| `/api/combos*` | Various | Combo management |
-| `/api/keys*` | Various | API key management |
-| `/api/pricing` | GET | Model pricing |
-
-### Usage & Analytics
-
-| Endpoint | Method | Description |
-| --------------------------- | ------ | -------------------- |
-| `/api/usage/history` | GET | Usage history |
-| `/api/usage/logs` | GET | Usage logs |
-| `/api/usage/request-logs` | GET | Request-level logs |
-| `/api/usage/[connectionId]` | GET | Per-connection usage |
-
-### Settings
-
-| Endpoint | Method | Description |
-| ------------------------------- | ------- | ---------------------- |
-| `/api/settings` | GET/PUT | General settings |
-| `/api/settings/proxy` | GET/PUT | Network proxy config |
-| `/api/settings/proxy/test` | POST | Test proxy connection |
-| `/api/settings/ip-filter` | GET/PUT | IP allowlist/blocklist |
-| `/api/settings/thinking-budget` | GET/PUT | Reasoning token budget |
-| `/api/settings/system-prompt` | GET/PUT | Global system prompt |
-
-### Monitoring
-
-| Endpoint | Method | Description |
-| ------------------------ | ---------- | ----------------------- |
-| `/api/sessions` | GET | Active session tracking |
-| `/api/rate-limits` | GET | Per-account rate limits |
-| `/api/monitoring/health` | GET | Health check |
-| `/api/cache` | GET/DELETE | Cache stats / clear |
-
-### Backup & Export/Import
-
-| Endpoint | Method | Description |
-| --------------------------- | ------ | --------------------------------------- |
-| `/api/db-backups` | GET | List available backups |
-| `/api/db-backups` | PUT | Create a manual backup |
-| `/api/db-backups` | POST | Restore from a specific backup |
-| `/api/db-backups/export` | GET | Download database as .sqlite file |
-| `/api/db-backups/import` | POST | Upload .sqlite file to replace database |
-| `/api/db-backups/exportAll` | GET | Download full backup as .tar.gz archive |
-
-### Cloud Sync
-
-| Endpoint | Method | Description |
-| ---------------------- | ------- | --------------------- |
-| `/api/sync/cloud` | Various | Cloud sync operations |
-| `/api/sync/initialize` | POST | Initialize sync |
-| `/api/cloud/*` | Various | Cloud management |
-
-### CLI Tools
-
-| Endpoint | Method | Description |
-| ---------------------------------- | ------ | ------------------- |
-| `/api/cli-tools/claude-settings` | GET | Claude CLI status |
-| `/api/cli-tools/codex-settings` | GET | Codex CLI status |
-| `/api/cli-tools/droid-settings` | GET | Droid CLI status |
-| `/api/cli-tools/openclaw-settings` | GET | OpenClaw CLI status |
-| `/api/cli-tools/runtime/[toolId]` | GET | Generic CLI runtime |
-
-CLI responses include: `installed`, `runnable`, `command`, `commandPath`, `runtimeMode`, `reason`.
-
-### ACP Agents
-
-| Endpoint | Method | Description |
-| ----------------- | ------ | -------------------------------------------------------- |
-| `/api/acp/agents` | GET | List all detected agents (built-in + custom) with status |
-| `/api/acp/agents` | POST | Add custom agent or refresh detection cache |
-| `/api/acp/agents` | DELETE | Remove a custom agent by `id` query param |
-
-GET response includes `agents[]` (id, name, binary, version, installed, protocol, isCustom) and `summary` (total, installed, notFound, builtIn, custom).
-
-### Resilience & Rate Limits
-
-| Endpoint | Method | Description |
-| ----------------------- | ------- | ------------------------------- |
-| `/api/resilience` | GET/PUT | Get/update resilience profiles |
-| `/api/resilience/reset` | POST | Reset circuit breakers |
-| `/api/rate-limits` | GET | Per-account rate limit status |
-| `/api/rate-limit` | GET | Global rate limit configuration |
-
-### Evals
-
-| Endpoint | Method | Description |
-| ------------ | -------- | --------------------------------- |
-| `/api/evals` | GET/POST | List eval suites / run evaluation |
-
-### Policies
-
-| Endpoint | Method | Description |
-| --------------- | --------------- | ----------------------- |
-| `/api/policies` | GET/POST/DELETE | Manage routing policies |
-
-### Compliance
-
-| Endpoint | Method | Description |
-| --------------------------- | ------ | ----------------------------- |
-| `/api/compliance/audit-log` | GET | Compliance audit log (last N) |
-
-### v1beta (Gemini-Compatible)
-
-| Endpoint | Method | Description |
-| -------------------------- | ------ | --------------------------------- |
-| `/v1beta/models` | GET | List models in Gemini format |
-| `/v1beta/models/{...path}` | POST | Gemini `generateContent` endpoint |
-
-These endpoints mirror Gemini's API format for clients that expect native Gemini SDK compatibility.
-
-### Internal / System APIs
-
-| Endpoint | Method | Description |
-| --------------- | ------ | ---------------------------------------------------- |
-| `/api/init` | GET | Application initialization check (used on first run) |
-| `/api/tags` | GET | Ollama-compatible model tags (for Ollama clients) |
-| `/api/restart` | POST | Trigger graceful server restart |
-| `/api/shutdown` | POST | Trigger graceful server shutdown |
-
-> **Note:** These endpoints are used internally by the system or for Ollama client compatibility. They are not typically called by end users.
-
----
-
-## Audio Transcription
-
-```bash
-POST /v1/audio/transcriptions
-Authorization: Bearer your-api-key
-Content-Type: multipart/form-data
-```
-
-Transcribe audio files using Deepgram or AssemblyAI.
-
-**Request:**
-
-```bash
-curl -X POST http://localhost:20128/v1/audio/transcriptions \
- -H "Authorization: Bearer your-api-key" \
- -F "file=@recording.mp3" \
- -F "model=deepgram/nova-3"
-```
-
-**Response:**
-
-```json
-{
- "text": "Hello, this is the transcribed audio content.",
- "task": "transcribe",
- "language": "en",
- "duration": 12.5
-}
-```
-
-**Supported providers:** `deepgram/nova-3`, `assemblyai/best`.
-
-**Supported formats:** `mp3`, `wav`, `m4a`, `flac`, `ogg`, `webm`.
-
----
-
-## Ollama Compatibility
-
-For clients that use Ollama's API format:
-
-```bash
-# Chat endpoint (Ollama format)
-POST /v1/api/chat
-
-# Model listing (Ollama format)
-GET /api/tags
-```
-
-Requests are automatically translated between Ollama and internal formats.
-
----
-
-## Telemetry
-
-```bash
-# Get latency telemetry summary (p50/p95/p99 per provider)
-GET /api/telemetry/summary
-```
-
-**Response:**
-
-```json
-{
- "providers": {
- "claudeCode": { "p50": 245, "p95": 890, "p99": 1200, "count": 150 },
- "github": { "p50": 180, "p95": 620, "p99": 950, "count": 320 }
- }
-}
-```
-
----
-
-## Budget
-
-```bash
-# Get budget status for all API keys
-GET /api/usage/budget
-
-# Set or update a budget
-POST /api/usage/budget
-Content-Type: application/json
-
-{
- "keyId": "key-123",
- "limit": 50.00,
- "period": "monthly"
-}
-```
-
----
-
-## Model Availability
-
-```bash
-# Get real-time model availability across all providers
-GET /api/models/availability
-
-# Check availability for a specific model
-POST /api/models/availability
-Content-Type: application/json
-
-{
- "model": "claude-sonnet-4-5-20250929"
-}
-```
-
----
-
-## Request Processing
-
-1. Client sends request to `/v1/*`
-2. Route handler calls `handleChat`, `handleEmbedding`, `handleAudioTranscription`, or `handleImageGeneration`
-3. Model is resolved (direct provider/model or alias/combo)
-4. Credentials selected from local DB with account availability filtering
-5. For chat: `handleChatCore` — format detection, translation, cache check, idempotency check
-6. Provider executor sends upstream request
-7. Response translated back to client format (chat) or returned as-is (embeddings/images/audio)
-8. Usage/logging recorded
-9. Fallback applies on errors according to combo rules
-
-Full architecture reference: [`ARCHITECTURE.md`](ARCHITECTURE.md)
-
----
-
-## Authentication
-
-- Dashboard routes (`/dashboard/*`) use `auth_token` cookie
-- Login uses saved password hash; fallback to `INITIAL_PASSWORD`
-- `requireLogin` toggleable via `/api/settings/require-login`
-- `/v1/*` routes optionally require Bearer API key when `REQUIRE_API_KEY=true`
diff --git a/docs/i18n/fr/ARCHITECTURE.md b/docs/i18n/fr/ARCHITECTURE.md
deleted file mode 100644
index 4ea06a29f2..0000000000
--- a/docs/i18n/fr/ARCHITECTURE.md
+++ /dev/null
@@ -1,787 +0,0 @@
-🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/ARCHITECTURE.md) · 🇪🇸 [es](../es/ARCHITECTURE.md) · 🇫🇷 [fr](../fr/ARCHITECTURE.md) · 🇩🇪 [de](../de/ARCHITECTURE.md) · 🇮🇹 [it](../it/ARCHITECTURE.md) · 🇷🇺 [ru](../ru/ARCHITECTURE.md) · 🇨🇳 [zh-CN](../zh-CN/ARCHITECTURE.md) · 🇯🇵 [ja](../ja/ARCHITECTURE.md) · 🇰🇷 [ko](../ko/ARCHITECTURE.md) · 🇸🇦 [ar](../ar/ARCHITECTURE.md) · 🇮🇳 [in](../in/ARCHITECTURE.md) · 🇹🇭 [th](../th/ARCHITECTURE.md) · 🇻🇳 [vi](../vi/ARCHITECTURE.md) · 🇮🇩 [id](../id/ARCHITECTURE.md) · 🇲🇾 [ms](../ms/ARCHITECTURE.md) · 🇳🇱 [nl](../nl/ARCHITECTURE.md) · 🇵🇱 [pl](../pl/ARCHITECTURE.md) · 🇸🇪 [sv](../sv/ARCHITECTURE.md) · 🇳🇴 [no](../no/ARCHITECTURE.md) · 🇩🇰 [da](../da/ARCHITECTURE.md) · 🇫🇮 [fi](../fi/ARCHITECTURE.md) · 🇵🇹 [pt](../pt/ARCHITECTURE.md) · 🇷🇴 [ro](../ro/ARCHITECTURE.md) · 🇭🇺 [hu](../hu/ARCHITECTURE.md) · 🇧🇬 [bg](../bg/ARCHITECTURE.md) · 🇸🇰 [sk](../sk/ARCHITECTURE.md) · 🇺🇦 [uk-UA](../uk-UA/ARCHITECTURE.md) · 🇮🇱 [he](../he/ARCHITECTURE.md) · 🇵🇭 [phi](../phi/ARCHITECTURE.md)
-
----
-
-# OmniRoute Architecture
-
-🌐 **Languages:** 🇺🇸 [English](ARCHITECTURE.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/ARCHITECTURE.md) | 🇪🇸 [Español](i18n/es/ARCHITECTURE.md) | 🇫🇷 [Français](i18n/fr/ARCHITECTURE.md) | 🇮🇹 [Italiano](i18n/it/ARCHITECTURE.md) | 🇷🇺 [Русский](i18n/ru/ARCHITECTURE.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/ARCHITECTURE.md) | 🇩🇪 [Deutsch](i18n/de/ARCHITECTURE.md) | 🇮🇳 [हिन्दी](i18n/in/ARCHITECTURE.md) | 🇹🇭 [ไทย](i18n/th/ARCHITECTURE.md) | 🇺🇦 [Українська](i18n/uk-UA/ARCHITECTURE.md) | 🇸🇦 [العربية](i18n/ar/ARCHITECTURE.md) | 🇯🇵 [日本語](i18n/ja/ARCHITECTURE.md) | 🇻🇳 [Tiếng Việt](i18n/vi/ARCHITECTURE.md) | 🇧🇬 [Български](i18n/bg/ARCHITECTURE.md) | 🇩🇰 [Dansk](i18n/da/ARCHITECTURE.md) | 🇫🇮 [Suomi](i18n/fi/ARCHITECTURE.md) | 🇮🇱 [עברית](i18n/he/ARCHITECTURE.md) | 🇭🇺 [Magyar](i18n/hu/ARCHITECTURE.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/ARCHITECTURE.md) | 🇰🇷 [한국어](i18n/ko/ARCHITECTURE.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/ARCHITECTURE.md) | 🇳🇱 [Nederlands](i18n/nl/ARCHITECTURE.md) | 🇳🇴 [Norsk](i18n/no/ARCHITECTURE.md) | 🇵🇹 [Português (Portugal)](i18n/pt/ARCHITECTURE.md) | 🇷🇴 [Română](i18n/ro/ARCHITECTURE.md) | 🇵🇱 [Polski](i18n/pl/ARCHITECTURE.md) | 🇸🇰 [Slovenčina](i18n/sk/ARCHITECTURE.md) | 🇸🇪 [Svenska](i18n/sv/ARCHITECTURE.md) | 🇵🇭 [Filipino](i18n/phi/ARCHITECTURE.md)
-
-_Last updated: 2026-03-04_
-
-## Executive Summary
-
-OmniRoute is a local AI routing gateway and dashboard built on Next.js.
-It provides a single OpenAI-compatible endpoint (`/v1/*`) and routes traffic across multiple upstream providers with translation, fallback, token refresh, and usage tracking.
-
-Core capabilities:
-
-- OpenAI-compatible API surface for CLI/tools (28 providers)
-- Request/response translation across provider formats
-- Model combo fallback (multi-model sequence)
-- Account-level fallback (multi-account per provider)
-- OAuth + API-key provider connection management
-- Embedding generation via `/v1/embeddings` (6 providers, 9 models)
-- Image generation via `/v1/images/generations` (4 providers, 9 models)
-- Think tag parsing (`...`) for reasoning models
-- Response sanitization for strict OpenAI SDK compatibility
-- Role normalization (developer→system, system→user) for cross-provider compatibility
-- Structured output conversion (json_schema → Gemini responseSchema)
-- Local persistence for providers, keys, aliases, combos, settings, pricing
-- Usage/cost tracking and request logging
-- Optional cloud sync for multi-device/state sync
-- IP allowlist/blocklist for API access control
-- Thinking budget management (passthrough/auto/custom/adaptive)
-- Global system prompt injection
-- Session tracking and fingerprinting
-- Per-account enhanced rate limiting with provider-specific profiles
-- Circuit breaker pattern for provider resilience
-- Anti-thundering herd protection with mutex locking
-- Signature-based request deduplication cache
-- Domain layer: model availability, cost rules, fallback policy, lockout policy
-- Domain state persistence (SQLite write-through cache for fallbacks, budgets, lockouts, circuit breakers)
-- Policy engine for centralized request evaluation (lockout → budget → fallback)
-- Request telemetry with p50/p95/p99 latency aggregation
-- Correlation ID (X-Request-Id) for end-to-end tracing
-- Compliance audit logging with opt-out per API key
-- Eval framework for LLM quality assurance
-- Resilience UI dashboard with real-time circuit breaker status
-- Modular OAuth providers (12 individual modules under `src/lib/oauth/providers/`)
-
-Primary runtime model:
-
-- Next.js app routes under `src/app/api/*` implement both dashboard APIs and compatibility APIs
-- A shared SSE/routing core in `src/sse/*` + `open-sse/*` handles provider execution, translation, streaming, fallback, and usage
-
-## Scope and Boundaries
-
-### In Scope
-
-- Local gateway runtime
-- Dashboard management APIs
-- Provider authentication and token refresh
-- Request translation and SSE streaming
-- Local state + usage persistence
-- Optional cloud sync orchestration
-
-### Out of Scope
-
-- Cloud service implementation behind `NEXT_PUBLIC_CLOUD_URL`
-- Provider SLA/control plane outside local process
-- External CLI binaries themselves (Claude CLI, Codex CLI, etc.)
-
-## High-Level System Context
-
-```mermaid
-flowchart LR
- subgraph Clients[Developer Clients]
- C1[Claude Code]
- C2[Codex CLI]
- C3[OpenClaw / Droid / Cline / Continue / Roo]
- C4[Custom OpenAI-compatible clients]
- BROWSER[Browser Dashboard]
- end
-
- subgraph Router[OmniRoute Local Process]
- API[V1 Compatibility API\n/v1/*]
- DASH[Dashboard + Management API\n/api/*]
- CORE[SSE + Translation Core\nopen-sse + src/sse]
- DB[(storage.sqlite)]
- UDB[(usage tables + log artifacts)]
- end
-
- subgraph Upstreams[Upstream Providers]
- P1[OAuth Providers\nClaude/Codex/Gemini/Qwen/Qoder/GitHub/Kiro/Cursor/Antigravity]
- P2[API Key Providers\nOpenAI/Anthropic/OpenRouter/GLM/Kimi/MiniMax\nDeepSeek/Groq/xAI/Mistral/Perplexity\nTogether/Fireworks/Cerebras/Cohere/NVIDIA]
- P3[Compatible Nodes\nOpenAI-compatible / Anthropic-compatible]
- end
-
- subgraph Cloud[Optional Cloud Sync]
- CLOUD[Cloud Sync Endpoint\nNEXT_PUBLIC_CLOUD_URL]
- end
-
- C1 --> API
- C2 --> API
- C3 --> API
- C4 --> API
- BROWSER --> DASH
-
- API --> CORE
- DASH --> DB
- CORE --> DB
- CORE --> UDB
-
- CORE --> P1
- CORE --> P2
- CORE --> P3
-
- DASH --> CLOUD
-```
-
-## Core Runtime Components
-
-## 1) API and Routing Layer (Next.js App Routes)
-
-Main directories:
-
-- `src/app/api/v1/*` and `src/app/api/v1beta/*` for compatibility APIs
-- `src/app/api/*` for management/configuration APIs
-- Next rewrites in `next.config.mjs` map `/v1/*` to `/api/v1/*`
-
-Important compatibility routes:
-
-- `src/app/api/v1/chat/completions/route.ts`
-- `src/app/api/v1/messages/route.ts`
-- `src/app/api/v1/responses/route.ts`
-- `src/app/api/v1/models/route.ts` — includes custom models with `custom: true`
-- `src/app/api/v1/embeddings/route.ts` — embedding generation (6 providers)
-- `src/app/api/v1/images/generations/route.ts` — image generation (4+ providers incl. Antigravity/Nebius)
-- `src/app/api/v1/messages/count_tokens/route.ts`
-- `src/app/api/v1/providers/[provider]/chat/completions/route.ts` — dedicated per-provider chat
-- `src/app/api/v1/providers/[provider]/embeddings/route.ts` — dedicated per-provider embeddings
-- `src/app/api/v1/providers/[provider]/images/generations/route.ts` — dedicated per-provider images
-- `src/app/api/v1beta/models/route.ts`
-- `src/app/api/v1beta/models/[...path]/route.ts`
-
-Management domains:
-
-- Auth/settings: `src/app/api/auth/*`, `src/app/api/settings/*`
-- Providers/connections: `src/app/api/providers*`
-- Provider nodes: `src/app/api/provider-nodes*`
-- Custom models: `src/app/api/provider-models` (GET/POST/DELETE)
-- Model catalog: `src/app/api/models/route.ts` (GET)
-- Proxy config: `src/app/api/settings/proxy` (GET/PUT/DELETE) + `src/app/api/settings/proxy/test` (POST)
-- OAuth: `src/app/api/oauth/*`
-- Keys/aliases/combos/pricing: `src/app/api/keys*`, `src/app/api/models/alias`, `src/app/api/combos*`, `src/app/api/pricing`
-- Usage: `src/app/api/usage/*`
-- Sync/cloud: `src/app/api/sync/*`, `src/app/api/cloud/*`
-- CLI tooling helpers: `src/app/api/cli-tools/*`
-- IP filter: `src/app/api/settings/ip-filter` (GET/PUT)
-- Thinking budget: `src/app/api/settings/thinking-budget` (GET/PUT)
-- System prompt: `src/app/api/settings/system-prompt` (GET/PUT)
-- Sessions: `src/app/api/sessions` (GET)
-- Rate limits: `src/app/api/rate-limits` (GET)
-- Resilience: `src/app/api/resilience` (GET/PATCH) — provider profiles, circuit breaker, rate limit state
-- Resilience reset: `src/app/api/resilience/reset` (POST) — reset breakers + cooldowns
-- Cache stats: `src/app/api/cache/stats` (GET/DELETE)
-- Model availability: `src/app/api/models/availability` (GET/POST)
-- Telemetry: `src/app/api/telemetry/summary` (GET)
-- Budget: `src/app/api/usage/budget` (GET/POST)
-- Fallback chains: `src/app/api/fallback/chains` (GET/POST/DELETE)
-- Compliance audit: `src/app/api/compliance/audit-log` (GET)
-- Evals: `src/app/api/evals` (GET/POST), `src/app/api/evals/[suiteId]` (GET)
-- Policies: `src/app/api/policies` (GET/POST)
-
-## 2) SSE + Translation Core
-
-Main flow modules:
-
-- Entry: `src/sse/handlers/chat.ts`
-- Core orchestration: `open-sse/handlers/chatCore.ts`
-- Provider execution adapters: `open-sse/executors/*`
-- Format detection/provider config: `open-sse/services/provider.ts`
-- Model parse/resolve: `src/sse/services/model.ts`, `open-sse/services/model.ts`
-- Account fallback logic: `open-sse/services/accountFallback.ts`
-- Translation registry: `open-sse/translator/index.ts`
-- Stream transformations: `open-sse/utils/stream.ts`, `open-sse/utils/streamHandler.ts`
-- Usage extraction/normalization: `open-sse/utils/usageTracking.ts`
-- Think tag parser: `open-sse/utils/thinkTagParser.ts`
-- Embedding handler: `open-sse/handlers/embeddings.ts`
-- Embedding provider registry: `open-sse/config/embeddingRegistry.ts`
-- Image generation handler: `open-sse/handlers/imageGeneration.ts`
-- Image provider registry: `open-sse/config/imageRegistry.ts`
-- Response sanitization: `open-sse/handlers/responseSanitizer.ts`
-- Role normalization: `open-sse/services/roleNormalizer.ts`
-
-Services (business logic):
-
-- Account selection/scoring: `open-sse/services/accountSelector.ts`
-- Context lifecycle management: `open-sse/services/contextManager.ts`
-- IP filter enforcement: `open-sse/services/ipFilter.ts`
-- Session tracking: `open-sse/services/sessionManager.ts`
-- Request deduplication: `open-sse/services/signatureCache.ts`
-- System prompt injection: `open-sse/services/systemPrompt.ts`
-- Thinking budget management: `open-sse/services/thinkingBudget.ts`
-- Wildcard model routing: `open-sse/services/wildcardRouter.ts`
-- Rate limit management: `open-sse/services/rateLimitManager.ts`
-- Circuit breaker: `open-sse/services/circuitBreaker.ts`
-
-Domain layer modules:
-
-- Model availability: `src/lib/domain/modelAvailability.ts`
-- Cost rules/budgets: `src/lib/domain/costRules.ts`
-- Fallback policy: `src/lib/domain/fallbackPolicy.ts`
-- Combo resolver: `src/lib/domain/comboResolver.ts`
-- Lockout policy: `src/lib/domain/lockoutPolicy.ts`
-- Policy engine: `src/domain/policyEngine.ts` — centralized lockout → budget → fallback evaluation
-- Error codes catalog: `src/lib/domain/errorCodes.ts`
-- Request ID: `src/lib/domain/requestId.ts`
-- Fetch timeout: `src/lib/domain/fetchTimeout.ts`
-- Request telemetry: `src/lib/domain/requestTelemetry.ts`
-- Compliance/audit: `src/lib/domain/compliance/index.ts`
-- Eval runner: `src/lib/domain/evalRunner.ts`
-- Domain state persistence: `src/lib/db/domainState.ts` — SQLite CRUD for fallback chains, budgets, cost history, lockout state, circuit breakers
-
-OAuth provider modules (12 individual files under `src/lib/oauth/providers/`):
-
-- Registry index: `src/lib/oauth/providers/index.ts`
-- Individual providers: `claude.ts`, `codex.ts`, `gemini.ts`, `antigravity.ts`, `qoder.ts`, `qwen.ts`, `kimi-coding.ts`, `github.ts`, `kiro.ts`, `cursor.ts`, `kilocode.ts`, `cline.ts`
-- Thin wrapper: `src/lib/oauth/providers.ts` — re-exports from individual modules
-
-## 3) Persistence Layer
-
-Primary state DB (SQLite):
-
-- Core infra: `src/lib/db/core.ts` (better-sqlite3, migrations, WAL)
-- Re-export facade: `src/lib/localDb.ts` (thin compatibility layer for callers)
-- file: `${DATA_DIR}/storage.sqlite` (or `$XDG_CONFIG_HOME/omniroute/storage.sqlite` when set, else `~/.omniroute/storage.sqlite`)
-- entities (tables + KV namespaces): providerConnections, providerNodes, modelAliases, combos, apiKeys, settings, pricing, **customModels**, **proxyConfig**, **ipFilter**, **thinkingBudget**, **systemPrompt**
-
-Usage persistence:
-
-- facade: `src/lib/usageDb.ts` (decomposed modules in `src/lib/usage/*`)
-- SQLite tables in `storage.sqlite`: `usage_history`, `call_logs`, `proxy_logs`
-- optional file artifacts remain for compatibility/debug (`${DATA_DIR}/log.txt`, `${DATA_DIR}/call_logs/`, `/logs/...`)
-- legacy JSON files are migrated to SQLite by startup migrations when present
-
-Domain State DB (SQLite):
-
-- `src/lib/db/domainState.ts` — CRUD operations for domain state
-- Tables (created in `src/lib/db/core.ts`): `domain_fallback_chains`, `domain_budgets`, `domain_cost_history`, `domain_lockout_state`, `domain_circuit_breakers`
-- Write-through cache pattern: in-memory Maps are authoritative at runtime; mutations are written synchronously to SQLite; state is restored from DB on cold start
-
-## 4) Auth + Security Surfaces
-
-- Dashboard cookie auth: `src/proxy.ts`, `src/app/api/auth/login/route.ts`
-- API key generation/verification: `src/shared/utils/apiKey.ts`
-- Provider secrets persisted in `providerConnections` entries
-- Outbound proxy support via `open-sse/utils/proxyFetch.ts` (env vars) and `open-sse/utils/networkProxy.ts` (configurable per-provider or global)
-
-## 5) Cloud Sync
-
-- Scheduler init: `src/lib/initCloudSync.ts`, `src/shared/services/initializeCloudSync.ts`
-- Periodic task: `src/shared/services/cloudSyncScheduler.ts`
-- Control route: `src/app/api/sync/cloud/route.ts`
-
-## Request Lifecycle (`/v1/chat/completions`)
-
-```mermaid
-sequenceDiagram
- autonumber
- participant Client as CLI/SDK Client
- participant Route as /api/v1/chat/completions
- participant Chat as src/sse/handlers/chat
- participant Core as open-sse/handlers/chatCore
- participant Model as Model Resolver
- participant Auth as Credential Selector
- participant Exec as Provider Executor
- participant Prov as Upstream Provider
- participant Stream as Stream Translator
- participant Usage as usageDb
-
- Client->>Route: POST /v1/chat/completions
- Route->>Chat: handleChat(request)
- Chat->>Model: parse/resolve model or combo
-
- alt Combo model
- Chat->>Chat: iterate combo models (handleComboChat)
- end
-
- Chat->>Auth: getProviderCredentials(provider)
- Auth-->>Chat: active account + tokens/api key
-
- Chat->>Core: handleChatCore(body, modelInfo, credentials)
- Core->>Core: detect source format
- Core->>Core: translate request to target format
- Core->>Exec: execute(provider, transformedBody)
- Exec->>Prov: upstream API call
- Prov-->>Exec: SSE/JSON response
- Exec-->>Core: response + metadata
-
- alt 401/403
- Core->>Exec: refreshCredentials()
- Exec-->>Core: updated tokens
- Core->>Exec: retry request
- end
-
- Core->>Stream: translate/normalize stream to client format
- Stream-->>Client: SSE chunks / JSON response
-
- Stream->>Usage: extract usage + persist history/log
-```
-
-## Combo + Account Fallback Flow
-
-```mermaid
-flowchart TD
- A[Incoming model string] --> B{Is combo name?}
- B -- Yes --> C[Load combo models sequence]
- B -- No --> D[Single model path]
-
- C --> E[Try model N]
- E --> F[Resolve provider/model]
- D --> F
-
- F --> G[Select account credentials]
- G --> H{Credentials available?}
- H -- No --> I[Return provider unavailable]
- H -- Yes --> J[Execute request]
-
- J --> K{Success?}
- K -- Yes --> L[Return response]
- K -- No --> M{Fallback-eligible error?}
-
- M -- No --> N[Return error]
- M -- Yes --> O[Mark account unavailable cooldown]
- O --> P{Another account for provider?}
- P -- Yes --> G
- P -- No --> Q{In combo with next model?}
- Q -- Yes --> E
- Q -- No --> R[Return all unavailable]
-```
-
-Fallback decisions are driven by `open-sse/services/accountFallback.ts` using status codes and error-message heuristics.
-
-## OAuth Onboarding and Token Refresh Lifecycle
-
-```mermaid
-sequenceDiagram
- autonumber
- participant UI as Dashboard UI
- participant OAuth as /api/oauth/[provider]/[action]
- participant ProvAuth as Provider Auth Server
- participant DB as localDb
- participant Test as /api/providers/[id]/test
- participant Exec as Provider Executor
-
- UI->>OAuth: GET authorize or device-code
- OAuth->>ProvAuth: create auth/device flow
- ProvAuth-->>OAuth: auth URL or device code payload
- OAuth-->>UI: flow data
-
- UI->>OAuth: POST exchange or poll
- OAuth->>ProvAuth: token exchange/poll
- ProvAuth-->>OAuth: access/refresh tokens
- OAuth->>DB: createProviderConnection(oauth data)
- OAuth-->>UI: success + connection id
-
- UI->>Test: POST /api/providers/[id]/test
- Test->>Exec: validate credentials / optional refresh
- Exec-->>Test: valid or refreshed token info
- Test->>DB: update status/tokens/errors
- Test-->>UI: validation result
-```
-
-Refresh during live traffic is executed inside `open-sse/handlers/chatCore.ts` via executor `refreshCredentials()`.
-
-## Cloud Sync Lifecycle (Enable / Sync / Disable)
-
-```mermaid
-sequenceDiagram
- autonumber
- participant UI as Endpoint Page UI
- participant Sync as /api/sync/cloud
- participant DB as localDb
- participant Cloud as External Cloud Sync
- participant Claude as ~/.claude/settings.json
-
- UI->>Sync: POST action=enable
- Sync->>DB: set cloudEnabled=true
- Sync->>DB: ensure API key exists
- Sync->>Cloud: POST /sync/{machineId} (providers/aliases/combos/keys)
- Cloud-->>Sync: sync result
- Sync->>Cloud: GET /{machineId}/v1/verify
- Sync-->>UI: enabled + verification status
-
- UI->>Sync: POST action=sync
- Sync->>Cloud: POST /sync/{machineId}
- Cloud-->>Sync: remote data
- Sync->>DB: update newer local tokens/status
- Sync-->>UI: synced
-
- UI->>Sync: POST action=disable
- Sync->>DB: set cloudEnabled=false
- Sync->>Cloud: DELETE /sync/{machineId}
- Sync->>Claude: switch ANTHROPIC_BASE_URL back to local (if needed)
- Sync-->>UI: disabled
-```
-
-Periodic sync is triggered by `CloudSyncScheduler` when cloud is enabled.
-
-## Data Model and Storage Map
-
-```mermaid
-erDiagram
- SETTINGS ||--o{ PROVIDER_CONNECTION : controls
- PROVIDER_NODE ||--o{ PROVIDER_CONNECTION : backs_compatible_provider
- PROVIDER_CONNECTION ||--o{ USAGE_ENTRY : emits_usage
-
- SETTINGS {
- boolean cloudEnabled
- number stickyRoundRobinLimit
- boolean requireLogin
- string password_hash
- string fallbackStrategy
- json rateLimitDefaults
- json providerProfiles
- }
-
- PROVIDER_CONNECTION {
- string id
- string provider
- string authType
- string name
- number priority
- boolean isActive
- string apiKey
- string accessToken
- string refreshToken
- string expiresAt
- string testStatus
- string lastError
- string rateLimitedUntil
- json providerSpecificData
- }
-
- PROVIDER_NODE {
- string id
- string type
- string name
- string prefix
- string apiType
- string baseUrl
- }
-
- MODEL_ALIAS {
- string alias
- string targetModel
- }
-
- COMBO {
- string id
- string name
- string[] models
- }
-
- API_KEY {
- string id
- string name
- string key
- string machineId
- }
-
- USAGE_ENTRY {
- string provider
- string model
- number prompt_tokens
- number completion_tokens
- string connectionId
- string timestamp
- }
-
- CUSTOM_MODEL {
- string id
- string name
- string providerId
- }
-
- PROXY_CONFIG {
- string global
- json providers
- }
-
- IP_FILTER {
- string mode
- string[] allowlist
- string[] blocklist
- }
-
- THINKING_BUDGET {
- string mode
- number customBudget
- string effortLevel
- }
-
- SYSTEM_PROMPT {
- boolean enabled
- string prompt
- string position
- }
-```
-
-Physical storage files:
-
-- primary runtime DB: `${DATA_DIR}/storage.sqlite`
-- request log lines: `${DATA_DIR}/log.txt` (compat/debug artifact)
-- structured call payload archives: `${DATA_DIR}/call_logs/`
-- optional translator/request debug sessions: `/logs/...`
-
-## Deployment Topology
-
-```mermaid
-flowchart LR
- subgraph LocalHost[Developer Host]
- CLI[CLI Tools]
- Browser[Dashboard Browser]
- end
-
- subgraph ContainerOrProcess[OmniRoute Runtime]
- Next[Next.js Server\nPORT=20128]
- Core[SSE Core + Executors]
- MainDB[(storage.sqlite)]
- UsageDB[(usage tables + log artifacts)]
- end
-
- subgraph External[External Services]
- Providers[AI Providers]
- SyncCloud[Cloud Sync Service]
- end
-
- CLI --> Next
- Browser --> Next
- Next --> Core
- Next --> MainDB
- Core --> MainDB
- Core --> UsageDB
- Core --> Providers
- Next --> SyncCloud
-```
-
-## Module Mapping (Decision-Critical)
-
-### Route and API Modules
-
-- `src/app/api/v1/*`, `src/app/api/v1beta/*`: compatibility APIs
-- `src/app/api/v1/providers/[provider]/*`: dedicated per-provider routes (chat, embeddings, images)
-- `src/app/api/providers*`: provider CRUD, validation, testing
-- `src/app/api/provider-nodes*`: custom compatible node management
-- `src/app/api/provider-models`: custom model management (CRUD)
-- `src/app/api/models/route.ts`: model catalog API (aliases + custom models)
-- `src/app/api/oauth/*`: OAuth/device-code flows
-- `src/app/api/keys*`: local API key lifecycle
-- `src/app/api/models/alias`: alias management
-- `src/app/api/combos*`: fallback combo management
-- `src/app/api/pricing`: pricing overrides for cost calculation
-- `src/app/api/settings/proxy`: proxy configuration (GET/PUT/DELETE)
-- `src/app/api/settings/proxy/test`: outbound proxy connectivity test (POST)
-- `src/app/api/usage/*`: usage and logs APIs
-- `src/app/api/sync/*` + `src/app/api/cloud/*`: cloud sync and cloud-facing helpers
-- `src/app/api/cli-tools/*`: local CLI config writers/checkers
-- `src/app/api/settings/ip-filter`: IP allowlist/blocklist (GET/PUT)
-- `src/app/api/settings/thinking-budget`: thinking token budget config (GET/PUT)
-- `src/app/api/settings/system-prompt`: global system prompt (GET/PUT)
-- `src/app/api/sessions`: active session listing (GET)
-- `src/app/api/rate-limits`: per-account rate limit status (GET)
-
-### Routing and Execution Core
-
-- `src/sse/handlers/chat.ts`: request parse, combo handling, account selection loop
-- `open-sse/handlers/chatCore.ts`: translation, executor dispatch, retry/refresh handling, stream setup
-- `open-sse/executors/*`: provider-specific network and format behavior
-
-### Translation Registry and Format Converters
-
-- `open-sse/translator/index.ts`: translator registry and orchestration
-- Request translators: `open-sse/translator/request/*`
-- Response translators: `open-sse/translator/response/*`
-- Format constants: `open-sse/translator/formats.ts`
-
-### Persistence
-
-- `src/lib/db/*`: persistent config/state and domain persistence on SQLite
-- `src/lib/localDb.ts`: compatibility re-export for DB modules
-- `src/lib/usageDb.ts`: usage history/call logs facade on top of SQLite tables
-
-## Provider Executor Coverage (Strategy Pattern)
-
-Each provider has a specialized executor extending `BaseExecutor` (in `open-sse/executors/base.ts`), which provides URL building, header construction, retry with exponential backoff, credential refresh hooks, and the `execute()` orchestration method.
-
-| Executor | Provider(s) | Special Handling |
-| --------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------ | -------------------------------------------------------------------- |
-| `DefaultExecutor` | OpenAI, Claude, Gemini, Qwen, Qoder, OpenRouter, GLM, Kimi, MiniMax, DeepSeek, Groq, xAI, Mistral, Perplexity, Together, Fireworks, Cerebras, Cohere, NVIDIA | Dynamic URL/header config per provider |
-| `AntigravityExecutor` | Google Antigravity | Custom project/session IDs, Retry-After parsing |
-| `CodexExecutor` | OpenAI Codex | Injects system instructions, forces reasoning effort |
-| `CursorExecutor` | Cursor IDE | ConnectRPC protocol, Protobuf encoding, request signing via checksum |
-| `GithubExecutor` | GitHub Copilot | Copilot token refresh, VSCode-mimicking headers |
-| `KiroExecutor` | AWS CodeWhisperer/Kiro | AWS EventStream binary format → SSE conversion |
-| `GeminiCLIExecutor` | Gemini CLI | Google OAuth token refresh cycle |
-
-All other providers (including custom compatible nodes) use the `DefaultExecutor`.
-
-## Provider Compatibility Matrix
-
-| Provider | Format | Auth | Stream | Non-Stream | Token Refresh | Usage API |
-| ---------------- | ---------------- | --------------------- | ---------------- | ---------- | ------------- | ------------------ |
-| Claude | claude | API Key / OAuth | ✅ | ✅ | ✅ | ⚠️ Admin only |
-| Gemini | gemini | API Key / OAuth | ✅ | ✅ | ✅ | ⚠️ Cloud Console |
-| Gemini CLI | gemini-cli | OAuth | ✅ | ✅ | ✅ | ⚠️ Cloud Console |
-| Antigravity | antigravity | OAuth | ✅ | ✅ | ✅ | ✅ Full quota API |
-| OpenAI | openai | API Key | ✅ | ✅ | ❌ | ❌ |
-| Codex | openai-responses | OAuth | ✅ forced | ❌ | ✅ | ✅ Rate limits |
-| GitHub Copilot | openai | OAuth + Copilot Token | ✅ | ✅ | ✅ | ✅ Quota snapshots |
-| Cursor | cursor | Custom checksum | ✅ | ✅ | ❌ | ❌ |
-| Kiro | kiro | AWS SSO OIDC | ✅ (EventStream) | ❌ | ✅ | ✅ Usage limits |
-| Qwen | openai | OAuth | ✅ | ✅ | ✅ | ⚠️ Per request |
-| Qoder | openai | OAuth (Basic) | ✅ | ✅ | ✅ | ⚠️ Per request |
-| OpenRouter | openai | API Key | ✅ | ✅ | ❌ | ❌ |
-| GLM/Kimi/MiniMax | claude | API Key | ✅ | ✅ | ❌ | ❌ |
-| DeepSeek | openai | API Key | ✅ | ✅ | ❌ | ❌ |
-| Groq | openai | API Key | ✅ | ✅ | ❌ | ❌ |
-| xAI (Grok) | openai | API Key | ✅ | ✅ | ❌ | ❌ |
-| Mistral | openai | API Key | ✅ | ✅ | ❌ | ❌ |
-| Perplexity | openai | API Key | ✅ | ✅ | ❌ | ❌ |
-| Together AI | openai | API Key | ✅ | ✅ | ❌ | ❌ |
-| Fireworks AI | openai | API Key | ✅ | ✅ | ❌ | ❌ |
-| Cerebras | openai | API Key | ✅ | ✅ | ❌ | ❌ |
-| Cohere | openai | API Key | ✅ | ✅ | ❌ | ❌ |
-| NVIDIA NIM | openai | API Key | ✅ | ✅ | ❌ | ❌ |
-
-## Format Translation Coverage
-
-Detected source formats include:
-
-- `openai`
-- `openai-responses`
-- `claude`
-- `gemini`
-
-Target formats include:
-
-- OpenAI chat/Responses
-- Claude
-- Gemini/Gemini-CLI/Antigravity envelope
-- Kiro
-- Cursor
-
-Translations use **OpenAI as the hub format** — all conversions go through OpenAI as intermediate:
-
-```
-Source Format → OpenAI (hub) → Target Format
-```
-
-Translations are selected dynamically based on source payload shape and provider target format.
-
-Additional processing layers in the translation pipeline:
-
-- **Response sanitization** — Strips non-standard fields from OpenAI-format responses (both streaming and non-streaming) to ensure strict SDK compliance
-- **Role normalization** — Converts `developer` → `system` for non-OpenAI targets; merges `system` → `user` for models that reject the system role (GLM, ERNIE)
-- **Think tag extraction** — Parses `...` blocks from content into `reasoning_content` field
-- **Structured output** — Converts OpenAI `response_format.json_schema` to Gemini's `responseMimeType` + `responseSchema`
-
-## Supported API Endpoints
-
-| Endpoint | Format | Handler |
-| -------------------------------------------------- | ------------------ | ---------------------------------------------------- |
-| `POST /v1/chat/completions` | OpenAI Chat | `src/sse/handlers/chat.ts` |
-| `POST /v1/messages` | Claude Messages | Same handler (auto-detected) |
-| `POST /v1/responses` | OpenAI Responses | `open-sse/handlers/responsesHandler.ts` |
-| `POST /v1/embeddings` | OpenAI Embeddings | `open-sse/handlers/embeddings.ts` |
-| `GET /v1/embeddings` | Model listing | API route |
-| `POST /v1/images/generations` | OpenAI Images | `open-sse/handlers/imageGeneration.ts` |
-| `GET /v1/images/generations` | Model listing | API route |
-| `POST /v1/providers/{provider}/chat/completions` | OpenAI Chat | Dedicated per-provider with model validation |
-| `POST /v1/providers/{provider}/embeddings` | OpenAI Embeddings | Dedicated per-provider with model validation |
-| `POST /v1/providers/{provider}/images/generations` | OpenAI Images | Dedicated per-provider with model validation |
-| `POST /v1/messages/count_tokens` | Claude Token Count | API route |
-| `GET /v1/models` | OpenAI Models list | API route (chat + embedding + image + custom models) |
-| `GET /api/models/catalog` | Catalog | All models grouped by provider + type |
-| `POST /v1beta/models/*:streamGenerateContent` | Gemini native | API route |
-| `GET/PUT/DELETE /api/settings/proxy` | Proxy Config | Network proxy configuration |
-| `POST /api/settings/proxy/test` | Proxy Connectivity | Proxy health/connectivity test endpoint |
-| `GET/POST/DELETE /api/provider-models` | Custom Models | Custom model management per provider |
-
-## Bypass Handler
-
-The bypass handler (`open-sse/utils/bypassHandler.ts`) intercepts known "throwaway" requests from Claude CLI — warmup pings, title extractions, and token counts — and returns a **fake response** without consuming upstream provider tokens. This is triggered only when `User-Agent` contains `claude-cli`.
-
-## Request Logger Pipeline
-
-The request logger (`open-sse/utils/requestLogger.ts`) provides a 7-stage debug logging pipeline, disabled by default, enabled via `ENABLE_REQUEST_LOGS=true`:
-
-```
-1_req_client.json → 2_req_source.json → 3_req_openai.json → 4_req_target.json
-→ 5_res_provider.txt → 6_res_openai.txt → 7_res_client.txt
-```
-
-Files are written to `/logs//` for each request session.
-
-## Failure Modes and Resilience
-
-## 1) Account/Provider Availability
-
-- provider account cooldown on transient/rate/auth errors
-- account fallback before failing request
-- combo model fallback when current model/provider path is exhausted
-
-## 2) Token Expiry
-
-- pre-check and refresh with retry for refreshable providers
-- 401/403 retry after refresh attempt in core path
-
-## 3) Stream Safety
-
-- disconnect-aware stream controller
-- translation stream with end-of-stream flush and `[DONE]` handling
-- usage estimation fallback when provider usage metadata is missing
-
-## 4) Cloud Sync Degradation
-
-- sync errors are surfaced but local runtime continues
-- scheduler has retry-capable logic, but periodic execution currently calls single-attempt sync by default
-
-## 5) Data Integrity
-
-- SQLite schema migrations and auto-upgrade hooks at startup
-- legacy JSON → SQLite migration compatibility path
-
-## Observability and Operational Signals
-
-Runtime visibility sources:
-
-- console logs from `src/sse/utils/logger.ts`
-- per-request usage aggregates in SQLite (`usage_history`, `call_logs`, `proxy_logs`)
-- textual request status log in `log.txt` (optional/compat)
-- optional deep request/translation logs under `logs/` when `ENABLE_REQUEST_LOGS=true`
-- dashboard usage endpoints (`/api/usage/*`) for UI consumption
-
-## Security-Sensitive Boundaries
-
-- JWT secret (`JWT_SECRET`) secures dashboard session cookie verification/signing
-- Initial password bootstrap (`INITIAL_PASSWORD`) should be explicitly configured for first-run provisioning
-- API key HMAC secret (`API_KEY_SECRET`) secures generated local API key format
-- Provider secrets (API keys/tokens) are persisted in local DB and should be protected at filesystem level
-- Cloud sync endpoints rely on API key auth + machine id semantics
-
-## Environment and Runtime Matrix
-
-Environment variables actively used by code:
-
-- App/auth: `JWT_SECRET`, `INITIAL_PASSWORD`
-- Storage: `DATA_DIR`
-- Compatible node behavior: `ALLOW_MULTI_CONNECTIONS_PER_COMPAT_NODE`
-- Optional storage base override (Linux/macOS when `DATA_DIR` unset): `XDG_CONFIG_HOME`
-- Security hashing: `API_KEY_SECRET`, `MACHINE_ID_SALT`
-- Logging: `ENABLE_REQUEST_LOGS`
-- Sync/cloud URLing: `NEXT_PUBLIC_BASE_URL`, `NEXT_PUBLIC_CLOUD_URL`
-- Outbound proxy: `HTTP_PROXY`, `HTTPS_PROXY`, `ALL_PROXY`, `NO_PROXY` and lowercase variants
-- SOCKS5 feature flags: `ENABLE_SOCKS5_PROXY`, `NEXT_PUBLIC_ENABLE_SOCKS5_PROXY`
-- Platform/runtime helpers (not app-specific config): `APPDATA`, `NODE_ENV`, `PORT`, `HOSTNAME`
-
-## Known Architectural Notes
-
-1. `usageDb` and `localDb` share the same base directory policy (`DATA_DIR` -> `XDG_CONFIG_HOME/omniroute` -> `~/.omniroute`) with legacy file migration.
-2. `/api/v1/route.ts` delegates to the same unified catalog builder used by `/api/v1/models` (`src/app/api/v1/models/catalog.ts`) to avoid semantic drift.
-3. Request logger writes full headers/body when enabled; treat log directory as sensitive.
-4. Cloud behavior depends on correct `NEXT_PUBLIC_BASE_URL` and cloud endpoint reachability.
-5. The `open-sse/` directory is published as the `@omniroute/open-sse` **npm workspace package**. Source code imports it via `@omniroute/open-sse/...` (resolved by Next.js `transpilePackages`). File paths in this document still use the directory name `open-sse/` for consistency.
-6. Charts in the dashboard use **Recharts** (SVG-based) for accessible, interactive analytics visualizations (model usage bar charts, provider breakdown tables with success rates).
-7. E2E tests use **Playwright** (`tests/e2e/`), run via `npm run test:e2e`. Unit tests use **Node.js test runner** (`tests/unit/`), run via `npm run test:unit`. Source code under `src/` is **TypeScript** (`.ts`/`.tsx`); the `open-sse/` workspace remains JavaScript (`.js`).
-8. Settings page is organized into 5 tabs: Security, Routing (6 global strategies: fill-first, round-robin, p2c, random, least-used, cost-optimized), Resilience (editable rate limits, circuit breaker, policies), AI (thinking budget, system prompt, prompt cache), Advanced (proxy).
-
-## Operational Verification Checklist
-
-- Build from source: `npm run build`
-- Build Docker image: `docker build -t omniroute .`
-- Start service and verify:
-- `GET /api/settings`
-- `GET /api/v1/models`
-- CLI target base URL should be `http://:20128/v1` when `PORT=20128`
diff --git a/docs/i18n/fr/AUTO-COMBO.md b/docs/i18n/fr/AUTO-COMBO.md
deleted file mode 100644
index 2166e41dff..0000000000
--- a/docs/i18n/fr/AUTO-COMBO.md
+++ /dev/null
@@ -1,67 +0,0 @@
-🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/AUTO-COMBO.md) · 🇪🇸 [es](../es/AUTO-COMBO.md) · 🇫🇷 [fr](../fr/AUTO-COMBO.md) · 🇩🇪 [de](../de/AUTO-COMBO.md) · 🇮🇹 [it](../it/AUTO-COMBO.md) · 🇷🇺 [ru](../ru/AUTO-COMBO.md) · 🇨🇳 [zh-CN](../zh-CN/AUTO-COMBO.md) · 🇯🇵 [ja](../ja/AUTO-COMBO.md) · 🇰🇷 [ko](../ko/AUTO-COMBO.md) · 🇸🇦 [ar](../ar/AUTO-COMBO.md) · 🇮🇳 [in](../in/AUTO-COMBO.md) · 🇹🇭 [th](../th/AUTO-COMBO.md) · 🇻🇳 [vi](../vi/AUTO-COMBO.md) · 🇮🇩 [id](../id/AUTO-COMBO.md) · 🇲🇾 [ms](../ms/AUTO-COMBO.md) · 🇳🇱 [nl](../nl/AUTO-COMBO.md) · 🇵🇱 [pl](../pl/AUTO-COMBO.md) · 🇸🇪 [sv](../sv/AUTO-COMBO.md) · 🇳🇴 [no](../no/AUTO-COMBO.md) · 🇩🇰 [da](../da/AUTO-COMBO.md) · 🇫🇮 [fi](../fi/AUTO-COMBO.md) · 🇵🇹 [pt](../pt/AUTO-COMBO.md) · 🇷🇴 [ro](../ro/AUTO-COMBO.md) · 🇭🇺 [hu](../hu/AUTO-COMBO.md) · 🇧🇬 [bg](../bg/AUTO-COMBO.md) · 🇸🇰 [sk](../sk/AUTO-COMBO.md) · 🇺🇦 [uk-UA](../uk-UA/AUTO-COMBO.md) · 🇮🇱 [he](../he/AUTO-COMBO.md) · 🇵🇭 [phi](../phi/AUTO-COMBO.md)
-
----
-
-# OmniRoute Auto-Combo Engine
-
-> Self-managing model chains with adaptive scoring
-
-## How It Works
-
-The Auto-Combo Engine dynamically selects the best provider/model for each request using a **6-factor scoring function**:
-
-| Factor | Weight | Description |
-| :--------- | :----- | :---------------------------------------------- |
-| Quota | 0.20 | Remaining capacity [0..1] |
-| Health | 0.25 | Circuit breaker: CLOSED=1.0, HALF=0.5, OPEN=0.0 |
-| CostInv | 0.20 | Inverse cost (cheaper = higher score) |
-| LatencyInv | 0.15 | Inverse p95 latency (faster = higher) |
-| TaskFit | 0.10 | Model × task type fitness score |
-| Stability | 0.10 | Low variance in latency/errors |
-
-## Mode Packs
-
-| Pack | Focus | Key Weight |
-| :---------------------- | :----------- | :--------------- |
-| 🚀 **Ship Fast** | Speed | latencyInv: 0.35 |
-| 💰 **Cost Saver** | Economy | costInv: 0.40 |
-| 🎯 **Quality First** | Best model | taskFit: 0.40 |
-| 📡 **Offline Friendly** | Availability | quota: 0.40 |
-
-## Self-Healing
-
-- **Temporary exclusion**: Score < 0.2 → excluded for 5 min (progressive backoff, max 30 min)
-- **Circuit breaker awareness**: OPEN → auto-excluded; HALF_OPEN → probe requests
-- **Incident mode**: >50% OPEN → disable exploration, maximize stability
-- **Cooldown recovery**: After exclusion, first request is a "probe" with reduced timeout
-
-## Bandit Exploration
-
-5% of requests (configurable) are routed to random providers for exploration. Disabled in incident mode.
-
-## API
-
-```bash
-# Create auto-combo
-curl -X POST http://localhost:20128/api/combos/auto \
- -H "Content-Type: application/json" \
- -d '{"id":"my-auto","name":"Auto Coder","candidatePool":["anthropic","google","openai"],"modePack":"ship-fast"}'
-
-# List auto-combos
-curl http://localhost:20128/api/combos/auto
-```
-
-## Task Fitness
-
-30+ models scored across 6 task types (`coding`, `review`, `planning`, `analysis`, `debugging`, `documentation`). Supports wildcard patterns (e.g., `*-coder` → high coding score).
-
-## Files
-
-| File | Purpose |
-| :------------------------------------------- | :------------------------------------ |
-| `open-sse/services/autoCombo/scoring.ts` | Scoring function & pool normalization |
-| `open-sse/services/autoCombo/taskFitness.ts` | Model × task fitness lookup |
-| `open-sse/services/autoCombo/engine.ts` | Selection logic, bandit, budget cap |
-| `open-sse/services/autoCombo/selfHealing.ts` | Exclusion, probes, incident mode |
-| `open-sse/services/autoCombo/modePacks.ts` | 4 weight profiles |
-| `src/app/api/combos/auto/route.ts` | REST API |
diff --git a/docs/i18n/fr/CHANGELOG.md b/docs/i18n/fr/CHANGELOG.md
index 7391f28706..8c8c0cc9db 100644
--- a/docs/i18n/fr/CHANGELOG.md
+++ b/docs/i18n/fr/CHANGELOG.md
@@ -1,12 +1,92 @@
# Changelog (Français)
-🌐 **Languages:** 🇺🇸 [English](../../../CHANGELOG.md) · 🇪🇸 [es](../es/CHANGELOG.md) · 🇫🇷 [fr](../fr/CHANGELOG.md) · 🇩🇪 [de](../de/CHANGELOG.md) · 🇮🇹 [it](../it/CHANGELOG.md) · 🇷🇺 [ru](../ru/CHANGELOG.md) · 🇨🇳 [zh-CN](../zh-CN/CHANGELOG.md) · 🇯🇵 [ja](../ja/CHANGELOG.md) · 🇰🇷 [ko](../ko/CHANGELOG.md) · 🇸🇦 [ar](../ar/CHANGELOG.md) · 🇮🇳 [in](../in/CHANGELOG.md) · 🇹🇭 [th](../th/CHANGELOG.md) · 🇻🇳 [vi](../vi/CHANGELOG.md) · 🇮🇩 [id](../id/CHANGELOG.md) · 🇲🇾 [ms](../ms/CHANGELOG.md) · 🇳🇱 [nl](../nl/CHANGELOG.md) · 🇵🇱 [pl](../pl/CHANGELOG.md) · 🇸🇪 [sv](../sv/CHANGELOG.md) · 🇳🇴 [no](../no/CHANGELOG.md) · 🇩🇰 [da](../da/CHANGELOG.md) · 🇫🇮 [fi](../fi/CHANGELOG.md) · 🇵🇹 [pt](../pt/CHANGELOG.md) · 🇷🇴 [ro](../ro/CHANGELOG.md) · 🇭🇺 [hu](../hu/CHANGELOG.md) · 🇧🇬 [bg](../bg/CHANGELOG.md) · 🇸🇰 [sk](../sk/CHANGELOG.md) · 🇺🇦 [uk-UA](../uk-UA/CHANGELOG.md) · 🇮🇱 [he](../he/CHANGELOG.md) · 🇵🇭 [phi](../phi/CHANGELOG.md) · 🇧🇷 [pt-BR](../pt-BR/CHANGELOG.md)
+🌐 **Languages:** 🇺🇸 [English](../../../CHANGELOG.md) · 🇪🇸 [es](../es/CHANGELOG.md) · 🇫🇷 [fr](../fr/CHANGELOG.md) · 🇩🇪 [de](../de/CHANGELOG.md) · 🇮🇹 [it](../it/CHANGELOG.md) · 🇷🇺 [ru](../ru/CHANGELOG.md) · 🇨🇳 [zh-CN](../zh-CN/CHANGELOG.md) · 🇯🇵 [ja](../ja/CHANGELOG.md) · 🇰🇷 [ko](../ko/CHANGELOG.md) · 🇸🇦 [ar](../ar/CHANGELOG.md) · 🇮🇳 [in](../in/CHANGELOG.md) · 🇹🇭 [th](../th/CHANGELOG.md) · 🇻🇳 [vi](../vi/CHANGELOG.md) · 🇮🇩 [id](../id/CHANGELOG.md) · 🇲🇾 [ms](../ms/CHANGELOG.md) · 🇳🇱 [nl](../nl/CHANGELOG.md) · 🇵🇱 [pl](../pl/CHANGELOG.md) · 🇸🇪 [sv](../sv/CHANGELOG.md) · 🇳🇴 [no](../no/CHANGELOG.md) · 🇩🇰 [da](../da/CHANGELOG.md) · 🇫🇮 [fi](../fi/CHANGELOG.md) · 🇵🇹 [pt](../pt/CHANGELOG.md) · 🇷🇴 [ro](../ro/CHANGELOG.md) · 🇭🇺 [hu](../hu/CHANGELOG.md) · 🇧🇬 [bg](../bg/CHANGELOG.md) · 🇸🇰 [sk](../sk/CHANGELOG.md) · 🇺🇦 [uk-UA](../uk-UA/CHANGELOG.md) · 🇮🇱 [he](../he/CHANGELOG.md) · 🇵🇭 [phi](../phi/CHANGELOG.md) · 🇧🇷 [pt-BR](../pt-BR/CHANGELOG.md) · 🇨🇿 [cs](../cs/CHANGELOG.md)
---
-
## [Unreleased]
+### 🛠️ Maintenance
+
+- **AGENTS.md rewrite:** Condensed from 297→153 lines. Added build/lint/test commands (including single-test execution), code style guidelines (Prettier, TypeScript, ESLint, naming, imports, error handling, security), and trimmed verbose architecture tables for AI agent consumption.
+
+## [3.4.2] - 2026-04-01
+
+### 🐛 Bug Fixes
+
+- **CI Stabilization:** Fixed failing analytics/settings Playwright selectors and request assertions so GitHub Actions E2E runs pass reliably across localized UIs and switch-based controls.
+- **Deterministic Tests:** Removed date-sensitive quota fixtures from Copilot usage tests and aligned idempotency/model catalog tests with the merged runtime behavior.
+- **MCP Type Hardening:** Removed zero-budget explicit `any` regressions from the MCP server tool registration path, restoring the `check:any-budget:t11` workflow gate.
+
+### 🛠️ Maintenance
+
+- **Release Branch Integration:** Consolidated the active feature branches into `release/v3.4.2` on top of current `main` and validated the branch with lint, unit, coverage, build, and CI-mode E2E runs.
+
+## [3.4.1] - 2026-03-31
+
+> [!WARNING]
+> **BREAKING CHANGE: request logging, retention, and logging environment variables have been redesigned.**
+> On the first startup after upgrading, OmniRoute archives legacy request logs from `DATA_DIR/logs/`, legacy `DATA_DIR/call_logs/`, and `DATA_DIR/log.txt` into `DATA_DIR/log_archives/*.zip`, then removes the deprecated layout and switches to the new unified artifact format under `DATA_DIR/call_logs/`.
+
+### ✨ New Features
+
+- **.ENV Migration Utility:** Included `scripts/migrate-env.mjs` to seamlessly migrate ` Your key looks like: `sk-xxxxxxxxxxxxxxxx-xxxxxxxxx`
-
----
-
-## Step 2 — Install CLI Tools
-
-All npm-based tools require Node.js 18+:
-
-```bash
-# Claude Code (Anthropic)
-npm install -g @anthropic-ai/claude-code
-
-# OpenAI Codex
-npm install -g @openai/codex
-
-# Gemini CLI (Google)
-npm install -g @google/gemini-cli
-
-# OpenCode
-npm install -g opencode-ai
-
-# Cline
-npm install -g cline
-
-# KiloCode
-npm install -g kilecode
-
-# Kiro CLI (Amazon — requires curl + unzip)
-apt-get install -y unzip # on Debian/Ubuntu
-curl -fsSL https://cli.kiro.dev/install | bash
-export PATH="$HOME/.local/bin:$PATH" # add to ~/.bashrc
-```
-
-**Verify:**
-
-```bash
-claude --version # 2.x.x
-codex --version # 0.x.x
-gemini --version # 0.x.x
-opencode --version # x.x.x
-cline --version # 2.x.x
-kilocode --version # x.x.x (or: kilo --version)
-kiro-cli --version # 1.x.x
-```
-
----
-
-## Step 3 — Set Global Environment Variables
-
-Add to `~/.bashrc` (or `~/.zshrc`), then run `source ~/.bashrc`:
-
-```bash
-# OmniRoute Universal Endpoint
-export OPENAI_BASE_URL="http://localhost:20128/v1"
-export OPENAI_API_KEY="sk-your-omniroute-key"
-export ANTHROPIC_BASE_URL="http://localhost:20128/v1"
-export ANTHROPIC_API_KEY="sk-your-omniroute-key"
-export GEMINI_BASE_URL="http://localhost:20128/v1"
-export GEMINI_API_KEY="sk-your-omniroute-key"
-```
-
-> For a **remote server** replace `localhost:20128` with the server IP or domain,
-> e.g. `http://192.168.0.15:20128`.
-
----
-
-## Step 4 — Configure Each Tool
-
-### Claude Code
-
-```bash
-# Via CLI:
-claude config set --global api-base-url http://localhost:20128/v1
-
-# Or create ~/.claude/settings.json:
-mkdir -p ~/.claude && cat > ~/.claude/settings.json << EOF
-{
- "apiBaseUrl": "http://localhost:20128/v1",
- "apiKey": "sk-your-omniroute-key"
-}
-EOF
-```
-
-**Test:** `claude "say hello"`
-
----
-
-### OpenAI Codex
-
-```bash
-mkdir -p ~/.codex && cat > ~/.codex/config.yaml << EOF
-model: auto
-apiKey: sk-your-omniroute-key
-apiBaseUrl: http://localhost:20128/v1
-EOF
-```
-
-**Test:** `codex "what is 2+2?"`
-
----
-
-### Gemini CLI
-
-```bash
-mkdir -p ~/.gemini && cat > ~/.gemini/settings.json << EOF
-{
- "apiKey": "sk-your-omniroute-key",
- "baseUrl": "http://localhost:20128/v1"
-}
-EOF
-```
-
-**Test:** `gemini "hello"`
-
----
-
-### OpenCode
-
-```bash
-mkdir -p ~/.config/opencode && cat > ~/.config/opencode/config.toml << EOF
-[provider.openai]
-base_url = "http://localhost:20128/v1"
-api_key = "sk-your-omniroute-key"
-EOF
-```
-
-**Test:** `opencode`
-
----
-
-### Cline (CLI or VS Code)
-
-**CLI mode:**
-
-```bash
-mkdir -p ~/.cline/data && cat > ~/.cline/data/globalState.json << EOF
-{
- "apiProvider": "openai",
- "openAiBaseUrl": "http://localhost:20128/v1",
- "openAiApiKey": "sk-your-omniroute-key"
-}
-EOF
-```
-
-**VS Code mode:**
-Cline extension settings → API Provider: `OpenAI Compatible` → Base URL: `http://localhost:20128/v1`
-
-Or use the OmniRoute dashboard → **CLI Tools → Cline → Apply Config**.
-
----
-
-### KiloCode (CLI or VS Code)
-
-**CLI mode:**
-
-```bash
-kilocode --api-base http://localhost:20128/v1 --api-key sk-your-omniroute-key
-```
-
-**VS Code settings:**
-
-```json
-{
- "kilo-code.openAiBaseUrl": "http://localhost:20128/v1",
- "kilo-code.apiKey": "sk-your-omniroute-key"
-}
-```
-
-Or use the OmniRoute dashboard → **CLI Tools → KiloCode → Apply Config**.
-
----
-
-### Continue (VS Code Extension)
-
-Edit `~/.continue/config.yaml`:
-
-```yaml
-models:
- - name: OmniRoute
- provider: openai
- model: auto
- apiBase: http://localhost:20128/v1
- apiKey: sk-your-omniroute-key
- default: true
-```
-
-Restart VS Code after editing.
-
----
-
-### Kiro CLI (Amazon)
-
-```bash
-# Login to your AWS/Kiro account:
-kiro-cli login
-
-# The CLI uses its own auth — OmniRoute is not needed as backend for Kiro CLI itself.
-# Use kiro-cli alongside OmniRoute for other tools.
-kiro-cli status
-```
-
----
-
-### Cursor (Desktop App)
-
-> **Note:** Cursor routes requests through its cloud. For OmniRoute integration,
-> enable **Cloud Endpoint** in OmniRoute Settings and use your public domain URL.
-
-Via GUI: **Settings → Models → OpenAI API Key**
-
-- Base URL: `https://your-domain.com/v1`
-- API Key: your OmniRoute key
-
----
-
-## Dashboard Auto-Configuration
-
-The OmniRoute dashboard automates configuration for most tools:
-
-1. Go to `http://localhost:20128/dashboard/cli-tools`
-2. Expand any tool card
-3. Select your API key from the dropdown
-4. Click **Apply Config** (if tool is detected as installed)
-5. Or copy the generated config snippet manually
-
----
-
-## Built-in Agents: Droid & OpenClaw
-
-**Droid** and **OpenClaw** are AI agents built directly into OmniRoute — no installation needed.
-They run as internal routes and use OmniRoute's model routing automatically.
-
-- Access: `http://localhost:20128/dashboard/agents`
-- Configure: same combos and providers as all other tools
-- No API key or CLI install required
-
----
-
-## Available API Endpoints
-
-| Endpoint | Description | Use For |
-| -------------------------- | ----------------------------- | --------------------------- |
-| `/v1/chat/completions` | Standard chat (all providers) | All modern tools |
-| `/v1/responses` | Responses API (OpenAI format) | Codex, agentic workflows |
-| `/v1/completions` | Legacy text completions | Older tools using `prompt:` |
-| `/v1/embeddings` | Text embeddings | RAG, search |
-| `/v1/images/generations` | Image generation | DALL-E, Flux, etc. |
-| `/v1/audio/speech` | Text-to-speech | ElevenLabs, OpenAI TTS |
-| `/v1/audio/transcriptions` | Speech-to-text | Deepgram, AssemblyAI |
-
----
-
-## Troubleshooting
-
-| Error | Cause | Fix |
-| ------------------------- | ----------------------- | ------------------------------------------ |
-| `Connection refused` | OmniRoute not running | `pm2 start omniroute` |
-| `401 Unauthorized` | Wrong API key | Check in `/dashboard/api-manager` |
-| `No combo configured` | No active routing combo | Set up in `/dashboard/combos` |
-| `invalid model` | Model not in catalog | Use `auto` or check `/dashboard/providers` |
-| CLI shows "not installed" | Binary not in PATH | Check `which ` |
-| `kiro-cli: not found` | Not in PATH | `export PATH="$HOME/.local/bin:$PATH"` |
-
----
-
-## Quick Setup Script (One Command)
-
-```bash
-# Install all CLIs and configure for OmniRoute (replace with your key and server URL)
-OMNIROUTE_URL="http://localhost:20128/v1"
-OMNIROUTE_KEY="sk-your-omniroute-key"
-
-npm install -g @anthropic-ai/claude-code @openai/codex @google/gemini-cli opencode-ai cline kilecode
-
-# Kiro CLI
-apt-get install -y unzip 2>/dev/null; curl -fsSL https://cli.kiro.dev/install | bash
-
-# Write configs
-mkdir -p ~/.claude ~/.codex ~/.gemini ~/.config/opencode ~/.continue
-
-cat > ~/.claude/settings.json <<< "{\"apiBaseUrl\":\"$OMNIROUTE_URL\",\"apiKey\":\"$OMNIROUTE_KEY\"}"
-cat > ~/.codex/config.yaml <<< "model: auto\napiKey: $OMNIROUTE_KEY\napiBaseUrl: $OMNIROUTE_URL"
-cat > ~/.gemini/settings.json <<< "{\"apiKey\":\"$OMNIROUTE_KEY\",\"baseUrl\":\"$OMNIROUTE_URL\"}"
-cat >> ~/.bashrc << EOF
-export OPENAI_BASE_URL="$OMNIROUTE_URL"
-export OPENAI_API_KEY="$OMNIROUTE_KEY"
-export ANTHROPIC_BASE_URL="$OMNIROUTE_URL"
-export ANTHROPIC_API_KEY="$OMNIROUTE_KEY"
-EOF
-
-source ~/.bashrc
-echo "✅ All CLIs installed and configured for OmniRoute"
-```
diff --git a/docs/i18n/fr/CODEBASE_DOCUMENTATION.md b/docs/i18n/fr/CODEBASE_DOCUMENTATION.md
deleted file mode 100644
index e2d7950052..0000000000
--- a/docs/i18n/fr/CODEBASE_DOCUMENTATION.md
+++ /dev/null
@@ -1,593 +0,0 @@
-🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/CODEBASE_DOCUMENTATION.md) · 🇪🇸 [es](../es/CODEBASE_DOCUMENTATION.md) · 🇫🇷 [fr](../fr/CODEBASE_DOCUMENTATION.md) · 🇩🇪 [de](../de/CODEBASE_DOCUMENTATION.md) · 🇮🇹 [it](../it/CODEBASE_DOCUMENTATION.md) · 🇷🇺 [ru](../ru/CODEBASE_DOCUMENTATION.md) · 🇨🇳 [zh-CN](../zh-CN/CODEBASE_DOCUMENTATION.md) · 🇯🇵 [ja](../ja/CODEBASE_DOCUMENTATION.md) · 🇰🇷 [ko](../ko/CODEBASE_DOCUMENTATION.md) · 🇸🇦 [ar](../ar/CODEBASE_DOCUMENTATION.md) · 🇮🇳 [in](../in/CODEBASE_DOCUMENTATION.md) · 🇹🇭 [th](../th/CODEBASE_DOCUMENTATION.md) · 🇻🇳 [vi](../vi/CODEBASE_DOCUMENTATION.md) · 🇮🇩 [id](../id/CODEBASE_DOCUMENTATION.md) · 🇲🇾 [ms](../ms/CODEBASE_DOCUMENTATION.md) · 🇳🇱 [nl](../nl/CODEBASE_DOCUMENTATION.md) · 🇵🇱 [pl](../pl/CODEBASE_DOCUMENTATION.md) · 🇸🇪 [sv](../sv/CODEBASE_DOCUMENTATION.md) · 🇳🇴 [no](../no/CODEBASE_DOCUMENTATION.md) · 🇩🇰 [da](../da/CODEBASE_DOCUMENTATION.md) · 🇫🇮 [fi](../fi/CODEBASE_DOCUMENTATION.md) · 🇵🇹 [pt](../pt/CODEBASE_DOCUMENTATION.md) · 🇷🇴 [ro](../ro/CODEBASE_DOCUMENTATION.md) · 🇭🇺 [hu](../hu/CODEBASE_DOCUMENTATION.md) · 🇧🇬 [bg](../bg/CODEBASE_DOCUMENTATION.md) · 🇸🇰 [sk](../sk/CODEBASE_DOCUMENTATION.md) · 🇺🇦 [uk-UA](../uk-UA/CODEBASE_DOCUMENTATION.md) · 🇮🇱 [he](../he/CODEBASE_DOCUMENTATION.md) · 🇵🇭 [phi](../phi/CODEBASE_DOCUMENTATION.md)
-
----
-
-# omniroute — Codebase Documentation
-
-🌐 **Languages:** 🇺🇸 [English](CODEBASE_DOCUMENTATION.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/CODEBASE_DOCUMENTATION.md) | 🇪🇸 [Español](i18n/es/CODEBASE_DOCUMENTATION.md) | 🇫🇷 [Français](i18n/fr/CODEBASE_DOCUMENTATION.md) | 🇮🇹 [Italiano](i18n/it/CODEBASE_DOCUMENTATION.md) | 🇷🇺 [Русский](i18n/ru/CODEBASE_DOCUMENTATION.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/CODEBASE_DOCUMENTATION.md) | 🇩🇪 [Deutsch](i18n/de/CODEBASE_DOCUMENTATION.md) | 🇮🇳 [हिन्दी](i18n/in/CODEBASE_DOCUMENTATION.md) | 🇹🇭 [ไทย](i18n/th/CODEBASE_DOCUMENTATION.md) | 🇺🇦 [Українська](i18n/uk-UA/CODEBASE_DOCUMENTATION.md) | 🇸🇦 [العربية](i18n/ar/CODEBASE_DOCUMENTATION.md) | 🇯🇵 [日本語](i18n/ja/CODEBASE_DOCUMENTATION.md) | 🇻🇳 [Tiếng Việt](i18n/vi/CODEBASE_DOCUMENTATION.md) | 🇧🇬 [Български](i18n/bg/CODEBASE_DOCUMENTATION.md) | 🇩🇰 [Dansk](i18n/da/CODEBASE_DOCUMENTATION.md) | 🇫🇮 [Suomi](i18n/fi/CODEBASE_DOCUMENTATION.md) | 🇮🇱 [עברית](i18n/he/CODEBASE_DOCUMENTATION.md) | 🇭🇺 [Magyar](i18n/hu/CODEBASE_DOCUMENTATION.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/CODEBASE_DOCUMENTATION.md) | 🇰🇷 [한국어](i18n/ko/CODEBASE_DOCUMENTATION.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/CODEBASE_DOCUMENTATION.md) | 🇳🇱 [Nederlands](i18n/nl/CODEBASE_DOCUMENTATION.md) | 🇳🇴 [Norsk](i18n/no/CODEBASE_DOCUMENTATION.md) | 🇵🇹 [Português (Portugal)](i18n/pt/CODEBASE_DOCUMENTATION.md) | 🇷🇴 [Română](i18n/ro/CODEBASE_DOCUMENTATION.md) | 🇵🇱 [Polski](i18n/pl/CODEBASE_DOCUMENTATION.md) | 🇸🇰 [Slovenčina](i18n/sk/CODEBASE_DOCUMENTATION.md) | 🇸🇪 [Svenska](i18n/sv/CODEBASE_DOCUMENTATION.md) | 🇵🇭 [Filipino](i18n/phi/CODEBASE_DOCUMENTATION.md)
-
-> A comprehensive, beginner-friendly guide to the **omniroute** multi-provider AI proxy router.
-
----
-
-## 1. What Is omniroute?
-
-omniroute is a **proxy router** that sits between AI clients (Claude CLI, Codex, Cursor IDE, etc.) and AI providers (Anthropic, Google, OpenAI, AWS, GitHub, etc.). It solves one big problem:
-
-> **Different AI clients speak different "languages" (API formats), and different AI providers expect different "languages" too.** omniroute translates between them automatically.
-
-Think of it like a universal translator at the United Nations — any delegate can speak any language, and the translator converts it for any other delegate.
-
----
-
-## 2. Architecture Overview
-
-```mermaid
-graph LR
- subgraph Clients
- A[Claude CLI]
- B[Codex]
- C[Cursor IDE]
- D[OpenAI-compatible]
- end
-
- subgraph omniroute
- E[Handler Layer]
- F[Translator Layer]
- G[Executor Layer]
- H[Services Layer]
- end
-
- subgraph Providers
- I[Anthropic Claude]
- J[Google Gemini]
- K[OpenAI / Codex]
- L[GitHub Copilot]
- M[AWS Kiro]
- N[Antigravity]
- O[Cursor API]
- end
-
- A --> E
- B --> E
- C --> E
- D --> E
- E --> F
- F --> G
- G --> I
- G --> J
- G --> K
- G --> L
- G --> M
- G --> N
- G --> O
- H -.-> E
- H -.-> G
-```
-
-### Core Principle: Hub-and-Spoke Translation
-
-All format translation passes through **OpenAI format as the hub**:
-
-```
-Client Format → [OpenAI Hub] → Provider Format (request)
-Provider Format → [OpenAI Hub] → Client Format (response)
-```
-
-This means you only need **N translators** (one per format) instead of **N²** (every pair).
-
----
-
-## 3. Project Structure
-
-```
-omniroute/
-├── open-sse/ ← Core proxy library (portable, framework-agnostic)
-│ ├── index.js ← Main entry point, exports everything
-│ ├── config/ ← Configuration & constants
-│ ├── executors/ ← Provider-specific request execution
-│ ├── handlers/ ← Request handling orchestration
-│ ├── services/ ← Business logic (auth, models, fallback, usage)
-│ ├── translator/ ← Format translation engine
-│ │ ├── request/ ← Request translators (8 files)
-│ │ ├── response/ ← Response translators (7 files)
-│ │ └── helpers/ ← Shared translation utilities (6 files)
-│ └── utils/ ← Utility functions
-├── src/ ← Application layer (Express/Worker runtime)
-│ ├── app/ ← Web UI, API routes, middleware
-│ ├── lib/ ← Database, auth, and shared library code
-│ ├── mitm/ ← Man-in-the-middle proxy utilities
-│ ├── models/ ← Database models
-│ ├── shared/ ← Shared utilities (wrappers around open-sse)
-│ ├── sse/ ← SSE endpoint handlers
-│ └── store/ ← State management
-├── data/ ← Runtime data (credentials, logs)
-│ └── provider-credentials.json (external credentials override, gitignored)
-└── tester/ ← Test utilities
-```
-
----
-
-## 4. Module-by-Module Breakdown
-
-### 4.1 Config (`open-sse/config/`)
-
-The **single source of truth** for all provider configuration.
-
-| File | Purpose |
-| ----------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| `constants.ts` | `PROVIDERS` object with base URLs, OAuth credentials (defaults), headers, and default system prompts for every provider. Also defines `HTTP_STATUS`, `ERROR_TYPES`, `COOLDOWN_MS`, `BACKOFF_CONFIG`, and `SKIP_PATTERNS`. |
-| `credentialLoader.ts` | Loads external credentials from `data/provider-credentials.json` and merges them over the hardcoded defaults in `PROVIDERS`. Keeps secrets out of source control while maintaining backwards compatibility. |
-| `providerModels.ts` | Central model registry: maps provider aliases → model IDs. Functions like `getModels()`, `getProviderByAlias()`. |
-| `codexInstructions.ts` | System instructions injected into Codex requests (editing constraints, sandbox rules, approval policies). |
-| `defaultThinkingSignature.ts` | Default "thinking" signatures for Claude and Gemini models. |
-| `ollamaModels.ts` | Schema definition for local Ollama models (name, size, family, quantization). |
-
-#### Credential Loading Flow
-
-```mermaid
-flowchart TD
- A["App starts"] --> B["constants.ts defines PROVIDERS\nwith hardcoded defaults"]
- B --> C{"data/provider-credentials.json\nexists?"}
- C -->|Yes| D["credentialLoader reads JSON"]
- C -->|No| E["Use hardcoded defaults"]
- D --> F{"For each provider in JSON"}
- F --> G{"Provider exists\nin PROVIDERS?"}
- G -->|No| H["Log warning, skip"]
- G -->|Yes| I{"Value is object?"}
- I -->|No| J["Log warning, skip"]
- I -->|Yes| K["Merge clientId, clientSecret,\ntokenUrl, authUrl, refreshUrl"]
- K --> F
- H --> F
- J --> F
- F -->|Done| L["PROVIDERS ready with\nmerged credentials"]
- E --> L
-```
-
----
-
-### 4.2 Executors (`open-sse/executors/`)
-
-Executors encapsulate **provider-specific logic** using the **Strategy Pattern**. Each executor overrides base methods as needed.
-
-```mermaid
-classDiagram
- class BaseExecutor {
- +buildUrl(model, stream, options)
- +buildHeaders(credentials, stream, body)
- +transformRequest(body, model, stream, credentials)
- +execute(url, options)
- +shouldRetry(status, error)
- +refreshCredentials(credentials, log)
- }
-
- class DefaultExecutor {
- +refreshCredentials()
- }
-
- class AntigravityExecutor {
- +buildUrl()
- +buildHeaders()
- +transformRequest()
- +shouldRetry()
- +refreshCredentials()
- }
-
- class CursorExecutor {
- +buildUrl()
- +buildHeaders()
- +transformRequest()
- +parseResponse()
- +generateChecksum()
- }
-
- class KiroExecutor {
- +buildUrl()
- +buildHeaders()
- +transformRequest()
- +parseEventStream()
- +refreshCredentials()
- }
-
- BaseExecutor <|-- DefaultExecutor
- BaseExecutor <|-- AntigravityExecutor
- BaseExecutor <|-- CursorExecutor
- BaseExecutor <|-- KiroExecutor
- BaseExecutor <|-- CodexExecutor
- BaseExecutor <|-- GeminiCLIExecutor
- BaseExecutor <|-- GithubExecutor
-```
-
-| Executor | Provider | Key Specializations |
-| ---------------- | ------------------------------------------ | ------------------------------------------------------------------------------------------------------------------- |
-| `base.ts` | — | Abstract base: URL building, headers, retry logic, credential refresh |
-| `default.ts` | Claude, Gemini, OpenAI, GLM, Kimi, MiniMax | Generic OAuth token refresh for standard providers |
-| `antigravity.ts` | Google Cloud Code | Project/session ID generation, multi-URL fallback, custom retry parsing from error messages ("reset after 2h7m23s") |
-| `cursor.ts` | Cursor IDE | **Most complex**: SHA-256 checksum auth, Protobuf request encoding, binary EventStream → SSE response parsing |
-| `codex.ts` | OpenAI Codex | Injects system instructions, manages thinking levels, removes unsupported parameters |
-| `gemini-cli.ts` | Google Gemini CLI | Custom URL building (`streamGenerateContent`), Google OAuth token refresh |
-| `github.ts` | GitHub Copilot | Dual token system (GitHub OAuth + Copilot token), VSCode header mimicking |
-| `kiro.ts` | AWS CodeWhisperer | AWS EventStream binary parsing, AMZN event frames, token estimation |
-| `index.ts` | — | Factory: maps provider name → executor class, with default fallback |
-
----
-
-### 4.3 Handlers (`open-sse/handlers/`)
-
-The **orchestration layer** — coordinates translation, execution, streaming, and error handling.
-
-| File | Purpose |
-| --------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| `chatCore.ts` | **Central orchestrator** (~600 lines). Handles the complete request lifecycle: format detection → translation → executor dispatch → streaming/non-streaming response → token refresh → error handling → usage logging. |
-| `responsesHandler.ts` | Adapter for OpenAI's Responses API: converts Responses format → Chat Completions → sends to `chatCore` → converts SSE back to Responses format. |
-| `embeddings.ts` | Embedding generation handler: resolves embedding model → provider, dispatches to provider API, returns OpenAI-compatible embedding response. Supports 6+ providers. |
-| `imageGeneration.ts` | Image generation handler: resolves image model → provider, supports OpenAI-compatible, Gemini-image (Antigravity), and fallback (Nebius) modes. Returns base64 or URL images. |
-
-#### Request Lifecycle (chatCore.ts)
-
-```mermaid
-sequenceDiagram
- participant Client
- participant chatCore
- participant Translator
- participant Executor
- participant Provider
-
- Client->>chatCore: Request (any format)
- chatCore->>chatCore: Detect source format
- chatCore->>chatCore: Check bypass patterns
- chatCore->>chatCore: Resolve model & provider
- chatCore->>Translator: Translate request (source → OpenAI → target)
- chatCore->>Executor: Get executor for provider
- Executor->>Executor: Build URL, headers, transform request
- Executor->>Executor: Refresh credentials if needed
- Executor->>Provider: HTTP fetch (streaming or non-streaming)
-
- alt Streaming
- Provider-->>chatCore: SSE stream
- chatCore->>chatCore: Pipe through SSE transform stream
- Note over chatCore: Transform stream translates
each chunk: target → OpenAI → source
- chatCore-->>Client: Translated SSE stream
- else Non-streaming
- Provider-->>chatCore: JSON response
- chatCore->>Translator: Translate response
- chatCore-->>Client: Translated JSON
- end
-
- alt Error (401, 429, 500...)
- chatCore->>Executor: Retry with credential refresh
- chatCore->>chatCore: Account fallback logic
- end
-```
-
----
-
-### 4.4 Services (`open-sse/services/`)
-
-Business logic that supports the handlers and executors.
-
-| File | Purpose |
-| -------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| `provider.ts` | **Format detection** (`detectFormat`): analyzes request body structure to identify Claude/OpenAI/Gemini/Antigravity/Responses formats (includes `max_tokens` heuristic for Claude). Also: URL building, header building, thinking config normalization. Supports `openai-compatible-*` and `anthropic-compatible-*` dynamic providers. |
-| `model.ts` | Model string parsing (`claude/model-name` → `{provider: "claude", model: "model-name"}`), alias resolution with collision detection, input sanitization (rejects path traversal/control chars), and model info resolution with async alias getter support. |
-| `accountFallback.ts` | Rate-limit handling: exponential backoff (1s → 2s → 4s → max 2min), account cooldown management, error classification (which errors trigger fallback vs. not). |
-| `tokenRefresh.ts` | OAuth token refresh for **every provider**: Google (Gemini, Antigravity), Claude, Codex, Qwen, Qoder, GitHub (OAuth + Copilot dual-token), Kiro (AWS SSO OIDC + Social Auth). Includes in-flight promise deduplication cache and retry with exponential backoff. |
-| `combo.ts` | **Combo models**: chains of fallback models. If model A fails with a fallback-eligible error, try model B, then C, etc. Returns actual upstream status codes. |
-| `usage.ts` | Fetches quota/usage data from provider APIs (GitHub Copilot quotas, Antigravity model quotas, Codex rate limits, Kiro usage breakdowns, Claude settings). |
-| `accountSelector.ts` | Smart account selection with scoring algorithm: considers priority, health status, round-robin position, and cooldown state to pick the optimal account for each request. |
-| `contextManager.ts` | Request context lifecycle management: creates and tracks per-request context objects with metadata (request ID, timestamps, provider info) for debugging and logging. |
-| `ipFilter.ts` | IP-based access control: supports allowlist and blocklist modes. Validates client IP against configured rules before processing API requests. |
-| `sessionManager.ts` | Session tracking with client fingerprinting: tracks active sessions using hashed client identifiers, monitors request counts, and provides session metrics. |
-| `signatureCache.ts` | Request signature-based deduplication cache: prevents duplicate requests by caching recent request signatures and returning cached responses for identical requests within a time window. |
-| `systemPrompt.ts` | Global system prompt injection: prepends or appends a configurable system prompt to all requests, with per-provider compatibility handling. |
-| `thinkingBudget.ts` | Reasoning token budget management: supports passthrough, auto (strip thinking config), custom (fixed budget), and adaptive (complexity-scaled) modes for controlling thinking/reasoning tokens. |
-| `wildcardRouter.ts` | Wildcard model pattern routing: resolves wildcard patterns (e.g., `*/claude-*`) to concrete provider/model pairs based on availability and priority. |
-
-#### Token Refresh Deduplication
-
-```mermaid
-sequenceDiagram
- participant R1 as Request 1
- participant R2 as Request 2
- participant Cache as refreshPromiseCache
- participant OAuth as OAuth Provider
-
- R1->>Cache: getAccessToken("gemini", token)
- Cache->>Cache: No in-flight promise
- Cache->>OAuth: Start refresh
- R2->>Cache: getAccessToken("gemini", token)
- Cache->>Cache: Found in-flight promise
- Cache-->>R2: Return existing promise
- OAuth-->>Cache: New access token
- Cache-->>R1: New access token
- Cache-->>R2: Same access token (shared)
- Cache->>Cache: Delete cache entry
-```
-
-#### Account Fallback State Machine
-
-```mermaid
-stateDiagram-v2
- [*] --> Active
- Active --> Error: Request fails (401/429/500)
- Error --> Cooldown: Apply backoff
- Cooldown --> Active: Cooldown expires
- Active --> Active: Request succeeds (reset backoff)
-
- state Error {
- [*] --> ClassifyError
- ClassifyError --> ShouldFallback: Rate limit / Auth / Transient
- ClassifyError --> NoFallback: 400 Bad Request
- }
-
- state Cooldown {
- [*] --> ExponentialBackoff
- ExponentialBackoff: Level 0 = 1s
- ExponentialBackoff: Level 1 = 2s
- ExponentialBackoff: Level 2 = 4s
- ExponentialBackoff: Max = 2min
- }
-```
-
-#### Combo Model Chain
-
-```mermaid
-flowchart LR
- A["Request with\ncombo model"] --> B["Model A"]
- B -->|"2xx Success"| C["Return response"]
- B -->|"429/401/500"| D{"Fallback\neligible?"}
- D -->|Yes| E["Model B"]
- D -->|No| F["Return error"]
- E -->|"2xx Success"| C
- E -->|"429/401/500"| G{"Fallback\neligible?"}
- G -->|Yes| H["Model C"]
- G -->|No| F
- H -->|"2xx Success"| C
- H -->|"Fail"| I["All failed →\nReturn last status"]
-```
-
----
-
-### 4.5 Translator (`open-sse/translator/`)
-
-The **format translation engine** using a self-registering plugin system.
-
-#### Architecture
-
-```mermaid
-graph TD
- subgraph "Request Translation"
- A["Claude → OpenAI"]
- B["Gemini → OpenAI"]
- C["Antigravity → OpenAI"]
- D["OpenAI Responses → OpenAI"]
- E["OpenAI → Claude"]
- F["OpenAI → Gemini"]
- G["OpenAI → Kiro"]
- H["OpenAI → Cursor"]
- end
-
- subgraph "Response Translation"
- I["Claude → OpenAI"]
- J["Gemini → OpenAI"]
- K["Kiro → OpenAI"]
- L["Cursor → OpenAI"]
- M["OpenAI → Claude"]
- N["OpenAI → Antigravity"]
- O["OpenAI → Responses"]
- end
-```
-
-| Directory | Files | Description |
-| ------------ | ------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| `request/` | 8 translators | Convert request bodies between formats. Each file self-registers via `register(from, to, fn)` on import. |
-| `response/` | 7 translators | Convert streaming response chunks between formats. Handles SSE event types, thinking blocks, tool calls. |
-| `helpers/` | 6 helpers | Shared utilities: `claudeHelper` (system prompt extraction, thinking config), `geminiHelper` (parts/contents mapping), `openaiHelper` (format filtering), `toolCallHelper` (ID generation, missing response injection), `maxTokensHelper`, `responsesApiHelper`. |
-| `index.ts` | — | Translation engine: `translateRequest()`, `translateResponse()`, state management, registry. |
-| `formats.ts` | — | Format constants: `OPENAI`, `CLAUDE`, `GEMINI`, `ANTIGRAVITY`, `KIRO`, `CURSOR`, `OPENAI_RESPONSES`. |
-
-#### Key Design: Self-Registering Plugins
-
-```javascript
-// Each translator file calls register() on import:
-import { register } from "../index.js";
-register("claude", "openai", translateClaudeToOpenAI);
-
-// The index.js imports all translator files, triggering registration:
-import "./request/claude-to-openai.js"; // ← self-registers
-```
-
----
-
-### 4.6 Utils (`open-sse/utils/`)
-
-| File | Purpose |
-| ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
-| `error.ts` | Error response building (OpenAI-compatible format), upstream error parsing, Antigravity retry-time extraction from error messages, SSE error streaming. |
-| `stream.ts` | **SSE Transform Stream** — the core streaming pipeline. Two modes: `TRANSLATE` (full format translation) and `PASSTHROUGH` (normalize + extract usage). Handles chunk buffering, usage estimation, content length tracking. Per-stream encoder/decoder instances avoid shared state. |
-| `streamHelpers.ts` | Low-level SSE utilities: `parseSSELine` (whitespace-tolerant), `hasValuableContent` (filters empty chunks for OpenAI/Claude/Gemini), `fixInvalidId`, `formatSSE` (format-aware SSE serialization with `perf_metrics` cleanup). |
-| `usageTracking.ts` | Token usage extraction from any format (Claude/OpenAI/Gemini/Responses), estimation with separate tool/message char-per-token ratios, buffer addition (2000 tokens safety margin), format-specific field filtering, console logging with ANSI colors. |
-| `requestLogger.ts` | File-based request logging (opt-in via `ENABLE_REQUEST_LOGS=true`). Creates session folders with numbered files: `1_req_client.json` → `7_res_client.txt`. All I/O is async (fire-and-forget). Masks sensitive headers. |
-| `bypassHandler.ts` | Intercepts specific patterns from Claude CLI (title extraction, warmup, count) and returns fake responses without calling any provider. Supports both streaming and non-streaming. Intentionally limited to Claude CLI scope. |
-| `networkProxy.ts` | Resolves outbound proxy URL for a given provider with precedence: provider-specific config → global config → environment variables (`HTTPS_PROXY`/`HTTP_PROXY`/`ALL_PROXY`). Supports `NO_PROXY` exclusions. Caches config for 30s. |
-
-#### SSE Streaming Pipeline
-
-```mermaid
-flowchart TD
- A["Provider SSE stream"] --> B["TextDecoder\n(per-stream instance)"]
- B --> C["Buffer lines\n(split on newline)"]
- C --> D["parseSSELine()\n(trim whitespace, parse JSON)"]
- D --> E{"Mode?"}
- E -->|TRANSLATE| F["translateResponse()\ntarget → OpenAI → source"]
- E -->|PASSTHROUGH| G["fixInvalidId()\nnormalize chunk"]
- F --> H["hasValuableContent()\nfilter empty chunks"]
- G --> H
- H -->|"Has content"| I["extractUsage()\ntrack token counts"]
- H -->|"Empty"| J["Skip chunk"]
- I --> K["formatSSE()\nserialize + clean perf_metrics"]
- K --> L["TextEncoder\n(per-stream instance)"]
- L --> M["Enqueue to\nclient stream"]
-
- style A fill:#f9f,stroke:#333
- style M fill:#9f9,stroke:#333
-```
-
-#### Request Logger Session Structure
-
-```
-logs/
-└── claude_gemini_claude-sonnet_20260208_143045/
- ├── 1_req_client.json ← Raw client request
- ├── 2_req_source.json ← After initial conversion
- ├── 3_req_openai.json ← OpenAI intermediate format
- ├── 4_req_target.json ← Final target format
- ├── 5_res_provider.txt ← Provider SSE chunks (streaming)
- ├── 5_res_provider.json ← Provider response (non-streaming)
- ├── 6_res_openai.txt ← OpenAI intermediate chunks
- ├── 7_res_client.txt ← Client-facing SSE chunks
- └── 6_error.json ← Error details (if any)
-```
-
----
-
-### 4.7 Application Layer (`src/`)
-
-| Directory | Purpose |
-| ------------- | ---------------------------------------------------------------------- |
-| `src/app/` | Web UI, API routes, Express middleware, OAuth callback handlers |
-| `src/lib/` | Database access (`localDb.ts`, `usageDb.ts`), authentication, shared |
-| `src/mitm/` | Man-in-the-middle proxy utilities for intercepting provider traffic |
-| `src/models/` | Database model definitions |
-| `src/shared/` | Wrappers around open-sse functions (provider, stream, error, etc.) |
-| `src/sse/` | SSE endpoint handlers that wire the open-sse library to Express routes |
-| `src/store/` | Application state management |
-
-#### Notable API Routes
-
-| Route | Methods | Purpose |
-| --------------------------------------------- | --------------- | ------------------------------------------------------------------------------------- |
-| `/api/provider-models` | GET/POST/DELETE | CRUD for custom models per provider |
-| `/api/models/catalog` | GET | Aggregated catalog of all models (chat, embedding, image, custom) grouped by provider |
-| `/api/settings/proxy` | GET/PUT/DELETE | Hierarchical outbound proxy configuration (`global/providers/combos/keys`) |
-| `/api/settings/proxy/test` | POST | Validates proxy connectivity and returns public IP/latency |
-| `/v1/providers/[provider]/chat/completions` | POST | Dedicated per-provider chat completions with model validation |
-| `/v1/providers/[provider]/embeddings` | POST | Dedicated per-provider embeddings with model validation |
-| `/v1/providers/[provider]/images/generations` | POST | Dedicated per-provider image generation with model validation |
-| `/api/settings/ip-filter` | GET/PUT | IP allowlist/blocklist management |
-| `/api/settings/thinking-budget` | GET/PUT | Reasoning token budget configuration (passthrough/auto/custom/adaptive) |
-| `/api/settings/system-prompt` | GET/PUT | Global system prompt injection for all requests |
-| `/api/sessions` | GET | Active session tracking and metrics |
-| `/api/rate-limits` | GET | Per-account rate limit status |
-
----
-
-## 5. Key Design Patterns
-
-### 5.1 Hub-and-Spoke Translation
-
-All formats translate through **OpenAI format as the hub**. Adding a new provider only requires writing **one pair** of translators (to/from OpenAI), not N pairs.
-
-### 5.2 Executor Strategy Pattern
-
-Each provider has a dedicated executor class inheriting from `BaseExecutor`. The factory in `executors/index.ts` selects the right one at runtime.
-
-### 5.3 Self-Registering Plugin System
-
-Translator modules register themselves on import via `register()`. Adding a new translator is just creating a file and importing it.
-
-### 5.4 Account Fallback with Exponential Backoff
-
-When a provider returns 429/401/500, the system can switch to the next account, applying exponential cooldowns (1s → 2s → 4s → max 2min).
-
-### 5.5 Combo Model Chains
-
-A "combo" groups multiple `provider/model` strings. If the first fails, fallback to the next automatically.
-
-### 5.6 Stateful Streaming Translation
-
-Response translation maintains state across SSE chunks (thinking block tracking, tool call accumulation, content block indexing) via the `initState()` mechanism.
-
-### 5.7 Usage Safety Buffer
-
-A 2000-token buffer is added to reported usage to prevent clients from hitting context window limits due to overhead from system prompts and format translation.
-
----
-
-## 6. Supported Formats
-
-| Format | Direction | Identifier |
-| ----------------------- | --------------- | ------------------ |
-| OpenAI Chat Completions | source + target | `openai` |
-| OpenAI Responses API | source + target | `openai-responses` |
-| Anthropic Claude | source + target | `claude` |
-| Google Gemini | source + target | `gemini` |
-| Google Gemini CLI | target only | `gemini-cli` |
-| Antigravity | source + target | `antigravity` |
-| AWS Kiro | target only | `kiro` |
-| Cursor | target only | `cursor` |
-
----
-
-## 7. Supported Providers
-
-| Provider | Auth Method | Executor | Key Notes |
-| ------------------------ | ---------------------- | ----------- | --------------------------------------------- |
-| Anthropic Claude | API key or OAuth | Default | Uses `x-api-key` header |
-| Google Gemini | API key or OAuth | Default | Uses `x-goog-api-key` header |
-| Google Gemini CLI | OAuth | GeminiCLI | Uses `streamGenerateContent` endpoint |
-| Antigravity | OAuth | Antigravity | Multi-URL fallback, custom retry parsing |
-| OpenAI | API key | Default | Standard Bearer auth |
-| Codex | OAuth | Codex | Injects system instructions, manages thinking |
-| GitHub Copilot | OAuth + Copilot token | Github | Dual token, VSCode header mimicking |
-| Kiro (AWS) | AWS SSO OIDC or Social | Kiro | Binary EventStream parsing |
-| Cursor IDE | Checksum auth | Cursor | Protobuf encoding, SHA-256 checksums |
-| Qwen | OAuth | Default | Standard auth |
-| Qoder | OAuth (Basic + Bearer) | Default | Dual auth header |
-| OpenRouter | API key | Default | Standard Bearer auth |
-| GLM, Kimi, MiniMax | API key | Default | Claude-compatible, use `x-api-key` |
-| `openai-compatible-*` | API key | Default | Dynamic: any OpenAI-compatible endpoint |
-| `anthropic-compatible-*` | API key | Default | Dynamic: any Claude-compatible endpoint |
-
----
-
-## 8. Data Flow Summary
-
-### Streaming Request
-
-```mermaid
-flowchart LR
- A["Client"] --> B["detectFormat()"]
- B --> C["translateRequest()\nsource → OpenAI → target"]
- C --> D["Executor\nbuildUrl + buildHeaders"]
- D --> E["fetch(providerURL)"]
- E --> F["createSSEStream()\nTRANSLATE mode"]
- F --> G["parseSSELine()"]
- G --> H["translateResponse()\ntarget → OpenAI → source"]
- H --> I["extractUsage()\n+ addBuffer"]
- I --> J["formatSSE()"]
- J --> K["Client receives\ntranslated SSE"]
- K --> L["logUsage()\nsaveRequestUsage()"]
-```
-
-### Non-Streaming Request
-
-```mermaid
-flowchart LR
- A["Client"] --> B["detectFormat()"]
- B --> C["translateRequest()\nsource → OpenAI → target"]
- C --> D["Executor.execute()"]
- D --> E["translateResponse()\ntarget → OpenAI → source"]
- E --> F["Return JSON\nresponse"]
-```
-
-### Bypass Flow (Claude CLI)
-
-```mermaid
-flowchart LR
- A["Claude CLI request"] --> B{"Match bypass\npattern?"}
- B -->|"Title/Warmup/Count"| C["Generate fake\nOpenAI response"]
- B -->|"No match"| D["Normal flow"]
- C --> E["Translate to\nsource format"]
- E --> F["Return without\ncalling provider"]
-```
diff --git a/docs/i18n/fr/CONTRIBUTING.md b/docs/i18n/fr/CONTRIBUTING.md
new file mode 100644
index 0000000000..3c1de7b148
--- /dev/null
+++ b/docs/i18n/fr/CONTRIBUTING.md
@@ -0,0 +1,299 @@
+# Contributing to OmniRoute (Français)
+
+🌐 **Languages:** 🇺🇸 [English](../../../CONTRIBUTING.md) · 🇪🇸 [es](../es/CONTRIBUTING.md) · 🇫🇷 [fr](../fr/CONTRIBUTING.md) · 🇩🇪 [de](../de/CONTRIBUTING.md) · 🇮🇹 [it](../it/CONTRIBUTING.md) · 🇷🇺 [ru](../ru/CONTRIBUTING.md) · 🇨🇳 [zh-CN](../zh-CN/CONTRIBUTING.md) · 🇯🇵 [ja](../ja/CONTRIBUTING.md) · 🇰🇷 [ko](../ko/CONTRIBUTING.md) · 🇸🇦 [ar](../ar/CONTRIBUTING.md) · 🇮🇳 [in](../in/CONTRIBUTING.md) · 🇹🇭 [th](../th/CONTRIBUTING.md) · 🇻🇳 [vi](../vi/CONTRIBUTING.md) · 🇮🇩 [id](../id/CONTRIBUTING.md) · 🇲🇾 [ms](../ms/CONTRIBUTING.md) · 🇳🇱 [nl](../nl/CONTRIBUTING.md) · 🇵🇱 [pl](../pl/CONTRIBUTING.md) · 🇸🇪 [sv](../sv/CONTRIBUTING.md) · 🇳🇴 [no](../no/CONTRIBUTING.md) · 🇩🇰 [da](../da/CONTRIBUTING.md) · 🇫🇮 [fi](../fi/CONTRIBUTING.md) · 🇵🇹 [pt](../pt/CONTRIBUTING.md) · 🇷🇴 [ro](../ro/CONTRIBUTING.md) · 🇭🇺 [hu](../hu/CONTRIBUTING.md) · 🇧🇬 [bg](../bg/CONTRIBUTING.md) · 🇸🇰 [sk](../sk/CONTRIBUTING.md) · 🇺🇦 [uk-UA](../uk-UA/CONTRIBUTING.md) · 🇮🇱 [he](../he/CONTRIBUTING.md) · 🇵🇭 [phi](../phi/CONTRIBUTING.md) · 🇧🇷 [pt-BR](../pt-BR/CONTRIBUTING.md) · 🇨🇿 [cs](../cs/CONTRIBUTING.md)
+
+---
+
+Thank you for your interest in contributing! This guide covers everything you need to get started.
+
+---
+
+## Development Setup
+
+### Prerequisites
+
+- **Node.js** >= 18 < 24 (recommended: 22 LTS)
+- **npm** 10+
+- **Git**
+
+### Clone & Install
+
+```bash
+git clone https://github.com/diegosouzapw/OmniRoute.git
+cd OmniRoute
+npm install
+```
+
+### Environment Variables
+
+```bash
+# Create your .env from the template
+cp .env.example .env
+
+# Generate required secrets
+echo "JWT_SECRET=$(openssl rand -base64 48)" >> .env
+echo "API_KEY_SECRET=$(openssl rand -hex 32)" >> .env
+```
+
+Key variables for development:
+
+| Variable | Development Default | Description |
+| ---------------------- | ------------------------ | --------------------- |
+| `PORT` | `20128` | Server port |
+| `NEXT_PUBLIC_BASE_URL` | `http://localhost:20128` | Base URL for frontend |
+| `JWT_SECRET` | (generate above) | JWT signing secret |
+| `INITIAL_PASSWORD` | `CHANGEME` | First login password |
+| `APP_LOG_LEVEL` | `info` | Log verbosity level |
+
+### Dashboard Settings
+
+The dashboard provides UI toggles for features that can also be configured via environment variables:
+
+| Setting Location | Toggle | Description |
+| ------------------- | ------------------ | ------------------------------ |
+| Settings → Advanced | Debug Mode | Enable debug request logs (UI) |
+| Settings → General | Sidebar Visibility | Show/hide sidebar sections |
+
+These settings are stored in the database and persist across restarts, overriding env var defaults when set.
+
+### Running Locally
+
+```bash
+# Development mode (hot reload)
+npm run dev
+
+# Production build
+npm run build
+npm run start
+
+# Common port configuration
+PORT=20128 NEXT_PUBLIC_BASE_URL=http://localhost:20128 npm run dev
+```
+
+Default URLs:
+
+- **Dashboard**: `http://localhost:20128/dashboard`
+- **API**: `http://localhost:20128/v1`
+
+---
+
+## Git Workflow
+
+> ⚠️ **NEVER commit directly to `main`.** Always use feature branches.
+
+```bash
+git checkout -b feat/your-feature-name
+# ... make changes ...
+git commit -m "feat: describe your change"
+git push -u origin feat/your-feature-name
+# Open a Pull Request on GitHub
+```
+
+### Branch Naming
+
+| Prefix | Purpose |
+| ----------- | ------------------------- |
+| `feat/` | New features |
+| `fix/` | Bug fixes |
+| `refactor/` | Code restructuring |
+| `docs/` | Documentation changes |
+| `test/` | Test additions/fixes |
+| `chore/` | Tooling, CI, dependencies |
+
+### Commit Messages
+
+Follow [Conventional Commits](https://www.conventionalcommits.org/):
+
+```
+feat: add circuit breaker for provider calls
+fix: resolve JWT secret validation edge case
+docs: update SECURITY.md with PII protection
+test: add observability unit tests
+refactor(db): consolidate rate limit tables
+```
+
+Scopes: `db`, `sse`, `oauth`, `dashboard`, `api`, `cli`, `docker`, `ci`, `mcp`, `a2a`, `memory`, `skills`.
+
+---
+
+## Running Tests
+
+```bash
+# All tests (unit + vitest + ecosystem + e2e)
+npm run test:all
+
+# Single test file (Node.js native test runner — most tests use this)
+node --import tsx/esm --test tests/unit/your-file.test.mjs
+
+# Vitest (MCP server, autoCombo, cache)
+npm run test:vitest
+
+# E2E tests (requires Playwright)
+npm run test:e2e
+
+# Protocol clients E2E (MCP transports, A2A)
+npm run test:protocols:e2e
+
+# Ecosystem compatibility tests
+npm run test:ecosystem
+
+# Coverage (55% min statements/lines/functions; 60% branches)
+npm run test:coverage
+npm run coverage:report
+
+# Lint + format check
+npm run lint
+npm run check
+```
+
+Coverage notes:
+
+- `npm run test:coverage` measures source coverage for the main unit test suite, excludes `tests/**`, and includes `open-sse/**`
+- `npm run coverage:report` prints the detailed file-by-file report from the latest coverage run
+- `npm run test:coverage:legacy` preserves the older metric for historical comparison
+- See `docs/COVERAGE_PLAN.md` for the phased coverage improvement roadmap
+
+Current test status: **122 unit test files** covering:
+
+- Provider translators and format conversion
+- Rate limiting, circuit breaker, and resilience
+- Semantic cache, idempotency, progress tracking
+- Database operations and schema (21 DB modules)
+- OAuth flows and authentication
+- API endpoint validation (Zod v4)
+- MCP server tools and scope enforcement
+- Memory and Skills systems
+
+---
+
+## Code Style
+
+- **ESLint** — Run `npm run lint` before committing
+- **Prettier** — Auto-formatted via `lint-staged` on commit (2 spaces, semicolons, double quotes, 100 char width, es5 trailing commas)
+- **TypeScript** — All `src/` code uses `.ts`/`.tsx`; `open-sse/` uses `.ts`/`.js`; document with TSDoc (`@param`, `@returns`, `@throws`)
+- **No `eval()`** — ESLint enforces `no-eval`, `no-implied-eval`, `no-new-func`
+- **Zod validation** — Use Zod v4 schemas for all API input validation
+- **Naming**: Files = camelCase/kebab-case, components = PascalCase, constants = UPPER_SNAKE
+
+---
+
+## Project Structure
+
+```
+src/ # TypeScript (.ts / .tsx)
+├── app/ # Next.js 16 App Router
+│ ├── (dashboard)/ # Dashboard pages (23 sections)
+│ ├── api/ # API routes (51 directories)
+│ └── login/ # Auth pages (.tsx)
+├── domain/ # Policy engine (policyEngine, comboResolver, costRules, etc.)
+├── lib/ # Core business logic (.ts)
+│ ├── a2a/ # Agent-to-Agent v0.3 protocol server
+│ ├── acp/ # Agent Communication Protocol registry
+│ ├── compliance/ # Compliance policy engine
+│ ├── db/ # SQLite database layer (21 modules + 16 migrations)
+│ ├── memory/ # Persistent conversational memory
+│ ├── oauth/ # OAuth providers, services, and utilities
+│ ├── skills/ # Extensible skill framework
+│ ├── usage/ # Usage tracking and cost calculation
+│ └── localDb.ts # Re-export layer only — never add logic here
+├── middleware/ # Request middleware (promptInjectionGuard)
+├── mitm/ # MITM proxy (cert, DNS, target routing)
+├── shared/
+│ ├── components/ # React components (.tsx)
+│ ├── constants/ # Provider definitions (60+), MCP scopes, routing strategies
+│ ├── utils/ # Circuit breaker, sanitizer, auth helpers
+│ └── validation/ # Zod v4 schemas
+└── sse/ # SSE proxy pipeline
+
+open-sse/ # @omniroute/open-sse workspace
+├── executors/ # 14 provider-specific request executors
+├── handlers/ # 11 request handlers (chat, responses, embeddings, images, etc.)
+├── mcp-server/ # MCP server (25 tools, 3 transports, 10 scopes)
+├── services/ # 36+ services (combo, autoCombo, rateLimitManager, etc.)
+├── translator/ # Format translators (OpenAI ↔ Claude ↔ Gemini ↔ Responses ↔ Ollama)
+├── transformer/ # Responses API transformer
+└── utils/ # 22 utility modules (stream, TLS, proxy, logging)
+
+electron/ # Electron desktop app (cross-platform)
+
+tests/
+├── unit/ # Node.js test runner (122 test files)
+├── integration/ # Integration tests
+├── e2e/ # Playwright tests
+├── security/ # Security tests
+├── translator/ # Translator-specific tests
+└── load/ # Load tests
+
+docs/ # Documentation
+├── ARCHITECTURE.md # System architecture
+├── API_REFERENCE.md # All endpoints
+├── USER_GUIDE.md # Provider setup, CLI integration
+├── TROUBLESHOOTING.md # Common issues
+├── MCP-SERVER.md # MCP server (25 tools)
+├── A2A-SERVER.md # A2A agent protocol
+├── AUTO-COMBO.md # Auto-combo engine
+├── CLI-TOOLS.md # CLI tools integration
+├── COVERAGE_PLAN.md # Test coverage improvement plan
+├── openapi.yaml # OpenAPI specification
+└── adr/ # Architecture Decision Records
+```
+
+---
+
+## Adding a New Provider
+
+### Step 1: Register Provider Constants
+
+Add to `src/shared/constants/providers.ts` — Zod-validated at module load.
+
+### Step 2: Add Executor (if custom logic needed)
+
+Create executor in `open-sse/executors/your-provider.ts` extending the base executor.
+
+### Step 3: Add Translator (if non-OpenAI format)
+
+Create request/response translators in `open-sse/translator/`.
+
+### Step 4: Add OAuth Config (if OAuth-based)
+
+Add OAuth credentials in `src/lib/oauth/constants/oauth.ts` and service in `src/lib/oauth/services/`.
+
+### Step 5: Register Models
+
+Add model definitions in `open-sse/config/providerRegistry.ts`.
+
+### Step 6: Add Tests
+
+Write unit tests in `tests/unit/` covering at minimum:
+
+- Provider registration
+- Request/response translation
+- Error handling
+
+---
+
+## Pull Request Checklist
+
+- [ ] Tests pass (`npm test`)
+- [ ] Linting passes (`npm run lint`)
+- [ ] Build succeeds (`npm run build`)
+- [ ] TypeScript types added for new public functions and interfaces
+- [ ] No hardcoded secrets or fallback values
+- [ ] All inputs validated with Zod schemas
+- [ ] CHANGELOG updated (if user-facing change)
+- [ ] Documentation updated (if applicable)
+
+---
+
+## Releasing
+
+Releases are managed via the `/generate-release` workflow. When a new GitHub Release is created, the package is **automatically published to npm** via GitHub Actions.
+
+---
+
+## Getting Help
+
+- **Architecture**: See [`docs/ARCHITECTURE.md`](docs/ARCHITECTURE.md)
+- **API Reference**: See [`docs/API_REFERENCE.md`](docs/API_REFERENCE.md)
+- **Issues**: [github.com/diegosouzapw/OmniRoute/issues](https://github.com/diegosouzapw/OmniRoute/issues)
+- **ADRs**: See `docs/adr/` for architectural decision records
diff --git a/docs/i18n/fr/FEATURES.md b/docs/i18n/fr/FEATURES.md
deleted file mode 100644
index a65b5ba05c..0000000000
--- a/docs/i18n/fr/FEATURES.md
+++ /dev/null
@@ -1,147 +0,0 @@
-# OmniRoute — Dashboard Features Gallery (Français)
-
-🌐 **Languages:** 🇺🇸 [English](../../../README.md) · 🇧🇷 [pt-BR](../pt-BR/README.md) · 🇪🇸 [es](../es/README.md) · 🇫🇷 [fr](../fr/README.md) · 🇩🇪 [de](../de/README.md) · 🇮🇹 [it](../it/README.md) · 🇷🇺 [ru](../ru/README.md) · 🇨🇳 [zh-CN](../zh-CN/README.md) · 🇯🇵 [ja](../ja/README.md) · 🇰🇷 [ko](../ko/README.md) · 🇸🇦 [ar](../ar/README.md) · 🇮🇳 [in](../in/README.md) · 🇹🇭 [th](../th/README.md) · 🇻🇳 [vi](../vi/README.md) · 🇮🇩 [id](../id/README.md) · 🇲🇾 [ms](../ms/README.md) · 🇳🇱 [nl](../nl/README.md) · 🇵🇱 [pl](../pl/README.md) · 🇸🇪 [sv](../sv/README.md) · 🇳🇴 [no](../no/README.md) · 🇩🇰 [da](../da/README.md) · 🇫🇮 [fi](../fi/README.md) · 🇵🇹 [pt](../pt/README.md) · 🇷🇴 [ro](../ro/README.md) · 🇭🇺 [hu](../hu/README.md) · 🇧🇬 [bg](../bg/README.md) · 🇸🇰 [sk](../sk/README.md) · 🇺🇦 [uk-UA](../uk-UA/README.md) · 🇮🇱 [he](../he/README.md) · 🇵🇭 [phi](../phi/README.md)
-
-> 🇺🇸 [English](../../../docs/FEATURES.md)
-
----
-
-Visual guide to every section of the OmniRoute dashboard.
-
----
-
-## 🔌 Providers
-
-Manage AI provider connections: OAuth providers (Claude Code, Codex, Gemini CLI), API key providers (Groq, DeepSeek, OpenRouter), and free providers (Qoder, Qwen, Kiro). Kiro accounts include credit balance tracking — remaining credits, total allowance, and renewal date visible in Dashboard → Usage.
-
-
-
----
-
-## 🎨 Combos
-
-Create model routing combos with 6 strategies: priority, weighted, round-robin, random, least-used, and cost-optimized. Each combo chains multiple models with automatic fallback and includes quick templates and readiness checks.
-
-
-
----
-
-## 📊 Analytics
-
-Comprehensive usage analytics with token consumption, cost estimates, activity heatmaps, weekly distribution charts, and per-provider breakdowns.
-
-
-
----
-
-## 🏥 System Health
-
-Real-time monitoring: uptime, memory, version, latency percentiles (p50/p95/p99), cache statistics, and provider circuit breaker states.
-
-
-
----
-
-## 🔧 Translator Playground
-
-Four modes for debugging API translations: **Playground** (format converter), **Chat Tester** (live requests), **Test Bench** (batch tests), and **Live Monitor** (real-time stream).
-
-
-
----
-
-## 🎮 Model Playground _(v2.0.9+)_
-
-Test any model directly from the dashboard. Select provider, model, and endpoint, write prompts with Monaco Editor, stream responses in real-time, abort mid-stream, and view timing metrics.
-
----
-
-## 🎨 Themes _(v2.0.5+)_
-
-Customizable color themes for the entire dashboard. Choose from 7 preset colors (Coral, Blue, Red, Green, Violet, Orange, Cyan) or create a custom theme by picking any hex color. Supports light, dark, and system mode.
-
----
-
-## ⚙️ Settings
-
-Comprehensive settings panel with tabs:
-
-- **General** — System storage, backup management (export/import database)
-- **Appearance** — Theme selector (dark/light/system), color theme presets and custom colors, health log visibility, sidebar item visibility controls
-- **Security** — API endpoint protection, custom provider blocking, IP filtering, session info
-- **Routing** — Model aliases, background task degradation
-- **Resilience** — Rate limit persistence, circuit breaker tuning
-- **Advanced** — Configuration overrides
-
-
-
----
-
-## 🔧 CLI Tools
-
-One-click configuration for AI coding tools: Claude Code, Codex CLI, Gemini CLI, OpenClaw, Kilo Code, Antigravity, Cline, Continue, Cursor, and Factory Droid. Features automated config apply/reset, connection profiles, and model mapping.
-
-
-
----
-
-## 🤖 CLI Agents _(v2.0.11+)_
-
-Dashboard for discovering and managing CLI agents. Shows a grid of 14 built-in agents (Codex, Claude, Goose, Gemini CLI, OpenClaw, Aider, OpenCode, Cline, Qwen Code, ForgeCode, Amazon Q, Open Interpreter, Cursor CLI, Warp) with:
-
-- **Installation status** — Installed / Not Found with version detection
-- **Protocol badges** — stdio, HTTP, etc.
-- **Custom agents** — Register any CLI tool via form (name, binary, version command, spawn args)
-- **CLI Fingerprint Matching** — Per-provider toggle to match native CLI request signatures, reducing ban risk while preserving proxy IP
-
----
-
-## 🖼️ Media _(v2.0.3+)_
-
-Generate images, videos, and music from the dashboard. Supports OpenAI, xAI, Together, Hyperbolic, SD WebUI, ComfyUI, AnimateDiff, Stable Audio Open, and MusicGen.
-
----
-
-## 📝 Request Logs
-
-Real-time request logging with filtering by provider, model, account, and API key. Shows status codes, token usage, latency, and response details.
-
-
-
----
-
-## 🌐 API Endpoint
-
-Your unified API endpoint with capability breakdown: Chat Completions, Responses API, Embeddings, Image Generation, Reranking, Audio Transcription, Text-to-Speech, Moderations, and registered API keys. Cloud proxy support for remote access.
-
-
-
----
-
-## 🔑 API Key Management
-
-Create, scope, and revoke API keys. Each key can be restricted to specific models/providers with full access or read-only permissions. Visual key management with usage tracking.
-
----
-
-## 📋 Audit Log
-
-Administrative action tracking with filtering by action type, actor, target, IP address, and timestamp. Full security event history.
-
----
-
-## 🖥️ Desktop Application
-
-Native Electron desktop app for Windows, macOS, and Linux. Run OmniRoute as a standalone application with system tray integration, offline support, auto-update, and one-click install.
-
-Key features:
-
-- Server readiness polling (no blank screen on cold start)
-- System tray with port management
-- Content Security Policy
-- Single-instance lock
-- Auto-update on restart
-- Platform-conditional UI (macOS traffic lights, Windows/Linux default titlebar)
-- Hardened Electron build packaging — symlinked `node_modules` in the standalone bundle is detected and rejected before packaging, preventing runtime dependency on the build machine (v2.5.5+)
-
-📖 See [`electron/README.md`](../electron/README.md) for full documentation.
diff --git a/docs/i18n/fr/MCP-SERVER.md b/docs/i18n/fr/MCP-SERVER.md
deleted file mode 100644
index 829acd30b1..0000000000
--- a/docs/i18n/fr/MCP-SERVER.md
+++ /dev/null
@@ -1,87 +0,0 @@
-🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/MCP-SERVER.md) · 🇪🇸 [es](../es/MCP-SERVER.md) · 🇫🇷 [fr](../fr/MCP-SERVER.md) · 🇩🇪 [de](../de/MCP-SERVER.md) · 🇮🇹 [it](../it/MCP-SERVER.md) · 🇷🇺 [ru](../ru/MCP-SERVER.md) · 🇨🇳 [zh-CN](../zh-CN/MCP-SERVER.md) · 🇯🇵 [ja](../ja/MCP-SERVER.md) · 🇰🇷 [ko](../ko/MCP-SERVER.md) · 🇸🇦 [ar](../ar/MCP-SERVER.md) · 🇮🇳 [in](../in/MCP-SERVER.md) · 🇹🇭 [th](../th/MCP-SERVER.md) · 🇻🇳 [vi](../vi/MCP-SERVER.md) · 🇮🇩 [id](../id/MCP-SERVER.md) · 🇲🇾 [ms](../ms/MCP-SERVER.md) · 🇳🇱 [nl](../nl/MCP-SERVER.md) · 🇵🇱 [pl](../pl/MCP-SERVER.md) · 🇸🇪 [sv](../sv/MCP-SERVER.md) · 🇳🇴 [no](../no/MCP-SERVER.md) · 🇩🇰 [da](../da/MCP-SERVER.md) · 🇫🇮 [fi](../fi/MCP-SERVER.md) · 🇵🇹 [pt](../pt/MCP-SERVER.md) · 🇷🇴 [ro](../ro/MCP-SERVER.md) · 🇭🇺 [hu](../hu/MCP-SERVER.md) · 🇧🇬 [bg](../bg/MCP-SERVER.md) · 🇸🇰 [sk](../sk/MCP-SERVER.md) · 🇺🇦 [uk-UA](../uk-UA/MCP-SERVER.md) · 🇮🇱 [he](../he/MCP-SERVER.md) · 🇵🇭 [phi](../phi/MCP-SERVER.md)
-
----
-
-# OmniRoute MCP Server Documentation
-
-> Model Context Protocol server with 16 intelligent tools
-
-## Installation
-
-OmniRoute MCP is built-in. Start it with:
-
-```bash
-omniroute --mcp
-```
-
-Or via the open-sse transport:
-
-```bash
-# HTTP streamable transport (port 20130)
-omniroute --dev # MCP auto-starts on /mcp endpoint
-```
-
-## IDE Configuration
-
-See [IDE Configs](integrations/ide-configs.md) for Antigravity, Cursor, Copilot, and Claude Desktop setup.
-
----
-
-## Essential Tools (8)
-
-| Tool | Description |
-| :------------------------------ | :--------------------------------------- |
-| `omniroute_get_health` | Gateway health, circuit breakers, uptime |
-| `omniroute_list_combos` | All configured combos with models |
-| `omniroute_get_combo_metrics` | Performance metrics for a specific combo |
-| `omniroute_switch_combo` | Switch active combo by ID/name |
-| `omniroute_check_quota` | Quota status per provider or all |
-| `omniroute_route_request` | Send a chat completion through OmniRoute |
-| `omniroute_cost_report` | Cost analytics for a time period |
-| `omniroute_list_models_catalog` | Full model catalog with capabilities |
-
-## Advanced Tools (8)
-
-| Tool | Description |
-| :--------------------------------- | :---------------------------------------------- |
-| `omniroute_simulate_route` | Dry-run routing simulation with fallback tree |
-| `omniroute_set_budget_guard` | Session budget with degrade/block/alert actions |
-| `omniroute_set_resilience_profile` | Apply conservative/balanced/aggressive preset |
-| `omniroute_test_combo` | Live-test all models in a combo |
-| `omniroute_get_provider_metrics` | Detailed metrics for one provider |
-| `omniroute_best_combo_for_task` | Task-fitness recommendation with alternatives |
-| `omniroute_explain_route` | Explain a past routing decision |
-| `omniroute_get_session_snapshot` | Full session state: costs, tokens, errors |
-
-## Authentication
-
-MCP tools are authenticated via API key scopes. Each tool requires specific scopes:
-
-| Scope | Tools |
-| :------------- | :----------------------------------------------- |
-| `read:health` | get_health, get_provider_metrics |
-| `read:combos` | list_combos, get_combo_metrics |
-| `write:combos` | switch_combo |
-| `read:quota` | check_quota |
-| `write:route` | route_request, simulate_route, test_combo |
-| `read:usage` | cost_report, get_session_snapshot, explain_route |
-| `write:config` | set_budget_guard, set_resilience_profile |
-| `read:models` | list_models_catalog, best_combo_for_task |
-
-## Audit Logging
-
-Every tool call is logged to `mcp_tool_audit` with:
-
-- Tool name, arguments, result
-- Duration (ms), success/failure
-- API key hash, timestamp
-
-## Files
-
-| File | Purpose |
-| :------------------------------------------- | :------------------------------------------ |
-| `open-sse/mcp-server/server.ts` | MCP server creation + 16 tool registrations |
-| `open-sse/mcp-server/transport.ts` | Stdio + HTTP transport |
-| `open-sse/mcp-server/auth.ts` | API key + scope validation |
-| `open-sse/mcp-server/audit.ts` | Tool call audit logging |
-| `open-sse/mcp-server/tools/advancedTools.ts` | 8 advanced tool handlers |
diff --git a/docs/i18n/fr/README.md b/docs/i18n/fr/README.md
index f2a21f9be6..8d3d52f5fb 100644
--- a/docs/i18n/fr/README.md
+++ b/docs/i18n/fr/README.md
@@ -1,13 +1,12 @@
# 🚀 OmniRoute — The Free AI Gateway (Français)
-🌐 **Languages:** 🇺🇸 [English](../../../README.md) · 🇪🇸 [es](../es/README.md) · 🇫🇷 [fr](../fr/README.md) · 🇩🇪 [de](../de/README.md) · 🇮🇹 [it](../it/README.md) · 🇷🇺 [ru](../ru/README.md) · 🇨🇳 [zh-CN](../zh-CN/README.md) · 🇯🇵 [ja](../ja/README.md) · 🇰🇷 [ko](../ko/README.md) · 🇸🇦 [ar](../ar/README.md) · 🇮🇳 [in](../in/README.md) · 🇹🇭 [th](../th/README.md) · 🇻🇳 [vi](../vi/README.md) · 🇮🇩 [id](../id/README.md) · 🇲🇾 [ms](../ms/README.md) · 🇳🇱 [nl](../nl/README.md) · 🇵🇱 [pl](../pl/README.md) · 🇸🇪 [sv](../sv/README.md) · 🇳🇴 [no](../no/README.md) · 🇩🇰 [da](../da/README.md) · 🇫🇮 [fi](../fi/README.md) · 🇵🇹 [pt](../pt/README.md) · 🇷🇴 [ro](../ro/README.md) · 🇭🇺 [hu](../hu/README.md) · 🇧🇬 [bg](../bg/README.md) · 🇸🇰 [sk](../sk/README.md) · 🇺🇦 [uk-UA](../uk-UA/README.md) · 🇮🇱 [he](../he/README.md) · 🇵🇭 [phi](../phi/README.md) · 🇧🇷 [pt-BR](../pt-BR/README.md)
+🌐 **Languages:** 🇺🇸 [English](../../../README.md) · 🇪🇸 [es](../es/README.md) · 🇫🇷 [fr](../fr/README.md) · 🇩🇪 [de](../de/README.md) · 🇮🇹 [it](../it/README.md) · 🇷🇺 [ru](../ru/README.md) · 🇨🇳 [zh-CN](../zh-CN/README.md) · 🇯🇵 [ja](../ja/README.md) · 🇰🇷 [ko](../ko/README.md) · 🇸🇦 [ar](../ar/README.md) · 🇮🇳 [in](../in/README.md) · 🇹🇭 [th](../th/README.md) · 🇻🇳 [vi](../vi/README.md) · 🇮🇩 [id](../id/README.md) · 🇲🇾 [ms](../ms/README.md) · 🇳🇱 [nl](../nl/README.md) · 🇵🇱 [pl](../pl/README.md) · 🇸🇪 [sv](../sv/README.md) · 🇳🇴 [no](../no/README.md) · 🇩🇰 [da](../da/README.md) · 🇫🇮 [fi](../fi/README.md) · 🇵🇹 [pt](../pt/README.md) · 🇷🇴 [ro](../ro/README.md) · 🇭🇺 [hu](../hu/README.md) · 🇧🇬 [bg](../bg/README.md) · 🇸🇰 [sk](../sk/README.md) · 🇺🇦 [uk-UA](../uk-UA/README.md) · 🇮🇱 [he](../he/README.md) · 🇵🇭 [phi](../phi/README.md) · 🇧🇷 [pt-BR](../pt-BR/README.md) · 🇨🇿 [cs](../cs/README.md)
---
-
### Never stop coding. Smart routing to **FREE & low-cost AI models** with automatic fallback.
-_Your universal API proxy — one endpoint, 67+ providers, zero downtime. Now with **MCP & A2A** agent orchestration._
+_Your universal API proxy — one endpoint, 60+ providers, zero downtime. Now with **MCP Server (25 tools)**, **A2A Protocol**, **Memory/Skills Systems** & **Electron Desktop App**._
**Chat Completions • Embeddings • Image Generation • Video • Music • Audio • Reranking • **Web Search** • MCP Server • A2A Protocol • 100% TypeScript**
@@ -47,15 +46,17 @@ _Your universal API proxy — one endpoint, 67+ providers, zero downtime. Now wi
> - `APP_LOG_FILE_PATH`
> - `APP_LOG_MAX_FILE_SIZE`
> - `APP_LOG_RETENTION_DAYS`
+> - `APP_LOG_MAX_FILES`
> - `APP_LOG_LEVEL`
> - `APP_LOG_FORMAT`
> - `CALL_LOG_RETENTION_DAYS`
+> - `CALL_LOG_MAX_ENTRIES`
>
> For release details and upgrade notes, see the [CHANGELOG](CHANGELOG.md).
---
-## 🆕 What's New in v3.0.0
+## 🆕 What's New
> **Upgrading from v2.9.5?** — See the [full CHANGELOG](CHANGELOG.md#300--2026-03-22-release-candidate--not-yet-merged-to-main) for all changes.
@@ -275,7 +276,7 @@ Developers pay $20–200/month for Claude Pro, Codex Pro, or GitHub Copilot. Eve
- **Smart 4-Tier Fallback** — If subscription quota runs out, automatically redirects to API Key → Cheap → Free with zero manual intervention
- **Real-Time Quota Tracking** — Shows token consumption in real-time with reset countdown (5h, daily, weekly)
- **Multi-Account Support** — Multiple accounts per provider with auto round-robin — when one runs out, switches to the next
-- **Custom Combos** — Customizable fallback chains with 6 balancing strategies (fill-first, round-robin, P2C, random, least-used, cost-optimized)
+- **Custom Combos** — Customizable fallback chains with 9 balancing strategies (priority, weighted, fill-first, round-robin, P2C, random, least-used, cost-optimized, strict-random)
- **Codex Business Quotas** — Business/Team workspace quota monitoring directly in the dashboard
@@ -287,7 +288,7 @@ OpenAI uses one format, Claude (Anthropic) uses another, Gemini yet another. If
**How OmniRoute solves it:**
-- **Unified Endpoint** — A single `http://localhost:20128/v1` serves as proxy for all 67+ providers
+- **Unified Endpoint** — A single `http://localhost:20128/v1` serves as proxy for all 60+ providers
- **Format Translation** — Automatic and transparent: OpenAI ↔ Claude ↔ Gemini ↔ Responses API
- **Response Sanitization** — Strips non-standard fields (`x_groq`, `usage_breakdown`, `service_tier`) that break OpenAI SDK v1.83+
- **Role Normalization** — Converts `developer` → `system` for non-OpenAI providers; `system` → `user` for GLM/ERNIE
@@ -373,7 +374,7 @@ Developers use Cursor, Claude Code, Codex CLI, OpenClaw, Gemini CLI, Kilo Code..
- **CLI Tools Dashboard** — Dedicated page with one-click setup for Claude Code, Codex CLI, OpenClaw, Kilo Code, Antigravity, Cline
- **GitHub Copilot Config Generator** — Generates `chatLanguageModels.json` for VS Code with bulk model selection
- **Onboarding Wizard** — Guided 4-step setup for first-time users
-- **One endpoint, all models** — Configure `http://localhost:20128/v1` once, access 67+ providers
+- **One endpoint, all models** — Configure `http://localhost:20128/v1` once, access 60+ providers
@@ -420,7 +421,7 @@ When a call fails, the dev doesn't know if it was a rate limit, expired token, w
- **SQLite Proxy Logs** — Persistent logs that survive server restarts
- **Translator Playground** — 4 debugging modes: Playground (format translation), Chat Tester (round-trip), Test Bench (batch), Live Monitor (real-time)
- **Request Telemetry** — p50/p95/p99 latency + X-Request-Id tracing
-- **File-Based Logging with Rotation** — Console interceptor captures everything to JSON log with size-based rotation
+- **File-Based Logging with Rotation** — App logs rotate by size, retention days, and archive count; call log artifacts rotate by retention days and file count
- **System Info Report** — `npm run system-info` generates `system-info.txt` with your full environment (Node version, OmniRoute version, OS, CLI tools, Docker/PM2 status). Attach it when reporting issues for instant triage.
@@ -515,7 +516,7 @@ Developers who want all responses in a specific language, with a specific tone,
- **System Prompt Injection** — Global prompt applied to all requests
- **Thinking Budget Validation** — Reasoning token allocation control per request (passthrough, auto, custom, adaptive)
-- **6 Routing Strategies** — Global strategies that determine how requests are distributed
+- **9 Routing Strategies** — Global strategies that determine how requests are distributed
- **Wildcard Router** — `provider/*` patterns route dynamically to any provider
- **Combo Enable/Disable Toggle** — Toggle combos directly from the dashboard
- **Provider Toggle** — Enable/disable all connections for a provider with one click
@@ -582,7 +583,7 @@ Different clients should have least-privilege access to tool categories.
**How OmniRoute solves it:**
-- 9 granular MCP scopes for controlled tool access
+- 10 granular MCP scopes for controlled tool access
- Scope enforcement and visibility in MCP management UI
- Safe default posture for operational tooling
@@ -1326,19 +1327,19 @@ OmniRoute v2.0 is built as an operational platform, not just a relay proxy.
### 🤖 Agent & Protocol Operations (v2.0)
-| Feature | What It Does |
-| ------------------------------------- | -------------------------------------------------------------------------------------------------- |
-| 🔧 **MCP Server (16 tools)** | IDE/agent tools via 3 transports: stdio, SSE (`/api/mcp/sse`), Streamable HTTP (`/api/mcp/stream`) |
-| 🤝 **A2A Server (JSON-RPC + SSE)** | Agent-to-agent task execution with sync and streaming flows |
-| 🧭 **Consolidated Endpoints Page** | Tabbed management page with Endpoint Proxy, MCP, A2A, and API Endpoints tabs |
-| 🎚️ **Service Enable/Disable Toggles** | ON/OFF switches for MCP and A2A with settings persistence (default: OFF) |
-| 🛰️ **MCP Runtime Heartbeat** | Real process status (pid, uptime, heartbeat age, transport, scope mode) |
-| 📋 **MCP Audit Trail** | Filterable audit logs with success/failure and key attribution |
-| 🔐 **MCP Scope Enforcement** | 9 granular scope permissions for controlled tool access |
-| 📡 **A2A Task Lifecycle Management** | List/filter tasks, inspect events/artifacts, cancel running tasks |
-| 📋 **Agent Card Discovery** | `/.well-known/agent.json` for client auto-discovery |
-| 🧪 **Protocol E2E Test Harness** | Real MCP SDK + A2A client flows in `test:protocols:e2e` |
-| ⚙️ **Operational Controls** | Switch combo, apply resilience profiles, reset breakers from one control surface |
+| Feature | What It Does |
+| ------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------- |
+| 🔧 **MCP Server (25 tools)** | IDE/agent tools via 3 transports: stdio, SSE (`/api/mcp/sse`), Streamable HTTP (`/api/mcp/stream`). 18 core + 3 memory + 4 skill tools |
+| 🤝 **A2A Server (JSON-RPC + SSE)** | Agent-to-agent task execution with sync and streaming flows |
+| 🧭 **Consolidated Endpoints Page** | Tabbed management page with Endpoint Proxy, MCP, A2A, and API Endpoints tabs |
+| 🎚️ **Service Enable/Disable Toggles** | ON/OFF switches for MCP and A2A with settings persistence (default: OFF) |
+| 🛰️ **MCP Runtime Heartbeat** | Real process status (pid, uptime, heartbeat age, transport, scope mode) |
+| 📋 **MCP Audit Trail** | Filterable audit logs with success/failure and key attribution |
+| 🔐 **MCP Scope Enforcement** | 10 granular scope permissions for controlled tool access |
+| 📡 **A2A Task Lifecycle Management** | List/filter tasks, inspect events/artifacts, cancel running tasks |
+| 📋 **Agent Card Discovery** | `/.well-known/agent.json` for client auto-discovery |
+| 🧪 **Protocol E2E Test Harness** | Real MCP SDK + A2A client flows in `test:protocols:e2e` |
+| ⚙️ **Operational Controls** | Switch combo, apply resilience profiles, reset breakers from one control surface |
### 🧠 Routing & Intelligence
@@ -1349,7 +1350,7 @@ OmniRoute v2.0 is built as an operational platform, not just a relay proxy.
| 🔄 **Format Translation** | OpenAI ↔ Claude ↔ Gemini ↔ Responses with schema-safe conversions |
| 👥 **Multi-Account Support** | Multiple accounts per provider with intelligent selection |
| 🔄 **Auto Token Refresh** | OAuth tokens refresh automatically with retry |
-| 🎨 **Custom Combos** | 6 balancing strategies + fallback chain control |
+| 🎨 **Custom Combos** | 9 balancing strategies + fallback chain control |
| 🌐 **Wildcard Router** | `provider/*` dynamic routing |
| 🧠 **Thinking Budget Controls** | Passthrough, auto, custom, and adaptive reasoning limits |
| 🔀 **Model Aliases** | Built-in + custom model aliasing and migration safety |
@@ -1950,6 +1951,7 @@ opencode
- Request artifacts are written to `DATA_DIR/call_logs/` as one JSON file per request
- Enable pipeline capture from Dashboard → Logs → Request Logs if you need detailed per-stage payloads
- Set `APP_LOG_TO_FILE=true` if you also want application console logs in `logs/application/app.log`
+- Adjust `APP_LOG_MAX_FILE_SIZE`, `APP_LOG_RETENTION_DAYS`, `APP_LOG_MAX_FILES`, and `CALL_LOG_MAX_ENTRIES` as needed
**Connection test shows "Invalid" for OpenAI-compatible providers**
diff --git a/docs/i18n/fr/RELEASE_CHECKLIST.md b/docs/i18n/fr/RELEASE_CHECKLIST.md
deleted file mode 100644
index 903e812c3f..0000000000
--- a/docs/i18n/fr/RELEASE_CHECKLIST.md
+++ /dev/null
@@ -1,37 +0,0 @@
-🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/RELEASE_CHECKLIST.md) · 🇪🇸 [es](../es/RELEASE_CHECKLIST.md) · 🇫🇷 [fr](../fr/RELEASE_CHECKLIST.md) · 🇩🇪 [de](../de/RELEASE_CHECKLIST.md) · 🇮🇹 [it](../it/RELEASE_CHECKLIST.md) · 🇷🇺 [ru](../ru/RELEASE_CHECKLIST.md) · 🇨🇳 [zh-CN](../zh-CN/RELEASE_CHECKLIST.md) · 🇯🇵 [ja](../ja/RELEASE_CHECKLIST.md) · 🇰🇷 [ko](../ko/RELEASE_CHECKLIST.md) · 🇸🇦 [ar](../ar/RELEASE_CHECKLIST.md) · 🇮🇳 [in](../in/RELEASE_CHECKLIST.md) · 🇹🇭 [th](../th/RELEASE_CHECKLIST.md) · 🇻🇳 [vi](../vi/RELEASE_CHECKLIST.md) · 🇮🇩 [id](../id/RELEASE_CHECKLIST.md) · 🇲🇾 [ms](../ms/RELEASE_CHECKLIST.md) · 🇳🇱 [nl](../nl/RELEASE_CHECKLIST.md) · 🇵🇱 [pl](../pl/RELEASE_CHECKLIST.md) · 🇸🇪 [sv](../sv/RELEASE_CHECKLIST.md) · 🇳🇴 [no](../no/RELEASE_CHECKLIST.md) · 🇩🇰 [da](../da/RELEASE_CHECKLIST.md) · 🇫🇮 [fi](../fi/RELEASE_CHECKLIST.md) · 🇵🇹 [pt](../pt/RELEASE_CHECKLIST.md) · 🇷🇴 [ro](../ro/RELEASE_CHECKLIST.md) · 🇭🇺 [hu](../hu/RELEASE_CHECKLIST.md) · 🇧🇬 [bg](../bg/RELEASE_CHECKLIST.md) · 🇸🇰 [sk](../sk/RELEASE_CHECKLIST.md) · 🇺🇦 [uk-UA](../uk-UA/RELEASE_CHECKLIST.md) · 🇮🇱 [he](../he/RELEASE_CHECKLIST.md) · 🇵🇭 [phi](../phi/RELEASE_CHECKLIST.md)
-
----
-
-# Release Checklist
-
-Use this checklist before tagging or publishing a new OmniRoute release.
-
-## Version and Changelog
-
-1. Bump `package.json` version (`x.y.z`) in the release branch.
-2. Move release notes from `## [Unreleased]` in `CHANGELOG.md` to a dated section:
- - `## [x.y.z] — YYYY-MM-DD`
-3. Keep `## [Unreleased]` as the first changelog section for upcoming work.
-4. Ensure the latest semver section in `CHANGELOG.md` equals `package.json` version.
-
-## API Docs
-
-1. Update `docs/openapi.yaml`:
- - `info.version` must equal `package.json` version.
-2. Validate endpoint examples if API contracts changed.
-
-## Runtime Docs
-
-1. Review `docs/ARCHITECTURE.md` for storage/runtime drift.
-2. Review `docs/TROUBLESHOOTING.md` for env var and operational drift.
-3. Update localized docs if source docs changed significantly.
-
-## Automated Check
-
-Run the sync guard locally before opening PR:
-
-```bash
-npm run check:docs-sync
-```
-
-CI also runs this check in `.github/workflows/ci.yml` (lint job).
diff --git a/docs/i18n/fr/SECURITY.md b/docs/i18n/fr/SECURITY.md
new file mode 100644
index 0000000000..84f07f5ca3
--- /dev/null
+++ b/docs/i18n/fr/SECURITY.md
@@ -0,0 +1,179 @@
+# Security Policy (Français)
+
+🌐 **Languages:** 🇺🇸 [English](../../../SECURITY.md) · 🇪🇸 [es](../es/SECURITY.md) · 🇫🇷 [fr](../fr/SECURITY.md) · 🇩🇪 [de](../de/SECURITY.md) · 🇮🇹 [it](../it/SECURITY.md) · 🇷🇺 [ru](../ru/SECURITY.md) · 🇨🇳 [zh-CN](../zh-CN/SECURITY.md) · 🇯🇵 [ja](../ja/SECURITY.md) · 🇰🇷 [ko](../ko/SECURITY.md) · 🇸🇦 [ar](../ar/SECURITY.md) · 🇮🇳 [in](../in/SECURITY.md) · 🇹🇭 [th](../th/SECURITY.md) · 🇻🇳 [vi](../vi/SECURITY.md) · 🇮🇩 [id](../id/SECURITY.md) · 🇲🇾 [ms](../ms/SECURITY.md) · 🇳🇱 [nl](../nl/SECURITY.md) · 🇵🇱 [pl](../pl/SECURITY.md) · 🇸🇪 [sv](../sv/SECURITY.md) · 🇳🇴 [no](../no/SECURITY.md) · 🇩🇰 [da](../da/SECURITY.md) · 🇫🇮 [fi](../fi/SECURITY.md) · 🇵🇹 [pt](../pt/SECURITY.md) · 🇷🇴 [ro](../ro/SECURITY.md) · 🇭🇺 [hu](../hu/SECURITY.md) · 🇧🇬 [bg](../bg/SECURITY.md) · 🇸🇰 [sk](../sk/SECURITY.md) · 🇺🇦 [uk-UA](../uk-UA/SECURITY.md) · 🇮🇱 [he](../he/SECURITY.md) · 🇵🇭 [phi](../phi/SECURITY.md) · 🇧🇷 [pt-BR](../pt-BR/SECURITY.md) · 🇨🇿 [cs](../cs/SECURITY.md)
+
+---
+
+## Reporting Vulnerabilities
+
+If you discover a security vulnerability in OmniRoute, please report it responsibly:
+
+1. **DO NOT** open a public GitHub issue
+2. Use [GitHub Security Advisories](https://github.com/diegosouzapw/OmniRoute/security/advisories/new)
+3. Include: description, reproduction steps, and potential impact
+
+## Response Timeline
+
+| Stage | Target |
+| ------------------- | --------------------------- |
+| Acknowledgment | 48 hours |
+| Triage & Assessment | 5 business days |
+| Patch Release | 14 business days (critical) |
+
+## Supported Versions
+
+| Version | Support Status |
+| ------- | -------------- |
+| 3.4.x | ✅ Active |
+| 3.0.x | ✅ Security |
+| < 3.0.0 | ❌ Unsupported |
+
+---
+
+## Security Architecture
+
+OmniRoute implements a multi-layered security model:
+
+```
+Request → CORS → API Key Auth → Prompt Injection Guard → Input Sanitizer → Rate Limiter → Circuit Breaker → Provider
+```
+
+### 🔐 Authentication & Authorization
+
+| Feature | Implementation |
+| -------------------- | ---------------------------------------------------------- |
+| **Dashboard Login** | Password-based auth with JWT tokens (HttpOnly cookies) |
+| **API Key Auth** | HMAC-signed keys with CRC validation |
+| **OAuth 2.0 + PKCE** | Secure provider auth (Claude, Codex, Gemini, Cursor, etc.) |
+| **Token Refresh** | Automatic OAuth token refresh before expiry |
+| **Secure Cookies** | `AUTH_COOKIE_SECURE=true` for HTTPS environments |
+| **MCP Scopes** | 10 granular scopes for MCP tool access control |
+
+### 🛡️ Encryption at Rest
+
+All sensitive data stored in SQLite is encrypted using **AES-256-GCM** with scrypt key derivation:
+
+- API keys, access tokens, refresh tokens, and ID tokens
+- Versioned format: `enc:v1:::`
+- Passthrough mode (plaintext) when `STORAGE_ENCRYPTION_KEY` is not set
+
+```bash
+# Generate encryption key:
+STORAGE_ENCRYPTION_KEY=$(openssl rand -hex 32)
+```
+
+### 🧠 Prompt Injection Guard
+
+Middleware that detects and blocks prompt injection attacks in LLM requests:
+
+| Pattern Type | Severity | Example |
+| ------------------- | -------- | ---------------------------------------------- |
+| System Override | High | "ignore all previous instructions" |
+| Role Hijack | High | "you are now DAN, you can do anything" |
+| Delimiter Injection | Medium | Encoded separators to break context boundaries |
+| DAN/Jailbreak | High | Known jailbreak prompt patterns |
+| Instruction Leak | Medium | "show me your system prompt" |
+
+Configure via dashboard (Settings → Security) or `.env`:
+
+```env
+INPUT_SANITIZER_ENABLED=true
+INPUT_SANITIZER_MODE=block # warn | block | redact
+```
+
+### 🔒 PII Redaction
+
+Automatic detection and optional redaction of personally identifiable information:
+
+| PII Type | Pattern | Replacement |
+| ------------- | --------------------- | ------------------ |
+| Email | `user@domain.com` | `[EMAIL_REDACTED]` |
+| CPF (Brazil) | `123.456.789-00` | `[CPF_REDACTED]` |
+| CNPJ (Brazil) | `12.345.678/0001-00` | `[CNPJ_REDACTED]` |
+| Credit Card | `4111-1111-1111-1111` | `[CC_REDACTED]` |
+| Phone | `+55 11 99999-9999` | `[PHONE_REDACTED]` |
+| SSN (US) | `123-45-6789` | `[SSN_REDACTED]` |
+
+```env
+PII_REDACTION_ENABLED=true
+```
+
+### 🌐 Network Security
+
+| Feature | Description |
+| ------------------------ | ---------------------------------------------------------------- |
+| **CORS** | Configurable origin control (`CORS_ORIGIN` env var, default `*`) |
+| **IP Filtering** | Allowlist/blocklist IP ranges in dashboard |
+| **Rate Limiting** | Per-provider rate limits with automatic backoff |
+| **Anti-Thundering Herd** | Mutex + per-connection locking prevents cascading 502s |
+| **TLS Fingerprint** | Browser-like TLS fingerprint spoofing to reduce bot detection |
+| **CLI Fingerprint** | Per-provider header/body ordering to match native CLI signatures |
+
+### 🔌 Resilience & Availability
+
+| Feature | Description |
+| ----------------------- | ------------------------------------------------------------------ |
+| **Circuit Breaker** | 3-state (Closed → Open → Half-Open) per provider, SQLite-persisted |
+| **Request Idempotency** | 5-second dedup window for duplicate requests |
+| **Exponential Backoff** | Automatic retry with increasing delays |
+| **Health Dashboard** | Real-time provider health monitoring |
+
+### 📋 Compliance
+
+| Feature | Description |
+| ------------------ | ----------------------------------------------------------- |
+| **Log Retention** | Automatic cleanup after `CALL_LOG_RETENTION_DAYS` |
+| **No-Log Opt-out** | Per API key `noLog` flag disables request logging |
+| **Audit Log** | Administrative actions tracked in `audit_log` table |
+| **MCP Audit** | SQLite-backed audit logging for all MCP tool calls |
+| **Zod Validation** | All API inputs validated with Zod v4 schemas at module load |
+
+---
+
+## Required Environment Variables
+
+All secrets must be set before starting the server. The server will **fail fast** if they are missing or weak.
+
+```bash
+# REQUIRED — server will not start without these:
+JWT_SECRET=$(openssl rand -base64 48) # min 32 chars
+API_KEY_SECRET=$(openssl rand -hex 32) # min 16 chars
+
+# RECOMMENDED — enables encryption at rest:
+STORAGE_ENCRYPTION_KEY=$(openssl rand -hex 32)
+```
+
+The server actively rejects known-weak values like `changeme`, `secret`, or `password`.
+
+---
+
+## Docker Security
+
+- Use non-root user in production
+- Mount secrets as read-only volumes
+- Never copy `.env` files into Docker images
+- Use `.dockerignore` to exclude sensitive files
+- Set `AUTH_COOKIE_SECURE=true` when behind HTTPS
+
+```bash
+docker run -d \
+ --name omniroute \
+ --restart unless-stopped \
+ --read-only \
+ -p 20128:20128 \
+ -v omniroute-data:/app/data \
+ -e JWT_SECRET="$(openssl rand -base64 48)" \
+ -e API_KEY_SECRET="$(openssl rand -hex 32)" \
+ -e STORAGE_ENCRYPTION_KEY="$(openssl rand -hex 32)" \
+ diegosouzapw/omniroute:latest
+```
+
+---
+
+## Dependencies
+
+- Run `npm audit` regularly
+- Keep dependencies updated
+- The project uses `husky` + `lint-staged` for pre-commit checks
+- CI pipeline runs ESLint security rules on every push
+- Provider constants validated at module load via Zod (`src/shared/validation/providerSchema.ts`)
diff --git a/docs/i18n/fr/TROUBLESHOOTING.md b/docs/i18n/fr/TROUBLESHOOTING.md
deleted file mode 100644
index 63c148000a..0000000000
--- a/docs/i18n/fr/TROUBLESHOOTING.md
+++ /dev/null
@@ -1,258 +0,0 @@
-🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/TROUBLESHOOTING.md) · 🇪🇸 [es](../es/TROUBLESHOOTING.md) · 🇫🇷 [fr](../fr/TROUBLESHOOTING.md) · 🇩🇪 [de](../de/TROUBLESHOOTING.md) · 🇮🇹 [it](../it/TROUBLESHOOTING.md) · 🇷🇺 [ru](../ru/TROUBLESHOOTING.md) · 🇨🇳 [zh-CN](../zh-CN/TROUBLESHOOTING.md) · 🇯🇵 [ja](../ja/TROUBLESHOOTING.md) · 🇰🇷 [ko](../ko/TROUBLESHOOTING.md) · 🇸🇦 [ar](../ar/TROUBLESHOOTING.md) · 🇮🇳 [in](../in/TROUBLESHOOTING.md) · 🇹🇭 [th](../th/TROUBLESHOOTING.md) · 🇻🇳 [vi](../vi/TROUBLESHOOTING.md) · 🇮🇩 [id](../id/TROUBLESHOOTING.md) · 🇲🇾 [ms](../ms/TROUBLESHOOTING.md) · 🇳🇱 [nl](../nl/TROUBLESHOOTING.md) · 🇵🇱 [pl](../pl/TROUBLESHOOTING.md) · 🇸🇪 [sv](../sv/TROUBLESHOOTING.md) · 🇳🇴 [no](../no/TROUBLESHOOTING.md) · 🇩🇰 [da](../da/TROUBLESHOOTING.md) · 🇫🇮 [fi](../fi/TROUBLESHOOTING.md) · 🇵🇹 [pt](../pt/TROUBLESHOOTING.md) · 🇷🇴 [ro](../ro/TROUBLESHOOTING.md) · 🇭🇺 [hu](../hu/TROUBLESHOOTING.md) · 🇧🇬 [bg](../bg/TROUBLESHOOTING.md) · 🇸🇰 [sk](../sk/TROUBLESHOOTING.md) · 🇺🇦 [uk-UA](../uk-UA/TROUBLESHOOTING.md) · 🇮🇱 [he](../he/TROUBLESHOOTING.md) · 🇵🇭 [phi](../phi/TROUBLESHOOTING.md)
-
----
-
-# Troubleshooting
-
-🌐 **Languages:** 🇺🇸 [English](TROUBLESHOOTING.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/TROUBLESHOOTING.md) | 🇪🇸 [Español](i18n/es/TROUBLESHOOTING.md) | 🇫🇷 [Français](i18n/fr/TROUBLESHOOTING.md) | 🇮🇹 [Italiano](i18n/it/TROUBLESHOOTING.md) | 🇷🇺 [Русский](i18n/ru/TROUBLESHOOTING.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/TROUBLESHOOTING.md) | 🇩🇪 [Deutsch](i18n/de/TROUBLESHOOTING.md) | 🇮🇳 [हिन्दी](i18n/in/TROUBLESHOOTING.md) | 🇹🇭 [ไทย](i18n/th/TROUBLESHOOTING.md) | 🇺🇦 [Українська](i18n/uk-UA/TROUBLESHOOTING.md) | 🇸🇦 [العربية](i18n/ar/TROUBLESHOOTING.md) | 🇯🇵 [日本語](i18n/ja/TROUBLESHOOTING.md) | 🇻🇳 [Tiếng Việt](i18n/vi/TROUBLESHOOTING.md) | 🇧🇬 [Български](i18n/bg/TROUBLESHOOTING.md) | 🇩🇰 [Dansk](i18n/da/TROUBLESHOOTING.md) | 🇫🇮 [Suomi](i18n/fi/TROUBLESHOOTING.md) | 🇮🇱 [עברית](i18n/he/TROUBLESHOOTING.md) | 🇭🇺 [Magyar](i18n/hu/TROUBLESHOOTING.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/TROUBLESHOOTING.md) | 🇰🇷 [한국어](i18n/ko/TROUBLESHOOTING.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/TROUBLESHOOTING.md) | 🇳🇱 [Nederlands](i18n/nl/TROUBLESHOOTING.md) | 🇳🇴 [Norsk](i18n/no/TROUBLESHOOTING.md) | 🇵🇹 [Português (Portugal)](i18n/pt/TROUBLESHOOTING.md) | 🇷🇴 [Română](i18n/ro/TROUBLESHOOTING.md) | 🇵🇱 [Polski](i18n/pl/TROUBLESHOOTING.md) | 🇸🇰 [Slovenčina](i18n/sk/TROUBLESHOOTING.md) | 🇸🇪 [Svenska](i18n/sv/TROUBLESHOOTING.md) | 🇵🇭 [Filipino](i18n/phi/TROUBLESHOOTING.md)
-
-Common problems and solutions for OmniRoute.
-
----
-
-## Quick Fixes
-
-| Problem | Solution |
-| ----------------------------- | ------------------------------------------------------------------ |
-| First login not working | Set `INITIAL_PASSWORD` in `.env` (no hardcoded default) |
-| Dashboard opens on wrong port | Set `PORT=20128` and `NEXT_PUBLIC_BASE_URL=http://localhost:20128` |
-| No request logs under `logs/` | Set `ENABLE_REQUEST_LOGS=true` |
-| EACCES: permission denied | Set `DATA_DIR=/path/to/writable/dir` to override `~/.omniroute` |
-| Routing strategy not saving | Update to v1.4.11+ (Zod schema fix for settings persistence) |
-
----
-
-## Provider Issues
-
-### "Language model did not provide messages"
-
-**Cause:** Provider quota exhausted.
-
-**Fix:**
-
-1. Check dashboard quota tracker
-2. Use a combo with fallback tiers
-3. Switch to cheaper/free tier
-
-### Rate Limiting
-
-**Cause:** Subscription quota exhausted.
-
-**Fix:**
-
-- Add fallback: `cc/claude-opus-4-6 → glm/glm-4.7 → if/kimi-k2-thinking`
-- Use GLM/MiniMax as cheap backup
-
-### OAuth Token Expired
-
-OmniRoute auto-refreshes tokens. If issues persist:
-
-1. Dashboard → Provider → Reconnect
-2. Delete and re-add the provider connection
-
----
-
-## Cloud Issues
-
-### Cloud Sync Errors
-
-1. Verify `BASE_URL` points to your running instance (e.g., `http://localhost:20128`)
-2. Verify `CLOUD_URL` points to your cloud endpoint (e.g., `https://omniroute.dev`)
-3. Keep `NEXT_PUBLIC_*` values aligned with server-side values
-
-### Cloud `stream=false` Returns 500
-
-**Symptom:** `Unexpected token 'd'...` on cloud endpoint for non-streaming calls.
-
-**Cause:** Upstream returns SSE payload while client expects JSON.
-
-**Workaround:** Use `stream=true` for cloud direct calls. Local runtime includes SSE→JSON fallback.
-
-### Cloud Says Connected but "Invalid API key"
-
-1. Create a fresh key from local dashboard (`/api/keys`)
-2. Run cloud sync: Enable Cloud → Sync Now
-3. Old/non-synced keys can still return `401` on cloud
-
----
-
-## Docker Issues
-
-### CLI Tool Shows Not Installed
-
-1. Check runtime fields: `curl http://localhost:20128/api/cli-tools/runtime/codex | jq`
-2. For portable mode: use image target `runner-cli` (bundled CLIs)
-3. For host mount mode: set `CLI_EXTRA_PATHS` and mount host bin directory as read-only
-4. If `installed=true` and `runnable=false`: binary was found but failed healthcheck
-
-### Quick Runtime Validation
-
-```bash
-curl -s http://localhost:20128/api/cli-tools/codex-settings | jq '{installed,runnable,commandPath,runtimeMode,reason}'
-curl -s http://localhost:20128/api/cli-tools/claude-settings | jq '{installed,runnable,commandPath,runtimeMode,reason}'
-curl -s http://localhost:20128/api/cli-tools/openclaw-settings | jq '{installed,runnable,commandPath,runtimeMode,reason}'
-```
-
----
-
-## Cost Issues
-
-### High Costs
-
-1. Check usage stats in Dashboard → Usage
-2. Switch primary model to GLM/MiniMax
-3. Use free tier (Gemini CLI, Qoder) for non-critical tasks
-4. Set cost budgets per API key: Dashboard → API Keys → Budget
-
----
-
-## Debugging
-
-### Enable Request Logs
-
-Set `ENABLE_REQUEST_LOGS=true` in your `.env` file. Logs appear under `logs/` directory.
-
-### Check Provider Health
-
-```bash
-# Health dashboard
-http://localhost:20128/dashboard/health
-
-# API health check
-curl http://localhost:20128/api/monitoring/health
-```
-
-### Runtime Storage
-
-- Main state: `${DATA_DIR}/storage.sqlite` (providers, combos, aliases, keys, settings)
-- Usage: SQLite tables in `storage.sqlite` (`usage_history`, `call_logs`, `proxy_logs`) + optional `${DATA_DIR}/log.txt` and `${DATA_DIR}/call_logs/`
-- Request logs: `/logs/...` (when `ENABLE_REQUEST_LOGS=true`)
-
----
-
-## Circuit Breaker Issues
-
-### Provider stuck in OPEN state
-
-When a provider's circuit breaker is OPEN, requests are blocked until the cooldown expires.
-
-**Fix:**
-
-1. Go to **Dashboard → Settings → Resilience**
-2. Check the circuit breaker card for the affected provider
-3. Click **Reset All** to clear all breakers, or wait for the cooldown to expire
-4. Verify the provider is actually available before resetting
-
-### Provider keeps tripping the circuit breaker
-
-If a provider repeatedly enters OPEN state:
-
-1. Check **Dashboard → Health → Provider Health** for the failure pattern
-2. Go to **Settings → Resilience → Provider Profiles** and increase the failure threshold
-3. Check if the provider has changed API limits or requires re-authentication
-4. Review latency telemetry — high latency may cause timeout-based failures
-
----
-
-## Audio Transcription Issues
-
-### "Unsupported model" error
-
-- Ensure you're using the correct prefix: `deepgram/nova-3` or `assemblyai/best`
-- Verify the provider is connected in **Dashboard → Providers**
-
-### Transcription returns empty or fails
-
-- Check supported audio formats: `mp3`, `wav`, `m4a`, `flac`, `ogg`, `webm`
-- Verify file size is within provider limits (typically < 25MB)
-- Check provider API key validity in the provider card
-
----
-
-## Translator Debugging
-
-Use **Dashboard → Translator** to debug format translation issues:
-
-| Mode | When to Use |
-| ---------------- | -------------------------------------------------------------------------------------------- |
-| **Playground** | Compare input/output formats side by side — paste a failing request to see how it translates |
-| **Chat Tester** | Send live messages and inspect the full request/response payload including headers |
-| **Test Bench** | Run batch tests across format combinations to find which translations are broken |
-| **Live Monitor** | Watch real-time request flow to catch intermittent translation issues |
-
-### Common format issues
-
-- **Thinking tags not appearing** — Check if the target provider supports thinking and the thinking budget setting
-- **Tool calls dropping** — Some format translations may strip unsupported fields; verify in Playground mode
-- **System prompt missing** — Claude and Gemini handle system prompts differently; check translation output
-- **SDK returns raw string instead of object** — Fixed in v1.1.0: response sanitizer now strips non-standard fields (`x_groq`, `usage_breakdown`, etc.) that cause OpenAI SDK Pydantic validation failures
-- **GLM/ERNIE rejects `system` role** — Fixed in v1.1.0: role normalizer automatically merges system messages into user messages for incompatible models
-- **`developer` role not recognized** — Fixed in v1.1.0: automatically converted to `system` for non-OpenAI providers
-- **`json_schema` not working with Gemini** — Fixed in v1.1.0: `response_format` is now converted to Gemini's `responseMimeType` + `responseSchema`
-
----
-
-## Resilience Settings
-
-### Auto rate-limit not triggering
-
-- Auto rate-limit only applies to API key providers (not OAuth/subscription)
-- Verify **Settings → Resilience → Provider Profiles** has auto-rate-limit enabled
-- Check if the provider returns `429` status codes or `Retry-After` headers
-
-### Tuning exponential backoff
-
-Provider profiles support these settings:
-
-- **Base delay** — Initial wait time after first failure (default: 1s)
-- **Max delay** — Maximum wait time cap (default: 30s)
-- **Multiplier** — How much to increase delay per consecutive failure (default: 2x)
-
-### Anti-thundering herd
-
-When many concurrent requests hit a rate-limited provider, OmniRoute uses mutex + auto rate-limiting to serialize requests and prevent cascading failures. This is automatic for API key providers.
-
----
-
-## Optional RAG / LLM failure taxonomy (16 problems)
-
-Some OmniRoute users place the gateway in front of RAG or agent stacks. In those setups it is common to see a strange pattern: OmniRoute looks healthy (providers up, routing profiles ok, no rate limit alerts) but the final answer is still wrong.
-
-In practice these incidents usually come from the downstream RAG pipeline, not from the gateway itself.
-
-If you want a shared vocabulary to describe those failures you can use the WFGY ProblemMap, an external MIT license text resource that defines sixteen recurring RAG / LLM failure patterns. At a high level it covers:
-
-- retrieval drift and broken context boundaries
-- empty or stale indexes and vector stores
-- embedding versus semantic mismatch
-- prompt assembly and context window issues
-- logic collapse and overconfident answers
-- long chain and agent coordination failures
-- multi agent memory and role drift
-- deployment and bootstrap ordering problems
-
-The idea is simple:
-
-1. When you investigate a bad response, capture:
- - user task and request
- - route or provider combo in OmniRoute
- - any RAG context used downstream (retrieved documents, tool calls, etc)
-2. Map the incident to one or two WFGY ProblemMap numbers (`No.1` … `No.16`).
-3. Store the number in your own dashboard, runbook, or incident tracker next to the OmniRoute logs.
-4. Use the corresponding WFGY page to decide whether you need to change your RAG stack, retriever, or routing strategy.
-
-Full text and concrete recipes live here (MIT license, text only):
-
-[WFGY ProblemMap README](https://github.com/onestardao/WFGY/blob/main/ProblemMap/README.md)
-
-You can ignore this section if you do not run RAG or agent pipelines behind OmniRoute.
-
----
-
-## Still Stuck?
-
-- **GitHub Issues**: [github.com/diegosouzapw/OmniRoute/issues](https://github.com/diegosouzapw/OmniRoute/issues)
-- **Architecture**: See [`docs/ARCHITECTURE.md`](ARCHITECTURE.md) for internal details
-- **API Reference**: See [`docs/API_REFERENCE.md`](API_REFERENCE.md) for all endpoints
-- **Health Dashboard**: Check **Dashboard → Health** for real-time system status
-- **Translator**: Use **Dashboard → Translator** to debug format issues
diff --git a/docs/i18n/fr/VM_DEPLOYMENT_GUIDE.md b/docs/i18n/fr/VM_DEPLOYMENT_GUIDE.md
deleted file mode 100644
index 3f95c0565e..0000000000
--- a/docs/i18n/fr/VM_DEPLOYMENT_GUIDE.md
+++ /dev/null
@@ -1,401 +0,0 @@
-# OmniRoute — Guide de déploiement sur VM avec Cloudflare
-
-🌐 **Languages:** 🇺🇸 [English](../../VM_DEPLOYMENT_GUIDE.md) | 🇧🇷 [Português (Brasil)](../pt-BR/VM_DEPLOYMENT_GUIDE.md) | 🇪🇸 [Español](../es/VM_DEPLOYMENT_GUIDE.md) | 🇫🇷 [Français](../fr/VM_DEPLOYMENT_GUIDE.md) | 🇮🇹 [Italiano](../it/VM_DEPLOYMENT_GUIDE.md) | 🇷🇺 [Русский](../ru/VM_DEPLOYMENT_GUIDE.md) | 🇨🇳 [中文 (简体)](../zh-CN/VM_DEPLOYMENT_GUIDE.md) | 🇩🇪 [Deutsch](../de/VM_DEPLOYMENT_GUIDE.md) | 🇮🇳 [हिन्दी](../in/VM_DEPLOYMENT_GUIDE.md) | 🇹🇭 [ไทย](../th/VM_DEPLOYMENT_GUIDE.md) | 🇺🇦 [Українська](../uk-UA/VM_DEPLOYMENT_GUIDE.md) | 🇸🇦 [العربية](../ar/VM_DEPLOYMENT_GUIDE.md) | 🇯🇵 [日本語](../ja/VM_DEPLOYMENT_GUIDE.md) | 🇻🇳 [Tiếng Việt](../vi/VM_DEPLOYMENT_GUIDE.md) | 🇧🇬 [Български](../bg/VM_DEPLOYMENT_GUIDE.md) | 🇩🇰 [Dansk](../da/VM_DEPLOYMENT_GUIDE.md) | 🇫🇮 [Suomi](../fi/VM_DEPLOYMENT_GUIDE.md) | 🇮🇱 [עברית](../he/VM_DEPLOYMENT_GUIDE.md) | 🇭🇺 [Magyar](../hu/VM_DEPLOYMENT_GUIDE.md) | 🇮🇩 [Bahasa Indonesia](../id/VM_DEPLOYMENT_GUIDE.md) | 🇰🇷 [한국어](../ko/VM_DEPLOYMENT_GUIDE.md) | 🇲🇾 [Bahasa Melayu](../ms/VM_DEPLOYMENT_GUIDE.md) | 🇳🇱 [Nederlands](../nl/VM_DEPLOYMENT_GUIDE.md) | 🇳🇴 [Norsk](../no/VM_DEPLOYMENT_GUIDE.md) | 🇵🇹 [Português (Portugal)](../pt/VM_DEPLOYMENT_GUIDE.md) | 🇷🇴 [Română](../ro/VM_DEPLOYMENT_GUIDE.md) | 🇵🇱 [Polski](../pl/VM_DEPLOYMENT_GUIDE.md) | 🇸🇰 [Slovenčina](../sk/VM_DEPLOYMENT_GUIDE.md) | 🇸🇪 [Svenska](../sv/VM_DEPLOYMENT_GUIDE.md) | 🇵🇭 [Filipino](../phi/VM_DEPLOYMENT_GUIDE.md) | 🇨🇿 [Čeština](../cs/VM_DEPLOYMENT_GUIDE.md)
-
-Guide complet pour installer et configurer OmniRoute sur une VM (VPS) avec domaine géré via Cloudflare.
-
----
-
-## Prérequis
-
-| Article | Minimum | Recommandé |
-| -------------- | ---------------------- | ---------------------- |
-| **processeur** | 1 processeur virtuel | 2 processeurs virtuels |
-| **RAM** | 1 Go | 2 Go |
-| **Disque** | Disque SSD de 10 Go | Disque SSD de 25 Go |
-| **OS** | Ubuntu 22.04 LTS | Ubuntu 24.04 LTS |
-| **Domaine** | Inscrit sur Cloudflare | — |
-| **Docker** | Moteur Docker 24+ | Docker 27+ |
-
-**Fournisseurs testés** : Akamai (Linode), DigitalOcean, Vultr, Hetzner, AWS Lightsail.
-
----
-
-## 1. Configurer la VM
-
-### 1.1 Créer l'instance
-
-Sur votre fournisseur VPS préféré :
-
-- Choisissez Ubuntu 24.04 LTS
-- Sélectionnez le forfait minimum (1 vCPU / 1 Go de RAM)
-- Définissez un mot de passe root fort ou configurez la clé SSH
-- Notez l'**IP publique** (par exemple, `203.0.113.10`)
-
-### 1.2 Connectez-vous via SSH
-
-```bash
-ssh root@203.0.113.10
-```
-
-### 1.3 Mettre à jour le système
-
-```bash
-apt update && apt upgrade -y
-```
-
-### 1.4 Installer Docker
-
-```bash
-# Install dependencies
-apt install -y ca-certificates curl gnupg
-
-# Add official Docker repository
-install -m 0755 -d /etc/apt/keyrings
-curl -fsSL https://download.docker.com/linux/ubuntu/gpg | gpg --dearmor -o /etc/apt/keyrings/docker.gpg
-chmod a+r /etc/apt/keyrings/docker.gpg
-echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu $ (. /etc/os-release && echo “$VERSION_CODENAME”) stable" | tee /etc/apt/sources.list.d/docker.list > /dev/null
-apt update
-apt install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin
-```
-
-### 1.5 Installer nginx
-
-```bash
-apt install -y nginx
-```
-
-### 1.6 Configurer le pare-feu (UFW)
-
-```bash
-ufw default deny incoming
-ufw default allow outgoing
-ufw allow 22/tcp # SSH
-ufw allow 80/tcp # HTTP (redirect)
-ufw allow 443/tcp # HTTPS
-ufw enable
-```
-
-> **Conseil** : Pour une sécurité maximale, limitez les ports 80 et 443 aux IP Cloudflare uniquement. Voir la section [Advanced Security](#advanced-security).
-
----
-
-## 2. Installez OmniRoute
-
-### 2.1 Créer un répertoire de configuration
-
-```bash
-mkdir -p /opt/omniroute
-```
-
-### 2.2 Créer un fichier de variables d'environnement
-
-```bash
-cat > /opt/omniroute/.env << ‘EOF’
-# === Security ===
-JWT_SECRET=CHANGE-TO-A-UNIQUE-64-CHAR-SECRET-KEY
-INITIAL_PASSWORD=YourSecurePassword123!
-API_KEY_SECRET=REPLACE-WITH-ANOTHER-SECRET-KEY
-STORAGE_ENCRYPTION_KEY=REPLACE-WITH-THIRD-SECRET-KEY
-STORAGE_ENCRYPTION_KEY_VERSION=v1
-MACHINE_ID_SALT=CHANGE-TO-A-UNIQUE-SALT
-
-# === App ===
-PORT=20128
-NODE_ENV=production
-HOSTNAME=0.0.0.0
-DATA_DIR=/app/data
-STORAGE_DRIVER=sqlite
-ENABLE_REQUEST_LOGS=true
-AUTH_COOKIE_SECURE=false
-REQUIRE_API_KEY=false
-
-# === Domain (change to your domain) ===
-BASE_URL=https://llms.seudominio.com
-NEXT_PUBLIC_BASE_URL=https://llms.seudominio.com
-
-# === Cloud Sync (optional) ===
-# CLOUD_URL=https://cloud.omniroute.online
-# NEXT_PUBLIC_CLOUD_URL=https://cloud.omniroute.online
-EOF
-```
-
-> ⚠️ **IMPORTANT** : Générez des clés secrètes uniques ! Utilisez `openssl rand -hex 32` pour chaque clé.
-
-### 2.3 Démarrer le conteneur
-
-```bash
-docker pull diegosouzapw/omniroute:latest
-
-docker run -d \
- --name omniroute \
- --restart unless-stopped \
- --env-file /opt/omniroute/.env \
- -p 20128:20128 \
- -v omniroute-data:/app/data \
- diegosouzapw/omniroute:latest
-```
-
-### 2.4 Vérifiez qu'il est en cours d'exécution
-
-```bash
-docker ps | grep omniroute
-docker logs omniroute --tail 20
-```
-
-Il doit afficher : `[DB] SQLite database ready` et `listening on port 20128`.
-
----
-
-## 3. Configurer nginx (proxy inverse)
-
-### 3.1 Générer un certificat SSL (Cloudflare Origin)
-
-Dans le tableau de bord Cloudflare :
-
-1. Accédez à **SSL/TLS → Serveur d'origine**
-2. Cliquez sur **Créer un certificat**
-3. Conservez les valeurs par défaut (15 ans, \*.votredomaine.com)
-4. Copiez le **Certificat d'origine** et la **Clé privée**
-
-```bash
-mkdir -p /etc/nginx/ssl
-
-# Paste the certificate
-nano /etc/nginx/ssl/origin.crt
-
-# Paste the private key
-nano /etc/nginx/ssl/origin.key
-
-chmod 600 /etc/nginx/ssl/origin.key
-```
-
-### 3.2 Configuration de Nginx
-
-```bash
-cat > /etc/nginx/sites-available/omniroute << ‘NGINX’
-# Default server — blocks direct access via IP
-server {
- listen 80 default_server;
- listen [::]:80 default_server;
- listen 443 ssl default_server;
- listen [::]:443 ssl default_server;
- ssl_certificate /etc/nginx/ssl/origin.crt;
- ssl_certificate_key /etc/nginx/ssl/origin.key;
- server_name _;
- return 444;
-}
-
-# OmniRoute — HTTPS
-server {
- listen 443 ssl;
- listen [::]:443 ssl;
- server_name llms.yourdomain.com; # Change to your domain
-
- ssl_certificate /etc/nginx/ssl/origin.crt;
- ssl_certificate_key /etc/nginx/ssl/origin.key;
- ssl_protocols TLSv1.2 TLSv1.3;
-
- client_max_body_size 100M;
-
- location / {
- proxy_pass http://127.0.0.1:20128;
- proxy_set_header Host $host;
- proxy_set_header X-Real-IP $remote_addr;
- proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
- proxy_set_header X-Forwarded-Proto $scheme;
-
- # WebSocket support
- proxy_http_version 1.1;
- proxy_set_header Upgrade $http_upgrade;
- proxy_set_header Connection “upgrade”;
-
- # SSE (Server-Sent Events) — streaming AI responses
- proxy_buffering off;
- proxy_cache off;
- proxy_read_timeout 300s;
- proxy_send_timeout 300s;
- }
-}
-
-# HTTP → HTTPS redirect
-server {
- listen 80;
- listen [::]:80;
- server_name llms.yourdomain.com;
- return 301 https://$server_name$request_uri;
-}
-NGINX
-```
-
-### 3.3 Activer et tester
-
-```bash
-# Remove default configuration
-rm -f /etc/nginx/sites-enabled/default
-
-# Enable OmniRoute
-ln -sf /etc/nginx/sites-available/omniroute /etc/nginx/sites-enabled/omniroute
-
-# Test and reload
-nginx -t && systemctl reload nginx
-```
-
----
-
-## 4. Configurer le DNS Cloudflare
-
-### 4.1 Ajouter un enregistrement DNS
-
-Dans le tableau de bord Cloudflare → DNS :
-
-| Tapez | Nom | Contenu | Proxy |
-| ----- | ------ | ------------------------------------------- | ------------- |
-| Un | `llms` | `203.0.113.10` (IP de la machine virtuelle) | ✅ Mandataire |
-
-### 4.2 Configurer SSL
-
-Sous **SSL/TLS → Présentation** :
-
-- Mode : **Complet (strict)**
-
-Sous **SSL/TLS → Certificats Edge** :
-
-- Utilisez toujours HTTPS : ✅ Activé
- -Version TLS minimale : TLS 1.2
-- Réécritures HTTPS automatiques : ✅ Activée
-
-### 4.3 Tests
-
-```bash
-curl -sI https://llms.seudominio.com/health
-# Should return HTTP/2 200
-```
-
----
-
-## 5. Exploitation et maintenance
-
-### Mettre à niveau vers une nouvelle version
-
-```bash
-docker pull diegosouzapw/omniroute:latest
-docker stop omniroute && docker rm omniroute
-docker run -d --name omniroute --restart unless-stopped \
- --env-file /opt/omniroute/.env \
- -p 20128:20128 \
- -v omniroute-data:/app/data \
- diegosouzapw/omniroute:latest
-```
-
-### Afficher les journaux
-
-```bash
-docker logs -f omniroute # Real-time stream
-docker logs omniroute --tail 50 # Last 50 lines
-```
-
-### Sauvegarde manuelle de la base de données
-
-```bash
-# Copy data from the volume to the host
-docker cp omniroute:/app/data ./backup-$(date +%F)
-
-# Or compress the entire volume
-docker run --rm -v omniroute-data:/data -v $(pwd):/backup \
- alpine tar czf /backup/omniroute-data-$(date +%F).tar.gz /data
-```
-
-### Restaurer à partir d'une sauvegarde
-
-```bash
-docker stop omniroute
-docker run --rm -v omniroute-data:/data -v $(pwd):/backup \
- alpine sh -c “rm -rf /data/* && tar xzf /backup/omniroute-data-YYYY-MM-DD.tar.gz -C /”
-docker start omniroute
-```
-
----
-
-## 6. Sécurité avancée
-
-### Restreindre nginx aux IP Cloudflare
-
-```bash
-cat > /etc/nginx/cloudflare-ips.conf << ‘CF’
-# Cloudflare IPv4 ranges — update periodically
-# https://www.cloudflare.com/ips-v4/
-set_real_ip_from 173.245.48.0/20;
-set_real_ip_from 103.21.244.0/22;
-set_real_ip_from 103.22.200.0/22;
-set_real_ip_from 103.31.4.0/22;
-set_real_ip_from 141.101.64.0/18;
-set_real_ip_from 108.162.192.0/18;
-set_real_ip_from 190.93.240.0/20;
-set_real_ip_from 188.114.96.0/20;
-set_real_ip_from 197.234.240.0/22;
-set_real_ip_from 198.41.128.0/17;
-set_real_ip_from 162.158.0.0/15;
-set_real_ip_from 104.16.0.0/13;
-set_real_ip_from 104.24.0.0/14;
-set_real_ip_from 172.64.0.0/13;
-set_real_ip_from 131.0.72.0/22;
-real_ip_header CF-Connecting-IP;
-CF
-```
-
-Ajoutez ce qui suit à `nginx.conf` à l'intérieur du bloc `http {}` :
-
-```nginx
-include /etc/nginx/cloudflare-ips.conf;
-```
-
-### Installer fail2ban
-
-```bash
-apt install -y fail2ban
-systemctl enable fail2ban
-systemctl start fail2ban
-
-# Check status
-fail2ban-client status sshd
-```
-
-### Bloquer l'accès direct au port Docker
-
-```bash
-# Prevent direct external access to port 20128
-iptables -I DOCKER-USER -p tcp --dport 20128 -j DROP
-iptables -I DOCKER-USER -i lo -p tcp --dport 20128 -j ACCEPT
-
-# Persist the rules
-apt install -y iptables-persistent
-netfilter-persistent save
-```
-
----
-
-## 7. Déployer sur Cloudflare Workers (facultatif)
-
-Pour un accès à distance via Cloudflare Workers (sans exposer directement la VM) :
-
-```bash
-# In the local repository
-cd omnirouteCloud
-npm install
-npx wrangler login
-npx wrangler deploy
-```
-
-Consultez la documentation complète sur [omnirouteCloud/README.md](../omnirouteCloud/README.md).
-
----
-
-## Résumé des ports
-
-| Port | Services | Accès |
-| ----- | ----------- | -------------------------------- |
-| 22 | SSH | Public (avec fail2ban) |
-| 80 | nginx HTTP | Redirection → HTTPS |
-| 443 | nginx HTTPS | Via le proxy Cloudflare |
-| 20128 | OmniRoute | Localhost uniquement (via nginx) |
diff --git a/docs/i18n/fr/docs/A2A-SERVER.md b/docs/i18n/fr/docs/A2A-SERVER.md
new file mode 100644
index 0000000000..19b7711e41
--- /dev/null
+++ b/docs/i18n/fr/docs/A2A-SERVER.md
@@ -0,0 +1,200 @@
+# OmniRoute A2A Server Documentation (Français)
+
+🌐 **Languages:** 🇺🇸 [English](../../../../docs/A2A-SERVER.md) · 🇪🇸 [es](../../es/docs/A2A-SERVER.md) · 🇫🇷 [fr](../../fr/docs/A2A-SERVER.md) · 🇩🇪 [de](../../de/docs/A2A-SERVER.md) · 🇮🇹 [it](../../it/docs/A2A-SERVER.md) · 🇷🇺 [ru](../../ru/docs/A2A-SERVER.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/A2A-SERVER.md) · 🇯🇵 [ja](../../ja/docs/A2A-SERVER.md) · 🇰🇷 [ko](../../ko/docs/A2A-SERVER.md) · 🇸🇦 [ar](../../ar/docs/A2A-SERVER.md) · 🇮🇳 [in](../../in/docs/A2A-SERVER.md) · 🇹🇭 [th](../../th/docs/A2A-SERVER.md) · 🇻🇳 [vi](../../vi/docs/A2A-SERVER.md) · 🇮🇩 [id](../../id/docs/A2A-SERVER.md) · 🇲🇾 [ms](../../ms/docs/A2A-SERVER.md) · 🇳🇱 [nl](../../nl/docs/A2A-SERVER.md) · 🇵🇱 [pl](../../pl/docs/A2A-SERVER.md) · 🇸🇪 [sv](../../sv/docs/A2A-SERVER.md) · 🇳🇴 [no](../../no/docs/A2A-SERVER.md) · 🇩🇰 [da](../../da/docs/A2A-SERVER.md) · 🇫🇮 [fi](../../fi/docs/A2A-SERVER.md) · 🇵🇹 [pt](../../pt/docs/A2A-SERVER.md) · 🇷🇴 [ro](../../ro/docs/A2A-SERVER.md) · 🇭🇺 [hu](../../hu/docs/A2A-SERVER.md) · 🇧🇬 [bg](../../bg/docs/A2A-SERVER.md) · 🇸🇰 [sk](../../sk/docs/A2A-SERVER.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/A2A-SERVER.md) · 🇮🇱 [he](../../he/docs/A2A-SERVER.md) · 🇵🇭 [phi](../../phi/docs/A2A-SERVER.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/A2A-SERVER.md) · 🇨🇿 [cs](../../cs/docs/A2A-SERVER.md)
+
+---
+
+> Agent-to-Agent Protocol v0.3 — OmniRoute as an intelligent routing agent
+
+## Agent Discovery
+
+```bash
+curl http://localhost:20128/.well-known/agent.json
+```
+
+Returns the Agent Card describing OmniRoute's capabilities, skills, and authentication requirements.
+
+---
+
+## Authentication
+
+All `/a2a` requests require an API key via the `Authorization` header:
+
+```
+Authorization: Bearer YOUR_OMNIROUTE_API_KEY
+```
+
+If no API key is configured on the server, authentication is bypassed.
+
+---
+
+## JSON-RPC 2.0 Methods
+
+### `message/send` — Synchronous Execution
+
+Sends a message to a skill and waits for the complete response.
+
+```bash
+curl -X POST http://localhost:20128/a2a \
+ -H "Content-Type: application/json" \
+ -H "Authorization: Bearer YOUR_KEY" \
+ -d '{
+ "jsonrpc": "2.0",
+ "id": "1",
+ "method": "message/send",
+ "params": {
+ "skill": "smart-routing",
+ "messages": [{"role": "user", "content": "Write a hello world in Python"}],
+ "metadata": {"model": "auto", "combo": "fast-coding"}
+ }
+ }'
+```
+
+**Response:**
+
+```json
+{
+ "jsonrpc": "2.0",
+ "id": "1",
+ "result": {
+ "task": { "id": "uuid", "state": "completed" },
+ "artifacts": [{ "type": "text", "content": "..." }],
+ "metadata": {
+ "routing_explanation": "Selected claude-sonnet via provider \"anthropic\" (latency: 1200ms, cost: $0.003)",
+ "cost_envelope": { "estimated": 0.005, "actual": 0.003, "currency": "USD" },
+ "resilience_trace": [
+ { "event": "primary_selected", "provider": "anthropic", "timestamp": "..." }
+ ],
+ "policy_verdict": { "allowed": true, "reason": "within budget and quota limits" }
+ }
+ }
+}
+```
+
+### `message/stream` — SSE Streaming
+
+Same as `message/send` but returns Server-Sent Events for real-time streaming.
+
+```bash
+curl -N -X POST http://localhost:20128/a2a \
+ -H "Content-Type: application/json" \
+ -H "Authorization: Bearer YOUR_KEY" \
+ -d '{
+ "jsonrpc": "2.0",
+ "id": "1",
+ "method": "message/stream",
+ "params": {
+ "skill": "smart-routing",
+ "messages": [{"role": "user", "content": "Explain quantum computing"}]
+ }
+ }'
+```
+
+**SSE Events:**
+
+```
+data: {"jsonrpc":"2.0","method":"message/stream","params":{"task":{"id":"...","state":"working"},"chunk":{"type":"text","content":"..."}}}
+
+: heartbeat 2026-03-03T17:00:00Z
+
+data: {"jsonrpc":"2.0","method":"message/stream","params":{"task":{"id":"...","state":"completed"},"metadata":{...}}}
+```
+
+### `tasks/get` — Query Task Status
+
+```bash
+curl -X POST http://localhost:20128/a2a \
+ -H "Content-Type: application/json" \
+ -H "Authorization: Bearer YOUR_KEY" \
+ -d '{"jsonrpc":"2.0","id":"2","method":"tasks/get","params":{"taskId":"TASK_UUID"}}'
+```
+
+### `tasks/cancel` — Cancel a Task
+
+```bash
+curl -X POST http://localhost:20128/a2a \
+ -H "Content-Type: application/json" \
+ -H "Authorization: Bearer YOUR_KEY" \
+ -d '{"jsonrpc":"2.0","id":"3","method":"tasks/cancel","params":{"taskId":"TASK_UUID"}}'
+```
+
+---
+
+## Available Skills
+
+| Skill | Description |
+| :----------------- | :------------------------------------------------------------------------------------------------------------------------------ |
+| `smart-routing` | Routes prompts through OmniRoute's intelligent pipeline. Returns response with routing explanation, cost, and resilience trace. |
+| `quota-management` | Answers natural-language queries about provider quotas, suggests free combos, and provides quota rankings. |
+
+---
+
+## Task Lifecycle
+
+```
+submitted → working → completed
+ → failed
+ → cancelled
+```
+
+- Tasks expire after 5 minutes (configurable)
+- Terminal states: `completed`, `failed`, `cancelled`
+- Event log tracks every state transition
+
+---
+
+## Error Codes
+
+| Code | Meaning |
+| :----- | :----------------------------- |
+| -32700 | Parse error (invalid JSON) |
+| -32600 | Invalid request / Unauthorized |
+| -32601 | Method or skill not found |
+| -32602 | Invalid params |
+| -32603 | Internal error |
+
+---
+
+## Integration Examples
+
+### Python (requests)
+
+```python
+import requests
+
+resp = requests.post("http://localhost:20128/a2a", json={
+ "jsonrpc": "2.0", "id": "1",
+ "method": "message/send",
+ "params": {
+ "skill": "smart-routing",
+ "messages": [{"role": "user", "content": "Hello"}]
+ }
+}, headers={"Authorization": "Bearer YOUR_KEY"})
+
+result = resp.json()["result"]
+print(result["artifacts"][0]["content"])
+print(result["metadata"]["routing_explanation"])
+```
+
+### TypeScript (fetch)
+
+```typescript
+const resp = await fetch("http://localhost:20128/a2a", {
+ method: "POST",
+ headers: {
+ "Content-Type": "application/json",
+ Authorization: "Bearer YOUR_KEY",
+ },
+ body: JSON.stringify({
+ jsonrpc: "2.0",
+ id: "1",
+ method: "message/send",
+ params: {
+ skill: "smart-routing",
+ messages: [{ role: "user", content: "Hello" }],
+ },
+ }),
+});
+const { result } = await resp.json();
+console.log(result.metadata.routing_explanation);
+```
diff --git a/docs/i18n/fr/docs/API_REFERENCE.md b/docs/i18n/fr/docs/API_REFERENCE.md
new file mode 100644
index 0000000000..9fe45fdc62
--- /dev/null
+++ b/docs/i18n/fr/docs/API_REFERENCE.md
@@ -0,0 +1,465 @@
+# API Reference (Français)
+
+🌐 **Languages:** 🇺🇸 [English](../../../../docs/API_REFERENCE.md) · 🇪🇸 [es](../../es/docs/API_REFERENCE.md) · 🇫🇷 [fr](../../fr/docs/API_REFERENCE.md) · 🇩🇪 [de](../../de/docs/API_REFERENCE.md) · 🇮🇹 [it](../../it/docs/API_REFERENCE.md) · 🇷🇺 [ru](../../ru/docs/API_REFERENCE.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/API_REFERENCE.md) · 🇯🇵 [ja](../../ja/docs/API_REFERENCE.md) · 🇰🇷 [ko](../../ko/docs/API_REFERENCE.md) · 🇸🇦 [ar](../../ar/docs/API_REFERENCE.md) · 🇮🇳 [in](../../in/docs/API_REFERENCE.md) · 🇹🇭 [th](../../th/docs/API_REFERENCE.md) · 🇻🇳 [vi](../../vi/docs/API_REFERENCE.md) · 🇮🇩 [id](../../id/docs/API_REFERENCE.md) · 🇲🇾 [ms](../../ms/docs/API_REFERENCE.md) · 🇳🇱 [nl](../../nl/docs/API_REFERENCE.md) · 🇵🇱 [pl](../../pl/docs/API_REFERENCE.md) · 🇸🇪 [sv](../../sv/docs/API_REFERENCE.md) · 🇳🇴 [no](../../no/docs/API_REFERENCE.md) · 🇩🇰 [da](../../da/docs/API_REFERENCE.md) · 🇫🇮 [fi](../../fi/docs/API_REFERENCE.md) · 🇵🇹 [pt](../../pt/docs/API_REFERENCE.md) · 🇷🇴 [ro](../../ro/docs/API_REFERENCE.md) · 🇭🇺 [hu](../../hu/docs/API_REFERENCE.md) · 🇧🇬 [bg](../../bg/docs/API_REFERENCE.md) · 🇸🇰 [sk](../../sk/docs/API_REFERENCE.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/API_REFERENCE.md) · 🇮🇱 [he](../../he/docs/API_REFERENCE.md) · 🇵🇭 [phi](../../phi/docs/API_REFERENCE.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/API_REFERENCE.md) · 🇨🇿 [cs](../../cs/docs/API_REFERENCE.md)
+
+---
+
+Complete reference for all OmniRoute API endpoints.
+
+---
+
+## Table of Contents
+
+- [Chat Completions](#chat-completions)
+- [Embeddings](#embeddings)
+- [Image Generation](#image-generation)
+- [List Models](#list-models)
+- [Compatibility Endpoints](#compatibility-endpoints)
+- [Semantic Cache](#semantic-cache)
+- [Dashboard & Management](#dashboard--management)
+- [Request Processing](#request-processing)
+- [Authentication](#authentication)
+
+---
+
+## Chat Completions
+
+```bash
+POST /v1/chat/completions
+Authorization: Bearer your-api-key
+Content-Type: application/json
+
+{
+ "model": "cc/claude-opus-4-6",
+ "messages": [
+ {"role": "user", "content": "Write a function to..."}
+ ],
+ "stream": true
+}
+```
+
+### Custom Headers
+
+| Header | Direction | Description |
+| ------------------------ | --------- | ------------------------------------------------ |
+| `X-OmniRoute-No-Cache` | Request | Set to `true` to bypass cache |
+| `X-OmniRoute-Progress` | Request | Set to `true` for progress events |
+| `X-Session-Id` | Request | Sticky session key for external session affinity |
+| `x_session_id` | Request | Underscore variant also accepted (direct HTTP) |
+| `Idempotency-Key` | Request | Dedup key (5s window) |
+| `X-Request-Id` | Request | Alternative dedup key |
+| `X-OmniRoute-Cache` | Response | `HIT` or `MISS` (non-streaming) |
+| `X-OmniRoute-Idempotent` | Response | `true` if deduplicated |
+| `X-OmniRoute-Progress` | Response | `enabled` if progress tracking on |
+| `X-OmniRoute-Session-Id` | Response | Effective session ID used by OmniRoute |
+
+> Nginx note: if you rely on underscore headers (for example `x_session_id`), enable `underscores_in_headers on;`.
+
+---
+
+## Embeddings
+
+```bash
+POST /v1/embeddings
+Authorization: Bearer your-api-key
+Content-Type: application/json
+
+{
+ "model": "nebius/Qwen/Qwen3-Embedding-8B",
+ "input": "The food was delicious"
+}
+```
+
+Available providers: Nebius, OpenAI, Mistral, Together AI, Fireworks, NVIDIA.
+
+```bash
+# List all embedding models
+GET /v1/embeddings
+```
+
+---
+
+## Image Generation
+
+```bash
+POST /v1/images/generations
+Authorization: Bearer your-api-key
+Content-Type: application/json
+
+{
+ "model": "openai/dall-e-3",
+ "prompt": "A beautiful sunset over mountains",
+ "size": "1024x1024"
+}
+```
+
+Available providers: OpenAI (DALL-E), xAI (Grok Image), Together AI (FLUX), Fireworks AI.
+
+```bash
+# List all image models
+GET /v1/images/generations
+```
+
+---
+
+## List Models
+
+```bash
+GET /v1/models
+Authorization: Bearer your-api-key
+
+→ Returns all chat, embedding, and image models + combos in OpenAI format
+```
+
+---
+
+## Compatibility Endpoints
+
+| Method | Path | Format |
+| ------ | --------------------------- | ---------------------- |
+| POST | `/v1/chat/completions` | OpenAI |
+| POST | `/v1/messages` | Anthropic |
+| POST | `/v1/responses` | OpenAI Responses |
+| POST | `/v1/embeddings` | OpenAI |
+| POST | `/v1/images/generations` | OpenAI |
+| GET | `/v1/models` | OpenAI |
+| POST | `/v1/messages/count_tokens` | Anthropic |
+| GET | `/v1beta/models` | Gemini |
+| POST | `/v1beta/models/{...path}` | Gemini generateContent |
+| POST | `/v1/api/chat` | Ollama |
+
+### Dedicated Provider Routes
+
+```bash
+POST /v1/providers/{provider}/chat/completions
+POST /v1/providers/{provider}/embeddings
+POST /v1/providers/{provider}/images/generations
+```
+
+The provider prefix is auto-added if missing. Mismatched models return `400`.
+
+---
+
+## Semantic Cache
+
+```bash
+# Get cache stats
+GET /api/cache/stats
+
+# Clear all caches
+DELETE /api/cache/stats
+```
+
+Response example:
+
+```json
+{
+ "semanticCache": {
+ "memorySize": 42,
+ "memoryMaxSize": 500,
+ "dbSize": 128,
+ "hitRate": 0.65
+ },
+ "idempotency": {
+ "activeKeys": 3,
+ "windowMs": 5000
+ }
+}
+```
+
+---
+
+## Dashboard & Management
+
+### Authentication
+
+| Endpoint | Method | Description |
+| ----------------------------- | ------- | --------------------- |
+| `/api/auth/login` | POST | Login |
+| `/api/auth/logout` | POST | Logout |
+| `/api/settings/require-login` | GET/PUT | Toggle login required |
+
+### Provider Management
+
+| Endpoint | Method | Description |
+| ---------------------------- | --------------- | ------------------------ |
+| `/api/providers` | GET/POST | List / create providers |
+| `/api/providers/[id]` | GET/PUT/DELETE | Manage a provider |
+| `/api/providers/[id]/test` | POST | Test provider connection |
+| `/api/providers/[id]/models` | GET | List provider models |
+| `/api/providers/validate` | POST | Validate provider config |
+| `/api/provider-nodes*` | Various | Provider node management |
+| `/api/provider-models` | GET/POST/DELETE | Custom models |
+
+### OAuth Flows
+
+| Endpoint | Method | Description |
+| -------------------------------- | ------- | ----------------------- |
+| `/api/oauth/[provider]/[action]` | Various | Provider-specific OAuth |
+
+### Routing & Config
+
+| Endpoint | Method | Description |
+| --------------------- | -------- | ----------------------------- |
+| `/api/models/alias` | GET/POST | Model aliases |
+| `/api/models/catalog` | GET | All models by provider + type |
+| `/api/combos*` | Various | Combo management |
+| `/api/keys*` | Various | API key management |
+| `/api/pricing` | GET | Model pricing |
+
+### Usage & Analytics
+
+| Endpoint | Method | Description |
+| --------------------------- | ------ | -------------------- |
+| `/api/usage/history` | GET | Usage history |
+| `/api/usage/logs` | GET | Usage logs |
+| `/api/usage/request-logs` | GET | Request-level logs |
+| `/api/usage/[connectionId]` | GET | Per-connection usage |
+
+### Settings
+
+| Endpoint | Method | Description |
+| ------------------------------- | ------------- | ---------------------- |
+| `/api/settings` | GET/PUT/PATCH | General settings |
+| `/api/settings/proxy` | GET/PUT | Network proxy config |
+| `/api/settings/proxy/test` | POST | Test proxy connection |
+| `/api/settings/ip-filter` | GET/PUT | IP allowlist/blocklist |
+| `/api/settings/thinking-budget` | GET/PUT | Reasoning token budget |
+| `/api/settings/system-prompt` | GET/PUT | Global system prompt |
+
+### Monitoring
+
+| Endpoint | Method | Description |
+| ------------------------ | ---------- | ---------------------------------------------------------------------------------------------------- |
+| `/api/sessions` | GET | Active session tracking |
+| `/api/rate-limits` | GET | Per-account rate limits |
+| `/api/monitoring/health` | GET | Health check + provider summary (`catalogCount`, `configuredCount`, `activeCount`, `monitoredCount`) |
+| `/api/cache/stats` | GET/DELETE | Cache stats / clear |
+
+### Backup & Export/Import
+
+| Endpoint | Method | Description |
+| --------------------------- | ------ | --------------------------------------- |
+| `/api/db-backups` | GET | List available backups |
+| `/api/db-backups` | PUT | Create a manual backup |
+| `/api/db-backups` | POST | Restore from a specific backup |
+| `/api/db-backups/export` | GET | Download database as .sqlite file |
+| `/api/db-backups/import` | POST | Upload .sqlite file to replace database |
+| `/api/db-backups/exportAll` | GET | Download full backup as .tar.gz archive |
+
+### Cloud Sync
+
+| Endpoint | Method | Description |
+| ---------------------- | ------- | --------------------- |
+| `/api/sync/cloud` | Various | Cloud sync operations |
+| `/api/sync/initialize` | POST | Initialize sync |
+| `/api/cloud/*` | Various | Cloud management |
+
+### Tunnels
+
+| Endpoint | Method | Description |
+| -------------------------- | ------ | ----------------------------------------------------------------------- |
+| `/api/tunnels/cloudflared` | GET | Read Cloudflare Quick Tunnel install/runtime status for the dashboard |
+| `/api/tunnels/cloudflared` | POST | Enable or disable the Cloudflare Quick Tunnel (`action=enable/disable`) |
+
+### CLI Tools
+
+| Endpoint | Method | Description |
+| ---------------------------------- | ------ | ------------------- |
+| `/api/cli-tools/claude-settings` | GET | Claude CLI status |
+| `/api/cli-tools/codex-settings` | GET | Codex CLI status |
+| `/api/cli-tools/droid-settings` | GET | Droid CLI status |
+| `/api/cli-tools/openclaw-settings` | GET | OpenClaw CLI status |
+| `/api/cli-tools/runtime/[toolId]` | GET | Generic CLI runtime |
+
+CLI responses include: `installed`, `runnable`, `command`, `commandPath`, `runtimeMode`, `reason`.
+
+### ACP Agents
+
+| Endpoint | Method | Description |
+| ----------------- | ------ | -------------------------------------------------------- |
+| `/api/acp/agents` | GET | List all detected agents (built-in + custom) with status |
+| `/api/acp/agents` | POST | Add custom agent or refresh detection cache |
+| `/api/acp/agents` | DELETE | Remove a custom agent by `id` query param |
+
+GET response includes `agents[]` (id, name, binary, version, installed, protocol, isCustom) and `summary` (total, installed, notFound, builtIn, custom).
+
+### Resilience & Rate Limits
+
+| Endpoint | Method | Description |
+| ----------------------- | --------- | ------------------------------- |
+| `/api/resilience` | GET/PATCH | Get/update resilience profiles |
+| `/api/resilience/reset` | POST | Reset circuit breakers |
+| `/api/rate-limits` | GET | Per-account rate limit status |
+| `/api/rate-limit` | GET | Global rate limit configuration |
+
+### Evals
+
+| Endpoint | Method | Description |
+| ------------ | -------- | --------------------------------- |
+| `/api/evals` | GET/POST | List eval suites / run evaluation |
+
+### Policies
+
+| Endpoint | Method | Description |
+| --------------- | --------------- | ----------------------- |
+| `/api/policies` | GET/POST/DELETE | Manage routing policies |
+
+### Compliance
+
+| Endpoint | Method | Description |
+| --------------------------- | ------ | ----------------------------- |
+| `/api/compliance/audit-log` | GET | Compliance audit log (last N) |
+
+### v1beta (Gemini-Compatible)
+
+| Endpoint | Method | Description |
+| -------------------------- | ------ | --------------------------------- |
+| `/v1beta/models` | GET | List models in Gemini format |
+| `/v1beta/models/{...path}` | POST | Gemini `generateContent` endpoint |
+
+These endpoints mirror Gemini's API format for clients that expect native Gemini SDK compatibility.
+
+### Internal / System APIs
+
+| Endpoint | Method | Description |
+| --------------- | ------ | ---------------------------------------------------- |
+| `/api/init` | GET | Application initialization check (used on first run) |
+| `/api/tags` | GET | Ollama-compatible model tags (for Ollama clients) |
+| `/api/restart` | POST | Trigger graceful server restart |
+| `/api/shutdown` | POST | Trigger graceful server shutdown |
+
+> **Note:** These endpoints are used internally by the system or for Ollama client compatibility. They are not typically called by end users.
+
+---
+
+## Audio Transcription
+
+```bash
+POST /v1/audio/transcriptions
+Authorization: Bearer your-api-key
+Content-Type: multipart/form-data
+```
+
+Transcribe audio files using Deepgram or AssemblyAI.
+
+**Request:**
+
+```bash
+curl -X POST http://localhost:20128/v1/audio/transcriptions \
+ -H "Authorization: Bearer your-api-key" \
+ -F "file=@recording.mp3" \
+ -F "model=deepgram/nova-3"
+```
+
+**Response:**
+
+```json
+{
+ "text": "Hello, this is the transcribed audio content.",
+ "task": "transcribe",
+ "language": "en",
+ "duration": 12.5
+}
+```
+
+**Supported providers:** `deepgram/nova-3`, `assemblyai/best`.
+
+**Supported formats:** `mp3`, `wav`, `m4a`, `flac`, `ogg`, `webm`.
+
+---
+
+## Ollama Compatibility
+
+For clients that use Ollama's API format:
+
+```bash
+# Chat endpoint (Ollama format)
+POST /v1/api/chat
+
+# Model listing (Ollama format)
+GET /api/tags
+```
+
+Requests are automatically translated between Ollama and internal formats.
+
+---
+
+## Telemetry
+
+```bash
+# Get latency telemetry summary (p50/p95/p99 per provider)
+GET /api/telemetry/summary
+```
+
+**Response:**
+
+```json
+{
+ "providers": {
+ "claudeCode": { "p50": 245, "p95": 890, "p99": 1200, "count": 150 },
+ "github": { "p50": 180, "p95": 620, "p99": 950, "count": 320 }
+ }
+}
+```
+
+---
+
+## Budget
+
+```bash
+# Get budget status for all API keys
+GET /api/usage/budget
+
+# Set or update a budget
+POST /api/usage/budget
+Content-Type: application/json
+
+{
+ "keyId": "key-123",
+ "limit": 50.00,
+ "period": "monthly"
+}
+```
+
+---
+
+## Model Availability
+
+```bash
+# Get real-time model availability across all providers
+GET /api/models/availability
+
+# Check availability for a specific model
+POST /api/models/availability
+Content-Type: application/json
+
+{
+ "model": "claude-sonnet-4-5-20250929"
+}
+```
+
+---
+
+## Request Processing
+
+1. Client sends request to `/v1/*`
+2. Route handler calls `handleChat`, `handleEmbedding`, `handleAudioTranscription`, or `handleImageGeneration`
+3. Model is resolved (direct provider/model or alias/combo)
+4. Credentials selected from local DB with account availability filtering
+5. For chat: `handleChatCore` — format detection, translation, cache check, idempotency check
+6. Provider executor sends upstream request
+7. Response translated back to client format (chat) or returned as-is (embeddings/images/audio)
+8. Usage/logging recorded
+9. Fallback applies on errors according to combo rules
+
+Full architecture reference: [`ARCHITECTURE.md`](ARCHITECTURE.md)
+
+---
+
+## Authentication
+
+- Dashboard routes (`/dashboard/*`) use `auth_token` cookie
+- Login uses saved password hash; fallback to `INITIAL_PASSWORD`
+- `requireLogin` toggleable via `/api/settings/require-login`
+- `/v1/*` routes optionally require Bearer API key when `REQUIRE_API_KEY=true`
diff --git a/docs/i18n/fr/docs/ARCHITECTURE.md b/docs/i18n/fr/docs/ARCHITECTURE.md
new file mode 100644
index 0000000000..aaa0200d38
--- /dev/null
+++ b/docs/i18n/fr/docs/ARCHITECTURE.md
@@ -0,0 +1,814 @@
+# OmniRoute Architecture (Français)
+
+🌐 **Languages:** 🇺🇸 [English](../../../../docs/ARCHITECTURE.md) · 🇪🇸 [es](../../es/docs/ARCHITECTURE.md) · 🇫🇷 [fr](../../fr/docs/ARCHITECTURE.md) · 🇩🇪 [de](../../de/docs/ARCHITECTURE.md) · 🇮🇹 [it](../../it/docs/ARCHITECTURE.md) · 🇷🇺 [ru](../../ru/docs/ARCHITECTURE.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/ARCHITECTURE.md) · 🇯🇵 [ja](../../ja/docs/ARCHITECTURE.md) · 🇰🇷 [ko](../../ko/docs/ARCHITECTURE.md) · 🇸🇦 [ar](../../ar/docs/ARCHITECTURE.md) · 🇮🇳 [in](../../in/docs/ARCHITECTURE.md) · 🇹🇭 [th](../../th/docs/ARCHITECTURE.md) · 🇻🇳 [vi](../../vi/docs/ARCHITECTURE.md) · 🇮🇩 [id](../../id/docs/ARCHITECTURE.md) · 🇲🇾 [ms](../../ms/docs/ARCHITECTURE.md) · 🇳🇱 [nl](../../nl/docs/ARCHITECTURE.md) · 🇵🇱 [pl](../../pl/docs/ARCHITECTURE.md) · 🇸🇪 [sv](../../sv/docs/ARCHITECTURE.md) · 🇳🇴 [no](../../no/docs/ARCHITECTURE.md) · 🇩🇰 [da](../../da/docs/ARCHITECTURE.md) · 🇫🇮 [fi](../../fi/docs/ARCHITECTURE.md) · 🇵🇹 [pt](../../pt/docs/ARCHITECTURE.md) · 🇷🇴 [ro](../../ro/docs/ARCHITECTURE.md) · 🇭🇺 [hu](../../hu/docs/ARCHITECTURE.md) · 🇧🇬 [bg](../../bg/docs/ARCHITECTURE.md) · 🇸🇰 [sk](../../sk/docs/ARCHITECTURE.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/ARCHITECTURE.md) · 🇮🇱 [he](../../he/docs/ARCHITECTURE.md) · 🇵🇭 [phi](../../phi/docs/ARCHITECTURE.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/ARCHITECTURE.md) · 🇨🇿 [cs](../../cs/docs/ARCHITECTURE.md)
+
+---
+
+_Last updated: 2026-03-28_
+
+## Executive Summary
+
+OmniRoute is a local AI routing gateway and dashboard built on Next.js.
+It provides a single OpenAI-compatible endpoint (`/v1/*`) and routes traffic across multiple upstream providers with translation, fallback, token refresh, and usage tracking.
+
+Core capabilities:
+
+- OpenAI-compatible API surface for CLI/tools (28 providers)
+- Request/response translation across provider formats
+- Model combo fallback (multi-model sequence)
+- Account-level fallback (multi-account per provider)
+- OAuth + API-key provider connection management
+- Embedding generation via `/v1/embeddings` (6 providers, 9 models)
+- Image generation via `/v1/images/generations` (4 providers, 9 models)
+- Think tag parsing (`...`) for reasoning models
+- Response sanitization for strict OpenAI SDK compatibility
+- Role normalization (developer→system, system→user) for cross-provider compatibility
+- Structured output conversion (json_schema → Gemini responseSchema)
+- Local persistence for providers, keys, aliases, combos, settings, pricing
+- Usage/cost tracking and request logging
+- Optional cloud sync for multi-device/state sync
+- IP allowlist/blocklist for API access control
+- Thinking budget management (passthrough/auto/custom/adaptive)
+- Global system prompt injection
+- Session tracking and fingerprinting
+- Per-account enhanced rate limiting with provider-specific profiles
+- Circuit breaker pattern for provider resilience
+- Anti-thundering herd protection with mutex locking
+- Signature-based request deduplication cache
+- Domain layer: model availability, cost rules, fallback policy, lockout policy
+- Domain state persistence (SQLite write-through cache for fallbacks, budgets, lockouts, circuit breakers)
+- Policy engine for centralized request evaluation (lockout → budget → fallback)
+- Request telemetry with p50/p95/p99 latency aggregation
+- Correlation ID (X-Request-Id) for end-to-end tracing
+- Compliance audit logging with opt-out per API key
+- Eval framework for LLM quality assurance
+- Resilience UI dashboard with real-time circuit breaker status
+- Modular OAuth providers (12 individual modules under `src/lib/oauth/providers/`)
+
+Primary runtime model:
+
+- Next.js app routes under `src/app/api/*` implement both dashboard APIs and compatibility APIs
+- A shared SSE/routing core in `src/sse/*` + `open-sse/*` handles provider execution, translation, streaming, fallback, and usage
+
+## Scope and Boundaries
+
+### In Scope
+
+- Local gateway runtime
+- Dashboard management APIs
+- Provider authentication and token refresh
+- Request translation and SSE streaming
+- Local state + usage persistence
+- Optional cloud sync orchestration
+
+### Out of Scope
+
+- Cloud service implementation behind `NEXT_PUBLIC_CLOUD_URL`
+- Provider SLA/control plane outside local process
+- External CLI binaries themselves (Claude CLI, Codex CLI, etc.)
+
+## Dashboard Surface (Current)
+
+Main pages under `src/app/(dashboard)/dashboard/`:
+
+- `/dashboard` — quick start + provider overview
+- `/dashboard/endpoint` — endpoint proxy + MCP + A2A + API endpoint tabs
+- `/dashboard/providers` — provider connections and credentials
+- `/dashboard/combos` — combo strategies, templates, model routing rules
+- `/dashboard/costs` — cost aggregation and pricing visibility
+- `/dashboard/analytics` — usage analytics and evaluations
+- `/dashboard/limits` — quota/rate controls
+- `/dashboard/cli-tools` — CLI onboarding, runtime detection, config generation
+- `/dashboard/agents` — detected ACP agents + custom agent registration
+- `/dashboard/media` — image/video/music playground
+- `/dashboard/search-tools` — search provider testing and history
+- `/dashboard/health` — uptime, circuit breakers, rate limits
+- `/dashboard/logs` — request/proxy/audit/console logs
+- `/dashboard/settings` — system settings tabs (general, routing, combo defaults, etc.)
+- `/dashboard/api-manager` — API key lifecycle and model permissions
+
+## High-Level System Context
+
+```mermaid
+flowchart LR
+ subgraph Clients[Developer Clients]
+ C1[Claude Code]
+ C2[Codex CLI]
+ C3[OpenClaw / Droid / Cline / Continue / Roo]
+ C4[Custom OpenAI-compatible clients]
+ BROWSER[Browser Dashboard]
+ end
+
+ subgraph Router[OmniRoute Local Process]
+ API[V1 Compatibility API\n/v1/*]
+ DASH[Dashboard + Management API\n/api/*]
+ CORE[SSE + Translation Core\nopen-sse + src/sse]
+ DB[(storage.sqlite)]
+ UDB[(usage tables + log artifacts)]
+ end
+
+ subgraph Upstreams[Upstream Providers]
+ P1[OAuth Providers\nClaude/Codex/Gemini/Qwen/Qoder/GitHub/Kiro/Cursor/Antigravity]
+ P2[API Key Providers\nOpenAI/Anthropic/OpenRouter/GLM/Kimi/MiniMax\nDeepSeek/Groq/xAI/Mistral/Perplexity\nTogether/Fireworks/Cerebras/Cohere/NVIDIA]
+ P3[Compatible Nodes\nOpenAI-compatible / Anthropic-compatible]
+ end
+
+ subgraph Cloud[Optional Cloud Sync]
+ CLOUD[Cloud Sync Endpoint\nNEXT_PUBLIC_CLOUD_URL]
+ end
+
+ C1 --> API
+ C2 --> API
+ C3 --> API
+ C4 --> API
+ BROWSER --> DASH
+
+ API --> CORE
+ DASH --> DB
+ CORE --> DB
+ CORE --> UDB
+
+ CORE --> P1
+ CORE --> P2
+ CORE --> P3
+
+ DASH --> CLOUD
+```
+
+## Core Runtime Components
+
+## 1) API and Routing Layer (Next.js App Routes)
+
+Main directories:
+
+- `src/app/api/v1/*` and `src/app/api/v1beta/*` for compatibility APIs
+- `src/app/api/*` for management/configuration APIs
+- Next rewrites in `next.config.mjs` map `/v1/*` to `/api/v1/*`
+
+Important compatibility routes:
+
+- `src/app/api/v1/chat/completions/route.ts`
+- `src/app/api/v1/messages/route.ts`
+- `src/app/api/v1/responses/route.ts`
+- `src/app/api/v1/models/route.ts` — includes custom models with `custom: true`
+- `src/app/api/v1/embeddings/route.ts` — embedding generation (6 providers)
+- `src/app/api/v1/images/generations/route.ts` — image generation (4+ providers incl. Antigravity/Nebius)
+- `src/app/api/v1/messages/count_tokens/route.ts`
+- `src/app/api/v1/providers/[provider]/chat/completions/route.ts` — dedicated per-provider chat
+- `src/app/api/v1/providers/[provider]/embeddings/route.ts` — dedicated per-provider embeddings
+- `src/app/api/v1/providers/[provider]/images/generations/route.ts` — dedicated per-provider images
+- `src/app/api/v1beta/models/route.ts`
+- `src/app/api/v1beta/models/[...path]/route.ts`
+
+Management domains:
+
+- Auth/settings: `src/app/api/auth/*`, `src/app/api/settings/*`
+- Providers/connections: `src/app/api/providers*`
+- Provider nodes: `src/app/api/provider-nodes*`
+- Custom models: `src/app/api/provider-models` (GET/POST/DELETE)
+- Model catalog: `src/app/api/models/route.ts` (GET)
+- Proxy config: `src/app/api/settings/proxy` (GET/PUT/DELETE) + `src/app/api/settings/proxy/test` (POST)
+- OAuth: `src/app/api/oauth/*`
+- Keys/aliases/combos/pricing: `src/app/api/keys*`, `src/app/api/models/alias`, `src/app/api/combos*`, `src/app/api/pricing`
+- Usage: `src/app/api/usage/*`
+- Sync/cloud: `src/app/api/sync/*`, `src/app/api/cloud/*`
+- CLI tooling helpers: `src/app/api/cli-tools/*`
+- IP filter: `src/app/api/settings/ip-filter` (GET/PUT)
+- Thinking budget: `src/app/api/settings/thinking-budget` (GET/PUT)
+- System prompt: `src/app/api/settings/system-prompt` (GET/PUT)
+- Sessions: `src/app/api/sessions` (GET)
+- Rate limits: `src/app/api/rate-limits` (GET)
+- Resilience: `src/app/api/resilience` (GET/PATCH) — provider profiles, circuit breaker, rate limit state
+- Resilience reset: `src/app/api/resilience/reset` (POST) — reset breakers + cooldowns
+- Cache stats: `src/app/api/cache/stats` (GET/DELETE)
+- Model availability: `src/app/api/models/availability` (GET/POST)
+- Telemetry: `src/app/api/telemetry/summary` (GET)
+- Budget: `src/app/api/usage/budget` (GET/POST)
+- Fallback chains: `src/app/api/fallback/chains` (GET/POST/DELETE)
+- Compliance audit: `src/app/api/compliance/audit-log` (GET)
+- Evals: `src/app/api/evals` (GET/POST), `src/app/api/evals/[suiteId]` (GET)
+- Policies: `src/app/api/policies` (GET/POST)
+
+## 2) SSE + Translation Core
+
+Main flow modules:
+
+- Entry: `src/sse/handlers/chat.ts`
+- Core orchestration: `open-sse/handlers/chatCore.ts`
+- Provider execution adapters: `open-sse/executors/*`
+- Format detection/provider config: `open-sse/services/provider.ts`
+- Model parse/resolve: `src/sse/services/model.ts`, `open-sse/services/model.ts`
+- Account fallback logic: `open-sse/services/accountFallback.ts`
+- Translation registry: `open-sse/translator/index.ts`
+- Stream transformations: `open-sse/utils/stream.ts`, `open-sse/utils/streamHandler.ts`
+- Usage extraction/normalization: `open-sse/utils/usageTracking.ts`
+- Think tag parser: `open-sse/utils/thinkTagParser.ts`
+- Embedding handler: `open-sse/handlers/embeddings.ts`
+- Embedding provider registry: `open-sse/config/embeddingRegistry.ts`
+- Image generation handler: `open-sse/handlers/imageGeneration.ts`
+- Image provider registry: `open-sse/config/imageRegistry.ts`
+- Response sanitization: `open-sse/handlers/responseSanitizer.ts`
+- Role normalization: `open-sse/services/roleNormalizer.ts`
+
+Services (business logic):
+
+- Account selection/scoring: `open-sse/services/accountSelector.ts`
+- Context lifecycle management: `open-sse/services/contextManager.ts`
+- IP filter enforcement: `open-sse/services/ipFilter.ts`
+- Session tracking: `open-sse/services/sessionManager.ts`
+- Request deduplication: `open-sse/services/signatureCache.ts`
+- System prompt injection: `open-sse/services/systemPrompt.ts`
+- Thinking budget management: `open-sse/services/thinkingBudget.ts`
+- Wildcard model routing: `open-sse/services/wildcardRouter.ts`
+- Rate limit management: `open-sse/services/rateLimitManager.ts`
+- Circuit breaker: `open-sse/services/circuitBreaker.ts`
+
+Domain layer modules:
+
+- Model availability: `src/lib/domain/modelAvailability.ts`
+- Cost rules/budgets: `src/lib/domain/costRules.ts`
+- Fallback policy: `src/lib/domain/fallbackPolicy.ts`
+- Combo resolver: `src/lib/domain/comboResolver.ts`
+- Lockout policy: `src/lib/domain/lockoutPolicy.ts`
+- Policy engine: `src/domain/policyEngine.ts` — centralized lockout → budget → fallback evaluation
+- Error codes catalog: `src/lib/domain/errorCodes.ts`
+- Request ID: `src/lib/domain/requestId.ts`
+- Fetch timeout: `src/lib/domain/fetchTimeout.ts`
+- Request telemetry: `src/lib/domain/requestTelemetry.ts`
+- Compliance/audit: `src/lib/domain/compliance/index.ts`
+- Eval runner: `src/lib/domain/evalRunner.ts`
+- Domain state persistence: `src/lib/db/domainState.ts` — SQLite CRUD for fallback chains, budgets, cost history, lockout state, circuit breakers
+
+OAuth provider modules (12 individual files under `src/lib/oauth/providers/`):
+
+- Registry index: `src/lib/oauth/providers/index.ts`
+- Individual providers: `claude.ts`, `codex.ts`, `gemini.ts`, `antigravity.ts`, `qoder.ts`, `qwen.ts`, `kimi-coding.ts`, `github.ts`, `kiro.ts`, `cursor.ts`, `kilocode.ts`, `cline.ts`
+- Thin wrapper: `src/lib/oauth/providers.ts` — re-exports from individual modules
+
+## 3) Persistence Layer
+
+Primary state DB (SQLite):
+
+- Core infra: `src/lib/db/core.ts` (better-sqlite3, migrations, WAL)
+- Re-export facade: `src/lib/localDb.ts` (thin compatibility layer for callers)
+- file: `${DATA_DIR}/storage.sqlite` (or `$XDG_CONFIG_HOME/omniroute/storage.sqlite` when set, else `~/.omniroute/storage.sqlite`)
+- entities (tables + KV namespaces): providerConnections, providerNodes, modelAliases, combos, apiKeys, settings, pricing, **customModels**, **proxyConfig**, **ipFilter**, **thinkingBudget**, **systemPrompt**
+
+Usage persistence:
+
+- facade: `src/lib/usageDb.ts` (decomposed modules in `src/lib/usage/*`)
+- SQLite tables in `storage.sqlite`: `usage_history`, `call_logs`, `proxy_logs`
+- optional file artifacts remain for compatibility/debug (`${DATA_DIR}/log.txt`, `${DATA_DIR}/call_logs/`, `/logs/...`)
+- legacy JSON files are migrated to SQLite by startup migrations when present
+
+Domain State DB (SQLite):
+
+- `src/lib/db/domainState.ts` — CRUD operations for domain state
+- Tables (created in `src/lib/db/core.ts`): `domain_fallback_chains`, `domain_budgets`, `domain_cost_history`, `domain_lockout_state`, `domain_circuit_breakers`
+- Write-through cache pattern: in-memory Maps are authoritative at runtime; mutations are written synchronously to SQLite; state is restored from DB on cold start
+
+## 4) Auth + Security Surfaces
+
+- Dashboard cookie auth: `src/proxy.ts`, `src/app/api/auth/login/route.ts`
+- API key generation/verification: `src/shared/utils/apiKey.ts`
+- Provider secrets persisted in `providerConnections` entries
+- Outbound proxy support via `open-sse/utils/proxyFetch.ts` (env vars) and `open-sse/utils/networkProxy.ts` (configurable per-provider or global)
+
+## 5) Cloud Sync
+
+- Scheduler init: `src/lib/initCloudSync.ts`, `src/shared/services/initializeCloudSync.ts`, `src/shared/services/modelSyncScheduler.ts`
+- Periodic task: `src/shared/services/cloudSyncScheduler.ts`
+- Periodic task: `src/shared/services/modelSyncScheduler.ts`
+- Control route: `src/app/api/sync/cloud/route.ts`
+
+## Request Lifecycle (`/v1/chat/completions`)
+
+```mermaid
+sequenceDiagram
+ autonumber
+ participant Client as CLI/SDK Client
+ participant Route as /api/v1/chat/completions
+ participant Chat as src/sse/handlers/chat
+ participant Core as open-sse/handlers/chatCore
+ participant Model as Model Resolver
+ participant Auth as Credential Selector
+ participant Exec as Provider Executor
+ participant Prov as Upstream Provider
+ participant Stream as Stream Translator
+ participant Usage as usageDb
+
+ Client->>Route: POST /v1/chat/completions
+ Route->>Chat: handleChat(request)
+ Chat->>Model: parse/resolve model or combo
+
+ alt Combo model
+ Chat->>Chat: iterate combo models (handleComboChat)
+ end
+
+ Chat->>Auth: getProviderCredentials(provider)
+ Auth-->>Chat: active account + tokens/api key
+
+ Chat->>Core: handleChatCore(body, modelInfo, credentials)
+ Core->>Core: detect source format
+ Core->>Core: translate request to target format
+ Core->>Exec: execute(provider, transformedBody)
+ Exec->>Prov: upstream API call
+ Prov-->>Exec: SSE/JSON response
+ Exec-->>Core: response + metadata
+
+ alt 401/403
+ Core->>Exec: refreshCredentials()
+ Exec-->>Core: updated tokens
+ Core->>Exec: retry request
+ end
+
+ Core->>Stream: translate/normalize stream to client format
+ Stream-->>Client: SSE chunks / JSON response
+
+ Stream->>Usage: extract usage + persist history/log
+```
+
+## Combo + Account Fallback Flow
+
+```mermaid
+flowchart TD
+ A[Incoming model string] --> B{Is combo name?}
+ B -- Yes --> C[Load combo models sequence]
+ B -- No --> D[Single model path]
+
+ C --> E[Try model N]
+ E --> F[Resolve provider/model]
+ D --> F
+
+ F --> G[Select account credentials]
+ G --> H{Credentials available?}
+ H -- No --> I[Return provider unavailable]
+ H -- Yes --> J[Execute request]
+
+ J --> K{Success?}
+ K -- Yes --> L[Return response]
+ K -- No --> M{Fallback-eligible error?}
+
+ M -- No --> N[Return error]
+ M -- Yes --> O[Mark account unavailable cooldown]
+ O --> P{Another account for provider?}
+ P -- Yes --> G
+ P -- No --> Q{In combo with next model?}
+ Q -- Yes --> E
+ Q -- No --> R[Return all unavailable]
+```
+
+Fallback decisions are driven by `open-sse/services/accountFallback.ts` using status codes and error-message heuristics. Combo routing adds one extra guard: provider-scoped 400s such as upstream content-block and role-validation failures are treated as model-local failures so later combo targets can still run.
+
+## OAuth Onboarding and Token Refresh Lifecycle
+
+```mermaid
+sequenceDiagram
+ autonumber
+ participant UI as Dashboard UI
+ participant OAuth as /api/oauth/[provider]/[action]
+ participant ProvAuth as Provider Auth Server
+ participant DB as localDb
+ participant Test as /api/providers/[id]/test
+ participant Exec as Provider Executor
+
+ UI->>OAuth: GET authorize or device-code
+ OAuth->>ProvAuth: create auth/device flow
+ ProvAuth-->>OAuth: auth URL or device code payload
+ OAuth-->>UI: flow data
+
+ UI->>OAuth: POST exchange or poll
+ OAuth->>ProvAuth: token exchange/poll
+ ProvAuth-->>OAuth: access/refresh tokens
+ OAuth->>DB: createProviderConnection(oauth data)
+ OAuth-->>UI: success + connection id
+
+ UI->>Test: POST /api/providers/[id]/test
+ Test->>Exec: validate credentials / optional refresh
+ Exec-->>Test: valid or refreshed token info
+ Test->>DB: update status/tokens/errors
+ Test-->>UI: validation result
+```
+
+Refresh during live traffic is executed inside `open-sse/handlers/chatCore.ts` via executor `refreshCredentials()`.
+
+## Cloud Sync Lifecycle (Enable / Sync / Disable)
+
+```mermaid
+sequenceDiagram
+ autonumber
+ participant UI as Endpoint Page UI
+ participant Sync as /api/sync/cloud
+ participant DB as localDb
+ participant Cloud as External Cloud Sync
+ participant Claude as ~/.claude/settings.json
+
+ UI->>Sync: POST action=enable
+ Sync->>DB: set cloudEnabled=true
+ Sync->>DB: ensure API key exists
+ Sync->>Cloud: POST /sync/{machineId} (providers/aliases/combos/keys)
+ Cloud-->>Sync: sync result
+ Sync->>Cloud: GET /{machineId}/v1/verify
+ Sync-->>UI: enabled + verification status
+
+ UI->>Sync: POST action=sync
+ Sync->>Cloud: POST /sync/{machineId}
+ Cloud-->>Sync: remote data
+ Sync->>DB: update newer local tokens/status
+ Sync-->>UI: synced
+
+ UI->>Sync: POST action=disable
+ Sync->>DB: set cloudEnabled=false
+ Sync->>Cloud: DELETE /sync/{machineId}
+ Sync->>Claude: switch ANTHROPIC_BASE_URL back to local (if needed)
+ Sync-->>UI: disabled
+```
+
+Periodic sync is triggered by `CloudSyncScheduler` when cloud is enabled.
+
+## Data Model and Storage Map
+
+```mermaid
+erDiagram
+ SETTINGS ||--o{ PROVIDER_CONNECTION : controls
+ PROVIDER_NODE ||--o{ PROVIDER_CONNECTION : backs_compatible_provider
+ PROVIDER_CONNECTION ||--o{ USAGE_ENTRY : emits_usage
+
+ SETTINGS {
+ boolean cloudEnabled
+ number stickyRoundRobinLimit
+ boolean requireLogin
+ string password_hash
+ string fallbackStrategy
+ json rateLimitDefaults
+ json providerProfiles
+ }
+
+ PROVIDER_CONNECTION {
+ string id
+ string provider
+ string authType
+ string name
+ number priority
+ boolean isActive
+ string apiKey
+ string accessToken
+ string refreshToken
+ string expiresAt
+ string testStatus
+ string lastError
+ string rateLimitedUntil
+ json providerSpecificData
+ }
+
+ PROVIDER_NODE {
+ string id
+ string type
+ string name
+ string prefix
+ string apiType
+ string baseUrl
+ }
+
+ MODEL_ALIAS {
+ string alias
+ string targetModel
+ }
+
+ COMBO {
+ string id
+ string name
+ string[] models
+ }
+
+ API_KEY {
+ string id
+ string name
+ string key
+ string machineId
+ }
+
+ USAGE_ENTRY {
+ string provider
+ string model
+ number prompt_tokens
+ number completion_tokens
+ string connectionId
+ string timestamp
+ }
+
+ CUSTOM_MODEL {
+ string id
+ string name
+ string providerId
+ }
+
+ PROXY_CONFIG {
+ string global
+ json providers
+ }
+
+ IP_FILTER {
+ string mode
+ string[] allowlist
+ string[] blocklist
+ }
+
+ THINKING_BUDGET {
+ string mode
+ number customBudget
+ string effortLevel
+ }
+
+ SYSTEM_PROMPT {
+ boolean enabled
+ string prompt
+ string position
+ }
+```
+
+Physical storage files:
+
+- primary runtime DB: `${DATA_DIR}/storage.sqlite`
+- request log lines: `${DATA_DIR}/log.txt` (compat/debug artifact)
+- structured call payload archives: `${DATA_DIR}/call_logs/`
+- optional translator/request debug sessions: `/logs/...`
+
+## Deployment Topology
+
+```mermaid
+flowchart LR
+ subgraph LocalHost[Developer Host]
+ CLI[CLI Tools]
+ Browser[Dashboard Browser]
+ end
+
+ subgraph ContainerOrProcess[OmniRoute Runtime]
+ Next[Next.js Server\nPORT=20128]
+ Core[SSE Core + Executors]
+ MainDB[(storage.sqlite)]
+ UsageDB[(usage tables + log artifacts)]
+ end
+
+ subgraph External[External Services]
+ Providers[AI Providers]
+ SyncCloud[Cloud Sync Service]
+ end
+
+ CLI --> Next
+ Browser --> Next
+ Next --> Core
+ Next --> MainDB
+ Core --> MainDB
+ Core --> UsageDB
+ Core --> Providers
+ Next --> SyncCloud
+```
+
+## Module Mapping (Decision-Critical)
+
+### Route and API Modules
+
+- `src/app/api/v1/*`, `src/app/api/v1beta/*`: compatibility APIs
+- `src/app/api/v1/providers/[provider]/*`: dedicated per-provider routes (chat, embeddings, images)
+- `src/app/api/providers*`: provider CRUD, validation, testing
+- `src/app/api/provider-nodes*`: custom compatible node management
+- `src/app/api/provider-models`: custom model management (CRUD)
+- `src/app/api/models/route.ts`: model catalog API (aliases + custom models)
+- `src/app/api/oauth/*`: OAuth/device-code flows
+- `src/app/api/keys*`: local API key lifecycle
+- `src/app/api/models/alias`: alias management
+- `src/app/api/combos*`: fallback combo management
+- `src/app/api/pricing`: pricing overrides for cost calculation
+- `src/app/api/settings/proxy`: proxy configuration (GET/PUT/DELETE)
+- `src/app/api/settings/proxy/test`: outbound proxy connectivity test (POST)
+- `src/app/api/usage/*`: usage and logs APIs
+- `src/app/api/sync/*` + `src/app/api/cloud/*`: cloud sync and cloud-facing helpers
+- `src/app/api/cli-tools/*`: local CLI config writers/checkers
+- `src/app/api/settings/ip-filter`: IP allowlist/blocklist (GET/PUT)
+- `src/app/api/settings/thinking-budget`: thinking token budget config (GET/PUT)
+- `src/app/api/settings/system-prompt`: global system prompt (GET/PUT)
+- `src/app/api/sessions`: active session listing (GET)
+- `src/app/api/rate-limits`: per-account rate limit status (GET)
+
+### Routing and Execution Core
+
+- `src/sse/handlers/chat.ts`: request parse, combo handling, account selection loop
+- `open-sse/handlers/chatCore.ts`: translation, executor dispatch, retry/refresh handling, stream setup
+- `open-sse/executors/*`: provider-specific network and format behavior
+
+### Translation Registry and Format Converters
+
+- `open-sse/translator/index.ts`: translator registry and orchestration
+- Request translators: `open-sse/translator/request/*`
+- Response translators: `open-sse/translator/response/*`
+- Format constants: `open-sse/translator/formats.ts`
+
+### Persistence
+
+- `src/lib/db/*`: persistent config/state and domain persistence on SQLite
+- `src/lib/localDb.ts`: compatibility re-export for DB modules
+- `src/lib/usageDb.ts`: usage history/call logs facade on top of SQLite tables
+
+## Provider Executor Coverage (Strategy Pattern)
+
+Each provider has a specialized executor extending `BaseExecutor` (in `open-sse/executors/base.ts`), which provides URL building, header construction, retry with exponential backoff, credential refresh hooks, and the `execute()` orchestration method.
+
+| Executor | Provider(s) | Special Handling |
+| --------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------ | -------------------------------------------------------------------- |
+| `DefaultExecutor` | OpenAI, Claude, Gemini, Qwen, Qoder, OpenRouter, GLM, Kimi, MiniMax, DeepSeek, Groq, xAI, Mistral, Perplexity, Together, Fireworks, Cerebras, Cohere, NVIDIA | Dynamic URL/header config per provider |
+| `AntigravityExecutor` | Google Antigravity | Custom project/session IDs, Retry-After parsing |
+| `CodexExecutor` | OpenAI Codex | Injects system instructions, forces reasoning effort |
+| `CursorExecutor` | Cursor IDE | ConnectRPC protocol, Protobuf encoding, request signing via checksum |
+| `GithubExecutor` | GitHub Copilot | Copilot token refresh, VSCode-mimicking headers |
+| `KiroExecutor` | AWS CodeWhisperer/Kiro | AWS EventStream binary format → SSE conversion |
+| `GeminiCLIExecutor` | Gemini CLI | Google OAuth token refresh cycle |
+
+All other providers (including custom compatible nodes) use the `DefaultExecutor`.
+
+## Provider Compatibility Matrix
+
+| Provider | Format | Auth | Stream | Non-Stream | Token Refresh | Usage API |
+| ---------------- | ---------------- | --------------------- | ---------------- | ---------- | ------------- | ------------------ |
+| Claude | claude | API Key / OAuth | ✅ | ✅ | ✅ | ⚠️ Admin only |
+| Gemini | gemini | API Key / OAuth | ✅ | ✅ | ✅ | ⚠️ Cloud Console |
+| Gemini CLI | gemini-cli | OAuth | ✅ | ✅ | ✅ | ⚠️ Cloud Console |
+| Antigravity | antigravity | OAuth | ✅ | ✅ | ✅ | ✅ Full quota API |
+| OpenAI | openai | API Key | ✅ | ✅ | ❌ | ❌ |
+| Codex | openai-responses | OAuth | ✅ forced | ❌ | ✅ | ✅ Rate limits |
+| GitHub Copilot | openai | OAuth + Copilot Token | ✅ | ✅ | ✅ | ✅ Quota snapshots |
+| Cursor | cursor | Custom checksum | ✅ | ✅ | ❌ | ❌ |
+| Kiro | kiro | AWS SSO OIDC | ✅ (EventStream) | ❌ | ✅ | ✅ Usage limits |
+| Qwen | openai | OAuth | ✅ | ✅ | ✅ | ⚠️ Per request |
+| Qoder | openai | OAuth (Basic) | ✅ | ✅ | ✅ | ⚠️ Per request |
+| OpenRouter | openai | API Key | ✅ | ✅ | ❌ | ❌ |
+| GLM/Kimi/MiniMax | claude | API Key | ✅ | ✅ | ❌ | ❌ |
+| DeepSeek | openai | API Key | ✅ | ✅ | ❌ | ❌ |
+| Groq | openai | API Key | ✅ | ✅ | ❌ | ❌ |
+| xAI (Grok) | openai | API Key | ✅ | ✅ | ❌ | ❌ |
+| Mistral | openai | API Key | ✅ | ✅ | ❌ | ❌ |
+| Perplexity | openai | API Key | ✅ | ✅ | ❌ | ❌ |
+| Together AI | openai | API Key | ✅ | ✅ | ❌ | ❌ |
+| Fireworks AI | openai | API Key | ✅ | ✅ | ❌ | ❌ |
+| Cerebras | openai | API Key | ✅ | ✅ | ❌ | ❌ |
+| Cohere | openai | API Key | ✅ | ✅ | ❌ | ❌ |
+| NVIDIA NIM | openai | API Key | ✅ | ✅ | ❌ | ❌ |
+
+## Format Translation Coverage
+
+Detected source formats include:
+
+- `openai`
+- `openai-responses`
+- `claude`
+- `gemini`
+
+Target formats include:
+
+- OpenAI chat/Responses
+- Claude
+- Gemini/Gemini-CLI/Antigravity envelope
+- Kiro
+- Cursor
+
+Translations use **OpenAI as the hub format** — all conversions go through OpenAI as intermediate:
+
+```
+Source Format → OpenAI (hub) → Target Format
+```
+
+Translations are selected dynamically based on source payload shape and provider target format.
+
+Additional processing layers in the translation pipeline:
+
+- **Response sanitization** — Strips non-standard fields from OpenAI-format responses (both streaming and non-streaming) to ensure strict SDK compliance
+- **Role normalization** — Converts `developer` → `system` for non-OpenAI targets; merges `system` → `user` for models that reject the system role (GLM, ERNIE)
+- **Think tag extraction** — Parses `...` blocks from content into `reasoning_content` field
+- **Structured output** — Converts OpenAI `response_format.json_schema` to Gemini's `responseMimeType` + `responseSchema`
+
+## Supported API Endpoints
+
+| Endpoint | Format | Handler |
+| -------------------------------------------------- | ------------------ | ------------------------------------------------------------------- |
+| `POST /v1/chat/completions` | OpenAI Chat | `src/sse/handlers/chat.ts` |
+| `POST /v1/messages` | Claude Messages | Same handler (auto-detected) |
+| `POST /v1/responses` | OpenAI Responses | `open-sse/handlers/responsesHandler.ts` |
+| `POST /v1/embeddings` | OpenAI Embeddings | `open-sse/handlers/embeddings.ts` |
+| `GET /v1/embeddings` | Model listing | API route |
+| `POST /v1/images/generations` | OpenAI Images | `open-sse/handlers/imageGeneration.ts` |
+| `GET /v1/images/generations` | Model listing | API route |
+| `POST /v1/providers/{provider}/chat/completions` | OpenAI Chat | Dedicated per-provider with model validation |
+| `POST /v1/providers/{provider}/embeddings` | OpenAI Embeddings | Dedicated per-provider with model validation |
+| `POST /v1/providers/{provider}/images/generations` | OpenAI Images | Dedicated per-provider with model validation |
+| `POST /v1/messages/count_tokens` | Claude Token Count | API route |
+| `GET /v1/models` | OpenAI Models list | API route (chat + embedding + image + custom models) |
+| `GET /api/models/catalog` | Catalog | All models grouped by provider + type |
+| `POST /v1beta/models/*:streamGenerateContent` | Gemini native | API route |
+| `GET/PUT/DELETE /api/settings/proxy` | Proxy Config | Network proxy configuration |
+| `POST /api/settings/proxy/test` | Proxy Connectivity | Proxy health/connectivity test endpoint |
+| `GET/POST/DELETE /api/provider-models` | Provider Models | Provider model metadata backing custom and managed available models |
+
+## Bypass Handler
+
+The bypass handler (`open-sse/utils/bypassHandler.ts`) intercepts known "throwaway" requests from Claude CLI — warmup pings, title extractions, and token counts — and returns a **fake response** without consuming upstream provider tokens. This is triggered only when `User-Agent` contains `claude-cli`.
+
+## Request Logger Pipeline
+
+The request logger (`open-sse/utils/requestLogger.ts`) provides a 7-stage debug logging pipeline, disabled by default, enabled via `ENABLE_REQUEST_LOGS=true`:
+
+```
+1_req_client.json → 2_req_source.json → 3_req_openai.json → 4_req_target.json
+→ 5_res_provider.txt → 6_res_openai.txt → 7_res_client.txt
+```
+
+Files are written to `/logs//` for each request session.
+
+## Failure Modes and Resilience
+
+## 1) Account/Provider Availability
+
+- provider account cooldown on transient/rate/auth errors
+- account fallback before failing request
+- combo model fallback when current model/provider path is exhausted
+
+## 2) Token Expiry
+
+- pre-check and refresh with retry for refreshable providers
+- 401/403 retry after refresh attempt in core path
+
+## 3) Stream Safety
+
+- disconnect-aware stream controller
+- translation stream with end-of-stream flush and `[DONE]` handling
+- usage estimation fallback when provider usage metadata is missing
+
+## 4) Cloud Sync Degradation
+
+- sync errors are surfaced but local runtime continues
+- scheduler has retry-capable logic, but periodic execution currently calls single-attempt sync by default
+
+## 5) Data Integrity
+
+- SQLite schema migrations and auto-upgrade hooks at startup
+- legacy JSON → SQLite migration compatibility path
+
+## Observability and Operational Signals
+
+Runtime visibility sources:
+
+- console logs from `src/sse/utils/logger.ts`
+- per-request usage aggregates in SQLite (`usage_history`, `call_logs`, `proxy_logs`)
+- four-stage detailed payload captures in SQLite (`request_detail_logs`) when `settings.detailed_logs_enabled=true`
+- textual request status log in `log.txt` (optional/compat)
+- optional deep request/translation logs under `logs/` when `ENABLE_REQUEST_LOGS=true`
+- dashboard usage endpoints (`/api/usage/*`) for UI consumption
+
+Detailed request payload capture stores up to four JSON payload stages per routed call:
+
+- raw request received from the client
+- translated request actually sent upstream
+- provider response reconstructed as JSON; streamed responses are compacted to the final summary plus stream metadata
+- final client response returned by OmniRoute; streamed responses are stored in the same compact summary form
+
+## Security-Sensitive Boundaries
+
+- JWT secret (`JWT_SECRET`) secures dashboard session cookie verification/signing
+- Initial password bootstrap (`INITIAL_PASSWORD`) should be explicitly configured for first-run provisioning
+- API key HMAC secret (`API_KEY_SECRET`) secures generated local API key format
+- Provider secrets (API keys/tokens) are persisted in local DB and should be protected at filesystem level
+- Cloud sync endpoints rely on API key auth + machine id semantics
+
+## Environment and Runtime Matrix
+
+Environment variables actively used by code:
+
+- App/auth: `JWT_SECRET`, `INITIAL_PASSWORD`
+- Storage: `DATA_DIR`
+- Compatible node behavior: `ALLOW_MULTI_CONNECTIONS_PER_COMPAT_NODE`
+- Optional storage base override (Linux/macOS when `DATA_DIR` unset): `XDG_CONFIG_HOME`
+- Security hashing: `API_KEY_SECRET`, `MACHINE_ID_SALT`
+- Logging: `ENABLE_REQUEST_LOGS`
+- Sync/cloud URLing: `NEXT_PUBLIC_BASE_URL`, `NEXT_PUBLIC_CLOUD_URL`
+- Outbound proxy: `HTTP_PROXY`, `HTTPS_PROXY`, `ALL_PROXY`, `NO_PROXY` and lowercase variants
+- SOCKS5 feature flags: `ENABLE_SOCKS5_PROXY`, `NEXT_PUBLIC_ENABLE_SOCKS5_PROXY`
+- Platform/runtime helpers (not app-specific config): `APPDATA`, `NODE_ENV`, `PORT`, `HOSTNAME`
+
+## Known Architectural Notes
+
+1. `usageDb` and `localDb` share the same base directory policy (`DATA_DIR` -> `XDG_CONFIG_HOME/omniroute` -> `~/.omniroute`) with legacy file migration.
+2. `/api/v1/route.ts` delegates to the same unified catalog builder used by `/api/v1/models` (`src/app/api/v1/models/catalog.ts`) to avoid semantic drift.
+3. Request logger writes full headers/body when enabled; treat log directory as sensitive.
+4. Cloud behavior depends on correct `NEXT_PUBLIC_BASE_URL` and cloud endpoint reachability.
+5. The `open-sse/` directory is published as the `@omniroute/open-sse` **npm workspace package**. Source code imports it via `@omniroute/open-sse/...` (resolved by Next.js `transpilePackages`). File paths in this document still use the directory name `open-sse/` for consistency.
+6. Charts in the dashboard use **Recharts** (SVG-based) for accessible, interactive analytics visualizations (model usage bar charts, provider breakdown tables with success rates).
+7. E2E tests use **Playwright** (`tests/e2e/`), run via `npm run test:e2e`. Unit tests use **Node.js test runner** (`tests/unit/`), run via `npm run test:unit`. Source code under `src/` is **TypeScript** (`.ts`/`.tsx`); the `open-sse/` workspace remains JavaScript (`.js`).
+8. Settings page is organized into 5 tabs: Security, Routing (6 global strategies: fill-first, round-robin, p2c, random, least-used, cost-optimized), Resilience (editable rate limits, circuit breaker, policies), AI (thinking budget, system prompt, prompt cache), Advanced (proxy).
+
+## Operational Verification Checklist
+
+- Build from source: `npm run build`
+- Build Docker image: `docker build -t omniroute .`
+- Start service and verify:
+- `GET /api/settings`
+- `GET /api/v1/models`
+- CLI target base URL should be `http://:20128/v1` when `PORT=20128`
diff --git a/docs/i18n/fr/docs/AUTO-COMBO.md b/docs/i18n/fr/docs/AUTO-COMBO.md
new file mode 100644
index 0000000000..9cf0f6d606
--- /dev/null
+++ b/docs/i18n/fr/docs/AUTO-COMBO.md
@@ -0,0 +1,67 @@
+# OmniRoute Auto-Combo Engine (Français)
+
+🌐 **Languages:** 🇺🇸 [English](../../../../docs/AUTO-COMBO.md) · 🇪🇸 [es](../../es/docs/AUTO-COMBO.md) · 🇫🇷 [fr](../../fr/docs/AUTO-COMBO.md) · 🇩🇪 [de](../../de/docs/AUTO-COMBO.md) · 🇮🇹 [it](../../it/docs/AUTO-COMBO.md) · 🇷🇺 [ru](../../ru/docs/AUTO-COMBO.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/AUTO-COMBO.md) · 🇯🇵 [ja](../../ja/docs/AUTO-COMBO.md) · 🇰🇷 [ko](../../ko/docs/AUTO-COMBO.md) · 🇸🇦 [ar](../../ar/docs/AUTO-COMBO.md) · 🇮🇳 [in](../../in/docs/AUTO-COMBO.md) · 🇹🇭 [th](../../th/docs/AUTO-COMBO.md) · 🇻🇳 [vi](../../vi/docs/AUTO-COMBO.md) · 🇮🇩 [id](../../id/docs/AUTO-COMBO.md) · 🇲🇾 [ms](../../ms/docs/AUTO-COMBO.md) · 🇳🇱 [nl](../../nl/docs/AUTO-COMBO.md) · 🇵🇱 [pl](../../pl/docs/AUTO-COMBO.md) · 🇸🇪 [sv](../../sv/docs/AUTO-COMBO.md) · 🇳🇴 [no](../../no/docs/AUTO-COMBO.md) · 🇩🇰 [da](../../da/docs/AUTO-COMBO.md) · 🇫🇮 [fi](../../fi/docs/AUTO-COMBO.md) · 🇵🇹 [pt](../../pt/docs/AUTO-COMBO.md) · 🇷🇴 [ro](../../ro/docs/AUTO-COMBO.md) · 🇭🇺 [hu](../../hu/docs/AUTO-COMBO.md) · 🇧🇬 [bg](../../bg/docs/AUTO-COMBO.md) · 🇸🇰 [sk](../../sk/docs/AUTO-COMBO.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/AUTO-COMBO.md) · 🇮🇱 [he](../../he/docs/AUTO-COMBO.md) · 🇵🇭 [phi](../../phi/docs/AUTO-COMBO.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/AUTO-COMBO.md) · 🇨🇿 [cs](../../cs/docs/AUTO-COMBO.md)
+
+---
+
+> Self-managing model chains with adaptive scoring
+
+## How It Works
+
+The Auto-Combo Engine dynamically selects the best provider/model for each request using a **6-factor scoring function**:
+
+| Factor | Weight | Description |
+| :--------- | :----- | :---------------------------------------------- |
+| Quota | 0.20 | Remaining capacity [0..1] |
+| Health | 0.25 | Circuit breaker: CLOSED=1.0, HALF=0.5, OPEN=0.0 |
+| CostInv | 0.20 | Inverse cost (cheaper = higher score) |
+| LatencyInv | 0.15 | Inverse p95 latency (faster = higher) |
+| TaskFit | 0.10 | Model × task type fitness score |
+| Stability | 0.10 | Low variance in latency/errors |
+
+## Mode Packs
+
+| Pack | Focus | Key Weight |
+| :---------------------- | :----------- | :--------------- |
+| 🚀 **Ship Fast** | Speed | latencyInv: 0.35 |
+| 💰 **Cost Saver** | Economy | costInv: 0.40 |
+| 🎯 **Quality First** | Best model | taskFit: 0.40 |
+| 📡 **Offline Friendly** | Availability | quota: 0.40 |
+
+## Self-Healing
+
+- **Temporary exclusion**: Score < 0.2 → excluded for 5 min (progressive backoff, max 30 min)
+- **Circuit breaker awareness**: OPEN → auto-excluded; HALF_OPEN → probe requests
+- **Incident mode**: >50% OPEN → disable exploration, maximize stability
+- **Cooldown recovery**: After exclusion, first request is a "probe" with reduced timeout
+
+## Bandit Exploration
+
+5% of requests (configurable) are routed to random providers for exploration. Disabled in incident mode.
+
+## API
+
+```bash
+# Create auto-combo
+curl -X POST http://localhost:20128/api/combos/auto \
+ -H "Content-Type: application/json" \
+ -d '{"id":"my-auto","name":"Auto Coder","candidatePool":["anthropic","google","openai"],"modePack":"ship-fast"}'
+
+# List auto-combos
+curl http://localhost:20128/api/combos/auto
+```
+
+## Task Fitness
+
+30+ models scored across 6 task types (`coding`, `review`, `planning`, `analysis`, `debugging`, `documentation`). Supports wildcard patterns (e.g., `*-coder` → high coding score).
+
+## Files
+
+| File | Purpose |
+| :------------------------------------------- | :------------------------------------ |
+| `open-sse/services/autoCombo/scoring.ts` | Scoring function & pool normalization |
+| `open-sse/services/autoCombo/taskFitness.ts` | Model × task fitness lookup |
+| `open-sse/services/autoCombo/engine.ts` | Selection logic, bandit, budget cap |
+| `open-sse/services/autoCombo/selfHealing.ts` | Exclusion, probes, incident mode |
+| `open-sse/services/autoCombo/modePacks.ts` | 4 weight profiles |
+| `src/app/api/combos/auto/route.ts` | REST API |
diff --git a/docs/i18n/fr/docs/CLI-TOOLS.md b/docs/i18n/fr/docs/CLI-TOOLS.md
new file mode 100644
index 0000000000..6cefebbbc1
--- /dev/null
+++ b/docs/i18n/fr/docs/CLI-TOOLS.md
@@ -0,0 +1,348 @@
+# CLI Tools Setup Guide — OmniRoute (Français)
+
+🌐 **Languages:** 🇺🇸 [English](../../../../docs/CLI-TOOLS.md) · 🇪🇸 [es](../../es/docs/CLI-TOOLS.md) · 🇫🇷 [fr](../../fr/docs/CLI-TOOLS.md) · 🇩🇪 [de](../../de/docs/CLI-TOOLS.md) · 🇮🇹 [it](../../it/docs/CLI-TOOLS.md) · 🇷🇺 [ru](../../ru/docs/CLI-TOOLS.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/CLI-TOOLS.md) · 🇯🇵 [ja](../../ja/docs/CLI-TOOLS.md) · 🇰🇷 [ko](../../ko/docs/CLI-TOOLS.md) · 🇸🇦 [ar](../../ar/docs/CLI-TOOLS.md) · 🇮🇳 [in](../../in/docs/CLI-TOOLS.md) · 🇹🇭 [th](../../th/docs/CLI-TOOLS.md) · 🇻🇳 [vi](../../vi/docs/CLI-TOOLS.md) · 🇮🇩 [id](../../id/docs/CLI-TOOLS.md) · 🇲🇾 [ms](../../ms/docs/CLI-TOOLS.md) · 🇳🇱 [nl](../../nl/docs/CLI-TOOLS.md) · 🇵🇱 [pl](../../pl/docs/CLI-TOOLS.md) · 🇸🇪 [sv](../../sv/docs/CLI-TOOLS.md) · 🇳🇴 [no](../../no/docs/CLI-TOOLS.md) · 🇩🇰 [da](../../da/docs/CLI-TOOLS.md) · 🇫🇮 [fi](../../fi/docs/CLI-TOOLS.md) · 🇵🇹 [pt](../../pt/docs/CLI-TOOLS.md) · 🇷🇴 [ro](../../ro/docs/CLI-TOOLS.md) · 🇭🇺 [hu](../../hu/docs/CLI-TOOLS.md) · 🇧🇬 [bg](../../bg/docs/CLI-TOOLS.md) · 🇸🇰 [sk](../../sk/docs/CLI-TOOLS.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/CLI-TOOLS.md) · 🇮🇱 [he](../../he/docs/CLI-TOOLS.md) · 🇵🇭 [phi](../../phi/docs/CLI-TOOLS.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/CLI-TOOLS.md) · 🇨🇿 [cs](../../cs/docs/CLI-TOOLS.md)
+
+---
+
+This guide explains how to install and configure all supported AI coding CLI tools
+to use **OmniRoute** as the unified backend, giving you centralized key management,
+cost tracking, model switching, and request logging across every tool.
+
+---
+
+## How It Works
+
+```
+Claude / Codex / OpenCode / Cline / KiloCode / Continue / Kiro / Cursor / Copilot
+ │
+ ▼ (all point to OmniRoute)
+ http://YOUR_SERVER:20128/v1
+ │
+ ▼ (OmniRoute routes to the right provider)
+ Anthropic / OpenAI / Gemini / DeepSeek / Groq / Mistral / ...
+```
+
+**Benefits:**
+
+- One API key to manage all tools
+- Cost tracking across all CLIs in the dashboard
+- Model switching without reconfiguring every tool
+- Works locally and on remote servers (VPS)
+
+---
+
+## Supported Tools (Dashboard Source of Truth)
+
+The dashboard cards in `/dashboard/cli-tools` are generated from `src/shared/constants/cliTools.ts`.
+Current list (v3.0.0-rc.16):
+
+| Tool | ID | Command | Setup Mode | Install Method |
+| ------------------ | ------------- | ---------- | ---------- | -------------- |
+| **Claude Code** | `claude` | `claude` | env | npm |
+| **OpenAI Codex** | `codex` | `codex` | custom | npm |
+| **Factory Droid** | `droid` | `droid` | custom | bundled/CLI |
+| **OpenClaw** | `openclaw` | `openclaw` | custom | bundled/CLI |
+| **Cursor** | `cursor` | app | guide | desktop app |
+| **Cline** | `cline` | `cline` | custom | npm |
+| **Kilo Code** | `kilo` | `kilocode` | custom | npm |
+| **Continue** | `continue` | extension | guide | VS Code |
+| **Antigravity** | `antigravity` | internal | mitm | OmniRoute |
+| **GitHub Copilot** | `copilot` | extension | custom | VS Code |
+| **OpenCode** | `opencode` | `opencode` | guide | npm |
+| **Kiro AI** | `kiro` | app/cli | mitm | desktop/CLI |
+
+### CLI fingerprint sync (Agents + Settings)
+
+`/dashboard/agents` and `Settings > CLI Fingerprint` use `src/shared/constants/cliCompatProviders.ts`.
+This keeps provider IDs aligned with CLI cards and legacy IDs.
+
+| CLI ID | Fingerprint Provider ID |
+| ---------------------------------------------------------------------------------------------------- | ----------------------- |
+| `kilo` | `kilocode` |
+| `copilot` | `github` |
+| `claude` / `codex` / `antigravity` / `kiro` / `cursor` / `cline` / `opencode` / `droid` / `openclaw` | same ID |
+
+Legacy IDs still accepted for compatibility: `copilot`, `kimi-coding`, `qwen`.
+
+---
+
+## Step 1 — Get an OmniRoute API Key
+
+1. Open the OmniRoute dashboard → **API Manager** (`/dashboard/api-manager`)
+2. Click **Create API Key**
+3. Give it a name (e.g. `cli-tools`) and select all permissions
+4. Copy the key — you'll need it for every CLI below
+
+> Your key looks like: `sk-xxxxxxxxxxxxxxxx-xxxxxxxxx`
+
+---
+
+## Step 2 — Install CLI Tools
+
+All npm-based tools require Node.js 18+:
+
+```bash
+# Claude Code (Anthropic)
+npm install -g @anthropic-ai/claude-code
+
+# OpenAI Codex
+npm install -g @openai/codex
+
+# OpenCode
+npm install -g opencode-ai
+
+# Cline
+npm install -g cline
+
+# KiloCode
+npm install -g kilocode
+
+# Kiro CLI (Amazon — requires curl + unzip)
+apt-get install -y unzip # on Debian/Ubuntu
+curl -fsSL https://cli.kiro.dev/install | bash
+export PATH="$HOME/.local/bin:$PATH" # add to ~/.bashrc
+```
+
+**Verify:**
+
+```bash
+claude --version # 2.x.x
+codex --version # 0.x.x
+opencode --version # x.x.x
+cline --version # 2.x.x
+kilocode --version # x.x.x (or: kilo --version)
+kiro-cli --version # 1.x.x
+```
+
+---
+
+## Step 3 — Set Global Environment Variables
+
+Add to `~/.bashrc` (or `~/.zshrc`), then run `source ~/.bashrc`:
+
+```bash
+# OmniRoute Universal Endpoint
+export OPENAI_BASE_URL="http://localhost:20128/v1"
+export OPENAI_API_KEY="sk-your-omniroute-key"
+export ANTHROPIC_BASE_URL="http://localhost:20128/v1"
+export ANTHROPIC_API_KEY="sk-your-omniroute-key"
+export GEMINI_BASE_URL="http://localhost:20128/v1"
+export GEMINI_API_KEY="sk-your-omniroute-key"
+```
+
+> For a **remote server** replace `localhost:20128` with the server IP or domain,
+> e.g. `http://192.168.0.15:20128`.
+
+---
+
+## Step 4 — Configure Each Tool
+
+### Claude Code
+
+```bash
+# Via CLI:
+claude config set --global api-base-url http://localhost:20128/v1
+
+# Or create ~/.claude/settings.json:
+mkdir -p ~/.claude && cat > ~/.claude/settings.json << EOF
+{
+ "apiBaseUrl": "http://localhost:20128/v1",
+ "apiKey": "sk-your-omniroute-key"
+}
+EOF
+```
+
+**Test:** `claude "say hello"`
+
+---
+
+### OpenAI Codex
+
+```bash
+mkdir -p ~/.codex && cat > ~/.codex/config.yaml << EOF
+model: auto
+apiKey: sk-your-omniroute-key
+apiBaseUrl: http://localhost:20128/v1
+EOF
+```
+
+**Test:** `codex "what is 2+2?"`
+
+---
+
+### OpenCode
+
+```bash
+mkdir -p ~/.config/opencode && cat > ~/.config/opencode/config.toml << EOF
+[provider.openai]
+base_url = "http://localhost:20128/v1"
+api_key = "sk-your-omniroute-key"
+EOF
+```
+
+**Test:** `opencode`
+
+---
+
+### Cline (CLI or VS Code)
+
+**CLI mode:**
+
+```bash
+mkdir -p ~/.cline/data && cat > ~/.cline/data/globalState.json << EOF
+{
+ "apiProvider": "openai",
+ "openAiBaseUrl": "http://localhost:20128/v1",
+ "openAiApiKey": "sk-your-omniroute-key"
+}
+EOF
+```
+
+**VS Code mode:**
+Cline extension settings → API Provider: `OpenAI Compatible` → Base URL: `http://localhost:20128/v1`
+
+Or use the OmniRoute dashboard → **CLI Tools → Cline → Apply Config**.
+
+---
+
+### KiloCode (CLI or VS Code)
+
+**CLI mode:**
+
+```bash
+kilocode --api-base http://localhost:20128/v1 --api-key sk-your-omniroute-key
+```
+
+**VS Code settings:**
+
+```json
+{
+ "kilo-code.openAiBaseUrl": "http://localhost:20128/v1",
+ "kilo-code.apiKey": "sk-your-omniroute-key"
+}
+```
+
+Or use the OmniRoute dashboard → **CLI Tools → KiloCode → Apply Config**.
+
+---
+
+### Continue (VS Code Extension)
+
+Edit `~/.continue/config.yaml`:
+
+```yaml
+models:
+ - name: OmniRoute
+ provider: openai
+ model: auto
+ apiBase: http://localhost:20128/v1
+ apiKey: sk-your-omniroute-key
+ default: true
+```
+
+Restart VS Code after editing.
+
+---
+
+### Kiro CLI (Amazon)
+
+```bash
+# Login to your AWS/Kiro account:
+kiro-cli login
+
+# The CLI uses its own auth — OmniRoute is not needed as backend for Kiro CLI itself.
+# Use kiro-cli alongside OmniRoute for other tools.
+kiro-cli status
+```
+
+---
+
+### Cursor (Desktop App)
+
+> **Note:** Cursor routes requests through its cloud. For OmniRoute integration,
+> enable **Cloud Endpoint** in OmniRoute Settings and use your public domain URL.
+
+Via GUI: **Settings → Models → OpenAI API Key**
+
+- Base URL: `https://your-domain.com/v1`
+- API Key: your OmniRoute key
+
+---
+
+## Dashboard Auto-Configuration
+
+The OmniRoute dashboard automates configuration for most tools:
+
+1. Go to `http://localhost:20128/dashboard/cli-tools`
+2. Expand any tool card
+3. Select your API key from the dropdown
+4. Click **Apply Config** (if tool is detected as installed)
+5. Or copy the generated config snippet manually
+
+---
+
+## Built-in Agents: Droid & OpenClaw
+
+**Droid** and **OpenClaw** are AI agents built directly into OmniRoute — no installation needed.
+They run as internal routes and use OmniRoute's model routing automatically.
+
+- Access: `http://localhost:20128/dashboard/agents`
+- Configure: same combos and providers as all other tools
+- No API key or CLI install required
+
+---
+
+## Available API Endpoints
+
+| Endpoint | Description | Use For |
+| -------------------------- | ----------------------------- | --------------------------- |
+| `/v1/chat/completions` | Standard chat (all providers) | All modern tools |
+| `/v1/responses` | Responses API (OpenAI format) | Codex, agentic workflows |
+| `/v1/completions` | Legacy text completions | Older tools using `prompt:` |
+| `/v1/embeddings` | Text embeddings | RAG, search |
+| `/v1/images/generations` | Image generation | DALL-E, Flux, etc. |
+| `/v1/audio/speech` | Text-to-speech | ElevenLabs, OpenAI TTS |
+| `/v1/audio/transcriptions` | Speech-to-text | Deepgram, AssemblyAI |
+
+---
+
+## Dépannage
+
+| Error | Cause | Fix |
+| ------------------------- | ----------------------- | ------------------------------------------ |
+| `Connection refused` | OmniRoute not running | `pm2 start omniroute` |
+| `401 Unauthorized` | Wrong API key | Check in `/dashboard/api-manager` |
+| `No combo configured` | No active routing combo | Set up in `/dashboard/combos` |
+| `invalid model` | Model not in catalog | Use `auto` or check `/dashboard/providers` |
+| CLI shows "not installed" | Binary not in PATH | Check `which ` |
+| `kiro-cli: not found` | Not in PATH | `export PATH="$HOME/.local/bin:$PATH"` |
+
+---
+
+## Quick Setup Script (One Command)
+
+```bash
+# Install all CLIs and configure for OmniRoute (replace with your key and server URL)
+OMNIROUTE_URL="http://localhost:20128/v1"
+OMNIROUTE_KEY="sk-your-omniroute-key"
+
+npm install -g @anthropic-ai/claude-code @openai/codex opencode-ai cline kilocode
+
+# Kiro CLI
+apt-get install -y unzip 2>/dev/null; curl -fsSL https://cli.kiro.dev/install | bash
+
+# Write configs
+mkdir -p ~/.claude ~/.codex ~/.config/opencode ~/.continue
+
+cat > ~/.claude/settings.json <<< "{\"apiBaseUrl\":\"$OMNIROUTE_URL\",\"apiKey\":\"$OMNIROUTE_KEY\"}"
+cat > ~/.codex/config.yaml <<< "model: auto\napiKey: $OMNIROUTE_KEY\napiBaseUrl: $OMNIROUTE_URL"
+cat >> ~/.bashrc << EOF
+export OPENAI_BASE_URL="$OMNIROUTE_URL"
+export OPENAI_API_KEY="$OMNIROUTE_KEY"
+export ANTHROPIC_BASE_URL="$OMNIROUTE_URL"
+export ANTHROPIC_API_KEY="$OMNIROUTE_KEY"
+EOF
+
+source ~/.bashrc
+echo "✅ All CLIs installed and configured for OmniRoute"
+```
diff --git a/docs/i18n/da/CODEBASE_DOCUMENTATION.md b/docs/i18n/fr/docs/CODEBASE_DOCUMENTATION.md
similarity index 91%
rename from docs/i18n/da/CODEBASE_DOCUMENTATION.md
rename to docs/i18n/fr/docs/CODEBASE_DOCUMENTATION.md
index e2d7950052..3801796702 100644
--- a/docs/i18n/da/CODEBASE_DOCUMENTATION.md
+++ b/docs/i18n/fr/docs/CODEBASE_DOCUMENTATION.md
@@ -1,11 +1,9 @@
-🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/CODEBASE_DOCUMENTATION.md) · 🇪🇸 [es](../es/CODEBASE_DOCUMENTATION.md) · 🇫🇷 [fr](../fr/CODEBASE_DOCUMENTATION.md) · 🇩🇪 [de](../de/CODEBASE_DOCUMENTATION.md) · 🇮🇹 [it](../it/CODEBASE_DOCUMENTATION.md) · 🇷🇺 [ru](../ru/CODEBASE_DOCUMENTATION.md) · 🇨🇳 [zh-CN](../zh-CN/CODEBASE_DOCUMENTATION.md) · 🇯🇵 [ja](../ja/CODEBASE_DOCUMENTATION.md) · 🇰🇷 [ko](../ko/CODEBASE_DOCUMENTATION.md) · 🇸🇦 [ar](../ar/CODEBASE_DOCUMENTATION.md) · 🇮🇳 [in](../in/CODEBASE_DOCUMENTATION.md) · 🇹🇭 [th](../th/CODEBASE_DOCUMENTATION.md) · 🇻🇳 [vi](../vi/CODEBASE_DOCUMENTATION.md) · 🇮🇩 [id](../id/CODEBASE_DOCUMENTATION.md) · 🇲🇾 [ms](../ms/CODEBASE_DOCUMENTATION.md) · 🇳🇱 [nl](../nl/CODEBASE_DOCUMENTATION.md) · 🇵🇱 [pl](../pl/CODEBASE_DOCUMENTATION.md) · 🇸🇪 [sv](../sv/CODEBASE_DOCUMENTATION.md) · 🇳🇴 [no](../no/CODEBASE_DOCUMENTATION.md) · 🇩🇰 [da](../da/CODEBASE_DOCUMENTATION.md) · 🇫🇮 [fi](../fi/CODEBASE_DOCUMENTATION.md) · 🇵🇹 [pt](../pt/CODEBASE_DOCUMENTATION.md) · 🇷🇴 [ro](../ro/CODEBASE_DOCUMENTATION.md) · 🇭🇺 [hu](../hu/CODEBASE_DOCUMENTATION.md) · 🇧🇬 [bg](../bg/CODEBASE_DOCUMENTATION.md) · 🇸🇰 [sk](../sk/CODEBASE_DOCUMENTATION.md) · 🇺🇦 [uk-UA](../uk-UA/CODEBASE_DOCUMENTATION.md) · 🇮🇱 [he](../he/CODEBASE_DOCUMENTATION.md) · 🇵🇭 [phi](../phi/CODEBASE_DOCUMENTATION.md)
+# omniroute — Codebase Documentation (Français)
+
+🌐 **Languages:** 🇺🇸 [English](../../../../docs/CODEBASE_DOCUMENTATION.md) · 🇪🇸 [es](../../es/docs/CODEBASE_DOCUMENTATION.md) · 🇫🇷 [fr](../../fr/docs/CODEBASE_DOCUMENTATION.md) · 🇩🇪 [de](../../de/docs/CODEBASE_DOCUMENTATION.md) · 🇮🇹 [it](../../it/docs/CODEBASE_DOCUMENTATION.md) · 🇷🇺 [ru](../../ru/docs/CODEBASE_DOCUMENTATION.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/CODEBASE_DOCUMENTATION.md) · 🇯🇵 [ja](../../ja/docs/CODEBASE_DOCUMENTATION.md) · 🇰🇷 [ko](../../ko/docs/CODEBASE_DOCUMENTATION.md) · 🇸🇦 [ar](../../ar/docs/CODEBASE_DOCUMENTATION.md) · 🇮🇳 [in](../../in/docs/CODEBASE_DOCUMENTATION.md) · 🇹🇭 [th](../../th/docs/CODEBASE_DOCUMENTATION.md) · 🇻🇳 [vi](../../vi/docs/CODEBASE_DOCUMENTATION.md) · 🇮🇩 [id](../../id/docs/CODEBASE_DOCUMENTATION.md) · 🇲🇾 [ms](../../ms/docs/CODEBASE_DOCUMENTATION.md) · 🇳🇱 [nl](../../nl/docs/CODEBASE_DOCUMENTATION.md) · 🇵🇱 [pl](../../pl/docs/CODEBASE_DOCUMENTATION.md) · 🇸🇪 [sv](../../sv/docs/CODEBASE_DOCUMENTATION.md) · 🇳🇴 [no](../../no/docs/CODEBASE_DOCUMENTATION.md) · 🇩🇰 [da](../../da/docs/CODEBASE_DOCUMENTATION.md) · 🇫🇮 [fi](../../fi/docs/CODEBASE_DOCUMENTATION.md) · 🇵🇹 [pt](../../pt/docs/CODEBASE_DOCUMENTATION.md) · 🇷🇴 [ro](../../ro/docs/CODEBASE_DOCUMENTATION.md) · 🇭🇺 [hu](../../hu/docs/CODEBASE_DOCUMENTATION.md) · 🇧🇬 [bg](../../bg/docs/CODEBASE_DOCUMENTATION.md) · 🇸🇰 [sk](../../sk/docs/CODEBASE_DOCUMENTATION.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/CODEBASE_DOCUMENTATION.md) · 🇮🇱 [he](../../he/docs/CODEBASE_DOCUMENTATION.md) · 🇵🇭 [phi](../../phi/docs/CODEBASE_DOCUMENTATION.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/CODEBASE_DOCUMENTATION.md) · 🇨🇿 [cs](../../cs/docs/CODEBASE_DOCUMENTATION.md)
---
-# omniroute — Codebase Documentation
-
-🌐 **Languages:** 🇺🇸 [English](CODEBASE_DOCUMENTATION.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/CODEBASE_DOCUMENTATION.md) | 🇪🇸 [Español](i18n/es/CODEBASE_DOCUMENTATION.md) | 🇫🇷 [Français](i18n/fr/CODEBASE_DOCUMENTATION.md) | 🇮🇹 [Italiano](i18n/it/CODEBASE_DOCUMENTATION.md) | 🇷🇺 [Русский](i18n/ru/CODEBASE_DOCUMENTATION.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/CODEBASE_DOCUMENTATION.md) | 🇩🇪 [Deutsch](i18n/de/CODEBASE_DOCUMENTATION.md) | 🇮🇳 [हिन्दी](i18n/in/CODEBASE_DOCUMENTATION.md) | 🇹🇭 [ไทย](i18n/th/CODEBASE_DOCUMENTATION.md) | 🇺🇦 [Українська](i18n/uk-UA/CODEBASE_DOCUMENTATION.md) | 🇸🇦 [العربية](i18n/ar/CODEBASE_DOCUMENTATION.md) | 🇯🇵 [日本語](i18n/ja/CODEBASE_DOCUMENTATION.md) | 🇻🇳 [Tiếng Việt](i18n/vi/CODEBASE_DOCUMENTATION.md) | 🇧🇬 [Български](i18n/bg/CODEBASE_DOCUMENTATION.md) | 🇩🇰 [Dansk](i18n/da/CODEBASE_DOCUMENTATION.md) | 🇫🇮 [Suomi](i18n/fi/CODEBASE_DOCUMENTATION.md) | 🇮🇱 [עברית](i18n/he/CODEBASE_DOCUMENTATION.md) | 🇭🇺 [Magyar](i18n/hu/CODEBASE_DOCUMENTATION.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/CODEBASE_DOCUMENTATION.md) | 🇰🇷 [한국어](i18n/ko/CODEBASE_DOCUMENTATION.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/CODEBASE_DOCUMENTATION.md) | 🇳🇱 [Nederlands](i18n/nl/CODEBASE_DOCUMENTATION.md) | 🇳🇴 [Norsk](i18n/no/CODEBASE_DOCUMENTATION.md) | 🇵🇹 [Português (Portugal)](i18n/pt/CODEBASE_DOCUMENTATION.md) | 🇷🇴 [Română](i18n/ro/CODEBASE_DOCUMENTATION.md) | 🇵🇱 [Polski](i18n/pl/CODEBASE_DOCUMENTATION.md) | 🇸🇰 [Slovenčina](i18n/sk/CODEBASE_DOCUMENTATION.md) | 🇸🇪 [Svenska](i18n/sv/CODEBASE_DOCUMENTATION.md) | 🇵🇭 [Filipino](i18n/phi/CODEBASE_DOCUMENTATION.md)
-
> A comprehensive, beginner-friendly guide to the **omniroute** multi-provider AI proxy router.
---
diff --git a/docs/i18n/fr/docs/COVERAGE_PLAN.md b/docs/i18n/fr/docs/COVERAGE_PLAN.md
new file mode 100644
index 0000000000..9367c5fb6d
--- /dev/null
+++ b/docs/i18n/fr/docs/COVERAGE_PLAN.md
@@ -0,0 +1,170 @@
+# Test Coverage Plan (Français)
+
+🌐 **Languages:** 🇺🇸 [English](../../../../docs/COVERAGE_PLAN.md) · 🇪🇸 [es](../../es/docs/COVERAGE_PLAN.md) · 🇫🇷 [fr](../../fr/docs/COVERAGE_PLAN.md) · 🇩🇪 [de](../../de/docs/COVERAGE_PLAN.md) · 🇮🇹 [it](../../it/docs/COVERAGE_PLAN.md) · 🇷🇺 [ru](../../ru/docs/COVERAGE_PLAN.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/COVERAGE_PLAN.md) · 🇯🇵 [ja](../../ja/docs/COVERAGE_PLAN.md) · 🇰🇷 [ko](../../ko/docs/COVERAGE_PLAN.md) · 🇸🇦 [ar](../../ar/docs/COVERAGE_PLAN.md) · 🇮🇳 [in](../../in/docs/COVERAGE_PLAN.md) · 🇹🇭 [th](../../th/docs/COVERAGE_PLAN.md) · 🇻🇳 [vi](../../vi/docs/COVERAGE_PLAN.md) · 🇮🇩 [id](../../id/docs/COVERAGE_PLAN.md) · 🇲🇾 [ms](../../ms/docs/COVERAGE_PLAN.md) · 🇳🇱 [nl](../../nl/docs/COVERAGE_PLAN.md) · 🇵🇱 [pl](../../pl/docs/COVERAGE_PLAN.md) · 🇸🇪 [sv](../../sv/docs/COVERAGE_PLAN.md) · 🇳🇴 [no](../../no/docs/COVERAGE_PLAN.md) · 🇩🇰 [da](../../da/docs/COVERAGE_PLAN.md) · 🇫🇮 [fi](../../fi/docs/COVERAGE_PLAN.md) · 🇵🇹 [pt](../../pt/docs/COVERAGE_PLAN.md) · 🇷🇴 [ro](../../ro/docs/COVERAGE_PLAN.md) · 🇭🇺 [hu](../../hu/docs/COVERAGE_PLAN.md) · 🇧🇬 [bg](../../bg/docs/COVERAGE_PLAN.md) · 🇸🇰 [sk](../../sk/docs/COVERAGE_PLAN.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/COVERAGE_PLAN.md) · 🇮🇱 [he](../../he/docs/COVERAGE_PLAN.md) · 🇵🇭 [phi](../../phi/docs/COVERAGE_PLAN.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/COVERAGE_PLAN.md) · 🇨🇿 [cs](../../cs/docs/COVERAGE_PLAN.md)
+
+---
+
+Last updated: 2026-03-28
+
+## Baseline
+
+There are multiple coverage numbers depending on how the report is computed. For planning, only one of them is useful.
+
+| Metric | Scope | Statements / Lines | Branches | Functions | Notes |
+| -------------------- | ----------------------------------------------------- | -----------------: | -------: | --------: | --------------------------------------------------- |
+| Legacy | Old `npm run test:coverage` | 79.42% | 75.15% | 67.94% | Inflated: counts test files and excludes `open-sse` |
+| Diagnostic | Source-only, excluding tests and excluding `open-sse` | 68.16% | 63.55% | 64.06% | Useful only to isolate `src/**` |
+| Recommended baseline | Source-only, excluding tests and including `open-sse` | 56.95% | 66.05% | 57.80% | This is the project-wide baseline to improve |
+
+The recommended baseline is the number to optimize against.
+
+## Rules
+
+- Coverage targets apply to source files, not to `tests/**`.
+- `open-sse/**` is part of the product and must remain in scope.
+- New code should not reduce coverage in touched areas.
+- Prefer testing behavior and branch outcomes over implementation details.
+- Prefer temp SQLite databases and small fixtures over broad mocks for `src/lib/db/**`.
+
+## Current command set
+
+- `npm run test:coverage`
+ - Main source coverage gate for the unit test suite
+ - Generates `text-summary`, `html`, `json-summary`, and `lcov`
+- `npm run coverage:report`
+ - Detailed file-by-file report from the latest run
+- `npm run test:coverage:legacy`
+ - Historical comparison only
+
+## Milestones
+
+| Phase | Target | Focus |
+| ------- | ---------------------: | ------------------------------------------------- |
+| Phase 1 | 60% statements / lines | Quick wins and low-risk utility coverage |
+| Phase 2 | 65% statements / lines | DB and route foundations |
+| Phase 3 | 70% statements / lines | Provider validation and usage analytics |
+| Phase 4 | 75% statements / lines | `open-sse` translators and helpers |
+| Phase 5 | 80% statements / lines | `open-sse` handlers and executor branches |
+| Phase 6 | 85% statements / lines | Harder edge cases, branch debt, regression suites |
+| Phase 7 | 90% statements / lines | Final sweep, gap closure, strict ratchet |
+
+Branches and functions should ratchet upward with each phase, but the primary hard target is statements / lines.
+
+## Priority hotspots
+
+These files or areas offer the best return for the next phases:
+
+1. `open-sse/handlers`
+ - `chatCore.ts` at 7.57%
+ - Overall directory at 29.07%
+2. `open-sse/translator/request`
+ - Overall directory at 36.39%
+ - Many translators are still near single-digit coverage
+3. `open-sse/translator/response`
+ - Overall directory at 8.07%
+4. `open-sse/executors`
+ - Overall directory at 36.62%
+5. `src/lib/db`
+ - `models.ts` at 20.66%
+ - `registeredKeys.ts` at 34.46%
+ - `modelComboMappings.ts` at 36.25%
+ - `settings.ts` at 46.40%
+ - `webhooks.ts` at 33.33%
+6. `src/lib/usage`
+ - `usageHistory.ts` at 21.12%
+ - `usageStats.ts` at 9.56%
+ - `costCalculator.ts` at 30.00%
+7. `src/lib/providers`
+ - `validation.ts` at 41.16%
+8. Low-risk utility and API files for early gains
+ - `src/shared/utils/upstreamError.ts`
+ - `src/shared/utils/apiAuth.ts`
+ - `src/lib/api/errorResponse.ts`
+ - `src/app/api/settings/require-login/route.ts`
+ - `src/app/api/providers/[id]/models/route.ts`
+
+## Execution checklist
+
+### Phase 1: 56.95% -> 60%
+
+- [x] Fix coverage metric so it reflects source code instead of test files
+- [x] Keep a legacy coverage script for comparison
+- [x] Record the baseline and hotspots in-repo
+- [ ] Add focused tests for low-risk utilities:
+ - `src/shared/utils/upstreamError.ts`
+ - `src/shared/utils/fetchTimeout.ts`
+ - `src/lib/api/errorResponse.ts`
+ - `src/shared/utils/apiAuth.ts`
+ - `src/lib/display/names.ts`
+- [ ] Add route tests for:
+ - `src/app/api/settings/require-login/route.ts`
+ - `src/app/api/providers/[id]/models/route.ts`
+
+### Phase 2: 60% -> 65%
+
+- [ ] Add DB-backed tests for:
+ - `src/lib/db/modelComboMappings.ts`
+ - `src/lib/db/settings.ts`
+ - `src/lib/db/registeredKeys.ts`
+- [ ] Cover branch behavior in:
+ - `src/lib/providers/validation.ts`
+ - `src/app/api/v1/embeddings/route.ts`
+ - `src/app/api/v1/moderations/route.ts`
+
+### Phase 3: 65% -> 70%
+
+- [ ] Add usage analytics tests for:
+ - `src/lib/usage/usageHistory.ts`
+ - `src/lib/usage/usageStats.ts`
+ - `src/lib/usage/costCalculator.ts`
+- [ ] Expand route coverage for proxy management and settings branches
+
+### Phase 4: 70% -> 75%
+
+- [ ] Cover translator helpers and central translation paths:
+ - `open-sse/translator/index.ts`
+ - `open-sse/translator/helpers/*`
+ - `open-sse/translator/request/*`
+ - `open-sse/translator/response/*`
+
+### Phase 5: 75% -> 80%
+
+- [ ] Add handler-level tests for:
+ - `open-sse/handlers/chatCore.ts`
+ - `open-sse/handlers/responsesHandler.js`
+ - `open-sse/handlers/imageGeneration.js`
+ - `open-sse/handlers/embeddings.js`
+- [ ] Add executor branch coverage for provider-specific auth, retries, and endpoint overrides
+
+### Phase 6: 80% -> 85%
+
+- [ ] Merge more edge-case suites into the main coverage path
+- [ ] Increase function coverage for DB modules with weak constructor/helper coverage
+- [ ] Close branch gaps in `settings.ts`, `registeredKeys.ts`, `validation.ts`, and translator helpers
+
+### Phase 7: 85% -> 90%
+
+- [ ] Treat the remaining low-coverage files as blockers
+- [ ] Add regression tests for every uncovered production bug fixed during the push to 90%
+- [ ] Raise the coverage gate in CI only after the local baseline is stable for at least two consecutive runs
+
+## Ratchet policy
+
+Update `npm run test:coverage` thresholds only after the project actually exceeds the next milestone with a comfortable buffer.
+
+Recommended ratchet sequence:
+
+1. 55/60/55
+2. 60/62/58
+3. 65/64/62
+4. 70/66/66
+5. 75/70/72
+6. 80/75/78
+7. 85/80/84
+8. 90/85/88
+
+Order is `statements-lines / branches / functions`.
+
+## Known gap
+
+The current coverage command measures the main Node unit suite and includes source reached from it, including `open-sse`. It does not yet merge Vitest coverage into a single unified report. That merge is worth doing later, but it is not a blocker for starting the 60% -> 80% climb.
diff --git a/docs/i18n/fr/docs/FEATURES.md b/docs/i18n/fr/docs/FEATURES.md
index ede8e2c315..d5e1ca59d6 100644
--- a/docs/i18n/fr/docs/FEATURES.md
+++ b/docs/i18n/fr/docs/FEATURES.md
@@ -1,6 +1,6 @@
# OmniRoute — Dashboard Features Gallery (Français)
-🌐 **Languages:** 🇺🇸 [English](../../../../docs/FEATURES.md) · 🇪🇸 [es](../../es/docs/FEATURES.md) · 🇫🇷 [fr](../../fr/docs/FEATURES.md) · 🇩🇪 [de](../../de/docs/FEATURES.md) · 🇮🇹 [it](../../it/docs/FEATURES.md) · 🇷🇺 [ru](../../ru/docs/FEATURES.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/FEATURES.md) · 🇯🇵 [ja](../../ja/docs/FEATURES.md) · 🇰🇷 [ko](../../ko/docs/FEATURES.md) · 🇸🇦 [ar](../../ar/docs/FEATURES.md) · 🇮🇳 [in](../../in/docs/FEATURES.md) · 🇹🇭 [th](../../th/docs/FEATURES.md) · 🇻🇳 [vi](../../vi/docs/FEATURES.md) · 🇮🇩 [id](../../id/docs/FEATURES.md) · 🇲🇾 [ms](../../ms/docs/FEATURES.md) · 🇳🇱 [nl](../../nl/docs/FEATURES.md) · 🇵🇱 [pl](../../pl/docs/FEATURES.md) · 🇸🇪 [sv](../../sv/docs/FEATURES.md) · 🇳🇴 [no](../../no/docs/FEATURES.md) · 🇩🇰 [da](../../da/docs/FEATURES.md) · 🇫🇮 [fi](../../fi/docs/FEATURES.md) · 🇵🇹 [pt](../../pt/docs/FEATURES.md) · 🇷🇴 [ro](../../ro/docs/FEATURES.md) · 🇭🇺 [hu](../../hu/docs/FEATURES.md) · 🇧🇬 [bg](../../bg/docs/FEATURES.md) · 🇸🇰 [sk](../../sk/docs/FEATURES.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/FEATURES.md) · 🇮🇱 [he](../../he/docs/FEATURES.md) · 🇵🇭 [phi](../../phi/docs/FEATURES.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/FEATURES.md)
+🌐 **Languages:** 🇺🇸 [English](../../../../docs/FEATURES.md) · 🇪🇸 [es](../../es/docs/FEATURES.md) · 🇫🇷 [fr](../../fr/docs/FEATURES.md) · 🇩🇪 [de](../../de/docs/FEATURES.md) · 🇮🇹 [it](../../it/docs/FEATURES.md) · 🇷🇺 [ru](../../ru/docs/FEATURES.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/FEATURES.md) · 🇯🇵 [ja](../../ja/docs/FEATURES.md) · 🇰🇷 [ko](../../ko/docs/FEATURES.md) · 🇸🇦 [ar](../../ar/docs/FEATURES.md) · 🇮🇳 [in](../../in/docs/FEATURES.md) · 🇹🇭 [th](../../th/docs/FEATURES.md) · 🇻🇳 [vi](../../vi/docs/FEATURES.md) · 🇮🇩 [id](../../id/docs/FEATURES.md) · 🇲🇾 [ms](../../ms/docs/FEATURES.md) · 🇳🇱 [nl](../../nl/docs/FEATURES.md) · 🇵🇱 [pl](../../pl/docs/FEATURES.md) · 🇸🇪 [sv](../../sv/docs/FEATURES.md) · 🇳🇴 [no](../../no/docs/FEATURES.md) · 🇩🇰 [da](../../da/docs/FEATURES.md) · 🇫🇮 [fi](../../fi/docs/FEATURES.md) · 🇵🇹 [pt](../../pt/docs/FEATURES.md) · 🇷🇴 [ro](../../ro/docs/FEATURES.md) · 🇭🇺 [hu](../../hu/docs/FEATURES.md) · 🇧🇬 [bg](../../bg/docs/FEATURES.md) · 🇸🇰 [sk](../../sk/docs/FEATURES.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/FEATURES.md) · 🇮🇱 [he](../../he/docs/FEATURES.md) · 🇵🇭 [phi](../../phi/docs/FEATURES.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/FEATURES.md) · 🇨🇿 [cs](../../cs/docs/FEATURES.md)
---
@@ -10,7 +10,7 @@ Visual guide to every section of the OmniRoute dashboard.
## 🔌 Providers
-Manage AI provider connections: OAuth providers (Claude Code, Codex, Gemini CLI), API key providers (Groq, DeepSeek, OpenRouter), and free providers (iFlow, Qwen, Kiro). Kiro accounts include credit balance tracking — remaining credits, total allowance, and renewal date visible in Dashboard → Usage.
+Manage AI provider connections: OAuth providers (Claude Code, Codex, Gemini CLI), API key providers (Groq, DeepSeek, OpenRouter), and free providers (Qoder, Qwen, Kiro). Kiro accounts include credit balance tracking — remaining credits, total allowance, and renewal date visible in Dashboard → Usage.

diff --git a/docs/i18n/fr/docs/MCP-SERVER.md b/docs/i18n/fr/docs/MCP-SERVER.md
new file mode 100644
index 0000000000..890f9830e8
--- /dev/null
+++ b/docs/i18n/fr/docs/MCP-SERVER.md
@@ -0,0 +1,87 @@
+# OmniRoute MCP Server Documentation (Français)
+
+🌐 **Languages:** 🇺🇸 [English](../../../../docs/MCP-SERVER.md) · 🇪🇸 [es](../../es/docs/MCP-SERVER.md) · 🇫🇷 [fr](../../fr/docs/MCP-SERVER.md) · 🇩🇪 [de](../../de/docs/MCP-SERVER.md) · 🇮🇹 [it](../../it/docs/MCP-SERVER.md) · 🇷🇺 [ru](../../ru/docs/MCP-SERVER.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/MCP-SERVER.md) · 🇯🇵 [ja](../../ja/docs/MCP-SERVER.md) · 🇰🇷 [ko](../../ko/docs/MCP-SERVER.md) · 🇸🇦 [ar](../../ar/docs/MCP-SERVER.md) · 🇮🇳 [in](../../in/docs/MCP-SERVER.md) · 🇹🇭 [th](../../th/docs/MCP-SERVER.md) · 🇻🇳 [vi](../../vi/docs/MCP-SERVER.md) · 🇮🇩 [id](../../id/docs/MCP-SERVER.md) · 🇲🇾 [ms](../../ms/docs/MCP-SERVER.md) · 🇳🇱 [nl](../../nl/docs/MCP-SERVER.md) · 🇵🇱 [pl](../../pl/docs/MCP-SERVER.md) · 🇸🇪 [sv](../../sv/docs/MCP-SERVER.md) · 🇳🇴 [no](../../no/docs/MCP-SERVER.md) · 🇩🇰 [da](../../da/docs/MCP-SERVER.md) · 🇫🇮 [fi](../../fi/docs/MCP-SERVER.md) · 🇵🇹 [pt](../../pt/docs/MCP-SERVER.md) · 🇷🇴 [ro](../../ro/docs/MCP-SERVER.md) · 🇭🇺 [hu](../../hu/docs/MCP-SERVER.md) · 🇧🇬 [bg](../../bg/docs/MCP-SERVER.md) · 🇸🇰 [sk](../../sk/docs/MCP-SERVER.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/MCP-SERVER.md) · 🇮🇱 [he](../../he/docs/MCP-SERVER.md) · 🇵🇭 [phi](../../phi/docs/MCP-SERVER.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/MCP-SERVER.md) · 🇨🇿 [cs](../../cs/docs/MCP-SERVER.md)
+
+---
+
+> Model Context Protocol server with 16 intelligent tools
+
+## Installer
+
+OmniRoute MCP is built-in. Start it with:
+
+```bash
+omniroute --mcp
+```
+
+Or via the open-sse transport:
+
+```bash
+# HTTP streamable transport (port 20130)
+omniroute --dev # MCP auto-starts on /mcp endpoint
+```
+
+## IDE Configuration
+
+See [IDE Configs](integrations/ide-configs.md) for Antigravity, Cursor, Copilot, and Claude Desktop setup.
+
+---
+
+## Essential Tools (8)
+
+| Tool | Description |
+| :------------------------------ | :--------------------------------------- |
+| `omniroute_get_health` | Gateway health, circuit breakers, uptime |
+| `omniroute_list_combos` | All configured combos with models |
+| `omniroute_get_combo_metrics` | Performance metrics for a specific combo |
+| `omniroute_switch_combo` | Switch active combo by ID/name |
+| `omniroute_check_quota` | Quota status per provider or all |
+| `omniroute_route_request` | Send a chat completion through OmniRoute |
+| `omniroute_cost_report` | Cost analytics for a time period |
+| `omniroute_list_models_catalog` | Full model catalog with capabilities |
+
+## Advanced Tools (8)
+
+| Tool | Description |
+| :--------------------------------- | :---------------------------------------------------------- |
+| `omniroute_simulate_route` | Dry-run routing simulation with fallback tree |
+| `omniroute_set_budget_guard` | Session budget with degrade/block/alert actions |
+| `omniroute_set_resilience_profile` | Apply conservative/balanced/aggressive preset |
+| `omniroute_test_combo` | Live-test all models in a combo via a real upstream request |
+| `omniroute_get_provider_metrics` | Detailed metrics for one provider |
+| `omniroute_best_combo_for_task` | Task-fitness recommendation with alternatives |
+| `omniroute_explain_route` | Explain a past routing decision |
+| `omniroute_get_session_snapshot` | Full session state: costs, tokens, errors |
+
+## Authentication
+
+MCP tools are authenticated via API key scopes. Each tool requires specific scopes:
+
+| Scope | Tools |
+| :------------- | :----------------------------------------------- |
+| `read:health` | get_health, get_provider_metrics |
+| `read:combos` | list_combos, get_combo_metrics |
+| `write:combos` | switch_combo |
+| `read:quota` | check_quota |
+| `write:route` | route_request, simulate_route, test_combo |
+| `read:usage` | cost_report, get_session_snapshot, explain_route |
+| `write:config` | set_budget_guard, set_resilience_profile |
+| `read:models` | list_models_catalog, best_combo_for_task |
+
+## Audit Logging
+
+Every tool call is logged to `mcp_tool_audit` with:
+
+- Tool name, arguments, result
+- Duration (ms), success/failure
+- API key hash, timestamp
+
+## Files
+
+| File | Purpose |
+| :------------------------------------------- | :------------------------------------------ |
+| `open-sse/mcp-server/server.ts` | MCP server creation + 16 tool registrations |
+| `open-sse/mcp-server/transport.ts` | Stdio + HTTP transport |
+| `open-sse/mcp-server/auth.ts` | API key + scope validation |
+| `open-sse/mcp-server/audit.ts` | Tool call audit logging |
+| `open-sse/mcp-server/tools/advancedTools.ts` | 8 advanced tool handlers |
diff --git a/docs/i18n/fr/docs/RELEASE_CHECKLIST.md b/docs/i18n/fr/docs/RELEASE_CHECKLIST.md
new file mode 100644
index 0000000000..e75f6294a8
--- /dev/null
+++ b/docs/i18n/fr/docs/RELEASE_CHECKLIST.md
@@ -0,0 +1,37 @@
+# Release Checklist (Français)
+
+🌐 **Languages:** 🇺🇸 [English](../../../../docs/RELEASE_CHECKLIST.md) · 🇪🇸 [es](../../es/docs/RELEASE_CHECKLIST.md) · 🇫🇷 [fr](../../fr/docs/RELEASE_CHECKLIST.md) · 🇩🇪 [de](../../de/docs/RELEASE_CHECKLIST.md) · 🇮🇹 [it](../../it/docs/RELEASE_CHECKLIST.md) · 🇷🇺 [ru](../../ru/docs/RELEASE_CHECKLIST.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/RELEASE_CHECKLIST.md) · 🇯🇵 [ja](../../ja/docs/RELEASE_CHECKLIST.md) · 🇰🇷 [ko](../../ko/docs/RELEASE_CHECKLIST.md) · 🇸🇦 [ar](../../ar/docs/RELEASE_CHECKLIST.md) · 🇮🇳 [in](../../in/docs/RELEASE_CHECKLIST.md) · 🇹🇭 [th](../../th/docs/RELEASE_CHECKLIST.md) · 🇻🇳 [vi](../../vi/docs/RELEASE_CHECKLIST.md) · 🇮🇩 [id](../../id/docs/RELEASE_CHECKLIST.md) · 🇲🇾 [ms](../../ms/docs/RELEASE_CHECKLIST.md) · 🇳🇱 [nl](../../nl/docs/RELEASE_CHECKLIST.md) · 🇵🇱 [pl](../../pl/docs/RELEASE_CHECKLIST.md) · 🇸🇪 [sv](../../sv/docs/RELEASE_CHECKLIST.md) · 🇳🇴 [no](../../no/docs/RELEASE_CHECKLIST.md) · 🇩🇰 [da](../../da/docs/RELEASE_CHECKLIST.md) · 🇫🇮 [fi](../../fi/docs/RELEASE_CHECKLIST.md) · 🇵🇹 [pt](../../pt/docs/RELEASE_CHECKLIST.md) · 🇷🇴 [ro](../../ro/docs/RELEASE_CHECKLIST.md) · 🇭🇺 [hu](../../hu/docs/RELEASE_CHECKLIST.md) · 🇧🇬 [bg](../../bg/docs/RELEASE_CHECKLIST.md) · 🇸🇰 [sk](../../sk/docs/RELEASE_CHECKLIST.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/RELEASE_CHECKLIST.md) · 🇮🇱 [he](../../he/docs/RELEASE_CHECKLIST.md) · 🇵🇭 [phi](../../phi/docs/RELEASE_CHECKLIST.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/RELEASE_CHECKLIST.md) · 🇨🇿 [cs](../../cs/docs/RELEASE_CHECKLIST.md)
+
+---
+
+Use this checklist before tagging or publishing a new OmniRoute release.
+
+## Version and Changelog
+
+1. Bump `package.json` version (`x.y.z`) in the release branch.
+2. Move release notes from `## [Unreleased]` in `CHANGELOG.md` to a dated section:
+ - `## [x.y.z] — YYYY-MM-DD`
+3. Keep `## [Unreleased]` as the first changelog section for upcoming work.
+4. Ensure the latest semver section in `CHANGELOG.md` equals `package.json` version.
+
+## API Docs
+
+1. Update `docs/openapi.yaml`:
+ - `info.version` must equal `package.json` version.
+2. Validate endpoint examples if API contracts changed.
+
+## Runtime Docs
+
+1. Review `docs/ARCHITECTURE.md` for storage/runtime drift.
+2. Review `docs/TROUBLESHOOTING.md` for env var and operational drift.
+3. Update localized docs if source docs changed significantly.
+
+## Automated Check
+
+Run the sync guard locally before opening PR:
+
+```bash
+npm run check:docs-sync
+```
+
+CI also runs this check in `.github/workflows/ci.yml` (lint job).
diff --git a/docs/i18n/fr/docs/TROUBLESHOOTING.md b/docs/i18n/fr/docs/TROUBLESHOOTING.md
new file mode 100644
index 0000000000..aad399143b
--- /dev/null
+++ b/docs/i18n/fr/docs/TROUBLESHOOTING.md
@@ -0,0 +1,256 @@
+# Troubleshooting (Français)
+
+🌐 **Languages:** 🇺🇸 [English](../../../../docs/TROUBLESHOOTING.md) · 🇪🇸 [es](../../es/docs/TROUBLESHOOTING.md) · 🇫🇷 [fr](../../fr/docs/TROUBLESHOOTING.md) · 🇩🇪 [de](../../de/docs/TROUBLESHOOTING.md) · 🇮🇹 [it](../../it/docs/TROUBLESHOOTING.md) · 🇷🇺 [ru](../../ru/docs/TROUBLESHOOTING.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/TROUBLESHOOTING.md) · 🇯🇵 [ja](../../ja/docs/TROUBLESHOOTING.md) · 🇰🇷 [ko](../../ko/docs/TROUBLESHOOTING.md) · 🇸🇦 [ar](../../ar/docs/TROUBLESHOOTING.md) · 🇮🇳 [in](../../in/docs/TROUBLESHOOTING.md) · 🇹🇭 [th](../../th/docs/TROUBLESHOOTING.md) · 🇻🇳 [vi](../../vi/docs/TROUBLESHOOTING.md) · 🇮🇩 [id](../../id/docs/TROUBLESHOOTING.md) · 🇲🇾 [ms](../../ms/docs/TROUBLESHOOTING.md) · 🇳🇱 [nl](../../nl/docs/TROUBLESHOOTING.md) · 🇵🇱 [pl](../../pl/docs/TROUBLESHOOTING.md) · 🇸🇪 [sv](../../sv/docs/TROUBLESHOOTING.md) · 🇳🇴 [no](../../no/docs/TROUBLESHOOTING.md) · 🇩🇰 [da](../../da/docs/TROUBLESHOOTING.md) · 🇫🇮 [fi](../../fi/docs/TROUBLESHOOTING.md) · 🇵🇹 [pt](../../pt/docs/TROUBLESHOOTING.md) · 🇷🇴 [ro](../../ro/docs/TROUBLESHOOTING.md) · 🇭🇺 [hu](../../hu/docs/TROUBLESHOOTING.md) · 🇧🇬 [bg](../../bg/docs/TROUBLESHOOTING.md) · 🇸🇰 [sk](../../sk/docs/TROUBLESHOOTING.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/TROUBLESHOOTING.md) · 🇮🇱 [he](../../he/docs/TROUBLESHOOTING.md) · 🇵🇭 [phi](../../phi/docs/TROUBLESHOOTING.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/TROUBLESHOOTING.md) · 🇨🇿 [cs](../../cs/docs/TROUBLESHOOTING.md)
+
+---
+
+Common problems and solutions for OmniRoute.
+
+---
+
+## Quick Fixes
+
+| Problem | Solution |
+| ----------------------------- | ------------------------------------------------------------------ |
+| First login not working | Set `INITIAL_PASSWORD` in `.env` (no hardcoded default) |
+| Dashboard opens on wrong port | Set `PORT=20128` and `NEXT_PUBLIC_BASE_URL=http://localhost:20128` |
+| No request logs under `logs/` | Set `ENABLE_REQUEST_LOGS=true` |
+| EACCES: permission denied | Set `DATA_DIR=/path/to/writable/dir` to override `~/.omniroute` |
+| Routing strategy not saving | Update to v1.4.11+ (Zod schema fix for settings persistence) |
+
+---
+
+## Provider Issues
+
+### "Language model did not provide messages"
+
+**Cause:** Provider quota exhausted.
+
+**Fix:**
+
+1. Check dashboard quota tracker
+2. Use a combo with fallback tiers
+3. Switch to cheaper/free tier
+
+### Rate Limiting
+
+**Cause:** Subscription quota exhausted.
+
+**Fix:**
+
+- Add fallback: `cc/claude-opus-4-6 → glm/glm-4.7 → if/kimi-k2-thinking`
+- Use GLM/MiniMax as cheap backup
+
+### OAuth Token Expired
+
+OmniRoute auto-refreshes tokens. If issues persist:
+
+1. Dashboard → Provider → Reconnect
+2. Delete and re-add the provider connection
+
+---
+
+## Cloud Issues
+
+### Cloud Sync Errors
+
+1. Verify `BASE_URL` points to your running instance (e.g., `http://localhost:20128`)
+2. Verify `CLOUD_URL` points to your cloud endpoint (e.g., `https://omniroute.dev`)
+3. Keep `NEXT_PUBLIC_*` values aligned with server-side values
+
+### Cloud `stream=false` Returns 500
+
+**Symptom:** `Unexpected token 'd'...` on cloud endpoint for non-streaming calls.
+
+**Cause:** Upstream returns SSE payload while client expects JSON.
+
+**Workaround:** Use `stream=true` for cloud direct calls. Local runtime includes SSE→JSON fallback.
+
+### Cloud Says Connected but "Invalid API key"
+
+1. Create a fresh key from local dashboard (`/api/keys`)
+2. Run cloud sync: Enable Cloud → Sync Now
+3. Old/non-synced keys can still return `401` on cloud
+
+---
+
+## Docker Issues
+
+### CLI Tool Shows Not Installed
+
+1. Check runtime fields: `curl http://localhost:20128/api/cli-tools/runtime/codex | jq`
+2. For portable mode: use image target `runner-cli` (bundled CLIs)
+3. For host mount mode: set `CLI_EXTRA_PATHS` and mount host bin directory as read-only
+4. If `installed=true` and `runnable=false`: binary was found but failed healthcheck
+
+### Quick Runtime Validation
+
+```bash
+curl -s http://localhost:20128/api/cli-tools/codex-settings | jq '{installed,runnable,commandPath,runtimeMode,reason}'
+curl -s http://localhost:20128/api/cli-tools/claude-settings | jq '{installed,runnable,commandPath,runtimeMode,reason}'
+curl -s http://localhost:20128/api/cli-tools/openclaw-settings | jq '{installed,runnable,commandPath,runtimeMode,reason}'
+```
+
+---
+
+## Cost Issues
+
+### High Costs
+
+1. Check usage stats in Dashboard → Usage
+2. Switch primary model to GLM/MiniMax
+3. Use free tier (Gemini CLI, Qoder) for non-critical tasks
+4. Set cost budgets per API key: Dashboard → API Keys → Budget
+
+---
+
+## Debugging
+
+### Enable Request Logs
+
+Set `ENABLE_REQUEST_LOGS=true` in your `.env` file. Logs appear under `logs/` directory.
+
+### Check Provider Health
+
+```bash
+# Health dashboard
+http://localhost:20128/dashboard/health
+
+# API health check
+curl http://localhost:20128/api/monitoring/health
+```
+
+### Runtime Storage
+
+- Main state: `${DATA_DIR}/storage.sqlite` (providers, combos, aliases, keys, settings)
+- Usage: SQLite tables in `storage.sqlite` (`usage_history`, `call_logs`, `proxy_logs`) + optional `${DATA_DIR}/log.txt` and `${DATA_DIR}/call_logs/`
+- Request logs: `/logs/...` (when `ENABLE_REQUEST_LOGS=true`)
+
+---
+
+## Circuit Breaker Issues
+
+### Provider stuck in OPEN state
+
+When a provider's circuit breaker is OPEN, requests are blocked until the cooldown expires.
+
+**Fix:**
+
+1. Go to **Dashboard → Settings → Resilience**
+2. Check the circuit breaker card for the affected provider
+3. Click **Reset All** to clear all breakers, or wait for the cooldown to expire
+4. Verify the provider is actually available before resetting
+
+### Provider keeps tripping the circuit breaker
+
+If a provider repeatedly enters OPEN state:
+
+1. Check **Dashboard → Health → Provider Health** for the failure pattern
+2. Go to **Settings → Resilience → Provider Profiles** and increase the failure threshold
+3. Check if the provider has changed API limits or requires re-authentication
+4. Review latency telemetry — high latency may cause timeout-based failures
+
+---
+
+## Audio Transcription Issues
+
+### "Unsupported model" error
+
+- Ensure you're using the correct prefix: `deepgram/nova-3` or `assemblyai/best`
+- Verify the provider is connected in **Dashboard → Providers**
+
+### Transcription returns empty or fails
+
+- Check supported audio formats: `mp3`, `wav`, `m4a`, `flac`, `ogg`, `webm`
+- Verify file size is within provider limits (typically < 25MB)
+- Check provider API key validity in the provider card
+
+---
+
+## Translator Debugging
+
+Use **Dashboard → Translator** to debug format translation issues:
+
+| Mode | When to Use |
+| ---------------- | -------------------------------------------------------------------------------------------- |
+| **Playground** | Compare input/output formats side by side — paste a failing request to see how it translates |
+| **Chat Tester** | Send live messages and inspect the full request/response payload including headers |
+| **Test Bench** | Run batch tests across format combinations to find which translations are broken |
+| **Live Monitor** | Watch real-time request flow to catch intermittent translation issues |
+
+### Common format issues
+
+- **Thinking tags not appearing** — Check if the target provider supports thinking and the thinking budget setting
+- **Tool calls dropping** — Some format translations may strip unsupported fields; verify in Playground mode
+- **System prompt missing** — Claude and Gemini handle system prompts differently; check translation output
+- **SDK returns raw string instead of object** — Fixed in v1.1.0: response sanitizer now strips non-standard fields (`x_groq`, `usage_breakdown`, etc.) that cause OpenAI SDK Pydantic validation failures
+- **GLM/ERNIE rejects `system` role** — Fixed in v1.1.0: role normalizer automatically merges system messages into user messages for incompatible models
+- **`developer` role not recognized** — Fixed in v1.1.0: automatically converted to `system` for non-OpenAI providers
+- **`json_schema` not working with Gemini** — Fixed in v1.1.0: `response_format` is now converted to Gemini's `responseMimeType` + `responseSchema`
+
+---
+
+## Resilience Settings
+
+### Auto rate-limit not triggering
+
+- Auto rate-limit only applies to API key providers (not OAuth/subscription)
+- Verify **Settings → Resilience → Provider Profiles** has auto-rate-limit enabled
+- Check if the provider returns `429` status codes or `Retry-After` headers
+
+### Tuning exponential backoff
+
+Provider profiles support these settings:
+
+- **Base delay** — Initial wait time after first failure (default: 1s)
+- **Max delay** — Maximum wait time cap (default: 30s)
+- **Multiplier** — How much to increase delay per consecutive failure (default: 2x)
+
+### Anti-thundering herd
+
+When many concurrent requests hit a rate-limited provider, OmniRoute uses mutex + auto rate-limiting to serialize requests and prevent cascading failures. This is automatic for API key providers.
+
+---
+
+## Optional RAG / LLM failure taxonomy (16 problems)
+
+Some OmniRoute users place the gateway in front of RAG or agent stacks. In those setups it is common to see a strange pattern: OmniRoute looks healthy (providers up, routing profiles ok, no rate limit alerts) but the final answer is still wrong.
+
+In practice these incidents usually come from the downstream RAG pipeline, not from the gateway itself.
+
+If you want a shared vocabulary to describe those failures you can use the WFGY ProblemMap, an external MIT license text resource that defines sixteen recurring RAG / LLM failure patterns. At a high level it covers:
+
+- retrieval drift and broken context boundaries
+- empty or stale indexes and vector stores
+- embedding versus semantic mismatch
+- prompt assembly and context window issues
+- logic collapse and overconfident answers
+- long chain and agent coordination failures
+- multi agent memory and role drift
+- deployment and bootstrap ordering problems
+
+The idea is simple:
+
+1. When you investigate a bad response, capture:
+ - user task and request
+ - route or provider combo in OmniRoute
+ - any RAG context used downstream (retrieved documents, tool calls, etc)
+2. Map the incident to one or two WFGY ProblemMap numbers (`No.1` … `No.16`).
+3. Store the number in your own dashboard, runbook, or incident tracker next to the OmniRoute logs.
+4. Use the corresponding WFGY page to decide whether you need to change your RAG stack, retriever, or routing strategy.
+
+Full text and concrete recipes live here (MIT license, text only):
+
+[WFGY ProblemMap README](https://github.com/onestardao/WFGY/blob/main/ProblemMap/README.md)
+
+You can ignore this section if you do not run RAG or agent pipelines behind OmniRoute.
+
+---
+
+## Still Stuck?
+
+- **GitHub Issues**: [github.com/diegosouzapw/OmniRoute/issues](https://github.com/diegosouzapw/OmniRoute/issues)
+- **Architecture**: See [`docs/ARCHITECTURE.md`](ARCHITECTURE.md) for internal details
+- **API Reference**: See [`docs/API_REFERENCE.md`](API_REFERENCE.md) for all endpoints
+- **Health Dashboard**: Check **Dashboard → Health** for real-time system status
+- **Translator**: Use **Dashboard → Translator** to debug format issues
diff --git a/docs/i18n/fr/USER_GUIDE.md b/docs/i18n/fr/docs/USER_GUIDE.md
similarity index 82%
rename from docs/i18n/fr/USER_GUIDE.md
rename to docs/i18n/fr/docs/USER_GUIDE.md
index a2066296e3..653c9a9853 100644
--- a/docs/i18n/fr/USER_GUIDE.md
+++ b/docs/i18n/fr/docs/USER_GUIDE.md
@@ -1,8 +1,6 @@
# User Guide (Français)
-🌐 **Languages:** 🇺🇸 [English](../../USER_GUIDE.md) · 🇧🇷 [pt-BR](../pt-BR/USER_GUIDE.md) · 🇪🇸 [es](../es/USER_GUIDE.md) · 🇫🇷 [fr](../fr/USER_GUIDE.md) · 🇩🇪 [de](../de/USER_GUIDE.md) · 🇮🇹 [it](../it/USER_GUIDE.md) · 🇷🇺 [ru](../ru/USER_GUIDE.md) · 🇨🇳 [zh-CN](../zh-CN/USER_GUIDE.md) · 🇯🇵 [ja](../ja/USER_GUIDE.md) · 🇰🇷 [ko](../ko/USER_GUIDE.md) · 🇸🇦 [ar](../ar/USER_GUIDE.md) · 🇮🇳 [in](../in/USER_GUIDE.md) · 🇹🇭 [th](../th/USER_GUIDE.md) · 🇻🇳 [vi](../vi/USER_GUIDE.md) · 🇮🇩 [id](../id/USER_GUIDE.md) · 🇲🇾 [ms](../ms/USER_GUIDE.md) · 🇳🇱 [nl](../nl/USER_GUIDE.md) · 🇵🇱 [pl](../pl/USER_GUIDE.md) · 🇸🇪 [sv](../sv/USER_GUIDE.md) · 🇳🇴 [no](../no/USER_GUIDE.md) · 🇩🇰 [da](../da/USER_GUIDE.md) · 🇫🇮 [fi](../fi/USER_GUIDE.md) · 🇵🇹 [pt](../pt/USER_GUIDE.md) · 🇷🇴 [ro](../ro/USER_GUIDE.md) · 🇭🇺 [hu](../hu/USER_GUIDE.md) · 🇧🇬 [bg](../bg/USER_GUIDE.md) · 🇸🇰 [sk](../sk/USER_GUIDE.md) · 🇺🇦 [uk-UA](../uk-UA/USER_GUIDE.md) · 🇮🇱 [he](../he/USER_GUIDE.md) · 🇵🇭 [phi](../phi/USER_GUIDE.md)
-
-> 🇺🇸 [English](../../USER_GUIDE.md)
+🌐 **Languages:** 🇺🇸 [English](../../../../docs/USER_GUIDE.md) · 🇪🇸 [es](../../es/docs/USER_GUIDE.md) · 🇫🇷 [fr](../../fr/docs/USER_GUIDE.md) · 🇩🇪 [de](../../de/docs/USER_GUIDE.md) · 🇮🇹 [it](../../it/docs/USER_GUIDE.md) · 🇷🇺 [ru](../../ru/docs/USER_GUIDE.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/USER_GUIDE.md) · 🇯🇵 [ja](../../ja/docs/USER_GUIDE.md) · 🇰🇷 [ko](../../ko/docs/USER_GUIDE.md) · 🇸🇦 [ar](../../ar/docs/USER_GUIDE.md) · 🇮🇳 [in](../../in/docs/USER_GUIDE.md) · 🇹🇭 [th](../../th/docs/USER_GUIDE.md) · 🇻🇳 [vi](../../vi/docs/USER_GUIDE.md) · 🇮🇩 [id](../../id/docs/USER_GUIDE.md) · 🇲🇾 [ms](../../ms/docs/USER_GUIDE.md) · 🇳🇱 [nl](../../nl/docs/USER_GUIDE.md) · 🇵🇱 [pl](../../pl/docs/USER_GUIDE.md) · 🇸🇪 [sv](../../sv/docs/USER_GUIDE.md) · 🇳🇴 [no](../../no/docs/USER_GUIDE.md) · 🇩🇰 [da](../../da/docs/USER_GUIDE.md) · 🇫🇮 [fi](../../fi/docs/USER_GUIDE.md) · 🇵🇹 [pt](../../pt/docs/USER_GUIDE.md) · 🇷🇴 [ro](../../ro/docs/USER_GUIDE.md) · 🇭🇺 [hu](../../hu/docs/USER_GUIDE.md) · 🇧🇬 [bg](../../bg/docs/USER_GUIDE.md) · 🇸🇰 [sk](../../sk/docs/USER_GUIDE.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/USER_GUIDE.md) · 🇮🇱 [he](../../he/docs/USER_GUIDE.md) · 🇵🇭 [phi](../../phi/docs/USER_GUIDE.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/USER_GUIDE.md) · 🇨🇿 [cs](../../cs/docs/USER_GUIDE.md)
---
@@ -320,7 +318,7 @@ Model: cc/claude-opus-4-6
---
-## 🚀 Deployment
+## Déploiement
### Global npm install (Recommended)
@@ -511,23 +509,26 @@ post_install() {
### Environment Variables
-| Variable | Default | Description |
-| ------------------------- | ------------------------------------ | ------------------------------------------------------- |
-| `JWT_SECRET` | `omniroute-default-secret-change-me` | JWT signing secret (**change in production**) |
-| `INITIAL_PASSWORD` | `123456` | First login password |
-| `DATA_DIR` | `~/.omniroute` | Data directory (db, usage, logs) |
-| `PORT` | framework default | Service port (`20128` in examples) |
-| `HOSTNAME` | framework default | Bind host (Docker defaults to `0.0.0.0`) |
-| `NODE_ENV` | runtime default | Set `production` for deploy |
-| `BASE_URL` | `http://localhost:20128` | Server-side internal base URL |
-| `CLOUD_URL` | `https://omniroute.dev` | Cloud sync endpoint base URL |
-| `API_KEY_SECRET` | `endpoint-proxy-api-key-secret` | HMAC secret for generated API keys |
-| `REQUIRE_API_KEY` | `false` | Enforce Bearer API key on `/v1/*` |
-| `ENABLE_REQUEST_LOGS` | `false` | Enables request/response logs |
-| `AUTH_COOKIE_SECURE` | `false` | Force `Secure` auth cookie (behind HTTPS reverse proxy) |
-| `OMNIROUTE_MEMORY_MB` | `512` | Node.js heap limit in MB |
-| `PROMPT_CACHE_MAX_SIZE` | `50` | Max prompt cache entries |
-| `SEMANTIC_CACHE_MAX_SIZE` | `100` | Max semantic cache entries |
+| Variable | Default | Description |
+| ---------------------------- | ------------------------------------ | ------------------------------------------------------------------------------------------ |
+| `JWT_SECRET` | `omniroute-default-secret-change-me` | JWT signing secret (**change in production**) |
+| `INITIAL_PASSWORD` | `123456` | First login password |
+| `DATA_DIR` | `~/.omniroute` | Data directory (db, usage, logs) |
+| `PORT` | framework default | Service port (`20128` in examples) |
+| `HOSTNAME` | framework default | Bind host (Docker defaults to `0.0.0.0`) |
+| `NODE_ENV` | runtime default | Set `production` for deploy |
+| `BASE_URL` | `http://localhost:20128` | Server-side internal base URL |
+| `CLOUD_URL` | `https://omniroute.dev` | Cloud sync endpoint base URL |
+| `API_KEY_SECRET` | `endpoint-proxy-api-key-secret` | HMAC secret for generated API keys |
+| `REQUIRE_API_KEY` | `false` | Enforce Bearer API key on `/v1/*` |
+| `ALLOW_API_KEY_REVEAL` | `false` | Allow Api Manager to copy full API keys on demand |
+| `DISABLE_SQLITE_AUTO_BACKUP` | `false` | Disable automatic SQLite snapshots before writes/import/restore; manual backups still work |
+| `ENABLE_REQUEST_LOGS` | `false` | Enables request/response logs |
+| `AUTH_COOKIE_SECURE` | `false` | Force `Secure` auth cookie (behind HTTPS reverse proxy) |
+| `CLOUDFLARED_BIN` | unset | Use an existing `cloudflared` binary instead of managed download |
+| `OMNIROUTE_MEMORY_MB` | `512` | Node.js heap limit in MB |
+| `PROMPT_CACHE_MAX_SIZE` | `50` | Max prompt cache entries |
+| `SEMANTIC_CACHE_MAX_SIZE` | `100` | Max semantic cache entries |
For the full environment variable reference, see the [README](../README.md).
@@ -598,6 +599,11 @@ curl -X POST http://localhost:20128/api/provider-models \
Or use Dashboard: **Providers → [Provider] → Custom Models**.
+Notes:
+
+- OpenRouter and OpenAI/Anthropic-compatible providers are managed from **Available Models** only. Manual add, import, and auto-sync all land in the same available-model list, so there is no separate Custom Models section for those providers.
+- The **Custom Models** section is intended for providers that do not expose managed available-model imports.
+
### Dedicated Provider Routes
Route requests directly to a specific provider with model validation:
@@ -642,6 +648,14 @@ Returns models grouped by provider with types (`chat`, `embedding`, `image`).
- Automatic background sync with timeout + fail-fast
- Prefer server-side `BASE_URL`/`CLOUD_URL` in production
+### Cloudflare Quick Tunnel
+
+- Available in **Dashboard → Endpoints** for Docker and other self-hosted deployments
+- Creates a temporary `https://*.trycloudflare.com` URL that forwards to your current OpenAI-compatible `/v1` endpoint
+- First enable installs `cloudflared` only when needed; later restarts reuse the same managed binary
+- Tunnel URLs are ephemeral and change every time you stop/start the tunnel
+- Set `CLOUDFLARED_BIN` if you prefer using a preinstalled `cloudflared` binary instead of the managed download
+
### LLM Gateway Intelligence (Phase 9)
- **Semantic Cache** — Auto-caches non-streaming, temperature=0 responses (bypass with `X-OmniRoute-No-Cache: true`)
@@ -757,11 +771,11 @@ OmniRoute implements provider-level resilience with four components:
Manage database backups in **Dashboard → Settings → System & Storage**.
-| Action | Description |
-| ------------------------ | ------------------------------------------------------------------------------------------------------------------------------ |
-| **Export Database** | Downloads the current SQLite database as a `.sqlite` file |
-| **Export All (.tar.gz)** | Downloads a full backup archive including: database, settings, combos, provider connections (no credentials), API key metadata |
-| **Import Database** | Upload a `.sqlite` file to replace the current database. A pre-import backup is automatically created |
+| Action | Description |
+| ------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------- |
+| **Export Database** | Downloads the current SQLite database as a `.sqlite` file |
+| **Export All (.tar.gz)** | Downloads a full backup archive including: database, settings, combos, provider connections (no credentials), API key metadata |
+| **Import Database** | Upload a `.sqlite` file to replace the current database. A pre-import backup is automatically created unless `DISABLE_SQLITE_AUTO_BACKUP=true` |
```bash
# API: Export database
@@ -787,10 +801,11 @@ curl -X POST http://localhost:20128/api/db-backups/import \
### Settings Dashboard
-The settings page is organized into 5 tabs for easy navigation:
+The settings page is organized into 6 tabs for easy navigation:
| Tab | Contents |
| -------------- | ---------------------------------------------------------------------------------------------- |
+| **General** | System storage tools, appearance settings, theme controls, and per-item sidebar visibility |
| **Security** | Login/Password settings, IP Access Control, API auth for `/models`, and Provider Blocking |
| **Routing** | Global routing strategy (6 options), wildcard model aliases, fallback chains, combo defaults |
| **Resilience** | Provider profiles, editable rate limits, circuit breaker status, policies & locked identifiers |
diff --git a/docs/i18n/fr/docs/VM_DEPLOYMENT_GUIDE.md b/docs/i18n/fr/docs/VM_DEPLOYMENT_GUIDE.md
new file mode 100644
index 0000000000..9b8c6af5f9
--- /dev/null
+++ b/docs/i18n/fr/docs/VM_DEPLOYMENT_GUIDE.md
@@ -0,0 +1,403 @@
+# OmniRoute — Deployment Guide on VM with Cloudflare (Français)
+
+🌐 **Languages:** 🇺🇸 [English](../../../../docs/VM_DEPLOYMENT_GUIDE.md) · 🇪🇸 [es](../../es/docs/VM_DEPLOYMENT_GUIDE.md) · 🇫🇷 [fr](../../fr/docs/VM_DEPLOYMENT_GUIDE.md) · 🇩🇪 [de](../../de/docs/VM_DEPLOYMENT_GUIDE.md) · 🇮🇹 [it](../../it/docs/VM_DEPLOYMENT_GUIDE.md) · 🇷🇺 [ru](../../ru/docs/VM_DEPLOYMENT_GUIDE.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/VM_DEPLOYMENT_GUIDE.md) · 🇯🇵 [ja](../../ja/docs/VM_DEPLOYMENT_GUIDE.md) · 🇰🇷 [ko](../../ko/docs/VM_DEPLOYMENT_GUIDE.md) · 🇸🇦 [ar](../../ar/docs/VM_DEPLOYMENT_GUIDE.md) · 🇮🇳 [in](../../in/docs/VM_DEPLOYMENT_GUIDE.md) · 🇹🇭 [th](../../th/docs/VM_DEPLOYMENT_GUIDE.md) · 🇻🇳 [vi](../../vi/docs/VM_DEPLOYMENT_GUIDE.md) · 🇮🇩 [id](../../id/docs/VM_DEPLOYMENT_GUIDE.md) · 🇲🇾 [ms](../../ms/docs/VM_DEPLOYMENT_GUIDE.md) · 🇳🇱 [nl](../../nl/docs/VM_DEPLOYMENT_GUIDE.md) · 🇵🇱 [pl](../../pl/docs/VM_DEPLOYMENT_GUIDE.md) · 🇸🇪 [sv](../../sv/docs/VM_DEPLOYMENT_GUIDE.md) · 🇳🇴 [no](../../no/docs/VM_DEPLOYMENT_GUIDE.md) · 🇩🇰 [da](../../da/docs/VM_DEPLOYMENT_GUIDE.md) · 🇫🇮 [fi](../../fi/docs/VM_DEPLOYMENT_GUIDE.md) · 🇵🇹 [pt](../../pt/docs/VM_DEPLOYMENT_GUIDE.md) · 🇷🇴 [ro](../../ro/docs/VM_DEPLOYMENT_GUIDE.md) · 🇭🇺 [hu](../../hu/docs/VM_DEPLOYMENT_GUIDE.md) · 🇧🇬 [bg](../../bg/docs/VM_DEPLOYMENT_GUIDE.md) · 🇸🇰 [sk](../../sk/docs/VM_DEPLOYMENT_GUIDE.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/VM_DEPLOYMENT_GUIDE.md) · 🇮🇱 [he](../../he/docs/VM_DEPLOYMENT_GUIDE.md) · 🇵🇭 [phi](../../phi/docs/VM_DEPLOYMENT_GUIDE.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/VM_DEPLOYMENT_GUIDE.md) · 🇨🇿 [cs](../../cs/docs/VM_DEPLOYMENT_GUIDE.md)
+
+---
+
+Complete guide to install and configure OmniRoute on a VM (VPS) with domain managed via Cloudflare.
+
+---
+
+## Prerequisites
+
+| Item | Minimum | Recommended |
+| ---------- | ------------------------ | ---------------- |
+| **CPU** | 1 vCPU | 2 vCPU |
+| **RAM** | 1 GB | 2 GB |
+| **Disk** | 10 GB SSD | 25 GB SSD |
+| **OS** | Ubuntu 22.04 LTS | Ubuntu 24.04 LTS |
+| **Domain** | Registered on Cloudflare | — |
+| **Docker** | Docker Engine 24+ | Docker 27+ |
+
+**Tested providers**: Akamai (Linode), DigitalOcean, Vultr, Hetzner, AWS Lightsail.
+
+---
+
+## 1. Configure the VM
+
+### 1.1 Create the instance
+
+On your preferred VPS provider:
+
+- Choose Ubuntu 24.04 LTS
+- Select the minimum plan (1 vCPU / 1 GB RAM)
+- Set a strong root password or configure SSH key
+- Note the **public IP** (e.g., `203.0.113.10`)
+
+### 1.2 Connect via SSH
+
+```bash
+ssh root@203.0.113.10
+```
+
+### 1.3 Update the system
+
+```bash
+apt update && apt upgrade -y
+```
+
+### 1.4 Install Docker
+
+```bash
+# Install dependencies
+apt install -y ca-certificates curl gnupg
+
+# Add official Docker repository
+install -m 0755 -d /etc/apt/keyrings
+curl -fsSL https://download.docker.com/linux/ubuntu/gpg | gpg --dearmor -o /etc/apt/keyrings/docker.gpg
+chmod a+r /etc/apt/keyrings/docker.gpg
+echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu $ (. /etc/os-release && echo “$VERSION_CODENAME”) stable" | tee /etc/apt/sources.list.d/docker.list > /dev/null
+apt update
+apt install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin
+```
+
+### 1.5 Install nginx
+
+```bash
+apt install -y nginx
+```
+
+### 1.6 Configure Firewall (UFW)
+
+```bash
+ufw default deny incoming
+ufw default allow outgoing
+ufw allow 22/tcp # SSH
+ufw allow 80/tcp # HTTP (redirect)
+ufw allow 443/tcp # HTTPS
+ufw enable
+```
+
+> **Tip**: For maximum security, restrict ports 80 and 443 to Cloudflare IPs only. See the [Advanced Security](#advanced-security) section.
+
+---
+
+## 2. Install OmniRoute
+
+### 2.1 Create configuration directory
+
+```bash
+mkdir -p /opt/omniroute
+```
+
+### 2.2 Create environment variables file
+
+```bash
+cat > /opt/omniroute/.env << ‘EOF’
+# === Security ===
+JWT_SECRET=CHANGE-TO-A-UNIQUE-64-CHAR-SECRET-KEY
+INITIAL_PASSWORD=YourSecurePassword123!
+API_KEY_SECRET=REPLACE-WITH-ANOTHER-SECRET-KEY
+STORAGE_ENCRYPTION_KEY=REPLACE-WITH-THIRD-SECRET-KEY
+STORAGE_ENCRYPTION_KEY_VERSION=v1
+MACHINE_ID_SALT=CHANGE-TO-A-UNIQUE-SALT
+
+# === App ===
+PORT=20128
+NODE_ENV=production
+HOSTNAME=0.0.0.0
+DATA_DIR=/app/data
+STORAGE_DRIVER=sqlite
+ENABLE_REQUEST_LOGS=true
+AUTH_COOKIE_SECURE=false
+REQUIRE_API_KEY=false
+
+# === Domain (change to your domain) ===
+BASE_URL=https://llms.seudominio.com
+NEXT_PUBLIC_BASE_URL=https://llms.seudominio.com
+
+# === Cloud Sync (optional) ===
+# CLOUD_URL=https://cloud.omniroute.online
+# NEXT_PUBLIC_CLOUD_URL=https://cloud.omniroute.online
+EOF
+```
+
+> ⚠️ **IMPORTANT**: Generate unique secret keys! Use `openssl rand -hex 32` for each key.
+
+### 2.3 Start the container
+
+```bash
+docker pull diegosouzapw/omniroute:latest
+
+docker run -d \
+ --name omniroute \
+ --restart unless-stopped \
+ --env-file /opt/omniroute/.env \
+ -p 20128:20128 \
+ -v omniroute-data:/app/data \
+ diegosouzapw/omniroute:latest
+```
+
+### 2.4 Verify that it is running
+
+```bash
+docker ps | grep omniroute
+docker logs omniroute --tail 20
+```
+
+It should display: `[DB] SQLite database ready` and `listening on port 20128`.
+
+---
+
+## 3. Configure nginx (Reverse Proxy)
+
+### 3.1 Generate SSL certificate (Cloudflare Origin)
+
+In the Cloudflare dashboard:
+
+1. Go to **SSL/TLS → Origin Server**
+2. Click **Create Certificate**
+3. Keep the defaults (15 years, \*.yourdomain.com)
+4. Copy the **Origin Certificate** and the **Private Key**
+
+```bash
+mkdir -p /etc/nginx/ssl
+
+# Paste the certificate
+nano /etc/nginx/ssl/origin.crt
+
+# Paste the private key
+nano /etc/nginx/ssl/origin.key
+
+chmod 600 /etc/nginx/ssl/origin.key
+```
+
+### 3.2 Nginx Configuration
+
+```bash
+cat > /etc/nginx/sites-available/omniroute << ‘NGINX’
+# Default server — blocks direct access via IP
+server {
+ listen 80 default_server;
+ listen [::]:80 default_server;
+ listen 443 ssl default_server;
+ listen [::]:443 ssl default_server;
+ ssl_certificate /etc/nginx/ssl/origin.crt;
+ ssl_certificate_key /etc/nginx/ssl/origin.key;
+ server_name _;
+ return 444;
+}
+
+# OmniRoute — HTTPS
+server {
+ listen 443 ssl;
+ listen [::]:443 ssl;
+ server_name llms.yourdomain.com; # Change to your domain
+
+ ssl_certificate /etc/nginx/ssl/origin.crt;
+ ssl_certificate_key /etc/nginx/ssl/origin.key;
+ ssl_protocols TLSv1.2 TLSv1.3;
+
+ client_max_body_size 100M;
+
+ location / {
+ proxy_pass http://127.0.0.1:20128;
+ proxy_set_header Host $host;
+ proxy_set_header X-Real-IP $remote_addr;
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
+ proxy_set_header X-Forwarded-Proto $scheme;
+
+ # WebSocket support
+ proxy_http_version 1.1;
+ proxy_set_header Upgrade $http_upgrade;
+ proxy_set_header Connection “upgrade”;
+
+ # SSE (Server-Sent Events) — streaming AI responses
+ proxy_buffering off;
+ proxy_cache off;
+ proxy_read_timeout 300s;
+ proxy_send_timeout 300s;
+ }
+}
+
+# HTTP → HTTPS redirect
+server {
+ listen 80;
+ listen [::]:80;
+ server_name llms.yourdomain.com;
+ return 301 https://$server_name$request_uri;
+}
+NGINX
+```
+
+### 3.3 Enable and Test
+
+```bash
+# Remove default configuration
+rm -f /etc/nginx/sites-enabled/default
+
+# Enable OmniRoute
+ln -sf /etc/nginx/sites-available/omniroute /etc/nginx/sites-enabled/omniroute
+
+# Test and reload
+nginx -t && systemctl reload nginx
+```
+
+---
+
+## 4. Configure Cloudflare DNS
+
+### 4.1 Add DNS record
+
+In the Cloudflare dashboard → DNS:
+
+| Type | Name | Content | Proxy |
+| ---- | ------ | ---------------------- | ---------- |
+| A | `llms` | `203.0.113.10` (VM IP) | ✅ Proxied |
+
+### 4.2 Configure SSL
+
+Under **SSL/TLS → Overview**:
+
+- Mode: **Full (Strict)**
+
+Under **SSL/TLS → Edge Certificates**:
+
+- Always Use HTTPS: ✅ On
+- Minimum TLS Version: TLS 1.2
+- Automatic HTTPS Rewrites: ✅ On
+
+### 4.3 Testing
+
+```bash
+curl -sI https://llms.seudominio.com/health
+# Should return HTTP/2 200
+```
+
+---
+
+## 5. Operations and Maintenance
+
+### Upgrade to a new version
+
+```bash
+docker pull diegosouzapw/omniroute:latest
+docker stop omniroute && docker rm omniroute
+docker run -d --name omniroute --restart unless-stopped \
+ --env-file /opt/omniroute/.env \
+ -p 20128:20128 \
+ -v omniroute-data:/app/data \
+ diegosouzapw/omniroute:latest
+```
+
+### View logs
+
+```bash
+docker logs -f omniroute # Real-time stream
+docker logs omniroute --tail 50 # Last 50 lines
+```
+
+### Manual database backup
+
+```bash
+# Copy data from the volume to the host
+docker cp omniroute:/app/data ./backup-$(date +%F)
+
+# Or compress the entire volume
+docker run --rm -v omniroute-data:/data -v $(pwd):/backup \
+ alpine tar czf /backup/omniroute-data-$(date +%F).tar.gz /data
+```
+
+### Restore from backup
+
+```bash
+docker stop omniroute
+docker run --rm -v omniroute-data:/data -v $(pwd):/backup \
+ alpine sh -c “rm -rf /data/* && tar xzf /backup/omniroute-data-YYYY-MM-DD.tar.gz -C /”
+docker start omniroute
+```
+
+---
+
+## 6. Advanced Security
+
+### Restrict nginx to Cloudflare IPs
+
+```bash
+cat > /etc/nginx/cloudflare-ips.conf << ‘CF’
+# Cloudflare IPv4 ranges — update periodically
+# https://www.cloudflare.com/ips-v4/
+set_real_ip_from 173.245.48.0/20;
+set_real_ip_from 103.21.244.0/22;
+set_real_ip_from 103.22.200.0/22;
+set_real_ip_from 103.31.4.0/22;
+set_real_ip_from 141.101.64.0/18;
+set_real_ip_from 108.162.192.0/18;
+set_real_ip_from 190.93.240.0/20;
+set_real_ip_from 188.114.96.0/20;
+set_real_ip_from 197.234.240.0/22;
+set_real_ip_from 198.41.128.0/17;
+set_real_ip_from 162.158.0.0/15;
+set_real_ip_from 104.16.0.0/13;
+set_real_ip_from 104.24.0.0/14;
+set_real_ip_from 172.64.0.0/13;
+set_real_ip_from 131.0.72.0/22;
+real_ip_header CF-Connecting-IP;
+CF
+```
+
+Add the following to `nginx.conf` inside the `http {}` block:
+
+```nginx
+include /etc/nginx/cloudflare-ips.conf;
+```
+
+### Install fail2ban
+
+```bash
+apt install -y fail2ban
+systemctl enable fail2ban
+systemctl start fail2ban
+
+# Check status
+fail2ban-client status sshd
+```
+
+### Block direct access to the Docker port
+
+```bash
+# Prevent direct external access to port 20128
+iptables -I DOCKER-USER -p tcp --dport 20128 -j DROP
+iptables -I DOCKER-USER -i lo -p tcp --dport 20128 -j ACCEPT
+
+# Persist the rules
+apt install -y iptables-persistent
+netfilter-persistent save
+```
+
+---
+
+## 7. Deploy to Cloudflare Workers (Optional)
+
+For remote access via Cloudflare Workers (without exposing the VM directly):
+
+```bash
+# In the local repository
+cd omnirouteCloud
+npm install
+npx wrangler login
+npx wrangler deploy
+```
+
+See the full documentation at [omnirouteCloud/README.md](../omnirouteCloud/README.md).
+
+---
+
+## Port Summary
+
+| Port | Service | Access |
+| ----- | ----------- | -------------------------- |
+| 22 | SSH | Public (with fail2ban) |
+| 80 | nginx HTTP | Redirect → HTTPS |
+| 443 | nginx HTTPS | Via Cloudflare Proxy |
+| 20128 | OmniRoute | Localhost only (via nginx) |
diff --git a/docs/i18n/fr/src/lib/a2a/README.md b/docs/i18n/fr/src/lib/a2a/README.md
new file mode 100644
index 0000000000..1b83226b1a
--- /dev/null
+++ b/docs/i18n/fr/src/lib/a2a/README.md
@@ -0,0 +1,752 @@
+# OmniRoute A2A Server (Français)
+
+🌐 **Languages:** 🇺🇸 [English](../../../../../../src/lib/a2a/README.md) · 🇪🇸 [es](../../../../es/src/lib/a2a/README.md) · 🇫🇷 [fr](../../../../fr/src/lib/a2a/README.md) · 🇩🇪 [de](../../../../de/src/lib/a2a/README.md) · 🇮🇹 [it](../../../../it/src/lib/a2a/README.md) · 🇷🇺 [ru](../../../../ru/src/lib/a2a/README.md) · 🇨🇳 [zh-CN](../../../../zh-CN/src/lib/a2a/README.md) · 🇯🇵 [ja](../../../../ja/src/lib/a2a/README.md) · 🇰🇷 [ko](../../../../ko/src/lib/a2a/README.md) · 🇸🇦 [ar](../../../../ar/src/lib/a2a/README.md) · 🇮🇳 [in](../../../../in/src/lib/a2a/README.md) · 🇹🇭 [th](../../../../th/src/lib/a2a/README.md) · 🇻🇳 [vi](../../../../vi/src/lib/a2a/README.md) · 🇮🇩 [id](../../../../id/src/lib/a2a/README.md) · 🇲🇾 [ms](../../../../ms/src/lib/a2a/README.md) · 🇳🇱 [nl](../../../../nl/src/lib/a2a/README.md) · 🇵🇱 [pl](../../../../pl/src/lib/a2a/README.md) · 🇸🇪 [sv](../../../../sv/src/lib/a2a/README.md) · 🇳🇴 [no](../../../../no/src/lib/a2a/README.md) · 🇩🇰 [da](../../../../da/src/lib/a2a/README.md) · 🇫🇮 [fi](../../../../fi/src/lib/a2a/README.md) · 🇵🇹 [pt](../../../../pt/src/lib/a2a/README.md) · 🇷🇴 [ro](../../../../ro/src/lib/a2a/README.md) · 🇭🇺 [hu](../../../../hu/src/lib/a2a/README.md) · 🇧🇬 [bg](../../../../bg/src/lib/a2a/README.md) · 🇸🇰 [sk](../../../../sk/src/lib/a2a/README.md) · 🇺🇦 [uk-UA](../../../../uk-UA/src/lib/a2a/README.md) · 🇮🇱 [he](../../../../he/src/lib/a2a/README.md) · 🇵🇭 [phi](../../../../phi/src/lib/a2a/README.md) · 🇧🇷 [pt-BR](../../../../pt-BR/src/lib/a2a/README.md) · 🇨🇿 [cs](../../../../cs/src/lib/a2a/README.md)
+
+---
+
+> **Agent-to-Agent Protocol v0.3** — Enables any AI agent to use OmniRoute as an intelligent routing agent via JSON-RPC 2.0.
+
+The A2A Server exposes OmniRoute as a **first-class agent** that other agents can discover, delegate tasks to, and collaborate with using the [A2A Protocol](https://google.github.io/A2A/).
+
+---
+
+## Architecture
+
+```
+┌──────────────────────────────────────────────────────────────────┐
+│ Orchestrator Agent │
+│ (LangChain, CrewAI, AutoGen, Custom Agent) │
+└──────────────────────┬───────────────────────────────────────────┘
+ │ 1. GET /.well-known/agent.json (discover)
+ │ 2. POST /a2a (JSON-RPC 2.0)
+ ▼
+┌──────────────────────────────────────────────────────────────────┐
+│ OmniRoute A2A Server │
+│ ┌────────────────┐ ┌────────────────┐ ┌───────────────────┐ │
+│ │ Task Manager │ │ Skill Engine │ │ SSE Streaming │ │
+│ │ (lifecycle) │──│ (registry) │──│ (real-time) │ │
+│ └────────────────┘ └────────┬───────┘ └───────────────────┘ │
+│ │ │
+│ Skills: │ │
+│ ├─ smart-routing ──────────┤ ┌────────────────────────────┐ │
+│ └─ quota-management ───────┘ │ Routing Decision Logger │ │
+│ └────────────────────────────┘ │
+└──────────────────────────────────────────────────────────────────┘
+ │
+ ▼ OmniRoute Gateway (internal)
+ /v1/chat/completions, /api/combos, /api/usage/quota
+```
+
+---
+
+## Démarrage Rapide
+
+### Agent Discovery
+
+Every A2A-compatible agent exposes an **Agent Card** at `/.well-known/agent.json`:
+
+```bash
+curl http://localhost:20128/.well-known/agent.json
+```
+
+**Response:**
+
+```json
+{
+ "name": "OmniRoute",
+ "description": "Intelligent AI gateway with auto-routing across 50+ providers",
+ "url": "http://localhost:20128/a2a",
+ "version": "1.8.1",
+ "capabilities": {
+ "streaming": true,
+ "pushNotifications": false
+ },
+ "skills": [
+ {
+ "id": "smart-routing",
+ "name": "Smart Routing",
+ "description": "Routes prompts through OmniRoute intelligent pipeline",
+ "tags": ["routing", "llm", "multi-provider", "cost-optimization"],
+ "examples": [
+ "Write a hello world in Python",
+ "Explain quantum computing using the cheapest provider"
+ ]
+ },
+ {
+ "id": "quota-management",
+ "name": "Quota Management",
+ "description": "Natural-language queries about provider quotas",
+ "tags": ["quota", "analytics", "cost"],
+ "examples": [
+ "Which provider has the most quota remaining?",
+ "Suggest a free combo for coding"
+ ]
+ }
+ ],
+ "authentication": {
+ "schemes": ["bearer"],
+ "apiKeyHeader": "Authorization"
+ }
+}
+```
+
+---
+
+## JSON-RPC 2.0 Methods
+
+### `message/send` — Synchronous Execution
+
+Send a message to a skill and receive the complete response.
+
+```bash
+curl -X POST http://localhost:20128/a2a \
+ -H "Content-Type: application/json" \
+ -H "Authorization: Bearer YOUR_KEY" \
+ -d '{
+ "jsonrpc": "2.0",
+ "id": "1",
+ "method": "message/send",
+ "params": {
+ "skill": "smart-routing",
+ "messages": [{"role": "user", "content": "Write a Python hello world"}],
+ "metadata": {"model": "auto", "combo": "fast-coding"}
+ }
+ }'
+```
+
+**Response:**
+
+```json
+{
+ "jsonrpc": "2.0",
+ "id": "1",
+ "result": {
+ "task": { "id": "a1b2c3d4-...", "state": "completed" },
+ "artifacts": [{ "type": "text", "content": "print('Hello, World!')" }],
+ "metadata": {
+ "routing_explanation": "Selected claude-sonnet via provider \"anthropic\" (latency: 1200ms, cost: $0.0030)",
+ "cost_envelope": { "estimated": 0.005, "actual": 0.003, "currency": "USD" },
+ "resilience_trace": [
+ { "event": "primary_selected", "provider": "anthropic", "timestamp": "2026-03-04T..." }
+ ],
+ "policy_verdict": { "allowed": true, "reason": "within budget and quota limits" }
+ }
+ }
+}
+```
+
+### `message/stream` — SSE Streaming
+
+Same as `message/send` but returns Server-Sent Events for real-time streaming.
+
+```bash
+curl -N -X POST http://localhost:20128/a2a \
+ -H "Content-Type: application/json" \
+ -H "Authorization: Bearer YOUR_KEY" \
+ -d '{
+ "jsonrpc": "2.0",
+ "id": "1",
+ "method": "message/stream",
+ "params": {
+ "skill": "smart-routing",
+ "messages": [{"role": "user", "content": "Explain quantum computing"}]
+ }
+ }'
+```
+
+**SSE Events:**
+
+```
+data: {"jsonrpc":"2.0","method":"message/stream","params":{"task":{"id":"...","state":"working"},"chunk":{"type":"text","content":"Quantum computing..."}}}
+
+: heartbeat 2026-03-04T21:00:00Z
+
+data: {"jsonrpc":"2.0","method":"message/stream","params":{"task":{"id":"...","state":"completed"},"metadata":{...}}}
+```
+
+### `tasks/get` — Query Task Status
+
+```bash
+curl -X POST http://localhost:20128/a2a \
+ -H "Content-Type: application/json" \
+ -H "Authorization: Bearer YOUR_KEY" \
+ -d '{"jsonrpc":"2.0","id":"2","method":"tasks/get","params":{"taskId":"TASK_UUID"}}'
+```
+
+### `tasks/cancel` — Cancel a Running Task
+
+```bash
+curl -X POST http://localhost:20128/a2a \
+ -H "Content-Type: application/json" \
+ -H "Authorization: Bearer YOUR_KEY" \
+ -d '{"jsonrpc":"2.0","id":"3","method":"tasks/cancel","params":{"taskId":"TASK_UUID"}}'
+```
+
+---
+
+## Skills Reference
+
+### `smart-routing`
+
+Routes prompts through OmniRoute's intelligent pipeline with full observability.
+
+**Parameters (in `metadata`):**
+
+| Parameter | Type | Default | Description |
+| --------- | -------- | ------------ | ---------------------------------------------------------------------------------------- |
+| `model` | `string` | `"auto"` | Target model (e.g., `claude-sonnet-4`, `gpt-4o`, `auto`) |
+| `combo` | `string` | active combo | Specific combo to route through |
+| `budget` | `number` | none | Maximum cost in USD for this request |
+| `role` | `string` | none | Task role hint: `coding`, `review`, `planning`, `analysis`, `debugging`, `documentation` |
+
+**Returns:**
+
+| Field | Description |
+| ------------------------------ | --------------------------------------------------------- |
+| `artifacts[].content` | The LLM response text |
+| `metadata.routing_explanation` | Human-readable explanation of routing decision |
+| `metadata.cost_envelope` | Estimated vs actual cost with currency |
+| `metadata.resilience_trace` | Array of events (primary_selected, fallback_needed, etc.) |
+| `metadata.policy_verdict` | Whether the request was allowed and why |
+
+### `quota-management`
+
+Answers natural-language queries about provider quotas.
+
+**Query types (inferred from message content):**
+
+| Query Pattern | Response Type |
+| ---------------------------------------------- | -------------------------------------------------------- |
+| Contains `"ranking"`, `"most quota"`, `"best"` | Providers ranked by remaining quota |
+| Contains `"free"`, `"suggest"` | Lists free combos or suggests free-tier providers |
+| Default | Full quota summary with warnings for low-quota providers |
+
+---
+
+## Task Lifecycle
+
+```
+submitted ──→ working ──→ completed
+ ──→ failed
+ ──────────→ cancelled
+```
+
+| State | Description |
+| ----------- | ----------------------------------------------------- |
+| `submitted` | Task created, queued for execution |
+| `working` | Skill handler is executing |
+| `completed` | Execution succeeded, artifacts available |
+| `failed` | Execution failed or task expired (TTL: 5 min default) |
+| `cancelled` | Cancelled by client via `tasks/cancel` |
+
+- Terminal states: `completed`, `failed`, `cancelled` (no further transitions)
+- Expired tasks in `submitted` or `working` are auto-marked as `failed`
+- Tasks are garbage-collected after 2× TTL
+
+---
+
+## Client Examples
+
+### Python — Orchestrator Agent
+
+```python
+"""
+A2A Client — Python example.
+Discovers OmniRoute agent, sends a task, and processes the result.
+"""
+import requests
+import json
+
+BASE_URL = "http://localhost:20128"
+API_KEY = "your-api-key"
+HEADERS = {
+ "Content-Type": "application/json",
+ "Authorization": f"Bearer {API_KEY}",
+}
+
+# 1. Discover agent capabilities
+agent_card = requests.get(f"{BASE_URL}/.well-known/agent.json").json()
+print(f"Agent: {agent_card['name']} v{agent_card['version']}")
+print(f"Skills: {[s['id'] for s in agent_card['skills']]}")
+
+# 2. Send a smart-routing task
+response = requests.post(f"{BASE_URL}/a2a", headers=HEADERS, json={
+ "jsonrpc": "2.0",
+ "id": "task-1",
+ "method": "message/send",
+ "params": {
+ "skill": "smart-routing",
+ "messages": [{"role": "user", "content": "Write a Python quicksort implementation"}],
+ "metadata": {
+ "model": "auto",
+ "combo": "fast-coding",
+ "budget": 0.10,
+ }
+ }
+})
+result = response.json()["result"]
+print(f"\n📝 Response: {result['artifacts'][0]['content'][:200]}...")
+print(f"🔀 Routing: {result['metadata']['routing_explanation']}")
+print(f"💰 Cost: ${result['metadata']['cost_envelope']['actual']}")
+print(f"🛡️ Policy: {result['metadata']['policy_verdict']['reason']}")
+
+# 3. Query quota status
+quota_resp = requests.post(f"{BASE_URL}/a2a", headers=HEADERS, json={
+ "jsonrpc": "2.0",
+ "id": "task-2",
+ "method": "message/send",
+ "params": {
+ "skill": "quota-management",
+ "messages": [{"role": "user", "content": "Which provider has the most quota remaining?"}],
+ }
+})
+quota_result = quota_resp.json()["result"]
+print(f"\n📊 Quota: {quota_result['artifacts'][0]['content']}")
+```
+
+### TypeScript — Multi-Agent Orchestrator
+
+```typescript
+/**
+ * A2A Client — TypeScript example.
+ * Shows agent discovery, task delegation, and streaming.
+ */
+
+const BASE_URL = "http://localhost:20128";
+const API_KEY = "your-api-key";
+
+interface JsonRpcResponse {
+ jsonrpc: "2.0";
+ id: string | number;
+ result?: T;
+ error?: { code: number; message: string };
+}
+
+async function a2aCall(method: string, params: Record): Promise {
+ const resp = await fetch(`${BASE_URL}/a2a`, {
+ method: "POST",
+ headers: {
+ "Content-Type": "application/json",
+ Authorization: `Bearer ${API_KEY}`,
+ },
+ body: JSON.stringify({
+ jsonrpc: "2.0",
+ id: `${method}-${Date.now()}`,
+ method,
+ params,
+ }),
+ });
+ const json: JsonRpcResponse = await resp.json();
+ if (json.error) throw new Error(`[${json.error.code}] ${json.error.message}`);
+ return json.result!;
+}
+
+// ── Agent Discovery ──
+const agentCard = await fetch(`${BASE_URL}/.well-known/agent.json`).then((r) => r.json());
+console.log(`Connected to: ${agentCard.name} (${agentCard.skills.length} skills)`);
+
+// ── Smart Routing: Send a coding task ──
+const routingResult = await a2aCall("message/send", {
+ skill: "smart-routing",
+ messages: [{ role: "user", content: "Implement a Redis cache wrapper in TypeScript" }],
+ metadata: { model: "claude-sonnet-4", role: "coding" },
+});
+console.log("Response:", routingResult.artifacts[0].content);
+console.log("Provider:", routingResult.metadata.routing_explanation);
+
+// ── Quota Management: Find free alternatives ──
+const quotaResult = await a2aCall("message/send", {
+ skill: "quota-management",
+ messages: [{ role: "user", content: "Suggest free combos for documentation" }],
+});
+console.log("Free combos:", quotaResult.artifacts[0].content);
+
+// ── Streaming: Real-time response ──
+const streamResp = await fetch(`${BASE_URL}/a2a`, {
+ method: "POST",
+ headers: {
+ "Content-Type": "application/json",
+ Authorization: `Bearer ${API_KEY}`,
+ },
+ body: JSON.stringify({
+ jsonrpc: "2.0",
+ id: "stream-1",
+ method: "message/stream",
+ params: {
+ skill: "smart-routing",
+ messages: [{ role: "user", content: "Explain microservices architecture" }],
+ },
+ }),
+});
+
+const reader = streamResp.body!.getReader();
+const decoder = new TextDecoder();
+while (true) {
+ const { done, value } = await reader.read();
+ if (done) break;
+ const chunk = decoder.decode(value);
+ for (const line of chunk.split("\n")) {
+ if (line.startsWith("data: ")) {
+ const event = JSON.parse(line.slice(6));
+ if (event.params.chunk) {
+ process.stdout.write(event.params.chunk.content);
+ }
+ if (event.params.task.state === "completed") {
+ console.log("\n✅ Stream completed");
+ }
+ }
+ }
+}
+```
+
+### Python — LangChain A2A Integration
+
+```python
+"""
+LangChain integration — Use OmniRoute A2A as a custom LLM.
+"""
+from langchain.llms.base import BaseLLM
+from langchain.schema import LLMResult, Generation
+import requests
+from typing import List, Optional
+
+class OmniRouteA2A(BaseLLM):
+ base_url: str = "http://localhost:20128"
+ api_key: str = ""
+ model: str = "auto"
+ combo: Optional[str] = None
+
+ @property
+ def _llm_type(self) -> str:
+ return "omniroute-a2a"
+
+ def _call(self, prompt: str, stop: Optional[List[str]] = None, **kwargs) -> str:
+ response = requests.post(
+ f"{self.base_url}/a2a",
+ headers={
+ "Content-Type": "application/json",
+ "Authorization": f"Bearer {self.api_key}",
+ },
+ json={
+ "jsonrpc": "2.0",
+ "id": "langchain-1",
+ "method": "message/send",
+ "params": {
+ "skill": "smart-routing",
+ "messages": [{"role": "user", "content": prompt}],
+ "metadata": {
+ "model": self.model,
+ **({"combo": self.combo} if self.combo else {}),
+ },
+ },
+ },
+ )
+ result = response.json()["result"]
+ return result["artifacts"][0]["content"]
+
+ def _generate(self, prompts: List[str], stop=None, **kwargs) -> LLMResult:
+ return LLMResult(
+ generations=[[Generation(text=self._call(p, stop))] for p in prompts]
+ )
+
+# Usage
+llm = OmniRouteA2A(
+ base_url="http://localhost:20128",
+ api_key="your-key",
+ model="auto",
+ combo="fast-coding",
+)
+result = llm("Write a Python function to merge two sorted lists")
+print(result)
+```
+
+### Go — A2A Client
+
+```go
+package main
+
+import (
+ "bytes"
+ "encoding/json"
+ "fmt"
+ "io"
+ "net/http"
+)
+
+const baseURL = "http://localhost:20128"
+const apiKey = "your-api-key"
+
+type JsonRpcRequest struct {
+ Jsonrpc string `json:"jsonrpc"`
+ ID string `json:"id"`
+ Method string `json:"method"`
+ Params interface{} `json:"params"`
+}
+
+type JsonRpcResponse struct {
+ Jsonrpc string `json:"jsonrpc"`
+ ID string `json:"id"`
+ Result interface{} `json:"result"`
+ Error *struct {
+ Code int `json:"code"`
+ Message string `json:"message"`
+ } `json:"error"`
+}
+
+func a2aCall(method string, params interface{}) (*JsonRpcResponse, error) {
+ body, _ := json.Marshal(JsonRpcRequest{
+ Jsonrpc: "2.0",
+ ID: "go-1",
+ Method: method,
+ Params: params,
+ })
+
+ req, _ := http.NewRequest("POST", baseURL+"/a2a", bytes.NewReader(body))
+ req.Header.Set("Content-Type", "application/json")
+ req.Header.Set("Authorization", "Bearer "+apiKey)
+
+ resp, err := http.DefaultClient.Do(req)
+ if err != nil {
+ return nil, err
+ }
+ defer resp.Body.Close()
+ data, _ := io.ReadAll(resp.Body)
+
+ var result JsonRpcResponse
+ json.Unmarshal(data, &result)
+ return &result, nil
+}
+
+func main() {
+ // Discover agent
+ resp, _ := http.Get(baseURL + "/.well-known/agent.json")
+ defer resp.Body.Close()
+ body, _ := io.ReadAll(resp.Body)
+ fmt.Println("Agent Card:", string(body))
+
+ // Send smart-routing task
+ result, _ := a2aCall("message/send", map[string]interface{}{
+ "skill": "smart-routing",
+ "messages": []map[string]string{{"role": "user", "content": "Hello from Go!"}},
+ "metadata": map[string]interface{}{"model": "auto"},
+ })
+ out, _ := json.MarshalIndent(result.Result, "", " ")
+ fmt.Println("Result:", string(out))
+}
+```
+
+---
+
+## Use Cases
+
+### 🤖 Use Case 1: Multi-Agent Coding Pipeline
+
+An orchestrator agent delegates code generation to OmniRoute, then passes the output to a review agent.
+
+```python
+def coding_pipeline(task: str):
+ # Step 1: Generate code via OmniRoute A2A
+ code_result = a2a_send("smart-routing", [
+ {"role": "user", "content": f"Write production-quality code: {task}"}
+ ], metadata={"model": "auto", "role": "coding"})
+ code = code_result["artifacts"][0]["content"]
+
+ # Step 2: Review the code via OmniRoute A2A (different model)
+ review_result = a2a_send("smart-routing", [
+ {"role": "user", "content": f"Review this code for bugs and improvements:\n\n{code}"}
+ ], metadata={"model": "auto", "role": "review"})
+ review = review_result["artifacts"][0]["content"]
+
+ # Step 3: Check costs
+ print(f"Code cost: ${code_result['metadata']['cost_envelope']['actual']}")
+ print(f"Review cost: ${review_result['metadata']['cost_envelope']['actual']}")
+
+ return {"code": code, "review": review}
+```
+
+### 💡 Use Case 2: Quota-Aware Agent Swarm
+
+Multiple agents share quota through OmniRoute, using the quota skill to coordinate.
+
+```python
+async def quota_aware_agent(agent_name: str, task: str):
+ # Check quota before starting
+ quota = a2a_send("quota-management", [
+ {"role": "user", "content": "Which provider has the most quota remaining?"}
+ ])
+ print(f"[{agent_name}] {quota['artifacts'][0]['content']}")
+
+ # Send request with budget constraint
+ result = a2a_send("smart-routing", [
+ {"role": "user", "content": task}
+ ], metadata={"budget": 0.05})
+
+ policy = result["metadata"]["policy_verdict"]
+ if not policy["allowed"]:
+ print(f"[{agent_name}] ⚠️ Budget exceeded: {policy['reason']}")
+ # Fall back to free combo
+ quota = a2a_send("quota-management", [
+ {"role": "user", "content": "Suggest free combos"}
+ ])
+ print(f"[{agent_name}] Free alternatives: {quota['artifacts'][0]['content']}")
+
+ return result
+```
+
+### 📊 Use Case 3: Real-Time Streaming Dashboard
+
+A monitoring agent streams responses and displays progress in real-time.
+
+```typescript
+async function streamingDashboard(prompt: string) {
+ const response = await fetch(`${BASE_URL}/a2a`, {
+ method: "POST",
+ headers: { "Content-Type": "application/json", Authorization: `Bearer ${API_KEY}` },
+ body: JSON.stringify({
+ jsonrpc: "2.0",
+ id: "dash-1",
+ method: "message/stream",
+ params: { skill: "smart-routing", messages: [{ role: "user", content: prompt }] },
+ }),
+ });
+
+ let totalChunks = 0;
+ const reader = response.body!.getReader();
+ const decoder = new TextDecoder();
+
+ while (true) {
+ const { done, value } = await reader.read();
+ if (done) break;
+
+ for (const line of decoder.decode(value).split("\n")) {
+ if (line.startsWith("data: ")) {
+ const event = JSON.parse(line.slice(6));
+ const state = event.params.task.state;
+
+ if (state === "working" && event.params.chunk) {
+ totalChunks++;
+ process.stdout.write(
+ `\r[Chunk ${totalChunks}] ${event.params.chunk.content.slice(0, 50)}...`
+ );
+ }
+ if (state === "completed") {
+ const meta = event.params.metadata;
+ console.log(
+ `\n✅ Done | Cost: $${meta?.cost_envelope?.actual || 0} | Route: ${meta?.routing_explanation || "N/A"}`
+ );
+ }
+ if (state === "failed") {
+ console.error(`\n❌ Failed: ${event.params.metadata?.error}`);
+ }
+ }
+ }
+ }
+}
+```
+
+### 🔁 Use Case 4: Task Polling Pattern
+
+For long-running tasks, poll the task status instead of waiting synchronously.
+
+```python
+import time
+
+def poll_task(task_id: str, timeout: int = 60):
+ """Poll task status until completion or timeout."""
+ start = time.time()
+ while time.time() - start < timeout:
+ result = requests.post(f"{BASE_URL}/a2a", headers=HEADERS, json={
+ "jsonrpc": "2.0",
+ "id": "poll-1",
+ "method": "tasks/get",
+ "params": {"taskId": task_id},
+ }).json()
+
+ task = result["result"]["task"]
+ state = task["state"]
+ print(f" Task {task_id[:8]}... state={state}")
+
+ if state in ("completed", "failed", "cancelled"):
+ return task
+ time.sleep(2)
+
+ # Timeout — cancel the task
+ requests.post(f"{BASE_URL}/a2a", headers=HEADERS, json={
+ "jsonrpc": "2.0",
+ "id": "cancel-1",
+ "method": "tasks/cancel",
+ "params": {"taskId": task_id},
+ })
+ raise TimeoutError(f"Task {task_id} timed out after {timeout}s")
+```
+
+---
+
+## Error Codes
+
+| Code | Constant | Meaning |
+| ------ | ------------------------ | ---------------------------------------- |
+| -32700 | — | Parse error (invalid JSON) |
+| -32600 | `INVALID_REQUEST` | Invalid JSON-RPC request or unauthorized |
+| -32601 | `METHOD_NOT_FOUND` | Unknown method or skill |
+| -32602 | `INVALID_PARAMS` | Missing or invalid parameters |
+| -32603 | `INTERNAL_ERROR` | Skill execution failed |
+| -32001 | `TASK_NOT_FOUND` | Task ID not found |
+| -32002 | `TASK_ALREADY_COMPLETED` | Cannot modify a completed task |
+| -32003 | `UNAUTHORIZED` | Invalid or missing API key |
+| -32004 | `BUDGET_EXCEEDED` | Request exceeds configured budget |
+| -32005 | `PROVIDER_UNAVAILABLE` | No available providers |
+
+---
+
+## Authentication
+
+All `/a2a` requests require a Bearer token via the `Authorization` header:
+
+```
+Authorization: Bearer YOUR_OMNIROUTE_API_KEY
+```
+
+If no API key is configured on the server (`OMNIROUTE_API_KEY` is empty), authentication is bypassed.
+
+---
+
+## File Structure
+
+```
+src/lib/a2a/
+├── taskManager.ts # Task lifecycle (create/update/cancel/list), TTL, cleanup
+├── taskExecution.ts # Generic task executor with state management
+├── streaming.ts # SSE stream formatting, heartbeat, chunk/completion events
+├── routingLogger.ts # Routing decision logger (stats, history, retention)
+└── skills/
+ ├── smartRouting.ts # Smart routing skill (routes via /v1/chat/completions)
+ └── quotaManagement.ts # Quota management skill (natural-language quota queries)
+
+src/app/a2a/
+└── route.ts # Next.js API route handler (JSON-RPC 2.0 dispatch)
+
+open-sse/mcp-server/
+└── schemas/a2a.ts # Zod schemas (AgentCard, Task, JSON-RPC, SSE events)
+```
+
+---
+
+## Comparison: MCP vs A2A
+
+| Feature | MCP Server | A2A Server |
+| ----------------- | ---------------------------- | ------------------------------------------------- |
+| **Protocol** | Model Context Protocol | Agent-to-Agent Protocol v0.3 |
+| **Transport** | stdio / HTTP | HTTP (JSON-RPC 2.0) |
+| **Discovery** | Tool listing via MCP | `/.well-known/agent.json` |
+| **Granularity** | 16 individual tools | 2 high-level skills |
+| **Best for** | IDE agents (Cursor, VS Code) | Multi-agent systems (LangChain, CrewAI) |
+| **Streaming** | Not supported | SSE via `message/stream` |
+| **Task tracking** | No | Full lifecycle (submitted → completed) |
+| **Observability** | Audit log per tool call | Cost envelope + resilience trace + policy verdict |
+
+---
+
+## Licence
+
+Part of [OmniRoute](https://github.com/diegosouzapw/OmniRoute) — MIT License.
diff --git a/docs/i18n/he/A2A-SERVER.md b/docs/i18n/he/A2A-SERVER.md
deleted file mode 100644
index 01531ff482..0000000000
--- a/docs/i18n/he/A2A-SERVER.md
+++ /dev/null
@@ -1,200 +0,0 @@
-🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/A2A-SERVER.md) · 🇪🇸 [es](../es/A2A-SERVER.md) · 🇫🇷 [fr](../fr/A2A-SERVER.md) · 🇩🇪 [de](../de/A2A-SERVER.md) · 🇮🇹 [it](../it/A2A-SERVER.md) · 🇷🇺 [ru](../ru/A2A-SERVER.md) · 🇨🇳 [zh-CN](../zh-CN/A2A-SERVER.md) · 🇯🇵 [ja](../ja/A2A-SERVER.md) · 🇰🇷 [ko](../ko/A2A-SERVER.md) · 🇸🇦 [ar](../ar/A2A-SERVER.md) · 🇮🇳 [in](../in/A2A-SERVER.md) · 🇹🇭 [th](../th/A2A-SERVER.md) · 🇻🇳 [vi](../vi/A2A-SERVER.md) · 🇮🇩 [id](../id/A2A-SERVER.md) · 🇲🇾 [ms](../ms/A2A-SERVER.md) · 🇳🇱 [nl](../nl/A2A-SERVER.md) · 🇵🇱 [pl](../pl/A2A-SERVER.md) · 🇸🇪 [sv](../sv/A2A-SERVER.md) · 🇳🇴 [no](../no/A2A-SERVER.md) · 🇩🇰 [da](../da/A2A-SERVER.md) · 🇫🇮 [fi](../fi/A2A-SERVER.md) · 🇵🇹 [pt](../pt/A2A-SERVER.md) · 🇷🇴 [ro](../ro/A2A-SERVER.md) · 🇭🇺 [hu](../hu/A2A-SERVER.md) · 🇧🇬 [bg](../bg/A2A-SERVER.md) · 🇸🇰 [sk](../sk/A2A-SERVER.md) · 🇺🇦 [uk-UA](../uk-UA/A2A-SERVER.md) · 🇮🇱 [he](../he/A2A-SERVER.md) · 🇵🇭 [phi](../phi/A2A-SERVER.md)
-
----
-
-# OmniRoute A2A Server Documentation
-
-> Agent-to-Agent Protocol v0.3 — OmniRoute as an intelligent routing agent
-
-## Agent Discovery
-
-```bash
-curl http://localhost:20128/.well-known/agent.json
-```
-
-Returns the Agent Card describing OmniRoute's capabilities, skills, and authentication requirements.
-
----
-
-## Authentication
-
-All `/a2a` requests require an API key via the `Authorization` header:
-
-```
-Authorization: Bearer YOUR_OMNIROUTE_API_KEY
-```
-
-If no API key is configured on the server, authentication is bypassed.
-
----
-
-## JSON-RPC 2.0 Methods
-
-### `message/send` — Synchronous Execution
-
-Sends a message to a skill and waits for the complete response.
-
-```bash
-curl -X POST http://localhost:20128/a2a \
- -H "Content-Type: application/json" \
- -H "Authorization: Bearer YOUR_KEY" \
- -d '{
- "jsonrpc": "2.0",
- "id": "1",
- "method": "message/send",
- "params": {
- "skill": "smart-routing",
- "messages": [{"role": "user", "content": "Write a hello world in Python"}],
- "metadata": {"model": "auto", "combo": "fast-coding"}
- }
- }'
-```
-
-**Response:**
-
-```json
-{
- "jsonrpc": "2.0",
- "id": "1",
- "result": {
- "task": { "id": "uuid", "state": "completed" },
- "artifacts": [{ "type": "text", "content": "..." }],
- "metadata": {
- "routing_explanation": "Selected claude-sonnet via provider \"anthropic\" (latency: 1200ms, cost: $0.003)",
- "cost_envelope": { "estimated": 0.005, "actual": 0.003, "currency": "USD" },
- "resilience_trace": [
- { "event": "primary_selected", "provider": "anthropic", "timestamp": "..." }
- ],
- "policy_verdict": { "allowed": true, "reason": "within budget and quota limits" }
- }
- }
-}
-```
-
-### `message/stream` — SSE Streaming
-
-Same as `message/send` but returns Server-Sent Events for real-time streaming.
-
-```bash
-curl -N -X POST http://localhost:20128/a2a \
- -H "Content-Type: application/json" \
- -H "Authorization: Bearer YOUR_KEY" \
- -d '{
- "jsonrpc": "2.0",
- "id": "1",
- "method": "message/stream",
- "params": {
- "skill": "smart-routing",
- "messages": [{"role": "user", "content": "Explain quantum computing"}]
- }
- }'
-```
-
-**SSE Events:**
-
-```
-data: {"jsonrpc":"2.0","method":"message/stream","params":{"task":{"id":"...","state":"working"},"chunk":{"type":"text","content":"..."}}}
-
-: heartbeat 2026-03-03T17:00:00Z
-
-data: {"jsonrpc":"2.0","method":"message/stream","params":{"task":{"id":"...","state":"completed"},"metadata":{...}}}
-```
-
-### `tasks/get` — Query Task Status
-
-```bash
-curl -X POST http://localhost:20128/a2a \
- -H "Content-Type: application/json" \
- -H "Authorization: Bearer YOUR_KEY" \
- -d '{"jsonrpc":"2.0","id":"2","method":"tasks/get","params":{"taskId":"TASK_UUID"}}'
-```
-
-### `tasks/cancel` — Cancel a Task
-
-```bash
-curl -X POST http://localhost:20128/a2a \
- -H "Content-Type: application/json" \
- -H "Authorization: Bearer YOUR_KEY" \
- -d '{"jsonrpc":"2.0","id":"3","method":"tasks/cancel","params":{"taskId":"TASK_UUID"}}'
-```
-
----
-
-## Available Skills
-
-| Skill | Description |
-| :----------------- | :------------------------------------------------------------------------------------------------------------------------------ |
-| `smart-routing` | Routes prompts through OmniRoute's intelligent pipeline. Returns response with routing explanation, cost, and resilience trace. |
-| `quota-management` | Answers natural-language queries about provider quotas, suggests free combos, and provides quota rankings. |
-
----
-
-## Task Lifecycle
-
-```
-submitted → working → completed
- → failed
- → cancelled
-```
-
-- Tasks expire after 5 minutes (configurable)
-- Terminal states: `completed`, `failed`, `cancelled`
-- Event log tracks every state transition
-
----
-
-## Error Codes
-
-| Code | Meaning |
-| :----- | :----------------------------- |
-| -32700 | Parse error (invalid JSON) |
-| -32600 | Invalid request / Unauthorized |
-| -32601 | Method or skill not found |
-| -32602 | Invalid params |
-| -32603 | Internal error |
-
----
-
-## Integration Examples
-
-### Python (requests)
-
-```python
-import requests
-
-resp = requests.post("http://localhost:20128/a2a", json={
- "jsonrpc": "2.0", "id": "1",
- "method": "message/send",
- "params": {
- "skill": "smart-routing",
- "messages": [{"role": "user", "content": "Hello"}]
- }
-}, headers={"Authorization": "Bearer YOUR_KEY"})
-
-result = resp.json()["result"]
-print(result["artifacts"][0]["content"])
-print(result["metadata"]["routing_explanation"])
-```
-
-### TypeScript (fetch)
-
-```typescript
-const resp = await fetch("http://localhost:20128/a2a", {
- method: "POST",
- headers: {
- "Content-Type": "application/json",
- Authorization: "Bearer YOUR_KEY",
- },
- body: JSON.stringify({
- jsonrpc: "2.0",
- id: "1",
- method: "message/send",
- params: {
- skill: "smart-routing",
- messages: [{ role: "user", content: "Hello" }],
- },
- }),
-});
-const { result } = await resp.json();
-console.log(result.metadata.routing_explanation);
-```
diff --git a/docs/i18n/he/API_REFERENCE.md b/docs/i18n/he/API_REFERENCE.md
deleted file mode 100644
index b878605221..0000000000
--- a/docs/i18n/he/API_REFERENCE.md
+++ /dev/null
@@ -1,455 +0,0 @@
-🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/API_REFERENCE.md) · 🇪🇸 [es](../es/API_REFERENCE.md) · 🇫🇷 [fr](../fr/API_REFERENCE.md) · 🇩🇪 [de](../de/API_REFERENCE.md) · 🇮🇹 [it](../it/API_REFERENCE.md) · 🇷🇺 [ru](../ru/API_REFERENCE.md) · 🇨🇳 [zh-CN](../zh-CN/API_REFERENCE.md) · 🇯🇵 [ja](../ja/API_REFERENCE.md) · 🇰🇷 [ko](../ko/API_REFERENCE.md) · 🇸🇦 [ar](../ar/API_REFERENCE.md) · 🇮🇳 [in](../in/API_REFERENCE.md) · 🇹🇭 [th](../th/API_REFERENCE.md) · 🇻🇳 [vi](../vi/API_REFERENCE.md) · 🇮🇩 [id](../id/API_REFERENCE.md) · 🇲🇾 [ms](../ms/API_REFERENCE.md) · 🇳🇱 [nl](../nl/API_REFERENCE.md) · 🇵🇱 [pl](../pl/API_REFERENCE.md) · 🇸🇪 [sv](../sv/API_REFERENCE.md) · 🇳🇴 [no](../no/API_REFERENCE.md) · 🇩🇰 [da](../da/API_REFERENCE.md) · 🇫🇮 [fi](../fi/API_REFERENCE.md) · 🇵🇹 [pt](../pt/API_REFERENCE.md) · 🇷🇴 [ro](../ro/API_REFERENCE.md) · 🇭🇺 [hu](../hu/API_REFERENCE.md) · 🇧🇬 [bg](../bg/API_REFERENCE.md) · 🇸🇰 [sk](../sk/API_REFERENCE.md) · 🇺🇦 [uk-UA](../uk-UA/API_REFERENCE.md) · 🇮🇱 [he](../he/API_REFERENCE.md) · 🇵🇭 [phi](../phi/API_REFERENCE.md)
-
----
-
-# API Reference
-
-🌐 **Languages:** 🇺🇸 [English](API_REFERENCE.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/API_REFERENCE.md) | 🇪🇸 [Español](i18n/es/API_REFERENCE.md) | 🇫🇷 [Français](i18n/fr/API_REFERENCE.md) | 🇮🇹 [Italiano](i18n/it/API_REFERENCE.md) | 🇷🇺 [Русский](i18n/ru/API_REFERENCE.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/API_REFERENCE.md) | 🇩🇪 [Deutsch](i18n/de/API_REFERENCE.md) | 🇮🇳 [हिन्दी](i18n/in/API_REFERENCE.md) | 🇹🇭 [ไทย](i18n/th/API_REFERENCE.md) | 🇺🇦 [Українська](i18n/uk-UA/API_REFERENCE.md) | 🇸🇦 [العربية](i18n/ar/API_REFERENCE.md) | 🇯🇵 [日本語](i18n/ja/API_REFERENCE.md) | 🇻🇳 [Tiếng Việt](i18n/vi/API_REFERENCE.md) | 🇧🇬 [Български](i18n/bg/API_REFERENCE.md) | 🇩🇰 [Dansk](i18n/da/API_REFERENCE.md) | 🇫🇮 [Suomi](i18n/fi/API_REFERENCE.md) | 🇮🇱 [עברית](i18n/he/API_REFERENCE.md) | 🇭🇺 [Magyar](i18n/hu/API_REFERENCE.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/API_REFERENCE.md) | 🇰🇷 [한국어](i18n/ko/API_REFERENCE.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/API_REFERENCE.md) | 🇳🇱 [Nederlands](i18n/nl/API_REFERENCE.md) | 🇳🇴 [Norsk](i18n/no/API_REFERENCE.md) | 🇵🇹 [Português (Portugal)](i18n/pt/API_REFERENCE.md) | 🇷🇴 [Română](i18n/ro/API_REFERENCE.md) | 🇵🇱 [Polski](i18n/pl/API_REFERENCE.md) | 🇸🇰 [Slovenčina](i18n/sk/API_REFERENCE.md) | 🇸🇪 [Svenska](i18n/sv/API_REFERENCE.md) | 🇵🇭 [Filipino](i18n/phi/API_REFERENCE.md)
-
-Complete reference for all OmniRoute API endpoints.
-
----
-
-## Table of Contents
-
-- [Chat Completions](#chat-completions)
-- [Embeddings](#embeddings)
-- [Image Generation](#image-generation)
-- [List Models](#list-models)
-- [Compatibility Endpoints](#compatibility-endpoints)
-- [Semantic Cache](#semantic-cache)
-- [Dashboard & Management](#dashboard--management)
-- [Request Processing](#request-processing)
-- [Authentication](#authentication)
-
----
-
-## Chat Completions
-
-```bash
-POST /v1/chat/completions
-Authorization: Bearer your-api-key
-Content-Type: application/json
-
-{
- "model": "cc/claude-opus-4-6",
- "messages": [
- {"role": "user", "content": "Write a function to..."}
- ],
- "stream": true
-}
-```
-
-### Custom Headers
-
-| Header | Direction | Description |
-| ------------------------ | --------- | --------------------------------- |
-| `X-OmniRoute-No-Cache` | Request | Set to `true` to bypass cache |
-| `X-OmniRoute-Progress` | Request | Set to `true` for progress events |
-| `Idempotency-Key` | Request | Dedup key (5s window) |
-| `X-Request-Id` | Request | Alternative dedup key |
-| `X-OmniRoute-Cache` | Response | `HIT` or `MISS` (non-streaming) |
-| `X-OmniRoute-Idempotent` | Response | `true` if deduplicated |
-| `X-OmniRoute-Progress` | Response | `enabled` if progress tracking on |
-
----
-
-## Embeddings
-
-```bash
-POST /v1/embeddings
-Authorization: Bearer your-api-key
-Content-Type: application/json
-
-{
- "model": "nebius/Qwen/Qwen3-Embedding-8B",
- "input": "The food was delicious"
-}
-```
-
-Available providers: Nebius, OpenAI, Mistral, Together AI, Fireworks, NVIDIA.
-
-```bash
-# List all embedding models
-GET /v1/embeddings
-```
-
----
-
-## Image Generation
-
-```bash
-POST /v1/images/generations
-Authorization: Bearer your-api-key
-Content-Type: application/json
-
-{
- "model": "openai/dall-e-3",
- "prompt": "A beautiful sunset over mountains",
- "size": "1024x1024"
-}
-```
-
-Available providers: OpenAI (DALL-E), xAI (Grok Image), Together AI (FLUX), Fireworks AI.
-
-```bash
-# List all image models
-GET /v1/images/generations
-```
-
----
-
-## List Models
-
-```bash
-GET /v1/models
-Authorization: Bearer your-api-key
-
-→ Returns all chat, embedding, and image models + combos in OpenAI format
-```
-
----
-
-## Compatibility Endpoints
-
-| Method | Path | Format |
-| ------ | --------------------------- | ---------------------- |
-| POST | `/v1/chat/completions` | OpenAI |
-| POST | `/v1/messages` | Anthropic |
-| POST | `/v1/responses` | OpenAI Responses |
-| POST | `/v1/embeddings` | OpenAI |
-| POST | `/v1/images/generations` | OpenAI |
-| GET | `/v1/models` | OpenAI |
-| POST | `/v1/messages/count_tokens` | Anthropic |
-| GET | `/v1beta/models` | Gemini |
-| POST | `/v1beta/models/{...path}` | Gemini generateContent |
-| POST | `/v1/api/chat` | Ollama |
-
-### Dedicated Provider Routes
-
-```bash
-POST /v1/providers/{provider}/chat/completions
-POST /v1/providers/{provider}/embeddings
-POST /v1/providers/{provider}/images/generations
-```
-
-The provider prefix is auto-added if missing. Mismatched models return `400`.
-
----
-
-## Semantic Cache
-
-```bash
-# Get cache stats
-GET /api/cache
-
-# Clear all caches
-DELETE /api/cache
-```
-
-Response example:
-
-```json
-{
- "semanticCache": {
- "memorySize": 42,
- "memoryMaxSize": 500,
- "dbSize": 128,
- "hitRate": 0.65
- },
- "idempotency": {
- "activeKeys": 3,
- "windowMs": 5000
- }
-}
-```
-
----
-
-## Dashboard & Management
-
-### Authentication
-
-| Endpoint | Method | Description |
-| ----------------------------- | ------- | --------------------- |
-| `/api/auth/login` | POST | Login |
-| `/api/auth/logout` | POST | Logout |
-| `/api/settings/require-login` | GET/PUT | Toggle login required |
-
-### Provider Management
-
-| Endpoint | Method | Description |
-| ---------------------------- | --------------- | ------------------------ |
-| `/api/providers` | GET/POST | List / create providers |
-| `/api/providers/[id]` | GET/PUT/DELETE | Manage a provider |
-| `/api/providers/[id]/test` | POST | Test provider connection |
-| `/api/providers/[id]/models` | GET | List provider models |
-| `/api/providers/validate` | POST | Validate provider config |
-| `/api/provider-nodes*` | Various | Provider node management |
-| `/api/provider-models` | GET/POST/DELETE | Custom models |
-
-### OAuth Flows
-
-| Endpoint | Method | Description |
-| -------------------------------- | ------- | ----------------------- |
-| `/api/oauth/[provider]/[action]` | Various | Provider-specific OAuth |
-
-### Routing & Config
-
-| Endpoint | Method | Description |
-| --------------------- | -------- | ----------------------------- |
-| `/api/models/alias` | GET/POST | Model aliases |
-| `/api/models/catalog` | GET | All models by provider + type |
-| `/api/combos*` | Various | Combo management |
-| `/api/keys*` | Various | API key management |
-| `/api/pricing` | GET | Model pricing |
-
-### Usage & Analytics
-
-| Endpoint | Method | Description |
-| --------------------------- | ------ | -------------------- |
-| `/api/usage/history` | GET | Usage history |
-| `/api/usage/logs` | GET | Usage logs |
-| `/api/usage/request-logs` | GET | Request-level logs |
-| `/api/usage/[connectionId]` | GET | Per-connection usage |
-
-### Settings
-
-| Endpoint | Method | Description |
-| ------------------------------- | ------- | ---------------------- |
-| `/api/settings` | GET/PUT | General settings |
-| `/api/settings/proxy` | GET/PUT | Network proxy config |
-| `/api/settings/proxy/test` | POST | Test proxy connection |
-| `/api/settings/ip-filter` | GET/PUT | IP allowlist/blocklist |
-| `/api/settings/thinking-budget` | GET/PUT | Reasoning token budget |
-| `/api/settings/system-prompt` | GET/PUT | Global system prompt |
-
-### Monitoring
-
-| Endpoint | Method | Description |
-| ------------------------ | ---------- | ----------------------- |
-| `/api/sessions` | GET | Active session tracking |
-| `/api/rate-limits` | GET | Per-account rate limits |
-| `/api/monitoring/health` | GET | Health check |
-| `/api/cache` | GET/DELETE | Cache stats / clear |
-
-### Backup & Export/Import
-
-| Endpoint | Method | Description |
-| --------------------------- | ------ | --------------------------------------- |
-| `/api/db-backups` | GET | List available backups |
-| `/api/db-backups` | PUT | Create a manual backup |
-| `/api/db-backups` | POST | Restore from a specific backup |
-| `/api/db-backups/export` | GET | Download database as .sqlite file |
-| `/api/db-backups/import` | POST | Upload .sqlite file to replace database |
-| `/api/db-backups/exportAll` | GET | Download full backup as .tar.gz archive |
-
-### Cloud Sync
-
-| Endpoint | Method | Description |
-| ---------------------- | ------- | --------------------- |
-| `/api/sync/cloud` | Various | Cloud sync operations |
-| `/api/sync/initialize` | POST | Initialize sync |
-| `/api/cloud/*` | Various | Cloud management |
-
-### CLI Tools
-
-| Endpoint | Method | Description |
-| ---------------------------------- | ------ | ------------------- |
-| `/api/cli-tools/claude-settings` | GET | Claude CLI status |
-| `/api/cli-tools/codex-settings` | GET | Codex CLI status |
-| `/api/cli-tools/droid-settings` | GET | Droid CLI status |
-| `/api/cli-tools/openclaw-settings` | GET | OpenClaw CLI status |
-| `/api/cli-tools/runtime/[toolId]` | GET | Generic CLI runtime |
-
-CLI responses include: `installed`, `runnable`, `command`, `commandPath`, `runtimeMode`, `reason`.
-
-### ACP Agents
-
-| Endpoint | Method | Description |
-| ----------------- | ------ | -------------------------------------------------------- |
-| `/api/acp/agents` | GET | List all detected agents (built-in + custom) with status |
-| `/api/acp/agents` | POST | Add custom agent or refresh detection cache |
-| `/api/acp/agents` | DELETE | Remove a custom agent by `id` query param |
-
-GET response includes `agents[]` (id, name, binary, version, installed, protocol, isCustom) and `summary` (total, installed, notFound, builtIn, custom).
-
-### Resilience & Rate Limits
-
-| Endpoint | Method | Description |
-| ----------------------- | ------- | ------------------------------- |
-| `/api/resilience` | GET/PUT | Get/update resilience profiles |
-| `/api/resilience/reset` | POST | Reset circuit breakers |
-| `/api/rate-limits` | GET | Per-account rate limit status |
-| `/api/rate-limit` | GET | Global rate limit configuration |
-
-### Evals
-
-| Endpoint | Method | Description |
-| ------------ | -------- | --------------------------------- |
-| `/api/evals` | GET/POST | List eval suites / run evaluation |
-
-### Policies
-
-| Endpoint | Method | Description |
-| --------------- | --------------- | ----------------------- |
-| `/api/policies` | GET/POST/DELETE | Manage routing policies |
-
-### Compliance
-
-| Endpoint | Method | Description |
-| --------------------------- | ------ | ----------------------------- |
-| `/api/compliance/audit-log` | GET | Compliance audit log (last N) |
-
-### v1beta (Gemini-Compatible)
-
-| Endpoint | Method | Description |
-| -------------------------- | ------ | --------------------------------- |
-| `/v1beta/models` | GET | List models in Gemini format |
-| `/v1beta/models/{...path}` | POST | Gemini `generateContent` endpoint |
-
-These endpoints mirror Gemini's API format for clients that expect native Gemini SDK compatibility.
-
-### Internal / System APIs
-
-| Endpoint | Method | Description |
-| --------------- | ------ | ---------------------------------------------------- |
-| `/api/init` | GET | Application initialization check (used on first run) |
-| `/api/tags` | GET | Ollama-compatible model tags (for Ollama clients) |
-| `/api/restart` | POST | Trigger graceful server restart |
-| `/api/shutdown` | POST | Trigger graceful server shutdown |
-
-> **Note:** These endpoints are used internally by the system or for Ollama client compatibility. They are not typically called by end users.
-
----
-
-## Audio Transcription
-
-```bash
-POST /v1/audio/transcriptions
-Authorization: Bearer your-api-key
-Content-Type: multipart/form-data
-```
-
-Transcribe audio files using Deepgram or AssemblyAI.
-
-**Request:**
-
-```bash
-curl -X POST http://localhost:20128/v1/audio/transcriptions \
- -H "Authorization: Bearer your-api-key" \
- -F "file=@recording.mp3" \
- -F "model=deepgram/nova-3"
-```
-
-**Response:**
-
-```json
-{
- "text": "Hello, this is the transcribed audio content.",
- "task": "transcribe",
- "language": "en",
- "duration": 12.5
-}
-```
-
-**Supported providers:** `deepgram/nova-3`, `assemblyai/best`.
-
-**Supported formats:** `mp3`, `wav`, `m4a`, `flac`, `ogg`, `webm`.
-
----
-
-## Ollama Compatibility
-
-For clients that use Ollama's API format:
-
-```bash
-# Chat endpoint (Ollama format)
-POST /v1/api/chat
-
-# Model listing (Ollama format)
-GET /api/tags
-```
-
-Requests are automatically translated between Ollama and internal formats.
-
----
-
-## Telemetry
-
-```bash
-# Get latency telemetry summary (p50/p95/p99 per provider)
-GET /api/telemetry/summary
-```
-
-**Response:**
-
-```json
-{
- "providers": {
- "claudeCode": { "p50": 245, "p95": 890, "p99": 1200, "count": 150 },
- "github": { "p50": 180, "p95": 620, "p99": 950, "count": 320 }
- }
-}
-```
-
----
-
-## Budget
-
-```bash
-# Get budget status for all API keys
-GET /api/usage/budget
-
-# Set or update a budget
-POST /api/usage/budget
-Content-Type: application/json
-
-{
- "keyId": "key-123",
- "limit": 50.00,
- "period": "monthly"
-}
-```
-
----
-
-## Model Availability
-
-```bash
-# Get real-time model availability across all providers
-GET /api/models/availability
-
-# Check availability for a specific model
-POST /api/models/availability
-Content-Type: application/json
-
-{
- "model": "claude-sonnet-4-5-20250929"
-}
-```
-
----
-
-## Request Processing
-
-1. Client sends request to `/v1/*`
-2. Route handler calls `handleChat`, `handleEmbedding`, `handleAudioTranscription`, or `handleImageGeneration`
-3. Model is resolved (direct provider/model or alias/combo)
-4. Credentials selected from local DB with account availability filtering
-5. For chat: `handleChatCore` — format detection, translation, cache check, idempotency check
-6. Provider executor sends upstream request
-7. Response translated back to client format (chat) or returned as-is (embeddings/images/audio)
-8. Usage/logging recorded
-9. Fallback applies on errors according to combo rules
-
-Full architecture reference: [`ARCHITECTURE.md`](ARCHITECTURE.md)
-
----
-
-## Authentication
-
-- Dashboard routes (`/dashboard/*`) use `auth_token` cookie
-- Login uses saved password hash; fallback to `INITIAL_PASSWORD`
-- `requireLogin` toggleable via `/api/settings/require-login`
-- `/v1/*` routes optionally require Bearer API key when `REQUIRE_API_KEY=true`
diff --git a/docs/i18n/he/ARCHITECTURE.md b/docs/i18n/he/ARCHITECTURE.md
deleted file mode 100644
index 4ea06a29f2..0000000000
--- a/docs/i18n/he/ARCHITECTURE.md
+++ /dev/null
@@ -1,787 +0,0 @@
-🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/ARCHITECTURE.md) · 🇪🇸 [es](../es/ARCHITECTURE.md) · 🇫🇷 [fr](../fr/ARCHITECTURE.md) · 🇩🇪 [de](../de/ARCHITECTURE.md) · 🇮🇹 [it](../it/ARCHITECTURE.md) · 🇷🇺 [ru](../ru/ARCHITECTURE.md) · 🇨🇳 [zh-CN](../zh-CN/ARCHITECTURE.md) · 🇯🇵 [ja](../ja/ARCHITECTURE.md) · 🇰🇷 [ko](../ko/ARCHITECTURE.md) · 🇸🇦 [ar](../ar/ARCHITECTURE.md) · 🇮🇳 [in](../in/ARCHITECTURE.md) · 🇹🇭 [th](../th/ARCHITECTURE.md) · 🇻🇳 [vi](../vi/ARCHITECTURE.md) · 🇮🇩 [id](../id/ARCHITECTURE.md) · 🇲🇾 [ms](../ms/ARCHITECTURE.md) · 🇳🇱 [nl](../nl/ARCHITECTURE.md) · 🇵🇱 [pl](../pl/ARCHITECTURE.md) · 🇸🇪 [sv](../sv/ARCHITECTURE.md) · 🇳🇴 [no](../no/ARCHITECTURE.md) · 🇩🇰 [da](../da/ARCHITECTURE.md) · 🇫🇮 [fi](../fi/ARCHITECTURE.md) · 🇵🇹 [pt](../pt/ARCHITECTURE.md) · 🇷🇴 [ro](../ro/ARCHITECTURE.md) · 🇭🇺 [hu](../hu/ARCHITECTURE.md) · 🇧🇬 [bg](../bg/ARCHITECTURE.md) · 🇸🇰 [sk](../sk/ARCHITECTURE.md) · 🇺🇦 [uk-UA](../uk-UA/ARCHITECTURE.md) · 🇮🇱 [he](../he/ARCHITECTURE.md) · 🇵🇭 [phi](../phi/ARCHITECTURE.md)
-
----
-
-# OmniRoute Architecture
-
-🌐 **Languages:** 🇺🇸 [English](ARCHITECTURE.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/ARCHITECTURE.md) | 🇪🇸 [Español](i18n/es/ARCHITECTURE.md) | 🇫🇷 [Français](i18n/fr/ARCHITECTURE.md) | 🇮🇹 [Italiano](i18n/it/ARCHITECTURE.md) | 🇷🇺 [Русский](i18n/ru/ARCHITECTURE.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/ARCHITECTURE.md) | 🇩🇪 [Deutsch](i18n/de/ARCHITECTURE.md) | 🇮🇳 [हिन्दी](i18n/in/ARCHITECTURE.md) | 🇹🇭 [ไทย](i18n/th/ARCHITECTURE.md) | 🇺🇦 [Українська](i18n/uk-UA/ARCHITECTURE.md) | 🇸🇦 [العربية](i18n/ar/ARCHITECTURE.md) | 🇯🇵 [日本語](i18n/ja/ARCHITECTURE.md) | 🇻🇳 [Tiếng Việt](i18n/vi/ARCHITECTURE.md) | 🇧🇬 [Български](i18n/bg/ARCHITECTURE.md) | 🇩🇰 [Dansk](i18n/da/ARCHITECTURE.md) | 🇫🇮 [Suomi](i18n/fi/ARCHITECTURE.md) | 🇮🇱 [עברית](i18n/he/ARCHITECTURE.md) | 🇭🇺 [Magyar](i18n/hu/ARCHITECTURE.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/ARCHITECTURE.md) | 🇰🇷 [한국어](i18n/ko/ARCHITECTURE.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/ARCHITECTURE.md) | 🇳🇱 [Nederlands](i18n/nl/ARCHITECTURE.md) | 🇳🇴 [Norsk](i18n/no/ARCHITECTURE.md) | 🇵🇹 [Português (Portugal)](i18n/pt/ARCHITECTURE.md) | 🇷🇴 [Română](i18n/ro/ARCHITECTURE.md) | 🇵🇱 [Polski](i18n/pl/ARCHITECTURE.md) | 🇸🇰 [Slovenčina](i18n/sk/ARCHITECTURE.md) | 🇸🇪 [Svenska](i18n/sv/ARCHITECTURE.md) | 🇵🇭 [Filipino](i18n/phi/ARCHITECTURE.md)
-
-_Last updated: 2026-03-04_
-
-## Executive Summary
-
-OmniRoute is a local AI routing gateway and dashboard built on Next.js.
-It provides a single OpenAI-compatible endpoint (`/v1/*`) and routes traffic across multiple upstream providers with translation, fallback, token refresh, and usage tracking.
-
-Core capabilities:
-
-- OpenAI-compatible API surface for CLI/tools (28 providers)
-- Request/response translation across provider formats
-- Model combo fallback (multi-model sequence)
-- Account-level fallback (multi-account per provider)
-- OAuth + API-key provider connection management
-- Embedding generation via `/v1/embeddings` (6 providers, 9 models)
-- Image generation via `/v1/images/generations` (4 providers, 9 models)
-- Think tag parsing (`...`) for reasoning models
-- Response sanitization for strict OpenAI SDK compatibility
-- Role normalization (developer→system, system→user) for cross-provider compatibility
-- Structured output conversion (json_schema → Gemini responseSchema)
-- Local persistence for providers, keys, aliases, combos, settings, pricing
-- Usage/cost tracking and request logging
-- Optional cloud sync for multi-device/state sync
-- IP allowlist/blocklist for API access control
-- Thinking budget management (passthrough/auto/custom/adaptive)
-- Global system prompt injection
-- Session tracking and fingerprinting
-- Per-account enhanced rate limiting with provider-specific profiles
-- Circuit breaker pattern for provider resilience
-- Anti-thundering herd protection with mutex locking
-- Signature-based request deduplication cache
-- Domain layer: model availability, cost rules, fallback policy, lockout policy
-- Domain state persistence (SQLite write-through cache for fallbacks, budgets, lockouts, circuit breakers)
-- Policy engine for centralized request evaluation (lockout → budget → fallback)
-- Request telemetry with p50/p95/p99 latency aggregation
-- Correlation ID (X-Request-Id) for end-to-end tracing
-- Compliance audit logging with opt-out per API key
-- Eval framework for LLM quality assurance
-- Resilience UI dashboard with real-time circuit breaker status
-- Modular OAuth providers (12 individual modules under `src/lib/oauth/providers/`)
-
-Primary runtime model:
-
-- Next.js app routes under `src/app/api/*` implement both dashboard APIs and compatibility APIs
-- A shared SSE/routing core in `src/sse/*` + `open-sse/*` handles provider execution, translation, streaming, fallback, and usage
-
-## Scope and Boundaries
-
-### In Scope
-
-- Local gateway runtime
-- Dashboard management APIs
-- Provider authentication and token refresh
-- Request translation and SSE streaming
-- Local state + usage persistence
-- Optional cloud sync orchestration
-
-### Out of Scope
-
-- Cloud service implementation behind `NEXT_PUBLIC_CLOUD_URL`
-- Provider SLA/control plane outside local process
-- External CLI binaries themselves (Claude CLI, Codex CLI, etc.)
-
-## High-Level System Context
-
-```mermaid
-flowchart LR
- subgraph Clients[Developer Clients]
- C1[Claude Code]
- C2[Codex CLI]
- C3[OpenClaw / Droid / Cline / Continue / Roo]
- C4[Custom OpenAI-compatible clients]
- BROWSER[Browser Dashboard]
- end
-
- subgraph Router[OmniRoute Local Process]
- API[V1 Compatibility API\n/v1/*]
- DASH[Dashboard + Management API\n/api/*]
- CORE[SSE + Translation Core\nopen-sse + src/sse]
- DB[(storage.sqlite)]
- UDB[(usage tables + log artifacts)]
- end
-
- subgraph Upstreams[Upstream Providers]
- P1[OAuth Providers\nClaude/Codex/Gemini/Qwen/Qoder/GitHub/Kiro/Cursor/Antigravity]
- P2[API Key Providers\nOpenAI/Anthropic/OpenRouter/GLM/Kimi/MiniMax\nDeepSeek/Groq/xAI/Mistral/Perplexity\nTogether/Fireworks/Cerebras/Cohere/NVIDIA]
- P3[Compatible Nodes\nOpenAI-compatible / Anthropic-compatible]
- end
-
- subgraph Cloud[Optional Cloud Sync]
- CLOUD[Cloud Sync Endpoint\nNEXT_PUBLIC_CLOUD_URL]
- end
-
- C1 --> API
- C2 --> API
- C3 --> API
- C4 --> API
- BROWSER --> DASH
-
- API --> CORE
- DASH --> DB
- CORE --> DB
- CORE --> UDB
-
- CORE --> P1
- CORE --> P2
- CORE --> P3
-
- DASH --> CLOUD
-```
-
-## Core Runtime Components
-
-## 1) API and Routing Layer (Next.js App Routes)
-
-Main directories:
-
-- `src/app/api/v1/*` and `src/app/api/v1beta/*` for compatibility APIs
-- `src/app/api/*` for management/configuration APIs
-- Next rewrites in `next.config.mjs` map `/v1/*` to `/api/v1/*`
-
-Important compatibility routes:
-
-- `src/app/api/v1/chat/completions/route.ts`
-- `src/app/api/v1/messages/route.ts`
-- `src/app/api/v1/responses/route.ts`
-- `src/app/api/v1/models/route.ts` — includes custom models with `custom: true`
-- `src/app/api/v1/embeddings/route.ts` — embedding generation (6 providers)
-- `src/app/api/v1/images/generations/route.ts` — image generation (4+ providers incl. Antigravity/Nebius)
-- `src/app/api/v1/messages/count_tokens/route.ts`
-- `src/app/api/v1/providers/[provider]/chat/completions/route.ts` — dedicated per-provider chat
-- `src/app/api/v1/providers/[provider]/embeddings/route.ts` — dedicated per-provider embeddings
-- `src/app/api/v1/providers/[provider]/images/generations/route.ts` — dedicated per-provider images
-- `src/app/api/v1beta/models/route.ts`
-- `src/app/api/v1beta/models/[...path]/route.ts`
-
-Management domains:
-
-- Auth/settings: `src/app/api/auth/*`, `src/app/api/settings/*`
-- Providers/connections: `src/app/api/providers*`
-- Provider nodes: `src/app/api/provider-nodes*`
-- Custom models: `src/app/api/provider-models` (GET/POST/DELETE)
-- Model catalog: `src/app/api/models/route.ts` (GET)
-- Proxy config: `src/app/api/settings/proxy` (GET/PUT/DELETE) + `src/app/api/settings/proxy/test` (POST)
-- OAuth: `src/app/api/oauth/*`
-- Keys/aliases/combos/pricing: `src/app/api/keys*`, `src/app/api/models/alias`, `src/app/api/combos*`, `src/app/api/pricing`
-- Usage: `src/app/api/usage/*`
-- Sync/cloud: `src/app/api/sync/*`, `src/app/api/cloud/*`
-- CLI tooling helpers: `src/app/api/cli-tools/*`
-- IP filter: `src/app/api/settings/ip-filter` (GET/PUT)
-- Thinking budget: `src/app/api/settings/thinking-budget` (GET/PUT)
-- System prompt: `src/app/api/settings/system-prompt` (GET/PUT)
-- Sessions: `src/app/api/sessions` (GET)
-- Rate limits: `src/app/api/rate-limits` (GET)
-- Resilience: `src/app/api/resilience` (GET/PATCH) — provider profiles, circuit breaker, rate limit state
-- Resilience reset: `src/app/api/resilience/reset` (POST) — reset breakers + cooldowns
-- Cache stats: `src/app/api/cache/stats` (GET/DELETE)
-- Model availability: `src/app/api/models/availability` (GET/POST)
-- Telemetry: `src/app/api/telemetry/summary` (GET)
-- Budget: `src/app/api/usage/budget` (GET/POST)
-- Fallback chains: `src/app/api/fallback/chains` (GET/POST/DELETE)
-- Compliance audit: `src/app/api/compliance/audit-log` (GET)
-- Evals: `src/app/api/evals` (GET/POST), `src/app/api/evals/[suiteId]` (GET)
-- Policies: `src/app/api/policies` (GET/POST)
-
-## 2) SSE + Translation Core
-
-Main flow modules:
-
-- Entry: `src/sse/handlers/chat.ts`
-- Core orchestration: `open-sse/handlers/chatCore.ts`
-- Provider execution adapters: `open-sse/executors/*`
-- Format detection/provider config: `open-sse/services/provider.ts`
-- Model parse/resolve: `src/sse/services/model.ts`, `open-sse/services/model.ts`
-- Account fallback logic: `open-sse/services/accountFallback.ts`
-- Translation registry: `open-sse/translator/index.ts`
-- Stream transformations: `open-sse/utils/stream.ts`, `open-sse/utils/streamHandler.ts`
-- Usage extraction/normalization: `open-sse/utils/usageTracking.ts`
-- Think tag parser: `open-sse/utils/thinkTagParser.ts`
-- Embedding handler: `open-sse/handlers/embeddings.ts`
-- Embedding provider registry: `open-sse/config/embeddingRegistry.ts`
-- Image generation handler: `open-sse/handlers/imageGeneration.ts`
-- Image provider registry: `open-sse/config/imageRegistry.ts`
-- Response sanitization: `open-sse/handlers/responseSanitizer.ts`
-- Role normalization: `open-sse/services/roleNormalizer.ts`
-
-Services (business logic):
-
-- Account selection/scoring: `open-sse/services/accountSelector.ts`
-- Context lifecycle management: `open-sse/services/contextManager.ts`
-- IP filter enforcement: `open-sse/services/ipFilter.ts`
-- Session tracking: `open-sse/services/sessionManager.ts`
-- Request deduplication: `open-sse/services/signatureCache.ts`
-- System prompt injection: `open-sse/services/systemPrompt.ts`
-- Thinking budget management: `open-sse/services/thinkingBudget.ts`
-- Wildcard model routing: `open-sse/services/wildcardRouter.ts`
-- Rate limit management: `open-sse/services/rateLimitManager.ts`
-- Circuit breaker: `open-sse/services/circuitBreaker.ts`
-
-Domain layer modules:
-
-- Model availability: `src/lib/domain/modelAvailability.ts`
-- Cost rules/budgets: `src/lib/domain/costRules.ts`
-- Fallback policy: `src/lib/domain/fallbackPolicy.ts`
-- Combo resolver: `src/lib/domain/comboResolver.ts`
-- Lockout policy: `src/lib/domain/lockoutPolicy.ts`
-- Policy engine: `src/domain/policyEngine.ts` — centralized lockout → budget → fallback evaluation
-- Error codes catalog: `src/lib/domain/errorCodes.ts`
-- Request ID: `src/lib/domain/requestId.ts`
-- Fetch timeout: `src/lib/domain/fetchTimeout.ts`
-- Request telemetry: `src/lib/domain/requestTelemetry.ts`
-- Compliance/audit: `src/lib/domain/compliance/index.ts`
-- Eval runner: `src/lib/domain/evalRunner.ts`
-- Domain state persistence: `src/lib/db/domainState.ts` — SQLite CRUD for fallback chains, budgets, cost history, lockout state, circuit breakers
-
-OAuth provider modules (12 individual files under `src/lib/oauth/providers/`):
-
-- Registry index: `src/lib/oauth/providers/index.ts`
-- Individual providers: `claude.ts`, `codex.ts`, `gemini.ts`, `antigravity.ts`, `qoder.ts`, `qwen.ts`, `kimi-coding.ts`, `github.ts`, `kiro.ts`, `cursor.ts`, `kilocode.ts`, `cline.ts`
-- Thin wrapper: `src/lib/oauth/providers.ts` — re-exports from individual modules
-
-## 3) Persistence Layer
-
-Primary state DB (SQLite):
-
-- Core infra: `src/lib/db/core.ts` (better-sqlite3, migrations, WAL)
-- Re-export facade: `src/lib/localDb.ts` (thin compatibility layer for callers)
-- file: `${DATA_DIR}/storage.sqlite` (or `$XDG_CONFIG_HOME/omniroute/storage.sqlite` when set, else `~/.omniroute/storage.sqlite`)
-- entities (tables + KV namespaces): providerConnections, providerNodes, modelAliases, combos, apiKeys, settings, pricing, **customModels**, **proxyConfig**, **ipFilter**, **thinkingBudget**, **systemPrompt**
-
-Usage persistence:
-
-- facade: `src/lib/usageDb.ts` (decomposed modules in `src/lib/usage/*`)
-- SQLite tables in `storage.sqlite`: `usage_history`, `call_logs`, `proxy_logs`
-- optional file artifacts remain for compatibility/debug (`${DATA_DIR}/log.txt`, `${DATA_DIR}/call_logs/`, `/logs/...`)
-- legacy JSON files are migrated to SQLite by startup migrations when present
-
-Domain State DB (SQLite):
-
-- `src/lib/db/domainState.ts` — CRUD operations for domain state
-- Tables (created in `src/lib/db/core.ts`): `domain_fallback_chains`, `domain_budgets`, `domain_cost_history`, `domain_lockout_state`, `domain_circuit_breakers`
-- Write-through cache pattern: in-memory Maps are authoritative at runtime; mutations are written synchronously to SQLite; state is restored from DB on cold start
-
-## 4) Auth + Security Surfaces
-
-- Dashboard cookie auth: `src/proxy.ts`, `src/app/api/auth/login/route.ts`
-- API key generation/verification: `src/shared/utils/apiKey.ts`
-- Provider secrets persisted in `providerConnections` entries
-- Outbound proxy support via `open-sse/utils/proxyFetch.ts` (env vars) and `open-sse/utils/networkProxy.ts` (configurable per-provider or global)
-
-## 5) Cloud Sync
-
-- Scheduler init: `src/lib/initCloudSync.ts`, `src/shared/services/initializeCloudSync.ts`
-- Periodic task: `src/shared/services/cloudSyncScheduler.ts`
-- Control route: `src/app/api/sync/cloud/route.ts`
-
-## Request Lifecycle (`/v1/chat/completions`)
-
-```mermaid
-sequenceDiagram
- autonumber
- participant Client as CLI/SDK Client
- participant Route as /api/v1/chat/completions
- participant Chat as src/sse/handlers/chat
- participant Core as open-sse/handlers/chatCore
- participant Model as Model Resolver
- participant Auth as Credential Selector
- participant Exec as Provider Executor
- participant Prov as Upstream Provider
- participant Stream as Stream Translator
- participant Usage as usageDb
-
- Client->>Route: POST /v1/chat/completions
- Route->>Chat: handleChat(request)
- Chat->>Model: parse/resolve model or combo
-
- alt Combo model
- Chat->>Chat: iterate combo models (handleComboChat)
- end
-
- Chat->>Auth: getProviderCredentials(provider)
- Auth-->>Chat: active account + tokens/api key
-
- Chat->>Core: handleChatCore(body, modelInfo, credentials)
- Core->>Core: detect source format
- Core->>Core: translate request to target format
- Core->>Exec: execute(provider, transformedBody)
- Exec->>Prov: upstream API call
- Prov-->>Exec: SSE/JSON response
- Exec-->>Core: response + metadata
-
- alt 401/403
- Core->>Exec: refreshCredentials()
- Exec-->>Core: updated tokens
- Core->>Exec: retry request
- end
-
- Core->>Stream: translate/normalize stream to client format
- Stream-->>Client: SSE chunks / JSON response
-
- Stream->>Usage: extract usage + persist history/log
-```
-
-## Combo + Account Fallback Flow
-
-```mermaid
-flowchart TD
- A[Incoming model string] --> B{Is combo name?}
- B -- Yes --> C[Load combo models sequence]
- B -- No --> D[Single model path]
-
- C --> E[Try model N]
- E --> F[Resolve provider/model]
- D --> F
-
- F --> G[Select account credentials]
- G --> H{Credentials available?}
- H -- No --> I[Return provider unavailable]
- H -- Yes --> J[Execute request]
-
- J --> K{Success?}
- K -- Yes --> L[Return response]
- K -- No --> M{Fallback-eligible error?}
-
- M -- No --> N[Return error]
- M -- Yes --> O[Mark account unavailable cooldown]
- O --> P{Another account for provider?}
- P -- Yes --> G
- P -- No --> Q{In combo with next model?}
- Q -- Yes --> E
- Q -- No --> R[Return all unavailable]
-```
-
-Fallback decisions are driven by `open-sse/services/accountFallback.ts` using status codes and error-message heuristics.
-
-## OAuth Onboarding and Token Refresh Lifecycle
-
-```mermaid
-sequenceDiagram
- autonumber
- participant UI as Dashboard UI
- participant OAuth as /api/oauth/[provider]/[action]
- participant ProvAuth as Provider Auth Server
- participant DB as localDb
- participant Test as /api/providers/[id]/test
- participant Exec as Provider Executor
-
- UI->>OAuth: GET authorize or device-code
- OAuth->>ProvAuth: create auth/device flow
- ProvAuth-->>OAuth: auth URL or device code payload
- OAuth-->>UI: flow data
-
- UI->>OAuth: POST exchange or poll
- OAuth->>ProvAuth: token exchange/poll
- ProvAuth-->>OAuth: access/refresh tokens
- OAuth->>DB: createProviderConnection(oauth data)
- OAuth-->>UI: success + connection id
-
- UI->>Test: POST /api/providers/[id]/test
- Test->>Exec: validate credentials / optional refresh
- Exec-->>Test: valid or refreshed token info
- Test->>DB: update status/tokens/errors
- Test-->>UI: validation result
-```
-
-Refresh during live traffic is executed inside `open-sse/handlers/chatCore.ts` via executor `refreshCredentials()`.
-
-## Cloud Sync Lifecycle (Enable / Sync / Disable)
-
-```mermaid
-sequenceDiagram
- autonumber
- participant UI as Endpoint Page UI
- participant Sync as /api/sync/cloud
- participant DB as localDb
- participant Cloud as External Cloud Sync
- participant Claude as ~/.claude/settings.json
-
- UI->>Sync: POST action=enable
- Sync->>DB: set cloudEnabled=true
- Sync->>DB: ensure API key exists
- Sync->>Cloud: POST /sync/{machineId} (providers/aliases/combos/keys)
- Cloud-->>Sync: sync result
- Sync->>Cloud: GET /{machineId}/v1/verify
- Sync-->>UI: enabled + verification status
-
- UI->>Sync: POST action=sync
- Sync->>Cloud: POST /sync/{machineId}
- Cloud-->>Sync: remote data
- Sync->>DB: update newer local tokens/status
- Sync-->>UI: synced
-
- UI->>Sync: POST action=disable
- Sync->>DB: set cloudEnabled=false
- Sync->>Cloud: DELETE /sync/{machineId}
- Sync->>Claude: switch ANTHROPIC_BASE_URL back to local (if needed)
- Sync-->>UI: disabled
-```
-
-Periodic sync is triggered by `CloudSyncScheduler` when cloud is enabled.
-
-## Data Model and Storage Map
-
-```mermaid
-erDiagram
- SETTINGS ||--o{ PROVIDER_CONNECTION : controls
- PROVIDER_NODE ||--o{ PROVIDER_CONNECTION : backs_compatible_provider
- PROVIDER_CONNECTION ||--o{ USAGE_ENTRY : emits_usage
-
- SETTINGS {
- boolean cloudEnabled
- number stickyRoundRobinLimit
- boolean requireLogin
- string password_hash
- string fallbackStrategy
- json rateLimitDefaults
- json providerProfiles
- }
-
- PROVIDER_CONNECTION {
- string id
- string provider
- string authType
- string name
- number priority
- boolean isActive
- string apiKey
- string accessToken
- string refreshToken
- string expiresAt
- string testStatus
- string lastError
- string rateLimitedUntil
- json providerSpecificData
- }
-
- PROVIDER_NODE {
- string id
- string type
- string name
- string prefix
- string apiType
- string baseUrl
- }
-
- MODEL_ALIAS {
- string alias
- string targetModel
- }
-
- COMBO {
- string id
- string name
- string[] models
- }
-
- API_KEY {
- string id
- string name
- string key
- string machineId
- }
-
- USAGE_ENTRY {
- string provider
- string model
- number prompt_tokens
- number completion_tokens
- string connectionId
- string timestamp
- }
-
- CUSTOM_MODEL {
- string id
- string name
- string providerId
- }
-
- PROXY_CONFIG {
- string global
- json providers
- }
-
- IP_FILTER {
- string mode
- string[] allowlist
- string[] blocklist
- }
-
- THINKING_BUDGET {
- string mode
- number customBudget
- string effortLevel
- }
-
- SYSTEM_PROMPT {
- boolean enabled
- string prompt
- string position
- }
-```
-
-Physical storage files:
-
-- primary runtime DB: `${DATA_DIR}/storage.sqlite`
-- request log lines: `${DATA_DIR}/log.txt` (compat/debug artifact)
-- structured call payload archives: `${DATA_DIR}/call_logs/`
-- optional translator/request debug sessions: `/logs/...`
-
-## Deployment Topology
-
-```mermaid
-flowchart LR
- subgraph LocalHost[Developer Host]
- CLI[CLI Tools]
- Browser[Dashboard Browser]
- end
-
- subgraph ContainerOrProcess[OmniRoute Runtime]
- Next[Next.js Server\nPORT=20128]
- Core[SSE Core + Executors]
- MainDB[(storage.sqlite)]
- UsageDB[(usage tables + log artifacts)]
- end
-
- subgraph External[External Services]
- Providers[AI Providers]
- SyncCloud[Cloud Sync Service]
- end
-
- CLI --> Next
- Browser --> Next
- Next --> Core
- Next --> MainDB
- Core --> MainDB
- Core --> UsageDB
- Core --> Providers
- Next --> SyncCloud
-```
-
-## Module Mapping (Decision-Critical)
-
-### Route and API Modules
-
-- `src/app/api/v1/*`, `src/app/api/v1beta/*`: compatibility APIs
-- `src/app/api/v1/providers/[provider]/*`: dedicated per-provider routes (chat, embeddings, images)
-- `src/app/api/providers*`: provider CRUD, validation, testing
-- `src/app/api/provider-nodes*`: custom compatible node management
-- `src/app/api/provider-models`: custom model management (CRUD)
-- `src/app/api/models/route.ts`: model catalog API (aliases + custom models)
-- `src/app/api/oauth/*`: OAuth/device-code flows
-- `src/app/api/keys*`: local API key lifecycle
-- `src/app/api/models/alias`: alias management
-- `src/app/api/combos*`: fallback combo management
-- `src/app/api/pricing`: pricing overrides for cost calculation
-- `src/app/api/settings/proxy`: proxy configuration (GET/PUT/DELETE)
-- `src/app/api/settings/proxy/test`: outbound proxy connectivity test (POST)
-- `src/app/api/usage/*`: usage and logs APIs
-- `src/app/api/sync/*` + `src/app/api/cloud/*`: cloud sync and cloud-facing helpers
-- `src/app/api/cli-tools/*`: local CLI config writers/checkers
-- `src/app/api/settings/ip-filter`: IP allowlist/blocklist (GET/PUT)
-- `src/app/api/settings/thinking-budget`: thinking token budget config (GET/PUT)
-- `src/app/api/settings/system-prompt`: global system prompt (GET/PUT)
-- `src/app/api/sessions`: active session listing (GET)
-- `src/app/api/rate-limits`: per-account rate limit status (GET)
-
-### Routing and Execution Core
-
-- `src/sse/handlers/chat.ts`: request parse, combo handling, account selection loop
-- `open-sse/handlers/chatCore.ts`: translation, executor dispatch, retry/refresh handling, stream setup
-- `open-sse/executors/*`: provider-specific network and format behavior
-
-### Translation Registry and Format Converters
-
-- `open-sse/translator/index.ts`: translator registry and orchestration
-- Request translators: `open-sse/translator/request/*`
-- Response translators: `open-sse/translator/response/*`
-- Format constants: `open-sse/translator/formats.ts`
-
-### Persistence
-
-- `src/lib/db/*`: persistent config/state and domain persistence on SQLite
-- `src/lib/localDb.ts`: compatibility re-export for DB modules
-- `src/lib/usageDb.ts`: usage history/call logs facade on top of SQLite tables
-
-## Provider Executor Coverage (Strategy Pattern)
-
-Each provider has a specialized executor extending `BaseExecutor` (in `open-sse/executors/base.ts`), which provides URL building, header construction, retry with exponential backoff, credential refresh hooks, and the `execute()` orchestration method.
-
-| Executor | Provider(s) | Special Handling |
-| --------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------ | -------------------------------------------------------------------- |
-| `DefaultExecutor` | OpenAI, Claude, Gemini, Qwen, Qoder, OpenRouter, GLM, Kimi, MiniMax, DeepSeek, Groq, xAI, Mistral, Perplexity, Together, Fireworks, Cerebras, Cohere, NVIDIA | Dynamic URL/header config per provider |
-| `AntigravityExecutor` | Google Antigravity | Custom project/session IDs, Retry-After parsing |
-| `CodexExecutor` | OpenAI Codex | Injects system instructions, forces reasoning effort |
-| `CursorExecutor` | Cursor IDE | ConnectRPC protocol, Protobuf encoding, request signing via checksum |
-| `GithubExecutor` | GitHub Copilot | Copilot token refresh, VSCode-mimicking headers |
-| `KiroExecutor` | AWS CodeWhisperer/Kiro | AWS EventStream binary format → SSE conversion |
-| `GeminiCLIExecutor` | Gemini CLI | Google OAuth token refresh cycle |
-
-All other providers (including custom compatible nodes) use the `DefaultExecutor`.
-
-## Provider Compatibility Matrix
-
-| Provider | Format | Auth | Stream | Non-Stream | Token Refresh | Usage API |
-| ---------------- | ---------------- | --------------------- | ---------------- | ---------- | ------------- | ------------------ |
-| Claude | claude | API Key / OAuth | ✅ | ✅ | ✅ | ⚠️ Admin only |
-| Gemini | gemini | API Key / OAuth | ✅ | ✅ | ✅ | ⚠️ Cloud Console |
-| Gemini CLI | gemini-cli | OAuth | ✅ | ✅ | ✅ | ⚠️ Cloud Console |
-| Antigravity | antigravity | OAuth | ✅ | ✅ | ✅ | ✅ Full quota API |
-| OpenAI | openai | API Key | ✅ | ✅ | ❌ | ❌ |
-| Codex | openai-responses | OAuth | ✅ forced | ❌ | ✅ | ✅ Rate limits |
-| GitHub Copilot | openai | OAuth + Copilot Token | ✅ | ✅ | ✅ | ✅ Quota snapshots |
-| Cursor | cursor | Custom checksum | ✅ | ✅ | ❌ | ❌ |
-| Kiro | kiro | AWS SSO OIDC | ✅ (EventStream) | ❌ | ✅ | ✅ Usage limits |
-| Qwen | openai | OAuth | ✅ | ✅ | ✅ | ⚠️ Per request |
-| Qoder | openai | OAuth (Basic) | ✅ | ✅ | ✅ | ⚠️ Per request |
-| OpenRouter | openai | API Key | ✅ | ✅ | ❌ | ❌ |
-| GLM/Kimi/MiniMax | claude | API Key | ✅ | ✅ | ❌ | ❌ |
-| DeepSeek | openai | API Key | ✅ | ✅ | ❌ | ❌ |
-| Groq | openai | API Key | ✅ | ✅ | ❌ | ❌ |
-| xAI (Grok) | openai | API Key | ✅ | ✅ | ❌ | ❌ |
-| Mistral | openai | API Key | ✅ | ✅ | ❌ | ❌ |
-| Perplexity | openai | API Key | ✅ | ✅ | ❌ | ❌ |
-| Together AI | openai | API Key | ✅ | ✅ | ❌ | ❌ |
-| Fireworks AI | openai | API Key | ✅ | ✅ | ❌ | ❌ |
-| Cerebras | openai | API Key | ✅ | ✅ | ❌ | ❌ |
-| Cohere | openai | API Key | ✅ | ✅ | ❌ | ❌ |
-| NVIDIA NIM | openai | API Key | ✅ | ✅ | ❌ | ❌ |
-
-## Format Translation Coverage
-
-Detected source formats include:
-
-- `openai`
-- `openai-responses`
-- `claude`
-- `gemini`
-
-Target formats include:
-
-- OpenAI chat/Responses
-- Claude
-- Gemini/Gemini-CLI/Antigravity envelope
-- Kiro
-- Cursor
-
-Translations use **OpenAI as the hub format** — all conversions go through OpenAI as intermediate:
-
-```
-Source Format → OpenAI (hub) → Target Format
-```
-
-Translations are selected dynamically based on source payload shape and provider target format.
-
-Additional processing layers in the translation pipeline:
-
-- **Response sanitization** — Strips non-standard fields from OpenAI-format responses (both streaming and non-streaming) to ensure strict SDK compliance
-- **Role normalization** — Converts `developer` → `system` for non-OpenAI targets; merges `system` → `user` for models that reject the system role (GLM, ERNIE)
-- **Think tag extraction** — Parses `...` blocks from content into `reasoning_content` field
-- **Structured output** — Converts OpenAI `response_format.json_schema` to Gemini's `responseMimeType` + `responseSchema`
-
-## Supported API Endpoints
-
-| Endpoint | Format | Handler |
-| -------------------------------------------------- | ------------------ | ---------------------------------------------------- |
-| `POST /v1/chat/completions` | OpenAI Chat | `src/sse/handlers/chat.ts` |
-| `POST /v1/messages` | Claude Messages | Same handler (auto-detected) |
-| `POST /v1/responses` | OpenAI Responses | `open-sse/handlers/responsesHandler.ts` |
-| `POST /v1/embeddings` | OpenAI Embeddings | `open-sse/handlers/embeddings.ts` |
-| `GET /v1/embeddings` | Model listing | API route |
-| `POST /v1/images/generations` | OpenAI Images | `open-sse/handlers/imageGeneration.ts` |
-| `GET /v1/images/generations` | Model listing | API route |
-| `POST /v1/providers/{provider}/chat/completions` | OpenAI Chat | Dedicated per-provider with model validation |
-| `POST /v1/providers/{provider}/embeddings` | OpenAI Embeddings | Dedicated per-provider with model validation |
-| `POST /v1/providers/{provider}/images/generations` | OpenAI Images | Dedicated per-provider with model validation |
-| `POST /v1/messages/count_tokens` | Claude Token Count | API route |
-| `GET /v1/models` | OpenAI Models list | API route (chat + embedding + image + custom models) |
-| `GET /api/models/catalog` | Catalog | All models grouped by provider + type |
-| `POST /v1beta/models/*:streamGenerateContent` | Gemini native | API route |
-| `GET/PUT/DELETE /api/settings/proxy` | Proxy Config | Network proxy configuration |
-| `POST /api/settings/proxy/test` | Proxy Connectivity | Proxy health/connectivity test endpoint |
-| `GET/POST/DELETE /api/provider-models` | Custom Models | Custom model management per provider |
-
-## Bypass Handler
-
-The bypass handler (`open-sse/utils/bypassHandler.ts`) intercepts known "throwaway" requests from Claude CLI — warmup pings, title extractions, and token counts — and returns a **fake response** without consuming upstream provider tokens. This is triggered only when `User-Agent` contains `claude-cli`.
-
-## Request Logger Pipeline
-
-The request logger (`open-sse/utils/requestLogger.ts`) provides a 7-stage debug logging pipeline, disabled by default, enabled via `ENABLE_REQUEST_LOGS=true`:
-
-```
-1_req_client.json → 2_req_source.json → 3_req_openai.json → 4_req_target.json
-→ 5_res_provider.txt → 6_res_openai.txt → 7_res_client.txt
-```
-
-Files are written to `/logs//` for each request session.
-
-## Failure Modes and Resilience
-
-## 1) Account/Provider Availability
-
-- provider account cooldown on transient/rate/auth errors
-- account fallback before failing request
-- combo model fallback when current model/provider path is exhausted
-
-## 2) Token Expiry
-
-- pre-check and refresh with retry for refreshable providers
-- 401/403 retry after refresh attempt in core path
-
-## 3) Stream Safety
-
-- disconnect-aware stream controller
-- translation stream with end-of-stream flush and `[DONE]` handling
-- usage estimation fallback when provider usage metadata is missing
-
-## 4) Cloud Sync Degradation
-
-- sync errors are surfaced but local runtime continues
-- scheduler has retry-capable logic, but periodic execution currently calls single-attempt sync by default
-
-## 5) Data Integrity
-
-- SQLite schema migrations and auto-upgrade hooks at startup
-- legacy JSON → SQLite migration compatibility path
-
-## Observability and Operational Signals
-
-Runtime visibility sources:
-
-- console logs from `src/sse/utils/logger.ts`
-- per-request usage aggregates in SQLite (`usage_history`, `call_logs`, `proxy_logs`)
-- textual request status log in `log.txt` (optional/compat)
-- optional deep request/translation logs under `logs/` when `ENABLE_REQUEST_LOGS=true`
-- dashboard usage endpoints (`/api/usage/*`) for UI consumption
-
-## Security-Sensitive Boundaries
-
-- JWT secret (`JWT_SECRET`) secures dashboard session cookie verification/signing
-- Initial password bootstrap (`INITIAL_PASSWORD`) should be explicitly configured for first-run provisioning
-- API key HMAC secret (`API_KEY_SECRET`) secures generated local API key format
-- Provider secrets (API keys/tokens) are persisted in local DB and should be protected at filesystem level
-- Cloud sync endpoints rely on API key auth + machine id semantics
-
-## Environment and Runtime Matrix
-
-Environment variables actively used by code:
-
-- App/auth: `JWT_SECRET`, `INITIAL_PASSWORD`
-- Storage: `DATA_DIR`
-- Compatible node behavior: `ALLOW_MULTI_CONNECTIONS_PER_COMPAT_NODE`
-- Optional storage base override (Linux/macOS when `DATA_DIR` unset): `XDG_CONFIG_HOME`
-- Security hashing: `API_KEY_SECRET`, `MACHINE_ID_SALT`
-- Logging: `ENABLE_REQUEST_LOGS`
-- Sync/cloud URLing: `NEXT_PUBLIC_BASE_URL`, `NEXT_PUBLIC_CLOUD_URL`
-- Outbound proxy: `HTTP_PROXY`, `HTTPS_PROXY`, `ALL_PROXY`, `NO_PROXY` and lowercase variants
-- SOCKS5 feature flags: `ENABLE_SOCKS5_PROXY`, `NEXT_PUBLIC_ENABLE_SOCKS5_PROXY`
-- Platform/runtime helpers (not app-specific config): `APPDATA`, `NODE_ENV`, `PORT`, `HOSTNAME`
-
-## Known Architectural Notes
-
-1. `usageDb` and `localDb` share the same base directory policy (`DATA_DIR` -> `XDG_CONFIG_HOME/omniroute` -> `~/.omniroute`) with legacy file migration.
-2. `/api/v1/route.ts` delegates to the same unified catalog builder used by `/api/v1/models` (`src/app/api/v1/models/catalog.ts`) to avoid semantic drift.
-3. Request logger writes full headers/body when enabled; treat log directory as sensitive.
-4. Cloud behavior depends on correct `NEXT_PUBLIC_BASE_URL` and cloud endpoint reachability.
-5. The `open-sse/` directory is published as the `@omniroute/open-sse` **npm workspace package**. Source code imports it via `@omniroute/open-sse/...` (resolved by Next.js `transpilePackages`). File paths in this document still use the directory name `open-sse/` for consistency.
-6. Charts in the dashboard use **Recharts** (SVG-based) for accessible, interactive analytics visualizations (model usage bar charts, provider breakdown tables with success rates).
-7. E2E tests use **Playwright** (`tests/e2e/`), run via `npm run test:e2e`. Unit tests use **Node.js test runner** (`tests/unit/`), run via `npm run test:unit`. Source code under `src/` is **TypeScript** (`.ts`/`.tsx`); the `open-sse/` workspace remains JavaScript (`.js`).
-8. Settings page is organized into 5 tabs: Security, Routing (6 global strategies: fill-first, round-robin, p2c, random, least-used, cost-optimized), Resilience (editable rate limits, circuit breaker, policies), AI (thinking budget, system prompt, prompt cache), Advanced (proxy).
-
-## Operational Verification Checklist
-
-- Build from source: `npm run build`
-- Build Docker image: `docker build -t omniroute .`
-- Start service and verify:
-- `GET /api/settings`
-- `GET /api/v1/models`
-- CLI target base URL should be `http://:20128/v1` when `PORT=20128`
diff --git a/docs/i18n/he/AUTO-COMBO.md b/docs/i18n/he/AUTO-COMBO.md
deleted file mode 100644
index 2166e41dff..0000000000
--- a/docs/i18n/he/AUTO-COMBO.md
+++ /dev/null
@@ -1,67 +0,0 @@
-🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/AUTO-COMBO.md) · 🇪🇸 [es](../es/AUTO-COMBO.md) · 🇫🇷 [fr](../fr/AUTO-COMBO.md) · 🇩🇪 [de](../de/AUTO-COMBO.md) · 🇮🇹 [it](../it/AUTO-COMBO.md) · 🇷🇺 [ru](../ru/AUTO-COMBO.md) · 🇨🇳 [zh-CN](../zh-CN/AUTO-COMBO.md) · 🇯🇵 [ja](../ja/AUTO-COMBO.md) · 🇰🇷 [ko](../ko/AUTO-COMBO.md) · 🇸🇦 [ar](../ar/AUTO-COMBO.md) · 🇮🇳 [in](../in/AUTO-COMBO.md) · 🇹🇭 [th](../th/AUTO-COMBO.md) · 🇻🇳 [vi](../vi/AUTO-COMBO.md) · 🇮🇩 [id](../id/AUTO-COMBO.md) · 🇲🇾 [ms](../ms/AUTO-COMBO.md) · 🇳🇱 [nl](../nl/AUTO-COMBO.md) · 🇵🇱 [pl](../pl/AUTO-COMBO.md) · 🇸🇪 [sv](../sv/AUTO-COMBO.md) · 🇳🇴 [no](../no/AUTO-COMBO.md) · 🇩🇰 [da](../da/AUTO-COMBO.md) · 🇫🇮 [fi](../fi/AUTO-COMBO.md) · 🇵🇹 [pt](../pt/AUTO-COMBO.md) · 🇷🇴 [ro](../ro/AUTO-COMBO.md) · 🇭🇺 [hu](../hu/AUTO-COMBO.md) · 🇧🇬 [bg](../bg/AUTO-COMBO.md) · 🇸🇰 [sk](../sk/AUTO-COMBO.md) · 🇺🇦 [uk-UA](../uk-UA/AUTO-COMBO.md) · 🇮🇱 [he](../he/AUTO-COMBO.md) · 🇵🇭 [phi](../phi/AUTO-COMBO.md)
-
----
-
-# OmniRoute Auto-Combo Engine
-
-> Self-managing model chains with adaptive scoring
-
-## How It Works
-
-The Auto-Combo Engine dynamically selects the best provider/model for each request using a **6-factor scoring function**:
-
-| Factor | Weight | Description |
-| :--------- | :----- | :---------------------------------------------- |
-| Quota | 0.20 | Remaining capacity [0..1] |
-| Health | 0.25 | Circuit breaker: CLOSED=1.0, HALF=0.5, OPEN=0.0 |
-| CostInv | 0.20 | Inverse cost (cheaper = higher score) |
-| LatencyInv | 0.15 | Inverse p95 latency (faster = higher) |
-| TaskFit | 0.10 | Model × task type fitness score |
-| Stability | 0.10 | Low variance in latency/errors |
-
-## Mode Packs
-
-| Pack | Focus | Key Weight |
-| :---------------------- | :----------- | :--------------- |
-| 🚀 **Ship Fast** | Speed | latencyInv: 0.35 |
-| 💰 **Cost Saver** | Economy | costInv: 0.40 |
-| 🎯 **Quality First** | Best model | taskFit: 0.40 |
-| 📡 **Offline Friendly** | Availability | quota: 0.40 |
-
-## Self-Healing
-
-- **Temporary exclusion**: Score < 0.2 → excluded for 5 min (progressive backoff, max 30 min)
-- **Circuit breaker awareness**: OPEN → auto-excluded; HALF_OPEN → probe requests
-- **Incident mode**: >50% OPEN → disable exploration, maximize stability
-- **Cooldown recovery**: After exclusion, first request is a "probe" with reduced timeout
-
-## Bandit Exploration
-
-5% of requests (configurable) are routed to random providers for exploration. Disabled in incident mode.
-
-## API
-
-```bash
-# Create auto-combo
-curl -X POST http://localhost:20128/api/combos/auto \
- -H "Content-Type: application/json" \
- -d '{"id":"my-auto","name":"Auto Coder","candidatePool":["anthropic","google","openai"],"modePack":"ship-fast"}'
-
-# List auto-combos
-curl http://localhost:20128/api/combos/auto
-```
-
-## Task Fitness
-
-30+ models scored across 6 task types (`coding`, `review`, `planning`, `analysis`, `debugging`, `documentation`). Supports wildcard patterns (e.g., `*-coder` → high coding score).
-
-## Files
-
-| File | Purpose |
-| :------------------------------------------- | :------------------------------------ |
-| `open-sse/services/autoCombo/scoring.ts` | Scoring function & pool normalization |
-| `open-sse/services/autoCombo/taskFitness.ts` | Model × task fitness lookup |
-| `open-sse/services/autoCombo/engine.ts` | Selection logic, bandit, budget cap |
-| `open-sse/services/autoCombo/selfHealing.ts` | Exclusion, probes, incident mode |
-| `open-sse/services/autoCombo/modePacks.ts` | 4 weight profiles |
-| `src/app/api/combos/auto/route.ts` | REST API |
diff --git a/docs/i18n/he/CHANGELOG.md b/docs/i18n/he/CHANGELOG.md
index 83a4241e34..eb36ed44ba 100644
--- a/docs/i18n/he/CHANGELOG.md
+++ b/docs/i18n/he/CHANGELOG.md
@@ -1,12 +1,92 @@
# Changelog (עברית)
-🌐 **Languages:** 🇺🇸 [English](../../../CHANGELOG.md) · 🇪🇸 [es](../es/CHANGELOG.md) · 🇫🇷 [fr](../fr/CHANGELOG.md) · 🇩🇪 [de](../de/CHANGELOG.md) · 🇮🇹 [it](../it/CHANGELOG.md) · 🇷🇺 [ru](../ru/CHANGELOG.md) · 🇨🇳 [zh-CN](../zh-CN/CHANGELOG.md) · 🇯🇵 [ja](../ja/CHANGELOG.md) · 🇰🇷 [ko](../ko/CHANGELOG.md) · 🇸🇦 [ar](../ar/CHANGELOG.md) · 🇮🇳 [in](../in/CHANGELOG.md) · 🇹🇭 [th](../th/CHANGELOG.md) · 🇻🇳 [vi](../vi/CHANGELOG.md) · 🇮🇩 [id](../id/CHANGELOG.md) · 🇲🇾 [ms](../ms/CHANGELOG.md) · 🇳🇱 [nl](../nl/CHANGELOG.md) · 🇵🇱 [pl](../pl/CHANGELOG.md) · 🇸🇪 [sv](../sv/CHANGELOG.md) · 🇳🇴 [no](../no/CHANGELOG.md) · 🇩🇰 [da](../da/CHANGELOG.md) · 🇫🇮 [fi](../fi/CHANGELOG.md) · 🇵🇹 [pt](../pt/CHANGELOG.md) · 🇷🇴 [ro](../ro/CHANGELOG.md) · 🇭🇺 [hu](../hu/CHANGELOG.md) · 🇧🇬 [bg](../bg/CHANGELOG.md) · 🇸🇰 [sk](../sk/CHANGELOG.md) · 🇺🇦 [uk-UA](../uk-UA/CHANGELOG.md) · 🇮🇱 [he](../he/CHANGELOG.md) · 🇵🇭 [phi](../phi/CHANGELOG.md) · 🇧🇷 [pt-BR](../pt-BR/CHANGELOG.md)
+🌐 **Languages:** 🇺🇸 [English](../../../CHANGELOG.md) · 🇪🇸 [es](../es/CHANGELOG.md) · 🇫🇷 [fr](../fr/CHANGELOG.md) · 🇩🇪 [de](../de/CHANGELOG.md) · 🇮🇹 [it](../it/CHANGELOG.md) · 🇷🇺 [ru](../ru/CHANGELOG.md) · 🇨🇳 [zh-CN](../zh-CN/CHANGELOG.md) · 🇯🇵 [ja](../ja/CHANGELOG.md) · 🇰🇷 [ko](../ko/CHANGELOG.md) · 🇸🇦 [ar](../ar/CHANGELOG.md) · 🇮🇳 [in](../in/CHANGELOG.md) · 🇹🇭 [th](../th/CHANGELOG.md) · 🇻🇳 [vi](../vi/CHANGELOG.md) · 🇮🇩 [id](../id/CHANGELOG.md) · 🇲🇾 [ms](../ms/CHANGELOG.md) · 🇳🇱 [nl](../nl/CHANGELOG.md) · 🇵🇱 [pl](../pl/CHANGELOG.md) · 🇸🇪 [sv](../sv/CHANGELOG.md) · 🇳🇴 [no](../no/CHANGELOG.md) · 🇩🇰 [da](../da/CHANGELOG.md) · 🇫🇮 [fi](../fi/CHANGELOG.md) · 🇵🇹 [pt](../pt/CHANGELOG.md) · 🇷🇴 [ro](../ro/CHANGELOG.md) · 🇭🇺 [hu](../hu/CHANGELOG.md) · 🇧🇬 [bg](../bg/CHANGELOG.md) · 🇸🇰 [sk](../sk/CHANGELOG.md) · 🇺🇦 [uk-UA](../uk-UA/CHANGELOG.md) · 🇮🇱 [he](../he/CHANGELOG.md) · 🇵🇭 [phi](../phi/CHANGELOG.md) · 🇧🇷 [pt-BR](../pt-BR/CHANGELOG.md) · 🇨🇿 [cs](../cs/CHANGELOG.md)
---
-
## [Unreleased]
+### 🛠️ Maintenance
+
+- **AGENTS.md rewrite:** Condensed from 297→153 lines. Added build/lint/test commands (including single-test execution), code style guidelines (Prettier, TypeScript, ESLint, naming, imports, error handling, security), and trimmed verbose architecture tables for AI agent consumption.
+
+## [3.4.2] - 2026-04-01
+
+### 🐛 Bug Fixes
+
+- **CI Stabilization:** Fixed failing analytics/settings Playwright selectors and request assertions so GitHub Actions E2E runs pass reliably across localized UIs and switch-based controls.
+- **Deterministic Tests:** Removed date-sensitive quota fixtures from Copilot usage tests and aligned idempotency/model catalog tests with the merged runtime behavior.
+- **MCP Type Hardening:** Removed zero-budget explicit `any` regressions from the MCP server tool registration path, restoring the `check:any-budget:t11` workflow gate.
+
+### 🛠️ Maintenance
+
+- **Release Branch Integration:** Consolidated the active feature branches into `release/v3.4.2` on top of current `main` and validated the branch with lint, unit, coverage, build, and CI-mode E2E runs.
+
+## [3.4.1] - 2026-03-31
+
+> [!WARNING]
+> **BREAKING CHANGE: request logging, retention, and logging environment variables have been redesigned.**
+> On the first startup after upgrading, OmniRoute archives legacy request logs from `DATA_DIR/logs/`, legacy `DATA_DIR/call_logs/`, and `DATA_DIR/log.txt` into `DATA_DIR/log_archives/*.zip`, then removes the deprecated layout and switches to the new unified artifact format under `DATA_DIR/call_logs/`.
+
+### ✨ New Features
+
+- **.ENV Migration Utility:** Included `scripts/migrate-env.mjs` to seamlessly migrate ` Your key looks like: `sk-xxxxxxxxxxxxxxxx-xxxxxxxxx`
-
----
-
-## Step 2 — Install CLI Tools
-
-All npm-based tools require Node.js 18+:
-
-```bash
-# Claude Code (Anthropic)
-npm install -g @anthropic-ai/claude-code
-
-# OpenAI Codex
-npm install -g @openai/codex
-
-# Gemini CLI (Google)
-npm install -g @google/gemini-cli
-
-# OpenCode
-npm install -g opencode-ai
-
-# Cline
-npm install -g cline
-
-# KiloCode
-npm install -g kilecode
-
-# Kiro CLI (Amazon — requires curl + unzip)
-apt-get install -y unzip # on Debian/Ubuntu
-curl -fsSL https://cli.kiro.dev/install | bash
-export PATH="$HOME/.local/bin:$PATH" # add to ~/.bashrc
-```
-
-**Verify:**
-
-```bash
-claude --version # 2.x.x
-codex --version # 0.x.x
-gemini --version # 0.x.x
-opencode --version # x.x.x
-cline --version # 2.x.x
-kilocode --version # x.x.x (or: kilo --version)
-kiro-cli --version # 1.x.x
-```
-
----
-
-## Step 3 — Set Global Environment Variables
-
-Add to `~/.bashrc` (or `~/.zshrc`), then run `source ~/.bashrc`:
-
-```bash
-# OmniRoute Universal Endpoint
-export OPENAI_BASE_URL="http://localhost:20128/v1"
-export OPENAI_API_KEY="sk-your-omniroute-key"
-export ANTHROPIC_BASE_URL="http://localhost:20128/v1"
-export ANTHROPIC_API_KEY="sk-your-omniroute-key"
-export GEMINI_BASE_URL="http://localhost:20128/v1"
-export GEMINI_API_KEY="sk-your-omniroute-key"
-```
-
-> For a **remote server** replace `localhost:20128` with the server IP or domain,
-> e.g. `http://192.168.0.15:20128`.
-
----
-
-## Step 4 — Configure Each Tool
-
-### Claude Code
-
-```bash
-# Via CLI:
-claude config set --global api-base-url http://localhost:20128/v1
-
-# Or create ~/.claude/settings.json:
-mkdir -p ~/.claude && cat > ~/.claude/settings.json << EOF
-{
- "apiBaseUrl": "http://localhost:20128/v1",
- "apiKey": "sk-your-omniroute-key"
-}
-EOF
-```
-
-**Test:** `claude "say hello"`
-
----
-
-### OpenAI Codex
-
-```bash
-mkdir -p ~/.codex && cat > ~/.codex/config.yaml << EOF
-model: auto
-apiKey: sk-your-omniroute-key
-apiBaseUrl: http://localhost:20128/v1
-EOF
-```
-
-**Test:** `codex "what is 2+2?"`
-
----
-
-### Gemini CLI
-
-```bash
-mkdir -p ~/.gemini && cat > ~/.gemini/settings.json << EOF
-{
- "apiKey": "sk-your-omniroute-key",
- "baseUrl": "http://localhost:20128/v1"
-}
-EOF
-```
-
-**Test:** `gemini "hello"`
-
----
-
-### OpenCode
-
-```bash
-mkdir -p ~/.config/opencode && cat > ~/.config/opencode/config.toml << EOF
-[provider.openai]
-base_url = "http://localhost:20128/v1"
-api_key = "sk-your-omniroute-key"
-EOF
-```
-
-**Test:** `opencode`
-
----
-
-### Cline (CLI or VS Code)
-
-**CLI mode:**
-
-```bash
-mkdir -p ~/.cline/data && cat > ~/.cline/data/globalState.json << EOF
-{
- "apiProvider": "openai",
- "openAiBaseUrl": "http://localhost:20128/v1",
- "openAiApiKey": "sk-your-omniroute-key"
-}
-EOF
-```
-
-**VS Code mode:**
-Cline extension settings → API Provider: `OpenAI Compatible` → Base URL: `http://localhost:20128/v1`
-
-Or use the OmniRoute dashboard → **CLI Tools → Cline → Apply Config**.
-
----
-
-### KiloCode (CLI or VS Code)
-
-**CLI mode:**
-
-```bash
-kilocode --api-base http://localhost:20128/v1 --api-key sk-your-omniroute-key
-```
-
-**VS Code settings:**
-
-```json
-{
- "kilo-code.openAiBaseUrl": "http://localhost:20128/v1",
- "kilo-code.apiKey": "sk-your-omniroute-key"
-}
-```
-
-Or use the OmniRoute dashboard → **CLI Tools → KiloCode → Apply Config**.
-
----
-
-### Continue (VS Code Extension)
-
-Edit `~/.continue/config.yaml`:
-
-```yaml
-models:
- - name: OmniRoute
- provider: openai
- model: auto
- apiBase: http://localhost:20128/v1
- apiKey: sk-your-omniroute-key
- default: true
-```
-
-Restart VS Code after editing.
-
----
-
-### Kiro CLI (Amazon)
-
-```bash
-# Login to your AWS/Kiro account:
-kiro-cli login
-
-# The CLI uses its own auth — OmniRoute is not needed as backend for Kiro CLI itself.
-# Use kiro-cli alongside OmniRoute for other tools.
-kiro-cli status
-```
-
----
-
-### Cursor (Desktop App)
-
-> **Note:** Cursor routes requests through its cloud. For OmniRoute integration,
-> enable **Cloud Endpoint** in OmniRoute Settings and use your public domain URL.
-
-Via GUI: **Settings → Models → OpenAI API Key**
-
-- Base URL: `https://your-domain.com/v1`
-- API Key: your OmniRoute key
-
----
-
-## Dashboard Auto-Configuration
-
-The OmniRoute dashboard automates configuration for most tools:
-
-1. Go to `http://localhost:20128/dashboard/cli-tools`
-2. Expand any tool card
-3. Select your API key from the dropdown
-4. Click **Apply Config** (if tool is detected as installed)
-5. Or copy the generated config snippet manually
-
----
-
-## Built-in Agents: Droid & OpenClaw
-
-**Droid** and **OpenClaw** are AI agents built directly into OmniRoute — no installation needed.
-They run as internal routes and use OmniRoute's model routing automatically.
-
-- Access: `http://localhost:20128/dashboard/agents`
-- Configure: same combos and providers as all other tools
-- No API key or CLI install required
-
----
-
-## Available API Endpoints
-
-| Endpoint | Description | Use For |
-| -------------------------- | ----------------------------- | --------------------------- |
-| `/v1/chat/completions` | Standard chat (all providers) | All modern tools |
-| `/v1/responses` | Responses API (OpenAI format) | Codex, agentic workflows |
-| `/v1/completions` | Legacy text completions | Older tools using `prompt:` |
-| `/v1/embeddings` | Text embeddings | RAG, search |
-| `/v1/images/generations` | Image generation | DALL-E, Flux, etc. |
-| `/v1/audio/speech` | Text-to-speech | ElevenLabs, OpenAI TTS |
-| `/v1/audio/transcriptions` | Speech-to-text | Deepgram, AssemblyAI |
-
----
-
-## Troubleshooting
-
-| Error | Cause | Fix |
-| ------------------------- | ----------------------- | ------------------------------------------ |
-| `Connection refused` | OmniRoute not running | `pm2 start omniroute` |
-| `401 Unauthorized` | Wrong API key | Check in `/dashboard/api-manager` |
-| `No combo configured` | No active routing combo | Set up in `/dashboard/combos` |
-| `invalid model` | Model not in catalog | Use `auto` or check `/dashboard/providers` |
-| CLI shows "not installed" | Binary not in PATH | Check `which ` |
-| `kiro-cli: not found` | Not in PATH | `export PATH="$HOME/.local/bin:$PATH"` |
-
----
-
-## Quick Setup Script (One Command)
-
-```bash
-# Install all CLIs and configure for OmniRoute (replace with your key and server URL)
-OMNIROUTE_URL="http://localhost:20128/v1"
-OMNIROUTE_KEY="sk-your-omniroute-key"
-
-npm install -g @anthropic-ai/claude-code @openai/codex @google/gemini-cli opencode-ai cline kilecode
-
-# Kiro CLI
-apt-get install -y unzip 2>/dev/null; curl -fsSL https://cli.kiro.dev/install | bash
-
-# Write configs
-mkdir -p ~/.claude ~/.codex ~/.gemini ~/.config/opencode ~/.continue
-
-cat > ~/.claude/settings.json <<< "{\"apiBaseUrl\":\"$OMNIROUTE_URL\",\"apiKey\":\"$OMNIROUTE_KEY\"}"
-cat > ~/.codex/config.yaml <<< "model: auto\napiKey: $OMNIROUTE_KEY\napiBaseUrl: $OMNIROUTE_URL"
-cat > ~/.gemini/settings.json <<< "{\"apiKey\":\"$OMNIROUTE_KEY\",\"baseUrl\":\"$OMNIROUTE_URL\"}"
-cat >> ~/.bashrc << EOF
-export OPENAI_BASE_URL="$OMNIROUTE_URL"
-export OPENAI_API_KEY="$OMNIROUTE_KEY"
-export ANTHROPIC_BASE_URL="$OMNIROUTE_URL"
-export ANTHROPIC_API_KEY="$OMNIROUTE_KEY"
-EOF
-
-source ~/.bashrc
-echo "✅ All CLIs installed and configured for OmniRoute"
-```
diff --git a/docs/i18n/he/CODEBASE_DOCUMENTATION.md b/docs/i18n/he/CODEBASE_DOCUMENTATION.md
deleted file mode 100644
index e2d7950052..0000000000
--- a/docs/i18n/he/CODEBASE_DOCUMENTATION.md
+++ /dev/null
@@ -1,593 +0,0 @@
-🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/CODEBASE_DOCUMENTATION.md) · 🇪🇸 [es](../es/CODEBASE_DOCUMENTATION.md) · 🇫🇷 [fr](../fr/CODEBASE_DOCUMENTATION.md) · 🇩🇪 [de](../de/CODEBASE_DOCUMENTATION.md) · 🇮🇹 [it](../it/CODEBASE_DOCUMENTATION.md) · 🇷🇺 [ru](../ru/CODEBASE_DOCUMENTATION.md) · 🇨🇳 [zh-CN](../zh-CN/CODEBASE_DOCUMENTATION.md) · 🇯🇵 [ja](../ja/CODEBASE_DOCUMENTATION.md) · 🇰🇷 [ko](../ko/CODEBASE_DOCUMENTATION.md) · 🇸🇦 [ar](../ar/CODEBASE_DOCUMENTATION.md) · 🇮🇳 [in](../in/CODEBASE_DOCUMENTATION.md) · 🇹🇭 [th](../th/CODEBASE_DOCUMENTATION.md) · 🇻🇳 [vi](../vi/CODEBASE_DOCUMENTATION.md) · 🇮🇩 [id](../id/CODEBASE_DOCUMENTATION.md) · 🇲🇾 [ms](../ms/CODEBASE_DOCUMENTATION.md) · 🇳🇱 [nl](../nl/CODEBASE_DOCUMENTATION.md) · 🇵🇱 [pl](../pl/CODEBASE_DOCUMENTATION.md) · 🇸🇪 [sv](../sv/CODEBASE_DOCUMENTATION.md) · 🇳🇴 [no](../no/CODEBASE_DOCUMENTATION.md) · 🇩🇰 [da](../da/CODEBASE_DOCUMENTATION.md) · 🇫🇮 [fi](../fi/CODEBASE_DOCUMENTATION.md) · 🇵🇹 [pt](../pt/CODEBASE_DOCUMENTATION.md) · 🇷🇴 [ro](../ro/CODEBASE_DOCUMENTATION.md) · 🇭🇺 [hu](../hu/CODEBASE_DOCUMENTATION.md) · 🇧🇬 [bg](../bg/CODEBASE_DOCUMENTATION.md) · 🇸🇰 [sk](../sk/CODEBASE_DOCUMENTATION.md) · 🇺🇦 [uk-UA](../uk-UA/CODEBASE_DOCUMENTATION.md) · 🇮🇱 [he](../he/CODEBASE_DOCUMENTATION.md) · 🇵🇭 [phi](../phi/CODEBASE_DOCUMENTATION.md)
-
----
-
-# omniroute — Codebase Documentation
-
-🌐 **Languages:** 🇺🇸 [English](CODEBASE_DOCUMENTATION.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/CODEBASE_DOCUMENTATION.md) | 🇪🇸 [Español](i18n/es/CODEBASE_DOCUMENTATION.md) | 🇫🇷 [Français](i18n/fr/CODEBASE_DOCUMENTATION.md) | 🇮🇹 [Italiano](i18n/it/CODEBASE_DOCUMENTATION.md) | 🇷🇺 [Русский](i18n/ru/CODEBASE_DOCUMENTATION.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/CODEBASE_DOCUMENTATION.md) | 🇩🇪 [Deutsch](i18n/de/CODEBASE_DOCUMENTATION.md) | 🇮🇳 [हिन्दी](i18n/in/CODEBASE_DOCUMENTATION.md) | 🇹🇭 [ไทย](i18n/th/CODEBASE_DOCUMENTATION.md) | 🇺🇦 [Українська](i18n/uk-UA/CODEBASE_DOCUMENTATION.md) | 🇸🇦 [العربية](i18n/ar/CODEBASE_DOCUMENTATION.md) | 🇯🇵 [日本語](i18n/ja/CODEBASE_DOCUMENTATION.md) | 🇻🇳 [Tiếng Việt](i18n/vi/CODEBASE_DOCUMENTATION.md) | 🇧🇬 [Български](i18n/bg/CODEBASE_DOCUMENTATION.md) | 🇩🇰 [Dansk](i18n/da/CODEBASE_DOCUMENTATION.md) | 🇫🇮 [Suomi](i18n/fi/CODEBASE_DOCUMENTATION.md) | 🇮🇱 [עברית](i18n/he/CODEBASE_DOCUMENTATION.md) | 🇭🇺 [Magyar](i18n/hu/CODEBASE_DOCUMENTATION.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/CODEBASE_DOCUMENTATION.md) | 🇰🇷 [한국어](i18n/ko/CODEBASE_DOCUMENTATION.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/CODEBASE_DOCUMENTATION.md) | 🇳🇱 [Nederlands](i18n/nl/CODEBASE_DOCUMENTATION.md) | 🇳🇴 [Norsk](i18n/no/CODEBASE_DOCUMENTATION.md) | 🇵🇹 [Português (Portugal)](i18n/pt/CODEBASE_DOCUMENTATION.md) | 🇷🇴 [Română](i18n/ro/CODEBASE_DOCUMENTATION.md) | 🇵🇱 [Polski](i18n/pl/CODEBASE_DOCUMENTATION.md) | 🇸🇰 [Slovenčina](i18n/sk/CODEBASE_DOCUMENTATION.md) | 🇸🇪 [Svenska](i18n/sv/CODEBASE_DOCUMENTATION.md) | 🇵🇭 [Filipino](i18n/phi/CODEBASE_DOCUMENTATION.md)
-
-> A comprehensive, beginner-friendly guide to the **omniroute** multi-provider AI proxy router.
-
----
-
-## 1. What Is omniroute?
-
-omniroute is a **proxy router** that sits between AI clients (Claude CLI, Codex, Cursor IDE, etc.) and AI providers (Anthropic, Google, OpenAI, AWS, GitHub, etc.). It solves one big problem:
-
-> **Different AI clients speak different "languages" (API formats), and different AI providers expect different "languages" too.** omniroute translates between them automatically.
-
-Think of it like a universal translator at the United Nations — any delegate can speak any language, and the translator converts it for any other delegate.
-
----
-
-## 2. Architecture Overview
-
-```mermaid
-graph LR
- subgraph Clients
- A[Claude CLI]
- B[Codex]
- C[Cursor IDE]
- D[OpenAI-compatible]
- end
-
- subgraph omniroute
- E[Handler Layer]
- F[Translator Layer]
- G[Executor Layer]
- H[Services Layer]
- end
-
- subgraph Providers
- I[Anthropic Claude]
- J[Google Gemini]
- K[OpenAI / Codex]
- L[GitHub Copilot]
- M[AWS Kiro]
- N[Antigravity]
- O[Cursor API]
- end
-
- A --> E
- B --> E
- C --> E
- D --> E
- E --> F
- F --> G
- G --> I
- G --> J
- G --> K
- G --> L
- G --> M
- G --> N
- G --> O
- H -.-> E
- H -.-> G
-```
-
-### Core Principle: Hub-and-Spoke Translation
-
-All format translation passes through **OpenAI format as the hub**:
-
-```
-Client Format → [OpenAI Hub] → Provider Format (request)
-Provider Format → [OpenAI Hub] → Client Format (response)
-```
-
-This means you only need **N translators** (one per format) instead of **N²** (every pair).
-
----
-
-## 3. Project Structure
-
-```
-omniroute/
-├── open-sse/ ← Core proxy library (portable, framework-agnostic)
-│ ├── index.js ← Main entry point, exports everything
-│ ├── config/ ← Configuration & constants
-│ ├── executors/ ← Provider-specific request execution
-│ ├── handlers/ ← Request handling orchestration
-│ ├── services/ ← Business logic (auth, models, fallback, usage)
-│ ├── translator/ ← Format translation engine
-│ │ ├── request/ ← Request translators (8 files)
-│ │ ├── response/ ← Response translators (7 files)
-│ │ └── helpers/ ← Shared translation utilities (6 files)
-│ └── utils/ ← Utility functions
-├── src/ ← Application layer (Express/Worker runtime)
-│ ├── app/ ← Web UI, API routes, middleware
-│ ├── lib/ ← Database, auth, and shared library code
-│ ├── mitm/ ← Man-in-the-middle proxy utilities
-│ ├── models/ ← Database models
-│ ├── shared/ ← Shared utilities (wrappers around open-sse)
-│ ├── sse/ ← SSE endpoint handlers
-│ └── store/ ← State management
-├── data/ ← Runtime data (credentials, logs)
-│ └── provider-credentials.json (external credentials override, gitignored)
-└── tester/ ← Test utilities
-```
-
----
-
-## 4. Module-by-Module Breakdown
-
-### 4.1 Config (`open-sse/config/`)
-
-The **single source of truth** for all provider configuration.
-
-| File | Purpose |
-| ----------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| `constants.ts` | `PROVIDERS` object with base URLs, OAuth credentials (defaults), headers, and default system prompts for every provider. Also defines `HTTP_STATUS`, `ERROR_TYPES`, `COOLDOWN_MS`, `BACKOFF_CONFIG`, and `SKIP_PATTERNS`. |
-| `credentialLoader.ts` | Loads external credentials from `data/provider-credentials.json` and merges them over the hardcoded defaults in `PROVIDERS`. Keeps secrets out of source control while maintaining backwards compatibility. |
-| `providerModels.ts` | Central model registry: maps provider aliases → model IDs. Functions like `getModels()`, `getProviderByAlias()`. |
-| `codexInstructions.ts` | System instructions injected into Codex requests (editing constraints, sandbox rules, approval policies). |
-| `defaultThinkingSignature.ts` | Default "thinking" signatures for Claude and Gemini models. |
-| `ollamaModels.ts` | Schema definition for local Ollama models (name, size, family, quantization). |
-
-#### Credential Loading Flow
-
-```mermaid
-flowchart TD
- A["App starts"] --> B["constants.ts defines PROVIDERS\nwith hardcoded defaults"]
- B --> C{"data/provider-credentials.json\nexists?"}
- C -->|Yes| D["credentialLoader reads JSON"]
- C -->|No| E["Use hardcoded defaults"]
- D --> F{"For each provider in JSON"}
- F --> G{"Provider exists\nin PROVIDERS?"}
- G -->|No| H["Log warning, skip"]
- G -->|Yes| I{"Value is object?"}
- I -->|No| J["Log warning, skip"]
- I -->|Yes| K["Merge clientId, clientSecret,\ntokenUrl, authUrl, refreshUrl"]
- K --> F
- H --> F
- J --> F
- F -->|Done| L["PROVIDERS ready with\nmerged credentials"]
- E --> L
-```
-
----
-
-### 4.2 Executors (`open-sse/executors/`)
-
-Executors encapsulate **provider-specific logic** using the **Strategy Pattern**. Each executor overrides base methods as needed.
-
-```mermaid
-classDiagram
- class BaseExecutor {
- +buildUrl(model, stream, options)
- +buildHeaders(credentials, stream, body)
- +transformRequest(body, model, stream, credentials)
- +execute(url, options)
- +shouldRetry(status, error)
- +refreshCredentials(credentials, log)
- }
-
- class DefaultExecutor {
- +refreshCredentials()
- }
-
- class AntigravityExecutor {
- +buildUrl()
- +buildHeaders()
- +transformRequest()
- +shouldRetry()
- +refreshCredentials()
- }
-
- class CursorExecutor {
- +buildUrl()
- +buildHeaders()
- +transformRequest()
- +parseResponse()
- +generateChecksum()
- }
-
- class KiroExecutor {
- +buildUrl()
- +buildHeaders()
- +transformRequest()
- +parseEventStream()
- +refreshCredentials()
- }
-
- BaseExecutor <|-- DefaultExecutor
- BaseExecutor <|-- AntigravityExecutor
- BaseExecutor <|-- CursorExecutor
- BaseExecutor <|-- KiroExecutor
- BaseExecutor <|-- CodexExecutor
- BaseExecutor <|-- GeminiCLIExecutor
- BaseExecutor <|-- GithubExecutor
-```
-
-| Executor | Provider | Key Specializations |
-| ---------------- | ------------------------------------------ | ------------------------------------------------------------------------------------------------------------------- |
-| `base.ts` | — | Abstract base: URL building, headers, retry logic, credential refresh |
-| `default.ts` | Claude, Gemini, OpenAI, GLM, Kimi, MiniMax | Generic OAuth token refresh for standard providers |
-| `antigravity.ts` | Google Cloud Code | Project/session ID generation, multi-URL fallback, custom retry parsing from error messages ("reset after 2h7m23s") |
-| `cursor.ts` | Cursor IDE | **Most complex**: SHA-256 checksum auth, Protobuf request encoding, binary EventStream → SSE response parsing |
-| `codex.ts` | OpenAI Codex | Injects system instructions, manages thinking levels, removes unsupported parameters |
-| `gemini-cli.ts` | Google Gemini CLI | Custom URL building (`streamGenerateContent`), Google OAuth token refresh |
-| `github.ts` | GitHub Copilot | Dual token system (GitHub OAuth + Copilot token), VSCode header mimicking |
-| `kiro.ts` | AWS CodeWhisperer | AWS EventStream binary parsing, AMZN event frames, token estimation |
-| `index.ts` | — | Factory: maps provider name → executor class, with default fallback |
-
----
-
-### 4.3 Handlers (`open-sse/handlers/`)
-
-The **orchestration layer** — coordinates translation, execution, streaming, and error handling.
-
-| File | Purpose |
-| --------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| `chatCore.ts` | **Central orchestrator** (~600 lines). Handles the complete request lifecycle: format detection → translation → executor dispatch → streaming/non-streaming response → token refresh → error handling → usage logging. |
-| `responsesHandler.ts` | Adapter for OpenAI's Responses API: converts Responses format → Chat Completions → sends to `chatCore` → converts SSE back to Responses format. |
-| `embeddings.ts` | Embedding generation handler: resolves embedding model → provider, dispatches to provider API, returns OpenAI-compatible embedding response. Supports 6+ providers. |
-| `imageGeneration.ts` | Image generation handler: resolves image model → provider, supports OpenAI-compatible, Gemini-image (Antigravity), and fallback (Nebius) modes. Returns base64 or URL images. |
-
-#### Request Lifecycle (chatCore.ts)
-
-```mermaid
-sequenceDiagram
- participant Client
- participant chatCore
- participant Translator
- participant Executor
- participant Provider
-
- Client->>chatCore: Request (any format)
- chatCore->>chatCore: Detect source format
- chatCore->>chatCore: Check bypass patterns
- chatCore->>chatCore: Resolve model & provider
- chatCore->>Translator: Translate request (source → OpenAI → target)
- chatCore->>Executor: Get executor for provider
- Executor->>Executor: Build URL, headers, transform request
- Executor->>Executor: Refresh credentials if needed
- Executor->>Provider: HTTP fetch (streaming or non-streaming)
-
- alt Streaming
- Provider-->>chatCore: SSE stream
- chatCore->>chatCore: Pipe through SSE transform stream
- Note over chatCore: Transform stream translates
each chunk: target → OpenAI → source
- chatCore-->>Client: Translated SSE stream
- else Non-streaming
- Provider-->>chatCore: JSON response
- chatCore->>Translator: Translate response
- chatCore-->>Client: Translated JSON
- end
-
- alt Error (401, 429, 500...)
- chatCore->>Executor: Retry with credential refresh
- chatCore->>chatCore: Account fallback logic
- end
-```
-
----
-
-### 4.4 Services (`open-sse/services/`)
-
-Business logic that supports the handlers and executors.
-
-| File | Purpose |
-| -------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| `provider.ts` | **Format detection** (`detectFormat`): analyzes request body structure to identify Claude/OpenAI/Gemini/Antigravity/Responses formats (includes `max_tokens` heuristic for Claude). Also: URL building, header building, thinking config normalization. Supports `openai-compatible-*` and `anthropic-compatible-*` dynamic providers. |
-| `model.ts` | Model string parsing (`claude/model-name` → `{provider: "claude", model: "model-name"}`), alias resolution with collision detection, input sanitization (rejects path traversal/control chars), and model info resolution with async alias getter support. |
-| `accountFallback.ts` | Rate-limit handling: exponential backoff (1s → 2s → 4s → max 2min), account cooldown management, error classification (which errors trigger fallback vs. not). |
-| `tokenRefresh.ts` | OAuth token refresh for **every provider**: Google (Gemini, Antigravity), Claude, Codex, Qwen, Qoder, GitHub (OAuth + Copilot dual-token), Kiro (AWS SSO OIDC + Social Auth). Includes in-flight promise deduplication cache and retry with exponential backoff. |
-| `combo.ts` | **Combo models**: chains of fallback models. If model A fails with a fallback-eligible error, try model B, then C, etc. Returns actual upstream status codes. |
-| `usage.ts` | Fetches quota/usage data from provider APIs (GitHub Copilot quotas, Antigravity model quotas, Codex rate limits, Kiro usage breakdowns, Claude settings). |
-| `accountSelector.ts` | Smart account selection with scoring algorithm: considers priority, health status, round-robin position, and cooldown state to pick the optimal account for each request. |
-| `contextManager.ts` | Request context lifecycle management: creates and tracks per-request context objects with metadata (request ID, timestamps, provider info) for debugging and logging. |
-| `ipFilter.ts` | IP-based access control: supports allowlist and blocklist modes. Validates client IP against configured rules before processing API requests. |
-| `sessionManager.ts` | Session tracking with client fingerprinting: tracks active sessions using hashed client identifiers, monitors request counts, and provides session metrics. |
-| `signatureCache.ts` | Request signature-based deduplication cache: prevents duplicate requests by caching recent request signatures and returning cached responses for identical requests within a time window. |
-| `systemPrompt.ts` | Global system prompt injection: prepends or appends a configurable system prompt to all requests, with per-provider compatibility handling. |
-| `thinkingBudget.ts` | Reasoning token budget management: supports passthrough, auto (strip thinking config), custom (fixed budget), and adaptive (complexity-scaled) modes for controlling thinking/reasoning tokens. |
-| `wildcardRouter.ts` | Wildcard model pattern routing: resolves wildcard patterns (e.g., `*/claude-*`) to concrete provider/model pairs based on availability and priority. |
-
-#### Token Refresh Deduplication
-
-```mermaid
-sequenceDiagram
- participant R1 as Request 1
- participant R2 as Request 2
- participant Cache as refreshPromiseCache
- participant OAuth as OAuth Provider
-
- R1->>Cache: getAccessToken("gemini", token)
- Cache->>Cache: No in-flight promise
- Cache->>OAuth: Start refresh
- R2->>Cache: getAccessToken("gemini", token)
- Cache->>Cache: Found in-flight promise
- Cache-->>R2: Return existing promise
- OAuth-->>Cache: New access token
- Cache-->>R1: New access token
- Cache-->>R2: Same access token (shared)
- Cache->>Cache: Delete cache entry
-```
-
-#### Account Fallback State Machine
-
-```mermaid
-stateDiagram-v2
- [*] --> Active
- Active --> Error: Request fails (401/429/500)
- Error --> Cooldown: Apply backoff
- Cooldown --> Active: Cooldown expires
- Active --> Active: Request succeeds (reset backoff)
-
- state Error {
- [*] --> ClassifyError
- ClassifyError --> ShouldFallback: Rate limit / Auth / Transient
- ClassifyError --> NoFallback: 400 Bad Request
- }
-
- state Cooldown {
- [*] --> ExponentialBackoff
- ExponentialBackoff: Level 0 = 1s
- ExponentialBackoff: Level 1 = 2s
- ExponentialBackoff: Level 2 = 4s
- ExponentialBackoff: Max = 2min
- }
-```
-
-#### Combo Model Chain
-
-```mermaid
-flowchart LR
- A["Request with\ncombo model"] --> B["Model A"]
- B -->|"2xx Success"| C["Return response"]
- B -->|"429/401/500"| D{"Fallback\neligible?"}
- D -->|Yes| E["Model B"]
- D -->|No| F["Return error"]
- E -->|"2xx Success"| C
- E -->|"429/401/500"| G{"Fallback\neligible?"}
- G -->|Yes| H["Model C"]
- G -->|No| F
- H -->|"2xx Success"| C
- H -->|"Fail"| I["All failed →\nReturn last status"]
-```
-
----
-
-### 4.5 Translator (`open-sse/translator/`)
-
-The **format translation engine** using a self-registering plugin system.
-
-#### Architecture
-
-```mermaid
-graph TD
- subgraph "Request Translation"
- A["Claude → OpenAI"]
- B["Gemini → OpenAI"]
- C["Antigravity → OpenAI"]
- D["OpenAI Responses → OpenAI"]
- E["OpenAI → Claude"]
- F["OpenAI → Gemini"]
- G["OpenAI → Kiro"]
- H["OpenAI → Cursor"]
- end
-
- subgraph "Response Translation"
- I["Claude → OpenAI"]
- J["Gemini → OpenAI"]
- K["Kiro → OpenAI"]
- L["Cursor → OpenAI"]
- M["OpenAI → Claude"]
- N["OpenAI → Antigravity"]
- O["OpenAI → Responses"]
- end
-```
-
-| Directory | Files | Description |
-| ------------ | ------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| `request/` | 8 translators | Convert request bodies between formats. Each file self-registers via `register(from, to, fn)` on import. |
-| `response/` | 7 translators | Convert streaming response chunks between formats. Handles SSE event types, thinking blocks, tool calls. |
-| `helpers/` | 6 helpers | Shared utilities: `claudeHelper` (system prompt extraction, thinking config), `geminiHelper` (parts/contents mapping), `openaiHelper` (format filtering), `toolCallHelper` (ID generation, missing response injection), `maxTokensHelper`, `responsesApiHelper`. |
-| `index.ts` | — | Translation engine: `translateRequest()`, `translateResponse()`, state management, registry. |
-| `formats.ts` | — | Format constants: `OPENAI`, `CLAUDE`, `GEMINI`, `ANTIGRAVITY`, `KIRO`, `CURSOR`, `OPENAI_RESPONSES`. |
-
-#### Key Design: Self-Registering Plugins
-
-```javascript
-// Each translator file calls register() on import:
-import { register } from "../index.js";
-register("claude", "openai", translateClaudeToOpenAI);
-
-// The index.js imports all translator files, triggering registration:
-import "./request/claude-to-openai.js"; // ← self-registers
-```
-
----
-
-### 4.6 Utils (`open-sse/utils/`)
-
-| File | Purpose |
-| ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
-| `error.ts` | Error response building (OpenAI-compatible format), upstream error parsing, Antigravity retry-time extraction from error messages, SSE error streaming. |
-| `stream.ts` | **SSE Transform Stream** — the core streaming pipeline. Two modes: `TRANSLATE` (full format translation) and `PASSTHROUGH` (normalize + extract usage). Handles chunk buffering, usage estimation, content length tracking. Per-stream encoder/decoder instances avoid shared state. |
-| `streamHelpers.ts` | Low-level SSE utilities: `parseSSELine` (whitespace-tolerant), `hasValuableContent` (filters empty chunks for OpenAI/Claude/Gemini), `fixInvalidId`, `formatSSE` (format-aware SSE serialization with `perf_metrics` cleanup). |
-| `usageTracking.ts` | Token usage extraction from any format (Claude/OpenAI/Gemini/Responses), estimation with separate tool/message char-per-token ratios, buffer addition (2000 tokens safety margin), format-specific field filtering, console logging with ANSI colors. |
-| `requestLogger.ts` | File-based request logging (opt-in via `ENABLE_REQUEST_LOGS=true`). Creates session folders with numbered files: `1_req_client.json` → `7_res_client.txt`. All I/O is async (fire-and-forget). Masks sensitive headers. |
-| `bypassHandler.ts` | Intercepts specific patterns from Claude CLI (title extraction, warmup, count) and returns fake responses without calling any provider. Supports both streaming and non-streaming. Intentionally limited to Claude CLI scope. |
-| `networkProxy.ts` | Resolves outbound proxy URL for a given provider with precedence: provider-specific config → global config → environment variables (`HTTPS_PROXY`/`HTTP_PROXY`/`ALL_PROXY`). Supports `NO_PROXY` exclusions. Caches config for 30s. |
-
-#### SSE Streaming Pipeline
-
-```mermaid
-flowchart TD
- A["Provider SSE stream"] --> B["TextDecoder\n(per-stream instance)"]
- B --> C["Buffer lines\n(split on newline)"]
- C --> D["parseSSELine()\n(trim whitespace, parse JSON)"]
- D --> E{"Mode?"}
- E -->|TRANSLATE| F["translateResponse()\ntarget → OpenAI → source"]
- E -->|PASSTHROUGH| G["fixInvalidId()\nnormalize chunk"]
- F --> H["hasValuableContent()\nfilter empty chunks"]
- G --> H
- H -->|"Has content"| I["extractUsage()\ntrack token counts"]
- H -->|"Empty"| J["Skip chunk"]
- I --> K["formatSSE()\nserialize + clean perf_metrics"]
- K --> L["TextEncoder\n(per-stream instance)"]
- L --> M["Enqueue to\nclient stream"]
-
- style A fill:#f9f,stroke:#333
- style M fill:#9f9,stroke:#333
-```
-
-#### Request Logger Session Structure
-
-```
-logs/
-└── claude_gemini_claude-sonnet_20260208_143045/
- ├── 1_req_client.json ← Raw client request
- ├── 2_req_source.json ← After initial conversion
- ├── 3_req_openai.json ← OpenAI intermediate format
- ├── 4_req_target.json ← Final target format
- ├── 5_res_provider.txt ← Provider SSE chunks (streaming)
- ├── 5_res_provider.json ← Provider response (non-streaming)
- ├── 6_res_openai.txt ← OpenAI intermediate chunks
- ├── 7_res_client.txt ← Client-facing SSE chunks
- └── 6_error.json ← Error details (if any)
-```
-
----
-
-### 4.7 Application Layer (`src/`)
-
-| Directory | Purpose |
-| ------------- | ---------------------------------------------------------------------- |
-| `src/app/` | Web UI, API routes, Express middleware, OAuth callback handlers |
-| `src/lib/` | Database access (`localDb.ts`, `usageDb.ts`), authentication, shared |
-| `src/mitm/` | Man-in-the-middle proxy utilities for intercepting provider traffic |
-| `src/models/` | Database model definitions |
-| `src/shared/` | Wrappers around open-sse functions (provider, stream, error, etc.) |
-| `src/sse/` | SSE endpoint handlers that wire the open-sse library to Express routes |
-| `src/store/` | Application state management |
-
-#### Notable API Routes
-
-| Route | Methods | Purpose |
-| --------------------------------------------- | --------------- | ------------------------------------------------------------------------------------- |
-| `/api/provider-models` | GET/POST/DELETE | CRUD for custom models per provider |
-| `/api/models/catalog` | GET | Aggregated catalog of all models (chat, embedding, image, custom) grouped by provider |
-| `/api/settings/proxy` | GET/PUT/DELETE | Hierarchical outbound proxy configuration (`global/providers/combos/keys`) |
-| `/api/settings/proxy/test` | POST | Validates proxy connectivity and returns public IP/latency |
-| `/v1/providers/[provider]/chat/completions` | POST | Dedicated per-provider chat completions with model validation |
-| `/v1/providers/[provider]/embeddings` | POST | Dedicated per-provider embeddings with model validation |
-| `/v1/providers/[provider]/images/generations` | POST | Dedicated per-provider image generation with model validation |
-| `/api/settings/ip-filter` | GET/PUT | IP allowlist/blocklist management |
-| `/api/settings/thinking-budget` | GET/PUT | Reasoning token budget configuration (passthrough/auto/custom/adaptive) |
-| `/api/settings/system-prompt` | GET/PUT | Global system prompt injection for all requests |
-| `/api/sessions` | GET | Active session tracking and metrics |
-| `/api/rate-limits` | GET | Per-account rate limit status |
-
----
-
-## 5. Key Design Patterns
-
-### 5.1 Hub-and-Spoke Translation
-
-All formats translate through **OpenAI format as the hub**. Adding a new provider only requires writing **one pair** of translators (to/from OpenAI), not N pairs.
-
-### 5.2 Executor Strategy Pattern
-
-Each provider has a dedicated executor class inheriting from `BaseExecutor`. The factory in `executors/index.ts` selects the right one at runtime.
-
-### 5.3 Self-Registering Plugin System
-
-Translator modules register themselves on import via `register()`. Adding a new translator is just creating a file and importing it.
-
-### 5.4 Account Fallback with Exponential Backoff
-
-When a provider returns 429/401/500, the system can switch to the next account, applying exponential cooldowns (1s → 2s → 4s → max 2min).
-
-### 5.5 Combo Model Chains
-
-A "combo" groups multiple `provider/model` strings. If the first fails, fallback to the next automatically.
-
-### 5.6 Stateful Streaming Translation
-
-Response translation maintains state across SSE chunks (thinking block tracking, tool call accumulation, content block indexing) via the `initState()` mechanism.
-
-### 5.7 Usage Safety Buffer
-
-A 2000-token buffer is added to reported usage to prevent clients from hitting context window limits due to overhead from system prompts and format translation.
-
----
-
-## 6. Supported Formats
-
-| Format | Direction | Identifier |
-| ----------------------- | --------------- | ------------------ |
-| OpenAI Chat Completions | source + target | `openai` |
-| OpenAI Responses API | source + target | `openai-responses` |
-| Anthropic Claude | source + target | `claude` |
-| Google Gemini | source + target | `gemini` |
-| Google Gemini CLI | target only | `gemini-cli` |
-| Antigravity | source + target | `antigravity` |
-| AWS Kiro | target only | `kiro` |
-| Cursor | target only | `cursor` |
-
----
-
-## 7. Supported Providers
-
-| Provider | Auth Method | Executor | Key Notes |
-| ------------------------ | ---------------------- | ----------- | --------------------------------------------- |
-| Anthropic Claude | API key or OAuth | Default | Uses `x-api-key` header |
-| Google Gemini | API key or OAuth | Default | Uses `x-goog-api-key` header |
-| Google Gemini CLI | OAuth | GeminiCLI | Uses `streamGenerateContent` endpoint |
-| Antigravity | OAuth | Antigravity | Multi-URL fallback, custom retry parsing |
-| OpenAI | API key | Default | Standard Bearer auth |
-| Codex | OAuth | Codex | Injects system instructions, manages thinking |
-| GitHub Copilot | OAuth + Copilot token | Github | Dual token, VSCode header mimicking |
-| Kiro (AWS) | AWS SSO OIDC or Social | Kiro | Binary EventStream parsing |
-| Cursor IDE | Checksum auth | Cursor | Protobuf encoding, SHA-256 checksums |
-| Qwen | OAuth | Default | Standard auth |
-| Qoder | OAuth (Basic + Bearer) | Default | Dual auth header |
-| OpenRouter | API key | Default | Standard Bearer auth |
-| GLM, Kimi, MiniMax | API key | Default | Claude-compatible, use `x-api-key` |
-| `openai-compatible-*` | API key | Default | Dynamic: any OpenAI-compatible endpoint |
-| `anthropic-compatible-*` | API key | Default | Dynamic: any Claude-compatible endpoint |
-
----
-
-## 8. Data Flow Summary
-
-### Streaming Request
-
-```mermaid
-flowchart LR
- A["Client"] --> B["detectFormat()"]
- B --> C["translateRequest()\nsource → OpenAI → target"]
- C --> D["Executor\nbuildUrl + buildHeaders"]
- D --> E["fetch(providerURL)"]
- E --> F["createSSEStream()\nTRANSLATE mode"]
- F --> G["parseSSELine()"]
- G --> H["translateResponse()\ntarget → OpenAI → source"]
- H --> I["extractUsage()\n+ addBuffer"]
- I --> J["formatSSE()"]
- J --> K["Client receives\ntranslated SSE"]
- K --> L["logUsage()\nsaveRequestUsage()"]
-```
-
-### Non-Streaming Request
-
-```mermaid
-flowchart LR
- A["Client"] --> B["detectFormat()"]
- B --> C["translateRequest()\nsource → OpenAI → target"]
- C --> D["Executor.execute()"]
- D --> E["translateResponse()\ntarget → OpenAI → source"]
- E --> F["Return JSON\nresponse"]
-```
-
-### Bypass Flow (Claude CLI)
-
-```mermaid
-flowchart LR
- A["Claude CLI request"] --> B{"Match bypass\npattern?"}
- B -->|"Title/Warmup/Count"| C["Generate fake\nOpenAI response"]
- B -->|"No match"| D["Normal flow"]
- C --> E["Translate to\nsource format"]
- E --> F["Return without\ncalling provider"]
-```
diff --git a/docs/i18n/he/CONTRIBUTING.md b/docs/i18n/he/CONTRIBUTING.md
new file mode 100644
index 0000000000..7d8516e147
--- /dev/null
+++ b/docs/i18n/he/CONTRIBUTING.md
@@ -0,0 +1,299 @@
+# Contributing to OmniRoute (עברית)
+
+🌐 **Languages:** 🇺🇸 [English](../../../CONTRIBUTING.md) · 🇪🇸 [es](../es/CONTRIBUTING.md) · 🇫🇷 [fr](../fr/CONTRIBUTING.md) · 🇩🇪 [de](../de/CONTRIBUTING.md) · 🇮🇹 [it](../it/CONTRIBUTING.md) · 🇷🇺 [ru](../ru/CONTRIBUTING.md) · 🇨🇳 [zh-CN](../zh-CN/CONTRIBUTING.md) · 🇯🇵 [ja](../ja/CONTRIBUTING.md) · 🇰🇷 [ko](../ko/CONTRIBUTING.md) · 🇸🇦 [ar](../ar/CONTRIBUTING.md) · 🇮🇳 [in](../in/CONTRIBUTING.md) · 🇹🇭 [th](../th/CONTRIBUTING.md) · 🇻🇳 [vi](../vi/CONTRIBUTING.md) · 🇮🇩 [id](../id/CONTRIBUTING.md) · 🇲🇾 [ms](../ms/CONTRIBUTING.md) · 🇳🇱 [nl](../nl/CONTRIBUTING.md) · 🇵🇱 [pl](../pl/CONTRIBUTING.md) · 🇸🇪 [sv](../sv/CONTRIBUTING.md) · 🇳🇴 [no](../no/CONTRIBUTING.md) · 🇩🇰 [da](../da/CONTRIBUTING.md) · 🇫🇮 [fi](../fi/CONTRIBUTING.md) · 🇵🇹 [pt](../pt/CONTRIBUTING.md) · 🇷🇴 [ro](../ro/CONTRIBUTING.md) · 🇭🇺 [hu](../hu/CONTRIBUTING.md) · 🇧🇬 [bg](../bg/CONTRIBUTING.md) · 🇸🇰 [sk](../sk/CONTRIBUTING.md) · 🇺🇦 [uk-UA](../uk-UA/CONTRIBUTING.md) · 🇮🇱 [he](../he/CONTRIBUTING.md) · 🇵🇭 [phi](../phi/CONTRIBUTING.md) · 🇧🇷 [pt-BR](../pt-BR/CONTRIBUTING.md) · 🇨🇿 [cs](../cs/CONTRIBUTING.md)
+
+---
+
+Thank you for your interest in contributing! This guide covers everything you need to get started.
+
+---
+
+## Development Setup
+
+### Prerequisites
+
+- **Node.js** >= 18 < 24 (recommended: 22 LTS)
+- **npm** 10+
+- **Git**
+
+### Clone & Install
+
+```bash
+git clone https://github.com/diegosouzapw/OmniRoute.git
+cd OmniRoute
+npm install
+```
+
+### Environment Variables
+
+```bash
+# Create your .env from the template
+cp .env.example .env
+
+# Generate required secrets
+echo "JWT_SECRET=$(openssl rand -base64 48)" >> .env
+echo "API_KEY_SECRET=$(openssl rand -hex 32)" >> .env
+```
+
+Key variables for development:
+
+| Variable | Development Default | Description |
+| ---------------------- | ------------------------ | --------------------- |
+| `PORT` | `20128` | Server port |
+| `NEXT_PUBLIC_BASE_URL` | `http://localhost:20128` | Base URL for frontend |
+| `JWT_SECRET` | (generate above) | JWT signing secret |
+| `INITIAL_PASSWORD` | `CHANGEME` | First login password |
+| `APP_LOG_LEVEL` | `info` | Log verbosity level |
+
+### Dashboard Settings
+
+The dashboard provides UI toggles for features that can also be configured via environment variables:
+
+| Setting Location | Toggle | Description |
+| ------------------- | ------------------ | ------------------------------ |
+| Settings → Advanced | Debug Mode | Enable debug request logs (UI) |
+| Settings → General | Sidebar Visibility | Show/hide sidebar sections |
+
+These settings are stored in the database and persist across restarts, overriding env var defaults when set.
+
+### Running Locally
+
+```bash
+# Development mode (hot reload)
+npm run dev
+
+# Production build
+npm run build
+npm run start
+
+# Common port configuration
+PORT=20128 NEXT_PUBLIC_BASE_URL=http://localhost:20128 npm run dev
+```
+
+Default URLs:
+
+- **Dashboard**: `http://localhost:20128/dashboard`
+- **API**: `http://localhost:20128/v1`
+
+---
+
+## Git Workflow
+
+> ⚠️ **NEVER commit directly to `main`.** Always use feature branches.
+
+```bash
+git checkout -b feat/your-feature-name
+# ... make changes ...
+git commit -m "feat: describe your change"
+git push -u origin feat/your-feature-name
+# Open a Pull Request on GitHub
+```
+
+### Branch Naming
+
+| Prefix | Purpose |
+| ----------- | ------------------------- |
+| `feat/` | New features |
+| `fix/` | Bug fixes |
+| `refactor/` | Code restructuring |
+| `docs/` | Documentation changes |
+| `test/` | Test additions/fixes |
+| `chore/` | Tooling, CI, dependencies |
+
+### Commit Messages
+
+Follow [Conventional Commits](https://www.conventionalcommits.org/):
+
+```
+feat: add circuit breaker for provider calls
+fix: resolve JWT secret validation edge case
+docs: update SECURITY.md with PII protection
+test: add observability unit tests
+refactor(db): consolidate rate limit tables
+```
+
+Scopes: `db`, `sse`, `oauth`, `dashboard`, `api`, `cli`, `docker`, `ci`, `mcp`, `a2a`, `memory`, `skills`.
+
+---
+
+## Running Tests
+
+```bash
+# All tests (unit + vitest + ecosystem + e2e)
+npm run test:all
+
+# Single test file (Node.js native test runner — most tests use this)
+node --import tsx/esm --test tests/unit/your-file.test.mjs
+
+# Vitest (MCP server, autoCombo, cache)
+npm run test:vitest
+
+# E2E tests (requires Playwright)
+npm run test:e2e
+
+# Protocol clients E2E (MCP transports, A2A)
+npm run test:protocols:e2e
+
+# Ecosystem compatibility tests
+npm run test:ecosystem
+
+# Coverage (55% min statements/lines/functions; 60% branches)
+npm run test:coverage
+npm run coverage:report
+
+# Lint + format check
+npm run lint
+npm run check
+```
+
+Coverage notes:
+
+- `npm run test:coverage` measures source coverage for the main unit test suite, excludes `tests/**`, and includes `open-sse/**`
+- `npm run coverage:report` prints the detailed file-by-file report from the latest coverage run
+- `npm run test:coverage:legacy` preserves the older metric for historical comparison
+- See `docs/COVERAGE_PLAN.md` for the phased coverage improvement roadmap
+
+Current test status: **122 unit test files** covering:
+
+- Provider translators and format conversion
+- Rate limiting, circuit breaker, and resilience
+- Semantic cache, idempotency, progress tracking
+- Database operations and schema (21 DB modules)
+- OAuth flows and authentication
+- API endpoint validation (Zod v4)
+- MCP server tools and scope enforcement
+- Memory and Skills systems
+
+---
+
+## Code Style
+
+- **ESLint** — Run `npm run lint` before committing
+- **Prettier** — Auto-formatted via `lint-staged` on commit (2 spaces, semicolons, double quotes, 100 char width, es5 trailing commas)
+- **TypeScript** — All `src/` code uses `.ts`/`.tsx`; `open-sse/` uses `.ts`/`.js`; document with TSDoc (`@param`, `@returns`, `@throws`)
+- **No `eval()`** — ESLint enforces `no-eval`, `no-implied-eval`, `no-new-func`
+- **Zod validation** — Use Zod v4 schemas for all API input validation
+- **Naming**: Files = camelCase/kebab-case, components = PascalCase, constants = UPPER_SNAKE
+
+---
+
+## Project Structure
+
+```
+src/ # TypeScript (.ts / .tsx)
+├── app/ # Next.js 16 App Router
+│ ├── (dashboard)/ # Dashboard pages (23 sections)
+│ ├── api/ # API routes (51 directories)
+│ └── login/ # Auth pages (.tsx)
+├── domain/ # Policy engine (policyEngine, comboResolver, costRules, etc.)
+├── lib/ # Core business logic (.ts)
+│ ├── a2a/ # Agent-to-Agent v0.3 protocol server
+│ ├── acp/ # Agent Communication Protocol registry
+│ ├── compliance/ # Compliance policy engine
+│ ├── db/ # SQLite database layer (21 modules + 16 migrations)
+│ ├── memory/ # Persistent conversational memory
+│ ├── oauth/ # OAuth providers, services, and utilities
+│ ├── skills/ # Extensible skill framework
+│ ├── usage/ # Usage tracking and cost calculation
+│ └── localDb.ts # Re-export layer only — never add logic here
+├── middleware/ # Request middleware (promptInjectionGuard)
+├── mitm/ # MITM proxy (cert, DNS, target routing)
+├── shared/
+│ ├── components/ # React components (.tsx)
+│ ├── constants/ # Provider definitions (60+), MCP scopes, routing strategies
+│ ├── utils/ # Circuit breaker, sanitizer, auth helpers
+│ └── validation/ # Zod v4 schemas
+└── sse/ # SSE proxy pipeline
+
+open-sse/ # @omniroute/open-sse workspace
+├── executors/ # 14 provider-specific request executors
+├── handlers/ # 11 request handlers (chat, responses, embeddings, images, etc.)
+├── mcp-server/ # MCP server (25 tools, 3 transports, 10 scopes)
+├── services/ # 36+ services (combo, autoCombo, rateLimitManager, etc.)
+├── translator/ # Format translators (OpenAI ↔ Claude ↔ Gemini ↔ Responses ↔ Ollama)
+├── transformer/ # Responses API transformer
+└── utils/ # 22 utility modules (stream, TLS, proxy, logging)
+
+electron/ # Electron desktop app (cross-platform)
+
+tests/
+├── unit/ # Node.js test runner (122 test files)
+├── integration/ # Integration tests
+├── e2e/ # Playwright tests
+├── security/ # Security tests
+├── translator/ # Translator-specific tests
+└── load/ # Load tests
+
+docs/ # Documentation
+├── ARCHITECTURE.md # System architecture
+├── API_REFERENCE.md # All endpoints
+├── USER_GUIDE.md # Provider setup, CLI integration
+├── TROUBLESHOOTING.md # Common issues
+├── MCP-SERVER.md # MCP server (25 tools)
+├── A2A-SERVER.md # A2A agent protocol
+├── AUTO-COMBO.md # Auto-combo engine
+├── CLI-TOOLS.md # CLI tools integration
+├── COVERAGE_PLAN.md # Test coverage improvement plan
+├── openapi.yaml # OpenAPI specification
+└── adr/ # Architecture Decision Records
+```
+
+---
+
+## Adding a New Provider
+
+### Step 1: Register Provider Constants
+
+Add to `src/shared/constants/providers.ts` — Zod-validated at module load.
+
+### Step 2: Add Executor (if custom logic needed)
+
+Create executor in `open-sse/executors/your-provider.ts` extending the base executor.
+
+### Step 3: Add Translator (if non-OpenAI format)
+
+Create request/response translators in `open-sse/translator/`.
+
+### Step 4: Add OAuth Config (if OAuth-based)
+
+Add OAuth credentials in `src/lib/oauth/constants/oauth.ts` and service in `src/lib/oauth/services/`.
+
+### Step 5: Register Models
+
+Add model definitions in `open-sse/config/providerRegistry.ts`.
+
+### Step 6: Add Tests
+
+Write unit tests in `tests/unit/` covering at minimum:
+
+- Provider registration
+- Request/response translation
+- Error handling
+
+---
+
+## Pull Request Checklist
+
+- [ ] Tests pass (`npm test`)
+- [ ] Linting passes (`npm run lint`)
+- [ ] Build succeeds (`npm run build`)
+- [ ] TypeScript types added for new public functions and interfaces
+- [ ] No hardcoded secrets or fallback values
+- [ ] All inputs validated with Zod schemas
+- [ ] CHANGELOG updated (if user-facing change)
+- [ ] Documentation updated (if applicable)
+
+---
+
+## Releasing
+
+Releases are managed via the `/generate-release` workflow. When a new GitHub Release is created, the package is **automatically published to npm** via GitHub Actions.
+
+---
+
+## Getting Help
+
+- **Architecture**: See [`docs/ARCHITECTURE.md`](docs/ARCHITECTURE.md)
+- **API Reference**: See [`docs/API_REFERENCE.md`](docs/API_REFERENCE.md)
+- **Issues**: [github.com/diegosouzapw/OmniRoute/issues](https://github.com/diegosouzapw/OmniRoute/issues)
+- **ADRs**: See `docs/adr/` for architectural decision records
diff --git a/docs/i18n/he/FEATURES.md b/docs/i18n/he/FEATURES.md
deleted file mode 100644
index 371ab6cc4f..0000000000
--- a/docs/i18n/he/FEATURES.md
+++ /dev/null
@@ -1,147 +0,0 @@
-# OmniRoute — Dashboard Features Gallery (עברית)
-
-🌐 **Languages:** 🇺🇸 [English](../../../README.md) · 🇧🇷 [pt-BR](../pt-BR/README.md) · 🇪🇸 [es](../es/README.md) · 🇫🇷 [fr](../fr/README.md) · 🇩🇪 [de](../de/README.md) · 🇮🇹 [it](../it/README.md) · 🇷🇺 [ru](../ru/README.md) · 🇨🇳 [zh-CN](../zh-CN/README.md) · 🇯🇵 [ja](../ja/README.md) · 🇰🇷 [ko](../ko/README.md) · 🇸🇦 [ar](../ar/README.md) · 🇮🇳 [in](../in/README.md) · 🇹🇭 [th](../th/README.md) · 🇻🇳 [vi](../vi/README.md) · 🇮🇩 [id](../id/README.md) · 🇲🇾 [ms](../ms/README.md) · 🇳🇱 [nl](../nl/README.md) · 🇵🇱 [pl](../pl/README.md) · 🇸🇪 [sv](../sv/README.md) · 🇳🇴 [no](../no/README.md) · 🇩🇰 [da](../da/README.md) · 🇫🇮 [fi](../fi/README.md) · 🇵🇹 [pt](../pt/README.md) · 🇷🇴 [ro](../ro/README.md) · 🇭🇺 [hu](../hu/README.md) · 🇧🇬 [bg](../bg/README.md) · 🇸🇰 [sk](../sk/README.md) · 🇺🇦 [uk-UA](../uk-UA/README.md) · 🇮🇱 [he](../he/README.md) · 🇵🇭 [phi](../phi/README.md)
-
-> 🇺🇸 [English](../../../docs/FEATURES.md)
-
----
-
-Visual guide to every section of the OmniRoute dashboard.
-
----
-
-## 🔌 Providers
-
-Manage AI provider connections: OAuth providers (Claude Code, Codex, Gemini CLI), API key providers (Groq, DeepSeek, OpenRouter), and free providers (Qoder, Qwen, Kiro). Kiro accounts include credit balance tracking — remaining credits, total allowance, and renewal date visible in Dashboard → Usage.
-
-
-
----
-
-## 🎨 Combos
-
-Create model routing combos with 6 strategies: priority, weighted, round-robin, random, least-used, and cost-optimized. Each combo chains multiple models with automatic fallback and includes quick templates and readiness checks.
-
-
-
----
-
-## 📊 Analytics
-
-Comprehensive usage analytics with token consumption, cost estimates, activity heatmaps, weekly distribution charts, and per-provider breakdowns.
-
-
-
----
-
-## 🏥 System Health
-
-Real-time monitoring: uptime, memory, version, latency percentiles (p50/p95/p99), cache statistics, and provider circuit breaker states.
-
-
-
----
-
-## 🔧 Translator Playground
-
-Four modes for debugging API translations: **Playground** (format converter), **Chat Tester** (live requests), **Test Bench** (batch tests), and **Live Monitor** (real-time stream).
-
-
-
----
-
-## 🎮 Model Playground _(v2.0.9+)_
-
-Test any model directly from the dashboard. Select provider, model, and endpoint, write prompts with Monaco Editor, stream responses in real-time, abort mid-stream, and view timing metrics.
-
----
-
-## 🎨 Themes _(v2.0.5+)_
-
-Customizable color themes for the entire dashboard. Choose from 7 preset colors (Coral, Blue, Red, Green, Violet, Orange, Cyan) or create a custom theme by picking any hex color. Supports light, dark, and system mode.
-
----
-
-## ⚙️ Settings
-
-Comprehensive settings panel with tabs:
-
-- **General** — System storage, backup management (export/import database)
-- **Appearance** — Theme selector (dark/light/system), color theme presets and custom colors, health log visibility, sidebar item visibility controls
-- **Security** — API endpoint protection, custom provider blocking, IP filtering, session info
-- **Routing** — Model aliases, background task degradation
-- **Resilience** — Rate limit persistence, circuit breaker tuning
-- **Advanced** — Configuration overrides
-
-
-
----
-
-## 🔧 CLI Tools
-
-One-click configuration for AI coding tools: Claude Code, Codex CLI, Gemini CLI, OpenClaw, Kilo Code, Antigravity, Cline, Continue, Cursor, and Factory Droid. Features automated config apply/reset, connection profiles, and model mapping.
-
-
-
----
-
-## 🤖 CLI Agents _(v2.0.11+)_
-
-Dashboard for discovering and managing CLI agents. Shows a grid of 14 built-in agents (Codex, Claude, Goose, Gemini CLI, OpenClaw, Aider, OpenCode, Cline, Qwen Code, ForgeCode, Amazon Q, Open Interpreter, Cursor CLI, Warp) with:
-
-- **Installation status** — Installed / Not Found with version detection
-- **Protocol badges** — stdio, HTTP, etc.
-- **Custom agents** — Register any CLI tool via form (name, binary, version command, spawn args)
-- **CLI Fingerprint Matching** — Per-provider toggle to match native CLI request signatures, reducing ban risk while preserving proxy IP
-
----
-
-## 🖼️ Media _(v2.0.3+)_
-
-Generate images, videos, and music from the dashboard. Supports OpenAI, xAI, Together, Hyperbolic, SD WebUI, ComfyUI, AnimateDiff, Stable Audio Open, and MusicGen.
-
----
-
-## 📝 Request Logs
-
-Real-time request logging with filtering by provider, model, account, and API key. Shows status codes, token usage, latency, and response details.
-
-
-
----
-
-## 🌐 API Endpoint
-
-Your unified API endpoint with capability breakdown: Chat Completions, Responses API, Embeddings, Image Generation, Reranking, Audio Transcription, Text-to-Speech, Moderations, and registered API keys. Cloud proxy support for remote access.
-
-
-
----
-
-## 🔑 API Key Management
-
-Create, scope, and revoke API keys. Each key can be restricted to specific models/providers with full access or read-only permissions. Visual key management with usage tracking.
-
----
-
-## 📋 Audit Log
-
-Administrative action tracking with filtering by action type, actor, target, IP address, and timestamp. Full security event history.
-
----
-
-## 🖥️ Desktop Application
-
-Native Electron desktop app for Windows, macOS, and Linux. Run OmniRoute as a standalone application with system tray integration, offline support, auto-update, and one-click install.
-
-Key features:
-
-- Server readiness polling (no blank screen on cold start)
-- System tray with port management
-- Content Security Policy
-- Single-instance lock
-- Auto-update on restart
-- Platform-conditional UI (macOS traffic lights, Windows/Linux default titlebar)
-- Hardened Electron build packaging — symlinked `node_modules` in the standalone bundle is detected and rejected before packaging, preventing runtime dependency on the build machine (v2.5.5+)
-
-📖 See [`electron/README.md`](../electron/README.md) for full documentation.
diff --git a/docs/i18n/he/MCP-SERVER.md b/docs/i18n/he/MCP-SERVER.md
deleted file mode 100644
index 829acd30b1..0000000000
--- a/docs/i18n/he/MCP-SERVER.md
+++ /dev/null
@@ -1,87 +0,0 @@
-🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/MCP-SERVER.md) · 🇪🇸 [es](../es/MCP-SERVER.md) · 🇫🇷 [fr](../fr/MCP-SERVER.md) · 🇩🇪 [de](../de/MCP-SERVER.md) · 🇮🇹 [it](../it/MCP-SERVER.md) · 🇷🇺 [ru](../ru/MCP-SERVER.md) · 🇨🇳 [zh-CN](../zh-CN/MCP-SERVER.md) · 🇯🇵 [ja](../ja/MCP-SERVER.md) · 🇰🇷 [ko](../ko/MCP-SERVER.md) · 🇸🇦 [ar](../ar/MCP-SERVER.md) · 🇮🇳 [in](../in/MCP-SERVER.md) · 🇹🇭 [th](../th/MCP-SERVER.md) · 🇻🇳 [vi](../vi/MCP-SERVER.md) · 🇮🇩 [id](../id/MCP-SERVER.md) · 🇲🇾 [ms](../ms/MCP-SERVER.md) · 🇳🇱 [nl](../nl/MCP-SERVER.md) · 🇵🇱 [pl](../pl/MCP-SERVER.md) · 🇸🇪 [sv](../sv/MCP-SERVER.md) · 🇳🇴 [no](../no/MCP-SERVER.md) · 🇩🇰 [da](../da/MCP-SERVER.md) · 🇫🇮 [fi](../fi/MCP-SERVER.md) · 🇵🇹 [pt](../pt/MCP-SERVER.md) · 🇷🇴 [ro](../ro/MCP-SERVER.md) · 🇭🇺 [hu](../hu/MCP-SERVER.md) · 🇧🇬 [bg](../bg/MCP-SERVER.md) · 🇸🇰 [sk](../sk/MCP-SERVER.md) · 🇺🇦 [uk-UA](../uk-UA/MCP-SERVER.md) · 🇮🇱 [he](../he/MCP-SERVER.md) · 🇵🇭 [phi](../phi/MCP-SERVER.md)
-
----
-
-# OmniRoute MCP Server Documentation
-
-> Model Context Protocol server with 16 intelligent tools
-
-## Installation
-
-OmniRoute MCP is built-in. Start it with:
-
-```bash
-omniroute --mcp
-```
-
-Or via the open-sse transport:
-
-```bash
-# HTTP streamable transport (port 20130)
-omniroute --dev # MCP auto-starts on /mcp endpoint
-```
-
-## IDE Configuration
-
-See [IDE Configs](integrations/ide-configs.md) for Antigravity, Cursor, Copilot, and Claude Desktop setup.
-
----
-
-## Essential Tools (8)
-
-| Tool | Description |
-| :------------------------------ | :--------------------------------------- |
-| `omniroute_get_health` | Gateway health, circuit breakers, uptime |
-| `omniroute_list_combos` | All configured combos with models |
-| `omniroute_get_combo_metrics` | Performance metrics for a specific combo |
-| `omniroute_switch_combo` | Switch active combo by ID/name |
-| `omniroute_check_quota` | Quota status per provider or all |
-| `omniroute_route_request` | Send a chat completion through OmniRoute |
-| `omniroute_cost_report` | Cost analytics for a time period |
-| `omniroute_list_models_catalog` | Full model catalog with capabilities |
-
-## Advanced Tools (8)
-
-| Tool | Description |
-| :--------------------------------- | :---------------------------------------------- |
-| `omniroute_simulate_route` | Dry-run routing simulation with fallback tree |
-| `omniroute_set_budget_guard` | Session budget with degrade/block/alert actions |
-| `omniroute_set_resilience_profile` | Apply conservative/balanced/aggressive preset |
-| `omniroute_test_combo` | Live-test all models in a combo |
-| `omniroute_get_provider_metrics` | Detailed metrics for one provider |
-| `omniroute_best_combo_for_task` | Task-fitness recommendation with alternatives |
-| `omniroute_explain_route` | Explain a past routing decision |
-| `omniroute_get_session_snapshot` | Full session state: costs, tokens, errors |
-
-## Authentication
-
-MCP tools are authenticated via API key scopes. Each tool requires specific scopes:
-
-| Scope | Tools |
-| :------------- | :----------------------------------------------- |
-| `read:health` | get_health, get_provider_metrics |
-| `read:combos` | list_combos, get_combo_metrics |
-| `write:combos` | switch_combo |
-| `read:quota` | check_quota |
-| `write:route` | route_request, simulate_route, test_combo |
-| `read:usage` | cost_report, get_session_snapshot, explain_route |
-| `write:config` | set_budget_guard, set_resilience_profile |
-| `read:models` | list_models_catalog, best_combo_for_task |
-
-## Audit Logging
-
-Every tool call is logged to `mcp_tool_audit` with:
-
-- Tool name, arguments, result
-- Duration (ms), success/failure
-- API key hash, timestamp
-
-## Files
-
-| File | Purpose |
-| :------------------------------------------- | :------------------------------------------ |
-| `open-sse/mcp-server/server.ts` | MCP server creation + 16 tool registrations |
-| `open-sse/mcp-server/transport.ts` | Stdio + HTTP transport |
-| `open-sse/mcp-server/auth.ts` | API key + scope validation |
-| `open-sse/mcp-server/audit.ts` | Tool call audit logging |
-| `open-sse/mcp-server/tools/advancedTools.ts` | 8 advanced tool handlers |
diff --git a/docs/i18n/he/README.md b/docs/i18n/he/README.md
index d1406a31cd..3590dce8c9 100644
--- a/docs/i18n/he/README.md
+++ b/docs/i18n/he/README.md
@@ -1,13 +1,12 @@
# 🚀 OmniRoute — The Free AI Gateway (עברית)
-🌐 **Languages:** 🇺🇸 [English](../../../README.md) · 🇪🇸 [es](../es/README.md) · 🇫🇷 [fr](../fr/README.md) · 🇩🇪 [de](../de/README.md) · 🇮🇹 [it](../it/README.md) · 🇷🇺 [ru](../ru/README.md) · 🇨🇳 [zh-CN](../zh-CN/README.md) · 🇯🇵 [ja](../ja/README.md) · 🇰🇷 [ko](../ko/README.md) · 🇸🇦 [ar](../ar/README.md) · 🇮🇳 [in](../in/README.md) · 🇹🇭 [th](../th/README.md) · 🇻🇳 [vi](../vi/README.md) · 🇮🇩 [id](../id/README.md) · 🇲🇾 [ms](../ms/README.md) · 🇳🇱 [nl](../nl/README.md) · 🇵🇱 [pl](../pl/README.md) · 🇸🇪 [sv](../sv/README.md) · 🇳🇴 [no](../no/README.md) · 🇩🇰 [da](../da/README.md) · 🇫🇮 [fi](../fi/README.md) · 🇵🇹 [pt](../pt/README.md) · 🇷🇴 [ro](../ro/README.md) · 🇭🇺 [hu](../hu/README.md) · 🇧🇬 [bg](../bg/README.md) · 🇸🇰 [sk](../sk/README.md) · 🇺🇦 [uk-UA](../uk-UA/README.md) · 🇮🇱 [he](../he/README.md) · 🇵🇭 [phi](../phi/README.md) · 🇧🇷 [pt-BR](../pt-BR/README.md)
+🌐 **Languages:** 🇺🇸 [English](../../../README.md) · 🇪🇸 [es](../es/README.md) · 🇫🇷 [fr](../fr/README.md) · 🇩🇪 [de](../de/README.md) · 🇮🇹 [it](../it/README.md) · 🇷🇺 [ru](../ru/README.md) · 🇨🇳 [zh-CN](../zh-CN/README.md) · 🇯🇵 [ja](../ja/README.md) · 🇰🇷 [ko](../ko/README.md) · 🇸🇦 [ar](../ar/README.md) · 🇮🇳 [in](../in/README.md) · 🇹🇭 [th](../th/README.md) · 🇻🇳 [vi](../vi/README.md) · 🇮🇩 [id](../id/README.md) · 🇲🇾 [ms](../ms/README.md) · 🇳🇱 [nl](../nl/README.md) · 🇵🇱 [pl](../pl/README.md) · 🇸🇪 [sv](../sv/README.md) · 🇳🇴 [no](../no/README.md) · 🇩🇰 [da](../da/README.md) · 🇫🇮 [fi](../fi/README.md) · 🇵🇹 [pt](../pt/README.md) · 🇷🇴 [ro](../ro/README.md) · 🇭🇺 [hu](../hu/README.md) · 🇧🇬 [bg](../bg/README.md) · 🇸🇰 [sk](../sk/README.md) · 🇺🇦 [uk-UA](../uk-UA/README.md) · 🇮🇱 [he](../he/README.md) · 🇵🇭 [phi](../phi/README.md) · 🇧🇷 [pt-BR](../pt-BR/README.md) · 🇨🇿 [cs](../cs/README.md)
---
-
### Never stop coding. Smart routing to **FREE & low-cost AI models** with automatic fallback.
-_Your universal API proxy — one endpoint, 67+ providers, zero downtime. Now with **MCP & A2A** agent orchestration._
+_Your universal API proxy — one endpoint, 60+ providers, zero downtime. Now with **MCP Server (25 tools)**, **A2A Protocol**, **Memory/Skills Systems** & **Electron Desktop App**._
**Chat Completions • Embeddings • Image Generation • Video • Music • Audio • Reranking • **Web Search** • MCP Server • A2A Protocol • 100% TypeScript**
@@ -47,15 +46,17 @@ _Your universal API proxy — one endpoint, 67+ providers, zero downtime. Now wi
> - `APP_LOG_FILE_PATH`
> - `APP_LOG_MAX_FILE_SIZE`
> - `APP_LOG_RETENTION_DAYS`
+> - `APP_LOG_MAX_FILES`
> - `APP_LOG_LEVEL`
> - `APP_LOG_FORMAT`
> - `CALL_LOG_RETENTION_DAYS`
+> - `CALL_LOG_MAX_ENTRIES`
>
> For release details and upgrade notes, see the [CHANGELOG](CHANGELOG.md).
---
-## 🆕 What's New in v3.0.0
+## 🆕 What's New
> **Upgrading from v2.9.5?** — See the [full CHANGELOG](CHANGELOG.md#300--2026-03-22-release-candidate--not-yet-merged-to-main) for all changes.
@@ -275,7 +276,7 @@ Developers pay $20–200/month for Claude Pro, Codex Pro, or GitHub Copilot. Eve
- **Smart 4-Tier Fallback** — If subscription quota runs out, automatically redirects to API Key → Cheap → Free with zero manual intervention
- **Real-Time Quota Tracking** — Shows token consumption in real-time with reset countdown (5h, daily, weekly)
- **Multi-Account Support** — Multiple accounts per provider with auto round-robin — when one runs out, switches to the next
-- **Custom Combos** — Customizable fallback chains with 6 balancing strategies (fill-first, round-robin, P2C, random, least-used, cost-optimized)
+- **Custom Combos** — Customizable fallback chains with 9 balancing strategies (priority, weighted, fill-first, round-robin, P2C, random, least-used, cost-optimized, strict-random)
- **Codex Business Quotas** — Business/Team workspace quota monitoring directly in the dashboard
@@ -287,7 +288,7 @@ OpenAI uses one format, Claude (Anthropic) uses another, Gemini yet another. If
**How OmniRoute solves it:**
-- **Unified Endpoint** — A single `http://localhost:20128/v1` serves as proxy for all 67+ providers
+- **Unified Endpoint** — A single `http://localhost:20128/v1` serves as proxy for all 60+ providers
- **Format Translation** — Automatic and transparent: OpenAI ↔ Claude ↔ Gemini ↔ Responses API
- **Response Sanitization** — Strips non-standard fields (`x_groq`, `usage_breakdown`, `service_tier`) that break OpenAI SDK v1.83+
- **Role Normalization** — Converts `developer` → `system` for non-OpenAI providers; `system` → `user` for GLM/ERNIE
@@ -373,7 +374,7 @@ Developers use Cursor, Claude Code, Codex CLI, OpenClaw, Gemini CLI, Kilo Code..
- **CLI Tools Dashboard** — Dedicated page with one-click setup for Claude Code, Codex CLI, OpenClaw, Kilo Code, Antigravity, Cline
- **GitHub Copilot Config Generator** — Generates `chatLanguageModels.json` for VS Code with bulk model selection
- **Onboarding Wizard** — Guided 4-step setup for first-time users
-- **One endpoint, all models** — Configure `http://localhost:20128/v1` once, access 67+ providers
+- **One endpoint, all models** — Configure `http://localhost:20128/v1` once, access 60+ providers
@@ -420,7 +421,7 @@ When a call fails, the dev doesn't know if it was a rate limit, expired token, w
- **SQLite Proxy Logs** — Persistent logs that survive server restarts
- **Translator Playground** — 4 debugging modes: Playground (format translation), Chat Tester (round-trip), Test Bench (batch), Live Monitor (real-time)
- **Request Telemetry** — p50/p95/p99 latency + X-Request-Id tracing
-- **File-Based Logging with Rotation** — Console interceptor captures everything to JSON log with size-based rotation
+- **File-Based Logging with Rotation** — App logs rotate by size, retention days, and archive count; call log artifacts rotate by retention days and file count
- **System Info Report** — `npm run system-info` generates `system-info.txt` with your full environment (Node version, OmniRoute version, OS, CLI tools, Docker/PM2 status). Attach it when reporting issues for instant triage.
@@ -515,7 +516,7 @@ Developers who want all responses in a specific language, with a specific tone,
- **System Prompt Injection** — Global prompt applied to all requests
- **Thinking Budget Validation** — Reasoning token allocation control per request (passthrough, auto, custom, adaptive)
-- **6 Routing Strategies** — Global strategies that determine how requests are distributed
+- **9 Routing Strategies** — Global strategies that determine how requests are distributed
- **Wildcard Router** — `provider/*` patterns route dynamically to any provider
- **Combo Enable/Disable Toggle** — Toggle combos directly from the dashboard
- **Provider Toggle** — Enable/disable all connections for a provider with one click
@@ -582,7 +583,7 @@ Different clients should have least-privilege access to tool categories.
**How OmniRoute solves it:**
-- 9 granular MCP scopes for controlled tool access
+- 10 granular MCP scopes for controlled tool access
- Scope enforcement and visibility in MCP management UI
- Safe default posture for operational tooling
@@ -1326,19 +1327,19 @@ OmniRoute v2.0 is built as an operational platform, not just a relay proxy.
### 🤖 Agent & Protocol Operations (v2.0)
-| Feature | What It Does |
-| ------------------------------------- | -------------------------------------------------------------------------------------------------- |
-| 🔧 **MCP Server (16 tools)** | IDE/agent tools via 3 transports: stdio, SSE (`/api/mcp/sse`), Streamable HTTP (`/api/mcp/stream`) |
-| 🤝 **A2A Server (JSON-RPC + SSE)** | Agent-to-agent task execution with sync and streaming flows |
-| 🧭 **Consolidated Endpoints Page** | Tabbed management page with Endpoint Proxy, MCP, A2A, and API Endpoints tabs |
-| 🎚️ **Service Enable/Disable Toggles** | ON/OFF switches for MCP and A2A with settings persistence (default: OFF) |
-| 🛰️ **MCP Runtime Heartbeat** | Real process status (pid, uptime, heartbeat age, transport, scope mode) |
-| 📋 **MCP Audit Trail** | Filterable audit logs with success/failure and key attribution |
-| 🔐 **MCP Scope Enforcement** | 9 granular scope permissions for controlled tool access |
-| 📡 **A2A Task Lifecycle Management** | List/filter tasks, inspect events/artifacts, cancel running tasks |
-| 📋 **Agent Card Discovery** | `/.well-known/agent.json` for client auto-discovery |
-| 🧪 **Protocol E2E Test Harness** | Real MCP SDK + A2A client flows in `test:protocols:e2e` |
-| ⚙️ **Operational Controls** | Switch combo, apply resilience profiles, reset breakers from one control surface |
+| Feature | What It Does |
+| ------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------- |
+| 🔧 **MCP Server (25 tools)** | IDE/agent tools via 3 transports: stdio, SSE (`/api/mcp/sse`), Streamable HTTP (`/api/mcp/stream`). 18 core + 3 memory + 4 skill tools |
+| 🤝 **A2A Server (JSON-RPC + SSE)** | Agent-to-agent task execution with sync and streaming flows |
+| 🧭 **Consolidated Endpoints Page** | Tabbed management page with Endpoint Proxy, MCP, A2A, and API Endpoints tabs |
+| 🎚️ **Service Enable/Disable Toggles** | ON/OFF switches for MCP and A2A with settings persistence (default: OFF) |
+| 🛰️ **MCP Runtime Heartbeat** | Real process status (pid, uptime, heartbeat age, transport, scope mode) |
+| 📋 **MCP Audit Trail** | Filterable audit logs with success/failure and key attribution |
+| 🔐 **MCP Scope Enforcement** | 10 granular scope permissions for controlled tool access |
+| 📡 **A2A Task Lifecycle Management** | List/filter tasks, inspect events/artifacts, cancel running tasks |
+| 📋 **Agent Card Discovery** | `/.well-known/agent.json` for client auto-discovery |
+| 🧪 **Protocol E2E Test Harness** | Real MCP SDK + A2A client flows in `test:protocols:e2e` |
+| ⚙️ **Operational Controls** | Switch combo, apply resilience profiles, reset breakers from one control surface |
### 🧠 Routing & Intelligence
@@ -1349,7 +1350,7 @@ OmniRoute v2.0 is built as an operational platform, not just a relay proxy.
| 🔄 **Format Translation** | OpenAI ↔ Claude ↔ Gemini ↔ Responses with schema-safe conversions |
| 👥 **Multi-Account Support** | Multiple accounts per provider with intelligent selection |
| 🔄 **Auto Token Refresh** | OAuth tokens refresh automatically with retry |
-| 🎨 **Custom Combos** | 6 balancing strategies + fallback chain control |
+| 🎨 **Custom Combos** | 9 balancing strategies + fallback chain control |
| 🌐 **Wildcard Router** | `provider/*` dynamic routing |
| 🧠 **Thinking Budget Controls** | Passthrough, auto, custom, and adaptive reasoning limits |
| 🔀 **Model Aliases** | Built-in + custom model aliasing and migration safety |
@@ -1950,6 +1951,7 @@ opencode
- Request artifacts are written to `DATA_DIR/call_logs/` as one JSON file per request
- Enable pipeline capture from Dashboard → Logs → Request Logs if you need detailed per-stage payloads
- Set `APP_LOG_TO_FILE=true` if you also want application console logs in `logs/application/app.log`
+- Adjust `APP_LOG_MAX_FILE_SIZE`, `APP_LOG_RETENTION_DAYS`, `APP_LOG_MAX_FILES`, and `CALL_LOG_MAX_ENTRIES` as needed
**Connection test shows "Invalid" for OpenAI-compatible providers**
diff --git a/docs/i18n/he/RELEASE_CHECKLIST.md b/docs/i18n/he/RELEASE_CHECKLIST.md
deleted file mode 100644
index 903e812c3f..0000000000
--- a/docs/i18n/he/RELEASE_CHECKLIST.md
+++ /dev/null
@@ -1,37 +0,0 @@
-🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/RELEASE_CHECKLIST.md) · 🇪🇸 [es](../es/RELEASE_CHECKLIST.md) · 🇫🇷 [fr](../fr/RELEASE_CHECKLIST.md) · 🇩🇪 [de](../de/RELEASE_CHECKLIST.md) · 🇮🇹 [it](../it/RELEASE_CHECKLIST.md) · 🇷🇺 [ru](../ru/RELEASE_CHECKLIST.md) · 🇨🇳 [zh-CN](../zh-CN/RELEASE_CHECKLIST.md) · 🇯🇵 [ja](../ja/RELEASE_CHECKLIST.md) · 🇰🇷 [ko](../ko/RELEASE_CHECKLIST.md) · 🇸🇦 [ar](../ar/RELEASE_CHECKLIST.md) · 🇮🇳 [in](../in/RELEASE_CHECKLIST.md) · 🇹🇭 [th](../th/RELEASE_CHECKLIST.md) · 🇻🇳 [vi](../vi/RELEASE_CHECKLIST.md) · 🇮🇩 [id](../id/RELEASE_CHECKLIST.md) · 🇲🇾 [ms](../ms/RELEASE_CHECKLIST.md) · 🇳🇱 [nl](../nl/RELEASE_CHECKLIST.md) · 🇵🇱 [pl](../pl/RELEASE_CHECKLIST.md) · 🇸🇪 [sv](../sv/RELEASE_CHECKLIST.md) · 🇳🇴 [no](../no/RELEASE_CHECKLIST.md) · 🇩🇰 [da](../da/RELEASE_CHECKLIST.md) · 🇫🇮 [fi](../fi/RELEASE_CHECKLIST.md) · 🇵🇹 [pt](../pt/RELEASE_CHECKLIST.md) · 🇷🇴 [ro](../ro/RELEASE_CHECKLIST.md) · 🇭🇺 [hu](../hu/RELEASE_CHECKLIST.md) · 🇧🇬 [bg](../bg/RELEASE_CHECKLIST.md) · 🇸🇰 [sk](../sk/RELEASE_CHECKLIST.md) · 🇺🇦 [uk-UA](../uk-UA/RELEASE_CHECKLIST.md) · 🇮🇱 [he](../he/RELEASE_CHECKLIST.md) · 🇵🇭 [phi](../phi/RELEASE_CHECKLIST.md)
-
----
-
-# Release Checklist
-
-Use this checklist before tagging or publishing a new OmniRoute release.
-
-## Version and Changelog
-
-1. Bump `package.json` version (`x.y.z`) in the release branch.
-2. Move release notes from `## [Unreleased]` in `CHANGELOG.md` to a dated section:
- - `## [x.y.z] — YYYY-MM-DD`
-3. Keep `## [Unreleased]` as the first changelog section for upcoming work.
-4. Ensure the latest semver section in `CHANGELOG.md` equals `package.json` version.
-
-## API Docs
-
-1. Update `docs/openapi.yaml`:
- - `info.version` must equal `package.json` version.
-2. Validate endpoint examples if API contracts changed.
-
-## Runtime Docs
-
-1. Review `docs/ARCHITECTURE.md` for storage/runtime drift.
-2. Review `docs/TROUBLESHOOTING.md` for env var and operational drift.
-3. Update localized docs if source docs changed significantly.
-
-## Automated Check
-
-Run the sync guard locally before opening PR:
-
-```bash
-npm run check:docs-sync
-```
-
-CI also runs this check in `.github/workflows/ci.yml` (lint job).
diff --git a/docs/i18n/he/SECURITY.md b/docs/i18n/he/SECURITY.md
new file mode 100644
index 0000000000..a542414696
--- /dev/null
+++ b/docs/i18n/he/SECURITY.md
@@ -0,0 +1,179 @@
+# Security Policy (עברית)
+
+🌐 **Languages:** 🇺🇸 [English](../../../SECURITY.md) · 🇪🇸 [es](../es/SECURITY.md) · 🇫🇷 [fr](../fr/SECURITY.md) · 🇩🇪 [de](../de/SECURITY.md) · 🇮🇹 [it](../it/SECURITY.md) · 🇷🇺 [ru](../ru/SECURITY.md) · 🇨🇳 [zh-CN](../zh-CN/SECURITY.md) · 🇯🇵 [ja](../ja/SECURITY.md) · 🇰🇷 [ko](../ko/SECURITY.md) · 🇸🇦 [ar](../ar/SECURITY.md) · 🇮🇳 [in](../in/SECURITY.md) · 🇹🇭 [th](../th/SECURITY.md) · 🇻🇳 [vi](../vi/SECURITY.md) · 🇮🇩 [id](../id/SECURITY.md) · 🇲🇾 [ms](../ms/SECURITY.md) · 🇳🇱 [nl](../nl/SECURITY.md) · 🇵🇱 [pl](../pl/SECURITY.md) · 🇸🇪 [sv](../sv/SECURITY.md) · 🇳🇴 [no](../no/SECURITY.md) · 🇩🇰 [da](../da/SECURITY.md) · 🇫🇮 [fi](../fi/SECURITY.md) · 🇵🇹 [pt](../pt/SECURITY.md) · 🇷🇴 [ro](../ro/SECURITY.md) · 🇭🇺 [hu](../hu/SECURITY.md) · 🇧🇬 [bg](../bg/SECURITY.md) · 🇸🇰 [sk](../sk/SECURITY.md) · 🇺🇦 [uk-UA](../uk-UA/SECURITY.md) · 🇮🇱 [he](../he/SECURITY.md) · 🇵🇭 [phi](../phi/SECURITY.md) · 🇧🇷 [pt-BR](../pt-BR/SECURITY.md) · 🇨🇿 [cs](../cs/SECURITY.md)
+
+---
+
+## Reporting Vulnerabilities
+
+If you discover a security vulnerability in OmniRoute, please report it responsibly:
+
+1. **DO NOT** open a public GitHub issue
+2. Use [GitHub Security Advisories](https://github.com/diegosouzapw/OmniRoute/security/advisories/new)
+3. Include: description, reproduction steps, and potential impact
+
+## Response Timeline
+
+| Stage | Target |
+| ------------------- | --------------------------- |
+| Acknowledgment | 48 hours |
+| Triage & Assessment | 5 business days |
+| Patch Release | 14 business days (critical) |
+
+## Supported Versions
+
+| Version | Support Status |
+| ------- | -------------- |
+| 3.4.x | ✅ Active |
+| 3.0.x | ✅ Security |
+| < 3.0.0 | ❌ Unsupported |
+
+---
+
+## Security Architecture
+
+OmniRoute implements a multi-layered security model:
+
+```
+Request → CORS → API Key Auth → Prompt Injection Guard → Input Sanitizer → Rate Limiter → Circuit Breaker → Provider
+```
+
+### 🔐 Authentication & Authorization
+
+| Feature | Implementation |
+| -------------------- | ---------------------------------------------------------- |
+| **Dashboard Login** | Password-based auth with JWT tokens (HttpOnly cookies) |
+| **API Key Auth** | HMAC-signed keys with CRC validation |
+| **OAuth 2.0 + PKCE** | Secure provider auth (Claude, Codex, Gemini, Cursor, etc.) |
+| **Token Refresh** | Automatic OAuth token refresh before expiry |
+| **Secure Cookies** | `AUTH_COOKIE_SECURE=true` for HTTPS environments |
+| **MCP Scopes** | 10 granular scopes for MCP tool access control |
+
+### 🛡️ Encryption at Rest
+
+All sensitive data stored in SQLite is encrypted using **AES-256-GCM** with scrypt key derivation:
+
+- API keys, access tokens, refresh tokens, and ID tokens
+- Versioned format: `enc:v1:::`
+- Passthrough mode (plaintext) when `STORAGE_ENCRYPTION_KEY` is not set
+
+```bash
+# Generate encryption key:
+STORAGE_ENCRYPTION_KEY=$(openssl rand -hex 32)
+```
+
+### 🧠 Prompt Injection Guard
+
+Middleware that detects and blocks prompt injection attacks in LLM requests:
+
+| Pattern Type | Severity | Example |
+| ------------------- | -------- | ---------------------------------------------- |
+| System Override | High | "ignore all previous instructions" |
+| Role Hijack | High | "you are now DAN, you can do anything" |
+| Delimiter Injection | Medium | Encoded separators to break context boundaries |
+| DAN/Jailbreak | High | Known jailbreak prompt patterns |
+| Instruction Leak | Medium | "show me your system prompt" |
+
+Configure via dashboard (Settings → Security) or `.env`:
+
+```env
+INPUT_SANITIZER_ENABLED=true
+INPUT_SANITIZER_MODE=block # warn | block | redact
+```
+
+### 🔒 PII Redaction
+
+Automatic detection and optional redaction of personally identifiable information:
+
+| PII Type | Pattern | Replacement |
+| ------------- | --------------------- | ------------------ |
+| Email | `user@domain.com` | `[EMAIL_REDACTED]` |
+| CPF (Brazil) | `123.456.789-00` | `[CPF_REDACTED]` |
+| CNPJ (Brazil) | `12.345.678/0001-00` | `[CNPJ_REDACTED]` |
+| Credit Card | `4111-1111-1111-1111` | `[CC_REDACTED]` |
+| Phone | `+55 11 99999-9999` | `[PHONE_REDACTED]` |
+| SSN (US) | `123-45-6789` | `[SSN_REDACTED]` |
+
+```env
+PII_REDACTION_ENABLED=true
+```
+
+### 🌐 Network Security
+
+| Feature | Description |
+| ------------------------ | ---------------------------------------------------------------- |
+| **CORS** | Configurable origin control (`CORS_ORIGIN` env var, default `*`) |
+| **IP Filtering** | Allowlist/blocklist IP ranges in dashboard |
+| **Rate Limiting** | Per-provider rate limits with automatic backoff |
+| **Anti-Thundering Herd** | Mutex + per-connection locking prevents cascading 502s |
+| **TLS Fingerprint** | Browser-like TLS fingerprint spoofing to reduce bot detection |
+| **CLI Fingerprint** | Per-provider header/body ordering to match native CLI signatures |
+
+### 🔌 Resilience & Availability
+
+| Feature | Description |
+| ----------------------- | ------------------------------------------------------------------ |
+| **Circuit Breaker** | 3-state (Closed → Open → Half-Open) per provider, SQLite-persisted |
+| **Request Idempotency** | 5-second dedup window for duplicate requests |
+| **Exponential Backoff** | Automatic retry with increasing delays |
+| **Health Dashboard** | Real-time provider health monitoring |
+
+### 📋 Compliance
+
+| Feature | Description |
+| ------------------ | ----------------------------------------------------------- |
+| **Log Retention** | Automatic cleanup after `CALL_LOG_RETENTION_DAYS` |
+| **No-Log Opt-out** | Per API key `noLog` flag disables request logging |
+| **Audit Log** | Administrative actions tracked in `audit_log` table |
+| **MCP Audit** | SQLite-backed audit logging for all MCP tool calls |
+| **Zod Validation** | All API inputs validated with Zod v4 schemas at module load |
+
+---
+
+## Required Environment Variables
+
+All secrets must be set before starting the server. The server will **fail fast** if they are missing or weak.
+
+```bash
+# REQUIRED — server will not start without these:
+JWT_SECRET=$(openssl rand -base64 48) # min 32 chars
+API_KEY_SECRET=$(openssl rand -hex 32) # min 16 chars
+
+# RECOMMENDED — enables encryption at rest:
+STORAGE_ENCRYPTION_KEY=$(openssl rand -hex 32)
+```
+
+The server actively rejects known-weak values like `changeme`, `secret`, or `password`.
+
+---
+
+## Docker Security
+
+- Use non-root user in production
+- Mount secrets as read-only volumes
+- Never copy `.env` files into Docker images
+- Use `.dockerignore` to exclude sensitive files
+- Set `AUTH_COOKIE_SECURE=true` when behind HTTPS
+
+```bash
+docker run -d \
+ --name omniroute \
+ --restart unless-stopped \
+ --read-only \
+ -p 20128:20128 \
+ -v omniroute-data:/app/data \
+ -e JWT_SECRET="$(openssl rand -base64 48)" \
+ -e API_KEY_SECRET="$(openssl rand -hex 32)" \
+ -e STORAGE_ENCRYPTION_KEY="$(openssl rand -hex 32)" \
+ diegosouzapw/omniroute:latest
+```
+
+---
+
+## Dependencies
+
+- Run `npm audit` regularly
+- Keep dependencies updated
+- The project uses `husky` + `lint-staged` for pre-commit checks
+- CI pipeline runs ESLint security rules on every push
+- Provider constants validated at module load via Zod (`src/shared/validation/providerSchema.ts`)
diff --git a/docs/i18n/he/TROUBLESHOOTING.md b/docs/i18n/he/TROUBLESHOOTING.md
deleted file mode 100644
index 63c148000a..0000000000
--- a/docs/i18n/he/TROUBLESHOOTING.md
+++ /dev/null
@@ -1,258 +0,0 @@
-🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/TROUBLESHOOTING.md) · 🇪🇸 [es](../es/TROUBLESHOOTING.md) · 🇫🇷 [fr](../fr/TROUBLESHOOTING.md) · 🇩🇪 [de](../de/TROUBLESHOOTING.md) · 🇮🇹 [it](../it/TROUBLESHOOTING.md) · 🇷🇺 [ru](../ru/TROUBLESHOOTING.md) · 🇨🇳 [zh-CN](../zh-CN/TROUBLESHOOTING.md) · 🇯🇵 [ja](../ja/TROUBLESHOOTING.md) · 🇰🇷 [ko](../ko/TROUBLESHOOTING.md) · 🇸🇦 [ar](../ar/TROUBLESHOOTING.md) · 🇮🇳 [in](../in/TROUBLESHOOTING.md) · 🇹🇭 [th](../th/TROUBLESHOOTING.md) · 🇻🇳 [vi](../vi/TROUBLESHOOTING.md) · 🇮🇩 [id](../id/TROUBLESHOOTING.md) · 🇲🇾 [ms](../ms/TROUBLESHOOTING.md) · 🇳🇱 [nl](../nl/TROUBLESHOOTING.md) · 🇵🇱 [pl](../pl/TROUBLESHOOTING.md) · 🇸🇪 [sv](../sv/TROUBLESHOOTING.md) · 🇳🇴 [no](../no/TROUBLESHOOTING.md) · 🇩🇰 [da](../da/TROUBLESHOOTING.md) · 🇫🇮 [fi](../fi/TROUBLESHOOTING.md) · 🇵🇹 [pt](../pt/TROUBLESHOOTING.md) · 🇷🇴 [ro](../ro/TROUBLESHOOTING.md) · 🇭🇺 [hu](../hu/TROUBLESHOOTING.md) · 🇧🇬 [bg](../bg/TROUBLESHOOTING.md) · 🇸🇰 [sk](../sk/TROUBLESHOOTING.md) · 🇺🇦 [uk-UA](../uk-UA/TROUBLESHOOTING.md) · 🇮🇱 [he](../he/TROUBLESHOOTING.md) · 🇵🇭 [phi](../phi/TROUBLESHOOTING.md)
-
----
-
-# Troubleshooting
-
-🌐 **Languages:** 🇺🇸 [English](TROUBLESHOOTING.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/TROUBLESHOOTING.md) | 🇪🇸 [Español](i18n/es/TROUBLESHOOTING.md) | 🇫🇷 [Français](i18n/fr/TROUBLESHOOTING.md) | 🇮🇹 [Italiano](i18n/it/TROUBLESHOOTING.md) | 🇷🇺 [Русский](i18n/ru/TROUBLESHOOTING.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/TROUBLESHOOTING.md) | 🇩🇪 [Deutsch](i18n/de/TROUBLESHOOTING.md) | 🇮🇳 [हिन्दी](i18n/in/TROUBLESHOOTING.md) | 🇹🇭 [ไทย](i18n/th/TROUBLESHOOTING.md) | 🇺🇦 [Українська](i18n/uk-UA/TROUBLESHOOTING.md) | 🇸🇦 [العربية](i18n/ar/TROUBLESHOOTING.md) | 🇯🇵 [日本語](i18n/ja/TROUBLESHOOTING.md) | 🇻🇳 [Tiếng Việt](i18n/vi/TROUBLESHOOTING.md) | 🇧🇬 [Български](i18n/bg/TROUBLESHOOTING.md) | 🇩🇰 [Dansk](i18n/da/TROUBLESHOOTING.md) | 🇫🇮 [Suomi](i18n/fi/TROUBLESHOOTING.md) | 🇮🇱 [עברית](i18n/he/TROUBLESHOOTING.md) | 🇭🇺 [Magyar](i18n/hu/TROUBLESHOOTING.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/TROUBLESHOOTING.md) | 🇰🇷 [한국어](i18n/ko/TROUBLESHOOTING.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/TROUBLESHOOTING.md) | 🇳🇱 [Nederlands](i18n/nl/TROUBLESHOOTING.md) | 🇳🇴 [Norsk](i18n/no/TROUBLESHOOTING.md) | 🇵🇹 [Português (Portugal)](i18n/pt/TROUBLESHOOTING.md) | 🇷🇴 [Română](i18n/ro/TROUBLESHOOTING.md) | 🇵🇱 [Polski](i18n/pl/TROUBLESHOOTING.md) | 🇸🇰 [Slovenčina](i18n/sk/TROUBLESHOOTING.md) | 🇸🇪 [Svenska](i18n/sv/TROUBLESHOOTING.md) | 🇵🇭 [Filipino](i18n/phi/TROUBLESHOOTING.md)
-
-Common problems and solutions for OmniRoute.
-
----
-
-## Quick Fixes
-
-| Problem | Solution |
-| ----------------------------- | ------------------------------------------------------------------ |
-| First login not working | Set `INITIAL_PASSWORD` in `.env` (no hardcoded default) |
-| Dashboard opens on wrong port | Set `PORT=20128` and `NEXT_PUBLIC_BASE_URL=http://localhost:20128` |
-| No request logs under `logs/` | Set `ENABLE_REQUEST_LOGS=true` |
-| EACCES: permission denied | Set `DATA_DIR=/path/to/writable/dir` to override `~/.omniroute` |
-| Routing strategy not saving | Update to v1.4.11+ (Zod schema fix for settings persistence) |
-
----
-
-## Provider Issues
-
-### "Language model did not provide messages"
-
-**Cause:** Provider quota exhausted.
-
-**Fix:**
-
-1. Check dashboard quota tracker
-2. Use a combo with fallback tiers
-3. Switch to cheaper/free tier
-
-### Rate Limiting
-
-**Cause:** Subscription quota exhausted.
-
-**Fix:**
-
-- Add fallback: `cc/claude-opus-4-6 → glm/glm-4.7 → if/kimi-k2-thinking`
-- Use GLM/MiniMax as cheap backup
-
-### OAuth Token Expired
-
-OmniRoute auto-refreshes tokens. If issues persist:
-
-1. Dashboard → Provider → Reconnect
-2. Delete and re-add the provider connection
-
----
-
-## Cloud Issues
-
-### Cloud Sync Errors
-
-1. Verify `BASE_URL` points to your running instance (e.g., `http://localhost:20128`)
-2. Verify `CLOUD_URL` points to your cloud endpoint (e.g., `https://omniroute.dev`)
-3. Keep `NEXT_PUBLIC_*` values aligned with server-side values
-
-### Cloud `stream=false` Returns 500
-
-**Symptom:** `Unexpected token 'd'...` on cloud endpoint for non-streaming calls.
-
-**Cause:** Upstream returns SSE payload while client expects JSON.
-
-**Workaround:** Use `stream=true` for cloud direct calls. Local runtime includes SSE→JSON fallback.
-
-### Cloud Says Connected but "Invalid API key"
-
-1. Create a fresh key from local dashboard (`/api/keys`)
-2. Run cloud sync: Enable Cloud → Sync Now
-3. Old/non-synced keys can still return `401` on cloud
-
----
-
-## Docker Issues
-
-### CLI Tool Shows Not Installed
-
-1. Check runtime fields: `curl http://localhost:20128/api/cli-tools/runtime/codex | jq`
-2. For portable mode: use image target `runner-cli` (bundled CLIs)
-3. For host mount mode: set `CLI_EXTRA_PATHS` and mount host bin directory as read-only
-4. If `installed=true` and `runnable=false`: binary was found but failed healthcheck
-
-### Quick Runtime Validation
-
-```bash
-curl -s http://localhost:20128/api/cli-tools/codex-settings | jq '{installed,runnable,commandPath,runtimeMode,reason}'
-curl -s http://localhost:20128/api/cli-tools/claude-settings | jq '{installed,runnable,commandPath,runtimeMode,reason}'
-curl -s http://localhost:20128/api/cli-tools/openclaw-settings | jq '{installed,runnable,commandPath,runtimeMode,reason}'
-```
-
----
-
-## Cost Issues
-
-### High Costs
-
-1. Check usage stats in Dashboard → Usage
-2. Switch primary model to GLM/MiniMax
-3. Use free tier (Gemini CLI, Qoder) for non-critical tasks
-4. Set cost budgets per API key: Dashboard → API Keys → Budget
-
----
-
-## Debugging
-
-### Enable Request Logs
-
-Set `ENABLE_REQUEST_LOGS=true` in your `.env` file. Logs appear under `logs/` directory.
-
-### Check Provider Health
-
-```bash
-# Health dashboard
-http://localhost:20128/dashboard/health
-
-# API health check
-curl http://localhost:20128/api/monitoring/health
-```
-
-### Runtime Storage
-
-- Main state: `${DATA_DIR}/storage.sqlite` (providers, combos, aliases, keys, settings)
-- Usage: SQLite tables in `storage.sqlite` (`usage_history`, `call_logs`, `proxy_logs`) + optional `${DATA_DIR}/log.txt` and `${DATA_DIR}/call_logs/`
-- Request logs: `/logs/...` (when `ENABLE_REQUEST_LOGS=true`)
-
----
-
-## Circuit Breaker Issues
-
-### Provider stuck in OPEN state
-
-When a provider's circuit breaker is OPEN, requests are blocked until the cooldown expires.
-
-**Fix:**
-
-1. Go to **Dashboard → Settings → Resilience**
-2. Check the circuit breaker card for the affected provider
-3. Click **Reset All** to clear all breakers, or wait for the cooldown to expire
-4. Verify the provider is actually available before resetting
-
-### Provider keeps tripping the circuit breaker
-
-If a provider repeatedly enters OPEN state:
-
-1. Check **Dashboard → Health → Provider Health** for the failure pattern
-2. Go to **Settings → Resilience → Provider Profiles** and increase the failure threshold
-3. Check if the provider has changed API limits or requires re-authentication
-4. Review latency telemetry — high latency may cause timeout-based failures
-
----
-
-## Audio Transcription Issues
-
-### "Unsupported model" error
-
-- Ensure you're using the correct prefix: `deepgram/nova-3` or `assemblyai/best`
-- Verify the provider is connected in **Dashboard → Providers**
-
-### Transcription returns empty or fails
-
-- Check supported audio formats: `mp3`, `wav`, `m4a`, `flac`, `ogg`, `webm`
-- Verify file size is within provider limits (typically < 25MB)
-- Check provider API key validity in the provider card
-
----
-
-## Translator Debugging
-
-Use **Dashboard → Translator** to debug format translation issues:
-
-| Mode | When to Use |
-| ---------------- | -------------------------------------------------------------------------------------------- |
-| **Playground** | Compare input/output formats side by side — paste a failing request to see how it translates |
-| **Chat Tester** | Send live messages and inspect the full request/response payload including headers |
-| **Test Bench** | Run batch tests across format combinations to find which translations are broken |
-| **Live Monitor** | Watch real-time request flow to catch intermittent translation issues |
-
-### Common format issues
-
-- **Thinking tags not appearing** — Check if the target provider supports thinking and the thinking budget setting
-- **Tool calls dropping** — Some format translations may strip unsupported fields; verify in Playground mode
-- **System prompt missing** — Claude and Gemini handle system prompts differently; check translation output
-- **SDK returns raw string instead of object** — Fixed in v1.1.0: response sanitizer now strips non-standard fields (`x_groq`, `usage_breakdown`, etc.) that cause OpenAI SDK Pydantic validation failures
-- **GLM/ERNIE rejects `system` role** — Fixed in v1.1.0: role normalizer automatically merges system messages into user messages for incompatible models
-- **`developer` role not recognized** — Fixed in v1.1.0: automatically converted to `system` for non-OpenAI providers
-- **`json_schema` not working with Gemini** — Fixed in v1.1.0: `response_format` is now converted to Gemini's `responseMimeType` + `responseSchema`
-
----
-
-## Resilience Settings
-
-### Auto rate-limit not triggering
-
-- Auto rate-limit only applies to API key providers (not OAuth/subscription)
-- Verify **Settings → Resilience → Provider Profiles** has auto-rate-limit enabled
-- Check if the provider returns `429` status codes or `Retry-After` headers
-
-### Tuning exponential backoff
-
-Provider profiles support these settings:
-
-- **Base delay** — Initial wait time after first failure (default: 1s)
-- **Max delay** — Maximum wait time cap (default: 30s)
-- **Multiplier** — How much to increase delay per consecutive failure (default: 2x)
-
-### Anti-thundering herd
-
-When many concurrent requests hit a rate-limited provider, OmniRoute uses mutex + auto rate-limiting to serialize requests and prevent cascading failures. This is automatic for API key providers.
-
----
-
-## Optional RAG / LLM failure taxonomy (16 problems)
-
-Some OmniRoute users place the gateway in front of RAG or agent stacks. In those setups it is common to see a strange pattern: OmniRoute looks healthy (providers up, routing profiles ok, no rate limit alerts) but the final answer is still wrong.
-
-In practice these incidents usually come from the downstream RAG pipeline, not from the gateway itself.
-
-If you want a shared vocabulary to describe those failures you can use the WFGY ProblemMap, an external MIT license text resource that defines sixteen recurring RAG / LLM failure patterns. At a high level it covers:
-
-- retrieval drift and broken context boundaries
-- empty or stale indexes and vector stores
-- embedding versus semantic mismatch
-- prompt assembly and context window issues
-- logic collapse and overconfident answers
-- long chain and agent coordination failures
-- multi agent memory and role drift
-- deployment and bootstrap ordering problems
-
-The idea is simple:
-
-1. When you investigate a bad response, capture:
- - user task and request
- - route or provider combo in OmniRoute
- - any RAG context used downstream (retrieved documents, tool calls, etc)
-2. Map the incident to one or two WFGY ProblemMap numbers (`No.1` … `No.16`).
-3. Store the number in your own dashboard, runbook, or incident tracker next to the OmniRoute logs.
-4. Use the corresponding WFGY page to decide whether you need to change your RAG stack, retriever, or routing strategy.
-
-Full text and concrete recipes live here (MIT license, text only):
-
-[WFGY ProblemMap README](https://github.com/onestardao/WFGY/blob/main/ProblemMap/README.md)
-
-You can ignore this section if you do not run RAG or agent pipelines behind OmniRoute.
-
----
-
-## Still Stuck?
-
-- **GitHub Issues**: [github.com/diegosouzapw/OmniRoute/issues](https://github.com/diegosouzapw/OmniRoute/issues)
-- **Architecture**: See [`docs/ARCHITECTURE.md`](ARCHITECTURE.md) for internal details
-- **API Reference**: See [`docs/API_REFERENCE.md`](API_REFERENCE.md) for all endpoints
-- **Health Dashboard**: Check **Dashboard → Health** for real-time system status
-- **Translator**: Use **Dashboard → Translator** to debug format issues
diff --git a/docs/i18n/he/VM_DEPLOYMENT_GUIDE.md b/docs/i18n/he/VM_DEPLOYMENT_GUIDE.md
deleted file mode 100644
index b00b99ddb9..0000000000
--- a/docs/i18n/he/VM_DEPLOYMENT_GUIDE.md
+++ /dev/null
@@ -1,401 +0,0 @@
-# OmniRoute — מדריך פריסה ב-VM עם Cloudflare
-
-🌐 **Languages:** 🇺🇸 [English](../../VM_DEPLOYMENT_GUIDE.md) | 🇧🇷 [Português (Brasil)](../pt-BR/VM_DEPLOYMENT_GUIDE.md) | 🇪🇸 [Español](../es/VM_DEPLOYMENT_GUIDE.md) | 🇫🇷 [Français](../fr/VM_DEPLOYMENT_GUIDE.md) | 🇮🇹 [Italiano](../it/VM_DEPLOYMENT_GUIDE.md) | 🇷🇺 [Русский](../ru/VM_DEPLOYMENT_GUIDE.md) | 🇨🇳 [中文 (简体)](../zh-CN/VM_DEPLOYMENT_GUIDE.md) | 🇩🇪 [Deutsch](../de/VM_DEPLOYMENT_GUIDE.md) | 🇮🇳 [हिन्दी](../in/VM_DEPLOYMENT_GUIDE.md) | 🇹🇭 [ไทย](../th/VM_DEPLOYMENT_GUIDE.md) | 🇺🇦 [Українська](../uk-UA/VM_DEPLOYMENT_GUIDE.md) | 🇸🇦 [العربية](../ar/VM_DEPLOYMENT_GUIDE.md) | 🇯🇵 [日本語](../ja/VM_DEPLOYMENT_GUIDE.md) | 🇻🇳 [Tiếng Việt](../vi/VM_DEPLOYMENT_GUIDE.md) | 🇧🇬 [Български](../bg/VM_DEPLOYMENT_GUIDE.md) | 🇩🇰 [Dansk](../da/VM_DEPLOYMENT_GUIDE.md) | 🇫🇮 [Suomi](../fi/VM_DEPLOYMENT_GUIDE.md) | 🇮🇱 [עברית](../he/VM_DEPLOYMENT_GUIDE.md) | 🇭🇺 [Magyar](../hu/VM_DEPLOYMENT_GUIDE.md) | 🇮🇩 [Bahasa Indonesia](../id/VM_DEPLOYMENT_GUIDE.md) | 🇰🇷 [한국어](../ko/VM_DEPLOYMENT_GUIDE.md) | 🇲🇾 [Bahasa Melayu](../ms/VM_DEPLOYMENT_GUIDE.md) | 🇳🇱 [Nederlands](../nl/VM_DEPLOYMENT_GUIDE.md) | 🇳🇴 [Norsk](../no/VM_DEPLOYMENT_GUIDE.md) | 🇵🇹 [Português (Portugal)](../pt/VM_DEPLOYMENT_GUIDE.md) | 🇷🇴 [Română](../ro/VM_DEPLOYMENT_GUIDE.md) | 🇵🇱 [Polski](../pl/VM_DEPLOYMENT_GUIDE.md) | 🇸🇰 [Slovenčina](../sk/VM_DEPLOYMENT_GUIDE.md) | 🇸🇪 [Svenska](../sv/VM_DEPLOYMENT_GUIDE.md) | 🇵🇭 [Filipino](../phi/VM_DEPLOYMENT_GUIDE.md) | 🇨🇿 [Čeština](../cs/VM_DEPLOYMENT_GUIDE.md)
-
-מדריך שלם להתקנה והגדרה של OmniRoute ב-VM (VPS) עם דומיין מנוהל באמצעות Cloudflare.
-
----
-
-## דרישות מוקדמות
-
-| פריט | מינימום | מומלץ |
-| ---------- | ----------------- | ----------------- |
-| **מעבד** | 1 vCPU | 2 vCPU |
-| **RAM** | 1 GB | 2 GB |
-| **דיסק** | 10 GB SSD | SSD 25 GB |
-| **OS** | אובונטו 22.04 LTS | אובונטו 24.04 LTS |
-| **דומיין** | רשום ב-Cloudflare | — |
-| **דוקר** | Docker Engine 24+ | Docker 27+ |
-
-**ספקים שנבדקו**: Akamai (Linode), DigitalOcean, Vultr, Hetzner, AWS Lightsail.
-
----
-
-## 1. הגדר את ה-VM
-
-### 1.1 צור את המופע
-
-בספק ה-VPS המועדף עליך:
-
-- בחר אובונטו 24.04 LTS
-- בחר את התוכנית המינימלית (1 vCPU / 1 GB RAM)
-- הגדר סיסמת שורש חזקה או הגדר את מפתח SSH
-- שימו לב ל-**IP הציבורי** (למשל, `203.0.113.10`)
-
-### 1.2 התחבר באמצעות SSH
-
-```bash
-ssh root@203.0.113.10
-```
-
-### 1.3 עדכן את המערכת
-
-```bash
-apt update && apt upgrade -y
-```
-
-### 1.4 התקן Docker
-
-```bash
-# Install dependencies
-apt install -y ca-certificates curl gnupg
-
-# Add official Docker repository
-install -m 0755 -d /etc/apt/keyrings
-curl -fsSL https://download.docker.com/linux/ubuntu/gpg | gpg --dearmor -o /etc/apt/keyrings/docker.gpg
-chmod a+r /etc/apt/keyrings/docker.gpg
-echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu $ (. /etc/os-release && echo “$VERSION_CODENAME”) stable" | tee /etc/apt/sources.list.d/docker.list > /dev/null
-apt update
-apt install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin
-```
-
-### 1.5 התקן את nginx
-
-```bash
-apt install -y nginx
-```
-
-### 1.6 הגדר חומת אש (UFW)
-
-```bash
-ufw default deny incoming
-ufw default allow outgoing
-ufw allow 22/tcp # SSH
-ufw allow 80/tcp # HTTP (redirect)
-ufw allow 443/tcp # HTTPS
-ufw enable
-```
-
-> **טיפ**: לאבטחה מירבית, הגבל את היציאות 80 ו-443 ל-IP של Cloudflare בלבד. עיין בסעיף [Advanced Security](#advanced-security).
-
----
-
-## 2. התקן את OmniRoute
-
-### 2.1 צור ספריית תצורה
-
-```bash
-mkdir -p /opt/omniroute
-```
-
-### 2.2 צור קובץ משתני סביבה
-
-```bash
-cat > /opt/omniroute/.env << ‘EOF’
-# === Security ===
-JWT_SECRET=CHANGE-TO-A-UNIQUE-64-CHAR-SECRET-KEY
-INITIAL_PASSWORD=YourSecurePassword123!
-API_KEY_SECRET=REPLACE-WITH-ANOTHER-SECRET-KEY
-STORAGE_ENCRYPTION_KEY=REPLACE-WITH-THIRD-SECRET-KEY
-STORAGE_ENCRYPTION_KEY_VERSION=v1
-MACHINE_ID_SALT=CHANGE-TO-A-UNIQUE-SALT
-
-# === App ===
-PORT=20128
-NODE_ENV=production
-HOSTNAME=0.0.0.0
-DATA_DIR=/app/data
-STORAGE_DRIVER=sqlite
-ENABLE_REQUEST_LOGS=true
-AUTH_COOKIE_SECURE=false
-REQUIRE_API_KEY=false
-
-# === Domain (change to your domain) ===
-BASE_URL=https://llms.seudominio.com
-NEXT_PUBLIC_BASE_URL=https://llms.seudominio.com
-
-# === Cloud Sync (optional) ===
-# CLOUD_URL=https://cloud.omniroute.online
-# NEXT_PUBLIC_CLOUD_URL=https://cloud.omniroute.online
-EOF
-```
-
-> ⚠️ **חשוב**: צור מפתחות סודיים ייחודיים! השתמש ב-`openssl rand -hex 32` עבור כל מפתח.
-
-### 2.3 הפעל את המיכל
-
-```bash
-docker pull diegosouzapw/omniroute:latest
-
-docker run -d \
- --name omniroute \
- --restart unless-stopped \
- --env-file /opt/omniroute/.env \
- -p 20128:20128 \
- -v omniroute-data:/app/data \
- diegosouzapw/omniroute:latest
-```
-
-### 2.4 ודא שהוא פועל
-
-```bash
-docker ps | grep omniroute
-docker logs omniroute --tail 20
-```
-
-זה אמור להציג: `[DB] SQLite database ready` ו-`listening on port 20128`.
-
----
-
-## 3. הגדר את nginx (פרוקסי הפוך)
-
-### 3.1 יצירת אישור SSL (מקור Cloudflare)
-
-בלוח המחוונים של Cloudflare:
-
-1. עבור אל **SSL/TLS → שרת מקור**
-2. לחץ על **צור אישור**
-3. שמור על ברירת המחדל (15 שנים, \*.yourdomain.com)
-4. העתק את **תעודת המקור** ואת **המפתח הפרטי**
-
-```bash
-mkdir -p /etc/nginx/ssl
-
-# Paste the certificate
-nano /etc/nginx/ssl/origin.crt
-
-# Paste the private key
-nano /etc/nginx/ssl/origin.key
-
-chmod 600 /etc/nginx/ssl/origin.key
-```
-
-### 3.2 תצורת Nginx
-
-```bash
-cat > /etc/nginx/sites-available/omniroute << ‘NGINX’
-# Default server — blocks direct access via IP
-server {
- listen 80 default_server;
- listen [::]:80 default_server;
- listen 443 ssl default_server;
- listen [::]:443 ssl default_server;
- ssl_certificate /etc/nginx/ssl/origin.crt;
- ssl_certificate_key /etc/nginx/ssl/origin.key;
- server_name _;
- return 444;
-}
-
-# OmniRoute — HTTPS
-server {
- listen 443 ssl;
- listen [::]:443 ssl;
- server_name llms.yourdomain.com; # Change to your domain
-
- ssl_certificate /etc/nginx/ssl/origin.crt;
- ssl_certificate_key /etc/nginx/ssl/origin.key;
- ssl_protocols TLSv1.2 TLSv1.3;
-
- client_max_body_size 100M;
-
- location / {
- proxy_pass http://127.0.0.1:20128;
- proxy_set_header Host $host;
- proxy_set_header X-Real-IP $remote_addr;
- proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
- proxy_set_header X-Forwarded-Proto $scheme;
-
- # WebSocket support
- proxy_http_version 1.1;
- proxy_set_header Upgrade $http_upgrade;
- proxy_set_header Connection “upgrade”;
-
- # SSE (Server-Sent Events) — streaming AI responses
- proxy_buffering off;
- proxy_cache off;
- proxy_read_timeout 300s;
- proxy_send_timeout 300s;
- }
-}
-
-# HTTP → HTTPS redirect
-server {
- listen 80;
- listen [::]:80;
- server_name llms.yourdomain.com;
- return 301 https://$server_name$request_uri;
-}
-NGINX
-```
-
-### 3.3 הפעל ובדוק
-
-```bash
-# Remove default configuration
-rm -f /etc/nginx/sites-enabled/default
-
-# Enable OmniRoute
-ln -sf /etc/nginx/sites-available/omniroute /etc/nginx/sites-enabled/omniroute
-
-# Test and reload
-nginx -t && systemctl reload nginx
-```
-
----
-
-## 4. הגדר את Cloudflare DNS
-
-### 4.1 הוסף רשומת DNS
-
-בלוח המחוונים של Cloudflare ← DNS:
-
-| הקלד | שם | תוכן | פרוקסי |
-| ---- | ------ | ---------------------- | --------- |
-| א | `llms` | `203.0.113.10` (VM IP) | ✅ פרוקסי |
-
-### 4.2 הגדר SSL
-
-תחת **SSL/TLS ← סקירה כללית**:
-
-- מצב: **מלא (קפדני)**
-
-תחת **SSL/TLS → Edge Certificates**:
-
-- השתמש תמיד ב-HTTPS: ✅ פועל
-- גרסת TLS מינימלית: TLS 1.2
-- שכתובים אוטומטיים של HTTPS: ✅ פועל
-
-### 4.3 בדיקה
-
-```bash
-curl -sI https://llms.seudominio.com/health
-# Should return HTTP/2 200
-```
-
----
-
-## 5. תפעול ותחזוקה
-
-### שדרג לגרסה חדשה
-
-```bash
-docker pull diegosouzapw/omniroute:latest
-docker stop omniroute && docker rm omniroute
-docker run -d --name omniroute --restart unless-stopped \
- --env-file /opt/omniroute/.env \
- -p 20128:20128 \
- -v omniroute-data:/app/data \
- diegosouzapw/omniroute:latest
-```
-
-### הצג יומנים
-
-```bash
-docker logs -f omniroute # Real-time stream
-docker logs omniroute --tail 50 # Last 50 lines
-```
-
-### גיבוי ידני של מסד הנתונים
-
-```bash
-# Copy data from the volume to the host
-docker cp omniroute:/app/data ./backup-$(date +%F)
-
-# Or compress the entire volume
-docker run --rm -v omniroute-data:/data -v $(pwd):/backup \
- alpine tar czf /backup/omniroute-data-$(date +%F).tar.gz /data
-```
-
-### שחזר מגיבוי
-
-```bash
-docker stop omniroute
-docker run --rm -v omniroute-data:/data -v $(pwd):/backup \
- alpine sh -c “rm -rf /data/* && tar xzf /backup/omniroute-data-YYYY-MM-DD.tar.gz -C /”
-docker start omniroute
-```
-
----
-
-## 6. אבטחה מתקדמת
-
-### הגבל את nginx לכתובות IP של Cloudflare
-
-```bash
-cat > /etc/nginx/cloudflare-ips.conf << ‘CF’
-# Cloudflare IPv4 ranges — update periodically
-# https://www.cloudflare.com/ips-v4/
-set_real_ip_from 173.245.48.0/20;
-set_real_ip_from 103.21.244.0/22;
-set_real_ip_from 103.22.200.0/22;
-set_real_ip_from 103.31.4.0/22;
-set_real_ip_from 141.101.64.0/18;
-set_real_ip_from 108.162.192.0/18;
-set_real_ip_from 190.93.240.0/20;
-set_real_ip_from 188.114.96.0/20;
-set_real_ip_from 197.234.240.0/22;
-set_real_ip_from 198.41.128.0/17;
-set_real_ip_from 162.158.0.0/15;
-set_real_ip_from 104.16.0.0/13;
-set_real_ip_from 104.24.0.0/14;
-set_real_ip_from 172.64.0.0/13;
-set_real_ip_from 131.0.72.0/22;
-real_ip_header CF-Connecting-IP;
-CF
-```
-
-הוסף את הדברים הבאים ל`nginx.conf` בתוך הבלוק `http {}`:
-
-```nginx
-include /etc/nginx/cloudflare-ips.conf;
-```
-
-### התקן fail2ban
-
-```bash
-apt install -y fail2ban
-systemctl enable fail2ban
-systemctl start fail2ban
-
-# Check status
-fail2ban-client status sshd
-```
-
-### חסום גישה ישירה ליציאת Docker
-
-```bash
-# Prevent direct external access to port 20128
-iptables -I DOCKER-USER -p tcp --dport 20128 -j DROP
-iptables -I DOCKER-USER -i lo -p tcp --dport 20128 -j ACCEPT
-
-# Persist the rules
-apt install -y iptables-persistent
-netfilter-persistent save
-```
-
----
-
-## 7. פריסה ל-Cloudflare Workers (אופציונלי)
-
-לגישה מרחוק דרך Cloudflare Workers (מבלי לחשוף ישירות את ה-VM):
-
-```bash
-# In the local repository
-cd omnirouteCloud
-npm install
-npx wrangler login
-npx wrangler deploy
-```
-
-ראה את התיעוד המלא ב-[omnirouteCloud/README.md](../omnirouteCloud/README.md).
-
----
-
-## סיכום יציאה
-
-| נמל | שירות | גישה |
-| ----- | ----------- | -------------------------- |
-| 22 | SSH | ציבורי (עם fail2ban) |
-| 80 | nginx HTTP | הפניה מחדש → HTTPS |
-| 443 | nginx HTTPS | דרך Cloudflare Proxy |
-| 20128 | OmniRoute | Localhost בלבד (דרך nginx) |
diff --git a/docs/i18n/he/docs/A2A-SERVER.md b/docs/i18n/he/docs/A2A-SERVER.md
new file mode 100644
index 0000000000..883b221ebd
--- /dev/null
+++ b/docs/i18n/he/docs/A2A-SERVER.md
@@ -0,0 +1,200 @@
+# OmniRoute A2A Server Documentation (עברית)
+
+🌐 **Languages:** 🇺🇸 [English](../../../../docs/A2A-SERVER.md) · 🇪🇸 [es](../../es/docs/A2A-SERVER.md) · 🇫🇷 [fr](../../fr/docs/A2A-SERVER.md) · 🇩🇪 [de](../../de/docs/A2A-SERVER.md) · 🇮🇹 [it](../../it/docs/A2A-SERVER.md) · 🇷🇺 [ru](../../ru/docs/A2A-SERVER.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/A2A-SERVER.md) · 🇯🇵 [ja](../../ja/docs/A2A-SERVER.md) · 🇰🇷 [ko](../../ko/docs/A2A-SERVER.md) · 🇸🇦 [ar](../../ar/docs/A2A-SERVER.md) · 🇮🇳 [in](../../in/docs/A2A-SERVER.md) · 🇹🇭 [th](../../th/docs/A2A-SERVER.md) · 🇻🇳 [vi](../../vi/docs/A2A-SERVER.md) · 🇮🇩 [id](../../id/docs/A2A-SERVER.md) · 🇲🇾 [ms](../../ms/docs/A2A-SERVER.md) · 🇳🇱 [nl](../../nl/docs/A2A-SERVER.md) · 🇵🇱 [pl](../../pl/docs/A2A-SERVER.md) · 🇸🇪 [sv](../../sv/docs/A2A-SERVER.md) · 🇳🇴 [no](../../no/docs/A2A-SERVER.md) · 🇩🇰 [da](../../da/docs/A2A-SERVER.md) · 🇫🇮 [fi](../../fi/docs/A2A-SERVER.md) · 🇵🇹 [pt](../../pt/docs/A2A-SERVER.md) · 🇷🇴 [ro](../../ro/docs/A2A-SERVER.md) · 🇭🇺 [hu](../../hu/docs/A2A-SERVER.md) · 🇧🇬 [bg](../../bg/docs/A2A-SERVER.md) · 🇸🇰 [sk](../../sk/docs/A2A-SERVER.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/A2A-SERVER.md) · 🇮🇱 [he](../../he/docs/A2A-SERVER.md) · 🇵🇭 [phi](../../phi/docs/A2A-SERVER.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/A2A-SERVER.md) · 🇨🇿 [cs](../../cs/docs/A2A-SERVER.md)
+
+---
+
+> Agent-to-Agent Protocol v0.3 — OmniRoute as an intelligent routing agent
+
+## Agent Discovery
+
+```bash
+curl http://localhost:20128/.well-known/agent.json
+```
+
+Returns the Agent Card describing OmniRoute's capabilities, skills, and authentication requirements.
+
+---
+
+## Authentication
+
+All `/a2a` requests require an API key via the `Authorization` header:
+
+```
+Authorization: Bearer YOUR_OMNIROUTE_API_KEY
+```
+
+If no API key is configured on the server, authentication is bypassed.
+
+---
+
+## JSON-RPC 2.0 Methods
+
+### `message/send` — Synchronous Execution
+
+Sends a message to a skill and waits for the complete response.
+
+```bash
+curl -X POST http://localhost:20128/a2a \
+ -H "Content-Type: application/json" \
+ -H "Authorization: Bearer YOUR_KEY" \
+ -d '{
+ "jsonrpc": "2.0",
+ "id": "1",
+ "method": "message/send",
+ "params": {
+ "skill": "smart-routing",
+ "messages": [{"role": "user", "content": "Write a hello world in Python"}],
+ "metadata": {"model": "auto", "combo": "fast-coding"}
+ }
+ }'
+```
+
+**Response:**
+
+```json
+{
+ "jsonrpc": "2.0",
+ "id": "1",
+ "result": {
+ "task": { "id": "uuid", "state": "completed" },
+ "artifacts": [{ "type": "text", "content": "..." }],
+ "metadata": {
+ "routing_explanation": "Selected claude-sonnet via provider \"anthropic\" (latency: 1200ms, cost: $0.003)",
+ "cost_envelope": { "estimated": 0.005, "actual": 0.003, "currency": "USD" },
+ "resilience_trace": [
+ { "event": "primary_selected", "provider": "anthropic", "timestamp": "..." }
+ ],
+ "policy_verdict": { "allowed": true, "reason": "within budget and quota limits" }
+ }
+ }
+}
+```
+
+### `message/stream` — SSE Streaming
+
+Same as `message/send` but returns Server-Sent Events for real-time streaming.
+
+```bash
+curl -N -X POST http://localhost:20128/a2a \
+ -H "Content-Type: application/json" \
+ -H "Authorization: Bearer YOUR_KEY" \
+ -d '{
+ "jsonrpc": "2.0",
+ "id": "1",
+ "method": "message/stream",
+ "params": {
+ "skill": "smart-routing",
+ "messages": [{"role": "user", "content": "Explain quantum computing"}]
+ }
+ }'
+```
+
+**SSE Events:**
+
+```
+data: {"jsonrpc":"2.0","method":"message/stream","params":{"task":{"id":"...","state":"working"},"chunk":{"type":"text","content":"..."}}}
+
+: heartbeat 2026-03-03T17:00:00Z
+
+data: {"jsonrpc":"2.0","method":"message/stream","params":{"task":{"id":"...","state":"completed"},"metadata":{...}}}
+```
+
+### `tasks/get` — Query Task Status
+
+```bash
+curl -X POST http://localhost:20128/a2a \
+ -H "Content-Type: application/json" \
+ -H "Authorization: Bearer YOUR_KEY" \
+ -d '{"jsonrpc":"2.0","id":"2","method":"tasks/get","params":{"taskId":"TASK_UUID"}}'
+```
+
+### `tasks/cancel` — Cancel a Task
+
+```bash
+curl -X POST http://localhost:20128/a2a \
+ -H "Content-Type: application/json" \
+ -H "Authorization: Bearer YOUR_KEY" \
+ -d '{"jsonrpc":"2.0","id":"3","method":"tasks/cancel","params":{"taskId":"TASK_UUID"}}'
+```
+
+---
+
+## Available Skills
+
+| Skill | Description |
+| :----------------- | :------------------------------------------------------------------------------------------------------------------------------ |
+| `smart-routing` | Routes prompts through OmniRoute's intelligent pipeline. Returns response with routing explanation, cost, and resilience trace. |
+| `quota-management` | Answers natural-language queries about provider quotas, suggests free combos, and provides quota rankings. |
+
+---
+
+## Task Lifecycle
+
+```
+submitted → working → completed
+ → failed
+ → cancelled
+```
+
+- Tasks expire after 5 minutes (configurable)
+- Terminal states: `completed`, `failed`, `cancelled`
+- Event log tracks every state transition
+
+---
+
+## Error Codes
+
+| Code | Meaning |
+| :----- | :----------------------------- |
+| -32700 | Parse error (invalid JSON) |
+| -32600 | Invalid request / Unauthorized |
+| -32601 | Method or skill not found |
+| -32602 | Invalid params |
+| -32603 | Internal error |
+
+---
+
+## Integration Examples
+
+### Python (requests)
+
+```python
+import requests
+
+resp = requests.post("http://localhost:20128/a2a", json={
+ "jsonrpc": "2.0", "id": "1",
+ "method": "message/send",
+ "params": {
+ "skill": "smart-routing",
+ "messages": [{"role": "user", "content": "Hello"}]
+ }
+}, headers={"Authorization": "Bearer YOUR_KEY"})
+
+result = resp.json()["result"]
+print(result["artifacts"][0]["content"])
+print(result["metadata"]["routing_explanation"])
+```
+
+### TypeScript (fetch)
+
+```typescript
+const resp = await fetch("http://localhost:20128/a2a", {
+ method: "POST",
+ headers: {
+ "Content-Type": "application/json",
+ Authorization: "Bearer YOUR_KEY",
+ },
+ body: JSON.stringify({
+ jsonrpc: "2.0",
+ id: "1",
+ method: "message/send",
+ params: {
+ skill: "smart-routing",
+ messages: [{ role: "user", content: "Hello" }],
+ },
+ }),
+});
+const { result } = await resp.json();
+console.log(result.metadata.routing_explanation);
+```
diff --git a/docs/i18n/he/docs/API_REFERENCE.md b/docs/i18n/he/docs/API_REFERENCE.md
new file mode 100644
index 0000000000..347d8b6491
--- /dev/null
+++ b/docs/i18n/he/docs/API_REFERENCE.md
@@ -0,0 +1,465 @@
+# API Reference (עברית)
+
+🌐 **Languages:** 🇺🇸 [English](../../../../docs/API_REFERENCE.md) · 🇪🇸 [es](../../es/docs/API_REFERENCE.md) · 🇫🇷 [fr](../../fr/docs/API_REFERENCE.md) · 🇩🇪 [de](../../de/docs/API_REFERENCE.md) · 🇮🇹 [it](../../it/docs/API_REFERENCE.md) · 🇷🇺 [ru](../../ru/docs/API_REFERENCE.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/API_REFERENCE.md) · 🇯🇵 [ja](../../ja/docs/API_REFERENCE.md) · 🇰🇷 [ko](../../ko/docs/API_REFERENCE.md) · 🇸🇦 [ar](../../ar/docs/API_REFERENCE.md) · 🇮🇳 [in](../../in/docs/API_REFERENCE.md) · 🇹🇭 [th](../../th/docs/API_REFERENCE.md) · 🇻🇳 [vi](../../vi/docs/API_REFERENCE.md) · 🇮🇩 [id](../../id/docs/API_REFERENCE.md) · 🇲🇾 [ms](../../ms/docs/API_REFERENCE.md) · 🇳🇱 [nl](../../nl/docs/API_REFERENCE.md) · 🇵🇱 [pl](../../pl/docs/API_REFERENCE.md) · 🇸🇪 [sv](../../sv/docs/API_REFERENCE.md) · 🇳🇴 [no](../../no/docs/API_REFERENCE.md) · 🇩🇰 [da](../../da/docs/API_REFERENCE.md) · 🇫🇮 [fi](../../fi/docs/API_REFERENCE.md) · 🇵🇹 [pt](../../pt/docs/API_REFERENCE.md) · 🇷🇴 [ro](../../ro/docs/API_REFERENCE.md) · 🇭🇺 [hu](../../hu/docs/API_REFERENCE.md) · 🇧🇬 [bg](../../bg/docs/API_REFERENCE.md) · 🇸🇰 [sk](../../sk/docs/API_REFERENCE.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/API_REFERENCE.md) · 🇮🇱 [he](../../he/docs/API_REFERENCE.md) · 🇵🇭 [phi](../../phi/docs/API_REFERENCE.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/API_REFERENCE.md) · 🇨🇿 [cs](../../cs/docs/API_REFERENCE.md)
+
+---
+
+Complete reference for all OmniRoute API endpoints.
+
+---
+
+## Table of Contents
+
+- [Chat Completions](#chat-completions)
+- [Embeddings](#embeddings)
+- [Image Generation](#image-generation)
+- [List Models](#list-models)
+- [Compatibility Endpoints](#compatibility-endpoints)
+- [Semantic Cache](#semantic-cache)
+- [Dashboard & Management](#dashboard--management)
+- [Request Processing](#request-processing)
+- [Authentication](#authentication)
+
+---
+
+## Chat Completions
+
+```bash
+POST /v1/chat/completions
+Authorization: Bearer your-api-key
+Content-Type: application/json
+
+{
+ "model": "cc/claude-opus-4-6",
+ "messages": [
+ {"role": "user", "content": "Write a function to..."}
+ ],
+ "stream": true
+}
+```
+
+### Custom Headers
+
+| Header | Direction | Description |
+| ------------------------ | --------- | ------------------------------------------------ |
+| `X-OmniRoute-No-Cache` | Request | Set to `true` to bypass cache |
+| `X-OmniRoute-Progress` | Request | Set to `true` for progress events |
+| `X-Session-Id` | Request | Sticky session key for external session affinity |
+| `x_session_id` | Request | Underscore variant also accepted (direct HTTP) |
+| `Idempotency-Key` | Request | Dedup key (5s window) |
+| `X-Request-Id` | Request | Alternative dedup key |
+| `X-OmniRoute-Cache` | Response | `HIT` or `MISS` (non-streaming) |
+| `X-OmniRoute-Idempotent` | Response | `true` if deduplicated |
+| `X-OmniRoute-Progress` | Response | `enabled` if progress tracking on |
+| `X-OmniRoute-Session-Id` | Response | Effective session ID used by OmniRoute |
+
+> Nginx note: if you rely on underscore headers (for example `x_session_id`), enable `underscores_in_headers on;`.
+
+---
+
+## Embeddings
+
+```bash
+POST /v1/embeddings
+Authorization: Bearer your-api-key
+Content-Type: application/json
+
+{
+ "model": "nebius/Qwen/Qwen3-Embedding-8B",
+ "input": "The food was delicious"
+}
+```
+
+Available providers: Nebius, OpenAI, Mistral, Together AI, Fireworks, NVIDIA.
+
+```bash
+# List all embedding models
+GET /v1/embeddings
+```
+
+---
+
+## Image Generation
+
+```bash
+POST /v1/images/generations
+Authorization: Bearer your-api-key
+Content-Type: application/json
+
+{
+ "model": "openai/dall-e-3",
+ "prompt": "A beautiful sunset over mountains",
+ "size": "1024x1024"
+}
+```
+
+Available providers: OpenAI (DALL-E), xAI (Grok Image), Together AI (FLUX), Fireworks AI.
+
+```bash
+# List all image models
+GET /v1/images/generations
+```
+
+---
+
+## List Models
+
+```bash
+GET /v1/models
+Authorization: Bearer your-api-key
+
+→ Returns all chat, embedding, and image models + combos in OpenAI format
+```
+
+---
+
+## Compatibility Endpoints
+
+| Method | Path | Format |
+| ------ | --------------------------- | ---------------------- |
+| POST | `/v1/chat/completions` | OpenAI |
+| POST | `/v1/messages` | Anthropic |
+| POST | `/v1/responses` | OpenAI Responses |
+| POST | `/v1/embeddings` | OpenAI |
+| POST | `/v1/images/generations` | OpenAI |
+| GET | `/v1/models` | OpenAI |
+| POST | `/v1/messages/count_tokens` | Anthropic |
+| GET | `/v1beta/models` | Gemini |
+| POST | `/v1beta/models/{...path}` | Gemini generateContent |
+| POST | `/v1/api/chat` | Ollama |
+
+### Dedicated Provider Routes
+
+```bash
+POST /v1/providers/{provider}/chat/completions
+POST /v1/providers/{provider}/embeddings
+POST /v1/providers/{provider}/images/generations
+```
+
+The provider prefix is auto-added if missing. Mismatched models return `400`.
+
+---
+
+## Semantic Cache
+
+```bash
+# Get cache stats
+GET /api/cache/stats
+
+# Clear all caches
+DELETE /api/cache/stats
+```
+
+Response example:
+
+```json
+{
+ "semanticCache": {
+ "memorySize": 42,
+ "memoryMaxSize": 500,
+ "dbSize": 128,
+ "hitRate": 0.65
+ },
+ "idempotency": {
+ "activeKeys": 3,
+ "windowMs": 5000
+ }
+}
+```
+
+---
+
+## Dashboard & Management
+
+### Authentication
+
+| Endpoint | Method | Description |
+| ----------------------------- | ------- | --------------------- |
+| `/api/auth/login` | POST | Login |
+| `/api/auth/logout` | POST | Logout |
+| `/api/settings/require-login` | GET/PUT | Toggle login required |
+
+### Provider Management
+
+| Endpoint | Method | Description |
+| ---------------------------- | --------------- | ------------------------ |
+| `/api/providers` | GET/POST | List / create providers |
+| `/api/providers/[id]` | GET/PUT/DELETE | Manage a provider |
+| `/api/providers/[id]/test` | POST | Test provider connection |
+| `/api/providers/[id]/models` | GET | List provider models |
+| `/api/providers/validate` | POST | Validate provider config |
+| `/api/provider-nodes*` | Various | Provider node management |
+| `/api/provider-models` | GET/POST/DELETE | Custom models |
+
+### OAuth Flows
+
+| Endpoint | Method | Description |
+| -------------------------------- | ------- | ----------------------- |
+| `/api/oauth/[provider]/[action]` | Various | Provider-specific OAuth |
+
+### Routing & Config
+
+| Endpoint | Method | Description |
+| --------------------- | -------- | ----------------------------- |
+| `/api/models/alias` | GET/POST | Model aliases |
+| `/api/models/catalog` | GET | All models by provider + type |
+| `/api/combos*` | Various | Combo management |
+| `/api/keys*` | Various | API key management |
+| `/api/pricing` | GET | Model pricing |
+
+### Usage & Analytics
+
+| Endpoint | Method | Description |
+| --------------------------- | ------ | -------------------- |
+| `/api/usage/history` | GET | Usage history |
+| `/api/usage/logs` | GET | Usage logs |
+| `/api/usage/request-logs` | GET | Request-level logs |
+| `/api/usage/[connectionId]` | GET | Per-connection usage |
+
+### Settings
+
+| Endpoint | Method | Description |
+| ------------------------------- | ------------- | ---------------------- |
+| `/api/settings` | GET/PUT/PATCH | General settings |
+| `/api/settings/proxy` | GET/PUT | Network proxy config |
+| `/api/settings/proxy/test` | POST | Test proxy connection |
+| `/api/settings/ip-filter` | GET/PUT | IP allowlist/blocklist |
+| `/api/settings/thinking-budget` | GET/PUT | Reasoning token budget |
+| `/api/settings/system-prompt` | GET/PUT | Global system prompt |
+
+### Monitoring
+
+| Endpoint | Method | Description |
+| ------------------------ | ---------- | ---------------------------------------------------------------------------------------------------- |
+| `/api/sessions` | GET | Active session tracking |
+| `/api/rate-limits` | GET | Per-account rate limits |
+| `/api/monitoring/health` | GET | Health check + provider summary (`catalogCount`, `configuredCount`, `activeCount`, `monitoredCount`) |
+| `/api/cache/stats` | GET/DELETE | Cache stats / clear |
+
+### Backup & Export/Import
+
+| Endpoint | Method | Description |
+| --------------------------- | ------ | --------------------------------------- |
+| `/api/db-backups` | GET | List available backups |
+| `/api/db-backups` | PUT | Create a manual backup |
+| `/api/db-backups` | POST | Restore from a specific backup |
+| `/api/db-backups/export` | GET | Download database as .sqlite file |
+| `/api/db-backups/import` | POST | Upload .sqlite file to replace database |
+| `/api/db-backups/exportAll` | GET | Download full backup as .tar.gz archive |
+
+### Cloud Sync
+
+| Endpoint | Method | Description |
+| ---------------------- | ------- | --------------------- |
+| `/api/sync/cloud` | Various | Cloud sync operations |
+| `/api/sync/initialize` | POST | Initialize sync |
+| `/api/cloud/*` | Various | Cloud management |
+
+### Tunnels
+
+| Endpoint | Method | Description |
+| -------------------------- | ------ | ----------------------------------------------------------------------- |
+| `/api/tunnels/cloudflared` | GET | Read Cloudflare Quick Tunnel install/runtime status for the dashboard |
+| `/api/tunnels/cloudflared` | POST | Enable or disable the Cloudflare Quick Tunnel (`action=enable/disable`) |
+
+### CLI Tools
+
+| Endpoint | Method | Description |
+| ---------------------------------- | ------ | ------------------- |
+| `/api/cli-tools/claude-settings` | GET | Claude CLI status |
+| `/api/cli-tools/codex-settings` | GET | Codex CLI status |
+| `/api/cli-tools/droid-settings` | GET | Droid CLI status |
+| `/api/cli-tools/openclaw-settings` | GET | OpenClaw CLI status |
+| `/api/cli-tools/runtime/[toolId]` | GET | Generic CLI runtime |
+
+CLI responses include: `installed`, `runnable`, `command`, `commandPath`, `runtimeMode`, `reason`.
+
+### ACP Agents
+
+| Endpoint | Method | Description |
+| ----------------- | ------ | -------------------------------------------------------- |
+| `/api/acp/agents` | GET | List all detected agents (built-in + custom) with status |
+| `/api/acp/agents` | POST | Add custom agent or refresh detection cache |
+| `/api/acp/agents` | DELETE | Remove a custom agent by `id` query param |
+
+GET response includes `agents[]` (id, name, binary, version, installed, protocol, isCustom) and `summary` (total, installed, notFound, builtIn, custom).
+
+### Resilience & Rate Limits
+
+| Endpoint | Method | Description |
+| ----------------------- | --------- | ------------------------------- |
+| `/api/resilience` | GET/PATCH | Get/update resilience profiles |
+| `/api/resilience/reset` | POST | Reset circuit breakers |
+| `/api/rate-limits` | GET | Per-account rate limit status |
+| `/api/rate-limit` | GET | Global rate limit configuration |
+
+### Evals
+
+| Endpoint | Method | Description |
+| ------------ | -------- | --------------------------------- |
+| `/api/evals` | GET/POST | List eval suites / run evaluation |
+
+### Policies
+
+| Endpoint | Method | Description |
+| --------------- | --------------- | ----------------------- |
+| `/api/policies` | GET/POST/DELETE | Manage routing policies |
+
+### Compliance
+
+| Endpoint | Method | Description |
+| --------------------------- | ------ | ----------------------------- |
+| `/api/compliance/audit-log` | GET | Compliance audit log (last N) |
+
+### v1beta (Gemini-Compatible)
+
+| Endpoint | Method | Description |
+| -------------------------- | ------ | --------------------------------- |
+| `/v1beta/models` | GET | List models in Gemini format |
+| `/v1beta/models/{...path}` | POST | Gemini `generateContent` endpoint |
+
+These endpoints mirror Gemini's API format for clients that expect native Gemini SDK compatibility.
+
+### Internal / System APIs
+
+| Endpoint | Method | Description |
+| --------------- | ------ | ---------------------------------------------------- |
+| `/api/init` | GET | Application initialization check (used on first run) |
+| `/api/tags` | GET | Ollama-compatible model tags (for Ollama clients) |
+| `/api/restart` | POST | Trigger graceful server restart |
+| `/api/shutdown` | POST | Trigger graceful server shutdown |
+
+> **Note:** These endpoints are used internally by the system or for Ollama client compatibility. They are not typically called by end users.
+
+---
+
+## Audio Transcription
+
+```bash
+POST /v1/audio/transcriptions
+Authorization: Bearer your-api-key
+Content-Type: multipart/form-data
+```
+
+Transcribe audio files using Deepgram or AssemblyAI.
+
+**Request:**
+
+```bash
+curl -X POST http://localhost:20128/v1/audio/transcriptions \
+ -H "Authorization: Bearer your-api-key" \
+ -F "file=@recording.mp3" \
+ -F "model=deepgram/nova-3"
+```
+
+**Response:**
+
+```json
+{
+ "text": "Hello, this is the transcribed audio content.",
+ "task": "transcribe",
+ "language": "en",
+ "duration": 12.5
+}
+```
+
+**Supported providers:** `deepgram/nova-3`, `assemblyai/best`.
+
+**Supported formats:** `mp3`, `wav`, `m4a`, `flac`, `ogg`, `webm`.
+
+---
+
+## Ollama Compatibility
+
+For clients that use Ollama's API format:
+
+```bash
+# Chat endpoint (Ollama format)
+POST /v1/api/chat
+
+# Model listing (Ollama format)
+GET /api/tags
+```
+
+Requests are automatically translated between Ollama and internal formats.
+
+---
+
+## Telemetry
+
+```bash
+# Get latency telemetry summary (p50/p95/p99 per provider)
+GET /api/telemetry/summary
+```
+
+**Response:**
+
+```json
+{
+ "providers": {
+ "claudeCode": { "p50": 245, "p95": 890, "p99": 1200, "count": 150 },
+ "github": { "p50": 180, "p95": 620, "p99": 950, "count": 320 }
+ }
+}
+```
+
+---
+
+## Budget
+
+```bash
+# Get budget status for all API keys
+GET /api/usage/budget
+
+# Set or update a budget
+POST /api/usage/budget
+Content-Type: application/json
+
+{
+ "keyId": "key-123",
+ "limit": 50.00,
+ "period": "monthly"
+}
+```
+
+---
+
+## Model Availability
+
+```bash
+# Get real-time model availability across all providers
+GET /api/models/availability
+
+# Check availability for a specific model
+POST /api/models/availability
+Content-Type: application/json
+
+{
+ "model": "claude-sonnet-4-5-20250929"
+}
+```
+
+---
+
+## Request Processing
+
+1. Client sends request to `/v1/*`
+2. Route handler calls `handleChat`, `handleEmbedding`, `handleAudioTranscription`, or `handleImageGeneration`
+3. Model is resolved (direct provider/model or alias/combo)
+4. Credentials selected from local DB with account availability filtering
+5. For chat: `handleChatCore` — format detection, translation, cache check, idempotency check
+6. Provider executor sends upstream request
+7. Response translated back to client format (chat) or returned as-is (embeddings/images/audio)
+8. Usage/logging recorded
+9. Fallback applies on errors according to combo rules
+
+Full architecture reference: [`ARCHITECTURE.md`](ARCHITECTURE.md)
+
+---
+
+## Authentication
+
+- Dashboard routes (`/dashboard/*`) use `auth_token` cookie
+- Login uses saved password hash; fallback to `INITIAL_PASSWORD`
+- `requireLogin` toggleable via `/api/settings/require-login`
+- `/v1/*` routes optionally require Bearer API key when `REQUIRE_API_KEY=true`
diff --git a/docs/i18n/he/docs/ARCHITECTURE.md b/docs/i18n/he/docs/ARCHITECTURE.md
new file mode 100644
index 0000000000..06d2ace626
--- /dev/null
+++ b/docs/i18n/he/docs/ARCHITECTURE.md
@@ -0,0 +1,814 @@
+# OmniRoute Architecture (עברית)
+
+🌐 **Languages:** 🇺🇸 [English](../../../../docs/ARCHITECTURE.md) · 🇪🇸 [es](../../es/docs/ARCHITECTURE.md) · 🇫🇷 [fr](../../fr/docs/ARCHITECTURE.md) · 🇩🇪 [de](../../de/docs/ARCHITECTURE.md) · 🇮🇹 [it](../../it/docs/ARCHITECTURE.md) · 🇷🇺 [ru](../../ru/docs/ARCHITECTURE.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/ARCHITECTURE.md) · 🇯🇵 [ja](../../ja/docs/ARCHITECTURE.md) · 🇰🇷 [ko](../../ko/docs/ARCHITECTURE.md) · 🇸🇦 [ar](../../ar/docs/ARCHITECTURE.md) · 🇮🇳 [in](../../in/docs/ARCHITECTURE.md) · 🇹🇭 [th](../../th/docs/ARCHITECTURE.md) · 🇻🇳 [vi](../../vi/docs/ARCHITECTURE.md) · 🇮🇩 [id](../../id/docs/ARCHITECTURE.md) · 🇲🇾 [ms](../../ms/docs/ARCHITECTURE.md) · 🇳🇱 [nl](../../nl/docs/ARCHITECTURE.md) · 🇵🇱 [pl](../../pl/docs/ARCHITECTURE.md) · 🇸🇪 [sv](../../sv/docs/ARCHITECTURE.md) · 🇳🇴 [no](../../no/docs/ARCHITECTURE.md) · 🇩🇰 [da](../../da/docs/ARCHITECTURE.md) · 🇫🇮 [fi](../../fi/docs/ARCHITECTURE.md) · 🇵🇹 [pt](../../pt/docs/ARCHITECTURE.md) · 🇷🇴 [ro](../../ro/docs/ARCHITECTURE.md) · 🇭🇺 [hu](../../hu/docs/ARCHITECTURE.md) · 🇧🇬 [bg](../../bg/docs/ARCHITECTURE.md) · 🇸🇰 [sk](../../sk/docs/ARCHITECTURE.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/ARCHITECTURE.md) · 🇮🇱 [he](../../he/docs/ARCHITECTURE.md) · 🇵🇭 [phi](../../phi/docs/ARCHITECTURE.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/ARCHITECTURE.md) · 🇨🇿 [cs](../../cs/docs/ARCHITECTURE.md)
+
+---
+
+_Last updated: 2026-03-28_
+
+## Executive Summary
+
+OmniRoute is a local AI routing gateway and dashboard built on Next.js.
+It provides a single OpenAI-compatible endpoint (`/v1/*`) and routes traffic across multiple upstream providers with translation, fallback, token refresh, and usage tracking.
+
+Core capabilities:
+
+- OpenAI-compatible API surface for CLI/tools (28 providers)
+- Request/response translation across provider formats
+- Model combo fallback (multi-model sequence)
+- Account-level fallback (multi-account per provider)
+- OAuth + API-key provider connection management
+- Embedding generation via `/v1/embeddings` (6 providers, 9 models)
+- Image generation via `/v1/images/generations` (4 providers, 9 models)
+- Think tag parsing (`...`) for reasoning models
+- Response sanitization for strict OpenAI SDK compatibility
+- Role normalization (developer→system, system→user) for cross-provider compatibility
+- Structured output conversion (json_schema → Gemini responseSchema)
+- Local persistence for providers, keys, aliases, combos, settings, pricing
+- Usage/cost tracking and request logging
+- Optional cloud sync for multi-device/state sync
+- IP allowlist/blocklist for API access control
+- Thinking budget management (passthrough/auto/custom/adaptive)
+- Global system prompt injection
+- Session tracking and fingerprinting
+- Per-account enhanced rate limiting with provider-specific profiles
+- Circuit breaker pattern for provider resilience
+- Anti-thundering herd protection with mutex locking
+- Signature-based request deduplication cache
+- Domain layer: model availability, cost rules, fallback policy, lockout policy
+- Domain state persistence (SQLite write-through cache for fallbacks, budgets, lockouts, circuit breakers)
+- Policy engine for centralized request evaluation (lockout → budget → fallback)
+- Request telemetry with p50/p95/p99 latency aggregation
+- Correlation ID (X-Request-Id) for end-to-end tracing
+- Compliance audit logging with opt-out per API key
+- Eval framework for LLM quality assurance
+- Resilience UI dashboard with real-time circuit breaker status
+- Modular OAuth providers (12 individual modules under `src/lib/oauth/providers/`)
+
+Primary runtime model:
+
+- Next.js app routes under `src/app/api/*` implement both dashboard APIs and compatibility APIs
+- A shared SSE/routing core in `src/sse/*` + `open-sse/*` handles provider execution, translation, streaming, fallback, and usage
+
+## Scope and Boundaries
+
+### In Scope
+
+- Local gateway runtime
+- Dashboard management APIs
+- Provider authentication and token refresh
+- Request translation and SSE streaming
+- Local state + usage persistence
+- Optional cloud sync orchestration
+
+### Out of Scope
+
+- Cloud service implementation behind `NEXT_PUBLIC_CLOUD_URL`
+- Provider SLA/control plane outside local process
+- External CLI binaries themselves (Claude CLI, Codex CLI, etc.)
+
+## Dashboard Surface (Current)
+
+Main pages under `src/app/(dashboard)/dashboard/`:
+
+- `/dashboard` — quick start + provider overview
+- `/dashboard/endpoint` — endpoint proxy + MCP + A2A + API endpoint tabs
+- `/dashboard/providers` — provider connections and credentials
+- `/dashboard/combos` — combo strategies, templates, model routing rules
+- `/dashboard/costs` — cost aggregation and pricing visibility
+- `/dashboard/analytics` — usage analytics and evaluations
+- `/dashboard/limits` — quota/rate controls
+- `/dashboard/cli-tools` — CLI onboarding, runtime detection, config generation
+- `/dashboard/agents` — detected ACP agents + custom agent registration
+- `/dashboard/media` — image/video/music playground
+- `/dashboard/search-tools` — search provider testing and history
+- `/dashboard/health` — uptime, circuit breakers, rate limits
+- `/dashboard/logs` — request/proxy/audit/console logs
+- `/dashboard/settings` — system settings tabs (general, routing, combo defaults, etc.)
+- `/dashboard/api-manager` — API key lifecycle and model permissions
+
+## High-Level System Context
+
+```mermaid
+flowchart LR
+ subgraph Clients[Developer Clients]
+ C1[Claude Code]
+ C2[Codex CLI]
+ C3[OpenClaw / Droid / Cline / Continue / Roo]
+ C4[Custom OpenAI-compatible clients]
+ BROWSER[Browser Dashboard]
+ end
+
+ subgraph Router[OmniRoute Local Process]
+ API[V1 Compatibility API\n/v1/*]
+ DASH[Dashboard + Management API\n/api/*]
+ CORE[SSE + Translation Core\nopen-sse + src/sse]
+ DB[(storage.sqlite)]
+ UDB[(usage tables + log artifacts)]
+ end
+
+ subgraph Upstreams[Upstream Providers]
+ P1[OAuth Providers\nClaude/Codex/Gemini/Qwen/Qoder/GitHub/Kiro/Cursor/Antigravity]
+ P2[API Key Providers\nOpenAI/Anthropic/OpenRouter/GLM/Kimi/MiniMax\nDeepSeek/Groq/xAI/Mistral/Perplexity\nTogether/Fireworks/Cerebras/Cohere/NVIDIA]
+ P3[Compatible Nodes\nOpenAI-compatible / Anthropic-compatible]
+ end
+
+ subgraph Cloud[Optional Cloud Sync]
+ CLOUD[Cloud Sync Endpoint\nNEXT_PUBLIC_CLOUD_URL]
+ end
+
+ C1 --> API
+ C2 --> API
+ C3 --> API
+ C4 --> API
+ BROWSER --> DASH
+
+ API --> CORE
+ DASH --> DB
+ CORE --> DB
+ CORE --> UDB
+
+ CORE --> P1
+ CORE --> P2
+ CORE --> P3
+
+ DASH --> CLOUD
+```
+
+## Core Runtime Components
+
+## 1) API and Routing Layer (Next.js App Routes)
+
+Main directories:
+
+- `src/app/api/v1/*` and `src/app/api/v1beta/*` for compatibility APIs
+- `src/app/api/*` for management/configuration APIs
+- Next rewrites in `next.config.mjs` map `/v1/*` to `/api/v1/*`
+
+Important compatibility routes:
+
+- `src/app/api/v1/chat/completions/route.ts`
+- `src/app/api/v1/messages/route.ts`
+- `src/app/api/v1/responses/route.ts`
+- `src/app/api/v1/models/route.ts` — includes custom models with `custom: true`
+- `src/app/api/v1/embeddings/route.ts` — embedding generation (6 providers)
+- `src/app/api/v1/images/generations/route.ts` — image generation (4+ providers incl. Antigravity/Nebius)
+- `src/app/api/v1/messages/count_tokens/route.ts`
+- `src/app/api/v1/providers/[provider]/chat/completions/route.ts` — dedicated per-provider chat
+- `src/app/api/v1/providers/[provider]/embeddings/route.ts` — dedicated per-provider embeddings
+- `src/app/api/v1/providers/[provider]/images/generations/route.ts` — dedicated per-provider images
+- `src/app/api/v1beta/models/route.ts`
+- `src/app/api/v1beta/models/[...path]/route.ts`
+
+Management domains:
+
+- Auth/settings: `src/app/api/auth/*`, `src/app/api/settings/*`
+- Providers/connections: `src/app/api/providers*`
+- Provider nodes: `src/app/api/provider-nodes*`
+- Custom models: `src/app/api/provider-models` (GET/POST/DELETE)
+- Model catalog: `src/app/api/models/route.ts` (GET)
+- Proxy config: `src/app/api/settings/proxy` (GET/PUT/DELETE) + `src/app/api/settings/proxy/test` (POST)
+- OAuth: `src/app/api/oauth/*`
+- Keys/aliases/combos/pricing: `src/app/api/keys*`, `src/app/api/models/alias`, `src/app/api/combos*`, `src/app/api/pricing`
+- Usage: `src/app/api/usage/*`
+- Sync/cloud: `src/app/api/sync/*`, `src/app/api/cloud/*`
+- CLI tooling helpers: `src/app/api/cli-tools/*`
+- IP filter: `src/app/api/settings/ip-filter` (GET/PUT)
+- Thinking budget: `src/app/api/settings/thinking-budget` (GET/PUT)
+- System prompt: `src/app/api/settings/system-prompt` (GET/PUT)
+- Sessions: `src/app/api/sessions` (GET)
+- Rate limits: `src/app/api/rate-limits` (GET)
+- Resilience: `src/app/api/resilience` (GET/PATCH) — provider profiles, circuit breaker, rate limit state
+- Resilience reset: `src/app/api/resilience/reset` (POST) — reset breakers + cooldowns
+- Cache stats: `src/app/api/cache/stats` (GET/DELETE)
+- Model availability: `src/app/api/models/availability` (GET/POST)
+- Telemetry: `src/app/api/telemetry/summary` (GET)
+- Budget: `src/app/api/usage/budget` (GET/POST)
+- Fallback chains: `src/app/api/fallback/chains` (GET/POST/DELETE)
+- Compliance audit: `src/app/api/compliance/audit-log` (GET)
+- Evals: `src/app/api/evals` (GET/POST), `src/app/api/evals/[suiteId]` (GET)
+- Policies: `src/app/api/policies` (GET/POST)
+
+## 2) SSE + Translation Core
+
+Main flow modules:
+
+- Entry: `src/sse/handlers/chat.ts`
+- Core orchestration: `open-sse/handlers/chatCore.ts`
+- Provider execution adapters: `open-sse/executors/*`
+- Format detection/provider config: `open-sse/services/provider.ts`
+- Model parse/resolve: `src/sse/services/model.ts`, `open-sse/services/model.ts`
+- Account fallback logic: `open-sse/services/accountFallback.ts`
+- Translation registry: `open-sse/translator/index.ts`
+- Stream transformations: `open-sse/utils/stream.ts`, `open-sse/utils/streamHandler.ts`
+- Usage extraction/normalization: `open-sse/utils/usageTracking.ts`
+- Think tag parser: `open-sse/utils/thinkTagParser.ts`
+- Embedding handler: `open-sse/handlers/embeddings.ts`
+- Embedding provider registry: `open-sse/config/embeddingRegistry.ts`
+- Image generation handler: `open-sse/handlers/imageGeneration.ts`
+- Image provider registry: `open-sse/config/imageRegistry.ts`
+- Response sanitization: `open-sse/handlers/responseSanitizer.ts`
+- Role normalization: `open-sse/services/roleNormalizer.ts`
+
+Services (business logic):
+
+- Account selection/scoring: `open-sse/services/accountSelector.ts`
+- Context lifecycle management: `open-sse/services/contextManager.ts`
+- IP filter enforcement: `open-sse/services/ipFilter.ts`
+- Session tracking: `open-sse/services/sessionManager.ts`
+- Request deduplication: `open-sse/services/signatureCache.ts`
+- System prompt injection: `open-sse/services/systemPrompt.ts`
+- Thinking budget management: `open-sse/services/thinkingBudget.ts`
+- Wildcard model routing: `open-sse/services/wildcardRouter.ts`
+- Rate limit management: `open-sse/services/rateLimitManager.ts`
+- Circuit breaker: `open-sse/services/circuitBreaker.ts`
+
+Domain layer modules:
+
+- Model availability: `src/lib/domain/modelAvailability.ts`
+- Cost rules/budgets: `src/lib/domain/costRules.ts`
+- Fallback policy: `src/lib/domain/fallbackPolicy.ts`
+- Combo resolver: `src/lib/domain/comboResolver.ts`
+- Lockout policy: `src/lib/domain/lockoutPolicy.ts`
+- Policy engine: `src/domain/policyEngine.ts` — centralized lockout → budget → fallback evaluation
+- Error codes catalog: `src/lib/domain/errorCodes.ts`
+- Request ID: `src/lib/domain/requestId.ts`
+- Fetch timeout: `src/lib/domain/fetchTimeout.ts`
+- Request telemetry: `src/lib/domain/requestTelemetry.ts`
+- Compliance/audit: `src/lib/domain/compliance/index.ts`
+- Eval runner: `src/lib/domain/evalRunner.ts`
+- Domain state persistence: `src/lib/db/domainState.ts` — SQLite CRUD for fallback chains, budgets, cost history, lockout state, circuit breakers
+
+OAuth provider modules (12 individual files under `src/lib/oauth/providers/`):
+
+- Registry index: `src/lib/oauth/providers/index.ts`
+- Individual providers: `claude.ts`, `codex.ts`, `gemini.ts`, `antigravity.ts`, `qoder.ts`, `qwen.ts`, `kimi-coding.ts`, `github.ts`, `kiro.ts`, `cursor.ts`, `kilocode.ts`, `cline.ts`
+- Thin wrapper: `src/lib/oauth/providers.ts` — re-exports from individual modules
+
+## 3) Persistence Layer
+
+Primary state DB (SQLite):
+
+- Core infra: `src/lib/db/core.ts` (better-sqlite3, migrations, WAL)
+- Re-export facade: `src/lib/localDb.ts` (thin compatibility layer for callers)
+- file: `${DATA_DIR}/storage.sqlite` (or `$XDG_CONFIG_HOME/omniroute/storage.sqlite` when set, else `~/.omniroute/storage.sqlite`)
+- entities (tables + KV namespaces): providerConnections, providerNodes, modelAliases, combos, apiKeys, settings, pricing, **customModels**, **proxyConfig**, **ipFilter**, **thinkingBudget**, **systemPrompt**
+
+Usage persistence:
+
+- facade: `src/lib/usageDb.ts` (decomposed modules in `src/lib/usage/*`)
+- SQLite tables in `storage.sqlite`: `usage_history`, `call_logs`, `proxy_logs`
+- optional file artifacts remain for compatibility/debug (`${DATA_DIR}/log.txt`, `${DATA_DIR}/call_logs/`, `/logs/...`)
+- legacy JSON files are migrated to SQLite by startup migrations when present
+
+Domain State DB (SQLite):
+
+- `src/lib/db/domainState.ts` — CRUD operations for domain state
+- Tables (created in `src/lib/db/core.ts`): `domain_fallback_chains`, `domain_budgets`, `domain_cost_history`, `domain_lockout_state`, `domain_circuit_breakers`
+- Write-through cache pattern: in-memory Maps are authoritative at runtime; mutations are written synchronously to SQLite; state is restored from DB on cold start
+
+## 4) Auth + Security Surfaces
+
+- Dashboard cookie auth: `src/proxy.ts`, `src/app/api/auth/login/route.ts`
+- API key generation/verification: `src/shared/utils/apiKey.ts`
+- Provider secrets persisted in `providerConnections` entries
+- Outbound proxy support via `open-sse/utils/proxyFetch.ts` (env vars) and `open-sse/utils/networkProxy.ts` (configurable per-provider or global)
+
+## 5) Cloud Sync
+
+- Scheduler init: `src/lib/initCloudSync.ts`, `src/shared/services/initializeCloudSync.ts`, `src/shared/services/modelSyncScheduler.ts`
+- Periodic task: `src/shared/services/cloudSyncScheduler.ts`
+- Periodic task: `src/shared/services/modelSyncScheduler.ts`
+- Control route: `src/app/api/sync/cloud/route.ts`
+
+## Request Lifecycle (`/v1/chat/completions`)
+
+```mermaid
+sequenceDiagram
+ autonumber
+ participant Client as CLI/SDK Client
+ participant Route as /api/v1/chat/completions
+ participant Chat as src/sse/handlers/chat
+ participant Core as open-sse/handlers/chatCore
+ participant Model as Model Resolver
+ participant Auth as Credential Selector
+ participant Exec as Provider Executor
+ participant Prov as Upstream Provider
+ participant Stream as Stream Translator
+ participant Usage as usageDb
+
+ Client->>Route: POST /v1/chat/completions
+ Route->>Chat: handleChat(request)
+ Chat->>Model: parse/resolve model or combo
+
+ alt Combo model
+ Chat->>Chat: iterate combo models (handleComboChat)
+ end
+
+ Chat->>Auth: getProviderCredentials(provider)
+ Auth-->>Chat: active account + tokens/api key
+
+ Chat->>Core: handleChatCore(body, modelInfo, credentials)
+ Core->>Core: detect source format
+ Core->>Core: translate request to target format
+ Core->>Exec: execute(provider, transformedBody)
+ Exec->>Prov: upstream API call
+ Prov-->>Exec: SSE/JSON response
+ Exec-->>Core: response + metadata
+
+ alt 401/403
+ Core->>Exec: refreshCredentials()
+ Exec-->>Core: updated tokens
+ Core->>Exec: retry request
+ end
+
+ Core->>Stream: translate/normalize stream to client format
+ Stream-->>Client: SSE chunks / JSON response
+
+ Stream->>Usage: extract usage + persist history/log
+```
+
+## Combo + Account Fallback Flow
+
+```mermaid
+flowchart TD
+ A[Incoming model string] --> B{Is combo name?}
+ B -- Yes --> C[Load combo models sequence]
+ B -- No --> D[Single model path]
+
+ C --> E[Try model N]
+ E --> F[Resolve provider/model]
+ D --> F
+
+ F --> G[Select account credentials]
+ G --> H{Credentials available?}
+ H -- No --> I[Return provider unavailable]
+ H -- Yes --> J[Execute request]
+
+ J --> K{Success?}
+ K -- Yes --> L[Return response]
+ K -- No --> M{Fallback-eligible error?}
+
+ M -- No --> N[Return error]
+ M -- Yes --> O[Mark account unavailable cooldown]
+ O --> P{Another account for provider?}
+ P -- Yes --> G
+ P -- No --> Q{In combo with next model?}
+ Q -- Yes --> E
+ Q -- No --> R[Return all unavailable]
+```
+
+Fallback decisions are driven by `open-sse/services/accountFallback.ts` using status codes and error-message heuristics. Combo routing adds one extra guard: provider-scoped 400s such as upstream content-block and role-validation failures are treated as model-local failures so later combo targets can still run.
+
+## OAuth Onboarding and Token Refresh Lifecycle
+
+```mermaid
+sequenceDiagram
+ autonumber
+ participant UI as Dashboard UI
+ participant OAuth as /api/oauth/[provider]/[action]
+ participant ProvAuth as Provider Auth Server
+ participant DB as localDb
+ participant Test as /api/providers/[id]/test
+ participant Exec as Provider Executor
+
+ UI->>OAuth: GET authorize or device-code
+ OAuth->>ProvAuth: create auth/device flow
+ ProvAuth-->>OAuth: auth URL or device code payload
+ OAuth-->>UI: flow data
+
+ UI->>OAuth: POST exchange or poll
+ OAuth->>ProvAuth: token exchange/poll
+ ProvAuth-->>OAuth: access/refresh tokens
+ OAuth->>DB: createProviderConnection(oauth data)
+ OAuth-->>UI: success + connection id
+
+ UI->>Test: POST /api/providers/[id]/test
+ Test->>Exec: validate credentials / optional refresh
+ Exec-->>Test: valid or refreshed token info
+ Test->>DB: update status/tokens/errors
+ Test-->>UI: validation result
+```
+
+Refresh during live traffic is executed inside `open-sse/handlers/chatCore.ts` via executor `refreshCredentials()`.
+
+## Cloud Sync Lifecycle (Enable / Sync / Disable)
+
+```mermaid
+sequenceDiagram
+ autonumber
+ participant UI as Endpoint Page UI
+ participant Sync as /api/sync/cloud
+ participant DB as localDb
+ participant Cloud as External Cloud Sync
+ participant Claude as ~/.claude/settings.json
+
+ UI->>Sync: POST action=enable
+ Sync->>DB: set cloudEnabled=true
+ Sync->>DB: ensure API key exists
+ Sync->>Cloud: POST /sync/{machineId} (providers/aliases/combos/keys)
+ Cloud-->>Sync: sync result
+ Sync->>Cloud: GET /{machineId}/v1/verify
+ Sync-->>UI: enabled + verification status
+
+ UI->>Sync: POST action=sync
+ Sync->>Cloud: POST /sync/{machineId}
+ Cloud-->>Sync: remote data
+ Sync->>DB: update newer local tokens/status
+ Sync-->>UI: synced
+
+ UI->>Sync: POST action=disable
+ Sync->>DB: set cloudEnabled=false
+ Sync->>Cloud: DELETE /sync/{machineId}
+ Sync->>Claude: switch ANTHROPIC_BASE_URL back to local (if needed)
+ Sync-->>UI: disabled
+```
+
+Periodic sync is triggered by `CloudSyncScheduler` when cloud is enabled.
+
+## Data Model and Storage Map
+
+```mermaid
+erDiagram
+ SETTINGS ||--o{ PROVIDER_CONNECTION : controls
+ PROVIDER_NODE ||--o{ PROVIDER_CONNECTION : backs_compatible_provider
+ PROVIDER_CONNECTION ||--o{ USAGE_ENTRY : emits_usage
+
+ SETTINGS {
+ boolean cloudEnabled
+ number stickyRoundRobinLimit
+ boolean requireLogin
+ string password_hash
+ string fallbackStrategy
+ json rateLimitDefaults
+ json providerProfiles
+ }
+
+ PROVIDER_CONNECTION {
+ string id
+ string provider
+ string authType
+ string name
+ number priority
+ boolean isActive
+ string apiKey
+ string accessToken
+ string refreshToken
+ string expiresAt
+ string testStatus
+ string lastError
+ string rateLimitedUntil
+ json providerSpecificData
+ }
+
+ PROVIDER_NODE {
+ string id
+ string type
+ string name
+ string prefix
+ string apiType
+ string baseUrl
+ }
+
+ MODEL_ALIAS {
+ string alias
+ string targetModel
+ }
+
+ COMBO {
+ string id
+ string name
+ string[] models
+ }
+
+ API_KEY {
+ string id
+ string name
+ string key
+ string machineId
+ }
+
+ USAGE_ENTRY {
+ string provider
+ string model
+ number prompt_tokens
+ number completion_tokens
+ string connectionId
+ string timestamp
+ }
+
+ CUSTOM_MODEL {
+ string id
+ string name
+ string providerId
+ }
+
+ PROXY_CONFIG {
+ string global
+ json providers
+ }
+
+ IP_FILTER {
+ string mode
+ string[] allowlist
+ string[] blocklist
+ }
+
+ THINKING_BUDGET {
+ string mode
+ number customBudget
+ string effortLevel
+ }
+
+ SYSTEM_PROMPT {
+ boolean enabled
+ string prompt
+ string position
+ }
+```
+
+Physical storage files:
+
+- primary runtime DB: `${DATA_DIR}/storage.sqlite`
+- request log lines: `${DATA_DIR}/log.txt` (compat/debug artifact)
+- structured call payload archives: `${DATA_DIR}/call_logs/`
+- optional translator/request debug sessions: `/logs/...`
+
+## Deployment Topology
+
+```mermaid
+flowchart LR
+ subgraph LocalHost[Developer Host]
+ CLI[CLI Tools]
+ Browser[Dashboard Browser]
+ end
+
+ subgraph ContainerOrProcess[OmniRoute Runtime]
+ Next[Next.js Server\nPORT=20128]
+ Core[SSE Core + Executors]
+ MainDB[(storage.sqlite)]
+ UsageDB[(usage tables + log artifacts)]
+ end
+
+ subgraph External[External Services]
+ Providers[AI Providers]
+ SyncCloud[Cloud Sync Service]
+ end
+
+ CLI --> Next
+ Browser --> Next
+ Next --> Core
+ Next --> MainDB
+ Core --> MainDB
+ Core --> UsageDB
+ Core --> Providers
+ Next --> SyncCloud
+```
+
+## Module Mapping (Decision-Critical)
+
+### Route and API Modules
+
+- `src/app/api/v1/*`, `src/app/api/v1beta/*`: compatibility APIs
+- `src/app/api/v1/providers/[provider]/*`: dedicated per-provider routes (chat, embeddings, images)
+- `src/app/api/providers*`: provider CRUD, validation, testing
+- `src/app/api/provider-nodes*`: custom compatible node management
+- `src/app/api/provider-models`: custom model management (CRUD)
+- `src/app/api/models/route.ts`: model catalog API (aliases + custom models)
+- `src/app/api/oauth/*`: OAuth/device-code flows
+- `src/app/api/keys*`: local API key lifecycle
+- `src/app/api/models/alias`: alias management
+- `src/app/api/combos*`: fallback combo management
+- `src/app/api/pricing`: pricing overrides for cost calculation
+- `src/app/api/settings/proxy`: proxy configuration (GET/PUT/DELETE)
+- `src/app/api/settings/proxy/test`: outbound proxy connectivity test (POST)
+- `src/app/api/usage/*`: usage and logs APIs
+- `src/app/api/sync/*` + `src/app/api/cloud/*`: cloud sync and cloud-facing helpers
+- `src/app/api/cli-tools/*`: local CLI config writers/checkers
+- `src/app/api/settings/ip-filter`: IP allowlist/blocklist (GET/PUT)
+- `src/app/api/settings/thinking-budget`: thinking token budget config (GET/PUT)
+- `src/app/api/settings/system-prompt`: global system prompt (GET/PUT)
+- `src/app/api/sessions`: active session listing (GET)
+- `src/app/api/rate-limits`: per-account rate limit status (GET)
+
+### Routing and Execution Core
+
+- `src/sse/handlers/chat.ts`: request parse, combo handling, account selection loop
+- `open-sse/handlers/chatCore.ts`: translation, executor dispatch, retry/refresh handling, stream setup
+- `open-sse/executors/*`: provider-specific network and format behavior
+
+### Translation Registry and Format Converters
+
+- `open-sse/translator/index.ts`: translator registry and orchestration
+- Request translators: `open-sse/translator/request/*`
+- Response translators: `open-sse/translator/response/*`
+- Format constants: `open-sse/translator/formats.ts`
+
+### Persistence
+
+- `src/lib/db/*`: persistent config/state and domain persistence on SQLite
+- `src/lib/localDb.ts`: compatibility re-export for DB modules
+- `src/lib/usageDb.ts`: usage history/call logs facade on top of SQLite tables
+
+## Provider Executor Coverage (Strategy Pattern)
+
+Each provider has a specialized executor extending `BaseExecutor` (in `open-sse/executors/base.ts`), which provides URL building, header construction, retry with exponential backoff, credential refresh hooks, and the `execute()` orchestration method.
+
+| Executor | Provider(s) | Special Handling |
+| --------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------ | -------------------------------------------------------------------- |
+| `DefaultExecutor` | OpenAI, Claude, Gemini, Qwen, Qoder, OpenRouter, GLM, Kimi, MiniMax, DeepSeek, Groq, xAI, Mistral, Perplexity, Together, Fireworks, Cerebras, Cohere, NVIDIA | Dynamic URL/header config per provider |
+| `AntigravityExecutor` | Google Antigravity | Custom project/session IDs, Retry-After parsing |
+| `CodexExecutor` | OpenAI Codex | Injects system instructions, forces reasoning effort |
+| `CursorExecutor` | Cursor IDE | ConnectRPC protocol, Protobuf encoding, request signing via checksum |
+| `GithubExecutor` | GitHub Copilot | Copilot token refresh, VSCode-mimicking headers |
+| `KiroExecutor` | AWS CodeWhisperer/Kiro | AWS EventStream binary format → SSE conversion |
+| `GeminiCLIExecutor` | Gemini CLI | Google OAuth token refresh cycle |
+
+All other providers (including custom compatible nodes) use the `DefaultExecutor`.
+
+## Provider Compatibility Matrix
+
+| Provider | Format | Auth | Stream | Non-Stream | Token Refresh | Usage API |
+| ---------------- | ---------------- | --------------------- | ---------------- | ---------- | ------------- | ------------------ |
+| Claude | claude | API Key / OAuth | ✅ | ✅ | ✅ | ⚠️ Admin only |
+| Gemini | gemini | API Key / OAuth | ✅ | ✅ | ✅ | ⚠️ Cloud Console |
+| Gemini CLI | gemini-cli | OAuth | ✅ | ✅ | ✅ | ⚠️ Cloud Console |
+| Antigravity | antigravity | OAuth | ✅ | ✅ | ✅ | ✅ Full quota API |
+| OpenAI | openai | API Key | ✅ | ✅ | ❌ | ❌ |
+| Codex | openai-responses | OAuth | ✅ forced | ❌ | ✅ | ✅ Rate limits |
+| GitHub Copilot | openai | OAuth + Copilot Token | ✅ | ✅ | ✅ | ✅ Quota snapshots |
+| Cursor | cursor | Custom checksum | ✅ | ✅ | ❌ | ❌ |
+| Kiro | kiro | AWS SSO OIDC | ✅ (EventStream) | ❌ | ✅ | ✅ Usage limits |
+| Qwen | openai | OAuth | ✅ | ✅ | ✅ | ⚠️ Per request |
+| Qoder | openai | OAuth (Basic) | ✅ | ✅ | ✅ | ⚠️ Per request |
+| OpenRouter | openai | API Key | ✅ | ✅ | ❌ | ❌ |
+| GLM/Kimi/MiniMax | claude | API Key | ✅ | ✅ | ❌ | ❌ |
+| DeepSeek | openai | API Key | ✅ | ✅ | ❌ | ❌ |
+| Groq | openai | API Key | ✅ | ✅ | ❌ | ❌ |
+| xAI (Grok) | openai | API Key | ✅ | ✅ | ❌ | ❌ |
+| Mistral | openai | API Key | ✅ | ✅ | ❌ | ❌ |
+| Perplexity | openai | API Key | ✅ | ✅ | ❌ | ❌ |
+| Together AI | openai | API Key | ✅ | ✅ | ❌ | ❌ |
+| Fireworks AI | openai | API Key | ✅ | ✅ | ❌ | ❌ |
+| Cerebras | openai | API Key | ✅ | ✅ | ❌ | ❌ |
+| Cohere | openai | API Key | ✅ | ✅ | ❌ | ❌ |
+| NVIDIA NIM | openai | API Key | ✅ | ✅ | ❌ | ❌ |
+
+## Format Translation Coverage
+
+Detected source formats include:
+
+- `openai`
+- `openai-responses`
+- `claude`
+- `gemini`
+
+Target formats include:
+
+- OpenAI chat/Responses
+- Claude
+- Gemini/Gemini-CLI/Antigravity envelope
+- Kiro
+- Cursor
+
+Translations use **OpenAI as the hub format** — all conversions go through OpenAI as intermediate:
+
+```
+Source Format → OpenAI (hub) → Target Format
+```
+
+Translations are selected dynamically based on source payload shape and provider target format.
+
+Additional processing layers in the translation pipeline:
+
+- **Response sanitization** — Strips non-standard fields from OpenAI-format responses (both streaming and non-streaming) to ensure strict SDK compliance
+- **Role normalization** — Converts `developer` → `system` for non-OpenAI targets; merges `system` → `user` for models that reject the system role (GLM, ERNIE)
+- **Think tag extraction** — Parses `...` blocks from content into `reasoning_content` field
+- **Structured output** — Converts OpenAI `response_format.json_schema` to Gemini's `responseMimeType` + `responseSchema`
+
+## Supported API Endpoints
+
+| Endpoint | Format | Handler |
+| -------------------------------------------------- | ------------------ | ------------------------------------------------------------------- |
+| `POST /v1/chat/completions` | OpenAI Chat | `src/sse/handlers/chat.ts` |
+| `POST /v1/messages` | Claude Messages | Same handler (auto-detected) |
+| `POST /v1/responses` | OpenAI Responses | `open-sse/handlers/responsesHandler.ts` |
+| `POST /v1/embeddings` | OpenAI Embeddings | `open-sse/handlers/embeddings.ts` |
+| `GET /v1/embeddings` | Model listing | API route |
+| `POST /v1/images/generations` | OpenAI Images | `open-sse/handlers/imageGeneration.ts` |
+| `GET /v1/images/generations` | Model listing | API route |
+| `POST /v1/providers/{provider}/chat/completions` | OpenAI Chat | Dedicated per-provider with model validation |
+| `POST /v1/providers/{provider}/embeddings` | OpenAI Embeddings | Dedicated per-provider with model validation |
+| `POST /v1/providers/{provider}/images/generations` | OpenAI Images | Dedicated per-provider with model validation |
+| `POST /v1/messages/count_tokens` | Claude Token Count | API route |
+| `GET /v1/models` | OpenAI Models list | API route (chat + embedding + image + custom models) |
+| `GET /api/models/catalog` | Catalog | All models grouped by provider + type |
+| `POST /v1beta/models/*:streamGenerateContent` | Gemini native | API route |
+| `GET/PUT/DELETE /api/settings/proxy` | Proxy Config | Network proxy configuration |
+| `POST /api/settings/proxy/test` | Proxy Connectivity | Proxy health/connectivity test endpoint |
+| `GET/POST/DELETE /api/provider-models` | Provider Models | Provider model metadata backing custom and managed available models |
+
+## Bypass Handler
+
+The bypass handler (`open-sse/utils/bypassHandler.ts`) intercepts known "throwaway" requests from Claude CLI — warmup pings, title extractions, and token counts — and returns a **fake response** without consuming upstream provider tokens. This is triggered only when `User-Agent` contains `claude-cli`.
+
+## Request Logger Pipeline
+
+The request logger (`open-sse/utils/requestLogger.ts`) provides a 7-stage debug logging pipeline, disabled by default, enabled via `ENABLE_REQUEST_LOGS=true`:
+
+```
+1_req_client.json → 2_req_source.json → 3_req_openai.json → 4_req_target.json
+→ 5_res_provider.txt → 6_res_openai.txt → 7_res_client.txt
+```
+
+Files are written to `/logs//` for each request session.
+
+## Failure Modes and Resilience
+
+## 1) Account/Provider Availability
+
+- provider account cooldown on transient/rate/auth errors
+- account fallback before failing request
+- combo model fallback when current model/provider path is exhausted
+
+## 2) Token Expiry
+
+- pre-check and refresh with retry for refreshable providers
+- 401/403 retry after refresh attempt in core path
+
+## 3) Stream Safety
+
+- disconnect-aware stream controller
+- translation stream with end-of-stream flush and `[DONE]` handling
+- usage estimation fallback when provider usage metadata is missing
+
+## 4) Cloud Sync Degradation
+
+- sync errors are surfaced but local runtime continues
+- scheduler has retry-capable logic, but periodic execution currently calls single-attempt sync by default
+
+## 5) Data Integrity
+
+- SQLite schema migrations and auto-upgrade hooks at startup
+- legacy JSON → SQLite migration compatibility path
+
+## Observability and Operational Signals
+
+Runtime visibility sources:
+
+- console logs from `src/sse/utils/logger.ts`
+- per-request usage aggregates in SQLite (`usage_history`, `call_logs`, `proxy_logs`)
+- four-stage detailed payload captures in SQLite (`request_detail_logs`) when `settings.detailed_logs_enabled=true`
+- textual request status log in `log.txt` (optional/compat)
+- optional deep request/translation logs under `logs/` when `ENABLE_REQUEST_LOGS=true`
+- dashboard usage endpoints (`/api/usage/*`) for UI consumption
+
+Detailed request payload capture stores up to four JSON payload stages per routed call:
+
+- raw request received from the client
+- translated request actually sent upstream
+- provider response reconstructed as JSON; streamed responses are compacted to the final summary plus stream metadata
+- final client response returned by OmniRoute; streamed responses are stored in the same compact summary form
+
+## Security-Sensitive Boundaries
+
+- JWT secret (`JWT_SECRET`) secures dashboard session cookie verification/signing
+- Initial password bootstrap (`INITIAL_PASSWORD`) should be explicitly configured for first-run provisioning
+- API key HMAC secret (`API_KEY_SECRET`) secures generated local API key format
+- Provider secrets (API keys/tokens) are persisted in local DB and should be protected at filesystem level
+- Cloud sync endpoints rely on API key auth + machine id semantics
+
+## Environment and Runtime Matrix
+
+Environment variables actively used by code:
+
+- App/auth: `JWT_SECRET`, `INITIAL_PASSWORD`
+- Storage: `DATA_DIR`
+- Compatible node behavior: `ALLOW_MULTI_CONNECTIONS_PER_COMPAT_NODE`
+- Optional storage base override (Linux/macOS when `DATA_DIR` unset): `XDG_CONFIG_HOME`
+- Security hashing: `API_KEY_SECRET`, `MACHINE_ID_SALT`
+- Logging: `ENABLE_REQUEST_LOGS`
+- Sync/cloud URLing: `NEXT_PUBLIC_BASE_URL`, `NEXT_PUBLIC_CLOUD_URL`
+- Outbound proxy: `HTTP_PROXY`, `HTTPS_PROXY`, `ALL_PROXY`, `NO_PROXY` and lowercase variants
+- SOCKS5 feature flags: `ENABLE_SOCKS5_PROXY`, `NEXT_PUBLIC_ENABLE_SOCKS5_PROXY`
+- Platform/runtime helpers (not app-specific config): `APPDATA`, `NODE_ENV`, `PORT`, `HOSTNAME`
+
+## Known Architectural Notes
+
+1. `usageDb` and `localDb` share the same base directory policy (`DATA_DIR` -> `XDG_CONFIG_HOME/omniroute` -> `~/.omniroute`) with legacy file migration.
+2. `/api/v1/route.ts` delegates to the same unified catalog builder used by `/api/v1/models` (`src/app/api/v1/models/catalog.ts`) to avoid semantic drift.
+3. Request logger writes full headers/body when enabled; treat log directory as sensitive.
+4. Cloud behavior depends on correct `NEXT_PUBLIC_BASE_URL` and cloud endpoint reachability.
+5. The `open-sse/` directory is published as the `@omniroute/open-sse` **npm workspace package**. Source code imports it via `@omniroute/open-sse/...` (resolved by Next.js `transpilePackages`). File paths in this document still use the directory name `open-sse/` for consistency.
+6. Charts in the dashboard use **Recharts** (SVG-based) for accessible, interactive analytics visualizations (model usage bar charts, provider breakdown tables with success rates).
+7. E2E tests use **Playwright** (`tests/e2e/`), run via `npm run test:e2e`. Unit tests use **Node.js test runner** (`tests/unit/`), run via `npm run test:unit`. Source code under `src/` is **TypeScript** (`.ts`/`.tsx`); the `open-sse/` workspace remains JavaScript (`.js`).
+8. Settings page is organized into 5 tabs: Security, Routing (6 global strategies: fill-first, round-robin, p2c, random, least-used, cost-optimized), Resilience (editable rate limits, circuit breaker, policies), AI (thinking budget, system prompt, prompt cache), Advanced (proxy).
+
+## Operational Verification Checklist
+
+- Build from source: `npm run build`
+- Build Docker image: `docker build -t omniroute .`
+- Start service and verify:
+- `GET /api/settings`
+- `GET /api/v1/models`
+- CLI target base URL should be `http://:20128/v1` when `PORT=20128`
diff --git a/docs/i18n/he/docs/AUTO-COMBO.md b/docs/i18n/he/docs/AUTO-COMBO.md
new file mode 100644
index 0000000000..d5979dc8db
--- /dev/null
+++ b/docs/i18n/he/docs/AUTO-COMBO.md
@@ -0,0 +1,67 @@
+# OmniRoute Auto-Combo Engine (עברית)
+
+🌐 **Languages:** 🇺🇸 [English](../../../../docs/AUTO-COMBO.md) · 🇪🇸 [es](../../es/docs/AUTO-COMBO.md) · 🇫🇷 [fr](../../fr/docs/AUTO-COMBO.md) · 🇩🇪 [de](../../de/docs/AUTO-COMBO.md) · 🇮🇹 [it](../../it/docs/AUTO-COMBO.md) · 🇷🇺 [ru](../../ru/docs/AUTO-COMBO.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/AUTO-COMBO.md) · 🇯🇵 [ja](../../ja/docs/AUTO-COMBO.md) · 🇰🇷 [ko](../../ko/docs/AUTO-COMBO.md) · 🇸🇦 [ar](../../ar/docs/AUTO-COMBO.md) · 🇮🇳 [in](../../in/docs/AUTO-COMBO.md) · 🇹🇭 [th](../../th/docs/AUTO-COMBO.md) · 🇻🇳 [vi](../../vi/docs/AUTO-COMBO.md) · 🇮🇩 [id](../../id/docs/AUTO-COMBO.md) · 🇲🇾 [ms](../../ms/docs/AUTO-COMBO.md) · 🇳🇱 [nl](../../nl/docs/AUTO-COMBO.md) · 🇵🇱 [pl](../../pl/docs/AUTO-COMBO.md) · 🇸🇪 [sv](../../sv/docs/AUTO-COMBO.md) · 🇳🇴 [no](../../no/docs/AUTO-COMBO.md) · 🇩🇰 [da](../../da/docs/AUTO-COMBO.md) · 🇫🇮 [fi](../../fi/docs/AUTO-COMBO.md) · 🇵🇹 [pt](../../pt/docs/AUTO-COMBO.md) · 🇷🇴 [ro](../../ro/docs/AUTO-COMBO.md) · 🇭🇺 [hu](../../hu/docs/AUTO-COMBO.md) · 🇧🇬 [bg](../../bg/docs/AUTO-COMBO.md) · 🇸🇰 [sk](../../sk/docs/AUTO-COMBO.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/AUTO-COMBO.md) · 🇮🇱 [he](../../he/docs/AUTO-COMBO.md) · 🇵🇭 [phi](../../phi/docs/AUTO-COMBO.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/AUTO-COMBO.md) · 🇨🇿 [cs](../../cs/docs/AUTO-COMBO.md)
+
+---
+
+> Self-managing model chains with adaptive scoring
+
+## How It Works
+
+The Auto-Combo Engine dynamically selects the best provider/model for each request using a **6-factor scoring function**:
+
+| Factor | Weight | Description |
+| :--------- | :----- | :---------------------------------------------- |
+| Quota | 0.20 | Remaining capacity [0..1] |
+| Health | 0.25 | Circuit breaker: CLOSED=1.0, HALF=0.5, OPEN=0.0 |
+| CostInv | 0.20 | Inverse cost (cheaper = higher score) |
+| LatencyInv | 0.15 | Inverse p95 latency (faster = higher) |
+| TaskFit | 0.10 | Model × task type fitness score |
+| Stability | 0.10 | Low variance in latency/errors |
+
+## Mode Packs
+
+| Pack | Focus | Key Weight |
+| :---------------------- | :----------- | :--------------- |
+| 🚀 **Ship Fast** | Speed | latencyInv: 0.35 |
+| 💰 **Cost Saver** | Economy | costInv: 0.40 |
+| 🎯 **Quality First** | Best model | taskFit: 0.40 |
+| 📡 **Offline Friendly** | Availability | quota: 0.40 |
+
+## Self-Healing
+
+- **Temporary exclusion**: Score < 0.2 → excluded for 5 min (progressive backoff, max 30 min)
+- **Circuit breaker awareness**: OPEN → auto-excluded; HALF_OPEN → probe requests
+- **Incident mode**: >50% OPEN → disable exploration, maximize stability
+- **Cooldown recovery**: After exclusion, first request is a "probe" with reduced timeout
+
+## Bandit Exploration
+
+5% of requests (configurable) are routed to random providers for exploration. Disabled in incident mode.
+
+## API
+
+```bash
+# Create auto-combo
+curl -X POST http://localhost:20128/api/combos/auto \
+ -H "Content-Type: application/json" \
+ -d '{"id":"my-auto","name":"Auto Coder","candidatePool":["anthropic","google","openai"],"modePack":"ship-fast"}'
+
+# List auto-combos
+curl http://localhost:20128/api/combos/auto
+```
+
+## Task Fitness
+
+30+ models scored across 6 task types (`coding`, `review`, `planning`, `analysis`, `debugging`, `documentation`). Supports wildcard patterns (e.g., `*-coder` → high coding score).
+
+## Files
+
+| File | Purpose |
+| :------------------------------------------- | :------------------------------------ |
+| `open-sse/services/autoCombo/scoring.ts` | Scoring function & pool normalization |
+| `open-sse/services/autoCombo/taskFitness.ts` | Model × task fitness lookup |
+| `open-sse/services/autoCombo/engine.ts` | Selection logic, bandit, budget cap |
+| `open-sse/services/autoCombo/selfHealing.ts` | Exclusion, probes, incident mode |
+| `open-sse/services/autoCombo/modePacks.ts` | 4 weight profiles |
+| `src/app/api/combos/auto/route.ts` | REST API |
diff --git a/docs/i18n/he/docs/CLI-TOOLS.md b/docs/i18n/he/docs/CLI-TOOLS.md
new file mode 100644
index 0000000000..b8416f0dbc
--- /dev/null
+++ b/docs/i18n/he/docs/CLI-TOOLS.md
@@ -0,0 +1,348 @@
+# CLI Tools Setup Guide — OmniRoute (עברית)
+
+🌐 **Languages:** 🇺🇸 [English](../../../../docs/CLI-TOOLS.md) · 🇪🇸 [es](../../es/docs/CLI-TOOLS.md) · 🇫🇷 [fr](../../fr/docs/CLI-TOOLS.md) · 🇩🇪 [de](../../de/docs/CLI-TOOLS.md) · 🇮🇹 [it](../../it/docs/CLI-TOOLS.md) · 🇷🇺 [ru](../../ru/docs/CLI-TOOLS.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/CLI-TOOLS.md) · 🇯🇵 [ja](../../ja/docs/CLI-TOOLS.md) · 🇰🇷 [ko](../../ko/docs/CLI-TOOLS.md) · 🇸🇦 [ar](../../ar/docs/CLI-TOOLS.md) · 🇮🇳 [in](../../in/docs/CLI-TOOLS.md) · 🇹🇭 [th](../../th/docs/CLI-TOOLS.md) · 🇻🇳 [vi](../../vi/docs/CLI-TOOLS.md) · 🇮🇩 [id](../../id/docs/CLI-TOOLS.md) · 🇲🇾 [ms](../../ms/docs/CLI-TOOLS.md) · 🇳🇱 [nl](../../nl/docs/CLI-TOOLS.md) · 🇵🇱 [pl](../../pl/docs/CLI-TOOLS.md) · 🇸🇪 [sv](../../sv/docs/CLI-TOOLS.md) · 🇳🇴 [no](../../no/docs/CLI-TOOLS.md) · 🇩🇰 [da](../../da/docs/CLI-TOOLS.md) · 🇫🇮 [fi](../../fi/docs/CLI-TOOLS.md) · 🇵🇹 [pt](../../pt/docs/CLI-TOOLS.md) · 🇷🇴 [ro](../../ro/docs/CLI-TOOLS.md) · 🇭🇺 [hu](../../hu/docs/CLI-TOOLS.md) · 🇧🇬 [bg](../../bg/docs/CLI-TOOLS.md) · 🇸🇰 [sk](../../sk/docs/CLI-TOOLS.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/CLI-TOOLS.md) · 🇮🇱 [he](../../he/docs/CLI-TOOLS.md) · 🇵🇭 [phi](../../phi/docs/CLI-TOOLS.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/CLI-TOOLS.md) · 🇨🇿 [cs](../../cs/docs/CLI-TOOLS.md)
+
+---
+
+This guide explains how to install and configure all supported AI coding CLI tools
+to use **OmniRoute** as the unified backend, giving you centralized key management,
+cost tracking, model switching, and request logging across every tool.
+
+---
+
+## How It Works
+
+```
+Claude / Codex / OpenCode / Cline / KiloCode / Continue / Kiro / Cursor / Copilot
+ │
+ ▼ (all point to OmniRoute)
+ http://YOUR_SERVER:20128/v1
+ │
+ ▼ (OmniRoute routes to the right provider)
+ Anthropic / OpenAI / Gemini / DeepSeek / Groq / Mistral / ...
+```
+
+**Benefits:**
+
+- One API key to manage all tools
+- Cost tracking across all CLIs in the dashboard
+- Model switching without reconfiguring every tool
+- Works locally and on remote servers (VPS)
+
+---
+
+## Supported Tools (Dashboard Source of Truth)
+
+The dashboard cards in `/dashboard/cli-tools` are generated from `src/shared/constants/cliTools.ts`.
+Current list (v3.0.0-rc.16):
+
+| Tool | ID | Command | Setup Mode | Install Method |
+| ------------------ | ------------- | ---------- | ---------- | -------------- |
+| **Claude Code** | `claude` | `claude` | env | npm |
+| **OpenAI Codex** | `codex` | `codex` | custom | npm |
+| **Factory Droid** | `droid` | `droid` | custom | bundled/CLI |
+| **OpenClaw** | `openclaw` | `openclaw` | custom | bundled/CLI |
+| **Cursor** | `cursor` | app | guide | desktop app |
+| **Cline** | `cline` | `cline` | custom | npm |
+| **Kilo Code** | `kilo` | `kilocode` | custom | npm |
+| **Continue** | `continue` | extension | guide | VS Code |
+| **Antigravity** | `antigravity` | internal | mitm | OmniRoute |
+| **GitHub Copilot** | `copilot` | extension | custom | VS Code |
+| **OpenCode** | `opencode` | `opencode` | guide | npm |
+| **Kiro AI** | `kiro` | app/cli | mitm | desktop/CLI |
+
+### CLI fingerprint sync (Agents + Settings)
+
+`/dashboard/agents` and `Settings > CLI Fingerprint` use `src/shared/constants/cliCompatProviders.ts`.
+This keeps provider IDs aligned with CLI cards and legacy IDs.
+
+| CLI ID | Fingerprint Provider ID |
+| ---------------------------------------------------------------------------------------------------- | ----------------------- |
+| `kilo` | `kilocode` |
+| `copilot` | `github` |
+| `claude` / `codex` / `antigravity` / `kiro` / `cursor` / `cline` / `opencode` / `droid` / `openclaw` | same ID |
+
+Legacy IDs still accepted for compatibility: `copilot`, `kimi-coding`, `qwen`.
+
+---
+
+## Step 1 — Get an OmniRoute API Key
+
+1. Open the OmniRoute dashboard → **API Manager** (`/dashboard/api-manager`)
+2. Click **Create API Key**
+3. Give it a name (e.g. `cli-tools`) and select all permissions
+4. Copy the key — you'll need it for every CLI below
+
+> Your key looks like: `sk-xxxxxxxxxxxxxxxx-xxxxxxxxx`
+
+---
+
+## Step 2 — Install CLI Tools
+
+All npm-based tools require Node.js 18+:
+
+```bash
+# Claude Code (Anthropic)
+npm install -g @anthropic-ai/claude-code
+
+# OpenAI Codex
+npm install -g @openai/codex
+
+# OpenCode
+npm install -g opencode-ai
+
+# Cline
+npm install -g cline
+
+# KiloCode
+npm install -g kilocode
+
+# Kiro CLI (Amazon — requires curl + unzip)
+apt-get install -y unzip # on Debian/Ubuntu
+curl -fsSL https://cli.kiro.dev/install | bash
+export PATH="$HOME/.local/bin:$PATH" # add to ~/.bashrc
+```
+
+**Verify:**
+
+```bash
+claude --version # 2.x.x
+codex --version # 0.x.x
+opencode --version # x.x.x
+cline --version # 2.x.x
+kilocode --version # x.x.x (or: kilo --version)
+kiro-cli --version # 1.x.x
+```
+
+---
+
+## Step 3 — Set Global Environment Variables
+
+Add to `~/.bashrc` (or `~/.zshrc`), then run `source ~/.bashrc`:
+
+```bash
+# OmniRoute Universal Endpoint
+export OPENAI_BASE_URL="http://localhost:20128/v1"
+export OPENAI_API_KEY="sk-your-omniroute-key"
+export ANTHROPIC_BASE_URL="http://localhost:20128/v1"
+export ANTHROPIC_API_KEY="sk-your-omniroute-key"
+export GEMINI_BASE_URL="http://localhost:20128/v1"
+export GEMINI_API_KEY="sk-your-omniroute-key"
+```
+
+> For a **remote server** replace `localhost:20128` with the server IP or domain,
+> e.g. `http://192.168.0.15:20128`.
+
+---
+
+## Step 4 — Configure Each Tool
+
+### Claude Code
+
+```bash
+# Via CLI:
+claude config set --global api-base-url http://localhost:20128/v1
+
+# Or create ~/.claude/settings.json:
+mkdir -p ~/.claude && cat > ~/.claude/settings.json << EOF
+{
+ "apiBaseUrl": "http://localhost:20128/v1",
+ "apiKey": "sk-your-omniroute-key"
+}
+EOF
+```
+
+**Test:** `claude "say hello"`
+
+---
+
+### OpenAI Codex
+
+```bash
+mkdir -p ~/.codex && cat > ~/.codex/config.yaml << EOF
+model: auto
+apiKey: sk-your-omniroute-key
+apiBaseUrl: http://localhost:20128/v1
+EOF
+```
+
+**Test:** `codex "what is 2+2?"`
+
+---
+
+### OpenCode
+
+```bash
+mkdir -p ~/.config/opencode && cat > ~/.config/opencode/config.toml << EOF
+[provider.openai]
+base_url = "http://localhost:20128/v1"
+api_key = "sk-your-omniroute-key"
+EOF
+```
+
+**Test:** `opencode`
+
+---
+
+### Cline (CLI or VS Code)
+
+**CLI mode:**
+
+```bash
+mkdir -p ~/.cline/data && cat > ~/.cline/data/globalState.json << EOF
+{
+ "apiProvider": "openai",
+ "openAiBaseUrl": "http://localhost:20128/v1",
+ "openAiApiKey": "sk-your-omniroute-key"
+}
+EOF
+```
+
+**VS Code mode:**
+Cline extension settings → API Provider: `OpenAI Compatible` → Base URL: `http://localhost:20128/v1`
+
+Or use the OmniRoute dashboard → **CLI Tools → Cline → Apply Config**.
+
+---
+
+### KiloCode (CLI or VS Code)
+
+**CLI mode:**
+
+```bash
+kilocode --api-base http://localhost:20128/v1 --api-key sk-your-omniroute-key
+```
+
+**VS Code settings:**
+
+```json
+{
+ "kilo-code.openAiBaseUrl": "http://localhost:20128/v1",
+ "kilo-code.apiKey": "sk-your-omniroute-key"
+}
+```
+
+Or use the OmniRoute dashboard → **CLI Tools → KiloCode → Apply Config**.
+
+---
+
+### Continue (VS Code Extension)
+
+Edit `~/.continue/config.yaml`:
+
+```yaml
+models:
+ - name: OmniRoute
+ provider: openai
+ model: auto
+ apiBase: http://localhost:20128/v1
+ apiKey: sk-your-omniroute-key
+ default: true
+```
+
+Restart VS Code after editing.
+
+---
+
+### Kiro CLI (Amazon)
+
+```bash
+# Login to your AWS/Kiro account:
+kiro-cli login
+
+# The CLI uses its own auth — OmniRoute is not needed as backend for Kiro CLI itself.
+# Use kiro-cli alongside OmniRoute for other tools.
+kiro-cli status
+```
+
+---
+
+### Cursor (Desktop App)
+
+> **Note:** Cursor routes requests through its cloud. For OmniRoute integration,
+> enable **Cloud Endpoint** in OmniRoute Settings and use your public domain URL.
+
+Via GUI: **Settings → Models → OpenAI API Key**
+
+- Base URL: `https://your-domain.com/v1`
+- API Key: your OmniRoute key
+
+---
+
+## Dashboard Auto-Configuration
+
+The OmniRoute dashboard automates configuration for most tools:
+
+1. Go to `http://localhost:20128/dashboard/cli-tools`
+2. Expand any tool card
+3. Select your API key from the dropdown
+4. Click **Apply Config** (if tool is detected as installed)
+5. Or copy the generated config snippet manually
+
+---
+
+## Built-in Agents: Droid & OpenClaw
+
+**Droid** and **OpenClaw** are AI agents built directly into OmniRoute — no installation needed.
+They run as internal routes and use OmniRoute's model routing automatically.
+
+- Access: `http://localhost:20128/dashboard/agents`
+- Configure: same combos and providers as all other tools
+- No API key or CLI install required
+
+---
+
+## Available API Endpoints
+
+| Endpoint | Description | Use For |
+| -------------------------- | ----------------------------- | --------------------------- |
+| `/v1/chat/completions` | Standard chat (all providers) | All modern tools |
+| `/v1/responses` | Responses API (OpenAI format) | Codex, agentic workflows |
+| `/v1/completions` | Legacy text completions | Older tools using `prompt:` |
+| `/v1/embeddings` | Text embeddings | RAG, search |
+| `/v1/images/generations` | Image generation | DALL-E, Flux, etc. |
+| `/v1/audio/speech` | Text-to-speech | ElevenLabs, OpenAI TTS |
+| `/v1/audio/transcriptions` | Speech-to-text | Deepgram, AssemblyAI |
+
+---
+
+## פתרון בעיות
+
+| Error | Cause | Fix |
+| ------------------------- | ----------------------- | ------------------------------------------ |
+| `Connection refused` | OmniRoute not running | `pm2 start omniroute` |
+| `401 Unauthorized` | Wrong API key | Check in `/dashboard/api-manager` |
+| `No combo configured` | No active routing combo | Set up in `/dashboard/combos` |
+| `invalid model` | Model not in catalog | Use `auto` or check `/dashboard/providers` |
+| CLI shows "not installed" | Binary not in PATH | Check `which ` |
+| `kiro-cli: not found` | Not in PATH | `export PATH="$HOME/.local/bin:$PATH"` |
+
+---
+
+## Quick Setup Script (One Command)
+
+```bash
+# Install all CLIs and configure for OmniRoute (replace with your key and server URL)
+OMNIROUTE_URL="http://localhost:20128/v1"
+OMNIROUTE_KEY="sk-your-omniroute-key"
+
+npm install -g @anthropic-ai/claude-code @openai/codex opencode-ai cline kilocode
+
+# Kiro CLI
+apt-get install -y unzip 2>/dev/null; curl -fsSL https://cli.kiro.dev/install | bash
+
+# Write configs
+mkdir -p ~/.claude ~/.codex ~/.config/opencode ~/.continue
+
+cat > ~/.claude/settings.json <<< "{\"apiBaseUrl\":\"$OMNIROUTE_URL\",\"apiKey\":\"$OMNIROUTE_KEY\"}"
+cat > ~/.codex/config.yaml <<< "model: auto\napiKey: $OMNIROUTE_KEY\napiBaseUrl: $OMNIROUTE_URL"
+cat >> ~/.bashrc << EOF
+export OPENAI_BASE_URL="$OMNIROUTE_URL"
+export OPENAI_API_KEY="$OMNIROUTE_KEY"
+export ANTHROPIC_BASE_URL="$OMNIROUTE_URL"
+export ANTHROPIC_API_KEY="$OMNIROUTE_KEY"
+EOF
+
+source ~/.bashrc
+echo "✅ All CLIs installed and configured for OmniRoute"
+```
diff --git a/docs/i18n/he/docs/CODEBASE_DOCUMENTATION.md b/docs/i18n/he/docs/CODEBASE_DOCUMENTATION.md
new file mode 100644
index 0000000000..8d47892964
--- /dev/null
+++ b/docs/i18n/he/docs/CODEBASE_DOCUMENTATION.md
@@ -0,0 +1,591 @@
+# omniroute — Codebase Documentation (עברית)
+
+🌐 **Languages:** 🇺🇸 [English](../../../../docs/CODEBASE_DOCUMENTATION.md) · 🇪🇸 [es](../../es/docs/CODEBASE_DOCUMENTATION.md) · 🇫🇷 [fr](../../fr/docs/CODEBASE_DOCUMENTATION.md) · 🇩🇪 [de](../../de/docs/CODEBASE_DOCUMENTATION.md) · 🇮🇹 [it](../../it/docs/CODEBASE_DOCUMENTATION.md) · 🇷🇺 [ru](../../ru/docs/CODEBASE_DOCUMENTATION.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/CODEBASE_DOCUMENTATION.md) · 🇯🇵 [ja](../../ja/docs/CODEBASE_DOCUMENTATION.md) · 🇰🇷 [ko](../../ko/docs/CODEBASE_DOCUMENTATION.md) · 🇸🇦 [ar](../../ar/docs/CODEBASE_DOCUMENTATION.md) · 🇮🇳 [in](../../in/docs/CODEBASE_DOCUMENTATION.md) · 🇹🇭 [th](../../th/docs/CODEBASE_DOCUMENTATION.md) · 🇻🇳 [vi](../../vi/docs/CODEBASE_DOCUMENTATION.md) · 🇮🇩 [id](../../id/docs/CODEBASE_DOCUMENTATION.md) · 🇲🇾 [ms](../../ms/docs/CODEBASE_DOCUMENTATION.md) · 🇳🇱 [nl](../../nl/docs/CODEBASE_DOCUMENTATION.md) · 🇵🇱 [pl](../../pl/docs/CODEBASE_DOCUMENTATION.md) · 🇸🇪 [sv](../../sv/docs/CODEBASE_DOCUMENTATION.md) · 🇳🇴 [no](../../no/docs/CODEBASE_DOCUMENTATION.md) · 🇩🇰 [da](../../da/docs/CODEBASE_DOCUMENTATION.md) · 🇫🇮 [fi](../../fi/docs/CODEBASE_DOCUMENTATION.md) · 🇵🇹 [pt](../../pt/docs/CODEBASE_DOCUMENTATION.md) · 🇷🇴 [ro](../../ro/docs/CODEBASE_DOCUMENTATION.md) · 🇭🇺 [hu](../../hu/docs/CODEBASE_DOCUMENTATION.md) · 🇧🇬 [bg](../../bg/docs/CODEBASE_DOCUMENTATION.md) · 🇸🇰 [sk](../../sk/docs/CODEBASE_DOCUMENTATION.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/CODEBASE_DOCUMENTATION.md) · 🇮🇱 [he](../../he/docs/CODEBASE_DOCUMENTATION.md) · 🇵🇭 [phi](../../phi/docs/CODEBASE_DOCUMENTATION.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/CODEBASE_DOCUMENTATION.md) · 🇨🇿 [cs](../../cs/docs/CODEBASE_DOCUMENTATION.md)
+
+---
+
+> A comprehensive, beginner-friendly guide to the **omniroute** multi-provider AI proxy router.
+
+---
+
+## 1. What Is omniroute?
+
+omniroute is a **proxy router** that sits between AI clients (Claude CLI, Codex, Cursor IDE, etc.) and AI providers (Anthropic, Google, OpenAI, AWS, GitHub, etc.). It solves one big problem:
+
+> **Different AI clients speak different "languages" (API formats), and different AI providers expect different "languages" too.** omniroute translates between them automatically.
+
+Think of it like a universal translator at the United Nations — any delegate can speak any language, and the translator converts it for any other delegate.
+
+---
+
+## 2. Architecture Overview
+
+```mermaid
+graph LR
+ subgraph Clients
+ A[Claude CLI]
+ B[Codex]
+ C[Cursor IDE]
+ D[OpenAI-compatible]
+ end
+
+ subgraph omniroute
+ E[Handler Layer]
+ F[Translator Layer]
+ G[Executor Layer]
+ H[Services Layer]
+ end
+
+ subgraph Providers
+ I[Anthropic Claude]
+ J[Google Gemini]
+ K[OpenAI / Codex]
+ L[GitHub Copilot]
+ M[AWS Kiro]
+ N[Antigravity]
+ O[Cursor API]
+ end
+
+ A --> E
+ B --> E
+ C --> E
+ D --> E
+ E --> F
+ F --> G
+ G --> I
+ G --> J
+ G --> K
+ G --> L
+ G --> M
+ G --> N
+ G --> O
+ H -.-> E
+ H -.-> G
+```
+
+### Core Principle: Hub-and-Spoke Translation
+
+All format translation passes through **OpenAI format as the hub**:
+
+```
+Client Format → [OpenAI Hub] → Provider Format (request)
+Provider Format → [OpenAI Hub] → Client Format (response)
+```
+
+This means you only need **N translators** (one per format) instead of **N²** (every pair).
+
+---
+
+## 3. Project Structure
+
+```
+omniroute/
+├── open-sse/ ← Core proxy library (portable, framework-agnostic)
+│ ├── index.js ← Main entry point, exports everything
+│ ├── config/ ← Configuration & constants
+│ ├── executors/ ← Provider-specific request execution
+│ ├── handlers/ ← Request handling orchestration
+│ ├── services/ ← Business logic (auth, models, fallback, usage)
+│ ├── translator/ ← Format translation engine
+│ │ ├── request/ ← Request translators (8 files)
+│ │ ├── response/ ← Response translators (7 files)
+│ │ └── helpers/ ← Shared translation utilities (6 files)
+│ └── utils/ ← Utility functions
+├── src/ ← Application layer (Express/Worker runtime)
+│ ├── app/ ← Web UI, API routes, middleware
+│ ├── lib/ ← Database, auth, and shared library code
+│ ├── mitm/ ← Man-in-the-middle proxy utilities
+│ ├── models/ ← Database models
+│ ├── shared/ ← Shared utilities (wrappers around open-sse)
+│ ├── sse/ ← SSE endpoint handlers
+│ └── store/ ← State management
+├── data/ ← Runtime data (credentials, logs)
+│ └── provider-credentials.json (external credentials override, gitignored)
+└── tester/ ← Test utilities
+```
+
+---
+
+## 4. Module-by-Module Breakdown
+
+### 4.1 Config (`open-sse/config/`)
+
+The **single source of truth** for all provider configuration.
+
+| File | Purpose |
+| ----------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| `constants.ts` | `PROVIDERS` object with base URLs, OAuth credentials (defaults), headers, and default system prompts for every provider. Also defines `HTTP_STATUS`, `ERROR_TYPES`, `COOLDOWN_MS`, `BACKOFF_CONFIG`, and `SKIP_PATTERNS`. |
+| `credentialLoader.ts` | Loads external credentials from `data/provider-credentials.json` and merges them over the hardcoded defaults in `PROVIDERS`. Keeps secrets out of source control while maintaining backwards compatibility. |
+| `providerModels.ts` | Central model registry: maps provider aliases → model IDs. Functions like `getModels()`, `getProviderByAlias()`. |
+| `codexInstructions.ts` | System instructions injected into Codex requests (editing constraints, sandbox rules, approval policies). |
+| `defaultThinkingSignature.ts` | Default "thinking" signatures for Claude and Gemini models. |
+| `ollamaModels.ts` | Schema definition for local Ollama models (name, size, family, quantization). |
+
+#### Credential Loading Flow
+
+```mermaid
+flowchart TD
+ A["App starts"] --> B["constants.ts defines PROVIDERS\nwith hardcoded defaults"]
+ B --> C{"data/provider-credentials.json\nexists?"}
+ C -->|Yes| D["credentialLoader reads JSON"]
+ C -->|No| E["Use hardcoded defaults"]
+ D --> F{"For each provider in JSON"}
+ F --> G{"Provider exists\nin PROVIDERS?"}
+ G -->|No| H["Log warning, skip"]
+ G -->|Yes| I{"Value is object?"}
+ I -->|No| J["Log warning, skip"]
+ I -->|Yes| K["Merge clientId, clientSecret,\ntokenUrl, authUrl, refreshUrl"]
+ K --> F
+ H --> F
+ J --> F
+ F -->|Done| L["PROVIDERS ready with\nmerged credentials"]
+ E --> L
+```
+
+---
+
+### 4.2 Executors (`open-sse/executors/`)
+
+Executors encapsulate **provider-specific logic** using the **Strategy Pattern**. Each executor overrides base methods as needed.
+
+```mermaid
+classDiagram
+ class BaseExecutor {
+ +buildUrl(model, stream, options)
+ +buildHeaders(credentials, stream, body)
+ +transformRequest(body, model, stream, credentials)
+ +execute(url, options)
+ +shouldRetry(status, error)
+ +refreshCredentials(credentials, log)
+ }
+
+ class DefaultExecutor {
+ +refreshCredentials()
+ }
+
+ class AntigravityExecutor {
+ +buildUrl()
+ +buildHeaders()
+ +transformRequest()
+ +shouldRetry()
+ +refreshCredentials()
+ }
+
+ class CursorExecutor {
+ +buildUrl()
+ +buildHeaders()
+ +transformRequest()
+ +parseResponse()
+ +generateChecksum()
+ }
+
+ class KiroExecutor {
+ +buildUrl()
+ +buildHeaders()
+ +transformRequest()
+ +parseEventStream()
+ +refreshCredentials()
+ }
+
+ BaseExecutor <|-- DefaultExecutor
+ BaseExecutor <|-- AntigravityExecutor
+ BaseExecutor <|-- CursorExecutor
+ BaseExecutor <|-- KiroExecutor
+ BaseExecutor <|-- CodexExecutor
+ BaseExecutor <|-- GeminiCLIExecutor
+ BaseExecutor <|-- GithubExecutor
+```
+
+| Executor | Provider | Key Specializations |
+| ---------------- | ------------------------------------------ | ------------------------------------------------------------------------------------------------------------------- |
+| `base.ts` | — | Abstract base: URL building, headers, retry logic, credential refresh |
+| `default.ts` | Claude, Gemini, OpenAI, GLM, Kimi, MiniMax | Generic OAuth token refresh for standard providers |
+| `antigravity.ts` | Google Cloud Code | Project/session ID generation, multi-URL fallback, custom retry parsing from error messages ("reset after 2h7m23s") |
+| `cursor.ts` | Cursor IDE | **Most complex**: SHA-256 checksum auth, Protobuf request encoding, binary EventStream → SSE response parsing |
+| `codex.ts` | OpenAI Codex | Injects system instructions, manages thinking levels, removes unsupported parameters |
+| `gemini-cli.ts` | Google Gemini CLI | Custom URL building (`streamGenerateContent`), Google OAuth token refresh |
+| `github.ts` | GitHub Copilot | Dual token system (GitHub OAuth + Copilot token), VSCode header mimicking |
+| `kiro.ts` | AWS CodeWhisperer | AWS EventStream binary parsing, AMZN event frames, token estimation |
+| `index.ts` | — | Factory: maps provider name → executor class, with default fallback |
+
+---
+
+### 4.3 Handlers (`open-sse/handlers/`)
+
+The **orchestration layer** — coordinates translation, execution, streaming, and error handling.
+
+| File | Purpose |
+| --------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| `chatCore.ts` | **Central orchestrator** (~600 lines). Handles the complete request lifecycle: format detection → translation → executor dispatch → streaming/non-streaming response → token refresh → error handling → usage logging. |
+| `responsesHandler.ts` | Adapter for OpenAI's Responses API: converts Responses format → Chat Completions → sends to `chatCore` → converts SSE back to Responses format. |
+| `embeddings.ts` | Embedding generation handler: resolves embedding model → provider, dispatches to provider API, returns OpenAI-compatible embedding response. Supports 6+ providers. |
+| `imageGeneration.ts` | Image generation handler: resolves image model → provider, supports OpenAI-compatible, Gemini-image (Antigravity), and fallback (Nebius) modes. Returns base64 or URL images. |
+
+#### Request Lifecycle (chatCore.ts)
+
+```mermaid
+sequenceDiagram
+ participant Client
+ participant chatCore
+ participant Translator
+ participant Executor
+ participant Provider
+
+ Client->>chatCore: Request (any format)
+ chatCore->>chatCore: Detect source format
+ chatCore->>chatCore: Check bypass patterns
+ chatCore->>chatCore: Resolve model & provider
+ chatCore->>Translator: Translate request (source → OpenAI → target)
+ chatCore->>Executor: Get executor for provider
+ Executor->>Executor: Build URL, headers, transform request
+ Executor->>Executor: Refresh credentials if needed
+ Executor->>Provider: HTTP fetch (streaming or non-streaming)
+
+ alt Streaming
+ Provider-->>chatCore: SSE stream
+ chatCore->>chatCore: Pipe through SSE transform stream
+ Note over chatCore: Transform stream translates
each chunk: target → OpenAI → source
+ chatCore-->>Client: Translated SSE stream
+ else Non-streaming
+ Provider-->>chatCore: JSON response
+ chatCore->>Translator: Translate response
+ chatCore-->>Client: Translated JSON
+ end
+
+ alt Error (401, 429, 500...)
+ chatCore->>Executor: Retry with credential refresh
+ chatCore->>chatCore: Account fallback logic
+ end
+```
+
+---
+
+### 4.4 Services (`open-sse/services/`)
+
+Business logic that supports the handlers and executors.
+
+| File | Purpose |
+| -------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| `provider.ts` | **Format detection** (`detectFormat`): analyzes request body structure to identify Claude/OpenAI/Gemini/Antigravity/Responses formats (includes `max_tokens` heuristic for Claude). Also: URL building, header building, thinking config normalization. Supports `openai-compatible-*` and `anthropic-compatible-*` dynamic providers. |
+| `model.ts` | Model string parsing (`claude/model-name` → `{provider: "claude", model: "model-name"}`), alias resolution with collision detection, input sanitization (rejects path traversal/control chars), and model info resolution with async alias getter support. |
+| `accountFallback.ts` | Rate-limit handling: exponential backoff (1s → 2s → 4s → max 2min), account cooldown management, error classification (which errors trigger fallback vs. not). |
+| `tokenRefresh.ts` | OAuth token refresh for **every provider**: Google (Gemini, Antigravity), Claude, Codex, Qwen, Qoder, GitHub (OAuth + Copilot dual-token), Kiro (AWS SSO OIDC + Social Auth). Includes in-flight promise deduplication cache and retry with exponential backoff. |
+| `combo.ts` | **Combo models**: chains of fallback models. If model A fails with a fallback-eligible error, try model B, then C, etc. Returns actual upstream status codes. |
+| `usage.ts` | Fetches quota/usage data from provider APIs (GitHub Copilot quotas, Antigravity model quotas, Codex rate limits, Kiro usage breakdowns, Claude settings). |
+| `accountSelector.ts` | Smart account selection with scoring algorithm: considers priority, health status, round-robin position, and cooldown state to pick the optimal account for each request. |
+| `contextManager.ts` | Request context lifecycle management: creates and tracks per-request context objects with metadata (request ID, timestamps, provider info) for debugging and logging. |
+| `ipFilter.ts` | IP-based access control: supports allowlist and blocklist modes. Validates client IP against configured rules before processing API requests. |
+| `sessionManager.ts` | Session tracking with client fingerprinting: tracks active sessions using hashed client identifiers, monitors request counts, and provides session metrics. |
+| `signatureCache.ts` | Request signature-based deduplication cache: prevents duplicate requests by caching recent request signatures and returning cached responses for identical requests within a time window. |
+| `systemPrompt.ts` | Global system prompt injection: prepends or appends a configurable system prompt to all requests, with per-provider compatibility handling. |
+| `thinkingBudget.ts` | Reasoning token budget management: supports passthrough, auto (strip thinking config), custom (fixed budget), and adaptive (complexity-scaled) modes for controlling thinking/reasoning tokens. |
+| `wildcardRouter.ts` | Wildcard model pattern routing: resolves wildcard patterns (e.g., `*/claude-*`) to concrete provider/model pairs based on availability and priority. |
+
+#### Token Refresh Deduplication
+
+```mermaid
+sequenceDiagram
+ participant R1 as Request 1
+ participant R2 as Request 2
+ participant Cache as refreshPromiseCache
+ participant OAuth as OAuth Provider
+
+ R1->>Cache: getAccessToken("gemini", token)
+ Cache->>Cache: No in-flight promise
+ Cache->>OAuth: Start refresh
+ R2->>Cache: getAccessToken("gemini", token)
+ Cache->>Cache: Found in-flight promise
+ Cache-->>R2: Return existing promise
+ OAuth-->>Cache: New access token
+ Cache-->>R1: New access token
+ Cache-->>R2: Same access token (shared)
+ Cache->>Cache: Delete cache entry
+```
+
+#### Account Fallback State Machine
+
+```mermaid
+stateDiagram-v2
+ [*] --> Active
+ Active --> Error: Request fails (401/429/500)
+ Error --> Cooldown: Apply backoff
+ Cooldown --> Active: Cooldown expires
+ Active --> Active: Request succeeds (reset backoff)
+
+ state Error {
+ [*] --> ClassifyError
+ ClassifyError --> ShouldFallback: Rate limit / Auth / Transient
+ ClassifyError --> NoFallback: 400 Bad Request
+ }
+
+ state Cooldown {
+ [*] --> ExponentialBackoff
+ ExponentialBackoff: Level 0 = 1s
+ ExponentialBackoff: Level 1 = 2s
+ ExponentialBackoff: Level 2 = 4s
+ ExponentialBackoff: Max = 2min
+ }
+```
+
+#### Combo Model Chain
+
+```mermaid
+flowchart LR
+ A["Request with\ncombo model"] --> B["Model A"]
+ B -->|"2xx Success"| C["Return response"]
+ B -->|"429/401/500"| D{"Fallback\neligible?"}
+ D -->|Yes| E["Model B"]
+ D -->|No| F["Return error"]
+ E -->|"2xx Success"| C
+ E -->|"429/401/500"| G{"Fallback\neligible?"}
+ G -->|Yes| H["Model C"]
+ G -->|No| F
+ H -->|"2xx Success"| C
+ H -->|"Fail"| I["All failed →\nReturn last status"]
+```
+
+---
+
+### 4.5 Translator (`open-sse/translator/`)
+
+The **format translation engine** using a self-registering plugin system.
+
+#### ארכיטקטורה
+
+```mermaid
+graph TD
+ subgraph "Request Translation"
+ A["Claude → OpenAI"]
+ B["Gemini → OpenAI"]
+ C["Antigravity → OpenAI"]
+ D["OpenAI Responses → OpenAI"]
+ E["OpenAI → Claude"]
+ F["OpenAI → Gemini"]
+ G["OpenAI → Kiro"]
+ H["OpenAI → Cursor"]
+ end
+
+ subgraph "Response Translation"
+ I["Claude → OpenAI"]
+ J["Gemini → OpenAI"]
+ K["Kiro → OpenAI"]
+ L["Cursor → OpenAI"]
+ M["OpenAI → Claude"]
+ N["OpenAI → Antigravity"]
+ O["OpenAI → Responses"]
+ end
+```
+
+| Directory | Files | Description |
+| ------------ | ------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| `request/` | 8 translators | Convert request bodies between formats. Each file self-registers via `register(from, to, fn)` on import. |
+| `response/` | 7 translators | Convert streaming response chunks between formats. Handles SSE event types, thinking blocks, tool calls. |
+| `helpers/` | 6 helpers | Shared utilities: `claudeHelper` (system prompt extraction, thinking config), `geminiHelper` (parts/contents mapping), `openaiHelper` (format filtering), `toolCallHelper` (ID generation, missing response injection), `maxTokensHelper`, `responsesApiHelper`. |
+| `index.ts` | — | Translation engine: `translateRequest()`, `translateResponse()`, state management, registry. |
+| `formats.ts` | — | Format constants: `OPENAI`, `CLAUDE`, `GEMINI`, `ANTIGRAVITY`, `KIRO`, `CURSOR`, `OPENAI_RESPONSES`. |
+
+#### Key Design: Self-Registering Plugins
+
+```javascript
+// Each translator file calls register() on import:
+import { register } from "../index.js";
+register("claude", "openai", translateClaudeToOpenAI);
+
+// The index.js imports all translator files, triggering registration:
+import "./request/claude-to-openai.js"; // ← self-registers
+```
+
+---
+
+### 4.6 Utils (`open-sse/utils/`)
+
+| File | Purpose |
+| ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
+| `error.ts` | Error response building (OpenAI-compatible format), upstream error parsing, Antigravity retry-time extraction from error messages, SSE error streaming. |
+| `stream.ts` | **SSE Transform Stream** — the core streaming pipeline. Two modes: `TRANSLATE` (full format translation) and `PASSTHROUGH` (normalize + extract usage). Handles chunk buffering, usage estimation, content length tracking. Per-stream encoder/decoder instances avoid shared state. |
+| `streamHelpers.ts` | Low-level SSE utilities: `parseSSELine` (whitespace-tolerant), `hasValuableContent` (filters empty chunks for OpenAI/Claude/Gemini), `fixInvalidId`, `formatSSE` (format-aware SSE serialization with `perf_metrics` cleanup). |
+| `usageTracking.ts` | Token usage extraction from any format (Claude/OpenAI/Gemini/Responses), estimation with separate tool/message char-per-token ratios, buffer addition (2000 tokens safety margin), format-specific field filtering, console logging with ANSI colors. |
+| `requestLogger.ts` | File-based request logging (opt-in via `ENABLE_REQUEST_LOGS=true`). Creates session folders with numbered files: `1_req_client.json` → `7_res_client.txt`. All I/O is async (fire-and-forget). Masks sensitive headers. |
+| `bypassHandler.ts` | Intercepts specific patterns from Claude CLI (title extraction, warmup, count) and returns fake responses without calling any provider. Supports both streaming and non-streaming. Intentionally limited to Claude CLI scope. |
+| `networkProxy.ts` | Resolves outbound proxy URL for a given provider with precedence: provider-specific config → global config → environment variables (`HTTPS_PROXY`/`HTTP_PROXY`/`ALL_PROXY`). Supports `NO_PROXY` exclusions. Caches config for 30s. |
+
+#### SSE Streaming Pipeline
+
+```mermaid
+flowchart TD
+ A["Provider SSE stream"] --> B["TextDecoder\n(per-stream instance)"]
+ B --> C["Buffer lines\n(split on newline)"]
+ C --> D["parseSSELine()\n(trim whitespace, parse JSON)"]
+ D --> E{"Mode?"}
+ E -->|TRANSLATE| F["translateResponse()\ntarget → OpenAI → source"]
+ E -->|PASSTHROUGH| G["fixInvalidId()\nnormalize chunk"]
+ F --> H["hasValuableContent()\nfilter empty chunks"]
+ G --> H
+ H -->|"Has content"| I["extractUsage()\ntrack token counts"]
+ H -->|"Empty"| J["Skip chunk"]
+ I --> K["formatSSE()\nserialize + clean perf_metrics"]
+ K --> L["TextEncoder\n(per-stream instance)"]
+ L --> M["Enqueue to\nclient stream"]
+
+ style A fill:#f9f,stroke:#333
+ style M fill:#9f9,stroke:#333
+```
+
+#### Request Logger Session Structure
+
+```
+logs/
+└── claude_gemini_claude-sonnet_20260208_143045/
+ ├── 1_req_client.json ← Raw client request
+ ├── 2_req_source.json ← After initial conversion
+ ├── 3_req_openai.json ← OpenAI intermediate format
+ ├── 4_req_target.json ← Final target format
+ ├── 5_res_provider.txt ← Provider SSE chunks (streaming)
+ ├── 5_res_provider.json ← Provider response (non-streaming)
+ ├── 6_res_openai.txt ← OpenAI intermediate chunks
+ ├── 7_res_client.txt ← Client-facing SSE chunks
+ └── 6_error.json ← Error details (if any)
+```
+
+---
+
+### 4.7 Application Layer (`src/`)
+
+| Directory | Purpose |
+| ------------- | ---------------------------------------------------------------------- |
+| `src/app/` | Web UI, API routes, Express middleware, OAuth callback handlers |
+| `src/lib/` | Database access (`localDb.ts`, `usageDb.ts`), authentication, shared |
+| `src/mitm/` | Man-in-the-middle proxy utilities for intercepting provider traffic |
+| `src/models/` | Database model definitions |
+| `src/shared/` | Wrappers around open-sse functions (provider, stream, error, etc.) |
+| `src/sse/` | SSE endpoint handlers that wire the open-sse library to Express routes |
+| `src/store/` | Application state management |
+
+#### Notable API Routes
+
+| Route | Methods | Purpose |
+| --------------------------------------------- | --------------- | ------------------------------------------------------------------------------------- |
+| `/api/provider-models` | GET/POST/DELETE | CRUD for custom models per provider |
+| `/api/models/catalog` | GET | Aggregated catalog of all models (chat, embedding, image, custom) grouped by provider |
+| `/api/settings/proxy` | GET/PUT/DELETE | Hierarchical outbound proxy configuration (`global/providers/combos/keys`) |
+| `/api/settings/proxy/test` | POST | Validates proxy connectivity and returns public IP/latency |
+| `/v1/providers/[provider]/chat/completions` | POST | Dedicated per-provider chat completions with model validation |
+| `/v1/providers/[provider]/embeddings` | POST | Dedicated per-provider embeddings with model validation |
+| `/v1/providers/[provider]/images/generations` | POST | Dedicated per-provider image generation with model validation |
+| `/api/settings/ip-filter` | GET/PUT | IP allowlist/blocklist management |
+| `/api/settings/thinking-budget` | GET/PUT | Reasoning token budget configuration (passthrough/auto/custom/adaptive) |
+| `/api/settings/system-prompt` | GET/PUT | Global system prompt injection for all requests |
+| `/api/sessions` | GET | Active session tracking and metrics |
+| `/api/rate-limits` | GET | Per-account rate limit status |
+
+---
+
+## 5. Key Design Patterns
+
+### 5.1 Hub-and-Spoke Translation
+
+All formats translate through **OpenAI format as the hub**. Adding a new provider only requires writing **one pair** of translators (to/from OpenAI), not N pairs.
+
+### 5.2 Executor Strategy Pattern
+
+Each provider has a dedicated executor class inheriting from `BaseExecutor`. The factory in `executors/index.ts` selects the right one at runtime.
+
+### 5.3 Self-Registering Plugin System
+
+Translator modules register themselves on import via `register()`. Adding a new translator is just creating a file and importing it.
+
+### 5.4 Account Fallback with Exponential Backoff
+
+When a provider returns 429/401/500, the system can switch to the next account, applying exponential cooldowns (1s → 2s → 4s → max 2min).
+
+### 5.5 Combo Model Chains
+
+A "combo" groups multiple `provider/model` strings. If the first fails, fallback to the next automatically.
+
+### 5.6 Stateful Streaming Translation
+
+Response translation maintains state across SSE chunks (thinking block tracking, tool call accumulation, content block indexing) via the `initState()` mechanism.
+
+### 5.7 Usage Safety Buffer
+
+A 2000-token buffer is added to reported usage to prevent clients from hitting context window limits due to overhead from system prompts and format translation.
+
+---
+
+## 6. Supported Formats
+
+| Format | Direction | Identifier |
+| ----------------------- | --------------- | ------------------ |
+| OpenAI Chat Completions | source + target | `openai` |
+| OpenAI Responses API | source + target | `openai-responses` |
+| Anthropic Claude | source + target | `claude` |
+| Google Gemini | source + target | `gemini` |
+| Google Gemini CLI | target only | `gemini-cli` |
+| Antigravity | source + target | `antigravity` |
+| AWS Kiro | target only | `kiro` |
+| Cursor | target only | `cursor` |
+
+---
+
+## 7. Supported Providers
+
+| Provider | Auth Method | Executor | Key Notes |
+| ------------------------ | ---------------------- | ----------- | --------------------------------------------- |
+| Anthropic Claude | API key or OAuth | Default | Uses `x-api-key` header |
+| Google Gemini | API key or OAuth | Default | Uses `x-goog-api-key` header |
+| Google Gemini CLI | OAuth | GeminiCLI | Uses `streamGenerateContent` endpoint |
+| Antigravity | OAuth | Antigravity | Multi-URL fallback, custom retry parsing |
+| OpenAI | API key | Default | Standard Bearer auth |
+| Codex | OAuth | Codex | Injects system instructions, manages thinking |
+| GitHub Copilot | OAuth + Copilot token | Github | Dual token, VSCode header mimicking |
+| Kiro (AWS) | AWS SSO OIDC or Social | Kiro | Binary EventStream parsing |
+| Cursor IDE | Checksum auth | Cursor | Protobuf encoding, SHA-256 checksums |
+| Qwen | OAuth | Default | Standard auth |
+| Qoder | OAuth (Basic + Bearer) | Default | Dual auth header |
+| OpenRouter | API key | Default | Standard Bearer auth |
+| GLM, Kimi, MiniMax | API key | Default | Claude-compatible, use `x-api-key` |
+| `openai-compatible-*` | API key | Default | Dynamic: any OpenAI-compatible endpoint |
+| `anthropic-compatible-*` | API key | Default | Dynamic: any Claude-compatible endpoint |
+
+---
+
+## 8. Data Flow Summary
+
+### Streaming Request
+
+```mermaid
+flowchart LR
+ A["Client"] --> B["detectFormat()"]
+ B --> C["translateRequest()\nsource → OpenAI → target"]
+ C --> D["Executor\nbuildUrl + buildHeaders"]
+ D --> E["fetch(providerURL)"]
+ E --> F["createSSEStream()\nTRANSLATE mode"]
+ F --> G["parseSSELine()"]
+ G --> H["translateResponse()\ntarget → OpenAI → source"]
+ H --> I["extractUsage()\n+ addBuffer"]
+ I --> J["formatSSE()"]
+ J --> K["Client receives\ntranslated SSE"]
+ K --> L["logUsage()\nsaveRequestUsage()"]
+```
+
+### Non-Streaming Request
+
+```mermaid
+flowchart LR
+ A["Client"] --> B["detectFormat()"]
+ B --> C["translateRequest()\nsource → OpenAI → target"]
+ C --> D["Executor.execute()"]
+ D --> E["translateResponse()\ntarget → OpenAI → source"]
+ E --> F["Return JSON\nresponse"]
+```
+
+### Bypass Flow (Claude CLI)
+
+```mermaid
+flowchart LR
+ A["Claude CLI request"] --> B{"Match bypass\npattern?"}
+ B -->|"Title/Warmup/Count"| C["Generate fake\nOpenAI response"]
+ B -->|"No match"| D["Normal flow"]
+ C --> E["Translate to\nsource format"]
+ E --> F["Return without\ncalling provider"]
+```
diff --git a/docs/i18n/he/docs/COVERAGE_PLAN.md b/docs/i18n/he/docs/COVERAGE_PLAN.md
new file mode 100644
index 0000000000..ae171638ef
--- /dev/null
+++ b/docs/i18n/he/docs/COVERAGE_PLAN.md
@@ -0,0 +1,170 @@
+# Test Coverage Plan (עברית)
+
+🌐 **Languages:** 🇺🇸 [English](../../../../docs/COVERAGE_PLAN.md) · 🇪🇸 [es](../../es/docs/COVERAGE_PLAN.md) · 🇫🇷 [fr](../../fr/docs/COVERAGE_PLAN.md) · 🇩🇪 [de](../../de/docs/COVERAGE_PLAN.md) · 🇮🇹 [it](../../it/docs/COVERAGE_PLAN.md) · 🇷🇺 [ru](../../ru/docs/COVERAGE_PLAN.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/COVERAGE_PLAN.md) · 🇯🇵 [ja](../../ja/docs/COVERAGE_PLAN.md) · 🇰🇷 [ko](../../ko/docs/COVERAGE_PLAN.md) · 🇸🇦 [ar](../../ar/docs/COVERAGE_PLAN.md) · 🇮🇳 [in](../../in/docs/COVERAGE_PLAN.md) · 🇹🇭 [th](../../th/docs/COVERAGE_PLAN.md) · 🇻🇳 [vi](../../vi/docs/COVERAGE_PLAN.md) · 🇮🇩 [id](../../id/docs/COVERAGE_PLAN.md) · 🇲🇾 [ms](../../ms/docs/COVERAGE_PLAN.md) · 🇳🇱 [nl](../../nl/docs/COVERAGE_PLAN.md) · 🇵🇱 [pl](../../pl/docs/COVERAGE_PLAN.md) · 🇸🇪 [sv](../../sv/docs/COVERAGE_PLAN.md) · 🇳🇴 [no](../../no/docs/COVERAGE_PLAN.md) · 🇩🇰 [da](../../da/docs/COVERAGE_PLAN.md) · 🇫🇮 [fi](../../fi/docs/COVERAGE_PLAN.md) · 🇵🇹 [pt](../../pt/docs/COVERAGE_PLAN.md) · 🇷🇴 [ro](../../ro/docs/COVERAGE_PLAN.md) · 🇭🇺 [hu](../../hu/docs/COVERAGE_PLAN.md) · 🇧🇬 [bg](../../bg/docs/COVERAGE_PLAN.md) · 🇸🇰 [sk](../../sk/docs/COVERAGE_PLAN.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/COVERAGE_PLAN.md) · 🇮🇱 [he](../../he/docs/COVERAGE_PLAN.md) · 🇵🇭 [phi](../../phi/docs/COVERAGE_PLAN.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/COVERAGE_PLAN.md) · 🇨🇿 [cs](../../cs/docs/COVERAGE_PLAN.md)
+
+---
+
+Last updated: 2026-03-28
+
+## Baseline
+
+There are multiple coverage numbers depending on how the report is computed. For planning, only one of them is useful.
+
+| Metric | Scope | Statements / Lines | Branches | Functions | Notes |
+| -------------------- | ----------------------------------------------------- | -----------------: | -------: | --------: | --------------------------------------------------- |
+| Legacy | Old `npm run test:coverage` | 79.42% | 75.15% | 67.94% | Inflated: counts test files and excludes `open-sse` |
+| Diagnostic | Source-only, excluding tests and excluding `open-sse` | 68.16% | 63.55% | 64.06% | Useful only to isolate `src/**` |
+| Recommended baseline | Source-only, excluding tests and including `open-sse` | 56.95% | 66.05% | 57.80% | This is the project-wide baseline to improve |
+
+The recommended baseline is the number to optimize against.
+
+## Rules
+
+- Coverage targets apply to source files, not to `tests/**`.
+- `open-sse/**` is part of the product and must remain in scope.
+- New code should not reduce coverage in touched areas.
+- Prefer testing behavior and branch outcomes over implementation details.
+- Prefer temp SQLite databases and small fixtures over broad mocks for `src/lib/db/**`.
+
+## Current command set
+
+- `npm run test:coverage`
+ - Main source coverage gate for the unit test suite
+ - Generates `text-summary`, `html`, `json-summary`, and `lcov`
+- `npm run coverage:report`
+ - Detailed file-by-file report from the latest run
+- `npm run test:coverage:legacy`
+ - Historical comparison only
+
+## Milestones
+
+| Phase | Target | Focus |
+| ------- | ---------------------: | ------------------------------------------------- |
+| Phase 1 | 60% statements / lines | Quick wins and low-risk utility coverage |
+| Phase 2 | 65% statements / lines | DB and route foundations |
+| Phase 3 | 70% statements / lines | Provider validation and usage analytics |
+| Phase 4 | 75% statements / lines | `open-sse` translators and helpers |
+| Phase 5 | 80% statements / lines | `open-sse` handlers and executor branches |
+| Phase 6 | 85% statements / lines | Harder edge cases, branch debt, regression suites |
+| Phase 7 | 90% statements / lines | Final sweep, gap closure, strict ratchet |
+
+Branches and functions should ratchet upward with each phase, but the primary hard target is statements / lines.
+
+## Priority hotspots
+
+These files or areas offer the best return for the next phases:
+
+1. `open-sse/handlers`
+ - `chatCore.ts` at 7.57%
+ - Overall directory at 29.07%
+2. `open-sse/translator/request`
+ - Overall directory at 36.39%
+ - Many translators are still near single-digit coverage
+3. `open-sse/translator/response`
+ - Overall directory at 8.07%
+4. `open-sse/executors`
+ - Overall directory at 36.62%
+5. `src/lib/db`
+ - `models.ts` at 20.66%
+ - `registeredKeys.ts` at 34.46%
+ - `modelComboMappings.ts` at 36.25%
+ - `settings.ts` at 46.40%
+ - `webhooks.ts` at 33.33%
+6. `src/lib/usage`
+ - `usageHistory.ts` at 21.12%
+ - `usageStats.ts` at 9.56%
+ - `costCalculator.ts` at 30.00%
+7. `src/lib/providers`
+ - `validation.ts` at 41.16%
+8. Low-risk utility and API files for early gains
+ - `src/shared/utils/upstreamError.ts`
+ - `src/shared/utils/apiAuth.ts`
+ - `src/lib/api/errorResponse.ts`
+ - `src/app/api/settings/require-login/route.ts`
+ - `src/app/api/providers/[id]/models/route.ts`
+
+## Execution checklist
+
+### Phase 1: 56.95% -> 60%
+
+- [x] Fix coverage metric so it reflects source code instead of test files
+- [x] Keep a legacy coverage script for comparison
+- [x] Record the baseline and hotspots in-repo
+- [ ] Add focused tests for low-risk utilities:
+ - `src/shared/utils/upstreamError.ts`
+ - `src/shared/utils/fetchTimeout.ts`
+ - `src/lib/api/errorResponse.ts`
+ - `src/shared/utils/apiAuth.ts`
+ - `src/lib/display/names.ts`
+- [ ] Add route tests for:
+ - `src/app/api/settings/require-login/route.ts`
+ - `src/app/api/providers/[id]/models/route.ts`
+
+### Phase 2: 60% -> 65%
+
+- [ ] Add DB-backed tests for:
+ - `src/lib/db/modelComboMappings.ts`
+ - `src/lib/db/settings.ts`
+ - `src/lib/db/registeredKeys.ts`
+- [ ] Cover branch behavior in:
+ - `src/lib/providers/validation.ts`
+ - `src/app/api/v1/embeddings/route.ts`
+ - `src/app/api/v1/moderations/route.ts`
+
+### Phase 3: 65% -> 70%
+
+- [ ] Add usage analytics tests for:
+ - `src/lib/usage/usageHistory.ts`
+ - `src/lib/usage/usageStats.ts`
+ - `src/lib/usage/costCalculator.ts`
+- [ ] Expand route coverage for proxy management and settings branches
+
+### Phase 4: 70% -> 75%
+
+- [ ] Cover translator helpers and central translation paths:
+ - `open-sse/translator/index.ts`
+ - `open-sse/translator/helpers/*`
+ - `open-sse/translator/request/*`
+ - `open-sse/translator/response/*`
+
+### Phase 5: 75% -> 80%
+
+- [ ] Add handler-level tests for:
+ - `open-sse/handlers/chatCore.ts`
+ - `open-sse/handlers/responsesHandler.js`
+ - `open-sse/handlers/imageGeneration.js`
+ - `open-sse/handlers/embeddings.js`
+- [ ] Add executor branch coverage for provider-specific auth, retries, and endpoint overrides
+
+### Phase 6: 80% -> 85%
+
+- [ ] Merge more edge-case suites into the main coverage path
+- [ ] Increase function coverage for DB modules with weak constructor/helper coverage
+- [ ] Close branch gaps in `settings.ts`, `registeredKeys.ts`, `validation.ts`, and translator helpers
+
+### Phase 7: 85% -> 90%
+
+- [ ] Treat the remaining low-coverage files as blockers
+- [ ] Add regression tests for every uncovered production bug fixed during the push to 90%
+- [ ] Raise the coverage gate in CI only after the local baseline is stable for at least two consecutive runs
+
+## Ratchet policy
+
+Update `npm run test:coverage` thresholds only after the project actually exceeds the next milestone with a comfortable buffer.
+
+Recommended ratchet sequence:
+
+1. 55/60/55
+2. 60/62/58
+3. 65/64/62
+4. 70/66/66
+5. 75/70/72
+6. 80/75/78
+7. 85/80/84
+8. 90/85/88
+
+Order is `statements-lines / branches / functions`.
+
+## Known gap
+
+The current coverage command measures the main Node unit suite and includes source reached from it, including `open-sse`. It does not yet merge Vitest coverage into a single unified report. That merge is worth doing later, but it is not a blocker for starting the 60% -> 80% climb.
diff --git a/docs/i18n/he/docs/FEATURES.md b/docs/i18n/he/docs/FEATURES.md
index 3eeee0d0b3..7049741023 100644
--- a/docs/i18n/he/docs/FEATURES.md
+++ b/docs/i18n/he/docs/FEATURES.md
@@ -1,6 +1,6 @@
# OmniRoute — Dashboard Features Gallery (עברית)
-🌐 **Languages:** 🇺🇸 [English](../../../../docs/FEATURES.md) · 🇪🇸 [es](../../es/docs/FEATURES.md) · 🇫🇷 [fr](../../fr/docs/FEATURES.md) · 🇩🇪 [de](../../de/docs/FEATURES.md) · 🇮🇹 [it](../../it/docs/FEATURES.md) · 🇷🇺 [ru](../../ru/docs/FEATURES.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/FEATURES.md) · 🇯🇵 [ja](../../ja/docs/FEATURES.md) · 🇰🇷 [ko](../../ko/docs/FEATURES.md) · 🇸🇦 [ar](../../ar/docs/FEATURES.md) · 🇮🇳 [in](../../in/docs/FEATURES.md) · 🇹🇭 [th](../../th/docs/FEATURES.md) · 🇻🇳 [vi](../../vi/docs/FEATURES.md) · 🇮🇩 [id](../../id/docs/FEATURES.md) · 🇲🇾 [ms](../../ms/docs/FEATURES.md) · 🇳🇱 [nl](../../nl/docs/FEATURES.md) · 🇵🇱 [pl](../../pl/docs/FEATURES.md) · 🇸🇪 [sv](../../sv/docs/FEATURES.md) · 🇳🇴 [no](../../no/docs/FEATURES.md) · 🇩🇰 [da](../../da/docs/FEATURES.md) · 🇫🇮 [fi](../../fi/docs/FEATURES.md) · 🇵🇹 [pt](../../pt/docs/FEATURES.md) · 🇷🇴 [ro](../../ro/docs/FEATURES.md) · 🇭🇺 [hu](../../hu/docs/FEATURES.md) · 🇧🇬 [bg](../../bg/docs/FEATURES.md) · 🇸🇰 [sk](../../sk/docs/FEATURES.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/FEATURES.md) · 🇮🇱 [he](../../he/docs/FEATURES.md) · 🇵🇭 [phi](../../phi/docs/FEATURES.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/FEATURES.md)
+🌐 **Languages:** 🇺🇸 [English](../../../../docs/FEATURES.md) · 🇪🇸 [es](../../es/docs/FEATURES.md) · 🇫🇷 [fr](../../fr/docs/FEATURES.md) · 🇩🇪 [de](../../de/docs/FEATURES.md) · 🇮🇹 [it](../../it/docs/FEATURES.md) · 🇷🇺 [ru](../../ru/docs/FEATURES.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/FEATURES.md) · 🇯🇵 [ja](../../ja/docs/FEATURES.md) · 🇰🇷 [ko](../../ko/docs/FEATURES.md) · 🇸🇦 [ar](../../ar/docs/FEATURES.md) · 🇮🇳 [in](../../in/docs/FEATURES.md) · 🇹🇭 [th](../../th/docs/FEATURES.md) · 🇻🇳 [vi](../../vi/docs/FEATURES.md) · 🇮🇩 [id](../../id/docs/FEATURES.md) · 🇲🇾 [ms](../../ms/docs/FEATURES.md) · 🇳🇱 [nl](../../nl/docs/FEATURES.md) · 🇵🇱 [pl](../../pl/docs/FEATURES.md) · 🇸🇪 [sv](../../sv/docs/FEATURES.md) · 🇳🇴 [no](../../no/docs/FEATURES.md) · 🇩🇰 [da](../../da/docs/FEATURES.md) · 🇫🇮 [fi](../../fi/docs/FEATURES.md) · 🇵🇹 [pt](../../pt/docs/FEATURES.md) · 🇷🇴 [ro](../../ro/docs/FEATURES.md) · 🇭🇺 [hu](../../hu/docs/FEATURES.md) · 🇧🇬 [bg](../../bg/docs/FEATURES.md) · 🇸🇰 [sk](../../sk/docs/FEATURES.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/FEATURES.md) · 🇮🇱 [he](../../he/docs/FEATURES.md) · 🇵🇭 [phi](../../phi/docs/FEATURES.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/FEATURES.md) · 🇨🇿 [cs](../../cs/docs/FEATURES.md)
---
@@ -10,7 +10,7 @@ Visual guide to every section of the OmniRoute dashboard.
## 🔌 Providers
-Manage AI provider connections: OAuth providers (Claude Code, Codex, Gemini CLI), API key providers (Groq, DeepSeek, OpenRouter), and free providers (iFlow, Qwen, Kiro). Kiro accounts include credit balance tracking — remaining credits, total allowance, and renewal date visible in Dashboard → Usage.
+Manage AI provider connections: OAuth providers (Claude Code, Codex, Gemini CLI), API key providers (Groq, DeepSeek, OpenRouter), and free providers (Qoder, Qwen, Kiro). Kiro accounts include credit balance tracking — remaining credits, total allowance, and renewal date visible in Dashboard → Usage.

diff --git a/docs/i18n/he/docs/MCP-SERVER.md b/docs/i18n/he/docs/MCP-SERVER.md
new file mode 100644
index 0000000000..58c3b31c6a
--- /dev/null
+++ b/docs/i18n/he/docs/MCP-SERVER.md
@@ -0,0 +1,87 @@
+# OmniRoute MCP Server Documentation (עברית)
+
+🌐 **Languages:** 🇺🇸 [English](../../../../docs/MCP-SERVER.md) · 🇪🇸 [es](../../es/docs/MCP-SERVER.md) · 🇫🇷 [fr](../../fr/docs/MCP-SERVER.md) · 🇩🇪 [de](../../de/docs/MCP-SERVER.md) · 🇮🇹 [it](../../it/docs/MCP-SERVER.md) · 🇷🇺 [ru](../../ru/docs/MCP-SERVER.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/MCP-SERVER.md) · 🇯🇵 [ja](../../ja/docs/MCP-SERVER.md) · 🇰🇷 [ko](../../ko/docs/MCP-SERVER.md) · 🇸🇦 [ar](../../ar/docs/MCP-SERVER.md) · 🇮🇳 [in](../../in/docs/MCP-SERVER.md) · 🇹🇭 [th](../../th/docs/MCP-SERVER.md) · 🇻🇳 [vi](../../vi/docs/MCP-SERVER.md) · 🇮🇩 [id](../../id/docs/MCP-SERVER.md) · 🇲🇾 [ms](../../ms/docs/MCP-SERVER.md) · 🇳🇱 [nl](../../nl/docs/MCP-SERVER.md) · 🇵🇱 [pl](../../pl/docs/MCP-SERVER.md) · 🇸🇪 [sv](../../sv/docs/MCP-SERVER.md) · 🇳🇴 [no](../../no/docs/MCP-SERVER.md) · 🇩🇰 [da](../../da/docs/MCP-SERVER.md) · 🇫🇮 [fi](../../fi/docs/MCP-SERVER.md) · 🇵🇹 [pt](../../pt/docs/MCP-SERVER.md) · 🇷🇴 [ro](../../ro/docs/MCP-SERVER.md) · 🇭🇺 [hu](../../hu/docs/MCP-SERVER.md) · 🇧🇬 [bg](../../bg/docs/MCP-SERVER.md) · 🇸🇰 [sk](../../sk/docs/MCP-SERVER.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/MCP-SERVER.md) · 🇮🇱 [he](../../he/docs/MCP-SERVER.md) · 🇵🇭 [phi](../../phi/docs/MCP-SERVER.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/MCP-SERVER.md) · 🇨🇿 [cs](../../cs/docs/MCP-SERVER.md)
+
+---
+
+> Model Context Protocol server with 16 intelligent tools
+
+## התקנה
+
+OmniRoute MCP is built-in. Start it with:
+
+```bash
+omniroute --mcp
+```
+
+Or via the open-sse transport:
+
+```bash
+# HTTP streamable transport (port 20130)
+omniroute --dev # MCP auto-starts on /mcp endpoint
+```
+
+## IDE Configuration
+
+See [IDE Configs](integrations/ide-configs.md) for Antigravity, Cursor, Copilot, and Claude Desktop setup.
+
+---
+
+## Essential Tools (8)
+
+| Tool | Description |
+| :------------------------------ | :--------------------------------------- |
+| `omniroute_get_health` | Gateway health, circuit breakers, uptime |
+| `omniroute_list_combos` | All configured combos with models |
+| `omniroute_get_combo_metrics` | Performance metrics for a specific combo |
+| `omniroute_switch_combo` | Switch active combo by ID/name |
+| `omniroute_check_quota` | Quota status per provider or all |
+| `omniroute_route_request` | Send a chat completion through OmniRoute |
+| `omniroute_cost_report` | Cost analytics for a time period |
+| `omniroute_list_models_catalog` | Full model catalog with capabilities |
+
+## Advanced Tools (8)
+
+| Tool | Description |
+| :--------------------------------- | :---------------------------------------------------------- |
+| `omniroute_simulate_route` | Dry-run routing simulation with fallback tree |
+| `omniroute_set_budget_guard` | Session budget with degrade/block/alert actions |
+| `omniroute_set_resilience_profile` | Apply conservative/balanced/aggressive preset |
+| `omniroute_test_combo` | Live-test all models in a combo via a real upstream request |
+| `omniroute_get_provider_metrics` | Detailed metrics for one provider |
+| `omniroute_best_combo_for_task` | Task-fitness recommendation with alternatives |
+| `omniroute_explain_route` | Explain a past routing decision |
+| `omniroute_get_session_snapshot` | Full session state: costs, tokens, errors |
+
+## Authentication
+
+MCP tools are authenticated via API key scopes. Each tool requires specific scopes:
+
+| Scope | Tools |
+| :------------- | :----------------------------------------------- |
+| `read:health` | get_health, get_provider_metrics |
+| `read:combos` | list_combos, get_combo_metrics |
+| `write:combos` | switch_combo |
+| `read:quota` | check_quota |
+| `write:route` | route_request, simulate_route, test_combo |
+| `read:usage` | cost_report, get_session_snapshot, explain_route |
+| `write:config` | set_budget_guard, set_resilience_profile |
+| `read:models` | list_models_catalog, best_combo_for_task |
+
+## Audit Logging
+
+Every tool call is logged to `mcp_tool_audit` with:
+
+- Tool name, arguments, result
+- Duration (ms), success/failure
+- API key hash, timestamp
+
+## Files
+
+| File | Purpose |
+| :------------------------------------------- | :------------------------------------------ |
+| `open-sse/mcp-server/server.ts` | MCP server creation + 16 tool registrations |
+| `open-sse/mcp-server/transport.ts` | Stdio + HTTP transport |
+| `open-sse/mcp-server/auth.ts` | API key + scope validation |
+| `open-sse/mcp-server/audit.ts` | Tool call audit logging |
+| `open-sse/mcp-server/tools/advancedTools.ts` | 8 advanced tool handlers |
diff --git a/docs/i18n/he/docs/RELEASE_CHECKLIST.md b/docs/i18n/he/docs/RELEASE_CHECKLIST.md
new file mode 100644
index 0000000000..5c707d543c
--- /dev/null
+++ b/docs/i18n/he/docs/RELEASE_CHECKLIST.md
@@ -0,0 +1,37 @@
+# Release Checklist (עברית)
+
+🌐 **Languages:** 🇺🇸 [English](../../../../docs/RELEASE_CHECKLIST.md) · 🇪🇸 [es](../../es/docs/RELEASE_CHECKLIST.md) · 🇫🇷 [fr](../../fr/docs/RELEASE_CHECKLIST.md) · 🇩🇪 [de](../../de/docs/RELEASE_CHECKLIST.md) · 🇮🇹 [it](../../it/docs/RELEASE_CHECKLIST.md) · 🇷🇺 [ru](../../ru/docs/RELEASE_CHECKLIST.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/RELEASE_CHECKLIST.md) · 🇯🇵 [ja](../../ja/docs/RELEASE_CHECKLIST.md) · 🇰🇷 [ko](../../ko/docs/RELEASE_CHECKLIST.md) · 🇸🇦 [ar](../../ar/docs/RELEASE_CHECKLIST.md) · 🇮🇳 [in](../../in/docs/RELEASE_CHECKLIST.md) · 🇹🇭 [th](../../th/docs/RELEASE_CHECKLIST.md) · 🇻🇳 [vi](../../vi/docs/RELEASE_CHECKLIST.md) · 🇮🇩 [id](../../id/docs/RELEASE_CHECKLIST.md) · 🇲🇾 [ms](../../ms/docs/RELEASE_CHECKLIST.md) · 🇳🇱 [nl](../../nl/docs/RELEASE_CHECKLIST.md) · 🇵🇱 [pl](../../pl/docs/RELEASE_CHECKLIST.md) · 🇸🇪 [sv](../../sv/docs/RELEASE_CHECKLIST.md) · 🇳🇴 [no](../../no/docs/RELEASE_CHECKLIST.md) · 🇩🇰 [da](../../da/docs/RELEASE_CHECKLIST.md) · 🇫🇮 [fi](../../fi/docs/RELEASE_CHECKLIST.md) · 🇵🇹 [pt](../../pt/docs/RELEASE_CHECKLIST.md) · 🇷🇴 [ro](../../ro/docs/RELEASE_CHECKLIST.md) · 🇭🇺 [hu](../../hu/docs/RELEASE_CHECKLIST.md) · 🇧🇬 [bg](../../bg/docs/RELEASE_CHECKLIST.md) · 🇸🇰 [sk](../../sk/docs/RELEASE_CHECKLIST.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/RELEASE_CHECKLIST.md) · 🇮🇱 [he](../../he/docs/RELEASE_CHECKLIST.md) · 🇵🇭 [phi](../../phi/docs/RELEASE_CHECKLIST.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/RELEASE_CHECKLIST.md) · 🇨🇿 [cs](../../cs/docs/RELEASE_CHECKLIST.md)
+
+---
+
+Use this checklist before tagging or publishing a new OmniRoute release.
+
+## Version and Changelog
+
+1. Bump `package.json` version (`x.y.z`) in the release branch.
+2. Move release notes from `## [Unreleased]` in `CHANGELOG.md` to a dated section:
+ - `## [x.y.z] — YYYY-MM-DD`
+3. Keep `## [Unreleased]` as the first changelog section for upcoming work.
+4. Ensure the latest semver section in `CHANGELOG.md` equals `package.json` version.
+
+## API Docs
+
+1. Update `docs/openapi.yaml`:
+ - `info.version` must equal `package.json` version.
+2. Validate endpoint examples if API contracts changed.
+
+## Runtime Docs
+
+1. Review `docs/ARCHITECTURE.md` for storage/runtime drift.
+2. Review `docs/TROUBLESHOOTING.md` for env var and operational drift.
+3. Update localized docs if source docs changed significantly.
+
+## Automated Check
+
+Run the sync guard locally before opening PR:
+
+```bash
+npm run check:docs-sync
+```
+
+CI also runs this check in `.github/workflows/ci.yml` (lint job).
diff --git a/docs/i18n/he/docs/TROUBLESHOOTING.md b/docs/i18n/he/docs/TROUBLESHOOTING.md
new file mode 100644
index 0000000000..2476cbfa84
--- /dev/null
+++ b/docs/i18n/he/docs/TROUBLESHOOTING.md
@@ -0,0 +1,256 @@
+# Troubleshooting (עברית)
+
+🌐 **Languages:** 🇺🇸 [English](../../../../docs/TROUBLESHOOTING.md) · 🇪🇸 [es](../../es/docs/TROUBLESHOOTING.md) · 🇫🇷 [fr](../../fr/docs/TROUBLESHOOTING.md) · 🇩🇪 [de](../../de/docs/TROUBLESHOOTING.md) · 🇮🇹 [it](../../it/docs/TROUBLESHOOTING.md) · 🇷🇺 [ru](../../ru/docs/TROUBLESHOOTING.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/TROUBLESHOOTING.md) · 🇯🇵 [ja](../../ja/docs/TROUBLESHOOTING.md) · 🇰🇷 [ko](../../ko/docs/TROUBLESHOOTING.md) · 🇸🇦 [ar](../../ar/docs/TROUBLESHOOTING.md) · 🇮🇳 [in](../../in/docs/TROUBLESHOOTING.md) · 🇹🇭 [th](../../th/docs/TROUBLESHOOTING.md) · 🇻🇳 [vi](../../vi/docs/TROUBLESHOOTING.md) · 🇮🇩 [id](../../id/docs/TROUBLESHOOTING.md) · 🇲🇾 [ms](../../ms/docs/TROUBLESHOOTING.md) · 🇳🇱 [nl](../../nl/docs/TROUBLESHOOTING.md) · 🇵🇱 [pl](../../pl/docs/TROUBLESHOOTING.md) · 🇸🇪 [sv](../../sv/docs/TROUBLESHOOTING.md) · 🇳🇴 [no](../../no/docs/TROUBLESHOOTING.md) · 🇩🇰 [da](../../da/docs/TROUBLESHOOTING.md) · 🇫🇮 [fi](../../fi/docs/TROUBLESHOOTING.md) · 🇵🇹 [pt](../../pt/docs/TROUBLESHOOTING.md) · 🇷🇴 [ro](../../ro/docs/TROUBLESHOOTING.md) · 🇭🇺 [hu](../../hu/docs/TROUBLESHOOTING.md) · 🇧🇬 [bg](../../bg/docs/TROUBLESHOOTING.md) · 🇸🇰 [sk](../../sk/docs/TROUBLESHOOTING.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/TROUBLESHOOTING.md) · 🇮🇱 [he](../../he/docs/TROUBLESHOOTING.md) · 🇵🇭 [phi](../../phi/docs/TROUBLESHOOTING.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/TROUBLESHOOTING.md) · 🇨🇿 [cs](../../cs/docs/TROUBLESHOOTING.md)
+
+---
+
+Common problems and solutions for OmniRoute.
+
+---
+
+## Quick Fixes
+
+| Problem | Solution |
+| ----------------------------- | ------------------------------------------------------------------ |
+| First login not working | Set `INITIAL_PASSWORD` in `.env` (no hardcoded default) |
+| Dashboard opens on wrong port | Set `PORT=20128` and `NEXT_PUBLIC_BASE_URL=http://localhost:20128` |
+| No request logs under `logs/` | Set `ENABLE_REQUEST_LOGS=true` |
+| EACCES: permission denied | Set `DATA_DIR=/path/to/writable/dir` to override `~/.omniroute` |
+| Routing strategy not saving | Update to v1.4.11+ (Zod schema fix for settings persistence) |
+
+---
+
+## Provider Issues
+
+### "Language model did not provide messages"
+
+**Cause:** Provider quota exhausted.
+
+**Fix:**
+
+1. Check dashboard quota tracker
+2. Use a combo with fallback tiers
+3. Switch to cheaper/free tier
+
+### Rate Limiting
+
+**Cause:** Subscription quota exhausted.
+
+**Fix:**
+
+- Add fallback: `cc/claude-opus-4-6 → glm/glm-4.7 → if/kimi-k2-thinking`
+- Use GLM/MiniMax as cheap backup
+
+### OAuth Token Expired
+
+OmniRoute auto-refreshes tokens. If issues persist:
+
+1. Dashboard → Provider → Reconnect
+2. Delete and re-add the provider connection
+
+---
+
+## Cloud Issues
+
+### Cloud Sync Errors
+
+1. Verify `BASE_URL` points to your running instance (e.g., `http://localhost:20128`)
+2. Verify `CLOUD_URL` points to your cloud endpoint (e.g., `https://omniroute.dev`)
+3. Keep `NEXT_PUBLIC_*` values aligned with server-side values
+
+### Cloud `stream=false` Returns 500
+
+**Symptom:** `Unexpected token 'd'...` on cloud endpoint for non-streaming calls.
+
+**Cause:** Upstream returns SSE payload while client expects JSON.
+
+**Workaround:** Use `stream=true` for cloud direct calls. Local runtime includes SSE→JSON fallback.
+
+### Cloud Says Connected but "Invalid API key"
+
+1. Create a fresh key from local dashboard (`/api/keys`)
+2. Run cloud sync: Enable Cloud → Sync Now
+3. Old/non-synced keys can still return `401` on cloud
+
+---
+
+## Docker Issues
+
+### CLI Tool Shows Not Installed
+
+1. Check runtime fields: `curl http://localhost:20128/api/cli-tools/runtime/codex | jq`
+2. For portable mode: use image target `runner-cli` (bundled CLIs)
+3. For host mount mode: set `CLI_EXTRA_PATHS` and mount host bin directory as read-only
+4. If `installed=true` and `runnable=false`: binary was found but failed healthcheck
+
+### Quick Runtime Validation
+
+```bash
+curl -s http://localhost:20128/api/cli-tools/codex-settings | jq '{installed,runnable,commandPath,runtimeMode,reason}'
+curl -s http://localhost:20128/api/cli-tools/claude-settings | jq '{installed,runnable,commandPath,runtimeMode,reason}'
+curl -s http://localhost:20128/api/cli-tools/openclaw-settings | jq '{installed,runnable,commandPath,runtimeMode,reason}'
+```
+
+---
+
+## Cost Issues
+
+### High Costs
+
+1. Check usage stats in Dashboard → Usage
+2. Switch primary model to GLM/MiniMax
+3. Use free tier (Gemini CLI, Qoder) for non-critical tasks
+4. Set cost budgets per API key: Dashboard → API Keys → Budget
+
+---
+
+## Debugging
+
+### Enable Request Logs
+
+Set `ENABLE_REQUEST_LOGS=true` in your `.env` file. Logs appear under `logs/` directory.
+
+### Check Provider Health
+
+```bash
+# Health dashboard
+http://localhost:20128/dashboard/health
+
+# API health check
+curl http://localhost:20128/api/monitoring/health
+```
+
+### Runtime Storage
+
+- Main state: `${DATA_DIR}/storage.sqlite` (providers, combos, aliases, keys, settings)
+- Usage: SQLite tables in `storage.sqlite` (`usage_history`, `call_logs`, `proxy_logs`) + optional `${DATA_DIR}/log.txt` and `${DATA_DIR}/call_logs/`
+- Request logs: `/logs/...` (when `ENABLE_REQUEST_LOGS=true`)
+
+---
+
+## Circuit Breaker Issues
+
+### Provider stuck in OPEN state
+
+When a provider's circuit breaker is OPEN, requests are blocked until the cooldown expires.
+
+**Fix:**
+
+1. Go to **Dashboard → Settings → Resilience**
+2. Check the circuit breaker card for the affected provider
+3. Click **Reset All** to clear all breakers, or wait for the cooldown to expire
+4. Verify the provider is actually available before resetting
+
+### Provider keeps tripping the circuit breaker
+
+If a provider repeatedly enters OPEN state:
+
+1. Check **Dashboard → Health → Provider Health** for the failure pattern
+2. Go to **Settings → Resilience → Provider Profiles** and increase the failure threshold
+3. Check if the provider has changed API limits or requires re-authentication
+4. Review latency telemetry — high latency may cause timeout-based failures
+
+---
+
+## Audio Transcription Issues
+
+### "Unsupported model" error
+
+- Ensure you're using the correct prefix: `deepgram/nova-3` or `assemblyai/best`
+- Verify the provider is connected in **Dashboard → Providers**
+
+### Transcription returns empty or fails
+
+- Check supported audio formats: `mp3`, `wav`, `m4a`, `flac`, `ogg`, `webm`
+- Verify file size is within provider limits (typically < 25MB)
+- Check provider API key validity in the provider card
+
+---
+
+## Translator Debugging
+
+Use **Dashboard → Translator** to debug format translation issues:
+
+| Mode | When to Use |
+| ---------------- | -------------------------------------------------------------------------------------------- |
+| **Playground** | Compare input/output formats side by side — paste a failing request to see how it translates |
+| **Chat Tester** | Send live messages and inspect the full request/response payload including headers |
+| **Test Bench** | Run batch tests across format combinations to find which translations are broken |
+| **Live Monitor** | Watch real-time request flow to catch intermittent translation issues |
+
+### Common format issues
+
+- **Thinking tags not appearing** — Check if the target provider supports thinking and the thinking budget setting
+- **Tool calls dropping** — Some format translations may strip unsupported fields; verify in Playground mode
+- **System prompt missing** — Claude and Gemini handle system prompts differently; check translation output
+- **SDK returns raw string instead of object** — Fixed in v1.1.0: response sanitizer now strips non-standard fields (`x_groq`, `usage_breakdown`, etc.) that cause OpenAI SDK Pydantic validation failures
+- **GLM/ERNIE rejects `system` role** — Fixed in v1.1.0: role normalizer automatically merges system messages into user messages for incompatible models
+- **`developer` role not recognized** — Fixed in v1.1.0: automatically converted to `system` for non-OpenAI providers
+- **`json_schema` not working with Gemini** — Fixed in v1.1.0: `response_format` is now converted to Gemini's `responseMimeType` + `responseSchema`
+
+---
+
+## Resilience Settings
+
+### Auto rate-limit not triggering
+
+- Auto rate-limit only applies to API key providers (not OAuth/subscription)
+- Verify **Settings → Resilience → Provider Profiles** has auto-rate-limit enabled
+- Check if the provider returns `429` status codes or `Retry-After` headers
+
+### Tuning exponential backoff
+
+Provider profiles support these settings:
+
+- **Base delay** — Initial wait time after first failure (default: 1s)
+- **Max delay** — Maximum wait time cap (default: 30s)
+- **Multiplier** — How much to increase delay per consecutive failure (default: 2x)
+
+### Anti-thundering herd
+
+When many concurrent requests hit a rate-limited provider, OmniRoute uses mutex + auto rate-limiting to serialize requests and prevent cascading failures. This is automatic for API key providers.
+
+---
+
+## Optional RAG / LLM failure taxonomy (16 problems)
+
+Some OmniRoute users place the gateway in front of RAG or agent stacks. In those setups it is common to see a strange pattern: OmniRoute looks healthy (providers up, routing profiles ok, no rate limit alerts) but the final answer is still wrong.
+
+In practice these incidents usually come from the downstream RAG pipeline, not from the gateway itself.
+
+If you want a shared vocabulary to describe those failures you can use the WFGY ProblemMap, an external MIT license text resource that defines sixteen recurring RAG / LLM failure patterns. At a high level it covers:
+
+- retrieval drift and broken context boundaries
+- empty or stale indexes and vector stores
+- embedding versus semantic mismatch
+- prompt assembly and context window issues
+- logic collapse and overconfident answers
+- long chain and agent coordination failures
+- multi agent memory and role drift
+- deployment and bootstrap ordering problems
+
+The idea is simple:
+
+1. When you investigate a bad response, capture:
+ - user task and request
+ - route or provider combo in OmniRoute
+ - any RAG context used downstream (retrieved documents, tool calls, etc)
+2. Map the incident to one or two WFGY ProblemMap numbers (`No.1` … `No.16`).
+3. Store the number in your own dashboard, runbook, or incident tracker next to the OmniRoute logs.
+4. Use the corresponding WFGY page to decide whether you need to change your RAG stack, retriever, or routing strategy.
+
+Full text and concrete recipes live here (MIT license, text only):
+
+[WFGY ProblemMap README](https://github.com/onestardao/WFGY/blob/main/ProblemMap/README.md)
+
+You can ignore this section if you do not run RAG or agent pipelines behind OmniRoute.
+
+---
+
+## Still Stuck?
+
+- **GitHub Issues**: [github.com/diegosouzapw/OmniRoute/issues](https://github.com/diegosouzapw/OmniRoute/issues)
+- **Architecture**: See [`docs/ARCHITECTURE.md`](ARCHITECTURE.md) for internal details
+- **API Reference**: See [`docs/API_REFERENCE.md`](API_REFERENCE.md) for all endpoints
+- **Health Dashboard**: Check **Dashboard → Health** for real-time system status
+- **Translator**: Use **Dashboard → Translator** to debug format issues
diff --git a/docs/i18n/he/USER_GUIDE.md b/docs/i18n/he/docs/USER_GUIDE.md
similarity index 82%
rename from docs/i18n/he/USER_GUIDE.md
rename to docs/i18n/he/docs/USER_GUIDE.md
index ebe3d7f53f..7a8885006f 100644
--- a/docs/i18n/he/USER_GUIDE.md
+++ b/docs/i18n/he/docs/USER_GUIDE.md
@@ -1,8 +1,6 @@
# User Guide (עברית)
-🌐 **Languages:** 🇺🇸 [English](../../USER_GUIDE.md) · 🇧🇷 [pt-BR](../pt-BR/USER_GUIDE.md) · 🇪🇸 [es](../es/USER_GUIDE.md) · 🇫🇷 [fr](../fr/USER_GUIDE.md) · 🇩🇪 [de](../de/USER_GUIDE.md) · 🇮🇹 [it](../it/USER_GUIDE.md) · 🇷🇺 [ru](../ru/USER_GUIDE.md) · 🇨🇳 [zh-CN](../zh-CN/USER_GUIDE.md) · 🇯🇵 [ja](../ja/USER_GUIDE.md) · 🇰🇷 [ko](../ko/USER_GUIDE.md) · 🇸🇦 [ar](../ar/USER_GUIDE.md) · 🇮🇳 [in](../in/USER_GUIDE.md) · 🇹🇭 [th](../th/USER_GUIDE.md) · 🇻🇳 [vi](../vi/USER_GUIDE.md) · 🇮🇩 [id](../id/USER_GUIDE.md) · 🇲🇾 [ms](../ms/USER_GUIDE.md) · 🇳🇱 [nl](../nl/USER_GUIDE.md) · 🇵🇱 [pl](../pl/USER_GUIDE.md) · 🇸🇪 [sv](../sv/USER_GUIDE.md) · 🇳🇴 [no](../no/USER_GUIDE.md) · 🇩🇰 [da](../da/USER_GUIDE.md) · 🇫🇮 [fi](../fi/USER_GUIDE.md) · 🇵🇹 [pt](../pt/USER_GUIDE.md) · 🇷🇴 [ro](../ro/USER_GUIDE.md) · 🇭🇺 [hu](../hu/USER_GUIDE.md) · 🇧🇬 [bg](../bg/USER_GUIDE.md) · 🇸🇰 [sk](../sk/USER_GUIDE.md) · 🇺🇦 [uk-UA](../uk-UA/USER_GUIDE.md) · 🇮🇱 [he](../he/USER_GUIDE.md) · 🇵🇭 [phi](../phi/USER_GUIDE.md)
-
-> 🇺🇸 [English](../../USER_GUIDE.md)
+🌐 **Languages:** 🇺🇸 [English](../../../../docs/USER_GUIDE.md) · 🇪🇸 [es](../../es/docs/USER_GUIDE.md) · 🇫🇷 [fr](../../fr/docs/USER_GUIDE.md) · 🇩🇪 [de](../../de/docs/USER_GUIDE.md) · 🇮🇹 [it](../../it/docs/USER_GUIDE.md) · 🇷🇺 [ru](../../ru/docs/USER_GUIDE.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/USER_GUIDE.md) · 🇯🇵 [ja](../../ja/docs/USER_GUIDE.md) · 🇰🇷 [ko](../../ko/docs/USER_GUIDE.md) · 🇸🇦 [ar](../../ar/docs/USER_GUIDE.md) · 🇮🇳 [in](../../in/docs/USER_GUIDE.md) · 🇹🇭 [th](../../th/docs/USER_GUIDE.md) · 🇻🇳 [vi](../../vi/docs/USER_GUIDE.md) · 🇮🇩 [id](../../id/docs/USER_GUIDE.md) · 🇲🇾 [ms](../../ms/docs/USER_GUIDE.md) · 🇳🇱 [nl](../../nl/docs/USER_GUIDE.md) · 🇵🇱 [pl](../../pl/docs/USER_GUIDE.md) · 🇸🇪 [sv](../../sv/docs/USER_GUIDE.md) · 🇳🇴 [no](../../no/docs/USER_GUIDE.md) · 🇩🇰 [da](../../da/docs/USER_GUIDE.md) · 🇫🇮 [fi](../../fi/docs/USER_GUIDE.md) · 🇵🇹 [pt](../../pt/docs/USER_GUIDE.md) · 🇷🇴 [ro](../../ro/docs/USER_GUIDE.md) · 🇭🇺 [hu](../../hu/docs/USER_GUIDE.md) · 🇧🇬 [bg](../../bg/docs/USER_GUIDE.md) · 🇸🇰 [sk](../../sk/docs/USER_GUIDE.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/USER_GUIDE.md) · 🇮🇱 [he](../../he/docs/USER_GUIDE.md) · 🇵🇭 [phi](../../phi/docs/USER_GUIDE.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/USER_GUIDE.md) · 🇨🇿 [cs](../../cs/docs/USER_GUIDE.md)
---
@@ -320,7 +318,7 @@ Model: cc/claude-opus-4-6
---
-## 🚀 Deployment
+## פריסה
### Global npm install (Recommended)
@@ -511,23 +509,26 @@ post_install() {
### Environment Variables
-| Variable | Default | Description |
-| ------------------------- | ------------------------------------ | ------------------------------------------------------- |
-| `JWT_SECRET` | `omniroute-default-secret-change-me` | JWT signing secret (**change in production**) |
-| `INITIAL_PASSWORD` | `123456` | First login password |
-| `DATA_DIR` | `~/.omniroute` | Data directory (db, usage, logs) |
-| `PORT` | framework default | Service port (`20128` in examples) |
-| `HOSTNAME` | framework default | Bind host (Docker defaults to `0.0.0.0`) |
-| `NODE_ENV` | runtime default | Set `production` for deploy |
-| `BASE_URL` | `http://localhost:20128` | Server-side internal base URL |
-| `CLOUD_URL` | `https://omniroute.dev` | Cloud sync endpoint base URL |
-| `API_KEY_SECRET` | `endpoint-proxy-api-key-secret` | HMAC secret for generated API keys |
-| `REQUIRE_API_KEY` | `false` | Enforce Bearer API key on `/v1/*` |
-| `ENABLE_REQUEST_LOGS` | `false` | Enables request/response logs |
-| `AUTH_COOKIE_SECURE` | `false` | Force `Secure` auth cookie (behind HTTPS reverse proxy) |
-| `OMNIROUTE_MEMORY_MB` | `512` | Node.js heap limit in MB |
-| `PROMPT_CACHE_MAX_SIZE` | `50` | Max prompt cache entries |
-| `SEMANTIC_CACHE_MAX_SIZE` | `100` | Max semantic cache entries |
+| Variable | Default | Description |
+| ---------------------------- | ------------------------------------ | ------------------------------------------------------------------------------------------ |
+| `JWT_SECRET` | `omniroute-default-secret-change-me` | JWT signing secret (**change in production**) |
+| `INITIAL_PASSWORD` | `123456` | First login password |
+| `DATA_DIR` | `~/.omniroute` | Data directory (db, usage, logs) |
+| `PORT` | framework default | Service port (`20128` in examples) |
+| `HOSTNAME` | framework default | Bind host (Docker defaults to `0.0.0.0`) |
+| `NODE_ENV` | runtime default | Set `production` for deploy |
+| `BASE_URL` | `http://localhost:20128` | Server-side internal base URL |
+| `CLOUD_URL` | `https://omniroute.dev` | Cloud sync endpoint base URL |
+| `API_KEY_SECRET` | `endpoint-proxy-api-key-secret` | HMAC secret for generated API keys |
+| `REQUIRE_API_KEY` | `false` | Enforce Bearer API key on `/v1/*` |
+| `ALLOW_API_KEY_REVEAL` | `false` | Allow Api Manager to copy full API keys on demand |
+| `DISABLE_SQLITE_AUTO_BACKUP` | `false` | Disable automatic SQLite snapshots before writes/import/restore; manual backups still work |
+| `ENABLE_REQUEST_LOGS` | `false` | Enables request/response logs |
+| `AUTH_COOKIE_SECURE` | `false` | Force `Secure` auth cookie (behind HTTPS reverse proxy) |
+| `CLOUDFLARED_BIN` | unset | Use an existing `cloudflared` binary instead of managed download |
+| `OMNIROUTE_MEMORY_MB` | `512` | Node.js heap limit in MB |
+| `PROMPT_CACHE_MAX_SIZE` | `50` | Max prompt cache entries |
+| `SEMANTIC_CACHE_MAX_SIZE` | `100` | Max semantic cache entries |
For the full environment variable reference, see the [README](../README.md).
@@ -598,6 +599,11 @@ curl -X POST http://localhost:20128/api/provider-models \
Or use Dashboard: **Providers → [Provider] → Custom Models**.
+Notes:
+
+- OpenRouter and OpenAI/Anthropic-compatible providers are managed from **Available Models** only. Manual add, import, and auto-sync all land in the same available-model list, so there is no separate Custom Models section for those providers.
+- The **Custom Models** section is intended for providers that do not expose managed available-model imports.
+
### Dedicated Provider Routes
Route requests directly to a specific provider with model validation:
@@ -642,6 +648,14 @@ Returns models grouped by provider with types (`chat`, `embedding`, `image`).
- Automatic background sync with timeout + fail-fast
- Prefer server-side `BASE_URL`/`CLOUD_URL` in production
+### Cloudflare Quick Tunnel
+
+- Available in **Dashboard → Endpoints** for Docker and other self-hosted deployments
+- Creates a temporary `https://*.trycloudflare.com` URL that forwards to your current OpenAI-compatible `/v1` endpoint
+- First enable installs `cloudflared` only when needed; later restarts reuse the same managed binary
+- Tunnel URLs are ephemeral and change every time you stop/start the tunnel
+- Set `CLOUDFLARED_BIN` if you prefer using a preinstalled `cloudflared` binary instead of the managed download
+
### LLM Gateway Intelligence (Phase 9)
- **Semantic Cache** — Auto-caches non-streaming, temperature=0 responses (bypass with `X-OmniRoute-No-Cache: true`)
@@ -757,11 +771,11 @@ OmniRoute implements provider-level resilience with four components:
Manage database backups in **Dashboard → Settings → System & Storage**.
-| Action | Description |
-| ------------------------ | ------------------------------------------------------------------------------------------------------------------------------ |
-| **Export Database** | Downloads the current SQLite database as a `.sqlite` file |
-| **Export All (.tar.gz)** | Downloads a full backup archive including: database, settings, combos, provider connections (no credentials), API key metadata |
-| **Import Database** | Upload a `.sqlite` file to replace the current database. A pre-import backup is automatically created |
+| Action | Description |
+| ------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------- |
+| **Export Database** | Downloads the current SQLite database as a `.sqlite` file |
+| **Export All (.tar.gz)** | Downloads a full backup archive including: database, settings, combos, provider connections (no credentials), API key metadata |
+| **Import Database** | Upload a `.sqlite` file to replace the current database. A pre-import backup is automatically created unless `DISABLE_SQLITE_AUTO_BACKUP=true` |
```bash
# API: Export database
@@ -787,10 +801,11 @@ curl -X POST http://localhost:20128/api/db-backups/import \
### Settings Dashboard
-The settings page is organized into 5 tabs for easy navigation:
+The settings page is organized into 6 tabs for easy navigation:
| Tab | Contents |
| -------------- | ---------------------------------------------------------------------------------------------- |
+| **General** | System storage tools, appearance settings, theme controls, and per-item sidebar visibility |
| **Security** | Login/Password settings, IP Access Control, API auth for `/models`, and Provider Blocking |
| **Routing** | Global routing strategy (6 options), wildcard model aliases, fallback chains, combo defaults |
| **Resilience** | Provider profiles, editable rate limits, circuit breaker status, policies & locked identifiers |
diff --git a/docs/i18n/he/docs/VM_DEPLOYMENT_GUIDE.md b/docs/i18n/he/docs/VM_DEPLOYMENT_GUIDE.md
new file mode 100644
index 0000000000..87d3746956
--- /dev/null
+++ b/docs/i18n/he/docs/VM_DEPLOYMENT_GUIDE.md
@@ -0,0 +1,403 @@
+# OmniRoute — Deployment Guide on VM with Cloudflare (עברית)
+
+🌐 **Languages:** 🇺🇸 [English](../../../../docs/VM_DEPLOYMENT_GUIDE.md) · 🇪🇸 [es](../../es/docs/VM_DEPLOYMENT_GUIDE.md) · 🇫🇷 [fr](../../fr/docs/VM_DEPLOYMENT_GUIDE.md) · 🇩🇪 [de](../../de/docs/VM_DEPLOYMENT_GUIDE.md) · 🇮🇹 [it](../../it/docs/VM_DEPLOYMENT_GUIDE.md) · 🇷🇺 [ru](../../ru/docs/VM_DEPLOYMENT_GUIDE.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/VM_DEPLOYMENT_GUIDE.md) · 🇯🇵 [ja](../../ja/docs/VM_DEPLOYMENT_GUIDE.md) · 🇰🇷 [ko](../../ko/docs/VM_DEPLOYMENT_GUIDE.md) · 🇸🇦 [ar](../../ar/docs/VM_DEPLOYMENT_GUIDE.md) · 🇮🇳 [in](../../in/docs/VM_DEPLOYMENT_GUIDE.md) · 🇹🇭 [th](../../th/docs/VM_DEPLOYMENT_GUIDE.md) · 🇻🇳 [vi](../../vi/docs/VM_DEPLOYMENT_GUIDE.md) · 🇮🇩 [id](../../id/docs/VM_DEPLOYMENT_GUIDE.md) · 🇲🇾 [ms](../../ms/docs/VM_DEPLOYMENT_GUIDE.md) · 🇳🇱 [nl](../../nl/docs/VM_DEPLOYMENT_GUIDE.md) · 🇵🇱 [pl](../../pl/docs/VM_DEPLOYMENT_GUIDE.md) · 🇸🇪 [sv](../../sv/docs/VM_DEPLOYMENT_GUIDE.md) · 🇳🇴 [no](../../no/docs/VM_DEPLOYMENT_GUIDE.md) · 🇩🇰 [da](../../da/docs/VM_DEPLOYMENT_GUIDE.md) · 🇫🇮 [fi](../../fi/docs/VM_DEPLOYMENT_GUIDE.md) · 🇵🇹 [pt](../../pt/docs/VM_DEPLOYMENT_GUIDE.md) · 🇷🇴 [ro](../../ro/docs/VM_DEPLOYMENT_GUIDE.md) · 🇭🇺 [hu](../../hu/docs/VM_DEPLOYMENT_GUIDE.md) · 🇧🇬 [bg](../../bg/docs/VM_DEPLOYMENT_GUIDE.md) · 🇸🇰 [sk](../../sk/docs/VM_DEPLOYMENT_GUIDE.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/VM_DEPLOYMENT_GUIDE.md) · 🇮🇱 [he](../../he/docs/VM_DEPLOYMENT_GUIDE.md) · 🇵🇭 [phi](../../phi/docs/VM_DEPLOYMENT_GUIDE.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/VM_DEPLOYMENT_GUIDE.md) · 🇨🇿 [cs](../../cs/docs/VM_DEPLOYMENT_GUIDE.md)
+
+---
+
+Complete guide to install and configure OmniRoute on a VM (VPS) with domain managed via Cloudflare.
+
+---
+
+## Prerequisites
+
+| Item | Minimum | Recommended |
+| ---------- | ------------------------ | ---------------- |
+| **CPU** | 1 vCPU | 2 vCPU |
+| **RAM** | 1 GB | 2 GB |
+| **Disk** | 10 GB SSD | 25 GB SSD |
+| **OS** | Ubuntu 22.04 LTS | Ubuntu 24.04 LTS |
+| **Domain** | Registered on Cloudflare | — |
+| **Docker** | Docker Engine 24+ | Docker 27+ |
+
+**Tested providers**: Akamai (Linode), DigitalOcean, Vultr, Hetzner, AWS Lightsail.
+
+---
+
+## 1. Configure the VM
+
+### 1.1 Create the instance
+
+On your preferred VPS provider:
+
+- Choose Ubuntu 24.04 LTS
+- Select the minimum plan (1 vCPU / 1 GB RAM)
+- Set a strong root password or configure SSH key
+- Note the **public IP** (e.g., `203.0.113.10`)
+
+### 1.2 Connect via SSH
+
+```bash
+ssh root@203.0.113.10
+```
+
+### 1.3 Update the system
+
+```bash
+apt update && apt upgrade -y
+```
+
+### 1.4 Install Docker
+
+```bash
+# Install dependencies
+apt install -y ca-certificates curl gnupg
+
+# Add official Docker repository
+install -m 0755 -d /etc/apt/keyrings
+curl -fsSL https://download.docker.com/linux/ubuntu/gpg | gpg --dearmor -o /etc/apt/keyrings/docker.gpg
+chmod a+r /etc/apt/keyrings/docker.gpg
+echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu $ (. /etc/os-release && echo “$VERSION_CODENAME”) stable" | tee /etc/apt/sources.list.d/docker.list > /dev/null
+apt update
+apt install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin
+```
+
+### 1.5 Install nginx
+
+```bash
+apt install -y nginx
+```
+
+### 1.6 Configure Firewall (UFW)
+
+```bash
+ufw default deny incoming
+ufw default allow outgoing
+ufw allow 22/tcp # SSH
+ufw allow 80/tcp # HTTP (redirect)
+ufw allow 443/tcp # HTTPS
+ufw enable
+```
+
+> **Tip**: For maximum security, restrict ports 80 and 443 to Cloudflare IPs only. See the [Advanced Security](#advanced-security) section.
+
+---
+
+## 2. Install OmniRoute
+
+### 2.1 Create configuration directory
+
+```bash
+mkdir -p /opt/omniroute
+```
+
+### 2.2 Create environment variables file
+
+```bash
+cat > /opt/omniroute/.env << ‘EOF’
+# === Security ===
+JWT_SECRET=CHANGE-TO-A-UNIQUE-64-CHAR-SECRET-KEY
+INITIAL_PASSWORD=YourSecurePassword123!
+API_KEY_SECRET=REPLACE-WITH-ANOTHER-SECRET-KEY
+STORAGE_ENCRYPTION_KEY=REPLACE-WITH-THIRD-SECRET-KEY
+STORAGE_ENCRYPTION_KEY_VERSION=v1
+MACHINE_ID_SALT=CHANGE-TO-A-UNIQUE-SALT
+
+# === App ===
+PORT=20128
+NODE_ENV=production
+HOSTNAME=0.0.0.0
+DATA_DIR=/app/data
+STORAGE_DRIVER=sqlite
+ENABLE_REQUEST_LOGS=true
+AUTH_COOKIE_SECURE=false
+REQUIRE_API_KEY=false
+
+# === Domain (change to your domain) ===
+BASE_URL=https://llms.seudominio.com
+NEXT_PUBLIC_BASE_URL=https://llms.seudominio.com
+
+# === Cloud Sync (optional) ===
+# CLOUD_URL=https://cloud.omniroute.online
+# NEXT_PUBLIC_CLOUD_URL=https://cloud.omniroute.online
+EOF
+```
+
+> ⚠️ **IMPORTANT**: Generate unique secret keys! Use `openssl rand -hex 32` for each key.
+
+### 2.3 Start the container
+
+```bash
+docker pull diegosouzapw/omniroute:latest
+
+docker run -d \
+ --name omniroute \
+ --restart unless-stopped \
+ --env-file /opt/omniroute/.env \
+ -p 20128:20128 \
+ -v omniroute-data:/app/data \
+ diegosouzapw/omniroute:latest
+```
+
+### 2.4 Verify that it is running
+
+```bash
+docker ps | grep omniroute
+docker logs omniroute --tail 20
+```
+
+It should display: `[DB] SQLite database ready` and `listening on port 20128`.
+
+---
+
+## 3. Configure nginx (Reverse Proxy)
+
+### 3.1 Generate SSL certificate (Cloudflare Origin)
+
+In the Cloudflare dashboard:
+
+1. Go to **SSL/TLS → Origin Server**
+2. Click **Create Certificate**
+3. Keep the defaults (15 years, \*.yourdomain.com)
+4. Copy the **Origin Certificate** and the **Private Key**
+
+```bash
+mkdir -p /etc/nginx/ssl
+
+# Paste the certificate
+nano /etc/nginx/ssl/origin.crt
+
+# Paste the private key
+nano /etc/nginx/ssl/origin.key
+
+chmod 600 /etc/nginx/ssl/origin.key
+```
+
+### 3.2 Nginx Configuration
+
+```bash
+cat > /etc/nginx/sites-available/omniroute << ‘NGINX’
+# Default server — blocks direct access via IP
+server {
+ listen 80 default_server;
+ listen [::]:80 default_server;
+ listen 443 ssl default_server;
+ listen [::]:443 ssl default_server;
+ ssl_certificate /etc/nginx/ssl/origin.crt;
+ ssl_certificate_key /etc/nginx/ssl/origin.key;
+ server_name _;
+ return 444;
+}
+
+# OmniRoute — HTTPS
+server {
+ listen 443 ssl;
+ listen [::]:443 ssl;
+ server_name llms.yourdomain.com; # Change to your domain
+
+ ssl_certificate /etc/nginx/ssl/origin.crt;
+ ssl_certificate_key /etc/nginx/ssl/origin.key;
+ ssl_protocols TLSv1.2 TLSv1.3;
+
+ client_max_body_size 100M;
+
+ location / {
+ proxy_pass http://127.0.0.1:20128;
+ proxy_set_header Host $host;
+ proxy_set_header X-Real-IP $remote_addr;
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
+ proxy_set_header X-Forwarded-Proto $scheme;
+
+ # WebSocket support
+ proxy_http_version 1.1;
+ proxy_set_header Upgrade $http_upgrade;
+ proxy_set_header Connection “upgrade”;
+
+ # SSE (Server-Sent Events) — streaming AI responses
+ proxy_buffering off;
+ proxy_cache off;
+ proxy_read_timeout 300s;
+ proxy_send_timeout 300s;
+ }
+}
+
+# HTTP → HTTPS redirect
+server {
+ listen 80;
+ listen [::]:80;
+ server_name llms.yourdomain.com;
+ return 301 https://$server_name$request_uri;
+}
+NGINX
+```
+
+### 3.3 Enable and Test
+
+```bash
+# Remove default configuration
+rm -f /etc/nginx/sites-enabled/default
+
+# Enable OmniRoute
+ln -sf /etc/nginx/sites-available/omniroute /etc/nginx/sites-enabled/omniroute
+
+# Test and reload
+nginx -t && systemctl reload nginx
+```
+
+---
+
+## 4. Configure Cloudflare DNS
+
+### 4.1 Add DNS record
+
+In the Cloudflare dashboard → DNS:
+
+| Type | Name | Content | Proxy |
+| ---- | ------ | ---------------------- | ---------- |
+| A | `llms` | `203.0.113.10` (VM IP) | ✅ Proxied |
+
+### 4.2 Configure SSL
+
+Under **SSL/TLS → Overview**:
+
+- Mode: **Full (Strict)**
+
+Under **SSL/TLS → Edge Certificates**:
+
+- Always Use HTTPS: ✅ On
+- Minimum TLS Version: TLS 1.2
+- Automatic HTTPS Rewrites: ✅ On
+
+### 4.3 Testing
+
+```bash
+curl -sI https://llms.seudominio.com/health
+# Should return HTTP/2 200
+```
+
+---
+
+## 5. Operations and Maintenance
+
+### Upgrade to a new version
+
+```bash
+docker pull diegosouzapw/omniroute:latest
+docker stop omniroute && docker rm omniroute
+docker run -d --name omniroute --restart unless-stopped \
+ --env-file /opt/omniroute/.env \
+ -p 20128:20128 \
+ -v omniroute-data:/app/data \
+ diegosouzapw/omniroute:latest
+```
+
+### View logs
+
+```bash
+docker logs -f omniroute # Real-time stream
+docker logs omniroute --tail 50 # Last 50 lines
+```
+
+### Manual database backup
+
+```bash
+# Copy data from the volume to the host
+docker cp omniroute:/app/data ./backup-$(date +%F)
+
+# Or compress the entire volume
+docker run --rm -v omniroute-data:/data -v $(pwd):/backup \
+ alpine tar czf /backup/omniroute-data-$(date +%F).tar.gz /data
+```
+
+### Restore from backup
+
+```bash
+docker stop omniroute
+docker run --rm -v omniroute-data:/data -v $(pwd):/backup \
+ alpine sh -c “rm -rf /data/* && tar xzf /backup/omniroute-data-YYYY-MM-DD.tar.gz -C /”
+docker start omniroute
+```
+
+---
+
+## 6. Advanced Security
+
+### Restrict nginx to Cloudflare IPs
+
+```bash
+cat > /etc/nginx/cloudflare-ips.conf << ‘CF’
+# Cloudflare IPv4 ranges — update periodically
+# https://www.cloudflare.com/ips-v4/
+set_real_ip_from 173.245.48.0/20;
+set_real_ip_from 103.21.244.0/22;
+set_real_ip_from 103.22.200.0/22;
+set_real_ip_from 103.31.4.0/22;
+set_real_ip_from 141.101.64.0/18;
+set_real_ip_from 108.162.192.0/18;
+set_real_ip_from 190.93.240.0/20;
+set_real_ip_from 188.114.96.0/20;
+set_real_ip_from 197.234.240.0/22;
+set_real_ip_from 198.41.128.0/17;
+set_real_ip_from 162.158.0.0/15;
+set_real_ip_from 104.16.0.0/13;
+set_real_ip_from 104.24.0.0/14;
+set_real_ip_from 172.64.0.0/13;
+set_real_ip_from 131.0.72.0/22;
+real_ip_header CF-Connecting-IP;
+CF
+```
+
+Add the following to `nginx.conf` inside the `http {}` block:
+
+```nginx
+include /etc/nginx/cloudflare-ips.conf;
+```
+
+### Install fail2ban
+
+```bash
+apt install -y fail2ban
+systemctl enable fail2ban
+systemctl start fail2ban
+
+# Check status
+fail2ban-client status sshd
+```
+
+### Block direct access to the Docker port
+
+```bash
+# Prevent direct external access to port 20128
+iptables -I DOCKER-USER -p tcp --dport 20128 -j DROP
+iptables -I DOCKER-USER -i lo -p tcp --dport 20128 -j ACCEPT
+
+# Persist the rules
+apt install -y iptables-persistent
+netfilter-persistent save
+```
+
+---
+
+## 7. Deploy to Cloudflare Workers (Optional)
+
+For remote access via Cloudflare Workers (without exposing the VM directly):
+
+```bash
+# In the local repository
+cd omnirouteCloud
+npm install
+npx wrangler login
+npx wrangler deploy
+```
+
+See the full documentation at [omnirouteCloud/README.md](../omnirouteCloud/README.md).
+
+---
+
+## Port Summary
+
+| Port | Service | Access |
+| ----- | ----------- | -------------------------- |
+| 22 | SSH | Public (with fail2ban) |
+| 80 | nginx HTTP | Redirect → HTTPS |
+| 443 | nginx HTTPS | Via Cloudflare Proxy |
+| 20128 | OmniRoute | Localhost only (via nginx) |
diff --git a/docs/i18n/he/src/lib/a2a/README.md b/docs/i18n/he/src/lib/a2a/README.md
new file mode 100644
index 0000000000..3d89bf85f6
--- /dev/null
+++ b/docs/i18n/he/src/lib/a2a/README.md
@@ -0,0 +1,752 @@
+# OmniRoute A2A Server (עברית)
+
+🌐 **Languages:** 🇺🇸 [English](../../../../../../src/lib/a2a/README.md) · 🇪🇸 [es](../../../../es/src/lib/a2a/README.md) · 🇫🇷 [fr](../../../../fr/src/lib/a2a/README.md) · 🇩🇪 [de](../../../../de/src/lib/a2a/README.md) · 🇮🇹 [it](../../../../it/src/lib/a2a/README.md) · 🇷🇺 [ru](../../../../ru/src/lib/a2a/README.md) · 🇨🇳 [zh-CN](../../../../zh-CN/src/lib/a2a/README.md) · 🇯🇵 [ja](../../../../ja/src/lib/a2a/README.md) · 🇰🇷 [ko](../../../../ko/src/lib/a2a/README.md) · 🇸🇦 [ar](../../../../ar/src/lib/a2a/README.md) · 🇮🇳 [in](../../../../in/src/lib/a2a/README.md) · 🇹🇭 [th](../../../../th/src/lib/a2a/README.md) · 🇻🇳 [vi](../../../../vi/src/lib/a2a/README.md) · 🇮🇩 [id](../../../../id/src/lib/a2a/README.md) · 🇲🇾 [ms](../../../../ms/src/lib/a2a/README.md) · 🇳🇱 [nl](../../../../nl/src/lib/a2a/README.md) · 🇵🇱 [pl](../../../../pl/src/lib/a2a/README.md) · 🇸🇪 [sv](../../../../sv/src/lib/a2a/README.md) · 🇳🇴 [no](../../../../no/src/lib/a2a/README.md) · 🇩🇰 [da](../../../../da/src/lib/a2a/README.md) · 🇫🇮 [fi](../../../../fi/src/lib/a2a/README.md) · 🇵🇹 [pt](../../../../pt/src/lib/a2a/README.md) · 🇷🇴 [ro](../../../../ro/src/lib/a2a/README.md) · 🇭🇺 [hu](../../../../hu/src/lib/a2a/README.md) · 🇧🇬 [bg](../../../../bg/src/lib/a2a/README.md) · 🇸🇰 [sk](../../../../sk/src/lib/a2a/README.md) · 🇺🇦 [uk-UA](../../../../uk-UA/src/lib/a2a/README.md) · 🇮🇱 [he](../../../../he/src/lib/a2a/README.md) · 🇵🇭 [phi](../../../../phi/src/lib/a2a/README.md) · 🇧🇷 [pt-BR](../../../../pt-BR/src/lib/a2a/README.md) · 🇨🇿 [cs](../../../../cs/src/lib/a2a/README.md)
+
+---
+
+> **Agent-to-Agent Protocol v0.3** — Enables any AI agent to use OmniRoute as an intelligent routing agent via JSON-RPC 2.0.
+
+The A2A Server exposes OmniRoute as a **first-class agent** that other agents can discover, delegate tasks to, and collaborate with using the [A2A Protocol](https://google.github.io/A2A/).
+
+---
+
+## ארכיטקטורה
+
+```
+┌──────────────────────────────────────────────────────────────────┐
+│ Orchestrator Agent │
+│ (LangChain, CrewAI, AutoGen, Custom Agent) │
+└──────────────────────┬───────────────────────────────────────────┘
+ │ 1. GET /.well-known/agent.json (discover)
+ │ 2. POST /a2a (JSON-RPC 2.0)
+ ▼
+┌──────────────────────────────────────────────────────────────────┐
+│ OmniRoute A2A Server │
+│ ┌────────────────┐ ┌────────────────┐ ┌───────────────────┐ │
+│ │ Task Manager │ │ Skill Engine │ │ SSE Streaming │ │
+│ │ (lifecycle) │──│ (registry) │──│ (real-time) │ │
+│ └────────────────┘ └────────┬───────┘ └───────────────────┘ │
+│ │ │
+│ Skills: │ │
+│ ├─ smart-routing ──────────┤ ┌────────────────────────────┐ │
+│ └─ quota-management ───────┘ │ Routing Decision Logger │ │
+│ └────────────────────────────┘ │
+└──────────────────────────────────────────────────────────────────┘
+ │
+ ▼ OmniRoute Gateway (internal)
+ /v1/chat/completions, /api/combos, /api/usage/quota
+```
+
+---
+
+## התחלה מהירה
+
+### Agent Discovery
+
+Every A2A-compatible agent exposes an **Agent Card** at `/.well-known/agent.json`:
+
+```bash
+curl http://localhost:20128/.well-known/agent.json
+```
+
+**Response:**
+
+```json
+{
+ "name": "OmniRoute",
+ "description": "Intelligent AI gateway with auto-routing across 50+ providers",
+ "url": "http://localhost:20128/a2a",
+ "version": "1.8.1",
+ "capabilities": {
+ "streaming": true,
+ "pushNotifications": false
+ },
+ "skills": [
+ {
+ "id": "smart-routing",
+ "name": "Smart Routing",
+ "description": "Routes prompts through OmniRoute intelligent pipeline",
+ "tags": ["routing", "llm", "multi-provider", "cost-optimization"],
+ "examples": [
+ "Write a hello world in Python",
+ "Explain quantum computing using the cheapest provider"
+ ]
+ },
+ {
+ "id": "quota-management",
+ "name": "Quota Management",
+ "description": "Natural-language queries about provider quotas",
+ "tags": ["quota", "analytics", "cost"],
+ "examples": [
+ "Which provider has the most quota remaining?",
+ "Suggest a free combo for coding"
+ ]
+ }
+ ],
+ "authentication": {
+ "schemes": ["bearer"],
+ "apiKeyHeader": "Authorization"
+ }
+}
+```
+
+---
+
+## JSON-RPC 2.0 Methods
+
+### `message/send` — Synchronous Execution
+
+Send a message to a skill and receive the complete response.
+
+```bash
+curl -X POST http://localhost:20128/a2a \
+ -H "Content-Type: application/json" \
+ -H "Authorization: Bearer YOUR_KEY" \
+ -d '{
+ "jsonrpc": "2.0",
+ "id": "1",
+ "method": "message/send",
+ "params": {
+ "skill": "smart-routing",
+ "messages": [{"role": "user", "content": "Write a Python hello world"}],
+ "metadata": {"model": "auto", "combo": "fast-coding"}
+ }
+ }'
+```
+
+**Response:**
+
+```json
+{
+ "jsonrpc": "2.0",
+ "id": "1",
+ "result": {
+ "task": { "id": "a1b2c3d4-...", "state": "completed" },
+ "artifacts": [{ "type": "text", "content": "print('Hello, World!')" }],
+ "metadata": {
+ "routing_explanation": "Selected claude-sonnet via provider \"anthropic\" (latency: 1200ms, cost: $0.0030)",
+ "cost_envelope": { "estimated": 0.005, "actual": 0.003, "currency": "USD" },
+ "resilience_trace": [
+ { "event": "primary_selected", "provider": "anthropic", "timestamp": "2026-03-04T..." }
+ ],
+ "policy_verdict": { "allowed": true, "reason": "within budget and quota limits" }
+ }
+ }
+}
+```
+
+### `message/stream` — SSE Streaming
+
+Same as `message/send` but returns Server-Sent Events for real-time streaming.
+
+```bash
+curl -N -X POST http://localhost:20128/a2a \
+ -H "Content-Type: application/json" \
+ -H "Authorization: Bearer YOUR_KEY" \
+ -d '{
+ "jsonrpc": "2.0",
+ "id": "1",
+ "method": "message/stream",
+ "params": {
+ "skill": "smart-routing",
+ "messages": [{"role": "user", "content": "Explain quantum computing"}]
+ }
+ }'
+```
+
+**SSE Events:**
+
+```
+data: {"jsonrpc":"2.0","method":"message/stream","params":{"task":{"id":"...","state":"working"},"chunk":{"type":"text","content":"Quantum computing..."}}}
+
+: heartbeat 2026-03-04T21:00:00Z
+
+data: {"jsonrpc":"2.0","method":"message/stream","params":{"task":{"id":"...","state":"completed"},"metadata":{...}}}
+```
+
+### `tasks/get` — Query Task Status
+
+```bash
+curl -X POST http://localhost:20128/a2a \
+ -H "Content-Type: application/json" \
+ -H "Authorization: Bearer YOUR_KEY" \
+ -d '{"jsonrpc":"2.0","id":"2","method":"tasks/get","params":{"taskId":"TASK_UUID"}}'
+```
+
+### `tasks/cancel` — Cancel a Running Task
+
+```bash
+curl -X POST http://localhost:20128/a2a \
+ -H "Content-Type: application/json" \
+ -H "Authorization: Bearer YOUR_KEY" \
+ -d '{"jsonrpc":"2.0","id":"3","method":"tasks/cancel","params":{"taskId":"TASK_UUID"}}'
+```
+
+---
+
+## Skills Reference
+
+### `smart-routing`
+
+Routes prompts through OmniRoute's intelligent pipeline with full observability.
+
+**Parameters (in `metadata`):**
+
+| Parameter | Type | Default | Description |
+| --------- | -------- | ------------ | ---------------------------------------------------------------------------------------- |
+| `model` | `string` | `"auto"` | Target model (e.g., `claude-sonnet-4`, `gpt-4o`, `auto`) |
+| `combo` | `string` | active combo | Specific combo to route through |
+| `budget` | `number` | none | Maximum cost in USD for this request |
+| `role` | `string` | none | Task role hint: `coding`, `review`, `planning`, `analysis`, `debugging`, `documentation` |
+
+**Returns:**
+
+| Field | Description |
+| ------------------------------ | --------------------------------------------------------- |
+| `artifacts[].content` | The LLM response text |
+| `metadata.routing_explanation` | Human-readable explanation of routing decision |
+| `metadata.cost_envelope` | Estimated vs actual cost with currency |
+| `metadata.resilience_trace` | Array of events (primary_selected, fallback_needed, etc.) |
+| `metadata.policy_verdict` | Whether the request was allowed and why |
+
+### `quota-management`
+
+Answers natural-language queries about provider quotas.
+
+**Query types (inferred from message content):**
+
+| Query Pattern | Response Type |
+| ---------------------------------------------- | -------------------------------------------------------- |
+| Contains `"ranking"`, `"most quota"`, `"best"` | Providers ranked by remaining quota |
+| Contains `"free"`, `"suggest"` | Lists free combos or suggests free-tier providers |
+| Default | Full quota summary with warnings for low-quota providers |
+
+---
+
+## Task Lifecycle
+
+```
+submitted ──→ working ──→ completed
+ ──→ failed
+ ──────────→ cancelled
+```
+
+| State | Description |
+| ----------- | ----------------------------------------------------- |
+| `submitted` | Task created, queued for execution |
+| `working` | Skill handler is executing |
+| `completed` | Execution succeeded, artifacts available |
+| `failed` | Execution failed or task expired (TTL: 5 min default) |
+| `cancelled` | Cancelled by client via `tasks/cancel` |
+
+- Terminal states: `completed`, `failed`, `cancelled` (no further transitions)
+- Expired tasks in `submitted` or `working` are auto-marked as `failed`
+- Tasks are garbage-collected after 2× TTL
+
+---
+
+## Client Examples
+
+### Python — Orchestrator Agent
+
+```python
+"""
+A2A Client — Python example.
+Discovers OmniRoute agent, sends a task, and processes the result.
+"""
+import requests
+import json
+
+BASE_URL = "http://localhost:20128"
+API_KEY = "your-api-key"
+HEADERS = {
+ "Content-Type": "application/json",
+ "Authorization": f"Bearer {API_KEY}",
+}
+
+# 1. Discover agent capabilities
+agent_card = requests.get(f"{BASE_URL}/.well-known/agent.json").json()
+print(f"Agent: {agent_card['name']} v{agent_card['version']}")
+print(f"Skills: {[s['id'] for s in agent_card['skills']]}")
+
+# 2. Send a smart-routing task
+response = requests.post(f"{BASE_URL}/a2a", headers=HEADERS, json={
+ "jsonrpc": "2.0",
+ "id": "task-1",
+ "method": "message/send",
+ "params": {
+ "skill": "smart-routing",
+ "messages": [{"role": "user", "content": "Write a Python quicksort implementation"}],
+ "metadata": {
+ "model": "auto",
+ "combo": "fast-coding",
+ "budget": 0.10,
+ }
+ }
+})
+result = response.json()["result"]
+print(f"\n📝 Response: {result['artifacts'][0]['content'][:200]}...")
+print(f"🔀 Routing: {result['metadata']['routing_explanation']}")
+print(f"💰 Cost: ${result['metadata']['cost_envelope']['actual']}")
+print(f"🛡️ Policy: {result['metadata']['policy_verdict']['reason']}")
+
+# 3. Query quota status
+quota_resp = requests.post(f"{BASE_URL}/a2a", headers=HEADERS, json={
+ "jsonrpc": "2.0",
+ "id": "task-2",
+ "method": "message/send",
+ "params": {
+ "skill": "quota-management",
+ "messages": [{"role": "user", "content": "Which provider has the most quota remaining?"}],
+ }
+})
+quota_result = quota_resp.json()["result"]
+print(f"\n📊 Quota: {quota_result['artifacts'][0]['content']}")
+```
+
+### TypeScript — Multi-Agent Orchestrator
+
+```typescript
+/**
+ * A2A Client — TypeScript example.
+ * Shows agent discovery, task delegation, and streaming.
+ */
+
+const BASE_URL = "http://localhost:20128";
+const API_KEY = "your-api-key";
+
+interface JsonRpcResponse {
+ jsonrpc: "2.0";
+ id: string | number;
+ result?: T;
+ error?: { code: number; message: string };
+}
+
+async function a2aCall(method: string, params: Record): Promise {
+ const resp = await fetch(`${BASE_URL}/a2a`, {
+ method: "POST",
+ headers: {
+ "Content-Type": "application/json",
+ Authorization: `Bearer ${API_KEY}`,
+ },
+ body: JSON.stringify({
+ jsonrpc: "2.0",
+ id: `${method}-${Date.now()}`,
+ method,
+ params,
+ }),
+ });
+ const json: JsonRpcResponse = await resp.json();
+ if (json.error) throw new Error(`[${json.error.code}] ${json.error.message}`);
+ return json.result!;
+}
+
+// ── Agent Discovery ──
+const agentCard = await fetch(`${BASE_URL}/.well-known/agent.json`).then((r) => r.json());
+console.log(`Connected to: ${agentCard.name} (${agentCard.skills.length} skills)`);
+
+// ── Smart Routing: Send a coding task ──
+const routingResult = await a2aCall("message/send", {
+ skill: "smart-routing",
+ messages: [{ role: "user", content: "Implement a Redis cache wrapper in TypeScript" }],
+ metadata: { model: "claude-sonnet-4", role: "coding" },
+});
+console.log("Response:", routingResult.artifacts[0].content);
+console.log("Provider:", routingResult.metadata.routing_explanation);
+
+// ── Quota Management: Find free alternatives ──
+const quotaResult = await a2aCall("message/send", {
+ skill: "quota-management",
+ messages: [{ role: "user", content: "Suggest free combos for documentation" }],
+});
+console.log("Free combos:", quotaResult.artifacts[0].content);
+
+// ── Streaming: Real-time response ──
+const streamResp = await fetch(`${BASE_URL}/a2a`, {
+ method: "POST",
+ headers: {
+ "Content-Type": "application/json",
+ Authorization: `Bearer ${API_KEY}`,
+ },
+ body: JSON.stringify({
+ jsonrpc: "2.0",
+ id: "stream-1",
+ method: "message/stream",
+ params: {
+ skill: "smart-routing",
+ messages: [{ role: "user", content: "Explain microservices architecture" }],
+ },
+ }),
+});
+
+const reader = streamResp.body!.getReader();
+const decoder = new TextDecoder();
+while (true) {
+ const { done, value } = await reader.read();
+ if (done) break;
+ const chunk = decoder.decode(value);
+ for (const line of chunk.split("\n")) {
+ if (line.startsWith("data: ")) {
+ const event = JSON.parse(line.slice(6));
+ if (event.params.chunk) {
+ process.stdout.write(event.params.chunk.content);
+ }
+ if (event.params.task.state === "completed") {
+ console.log("\n✅ Stream completed");
+ }
+ }
+ }
+}
+```
+
+### Python — LangChain A2A Integration
+
+```python
+"""
+LangChain integration — Use OmniRoute A2A as a custom LLM.
+"""
+from langchain.llms.base import BaseLLM
+from langchain.schema import LLMResult, Generation
+import requests
+from typing import List, Optional
+
+class OmniRouteA2A(BaseLLM):
+ base_url: str = "http://localhost:20128"
+ api_key: str = ""
+ model: str = "auto"
+ combo: Optional[str] = None
+
+ @property
+ def _llm_type(self) -> str:
+ return "omniroute-a2a"
+
+ def _call(self, prompt: str, stop: Optional[List[str]] = None, **kwargs) -> str:
+ response = requests.post(
+ f"{self.base_url}/a2a",
+ headers={
+ "Content-Type": "application/json",
+ "Authorization": f"Bearer {self.api_key}",
+ },
+ json={
+ "jsonrpc": "2.0",
+ "id": "langchain-1",
+ "method": "message/send",
+ "params": {
+ "skill": "smart-routing",
+ "messages": [{"role": "user", "content": prompt}],
+ "metadata": {
+ "model": self.model,
+ **({"combo": self.combo} if self.combo else {}),
+ },
+ },
+ },
+ )
+ result = response.json()["result"]
+ return result["artifacts"][0]["content"]
+
+ def _generate(self, prompts: List[str], stop=None, **kwargs) -> LLMResult:
+ return LLMResult(
+ generations=[[Generation(text=self._call(p, stop))] for p in prompts]
+ )
+
+# Usage
+llm = OmniRouteA2A(
+ base_url="http://localhost:20128",
+ api_key="your-key",
+ model="auto",
+ combo="fast-coding",
+)
+result = llm("Write a Python function to merge two sorted lists")
+print(result)
+```
+
+### Go — A2A Client
+
+```go
+package main
+
+import (
+ "bytes"
+ "encoding/json"
+ "fmt"
+ "io"
+ "net/http"
+)
+
+const baseURL = "http://localhost:20128"
+const apiKey = "your-api-key"
+
+type JsonRpcRequest struct {
+ Jsonrpc string `json:"jsonrpc"`
+ ID string `json:"id"`
+ Method string `json:"method"`
+ Params interface{} `json:"params"`
+}
+
+type JsonRpcResponse struct {
+ Jsonrpc string `json:"jsonrpc"`
+ ID string `json:"id"`
+ Result interface{} `json:"result"`
+ Error *struct {
+ Code int `json:"code"`
+ Message string `json:"message"`
+ } `json:"error"`
+}
+
+func a2aCall(method string, params interface{}) (*JsonRpcResponse, error) {
+ body, _ := json.Marshal(JsonRpcRequest{
+ Jsonrpc: "2.0",
+ ID: "go-1",
+ Method: method,
+ Params: params,
+ })
+
+ req, _ := http.NewRequest("POST", baseURL+"/a2a", bytes.NewReader(body))
+ req.Header.Set("Content-Type", "application/json")
+ req.Header.Set("Authorization", "Bearer "+apiKey)
+
+ resp, err := http.DefaultClient.Do(req)
+ if err != nil {
+ return nil, err
+ }
+ defer resp.Body.Close()
+ data, _ := io.ReadAll(resp.Body)
+
+ var result JsonRpcResponse
+ json.Unmarshal(data, &result)
+ return &result, nil
+}
+
+func main() {
+ // Discover agent
+ resp, _ := http.Get(baseURL + "/.well-known/agent.json")
+ defer resp.Body.Close()
+ body, _ := io.ReadAll(resp.Body)
+ fmt.Println("Agent Card:", string(body))
+
+ // Send smart-routing task
+ result, _ := a2aCall("message/send", map[string]interface{}{
+ "skill": "smart-routing",
+ "messages": []map[string]string{{"role": "user", "content": "Hello from Go!"}},
+ "metadata": map[string]interface{}{"model": "auto"},
+ })
+ out, _ := json.MarshalIndent(result.Result, "", " ")
+ fmt.Println("Result:", string(out))
+}
+```
+
+---
+
+## Use Cases
+
+### 🤖 Use Case 1: Multi-Agent Coding Pipeline
+
+An orchestrator agent delegates code generation to OmniRoute, then passes the output to a review agent.
+
+```python
+def coding_pipeline(task: str):
+ # Step 1: Generate code via OmniRoute A2A
+ code_result = a2a_send("smart-routing", [
+ {"role": "user", "content": f"Write production-quality code: {task}"}
+ ], metadata={"model": "auto", "role": "coding"})
+ code = code_result["artifacts"][0]["content"]
+
+ # Step 2: Review the code via OmniRoute A2A (different model)
+ review_result = a2a_send("smart-routing", [
+ {"role": "user", "content": f"Review this code for bugs and improvements:\n\n{code}"}
+ ], metadata={"model": "auto", "role": "review"})
+ review = review_result["artifacts"][0]["content"]
+
+ # Step 3: Check costs
+ print(f"Code cost: ${code_result['metadata']['cost_envelope']['actual']}")
+ print(f"Review cost: ${review_result['metadata']['cost_envelope']['actual']}")
+
+ return {"code": code, "review": review}
+```
+
+### 💡 Use Case 2: Quota-Aware Agent Swarm
+
+Multiple agents share quota through OmniRoute, using the quota skill to coordinate.
+
+```python
+async def quota_aware_agent(agent_name: str, task: str):
+ # Check quota before starting
+ quota = a2a_send("quota-management", [
+ {"role": "user", "content": "Which provider has the most quota remaining?"}
+ ])
+ print(f"[{agent_name}] {quota['artifacts'][0]['content']}")
+
+ # Send request with budget constraint
+ result = a2a_send("smart-routing", [
+ {"role": "user", "content": task}
+ ], metadata={"budget": 0.05})
+
+ policy = result["metadata"]["policy_verdict"]
+ if not policy["allowed"]:
+ print(f"[{agent_name}] ⚠️ Budget exceeded: {policy['reason']}")
+ # Fall back to free combo
+ quota = a2a_send("quota-management", [
+ {"role": "user", "content": "Suggest free combos"}
+ ])
+ print(f"[{agent_name}] Free alternatives: {quota['artifacts'][0]['content']}")
+
+ return result
+```
+
+### 📊 Use Case 3: Real-Time Streaming Dashboard
+
+A monitoring agent streams responses and displays progress in real-time.
+
+```typescript
+async function streamingDashboard(prompt: string) {
+ const response = await fetch(`${BASE_URL}/a2a`, {
+ method: "POST",
+ headers: { "Content-Type": "application/json", Authorization: `Bearer ${API_KEY}` },
+ body: JSON.stringify({
+ jsonrpc: "2.0",
+ id: "dash-1",
+ method: "message/stream",
+ params: { skill: "smart-routing", messages: [{ role: "user", content: prompt }] },
+ }),
+ });
+
+ let totalChunks = 0;
+ const reader = response.body!.getReader();
+ const decoder = new TextDecoder();
+
+ while (true) {
+ const { done, value } = await reader.read();
+ if (done) break;
+
+ for (const line of decoder.decode(value).split("\n")) {
+ if (line.startsWith("data: ")) {
+ const event = JSON.parse(line.slice(6));
+ const state = event.params.task.state;
+
+ if (state === "working" && event.params.chunk) {
+ totalChunks++;
+ process.stdout.write(
+ `\r[Chunk ${totalChunks}] ${event.params.chunk.content.slice(0, 50)}...`
+ );
+ }
+ if (state === "completed") {
+ const meta = event.params.metadata;
+ console.log(
+ `\n✅ Done | Cost: $${meta?.cost_envelope?.actual || 0} | Route: ${meta?.routing_explanation || "N/A"}`
+ );
+ }
+ if (state === "failed") {
+ console.error(`\n❌ Failed: ${event.params.metadata?.error}`);
+ }
+ }
+ }
+ }
+}
+```
+
+### 🔁 Use Case 4: Task Polling Pattern
+
+For long-running tasks, poll the task status instead of waiting synchronously.
+
+```python
+import time
+
+def poll_task(task_id: str, timeout: int = 60):
+ """Poll task status until completion or timeout."""
+ start = time.time()
+ while time.time() - start < timeout:
+ result = requests.post(f"{BASE_URL}/a2a", headers=HEADERS, json={
+ "jsonrpc": "2.0",
+ "id": "poll-1",
+ "method": "tasks/get",
+ "params": {"taskId": task_id},
+ }).json()
+
+ task = result["result"]["task"]
+ state = task["state"]
+ print(f" Task {task_id[:8]}... state={state}")
+
+ if state in ("completed", "failed", "cancelled"):
+ return task
+ time.sleep(2)
+
+ # Timeout — cancel the task
+ requests.post(f"{BASE_URL}/a2a", headers=HEADERS, json={
+ "jsonrpc": "2.0",
+ "id": "cancel-1",
+ "method": "tasks/cancel",
+ "params": {"taskId": task_id},
+ })
+ raise TimeoutError(f"Task {task_id} timed out after {timeout}s")
+```
+
+---
+
+## Error Codes
+
+| Code | Constant | Meaning |
+| ------ | ------------------------ | ---------------------------------------- |
+| -32700 | — | Parse error (invalid JSON) |
+| -32600 | `INVALID_REQUEST` | Invalid JSON-RPC request or unauthorized |
+| -32601 | `METHOD_NOT_FOUND` | Unknown method or skill |
+| -32602 | `INVALID_PARAMS` | Missing or invalid parameters |
+| -32603 | `INTERNAL_ERROR` | Skill execution failed |
+| -32001 | `TASK_NOT_FOUND` | Task ID not found |
+| -32002 | `TASK_ALREADY_COMPLETED` | Cannot modify a completed task |
+| -32003 | `UNAUTHORIZED` | Invalid or missing API key |
+| -32004 | `BUDGET_EXCEEDED` | Request exceeds configured budget |
+| -32005 | `PROVIDER_UNAVAILABLE` | No available providers |
+
+---
+
+## Authentication
+
+All `/a2a` requests require a Bearer token via the `Authorization` header:
+
+```
+Authorization: Bearer YOUR_OMNIROUTE_API_KEY
+```
+
+If no API key is configured on the server (`OMNIROUTE_API_KEY` is empty), authentication is bypassed.
+
+---
+
+## File Structure
+
+```
+src/lib/a2a/
+├── taskManager.ts # Task lifecycle (create/update/cancel/list), TTL, cleanup
+├── taskExecution.ts # Generic task executor with state management
+├── streaming.ts # SSE stream formatting, heartbeat, chunk/completion events
+├── routingLogger.ts # Routing decision logger (stats, history, retention)
+└── skills/
+ ├── smartRouting.ts # Smart routing skill (routes via /v1/chat/completions)
+ └── quotaManagement.ts # Quota management skill (natural-language quota queries)
+
+src/app/a2a/
+└── route.ts # Next.js API route handler (JSON-RPC 2.0 dispatch)
+
+open-sse/mcp-server/
+└── schemas/a2a.ts # Zod schemas (AgentCard, Task, JSON-RPC, SSE events)
+```
+
+---
+
+## Comparison: MCP vs A2A
+
+| Feature | MCP Server | A2A Server |
+| ----------------- | ---------------------------- | ------------------------------------------------- |
+| **Protocol** | Model Context Protocol | Agent-to-Agent Protocol v0.3 |
+| **Transport** | stdio / HTTP | HTTP (JSON-RPC 2.0) |
+| **Discovery** | Tool listing via MCP | `/.well-known/agent.json` |
+| **Granularity** | 16 individual tools | 2 high-level skills |
+| **Best for** | IDE agents (Cursor, VS Code) | Multi-agent systems (LangChain, CrewAI) |
+| **Streaming** | Not supported | SSE via `message/stream` |
+| **Task tracking** | No | Full lifecycle (submitted → completed) |
+| **Observability** | Audit log per tool call | Cost envelope + resilience trace + policy verdict |
+
+---
+
+## רישיון
+
+Part of [OmniRoute](https://github.com/diegosouzapw/OmniRoute) — MIT License.
diff --git a/docs/i18n/hu/A2A-SERVER.md b/docs/i18n/hu/A2A-SERVER.md
deleted file mode 100644
index 01531ff482..0000000000
--- a/docs/i18n/hu/A2A-SERVER.md
+++ /dev/null
@@ -1,200 +0,0 @@
-🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/A2A-SERVER.md) · 🇪🇸 [es](../es/A2A-SERVER.md) · 🇫🇷 [fr](../fr/A2A-SERVER.md) · 🇩🇪 [de](../de/A2A-SERVER.md) · 🇮🇹 [it](../it/A2A-SERVER.md) · 🇷🇺 [ru](../ru/A2A-SERVER.md) · 🇨🇳 [zh-CN](../zh-CN/A2A-SERVER.md) · 🇯🇵 [ja](../ja/A2A-SERVER.md) · 🇰🇷 [ko](../ko/A2A-SERVER.md) · 🇸🇦 [ar](../ar/A2A-SERVER.md) · 🇮🇳 [in](../in/A2A-SERVER.md) · 🇹🇭 [th](../th/A2A-SERVER.md) · 🇻🇳 [vi](../vi/A2A-SERVER.md) · 🇮🇩 [id](../id/A2A-SERVER.md) · 🇲🇾 [ms](../ms/A2A-SERVER.md) · 🇳🇱 [nl](../nl/A2A-SERVER.md) · 🇵🇱 [pl](../pl/A2A-SERVER.md) · 🇸🇪 [sv](../sv/A2A-SERVER.md) · 🇳🇴 [no](../no/A2A-SERVER.md) · 🇩🇰 [da](../da/A2A-SERVER.md) · 🇫🇮 [fi](../fi/A2A-SERVER.md) · 🇵🇹 [pt](../pt/A2A-SERVER.md) · 🇷🇴 [ro](../ro/A2A-SERVER.md) · 🇭🇺 [hu](../hu/A2A-SERVER.md) · 🇧🇬 [bg](../bg/A2A-SERVER.md) · 🇸🇰 [sk](../sk/A2A-SERVER.md) · 🇺🇦 [uk-UA](../uk-UA/A2A-SERVER.md) · 🇮🇱 [he](../he/A2A-SERVER.md) · 🇵🇭 [phi](../phi/A2A-SERVER.md)
-
----
-
-# OmniRoute A2A Server Documentation
-
-> Agent-to-Agent Protocol v0.3 — OmniRoute as an intelligent routing agent
-
-## Agent Discovery
-
-```bash
-curl http://localhost:20128/.well-known/agent.json
-```
-
-Returns the Agent Card describing OmniRoute's capabilities, skills, and authentication requirements.
-
----
-
-## Authentication
-
-All `/a2a` requests require an API key via the `Authorization` header:
-
-```
-Authorization: Bearer YOUR_OMNIROUTE_API_KEY
-```
-
-If no API key is configured on the server, authentication is bypassed.
-
----
-
-## JSON-RPC 2.0 Methods
-
-### `message/send` — Synchronous Execution
-
-Sends a message to a skill and waits for the complete response.
-
-```bash
-curl -X POST http://localhost:20128/a2a \
- -H "Content-Type: application/json" \
- -H "Authorization: Bearer YOUR_KEY" \
- -d '{
- "jsonrpc": "2.0",
- "id": "1",
- "method": "message/send",
- "params": {
- "skill": "smart-routing",
- "messages": [{"role": "user", "content": "Write a hello world in Python"}],
- "metadata": {"model": "auto", "combo": "fast-coding"}
- }
- }'
-```
-
-**Response:**
-
-```json
-{
- "jsonrpc": "2.0",
- "id": "1",
- "result": {
- "task": { "id": "uuid", "state": "completed" },
- "artifacts": [{ "type": "text", "content": "..." }],
- "metadata": {
- "routing_explanation": "Selected claude-sonnet via provider \"anthropic\" (latency: 1200ms, cost: $0.003)",
- "cost_envelope": { "estimated": 0.005, "actual": 0.003, "currency": "USD" },
- "resilience_trace": [
- { "event": "primary_selected", "provider": "anthropic", "timestamp": "..." }
- ],
- "policy_verdict": { "allowed": true, "reason": "within budget and quota limits" }
- }
- }
-}
-```
-
-### `message/stream` — SSE Streaming
-
-Same as `message/send` but returns Server-Sent Events for real-time streaming.
-
-```bash
-curl -N -X POST http://localhost:20128/a2a \
- -H "Content-Type: application/json" \
- -H "Authorization: Bearer YOUR_KEY" \
- -d '{
- "jsonrpc": "2.0",
- "id": "1",
- "method": "message/stream",
- "params": {
- "skill": "smart-routing",
- "messages": [{"role": "user", "content": "Explain quantum computing"}]
- }
- }'
-```
-
-**SSE Events:**
-
-```
-data: {"jsonrpc":"2.0","method":"message/stream","params":{"task":{"id":"...","state":"working"},"chunk":{"type":"text","content":"..."}}}
-
-: heartbeat 2026-03-03T17:00:00Z
-
-data: {"jsonrpc":"2.0","method":"message/stream","params":{"task":{"id":"...","state":"completed"},"metadata":{...}}}
-```
-
-### `tasks/get` — Query Task Status
-
-```bash
-curl -X POST http://localhost:20128/a2a \
- -H "Content-Type: application/json" \
- -H "Authorization: Bearer YOUR_KEY" \
- -d '{"jsonrpc":"2.0","id":"2","method":"tasks/get","params":{"taskId":"TASK_UUID"}}'
-```
-
-### `tasks/cancel` — Cancel a Task
-
-```bash
-curl -X POST http://localhost:20128/a2a \
- -H "Content-Type: application/json" \
- -H "Authorization: Bearer YOUR_KEY" \
- -d '{"jsonrpc":"2.0","id":"3","method":"tasks/cancel","params":{"taskId":"TASK_UUID"}}'
-```
-
----
-
-## Available Skills
-
-| Skill | Description |
-| :----------------- | :------------------------------------------------------------------------------------------------------------------------------ |
-| `smart-routing` | Routes prompts through OmniRoute's intelligent pipeline. Returns response with routing explanation, cost, and resilience trace. |
-| `quota-management` | Answers natural-language queries about provider quotas, suggests free combos, and provides quota rankings. |
-
----
-
-## Task Lifecycle
-
-```
-submitted → working → completed
- → failed
- → cancelled
-```
-
-- Tasks expire after 5 minutes (configurable)
-- Terminal states: `completed`, `failed`, `cancelled`
-- Event log tracks every state transition
-
----
-
-## Error Codes
-
-| Code | Meaning |
-| :----- | :----------------------------- |
-| -32700 | Parse error (invalid JSON) |
-| -32600 | Invalid request / Unauthorized |
-| -32601 | Method or skill not found |
-| -32602 | Invalid params |
-| -32603 | Internal error |
-
----
-
-## Integration Examples
-
-### Python (requests)
-
-```python
-import requests
-
-resp = requests.post("http://localhost:20128/a2a", json={
- "jsonrpc": "2.0", "id": "1",
- "method": "message/send",
- "params": {
- "skill": "smart-routing",
- "messages": [{"role": "user", "content": "Hello"}]
- }
-}, headers={"Authorization": "Bearer YOUR_KEY"})
-
-result = resp.json()["result"]
-print(result["artifacts"][0]["content"])
-print(result["metadata"]["routing_explanation"])
-```
-
-### TypeScript (fetch)
-
-```typescript
-const resp = await fetch("http://localhost:20128/a2a", {
- method: "POST",
- headers: {
- "Content-Type": "application/json",
- Authorization: "Bearer YOUR_KEY",
- },
- body: JSON.stringify({
- jsonrpc: "2.0",
- id: "1",
- method: "message/send",
- params: {
- skill: "smart-routing",
- messages: [{ role: "user", content: "Hello" }],
- },
- }),
-});
-const { result } = await resp.json();
-console.log(result.metadata.routing_explanation);
-```
diff --git a/docs/i18n/hu/API_REFERENCE.md b/docs/i18n/hu/API_REFERENCE.md
deleted file mode 100644
index b878605221..0000000000
--- a/docs/i18n/hu/API_REFERENCE.md
+++ /dev/null
@@ -1,455 +0,0 @@
-🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/API_REFERENCE.md) · 🇪🇸 [es](../es/API_REFERENCE.md) · 🇫🇷 [fr](../fr/API_REFERENCE.md) · 🇩🇪 [de](../de/API_REFERENCE.md) · 🇮🇹 [it](../it/API_REFERENCE.md) · 🇷🇺 [ru](../ru/API_REFERENCE.md) · 🇨🇳 [zh-CN](../zh-CN/API_REFERENCE.md) · 🇯🇵 [ja](../ja/API_REFERENCE.md) · 🇰🇷 [ko](../ko/API_REFERENCE.md) · 🇸🇦 [ar](../ar/API_REFERENCE.md) · 🇮🇳 [in](../in/API_REFERENCE.md) · 🇹🇭 [th](../th/API_REFERENCE.md) · 🇻🇳 [vi](../vi/API_REFERENCE.md) · 🇮🇩 [id](../id/API_REFERENCE.md) · 🇲🇾 [ms](../ms/API_REFERENCE.md) · 🇳🇱 [nl](../nl/API_REFERENCE.md) · 🇵🇱 [pl](../pl/API_REFERENCE.md) · 🇸🇪 [sv](../sv/API_REFERENCE.md) · 🇳🇴 [no](../no/API_REFERENCE.md) · 🇩🇰 [da](../da/API_REFERENCE.md) · 🇫🇮 [fi](../fi/API_REFERENCE.md) · 🇵🇹 [pt](../pt/API_REFERENCE.md) · 🇷🇴 [ro](../ro/API_REFERENCE.md) · 🇭🇺 [hu](../hu/API_REFERENCE.md) · 🇧🇬 [bg](../bg/API_REFERENCE.md) · 🇸🇰 [sk](../sk/API_REFERENCE.md) · 🇺🇦 [uk-UA](../uk-UA/API_REFERENCE.md) · 🇮🇱 [he](../he/API_REFERENCE.md) · 🇵🇭 [phi](../phi/API_REFERENCE.md)
-
----
-
-# API Reference
-
-🌐 **Languages:** 🇺🇸 [English](API_REFERENCE.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/API_REFERENCE.md) | 🇪🇸 [Español](i18n/es/API_REFERENCE.md) | 🇫🇷 [Français](i18n/fr/API_REFERENCE.md) | 🇮🇹 [Italiano](i18n/it/API_REFERENCE.md) | 🇷🇺 [Русский](i18n/ru/API_REFERENCE.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/API_REFERENCE.md) | 🇩🇪 [Deutsch](i18n/de/API_REFERENCE.md) | 🇮🇳 [हिन्दी](i18n/in/API_REFERENCE.md) | 🇹🇭 [ไทย](i18n/th/API_REFERENCE.md) | 🇺🇦 [Українська](i18n/uk-UA/API_REFERENCE.md) | 🇸🇦 [العربية](i18n/ar/API_REFERENCE.md) | 🇯🇵 [日本語](i18n/ja/API_REFERENCE.md) | 🇻🇳 [Tiếng Việt](i18n/vi/API_REFERENCE.md) | 🇧🇬 [Български](i18n/bg/API_REFERENCE.md) | 🇩🇰 [Dansk](i18n/da/API_REFERENCE.md) | 🇫🇮 [Suomi](i18n/fi/API_REFERENCE.md) | 🇮🇱 [עברית](i18n/he/API_REFERENCE.md) | 🇭🇺 [Magyar](i18n/hu/API_REFERENCE.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/API_REFERENCE.md) | 🇰🇷 [한국어](i18n/ko/API_REFERENCE.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/API_REFERENCE.md) | 🇳🇱 [Nederlands](i18n/nl/API_REFERENCE.md) | 🇳🇴 [Norsk](i18n/no/API_REFERENCE.md) | 🇵🇹 [Português (Portugal)](i18n/pt/API_REFERENCE.md) | 🇷🇴 [Română](i18n/ro/API_REFERENCE.md) | 🇵🇱 [Polski](i18n/pl/API_REFERENCE.md) | 🇸🇰 [Slovenčina](i18n/sk/API_REFERENCE.md) | 🇸🇪 [Svenska](i18n/sv/API_REFERENCE.md) | 🇵🇭 [Filipino](i18n/phi/API_REFERENCE.md)
-
-Complete reference for all OmniRoute API endpoints.
-
----
-
-## Table of Contents
-
-- [Chat Completions](#chat-completions)
-- [Embeddings](#embeddings)
-- [Image Generation](#image-generation)
-- [List Models](#list-models)
-- [Compatibility Endpoints](#compatibility-endpoints)
-- [Semantic Cache](#semantic-cache)
-- [Dashboard & Management](#dashboard--management)
-- [Request Processing](#request-processing)
-- [Authentication](#authentication)
-
----
-
-## Chat Completions
-
-```bash
-POST /v1/chat/completions
-Authorization: Bearer your-api-key
-Content-Type: application/json
-
-{
- "model": "cc/claude-opus-4-6",
- "messages": [
- {"role": "user", "content": "Write a function to..."}
- ],
- "stream": true
-}
-```
-
-### Custom Headers
-
-| Header | Direction | Description |
-| ------------------------ | --------- | --------------------------------- |
-| `X-OmniRoute-No-Cache` | Request | Set to `true` to bypass cache |
-| `X-OmniRoute-Progress` | Request | Set to `true` for progress events |
-| `Idempotency-Key` | Request | Dedup key (5s window) |
-| `X-Request-Id` | Request | Alternative dedup key |
-| `X-OmniRoute-Cache` | Response | `HIT` or `MISS` (non-streaming) |
-| `X-OmniRoute-Idempotent` | Response | `true` if deduplicated |
-| `X-OmniRoute-Progress` | Response | `enabled` if progress tracking on |
-
----
-
-## Embeddings
-
-```bash
-POST /v1/embeddings
-Authorization: Bearer your-api-key
-Content-Type: application/json
-
-{
- "model": "nebius/Qwen/Qwen3-Embedding-8B",
- "input": "The food was delicious"
-}
-```
-
-Available providers: Nebius, OpenAI, Mistral, Together AI, Fireworks, NVIDIA.
-
-```bash
-# List all embedding models
-GET /v1/embeddings
-```
-
----
-
-## Image Generation
-
-```bash
-POST /v1/images/generations
-Authorization: Bearer your-api-key
-Content-Type: application/json
-
-{
- "model": "openai/dall-e-3",
- "prompt": "A beautiful sunset over mountains",
- "size": "1024x1024"
-}
-```
-
-Available providers: OpenAI (DALL-E), xAI (Grok Image), Together AI (FLUX), Fireworks AI.
-
-```bash
-# List all image models
-GET /v1/images/generations
-```
-
----
-
-## List Models
-
-```bash
-GET /v1/models
-Authorization: Bearer your-api-key
-
-→ Returns all chat, embedding, and image models + combos in OpenAI format
-```
-
----
-
-## Compatibility Endpoints
-
-| Method | Path | Format |
-| ------ | --------------------------- | ---------------------- |
-| POST | `/v1/chat/completions` | OpenAI |
-| POST | `/v1/messages` | Anthropic |
-| POST | `/v1/responses` | OpenAI Responses |
-| POST | `/v1/embeddings` | OpenAI |
-| POST | `/v1/images/generations` | OpenAI |
-| GET | `/v1/models` | OpenAI |
-| POST | `/v1/messages/count_tokens` | Anthropic |
-| GET | `/v1beta/models` | Gemini |
-| POST | `/v1beta/models/{...path}` | Gemini generateContent |
-| POST | `/v1/api/chat` | Ollama |
-
-### Dedicated Provider Routes
-
-```bash
-POST /v1/providers/{provider}/chat/completions
-POST /v1/providers/{provider}/embeddings
-POST /v1/providers/{provider}/images/generations
-```
-
-The provider prefix is auto-added if missing. Mismatched models return `400`.
-
----
-
-## Semantic Cache
-
-```bash
-# Get cache stats
-GET /api/cache
-
-# Clear all caches
-DELETE /api/cache
-```
-
-Response example:
-
-```json
-{
- "semanticCache": {
- "memorySize": 42,
- "memoryMaxSize": 500,
- "dbSize": 128,
- "hitRate": 0.65
- },
- "idempotency": {
- "activeKeys": 3,
- "windowMs": 5000
- }
-}
-```
-
----
-
-## Dashboard & Management
-
-### Authentication
-
-| Endpoint | Method | Description |
-| ----------------------------- | ------- | --------------------- |
-| `/api/auth/login` | POST | Login |
-| `/api/auth/logout` | POST | Logout |
-| `/api/settings/require-login` | GET/PUT | Toggle login required |
-
-### Provider Management
-
-| Endpoint | Method | Description |
-| ---------------------------- | --------------- | ------------------------ |
-| `/api/providers` | GET/POST | List / create providers |
-| `/api/providers/[id]` | GET/PUT/DELETE | Manage a provider |
-| `/api/providers/[id]/test` | POST | Test provider connection |
-| `/api/providers/[id]/models` | GET | List provider models |
-| `/api/providers/validate` | POST | Validate provider config |
-| `/api/provider-nodes*` | Various | Provider node management |
-| `/api/provider-models` | GET/POST/DELETE | Custom models |
-
-### OAuth Flows
-
-| Endpoint | Method | Description |
-| -------------------------------- | ------- | ----------------------- |
-| `/api/oauth/[provider]/[action]` | Various | Provider-specific OAuth |
-
-### Routing & Config
-
-| Endpoint | Method | Description |
-| --------------------- | -------- | ----------------------------- |
-| `/api/models/alias` | GET/POST | Model aliases |
-| `/api/models/catalog` | GET | All models by provider + type |
-| `/api/combos*` | Various | Combo management |
-| `/api/keys*` | Various | API key management |
-| `/api/pricing` | GET | Model pricing |
-
-### Usage & Analytics
-
-| Endpoint | Method | Description |
-| --------------------------- | ------ | -------------------- |
-| `/api/usage/history` | GET | Usage history |
-| `/api/usage/logs` | GET | Usage logs |
-| `/api/usage/request-logs` | GET | Request-level logs |
-| `/api/usage/[connectionId]` | GET | Per-connection usage |
-
-### Settings
-
-| Endpoint | Method | Description |
-| ------------------------------- | ------- | ---------------------- |
-| `/api/settings` | GET/PUT | General settings |
-| `/api/settings/proxy` | GET/PUT | Network proxy config |
-| `/api/settings/proxy/test` | POST | Test proxy connection |
-| `/api/settings/ip-filter` | GET/PUT | IP allowlist/blocklist |
-| `/api/settings/thinking-budget` | GET/PUT | Reasoning token budget |
-| `/api/settings/system-prompt` | GET/PUT | Global system prompt |
-
-### Monitoring
-
-| Endpoint | Method | Description |
-| ------------------------ | ---------- | ----------------------- |
-| `/api/sessions` | GET | Active session tracking |
-| `/api/rate-limits` | GET | Per-account rate limits |
-| `/api/monitoring/health` | GET | Health check |
-| `/api/cache` | GET/DELETE | Cache stats / clear |
-
-### Backup & Export/Import
-
-| Endpoint | Method | Description |
-| --------------------------- | ------ | --------------------------------------- |
-| `/api/db-backups` | GET | List available backups |
-| `/api/db-backups` | PUT | Create a manual backup |
-| `/api/db-backups` | POST | Restore from a specific backup |
-| `/api/db-backups/export` | GET | Download database as .sqlite file |
-| `/api/db-backups/import` | POST | Upload .sqlite file to replace database |
-| `/api/db-backups/exportAll` | GET | Download full backup as .tar.gz archive |
-
-### Cloud Sync
-
-| Endpoint | Method | Description |
-| ---------------------- | ------- | --------------------- |
-| `/api/sync/cloud` | Various | Cloud sync operations |
-| `/api/sync/initialize` | POST | Initialize sync |
-| `/api/cloud/*` | Various | Cloud management |
-
-### CLI Tools
-
-| Endpoint | Method | Description |
-| ---------------------------------- | ------ | ------------------- |
-| `/api/cli-tools/claude-settings` | GET | Claude CLI status |
-| `/api/cli-tools/codex-settings` | GET | Codex CLI status |
-| `/api/cli-tools/droid-settings` | GET | Droid CLI status |
-| `/api/cli-tools/openclaw-settings` | GET | OpenClaw CLI status |
-| `/api/cli-tools/runtime/[toolId]` | GET | Generic CLI runtime |
-
-CLI responses include: `installed`, `runnable`, `command`, `commandPath`, `runtimeMode`, `reason`.
-
-### ACP Agents
-
-| Endpoint | Method | Description |
-| ----------------- | ------ | -------------------------------------------------------- |
-| `/api/acp/agents` | GET | List all detected agents (built-in + custom) with status |
-| `/api/acp/agents` | POST | Add custom agent or refresh detection cache |
-| `/api/acp/agents` | DELETE | Remove a custom agent by `id` query param |
-
-GET response includes `agents[]` (id, name, binary, version, installed, protocol, isCustom) and `summary` (total, installed, notFound, builtIn, custom).
-
-### Resilience & Rate Limits
-
-| Endpoint | Method | Description |
-| ----------------------- | ------- | ------------------------------- |
-| `/api/resilience` | GET/PUT | Get/update resilience profiles |
-| `/api/resilience/reset` | POST | Reset circuit breakers |
-| `/api/rate-limits` | GET | Per-account rate limit status |
-| `/api/rate-limit` | GET | Global rate limit configuration |
-
-### Evals
-
-| Endpoint | Method | Description |
-| ------------ | -------- | --------------------------------- |
-| `/api/evals` | GET/POST | List eval suites / run evaluation |
-
-### Policies
-
-| Endpoint | Method | Description |
-| --------------- | --------------- | ----------------------- |
-| `/api/policies` | GET/POST/DELETE | Manage routing policies |
-
-### Compliance
-
-| Endpoint | Method | Description |
-| --------------------------- | ------ | ----------------------------- |
-| `/api/compliance/audit-log` | GET | Compliance audit log (last N) |
-
-### v1beta (Gemini-Compatible)
-
-| Endpoint | Method | Description |
-| -------------------------- | ------ | --------------------------------- |
-| `/v1beta/models` | GET | List models in Gemini format |
-| `/v1beta/models/{...path}` | POST | Gemini `generateContent` endpoint |
-
-These endpoints mirror Gemini's API format for clients that expect native Gemini SDK compatibility.
-
-### Internal / System APIs
-
-| Endpoint | Method | Description |
-| --------------- | ------ | ---------------------------------------------------- |
-| `/api/init` | GET | Application initialization check (used on first run) |
-| `/api/tags` | GET | Ollama-compatible model tags (for Ollama clients) |
-| `/api/restart` | POST | Trigger graceful server restart |
-| `/api/shutdown` | POST | Trigger graceful server shutdown |
-
-> **Note:** These endpoints are used internally by the system or for Ollama client compatibility. They are not typically called by end users.
-
----
-
-## Audio Transcription
-
-```bash
-POST /v1/audio/transcriptions
-Authorization: Bearer your-api-key
-Content-Type: multipart/form-data
-```
-
-Transcribe audio files using Deepgram or AssemblyAI.
-
-**Request:**
-
-```bash
-curl -X POST http://localhost:20128/v1/audio/transcriptions \
- -H "Authorization: Bearer your-api-key" \
- -F "file=@recording.mp3" \
- -F "model=deepgram/nova-3"
-```
-
-**Response:**
-
-```json
-{
- "text": "Hello, this is the transcribed audio content.",
- "task": "transcribe",
- "language": "en",
- "duration": 12.5
-}
-```
-
-**Supported providers:** `deepgram/nova-3`, `assemblyai/best`.
-
-**Supported formats:** `mp3`, `wav`, `m4a`, `flac`, `ogg`, `webm`.
-
----
-
-## Ollama Compatibility
-
-For clients that use Ollama's API format:
-
-```bash
-# Chat endpoint (Ollama format)
-POST /v1/api/chat
-
-# Model listing (Ollama format)
-GET /api/tags
-```
-
-Requests are automatically translated between Ollama and internal formats.
-
----
-
-## Telemetry
-
-```bash
-# Get latency telemetry summary (p50/p95/p99 per provider)
-GET /api/telemetry/summary
-```
-
-**Response:**
-
-```json
-{
- "providers": {
- "claudeCode": { "p50": 245, "p95": 890, "p99": 1200, "count": 150 },
- "github": { "p50": 180, "p95": 620, "p99": 950, "count": 320 }
- }
-}
-```
-
----
-
-## Budget
-
-```bash
-# Get budget status for all API keys
-GET /api/usage/budget
-
-# Set or update a budget
-POST /api/usage/budget
-Content-Type: application/json
-
-{
- "keyId": "key-123",
- "limit": 50.00,
- "period": "monthly"
-}
-```
-
----
-
-## Model Availability
-
-```bash
-# Get real-time model availability across all providers
-GET /api/models/availability
-
-# Check availability for a specific model
-POST /api/models/availability
-Content-Type: application/json
-
-{
- "model": "claude-sonnet-4-5-20250929"
-}
-```
-
----
-
-## Request Processing
-
-1. Client sends request to `/v1/*`
-2. Route handler calls `handleChat`, `handleEmbedding`, `handleAudioTranscription`, or `handleImageGeneration`
-3. Model is resolved (direct provider/model or alias/combo)
-4. Credentials selected from local DB with account availability filtering
-5. For chat: `handleChatCore` — format detection, translation, cache check, idempotency check
-6. Provider executor sends upstream request
-7. Response translated back to client format (chat) or returned as-is (embeddings/images/audio)
-8. Usage/logging recorded
-9. Fallback applies on errors according to combo rules
-
-Full architecture reference: [`ARCHITECTURE.md`](ARCHITECTURE.md)
-
----
-
-## Authentication
-
-- Dashboard routes (`/dashboard/*`) use `auth_token` cookie
-- Login uses saved password hash; fallback to `INITIAL_PASSWORD`
-- `requireLogin` toggleable via `/api/settings/require-login`
-- `/v1/*` routes optionally require Bearer API key when `REQUIRE_API_KEY=true`
diff --git a/docs/i18n/hu/ARCHITECTURE.md b/docs/i18n/hu/ARCHITECTURE.md
deleted file mode 100644
index 4ea06a29f2..0000000000
--- a/docs/i18n/hu/ARCHITECTURE.md
+++ /dev/null
@@ -1,787 +0,0 @@
-🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/ARCHITECTURE.md) · 🇪🇸 [es](../es/ARCHITECTURE.md) · 🇫🇷 [fr](../fr/ARCHITECTURE.md) · 🇩🇪 [de](../de/ARCHITECTURE.md) · 🇮🇹 [it](../it/ARCHITECTURE.md) · 🇷🇺 [ru](../ru/ARCHITECTURE.md) · 🇨🇳 [zh-CN](../zh-CN/ARCHITECTURE.md) · 🇯🇵 [ja](../ja/ARCHITECTURE.md) · 🇰🇷 [ko](../ko/ARCHITECTURE.md) · 🇸🇦 [ar](../ar/ARCHITECTURE.md) · 🇮🇳 [in](../in/ARCHITECTURE.md) · 🇹🇭 [th](../th/ARCHITECTURE.md) · 🇻🇳 [vi](../vi/ARCHITECTURE.md) · 🇮🇩 [id](../id/ARCHITECTURE.md) · 🇲🇾 [ms](../ms/ARCHITECTURE.md) · 🇳🇱 [nl](../nl/ARCHITECTURE.md) · 🇵🇱 [pl](../pl/ARCHITECTURE.md) · 🇸🇪 [sv](../sv/ARCHITECTURE.md) · 🇳🇴 [no](../no/ARCHITECTURE.md) · 🇩🇰 [da](../da/ARCHITECTURE.md) · 🇫🇮 [fi](../fi/ARCHITECTURE.md) · 🇵🇹 [pt](../pt/ARCHITECTURE.md) · 🇷🇴 [ro](../ro/ARCHITECTURE.md) · 🇭🇺 [hu](../hu/ARCHITECTURE.md) · 🇧🇬 [bg](../bg/ARCHITECTURE.md) · 🇸🇰 [sk](../sk/ARCHITECTURE.md) · 🇺🇦 [uk-UA](../uk-UA/ARCHITECTURE.md) · 🇮🇱 [he](../he/ARCHITECTURE.md) · 🇵🇭 [phi](../phi/ARCHITECTURE.md)
-
----
-
-# OmniRoute Architecture
-
-🌐 **Languages:** 🇺🇸 [English](ARCHITECTURE.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/ARCHITECTURE.md) | 🇪🇸 [Español](i18n/es/ARCHITECTURE.md) | 🇫🇷 [Français](i18n/fr/ARCHITECTURE.md) | 🇮🇹 [Italiano](i18n/it/ARCHITECTURE.md) | 🇷🇺 [Русский](i18n/ru/ARCHITECTURE.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/ARCHITECTURE.md) | 🇩🇪 [Deutsch](i18n/de/ARCHITECTURE.md) | 🇮🇳 [हिन्दी](i18n/in/ARCHITECTURE.md) | 🇹🇭 [ไทย](i18n/th/ARCHITECTURE.md) | 🇺🇦 [Українська](i18n/uk-UA/ARCHITECTURE.md) | 🇸🇦 [العربية](i18n/ar/ARCHITECTURE.md) | 🇯🇵 [日本語](i18n/ja/ARCHITECTURE.md) | 🇻🇳 [Tiếng Việt](i18n/vi/ARCHITECTURE.md) | 🇧🇬 [Български](i18n/bg/ARCHITECTURE.md) | 🇩🇰 [Dansk](i18n/da/ARCHITECTURE.md) | 🇫🇮 [Suomi](i18n/fi/ARCHITECTURE.md) | 🇮🇱 [עברית](i18n/he/ARCHITECTURE.md) | 🇭🇺 [Magyar](i18n/hu/ARCHITECTURE.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/ARCHITECTURE.md) | 🇰🇷 [한국어](i18n/ko/ARCHITECTURE.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/ARCHITECTURE.md) | 🇳🇱 [Nederlands](i18n/nl/ARCHITECTURE.md) | 🇳🇴 [Norsk](i18n/no/ARCHITECTURE.md) | 🇵🇹 [Português (Portugal)](i18n/pt/ARCHITECTURE.md) | 🇷🇴 [Română](i18n/ro/ARCHITECTURE.md) | 🇵🇱 [Polski](i18n/pl/ARCHITECTURE.md) | 🇸🇰 [Slovenčina](i18n/sk/ARCHITECTURE.md) | 🇸🇪 [Svenska](i18n/sv/ARCHITECTURE.md) | 🇵🇭 [Filipino](i18n/phi/ARCHITECTURE.md)
-
-_Last updated: 2026-03-04_
-
-## Executive Summary
-
-OmniRoute is a local AI routing gateway and dashboard built on Next.js.
-It provides a single OpenAI-compatible endpoint (`/v1/*`) and routes traffic across multiple upstream providers with translation, fallback, token refresh, and usage tracking.
-
-Core capabilities:
-
-- OpenAI-compatible API surface for CLI/tools (28 providers)
-- Request/response translation across provider formats
-- Model combo fallback (multi-model sequence)
-- Account-level fallback (multi-account per provider)
-- OAuth + API-key provider connection management
-- Embedding generation via `/v1/embeddings` (6 providers, 9 models)
-- Image generation via `/v1/images/generations` (4 providers, 9 models)
-- Think tag parsing (`...`) for reasoning models
-- Response sanitization for strict OpenAI SDK compatibility
-- Role normalization (developer→system, system→user) for cross-provider compatibility
-- Structured output conversion (json_schema → Gemini responseSchema)
-- Local persistence for providers, keys, aliases, combos, settings, pricing
-- Usage/cost tracking and request logging
-- Optional cloud sync for multi-device/state sync
-- IP allowlist/blocklist for API access control
-- Thinking budget management (passthrough/auto/custom/adaptive)
-- Global system prompt injection
-- Session tracking and fingerprinting
-- Per-account enhanced rate limiting with provider-specific profiles
-- Circuit breaker pattern for provider resilience
-- Anti-thundering herd protection with mutex locking
-- Signature-based request deduplication cache
-- Domain layer: model availability, cost rules, fallback policy, lockout policy
-- Domain state persistence (SQLite write-through cache for fallbacks, budgets, lockouts, circuit breakers)
-- Policy engine for centralized request evaluation (lockout → budget → fallback)
-- Request telemetry with p50/p95/p99 latency aggregation
-- Correlation ID (X-Request-Id) for end-to-end tracing
-- Compliance audit logging with opt-out per API key
-- Eval framework for LLM quality assurance
-- Resilience UI dashboard with real-time circuit breaker status
-- Modular OAuth providers (12 individual modules under `src/lib/oauth/providers/`)
-
-Primary runtime model:
-
-- Next.js app routes under `src/app/api/*` implement both dashboard APIs and compatibility APIs
-- A shared SSE/routing core in `src/sse/*` + `open-sse/*` handles provider execution, translation, streaming, fallback, and usage
-
-## Scope and Boundaries
-
-### In Scope
-
-- Local gateway runtime
-- Dashboard management APIs
-- Provider authentication and token refresh
-- Request translation and SSE streaming
-- Local state + usage persistence
-- Optional cloud sync orchestration
-
-### Out of Scope
-
-- Cloud service implementation behind `NEXT_PUBLIC_CLOUD_URL`
-- Provider SLA/control plane outside local process
-- External CLI binaries themselves (Claude CLI, Codex CLI, etc.)
-
-## High-Level System Context
-
-```mermaid
-flowchart LR
- subgraph Clients[Developer Clients]
- C1[Claude Code]
- C2[Codex CLI]
- C3[OpenClaw / Droid / Cline / Continue / Roo]
- C4[Custom OpenAI-compatible clients]
- BROWSER[Browser Dashboard]
- end
-
- subgraph Router[OmniRoute Local Process]
- API[V1 Compatibility API\n/v1/*]
- DASH[Dashboard + Management API\n/api/*]
- CORE[SSE + Translation Core\nopen-sse + src/sse]
- DB[(storage.sqlite)]
- UDB[(usage tables + log artifacts)]
- end
-
- subgraph Upstreams[Upstream Providers]
- P1[OAuth Providers\nClaude/Codex/Gemini/Qwen/Qoder/GitHub/Kiro/Cursor/Antigravity]
- P2[API Key Providers\nOpenAI/Anthropic/OpenRouter/GLM/Kimi/MiniMax\nDeepSeek/Groq/xAI/Mistral/Perplexity\nTogether/Fireworks/Cerebras/Cohere/NVIDIA]
- P3[Compatible Nodes\nOpenAI-compatible / Anthropic-compatible]
- end
-
- subgraph Cloud[Optional Cloud Sync]
- CLOUD[Cloud Sync Endpoint\nNEXT_PUBLIC_CLOUD_URL]
- end
-
- C1 --> API
- C2 --> API
- C3 --> API
- C4 --> API
- BROWSER --> DASH
-
- API --> CORE
- DASH --> DB
- CORE --> DB
- CORE --> UDB
-
- CORE --> P1
- CORE --> P2
- CORE --> P3
-
- DASH --> CLOUD
-```
-
-## Core Runtime Components
-
-## 1) API and Routing Layer (Next.js App Routes)
-
-Main directories:
-
-- `src/app/api/v1/*` and `src/app/api/v1beta/*` for compatibility APIs
-- `src/app/api/*` for management/configuration APIs
-- Next rewrites in `next.config.mjs` map `/v1/*` to `/api/v1/*`
-
-Important compatibility routes:
-
-- `src/app/api/v1/chat/completions/route.ts`
-- `src/app/api/v1/messages/route.ts`
-- `src/app/api/v1/responses/route.ts`
-- `src/app/api/v1/models/route.ts` — includes custom models with `custom: true`
-- `src/app/api/v1/embeddings/route.ts` — embedding generation (6 providers)
-- `src/app/api/v1/images/generations/route.ts` — image generation (4+ providers incl. Antigravity/Nebius)
-- `src/app/api/v1/messages/count_tokens/route.ts`
-- `src/app/api/v1/providers/[provider]/chat/completions/route.ts` — dedicated per-provider chat
-- `src/app/api/v1/providers/[provider]/embeddings/route.ts` — dedicated per-provider embeddings
-- `src/app/api/v1/providers/[provider]/images/generations/route.ts` — dedicated per-provider images
-- `src/app/api/v1beta/models/route.ts`
-- `src/app/api/v1beta/models/[...path]/route.ts`
-
-Management domains:
-
-- Auth/settings: `src/app/api/auth/*`, `src/app/api/settings/*`
-- Providers/connections: `src/app/api/providers*`
-- Provider nodes: `src/app/api/provider-nodes*`
-- Custom models: `src/app/api/provider-models` (GET/POST/DELETE)
-- Model catalog: `src/app/api/models/route.ts` (GET)
-- Proxy config: `src/app/api/settings/proxy` (GET/PUT/DELETE) + `src/app/api/settings/proxy/test` (POST)
-- OAuth: `src/app/api/oauth/*`
-- Keys/aliases/combos/pricing: `src/app/api/keys*`, `src/app/api/models/alias`, `src/app/api/combos*`, `src/app/api/pricing`
-- Usage: `src/app/api/usage/*`
-- Sync/cloud: `src/app/api/sync/*`, `src/app/api/cloud/*`
-- CLI tooling helpers: `src/app/api/cli-tools/*`
-- IP filter: `src/app/api/settings/ip-filter` (GET/PUT)
-- Thinking budget: `src/app/api/settings/thinking-budget` (GET/PUT)
-- System prompt: `src/app/api/settings/system-prompt` (GET/PUT)
-- Sessions: `src/app/api/sessions` (GET)
-- Rate limits: `src/app/api/rate-limits` (GET)
-- Resilience: `src/app/api/resilience` (GET/PATCH) — provider profiles, circuit breaker, rate limit state
-- Resilience reset: `src/app/api/resilience/reset` (POST) — reset breakers + cooldowns
-- Cache stats: `src/app/api/cache/stats` (GET/DELETE)
-- Model availability: `src/app/api/models/availability` (GET/POST)
-- Telemetry: `src/app/api/telemetry/summary` (GET)
-- Budget: `src/app/api/usage/budget` (GET/POST)
-- Fallback chains: `src/app/api/fallback/chains` (GET/POST/DELETE)
-- Compliance audit: `src/app/api/compliance/audit-log` (GET)
-- Evals: `src/app/api/evals` (GET/POST), `src/app/api/evals/[suiteId]` (GET)
-- Policies: `src/app/api/policies` (GET/POST)
-
-## 2) SSE + Translation Core
-
-Main flow modules:
-
-- Entry: `src/sse/handlers/chat.ts`
-- Core orchestration: `open-sse/handlers/chatCore.ts`
-- Provider execution adapters: `open-sse/executors/*`
-- Format detection/provider config: `open-sse/services/provider.ts`
-- Model parse/resolve: `src/sse/services/model.ts`, `open-sse/services/model.ts`
-- Account fallback logic: `open-sse/services/accountFallback.ts`
-- Translation registry: `open-sse/translator/index.ts`
-- Stream transformations: `open-sse/utils/stream.ts`, `open-sse/utils/streamHandler.ts`
-- Usage extraction/normalization: `open-sse/utils/usageTracking.ts`
-- Think tag parser: `open-sse/utils/thinkTagParser.ts`
-- Embedding handler: `open-sse/handlers/embeddings.ts`
-- Embedding provider registry: `open-sse/config/embeddingRegistry.ts`
-- Image generation handler: `open-sse/handlers/imageGeneration.ts`
-- Image provider registry: `open-sse/config/imageRegistry.ts`
-- Response sanitization: `open-sse/handlers/responseSanitizer.ts`
-- Role normalization: `open-sse/services/roleNormalizer.ts`
-
-Services (business logic):
-
-- Account selection/scoring: `open-sse/services/accountSelector.ts`
-- Context lifecycle management: `open-sse/services/contextManager.ts`
-- IP filter enforcement: `open-sse/services/ipFilter.ts`
-- Session tracking: `open-sse/services/sessionManager.ts`
-- Request deduplication: `open-sse/services/signatureCache.ts`
-- System prompt injection: `open-sse/services/systemPrompt.ts`
-- Thinking budget management: `open-sse/services/thinkingBudget.ts`
-- Wildcard model routing: `open-sse/services/wildcardRouter.ts`
-- Rate limit management: `open-sse/services/rateLimitManager.ts`
-- Circuit breaker: `open-sse/services/circuitBreaker.ts`
-
-Domain layer modules:
-
-- Model availability: `src/lib/domain/modelAvailability.ts`
-- Cost rules/budgets: `src/lib/domain/costRules.ts`
-- Fallback policy: `src/lib/domain/fallbackPolicy.ts`
-- Combo resolver: `src/lib/domain/comboResolver.ts`
-- Lockout policy: `src/lib/domain/lockoutPolicy.ts`
-- Policy engine: `src/domain/policyEngine.ts` — centralized lockout → budget → fallback evaluation
-- Error codes catalog: `src/lib/domain/errorCodes.ts`
-- Request ID: `src/lib/domain/requestId.ts`
-- Fetch timeout: `src/lib/domain/fetchTimeout.ts`
-- Request telemetry: `src/lib/domain/requestTelemetry.ts`
-- Compliance/audit: `src/lib/domain/compliance/index.ts`
-- Eval runner: `src/lib/domain/evalRunner.ts`
-- Domain state persistence: `src/lib/db/domainState.ts` — SQLite CRUD for fallback chains, budgets, cost history, lockout state, circuit breakers
-
-OAuth provider modules (12 individual files under `src/lib/oauth/providers/`):
-
-- Registry index: `src/lib/oauth/providers/index.ts`
-- Individual providers: `claude.ts`, `codex.ts`, `gemini.ts`, `antigravity.ts`, `qoder.ts`, `qwen.ts`, `kimi-coding.ts`, `github.ts`, `kiro.ts`, `cursor.ts`, `kilocode.ts`, `cline.ts`
-- Thin wrapper: `src/lib/oauth/providers.ts` — re-exports from individual modules
-
-## 3) Persistence Layer
-
-Primary state DB (SQLite):
-
-- Core infra: `src/lib/db/core.ts` (better-sqlite3, migrations, WAL)
-- Re-export facade: `src/lib/localDb.ts` (thin compatibility layer for callers)
-- file: `${DATA_DIR}/storage.sqlite` (or `$XDG_CONFIG_HOME/omniroute/storage.sqlite` when set, else `~/.omniroute/storage.sqlite`)
-- entities (tables + KV namespaces): providerConnections, providerNodes, modelAliases, combos, apiKeys, settings, pricing, **customModels**, **proxyConfig**, **ipFilter**, **thinkingBudget**, **systemPrompt**
-
-Usage persistence:
-
-- facade: `src/lib/usageDb.ts` (decomposed modules in `src/lib/usage/*`)
-- SQLite tables in `storage.sqlite`: `usage_history`, `call_logs`, `proxy_logs`
-- optional file artifacts remain for compatibility/debug (`${DATA_DIR}/log.txt`, `${DATA_DIR}/call_logs/`, `/logs/...`)
-- legacy JSON files are migrated to SQLite by startup migrations when present
-
-Domain State DB (SQLite):
-
-- `src/lib/db/domainState.ts` — CRUD operations for domain state
-- Tables (created in `src/lib/db/core.ts`): `domain_fallback_chains`, `domain_budgets`, `domain_cost_history`, `domain_lockout_state`, `domain_circuit_breakers`
-- Write-through cache pattern: in-memory Maps are authoritative at runtime; mutations are written synchronously to SQLite; state is restored from DB on cold start
-
-## 4) Auth + Security Surfaces
-
-- Dashboard cookie auth: `src/proxy.ts`, `src/app/api/auth/login/route.ts`
-- API key generation/verification: `src/shared/utils/apiKey.ts`
-- Provider secrets persisted in `providerConnections` entries
-- Outbound proxy support via `open-sse/utils/proxyFetch.ts` (env vars) and `open-sse/utils/networkProxy.ts` (configurable per-provider or global)
-
-## 5) Cloud Sync
-
-- Scheduler init: `src/lib/initCloudSync.ts`, `src/shared/services/initializeCloudSync.ts`
-- Periodic task: `src/shared/services/cloudSyncScheduler.ts`
-- Control route: `src/app/api/sync/cloud/route.ts`
-
-## Request Lifecycle (`/v1/chat/completions`)
-
-```mermaid
-sequenceDiagram
- autonumber
- participant Client as CLI/SDK Client
- participant Route as /api/v1/chat/completions
- participant Chat as src/sse/handlers/chat
- participant Core as open-sse/handlers/chatCore
- participant Model as Model Resolver
- participant Auth as Credential Selector
- participant Exec as Provider Executor
- participant Prov as Upstream Provider
- participant Stream as Stream Translator
- participant Usage as usageDb
-
- Client->>Route: POST /v1/chat/completions
- Route->>Chat: handleChat(request)
- Chat->>Model: parse/resolve model or combo
-
- alt Combo model
- Chat->>Chat: iterate combo models (handleComboChat)
- end
-
- Chat->>Auth: getProviderCredentials(provider)
- Auth-->>Chat: active account + tokens/api key
-
- Chat->>Core: handleChatCore(body, modelInfo, credentials)
- Core->>Core: detect source format
- Core->>Core: translate request to target format
- Core->>Exec: execute(provider, transformedBody)
- Exec->>Prov: upstream API call
- Prov-->>Exec: SSE/JSON response
- Exec-->>Core: response + metadata
-
- alt 401/403
- Core->>Exec: refreshCredentials()
- Exec-->>Core: updated tokens
- Core->>Exec: retry request
- end
-
- Core->>Stream: translate/normalize stream to client format
- Stream-->>Client: SSE chunks / JSON response
-
- Stream->>Usage: extract usage + persist history/log
-```
-
-## Combo + Account Fallback Flow
-
-```mermaid
-flowchart TD
- A[Incoming model string] --> B{Is combo name?}
- B -- Yes --> C[Load combo models sequence]
- B -- No --> D[Single model path]
-
- C --> E[Try model N]
- E --> F[Resolve provider/model]
- D --> F
-
- F --> G[Select account credentials]
- G --> H{Credentials available?}
- H -- No --> I[Return provider unavailable]
- H -- Yes --> J[Execute request]
-
- J --> K{Success?}
- K -- Yes --> L[Return response]
- K -- No --> M{Fallback-eligible error?}
-
- M -- No --> N[Return error]
- M -- Yes --> O[Mark account unavailable cooldown]
- O --> P{Another account for provider?}
- P -- Yes --> G
- P -- No --> Q{In combo with next model?}
- Q -- Yes --> E
- Q -- No --> R[Return all unavailable]
-```
-
-Fallback decisions are driven by `open-sse/services/accountFallback.ts` using status codes and error-message heuristics.
-
-## OAuth Onboarding and Token Refresh Lifecycle
-
-```mermaid
-sequenceDiagram
- autonumber
- participant UI as Dashboard UI
- participant OAuth as /api/oauth/[provider]/[action]
- participant ProvAuth as Provider Auth Server
- participant DB as localDb
- participant Test as /api/providers/[id]/test
- participant Exec as Provider Executor
-
- UI->>OAuth: GET authorize or device-code
- OAuth->>ProvAuth: create auth/device flow
- ProvAuth-->>OAuth: auth URL or device code payload
- OAuth-->>UI: flow data
-
- UI->>OAuth: POST exchange or poll
- OAuth->>ProvAuth: token exchange/poll
- ProvAuth-->>OAuth: access/refresh tokens
- OAuth->>DB: createProviderConnection(oauth data)
- OAuth-->>UI: success + connection id
-
- UI->>Test: POST /api/providers/[id]/test
- Test->>Exec: validate credentials / optional refresh
- Exec-->>Test: valid or refreshed token info
- Test->>DB: update status/tokens/errors
- Test-->>UI: validation result
-```
-
-Refresh during live traffic is executed inside `open-sse/handlers/chatCore.ts` via executor `refreshCredentials()`.
-
-## Cloud Sync Lifecycle (Enable / Sync / Disable)
-
-```mermaid
-sequenceDiagram
- autonumber
- participant UI as Endpoint Page UI
- participant Sync as /api/sync/cloud
- participant DB as localDb
- participant Cloud as External Cloud Sync
- participant Claude as ~/.claude/settings.json
-
- UI->>Sync: POST action=enable
- Sync->>DB: set cloudEnabled=true
- Sync->>DB: ensure API key exists
- Sync->>Cloud: POST /sync/{machineId} (providers/aliases/combos/keys)
- Cloud-->>Sync: sync result
- Sync->>Cloud: GET /{machineId}/v1/verify
- Sync-->>UI: enabled + verification status
-
- UI->>Sync: POST action=sync
- Sync->>Cloud: POST /sync/{machineId}
- Cloud-->>Sync: remote data
- Sync->>DB: update newer local tokens/status
- Sync-->>UI: synced
-
- UI->>Sync: POST action=disable
- Sync->>DB: set cloudEnabled=false
- Sync->>Cloud: DELETE /sync/{machineId}
- Sync->>Claude: switch ANTHROPIC_BASE_URL back to local (if needed)
- Sync-->>UI: disabled
-```
-
-Periodic sync is triggered by `CloudSyncScheduler` when cloud is enabled.
-
-## Data Model and Storage Map
-
-```mermaid
-erDiagram
- SETTINGS ||--o{ PROVIDER_CONNECTION : controls
- PROVIDER_NODE ||--o{ PROVIDER_CONNECTION : backs_compatible_provider
- PROVIDER_CONNECTION ||--o{ USAGE_ENTRY : emits_usage
-
- SETTINGS {
- boolean cloudEnabled
- number stickyRoundRobinLimit
- boolean requireLogin
- string password_hash
- string fallbackStrategy
- json rateLimitDefaults
- json providerProfiles
- }
-
- PROVIDER_CONNECTION {
- string id
- string provider
- string authType
- string name
- number priority
- boolean isActive
- string apiKey
- string accessToken
- string refreshToken
- string expiresAt
- string testStatus
- string lastError
- string rateLimitedUntil
- json providerSpecificData
- }
-
- PROVIDER_NODE {
- string id
- string type
- string name
- string prefix
- string apiType
- string baseUrl
- }
-
- MODEL_ALIAS {
- string alias
- string targetModel
- }
-
- COMBO {
- string id
- string name
- string[] models
- }
-
- API_KEY {
- string id
- string name
- string key
- string machineId
- }
-
- USAGE_ENTRY {
- string provider
- string model
- number prompt_tokens
- number completion_tokens
- string connectionId
- string timestamp
- }
-
- CUSTOM_MODEL {
- string id
- string name
- string providerId
- }
-
- PROXY_CONFIG {
- string global
- json providers
- }
-
- IP_FILTER {
- string mode
- string[] allowlist
- string[] blocklist
- }
-
- THINKING_BUDGET {
- string mode
- number customBudget
- string effortLevel
- }
-
- SYSTEM_PROMPT {
- boolean enabled
- string prompt
- string position
- }
-```
-
-Physical storage files:
-
-- primary runtime DB: `${DATA_DIR}/storage.sqlite`
-- request log lines: `${DATA_DIR}/log.txt` (compat/debug artifact)
-- structured call payload archives: `${DATA_DIR}/call_logs/`
-- optional translator/request debug sessions: `/logs/...`
-
-## Deployment Topology
-
-```mermaid
-flowchart LR
- subgraph LocalHost[Developer Host]
- CLI[CLI Tools]
- Browser[Dashboard Browser]
- end
-
- subgraph ContainerOrProcess[OmniRoute Runtime]
- Next[Next.js Server\nPORT=20128]
- Core[SSE Core + Executors]
- MainDB[(storage.sqlite)]
- UsageDB[(usage tables + log artifacts)]
- end
-
- subgraph External[External Services]
- Providers[AI Providers]
- SyncCloud[Cloud Sync Service]
- end
-
- CLI --> Next
- Browser --> Next
- Next --> Core
- Next --> MainDB
- Core --> MainDB
- Core --> UsageDB
- Core --> Providers
- Next --> SyncCloud
-```
-
-## Module Mapping (Decision-Critical)
-
-### Route and API Modules
-
-- `src/app/api/v1/*`, `src/app/api/v1beta/*`: compatibility APIs
-- `src/app/api/v1/providers/[provider]/*`: dedicated per-provider routes (chat, embeddings, images)
-- `src/app/api/providers*`: provider CRUD, validation, testing
-- `src/app/api/provider-nodes*`: custom compatible node management
-- `src/app/api/provider-models`: custom model management (CRUD)
-- `src/app/api/models/route.ts`: model catalog API (aliases + custom models)
-- `src/app/api/oauth/*`: OAuth/device-code flows
-- `src/app/api/keys*`: local API key lifecycle
-- `src/app/api/models/alias`: alias management
-- `src/app/api/combos*`: fallback combo management
-- `src/app/api/pricing`: pricing overrides for cost calculation
-- `src/app/api/settings/proxy`: proxy configuration (GET/PUT/DELETE)
-- `src/app/api/settings/proxy/test`: outbound proxy connectivity test (POST)
-- `src/app/api/usage/*`: usage and logs APIs
-- `src/app/api/sync/*` + `src/app/api/cloud/*`: cloud sync and cloud-facing helpers
-- `src/app/api/cli-tools/*`: local CLI config writers/checkers
-- `src/app/api/settings/ip-filter`: IP allowlist/blocklist (GET/PUT)
-- `src/app/api/settings/thinking-budget`: thinking token budget config (GET/PUT)
-- `src/app/api/settings/system-prompt`: global system prompt (GET/PUT)
-- `src/app/api/sessions`: active session listing (GET)
-- `src/app/api/rate-limits`: per-account rate limit status (GET)
-
-### Routing and Execution Core
-
-- `src/sse/handlers/chat.ts`: request parse, combo handling, account selection loop
-- `open-sse/handlers/chatCore.ts`: translation, executor dispatch, retry/refresh handling, stream setup
-- `open-sse/executors/*`: provider-specific network and format behavior
-
-### Translation Registry and Format Converters
-
-- `open-sse/translator/index.ts`: translator registry and orchestration
-- Request translators: `open-sse/translator/request/*`
-- Response translators: `open-sse/translator/response/*`
-- Format constants: `open-sse/translator/formats.ts`
-
-### Persistence
-
-- `src/lib/db/*`: persistent config/state and domain persistence on SQLite
-- `src/lib/localDb.ts`: compatibility re-export for DB modules
-- `src/lib/usageDb.ts`: usage history/call logs facade on top of SQLite tables
-
-## Provider Executor Coverage (Strategy Pattern)
-
-Each provider has a specialized executor extending `BaseExecutor` (in `open-sse/executors/base.ts`), which provides URL building, header construction, retry with exponential backoff, credential refresh hooks, and the `execute()` orchestration method.
-
-| Executor | Provider(s) | Special Handling |
-| --------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------ | -------------------------------------------------------------------- |
-| `DefaultExecutor` | OpenAI, Claude, Gemini, Qwen, Qoder, OpenRouter, GLM, Kimi, MiniMax, DeepSeek, Groq, xAI, Mistral, Perplexity, Together, Fireworks, Cerebras, Cohere, NVIDIA | Dynamic URL/header config per provider |
-| `AntigravityExecutor` | Google Antigravity | Custom project/session IDs, Retry-After parsing |
-| `CodexExecutor` | OpenAI Codex | Injects system instructions, forces reasoning effort |
-| `CursorExecutor` | Cursor IDE | ConnectRPC protocol, Protobuf encoding, request signing via checksum |
-| `GithubExecutor` | GitHub Copilot | Copilot token refresh, VSCode-mimicking headers |
-| `KiroExecutor` | AWS CodeWhisperer/Kiro | AWS EventStream binary format → SSE conversion |
-| `GeminiCLIExecutor` | Gemini CLI | Google OAuth token refresh cycle |
-
-All other providers (including custom compatible nodes) use the `DefaultExecutor`.
-
-## Provider Compatibility Matrix
-
-| Provider | Format | Auth | Stream | Non-Stream | Token Refresh | Usage API |
-| ---------------- | ---------------- | --------------------- | ---------------- | ---------- | ------------- | ------------------ |
-| Claude | claude | API Key / OAuth | ✅ | ✅ | ✅ | ⚠️ Admin only |
-| Gemini | gemini | API Key / OAuth | ✅ | ✅ | ✅ | ⚠️ Cloud Console |
-| Gemini CLI | gemini-cli | OAuth | ✅ | ✅ | ✅ | ⚠️ Cloud Console |
-| Antigravity | antigravity | OAuth | ✅ | ✅ | ✅ | ✅ Full quota API |
-| OpenAI | openai | API Key | ✅ | ✅ | ❌ | ❌ |
-| Codex | openai-responses | OAuth | ✅ forced | ❌ | ✅ | ✅ Rate limits |
-| GitHub Copilot | openai | OAuth + Copilot Token | ✅ | ✅ | ✅ | ✅ Quota snapshots |
-| Cursor | cursor | Custom checksum | ✅ | ✅ | ❌ | ❌ |
-| Kiro | kiro | AWS SSO OIDC | ✅ (EventStream) | ❌ | ✅ | ✅ Usage limits |
-| Qwen | openai | OAuth | ✅ | ✅ | ✅ | ⚠️ Per request |
-| Qoder | openai | OAuth (Basic) | ✅ | ✅ | ✅ | ⚠️ Per request |
-| OpenRouter | openai | API Key | ✅ | ✅ | ❌ | ❌ |
-| GLM/Kimi/MiniMax | claude | API Key | ✅ | ✅ | ❌ | ❌ |
-| DeepSeek | openai | API Key | ✅ | ✅ | ❌ | ❌ |
-| Groq | openai | API Key | ✅ | ✅ | ❌ | ❌ |
-| xAI (Grok) | openai | API Key | ✅ | ✅ | ❌ | ❌ |
-| Mistral | openai | API Key | ✅ | ✅ | ❌ | ❌ |
-| Perplexity | openai | API Key | ✅ | ✅ | ❌ | ❌ |
-| Together AI | openai | API Key | ✅ | ✅ | ❌ | ❌ |
-| Fireworks AI | openai | API Key | ✅ | ✅ | ❌ | ❌ |
-| Cerebras | openai | API Key | ✅ | ✅ | ❌ | ❌ |
-| Cohere | openai | API Key | ✅ | ✅ | ❌ | ❌ |
-| NVIDIA NIM | openai | API Key | ✅ | ✅ | ❌ | ❌ |
-
-## Format Translation Coverage
-
-Detected source formats include:
-
-- `openai`
-- `openai-responses`
-- `claude`
-- `gemini`
-
-Target formats include:
-
-- OpenAI chat/Responses
-- Claude
-- Gemini/Gemini-CLI/Antigravity envelope
-- Kiro
-- Cursor
-
-Translations use **OpenAI as the hub format** — all conversions go through OpenAI as intermediate:
-
-```
-Source Format → OpenAI (hub) → Target Format
-```
-
-Translations are selected dynamically based on source payload shape and provider target format.
-
-Additional processing layers in the translation pipeline:
-
-- **Response sanitization** — Strips non-standard fields from OpenAI-format responses (both streaming and non-streaming) to ensure strict SDK compliance
-- **Role normalization** — Converts `developer` → `system` for non-OpenAI targets; merges `system` → `user` for models that reject the system role (GLM, ERNIE)
-- **Think tag extraction** — Parses `...` blocks from content into `reasoning_content` field
-- **Structured output** — Converts OpenAI `response_format.json_schema` to Gemini's `responseMimeType` + `responseSchema`
-
-## Supported API Endpoints
-
-| Endpoint | Format | Handler |
-| -------------------------------------------------- | ------------------ | ---------------------------------------------------- |
-| `POST /v1/chat/completions` | OpenAI Chat | `src/sse/handlers/chat.ts` |
-| `POST /v1/messages` | Claude Messages | Same handler (auto-detected) |
-| `POST /v1/responses` | OpenAI Responses | `open-sse/handlers/responsesHandler.ts` |
-| `POST /v1/embeddings` | OpenAI Embeddings | `open-sse/handlers/embeddings.ts` |
-| `GET /v1/embeddings` | Model listing | API route |
-| `POST /v1/images/generations` | OpenAI Images | `open-sse/handlers/imageGeneration.ts` |
-| `GET /v1/images/generations` | Model listing | API route |
-| `POST /v1/providers/{provider}/chat/completions` | OpenAI Chat | Dedicated per-provider with model validation |
-| `POST /v1/providers/{provider}/embeddings` | OpenAI Embeddings | Dedicated per-provider with model validation |
-| `POST /v1/providers/{provider}/images/generations` | OpenAI Images | Dedicated per-provider with model validation |
-| `POST /v1/messages/count_tokens` | Claude Token Count | API route |
-| `GET /v1/models` | OpenAI Models list | API route (chat + embedding + image + custom models) |
-| `GET /api/models/catalog` | Catalog | All models grouped by provider + type |
-| `POST /v1beta/models/*:streamGenerateContent` | Gemini native | API route |
-| `GET/PUT/DELETE /api/settings/proxy` | Proxy Config | Network proxy configuration |
-| `POST /api/settings/proxy/test` | Proxy Connectivity | Proxy health/connectivity test endpoint |
-| `GET/POST/DELETE /api/provider-models` | Custom Models | Custom model management per provider |
-
-## Bypass Handler
-
-The bypass handler (`open-sse/utils/bypassHandler.ts`) intercepts known "throwaway" requests from Claude CLI — warmup pings, title extractions, and token counts — and returns a **fake response** without consuming upstream provider tokens. This is triggered only when `User-Agent` contains `claude-cli`.
-
-## Request Logger Pipeline
-
-The request logger (`open-sse/utils/requestLogger.ts`) provides a 7-stage debug logging pipeline, disabled by default, enabled via `ENABLE_REQUEST_LOGS=true`:
-
-```
-1_req_client.json → 2_req_source.json → 3_req_openai.json → 4_req_target.json
-→ 5_res_provider.txt → 6_res_openai.txt → 7_res_client.txt
-```
-
-Files are written to `/logs//` for each request session.
-
-## Failure Modes and Resilience
-
-## 1) Account/Provider Availability
-
-- provider account cooldown on transient/rate/auth errors
-- account fallback before failing request
-- combo model fallback when current model/provider path is exhausted
-
-## 2) Token Expiry
-
-- pre-check and refresh with retry for refreshable providers
-- 401/403 retry after refresh attempt in core path
-
-## 3) Stream Safety
-
-- disconnect-aware stream controller
-- translation stream with end-of-stream flush and `[DONE]` handling
-- usage estimation fallback when provider usage metadata is missing
-
-## 4) Cloud Sync Degradation
-
-- sync errors are surfaced but local runtime continues
-- scheduler has retry-capable logic, but periodic execution currently calls single-attempt sync by default
-
-## 5) Data Integrity
-
-- SQLite schema migrations and auto-upgrade hooks at startup
-- legacy JSON → SQLite migration compatibility path
-
-## Observability and Operational Signals
-
-Runtime visibility sources:
-
-- console logs from `src/sse/utils/logger.ts`
-- per-request usage aggregates in SQLite (`usage_history`, `call_logs`, `proxy_logs`)
-- textual request status log in `log.txt` (optional/compat)
-- optional deep request/translation logs under `logs/` when `ENABLE_REQUEST_LOGS=true`
-- dashboard usage endpoints (`/api/usage/*`) for UI consumption
-
-## Security-Sensitive Boundaries
-
-- JWT secret (`JWT_SECRET`) secures dashboard session cookie verification/signing
-- Initial password bootstrap (`INITIAL_PASSWORD`) should be explicitly configured for first-run provisioning
-- API key HMAC secret (`API_KEY_SECRET`) secures generated local API key format
-- Provider secrets (API keys/tokens) are persisted in local DB and should be protected at filesystem level
-- Cloud sync endpoints rely on API key auth + machine id semantics
-
-## Environment and Runtime Matrix
-
-Environment variables actively used by code:
-
-- App/auth: `JWT_SECRET`, `INITIAL_PASSWORD`
-- Storage: `DATA_DIR`
-- Compatible node behavior: `ALLOW_MULTI_CONNECTIONS_PER_COMPAT_NODE`
-- Optional storage base override (Linux/macOS when `DATA_DIR` unset): `XDG_CONFIG_HOME`
-- Security hashing: `API_KEY_SECRET`, `MACHINE_ID_SALT`
-- Logging: `ENABLE_REQUEST_LOGS`
-- Sync/cloud URLing: `NEXT_PUBLIC_BASE_URL`, `NEXT_PUBLIC_CLOUD_URL`
-- Outbound proxy: `HTTP_PROXY`, `HTTPS_PROXY`, `ALL_PROXY`, `NO_PROXY` and lowercase variants
-- SOCKS5 feature flags: `ENABLE_SOCKS5_PROXY`, `NEXT_PUBLIC_ENABLE_SOCKS5_PROXY`
-- Platform/runtime helpers (not app-specific config): `APPDATA`, `NODE_ENV`, `PORT`, `HOSTNAME`
-
-## Known Architectural Notes
-
-1. `usageDb` and `localDb` share the same base directory policy (`DATA_DIR` -> `XDG_CONFIG_HOME/omniroute` -> `~/.omniroute`) with legacy file migration.
-2. `/api/v1/route.ts` delegates to the same unified catalog builder used by `/api/v1/models` (`src/app/api/v1/models/catalog.ts`) to avoid semantic drift.
-3. Request logger writes full headers/body when enabled; treat log directory as sensitive.
-4. Cloud behavior depends on correct `NEXT_PUBLIC_BASE_URL` and cloud endpoint reachability.
-5. The `open-sse/` directory is published as the `@omniroute/open-sse` **npm workspace package**. Source code imports it via `@omniroute/open-sse/...` (resolved by Next.js `transpilePackages`). File paths in this document still use the directory name `open-sse/` for consistency.
-6. Charts in the dashboard use **Recharts** (SVG-based) for accessible, interactive analytics visualizations (model usage bar charts, provider breakdown tables with success rates).
-7. E2E tests use **Playwright** (`tests/e2e/`), run via `npm run test:e2e`. Unit tests use **Node.js test runner** (`tests/unit/`), run via `npm run test:unit`. Source code under `src/` is **TypeScript** (`.ts`/`.tsx`); the `open-sse/` workspace remains JavaScript (`.js`).
-8. Settings page is organized into 5 tabs: Security, Routing (6 global strategies: fill-first, round-robin, p2c, random, least-used, cost-optimized), Resilience (editable rate limits, circuit breaker, policies), AI (thinking budget, system prompt, prompt cache), Advanced (proxy).
-
-## Operational Verification Checklist
-
-- Build from source: `npm run build`
-- Build Docker image: `docker build -t omniroute .`
-- Start service and verify:
-- `GET /api/settings`
-- `GET /api/v1/models`
-- CLI target base URL should be `http://:20128/v1` when `PORT=20128`
diff --git a/docs/i18n/hu/AUTO-COMBO.md b/docs/i18n/hu/AUTO-COMBO.md
deleted file mode 100644
index 2166e41dff..0000000000
--- a/docs/i18n/hu/AUTO-COMBO.md
+++ /dev/null
@@ -1,67 +0,0 @@
-🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/AUTO-COMBO.md) · 🇪🇸 [es](../es/AUTO-COMBO.md) · 🇫🇷 [fr](../fr/AUTO-COMBO.md) · 🇩🇪 [de](../de/AUTO-COMBO.md) · 🇮🇹 [it](../it/AUTO-COMBO.md) · 🇷🇺 [ru](../ru/AUTO-COMBO.md) · 🇨🇳 [zh-CN](../zh-CN/AUTO-COMBO.md) · 🇯🇵 [ja](../ja/AUTO-COMBO.md) · 🇰🇷 [ko](../ko/AUTO-COMBO.md) · 🇸🇦 [ar](../ar/AUTO-COMBO.md) · 🇮🇳 [in](../in/AUTO-COMBO.md) · 🇹🇭 [th](../th/AUTO-COMBO.md) · 🇻🇳 [vi](../vi/AUTO-COMBO.md) · 🇮🇩 [id](../id/AUTO-COMBO.md) · 🇲🇾 [ms](../ms/AUTO-COMBO.md) · 🇳🇱 [nl](../nl/AUTO-COMBO.md) · 🇵🇱 [pl](../pl/AUTO-COMBO.md) · 🇸🇪 [sv](../sv/AUTO-COMBO.md) · 🇳🇴 [no](../no/AUTO-COMBO.md) · 🇩🇰 [da](../da/AUTO-COMBO.md) · 🇫🇮 [fi](../fi/AUTO-COMBO.md) · 🇵🇹 [pt](../pt/AUTO-COMBO.md) · 🇷🇴 [ro](../ro/AUTO-COMBO.md) · 🇭🇺 [hu](../hu/AUTO-COMBO.md) · 🇧🇬 [bg](../bg/AUTO-COMBO.md) · 🇸🇰 [sk](../sk/AUTO-COMBO.md) · 🇺🇦 [uk-UA](../uk-UA/AUTO-COMBO.md) · 🇮🇱 [he](../he/AUTO-COMBO.md) · 🇵🇭 [phi](../phi/AUTO-COMBO.md)
-
----
-
-# OmniRoute Auto-Combo Engine
-
-> Self-managing model chains with adaptive scoring
-
-## How It Works
-
-The Auto-Combo Engine dynamically selects the best provider/model for each request using a **6-factor scoring function**:
-
-| Factor | Weight | Description |
-| :--------- | :----- | :---------------------------------------------- |
-| Quota | 0.20 | Remaining capacity [0..1] |
-| Health | 0.25 | Circuit breaker: CLOSED=1.0, HALF=0.5, OPEN=0.0 |
-| CostInv | 0.20 | Inverse cost (cheaper = higher score) |
-| LatencyInv | 0.15 | Inverse p95 latency (faster = higher) |
-| TaskFit | 0.10 | Model × task type fitness score |
-| Stability | 0.10 | Low variance in latency/errors |
-
-## Mode Packs
-
-| Pack | Focus | Key Weight |
-| :---------------------- | :----------- | :--------------- |
-| 🚀 **Ship Fast** | Speed | latencyInv: 0.35 |
-| 💰 **Cost Saver** | Economy | costInv: 0.40 |
-| 🎯 **Quality First** | Best model | taskFit: 0.40 |
-| 📡 **Offline Friendly** | Availability | quota: 0.40 |
-
-## Self-Healing
-
-- **Temporary exclusion**: Score < 0.2 → excluded for 5 min (progressive backoff, max 30 min)
-- **Circuit breaker awareness**: OPEN → auto-excluded; HALF_OPEN → probe requests
-- **Incident mode**: >50% OPEN → disable exploration, maximize stability
-- **Cooldown recovery**: After exclusion, first request is a "probe" with reduced timeout
-
-## Bandit Exploration
-
-5% of requests (configurable) are routed to random providers for exploration. Disabled in incident mode.
-
-## API
-
-```bash
-# Create auto-combo
-curl -X POST http://localhost:20128/api/combos/auto \
- -H "Content-Type: application/json" \
- -d '{"id":"my-auto","name":"Auto Coder","candidatePool":["anthropic","google","openai"],"modePack":"ship-fast"}'
-
-# List auto-combos
-curl http://localhost:20128/api/combos/auto
-```
-
-## Task Fitness
-
-30+ models scored across 6 task types (`coding`, `review`, `planning`, `analysis`, `debugging`, `documentation`). Supports wildcard patterns (e.g., `*-coder` → high coding score).
-
-## Files
-
-| File | Purpose |
-| :------------------------------------------- | :------------------------------------ |
-| `open-sse/services/autoCombo/scoring.ts` | Scoring function & pool normalization |
-| `open-sse/services/autoCombo/taskFitness.ts` | Model × task fitness lookup |
-| `open-sse/services/autoCombo/engine.ts` | Selection logic, bandit, budget cap |
-| `open-sse/services/autoCombo/selfHealing.ts` | Exclusion, probes, incident mode |
-| `open-sse/services/autoCombo/modePacks.ts` | 4 weight profiles |
-| `src/app/api/combos/auto/route.ts` | REST API |
diff --git a/docs/i18n/hu/CHANGELOG.md b/docs/i18n/hu/CHANGELOG.md
index bf9bb34f88..31dff77cb5 100644
--- a/docs/i18n/hu/CHANGELOG.md
+++ b/docs/i18n/hu/CHANGELOG.md
@@ -1,12 +1,92 @@
# Changelog (Magyar)
-🌐 **Languages:** 🇺🇸 [English](../../../CHANGELOG.md) · 🇪🇸 [es](../es/CHANGELOG.md) · 🇫🇷 [fr](../fr/CHANGELOG.md) · 🇩🇪 [de](../de/CHANGELOG.md) · 🇮🇹 [it](../it/CHANGELOG.md) · 🇷🇺 [ru](../ru/CHANGELOG.md) · 🇨🇳 [zh-CN](../zh-CN/CHANGELOG.md) · 🇯🇵 [ja](../ja/CHANGELOG.md) · 🇰🇷 [ko](../ko/CHANGELOG.md) · 🇸🇦 [ar](../ar/CHANGELOG.md) · 🇮🇳 [in](../in/CHANGELOG.md) · 🇹🇭 [th](../th/CHANGELOG.md) · 🇻🇳 [vi](../vi/CHANGELOG.md) · 🇮🇩 [id](../id/CHANGELOG.md) · 🇲🇾 [ms](../ms/CHANGELOG.md) · 🇳🇱 [nl](../nl/CHANGELOG.md) · 🇵🇱 [pl](../pl/CHANGELOG.md) · 🇸🇪 [sv](../sv/CHANGELOG.md) · 🇳🇴 [no](../no/CHANGELOG.md) · 🇩🇰 [da](../da/CHANGELOG.md) · 🇫🇮 [fi](../fi/CHANGELOG.md) · 🇵🇹 [pt](../pt/CHANGELOG.md) · 🇷🇴 [ro](../ro/CHANGELOG.md) · 🇭🇺 [hu](../hu/CHANGELOG.md) · 🇧🇬 [bg](../bg/CHANGELOG.md) · 🇸🇰 [sk](../sk/CHANGELOG.md) · 🇺🇦 [uk-UA](../uk-UA/CHANGELOG.md) · 🇮🇱 [he](../he/CHANGELOG.md) · 🇵🇭 [phi](../phi/CHANGELOG.md) · 🇧🇷 [pt-BR](../pt-BR/CHANGELOG.md)
+🌐 **Languages:** 🇺🇸 [English](../../../CHANGELOG.md) · 🇪🇸 [es](../es/CHANGELOG.md) · 🇫🇷 [fr](../fr/CHANGELOG.md) · 🇩🇪 [de](../de/CHANGELOG.md) · 🇮🇹 [it](../it/CHANGELOG.md) · 🇷🇺 [ru](../ru/CHANGELOG.md) · 🇨🇳 [zh-CN](../zh-CN/CHANGELOG.md) · 🇯🇵 [ja](../ja/CHANGELOG.md) · 🇰🇷 [ko](../ko/CHANGELOG.md) · 🇸🇦 [ar](../ar/CHANGELOG.md) · 🇮🇳 [in](../in/CHANGELOG.md) · 🇹🇭 [th](../th/CHANGELOG.md) · 🇻🇳 [vi](../vi/CHANGELOG.md) · 🇮🇩 [id](../id/CHANGELOG.md) · 🇲🇾 [ms](../ms/CHANGELOG.md) · 🇳🇱 [nl](../nl/CHANGELOG.md) · 🇵🇱 [pl](../pl/CHANGELOG.md) · 🇸🇪 [sv](../sv/CHANGELOG.md) · 🇳🇴 [no](../no/CHANGELOG.md) · 🇩🇰 [da](../da/CHANGELOG.md) · 🇫🇮 [fi](../fi/CHANGELOG.md) · 🇵🇹 [pt](../pt/CHANGELOG.md) · 🇷🇴 [ro](../ro/CHANGELOG.md) · 🇭🇺 [hu](../hu/CHANGELOG.md) · 🇧🇬 [bg](../bg/CHANGELOG.md) · 🇸🇰 [sk](../sk/CHANGELOG.md) · 🇺🇦 [uk-UA](../uk-UA/CHANGELOG.md) · 🇮🇱 [he](../he/CHANGELOG.md) · 🇵🇭 [phi](../phi/CHANGELOG.md) · 🇧🇷 [pt-BR](../pt-BR/CHANGELOG.md) · 🇨🇿 [cs](../cs/CHANGELOG.md)
---
-
## [Unreleased]
+### 🛠️ Maintenance
+
+- **AGENTS.md rewrite:** Condensed from 297→153 lines. Added build/lint/test commands (including single-test execution), code style guidelines (Prettier, TypeScript, ESLint, naming, imports, error handling, security), and trimmed verbose architecture tables for AI agent consumption.
+
+## [3.4.2] - 2026-04-01
+
+### 🐛 Bug Fixes
+
+- **CI Stabilization:** Fixed failing analytics/settings Playwright selectors and request assertions so GitHub Actions E2E runs pass reliably across localized UIs and switch-based controls.
+- **Deterministic Tests:** Removed date-sensitive quota fixtures from Copilot usage tests and aligned idempotency/model catalog tests with the merged runtime behavior.
+- **MCP Type Hardening:** Removed zero-budget explicit `any` regressions from the MCP server tool registration path, restoring the `check:any-budget:t11` workflow gate.
+
+### 🛠️ Maintenance
+
+- **Release Branch Integration:** Consolidated the active feature branches into `release/v3.4.2` on top of current `main` and validated the branch with lint, unit, coverage, build, and CI-mode E2E runs.
+
+## [3.4.1] - 2026-03-31
+
+> [!WARNING]
+> **BREAKING CHANGE: request logging, retention, and logging environment variables have been redesigned.**
+> On the first startup after upgrading, OmniRoute archives legacy request logs from `DATA_DIR/logs/`, legacy `DATA_DIR/call_logs/`, and `DATA_DIR/log.txt` into `DATA_DIR/log_archives/*.zip`, then removes the deprecated layout and switches to the new unified artifact format under `DATA_DIR/call_logs/`.
+
+### ✨ New Features
+
+- **.ENV Migration Utility:** Included `scripts/migrate-env.mjs` to seamlessly migrate ` Your key looks like: `sk-xxxxxxxxxxxxxxxx-xxxxxxxxx`
-
----
-
-## Step 2 — Install CLI Tools
-
-All npm-based tools require Node.js 18+:
-
-```bash
-# Claude Code (Anthropic)
-npm install -g @anthropic-ai/claude-code
-
-# OpenAI Codex
-npm install -g @openai/codex
-
-# Gemini CLI (Google)
-npm install -g @google/gemini-cli
-
-# OpenCode
-npm install -g opencode-ai
-
-# Cline
-npm install -g cline
-
-# KiloCode
-npm install -g kilecode
-
-# Kiro CLI (Amazon — requires curl + unzip)
-apt-get install -y unzip # on Debian/Ubuntu
-curl -fsSL https://cli.kiro.dev/install | bash
-export PATH="$HOME/.local/bin:$PATH" # add to ~/.bashrc
-```
-
-**Verify:**
-
-```bash
-claude --version # 2.x.x
-codex --version # 0.x.x
-gemini --version # 0.x.x
-opencode --version # x.x.x
-cline --version # 2.x.x
-kilocode --version # x.x.x (or: kilo --version)
-kiro-cli --version # 1.x.x
-```
-
----
-
-## Step 3 — Set Global Environment Variables
-
-Add to `~/.bashrc` (or `~/.zshrc`), then run `source ~/.bashrc`:
-
-```bash
-# OmniRoute Universal Endpoint
-export OPENAI_BASE_URL="http://localhost:20128/v1"
-export OPENAI_API_KEY="sk-your-omniroute-key"
-export ANTHROPIC_BASE_URL="http://localhost:20128/v1"
-export ANTHROPIC_API_KEY="sk-your-omniroute-key"
-export GEMINI_BASE_URL="http://localhost:20128/v1"
-export GEMINI_API_KEY="sk-your-omniroute-key"
-```
-
-> For a **remote server** replace `localhost:20128` with the server IP or domain,
-> e.g. `http://192.168.0.15:20128`.
-
----
-
-## Step 4 — Configure Each Tool
-
-### Claude Code
-
-```bash
-# Via CLI:
-claude config set --global api-base-url http://localhost:20128/v1
-
-# Or create ~/.claude/settings.json:
-mkdir -p ~/.claude && cat > ~/.claude/settings.json << EOF
-{
- "apiBaseUrl": "http://localhost:20128/v1",
- "apiKey": "sk-your-omniroute-key"
-}
-EOF
-```
-
-**Test:** `claude "say hello"`
-
----
-
-### OpenAI Codex
-
-```bash
-mkdir -p ~/.codex && cat > ~/.codex/config.yaml << EOF
-model: auto
-apiKey: sk-your-omniroute-key
-apiBaseUrl: http://localhost:20128/v1
-EOF
-```
-
-**Test:** `codex "what is 2+2?"`
-
----
-
-### Gemini CLI
-
-```bash
-mkdir -p ~/.gemini && cat > ~/.gemini/settings.json << EOF
-{
- "apiKey": "sk-your-omniroute-key",
- "baseUrl": "http://localhost:20128/v1"
-}
-EOF
-```
-
-**Test:** `gemini "hello"`
-
----
-
-### OpenCode
-
-```bash
-mkdir -p ~/.config/opencode && cat > ~/.config/opencode/config.toml << EOF
-[provider.openai]
-base_url = "http://localhost:20128/v1"
-api_key = "sk-your-omniroute-key"
-EOF
-```
-
-**Test:** `opencode`
-
----
-
-### Cline (CLI or VS Code)
-
-**CLI mode:**
-
-```bash
-mkdir -p ~/.cline/data && cat > ~/.cline/data/globalState.json << EOF
-{
- "apiProvider": "openai",
- "openAiBaseUrl": "http://localhost:20128/v1",
- "openAiApiKey": "sk-your-omniroute-key"
-}
-EOF
-```
-
-**VS Code mode:**
-Cline extension settings → API Provider: `OpenAI Compatible` → Base URL: `http://localhost:20128/v1`
-
-Or use the OmniRoute dashboard → **CLI Tools → Cline → Apply Config**.
-
----
-
-### KiloCode (CLI or VS Code)
-
-**CLI mode:**
-
-```bash
-kilocode --api-base http://localhost:20128/v1 --api-key sk-your-omniroute-key
-```
-
-**VS Code settings:**
-
-```json
-{
- "kilo-code.openAiBaseUrl": "http://localhost:20128/v1",
- "kilo-code.apiKey": "sk-your-omniroute-key"
-}
-```
-
-Or use the OmniRoute dashboard → **CLI Tools → KiloCode → Apply Config**.
-
----
-
-### Continue (VS Code Extension)
-
-Edit `~/.continue/config.yaml`:
-
-```yaml
-models:
- - name: OmniRoute
- provider: openai
- model: auto
- apiBase: http://localhost:20128/v1
- apiKey: sk-your-omniroute-key
- default: true
-```
-
-Restart VS Code after editing.
-
----
-
-### Kiro CLI (Amazon)
-
-```bash
-# Login to your AWS/Kiro account:
-kiro-cli login
-
-# The CLI uses its own auth — OmniRoute is not needed as backend for Kiro CLI itself.
-# Use kiro-cli alongside OmniRoute for other tools.
-kiro-cli status
-```
-
----
-
-### Cursor (Desktop App)
-
-> **Note:** Cursor routes requests through its cloud. For OmniRoute integration,
-> enable **Cloud Endpoint** in OmniRoute Settings and use your public domain URL.
-
-Via GUI: **Settings → Models → OpenAI API Key**
-
-- Base URL: `https://your-domain.com/v1`
-- API Key: your OmniRoute key
-
----
-
-## Dashboard Auto-Configuration
-
-The OmniRoute dashboard automates configuration for most tools:
-
-1. Go to `http://localhost:20128/dashboard/cli-tools`
-2. Expand any tool card
-3. Select your API key from the dropdown
-4. Click **Apply Config** (if tool is detected as installed)
-5. Or copy the generated config snippet manually
-
----
-
-## Built-in Agents: Droid & OpenClaw
-
-**Droid** and **OpenClaw** are AI agents built directly into OmniRoute — no installation needed.
-They run as internal routes and use OmniRoute's model routing automatically.
-
-- Access: `http://localhost:20128/dashboard/agents`
-- Configure: same combos and providers as all other tools
-- No API key or CLI install required
-
----
-
-## Available API Endpoints
-
-| Endpoint | Description | Use For |
-| -------------------------- | ----------------------------- | --------------------------- |
-| `/v1/chat/completions` | Standard chat (all providers) | All modern tools |
-| `/v1/responses` | Responses API (OpenAI format) | Codex, agentic workflows |
-| `/v1/completions` | Legacy text completions | Older tools using `prompt:` |
-| `/v1/embeddings` | Text embeddings | RAG, search |
-| `/v1/images/generations` | Image generation | DALL-E, Flux, etc. |
-| `/v1/audio/speech` | Text-to-speech | ElevenLabs, OpenAI TTS |
-| `/v1/audio/transcriptions` | Speech-to-text | Deepgram, AssemblyAI |
-
----
-
-## Troubleshooting
-
-| Error | Cause | Fix |
-| ------------------------- | ----------------------- | ------------------------------------------ |
-| `Connection refused` | OmniRoute not running | `pm2 start omniroute` |
-| `401 Unauthorized` | Wrong API key | Check in `/dashboard/api-manager` |
-| `No combo configured` | No active routing combo | Set up in `/dashboard/combos` |
-| `invalid model` | Model not in catalog | Use `auto` or check `/dashboard/providers` |
-| CLI shows "not installed" | Binary not in PATH | Check `which ` |
-| `kiro-cli: not found` | Not in PATH | `export PATH="$HOME/.local/bin:$PATH"` |
-
----
-
-## Quick Setup Script (One Command)
-
-```bash
-# Install all CLIs and configure for OmniRoute (replace with your key and server URL)
-OMNIROUTE_URL="http://localhost:20128/v1"
-OMNIROUTE_KEY="sk-your-omniroute-key"
-
-npm install -g @anthropic-ai/claude-code @openai/codex @google/gemini-cli opencode-ai cline kilecode
-
-# Kiro CLI
-apt-get install -y unzip 2>/dev/null; curl -fsSL https://cli.kiro.dev/install | bash
-
-# Write configs
-mkdir -p ~/.claude ~/.codex ~/.gemini ~/.config/opencode ~/.continue
-
-cat > ~/.claude/settings.json <<< "{\"apiBaseUrl\":\"$OMNIROUTE_URL\",\"apiKey\":\"$OMNIROUTE_KEY\"}"
-cat > ~/.codex/config.yaml <<< "model: auto\napiKey: $OMNIROUTE_KEY\napiBaseUrl: $OMNIROUTE_URL"
-cat > ~/.gemini/settings.json <<< "{\"apiKey\":\"$OMNIROUTE_KEY\",\"baseUrl\":\"$OMNIROUTE_URL\"}"
-cat >> ~/.bashrc << EOF
-export OPENAI_BASE_URL="$OMNIROUTE_URL"
-export OPENAI_API_KEY="$OMNIROUTE_KEY"
-export ANTHROPIC_BASE_URL="$OMNIROUTE_URL"
-export ANTHROPIC_API_KEY="$OMNIROUTE_KEY"
-EOF
-
-source ~/.bashrc
-echo "✅ All CLIs installed and configured for OmniRoute"
-```
diff --git a/docs/i18n/hu/CODEBASE_DOCUMENTATION.md b/docs/i18n/hu/CODEBASE_DOCUMENTATION.md
deleted file mode 100644
index e2d7950052..0000000000
--- a/docs/i18n/hu/CODEBASE_DOCUMENTATION.md
+++ /dev/null
@@ -1,593 +0,0 @@
-🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/CODEBASE_DOCUMENTATION.md) · 🇪🇸 [es](../es/CODEBASE_DOCUMENTATION.md) · 🇫🇷 [fr](../fr/CODEBASE_DOCUMENTATION.md) · 🇩🇪 [de](../de/CODEBASE_DOCUMENTATION.md) · 🇮🇹 [it](../it/CODEBASE_DOCUMENTATION.md) · 🇷🇺 [ru](../ru/CODEBASE_DOCUMENTATION.md) · 🇨🇳 [zh-CN](../zh-CN/CODEBASE_DOCUMENTATION.md) · 🇯🇵 [ja](../ja/CODEBASE_DOCUMENTATION.md) · 🇰🇷 [ko](../ko/CODEBASE_DOCUMENTATION.md) · 🇸🇦 [ar](../ar/CODEBASE_DOCUMENTATION.md) · 🇮🇳 [in](../in/CODEBASE_DOCUMENTATION.md) · 🇹🇭 [th](../th/CODEBASE_DOCUMENTATION.md) · 🇻🇳 [vi](../vi/CODEBASE_DOCUMENTATION.md) · 🇮🇩 [id](../id/CODEBASE_DOCUMENTATION.md) · 🇲🇾 [ms](../ms/CODEBASE_DOCUMENTATION.md) · 🇳🇱 [nl](../nl/CODEBASE_DOCUMENTATION.md) · 🇵🇱 [pl](../pl/CODEBASE_DOCUMENTATION.md) · 🇸🇪 [sv](../sv/CODEBASE_DOCUMENTATION.md) · 🇳🇴 [no](../no/CODEBASE_DOCUMENTATION.md) · 🇩🇰 [da](../da/CODEBASE_DOCUMENTATION.md) · 🇫🇮 [fi](../fi/CODEBASE_DOCUMENTATION.md) · 🇵🇹 [pt](../pt/CODEBASE_DOCUMENTATION.md) · 🇷🇴 [ro](../ro/CODEBASE_DOCUMENTATION.md) · 🇭🇺 [hu](../hu/CODEBASE_DOCUMENTATION.md) · 🇧🇬 [bg](../bg/CODEBASE_DOCUMENTATION.md) · 🇸🇰 [sk](../sk/CODEBASE_DOCUMENTATION.md) · 🇺🇦 [uk-UA](../uk-UA/CODEBASE_DOCUMENTATION.md) · 🇮🇱 [he](../he/CODEBASE_DOCUMENTATION.md) · 🇵🇭 [phi](../phi/CODEBASE_DOCUMENTATION.md)
-
----
-
-# omniroute — Codebase Documentation
-
-🌐 **Languages:** 🇺🇸 [English](CODEBASE_DOCUMENTATION.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/CODEBASE_DOCUMENTATION.md) | 🇪🇸 [Español](i18n/es/CODEBASE_DOCUMENTATION.md) | 🇫🇷 [Français](i18n/fr/CODEBASE_DOCUMENTATION.md) | 🇮🇹 [Italiano](i18n/it/CODEBASE_DOCUMENTATION.md) | 🇷🇺 [Русский](i18n/ru/CODEBASE_DOCUMENTATION.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/CODEBASE_DOCUMENTATION.md) | 🇩🇪 [Deutsch](i18n/de/CODEBASE_DOCUMENTATION.md) | 🇮🇳 [हिन्दी](i18n/in/CODEBASE_DOCUMENTATION.md) | 🇹🇭 [ไทย](i18n/th/CODEBASE_DOCUMENTATION.md) | 🇺🇦 [Українська](i18n/uk-UA/CODEBASE_DOCUMENTATION.md) | 🇸🇦 [العربية](i18n/ar/CODEBASE_DOCUMENTATION.md) | 🇯🇵 [日本語](i18n/ja/CODEBASE_DOCUMENTATION.md) | 🇻🇳 [Tiếng Việt](i18n/vi/CODEBASE_DOCUMENTATION.md) | 🇧🇬 [Български](i18n/bg/CODEBASE_DOCUMENTATION.md) | 🇩🇰 [Dansk](i18n/da/CODEBASE_DOCUMENTATION.md) | 🇫🇮 [Suomi](i18n/fi/CODEBASE_DOCUMENTATION.md) | 🇮🇱 [עברית](i18n/he/CODEBASE_DOCUMENTATION.md) | 🇭🇺 [Magyar](i18n/hu/CODEBASE_DOCUMENTATION.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/CODEBASE_DOCUMENTATION.md) | 🇰🇷 [한국어](i18n/ko/CODEBASE_DOCUMENTATION.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/CODEBASE_DOCUMENTATION.md) | 🇳🇱 [Nederlands](i18n/nl/CODEBASE_DOCUMENTATION.md) | 🇳🇴 [Norsk](i18n/no/CODEBASE_DOCUMENTATION.md) | 🇵🇹 [Português (Portugal)](i18n/pt/CODEBASE_DOCUMENTATION.md) | 🇷🇴 [Română](i18n/ro/CODEBASE_DOCUMENTATION.md) | 🇵🇱 [Polski](i18n/pl/CODEBASE_DOCUMENTATION.md) | 🇸🇰 [Slovenčina](i18n/sk/CODEBASE_DOCUMENTATION.md) | 🇸🇪 [Svenska](i18n/sv/CODEBASE_DOCUMENTATION.md) | 🇵🇭 [Filipino](i18n/phi/CODEBASE_DOCUMENTATION.md)
-
-> A comprehensive, beginner-friendly guide to the **omniroute** multi-provider AI proxy router.
-
----
-
-## 1. What Is omniroute?
-
-omniroute is a **proxy router** that sits between AI clients (Claude CLI, Codex, Cursor IDE, etc.) and AI providers (Anthropic, Google, OpenAI, AWS, GitHub, etc.). It solves one big problem:
-
-> **Different AI clients speak different "languages" (API formats), and different AI providers expect different "languages" too.** omniroute translates between them automatically.
-
-Think of it like a universal translator at the United Nations — any delegate can speak any language, and the translator converts it for any other delegate.
-
----
-
-## 2. Architecture Overview
-
-```mermaid
-graph LR
- subgraph Clients
- A[Claude CLI]
- B[Codex]
- C[Cursor IDE]
- D[OpenAI-compatible]
- end
-
- subgraph omniroute
- E[Handler Layer]
- F[Translator Layer]
- G[Executor Layer]
- H[Services Layer]
- end
-
- subgraph Providers
- I[Anthropic Claude]
- J[Google Gemini]
- K[OpenAI / Codex]
- L[GitHub Copilot]
- M[AWS Kiro]
- N[Antigravity]
- O[Cursor API]
- end
-
- A --> E
- B --> E
- C --> E
- D --> E
- E --> F
- F --> G
- G --> I
- G --> J
- G --> K
- G --> L
- G --> M
- G --> N
- G --> O
- H -.-> E
- H -.-> G
-```
-
-### Core Principle: Hub-and-Spoke Translation
-
-All format translation passes through **OpenAI format as the hub**:
-
-```
-Client Format → [OpenAI Hub] → Provider Format (request)
-Provider Format → [OpenAI Hub] → Client Format (response)
-```
-
-This means you only need **N translators** (one per format) instead of **N²** (every pair).
-
----
-
-## 3. Project Structure
-
-```
-omniroute/
-├── open-sse/ ← Core proxy library (portable, framework-agnostic)
-│ ├── index.js ← Main entry point, exports everything
-│ ├── config/ ← Configuration & constants
-│ ├── executors/ ← Provider-specific request execution
-│ ├── handlers/ ← Request handling orchestration
-│ ├── services/ ← Business logic (auth, models, fallback, usage)
-│ ├── translator/ ← Format translation engine
-│ │ ├── request/ ← Request translators (8 files)
-│ │ ├── response/ ← Response translators (7 files)
-│ │ └── helpers/ ← Shared translation utilities (6 files)
-│ └── utils/ ← Utility functions
-├── src/ ← Application layer (Express/Worker runtime)
-│ ├── app/ ← Web UI, API routes, middleware
-│ ├── lib/ ← Database, auth, and shared library code
-│ ├── mitm/ ← Man-in-the-middle proxy utilities
-│ ├── models/ ← Database models
-│ ├── shared/ ← Shared utilities (wrappers around open-sse)
-│ ├── sse/ ← SSE endpoint handlers
-│ └── store/ ← State management
-├── data/ ← Runtime data (credentials, logs)
-│ └── provider-credentials.json (external credentials override, gitignored)
-└── tester/ ← Test utilities
-```
-
----
-
-## 4. Module-by-Module Breakdown
-
-### 4.1 Config (`open-sse/config/`)
-
-The **single source of truth** for all provider configuration.
-
-| File | Purpose |
-| ----------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| `constants.ts` | `PROVIDERS` object with base URLs, OAuth credentials (defaults), headers, and default system prompts for every provider. Also defines `HTTP_STATUS`, `ERROR_TYPES`, `COOLDOWN_MS`, `BACKOFF_CONFIG`, and `SKIP_PATTERNS`. |
-| `credentialLoader.ts` | Loads external credentials from `data/provider-credentials.json` and merges them over the hardcoded defaults in `PROVIDERS`. Keeps secrets out of source control while maintaining backwards compatibility. |
-| `providerModels.ts` | Central model registry: maps provider aliases → model IDs. Functions like `getModels()`, `getProviderByAlias()`. |
-| `codexInstructions.ts` | System instructions injected into Codex requests (editing constraints, sandbox rules, approval policies). |
-| `defaultThinkingSignature.ts` | Default "thinking" signatures for Claude and Gemini models. |
-| `ollamaModels.ts` | Schema definition for local Ollama models (name, size, family, quantization). |
-
-#### Credential Loading Flow
-
-```mermaid
-flowchart TD
- A["App starts"] --> B["constants.ts defines PROVIDERS\nwith hardcoded defaults"]
- B --> C{"data/provider-credentials.json\nexists?"}
- C -->|Yes| D["credentialLoader reads JSON"]
- C -->|No| E["Use hardcoded defaults"]
- D --> F{"For each provider in JSON"}
- F --> G{"Provider exists\nin PROVIDERS?"}
- G -->|No| H["Log warning, skip"]
- G -->|Yes| I{"Value is object?"}
- I -->|No| J["Log warning, skip"]
- I -->|Yes| K["Merge clientId, clientSecret,\ntokenUrl, authUrl, refreshUrl"]
- K --> F
- H --> F
- J --> F
- F -->|Done| L["PROVIDERS ready with\nmerged credentials"]
- E --> L
-```
-
----
-
-### 4.2 Executors (`open-sse/executors/`)
-
-Executors encapsulate **provider-specific logic** using the **Strategy Pattern**. Each executor overrides base methods as needed.
-
-```mermaid
-classDiagram
- class BaseExecutor {
- +buildUrl(model, stream, options)
- +buildHeaders(credentials, stream, body)
- +transformRequest(body, model, stream, credentials)
- +execute(url, options)
- +shouldRetry(status, error)
- +refreshCredentials(credentials, log)
- }
-
- class DefaultExecutor {
- +refreshCredentials()
- }
-
- class AntigravityExecutor {
- +buildUrl()
- +buildHeaders()
- +transformRequest()
- +shouldRetry()
- +refreshCredentials()
- }
-
- class CursorExecutor {
- +buildUrl()
- +buildHeaders()
- +transformRequest()
- +parseResponse()
- +generateChecksum()
- }
-
- class KiroExecutor {
- +buildUrl()
- +buildHeaders()
- +transformRequest()
- +parseEventStream()
- +refreshCredentials()
- }
-
- BaseExecutor <|-- DefaultExecutor
- BaseExecutor <|-- AntigravityExecutor
- BaseExecutor <|-- CursorExecutor
- BaseExecutor <|-- KiroExecutor
- BaseExecutor <|-- CodexExecutor
- BaseExecutor <|-- GeminiCLIExecutor
- BaseExecutor <|-- GithubExecutor
-```
-
-| Executor | Provider | Key Specializations |
-| ---------------- | ------------------------------------------ | ------------------------------------------------------------------------------------------------------------------- |
-| `base.ts` | — | Abstract base: URL building, headers, retry logic, credential refresh |
-| `default.ts` | Claude, Gemini, OpenAI, GLM, Kimi, MiniMax | Generic OAuth token refresh for standard providers |
-| `antigravity.ts` | Google Cloud Code | Project/session ID generation, multi-URL fallback, custom retry parsing from error messages ("reset after 2h7m23s") |
-| `cursor.ts` | Cursor IDE | **Most complex**: SHA-256 checksum auth, Protobuf request encoding, binary EventStream → SSE response parsing |
-| `codex.ts` | OpenAI Codex | Injects system instructions, manages thinking levels, removes unsupported parameters |
-| `gemini-cli.ts` | Google Gemini CLI | Custom URL building (`streamGenerateContent`), Google OAuth token refresh |
-| `github.ts` | GitHub Copilot | Dual token system (GitHub OAuth + Copilot token), VSCode header mimicking |
-| `kiro.ts` | AWS CodeWhisperer | AWS EventStream binary parsing, AMZN event frames, token estimation |
-| `index.ts` | — | Factory: maps provider name → executor class, with default fallback |
-
----
-
-### 4.3 Handlers (`open-sse/handlers/`)
-
-The **orchestration layer** — coordinates translation, execution, streaming, and error handling.
-
-| File | Purpose |
-| --------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| `chatCore.ts` | **Central orchestrator** (~600 lines). Handles the complete request lifecycle: format detection → translation → executor dispatch → streaming/non-streaming response → token refresh → error handling → usage logging. |
-| `responsesHandler.ts` | Adapter for OpenAI's Responses API: converts Responses format → Chat Completions → sends to `chatCore` → converts SSE back to Responses format. |
-| `embeddings.ts` | Embedding generation handler: resolves embedding model → provider, dispatches to provider API, returns OpenAI-compatible embedding response. Supports 6+ providers. |
-| `imageGeneration.ts` | Image generation handler: resolves image model → provider, supports OpenAI-compatible, Gemini-image (Antigravity), and fallback (Nebius) modes. Returns base64 or URL images. |
-
-#### Request Lifecycle (chatCore.ts)
-
-```mermaid
-sequenceDiagram
- participant Client
- participant chatCore
- participant Translator
- participant Executor
- participant Provider
-
- Client->>chatCore: Request (any format)
- chatCore->>chatCore: Detect source format
- chatCore->>chatCore: Check bypass patterns
- chatCore->>chatCore: Resolve model & provider
- chatCore->>Translator: Translate request (source → OpenAI → target)
- chatCore->>Executor: Get executor for provider
- Executor->>Executor: Build URL, headers, transform request
- Executor->>Executor: Refresh credentials if needed
- Executor->>Provider: HTTP fetch (streaming or non-streaming)
-
- alt Streaming
- Provider-->>chatCore: SSE stream
- chatCore->>chatCore: Pipe through SSE transform stream
- Note over chatCore: Transform stream translates
each chunk: target → OpenAI → source
- chatCore-->>Client: Translated SSE stream
- else Non-streaming
- Provider-->>chatCore: JSON response
- chatCore->>Translator: Translate response
- chatCore-->>Client: Translated JSON
- end
-
- alt Error (401, 429, 500...)
- chatCore->>Executor: Retry with credential refresh
- chatCore->>chatCore: Account fallback logic
- end
-```
-
----
-
-### 4.4 Services (`open-sse/services/`)
-
-Business logic that supports the handlers and executors.
-
-| File | Purpose |
-| -------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| `provider.ts` | **Format detection** (`detectFormat`): analyzes request body structure to identify Claude/OpenAI/Gemini/Antigravity/Responses formats (includes `max_tokens` heuristic for Claude). Also: URL building, header building, thinking config normalization. Supports `openai-compatible-*` and `anthropic-compatible-*` dynamic providers. |
-| `model.ts` | Model string parsing (`claude/model-name` → `{provider: "claude", model: "model-name"}`), alias resolution with collision detection, input sanitization (rejects path traversal/control chars), and model info resolution with async alias getter support. |
-| `accountFallback.ts` | Rate-limit handling: exponential backoff (1s → 2s → 4s → max 2min), account cooldown management, error classification (which errors trigger fallback vs. not). |
-| `tokenRefresh.ts` | OAuth token refresh for **every provider**: Google (Gemini, Antigravity), Claude, Codex, Qwen, Qoder, GitHub (OAuth + Copilot dual-token), Kiro (AWS SSO OIDC + Social Auth). Includes in-flight promise deduplication cache and retry with exponential backoff. |
-| `combo.ts` | **Combo models**: chains of fallback models. If model A fails with a fallback-eligible error, try model B, then C, etc. Returns actual upstream status codes. |
-| `usage.ts` | Fetches quota/usage data from provider APIs (GitHub Copilot quotas, Antigravity model quotas, Codex rate limits, Kiro usage breakdowns, Claude settings). |
-| `accountSelector.ts` | Smart account selection with scoring algorithm: considers priority, health status, round-robin position, and cooldown state to pick the optimal account for each request. |
-| `contextManager.ts` | Request context lifecycle management: creates and tracks per-request context objects with metadata (request ID, timestamps, provider info) for debugging and logging. |
-| `ipFilter.ts` | IP-based access control: supports allowlist and blocklist modes. Validates client IP against configured rules before processing API requests. |
-| `sessionManager.ts` | Session tracking with client fingerprinting: tracks active sessions using hashed client identifiers, monitors request counts, and provides session metrics. |
-| `signatureCache.ts` | Request signature-based deduplication cache: prevents duplicate requests by caching recent request signatures and returning cached responses for identical requests within a time window. |
-| `systemPrompt.ts` | Global system prompt injection: prepends or appends a configurable system prompt to all requests, with per-provider compatibility handling. |
-| `thinkingBudget.ts` | Reasoning token budget management: supports passthrough, auto (strip thinking config), custom (fixed budget), and adaptive (complexity-scaled) modes for controlling thinking/reasoning tokens. |
-| `wildcardRouter.ts` | Wildcard model pattern routing: resolves wildcard patterns (e.g., `*/claude-*`) to concrete provider/model pairs based on availability and priority. |
-
-#### Token Refresh Deduplication
-
-```mermaid
-sequenceDiagram
- participant R1 as Request 1
- participant R2 as Request 2
- participant Cache as refreshPromiseCache
- participant OAuth as OAuth Provider
-
- R1->>Cache: getAccessToken("gemini", token)
- Cache->>Cache: No in-flight promise
- Cache->>OAuth: Start refresh
- R2->>Cache: getAccessToken("gemini", token)
- Cache->>Cache: Found in-flight promise
- Cache-->>R2: Return existing promise
- OAuth-->>Cache: New access token
- Cache-->>R1: New access token
- Cache-->>R2: Same access token (shared)
- Cache->>Cache: Delete cache entry
-```
-
-#### Account Fallback State Machine
-
-```mermaid
-stateDiagram-v2
- [*] --> Active
- Active --> Error: Request fails (401/429/500)
- Error --> Cooldown: Apply backoff
- Cooldown --> Active: Cooldown expires
- Active --> Active: Request succeeds (reset backoff)
-
- state Error {
- [*] --> ClassifyError
- ClassifyError --> ShouldFallback: Rate limit / Auth / Transient
- ClassifyError --> NoFallback: 400 Bad Request
- }
-
- state Cooldown {
- [*] --> ExponentialBackoff
- ExponentialBackoff: Level 0 = 1s
- ExponentialBackoff: Level 1 = 2s
- ExponentialBackoff: Level 2 = 4s
- ExponentialBackoff: Max = 2min
- }
-```
-
-#### Combo Model Chain
-
-```mermaid
-flowchart LR
- A["Request with\ncombo model"] --> B["Model A"]
- B -->|"2xx Success"| C["Return response"]
- B -->|"429/401/500"| D{"Fallback\neligible?"}
- D -->|Yes| E["Model B"]
- D -->|No| F["Return error"]
- E -->|"2xx Success"| C
- E -->|"429/401/500"| G{"Fallback\neligible?"}
- G -->|Yes| H["Model C"]
- G -->|No| F
- H -->|"2xx Success"| C
- H -->|"Fail"| I["All failed →\nReturn last status"]
-```
-
----
-
-### 4.5 Translator (`open-sse/translator/`)
-
-The **format translation engine** using a self-registering plugin system.
-
-#### Architecture
-
-```mermaid
-graph TD
- subgraph "Request Translation"
- A["Claude → OpenAI"]
- B["Gemini → OpenAI"]
- C["Antigravity → OpenAI"]
- D["OpenAI Responses → OpenAI"]
- E["OpenAI → Claude"]
- F["OpenAI → Gemini"]
- G["OpenAI → Kiro"]
- H["OpenAI → Cursor"]
- end
-
- subgraph "Response Translation"
- I["Claude → OpenAI"]
- J["Gemini → OpenAI"]
- K["Kiro → OpenAI"]
- L["Cursor → OpenAI"]
- M["OpenAI → Claude"]
- N["OpenAI → Antigravity"]
- O["OpenAI → Responses"]
- end
-```
-
-| Directory | Files | Description |
-| ------------ | ------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| `request/` | 8 translators | Convert request bodies between formats. Each file self-registers via `register(from, to, fn)` on import. |
-| `response/` | 7 translators | Convert streaming response chunks between formats. Handles SSE event types, thinking blocks, tool calls. |
-| `helpers/` | 6 helpers | Shared utilities: `claudeHelper` (system prompt extraction, thinking config), `geminiHelper` (parts/contents mapping), `openaiHelper` (format filtering), `toolCallHelper` (ID generation, missing response injection), `maxTokensHelper`, `responsesApiHelper`. |
-| `index.ts` | — | Translation engine: `translateRequest()`, `translateResponse()`, state management, registry. |
-| `formats.ts` | — | Format constants: `OPENAI`, `CLAUDE`, `GEMINI`, `ANTIGRAVITY`, `KIRO`, `CURSOR`, `OPENAI_RESPONSES`. |
-
-#### Key Design: Self-Registering Plugins
-
-```javascript
-// Each translator file calls register() on import:
-import { register } from "../index.js";
-register("claude", "openai", translateClaudeToOpenAI);
-
-// The index.js imports all translator files, triggering registration:
-import "./request/claude-to-openai.js"; // ← self-registers
-```
-
----
-
-### 4.6 Utils (`open-sse/utils/`)
-
-| File | Purpose |
-| ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
-| `error.ts` | Error response building (OpenAI-compatible format), upstream error parsing, Antigravity retry-time extraction from error messages, SSE error streaming. |
-| `stream.ts` | **SSE Transform Stream** — the core streaming pipeline. Two modes: `TRANSLATE` (full format translation) and `PASSTHROUGH` (normalize + extract usage). Handles chunk buffering, usage estimation, content length tracking. Per-stream encoder/decoder instances avoid shared state. |
-| `streamHelpers.ts` | Low-level SSE utilities: `parseSSELine` (whitespace-tolerant), `hasValuableContent` (filters empty chunks for OpenAI/Claude/Gemini), `fixInvalidId`, `formatSSE` (format-aware SSE serialization with `perf_metrics` cleanup). |
-| `usageTracking.ts` | Token usage extraction from any format (Claude/OpenAI/Gemini/Responses), estimation with separate tool/message char-per-token ratios, buffer addition (2000 tokens safety margin), format-specific field filtering, console logging with ANSI colors. |
-| `requestLogger.ts` | File-based request logging (opt-in via `ENABLE_REQUEST_LOGS=true`). Creates session folders with numbered files: `1_req_client.json` → `7_res_client.txt`. All I/O is async (fire-and-forget). Masks sensitive headers. |
-| `bypassHandler.ts` | Intercepts specific patterns from Claude CLI (title extraction, warmup, count) and returns fake responses without calling any provider. Supports both streaming and non-streaming. Intentionally limited to Claude CLI scope. |
-| `networkProxy.ts` | Resolves outbound proxy URL for a given provider with precedence: provider-specific config → global config → environment variables (`HTTPS_PROXY`/`HTTP_PROXY`/`ALL_PROXY`). Supports `NO_PROXY` exclusions. Caches config for 30s. |
-
-#### SSE Streaming Pipeline
-
-```mermaid
-flowchart TD
- A["Provider SSE stream"] --> B["TextDecoder\n(per-stream instance)"]
- B --> C["Buffer lines\n(split on newline)"]
- C --> D["parseSSELine()\n(trim whitespace, parse JSON)"]
- D --> E{"Mode?"}
- E -->|TRANSLATE| F["translateResponse()\ntarget → OpenAI → source"]
- E -->|PASSTHROUGH| G["fixInvalidId()\nnormalize chunk"]
- F --> H["hasValuableContent()\nfilter empty chunks"]
- G --> H
- H -->|"Has content"| I["extractUsage()\ntrack token counts"]
- H -->|"Empty"| J["Skip chunk"]
- I --> K["formatSSE()\nserialize + clean perf_metrics"]
- K --> L["TextEncoder\n(per-stream instance)"]
- L --> M["Enqueue to\nclient stream"]
-
- style A fill:#f9f,stroke:#333
- style M fill:#9f9,stroke:#333
-```
-
-#### Request Logger Session Structure
-
-```
-logs/
-└── claude_gemini_claude-sonnet_20260208_143045/
- ├── 1_req_client.json ← Raw client request
- ├── 2_req_source.json ← After initial conversion
- ├── 3_req_openai.json ← OpenAI intermediate format
- ├── 4_req_target.json ← Final target format
- ├── 5_res_provider.txt ← Provider SSE chunks (streaming)
- ├── 5_res_provider.json ← Provider response (non-streaming)
- ├── 6_res_openai.txt ← OpenAI intermediate chunks
- ├── 7_res_client.txt ← Client-facing SSE chunks
- └── 6_error.json ← Error details (if any)
-```
-
----
-
-### 4.7 Application Layer (`src/`)
-
-| Directory | Purpose |
-| ------------- | ---------------------------------------------------------------------- |
-| `src/app/` | Web UI, API routes, Express middleware, OAuth callback handlers |
-| `src/lib/` | Database access (`localDb.ts`, `usageDb.ts`), authentication, shared |
-| `src/mitm/` | Man-in-the-middle proxy utilities for intercepting provider traffic |
-| `src/models/` | Database model definitions |
-| `src/shared/` | Wrappers around open-sse functions (provider, stream, error, etc.) |
-| `src/sse/` | SSE endpoint handlers that wire the open-sse library to Express routes |
-| `src/store/` | Application state management |
-
-#### Notable API Routes
-
-| Route | Methods | Purpose |
-| --------------------------------------------- | --------------- | ------------------------------------------------------------------------------------- |
-| `/api/provider-models` | GET/POST/DELETE | CRUD for custom models per provider |
-| `/api/models/catalog` | GET | Aggregated catalog of all models (chat, embedding, image, custom) grouped by provider |
-| `/api/settings/proxy` | GET/PUT/DELETE | Hierarchical outbound proxy configuration (`global/providers/combos/keys`) |
-| `/api/settings/proxy/test` | POST | Validates proxy connectivity and returns public IP/latency |
-| `/v1/providers/[provider]/chat/completions` | POST | Dedicated per-provider chat completions with model validation |
-| `/v1/providers/[provider]/embeddings` | POST | Dedicated per-provider embeddings with model validation |
-| `/v1/providers/[provider]/images/generations` | POST | Dedicated per-provider image generation with model validation |
-| `/api/settings/ip-filter` | GET/PUT | IP allowlist/blocklist management |
-| `/api/settings/thinking-budget` | GET/PUT | Reasoning token budget configuration (passthrough/auto/custom/adaptive) |
-| `/api/settings/system-prompt` | GET/PUT | Global system prompt injection for all requests |
-| `/api/sessions` | GET | Active session tracking and metrics |
-| `/api/rate-limits` | GET | Per-account rate limit status |
-
----
-
-## 5. Key Design Patterns
-
-### 5.1 Hub-and-Spoke Translation
-
-All formats translate through **OpenAI format as the hub**. Adding a new provider only requires writing **one pair** of translators (to/from OpenAI), not N pairs.
-
-### 5.2 Executor Strategy Pattern
-
-Each provider has a dedicated executor class inheriting from `BaseExecutor`. The factory in `executors/index.ts` selects the right one at runtime.
-
-### 5.3 Self-Registering Plugin System
-
-Translator modules register themselves on import via `register()`. Adding a new translator is just creating a file and importing it.
-
-### 5.4 Account Fallback with Exponential Backoff
-
-When a provider returns 429/401/500, the system can switch to the next account, applying exponential cooldowns (1s → 2s → 4s → max 2min).
-
-### 5.5 Combo Model Chains
-
-A "combo" groups multiple `provider/model` strings. If the first fails, fallback to the next automatically.
-
-### 5.6 Stateful Streaming Translation
-
-Response translation maintains state across SSE chunks (thinking block tracking, tool call accumulation, content block indexing) via the `initState()` mechanism.
-
-### 5.7 Usage Safety Buffer
-
-A 2000-token buffer is added to reported usage to prevent clients from hitting context window limits due to overhead from system prompts and format translation.
-
----
-
-## 6. Supported Formats
-
-| Format | Direction | Identifier |
-| ----------------------- | --------------- | ------------------ |
-| OpenAI Chat Completions | source + target | `openai` |
-| OpenAI Responses API | source + target | `openai-responses` |
-| Anthropic Claude | source + target | `claude` |
-| Google Gemini | source + target | `gemini` |
-| Google Gemini CLI | target only | `gemini-cli` |
-| Antigravity | source + target | `antigravity` |
-| AWS Kiro | target only | `kiro` |
-| Cursor | target only | `cursor` |
-
----
-
-## 7. Supported Providers
-
-| Provider | Auth Method | Executor | Key Notes |
-| ------------------------ | ---------------------- | ----------- | --------------------------------------------- |
-| Anthropic Claude | API key or OAuth | Default | Uses `x-api-key` header |
-| Google Gemini | API key or OAuth | Default | Uses `x-goog-api-key` header |
-| Google Gemini CLI | OAuth | GeminiCLI | Uses `streamGenerateContent` endpoint |
-| Antigravity | OAuth | Antigravity | Multi-URL fallback, custom retry parsing |
-| OpenAI | API key | Default | Standard Bearer auth |
-| Codex | OAuth | Codex | Injects system instructions, manages thinking |
-| GitHub Copilot | OAuth + Copilot token | Github | Dual token, VSCode header mimicking |
-| Kiro (AWS) | AWS SSO OIDC or Social | Kiro | Binary EventStream parsing |
-| Cursor IDE | Checksum auth | Cursor | Protobuf encoding, SHA-256 checksums |
-| Qwen | OAuth | Default | Standard auth |
-| Qoder | OAuth (Basic + Bearer) | Default | Dual auth header |
-| OpenRouter | API key | Default | Standard Bearer auth |
-| GLM, Kimi, MiniMax | API key | Default | Claude-compatible, use `x-api-key` |
-| `openai-compatible-*` | API key | Default | Dynamic: any OpenAI-compatible endpoint |
-| `anthropic-compatible-*` | API key | Default | Dynamic: any Claude-compatible endpoint |
-
----
-
-## 8. Data Flow Summary
-
-### Streaming Request
-
-```mermaid
-flowchart LR
- A["Client"] --> B["detectFormat()"]
- B --> C["translateRequest()\nsource → OpenAI → target"]
- C --> D["Executor\nbuildUrl + buildHeaders"]
- D --> E["fetch(providerURL)"]
- E --> F["createSSEStream()\nTRANSLATE mode"]
- F --> G["parseSSELine()"]
- G --> H["translateResponse()\ntarget → OpenAI → source"]
- H --> I["extractUsage()\n+ addBuffer"]
- I --> J["formatSSE()"]
- J --> K["Client receives\ntranslated SSE"]
- K --> L["logUsage()\nsaveRequestUsage()"]
-```
-
-### Non-Streaming Request
-
-```mermaid
-flowchart LR
- A["Client"] --> B["detectFormat()"]
- B --> C["translateRequest()\nsource → OpenAI → target"]
- C --> D["Executor.execute()"]
- D --> E["translateResponse()\ntarget → OpenAI → source"]
- E --> F["Return JSON\nresponse"]
-```
-
-### Bypass Flow (Claude CLI)
-
-```mermaid
-flowchart LR
- A["Claude CLI request"] --> B{"Match bypass\npattern?"}
- B -->|"Title/Warmup/Count"| C["Generate fake\nOpenAI response"]
- B -->|"No match"| D["Normal flow"]
- C --> E["Translate to\nsource format"]
- E --> F["Return without\ncalling provider"]
-```
diff --git a/docs/i18n/hu/CONTRIBUTING.md b/docs/i18n/hu/CONTRIBUTING.md
new file mode 100644
index 0000000000..ffc88278f7
--- /dev/null
+++ b/docs/i18n/hu/CONTRIBUTING.md
@@ -0,0 +1,299 @@
+# Contributing to OmniRoute (Magyar)
+
+🌐 **Languages:** 🇺🇸 [English](../../../CONTRIBUTING.md) · 🇪🇸 [es](../es/CONTRIBUTING.md) · 🇫🇷 [fr](../fr/CONTRIBUTING.md) · 🇩🇪 [de](../de/CONTRIBUTING.md) · 🇮🇹 [it](../it/CONTRIBUTING.md) · 🇷🇺 [ru](../ru/CONTRIBUTING.md) · 🇨🇳 [zh-CN](../zh-CN/CONTRIBUTING.md) · 🇯🇵 [ja](../ja/CONTRIBUTING.md) · 🇰🇷 [ko](../ko/CONTRIBUTING.md) · 🇸🇦 [ar](../ar/CONTRIBUTING.md) · 🇮🇳 [in](../in/CONTRIBUTING.md) · 🇹🇭 [th](../th/CONTRIBUTING.md) · 🇻🇳 [vi](../vi/CONTRIBUTING.md) · 🇮🇩 [id](../id/CONTRIBUTING.md) · 🇲🇾 [ms](../ms/CONTRIBUTING.md) · 🇳🇱 [nl](../nl/CONTRIBUTING.md) · 🇵🇱 [pl](../pl/CONTRIBUTING.md) · 🇸🇪 [sv](../sv/CONTRIBUTING.md) · 🇳🇴 [no](../no/CONTRIBUTING.md) · 🇩🇰 [da](../da/CONTRIBUTING.md) · 🇫🇮 [fi](../fi/CONTRIBUTING.md) · 🇵🇹 [pt](../pt/CONTRIBUTING.md) · 🇷🇴 [ro](../ro/CONTRIBUTING.md) · 🇭🇺 [hu](../hu/CONTRIBUTING.md) · 🇧🇬 [bg](../bg/CONTRIBUTING.md) · 🇸🇰 [sk](../sk/CONTRIBUTING.md) · 🇺🇦 [uk-UA](../uk-UA/CONTRIBUTING.md) · 🇮🇱 [he](../he/CONTRIBUTING.md) · 🇵🇭 [phi](../phi/CONTRIBUTING.md) · 🇧🇷 [pt-BR](../pt-BR/CONTRIBUTING.md) · 🇨🇿 [cs](../cs/CONTRIBUTING.md)
+
+---
+
+Thank you for your interest in contributing! This guide covers everything you need to get started.
+
+---
+
+## Development Setup
+
+### Prerequisites
+
+- **Node.js** >= 18 < 24 (recommended: 22 LTS)
+- **npm** 10+
+- **Git**
+
+### Clone & Install
+
+```bash
+git clone https://github.com/diegosouzapw/OmniRoute.git
+cd OmniRoute
+npm install
+```
+
+### Environment Variables
+
+```bash
+# Create your .env from the template
+cp .env.example .env
+
+# Generate required secrets
+echo "JWT_SECRET=$(openssl rand -base64 48)" >> .env
+echo "API_KEY_SECRET=$(openssl rand -hex 32)" >> .env
+```
+
+Key variables for development:
+
+| Variable | Development Default | Description |
+| ---------------------- | ------------------------ | --------------------- |
+| `PORT` | `20128` | Server port |
+| `NEXT_PUBLIC_BASE_URL` | `http://localhost:20128` | Base URL for frontend |
+| `JWT_SECRET` | (generate above) | JWT signing secret |
+| `INITIAL_PASSWORD` | `CHANGEME` | First login password |
+| `APP_LOG_LEVEL` | `info` | Log verbosity level |
+
+### Dashboard Settings
+
+The dashboard provides UI toggles for features that can also be configured via environment variables:
+
+| Setting Location | Toggle | Description |
+| ------------------- | ------------------ | ------------------------------ |
+| Settings → Advanced | Debug Mode | Enable debug request logs (UI) |
+| Settings → General | Sidebar Visibility | Show/hide sidebar sections |
+
+These settings are stored in the database and persist across restarts, overriding env var defaults when set.
+
+### Running Locally
+
+```bash
+# Development mode (hot reload)
+npm run dev
+
+# Production build
+npm run build
+npm run start
+
+# Common port configuration
+PORT=20128 NEXT_PUBLIC_BASE_URL=http://localhost:20128 npm run dev
+```
+
+Default URLs:
+
+- **Dashboard**: `http://localhost:20128/dashboard`
+- **API**: `http://localhost:20128/v1`
+
+---
+
+## Git Workflow
+
+> ⚠️ **NEVER commit directly to `main`.** Always use feature branches.
+
+```bash
+git checkout -b feat/your-feature-name
+# ... make changes ...
+git commit -m "feat: describe your change"
+git push -u origin feat/your-feature-name
+# Open a Pull Request on GitHub
+```
+
+### Branch Naming
+
+| Prefix | Purpose |
+| ----------- | ------------------------- |
+| `feat/` | New features |
+| `fix/` | Bug fixes |
+| `refactor/` | Code restructuring |
+| `docs/` | Documentation changes |
+| `test/` | Test additions/fixes |
+| `chore/` | Tooling, CI, dependencies |
+
+### Commit Messages
+
+Follow [Conventional Commits](https://www.conventionalcommits.org/):
+
+```
+feat: add circuit breaker for provider calls
+fix: resolve JWT secret validation edge case
+docs: update SECURITY.md with PII protection
+test: add observability unit tests
+refactor(db): consolidate rate limit tables
+```
+
+Scopes: `db`, `sse`, `oauth`, `dashboard`, `api`, `cli`, `docker`, `ci`, `mcp`, `a2a`, `memory`, `skills`.
+
+---
+
+## Running Tests
+
+```bash
+# All tests (unit + vitest + ecosystem + e2e)
+npm run test:all
+
+# Single test file (Node.js native test runner — most tests use this)
+node --import tsx/esm --test tests/unit/your-file.test.mjs
+
+# Vitest (MCP server, autoCombo, cache)
+npm run test:vitest
+
+# E2E tests (requires Playwright)
+npm run test:e2e
+
+# Protocol clients E2E (MCP transports, A2A)
+npm run test:protocols:e2e
+
+# Ecosystem compatibility tests
+npm run test:ecosystem
+
+# Coverage (55% min statements/lines/functions; 60% branches)
+npm run test:coverage
+npm run coverage:report
+
+# Lint + format check
+npm run lint
+npm run check
+```
+
+Coverage notes:
+
+- `npm run test:coverage` measures source coverage for the main unit test suite, excludes `tests/**`, and includes `open-sse/**`
+- `npm run coverage:report` prints the detailed file-by-file report from the latest coverage run
+- `npm run test:coverage:legacy` preserves the older metric for historical comparison
+- See `docs/COVERAGE_PLAN.md` for the phased coverage improvement roadmap
+
+Current test status: **122 unit test files** covering:
+
+- Provider translators and format conversion
+- Rate limiting, circuit breaker, and resilience
+- Semantic cache, idempotency, progress tracking
+- Database operations and schema (21 DB modules)
+- OAuth flows and authentication
+- API endpoint validation (Zod v4)
+- MCP server tools and scope enforcement
+- Memory and Skills systems
+
+---
+
+## Code Style
+
+- **ESLint** — Run `npm run lint` before committing
+- **Prettier** — Auto-formatted via `lint-staged` on commit (2 spaces, semicolons, double quotes, 100 char width, es5 trailing commas)
+- **TypeScript** — All `src/` code uses `.ts`/`.tsx`; `open-sse/` uses `.ts`/`.js`; document with TSDoc (`@param`, `@returns`, `@throws`)
+- **No `eval()`** — ESLint enforces `no-eval`, `no-implied-eval`, `no-new-func`
+- **Zod validation** — Use Zod v4 schemas for all API input validation
+- **Naming**: Files = camelCase/kebab-case, components = PascalCase, constants = UPPER_SNAKE
+
+---
+
+## Project Structure
+
+```
+src/ # TypeScript (.ts / .tsx)
+├── app/ # Next.js 16 App Router
+│ ├── (dashboard)/ # Dashboard pages (23 sections)
+│ ├── api/ # API routes (51 directories)
+│ └── login/ # Auth pages (.tsx)
+├── domain/ # Policy engine (policyEngine, comboResolver, costRules, etc.)
+├── lib/ # Core business logic (.ts)
+│ ├── a2a/ # Agent-to-Agent v0.3 protocol server
+│ ├── acp/ # Agent Communication Protocol registry
+│ ├── compliance/ # Compliance policy engine
+│ ├── db/ # SQLite database layer (21 modules + 16 migrations)
+│ ├── memory/ # Persistent conversational memory
+│ ├── oauth/ # OAuth providers, services, and utilities
+│ ├── skills/ # Extensible skill framework
+│ ├── usage/ # Usage tracking and cost calculation
+│ └── localDb.ts # Re-export layer only — never add logic here
+├── middleware/ # Request middleware (promptInjectionGuard)
+├── mitm/ # MITM proxy (cert, DNS, target routing)
+├── shared/
+│ ├── components/ # React components (.tsx)
+│ ├── constants/ # Provider definitions (60+), MCP scopes, routing strategies
+│ ├── utils/ # Circuit breaker, sanitizer, auth helpers
+│ └── validation/ # Zod v4 schemas
+└── sse/ # SSE proxy pipeline
+
+open-sse/ # @omniroute/open-sse workspace
+├── executors/ # 14 provider-specific request executors
+├── handlers/ # 11 request handlers (chat, responses, embeddings, images, etc.)
+├── mcp-server/ # MCP server (25 tools, 3 transports, 10 scopes)
+├── services/ # 36+ services (combo, autoCombo, rateLimitManager, etc.)
+├── translator/ # Format translators (OpenAI ↔ Claude ↔ Gemini ↔ Responses ↔ Ollama)
+├── transformer/ # Responses API transformer
+└── utils/ # 22 utility modules (stream, TLS, proxy, logging)
+
+electron/ # Electron desktop app (cross-platform)
+
+tests/
+├── unit/ # Node.js test runner (122 test files)
+├── integration/ # Integration tests
+├── e2e/ # Playwright tests
+├── security/ # Security tests
+├── translator/ # Translator-specific tests
+└── load/ # Load tests
+
+docs/ # Documentation
+├── ARCHITECTURE.md # System architecture
+├── API_REFERENCE.md # All endpoints
+├── USER_GUIDE.md # Provider setup, CLI integration
+├── TROUBLESHOOTING.md # Common issues
+├── MCP-SERVER.md # MCP server (25 tools)
+├── A2A-SERVER.md # A2A agent protocol
+├── AUTO-COMBO.md # Auto-combo engine
+├── CLI-TOOLS.md # CLI tools integration
+├── COVERAGE_PLAN.md # Test coverage improvement plan
+├── openapi.yaml # OpenAPI specification
+└── adr/ # Architecture Decision Records
+```
+
+---
+
+## Adding a New Provider
+
+### Step 1: Register Provider Constants
+
+Add to `src/shared/constants/providers.ts` — Zod-validated at module load.
+
+### Step 2: Add Executor (if custom logic needed)
+
+Create executor in `open-sse/executors/your-provider.ts` extending the base executor.
+
+### Step 3: Add Translator (if non-OpenAI format)
+
+Create request/response translators in `open-sse/translator/`.
+
+### Step 4: Add OAuth Config (if OAuth-based)
+
+Add OAuth credentials in `src/lib/oauth/constants/oauth.ts` and service in `src/lib/oauth/services/`.
+
+### Step 5: Register Models
+
+Add model definitions in `open-sse/config/providerRegistry.ts`.
+
+### Step 6: Add Tests
+
+Write unit tests in `tests/unit/` covering at minimum:
+
+- Provider registration
+- Request/response translation
+- Error handling
+
+---
+
+## Pull Request Checklist
+
+- [ ] Tests pass (`npm test`)
+- [ ] Linting passes (`npm run lint`)
+- [ ] Build succeeds (`npm run build`)
+- [ ] TypeScript types added for new public functions and interfaces
+- [ ] No hardcoded secrets or fallback values
+- [ ] All inputs validated with Zod schemas
+- [ ] CHANGELOG updated (if user-facing change)
+- [ ] Documentation updated (if applicable)
+
+---
+
+## Releasing
+
+Releases are managed via the `/generate-release` workflow. When a new GitHub Release is created, the package is **automatically published to npm** via GitHub Actions.
+
+---
+
+## Getting Help
+
+- **Architecture**: See [`docs/ARCHITECTURE.md`](docs/ARCHITECTURE.md)
+- **API Reference**: See [`docs/API_REFERENCE.md`](docs/API_REFERENCE.md)
+- **Issues**: [github.com/diegosouzapw/OmniRoute/issues](https://github.com/diegosouzapw/OmniRoute/issues)
+- **ADRs**: See `docs/adr/` for architectural decision records
diff --git a/docs/i18n/hu/FEATURES.md b/docs/i18n/hu/FEATURES.md
deleted file mode 100644
index 0185f3ba35..0000000000
--- a/docs/i18n/hu/FEATURES.md
+++ /dev/null
@@ -1,147 +0,0 @@
-# OmniRoute — Dashboard Features Gallery (Magyar)
-
-🌐 **Languages:** 🇺🇸 [English](../../../README.md) · 🇧🇷 [pt-BR](../pt-BR/README.md) · 🇪🇸 [es](../es/README.md) · 🇫🇷 [fr](../fr/README.md) · 🇩🇪 [de](../de/README.md) · 🇮🇹 [it](../it/README.md) · 🇷🇺 [ru](../ru/README.md) · 🇨🇳 [zh-CN](../zh-CN/README.md) · 🇯🇵 [ja](../ja/README.md) · 🇰🇷 [ko](../ko/README.md) · 🇸🇦 [ar](../ar/README.md) · 🇮🇳 [in](../in/README.md) · 🇹🇭 [th](../th/README.md) · 🇻🇳 [vi](../vi/README.md) · 🇮🇩 [id](../id/README.md) · 🇲🇾 [ms](../ms/README.md) · 🇳🇱 [nl](../nl/README.md) · 🇵🇱 [pl](../pl/README.md) · 🇸🇪 [sv](../sv/README.md) · 🇳🇴 [no](../no/README.md) · 🇩🇰 [da](../da/README.md) · 🇫🇮 [fi](../fi/README.md) · 🇵🇹 [pt](../pt/README.md) · 🇷🇴 [ro](../ro/README.md) · 🇭🇺 [hu](../hu/README.md) · 🇧🇬 [bg](../bg/README.md) · 🇸🇰 [sk](../sk/README.md) · 🇺🇦 [uk-UA](../uk-UA/README.md) · 🇮🇱 [he](../he/README.md) · 🇵🇭 [phi](../phi/README.md)
-
-> 🇺🇸 [English](../../../docs/FEATURES.md)
-
----
-
-Visual guide to every section of the OmniRoute dashboard.
-
----
-
-## 🔌 Providers
-
-Manage AI provider connections: OAuth providers (Claude Code, Codex, Gemini CLI), API key providers (Groq, DeepSeek, OpenRouter), and free providers (Qoder, Qwen, Kiro). Kiro accounts include credit balance tracking — remaining credits, total allowance, and renewal date visible in Dashboard → Usage.
-
-
-
----
-
-## 🎨 Combos
-
-Create model routing combos with 6 strategies: priority, weighted, round-robin, random, least-used, and cost-optimized. Each combo chains multiple models with automatic fallback and includes quick templates and readiness checks.
-
-
-
----
-
-## 📊 Analytics
-
-Comprehensive usage analytics with token consumption, cost estimates, activity heatmaps, weekly distribution charts, and per-provider breakdowns.
-
-
-
----
-
-## 🏥 System Health
-
-Real-time monitoring: uptime, memory, version, latency percentiles (p50/p95/p99), cache statistics, and provider circuit breaker states.
-
-
-
----
-
-## 🔧 Translator Playground
-
-Four modes for debugging API translations: **Playground** (format converter), **Chat Tester** (live requests), **Test Bench** (batch tests), and **Live Monitor** (real-time stream).
-
-
-
----
-
-## 🎮 Model Playground _(v2.0.9+)_
-
-Test any model directly from the dashboard. Select provider, model, and endpoint, write prompts with Monaco Editor, stream responses in real-time, abort mid-stream, and view timing metrics.
-
----
-
-## 🎨 Themes _(v2.0.5+)_
-
-Customizable color themes for the entire dashboard. Choose from 7 preset colors (Coral, Blue, Red, Green, Violet, Orange, Cyan) or create a custom theme by picking any hex color. Supports light, dark, and system mode.
-
----
-
-## ⚙️ Settings
-
-Comprehensive settings panel with tabs:
-
-- **General** — System storage, backup management (export/import database)
-- **Appearance** — Theme selector (dark/light/system), color theme presets and custom colors, health log visibility, sidebar item visibility controls
-- **Security** — API endpoint protection, custom provider blocking, IP filtering, session info
-- **Routing** — Model aliases, background task degradation
-- **Resilience** — Rate limit persistence, circuit breaker tuning
-- **Advanced** — Configuration overrides
-
-
-
----
-
-## 🔧 CLI Tools
-
-One-click configuration for AI coding tools: Claude Code, Codex CLI, Gemini CLI, OpenClaw, Kilo Code, Antigravity, Cline, Continue, Cursor, and Factory Droid. Features automated config apply/reset, connection profiles, and model mapping.
-
-
-
----
-
-## 🤖 CLI Agents _(v2.0.11+)_
-
-Dashboard for discovering and managing CLI agents. Shows a grid of 14 built-in agents (Codex, Claude, Goose, Gemini CLI, OpenClaw, Aider, OpenCode, Cline, Qwen Code, ForgeCode, Amazon Q, Open Interpreter, Cursor CLI, Warp) with:
-
-- **Installation status** — Installed / Not Found with version detection
-- **Protocol badges** — stdio, HTTP, etc.
-- **Custom agents** — Register any CLI tool via form (name, binary, version command, spawn args)
-- **CLI Fingerprint Matching** — Per-provider toggle to match native CLI request signatures, reducing ban risk while preserving proxy IP
-
----
-
-## 🖼️ Media _(v2.0.3+)_
-
-Generate images, videos, and music from the dashboard. Supports OpenAI, xAI, Together, Hyperbolic, SD WebUI, ComfyUI, AnimateDiff, Stable Audio Open, and MusicGen.
-
----
-
-## 📝 Request Logs
-
-Real-time request logging with filtering by provider, model, account, and API key. Shows status codes, token usage, latency, and response details.
-
-
-
----
-
-## 🌐 API Endpoint
-
-Your unified API endpoint with capability breakdown: Chat Completions, Responses API, Embeddings, Image Generation, Reranking, Audio Transcription, Text-to-Speech, Moderations, and registered API keys. Cloud proxy support for remote access.
-
-
-
----
-
-## 🔑 API Key Management
-
-Create, scope, and revoke API keys. Each key can be restricted to specific models/providers with full access or read-only permissions. Visual key management with usage tracking.
-
----
-
-## 📋 Audit Log
-
-Administrative action tracking with filtering by action type, actor, target, IP address, and timestamp. Full security event history.
-
----
-
-## 🖥️ Desktop Application
-
-Native Electron desktop app for Windows, macOS, and Linux. Run OmniRoute as a standalone application with system tray integration, offline support, auto-update, and one-click install.
-
-Key features:
-
-- Server readiness polling (no blank screen on cold start)
-- System tray with port management
-- Content Security Policy
-- Single-instance lock
-- Auto-update on restart
-- Platform-conditional UI (macOS traffic lights, Windows/Linux default titlebar)
-- Hardened Electron build packaging — symlinked `node_modules` in the standalone bundle is detected and rejected before packaging, preventing runtime dependency on the build machine (v2.5.5+)
-
-📖 See [`electron/README.md`](../electron/README.md) for full documentation.
diff --git a/docs/i18n/hu/MCP-SERVER.md b/docs/i18n/hu/MCP-SERVER.md
deleted file mode 100644
index 829acd30b1..0000000000
--- a/docs/i18n/hu/MCP-SERVER.md
+++ /dev/null
@@ -1,87 +0,0 @@
-🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/MCP-SERVER.md) · 🇪🇸 [es](../es/MCP-SERVER.md) · 🇫🇷 [fr](../fr/MCP-SERVER.md) · 🇩🇪 [de](../de/MCP-SERVER.md) · 🇮🇹 [it](../it/MCP-SERVER.md) · 🇷🇺 [ru](../ru/MCP-SERVER.md) · 🇨🇳 [zh-CN](../zh-CN/MCP-SERVER.md) · 🇯🇵 [ja](../ja/MCP-SERVER.md) · 🇰🇷 [ko](../ko/MCP-SERVER.md) · 🇸🇦 [ar](../ar/MCP-SERVER.md) · 🇮🇳 [in](../in/MCP-SERVER.md) · 🇹🇭 [th](../th/MCP-SERVER.md) · 🇻🇳 [vi](../vi/MCP-SERVER.md) · 🇮🇩 [id](../id/MCP-SERVER.md) · 🇲🇾 [ms](../ms/MCP-SERVER.md) · 🇳🇱 [nl](../nl/MCP-SERVER.md) · 🇵🇱 [pl](../pl/MCP-SERVER.md) · 🇸🇪 [sv](../sv/MCP-SERVER.md) · 🇳🇴 [no](../no/MCP-SERVER.md) · 🇩🇰 [da](../da/MCP-SERVER.md) · 🇫🇮 [fi](../fi/MCP-SERVER.md) · 🇵🇹 [pt](../pt/MCP-SERVER.md) · 🇷🇴 [ro](../ro/MCP-SERVER.md) · 🇭🇺 [hu](../hu/MCP-SERVER.md) · 🇧🇬 [bg](../bg/MCP-SERVER.md) · 🇸🇰 [sk](../sk/MCP-SERVER.md) · 🇺🇦 [uk-UA](../uk-UA/MCP-SERVER.md) · 🇮🇱 [he](../he/MCP-SERVER.md) · 🇵🇭 [phi](../phi/MCP-SERVER.md)
-
----
-
-# OmniRoute MCP Server Documentation
-
-> Model Context Protocol server with 16 intelligent tools
-
-## Installation
-
-OmniRoute MCP is built-in. Start it with:
-
-```bash
-omniroute --mcp
-```
-
-Or via the open-sse transport:
-
-```bash
-# HTTP streamable transport (port 20130)
-omniroute --dev # MCP auto-starts on /mcp endpoint
-```
-
-## IDE Configuration
-
-See [IDE Configs](integrations/ide-configs.md) for Antigravity, Cursor, Copilot, and Claude Desktop setup.
-
----
-
-## Essential Tools (8)
-
-| Tool | Description |
-| :------------------------------ | :--------------------------------------- |
-| `omniroute_get_health` | Gateway health, circuit breakers, uptime |
-| `omniroute_list_combos` | All configured combos with models |
-| `omniroute_get_combo_metrics` | Performance metrics for a specific combo |
-| `omniroute_switch_combo` | Switch active combo by ID/name |
-| `omniroute_check_quota` | Quota status per provider or all |
-| `omniroute_route_request` | Send a chat completion through OmniRoute |
-| `omniroute_cost_report` | Cost analytics for a time period |
-| `omniroute_list_models_catalog` | Full model catalog with capabilities |
-
-## Advanced Tools (8)
-
-| Tool | Description |
-| :--------------------------------- | :---------------------------------------------- |
-| `omniroute_simulate_route` | Dry-run routing simulation with fallback tree |
-| `omniroute_set_budget_guard` | Session budget with degrade/block/alert actions |
-| `omniroute_set_resilience_profile` | Apply conservative/balanced/aggressive preset |
-| `omniroute_test_combo` | Live-test all models in a combo |
-| `omniroute_get_provider_metrics` | Detailed metrics for one provider |
-| `omniroute_best_combo_for_task` | Task-fitness recommendation with alternatives |
-| `omniroute_explain_route` | Explain a past routing decision |
-| `omniroute_get_session_snapshot` | Full session state: costs, tokens, errors |
-
-## Authentication
-
-MCP tools are authenticated via API key scopes. Each tool requires specific scopes:
-
-| Scope | Tools |
-| :------------- | :----------------------------------------------- |
-| `read:health` | get_health, get_provider_metrics |
-| `read:combos` | list_combos, get_combo_metrics |
-| `write:combos` | switch_combo |
-| `read:quota` | check_quota |
-| `write:route` | route_request, simulate_route, test_combo |
-| `read:usage` | cost_report, get_session_snapshot, explain_route |
-| `write:config` | set_budget_guard, set_resilience_profile |
-| `read:models` | list_models_catalog, best_combo_for_task |
-
-## Audit Logging
-
-Every tool call is logged to `mcp_tool_audit` with:
-
-- Tool name, arguments, result
-- Duration (ms), success/failure
-- API key hash, timestamp
-
-## Files
-
-| File | Purpose |
-| :------------------------------------------- | :------------------------------------------ |
-| `open-sse/mcp-server/server.ts` | MCP server creation + 16 tool registrations |
-| `open-sse/mcp-server/transport.ts` | Stdio + HTTP transport |
-| `open-sse/mcp-server/auth.ts` | API key + scope validation |
-| `open-sse/mcp-server/audit.ts` | Tool call audit logging |
-| `open-sse/mcp-server/tools/advancedTools.ts` | 8 advanced tool handlers |
diff --git a/docs/i18n/hu/README.md b/docs/i18n/hu/README.md
index 6281ea4d2f..36d3a748cb 100644
--- a/docs/i18n/hu/README.md
+++ b/docs/i18n/hu/README.md
@@ -1,13 +1,12 @@
# 🚀 OmniRoute — The Free AI Gateway (Magyar)
-🌐 **Languages:** 🇺🇸 [English](../../../README.md) · 🇪🇸 [es](../es/README.md) · 🇫🇷 [fr](../fr/README.md) · 🇩🇪 [de](../de/README.md) · 🇮🇹 [it](../it/README.md) · 🇷🇺 [ru](../ru/README.md) · 🇨🇳 [zh-CN](../zh-CN/README.md) · 🇯🇵 [ja](../ja/README.md) · 🇰🇷 [ko](../ko/README.md) · 🇸🇦 [ar](../ar/README.md) · 🇮🇳 [in](../in/README.md) · 🇹🇭 [th](../th/README.md) · 🇻🇳 [vi](../vi/README.md) · 🇮🇩 [id](../id/README.md) · 🇲🇾 [ms](../ms/README.md) · 🇳🇱 [nl](../nl/README.md) · 🇵🇱 [pl](../pl/README.md) · 🇸🇪 [sv](../sv/README.md) · 🇳🇴 [no](../no/README.md) · 🇩🇰 [da](../da/README.md) · 🇫🇮 [fi](../fi/README.md) · 🇵🇹 [pt](../pt/README.md) · 🇷🇴 [ro](../ro/README.md) · 🇭🇺 [hu](../hu/README.md) · 🇧🇬 [bg](../bg/README.md) · 🇸🇰 [sk](../sk/README.md) · 🇺🇦 [uk-UA](../uk-UA/README.md) · 🇮🇱 [he](../he/README.md) · 🇵🇭 [phi](../phi/README.md) · 🇧🇷 [pt-BR](../pt-BR/README.md)
+🌐 **Languages:** 🇺🇸 [English](../../../README.md) · 🇪🇸 [es](../es/README.md) · 🇫🇷 [fr](../fr/README.md) · 🇩🇪 [de](../de/README.md) · 🇮🇹 [it](../it/README.md) · 🇷🇺 [ru](../ru/README.md) · 🇨🇳 [zh-CN](../zh-CN/README.md) · 🇯🇵 [ja](../ja/README.md) · 🇰🇷 [ko](../ko/README.md) · 🇸🇦 [ar](../ar/README.md) · 🇮🇳 [in](../in/README.md) · 🇹🇭 [th](../th/README.md) · 🇻🇳 [vi](../vi/README.md) · 🇮🇩 [id](../id/README.md) · 🇲🇾 [ms](../ms/README.md) · 🇳🇱 [nl](../nl/README.md) · 🇵🇱 [pl](../pl/README.md) · 🇸🇪 [sv](../sv/README.md) · 🇳🇴 [no](../no/README.md) · 🇩🇰 [da](../da/README.md) · 🇫🇮 [fi](../fi/README.md) · 🇵🇹 [pt](../pt/README.md) · 🇷🇴 [ro](../ro/README.md) · 🇭🇺 [hu](../hu/README.md) · 🇧🇬 [bg](../bg/README.md) · 🇸🇰 [sk](../sk/README.md) · 🇺🇦 [uk-UA](../uk-UA/README.md) · 🇮🇱 [he](../he/README.md) · 🇵🇭 [phi](../phi/README.md) · 🇧🇷 [pt-BR](../pt-BR/README.md) · 🇨🇿 [cs](../cs/README.md)
---
-
### Never stop coding. Smart routing to **FREE & low-cost AI models** with automatic fallback.
-_Your universal API proxy — one endpoint, 67+ providers, zero downtime. Now with **MCP & A2A** agent orchestration._
+_Your universal API proxy — one endpoint, 60+ providers, zero downtime. Now with **MCP Server (25 tools)**, **A2A Protocol**, **Memory/Skills Systems** & **Electron Desktop App**._
**Chat Completions • Embeddings • Image Generation • Video • Music • Audio • Reranking • **Web Search** • MCP Server • A2A Protocol • 100% TypeScript**
@@ -47,15 +46,17 @@ _Your universal API proxy — one endpoint, 67+ providers, zero downtime. Now wi
> - `APP_LOG_FILE_PATH`
> - `APP_LOG_MAX_FILE_SIZE`
> - `APP_LOG_RETENTION_DAYS`
+> - `APP_LOG_MAX_FILES`
> - `APP_LOG_LEVEL`
> - `APP_LOG_FORMAT`
> - `CALL_LOG_RETENTION_DAYS`
+> - `CALL_LOG_MAX_ENTRIES`
>
> For release details and upgrade notes, see the [CHANGELOG](CHANGELOG.md).
---
-## 🆕 What's New in v3.0.0
+## 🆕 What's New
> **Upgrading from v2.9.5?** — See the [full CHANGELOG](CHANGELOG.md#300--2026-03-22-release-candidate--not-yet-merged-to-main) for all changes.
@@ -275,7 +276,7 @@ Developers pay $20–200/month for Claude Pro, Codex Pro, or GitHub Copilot. Eve
- **Smart 4-Tier Fallback** — If subscription quota runs out, automatically redirects to API Key → Cheap → Free with zero manual intervention
- **Real-Time Quota Tracking** — Shows token consumption in real-time with reset countdown (5h, daily, weekly)
- **Multi-Account Support** — Multiple accounts per provider with auto round-robin — when one runs out, switches to the next
-- **Custom Combos** — Customizable fallback chains with 6 balancing strategies (fill-first, round-robin, P2C, random, least-used, cost-optimized)
+- **Custom Combos** — Customizable fallback chains with 9 balancing strategies (priority, weighted, fill-first, round-robin, P2C, random, least-used, cost-optimized, strict-random)
- **Codex Business Quotas** — Business/Team workspace quota monitoring directly in the dashboard
@@ -287,7 +288,7 @@ OpenAI uses one format, Claude (Anthropic) uses another, Gemini yet another. If
**How OmniRoute solves it:**
-- **Unified Endpoint** — A single `http://localhost:20128/v1` serves as proxy for all 67+ providers
+- **Unified Endpoint** — A single `http://localhost:20128/v1` serves as proxy for all 60+ providers
- **Format Translation** — Automatic and transparent: OpenAI ↔ Claude ↔ Gemini ↔ Responses API
- **Response Sanitization** — Strips non-standard fields (`x_groq`, `usage_breakdown`, `service_tier`) that break OpenAI SDK v1.83+
- **Role Normalization** — Converts `developer` → `system` for non-OpenAI providers; `system` → `user` for GLM/ERNIE
@@ -373,7 +374,7 @@ Developers use Cursor, Claude Code, Codex CLI, OpenClaw, Gemini CLI, Kilo Code..
- **CLI Tools Dashboard** — Dedicated page with one-click setup for Claude Code, Codex CLI, OpenClaw, Kilo Code, Antigravity, Cline
- **GitHub Copilot Config Generator** — Generates `chatLanguageModels.json` for VS Code with bulk model selection
- **Onboarding Wizard** — Guided 4-step setup for first-time users
-- **One endpoint, all models** — Configure `http://localhost:20128/v1` once, access 67+ providers
+- **One endpoint, all models** — Configure `http://localhost:20128/v1` once, access 60+ providers
@@ -420,7 +421,7 @@ When a call fails, the dev doesn't know if it was a rate limit, expired token, w
- **SQLite Proxy Logs** — Persistent logs that survive server restarts
- **Translator Playground** — 4 debugging modes: Playground (format translation), Chat Tester (round-trip), Test Bench (batch), Live Monitor (real-time)
- **Request Telemetry** — p50/p95/p99 latency + X-Request-Id tracing
-- **File-Based Logging with Rotation** — Console interceptor captures everything to JSON log with size-based rotation
+- **File-Based Logging with Rotation** — App logs rotate by size, retention days, and archive count; call log artifacts rotate by retention days and file count
- **System Info Report** — `npm run system-info` generates `system-info.txt` with your full environment (Node version, OmniRoute version, OS, CLI tools, Docker/PM2 status). Attach it when reporting issues for instant triage.
@@ -515,7 +516,7 @@ Developers who want all responses in a specific language, with a specific tone,
- **System Prompt Injection** — Global prompt applied to all requests
- **Thinking Budget Validation** — Reasoning token allocation control per request (passthrough, auto, custom, adaptive)
-- **6 Routing Strategies** — Global strategies that determine how requests are distributed
+- **9 Routing Strategies** — Global strategies that determine how requests are distributed
- **Wildcard Router** — `provider/*` patterns route dynamically to any provider
- **Combo Enable/Disable Toggle** — Toggle combos directly from the dashboard
- **Provider Toggle** — Enable/disable all connections for a provider with one click
@@ -582,7 +583,7 @@ Different clients should have least-privilege access to tool categories.
**How OmniRoute solves it:**
-- 9 granular MCP scopes for controlled tool access
+- 10 granular MCP scopes for controlled tool access
- Scope enforcement and visibility in MCP management UI
- Safe default posture for operational tooling
@@ -1326,19 +1327,19 @@ OmniRoute v2.0 is built as an operational platform, not just a relay proxy.
### 🤖 Agent & Protocol Operations (v2.0)
-| Feature | What It Does |
-| ------------------------------------- | -------------------------------------------------------------------------------------------------- |
-| 🔧 **MCP Server (16 tools)** | IDE/agent tools via 3 transports: stdio, SSE (`/api/mcp/sse`), Streamable HTTP (`/api/mcp/stream`) |
-| 🤝 **A2A Server (JSON-RPC + SSE)** | Agent-to-agent task execution with sync and streaming flows |
-| 🧭 **Consolidated Endpoints Page** | Tabbed management page with Endpoint Proxy, MCP, A2A, and API Endpoints tabs |
-| 🎚️ **Service Enable/Disable Toggles** | ON/OFF switches for MCP and A2A with settings persistence (default: OFF) |
-| 🛰️ **MCP Runtime Heartbeat** | Real process status (pid, uptime, heartbeat age, transport, scope mode) |
-| 📋 **MCP Audit Trail** | Filterable audit logs with success/failure and key attribution |
-| 🔐 **MCP Scope Enforcement** | 9 granular scope permissions for controlled tool access |
-| 📡 **A2A Task Lifecycle Management** | List/filter tasks, inspect events/artifacts, cancel running tasks |
-| 📋 **Agent Card Discovery** | `/.well-known/agent.json` for client auto-discovery |
-| 🧪 **Protocol E2E Test Harness** | Real MCP SDK + A2A client flows in `test:protocols:e2e` |
-| ⚙️ **Operational Controls** | Switch combo, apply resilience profiles, reset breakers from one control surface |
+| Feature | What It Does |
+| ------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------- |
+| 🔧 **MCP Server (25 tools)** | IDE/agent tools via 3 transports: stdio, SSE (`/api/mcp/sse`), Streamable HTTP (`/api/mcp/stream`). 18 core + 3 memory + 4 skill tools |
+| 🤝 **A2A Server (JSON-RPC + SSE)** | Agent-to-agent task execution with sync and streaming flows |
+| 🧭 **Consolidated Endpoints Page** | Tabbed management page with Endpoint Proxy, MCP, A2A, and API Endpoints tabs |
+| 🎚️ **Service Enable/Disable Toggles** | ON/OFF switches for MCP and A2A with settings persistence (default: OFF) |
+| 🛰️ **MCP Runtime Heartbeat** | Real process status (pid, uptime, heartbeat age, transport, scope mode) |
+| 📋 **MCP Audit Trail** | Filterable audit logs with success/failure and key attribution |
+| 🔐 **MCP Scope Enforcement** | 10 granular scope permissions for controlled tool access |
+| 📡 **A2A Task Lifecycle Management** | List/filter tasks, inspect events/artifacts, cancel running tasks |
+| 📋 **Agent Card Discovery** | `/.well-known/agent.json` for client auto-discovery |
+| 🧪 **Protocol E2E Test Harness** | Real MCP SDK + A2A client flows in `test:protocols:e2e` |
+| ⚙️ **Operational Controls** | Switch combo, apply resilience profiles, reset breakers from one control surface |
### 🧠 Routing & Intelligence
@@ -1349,7 +1350,7 @@ OmniRoute v2.0 is built as an operational platform, not just a relay proxy.
| 🔄 **Format Translation** | OpenAI ↔ Claude ↔ Gemini ↔ Responses with schema-safe conversions |
| 👥 **Multi-Account Support** | Multiple accounts per provider with intelligent selection |
| 🔄 **Auto Token Refresh** | OAuth tokens refresh automatically with retry |
-| 🎨 **Custom Combos** | 6 balancing strategies + fallback chain control |
+| 🎨 **Custom Combos** | 9 balancing strategies + fallback chain control |
| 🌐 **Wildcard Router** | `provider/*` dynamic routing |
| 🧠 **Thinking Budget Controls** | Passthrough, auto, custom, and adaptive reasoning limits |
| 🔀 **Model Aliases** | Built-in + custom model aliasing and migration safety |
@@ -1950,6 +1951,7 @@ opencode
- Request artifacts are written to `DATA_DIR/call_logs/` as one JSON file per request
- Enable pipeline capture from Dashboard → Logs → Request Logs if you need detailed per-stage payloads
- Set `APP_LOG_TO_FILE=true` if you also want application console logs in `logs/application/app.log`
+- Adjust `APP_LOG_MAX_FILE_SIZE`, `APP_LOG_RETENTION_DAYS`, `APP_LOG_MAX_FILES`, and `CALL_LOG_MAX_ENTRIES` as needed
**Connection test shows "Invalid" for OpenAI-compatible providers**
diff --git a/docs/i18n/hu/RELEASE_CHECKLIST.md b/docs/i18n/hu/RELEASE_CHECKLIST.md
deleted file mode 100644
index 903e812c3f..0000000000
--- a/docs/i18n/hu/RELEASE_CHECKLIST.md
+++ /dev/null
@@ -1,37 +0,0 @@
-🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/RELEASE_CHECKLIST.md) · 🇪🇸 [es](../es/RELEASE_CHECKLIST.md) · 🇫🇷 [fr](../fr/RELEASE_CHECKLIST.md) · 🇩🇪 [de](../de/RELEASE_CHECKLIST.md) · 🇮🇹 [it](../it/RELEASE_CHECKLIST.md) · 🇷🇺 [ru](../ru/RELEASE_CHECKLIST.md) · 🇨🇳 [zh-CN](../zh-CN/RELEASE_CHECKLIST.md) · 🇯🇵 [ja](../ja/RELEASE_CHECKLIST.md) · 🇰🇷 [ko](../ko/RELEASE_CHECKLIST.md) · 🇸🇦 [ar](../ar/RELEASE_CHECKLIST.md) · 🇮🇳 [in](../in/RELEASE_CHECKLIST.md) · 🇹🇭 [th](../th/RELEASE_CHECKLIST.md) · 🇻🇳 [vi](../vi/RELEASE_CHECKLIST.md) · 🇮🇩 [id](../id/RELEASE_CHECKLIST.md) · 🇲🇾 [ms](../ms/RELEASE_CHECKLIST.md) · 🇳🇱 [nl](../nl/RELEASE_CHECKLIST.md) · 🇵🇱 [pl](../pl/RELEASE_CHECKLIST.md) · 🇸🇪 [sv](../sv/RELEASE_CHECKLIST.md) · 🇳🇴 [no](../no/RELEASE_CHECKLIST.md) · 🇩🇰 [da](../da/RELEASE_CHECKLIST.md) · 🇫🇮 [fi](../fi/RELEASE_CHECKLIST.md) · 🇵🇹 [pt](../pt/RELEASE_CHECKLIST.md) · 🇷🇴 [ro](../ro/RELEASE_CHECKLIST.md) · 🇭🇺 [hu](../hu/RELEASE_CHECKLIST.md) · 🇧🇬 [bg](../bg/RELEASE_CHECKLIST.md) · 🇸🇰 [sk](../sk/RELEASE_CHECKLIST.md) · 🇺🇦 [uk-UA](../uk-UA/RELEASE_CHECKLIST.md) · 🇮🇱 [he](../he/RELEASE_CHECKLIST.md) · 🇵🇭 [phi](../phi/RELEASE_CHECKLIST.md)
-
----
-
-# Release Checklist
-
-Use this checklist before tagging or publishing a new OmniRoute release.
-
-## Version and Changelog
-
-1. Bump `package.json` version (`x.y.z`) in the release branch.
-2. Move release notes from `## [Unreleased]` in `CHANGELOG.md` to a dated section:
- - `## [x.y.z] — YYYY-MM-DD`
-3. Keep `## [Unreleased]` as the first changelog section for upcoming work.
-4. Ensure the latest semver section in `CHANGELOG.md` equals `package.json` version.
-
-## API Docs
-
-1. Update `docs/openapi.yaml`:
- - `info.version` must equal `package.json` version.
-2. Validate endpoint examples if API contracts changed.
-
-## Runtime Docs
-
-1. Review `docs/ARCHITECTURE.md` for storage/runtime drift.
-2. Review `docs/TROUBLESHOOTING.md` for env var and operational drift.
-3. Update localized docs if source docs changed significantly.
-
-## Automated Check
-
-Run the sync guard locally before opening PR:
-
-```bash
-npm run check:docs-sync
-```
-
-CI also runs this check in `.github/workflows/ci.yml` (lint job).
diff --git a/docs/i18n/hu/SECURITY.md b/docs/i18n/hu/SECURITY.md
new file mode 100644
index 0000000000..5e6595fe56
--- /dev/null
+++ b/docs/i18n/hu/SECURITY.md
@@ -0,0 +1,179 @@
+# Security Policy (Magyar)
+
+🌐 **Languages:** 🇺🇸 [English](../../../SECURITY.md) · 🇪🇸 [es](../es/SECURITY.md) · 🇫🇷 [fr](../fr/SECURITY.md) · 🇩🇪 [de](../de/SECURITY.md) · 🇮🇹 [it](../it/SECURITY.md) · 🇷🇺 [ru](../ru/SECURITY.md) · 🇨🇳 [zh-CN](../zh-CN/SECURITY.md) · 🇯🇵 [ja](../ja/SECURITY.md) · 🇰🇷 [ko](../ko/SECURITY.md) · 🇸🇦 [ar](../ar/SECURITY.md) · 🇮🇳 [in](../in/SECURITY.md) · 🇹🇭 [th](../th/SECURITY.md) · 🇻🇳 [vi](../vi/SECURITY.md) · 🇮🇩 [id](../id/SECURITY.md) · 🇲🇾 [ms](../ms/SECURITY.md) · 🇳🇱 [nl](../nl/SECURITY.md) · 🇵🇱 [pl](../pl/SECURITY.md) · 🇸🇪 [sv](../sv/SECURITY.md) · 🇳🇴 [no](../no/SECURITY.md) · 🇩🇰 [da](../da/SECURITY.md) · 🇫🇮 [fi](../fi/SECURITY.md) · 🇵🇹 [pt](../pt/SECURITY.md) · 🇷🇴 [ro](../ro/SECURITY.md) · 🇭🇺 [hu](../hu/SECURITY.md) · 🇧🇬 [bg](../bg/SECURITY.md) · 🇸🇰 [sk](../sk/SECURITY.md) · 🇺🇦 [uk-UA](../uk-UA/SECURITY.md) · 🇮🇱 [he](../he/SECURITY.md) · 🇵🇭 [phi](../phi/SECURITY.md) · 🇧🇷 [pt-BR](../pt-BR/SECURITY.md) · 🇨🇿 [cs](../cs/SECURITY.md)
+
+---
+
+## Reporting Vulnerabilities
+
+If you discover a security vulnerability in OmniRoute, please report it responsibly:
+
+1. **DO NOT** open a public GitHub issue
+2. Use [GitHub Security Advisories](https://github.com/diegosouzapw/OmniRoute/security/advisories/new)
+3. Include: description, reproduction steps, and potential impact
+
+## Response Timeline
+
+| Stage | Target |
+| ------------------- | --------------------------- |
+| Acknowledgment | 48 hours |
+| Triage & Assessment | 5 business days |
+| Patch Release | 14 business days (critical) |
+
+## Supported Versions
+
+| Version | Support Status |
+| ------- | -------------- |
+| 3.4.x | ✅ Active |
+| 3.0.x | ✅ Security |
+| < 3.0.0 | ❌ Unsupported |
+
+---
+
+## Security Architecture
+
+OmniRoute implements a multi-layered security model:
+
+```
+Request → CORS → API Key Auth → Prompt Injection Guard → Input Sanitizer → Rate Limiter → Circuit Breaker → Provider
+```
+
+### 🔐 Authentication & Authorization
+
+| Feature | Implementation |
+| -------------------- | ---------------------------------------------------------- |
+| **Dashboard Login** | Password-based auth with JWT tokens (HttpOnly cookies) |
+| **API Key Auth** | HMAC-signed keys with CRC validation |
+| **OAuth 2.0 + PKCE** | Secure provider auth (Claude, Codex, Gemini, Cursor, etc.) |
+| **Token Refresh** | Automatic OAuth token refresh before expiry |
+| **Secure Cookies** | `AUTH_COOKIE_SECURE=true` for HTTPS environments |
+| **MCP Scopes** | 10 granular scopes for MCP tool access control |
+
+### 🛡️ Encryption at Rest
+
+All sensitive data stored in SQLite is encrypted using **AES-256-GCM** with scrypt key derivation:
+
+- API keys, access tokens, refresh tokens, and ID tokens
+- Versioned format: `enc:v1:::`
+- Passthrough mode (plaintext) when `STORAGE_ENCRYPTION_KEY` is not set
+
+```bash
+# Generate encryption key:
+STORAGE_ENCRYPTION_KEY=$(openssl rand -hex 32)
+```
+
+### 🧠 Prompt Injection Guard
+
+Middleware that detects and blocks prompt injection attacks in LLM requests:
+
+| Pattern Type | Severity | Example |
+| ------------------- | -------- | ---------------------------------------------- |
+| System Override | High | "ignore all previous instructions" |
+| Role Hijack | High | "you are now DAN, you can do anything" |
+| Delimiter Injection | Medium | Encoded separators to break context boundaries |
+| DAN/Jailbreak | High | Known jailbreak prompt patterns |
+| Instruction Leak | Medium | "show me your system prompt" |
+
+Configure via dashboard (Settings → Security) or `.env`:
+
+```env
+INPUT_SANITIZER_ENABLED=true
+INPUT_SANITIZER_MODE=block # warn | block | redact
+```
+
+### 🔒 PII Redaction
+
+Automatic detection and optional redaction of personally identifiable information:
+
+| PII Type | Pattern | Replacement |
+| ------------- | --------------------- | ------------------ |
+| Email | `user@domain.com` | `[EMAIL_REDACTED]` |
+| CPF (Brazil) | `123.456.789-00` | `[CPF_REDACTED]` |
+| CNPJ (Brazil) | `12.345.678/0001-00` | `[CNPJ_REDACTED]` |
+| Credit Card | `4111-1111-1111-1111` | `[CC_REDACTED]` |
+| Phone | `+55 11 99999-9999` | `[PHONE_REDACTED]` |
+| SSN (US) | `123-45-6789` | `[SSN_REDACTED]` |
+
+```env
+PII_REDACTION_ENABLED=true
+```
+
+### 🌐 Network Security
+
+| Feature | Description |
+| ------------------------ | ---------------------------------------------------------------- |
+| **CORS** | Configurable origin control (`CORS_ORIGIN` env var, default `*`) |
+| **IP Filtering** | Allowlist/blocklist IP ranges in dashboard |
+| **Rate Limiting** | Per-provider rate limits with automatic backoff |
+| **Anti-Thundering Herd** | Mutex + per-connection locking prevents cascading 502s |
+| **TLS Fingerprint** | Browser-like TLS fingerprint spoofing to reduce bot detection |
+| **CLI Fingerprint** | Per-provider header/body ordering to match native CLI signatures |
+
+### 🔌 Resilience & Availability
+
+| Feature | Description |
+| ----------------------- | ------------------------------------------------------------------ |
+| **Circuit Breaker** | 3-state (Closed → Open → Half-Open) per provider, SQLite-persisted |
+| **Request Idempotency** | 5-second dedup window for duplicate requests |
+| **Exponential Backoff** | Automatic retry with increasing delays |
+| **Health Dashboard** | Real-time provider health monitoring |
+
+### 📋 Compliance
+
+| Feature | Description |
+| ------------------ | ----------------------------------------------------------- |
+| **Log Retention** | Automatic cleanup after `CALL_LOG_RETENTION_DAYS` |
+| **No-Log Opt-out** | Per API key `noLog` flag disables request logging |
+| **Audit Log** | Administrative actions tracked in `audit_log` table |
+| **MCP Audit** | SQLite-backed audit logging for all MCP tool calls |
+| **Zod Validation** | All API inputs validated with Zod v4 schemas at module load |
+
+---
+
+## Required Environment Variables
+
+All secrets must be set before starting the server. The server will **fail fast** if they are missing or weak.
+
+```bash
+# REQUIRED — server will not start without these:
+JWT_SECRET=$(openssl rand -base64 48) # min 32 chars
+API_KEY_SECRET=$(openssl rand -hex 32) # min 16 chars
+
+# RECOMMENDED — enables encryption at rest:
+STORAGE_ENCRYPTION_KEY=$(openssl rand -hex 32)
+```
+
+The server actively rejects known-weak values like `changeme`, `secret`, or `password`.
+
+---
+
+## Docker Security
+
+- Use non-root user in production
+- Mount secrets as read-only volumes
+- Never copy `.env` files into Docker images
+- Use `.dockerignore` to exclude sensitive files
+- Set `AUTH_COOKIE_SECURE=true` when behind HTTPS
+
+```bash
+docker run -d \
+ --name omniroute \
+ --restart unless-stopped \
+ --read-only \
+ -p 20128:20128 \
+ -v omniroute-data:/app/data \
+ -e JWT_SECRET="$(openssl rand -base64 48)" \
+ -e API_KEY_SECRET="$(openssl rand -hex 32)" \
+ -e STORAGE_ENCRYPTION_KEY="$(openssl rand -hex 32)" \
+ diegosouzapw/omniroute:latest
+```
+
+---
+
+## Dependencies
+
+- Run `npm audit` regularly
+- Keep dependencies updated
+- The project uses `husky` + `lint-staged` for pre-commit checks
+- CI pipeline runs ESLint security rules on every push
+- Provider constants validated at module load via Zod (`src/shared/validation/providerSchema.ts`)
diff --git a/docs/i18n/hu/TROUBLESHOOTING.md b/docs/i18n/hu/TROUBLESHOOTING.md
deleted file mode 100644
index 63c148000a..0000000000
--- a/docs/i18n/hu/TROUBLESHOOTING.md
+++ /dev/null
@@ -1,258 +0,0 @@
-🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/TROUBLESHOOTING.md) · 🇪🇸 [es](../es/TROUBLESHOOTING.md) · 🇫🇷 [fr](../fr/TROUBLESHOOTING.md) · 🇩🇪 [de](../de/TROUBLESHOOTING.md) · 🇮🇹 [it](../it/TROUBLESHOOTING.md) · 🇷🇺 [ru](../ru/TROUBLESHOOTING.md) · 🇨🇳 [zh-CN](../zh-CN/TROUBLESHOOTING.md) · 🇯🇵 [ja](../ja/TROUBLESHOOTING.md) · 🇰🇷 [ko](../ko/TROUBLESHOOTING.md) · 🇸🇦 [ar](../ar/TROUBLESHOOTING.md) · 🇮🇳 [in](../in/TROUBLESHOOTING.md) · 🇹🇭 [th](../th/TROUBLESHOOTING.md) · 🇻🇳 [vi](../vi/TROUBLESHOOTING.md) · 🇮🇩 [id](../id/TROUBLESHOOTING.md) · 🇲🇾 [ms](../ms/TROUBLESHOOTING.md) · 🇳🇱 [nl](../nl/TROUBLESHOOTING.md) · 🇵🇱 [pl](../pl/TROUBLESHOOTING.md) · 🇸🇪 [sv](../sv/TROUBLESHOOTING.md) · 🇳🇴 [no](../no/TROUBLESHOOTING.md) · 🇩🇰 [da](../da/TROUBLESHOOTING.md) · 🇫🇮 [fi](../fi/TROUBLESHOOTING.md) · 🇵🇹 [pt](../pt/TROUBLESHOOTING.md) · 🇷🇴 [ro](../ro/TROUBLESHOOTING.md) · 🇭🇺 [hu](../hu/TROUBLESHOOTING.md) · 🇧🇬 [bg](../bg/TROUBLESHOOTING.md) · 🇸🇰 [sk](../sk/TROUBLESHOOTING.md) · 🇺🇦 [uk-UA](../uk-UA/TROUBLESHOOTING.md) · 🇮🇱 [he](../he/TROUBLESHOOTING.md) · 🇵🇭 [phi](../phi/TROUBLESHOOTING.md)
-
----
-
-# Troubleshooting
-
-🌐 **Languages:** 🇺🇸 [English](TROUBLESHOOTING.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/TROUBLESHOOTING.md) | 🇪🇸 [Español](i18n/es/TROUBLESHOOTING.md) | 🇫🇷 [Français](i18n/fr/TROUBLESHOOTING.md) | 🇮🇹 [Italiano](i18n/it/TROUBLESHOOTING.md) | 🇷🇺 [Русский](i18n/ru/TROUBLESHOOTING.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/TROUBLESHOOTING.md) | 🇩🇪 [Deutsch](i18n/de/TROUBLESHOOTING.md) | 🇮🇳 [हिन्दी](i18n/in/TROUBLESHOOTING.md) | 🇹🇭 [ไทย](i18n/th/TROUBLESHOOTING.md) | 🇺🇦 [Українська](i18n/uk-UA/TROUBLESHOOTING.md) | 🇸🇦 [العربية](i18n/ar/TROUBLESHOOTING.md) | 🇯🇵 [日本語](i18n/ja/TROUBLESHOOTING.md) | 🇻🇳 [Tiếng Việt](i18n/vi/TROUBLESHOOTING.md) | 🇧🇬 [Български](i18n/bg/TROUBLESHOOTING.md) | 🇩🇰 [Dansk](i18n/da/TROUBLESHOOTING.md) | 🇫🇮 [Suomi](i18n/fi/TROUBLESHOOTING.md) | 🇮🇱 [עברית](i18n/he/TROUBLESHOOTING.md) | 🇭🇺 [Magyar](i18n/hu/TROUBLESHOOTING.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/TROUBLESHOOTING.md) | 🇰🇷 [한국어](i18n/ko/TROUBLESHOOTING.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/TROUBLESHOOTING.md) | 🇳🇱 [Nederlands](i18n/nl/TROUBLESHOOTING.md) | 🇳🇴 [Norsk](i18n/no/TROUBLESHOOTING.md) | 🇵🇹 [Português (Portugal)](i18n/pt/TROUBLESHOOTING.md) | 🇷🇴 [Română](i18n/ro/TROUBLESHOOTING.md) | 🇵🇱 [Polski](i18n/pl/TROUBLESHOOTING.md) | 🇸🇰 [Slovenčina](i18n/sk/TROUBLESHOOTING.md) | 🇸🇪 [Svenska](i18n/sv/TROUBLESHOOTING.md) | 🇵🇭 [Filipino](i18n/phi/TROUBLESHOOTING.md)
-
-Common problems and solutions for OmniRoute.
-
----
-
-## Quick Fixes
-
-| Problem | Solution |
-| ----------------------------- | ------------------------------------------------------------------ |
-| First login not working | Set `INITIAL_PASSWORD` in `.env` (no hardcoded default) |
-| Dashboard opens on wrong port | Set `PORT=20128` and `NEXT_PUBLIC_BASE_URL=http://localhost:20128` |
-| No request logs under `logs/` | Set `ENABLE_REQUEST_LOGS=true` |
-| EACCES: permission denied | Set `DATA_DIR=/path/to/writable/dir` to override `~/.omniroute` |
-| Routing strategy not saving | Update to v1.4.11+ (Zod schema fix for settings persistence) |
-
----
-
-## Provider Issues
-
-### "Language model did not provide messages"
-
-**Cause:** Provider quota exhausted.
-
-**Fix:**
-
-1. Check dashboard quota tracker
-2. Use a combo with fallback tiers
-3. Switch to cheaper/free tier
-
-### Rate Limiting
-
-**Cause:** Subscription quota exhausted.
-
-**Fix:**
-
-- Add fallback: `cc/claude-opus-4-6 → glm/glm-4.7 → if/kimi-k2-thinking`
-- Use GLM/MiniMax as cheap backup
-
-### OAuth Token Expired
-
-OmniRoute auto-refreshes tokens. If issues persist:
-
-1. Dashboard → Provider → Reconnect
-2. Delete and re-add the provider connection
-
----
-
-## Cloud Issues
-
-### Cloud Sync Errors
-
-1. Verify `BASE_URL` points to your running instance (e.g., `http://localhost:20128`)
-2. Verify `CLOUD_URL` points to your cloud endpoint (e.g., `https://omniroute.dev`)
-3. Keep `NEXT_PUBLIC_*` values aligned with server-side values
-
-### Cloud `stream=false` Returns 500
-
-**Symptom:** `Unexpected token 'd'...` on cloud endpoint for non-streaming calls.
-
-**Cause:** Upstream returns SSE payload while client expects JSON.
-
-**Workaround:** Use `stream=true` for cloud direct calls. Local runtime includes SSE→JSON fallback.
-
-### Cloud Says Connected but "Invalid API key"
-
-1. Create a fresh key from local dashboard (`/api/keys`)
-2. Run cloud sync: Enable Cloud → Sync Now
-3. Old/non-synced keys can still return `401` on cloud
-
----
-
-## Docker Issues
-
-### CLI Tool Shows Not Installed
-
-1. Check runtime fields: `curl http://localhost:20128/api/cli-tools/runtime/codex | jq`
-2. For portable mode: use image target `runner-cli` (bundled CLIs)
-3. For host mount mode: set `CLI_EXTRA_PATHS` and mount host bin directory as read-only
-4. If `installed=true` and `runnable=false`: binary was found but failed healthcheck
-
-### Quick Runtime Validation
-
-```bash
-curl -s http://localhost:20128/api/cli-tools/codex-settings | jq '{installed,runnable,commandPath,runtimeMode,reason}'
-curl -s http://localhost:20128/api/cli-tools/claude-settings | jq '{installed,runnable,commandPath,runtimeMode,reason}'
-curl -s http://localhost:20128/api/cli-tools/openclaw-settings | jq '{installed,runnable,commandPath,runtimeMode,reason}'
-```
-
----
-
-## Cost Issues
-
-### High Costs
-
-1. Check usage stats in Dashboard → Usage
-2. Switch primary model to GLM/MiniMax
-3. Use free tier (Gemini CLI, Qoder) for non-critical tasks
-4. Set cost budgets per API key: Dashboard → API Keys → Budget
-
----
-
-## Debugging
-
-### Enable Request Logs
-
-Set `ENABLE_REQUEST_LOGS=true` in your `.env` file. Logs appear under `logs/` directory.
-
-### Check Provider Health
-
-```bash
-# Health dashboard
-http://localhost:20128/dashboard/health
-
-# API health check
-curl http://localhost:20128/api/monitoring/health
-```
-
-### Runtime Storage
-
-- Main state: `${DATA_DIR}/storage.sqlite` (providers, combos, aliases, keys, settings)
-- Usage: SQLite tables in `storage.sqlite` (`usage_history`, `call_logs`, `proxy_logs`) + optional `${DATA_DIR}/log.txt` and `${DATA_DIR}/call_logs/`
-- Request logs: `/logs/...` (when `ENABLE_REQUEST_LOGS=true`)
-
----
-
-## Circuit Breaker Issues
-
-### Provider stuck in OPEN state
-
-When a provider's circuit breaker is OPEN, requests are blocked until the cooldown expires.
-
-**Fix:**
-
-1. Go to **Dashboard → Settings → Resilience**
-2. Check the circuit breaker card for the affected provider
-3. Click **Reset All** to clear all breakers, or wait for the cooldown to expire
-4. Verify the provider is actually available before resetting
-
-### Provider keeps tripping the circuit breaker
-
-If a provider repeatedly enters OPEN state:
-
-1. Check **Dashboard → Health → Provider Health** for the failure pattern
-2. Go to **Settings → Resilience → Provider Profiles** and increase the failure threshold
-3. Check if the provider has changed API limits or requires re-authentication
-4. Review latency telemetry — high latency may cause timeout-based failures
-
----
-
-## Audio Transcription Issues
-
-### "Unsupported model" error
-
-- Ensure you're using the correct prefix: `deepgram/nova-3` or `assemblyai/best`
-- Verify the provider is connected in **Dashboard → Providers**
-
-### Transcription returns empty or fails
-
-- Check supported audio formats: `mp3`, `wav`, `m4a`, `flac`, `ogg`, `webm`
-- Verify file size is within provider limits (typically < 25MB)
-- Check provider API key validity in the provider card
-
----
-
-## Translator Debugging
-
-Use **Dashboard → Translator** to debug format translation issues:
-
-| Mode | When to Use |
-| ---------------- | -------------------------------------------------------------------------------------------- |
-| **Playground** | Compare input/output formats side by side — paste a failing request to see how it translates |
-| **Chat Tester** | Send live messages and inspect the full request/response payload including headers |
-| **Test Bench** | Run batch tests across format combinations to find which translations are broken |
-| **Live Monitor** | Watch real-time request flow to catch intermittent translation issues |
-
-### Common format issues
-
-- **Thinking tags not appearing** — Check if the target provider supports thinking and the thinking budget setting
-- **Tool calls dropping** — Some format translations may strip unsupported fields; verify in Playground mode
-- **System prompt missing** — Claude and Gemini handle system prompts differently; check translation output
-- **SDK returns raw string instead of object** — Fixed in v1.1.0: response sanitizer now strips non-standard fields (`x_groq`, `usage_breakdown`, etc.) that cause OpenAI SDK Pydantic validation failures
-- **GLM/ERNIE rejects `system` role** — Fixed in v1.1.0: role normalizer automatically merges system messages into user messages for incompatible models
-- **`developer` role not recognized** — Fixed in v1.1.0: automatically converted to `system` for non-OpenAI providers
-- **`json_schema` not working with Gemini** — Fixed in v1.1.0: `response_format` is now converted to Gemini's `responseMimeType` + `responseSchema`
-
----
-
-## Resilience Settings
-
-### Auto rate-limit not triggering
-
-- Auto rate-limit only applies to API key providers (not OAuth/subscription)
-- Verify **Settings → Resilience → Provider Profiles** has auto-rate-limit enabled
-- Check if the provider returns `429` status codes or `Retry-After` headers
-
-### Tuning exponential backoff
-
-Provider profiles support these settings:
-
-- **Base delay** — Initial wait time after first failure (default: 1s)
-- **Max delay** — Maximum wait time cap (default: 30s)
-- **Multiplier** — How much to increase delay per consecutive failure (default: 2x)
-
-### Anti-thundering herd
-
-When many concurrent requests hit a rate-limited provider, OmniRoute uses mutex + auto rate-limiting to serialize requests and prevent cascading failures. This is automatic for API key providers.
-
----
-
-## Optional RAG / LLM failure taxonomy (16 problems)
-
-Some OmniRoute users place the gateway in front of RAG or agent stacks. In those setups it is common to see a strange pattern: OmniRoute looks healthy (providers up, routing profiles ok, no rate limit alerts) but the final answer is still wrong.
-
-In practice these incidents usually come from the downstream RAG pipeline, not from the gateway itself.
-
-If you want a shared vocabulary to describe those failures you can use the WFGY ProblemMap, an external MIT license text resource that defines sixteen recurring RAG / LLM failure patterns. At a high level it covers:
-
-- retrieval drift and broken context boundaries
-- empty or stale indexes and vector stores
-- embedding versus semantic mismatch
-- prompt assembly and context window issues
-- logic collapse and overconfident answers
-- long chain and agent coordination failures
-- multi agent memory and role drift
-- deployment and bootstrap ordering problems
-
-The idea is simple:
-
-1. When you investigate a bad response, capture:
- - user task and request
- - route or provider combo in OmniRoute
- - any RAG context used downstream (retrieved documents, tool calls, etc)
-2. Map the incident to one or two WFGY ProblemMap numbers (`No.1` … `No.16`).
-3. Store the number in your own dashboard, runbook, or incident tracker next to the OmniRoute logs.
-4. Use the corresponding WFGY page to decide whether you need to change your RAG stack, retriever, or routing strategy.
-
-Full text and concrete recipes live here (MIT license, text only):
-
-[WFGY ProblemMap README](https://github.com/onestardao/WFGY/blob/main/ProblemMap/README.md)
-
-You can ignore this section if you do not run RAG or agent pipelines behind OmniRoute.
-
----
-
-## Still Stuck?
-
-- **GitHub Issues**: [github.com/diegosouzapw/OmniRoute/issues](https://github.com/diegosouzapw/OmniRoute/issues)
-- **Architecture**: See [`docs/ARCHITECTURE.md`](ARCHITECTURE.md) for internal details
-- **API Reference**: See [`docs/API_REFERENCE.md`](API_REFERENCE.md) for all endpoints
-- **Health Dashboard**: Check **Dashboard → Health** for real-time system status
-- **Translator**: Use **Dashboard → Translator** to debug format issues
diff --git a/docs/i18n/hu/VM_DEPLOYMENT_GUIDE.md b/docs/i18n/hu/VM_DEPLOYMENT_GUIDE.md
deleted file mode 100644
index 09d559e465..0000000000
--- a/docs/i18n/hu/VM_DEPLOYMENT_GUIDE.md
+++ /dev/null
@@ -1,401 +0,0 @@
-# OmniRoute — Telepítési útmutató a Cloudflare-rel rendelkező virtuális gépen
-
-🌐 **Languages:** 🇺🇸 [English](../../VM_DEPLOYMENT_GUIDE.md) | 🇧🇷 [Português (Brasil)](../pt-BR/VM_DEPLOYMENT_GUIDE.md) | 🇪🇸 [Español](../es/VM_DEPLOYMENT_GUIDE.md) | 🇫🇷 [Français](../fr/VM_DEPLOYMENT_GUIDE.md) | 🇮🇹 [Italiano](../it/VM_DEPLOYMENT_GUIDE.md) | 🇷🇺 [Русский](../ru/VM_DEPLOYMENT_GUIDE.md) | 🇨🇳 [中文 (简体)](../zh-CN/VM_DEPLOYMENT_GUIDE.md) | 🇩🇪 [Deutsch](../de/VM_DEPLOYMENT_GUIDE.md) | 🇮🇳 [हिन्दी](../in/VM_DEPLOYMENT_GUIDE.md) | 🇹🇭 [ไทย](../th/VM_DEPLOYMENT_GUIDE.md) | 🇺🇦 [Українська](../uk-UA/VM_DEPLOYMENT_GUIDE.md) | 🇸🇦 [العربية](../ar/VM_DEPLOYMENT_GUIDE.md) | 🇯🇵 [日本語](../ja/VM_DEPLOYMENT_GUIDE.md) | 🇻🇳 [Tiếng Việt](../vi/VM_DEPLOYMENT_GUIDE.md) | 🇧🇬 [Български](../bg/VM_DEPLOYMENT_GUIDE.md) | 🇩🇰 [Dansk](../da/VM_DEPLOYMENT_GUIDE.md) | 🇫🇮 [Suomi](../fi/VM_DEPLOYMENT_GUIDE.md) | 🇮🇱 [עברית](../he/VM_DEPLOYMENT_GUIDE.md) | 🇭🇺 [Magyar](../hu/VM_DEPLOYMENT_GUIDE.md) | 🇮🇩 [Bahasa Indonesia](../id/VM_DEPLOYMENT_GUIDE.md) | 🇰🇷 [한국어](../ko/VM_DEPLOYMENT_GUIDE.md) | 🇲🇾 [Bahasa Melayu](../ms/VM_DEPLOYMENT_GUIDE.md) | 🇳🇱 [Nederlands](../nl/VM_DEPLOYMENT_GUIDE.md) | 🇳🇴 [Norsk](../no/VM_DEPLOYMENT_GUIDE.md) | 🇵🇹 [Português (Portugal)](../pt/VM_DEPLOYMENT_GUIDE.md) | 🇷🇴 [Română](../ro/VM_DEPLOYMENT_GUIDE.md) | 🇵🇱 [Polski](../pl/VM_DEPLOYMENT_GUIDE.md) | 🇸🇰 [Slovenčina](../sk/VM_DEPLOYMENT_GUIDE.md) | 🇸🇪 [Svenska](../sv/VM_DEPLOYMENT_GUIDE.md) | 🇵🇭 [Filipino](../phi/VM_DEPLOYMENT_GUIDE.md) | 🇨🇿 [Čeština](../cs/VM_DEPLOYMENT_GUIDE.md)
-
-Teljes útmutató az OmniRoute telepítéséhez és konfigurálásához Cloudflare-en keresztül kezelt tartományú virtuális gépen (VPS).
-
----
-
-## Előfeltételek
-
-| Tétel | Minimum | Ajánlott |
-| ----------- | ------------------------- | ---------------- |
-| **CPU** | 1 vCPU | 2 vCPU |
-| **RAM** | 1 GB | 2 GB |
-| **Lemez** | 10 GB SSD | 25 GB SSD |
-| **OS** | Ubuntu 22.04 LTS | Ubuntu 24.04 LTS |
-| **Domain** | Regisztrálva a Cloudflare | — |
-| **Dokkoló** | Docker Engine 24+ | Docker 27+ |
-
-**Tesztelt szolgáltatók**: Akamai (Linode), DigitalOcean, Vultr, Hetzner, AWS Lightsail.
-
----
-
-## 1. Konfigurálja a virtuális gépet
-
-### 1.1 Hozza létre a példányt
-
-A választott VPS-szolgáltatónál:
-
-- Válassza az Ubuntu 24.04 LTS-t
-- Válassza ki a minimális csomagot (1 vCPU / 1 GB RAM)
-- Állítson be erős root jelszót vagy konfigurálja az SSH-kulcsot
-- Jegyezze fel a **nyilvános IP-címet** (pl. `203.0.113.10`)
-
-### 1.2 Csatlakozás SSH-n keresztül
-
-```bash
-ssh root@203.0.113.10
-```
-
-### 1.3 Frissítse a rendszert
-
-```bash
-apt update && apt upgrade -y
-```
-
-### 1.4 Telepítse a Dockert
-
-```bash
-# Install dependencies
-apt install -y ca-certificates curl gnupg
-
-# Add official Docker repository
-install -m 0755 -d /etc/apt/keyrings
-curl -fsSL https://download.docker.com/linux/ubuntu/gpg | gpg --dearmor -o /etc/apt/keyrings/docker.gpg
-chmod a+r /etc/apt/keyrings/docker.gpg
-echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu $ (. /etc/os-release && echo “$VERSION_CODENAME”) stable" | tee /etc/apt/sources.list.d/docker.list > /dev/null
-apt update
-apt install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin
-```
-
-### 1.5 Az nginx telepítése
-
-```bash
-apt install -y nginx
-```
-
-### 1.6 Tűzfal konfigurálása (UFW)
-
-```bash
-ufw default deny incoming
-ufw default allow outgoing
-ufw allow 22/tcp # SSH
-ufw allow 80/tcp # HTTP (redirect)
-ufw allow 443/tcp # HTTPS
-ufw enable
-```
-
-> **Tipp**: A maximális biztonság érdekében korlátozza a 80-as és 443-as portot csak a Cloudflare IP-címekre. Lásd a [Advanced Security](#advanced-security) részt.
-
----
-
-## 2. Telepítse az OmniRoute programot
-
-### 2.1 Konfigurációs könyvtár létrehozása
-
-```bash
-mkdir -p /opt/omniroute
-```
-
-### 2.2 Környezeti változók fájl létrehozása
-
-```bash
-cat > /opt/omniroute/.env << ‘EOF’
-# === Security ===
-JWT_SECRET=CHANGE-TO-A-UNIQUE-64-CHAR-SECRET-KEY
-INITIAL_PASSWORD=YourSecurePassword123!
-API_KEY_SECRET=REPLACE-WITH-ANOTHER-SECRET-KEY
-STORAGE_ENCRYPTION_KEY=REPLACE-WITH-THIRD-SECRET-KEY
-STORAGE_ENCRYPTION_KEY_VERSION=v1
-MACHINE_ID_SALT=CHANGE-TO-A-UNIQUE-SALT
-
-# === App ===
-PORT=20128
-NODE_ENV=production
-HOSTNAME=0.0.0.0
-DATA_DIR=/app/data
-STORAGE_DRIVER=sqlite
-ENABLE_REQUEST_LOGS=true
-AUTH_COOKIE_SECURE=false
-REQUIRE_API_KEY=false
-
-# === Domain (change to your domain) ===
-BASE_URL=https://llms.seudominio.com
-NEXT_PUBLIC_BASE_URL=https://llms.seudominio.com
-
-# === Cloud Sync (optional) ===
-# CLOUD_URL=https://cloud.omniroute.online
-# NEXT_PUBLIC_CLOUD_URL=https://cloud.omniroute.online
-EOF
-```
-
-> ⚠️ **FONTOS**: Hozzon létre egyedi titkos kulcsokat! Minden kulcshoz használja az `openssl rand -hex 32` értéket.
-
-### 2.3 Indítsa el a tárolót
-
-```bash
-docker pull diegosouzapw/omniroute:latest
-
-docker run -d \
- --name omniroute \
- --restart unless-stopped \
- --env-file /opt/omniroute/.env \
- -p 20128:20128 \
- -v omniroute-data:/app/data \
- diegosouzapw/omniroute:latest
-```
-
-### 2.4 Ellenőrizze, hogy fut-e
-
-```bash
-docker ps | grep omniroute
-docker logs omniroute --tail 20
-```
-
-Meg kell jelennie: `[DB] SQLite database ready` és `listening on port 20128`.
-
----
-
-## 3. Az nginx (fordított proxy) konfigurálása
-
-### 3.1 SSL-tanúsítvány generálása (Cloudflare Origin)
-
-A Cloudflare irányítópulton:
-
-1. Nyissa meg az **SSL/TLS → Origin Server** lehetőséget.
-2. Kattintson a **Tanúsítvány létrehozása** lehetőségre.
-3. Tartsa meg az alapértelmezett értékeket (15 év, \*.sajatdomain.com)
-4. Másolja ki az **Eredeti tanúsítványt** és a **Privát kulcsot**
-
-```bash
-mkdir -p /etc/nginx/ssl
-
-# Paste the certificate
-nano /etc/nginx/ssl/origin.crt
-
-# Paste the private key
-nano /etc/nginx/ssl/origin.key
-
-chmod 600 /etc/nginx/ssl/origin.key
-```
-
-### 3.2 Nginx konfiguráció
-
-```bash
-cat > /etc/nginx/sites-available/omniroute << ‘NGINX’
-# Default server — blocks direct access via IP
-server {
- listen 80 default_server;
- listen [::]:80 default_server;
- listen 443 ssl default_server;
- listen [::]:443 ssl default_server;
- ssl_certificate /etc/nginx/ssl/origin.crt;
- ssl_certificate_key /etc/nginx/ssl/origin.key;
- server_name _;
- return 444;
-}
-
-# OmniRoute — HTTPS
-server {
- listen 443 ssl;
- listen [::]:443 ssl;
- server_name llms.yourdomain.com; # Change to your domain
-
- ssl_certificate /etc/nginx/ssl/origin.crt;
- ssl_certificate_key /etc/nginx/ssl/origin.key;
- ssl_protocols TLSv1.2 TLSv1.3;
-
- client_max_body_size 100M;
-
- location / {
- proxy_pass http://127.0.0.1:20128;
- proxy_set_header Host $host;
- proxy_set_header X-Real-IP $remote_addr;
- proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
- proxy_set_header X-Forwarded-Proto $scheme;
-
- # WebSocket support
- proxy_http_version 1.1;
- proxy_set_header Upgrade $http_upgrade;
- proxy_set_header Connection “upgrade”;
-
- # SSE (Server-Sent Events) — streaming AI responses
- proxy_buffering off;
- proxy_cache off;
- proxy_read_timeout 300s;
- proxy_send_timeout 300s;
- }
-}
-
-# HTTP → HTTPS redirect
-server {
- listen 80;
- listen [::]:80;
- server_name llms.yourdomain.com;
- return 301 https://$server_name$request_uri;
-}
-NGINX
-```
-
-### 3.3 Engedélyezés és tesztelés
-
-```bash
-# Remove default configuration
-rm -f /etc/nginx/sites-enabled/default
-
-# Enable OmniRoute
-ln -sf /etc/nginx/sites-available/omniroute /etc/nginx/sites-enabled/omniroute
-
-# Test and reload
-nginx -t && systemctl reload nginx
-```
-
----
-
-## 4. Konfigurálja a Cloudflare DNS-t
-
-### 4.1 DNS-rekord hozzáadása
-
-A Cloudflare irányítópulton → DNS:
-
-| Típus | Név | Tartalom | Proxy |
-| ----- | ------ | ---------------------- | ----------------- |
-| A | `llms` | `203.0.113.10` (VM IP) | ✅ Meghatalmazott |
-
-### 4.2 SSL konfigurálása
-
-Az **SSL/TLS → Áttekintés** alatt:
-
-- Mód: **Teljes (szigorú)**
-
-**SSL/TLS → Edge Certificates** alatt:
-
-- Mindig használjon HTTPS-t: ✅ Be
-- Minimális TLS-verzió: TLS 1.2
-- Automatikus HTTPS-újraírások: ✅ Be
-
-### 4.3 Tesztelés
-
-```bash
-curl -sI https://llms.seudominio.com/health
-# Should return HTTP/2 200
-```
-
----
-
-## 5. Műveletek és karbantartás
-
-### Frissítsen egy új verzióra
-
-```bash
-docker pull diegosouzapw/omniroute:latest
-docker stop omniroute && docker rm omniroute
-docker run -d --name omniroute --restart unless-stopped \
- --env-file /opt/omniroute/.env \
- -p 20128:20128 \
- -v omniroute-data:/app/data \
- diegosouzapw/omniroute:latest
-```
-
-### Naplók megtekintése
-
-```bash
-docker logs -f omniroute # Real-time stream
-docker logs omniroute --tail 50 # Last 50 lines
-```
-
-### Manuális adatbázis-mentés
-
-```bash
-# Copy data from the volume to the host
-docker cp omniroute:/app/data ./backup-$(date +%F)
-
-# Or compress the entire volume
-docker run --rm -v omniroute-data:/data -v $(pwd):/backup \
- alpine tar czf /backup/omniroute-data-$(date +%F).tar.gz /data
-```
-
-### Visszaállítás biztonsági másolatból
-
-```bash
-docker stop omniroute
-docker run --rm -v omniroute-data:/data -v $(pwd):/backup \
- alpine sh -c “rm -rf /data/* && tar xzf /backup/omniroute-data-YYYY-MM-DD.tar.gz -C /”
-docker start omniroute
-```
-
----
-
-## 6. Speciális biztonság
-
-### Az nginx korlátozása a Cloudflare IP-címekre
-
-```bash
-cat > /etc/nginx/cloudflare-ips.conf << ‘CF’
-# Cloudflare IPv4 ranges — update periodically
-# https://www.cloudflare.com/ips-v4/
-set_real_ip_from 173.245.48.0/20;
-set_real_ip_from 103.21.244.0/22;
-set_real_ip_from 103.22.200.0/22;
-set_real_ip_from 103.31.4.0/22;
-set_real_ip_from 141.101.64.0/18;
-set_real_ip_from 108.162.192.0/18;
-set_real_ip_from 190.93.240.0/20;
-set_real_ip_from 188.114.96.0/20;
-set_real_ip_from 197.234.240.0/22;
-set_real_ip_from 198.41.128.0/17;
-set_real_ip_from 162.158.0.0/15;
-set_real_ip_from 104.16.0.0/13;
-set_real_ip_from 104.24.0.0/14;
-set_real_ip_from 172.64.0.0/13;
-set_real_ip_from 131.0.72.0/22;
-real_ip_header CF-Connecting-IP;
-CF
-```
-
-Adja hozzá a következőket a `nginx.conf` elemhez a `http {}` blokkon belül:
-
-```nginx
-include /etc/nginx/cloudflare-ips.conf;
-```
-
-### Telepítse a fail2ban-t
-
-```bash
-apt install -y fail2ban
-systemctl enable fail2ban
-systemctl start fail2ban
-
-# Check status
-fail2ban-client status sshd
-```
-
-### A Docker-porthoz való közvetlen hozzáférés letiltása
-
-```bash
-# Prevent direct external access to port 20128
-iptables -I DOCKER-USER -p tcp --dport 20128 -j DROP
-iptables -I DOCKER-USER -i lo -p tcp --dport 20128 -j ACCEPT
-
-# Persist the rules
-apt install -y iptables-persistent
-netfilter-persistent save
-```
-
----
-
-## 7. Telepítés a Cloudflare Workers számára (opcionális)
-
-A Cloudflare Workersen keresztüli távoli eléréshez (a virtuális gép közvetlen feltárása nélkül):
-
-```bash
-# In the local repository
-cd omnirouteCloud
-npm install
-npx wrangler login
-npx wrangler deploy
-```
-
-Tekintse meg a teljes dokumentációt: [omnirouteCloud/README.md](../omnirouteCloud/README.md).
-
----
-
-## Port összefoglaló
-
-| Kikötő | Szolgáltatás | Hozzáférés |
-| ------ | ------------ | ----------------------------------- |
-| 22 | SSH | Nyilvános (fail2ban-nal) |
-| 80 | nginx HTTP | Átirányítás → HTTPS |
-| 443 | nginx HTTPS | Cloudflare Proxy segítségével |
-| 20128 | OmniRoute | Csak Localhost (nginx-en keresztül) |
diff --git a/docs/i18n/da/A2A-SERVER.md b/docs/i18n/hu/docs/A2A-SERVER.md
similarity index 77%
rename from docs/i18n/da/A2A-SERVER.md
rename to docs/i18n/hu/docs/A2A-SERVER.md
index 01531ff482..14946eca62 100644
--- a/docs/i18n/da/A2A-SERVER.md
+++ b/docs/i18n/hu/docs/A2A-SERVER.md
@@ -1,9 +1,9 @@
-🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/A2A-SERVER.md) · 🇪🇸 [es](../es/A2A-SERVER.md) · 🇫🇷 [fr](../fr/A2A-SERVER.md) · 🇩🇪 [de](../de/A2A-SERVER.md) · 🇮🇹 [it](../it/A2A-SERVER.md) · 🇷🇺 [ru](../ru/A2A-SERVER.md) · 🇨🇳 [zh-CN](../zh-CN/A2A-SERVER.md) · 🇯🇵 [ja](../ja/A2A-SERVER.md) · 🇰🇷 [ko](../ko/A2A-SERVER.md) · 🇸🇦 [ar](../ar/A2A-SERVER.md) · 🇮🇳 [in](../in/A2A-SERVER.md) · 🇹🇭 [th](../th/A2A-SERVER.md) · 🇻🇳 [vi](../vi/A2A-SERVER.md) · 🇮🇩 [id](../id/A2A-SERVER.md) · 🇲🇾 [ms](../ms/A2A-SERVER.md) · 🇳🇱 [nl](../nl/A2A-SERVER.md) · 🇵🇱 [pl](../pl/A2A-SERVER.md) · 🇸🇪 [sv](../sv/A2A-SERVER.md) · 🇳🇴 [no](../no/A2A-SERVER.md) · 🇩🇰 [da](../da/A2A-SERVER.md) · 🇫🇮 [fi](../fi/A2A-SERVER.md) · 🇵🇹 [pt](../pt/A2A-SERVER.md) · 🇷🇴 [ro](../ro/A2A-SERVER.md) · 🇭🇺 [hu](../hu/A2A-SERVER.md) · 🇧🇬 [bg](../bg/A2A-SERVER.md) · 🇸🇰 [sk](../sk/A2A-SERVER.md) · 🇺🇦 [uk-UA](../uk-UA/A2A-SERVER.md) · 🇮🇱 [he](../he/A2A-SERVER.md) · 🇵🇭 [phi](../phi/A2A-SERVER.md)
+# OmniRoute A2A Server Documentation (Magyar)
+
+🌐 **Languages:** 🇺🇸 [English](../../../../docs/A2A-SERVER.md) · 🇪🇸 [es](../../es/docs/A2A-SERVER.md) · 🇫🇷 [fr](../../fr/docs/A2A-SERVER.md) · 🇩🇪 [de](../../de/docs/A2A-SERVER.md) · 🇮🇹 [it](../../it/docs/A2A-SERVER.md) · 🇷🇺 [ru](../../ru/docs/A2A-SERVER.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/A2A-SERVER.md) · 🇯🇵 [ja](../../ja/docs/A2A-SERVER.md) · 🇰🇷 [ko](../../ko/docs/A2A-SERVER.md) · 🇸🇦 [ar](../../ar/docs/A2A-SERVER.md) · 🇮🇳 [in](../../in/docs/A2A-SERVER.md) · 🇹🇭 [th](../../th/docs/A2A-SERVER.md) · 🇻🇳 [vi](../../vi/docs/A2A-SERVER.md) · 🇮🇩 [id](../../id/docs/A2A-SERVER.md) · 🇲🇾 [ms](../../ms/docs/A2A-SERVER.md) · 🇳🇱 [nl](../../nl/docs/A2A-SERVER.md) · 🇵🇱 [pl](../../pl/docs/A2A-SERVER.md) · 🇸🇪 [sv](../../sv/docs/A2A-SERVER.md) · 🇳🇴 [no](../../no/docs/A2A-SERVER.md) · 🇩🇰 [da](../../da/docs/A2A-SERVER.md) · 🇫🇮 [fi](../../fi/docs/A2A-SERVER.md) · 🇵🇹 [pt](../../pt/docs/A2A-SERVER.md) · 🇷🇴 [ro](../../ro/docs/A2A-SERVER.md) · 🇭🇺 [hu](../../hu/docs/A2A-SERVER.md) · 🇧🇬 [bg](../../bg/docs/A2A-SERVER.md) · 🇸🇰 [sk](../../sk/docs/A2A-SERVER.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/A2A-SERVER.md) · 🇮🇱 [he](../../he/docs/A2A-SERVER.md) · 🇵🇭 [phi](../../phi/docs/A2A-SERVER.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/A2A-SERVER.md) · 🇨🇿 [cs](../../cs/docs/A2A-SERVER.md)
---
-# OmniRoute A2A Server Documentation
-
> Agent-to-Agent Protocol v0.3 — OmniRoute as an intelligent routing agent
## Agent Discovery
diff --git a/docs/i18n/da/API_REFERENCE.md b/docs/i18n/hu/docs/API_REFERENCE.md
similarity index 74%
rename from docs/i18n/da/API_REFERENCE.md
rename to docs/i18n/hu/docs/API_REFERENCE.md
index b878605221..9702f795f7 100644
--- a/docs/i18n/da/API_REFERENCE.md
+++ b/docs/i18n/hu/docs/API_REFERENCE.md
@@ -1,11 +1,9 @@
-🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/API_REFERENCE.md) · 🇪🇸 [es](../es/API_REFERENCE.md) · 🇫🇷 [fr](../fr/API_REFERENCE.md) · 🇩🇪 [de](../de/API_REFERENCE.md) · 🇮🇹 [it](../it/API_REFERENCE.md) · 🇷🇺 [ru](../ru/API_REFERENCE.md) · 🇨🇳 [zh-CN](../zh-CN/API_REFERENCE.md) · 🇯🇵 [ja](../ja/API_REFERENCE.md) · 🇰🇷 [ko](../ko/API_REFERENCE.md) · 🇸🇦 [ar](../ar/API_REFERENCE.md) · 🇮🇳 [in](../in/API_REFERENCE.md) · 🇹🇭 [th](../th/API_REFERENCE.md) · 🇻🇳 [vi](../vi/API_REFERENCE.md) · 🇮🇩 [id](../id/API_REFERENCE.md) · 🇲🇾 [ms](../ms/API_REFERENCE.md) · 🇳🇱 [nl](../nl/API_REFERENCE.md) · 🇵🇱 [pl](../pl/API_REFERENCE.md) · 🇸🇪 [sv](../sv/API_REFERENCE.md) · 🇳🇴 [no](../no/API_REFERENCE.md) · 🇩🇰 [da](../da/API_REFERENCE.md) · 🇫🇮 [fi](../fi/API_REFERENCE.md) · 🇵🇹 [pt](../pt/API_REFERENCE.md) · 🇷🇴 [ro](../ro/API_REFERENCE.md) · 🇭🇺 [hu](../hu/API_REFERENCE.md) · 🇧🇬 [bg](../bg/API_REFERENCE.md) · 🇸🇰 [sk](../sk/API_REFERENCE.md) · 🇺🇦 [uk-UA](../uk-UA/API_REFERENCE.md) · 🇮🇱 [he](../he/API_REFERENCE.md) · 🇵🇭 [phi](../phi/API_REFERENCE.md)
+# API Reference (Magyar)
+
+🌐 **Languages:** 🇺🇸 [English](../../../../docs/API_REFERENCE.md) · 🇪🇸 [es](../../es/docs/API_REFERENCE.md) · 🇫🇷 [fr](../../fr/docs/API_REFERENCE.md) · 🇩🇪 [de](../../de/docs/API_REFERENCE.md) · 🇮🇹 [it](../../it/docs/API_REFERENCE.md) · 🇷🇺 [ru](../../ru/docs/API_REFERENCE.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/API_REFERENCE.md) · 🇯🇵 [ja](../../ja/docs/API_REFERENCE.md) · 🇰🇷 [ko](../../ko/docs/API_REFERENCE.md) · 🇸🇦 [ar](../../ar/docs/API_REFERENCE.md) · 🇮🇳 [in](../../in/docs/API_REFERENCE.md) · 🇹🇭 [th](../../th/docs/API_REFERENCE.md) · 🇻🇳 [vi](../../vi/docs/API_REFERENCE.md) · 🇮🇩 [id](../../id/docs/API_REFERENCE.md) · 🇲🇾 [ms](../../ms/docs/API_REFERENCE.md) · 🇳🇱 [nl](../../nl/docs/API_REFERENCE.md) · 🇵🇱 [pl](../../pl/docs/API_REFERENCE.md) · 🇸🇪 [sv](../../sv/docs/API_REFERENCE.md) · 🇳🇴 [no](../../no/docs/API_REFERENCE.md) · 🇩🇰 [da](../../da/docs/API_REFERENCE.md) · 🇫🇮 [fi](../../fi/docs/API_REFERENCE.md) · 🇵🇹 [pt](../../pt/docs/API_REFERENCE.md) · 🇷🇴 [ro](../../ro/docs/API_REFERENCE.md) · 🇭🇺 [hu](../../hu/docs/API_REFERENCE.md) · 🇧🇬 [bg](../../bg/docs/API_REFERENCE.md) · 🇸🇰 [sk](../../sk/docs/API_REFERENCE.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/API_REFERENCE.md) · 🇮🇱 [he](../../he/docs/API_REFERENCE.md) · 🇵🇭 [phi](../../phi/docs/API_REFERENCE.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/API_REFERENCE.md) · 🇨🇿 [cs](../../cs/docs/API_REFERENCE.md)
---
-# API Reference
-
-🌐 **Languages:** 🇺🇸 [English](API_REFERENCE.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/API_REFERENCE.md) | 🇪🇸 [Español](i18n/es/API_REFERENCE.md) | 🇫🇷 [Français](i18n/fr/API_REFERENCE.md) | 🇮🇹 [Italiano](i18n/it/API_REFERENCE.md) | 🇷🇺 [Русский](i18n/ru/API_REFERENCE.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/API_REFERENCE.md) | 🇩🇪 [Deutsch](i18n/de/API_REFERENCE.md) | 🇮🇳 [हिन्दी](i18n/in/API_REFERENCE.md) | 🇹🇭 [ไทย](i18n/th/API_REFERENCE.md) | 🇺🇦 [Українська](i18n/uk-UA/API_REFERENCE.md) | 🇸🇦 [العربية](i18n/ar/API_REFERENCE.md) | 🇯🇵 [日本語](i18n/ja/API_REFERENCE.md) | 🇻🇳 [Tiếng Việt](i18n/vi/API_REFERENCE.md) | 🇧🇬 [Български](i18n/bg/API_REFERENCE.md) | 🇩🇰 [Dansk](i18n/da/API_REFERENCE.md) | 🇫🇮 [Suomi](i18n/fi/API_REFERENCE.md) | 🇮🇱 [עברית](i18n/he/API_REFERENCE.md) | 🇭🇺 [Magyar](i18n/hu/API_REFERENCE.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/API_REFERENCE.md) | 🇰🇷 [한국어](i18n/ko/API_REFERENCE.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/API_REFERENCE.md) | 🇳🇱 [Nederlands](i18n/nl/API_REFERENCE.md) | 🇳🇴 [Norsk](i18n/no/API_REFERENCE.md) | 🇵🇹 [Português (Portugal)](i18n/pt/API_REFERENCE.md) | 🇷🇴 [Română](i18n/ro/API_REFERENCE.md) | 🇵🇱 [Polski](i18n/pl/API_REFERENCE.md) | 🇸🇰 [Slovenčina](i18n/sk/API_REFERENCE.md) | 🇸🇪 [Svenska](i18n/sv/API_REFERENCE.md) | 🇵🇭 [Filipino](i18n/phi/API_REFERENCE.md)
-
Complete reference for all OmniRoute API endpoints.
---
@@ -42,15 +40,20 @@ Content-Type: application/json
### Custom Headers
-| Header | Direction | Description |
-| ------------------------ | --------- | --------------------------------- |
-| `X-OmniRoute-No-Cache` | Request | Set to `true` to bypass cache |
-| `X-OmniRoute-Progress` | Request | Set to `true` for progress events |
-| `Idempotency-Key` | Request | Dedup key (5s window) |
-| `X-Request-Id` | Request | Alternative dedup key |
-| `X-OmniRoute-Cache` | Response | `HIT` or `MISS` (non-streaming) |
-| `X-OmniRoute-Idempotent` | Response | `true` if deduplicated |
-| `X-OmniRoute-Progress` | Response | `enabled` if progress tracking on |
+| Header | Direction | Description |
+| ------------------------ | --------- | ------------------------------------------------ |
+| `X-OmniRoute-No-Cache` | Request | Set to `true` to bypass cache |
+| `X-OmniRoute-Progress` | Request | Set to `true` for progress events |
+| `X-Session-Id` | Request | Sticky session key for external session affinity |
+| `x_session_id` | Request | Underscore variant also accepted (direct HTTP) |
+| `Idempotency-Key` | Request | Dedup key (5s window) |
+| `X-Request-Id` | Request | Alternative dedup key |
+| `X-OmniRoute-Cache` | Response | `HIT` or `MISS` (non-streaming) |
+| `X-OmniRoute-Idempotent` | Response | `true` if deduplicated |
+| `X-OmniRoute-Progress` | Response | `enabled` if progress tracking on |
+| `X-OmniRoute-Session-Id` | Response | Effective session ID used by OmniRoute |
+
+> Nginx note: if you rely on underscore headers (for example `x_session_id`), enable `underscores_in_headers on;`.
---
@@ -141,10 +144,10 @@ The provider prefix is auto-added if missing. Mismatched models return `400`.
```bash
# Get cache stats
-GET /api/cache
+GET /api/cache/stats
# Clear all caches
-DELETE /api/cache
+DELETE /api/cache/stats
```
Response example:
@@ -215,23 +218,23 @@ Response example:
### Settings
-| Endpoint | Method | Description |
-| ------------------------------- | ------- | ---------------------- |
-| `/api/settings` | GET/PUT | General settings |
-| `/api/settings/proxy` | GET/PUT | Network proxy config |
-| `/api/settings/proxy/test` | POST | Test proxy connection |
-| `/api/settings/ip-filter` | GET/PUT | IP allowlist/blocklist |
-| `/api/settings/thinking-budget` | GET/PUT | Reasoning token budget |
-| `/api/settings/system-prompt` | GET/PUT | Global system prompt |
+| Endpoint | Method | Description |
+| ------------------------------- | ------------- | ---------------------- |
+| `/api/settings` | GET/PUT/PATCH | General settings |
+| `/api/settings/proxy` | GET/PUT | Network proxy config |
+| `/api/settings/proxy/test` | POST | Test proxy connection |
+| `/api/settings/ip-filter` | GET/PUT | IP allowlist/blocklist |
+| `/api/settings/thinking-budget` | GET/PUT | Reasoning token budget |
+| `/api/settings/system-prompt` | GET/PUT | Global system prompt |
### Monitoring
-| Endpoint | Method | Description |
-| ------------------------ | ---------- | ----------------------- |
-| `/api/sessions` | GET | Active session tracking |
-| `/api/rate-limits` | GET | Per-account rate limits |
-| `/api/monitoring/health` | GET | Health check |
-| `/api/cache` | GET/DELETE | Cache stats / clear |
+| Endpoint | Method | Description |
+| ------------------------ | ---------- | ---------------------------------------------------------------------------------------------------- |
+| `/api/sessions` | GET | Active session tracking |
+| `/api/rate-limits` | GET | Per-account rate limits |
+| `/api/monitoring/health` | GET | Health check + provider summary (`catalogCount`, `configuredCount`, `activeCount`, `monitoredCount`) |
+| `/api/cache/stats` | GET/DELETE | Cache stats / clear |
### Backup & Export/Import
@@ -252,6 +255,13 @@ Response example:
| `/api/sync/initialize` | POST | Initialize sync |
| `/api/cloud/*` | Various | Cloud management |
+### Tunnels
+
+| Endpoint | Method | Description |
+| -------------------------- | ------ | ----------------------------------------------------------------------- |
+| `/api/tunnels/cloudflared` | GET | Read Cloudflare Quick Tunnel install/runtime status for the dashboard |
+| `/api/tunnels/cloudflared` | POST | Enable or disable the Cloudflare Quick Tunnel (`action=enable/disable`) |
+
### CLI Tools
| Endpoint | Method | Description |
@@ -276,12 +286,12 @@ GET response includes `agents[]` (id, name, binary, version, installed, protocol
### Resilience & Rate Limits
-| Endpoint | Method | Description |
-| ----------------------- | ------- | ------------------------------- |
-| `/api/resilience` | GET/PUT | Get/update resilience profiles |
-| `/api/resilience/reset` | POST | Reset circuit breakers |
-| `/api/rate-limits` | GET | Per-account rate limit status |
-| `/api/rate-limit` | GET | Global rate limit configuration |
+| Endpoint | Method | Description |
+| ----------------------- | --------- | ------------------------------- |
+| `/api/resilience` | GET/PATCH | Get/update resilience profiles |
+| `/api/resilience/reset` | POST | Reset circuit breakers |
+| `/api/rate-limits` | GET | Per-account rate limit status |
+| `/api/rate-limit` | GET | Global rate limit configuration |
### Evals
diff --git a/docs/i18n/bg/ARCHITECTURE.md b/docs/i18n/hu/docs/ARCHITECTURE.md
similarity index 89%
rename from docs/i18n/bg/ARCHITECTURE.md
rename to docs/i18n/hu/docs/ARCHITECTURE.md
index 4ea06a29f2..530ba3dad8 100644
--- a/docs/i18n/bg/ARCHITECTURE.md
+++ b/docs/i18n/hu/docs/ARCHITECTURE.md
@@ -1,12 +1,10 @@
-🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/ARCHITECTURE.md) · 🇪🇸 [es](../es/ARCHITECTURE.md) · 🇫🇷 [fr](../fr/ARCHITECTURE.md) · 🇩🇪 [de](../de/ARCHITECTURE.md) · 🇮🇹 [it](../it/ARCHITECTURE.md) · 🇷🇺 [ru](../ru/ARCHITECTURE.md) · 🇨🇳 [zh-CN](../zh-CN/ARCHITECTURE.md) · 🇯🇵 [ja](../ja/ARCHITECTURE.md) · 🇰🇷 [ko](../ko/ARCHITECTURE.md) · 🇸🇦 [ar](../ar/ARCHITECTURE.md) · 🇮🇳 [in](../in/ARCHITECTURE.md) · 🇹🇭 [th](../th/ARCHITECTURE.md) · 🇻🇳 [vi](../vi/ARCHITECTURE.md) · 🇮🇩 [id](../id/ARCHITECTURE.md) · 🇲🇾 [ms](../ms/ARCHITECTURE.md) · 🇳🇱 [nl](../nl/ARCHITECTURE.md) · 🇵🇱 [pl](../pl/ARCHITECTURE.md) · 🇸🇪 [sv](../sv/ARCHITECTURE.md) · 🇳🇴 [no](../no/ARCHITECTURE.md) · 🇩🇰 [da](../da/ARCHITECTURE.md) · 🇫🇮 [fi](../fi/ARCHITECTURE.md) · 🇵🇹 [pt](../pt/ARCHITECTURE.md) · 🇷🇴 [ro](../ro/ARCHITECTURE.md) · 🇭🇺 [hu](../hu/ARCHITECTURE.md) · 🇧🇬 [bg](../bg/ARCHITECTURE.md) · 🇸🇰 [sk](../sk/ARCHITECTURE.md) · 🇺🇦 [uk-UA](../uk-UA/ARCHITECTURE.md) · 🇮🇱 [he](../he/ARCHITECTURE.md) · 🇵🇭 [phi](../phi/ARCHITECTURE.md)
+# OmniRoute Architecture (Magyar)
+
+🌐 **Languages:** 🇺🇸 [English](../../../../docs/ARCHITECTURE.md) · 🇪🇸 [es](../../es/docs/ARCHITECTURE.md) · 🇫🇷 [fr](../../fr/docs/ARCHITECTURE.md) · 🇩🇪 [de](../../de/docs/ARCHITECTURE.md) · 🇮🇹 [it](../../it/docs/ARCHITECTURE.md) · 🇷🇺 [ru](../../ru/docs/ARCHITECTURE.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/ARCHITECTURE.md) · 🇯🇵 [ja](../../ja/docs/ARCHITECTURE.md) · 🇰🇷 [ko](../../ko/docs/ARCHITECTURE.md) · 🇸🇦 [ar](../../ar/docs/ARCHITECTURE.md) · 🇮🇳 [in](../../in/docs/ARCHITECTURE.md) · 🇹🇭 [th](../../th/docs/ARCHITECTURE.md) · 🇻🇳 [vi](../../vi/docs/ARCHITECTURE.md) · 🇮🇩 [id](../../id/docs/ARCHITECTURE.md) · 🇲🇾 [ms](../../ms/docs/ARCHITECTURE.md) · 🇳🇱 [nl](../../nl/docs/ARCHITECTURE.md) · 🇵🇱 [pl](../../pl/docs/ARCHITECTURE.md) · 🇸🇪 [sv](../../sv/docs/ARCHITECTURE.md) · 🇳🇴 [no](../../no/docs/ARCHITECTURE.md) · 🇩🇰 [da](../../da/docs/ARCHITECTURE.md) · 🇫🇮 [fi](../../fi/docs/ARCHITECTURE.md) · 🇵🇹 [pt](../../pt/docs/ARCHITECTURE.md) · 🇷🇴 [ro](../../ro/docs/ARCHITECTURE.md) · 🇭🇺 [hu](../../hu/docs/ARCHITECTURE.md) · 🇧🇬 [bg](../../bg/docs/ARCHITECTURE.md) · 🇸🇰 [sk](../../sk/docs/ARCHITECTURE.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/ARCHITECTURE.md) · 🇮🇱 [he](../../he/docs/ARCHITECTURE.md) · 🇵🇭 [phi](../../phi/docs/ARCHITECTURE.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/ARCHITECTURE.md) · 🇨🇿 [cs](../../cs/docs/ARCHITECTURE.md)
---
-# OmniRoute Architecture
-
-🌐 **Languages:** 🇺🇸 [English](ARCHITECTURE.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/ARCHITECTURE.md) | 🇪🇸 [Español](i18n/es/ARCHITECTURE.md) | 🇫🇷 [Français](i18n/fr/ARCHITECTURE.md) | 🇮🇹 [Italiano](i18n/it/ARCHITECTURE.md) | 🇷🇺 [Русский](i18n/ru/ARCHITECTURE.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/ARCHITECTURE.md) | 🇩🇪 [Deutsch](i18n/de/ARCHITECTURE.md) | 🇮🇳 [हिन्दी](i18n/in/ARCHITECTURE.md) | 🇹🇭 [ไทย](i18n/th/ARCHITECTURE.md) | 🇺🇦 [Українська](i18n/uk-UA/ARCHITECTURE.md) | 🇸🇦 [العربية](i18n/ar/ARCHITECTURE.md) | 🇯🇵 [日本語](i18n/ja/ARCHITECTURE.md) | 🇻🇳 [Tiếng Việt](i18n/vi/ARCHITECTURE.md) | 🇧🇬 [Български](i18n/bg/ARCHITECTURE.md) | 🇩🇰 [Dansk](i18n/da/ARCHITECTURE.md) | 🇫🇮 [Suomi](i18n/fi/ARCHITECTURE.md) | 🇮🇱 [עברית](i18n/he/ARCHITECTURE.md) | 🇭🇺 [Magyar](i18n/hu/ARCHITECTURE.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/ARCHITECTURE.md) | 🇰🇷 [한국어](i18n/ko/ARCHITECTURE.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/ARCHITECTURE.md) | 🇳🇱 [Nederlands](i18n/nl/ARCHITECTURE.md) | 🇳🇴 [Norsk](i18n/no/ARCHITECTURE.md) | 🇵🇹 [Português (Portugal)](i18n/pt/ARCHITECTURE.md) | 🇷🇴 [Română](i18n/ro/ARCHITECTURE.md) | 🇵🇱 [Polski](i18n/pl/ARCHITECTURE.md) | 🇸🇰 [Slovenčina](i18n/sk/ARCHITECTURE.md) | 🇸🇪 [Svenska](i18n/sv/ARCHITECTURE.md) | 🇵🇭 [Filipino](i18n/phi/ARCHITECTURE.md)
-
-_Last updated: 2026-03-04_
+_Last updated: 2026-03-28_
## Executive Summary
@@ -69,6 +67,26 @@ Primary runtime model:
- Provider SLA/control plane outside local process
- External CLI binaries themselves (Claude CLI, Codex CLI, etc.)
+## Dashboard Surface (Current)
+
+Main pages under `src/app/(dashboard)/dashboard/`:
+
+- `/dashboard` — quick start + provider overview
+- `/dashboard/endpoint` — endpoint proxy + MCP + A2A + API endpoint tabs
+- `/dashboard/providers` — provider connections and credentials
+- `/dashboard/combos` — combo strategies, templates, model routing rules
+- `/dashboard/costs` — cost aggregation and pricing visibility
+- `/dashboard/analytics` — usage analytics and evaluations
+- `/dashboard/limits` — quota/rate controls
+- `/dashboard/cli-tools` — CLI onboarding, runtime detection, config generation
+- `/dashboard/agents` — detected ACP agents + custom agent registration
+- `/dashboard/media` — image/video/music playground
+- `/dashboard/search-tools` — search provider testing and history
+- `/dashboard/health` — uptime, circuit breakers, rate limits
+- `/dashboard/logs` — request/proxy/audit/console logs
+- `/dashboard/settings` — system settings tabs (general, routing, combo defaults, etc.)
+- `/dashboard/api-manager` — API key lifecycle and model permissions
+
## High-Level System Context
```mermaid
@@ -258,8 +276,9 @@ Domain State DB (SQLite):
## 5) Cloud Sync
-- Scheduler init: `src/lib/initCloudSync.ts`, `src/shared/services/initializeCloudSync.ts`
+- Scheduler init: `src/lib/initCloudSync.ts`, `src/shared/services/initializeCloudSync.ts`, `src/shared/services/modelSyncScheduler.ts`
- Periodic task: `src/shared/services/cloudSyncScheduler.ts`
+- Periodic task: `src/shared/services/modelSyncScheduler.ts`
- Control route: `src/app/api/sync/cloud/route.ts`
## Request Lifecycle (`/v1/chat/completions`)
@@ -339,7 +358,7 @@ flowchart TD
Q -- No --> R[Return all unavailable]
```
-Fallback decisions are driven by `open-sse/services/accountFallback.ts` using status codes and error-message heuristics.
+Fallback decisions are driven by `open-sse/services/accountFallback.ts` using status codes and error-message heuristics. Combo routing adds one extra guard: provider-scoped 400s such as upstream content-block and role-validation failures are treated as model-local failures so later combo targets can still run.
## OAuth Onboarding and Token Refresh Lifecycle
@@ -669,25 +688,25 @@ Additional processing layers in the translation pipeline:
## Supported API Endpoints
-| Endpoint | Format | Handler |
-| -------------------------------------------------- | ------------------ | ---------------------------------------------------- |
-| `POST /v1/chat/completions` | OpenAI Chat | `src/sse/handlers/chat.ts` |
-| `POST /v1/messages` | Claude Messages | Same handler (auto-detected) |
-| `POST /v1/responses` | OpenAI Responses | `open-sse/handlers/responsesHandler.ts` |
-| `POST /v1/embeddings` | OpenAI Embeddings | `open-sse/handlers/embeddings.ts` |
-| `GET /v1/embeddings` | Model listing | API route |
-| `POST /v1/images/generations` | OpenAI Images | `open-sse/handlers/imageGeneration.ts` |
-| `GET /v1/images/generations` | Model listing | API route |
-| `POST /v1/providers/{provider}/chat/completions` | OpenAI Chat | Dedicated per-provider with model validation |
-| `POST /v1/providers/{provider}/embeddings` | OpenAI Embeddings | Dedicated per-provider with model validation |
-| `POST /v1/providers/{provider}/images/generations` | OpenAI Images | Dedicated per-provider with model validation |
-| `POST /v1/messages/count_tokens` | Claude Token Count | API route |
-| `GET /v1/models` | OpenAI Models list | API route (chat + embedding + image + custom models) |
-| `GET /api/models/catalog` | Catalog | All models grouped by provider + type |
-| `POST /v1beta/models/*:streamGenerateContent` | Gemini native | API route |
-| `GET/PUT/DELETE /api/settings/proxy` | Proxy Config | Network proxy configuration |
-| `POST /api/settings/proxy/test` | Proxy Connectivity | Proxy health/connectivity test endpoint |
-| `GET/POST/DELETE /api/provider-models` | Custom Models | Custom model management per provider |
+| Endpoint | Format | Handler |
+| -------------------------------------------------- | ------------------ | ------------------------------------------------------------------- |
+| `POST /v1/chat/completions` | OpenAI Chat | `src/sse/handlers/chat.ts` |
+| `POST /v1/messages` | Claude Messages | Same handler (auto-detected) |
+| `POST /v1/responses` | OpenAI Responses | `open-sse/handlers/responsesHandler.ts` |
+| `POST /v1/embeddings` | OpenAI Embeddings | `open-sse/handlers/embeddings.ts` |
+| `GET /v1/embeddings` | Model listing | API route |
+| `POST /v1/images/generations` | OpenAI Images | `open-sse/handlers/imageGeneration.ts` |
+| `GET /v1/images/generations` | Model listing | API route |
+| `POST /v1/providers/{provider}/chat/completions` | OpenAI Chat | Dedicated per-provider with model validation |
+| `POST /v1/providers/{provider}/embeddings` | OpenAI Embeddings | Dedicated per-provider with model validation |
+| `POST /v1/providers/{provider}/images/generations` | OpenAI Images | Dedicated per-provider with model validation |
+| `POST /v1/messages/count_tokens` | Claude Token Count | API route |
+| `GET /v1/models` | OpenAI Models list | API route (chat + embedding + image + custom models) |
+| `GET /api/models/catalog` | Catalog | All models grouped by provider + type |
+| `POST /v1beta/models/*:streamGenerateContent` | Gemini native | API route |
+| `GET/PUT/DELETE /api/settings/proxy` | Proxy Config | Network proxy configuration |
+| `POST /api/settings/proxy/test` | Proxy Connectivity | Proxy health/connectivity test endpoint |
+| `GET/POST/DELETE /api/provider-models` | Provider Models | Provider model metadata backing custom and managed available models |
## Bypass Handler
@@ -739,10 +758,18 @@ Runtime visibility sources:
- console logs from `src/sse/utils/logger.ts`
- per-request usage aggregates in SQLite (`usage_history`, `call_logs`, `proxy_logs`)
+- four-stage detailed payload captures in SQLite (`request_detail_logs`) when `settings.detailed_logs_enabled=true`
- textual request status log in `log.txt` (optional/compat)
- optional deep request/translation logs under `logs/` when `ENABLE_REQUEST_LOGS=true`
- dashboard usage endpoints (`/api/usage/*`) for UI consumption
+Detailed request payload capture stores up to four JSON payload stages per routed call:
+
+- raw request received from the client
+- translated request actually sent upstream
+- provider response reconstructed as JSON; streamed responses are compacted to the final summary plus stream metadata
+- final client response returned by OmniRoute; streamed responses are stored in the same compact summary form
+
## Security-Sensitive Boundaries
- JWT secret (`JWT_SECRET`) secures dashboard session cookie verification/signing
diff --git a/docs/i18n/da/AUTO-COMBO.md b/docs/i18n/hu/docs/AUTO-COMBO.md
similarity index 65%
rename from docs/i18n/da/AUTO-COMBO.md
rename to docs/i18n/hu/docs/AUTO-COMBO.md
index 2166e41dff..7d754b6027 100644
--- a/docs/i18n/da/AUTO-COMBO.md
+++ b/docs/i18n/hu/docs/AUTO-COMBO.md
@@ -1,9 +1,9 @@
-🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/AUTO-COMBO.md) · 🇪🇸 [es](../es/AUTO-COMBO.md) · 🇫🇷 [fr](../fr/AUTO-COMBO.md) · 🇩🇪 [de](../de/AUTO-COMBO.md) · 🇮🇹 [it](../it/AUTO-COMBO.md) · 🇷🇺 [ru](../ru/AUTO-COMBO.md) · 🇨🇳 [zh-CN](../zh-CN/AUTO-COMBO.md) · 🇯🇵 [ja](../ja/AUTO-COMBO.md) · 🇰🇷 [ko](../ko/AUTO-COMBO.md) · 🇸🇦 [ar](../ar/AUTO-COMBO.md) · 🇮🇳 [in](../in/AUTO-COMBO.md) · 🇹🇭 [th](../th/AUTO-COMBO.md) · 🇻🇳 [vi](../vi/AUTO-COMBO.md) · 🇮🇩 [id](../id/AUTO-COMBO.md) · 🇲🇾 [ms](../ms/AUTO-COMBO.md) · 🇳🇱 [nl](../nl/AUTO-COMBO.md) · 🇵🇱 [pl](../pl/AUTO-COMBO.md) · 🇸🇪 [sv](../sv/AUTO-COMBO.md) · 🇳🇴 [no](../no/AUTO-COMBO.md) · 🇩🇰 [da](../da/AUTO-COMBO.md) · 🇫🇮 [fi](../fi/AUTO-COMBO.md) · 🇵🇹 [pt](../pt/AUTO-COMBO.md) · 🇷🇴 [ro](../ro/AUTO-COMBO.md) · 🇭🇺 [hu](../hu/AUTO-COMBO.md) · 🇧🇬 [bg](../bg/AUTO-COMBO.md) · 🇸🇰 [sk](../sk/AUTO-COMBO.md) · 🇺🇦 [uk-UA](../uk-UA/AUTO-COMBO.md) · 🇮🇱 [he](../he/AUTO-COMBO.md) · 🇵🇭 [phi](../phi/AUTO-COMBO.md)
+# OmniRoute Auto-Combo Engine (Magyar)
+
+🌐 **Languages:** 🇺🇸 [English](../../../../docs/AUTO-COMBO.md) · 🇪🇸 [es](../../es/docs/AUTO-COMBO.md) · 🇫🇷 [fr](../../fr/docs/AUTO-COMBO.md) · 🇩🇪 [de](../../de/docs/AUTO-COMBO.md) · 🇮🇹 [it](../../it/docs/AUTO-COMBO.md) · 🇷🇺 [ru](../../ru/docs/AUTO-COMBO.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/AUTO-COMBO.md) · 🇯🇵 [ja](../../ja/docs/AUTO-COMBO.md) · 🇰🇷 [ko](../../ko/docs/AUTO-COMBO.md) · 🇸🇦 [ar](../../ar/docs/AUTO-COMBO.md) · 🇮🇳 [in](../../in/docs/AUTO-COMBO.md) · 🇹🇭 [th](../../th/docs/AUTO-COMBO.md) · 🇻🇳 [vi](../../vi/docs/AUTO-COMBO.md) · 🇮🇩 [id](../../id/docs/AUTO-COMBO.md) · 🇲🇾 [ms](../../ms/docs/AUTO-COMBO.md) · 🇳🇱 [nl](../../nl/docs/AUTO-COMBO.md) · 🇵🇱 [pl](../../pl/docs/AUTO-COMBO.md) · 🇸🇪 [sv](../../sv/docs/AUTO-COMBO.md) · 🇳🇴 [no](../../no/docs/AUTO-COMBO.md) · 🇩🇰 [da](../../da/docs/AUTO-COMBO.md) · 🇫🇮 [fi](../../fi/docs/AUTO-COMBO.md) · 🇵🇹 [pt](../../pt/docs/AUTO-COMBO.md) · 🇷🇴 [ro](../../ro/docs/AUTO-COMBO.md) · 🇭🇺 [hu](../../hu/docs/AUTO-COMBO.md) · 🇧🇬 [bg](../../bg/docs/AUTO-COMBO.md) · 🇸🇰 [sk](../../sk/docs/AUTO-COMBO.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/AUTO-COMBO.md) · 🇮🇱 [he](../../he/docs/AUTO-COMBO.md) · 🇵🇭 [phi](../../phi/docs/AUTO-COMBO.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/AUTO-COMBO.md) · 🇨🇿 [cs](../../cs/docs/AUTO-COMBO.md)
---
-# OmniRoute Auto-Combo Engine
-
> Self-managing model chains with adaptive scoring
## How It Works
diff --git a/docs/i18n/hu/docs/CLI-TOOLS.md b/docs/i18n/hu/docs/CLI-TOOLS.md
new file mode 100644
index 0000000000..de160b39ae
--- /dev/null
+++ b/docs/i18n/hu/docs/CLI-TOOLS.md
@@ -0,0 +1,348 @@
+# CLI Tools Setup Guide — OmniRoute (Magyar)
+
+🌐 **Languages:** 🇺🇸 [English](../../../../docs/CLI-TOOLS.md) · 🇪🇸 [es](../../es/docs/CLI-TOOLS.md) · 🇫🇷 [fr](../../fr/docs/CLI-TOOLS.md) · 🇩🇪 [de](../../de/docs/CLI-TOOLS.md) · 🇮🇹 [it](../../it/docs/CLI-TOOLS.md) · 🇷🇺 [ru](../../ru/docs/CLI-TOOLS.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/CLI-TOOLS.md) · 🇯🇵 [ja](../../ja/docs/CLI-TOOLS.md) · 🇰🇷 [ko](../../ko/docs/CLI-TOOLS.md) · 🇸🇦 [ar](../../ar/docs/CLI-TOOLS.md) · 🇮🇳 [in](../../in/docs/CLI-TOOLS.md) · 🇹🇭 [th](../../th/docs/CLI-TOOLS.md) · 🇻🇳 [vi](../../vi/docs/CLI-TOOLS.md) · 🇮🇩 [id](../../id/docs/CLI-TOOLS.md) · 🇲🇾 [ms](../../ms/docs/CLI-TOOLS.md) · 🇳🇱 [nl](../../nl/docs/CLI-TOOLS.md) · 🇵🇱 [pl](../../pl/docs/CLI-TOOLS.md) · 🇸🇪 [sv](../../sv/docs/CLI-TOOLS.md) · 🇳🇴 [no](../../no/docs/CLI-TOOLS.md) · 🇩🇰 [da](../../da/docs/CLI-TOOLS.md) · 🇫🇮 [fi](../../fi/docs/CLI-TOOLS.md) · 🇵🇹 [pt](../../pt/docs/CLI-TOOLS.md) · 🇷🇴 [ro](../../ro/docs/CLI-TOOLS.md) · 🇭🇺 [hu](../../hu/docs/CLI-TOOLS.md) · 🇧🇬 [bg](../../bg/docs/CLI-TOOLS.md) · 🇸🇰 [sk](../../sk/docs/CLI-TOOLS.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/CLI-TOOLS.md) · 🇮🇱 [he](../../he/docs/CLI-TOOLS.md) · 🇵🇭 [phi](../../phi/docs/CLI-TOOLS.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/CLI-TOOLS.md) · 🇨🇿 [cs](../../cs/docs/CLI-TOOLS.md)
+
+---
+
+This guide explains how to install and configure all supported AI coding CLI tools
+to use **OmniRoute** as the unified backend, giving you centralized key management,
+cost tracking, model switching, and request logging across every tool.
+
+---
+
+## How It Works
+
+```
+Claude / Codex / OpenCode / Cline / KiloCode / Continue / Kiro / Cursor / Copilot
+ │
+ ▼ (all point to OmniRoute)
+ http://YOUR_SERVER:20128/v1
+ │
+ ▼ (OmniRoute routes to the right provider)
+ Anthropic / OpenAI / Gemini / DeepSeek / Groq / Mistral / ...
+```
+
+**Benefits:**
+
+- One API key to manage all tools
+- Cost tracking across all CLIs in the dashboard
+- Model switching without reconfiguring every tool
+- Works locally and on remote servers (VPS)
+
+---
+
+## Supported Tools (Dashboard Source of Truth)
+
+The dashboard cards in `/dashboard/cli-tools` are generated from `src/shared/constants/cliTools.ts`.
+Current list (v3.0.0-rc.16):
+
+| Tool | ID | Command | Setup Mode | Install Method |
+| ------------------ | ------------- | ---------- | ---------- | -------------- |
+| **Claude Code** | `claude` | `claude` | env | npm |
+| **OpenAI Codex** | `codex` | `codex` | custom | npm |
+| **Factory Droid** | `droid` | `droid` | custom | bundled/CLI |
+| **OpenClaw** | `openclaw` | `openclaw` | custom | bundled/CLI |
+| **Cursor** | `cursor` | app | guide | desktop app |
+| **Cline** | `cline` | `cline` | custom | npm |
+| **Kilo Code** | `kilo` | `kilocode` | custom | npm |
+| **Continue** | `continue` | extension | guide | VS Code |
+| **Antigravity** | `antigravity` | internal | mitm | OmniRoute |
+| **GitHub Copilot** | `copilot` | extension | custom | VS Code |
+| **OpenCode** | `opencode` | `opencode` | guide | npm |
+| **Kiro AI** | `kiro` | app/cli | mitm | desktop/CLI |
+
+### CLI fingerprint sync (Agents + Settings)
+
+`/dashboard/agents` and `Settings > CLI Fingerprint` use `src/shared/constants/cliCompatProviders.ts`.
+This keeps provider IDs aligned with CLI cards and legacy IDs.
+
+| CLI ID | Fingerprint Provider ID |
+| ---------------------------------------------------------------------------------------------------- | ----------------------- |
+| `kilo` | `kilocode` |
+| `copilot` | `github` |
+| `claude` / `codex` / `antigravity` / `kiro` / `cursor` / `cline` / `opencode` / `droid` / `openclaw` | same ID |
+
+Legacy IDs still accepted for compatibility: `copilot`, `kimi-coding`, `qwen`.
+
+---
+
+## Step 1 — Get an OmniRoute API Key
+
+1. Open the OmniRoute dashboard → **API Manager** (`/dashboard/api-manager`)
+2. Click **Create API Key**
+3. Give it a name (e.g. `cli-tools`) and select all permissions
+4. Copy the key — you'll need it for every CLI below
+
+> Your key looks like: `sk-xxxxxxxxxxxxxxxx-xxxxxxxxx`
+
+---
+
+## Step 2 — Install CLI Tools
+
+All npm-based tools require Node.js 18+:
+
+```bash
+# Claude Code (Anthropic)
+npm install -g @anthropic-ai/claude-code
+
+# OpenAI Codex
+npm install -g @openai/codex
+
+# OpenCode
+npm install -g opencode-ai
+
+# Cline
+npm install -g cline
+
+# KiloCode
+npm install -g kilocode
+
+# Kiro CLI (Amazon — requires curl + unzip)
+apt-get install -y unzip # on Debian/Ubuntu
+curl -fsSL https://cli.kiro.dev/install | bash
+export PATH="$HOME/.local/bin:$PATH" # add to ~/.bashrc
+```
+
+**Verify:**
+
+```bash
+claude --version # 2.x.x
+codex --version # 0.x.x
+opencode --version # x.x.x
+cline --version # 2.x.x
+kilocode --version # x.x.x (or: kilo --version)
+kiro-cli --version # 1.x.x
+```
+
+---
+
+## Step 3 — Set Global Environment Variables
+
+Add to `~/.bashrc` (or `~/.zshrc`), then run `source ~/.bashrc`:
+
+```bash
+# OmniRoute Universal Endpoint
+export OPENAI_BASE_URL="http://localhost:20128/v1"
+export OPENAI_API_KEY="sk-your-omniroute-key"
+export ANTHROPIC_BASE_URL="http://localhost:20128/v1"
+export ANTHROPIC_API_KEY="sk-your-omniroute-key"
+export GEMINI_BASE_URL="http://localhost:20128/v1"
+export GEMINI_API_KEY="sk-your-omniroute-key"
+```
+
+> For a **remote server** replace `localhost:20128` with the server IP or domain,
+> e.g. `http://192.168.0.15:20128`.
+
+---
+
+## Step 4 — Configure Each Tool
+
+### Claude Code
+
+```bash
+# Via CLI:
+claude config set --global api-base-url http://localhost:20128/v1
+
+# Or create ~/.claude/settings.json:
+mkdir -p ~/.claude && cat > ~/.claude/settings.json << EOF
+{
+ "apiBaseUrl": "http://localhost:20128/v1",
+ "apiKey": "sk-your-omniroute-key"
+}
+EOF
+```
+
+**Test:** `claude "say hello"`
+
+---
+
+### OpenAI Codex
+
+```bash
+mkdir -p ~/.codex && cat > ~/.codex/config.yaml << EOF
+model: auto
+apiKey: sk-your-omniroute-key
+apiBaseUrl: http://localhost:20128/v1
+EOF
+```
+
+**Test:** `codex "what is 2+2?"`
+
+---
+
+### OpenCode
+
+```bash
+mkdir -p ~/.config/opencode && cat > ~/.config/opencode/config.toml << EOF
+[provider.openai]
+base_url = "http://localhost:20128/v1"
+api_key = "sk-your-omniroute-key"
+EOF
+```
+
+**Test:** `opencode`
+
+---
+
+### Cline (CLI or VS Code)
+
+**CLI mode:**
+
+```bash
+mkdir -p ~/.cline/data && cat > ~/.cline/data/globalState.json << EOF
+{
+ "apiProvider": "openai",
+ "openAiBaseUrl": "http://localhost:20128/v1",
+ "openAiApiKey": "sk-your-omniroute-key"
+}
+EOF
+```
+
+**VS Code mode:**
+Cline extension settings → API Provider: `OpenAI Compatible` → Base URL: `http://localhost:20128/v1`
+
+Or use the OmniRoute dashboard → **CLI Tools → Cline → Apply Config**.
+
+---
+
+### KiloCode (CLI or VS Code)
+
+**CLI mode:**
+
+```bash
+kilocode --api-base http://localhost:20128/v1 --api-key sk-your-omniroute-key
+```
+
+**VS Code settings:**
+
+```json
+{
+ "kilo-code.openAiBaseUrl": "http://localhost:20128/v1",
+ "kilo-code.apiKey": "sk-your-omniroute-key"
+}
+```
+
+Or use the OmniRoute dashboard → **CLI Tools → KiloCode → Apply Config**.
+
+---
+
+### Continue (VS Code Extension)
+
+Edit `~/.continue/config.yaml`:
+
+```yaml
+models:
+ - name: OmniRoute
+ provider: openai
+ model: auto
+ apiBase: http://localhost:20128/v1
+ apiKey: sk-your-omniroute-key
+ default: true
+```
+
+Restart VS Code after editing.
+
+---
+
+### Kiro CLI (Amazon)
+
+```bash
+# Login to your AWS/Kiro account:
+kiro-cli login
+
+# The CLI uses its own auth — OmniRoute is not needed as backend for Kiro CLI itself.
+# Use kiro-cli alongside OmniRoute for other tools.
+kiro-cli status
+```
+
+---
+
+### Cursor (Desktop App)
+
+> **Note:** Cursor routes requests through its cloud. For OmniRoute integration,
+> enable **Cloud Endpoint** in OmniRoute Settings and use your public domain URL.
+
+Via GUI: **Settings → Models → OpenAI API Key**
+
+- Base URL: `https://your-domain.com/v1`
+- API Key: your OmniRoute key
+
+---
+
+## Dashboard Auto-Configuration
+
+The OmniRoute dashboard automates configuration for most tools:
+
+1. Go to `http://localhost:20128/dashboard/cli-tools`
+2. Expand any tool card
+3. Select your API key from the dropdown
+4. Click **Apply Config** (if tool is detected as installed)
+5. Or copy the generated config snippet manually
+
+---
+
+## Built-in Agents: Droid & OpenClaw
+
+**Droid** and **OpenClaw** are AI agents built directly into OmniRoute — no installation needed.
+They run as internal routes and use OmniRoute's model routing automatically.
+
+- Access: `http://localhost:20128/dashboard/agents`
+- Configure: same combos and providers as all other tools
+- No API key or CLI install required
+
+---
+
+## Available API Endpoints
+
+| Endpoint | Description | Use For |
+| -------------------------- | ----------------------------- | --------------------------- |
+| `/v1/chat/completions` | Standard chat (all providers) | All modern tools |
+| `/v1/responses` | Responses API (OpenAI format) | Codex, agentic workflows |
+| `/v1/completions` | Legacy text completions | Older tools using `prompt:` |
+| `/v1/embeddings` | Text embeddings | RAG, search |
+| `/v1/images/generations` | Image generation | DALL-E, Flux, etc. |
+| `/v1/audio/speech` | Text-to-speech | ElevenLabs, OpenAI TTS |
+| `/v1/audio/transcriptions` | Speech-to-text | Deepgram, AssemblyAI |
+
+---
+
+## Hibaelhárítás
+
+| Error | Cause | Fix |
+| ------------------------- | ----------------------- | ------------------------------------------ |
+| `Connection refused` | OmniRoute not running | `pm2 start omniroute` |
+| `401 Unauthorized` | Wrong API key | Check in `/dashboard/api-manager` |
+| `No combo configured` | No active routing combo | Set up in `/dashboard/combos` |
+| `invalid model` | Model not in catalog | Use `auto` or check `/dashboard/providers` |
+| CLI shows "not installed" | Binary not in PATH | Check `which ` |
+| `kiro-cli: not found` | Not in PATH | `export PATH="$HOME/.local/bin:$PATH"` |
+
+---
+
+## Quick Setup Script (One Command)
+
+```bash
+# Install all CLIs and configure for OmniRoute (replace with your key and server URL)
+OMNIROUTE_URL="http://localhost:20128/v1"
+OMNIROUTE_KEY="sk-your-omniroute-key"
+
+npm install -g @anthropic-ai/claude-code @openai/codex opencode-ai cline kilocode
+
+# Kiro CLI
+apt-get install -y unzip 2>/dev/null; curl -fsSL https://cli.kiro.dev/install | bash
+
+# Write configs
+mkdir -p ~/.claude ~/.codex ~/.config/opencode ~/.continue
+
+cat > ~/.claude/settings.json <<< "{\"apiBaseUrl\":\"$OMNIROUTE_URL\",\"apiKey\":\"$OMNIROUTE_KEY\"}"
+cat > ~/.codex/config.yaml <<< "model: auto\napiKey: $OMNIROUTE_KEY\napiBaseUrl: $OMNIROUTE_URL"
+cat >> ~/.bashrc << EOF
+export OPENAI_BASE_URL="$OMNIROUTE_URL"
+export OPENAI_API_KEY="$OMNIROUTE_KEY"
+export ANTHROPIC_BASE_URL="$OMNIROUTE_URL"
+export ANTHROPIC_API_KEY="$OMNIROUTE_KEY"
+EOF
+
+source ~/.bashrc
+echo "✅ All CLIs installed and configured for OmniRoute"
+```
diff --git a/docs/i18n/hu/docs/CODEBASE_DOCUMENTATION.md b/docs/i18n/hu/docs/CODEBASE_DOCUMENTATION.md
new file mode 100644
index 0000000000..ccb188ac92
--- /dev/null
+++ b/docs/i18n/hu/docs/CODEBASE_DOCUMENTATION.md
@@ -0,0 +1,591 @@
+# omniroute — Codebase Documentation (Magyar)
+
+🌐 **Languages:** 🇺🇸 [English](../../../../docs/CODEBASE_DOCUMENTATION.md) · 🇪🇸 [es](../../es/docs/CODEBASE_DOCUMENTATION.md) · 🇫🇷 [fr](../../fr/docs/CODEBASE_DOCUMENTATION.md) · 🇩🇪 [de](../../de/docs/CODEBASE_DOCUMENTATION.md) · 🇮🇹 [it](../../it/docs/CODEBASE_DOCUMENTATION.md) · 🇷🇺 [ru](../../ru/docs/CODEBASE_DOCUMENTATION.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/CODEBASE_DOCUMENTATION.md) · 🇯🇵 [ja](../../ja/docs/CODEBASE_DOCUMENTATION.md) · 🇰🇷 [ko](../../ko/docs/CODEBASE_DOCUMENTATION.md) · 🇸🇦 [ar](../../ar/docs/CODEBASE_DOCUMENTATION.md) · 🇮🇳 [in](../../in/docs/CODEBASE_DOCUMENTATION.md) · 🇹🇭 [th](../../th/docs/CODEBASE_DOCUMENTATION.md) · 🇻🇳 [vi](../../vi/docs/CODEBASE_DOCUMENTATION.md) · 🇮🇩 [id](../../id/docs/CODEBASE_DOCUMENTATION.md) · 🇲🇾 [ms](../../ms/docs/CODEBASE_DOCUMENTATION.md) · 🇳🇱 [nl](../../nl/docs/CODEBASE_DOCUMENTATION.md) · 🇵🇱 [pl](../../pl/docs/CODEBASE_DOCUMENTATION.md) · 🇸🇪 [sv](../../sv/docs/CODEBASE_DOCUMENTATION.md) · 🇳🇴 [no](../../no/docs/CODEBASE_DOCUMENTATION.md) · 🇩🇰 [da](../../da/docs/CODEBASE_DOCUMENTATION.md) · 🇫🇮 [fi](../../fi/docs/CODEBASE_DOCUMENTATION.md) · 🇵🇹 [pt](../../pt/docs/CODEBASE_DOCUMENTATION.md) · 🇷🇴 [ro](../../ro/docs/CODEBASE_DOCUMENTATION.md) · 🇭🇺 [hu](../../hu/docs/CODEBASE_DOCUMENTATION.md) · 🇧🇬 [bg](../../bg/docs/CODEBASE_DOCUMENTATION.md) · 🇸🇰 [sk](../../sk/docs/CODEBASE_DOCUMENTATION.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/CODEBASE_DOCUMENTATION.md) · 🇮🇱 [he](../../he/docs/CODEBASE_DOCUMENTATION.md) · 🇵🇭 [phi](../../phi/docs/CODEBASE_DOCUMENTATION.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/CODEBASE_DOCUMENTATION.md) · 🇨🇿 [cs](../../cs/docs/CODEBASE_DOCUMENTATION.md)
+
+---
+
+> A comprehensive, beginner-friendly guide to the **omniroute** multi-provider AI proxy router.
+
+---
+
+## 1. What Is omniroute?
+
+omniroute is a **proxy router** that sits between AI clients (Claude CLI, Codex, Cursor IDE, etc.) and AI providers (Anthropic, Google, OpenAI, AWS, GitHub, etc.). It solves one big problem:
+
+> **Different AI clients speak different "languages" (API formats), and different AI providers expect different "languages" too.** omniroute translates between them automatically.
+
+Think of it like a universal translator at the United Nations — any delegate can speak any language, and the translator converts it for any other delegate.
+
+---
+
+## 2. Architecture Overview
+
+```mermaid
+graph LR
+ subgraph Clients
+ A[Claude CLI]
+ B[Codex]
+ C[Cursor IDE]
+ D[OpenAI-compatible]
+ end
+
+ subgraph omniroute
+ E[Handler Layer]
+ F[Translator Layer]
+ G[Executor Layer]
+ H[Services Layer]
+ end
+
+ subgraph Providers
+ I[Anthropic Claude]
+ J[Google Gemini]
+ K[OpenAI / Codex]
+ L[GitHub Copilot]
+ M[AWS Kiro]
+ N[Antigravity]
+ O[Cursor API]
+ end
+
+ A --> E
+ B --> E
+ C --> E
+ D --> E
+ E --> F
+ F --> G
+ G --> I
+ G --> J
+ G --> K
+ G --> L
+ G --> M
+ G --> N
+ G --> O
+ H -.-> E
+ H -.-> G
+```
+
+### Core Principle: Hub-and-Spoke Translation
+
+All format translation passes through **OpenAI format as the hub**:
+
+```
+Client Format → [OpenAI Hub] → Provider Format (request)
+Provider Format → [OpenAI Hub] → Client Format (response)
+```
+
+This means you only need **N translators** (one per format) instead of **N²** (every pair).
+
+---
+
+## 3. Project Structure
+
+```
+omniroute/
+├── open-sse/ ← Core proxy library (portable, framework-agnostic)
+│ ├── index.js ← Main entry point, exports everything
+│ ├── config/ ← Configuration & constants
+│ ├── executors/ ← Provider-specific request execution
+│ ├── handlers/ ← Request handling orchestration
+│ ├── services/ ← Business logic (auth, models, fallback, usage)
+│ ├── translator/ ← Format translation engine
+│ │ ├── request/ ← Request translators (8 files)
+│ │ ├── response/ ← Response translators (7 files)
+│ │ └── helpers/ ← Shared translation utilities (6 files)
+│ └── utils/ ← Utility functions
+├── src/ ← Application layer (Express/Worker runtime)
+│ ├── app/ ← Web UI, API routes, middleware
+│ ├── lib/ ← Database, auth, and shared library code
+│ ├── mitm/ ← Man-in-the-middle proxy utilities
+│ ├── models/ ← Database models
+│ ├── shared/ ← Shared utilities (wrappers around open-sse)
+│ ├── sse/ ← SSE endpoint handlers
+│ └── store/ ← State management
+├── data/ ← Runtime data (credentials, logs)
+│ └── provider-credentials.json (external credentials override, gitignored)
+└── tester/ ← Test utilities
+```
+
+---
+
+## 4. Module-by-Module Breakdown
+
+### 4.1 Config (`open-sse/config/`)
+
+The **single source of truth** for all provider configuration.
+
+| File | Purpose |
+| ----------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| `constants.ts` | `PROVIDERS` object with base URLs, OAuth credentials (defaults), headers, and default system prompts for every provider. Also defines `HTTP_STATUS`, `ERROR_TYPES`, `COOLDOWN_MS`, `BACKOFF_CONFIG`, and `SKIP_PATTERNS`. |
+| `credentialLoader.ts` | Loads external credentials from `data/provider-credentials.json` and merges them over the hardcoded defaults in `PROVIDERS`. Keeps secrets out of source control while maintaining backwards compatibility. |
+| `providerModels.ts` | Central model registry: maps provider aliases → model IDs. Functions like `getModels()`, `getProviderByAlias()`. |
+| `codexInstructions.ts` | System instructions injected into Codex requests (editing constraints, sandbox rules, approval policies). |
+| `defaultThinkingSignature.ts` | Default "thinking" signatures for Claude and Gemini models. |
+| `ollamaModels.ts` | Schema definition for local Ollama models (name, size, family, quantization). |
+
+#### Credential Loading Flow
+
+```mermaid
+flowchart TD
+ A["App starts"] --> B["constants.ts defines PROVIDERS\nwith hardcoded defaults"]
+ B --> C{"data/provider-credentials.json\nexists?"}
+ C -->|Yes| D["credentialLoader reads JSON"]
+ C -->|No| E["Use hardcoded defaults"]
+ D --> F{"For each provider in JSON"}
+ F --> G{"Provider exists\nin PROVIDERS?"}
+ G -->|No| H["Log warning, skip"]
+ G -->|Yes| I{"Value is object?"}
+ I -->|No| J["Log warning, skip"]
+ I -->|Yes| K["Merge clientId, clientSecret,\ntokenUrl, authUrl, refreshUrl"]
+ K --> F
+ H --> F
+ J --> F
+ F -->|Done| L["PROVIDERS ready with\nmerged credentials"]
+ E --> L
+```
+
+---
+
+### 4.2 Executors (`open-sse/executors/`)
+
+Executors encapsulate **provider-specific logic** using the **Strategy Pattern**. Each executor overrides base methods as needed.
+
+```mermaid
+classDiagram
+ class BaseExecutor {
+ +buildUrl(model, stream, options)
+ +buildHeaders(credentials, stream, body)
+ +transformRequest(body, model, stream, credentials)
+ +execute(url, options)
+ +shouldRetry(status, error)
+ +refreshCredentials(credentials, log)
+ }
+
+ class DefaultExecutor {
+ +refreshCredentials()
+ }
+
+ class AntigravityExecutor {
+ +buildUrl()
+ +buildHeaders()
+ +transformRequest()
+ +shouldRetry()
+ +refreshCredentials()
+ }
+
+ class CursorExecutor {
+ +buildUrl()
+ +buildHeaders()
+ +transformRequest()
+ +parseResponse()
+ +generateChecksum()
+ }
+
+ class KiroExecutor {
+ +buildUrl()
+ +buildHeaders()
+ +transformRequest()
+ +parseEventStream()
+ +refreshCredentials()
+ }
+
+ BaseExecutor <|-- DefaultExecutor
+ BaseExecutor <|-- AntigravityExecutor
+ BaseExecutor <|-- CursorExecutor
+ BaseExecutor <|-- KiroExecutor
+ BaseExecutor <|-- CodexExecutor
+ BaseExecutor <|-- GeminiCLIExecutor
+ BaseExecutor <|-- GithubExecutor
+```
+
+| Executor | Provider | Key Specializations |
+| ---------------- | ------------------------------------------ | ------------------------------------------------------------------------------------------------------------------- |
+| `base.ts` | — | Abstract base: URL building, headers, retry logic, credential refresh |
+| `default.ts` | Claude, Gemini, OpenAI, GLM, Kimi, MiniMax | Generic OAuth token refresh for standard providers |
+| `antigravity.ts` | Google Cloud Code | Project/session ID generation, multi-URL fallback, custom retry parsing from error messages ("reset after 2h7m23s") |
+| `cursor.ts` | Cursor IDE | **Most complex**: SHA-256 checksum auth, Protobuf request encoding, binary EventStream → SSE response parsing |
+| `codex.ts` | OpenAI Codex | Injects system instructions, manages thinking levels, removes unsupported parameters |
+| `gemini-cli.ts` | Google Gemini CLI | Custom URL building (`streamGenerateContent`), Google OAuth token refresh |
+| `github.ts` | GitHub Copilot | Dual token system (GitHub OAuth + Copilot token), VSCode header mimicking |
+| `kiro.ts` | AWS CodeWhisperer | AWS EventStream binary parsing, AMZN event frames, token estimation |
+| `index.ts` | — | Factory: maps provider name → executor class, with default fallback |
+
+---
+
+### 4.3 Handlers (`open-sse/handlers/`)
+
+The **orchestration layer** — coordinates translation, execution, streaming, and error handling.
+
+| File | Purpose |
+| --------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| `chatCore.ts` | **Central orchestrator** (~600 lines). Handles the complete request lifecycle: format detection → translation → executor dispatch → streaming/non-streaming response → token refresh → error handling → usage logging. |
+| `responsesHandler.ts` | Adapter for OpenAI's Responses API: converts Responses format → Chat Completions → sends to `chatCore` → converts SSE back to Responses format. |
+| `embeddings.ts` | Embedding generation handler: resolves embedding model → provider, dispatches to provider API, returns OpenAI-compatible embedding response. Supports 6+ providers. |
+| `imageGeneration.ts` | Image generation handler: resolves image model → provider, supports OpenAI-compatible, Gemini-image (Antigravity), and fallback (Nebius) modes. Returns base64 or URL images. |
+
+#### Request Lifecycle (chatCore.ts)
+
+```mermaid
+sequenceDiagram
+ participant Client
+ participant chatCore
+ participant Translator
+ participant Executor
+ participant Provider
+
+ Client->>chatCore: Request (any format)
+ chatCore->>chatCore: Detect source format
+ chatCore->>chatCore: Check bypass patterns
+ chatCore->>chatCore: Resolve model & provider
+ chatCore->>Translator: Translate request (source → OpenAI → target)
+ chatCore->>Executor: Get executor for provider
+ Executor->>Executor: Build URL, headers, transform request
+ Executor->>Executor: Refresh credentials if needed
+ Executor->>Provider: HTTP fetch (streaming or non-streaming)
+
+ alt Streaming
+ Provider-->>chatCore: SSE stream
+ chatCore->>chatCore: Pipe through SSE transform stream
+ Note over chatCore: Transform stream translates
each chunk: target → OpenAI → source
+ chatCore-->>Client: Translated SSE stream
+ else Non-streaming
+ Provider-->>chatCore: JSON response
+ chatCore->>Translator: Translate response
+ chatCore-->>Client: Translated JSON
+ end
+
+ alt Error (401, 429, 500...)
+ chatCore->>Executor: Retry with credential refresh
+ chatCore->>chatCore: Account fallback logic
+ end
+```
+
+---
+
+### 4.4 Services (`open-sse/services/`)
+
+Business logic that supports the handlers and executors.
+
+| File | Purpose |
+| -------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| `provider.ts` | **Format detection** (`detectFormat`): analyzes request body structure to identify Claude/OpenAI/Gemini/Antigravity/Responses formats (includes `max_tokens` heuristic for Claude). Also: URL building, header building, thinking config normalization. Supports `openai-compatible-*` and `anthropic-compatible-*` dynamic providers. |
+| `model.ts` | Model string parsing (`claude/model-name` → `{provider: "claude", model: "model-name"}`), alias resolution with collision detection, input sanitization (rejects path traversal/control chars), and model info resolution with async alias getter support. |
+| `accountFallback.ts` | Rate-limit handling: exponential backoff (1s → 2s → 4s → max 2min), account cooldown management, error classification (which errors trigger fallback vs. not). |
+| `tokenRefresh.ts` | OAuth token refresh for **every provider**: Google (Gemini, Antigravity), Claude, Codex, Qwen, Qoder, GitHub (OAuth + Copilot dual-token), Kiro (AWS SSO OIDC + Social Auth). Includes in-flight promise deduplication cache and retry with exponential backoff. |
+| `combo.ts` | **Combo models**: chains of fallback models. If model A fails with a fallback-eligible error, try model B, then C, etc. Returns actual upstream status codes. |
+| `usage.ts` | Fetches quota/usage data from provider APIs (GitHub Copilot quotas, Antigravity model quotas, Codex rate limits, Kiro usage breakdowns, Claude settings). |
+| `accountSelector.ts` | Smart account selection with scoring algorithm: considers priority, health status, round-robin position, and cooldown state to pick the optimal account for each request. |
+| `contextManager.ts` | Request context lifecycle management: creates and tracks per-request context objects with metadata (request ID, timestamps, provider info) for debugging and logging. |
+| `ipFilter.ts` | IP-based access control: supports allowlist and blocklist modes. Validates client IP against configured rules before processing API requests. |
+| `sessionManager.ts` | Session tracking with client fingerprinting: tracks active sessions using hashed client identifiers, monitors request counts, and provides session metrics. |
+| `signatureCache.ts` | Request signature-based deduplication cache: prevents duplicate requests by caching recent request signatures and returning cached responses for identical requests within a time window. |
+| `systemPrompt.ts` | Global system prompt injection: prepends or appends a configurable system prompt to all requests, with per-provider compatibility handling. |
+| `thinkingBudget.ts` | Reasoning token budget management: supports passthrough, auto (strip thinking config), custom (fixed budget), and adaptive (complexity-scaled) modes for controlling thinking/reasoning tokens. |
+| `wildcardRouter.ts` | Wildcard model pattern routing: resolves wildcard patterns (e.g., `*/claude-*`) to concrete provider/model pairs based on availability and priority. |
+
+#### Token Refresh Deduplication
+
+```mermaid
+sequenceDiagram
+ participant R1 as Request 1
+ participant R2 as Request 2
+ participant Cache as refreshPromiseCache
+ participant OAuth as OAuth Provider
+
+ R1->>Cache: getAccessToken("gemini", token)
+ Cache->>Cache: No in-flight promise
+ Cache->>OAuth: Start refresh
+ R2->>Cache: getAccessToken("gemini", token)
+ Cache->>Cache: Found in-flight promise
+ Cache-->>R2: Return existing promise
+ OAuth-->>Cache: New access token
+ Cache-->>R1: New access token
+ Cache-->>R2: Same access token (shared)
+ Cache->>Cache: Delete cache entry
+```
+
+#### Account Fallback State Machine
+
+```mermaid
+stateDiagram-v2
+ [*] --> Active
+ Active --> Error: Request fails (401/429/500)
+ Error --> Cooldown: Apply backoff
+ Cooldown --> Active: Cooldown expires
+ Active --> Active: Request succeeds (reset backoff)
+
+ state Error {
+ [*] --> ClassifyError
+ ClassifyError --> ShouldFallback: Rate limit / Auth / Transient
+ ClassifyError --> NoFallback: 400 Bad Request
+ }
+
+ state Cooldown {
+ [*] --> ExponentialBackoff
+ ExponentialBackoff: Level 0 = 1s
+ ExponentialBackoff: Level 1 = 2s
+ ExponentialBackoff: Level 2 = 4s
+ ExponentialBackoff: Max = 2min
+ }
+```
+
+#### Combo Model Chain
+
+```mermaid
+flowchart LR
+ A["Request with\ncombo model"] --> B["Model A"]
+ B -->|"2xx Success"| C["Return response"]
+ B -->|"429/401/500"| D{"Fallback\neligible?"}
+ D -->|Yes| E["Model B"]
+ D -->|No| F["Return error"]
+ E -->|"2xx Success"| C
+ E -->|"429/401/500"| G{"Fallback\neligible?"}
+ G -->|Yes| H["Model C"]
+ G -->|No| F
+ H -->|"2xx Success"| C
+ H -->|"Fail"| I["All failed →\nReturn last status"]
+```
+
+---
+
+### 4.5 Translator (`open-sse/translator/`)
+
+The **format translation engine** using a self-registering plugin system.
+
+#### Architektúra
+
+```mermaid
+graph TD
+ subgraph "Request Translation"
+ A["Claude → OpenAI"]
+ B["Gemini → OpenAI"]
+ C["Antigravity → OpenAI"]
+ D["OpenAI Responses → OpenAI"]
+ E["OpenAI → Claude"]
+ F["OpenAI → Gemini"]
+ G["OpenAI → Kiro"]
+ H["OpenAI → Cursor"]
+ end
+
+ subgraph "Response Translation"
+ I["Claude → OpenAI"]
+ J["Gemini → OpenAI"]
+ K["Kiro → OpenAI"]
+ L["Cursor → OpenAI"]
+ M["OpenAI → Claude"]
+ N["OpenAI → Antigravity"]
+ O["OpenAI → Responses"]
+ end
+```
+
+| Directory | Files | Description |
+| ------------ | ------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| `request/` | 8 translators | Convert request bodies between formats. Each file self-registers via `register(from, to, fn)` on import. |
+| `response/` | 7 translators | Convert streaming response chunks between formats. Handles SSE event types, thinking blocks, tool calls. |
+| `helpers/` | 6 helpers | Shared utilities: `claudeHelper` (system prompt extraction, thinking config), `geminiHelper` (parts/contents mapping), `openaiHelper` (format filtering), `toolCallHelper` (ID generation, missing response injection), `maxTokensHelper`, `responsesApiHelper`. |
+| `index.ts` | — | Translation engine: `translateRequest()`, `translateResponse()`, state management, registry. |
+| `formats.ts` | — | Format constants: `OPENAI`, `CLAUDE`, `GEMINI`, `ANTIGRAVITY`, `KIRO`, `CURSOR`, `OPENAI_RESPONSES`. |
+
+#### Key Design: Self-Registering Plugins
+
+```javascript
+// Each translator file calls register() on import:
+import { register } from "../index.js";
+register("claude", "openai", translateClaudeToOpenAI);
+
+// The index.js imports all translator files, triggering registration:
+import "./request/claude-to-openai.js"; // ← self-registers
+```
+
+---
+
+### 4.6 Utils (`open-sse/utils/`)
+
+| File | Purpose |
+| ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
+| `error.ts` | Error response building (OpenAI-compatible format), upstream error parsing, Antigravity retry-time extraction from error messages, SSE error streaming. |
+| `stream.ts` | **SSE Transform Stream** — the core streaming pipeline. Two modes: `TRANSLATE` (full format translation) and `PASSTHROUGH` (normalize + extract usage). Handles chunk buffering, usage estimation, content length tracking. Per-stream encoder/decoder instances avoid shared state. |
+| `streamHelpers.ts` | Low-level SSE utilities: `parseSSELine` (whitespace-tolerant), `hasValuableContent` (filters empty chunks for OpenAI/Claude/Gemini), `fixInvalidId`, `formatSSE` (format-aware SSE serialization with `perf_metrics` cleanup). |
+| `usageTracking.ts` | Token usage extraction from any format (Claude/OpenAI/Gemini/Responses), estimation with separate tool/message char-per-token ratios, buffer addition (2000 tokens safety margin), format-specific field filtering, console logging with ANSI colors. |
+| `requestLogger.ts` | File-based request logging (opt-in via `ENABLE_REQUEST_LOGS=true`). Creates session folders with numbered files: `1_req_client.json` → `7_res_client.txt`. All I/O is async (fire-and-forget). Masks sensitive headers. |
+| `bypassHandler.ts` | Intercepts specific patterns from Claude CLI (title extraction, warmup, count) and returns fake responses without calling any provider. Supports both streaming and non-streaming. Intentionally limited to Claude CLI scope. |
+| `networkProxy.ts` | Resolves outbound proxy URL for a given provider with precedence: provider-specific config → global config → environment variables (`HTTPS_PROXY`/`HTTP_PROXY`/`ALL_PROXY`). Supports `NO_PROXY` exclusions. Caches config for 30s. |
+
+#### SSE Streaming Pipeline
+
+```mermaid
+flowchart TD
+ A["Provider SSE stream"] --> B["TextDecoder\n(per-stream instance)"]
+ B --> C["Buffer lines\n(split on newline)"]
+ C --> D["parseSSELine()\n(trim whitespace, parse JSON)"]
+ D --> E{"Mode?"}
+ E -->|TRANSLATE| F["translateResponse()\ntarget → OpenAI → source"]
+ E -->|PASSTHROUGH| G["fixInvalidId()\nnormalize chunk"]
+ F --> H["hasValuableContent()\nfilter empty chunks"]
+ G --> H
+ H -->|"Has content"| I["extractUsage()\ntrack token counts"]
+ H -->|"Empty"| J["Skip chunk"]
+ I --> K["formatSSE()\nserialize + clean perf_metrics"]
+ K --> L["TextEncoder\n(per-stream instance)"]
+ L --> M["Enqueue to\nclient stream"]
+
+ style A fill:#f9f,stroke:#333
+ style M fill:#9f9,stroke:#333
+```
+
+#### Request Logger Session Structure
+
+```
+logs/
+└── claude_gemini_claude-sonnet_20260208_143045/
+ ├── 1_req_client.json ← Raw client request
+ ├── 2_req_source.json ← After initial conversion
+ ├── 3_req_openai.json ← OpenAI intermediate format
+ ├── 4_req_target.json ← Final target format
+ ├── 5_res_provider.txt ← Provider SSE chunks (streaming)
+ ├── 5_res_provider.json ← Provider response (non-streaming)
+ ├── 6_res_openai.txt ← OpenAI intermediate chunks
+ ├── 7_res_client.txt ← Client-facing SSE chunks
+ └── 6_error.json ← Error details (if any)
+```
+
+---
+
+### 4.7 Application Layer (`src/`)
+
+| Directory | Purpose |
+| ------------- | ---------------------------------------------------------------------- |
+| `src/app/` | Web UI, API routes, Express middleware, OAuth callback handlers |
+| `src/lib/` | Database access (`localDb.ts`, `usageDb.ts`), authentication, shared |
+| `src/mitm/` | Man-in-the-middle proxy utilities for intercepting provider traffic |
+| `src/models/` | Database model definitions |
+| `src/shared/` | Wrappers around open-sse functions (provider, stream, error, etc.) |
+| `src/sse/` | SSE endpoint handlers that wire the open-sse library to Express routes |
+| `src/store/` | Application state management |
+
+#### Notable API Routes
+
+| Route | Methods | Purpose |
+| --------------------------------------------- | --------------- | ------------------------------------------------------------------------------------- |
+| `/api/provider-models` | GET/POST/DELETE | CRUD for custom models per provider |
+| `/api/models/catalog` | GET | Aggregated catalog of all models (chat, embedding, image, custom) grouped by provider |
+| `/api/settings/proxy` | GET/PUT/DELETE | Hierarchical outbound proxy configuration (`global/providers/combos/keys`) |
+| `/api/settings/proxy/test` | POST | Validates proxy connectivity and returns public IP/latency |
+| `/v1/providers/[provider]/chat/completions` | POST | Dedicated per-provider chat completions with model validation |
+| `/v1/providers/[provider]/embeddings` | POST | Dedicated per-provider embeddings with model validation |
+| `/v1/providers/[provider]/images/generations` | POST | Dedicated per-provider image generation with model validation |
+| `/api/settings/ip-filter` | GET/PUT | IP allowlist/blocklist management |
+| `/api/settings/thinking-budget` | GET/PUT | Reasoning token budget configuration (passthrough/auto/custom/adaptive) |
+| `/api/settings/system-prompt` | GET/PUT | Global system prompt injection for all requests |
+| `/api/sessions` | GET | Active session tracking and metrics |
+| `/api/rate-limits` | GET | Per-account rate limit status |
+
+---
+
+## 5. Key Design Patterns
+
+### 5.1 Hub-and-Spoke Translation
+
+All formats translate through **OpenAI format as the hub**. Adding a new provider only requires writing **one pair** of translators (to/from OpenAI), not N pairs.
+
+### 5.2 Executor Strategy Pattern
+
+Each provider has a dedicated executor class inheriting from `BaseExecutor`. The factory in `executors/index.ts` selects the right one at runtime.
+
+### 5.3 Self-Registering Plugin System
+
+Translator modules register themselves on import via `register()`. Adding a new translator is just creating a file and importing it.
+
+### 5.4 Account Fallback with Exponential Backoff
+
+When a provider returns 429/401/500, the system can switch to the next account, applying exponential cooldowns (1s → 2s → 4s → max 2min).
+
+### 5.5 Combo Model Chains
+
+A "combo" groups multiple `provider/model` strings. If the first fails, fallback to the next automatically.
+
+### 5.6 Stateful Streaming Translation
+
+Response translation maintains state across SSE chunks (thinking block tracking, tool call accumulation, content block indexing) via the `initState()` mechanism.
+
+### 5.7 Usage Safety Buffer
+
+A 2000-token buffer is added to reported usage to prevent clients from hitting context window limits due to overhead from system prompts and format translation.
+
+---
+
+## 6. Supported Formats
+
+| Format | Direction | Identifier |
+| ----------------------- | --------------- | ------------------ |
+| OpenAI Chat Completions | source + target | `openai` |
+| OpenAI Responses API | source + target | `openai-responses` |
+| Anthropic Claude | source + target | `claude` |
+| Google Gemini | source + target | `gemini` |
+| Google Gemini CLI | target only | `gemini-cli` |
+| Antigravity | source + target | `antigravity` |
+| AWS Kiro | target only | `kiro` |
+| Cursor | target only | `cursor` |
+
+---
+
+## 7. Supported Providers
+
+| Provider | Auth Method | Executor | Key Notes |
+| ------------------------ | ---------------------- | ----------- | --------------------------------------------- |
+| Anthropic Claude | API key or OAuth | Default | Uses `x-api-key` header |
+| Google Gemini | API key or OAuth | Default | Uses `x-goog-api-key` header |
+| Google Gemini CLI | OAuth | GeminiCLI | Uses `streamGenerateContent` endpoint |
+| Antigravity | OAuth | Antigravity | Multi-URL fallback, custom retry parsing |
+| OpenAI | API key | Default | Standard Bearer auth |
+| Codex | OAuth | Codex | Injects system instructions, manages thinking |
+| GitHub Copilot | OAuth + Copilot token | Github | Dual token, VSCode header mimicking |
+| Kiro (AWS) | AWS SSO OIDC or Social | Kiro | Binary EventStream parsing |
+| Cursor IDE | Checksum auth | Cursor | Protobuf encoding, SHA-256 checksums |
+| Qwen | OAuth | Default | Standard auth |
+| Qoder | OAuth (Basic + Bearer) | Default | Dual auth header |
+| OpenRouter | API key | Default | Standard Bearer auth |
+| GLM, Kimi, MiniMax | API key | Default | Claude-compatible, use `x-api-key` |
+| `openai-compatible-*` | API key | Default | Dynamic: any OpenAI-compatible endpoint |
+| `anthropic-compatible-*` | API key | Default | Dynamic: any Claude-compatible endpoint |
+
+---
+
+## 8. Data Flow Summary
+
+### Streaming Request
+
+```mermaid
+flowchart LR
+ A["Client"] --> B["detectFormat()"]
+ B --> C["translateRequest()\nsource → OpenAI → target"]
+ C --> D["Executor\nbuildUrl + buildHeaders"]
+ D --> E["fetch(providerURL)"]
+ E --> F["createSSEStream()\nTRANSLATE mode"]
+ F --> G["parseSSELine()"]
+ G --> H["translateResponse()\ntarget → OpenAI → source"]
+ H --> I["extractUsage()\n+ addBuffer"]
+ I --> J["formatSSE()"]
+ J --> K["Client receives\ntranslated SSE"]
+ K --> L["logUsage()\nsaveRequestUsage()"]
+```
+
+### Non-Streaming Request
+
+```mermaid
+flowchart LR
+ A["Client"] --> B["detectFormat()"]
+ B --> C["translateRequest()\nsource → OpenAI → target"]
+ C --> D["Executor.execute()"]
+ D --> E["translateResponse()\ntarget → OpenAI → source"]
+ E --> F["Return JSON\nresponse"]
+```
+
+### Bypass Flow (Claude CLI)
+
+```mermaid
+flowchart LR
+ A["Claude CLI request"] --> B{"Match bypass\npattern?"}
+ B -->|"Title/Warmup/Count"| C["Generate fake\nOpenAI response"]
+ B -->|"No match"| D["Normal flow"]
+ C --> E["Translate to\nsource format"]
+ E --> F["Return without\ncalling provider"]
+```
diff --git a/docs/i18n/hu/docs/COVERAGE_PLAN.md b/docs/i18n/hu/docs/COVERAGE_PLAN.md
new file mode 100644
index 0000000000..617d5d6da1
--- /dev/null
+++ b/docs/i18n/hu/docs/COVERAGE_PLAN.md
@@ -0,0 +1,170 @@
+# Test Coverage Plan (Magyar)
+
+🌐 **Languages:** 🇺🇸 [English](../../../../docs/COVERAGE_PLAN.md) · 🇪🇸 [es](../../es/docs/COVERAGE_PLAN.md) · 🇫🇷 [fr](../../fr/docs/COVERAGE_PLAN.md) · 🇩🇪 [de](../../de/docs/COVERAGE_PLAN.md) · 🇮🇹 [it](../../it/docs/COVERAGE_PLAN.md) · 🇷🇺 [ru](../../ru/docs/COVERAGE_PLAN.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/COVERAGE_PLAN.md) · 🇯🇵 [ja](../../ja/docs/COVERAGE_PLAN.md) · 🇰🇷 [ko](../../ko/docs/COVERAGE_PLAN.md) · 🇸🇦 [ar](../../ar/docs/COVERAGE_PLAN.md) · 🇮🇳 [in](../../in/docs/COVERAGE_PLAN.md) · 🇹🇭 [th](../../th/docs/COVERAGE_PLAN.md) · 🇻🇳 [vi](../../vi/docs/COVERAGE_PLAN.md) · 🇮🇩 [id](../../id/docs/COVERAGE_PLAN.md) · 🇲🇾 [ms](../../ms/docs/COVERAGE_PLAN.md) · 🇳🇱 [nl](../../nl/docs/COVERAGE_PLAN.md) · 🇵🇱 [pl](../../pl/docs/COVERAGE_PLAN.md) · 🇸🇪 [sv](../../sv/docs/COVERAGE_PLAN.md) · 🇳🇴 [no](../../no/docs/COVERAGE_PLAN.md) · 🇩🇰 [da](../../da/docs/COVERAGE_PLAN.md) · 🇫🇮 [fi](../../fi/docs/COVERAGE_PLAN.md) · 🇵🇹 [pt](../../pt/docs/COVERAGE_PLAN.md) · 🇷🇴 [ro](../../ro/docs/COVERAGE_PLAN.md) · 🇭🇺 [hu](../../hu/docs/COVERAGE_PLAN.md) · 🇧🇬 [bg](../../bg/docs/COVERAGE_PLAN.md) · 🇸🇰 [sk](../../sk/docs/COVERAGE_PLAN.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/COVERAGE_PLAN.md) · 🇮🇱 [he](../../he/docs/COVERAGE_PLAN.md) · 🇵🇭 [phi](../../phi/docs/COVERAGE_PLAN.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/COVERAGE_PLAN.md) · 🇨🇿 [cs](../../cs/docs/COVERAGE_PLAN.md)
+
+---
+
+Last updated: 2026-03-28
+
+## Baseline
+
+There are multiple coverage numbers depending on how the report is computed. For planning, only one of them is useful.
+
+| Metric | Scope | Statements / Lines | Branches | Functions | Notes |
+| -------------------- | ----------------------------------------------------- | -----------------: | -------: | --------: | --------------------------------------------------- |
+| Legacy | Old `npm run test:coverage` | 79.42% | 75.15% | 67.94% | Inflated: counts test files and excludes `open-sse` |
+| Diagnostic | Source-only, excluding tests and excluding `open-sse` | 68.16% | 63.55% | 64.06% | Useful only to isolate `src/**` |
+| Recommended baseline | Source-only, excluding tests and including `open-sse` | 56.95% | 66.05% | 57.80% | This is the project-wide baseline to improve |
+
+The recommended baseline is the number to optimize against.
+
+## Rules
+
+- Coverage targets apply to source files, not to `tests/**`.
+- `open-sse/**` is part of the product and must remain in scope.
+- New code should not reduce coverage in touched areas.
+- Prefer testing behavior and branch outcomes over implementation details.
+- Prefer temp SQLite databases and small fixtures over broad mocks for `src/lib/db/**`.
+
+## Current command set
+
+- `npm run test:coverage`
+ - Main source coverage gate for the unit test suite
+ - Generates `text-summary`, `html`, `json-summary`, and `lcov`
+- `npm run coverage:report`
+ - Detailed file-by-file report from the latest run
+- `npm run test:coverage:legacy`
+ - Historical comparison only
+
+## Milestones
+
+| Phase | Target | Focus |
+| ------- | ---------------------: | ------------------------------------------------- |
+| Phase 1 | 60% statements / lines | Quick wins and low-risk utility coverage |
+| Phase 2 | 65% statements / lines | DB and route foundations |
+| Phase 3 | 70% statements / lines | Provider validation and usage analytics |
+| Phase 4 | 75% statements / lines | `open-sse` translators and helpers |
+| Phase 5 | 80% statements / lines | `open-sse` handlers and executor branches |
+| Phase 6 | 85% statements / lines | Harder edge cases, branch debt, regression suites |
+| Phase 7 | 90% statements / lines | Final sweep, gap closure, strict ratchet |
+
+Branches and functions should ratchet upward with each phase, but the primary hard target is statements / lines.
+
+## Priority hotspots
+
+These files or areas offer the best return for the next phases:
+
+1. `open-sse/handlers`
+ - `chatCore.ts` at 7.57%
+ - Overall directory at 29.07%
+2. `open-sse/translator/request`
+ - Overall directory at 36.39%
+ - Many translators are still near single-digit coverage
+3. `open-sse/translator/response`
+ - Overall directory at 8.07%
+4. `open-sse/executors`
+ - Overall directory at 36.62%
+5. `src/lib/db`
+ - `models.ts` at 20.66%
+ - `registeredKeys.ts` at 34.46%
+ - `modelComboMappings.ts` at 36.25%
+ - `settings.ts` at 46.40%
+ - `webhooks.ts` at 33.33%
+6. `src/lib/usage`
+ - `usageHistory.ts` at 21.12%
+ - `usageStats.ts` at 9.56%
+ - `costCalculator.ts` at 30.00%
+7. `src/lib/providers`
+ - `validation.ts` at 41.16%
+8. Low-risk utility and API files for early gains
+ - `src/shared/utils/upstreamError.ts`
+ - `src/shared/utils/apiAuth.ts`
+ - `src/lib/api/errorResponse.ts`
+ - `src/app/api/settings/require-login/route.ts`
+ - `src/app/api/providers/[id]/models/route.ts`
+
+## Execution checklist
+
+### Phase 1: 56.95% -> 60%
+
+- [x] Fix coverage metric so it reflects source code instead of test files
+- [x] Keep a legacy coverage script for comparison
+- [x] Record the baseline and hotspots in-repo
+- [ ] Add focused tests for low-risk utilities:
+ - `src/shared/utils/upstreamError.ts`
+ - `src/shared/utils/fetchTimeout.ts`
+ - `src/lib/api/errorResponse.ts`
+ - `src/shared/utils/apiAuth.ts`
+ - `src/lib/display/names.ts`
+- [ ] Add route tests for:
+ - `src/app/api/settings/require-login/route.ts`
+ - `src/app/api/providers/[id]/models/route.ts`
+
+### Phase 2: 60% -> 65%
+
+- [ ] Add DB-backed tests for:
+ - `src/lib/db/modelComboMappings.ts`
+ - `src/lib/db/settings.ts`
+ - `src/lib/db/registeredKeys.ts`
+- [ ] Cover branch behavior in:
+ - `src/lib/providers/validation.ts`
+ - `src/app/api/v1/embeddings/route.ts`
+ - `src/app/api/v1/moderations/route.ts`
+
+### Phase 3: 65% -> 70%
+
+- [ ] Add usage analytics tests for:
+ - `src/lib/usage/usageHistory.ts`
+ - `src/lib/usage/usageStats.ts`
+ - `src/lib/usage/costCalculator.ts`
+- [ ] Expand route coverage for proxy management and settings branches
+
+### Phase 4: 70% -> 75%
+
+- [ ] Cover translator helpers and central translation paths:
+ - `open-sse/translator/index.ts`
+ - `open-sse/translator/helpers/*`
+ - `open-sse/translator/request/*`
+ - `open-sse/translator/response/*`
+
+### Phase 5: 75% -> 80%
+
+- [ ] Add handler-level tests for:
+ - `open-sse/handlers/chatCore.ts`
+ - `open-sse/handlers/responsesHandler.js`
+ - `open-sse/handlers/imageGeneration.js`
+ - `open-sse/handlers/embeddings.js`
+- [ ] Add executor branch coverage for provider-specific auth, retries, and endpoint overrides
+
+### Phase 6: 80% -> 85%
+
+- [ ] Merge more edge-case suites into the main coverage path
+- [ ] Increase function coverage for DB modules with weak constructor/helper coverage
+- [ ] Close branch gaps in `settings.ts`, `registeredKeys.ts`, `validation.ts`, and translator helpers
+
+### Phase 7: 85% -> 90%
+
+- [ ] Treat the remaining low-coverage files as blockers
+- [ ] Add regression tests for every uncovered production bug fixed during the push to 90%
+- [ ] Raise the coverage gate in CI only after the local baseline is stable for at least two consecutive runs
+
+## Ratchet policy
+
+Update `npm run test:coverage` thresholds only after the project actually exceeds the next milestone with a comfortable buffer.
+
+Recommended ratchet sequence:
+
+1. 55/60/55
+2. 60/62/58
+3. 65/64/62
+4. 70/66/66
+5. 75/70/72
+6. 80/75/78
+7. 85/80/84
+8. 90/85/88
+
+Order is `statements-lines / branches / functions`.
+
+## Known gap
+
+The current coverage command measures the main Node unit suite and includes source reached from it, including `open-sse`. It does not yet merge Vitest coverage into a single unified report. That merge is worth doing later, but it is not a blocker for starting the 60% -> 80% climb.
diff --git a/docs/i18n/hu/docs/FEATURES.md b/docs/i18n/hu/docs/FEATURES.md
index 61e2886ecf..cafb95d55f 100644
--- a/docs/i18n/hu/docs/FEATURES.md
+++ b/docs/i18n/hu/docs/FEATURES.md
@@ -1,6 +1,6 @@
# OmniRoute — Dashboard Features Gallery (Magyar)
-🌐 **Languages:** 🇺🇸 [English](../../../../docs/FEATURES.md) · 🇪🇸 [es](../../es/docs/FEATURES.md) · 🇫🇷 [fr](../../fr/docs/FEATURES.md) · 🇩🇪 [de](../../de/docs/FEATURES.md) · 🇮🇹 [it](../../it/docs/FEATURES.md) · 🇷🇺 [ru](../../ru/docs/FEATURES.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/FEATURES.md) · 🇯🇵 [ja](../../ja/docs/FEATURES.md) · 🇰🇷 [ko](../../ko/docs/FEATURES.md) · 🇸🇦 [ar](../../ar/docs/FEATURES.md) · 🇮🇳 [in](../../in/docs/FEATURES.md) · 🇹🇭 [th](../../th/docs/FEATURES.md) · 🇻🇳 [vi](../../vi/docs/FEATURES.md) · 🇮🇩 [id](../../id/docs/FEATURES.md) · 🇲🇾 [ms](../../ms/docs/FEATURES.md) · 🇳🇱 [nl](../../nl/docs/FEATURES.md) · 🇵🇱 [pl](../../pl/docs/FEATURES.md) · 🇸🇪 [sv](../../sv/docs/FEATURES.md) · 🇳🇴 [no](../../no/docs/FEATURES.md) · 🇩🇰 [da](../../da/docs/FEATURES.md) · 🇫🇮 [fi](../../fi/docs/FEATURES.md) · 🇵🇹 [pt](../../pt/docs/FEATURES.md) · 🇷🇴 [ro](../../ro/docs/FEATURES.md) · 🇭🇺 [hu](../../hu/docs/FEATURES.md) · 🇧🇬 [bg](../../bg/docs/FEATURES.md) · 🇸🇰 [sk](../../sk/docs/FEATURES.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/FEATURES.md) · 🇮🇱 [he](../../he/docs/FEATURES.md) · 🇵🇭 [phi](../../phi/docs/FEATURES.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/FEATURES.md)
+🌐 **Languages:** 🇺🇸 [English](../../../../docs/FEATURES.md) · 🇪🇸 [es](../../es/docs/FEATURES.md) · 🇫🇷 [fr](../../fr/docs/FEATURES.md) · 🇩🇪 [de](../../de/docs/FEATURES.md) · 🇮🇹 [it](../../it/docs/FEATURES.md) · 🇷🇺 [ru](../../ru/docs/FEATURES.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/FEATURES.md) · 🇯🇵 [ja](../../ja/docs/FEATURES.md) · 🇰🇷 [ko](../../ko/docs/FEATURES.md) · 🇸🇦 [ar](../../ar/docs/FEATURES.md) · 🇮🇳 [in](../../in/docs/FEATURES.md) · 🇹🇭 [th](../../th/docs/FEATURES.md) · 🇻🇳 [vi](../../vi/docs/FEATURES.md) · 🇮🇩 [id](../../id/docs/FEATURES.md) · 🇲🇾 [ms](../../ms/docs/FEATURES.md) · 🇳🇱 [nl](../../nl/docs/FEATURES.md) · 🇵🇱 [pl](../../pl/docs/FEATURES.md) · 🇸🇪 [sv](../../sv/docs/FEATURES.md) · 🇳🇴 [no](../../no/docs/FEATURES.md) · 🇩🇰 [da](../../da/docs/FEATURES.md) · 🇫🇮 [fi](../../fi/docs/FEATURES.md) · 🇵🇹 [pt](../../pt/docs/FEATURES.md) · 🇷🇴 [ro](../../ro/docs/FEATURES.md) · 🇭🇺 [hu](../../hu/docs/FEATURES.md) · 🇧🇬 [bg](../../bg/docs/FEATURES.md) · 🇸🇰 [sk](../../sk/docs/FEATURES.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/FEATURES.md) · 🇮🇱 [he](../../he/docs/FEATURES.md) · 🇵🇭 [phi](../../phi/docs/FEATURES.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/FEATURES.md) · 🇨🇿 [cs](../../cs/docs/FEATURES.md)
---
@@ -10,7 +10,7 @@ Visual guide to every section of the OmniRoute dashboard.
## 🔌 Providers
-Manage AI provider connections: OAuth providers (Claude Code, Codex, Gemini CLI), API key providers (Groq, DeepSeek, OpenRouter), and free providers (iFlow, Qwen, Kiro). Kiro accounts include credit balance tracking — remaining credits, total allowance, and renewal date visible in Dashboard → Usage.
+Manage AI provider connections: OAuth providers (Claude Code, Codex, Gemini CLI), API key providers (Groq, DeepSeek, OpenRouter), and free providers (Qoder, Qwen, Kiro). Kiro accounts include credit balance tracking — remaining credits, total allowance, and renewal date visible in Dashboard → Usage.

diff --git a/docs/i18n/hu/docs/MCP-SERVER.md b/docs/i18n/hu/docs/MCP-SERVER.md
new file mode 100644
index 0000000000..56eb669855
--- /dev/null
+++ b/docs/i18n/hu/docs/MCP-SERVER.md
@@ -0,0 +1,87 @@
+# OmniRoute MCP Server Documentation (Magyar)
+
+🌐 **Languages:** 🇺🇸 [English](../../../../docs/MCP-SERVER.md) · 🇪🇸 [es](../../es/docs/MCP-SERVER.md) · 🇫🇷 [fr](../../fr/docs/MCP-SERVER.md) · 🇩🇪 [de](../../de/docs/MCP-SERVER.md) · 🇮🇹 [it](../../it/docs/MCP-SERVER.md) · 🇷🇺 [ru](../../ru/docs/MCP-SERVER.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/MCP-SERVER.md) · 🇯🇵 [ja](../../ja/docs/MCP-SERVER.md) · 🇰🇷 [ko](../../ko/docs/MCP-SERVER.md) · 🇸🇦 [ar](../../ar/docs/MCP-SERVER.md) · 🇮🇳 [in](../../in/docs/MCP-SERVER.md) · 🇹🇭 [th](../../th/docs/MCP-SERVER.md) · 🇻🇳 [vi](../../vi/docs/MCP-SERVER.md) · 🇮🇩 [id](../../id/docs/MCP-SERVER.md) · 🇲🇾 [ms](../../ms/docs/MCP-SERVER.md) · 🇳🇱 [nl](../../nl/docs/MCP-SERVER.md) · 🇵🇱 [pl](../../pl/docs/MCP-SERVER.md) · 🇸🇪 [sv](../../sv/docs/MCP-SERVER.md) · 🇳🇴 [no](../../no/docs/MCP-SERVER.md) · 🇩🇰 [da](../../da/docs/MCP-SERVER.md) · 🇫🇮 [fi](../../fi/docs/MCP-SERVER.md) · 🇵🇹 [pt](../../pt/docs/MCP-SERVER.md) · 🇷🇴 [ro](../../ro/docs/MCP-SERVER.md) · 🇭🇺 [hu](../../hu/docs/MCP-SERVER.md) · 🇧🇬 [bg](../../bg/docs/MCP-SERVER.md) · 🇸🇰 [sk](../../sk/docs/MCP-SERVER.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/MCP-SERVER.md) · 🇮🇱 [he](../../he/docs/MCP-SERVER.md) · 🇵🇭 [phi](../../phi/docs/MCP-SERVER.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/MCP-SERVER.md) · 🇨🇿 [cs](../../cs/docs/MCP-SERVER.md)
+
+---
+
+> Model Context Protocol server with 16 intelligent tools
+
+## Telepítés
+
+OmniRoute MCP is built-in. Start it with:
+
+```bash
+omniroute --mcp
+```
+
+Or via the open-sse transport:
+
+```bash
+# HTTP streamable transport (port 20130)
+omniroute --dev # MCP auto-starts on /mcp endpoint
+```
+
+## IDE Configuration
+
+See [IDE Configs](integrations/ide-configs.md) for Antigravity, Cursor, Copilot, and Claude Desktop setup.
+
+---
+
+## Essential Tools (8)
+
+| Tool | Description |
+| :------------------------------ | :--------------------------------------- |
+| `omniroute_get_health` | Gateway health, circuit breakers, uptime |
+| `omniroute_list_combos` | All configured combos with models |
+| `omniroute_get_combo_metrics` | Performance metrics for a specific combo |
+| `omniroute_switch_combo` | Switch active combo by ID/name |
+| `omniroute_check_quota` | Quota status per provider or all |
+| `omniroute_route_request` | Send a chat completion through OmniRoute |
+| `omniroute_cost_report` | Cost analytics for a time period |
+| `omniroute_list_models_catalog` | Full model catalog with capabilities |
+
+## Advanced Tools (8)
+
+| Tool | Description |
+| :--------------------------------- | :---------------------------------------------------------- |
+| `omniroute_simulate_route` | Dry-run routing simulation with fallback tree |
+| `omniroute_set_budget_guard` | Session budget with degrade/block/alert actions |
+| `omniroute_set_resilience_profile` | Apply conservative/balanced/aggressive preset |
+| `omniroute_test_combo` | Live-test all models in a combo via a real upstream request |
+| `omniroute_get_provider_metrics` | Detailed metrics for one provider |
+| `omniroute_best_combo_for_task` | Task-fitness recommendation with alternatives |
+| `omniroute_explain_route` | Explain a past routing decision |
+| `omniroute_get_session_snapshot` | Full session state: costs, tokens, errors |
+
+## Authentication
+
+MCP tools are authenticated via API key scopes. Each tool requires specific scopes:
+
+| Scope | Tools |
+| :------------- | :----------------------------------------------- |
+| `read:health` | get_health, get_provider_metrics |
+| `read:combos` | list_combos, get_combo_metrics |
+| `write:combos` | switch_combo |
+| `read:quota` | check_quota |
+| `write:route` | route_request, simulate_route, test_combo |
+| `read:usage` | cost_report, get_session_snapshot, explain_route |
+| `write:config` | set_budget_guard, set_resilience_profile |
+| `read:models` | list_models_catalog, best_combo_for_task |
+
+## Audit Logging
+
+Every tool call is logged to `mcp_tool_audit` with:
+
+- Tool name, arguments, result
+- Duration (ms), success/failure
+- API key hash, timestamp
+
+## Files
+
+| File | Purpose |
+| :------------------------------------------- | :------------------------------------------ |
+| `open-sse/mcp-server/server.ts` | MCP server creation + 16 tool registrations |
+| `open-sse/mcp-server/transport.ts` | Stdio + HTTP transport |
+| `open-sse/mcp-server/auth.ts` | API key + scope validation |
+| `open-sse/mcp-server/audit.ts` | Tool call audit logging |
+| `open-sse/mcp-server/tools/advancedTools.ts` | 8 advanced tool handlers |
diff --git a/docs/i18n/hu/docs/RELEASE_CHECKLIST.md b/docs/i18n/hu/docs/RELEASE_CHECKLIST.md
new file mode 100644
index 0000000000..63d257c74a
--- /dev/null
+++ b/docs/i18n/hu/docs/RELEASE_CHECKLIST.md
@@ -0,0 +1,37 @@
+# Release Checklist (Magyar)
+
+🌐 **Languages:** 🇺🇸 [English](../../../../docs/RELEASE_CHECKLIST.md) · 🇪🇸 [es](../../es/docs/RELEASE_CHECKLIST.md) · 🇫🇷 [fr](../../fr/docs/RELEASE_CHECKLIST.md) · 🇩🇪 [de](../../de/docs/RELEASE_CHECKLIST.md) · 🇮🇹 [it](../../it/docs/RELEASE_CHECKLIST.md) · 🇷🇺 [ru](../../ru/docs/RELEASE_CHECKLIST.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/RELEASE_CHECKLIST.md) · 🇯🇵 [ja](../../ja/docs/RELEASE_CHECKLIST.md) · 🇰🇷 [ko](../../ko/docs/RELEASE_CHECKLIST.md) · 🇸🇦 [ar](../../ar/docs/RELEASE_CHECKLIST.md) · 🇮🇳 [in](../../in/docs/RELEASE_CHECKLIST.md) · 🇹🇭 [th](../../th/docs/RELEASE_CHECKLIST.md) · 🇻🇳 [vi](../../vi/docs/RELEASE_CHECKLIST.md) · 🇮🇩 [id](../../id/docs/RELEASE_CHECKLIST.md) · 🇲🇾 [ms](../../ms/docs/RELEASE_CHECKLIST.md) · 🇳🇱 [nl](../../nl/docs/RELEASE_CHECKLIST.md) · 🇵🇱 [pl](../../pl/docs/RELEASE_CHECKLIST.md) · 🇸🇪 [sv](../../sv/docs/RELEASE_CHECKLIST.md) · 🇳🇴 [no](../../no/docs/RELEASE_CHECKLIST.md) · 🇩🇰 [da](../../da/docs/RELEASE_CHECKLIST.md) · 🇫🇮 [fi](../../fi/docs/RELEASE_CHECKLIST.md) · 🇵🇹 [pt](../../pt/docs/RELEASE_CHECKLIST.md) · 🇷🇴 [ro](../../ro/docs/RELEASE_CHECKLIST.md) · 🇭🇺 [hu](../../hu/docs/RELEASE_CHECKLIST.md) · 🇧🇬 [bg](../../bg/docs/RELEASE_CHECKLIST.md) · 🇸🇰 [sk](../../sk/docs/RELEASE_CHECKLIST.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/RELEASE_CHECKLIST.md) · 🇮🇱 [he](../../he/docs/RELEASE_CHECKLIST.md) · 🇵🇭 [phi](../../phi/docs/RELEASE_CHECKLIST.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/RELEASE_CHECKLIST.md) · 🇨🇿 [cs](../../cs/docs/RELEASE_CHECKLIST.md)
+
+---
+
+Use this checklist before tagging or publishing a new OmniRoute release.
+
+## Version and Changelog
+
+1. Bump `package.json` version (`x.y.z`) in the release branch.
+2. Move release notes from `## [Unreleased]` in `CHANGELOG.md` to a dated section:
+ - `## [x.y.z] — YYYY-MM-DD`
+3. Keep `## [Unreleased]` as the first changelog section for upcoming work.
+4. Ensure the latest semver section in `CHANGELOG.md` equals `package.json` version.
+
+## API Docs
+
+1. Update `docs/openapi.yaml`:
+ - `info.version` must equal `package.json` version.
+2. Validate endpoint examples if API contracts changed.
+
+## Runtime Docs
+
+1. Review `docs/ARCHITECTURE.md` for storage/runtime drift.
+2. Review `docs/TROUBLESHOOTING.md` for env var and operational drift.
+3. Update localized docs if source docs changed significantly.
+
+## Automated Check
+
+Run the sync guard locally before opening PR:
+
+```bash
+npm run check:docs-sync
+```
+
+CI also runs this check in `.github/workflows/ci.yml` (lint job).
diff --git a/docs/i18n/hu/docs/TROUBLESHOOTING.md b/docs/i18n/hu/docs/TROUBLESHOOTING.md
new file mode 100644
index 0000000000..28bc2c7fc5
--- /dev/null
+++ b/docs/i18n/hu/docs/TROUBLESHOOTING.md
@@ -0,0 +1,256 @@
+# Troubleshooting (Magyar)
+
+🌐 **Languages:** 🇺🇸 [English](../../../../docs/TROUBLESHOOTING.md) · 🇪🇸 [es](../../es/docs/TROUBLESHOOTING.md) · 🇫🇷 [fr](../../fr/docs/TROUBLESHOOTING.md) · 🇩🇪 [de](../../de/docs/TROUBLESHOOTING.md) · 🇮🇹 [it](../../it/docs/TROUBLESHOOTING.md) · 🇷🇺 [ru](../../ru/docs/TROUBLESHOOTING.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/TROUBLESHOOTING.md) · 🇯🇵 [ja](../../ja/docs/TROUBLESHOOTING.md) · 🇰🇷 [ko](../../ko/docs/TROUBLESHOOTING.md) · 🇸🇦 [ar](../../ar/docs/TROUBLESHOOTING.md) · 🇮🇳 [in](../../in/docs/TROUBLESHOOTING.md) · 🇹🇭 [th](../../th/docs/TROUBLESHOOTING.md) · 🇻🇳 [vi](../../vi/docs/TROUBLESHOOTING.md) · 🇮🇩 [id](../../id/docs/TROUBLESHOOTING.md) · 🇲🇾 [ms](../../ms/docs/TROUBLESHOOTING.md) · 🇳🇱 [nl](../../nl/docs/TROUBLESHOOTING.md) · 🇵🇱 [pl](../../pl/docs/TROUBLESHOOTING.md) · 🇸🇪 [sv](../../sv/docs/TROUBLESHOOTING.md) · 🇳🇴 [no](../../no/docs/TROUBLESHOOTING.md) · 🇩🇰 [da](../../da/docs/TROUBLESHOOTING.md) · 🇫🇮 [fi](../../fi/docs/TROUBLESHOOTING.md) · 🇵🇹 [pt](../../pt/docs/TROUBLESHOOTING.md) · 🇷🇴 [ro](../../ro/docs/TROUBLESHOOTING.md) · 🇭🇺 [hu](../../hu/docs/TROUBLESHOOTING.md) · 🇧🇬 [bg](../../bg/docs/TROUBLESHOOTING.md) · 🇸🇰 [sk](../../sk/docs/TROUBLESHOOTING.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/TROUBLESHOOTING.md) · 🇮🇱 [he](../../he/docs/TROUBLESHOOTING.md) · 🇵🇭 [phi](../../phi/docs/TROUBLESHOOTING.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/TROUBLESHOOTING.md) · 🇨🇿 [cs](../../cs/docs/TROUBLESHOOTING.md)
+
+---
+
+Common problems and solutions for OmniRoute.
+
+---
+
+## Quick Fixes
+
+| Problem | Solution |
+| ----------------------------- | ------------------------------------------------------------------ |
+| First login not working | Set `INITIAL_PASSWORD` in `.env` (no hardcoded default) |
+| Dashboard opens on wrong port | Set `PORT=20128` and `NEXT_PUBLIC_BASE_URL=http://localhost:20128` |
+| No request logs under `logs/` | Set `ENABLE_REQUEST_LOGS=true` |
+| EACCES: permission denied | Set `DATA_DIR=/path/to/writable/dir` to override `~/.omniroute` |
+| Routing strategy not saving | Update to v1.4.11+ (Zod schema fix for settings persistence) |
+
+---
+
+## Provider Issues
+
+### "Language model did not provide messages"
+
+**Cause:** Provider quota exhausted.
+
+**Fix:**
+
+1. Check dashboard quota tracker
+2. Use a combo with fallback tiers
+3. Switch to cheaper/free tier
+
+### Rate Limiting
+
+**Cause:** Subscription quota exhausted.
+
+**Fix:**
+
+- Add fallback: `cc/claude-opus-4-6 → glm/glm-4.7 → if/kimi-k2-thinking`
+- Use GLM/MiniMax as cheap backup
+
+### OAuth Token Expired
+
+OmniRoute auto-refreshes tokens. If issues persist:
+
+1. Dashboard → Provider → Reconnect
+2. Delete and re-add the provider connection
+
+---
+
+## Cloud Issues
+
+### Cloud Sync Errors
+
+1. Verify `BASE_URL` points to your running instance (e.g., `http://localhost:20128`)
+2. Verify `CLOUD_URL` points to your cloud endpoint (e.g., `https://omniroute.dev`)
+3. Keep `NEXT_PUBLIC_*` values aligned with server-side values
+
+### Cloud `stream=false` Returns 500
+
+**Symptom:** `Unexpected token 'd'...` on cloud endpoint for non-streaming calls.
+
+**Cause:** Upstream returns SSE payload while client expects JSON.
+
+**Workaround:** Use `stream=true` for cloud direct calls. Local runtime includes SSE→JSON fallback.
+
+### Cloud Says Connected but "Invalid API key"
+
+1. Create a fresh key from local dashboard (`/api/keys`)
+2. Run cloud sync: Enable Cloud → Sync Now
+3. Old/non-synced keys can still return `401` on cloud
+
+---
+
+## Docker Issues
+
+### CLI Tool Shows Not Installed
+
+1. Check runtime fields: `curl http://localhost:20128/api/cli-tools/runtime/codex | jq`
+2. For portable mode: use image target `runner-cli` (bundled CLIs)
+3. For host mount mode: set `CLI_EXTRA_PATHS` and mount host bin directory as read-only
+4. If `installed=true` and `runnable=false`: binary was found but failed healthcheck
+
+### Quick Runtime Validation
+
+```bash
+curl -s http://localhost:20128/api/cli-tools/codex-settings | jq '{installed,runnable,commandPath,runtimeMode,reason}'
+curl -s http://localhost:20128/api/cli-tools/claude-settings | jq '{installed,runnable,commandPath,runtimeMode,reason}'
+curl -s http://localhost:20128/api/cli-tools/openclaw-settings | jq '{installed,runnable,commandPath,runtimeMode,reason}'
+```
+
+---
+
+## Cost Issues
+
+### High Costs
+
+1. Check usage stats in Dashboard → Usage
+2. Switch primary model to GLM/MiniMax
+3. Use free tier (Gemini CLI, Qoder) for non-critical tasks
+4. Set cost budgets per API key: Dashboard → API Keys → Budget
+
+---
+
+## Debugging
+
+### Enable Request Logs
+
+Set `ENABLE_REQUEST_LOGS=true` in your `.env` file. Logs appear under `logs/` directory.
+
+### Check Provider Health
+
+```bash
+# Health dashboard
+http://localhost:20128/dashboard/health
+
+# API health check
+curl http://localhost:20128/api/monitoring/health
+```
+
+### Runtime Storage
+
+- Main state: `${DATA_DIR}/storage.sqlite` (providers, combos, aliases, keys, settings)
+- Usage: SQLite tables in `storage.sqlite` (`usage_history`, `call_logs`, `proxy_logs`) + optional `${DATA_DIR}/log.txt` and `${DATA_DIR}/call_logs/`
+- Request logs: `/logs/...` (when `ENABLE_REQUEST_LOGS=true`)
+
+---
+
+## Circuit Breaker Issues
+
+### Provider stuck in OPEN state
+
+When a provider's circuit breaker is OPEN, requests are blocked until the cooldown expires.
+
+**Fix:**
+
+1. Go to **Dashboard → Settings → Resilience**
+2. Check the circuit breaker card for the affected provider
+3. Click **Reset All** to clear all breakers, or wait for the cooldown to expire
+4. Verify the provider is actually available before resetting
+
+### Provider keeps tripping the circuit breaker
+
+If a provider repeatedly enters OPEN state:
+
+1. Check **Dashboard → Health → Provider Health** for the failure pattern
+2. Go to **Settings → Resilience → Provider Profiles** and increase the failure threshold
+3. Check if the provider has changed API limits or requires re-authentication
+4. Review latency telemetry — high latency may cause timeout-based failures
+
+---
+
+## Audio Transcription Issues
+
+### "Unsupported model" error
+
+- Ensure you're using the correct prefix: `deepgram/nova-3` or `assemblyai/best`
+- Verify the provider is connected in **Dashboard → Providers**
+
+### Transcription returns empty or fails
+
+- Check supported audio formats: `mp3`, `wav`, `m4a`, `flac`, `ogg`, `webm`
+- Verify file size is within provider limits (typically < 25MB)
+- Check provider API key validity in the provider card
+
+---
+
+## Translator Debugging
+
+Use **Dashboard → Translator** to debug format translation issues:
+
+| Mode | When to Use |
+| ---------------- | -------------------------------------------------------------------------------------------- |
+| **Playground** | Compare input/output formats side by side — paste a failing request to see how it translates |
+| **Chat Tester** | Send live messages and inspect the full request/response payload including headers |
+| **Test Bench** | Run batch tests across format combinations to find which translations are broken |
+| **Live Monitor** | Watch real-time request flow to catch intermittent translation issues |
+
+### Common format issues
+
+- **Thinking tags not appearing** — Check if the target provider supports thinking and the thinking budget setting
+- **Tool calls dropping** — Some format translations may strip unsupported fields; verify in Playground mode
+- **System prompt missing** — Claude and Gemini handle system prompts differently; check translation output
+- **SDK returns raw string instead of object** — Fixed in v1.1.0: response sanitizer now strips non-standard fields (`x_groq`, `usage_breakdown`, etc.) that cause OpenAI SDK Pydantic validation failures
+- **GLM/ERNIE rejects `system` role** — Fixed in v1.1.0: role normalizer automatically merges system messages into user messages for incompatible models
+- **`developer` role not recognized** — Fixed in v1.1.0: automatically converted to `system` for non-OpenAI providers
+- **`json_schema` not working with Gemini** — Fixed in v1.1.0: `response_format` is now converted to Gemini's `responseMimeType` + `responseSchema`
+
+---
+
+## Resilience Settings
+
+### Auto rate-limit not triggering
+
+- Auto rate-limit only applies to API key providers (not OAuth/subscription)
+- Verify **Settings → Resilience → Provider Profiles** has auto-rate-limit enabled
+- Check if the provider returns `429` status codes or `Retry-After` headers
+
+### Tuning exponential backoff
+
+Provider profiles support these settings:
+
+- **Base delay** — Initial wait time after first failure (default: 1s)
+- **Max delay** — Maximum wait time cap (default: 30s)
+- **Multiplier** — How much to increase delay per consecutive failure (default: 2x)
+
+### Anti-thundering herd
+
+When many concurrent requests hit a rate-limited provider, OmniRoute uses mutex + auto rate-limiting to serialize requests and prevent cascading failures. This is automatic for API key providers.
+
+---
+
+## Optional RAG / LLM failure taxonomy (16 problems)
+
+Some OmniRoute users place the gateway in front of RAG or agent stacks. In those setups it is common to see a strange pattern: OmniRoute looks healthy (providers up, routing profiles ok, no rate limit alerts) but the final answer is still wrong.
+
+In practice these incidents usually come from the downstream RAG pipeline, not from the gateway itself.
+
+If you want a shared vocabulary to describe those failures you can use the WFGY ProblemMap, an external MIT license text resource that defines sixteen recurring RAG / LLM failure patterns. At a high level it covers:
+
+- retrieval drift and broken context boundaries
+- empty or stale indexes and vector stores
+- embedding versus semantic mismatch
+- prompt assembly and context window issues
+- logic collapse and overconfident answers
+- long chain and agent coordination failures
+- multi agent memory and role drift
+- deployment and bootstrap ordering problems
+
+The idea is simple:
+
+1. When you investigate a bad response, capture:
+ - user task and request
+ - route or provider combo in OmniRoute
+ - any RAG context used downstream (retrieved documents, tool calls, etc)
+2. Map the incident to one or two WFGY ProblemMap numbers (`No.1` … `No.16`).
+3. Store the number in your own dashboard, runbook, or incident tracker next to the OmniRoute logs.
+4. Use the corresponding WFGY page to decide whether you need to change your RAG stack, retriever, or routing strategy.
+
+Full text and concrete recipes live here (MIT license, text only):
+
+[WFGY ProblemMap README](https://github.com/onestardao/WFGY/blob/main/ProblemMap/README.md)
+
+You can ignore this section if you do not run RAG or agent pipelines behind OmniRoute.
+
+---
+
+## Still Stuck?
+
+- **GitHub Issues**: [github.com/diegosouzapw/OmniRoute/issues](https://github.com/diegosouzapw/OmniRoute/issues)
+- **Architecture**: See [`docs/ARCHITECTURE.md`](ARCHITECTURE.md) for internal details
+- **API Reference**: See [`docs/API_REFERENCE.md`](API_REFERENCE.md) for all endpoints
+- **Health Dashboard**: Check **Dashboard → Health** for real-time system status
+- **Translator**: Use **Dashboard → Translator** to debug format issues
diff --git a/docs/i18n/hu/USER_GUIDE.md b/docs/i18n/hu/docs/USER_GUIDE.md
similarity index 82%
rename from docs/i18n/hu/USER_GUIDE.md
rename to docs/i18n/hu/docs/USER_GUIDE.md
index ca10bd9a28..5fc65fdc4f 100644
--- a/docs/i18n/hu/USER_GUIDE.md
+++ b/docs/i18n/hu/docs/USER_GUIDE.md
@@ -1,8 +1,6 @@
# User Guide (Magyar)
-🌐 **Languages:** 🇺🇸 [English](../../USER_GUIDE.md) · 🇧🇷 [pt-BR](../pt-BR/USER_GUIDE.md) · 🇪🇸 [es](../es/USER_GUIDE.md) · 🇫🇷 [fr](../fr/USER_GUIDE.md) · 🇩🇪 [de](../de/USER_GUIDE.md) · 🇮🇹 [it](../it/USER_GUIDE.md) · 🇷🇺 [ru](../ru/USER_GUIDE.md) · 🇨🇳 [zh-CN](../zh-CN/USER_GUIDE.md) · 🇯🇵 [ja](../ja/USER_GUIDE.md) · 🇰🇷 [ko](../ko/USER_GUIDE.md) · 🇸🇦 [ar](../ar/USER_GUIDE.md) · 🇮🇳 [in](../in/USER_GUIDE.md) · 🇹🇭 [th](../th/USER_GUIDE.md) · 🇻🇳 [vi](../vi/USER_GUIDE.md) · 🇮🇩 [id](../id/USER_GUIDE.md) · 🇲🇾 [ms](../ms/USER_GUIDE.md) · 🇳🇱 [nl](../nl/USER_GUIDE.md) · 🇵🇱 [pl](../pl/USER_GUIDE.md) · 🇸🇪 [sv](../sv/USER_GUIDE.md) · 🇳🇴 [no](../no/USER_GUIDE.md) · 🇩🇰 [da](../da/USER_GUIDE.md) · 🇫🇮 [fi](../fi/USER_GUIDE.md) · 🇵🇹 [pt](../pt/USER_GUIDE.md) · 🇷🇴 [ro](../ro/USER_GUIDE.md) · 🇭🇺 [hu](../hu/USER_GUIDE.md) · 🇧🇬 [bg](../bg/USER_GUIDE.md) · 🇸🇰 [sk](../sk/USER_GUIDE.md) · 🇺🇦 [uk-UA](../uk-UA/USER_GUIDE.md) · 🇮🇱 [he](../he/USER_GUIDE.md) · 🇵🇭 [phi](../phi/USER_GUIDE.md)
-
-> 🇺🇸 [English](../../USER_GUIDE.md)
+🌐 **Languages:** 🇺🇸 [English](../../../../docs/USER_GUIDE.md) · 🇪🇸 [es](../../es/docs/USER_GUIDE.md) · 🇫🇷 [fr](../../fr/docs/USER_GUIDE.md) · 🇩🇪 [de](../../de/docs/USER_GUIDE.md) · 🇮🇹 [it](../../it/docs/USER_GUIDE.md) · 🇷🇺 [ru](../../ru/docs/USER_GUIDE.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/USER_GUIDE.md) · 🇯🇵 [ja](../../ja/docs/USER_GUIDE.md) · 🇰🇷 [ko](../../ko/docs/USER_GUIDE.md) · 🇸🇦 [ar](../../ar/docs/USER_GUIDE.md) · 🇮🇳 [in](../../in/docs/USER_GUIDE.md) · 🇹🇭 [th](../../th/docs/USER_GUIDE.md) · 🇻🇳 [vi](../../vi/docs/USER_GUIDE.md) · 🇮🇩 [id](../../id/docs/USER_GUIDE.md) · 🇲🇾 [ms](../../ms/docs/USER_GUIDE.md) · 🇳🇱 [nl](../../nl/docs/USER_GUIDE.md) · 🇵🇱 [pl](../../pl/docs/USER_GUIDE.md) · 🇸🇪 [sv](../../sv/docs/USER_GUIDE.md) · 🇳🇴 [no](../../no/docs/USER_GUIDE.md) · 🇩🇰 [da](../../da/docs/USER_GUIDE.md) · 🇫🇮 [fi](../../fi/docs/USER_GUIDE.md) · 🇵🇹 [pt](../../pt/docs/USER_GUIDE.md) · 🇷🇴 [ro](../../ro/docs/USER_GUIDE.md) · 🇭🇺 [hu](../../hu/docs/USER_GUIDE.md) · 🇧🇬 [bg](../../bg/docs/USER_GUIDE.md) · 🇸🇰 [sk](../../sk/docs/USER_GUIDE.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/USER_GUIDE.md) · 🇮🇱 [he](../../he/docs/USER_GUIDE.md) · 🇵🇭 [phi](../../phi/docs/USER_GUIDE.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/USER_GUIDE.md) · 🇨🇿 [cs](../../cs/docs/USER_GUIDE.md)
---
@@ -320,7 +318,7 @@ Model: cc/claude-opus-4-6
---
-## 🚀 Deployment
+## Telepítés
### Global npm install (Recommended)
@@ -511,23 +509,26 @@ post_install() {
### Environment Variables
-| Variable | Default | Description |
-| ------------------------- | ------------------------------------ | ------------------------------------------------------- |
-| `JWT_SECRET` | `omniroute-default-secret-change-me` | JWT signing secret (**change in production**) |
-| `INITIAL_PASSWORD` | `123456` | First login password |
-| `DATA_DIR` | `~/.omniroute` | Data directory (db, usage, logs) |
-| `PORT` | framework default | Service port (`20128` in examples) |
-| `HOSTNAME` | framework default | Bind host (Docker defaults to `0.0.0.0`) |
-| `NODE_ENV` | runtime default | Set `production` for deploy |
-| `BASE_URL` | `http://localhost:20128` | Server-side internal base URL |
-| `CLOUD_URL` | `https://omniroute.dev` | Cloud sync endpoint base URL |
-| `API_KEY_SECRET` | `endpoint-proxy-api-key-secret` | HMAC secret for generated API keys |
-| `REQUIRE_API_KEY` | `false` | Enforce Bearer API key on `/v1/*` |
-| `ENABLE_REQUEST_LOGS` | `false` | Enables request/response logs |
-| `AUTH_COOKIE_SECURE` | `false` | Force `Secure` auth cookie (behind HTTPS reverse proxy) |
-| `OMNIROUTE_MEMORY_MB` | `512` | Node.js heap limit in MB |
-| `PROMPT_CACHE_MAX_SIZE` | `50` | Max prompt cache entries |
-| `SEMANTIC_CACHE_MAX_SIZE` | `100` | Max semantic cache entries |
+| Variable | Default | Description |
+| ---------------------------- | ------------------------------------ | ------------------------------------------------------------------------------------------ |
+| `JWT_SECRET` | `omniroute-default-secret-change-me` | JWT signing secret (**change in production**) |
+| `INITIAL_PASSWORD` | `123456` | First login password |
+| `DATA_DIR` | `~/.omniroute` | Data directory (db, usage, logs) |
+| `PORT` | framework default | Service port (`20128` in examples) |
+| `HOSTNAME` | framework default | Bind host (Docker defaults to `0.0.0.0`) |
+| `NODE_ENV` | runtime default | Set `production` for deploy |
+| `BASE_URL` | `http://localhost:20128` | Server-side internal base URL |
+| `CLOUD_URL` | `https://omniroute.dev` | Cloud sync endpoint base URL |
+| `API_KEY_SECRET` | `endpoint-proxy-api-key-secret` | HMAC secret for generated API keys |
+| `REQUIRE_API_KEY` | `false` | Enforce Bearer API key on `/v1/*` |
+| `ALLOW_API_KEY_REVEAL` | `false` | Allow Api Manager to copy full API keys on demand |
+| `DISABLE_SQLITE_AUTO_BACKUP` | `false` | Disable automatic SQLite snapshots before writes/import/restore; manual backups still work |
+| `ENABLE_REQUEST_LOGS` | `false` | Enables request/response logs |
+| `AUTH_COOKIE_SECURE` | `false` | Force `Secure` auth cookie (behind HTTPS reverse proxy) |
+| `CLOUDFLARED_BIN` | unset | Use an existing `cloudflared` binary instead of managed download |
+| `OMNIROUTE_MEMORY_MB` | `512` | Node.js heap limit in MB |
+| `PROMPT_CACHE_MAX_SIZE` | `50` | Max prompt cache entries |
+| `SEMANTIC_CACHE_MAX_SIZE` | `100` | Max semantic cache entries |
For the full environment variable reference, see the [README](../README.md).
@@ -598,6 +599,11 @@ curl -X POST http://localhost:20128/api/provider-models \
Or use Dashboard: **Providers → [Provider] → Custom Models**.
+Notes:
+
+- OpenRouter and OpenAI/Anthropic-compatible providers are managed from **Available Models** only. Manual add, import, and auto-sync all land in the same available-model list, so there is no separate Custom Models section for those providers.
+- The **Custom Models** section is intended for providers that do not expose managed available-model imports.
+
### Dedicated Provider Routes
Route requests directly to a specific provider with model validation:
@@ -642,6 +648,14 @@ Returns models grouped by provider with types (`chat`, `embedding`, `image`).
- Automatic background sync with timeout + fail-fast
- Prefer server-side `BASE_URL`/`CLOUD_URL` in production
+### Cloudflare Quick Tunnel
+
+- Available in **Dashboard → Endpoints** for Docker and other self-hosted deployments
+- Creates a temporary `https://*.trycloudflare.com` URL that forwards to your current OpenAI-compatible `/v1` endpoint
+- First enable installs `cloudflared` only when needed; later restarts reuse the same managed binary
+- Tunnel URLs are ephemeral and change every time you stop/start the tunnel
+- Set `CLOUDFLARED_BIN` if you prefer using a preinstalled `cloudflared` binary instead of the managed download
+
### LLM Gateway Intelligence (Phase 9)
- **Semantic Cache** — Auto-caches non-streaming, temperature=0 responses (bypass with `X-OmniRoute-No-Cache: true`)
@@ -757,11 +771,11 @@ OmniRoute implements provider-level resilience with four components:
Manage database backups in **Dashboard → Settings → System & Storage**.
-| Action | Description |
-| ------------------------ | ------------------------------------------------------------------------------------------------------------------------------ |
-| **Export Database** | Downloads the current SQLite database as a `.sqlite` file |
-| **Export All (.tar.gz)** | Downloads a full backup archive including: database, settings, combos, provider connections (no credentials), API key metadata |
-| **Import Database** | Upload a `.sqlite` file to replace the current database. A pre-import backup is automatically created |
+| Action | Description |
+| ------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------- |
+| **Export Database** | Downloads the current SQLite database as a `.sqlite` file |
+| **Export All (.tar.gz)** | Downloads a full backup archive including: database, settings, combos, provider connections (no credentials), API key metadata |
+| **Import Database** | Upload a `.sqlite` file to replace the current database. A pre-import backup is automatically created unless `DISABLE_SQLITE_AUTO_BACKUP=true` |
```bash
# API: Export database
@@ -787,10 +801,11 @@ curl -X POST http://localhost:20128/api/db-backups/import \
### Settings Dashboard
-The settings page is organized into 5 tabs for easy navigation:
+The settings page is organized into 6 tabs for easy navigation:
| Tab | Contents |
| -------------- | ---------------------------------------------------------------------------------------------- |
+| **General** | System storage tools, appearance settings, theme controls, and per-item sidebar visibility |
| **Security** | Login/Password settings, IP Access Control, API auth for `/models`, and Provider Blocking |
| **Routing** | Global routing strategy (6 options), wildcard model aliases, fallback chains, combo defaults |
| **Resilience** | Provider profiles, editable rate limits, circuit breaker status, policies & locked identifiers |
diff --git a/docs/i18n/hu/docs/VM_DEPLOYMENT_GUIDE.md b/docs/i18n/hu/docs/VM_DEPLOYMENT_GUIDE.md
new file mode 100644
index 0000000000..fbce85463c
--- /dev/null
+++ b/docs/i18n/hu/docs/VM_DEPLOYMENT_GUIDE.md
@@ -0,0 +1,403 @@
+# OmniRoute — Deployment Guide on VM with Cloudflare (Magyar)
+
+🌐 **Languages:** 🇺🇸 [English](../../../../docs/VM_DEPLOYMENT_GUIDE.md) · 🇪🇸 [es](../../es/docs/VM_DEPLOYMENT_GUIDE.md) · 🇫🇷 [fr](../../fr/docs/VM_DEPLOYMENT_GUIDE.md) · 🇩🇪 [de](../../de/docs/VM_DEPLOYMENT_GUIDE.md) · 🇮🇹 [it](../../it/docs/VM_DEPLOYMENT_GUIDE.md) · 🇷🇺 [ru](../../ru/docs/VM_DEPLOYMENT_GUIDE.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/VM_DEPLOYMENT_GUIDE.md) · 🇯🇵 [ja](../../ja/docs/VM_DEPLOYMENT_GUIDE.md) · 🇰🇷 [ko](../../ko/docs/VM_DEPLOYMENT_GUIDE.md) · 🇸🇦 [ar](../../ar/docs/VM_DEPLOYMENT_GUIDE.md) · 🇮🇳 [in](../../in/docs/VM_DEPLOYMENT_GUIDE.md) · 🇹🇭 [th](../../th/docs/VM_DEPLOYMENT_GUIDE.md) · 🇻🇳 [vi](../../vi/docs/VM_DEPLOYMENT_GUIDE.md) · 🇮🇩 [id](../../id/docs/VM_DEPLOYMENT_GUIDE.md) · 🇲🇾 [ms](../../ms/docs/VM_DEPLOYMENT_GUIDE.md) · 🇳🇱 [nl](../../nl/docs/VM_DEPLOYMENT_GUIDE.md) · 🇵🇱 [pl](../../pl/docs/VM_DEPLOYMENT_GUIDE.md) · 🇸🇪 [sv](../../sv/docs/VM_DEPLOYMENT_GUIDE.md) · 🇳🇴 [no](../../no/docs/VM_DEPLOYMENT_GUIDE.md) · 🇩🇰 [da](../../da/docs/VM_DEPLOYMENT_GUIDE.md) · 🇫🇮 [fi](../../fi/docs/VM_DEPLOYMENT_GUIDE.md) · 🇵🇹 [pt](../../pt/docs/VM_DEPLOYMENT_GUIDE.md) · 🇷🇴 [ro](../../ro/docs/VM_DEPLOYMENT_GUIDE.md) · 🇭🇺 [hu](../../hu/docs/VM_DEPLOYMENT_GUIDE.md) · 🇧🇬 [bg](../../bg/docs/VM_DEPLOYMENT_GUIDE.md) · 🇸🇰 [sk](../../sk/docs/VM_DEPLOYMENT_GUIDE.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/VM_DEPLOYMENT_GUIDE.md) · 🇮🇱 [he](../../he/docs/VM_DEPLOYMENT_GUIDE.md) · 🇵🇭 [phi](../../phi/docs/VM_DEPLOYMENT_GUIDE.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/VM_DEPLOYMENT_GUIDE.md) · 🇨🇿 [cs](../../cs/docs/VM_DEPLOYMENT_GUIDE.md)
+
+---
+
+Complete guide to install and configure OmniRoute on a VM (VPS) with domain managed via Cloudflare.
+
+---
+
+## Prerequisites
+
+| Item | Minimum | Recommended |
+| ---------- | ------------------------ | ---------------- |
+| **CPU** | 1 vCPU | 2 vCPU |
+| **RAM** | 1 GB | 2 GB |
+| **Disk** | 10 GB SSD | 25 GB SSD |
+| **OS** | Ubuntu 22.04 LTS | Ubuntu 24.04 LTS |
+| **Domain** | Registered on Cloudflare | — |
+| **Docker** | Docker Engine 24+ | Docker 27+ |
+
+**Tested providers**: Akamai (Linode), DigitalOcean, Vultr, Hetzner, AWS Lightsail.
+
+---
+
+## 1. Configure the VM
+
+### 1.1 Create the instance
+
+On your preferred VPS provider:
+
+- Choose Ubuntu 24.04 LTS
+- Select the minimum plan (1 vCPU / 1 GB RAM)
+- Set a strong root password or configure SSH key
+- Note the **public IP** (e.g., `203.0.113.10`)
+
+### 1.2 Connect via SSH
+
+```bash
+ssh root@203.0.113.10
+```
+
+### 1.3 Update the system
+
+```bash
+apt update && apt upgrade -y
+```
+
+### 1.4 Install Docker
+
+```bash
+# Install dependencies
+apt install -y ca-certificates curl gnupg
+
+# Add official Docker repository
+install -m 0755 -d /etc/apt/keyrings
+curl -fsSL https://download.docker.com/linux/ubuntu/gpg | gpg --dearmor -o /etc/apt/keyrings/docker.gpg
+chmod a+r /etc/apt/keyrings/docker.gpg
+echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu $ (. /etc/os-release && echo “$VERSION_CODENAME”) stable" | tee /etc/apt/sources.list.d/docker.list > /dev/null
+apt update
+apt install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin
+```
+
+### 1.5 Install nginx
+
+```bash
+apt install -y nginx
+```
+
+### 1.6 Configure Firewall (UFW)
+
+```bash
+ufw default deny incoming
+ufw default allow outgoing
+ufw allow 22/tcp # SSH
+ufw allow 80/tcp # HTTP (redirect)
+ufw allow 443/tcp # HTTPS
+ufw enable
+```
+
+> **Tip**: For maximum security, restrict ports 80 and 443 to Cloudflare IPs only. See the [Advanced Security](#advanced-security) section.
+
+---
+
+## 2. Install OmniRoute
+
+### 2.1 Create configuration directory
+
+```bash
+mkdir -p /opt/omniroute
+```
+
+### 2.2 Create environment variables file
+
+```bash
+cat > /opt/omniroute/.env << ‘EOF’
+# === Security ===
+JWT_SECRET=CHANGE-TO-A-UNIQUE-64-CHAR-SECRET-KEY
+INITIAL_PASSWORD=YourSecurePassword123!
+API_KEY_SECRET=REPLACE-WITH-ANOTHER-SECRET-KEY
+STORAGE_ENCRYPTION_KEY=REPLACE-WITH-THIRD-SECRET-KEY
+STORAGE_ENCRYPTION_KEY_VERSION=v1
+MACHINE_ID_SALT=CHANGE-TO-A-UNIQUE-SALT
+
+# === App ===
+PORT=20128
+NODE_ENV=production
+HOSTNAME=0.0.0.0
+DATA_DIR=/app/data
+STORAGE_DRIVER=sqlite
+ENABLE_REQUEST_LOGS=true
+AUTH_COOKIE_SECURE=false
+REQUIRE_API_KEY=false
+
+# === Domain (change to your domain) ===
+BASE_URL=https://llms.seudominio.com
+NEXT_PUBLIC_BASE_URL=https://llms.seudominio.com
+
+# === Cloud Sync (optional) ===
+# CLOUD_URL=https://cloud.omniroute.online
+# NEXT_PUBLIC_CLOUD_URL=https://cloud.omniroute.online
+EOF
+```
+
+> ⚠️ **IMPORTANT**: Generate unique secret keys! Use `openssl rand -hex 32` for each key.
+
+### 2.3 Start the container
+
+```bash
+docker pull diegosouzapw/omniroute:latest
+
+docker run -d \
+ --name omniroute \
+ --restart unless-stopped \
+ --env-file /opt/omniroute/.env \
+ -p 20128:20128 \
+ -v omniroute-data:/app/data \
+ diegosouzapw/omniroute:latest
+```
+
+### 2.4 Verify that it is running
+
+```bash
+docker ps | grep omniroute
+docker logs omniroute --tail 20
+```
+
+It should display: `[DB] SQLite database ready` and `listening on port 20128`.
+
+---
+
+## 3. Configure nginx (Reverse Proxy)
+
+### 3.1 Generate SSL certificate (Cloudflare Origin)
+
+In the Cloudflare dashboard:
+
+1. Go to **SSL/TLS → Origin Server**
+2. Click **Create Certificate**
+3. Keep the defaults (15 years, \*.yourdomain.com)
+4. Copy the **Origin Certificate** and the **Private Key**
+
+```bash
+mkdir -p /etc/nginx/ssl
+
+# Paste the certificate
+nano /etc/nginx/ssl/origin.crt
+
+# Paste the private key
+nano /etc/nginx/ssl/origin.key
+
+chmod 600 /etc/nginx/ssl/origin.key
+```
+
+### 3.2 Nginx Configuration
+
+```bash
+cat > /etc/nginx/sites-available/omniroute << ‘NGINX’
+# Default server — blocks direct access via IP
+server {
+ listen 80 default_server;
+ listen [::]:80 default_server;
+ listen 443 ssl default_server;
+ listen [::]:443 ssl default_server;
+ ssl_certificate /etc/nginx/ssl/origin.crt;
+ ssl_certificate_key /etc/nginx/ssl/origin.key;
+ server_name _;
+ return 444;
+}
+
+# OmniRoute — HTTPS
+server {
+ listen 443 ssl;
+ listen [::]:443 ssl;
+ server_name llms.yourdomain.com; # Change to your domain
+
+ ssl_certificate /etc/nginx/ssl/origin.crt;
+ ssl_certificate_key /etc/nginx/ssl/origin.key;
+ ssl_protocols TLSv1.2 TLSv1.3;
+
+ client_max_body_size 100M;
+
+ location / {
+ proxy_pass http://127.0.0.1:20128;
+ proxy_set_header Host $host;
+ proxy_set_header X-Real-IP $remote_addr;
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
+ proxy_set_header X-Forwarded-Proto $scheme;
+
+ # WebSocket support
+ proxy_http_version 1.1;
+ proxy_set_header Upgrade $http_upgrade;
+ proxy_set_header Connection “upgrade”;
+
+ # SSE (Server-Sent Events) — streaming AI responses
+ proxy_buffering off;
+ proxy_cache off;
+ proxy_read_timeout 300s;
+ proxy_send_timeout 300s;
+ }
+}
+
+# HTTP → HTTPS redirect
+server {
+ listen 80;
+ listen [::]:80;
+ server_name llms.yourdomain.com;
+ return 301 https://$server_name$request_uri;
+}
+NGINX
+```
+
+### 3.3 Enable and Test
+
+```bash
+# Remove default configuration
+rm -f /etc/nginx/sites-enabled/default
+
+# Enable OmniRoute
+ln -sf /etc/nginx/sites-available/omniroute /etc/nginx/sites-enabled/omniroute
+
+# Test and reload
+nginx -t && systemctl reload nginx
+```
+
+---
+
+## 4. Configure Cloudflare DNS
+
+### 4.1 Add DNS record
+
+In the Cloudflare dashboard → DNS:
+
+| Type | Name | Content | Proxy |
+| ---- | ------ | ---------------------- | ---------- |
+| A | `llms` | `203.0.113.10` (VM IP) | ✅ Proxied |
+
+### 4.2 Configure SSL
+
+Under **SSL/TLS → Overview**:
+
+- Mode: **Full (Strict)**
+
+Under **SSL/TLS → Edge Certificates**:
+
+- Always Use HTTPS: ✅ On
+- Minimum TLS Version: TLS 1.2
+- Automatic HTTPS Rewrites: ✅ On
+
+### 4.3 Testing
+
+```bash
+curl -sI https://llms.seudominio.com/health
+# Should return HTTP/2 200
+```
+
+---
+
+## 5. Operations and Maintenance
+
+### Upgrade to a new version
+
+```bash
+docker pull diegosouzapw/omniroute:latest
+docker stop omniroute && docker rm omniroute
+docker run -d --name omniroute --restart unless-stopped \
+ --env-file /opt/omniroute/.env \
+ -p 20128:20128 \
+ -v omniroute-data:/app/data \
+ diegosouzapw/omniroute:latest
+```
+
+### View logs
+
+```bash
+docker logs -f omniroute # Real-time stream
+docker logs omniroute --tail 50 # Last 50 lines
+```
+
+### Manual database backup
+
+```bash
+# Copy data from the volume to the host
+docker cp omniroute:/app/data ./backup-$(date +%F)
+
+# Or compress the entire volume
+docker run --rm -v omniroute-data:/data -v $(pwd):/backup \
+ alpine tar czf /backup/omniroute-data-$(date +%F).tar.gz /data
+```
+
+### Restore from backup
+
+```bash
+docker stop omniroute
+docker run --rm -v omniroute-data:/data -v $(pwd):/backup \
+ alpine sh -c “rm -rf /data/* && tar xzf /backup/omniroute-data-YYYY-MM-DD.tar.gz -C /”
+docker start omniroute
+```
+
+---
+
+## 6. Advanced Security
+
+### Restrict nginx to Cloudflare IPs
+
+```bash
+cat > /etc/nginx/cloudflare-ips.conf << ‘CF’
+# Cloudflare IPv4 ranges — update periodically
+# https://www.cloudflare.com/ips-v4/
+set_real_ip_from 173.245.48.0/20;
+set_real_ip_from 103.21.244.0/22;
+set_real_ip_from 103.22.200.0/22;
+set_real_ip_from 103.31.4.0/22;
+set_real_ip_from 141.101.64.0/18;
+set_real_ip_from 108.162.192.0/18;
+set_real_ip_from 190.93.240.0/20;
+set_real_ip_from 188.114.96.0/20;
+set_real_ip_from 197.234.240.0/22;
+set_real_ip_from 198.41.128.0/17;
+set_real_ip_from 162.158.0.0/15;
+set_real_ip_from 104.16.0.0/13;
+set_real_ip_from 104.24.0.0/14;
+set_real_ip_from 172.64.0.0/13;
+set_real_ip_from 131.0.72.0/22;
+real_ip_header CF-Connecting-IP;
+CF
+```
+
+Add the following to `nginx.conf` inside the `http {}` block:
+
+```nginx
+include /etc/nginx/cloudflare-ips.conf;
+```
+
+### Install fail2ban
+
+```bash
+apt install -y fail2ban
+systemctl enable fail2ban
+systemctl start fail2ban
+
+# Check status
+fail2ban-client status sshd
+```
+
+### Block direct access to the Docker port
+
+```bash
+# Prevent direct external access to port 20128
+iptables -I DOCKER-USER -p tcp --dport 20128 -j DROP
+iptables -I DOCKER-USER -i lo -p tcp --dport 20128 -j ACCEPT
+
+# Persist the rules
+apt install -y iptables-persistent
+netfilter-persistent save
+```
+
+---
+
+## 7. Deploy to Cloudflare Workers (Optional)
+
+For remote access via Cloudflare Workers (without exposing the VM directly):
+
+```bash
+# In the local repository
+cd omnirouteCloud
+npm install
+npx wrangler login
+npx wrangler deploy
+```
+
+See the full documentation at [omnirouteCloud/README.md](../omnirouteCloud/README.md).
+
+---
+
+## Port Summary
+
+| Port | Service | Access |
+| ----- | ----------- | -------------------------- |
+| 22 | SSH | Public (with fail2ban) |
+| 80 | nginx HTTP | Redirect → HTTPS |
+| 443 | nginx HTTPS | Via Cloudflare Proxy |
+| 20128 | OmniRoute | Localhost only (via nginx) |
diff --git a/docs/i18n/hu/src/lib/a2a/README.md b/docs/i18n/hu/src/lib/a2a/README.md
new file mode 100644
index 0000000000..cc1863ddd5
--- /dev/null
+++ b/docs/i18n/hu/src/lib/a2a/README.md
@@ -0,0 +1,752 @@
+# OmniRoute A2A Server (Magyar)
+
+🌐 **Languages:** 🇺🇸 [English](../../../../../../src/lib/a2a/README.md) · 🇪🇸 [es](../../../../es/src/lib/a2a/README.md) · 🇫🇷 [fr](../../../../fr/src/lib/a2a/README.md) · 🇩🇪 [de](../../../../de/src/lib/a2a/README.md) · 🇮🇹 [it](../../../../it/src/lib/a2a/README.md) · 🇷🇺 [ru](../../../../ru/src/lib/a2a/README.md) · 🇨🇳 [zh-CN](../../../../zh-CN/src/lib/a2a/README.md) · 🇯🇵 [ja](../../../../ja/src/lib/a2a/README.md) · 🇰🇷 [ko](../../../../ko/src/lib/a2a/README.md) · 🇸🇦 [ar](../../../../ar/src/lib/a2a/README.md) · 🇮🇳 [in](../../../../in/src/lib/a2a/README.md) · 🇹🇭 [th](../../../../th/src/lib/a2a/README.md) · 🇻🇳 [vi](../../../../vi/src/lib/a2a/README.md) · 🇮🇩 [id](../../../../id/src/lib/a2a/README.md) · 🇲🇾 [ms](../../../../ms/src/lib/a2a/README.md) · 🇳🇱 [nl](../../../../nl/src/lib/a2a/README.md) · 🇵🇱 [pl](../../../../pl/src/lib/a2a/README.md) · 🇸🇪 [sv](../../../../sv/src/lib/a2a/README.md) · 🇳🇴 [no](../../../../no/src/lib/a2a/README.md) · 🇩🇰 [da](../../../../da/src/lib/a2a/README.md) · 🇫🇮 [fi](../../../../fi/src/lib/a2a/README.md) · 🇵🇹 [pt](../../../../pt/src/lib/a2a/README.md) · 🇷🇴 [ro](../../../../ro/src/lib/a2a/README.md) · 🇭🇺 [hu](../../../../hu/src/lib/a2a/README.md) · 🇧🇬 [bg](../../../../bg/src/lib/a2a/README.md) · 🇸🇰 [sk](../../../../sk/src/lib/a2a/README.md) · 🇺🇦 [uk-UA](../../../../uk-UA/src/lib/a2a/README.md) · 🇮🇱 [he](../../../../he/src/lib/a2a/README.md) · 🇵🇭 [phi](../../../../phi/src/lib/a2a/README.md) · 🇧🇷 [pt-BR](../../../../pt-BR/src/lib/a2a/README.md) · 🇨🇿 [cs](../../../../cs/src/lib/a2a/README.md)
+
+---
+
+> **Agent-to-Agent Protocol v0.3** — Enables any AI agent to use OmniRoute as an intelligent routing agent via JSON-RPC 2.0.
+
+The A2A Server exposes OmniRoute as a **first-class agent** that other agents can discover, delegate tasks to, and collaborate with using the [A2A Protocol](https://google.github.io/A2A/).
+
+---
+
+## Architektúra
+
+```
+┌──────────────────────────────────────────────────────────────────┐
+│ Orchestrator Agent │
+│ (LangChain, CrewAI, AutoGen, Custom Agent) │
+└──────────────────────┬───────────────────────────────────────────┘
+ │ 1. GET /.well-known/agent.json (discover)
+ │ 2. POST /a2a (JSON-RPC 2.0)
+ ▼
+┌──────────────────────────────────────────────────────────────────┐
+│ OmniRoute A2A Server │
+│ ┌────────────────┐ ┌────────────────┐ ┌───────────────────┐ │
+│ │ Task Manager │ │ Skill Engine │ │ SSE Streaming │ │
+│ │ (lifecycle) │──│ (registry) │──│ (real-time) │ │
+│ └────────────────┘ └────────┬───────┘ └───────────────────┘ │
+│ │ │
+│ Skills: │ │
+│ ├─ smart-routing ──────────┤ ┌────────────────────────────┐ │
+│ └─ quota-management ───────┘ │ Routing Decision Logger │ │
+│ └────────────────────────────┘ │
+└──────────────────────────────────────────────────────────────────┘
+ │
+ ▼ OmniRoute Gateway (internal)
+ /v1/chat/completions, /api/combos, /api/usage/quota
+```
+
+---
+
+## Gyors kezdés
+
+### Agent Discovery
+
+Every A2A-compatible agent exposes an **Agent Card** at `/.well-known/agent.json`:
+
+```bash
+curl http://localhost:20128/.well-known/agent.json
+```
+
+**Response:**
+
+```json
+{
+ "name": "OmniRoute",
+ "description": "Intelligent AI gateway with auto-routing across 50+ providers",
+ "url": "http://localhost:20128/a2a",
+ "version": "1.8.1",
+ "capabilities": {
+ "streaming": true,
+ "pushNotifications": false
+ },
+ "skills": [
+ {
+ "id": "smart-routing",
+ "name": "Smart Routing",
+ "description": "Routes prompts through OmniRoute intelligent pipeline",
+ "tags": ["routing", "llm", "multi-provider", "cost-optimization"],
+ "examples": [
+ "Write a hello world in Python",
+ "Explain quantum computing using the cheapest provider"
+ ]
+ },
+ {
+ "id": "quota-management",
+ "name": "Quota Management",
+ "description": "Natural-language queries about provider quotas",
+ "tags": ["quota", "analytics", "cost"],
+ "examples": [
+ "Which provider has the most quota remaining?",
+ "Suggest a free combo for coding"
+ ]
+ }
+ ],
+ "authentication": {
+ "schemes": ["bearer"],
+ "apiKeyHeader": "Authorization"
+ }
+}
+```
+
+---
+
+## JSON-RPC 2.0 Methods
+
+### `message/send` — Synchronous Execution
+
+Send a message to a skill and receive the complete response.
+
+```bash
+curl -X POST http://localhost:20128/a2a \
+ -H "Content-Type: application/json" \
+ -H "Authorization: Bearer YOUR_KEY" \
+ -d '{
+ "jsonrpc": "2.0",
+ "id": "1",
+ "method": "message/send",
+ "params": {
+ "skill": "smart-routing",
+ "messages": [{"role": "user", "content": "Write a Python hello world"}],
+ "metadata": {"model": "auto", "combo": "fast-coding"}
+ }
+ }'
+```
+
+**Response:**
+
+```json
+{
+ "jsonrpc": "2.0",
+ "id": "1",
+ "result": {
+ "task": { "id": "a1b2c3d4-...", "state": "completed" },
+ "artifacts": [{ "type": "text", "content": "print('Hello, World!')" }],
+ "metadata": {
+ "routing_explanation": "Selected claude-sonnet via provider \"anthropic\" (latency: 1200ms, cost: $0.0030)",
+ "cost_envelope": { "estimated": 0.005, "actual": 0.003, "currency": "USD" },
+ "resilience_trace": [
+ { "event": "primary_selected", "provider": "anthropic", "timestamp": "2026-03-04T..." }
+ ],
+ "policy_verdict": { "allowed": true, "reason": "within budget and quota limits" }
+ }
+ }
+}
+```
+
+### `message/stream` — SSE Streaming
+
+Same as `message/send` but returns Server-Sent Events for real-time streaming.
+
+```bash
+curl -N -X POST http://localhost:20128/a2a \
+ -H "Content-Type: application/json" \
+ -H "Authorization: Bearer YOUR_KEY" \
+ -d '{
+ "jsonrpc": "2.0",
+ "id": "1",
+ "method": "message/stream",
+ "params": {
+ "skill": "smart-routing",
+ "messages": [{"role": "user", "content": "Explain quantum computing"}]
+ }
+ }'
+```
+
+**SSE Events:**
+
+```
+data: {"jsonrpc":"2.0","method":"message/stream","params":{"task":{"id":"...","state":"working"},"chunk":{"type":"text","content":"Quantum computing..."}}}
+
+: heartbeat 2026-03-04T21:00:00Z
+
+data: {"jsonrpc":"2.0","method":"message/stream","params":{"task":{"id":"...","state":"completed"},"metadata":{...}}}
+```
+
+### `tasks/get` — Query Task Status
+
+```bash
+curl -X POST http://localhost:20128/a2a \
+ -H "Content-Type: application/json" \
+ -H "Authorization: Bearer YOUR_KEY" \
+ -d '{"jsonrpc":"2.0","id":"2","method":"tasks/get","params":{"taskId":"TASK_UUID"}}'
+```
+
+### `tasks/cancel` — Cancel a Running Task
+
+```bash
+curl -X POST http://localhost:20128/a2a \
+ -H "Content-Type: application/json" \
+ -H "Authorization: Bearer YOUR_KEY" \
+ -d '{"jsonrpc":"2.0","id":"3","method":"tasks/cancel","params":{"taskId":"TASK_UUID"}}'
+```
+
+---
+
+## Skills Reference
+
+### `smart-routing`
+
+Routes prompts through OmniRoute's intelligent pipeline with full observability.
+
+**Parameters (in `metadata`):**
+
+| Parameter | Type | Default | Description |
+| --------- | -------- | ------------ | ---------------------------------------------------------------------------------------- |
+| `model` | `string` | `"auto"` | Target model (e.g., `claude-sonnet-4`, `gpt-4o`, `auto`) |
+| `combo` | `string` | active combo | Specific combo to route through |
+| `budget` | `number` | none | Maximum cost in USD for this request |
+| `role` | `string` | none | Task role hint: `coding`, `review`, `planning`, `analysis`, `debugging`, `documentation` |
+
+**Returns:**
+
+| Field | Description |
+| ------------------------------ | --------------------------------------------------------- |
+| `artifacts[].content` | The LLM response text |
+| `metadata.routing_explanation` | Human-readable explanation of routing decision |
+| `metadata.cost_envelope` | Estimated vs actual cost with currency |
+| `metadata.resilience_trace` | Array of events (primary_selected, fallback_needed, etc.) |
+| `metadata.policy_verdict` | Whether the request was allowed and why |
+
+### `quota-management`
+
+Answers natural-language queries about provider quotas.
+
+**Query types (inferred from message content):**
+
+| Query Pattern | Response Type |
+| ---------------------------------------------- | -------------------------------------------------------- |
+| Contains `"ranking"`, `"most quota"`, `"best"` | Providers ranked by remaining quota |
+| Contains `"free"`, `"suggest"` | Lists free combos or suggests free-tier providers |
+| Default | Full quota summary with warnings for low-quota providers |
+
+---
+
+## Task Lifecycle
+
+```
+submitted ──→ working ──→ completed
+ ──→ failed
+ ──────────→ cancelled
+```
+
+| State | Description |
+| ----------- | ----------------------------------------------------- |
+| `submitted` | Task created, queued for execution |
+| `working` | Skill handler is executing |
+| `completed` | Execution succeeded, artifacts available |
+| `failed` | Execution failed or task expired (TTL: 5 min default) |
+| `cancelled` | Cancelled by client via `tasks/cancel` |
+
+- Terminal states: `completed`, `failed`, `cancelled` (no further transitions)
+- Expired tasks in `submitted` or `working` are auto-marked as `failed`
+- Tasks are garbage-collected after 2× TTL
+
+---
+
+## Client Examples
+
+### Python — Orchestrator Agent
+
+```python
+"""
+A2A Client — Python example.
+Discovers OmniRoute agent, sends a task, and processes the result.
+"""
+import requests
+import json
+
+BASE_URL = "http://localhost:20128"
+API_KEY = "your-api-key"
+HEADERS = {
+ "Content-Type": "application/json",
+ "Authorization": f"Bearer {API_KEY}",
+}
+
+# 1. Discover agent capabilities
+agent_card = requests.get(f"{BASE_URL}/.well-known/agent.json").json()
+print(f"Agent: {agent_card['name']} v{agent_card['version']}")
+print(f"Skills: {[s['id'] for s in agent_card['skills']]}")
+
+# 2. Send a smart-routing task
+response = requests.post(f"{BASE_URL}/a2a", headers=HEADERS, json={
+ "jsonrpc": "2.0",
+ "id": "task-1",
+ "method": "message/send",
+ "params": {
+ "skill": "smart-routing",
+ "messages": [{"role": "user", "content": "Write a Python quicksort implementation"}],
+ "metadata": {
+ "model": "auto",
+ "combo": "fast-coding",
+ "budget": 0.10,
+ }
+ }
+})
+result = response.json()["result"]
+print(f"\n📝 Response: {result['artifacts'][0]['content'][:200]}...")
+print(f"🔀 Routing: {result['metadata']['routing_explanation']}")
+print(f"💰 Cost: ${result['metadata']['cost_envelope']['actual']}")
+print(f"🛡️ Policy: {result['metadata']['policy_verdict']['reason']}")
+
+# 3. Query quota status
+quota_resp = requests.post(f"{BASE_URL}/a2a", headers=HEADERS, json={
+ "jsonrpc": "2.0",
+ "id": "task-2",
+ "method": "message/send",
+ "params": {
+ "skill": "quota-management",
+ "messages": [{"role": "user", "content": "Which provider has the most quota remaining?"}],
+ }
+})
+quota_result = quota_resp.json()["result"]
+print(f"\n📊 Quota: {quota_result['artifacts'][0]['content']}")
+```
+
+### TypeScript — Multi-Agent Orchestrator
+
+```typescript
+/**
+ * A2A Client — TypeScript example.
+ * Shows agent discovery, task delegation, and streaming.
+ */
+
+const BASE_URL = "http://localhost:20128";
+const API_KEY = "your-api-key";
+
+interface JsonRpcResponse {
+ jsonrpc: "2.0";
+ id: string | number;
+ result?: T;
+ error?: { code: number; message: string };
+}
+
+async function a2aCall(method: string, params: Record): Promise {
+ const resp = await fetch(`${BASE_URL}/a2a`, {
+ method: "POST",
+ headers: {
+ "Content-Type": "application/json",
+ Authorization: `Bearer ${API_KEY}`,
+ },
+ body: JSON.stringify({
+ jsonrpc: "2.0",
+ id: `${method}-${Date.now()}`,
+ method,
+ params,
+ }),
+ });
+ const json: JsonRpcResponse = await resp.json();
+ if (json.error) throw new Error(`[${json.error.code}] ${json.error.message}`);
+ return json.result!;
+}
+
+// ── Agent Discovery ──
+const agentCard = await fetch(`${BASE_URL}/.well-known/agent.json`).then((r) => r.json());
+console.log(`Connected to: ${agentCard.name} (${agentCard.skills.length} skills)`);
+
+// ── Smart Routing: Send a coding task ──
+const routingResult = await a2aCall("message/send", {
+ skill: "smart-routing",
+ messages: [{ role: "user", content: "Implement a Redis cache wrapper in TypeScript" }],
+ metadata: { model: "claude-sonnet-4", role: "coding" },
+});
+console.log("Response:", routingResult.artifacts[0].content);
+console.log("Provider:", routingResult.metadata.routing_explanation);
+
+// ── Quota Management: Find free alternatives ──
+const quotaResult = await a2aCall("message/send", {
+ skill: "quota-management",
+ messages: [{ role: "user", content: "Suggest free combos for documentation" }],
+});
+console.log("Free combos:", quotaResult.artifacts[0].content);
+
+// ── Streaming: Real-time response ──
+const streamResp = await fetch(`${BASE_URL}/a2a`, {
+ method: "POST",
+ headers: {
+ "Content-Type": "application/json",
+ Authorization: `Bearer ${API_KEY}`,
+ },
+ body: JSON.stringify({
+ jsonrpc: "2.0",
+ id: "stream-1",
+ method: "message/stream",
+ params: {
+ skill: "smart-routing",
+ messages: [{ role: "user", content: "Explain microservices architecture" }],
+ },
+ }),
+});
+
+const reader = streamResp.body!.getReader();
+const decoder = new TextDecoder();
+while (true) {
+ const { done, value } = await reader.read();
+ if (done) break;
+ const chunk = decoder.decode(value);
+ for (const line of chunk.split("\n")) {
+ if (line.startsWith("data: ")) {
+ const event = JSON.parse(line.slice(6));
+ if (event.params.chunk) {
+ process.stdout.write(event.params.chunk.content);
+ }
+ if (event.params.task.state === "completed") {
+ console.log("\n✅ Stream completed");
+ }
+ }
+ }
+}
+```
+
+### Python — LangChain A2A Integration
+
+```python
+"""
+LangChain integration — Use OmniRoute A2A as a custom LLM.
+"""
+from langchain.llms.base import BaseLLM
+from langchain.schema import LLMResult, Generation
+import requests
+from typing import List, Optional
+
+class OmniRouteA2A(BaseLLM):
+ base_url: str = "http://localhost:20128"
+ api_key: str = ""
+ model: str = "auto"
+ combo: Optional[str] = None
+
+ @property
+ def _llm_type(self) -> str:
+ return "omniroute-a2a"
+
+ def _call(self, prompt: str, stop: Optional[List[str]] = None, **kwargs) -> str:
+ response = requests.post(
+ f"{self.base_url}/a2a",
+ headers={
+ "Content-Type": "application/json",
+ "Authorization": f"Bearer {self.api_key}",
+ },
+ json={
+ "jsonrpc": "2.0",
+ "id": "langchain-1",
+ "method": "message/send",
+ "params": {
+ "skill": "smart-routing",
+ "messages": [{"role": "user", "content": prompt}],
+ "metadata": {
+ "model": self.model,
+ **({"combo": self.combo} if self.combo else {}),
+ },
+ },
+ },
+ )
+ result = response.json()["result"]
+ return result["artifacts"][0]["content"]
+
+ def _generate(self, prompts: List[str], stop=None, **kwargs) -> LLMResult:
+ return LLMResult(
+ generations=[[Generation(text=self._call(p, stop))] for p in prompts]
+ )
+
+# Usage
+llm = OmniRouteA2A(
+ base_url="http://localhost:20128",
+ api_key="your-key",
+ model="auto",
+ combo="fast-coding",
+)
+result = llm("Write a Python function to merge two sorted lists")
+print(result)
+```
+
+### Go — A2A Client
+
+```go
+package main
+
+import (
+ "bytes"
+ "encoding/json"
+ "fmt"
+ "io"
+ "net/http"
+)
+
+const baseURL = "http://localhost:20128"
+const apiKey = "your-api-key"
+
+type JsonRpcRequest struct {
+ Jsonrpc string `json:"jsonrpc"`
+ ID string `json:"id"`
+ Method string `json:"method"`
+ Params interface{} `json:"params"`
+}
+
+type JsonRpcResponse struct {
+ Jsonrpc string `json:"jsonrpc"`
+ ID string `json:"id"`
+ Result interface{} `json:"result"`
+ Error *struct {
+ Code int `json:"code"`
+ Message string `json:"message"`
+ } `json:"error"`
+}
+
+func a2aCall(method string, params interface{}) (*JsonRpcResponse, error) {
+ body, _ := json.Marshal(JsonRpcRequest{
+ Jsonrpc: "2.0",
+ ID: "go-1",
+ Method: method,
+ Params: params,
+ })
+
+ req, _ := http.NewRequest("POST", baseURL+"/a2a", bytes.NewReader(body))
+ req.Header.Set("Content-Type", "application/json")
+ req.Header.Set("Authorization", "Bearer "+apiKey)
+
+ resp, err := http.DefaultClient.Do(req)
+ if err != nil {
+ return nil, err
+ }
+ defer resp.Body.Close()
+ data, _ := io.ReadAll(resp.Body)
+
+ var result JsonRpcResponse
+ json.Unmarshal(data, &result)
+ return &result, nil
+}
+
+func main() {
+ // Discover agent
+ resp, _ := http.Get(baseURL + "/.well-known/agent.json")
+ defer resp.Body.Close()
+ body, _ := io.ReadAll(resp.Body)
+ fmt.Println("Agent Card:", string(body))
+
+ // Send smart-routing task
+ result, _ := a2aCall("message/send", map[string]interface{}{
+ "skill": "smart-routing",
+ "messages": []map[string]string{{"role": "user", "content": "Hello from Go!"}},
+ "metadata": map[string]interface{}{"model": "auto"},
+ })
+ out, _ := json.MarshalIndent(result.Result, "", " ")
+ fmt.Println("Result:", string(out))
+}
+```
+
+---
+
+## Use Cases
+
+### 🤖 Use Case 1: Multi-Agent Coding Pipeline
+
+An orchestrator agent delegates code generation to OmniRoute, then passes the output to a review agent.
+
+```python
+def coding_pipeline(task: str):
+ # Step 1: Generate code via OmniRoute A2A
+ code_result = a2a_send("smart-routing", [
+ {"role": "user", "content": f"Write production-quality code: {task}"}
+ ], metadata={"model": "auto", "role": "coding"})
+ code = code_result["artifacts"][0]["content"]
+
+ # Step 2: Review the code via OmniRoute A2A (different model)
+ review_result = a2a_send("smart-routing", [
+ {"role": "user", "content": f"Review this code for bugs and improvements:\n\n{code}"}
+ ], metadata={"model": "auto", "role": "review"})
+ review = review_result["artifacts"][0]["content"]
+
+ # Step 3: Check costs
+ print(f"Code cost: ${code_result['metadata']['cost_envelope']['actual']}")
+ print(f"Review cost: ${review_result['metadata']['cost_envelope']['actual']}")
+
+ return {"code": code, "review": review}
+```
+
+### 💡 Use Case 2: Quota-Aware Agent Swarm
+
+Multiple agents share quota through OmniRoute, using the quota skill to coordinate.
+
+```python
+async def quota_aware_agent(agent_name: str, task: str):
+ # Check quota before starting
+ quota = a2a_send("quota-management", [
+ {"role": "user", "content": "Which provider has the most quota remaining?"}
+ ])
+ print(f"[{agent_name}] {quota['artifacts'][0]['content']}")
+
+ # Send request with budget constraint
+ result = a2a_send("smart-routing", [
+ {"role": "user", "content": task}
+ ], metadata={"budget": 0.05})
+
+ policy = result["metadata"]["policy_verdict"]
+ if not policy["allowed"]:
+ print(f"[{agent_name}] ⚠️ Budget exceeded: {policy['reason']}")
+ # Fall back to free combo
+ quota = a2a_send("quota-management", [
+ {"role": "user", "content": "Suggest free combos"}
+ ])
+ print(f"[{agent_name}] Free alternatives: {quota['artifacts'][0]['content']}")
+
+ return result
+```
+
+### 📊 Use Case 3: Real-Time Streaming Dashboard
+
+A monitoring agent streams responses and displays progress in real-time.
+
+```typescript
+async function streamingDashboard(prompt: string) {
+ const response = await fetch(`${BASE_URL}/a2a`, {
+ method: "POST",
+ headers: { "Content-Type": "application/json", Authorization: `Bearer ${API_KEY}` },
+ body: JSON.stringify({
+ jsonrpc: "2.0",
+ id: "dash-1",
+ method: "message/stream",
+ params: { skill: "smart-routing", messages: [{ role: "user", content: prompt }] },
+ }),
+ });
+
+ let totalChunks = 0;
+ const reader = response.body!.getReader();
+ const decoder = new TextDecoder();
+
+ while (true) {
+ const { done, value } = await reader.read();
+ if (done) break;
+
+ for (const line of decoder.decode(value).split("\n")) {
+ if (line.startsWith("data: ")) {
+ const event = JSON.parse(line.slice(6));
+ const state = event.params.task.state;
+
+ if (state === "working" && event.params.chunk) {
+ totalChunks++;
+ process.stdout.write(
+ `\r[Chunk ${totalChunks}] ${event.params.chunk.content.slice(0, 50)}...`
+ );
+ }
+ if (state === "completed") {
+ const meta = event.params.metadata;
+ console.log(
+ `\n✅ Done | Cost: $${meta?.cost_envelope?.actual || 0} | Route: ${meta?.routing_explanation || "N/A"}`
+ );
+ }
+ if (state === "failed") {
+ console.error(`\n❌ Failed: ${event.params.metadata?.error}`);
+ }
+ }
+ }
+ }
+}
+```
+
+### 🔁 Use Case 4: Task Polling Pattern
+
+For long-running tasks, poll the task status instead of waiting synchronously.
+
+```python
+import time
+
+def poll_task(task_id: str, timeout: int = 60):
+ """Poll task status until completion or timeout."""
+ start = time.time()
+ while time.time() - start < timeout:
+ result = requests.post(f"{BASE_URL}/a2a", headers=HEADERS, json={
+ "jsonrpc": "2.0",
+ "id": "poll-1",
+ "method": "tasks/get",
+ "params": {"taskId": task_id},
+ }).json()
+
+ task = result["result"]["task"]
+ state = task["state"]
+ print(f" Task {task_id[:8]}... state={state}")
+
+ if state in ("completed", "failed", "cancelled"):
+ return task
+ time.sleep(2)
+
+ # Timeout — cancel the task
+ requests.post(f"{BASE_URL}/a2a", headers=HEADERS, json={
+ "jsonrpc": "2.0",
+ "id": "cancel-1",
+ "method": "tasks/cancel",
+ "params": {"taskId": task_id},
+ })
+ raise TimeoutError(f"Task {task_id} timed out after {timeout}s")
+```
+
+---
+
+## Error Codes
+
+| Code | Constant | Meaning |
+| ------ | ------------------------ | ---------------------------------------- |
+| -32700 | — | Parse error (invalid JSON) |
+| -32600 | `INVALID_REQUEST` | Invalid JSON-RPC request or unauthorized |
+| -32601 | `METHOD_NOT_FOUND` | Unknown method or skill |
+| -32602 | `INVALID_PARAMS` | Missing or invalid parameters |
+| -32603 | `INTERNAL_ERROR` | Skill execution failed |
+| -32001 | `TASK_NOT_FOUND` | Task ID not found |
+| -32002 | `TASK_ALREADY_COMPLETED` | Cannot modify a completed task |
+| -32003 | `UNAUTHORIZED` | Invalid or missing API key |
+| -32004 | `BUDGET_EXCEEDED` | Request exceeds configured budget |
+| -32005 | `PROVIDER_UNAVAILABLE` | No available providers |
+
+---
+
+## Authentication
+
+All `/a2a` requests require a Bearer token via the `Authorization` header:
+
+```
+Authorization: Bearer YOUR_OMNIROUTE_API_KEY
+```
+
+If no API key is configured on the server (`OMNIROUTE_API_KEY` is empty), authentication is bypassed.
+
+---
+
+## File Structure
+
+```
+src/lib/a2a/
+├── taskManager.ts # Task lifecycle (create/update/cancel/list), TTL, cleanup
+├── taskExecution.ts # Generic task executor with state management
+├── streaming.ts # SSE stream formatting, heartbeat, chunk/completion events
+├── routingLogger.ts # Routing decision logger (stats, history, retention)
+└── skills/
+ ├── smartRouting.ts # Smart routing skill (routes via /v1/chat/completions)
+ └── quotaManagement.ts # Quota management skill (natural-language quota queries)
+
+src/app/a2a/
+└── route.ts # Next.js API route handler (JSON-RPC 2.0 dispatch)
+
+open-sse/mcp-server/
+└── schemas/a2a.ts # Zod schemas (AgentCard, Task, JSON-RPC, SSE events)
+```
+
+---
+
+## Comparison: MCP vs A2A
+
+| Feature | MCP Server | A2A Server |
+| ----------------- | ---------------------------- | ------------------------------------------------- |
+| **Protocol** | Model Context Protocol | Agent-to-Agent Protocol v0.3 |
+| **Transport** | stdio / HTTP | HTTP (JSON-RPC 2.0) |
+| **Discovery** | Tool listing via MCP | `/.well-known/agent.json` |
+| **Granularity** | 16 individual tools | 2 high-level skills |
+| **Best for** | IDE agents (Cursor, VS Code) | Multi-agent systems (LangChain, CrewAI) |
+| **Streaming** | Not supported | SSE via `message/stream` |
+| **Task tracking** | No | Full lifecycle (submitted → completed) |
+| **Observability** | Audit log per tool call | Cost envelope + resilience trace + policy verdict |
+
+---
+
+## Licenc
+
+Part of [OmniRoute](https://github.com/diegosouzapw/OmniRoute) — MIT License.
diff --git a/docs/i18n/id/A2A-SERVER.md b/docs/i18n/id/A2A-SERVER.md
deleted file mode 100644
index 01531ff482..0000000000
--- a/docs/i18n/id/A2A-SERVER.md
+++ /dev/null
@@ -1,200 +0,0 @@
-🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/A2A-SERVER.md) · 🇪🇸 [es](../es/A2A-SERVER.md) · 🇫🇷 [fr](../fr/A2A-SERVER.md) · 🇩🇪 [de](../de/A2A-SERVER.md) · 🇮🇹 [it](../it/A2A-SERVER.md) · 🇷🇺 [ru](../ru/A2A-SERVER.md) · 🇨🇳 [zh-CN](../zh-CN/A2A-SERVER.md) · 🇯🇵 [ja](../ja/A2A-SERVER.md) · 🇰🇷 [ko](../ko/A2A-SERVER.md) · 🇸🇦 [ar](../ar/A2A-SERVER.md) · 🇮🇳 [in](../in/A2A-SERVER.md) · 🇹🇭 [th](../th/A2A-SERVER.md) · 🇻🇳 [vi](../vi/A2A-SERVER.md) · 🇮🇩 [id](../id/A2A-SERVER.md) · 🇲🇾 [ms](../ms/A2A-SERVER.md) · 🇳🇱 [nl](../nl/A2A-SERVER.md) · 🇵🇱 [pl](../pl/A2A-SERVER.md) · 🇸🇪 [sv](../sv/A2A-SERVER.md) · 🇳🇴 [no](../no/A2A-SERVER.md) · 🇩🇰 [da](../da/A2A-SERVER.md) · 🇫🇮 [fi](../fi/A2A-SERVER.md) · 🇵🇹 [pt](../pt/A2A-SERVER.md) · 🇷🇴 [ro](../ro/A2A-SERVER.md) · 🇭🇺 [hu](../hu/A2A-SERVER.md) · 🇧🇬 [bg](../bg/A2A-SERVER.md) · 🇸🇰 [sk](../sk/A2A-SERVER.md) · 🇺🇦 [uk-UA](../uk-UA/A2A-SERVER.md) · 🇮🇱 [he](../he/A2A-SERVER.md) · 🇵🇭 [phi](../phi/A2A-SERVER.md)
-
----
-
-# OmniRoute A2A Server Documentation
-
-> Agent-to-Agent Protocol v0.3 — OmniRoute as an intelligent routing agent
-
-## Agent Discovery
-
-```bash
-curl http://localhost:20128/.well-known/agent.json
-```
-
-Returns the Agent Card describing OmniRoute's capabilities, skills, and authentication requirements.
-
----
-
-## Authentication
-
-All `/a2a` requests require an API key via the `Authorization` header:
-
-```
-Authorization: Bearer YOUR_OMNIROUTE_API_KEY
-```
-
-If no API key is configured on the server, authentication is bypassed.
-
----
-
-## JSON-RPC 2.0 Methods
-
-### `message/send` — Synchronous Execution
-
-Sends a message to a skill and waits for the complete response.
-
-```bash
-curl -X POST http://localhost:20128/a2a \
- -H "Content-Type: application/json" \
- -H "Authorization: Bearer YOUR_KEY" \
- -d '{
- "jsonrpc": "2.0",
- "id": "1",
- "method": "message/send",
- "params": {
- "skill": "smart-routing",
- "messages": [{"role": "user", "content": "Write a hello world in Python"}],
- "metadata": {"model": "auto", "combo": "fast-coding"}
- }
- }'
-```
-
-**Response:**
-
-```json
-{
- "jsonrpc": "2.0",
- "id": "1",
- "result": {
- "task": { "id": "uuid", "state": "completed" },
- "artifacts": [{ "type": "text", "content": "..." }],
- "metadata": {
- "routing_explanation": "Selected claude-sonnet via provider \"anthropic\" (latency: 1200ms, cost: $0.003)",
- "cost_envelope": { "estimated": 0.005, "actual": 0.003, "currency": "USD" },
- "resilience_trace": [
- { "event": "primary_selected", "provider": "anthropic", "timestamp": "..." }
- ],
- "policy_verdict": { "allowed": true, "reason": "within budget and quota limits" }
- }
- }
-}
-```
-
-### `message/stream` — SSE Streaming
-
-Same as `message/send` but returns Server-Sent Events for real-time streaming.
-
-```bash
-curl -N -X POST http://localhost:20128/a2a \
- -H "Content-Type: application/json" \
- -H "Authorization: Bearer YOUR_KEY" \
- -d '{
- "jsonrpc": "2.0",
- "id": "1",
- "method": "message/stream",
- "params": {
- "skill": "smart-routing",
- "messages": [{"role": "user", "content": "Explain quantum computing"}]
- }
- }'
-```
-
-**SSE Events:**
-
-```
-data: {"jsonrpc":"2.0","method":"message/stream","params":{"task":{"id":"...","state":"working"},"chunk":{"type":"text","content":"..."}}}
-
-: heartbeat 2026-03-03T17:00:00Z
-
-data: {"jsonrpc":"2.0","method":"message/stream","params":{"task":{"id":"...","state":"completed"},"metadata":{...}}}
-```
-
-### `tasks/get` — Query Task Status
-
-```bash
-curl -X POST http://localhost:20128/a2a \
- -H "Content-Type: application/json" \
- -H "Authorization: Bearer YOUR_KEY" \
- -d '{"jsonrpc":"2.0","id":"2","method":"tasks/get","params":{"taskId":"TASK_UUID"}}'
-```
-
-### `tasks/cancel` — Cancel a Task
-
-```bash
-curl -X POST http://localhost:20128/a2a \
- -H "Content-Type: application/json" \
- -H "Authorization: Bearer YOUR_KEY" \
- -d '{"jsonrpc":"2.0","id":"3","method":"tasks/cancel","params":{"taskId":"TASK_UUID"}}'
-```
-
----
-
-## Available Skills
-
-| Skill | Description |
-| :----------------- | :------------------------------------------------------------------------------------------------------------------------------ |
-| `smart-routing` | Routes prompts through OmniRoute's intelligent pipeline. Returns response with routing explanation, cost, and resilience trace. |
-| `quota-management` | Answers natural-language queries about provider quotas, suggests free combos, and provides quota rankings. |
-
----
-
-## Task Lifecycle
-
-```
-submitted → working → completed
- → failed
- → cancelled
-```
-
-- Tasks expire after 5 minutes (configurable)
-- Terminal states: `completed`, `failed`, `cancelled`
-- Event log tracks every state transition
-
----
-
-## Error Codes
-
-| Code | Meaning |
-| :----- | :----------------------------- |
-| -32700 | Parse error (invalid JSON) |
-| -32600 | Invalid request / Unauthorized |
-| -32601 | Method or skill not found |
-| -32602 | Invalid params |
-| -32603 | Internal error |
-
----
-
-## Integration Examples
-
-### Python (requests)
-
-```python
-import requests
-
-resp = requests.post("http://localhost:20128/a2a", json={
- "jsonrpc": "2.0", "id": "1",
- "method": "message/send",
- "params": {
- "skill": "smart-routing",
- "messages": [{"role": "user", "content": "Hello"}]
- }
-}, headers={"Authorization": "Bearer YOUR_KEY"})
-
-result = resp.json()["result"]
-print(result["artifacts"][0]["content"])
-print(result["metadata"]["routing_explanation"])
-```
-
-### TypeScript (fetch)
-
-```typescript
-const resp = await fetch("http://localhost:20128/a2a", {
- method: "POST",
- headers: {
- "Content-Type": "application/json",
- Authorization: "Bearer YOUR_KEY",
- },
- body: JSON.stringify({
- jsonrpc: "2.0",
- id: "1",
- method: "message/send",
- params: {
- skill: "smart-routing",
- messages: [{ role: "user", content: "Hello" }],
- },
- }),
-});
-const { result } = await resp.json();
-console.log(result.metadata.routing_explanation);
-```
diff --git a/docs/i18n/id/API_REFERENCE.md b/docs/i18n/id/API_REFERENCE.md
deleted file mode 100644
index b878605221..0000000000
--- a/docs/i18n/id/API_REFERENCE.md
+++ /dev/null
@@ -1,455 +0,0 @@
-🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/API_REFERENCE.md) · 🇪🇸 [es](../es/API_REFERENCE.md) · 🇫🇷 [fr](../fr/API_REFERENCE.md) · 🇩🇪 [de](../de/API_REFERENCE.md) · 🇮🇹 [it](../it/API_REFERENCE.md) · 🇷🇺 [ru](../ru/API_REFERENCE.md) · 🇨🇳 [zh-CN](../zh-CN/API_REFERENCE.md) · 🇯🇵 [ja](../ja/API_REFERENCE.md) · 🇰🇷 [ko](../ko/API_REFERENCE.md) · 🇸🇦 [ar](../ar/API_REFERENCE.md) · 🇮🇳 [in](../in/API_REFERENCE.md) · 🇹🇭 [th](../th/API_REFERENCE.md) · 🇻🇳 [vi](../vi/API_REFERENCE.md) · 🇮🇩 [id](../id/API_REFERENCE.md) · 🇲🇾 [ms](../ms/API_REFERENCE.md) · 🇳🇱 [nl](../nl/API_REFERENCE.md) · 🇵🇱 [pl](../pl/API_REFERENCE.md) · 🇸🇪 [sv](../sv/API_REFERENCE.md) · 🇳🇴 [no](../no/API_REFERENCE.md) · 🇩🇰 [da](../da/API_REFERENCE.md) · 🇫🇮 [fi](../fi/API_REFERENCE.md) · 🇵🇹 [pt](../pt/API_REFERENCE.md) · 🇷🇴 [ro](../ro/API_REFERENCE.md) · 🇭🇺 [hu](../hu/API_REFERENCE.md) · 🇧🇬 [bg](../bg/API_REFERENCE.md) · 🇸🇰 [sk](../sk/API_REFERENCE.md) · 🇺🇦 [uk-UA](../uk-UA/API_REFERENCE.md) · 🇮🇱 [he](../he/API_REFERENCE.md) · 🇵🇭 [phi](../phi/API_REFERENCE.md)
-
----
-
-# API Reference
-
-🌐 **Languages:** 🇺🇸 [English](API_REFERENCE.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/API_REFERENCE.md) | 🇪🇸 [Español](i18n/es/API_REFERENCE.md) | 🇫🇷 [Français](i18n/fr/API_REFERENCE.md) | 🇮🇹 [Italiano](i18n/it/API_REFERENCE.md) | 🇷🇺 [Русский](i18n/ru/API_REFERENCE.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/API_REFERENCE.md) | 🇩🇪 [Deutsch](i18n/de/API_REFERENCE.md) | 🇮🇳 [हिन्दी](i18n/in/API_REFERENCE.md) | 🇹🇭 [ไทย](i18n/th/API_REFERENCE.md) | 🇺🇦 [Українська](i18n/uk-UA/API_REFERENCE.md) | 🇸🇦 [العربية](i18n/ar/API_REFERENCE.md) | 🇯🇵 [日本語](i18n/ja/API_REFERENCE.md) | 🇻🇳 [Tiếng Việt](i18n/vi/API_REFERENCE.md) | 🇧🇬 [Български](i18n/bg/API_REFERENCE.md) | 🇩🇰 [Dansk](i18n/da/API_REFERENCE.md) | 🇫🇮 [Suomi](i18n/fi/API_REFERENCE.md) | 🇮🇱 [עברית](i18n/he/API_REFERENCE.md) | 🇭🇺 [Magyar](i18n/hu/API_REFERENCE.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/API_REFERENCE.md) | 🇰🇷 [한국어](i18n/ko/API_REFERENCE.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/API_REFERENCE.md) | 🇳🇱 [Nederlands](i18n/nl/API_REFERENCE.md) | 🇳🇴 [Norsk](i18n/no/API_REFERENCE.md) | 🇵🇹 [Português (Portugal)](i18n/pt/API_REFERENCE.md) | 🇷🇴 [Română](i18n/ro/API_REFERENCE.md) | 🇵🇱 [Polski](i18n/pl/API_REFERENCE.md) | 🇸🇰 [Slovenčina](i18n/sk/API_REFERENCE.md) | 🇸🇪 [Svenska](i18n/sv/API_REFERENCE.md) | 🇵🇭 [Filipino](i18n/phi/API_REFERENCE.md)
-
-Complete reference for all OmniRoute API endpoints.
-
----
-
-## Table of Contents
-
-- [Chat Completions](#chat-completions)
-- [Embeddings](#embeddings)
-- [Image Generation](#image-generation)
-- [List Models](#list-models)
-- [Compatibility Endpoints](#compatibility-endpoints)
-- [Semantic Cache](#semantic-cache)
-- [Dashboard & Management](#dashboard--management)
-- [Request Processing](#request-processing)
-- [Authentication](#authentication)
-
----
-
-## Chat Completions
-
-```bash
-POST /v1/chat/completions
-Authorization: Bearer your-api-key
-Content-Type: application/json
-
-{
- "model": "cc/claude-opus-4-6",
- "messages": [
- {"role": "user", "content": "Write a function to..."}
- ],
- "stream": true
-}
-```
-
-### Custom Headers
-
-| Header | Direction | Description |
-| ------------------------ | --------- | --------------------------------- |
-| `X-OmniRoute-No-Cache` | Request | Set to `true` to bypass cache |
-| `X-OmniRoute-Progress` | Request | Set to `true` for progress events |
-| `Idempotency-Key` | Request | Dedup key (5s window) |
-| `X-Request-Id` | Request | Alternative dedup key |
-| `X-OmniRoute-Cache` | Response | `HIT` or `MISS` (non-streaming) |
-| `X-OmniRoute-Idempotent` | Response | `true` if deduplicated |
-| `X-OmniRoute-Progress` | Response | `enabled` if progress tracking on |
-
----
-
-## Embeddings
-
-```bash
-POST /v1/embeddings
-Authorization: Bearer your-api-key
-Content-Type: application/json
-
-{
- "model": "nebius/Qwen/Qwen3-Embedding-8B",
- "input": "The food was delicious"
-}
-```
-
-Available providers: Nebius, OpenAI, Mistral, Together AI, Fireworks, NVIDIA.
-
-```bash
-# List all embedding models
-GET /v1/embeddings
-```
-
----
-
-## Image Generation
-
-```bash
-POST /v1/images/generations
-Authorization: Bearer your-api-key
-Content-Type: application/json
-
-{
- "model": "openai/dall-e-3",
- "prompt": "A beautiful sunset over mountains",
- "size": "1024x1024"
-}
-```
-
-Available providers: OpenAI (DALL-E), xAI (Grok Image), Together AI (FLUX), Fireworks AI.
-
-```bash
-# List all image models
-GET /v1/images/generations
-```
-
----
-
-## List Models
-
-```bash
-GET /v1/models
-Authorization: Bearer your-api-key
-
-→ Returns all chat, embedding, and image models + combos in OpenAI format
-```
-
----
-
-## Compatibility Endpoints
-
-| Method | Path | Format |
-| ------ | --------------------------- | ---------------------- |
-| POST | `/v1/chat/completions` | OpenAI |
-| POST | `/v1/messages` | Anthropic |
-| POST | `/v1/responses` | OpenAI Responses |
-| POST | `/v1/embeddings` | OpenAI |
-| POST | `/v1/images/generations` | OpenAI |
-| GET | `/v1/models` | OpenAI |
-| POST | `/v1/messages/count_tokens` | Anthropic |
-| GET | `/v1beta/models` | Gemini |
-| POST | `/v1beta/models/{...path}` | Gemini generateContent |
-| POST | `/v1/api/chat` | Ollama |
-
-### Dedicated Provider Routes
-
-```bash
-POST /v1/providers/{provider}/chat/completions
-POST /v1/providers/{provider}/embeddings
-POST /v1/providers/{provider}/images/generations
-```
-
-The provider prefix is auto-added if missing. Mismatched models return `400`.
-
----
-
-## Semantic Cache
-
-```bash
-# Get cache stats
-GET /api/cache
-
-# Clear all caches
-DELETE /api/cache
-```
-
-Response example:
-
-```json
-{
- "semanticCache": {
- "memorySize": 42,
- "memoryMaxSize": 500,
- "dbSize": 128,
- "hitRate": 0.65
- },
- "idempotency": {
- "activeKeys": 3,
- "windowMs": 5000
- }
-}
-```
-
----
-
-## Dashboard & Management
-
-### Authentication
-
-| Endpoint | Method | Description |
-| ----------------------------- | ------- | --------------------- |
-| `/api/auth/login` | POST | Login |
-| `/api/auth/logout` | POST | Logout |
-| `/api/settings/require-login` | GET/PUT | Toggle login required |
-
-### Provider Management
-
-| Endpoint | Method | Description |
-| ---------------------------- | --------------- | ------------------------ |
-| `/api/providers` | GET/POST | List / create providers |
-| `/api/providers/[id]` | GET/PUT/DELETE | Manage a provider |
-| `/api/providers/[id]/test` | POST | Test provider connection |
-| `/api/providers/[id]/models` | GET | List provider models |
-| `/api/providers/validate` | POST | Validate provider config |
-| `/api/provider-nodes*` | Various | Provider node management |
-| `/api/provider-models` | GET/POST/DELETE | Custom models |
-
-### OAuth Flows
-
-| Endpoint | Method | Description |
-| -------------------------------- | ------- | ----------------------- |
-| `/api/oauth/[provider]/[action]` | Various | Provider-specific OAuth |
-
-### Routing & Config
-
-| Endpoint | Method | Description |
-| --------------------- | -------- | ----------------------------- |
-| `/api/models/alias` | GET/POST | Model aliases |
-| `/api/models/catalog` | GET | All models by provider + type |
-| `/api/combos*` | Various | Combo management |
-| `/api/keys*` | Various | API key management |
-| `/api/pricing` | GET | Model pricing |
-
-### Usage & Analytics
-
-| Endpoint | Method | Description |
-| --------------------------- | ------ | -------------------- |
-| `/api/usage/history` | GET | Usage history |
-| `/api/usage/logs` | GET | Usage logs |
-| `/api/usage/request-logs` | GET | Request-level logs |
-| `/api/usage/[connectionId]` | GET | Per-connection usage |
-
-### Settings
-
-| Endpoint | Method | Description |
-| ------------------------------- | ------- | ---------------------- |
-| `/api/settings` | GET/PUT | General settings |
-| `/api/settings/proxy` | GET/PUT | Network proxy config |
-| `/api/settings/proxy/test` | POST | Test proxy connection |
-| `/api/settings/ip-filter` | GET/PUT | IP allowlist/blocklist |
-| `/api/settings/thinking-budget` | GET/PUT | Reasoning token budget |
-| `/api/settings/system-prompt` | GET/PUT | Global system prompt |
-
-### Monitoring
-
-| Endpoint | Method | Description |
-| ------------------------ | ---------- | ----------------------- |
-| `/api/sessions` | GET | Active session tracking |
-| `/api/rate-limits` | GET | Per-account rate limits |
-| `/api/monitoring/health` | GET | Health check |
-| `/api/cache` | GET/DELETE | Cache stats / clear |
-
-### Backup & Export/Import
-
-| Endpoint | Method | Description |
-| --------------------------- | ------ | --------------------------------------- |
-| `/api/db-backups` | GET | List available backups |
-| `/api/db-backups` | PUT | Create a manual backup |
-| `/api/db-backups` | POST | Restore from a specific backup |
-| `/api/db-backups/export` | GET | Download database as .sqlite file |
-| `/api/db-backups/import` | POST | Upload .sqlite file to replace database |
-| `/api/db-backups/exportAll` | GET | Download full backup as .tar.gz archive |
-
-### Cloud Sync
-
-| Endpoint | Method | Description |
-| ---------------------- | ------- | --------------------- |
-| `/api/sync/cloud` | Various | Cloud sync operations |
-| `/api/sync/initialize` | POST | Initialize sync |
-| `/api/cloud/*` | Various | Cloud management |
-
-### CLI Tools
-
-| Endpoint | Method | Description |
-| ---------------------------------- | ------ | ------------------- |
-| `/api/cli-tools/claude-settings` | GET | Claude CLI status |
-| `/api/cli-tools/codex-settings` | GET | Codex CLI status |
-| `/api/cli-tools/droid-settings` | GET | Droid CLI status |
-| `/api/cli-tools/openclaw-settings` | GET | OpenClaw CLI status |
-| `/api/cli-tools/runtime/[toolId]` | GET | Generic CLI runtime |
-
-CLI responses include: `installed`, `runnable`, `command`, `commandPath`, `runtimeMode`, `reason`.
-
-### ACP Agents
-
-| Endpoint | Method | Description |
-| ----------------- | ------ | -------------------------------------------------------- |
-| `/api/acp/agents` | GET | List all detected agents (built-in + custom) with status |
-| `/api/acp/agents` | POST | Add custom agent or refresh detection cache |
-| `/api/acp/agents` | DELETE | Remove a custom agent by `id` query param |
-
-GET response includes `agents[]` (id, name, binary, version, installed, protocol, isCustom) and `summary` (total, installed, notFound, builtIn, custom).
-
-### Resilience & Rate Limits
-
-| Endpoint | Method | Description |
-| ----------------------- | ------- | ------------------------------- |
-| `/api/resilience` | GET/PUT | Get/update resilience profiles |
-| `/api/resilience/reset` | POST | Reset circuit breakers |
-| `/api/rate-limits` | GET | Per-account rate limit status |
-| `/api/rate-limit` | GET | Global rate limit configuration |
-
-### Evals
-
-| Endpoint | Method | Description |
-| ------------ | -------- | --------------------------------- |
-| `/api/evals` | GET/POST | List eval suites / run evaluation |
-
-### Policies
-
-| Endpoint | Method | Description |
-| --------------- | --------------- | ----------------------- |
-| `/api/policies` | GET/POST/DELETE | Manage routing policies |
-
-### Compliance
-
-| Endpoint | Method | Description |
-| --------------------------- | ------ | ----------------------------- |
-| `/api/compliance/audit-log` | GET | Compliance audit log (last N) |
-
-### v1beta (Gemini-Compatible)
-
-| Endpoint | Method | Description |
-| -------------------------- | ------ | --------------------------------- |
-| `/v1beta/models` | GET | List models in Gemini format |
-| `/v1beta/models/{...path}` | POST | Gemini `generateContent` endpoint |
-
-These endpoints mirror Gemini's API format for clients that expect native Gemini SDK compatibility.
-
-### Internal / System APIs
-
-| Endpoint | Method | Description |
-| --------------- | ------ | ---------------------------------------------------- |
-| `/api/init` | GET | Application initialization check (used on first run) |
-| `/api/tags` | GET | Ollama-compatible model tags (for Ollama clients) |
-| `/api/restart` | POST | Trigger graceful server restart |
-| `/api/shutdown` | POST | Trigger graceful server shutdown |
-
-> **Note:** These endpoints are used internally by the system or for Ollama client compatibility. They are not typically called by end users.
-
----
-
-## Audio Transcription
-
-```bash
-POST /v1/audio/transcriptions
-Authorization: Bearer your-api-key
-Content-Type: multipart/form-data
-```
-
-Transcribe audio files using Deepgram or AssemblyAI.
-
-**Request:**
-
-```bash
-curl -X POST http://localhost:20128/v1/audio/transcriptions \
- -H "Authorization: Bearer your-api-key" \
- -F "file=@recording.mp3" \
- -F "model=deepgram/nova-3"
-```
-
-**Response:**
-
-```json
-{
- "text": "Hello, this is the transcribed audio content.",
- "task": "transcribe",
- "language": "en",
- "duration": 12.5
-}
-```
-
-**Supported providers:** `deepgram/nova-3`, `assemblyai/best`.
-
-**Supported formats:** `mp3`, `wav`, `m4a`, `flac`, `ogg`, `webm`.
-
----
-
-## Ollama Compatibility
-
-For clients that use Ollama's API format:
-
-```bash
-# Chat endpoint (Ollama format)
-POST /v1/api/chat
-
-# Model listing (Ollama format)
-GET /api/tags
-```
-
-Requests are automatically translated between Ollama and internal formats.
-
----
-
-## Telemetry
-
-```bash
-# Get latency telemetry summary (p50/p95/p99 per provider)
-GET /api/telemetry/summary
-```
-
-**Response:**
-
-```json
-{
- "providers": {
- "claudeCode": { "p50": 245, "p95": 890, "p99": 1200, "count": 150 },
- "github": { "p50": 180, "p95": 620, "p99": 950, "count": 320 }
- }
-}
-```
-
----
-
-## Budget
-
-```bash
-# Get budget status for all API keys
-GET /api/usage/budget
-
-# Set or update a budget
-POST /api/usage/budget
-Content-Type: application/json
-
-{
- "keyId": "key-123",
- "limit": 50.00,
- "period": "monthly"
-}
-```
-
----
-
-## Model Availability
-
-```bash
-# Get real-time model availability across all providers
-GET /api/models/availability
-
-# Check availability for a specific model
-POST /api/models/availability
-Content-Type: application/json
-
-{
- "model": "claude-sonnet-4-5-20250929"
-}
-```
-
----
-
-## Request Processing
-
-1. Client sends request to `/v1/*`
-2. Route handler calls `handleChat`, `handleEmbedding`, `handleAudioTranscription`, or `handleImageGeneration`
-3. Model is resolved (direct provider/model or alias/combo)
-4. Credentials selected from local DB with account availability filtering
-5. For chat: `handleChatCore` — format detection, translation, cache check, idempotency check
-6. Provider executor sends upstream request
-7. Response translated back to client format (chat) or returned as-is (embeddings/images/audio)
-8. Usage/logging recorded
-9. Fallback applies on errors according to combo rules
-
-Full architecture reference: [`ARCHITECTURE.md`](ARCHITECTURE.md)
-
----
-
-## Authentication
-
-- Dashboard routes (`/dashboard/*`) use `auth_token` cookie
-- Login uses saved password hash; fallback to `INITIAL_PASSWORD`
-- `requireLogin` toggleable via `/api/settings/require-login`
-- `/v1/*` routes optionally require Bearer API key when `REQUIRE_API_KEY=true`
diff --git a/docs/i18n/id/ARCHITECTURE.md b/docs/i18n/id/ARCHITECTURE.md
deleted file mode 100644
index 4ea06a29f2..0000000000
--- a/docs/i18n/id/ARCHITECTURE.md
+++ /dev/null
@@ -1,787 +0,0 @@
-🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/ARCHITECTURE.md) · 🇪🇸 [es](../es/ARCHITECTURE.md) · 🇫🇷 [fr](../fr/ARCHITECTURE.md) · 🇩🇪 [de](../de/ARCHITECTURE.md) · 🇮🇹 [it](../it/ARCHITECTURE.md) · 🇷🇺 [ru](../ru/ARCHITECTURE.md) · 🇨🇳 [zh-CN](../zh-CN/ARCHITECTURE.md) · 🇯🇵 [ja](../ja/ARCHITECTURE.md) · 🇰🇷 [ko](../ko/ARCHITECTURE.md) · 🇸🇦 [ar](../ar/ARCHITECTURE.md) · 🇮🇳 [in](../in/ARCHITECTURE.md) · 🇹🇭 [th](../th/ARCHITECTURE.md) · 🇻🇳 [vi](../vi/ARCHITECTURE.md) · 🇮🇩 [id](../id/ARCHITECTURE.md) · 🇲🇾 [ms](../ms/ARCHITECTURE.md) · 🇳🇱 [nl](../nl/ARCHITECTURE.md) · 🇵🇱 [pl](../pl/ARCHITECTURE.md) · 🇸🇪 [sv](../sv/ARCHITECTURE.md) · 🇳🇴 [no](../no/ARCHITECTURE.md) · 🇩🇰 [da](../da/ARCHITECTURE.md) · 🇫🇮 [fi](../fi/ARCHITECTURE.md) · 🇵🇹 [pt](../pt/ARCHITECTURE.md) · 🇷🇴 [ro](../ro/ARCHITECTURE.md) · 🇭🇺 [hu](../hu/ARCHITECTURE.md) · 🇧🇬 [bg](../bg/ARCHITECTURE.md) · 🇸🇰 [sk](../sk/ARCHITECTURE.md) · 🇺🇦 [uk-UA](../uk-UA/ARCHITECTURE.md) · 🇮🇱 [he](../he/ARCHITECTURE.md) · 🇵🇭 [phi](../phi/ARCHITECTURE.md)
-
----
-
-# OmniRoute Architecture
-
-🌐 **Languages:** 🇺🇸 [English](ARCHITECTURE.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/ARCHITECTURE.md) | 🇪🇸 [Español](i18n/es/ARCHITECTURE.md) | 🇫🇷 [Français](i18n/fr/ARCHITECTURE.md) | 🇮🇹 [Italiano](i18n/it/ARCHITECTURE.md) | 🇷🇺 [Русский](i18n/ru/ARCHITECTURE.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/ARCHITECTURE.md) | 🇩🇪 [Deutsch](i18n/de/ARCHITECTURE.md) | 🇮🇳 [हिन्दी](i18n/in/ARCHITECTURE.md) | 🇹🇭 [ไทย](i18n/th/ARCHITECTURE.md) | 🇺🇦 [Українська](i18n/uk-UA/ARCHITECTURE.md) | 🇸🇦 [العربية](i18n/ar/ARCHITECTURE.md) | 🇯🇵 [日本語](i18n/ja/ARCHITECTURE.md) | 🇻🇳 [Tiếng Việt](i18n/vi/ARCHITECTURE.md) | 🇧🇬 [Български](i18n/bg/ARCHITECTURE.md) | 🇩🇰 [Dansk](i18n/da/ARCHITECTURE.md) | 🇫🇮 [Suomi](i18n/fi/ARCHITECTURE.md) | 🇮🇱 [עברית](i18n/he/ARCHITECTURE.md) | 🇭🇺 [Magyar](i18n/hu/ARCHITECTURE.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/ARCHITECTURE.md) | 🇰🇷 [한국어](i18n/ko/ARCHITECTURE.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/ARCHITECTURE.md) | 🇳🇱 [Nederlands](i18n/nl/ARCHITECTURE.md) | 🇳🇴 [Norsk](i18n/no/ARCHITECTURE.md) | 🇵🇹 [Português (Portugal)](i18n/pt/ARCHITECTURE.md) | 🇷🇴 [Română](i18n/ro/ARCHITECTURE.md) | 🇵🇱 [Polski](i18n/pl/ARCHITECTURE.md) | 🇸🇰 [Slovenčina](i18n/sk/ARCHITECTURE.md) | 🇸🇪 [Svenska](i18n/sv/ARCHITECTURE.md) | 🇵🇭 [Filipino](i18n/phi/ARCHITECTURE.md)
-
-_Last updated: 2026-03-04_
-
-## Executive Summary
-
-OmniRoute is a local AI routing gateway and dashboard built on Next.js.
-It provides a single OpenAI-compatible endpoint (`/v1/*`) and routes traffic across multiple upstream providers with translation, fallback, token refresh, and usage tracking.
-
-Core capabilities:
-
-- OpenAI-compatible API surface for CLI/tools (28 providers)
-- Request/response translation across provider formats
-- Model combo fallback (multi-model sequence)
-- Account-level fallback (multi-account per provider)
-- OAuth + API-key provider connection management
-- Embedding generation via `/v1/embeddings` (6 providers, 9 models)
-- Image generation via `/v1/images/generations` (4 providers, 9 models)
-- Think tag parsing (`...`) for reasoning models
-- Response sanitization for strict OpenAI SDK compatibility
-- Role normalization (developer→system, system→user) for cross-provider compatibility
-- Structured output conversion (json_schema → Gemini responseSchema)
-- Local persistence for providers, keys, aliases, combos, settings, pricing
-- Usage/cost tracking and request logging
-- Optional cloud sync for multi-device/state sync
-- IP allowlist/blocklist for API access control
-- Thinking budget management (passthrough/auto/custom/adaptive)
-- Global system prompt injection
-- Session tracking and fingerprinting
-- Per-account enhanced rate limiting with provider-specific profiles
-- Circuit breaker pattern for provider resilience
-- Anti-thundering herd protection with mutex locking
-- Signature-based request deduplication cache
-- Domain layer: model availability, cost rules, fallback policy, lockout policy
-- Domain state persistence (SQLite write-through cache for fallbacks, budgets, lockouts, circuit breakers)
-- Policy engine for centralized request evaluation (lockout → budget → fallback)
-- Request telemetry with p50/p95/p99 latency aggregation
-- Correlation ID (X-Request-Id) for end-to-end tracing
-- Compliance audit logging with opt-out per API key
-- Eval framework for LLM quality assurance
-- Resilience UI dashboard with real-time circuit breaker status
-- Modular OAuth providers (12 individual modules under `src/lib/oauth/providers/`)
-
-Primary runtime model:
-
-- Next.js app routes under `src/app/api/*` implement both dashboard APIs and compatibility APIs
-- A shared SSE/routing core in `src/sse/*` + `open-sse/*` handles provider execution, translation, streaming, fallback, and usage
-
-## Scope and Boundaries
-
-### In Scope
-
-- Local gateway runtime
-- Dashboard management APIs
-- Provider authentication and token refresh
-- Request translation and SSE streaming
-- Local state + usage persistence
-- Optional cloud sync orchestration
-
-### Out of Scope
-
-- Cloud service implementation behind `NEXT_PUBLIC_CLOUD_URL`
-- Provider SLA/control plane outside local process
-- External CLI binaries themselves (Claude CLI, Codex CLI, etc.)
-
-## High-Level System Context
-
-```mermaid
-flowchart LR
- subgraph Clients[Developer Clients]
- C1[Claude Code]
- C2[Codex CLI]
- C3[OpenClaw / Droid / Cline / Continue / Roo]
- C4[Custom OpenAI-compatible clients]
- BROWSER[Browser Dashboard]
- end
-
- subgraph Router[OmniRoute Local Process]
- API[V1 Compatibility API\n/v1/*]
- DASH[Dashboard + Management API\n/api/*]
- CORE[SSE + Translation Core\nopen-sse + src/sse]
- DB[(storage.sqlite)]
- UDB[(usage tables + log artifacts)]
- end
-
- subgraph Upstreams[Upstream Providers]
- P1[OAuth Providers\nClaude/Codex/Gemini/Qwen/Qoder/GitHub/Kiro/Cursor/Antigravity]
- P2[API Key Providers\nOpenAI/Anthropic/OpenRouter/GLM/Kimi/MiniMax\nDeepSeek/Groq/xAI/Mistral/Perplexity\nTogether/Fireworks/Cerebras/Cohere/NVIDIA]
- P3[Compatible Nodes\nOpenAI-compatible / Anthropic-compatible]
- end
-
- subgraph Cloud[Optional Cloud Sync]
- CLOUD[Cloud Sync Endpoint\nNEXT_PUBLIC_CLOUD_URL]
- end
-
- C1 --> API
- C2 --> API
- C3 --> API
- C4 --> API
- BROWSER --> DASH
-
- API --> CORE
- DASH --> DB
- CORE --> DB
- CORE --> UDB
-
- CORE --> P1
- CORE --> P2
- CORE --> P3
-
- DASH --> CLOUD
-```
-
-## Core Runtime Components
-
-## 1) API and Routing Layer (Next.js App Routes)
-
-Main directories:
-
-- `src/app/api/v1/*` and `src/app/api/v1beta/*` for compatibility APIs
-- `src/app/api/*` for management/configuration APIs
-- Next rewrites in `next.config.mjs` map `/v1/*` to `/api/v1/*`
-
-Important compatibility routes:
-
-- `src/app/api/v1/chat/completions/route.ts`
-- `src/app/api/v1/messages/route.ts`
-- `src/app/api/v1/responses/route.ts`
-- `src/app/api/v1/models/route.ts` — includes custom models with `custom: true`
-- `src/app/api/v1/embeddings/route.ts` — embedding generation (6 providers)
-- `src/app/api/v1/images/generations/route.ts` — image generation (4+ providers incl. Antigravity/Nebius)
-- `src/app/api/v1/messages/count_tokens/route.ts`
-- `src/app/api/v1/providers/[provider]/chat/completions/route.ts` — dedicated per-provider chat
-- `src/app/api/v1/providers/[provider]/embeddings/route.ts` — dedicated per-provider embeddings
-- `src/app/api/v1/providers/[provider]/images/generations/route.ts` — dedicated per-provider images
-- `src/app/api/v1beta/models/route.ts`
-- `src/app/api/v1beta/models/[...path]/route.ts`
-
-Management domains:
-
-- Auth/settings: `src/app/api/auth/*`, `src/app/api/settings/*`
-- Providers/connections: `src/app/api/providers*`
-- Provider nodes: `src/app/api/provider-nodes*`
-- Custom models: `src/app/api/provider-models` (GET/POST/DELETE)
-- Model catalog: `src/app/api/models/route.ts` (GET)
-- Proxy config: `src/app/api/settings/proxy` (GET/PUT/DELETE) + `src/app/api/settings/proxy/test` (POST)
-- OAuth: `src/app/api/oauth/*`
-- Keys/aliases/combos/pricing: `src/app/api/keys*`, `src/app/api/models/alias`, `src/app/api/combos*`, `src/app/api/pricing`
-- Usage: `src/app/api/usage/*`
-- Sync/cloud: `src/app/api/sync/*`, `src/app/api/cloud/*`
-- CLI tooling helpers: `src/app/api/cli-tools/*`
-- IP filter: `src/app/api/settings/ip-filter` (GET/PUT)
-- Thinking budget: `src/app/api/settings/thinking-budget` (GET/PUT)
-- System prompt: `src/app/api/settings/system-prompt` (GET/PUT)
-- Sessions: `src/app/api/sessions` (GET)
-- Rate limits: `src/app/api/rate-limits` (GET)
-- Resilience: `src/app/api/resilience` (GET/PATCH) — provider profiles, circuit breaker, rate limit state
-- Resilience reset: `src/app/api/resilience/reset` (POST) — reset breakers + cooldowns
-- Cache stats: `src/app/api/cache/stats` (GET/DELETE)
-- Model availability: `src/app/api/models/availability` (GET/POST)
-- Telemetry: `src/app/api/telemetry/summary` (GET)
-- Budget: `src/app/api/usage/budget` (GET/POST)
-- Fallback chains: `src/app/api/fallback/chains` (GET/POST/DELETE)
-- Compliance audit: `src/app/api/compliance/audit-log` (GET)
-- Evals: `src/app/api/evals` (GET/POST), `src/app/api/evals/[suiteId]` (GET)
-- Policies: `src/app/api/policies` (GET/POST)
-
-## 2) SSE + Translation Core
-
-Main flow modules:
-
-- Entry: `src/sse/handlers/chat.ts`
-- Core orchestration: `open-sse/handlers/chatCore.ts`
-- Provider execution adapters: `open-sse/executors/*`
-- Format detection/provider config: `open-sse/services/provider.ts`
-- Model parse/resolve: `src/sse/services/model.ts`, `open-sse/services/model.ts`
-- Account fallback logic: `open-sse/services/accountFallback.ts`
-- Translation registry: `open-sse/translator/index.ts`
-- Stream transformations: `open-sse/utils/stream.ts`, `open-sse/utils/streamHandler.ts`
-- Usage extraction/normalization: `open-sse/utils/usageTracking.ts`
-- Think tag parser: `open-sse/utils/thinkTagParser.ts`
-- Embedding handler: `open-sse/handlers/embeddings.ts`
-- Embedding provider registry: `open-sse/config/embeddingRegistry.ts`
-- Image generation handler: `open-sse/handlers/imageGeneration.ts`
-- Image provider registry: `open-sse/config/imageRegistry.ts`
-- Response sanitization: `open-sse/handlers/responseSanitizer.ts`
-- Role normalization: `open-sse/services/roleNormalizer.ts`
-
-Services (business logic):
-
-- Account selection/scoring: `open-sse/services/accountSelector.ts`
-- Context lifecycle management: `open-sse/services/contextManager.ts`
-- IP filter enforcement: `open-sse/services/ipFilter.ts`
-- Session tracking: `open-sse/services/sessionManager.ts`
-- Request deduplication: `open-sse/services/signatureCache.ts`
-- System prompt injection: `open-sse/services/systemPrompt.ts`
-- Thinking budget management: `open-sse/services/thinkingBudget.ts`
-- Wildcard model routing: `open-sse/services/wildcardRouter.ts`
-- Rate limit management: `open-sse/services/rateLimitManager.ts`
-- Circuit breaker: `open-sse/services/circuitBreaker.ts`
-
-Domain layer modules:
-
-- Model availability: `src/lib/domain/modelAvailability.ts`
-- Cost rules/budgets: `src/lib/domain/costRules.ts`
-- Fallback policy: `src/lib/domain/fallbackPolicy.ts`
-- Combo resolver: `src/lib/domain/comboResolver.ts`
-- Lockout policy: `src/lib/domain/lockoutPolicy.ts`
-- Policy engine: `src/domain/policyEngine.ts` — centralized lockout → budget → fallback evaluation
-- Error codes catalog: `src/lib/domain/errorCodes.ts`
-- Request ID: `src/lib/domain/requestId.ts`
-- Fetch timeout: `src/lib/domain/fetchTimeout.ts`
-- Request telemetry: `src/lib/domain/requestTelemetry.ts`
-- Compliance/audit: `src/lib/domain/compliance/index.ts`
-- Eval runner: `src/lib/domain/evalRunner.ts`
-- Domain state persistence: `src/lib/db/domainState.ts` — SQLite CRUD for fallback chains, budgets, cost history, lockout state, circuit breakers
-
-OAuth provider modules (12 individual files under `src/lib/oauth/providers/`):
-
-- Registry index: `src/lib/oauth/providers/index.ts`
-- Individual providers: `claude.ts`, `codex.ts`, `gemini.ts`, `antigravity.ts`, `qoder.ts`, `qwen.ts`, `kimi-coding.ts`, `github.ts`, `kiro.ts`, `cursor.ts`, `kilocode.ts`, `cline.ts`
-- Thin wrapper: `src/lib/oauth/providers.ts` — re-exports from individual modules
-
-## 3) Persistence Layer
-
-Primary state DB (SQLite):
-
-- Core infra: `src/lib/db/core.ts` (better-sqlite3, migrations, WAL)
-- Re-export facade: `src/lib/localDb.ts` (thin compatibility layer for callers)
-- file: `${DATA_DIR}/storage.sqlite` (or `$XDG_CONFIG_HOME/omniroute/storage.sqlite` when set, else `~/.omniroute/storage.sqlite`)
-- entities (tables + KV namespaces): providerConnections, providerNodes, modelAliases, combos, apiKeys, settings, pricing, **customModels**, **proxyConfig**, **ipFilter**, **thinkingBudget**, **systemPrompt**
-
-Usage persistence:
-
-- facade: `src/lib/usageDb.ts` (decomposed modules in `src/lib/usage/*`)
-- SQLite tables in `storage.sqlite`: `usage_history`, `call_logs`, `proxy_logs`
-- optional file artifacts remain for compatibility/debug (`${DATA_DIR}/log.txt`, `${DATA_DIR}/call_logs/`, `/logs/...`)
-- legacy JSON files are migrated to SQLite by startup migrations when present
-
-Domain State DB (SQLite):
-
-- `src/lib/db/domainState.ts` — CRUD operations for domain state
-- Tables (created in `src/lib/db/core.ts`): `domain_fallback_chains`, `domain_budgets`, `domain_cost_history`, `domain_lockout_state`, `domain_circuit_breakers`
-- Write-through cache pattern: in-memory Maps are authoritative at runtime; mutations are written synchronously to SQLite; state is restored from DB on cold start
-
-## 4) Auth + Security Surfaces
-
-- Dashboard cookie auth: `src/proxy.ts`, `src/app/api/auth/login/route.ts`
-- API key generation/verification: `src/shared/utils/apiKey.ts`
-- Provider secrets persisted in `providerConnections` entries
-- Outbound proxy support via `open-sse/utils/proxyFetch.ts` (env vars) and `open-sse/utils/networkProxy.ts` (configurable per-provider or global)
-
-## 5) Cloud Sync
-
-- Scheduler init: `src/lib/initCloudSync.ts`, `src/shared/services/initializeCloudSync.ts`
-- Periodic task: `src/shared/services/cloudSyncScheduler.ts`
-- Control route: `src/app/api/sync/cloud/route.ts`
-
-## Request Lifecycle (`/v1/chat/completions`)
-
-```mermaid
-sequenceDiagram
- autonumber
- participant Client as CLI/SDK Client
- participant Route as /api/v1/chat/completions
- participant Chat as src/sse/handlers/chat
- participant Core as open-sse/handlers/chatCore
- participant Model as Model Resolver
- participant Auth as Credential Selector
- participant Exec as Provider Executor
- participant Prov as Upstream Provider
- participant Stream as Stream Translator
- participant Usage as usageDb
-
- Client->>Route: POST /v1/chat/completions
- Route->>Chat: handleChat(request)
- Chat->>Model: parse/resolve model or combo
-
- alt Combo model
- Chat->>Chat: iterate combo models (handleComboChat)
- end
-
- Chat->>Auth: getProviderCredentials(provider)
- Auth-->>Chat: active account + tokens/api key
-
- Chat->>Core: handleChatCore(body, modelInfo, credentials)
- Core->>Core: detect source format
- Core->>Core: translate request to target format
- Core->>Exec: execute(provider, transformedBody)
- Exec->>Prov: upstream API call
- Prov-->>Exec: SSE/JSON response
- Exec-->>Core: response + metadata
-
- alt 401/403
- Core->>Exec: refreshCredentials()
- Exec-->>Core: updated tokens
- Core->>Exec: retry request
- end
-
- Core->>Stream: translate/normalize stream to client format
- Stream-->>Client: SSE chunks / JSON response
-
- Stream->>Usage: extract usage + persist history/log
-```
-
-## Combo + Account Fallback Flow
-
-```mermaid
-flowchart TD
- A[Incoming model string] --> B{Is combo name?}
- B -- Yes --> C[Load combo models sequence]
- B -- No --> D[Single model path]
-
- C --> E[Try model N]
- E --> F[Resolve provider/model]
- D --> F
-
- F --> G[Select account credentials]
- G --> H{Credentials available?}
- H -- No --> I[Return provider unavailable]
- H -- Yes --> J[Execute request]
-
- J --> K{Success?}
- K -- Yes --> L[Return response]
- K -- No --> M{Fallback-eligible error?}
-
- M -- No --> N[Return error]
- M -- Yes --> O[Mark account unavailable cooldown]
- O --> P{Another account for provider?}
- P -- Yes --> G
- P -- No --> Q{In combo with next model?}
- Q -- Yes --> E
- Q -- No --> R[Return all unavailable]
-```
-
-Fallback decisions are driven by `open-sse/services/accountFallback.ts` using status codes and error-message heuristics.
-
-## OAuth Onboarding and Token Refresh Lifecycle
-
-```mermaid
-sequenceDiagram
- autonumber
- participant UI as Dashboard UI
- participant OAuth as /api/oauth/[provider]/[action]
- participant ProvAuth as Provider Auth Server
- participant DB as localDb
- participant Test as /api/providers/[id]/test
- participant Exec as Provider Executor
-
- UI->>OAuth: GET authorize or device-code
- OAuth->>ProvAuth: create auth/device flow
- ProvAuth-->>OAuth: auth URL or device code payload
- OAuth-->>UI: flow data
-
- UI->>OAuth: POST exchange or poll
- OAuth->>ProvAuth: token exchange/poll
- ProvAuth-->>OAuth: access/refresh tokens
- OAuth->>DB: createProviderConnection(oauth data)
- OAuth-->>UI: success + connection id
-
- UI->>Test: POST /api/providers/[id]/test
- Test->>Exec: validate credentials / optional refresh
- Exec-->>Test: valid or refreshed token info
- Test->>DB: update status/tokens/errors
- Test-->>UI: validation result
-```
-
-Refresh during live traffic is executed inside `open-sse/handlers/chatCore.ts` via executor `refreshCredentials()`.
-
-## Cloud Sync Lifecycle (Enable / Sync / Disable)
-
-```mermaid
-sequenceDiagram
- autonumber
- participant UI as Endpoint Page UI
- participant Sync as /api/sync/cloud
- participant DB as localDb
- participant Cloud as External Cloud Sync
- participant Claude as ~/.claude/settings.json
-
- UI->>Sync: POST action=enable
- Sync->>DB: set cloudEnabled=true
- Sync->>DB: ensure API key exists
- Sync->>Cloud: POST /sync/{machineId} (providers/aliases/combos/keys)
- Cloud-->>Sync: sync result
- Sync->>Cloud: GET /{machineId}/v1/verify
- Sync-->>UI: enabled + verification status
-
- UI->>Sync: POST action=sync
- Sync->>Cloud: POST /sync/{machineId}
- Cloud-->>Sync: remote data
- Sync->>DB: update newer local tokens/status
- Sync-->>UI: synced
-
- UI->>Sync: POST action=disable
- Sync->>DB: set cloudEnabled=false
- Sync->>Cloud: DELETE /sync/{machineId}
- Sync->>Claude: switch ANTHROPIC_BASE_URL back to local (if needed)
- Sync-->>UI: disabled
-```
-
-Periodic sync is triggered by `CloudSyncScheduler` when cloud is enabled.
-
-## Data Model and Storage Map
-
-```mermaid
-erDiagram
- SETTINGS ||--o{ PROVIDER_CONNECTION : controls
- PROVIDER_NODE ||--o{ PROVIDER_CONNECTION : backs_compatible_provider
- PROVIDER_CONNECTION ||--o{ USAGE_ENTRY : emits_usage
-
- SETTINGS {
- boolean cloudEnabled
- number stickyRoundRobinLimit
- boolean requireLogin
- string password_hash
- string fallbackStrategy
- json rateLimitDefaults
- json providerProfiles
- }
-
- PROVIDER_CONNECTION {
- string id
- string provider
- string authType
- string name
- number priority
- boolean isActive
- string apiKey
- string accessToken
- string refreshToken
- string expiresAt
- string testStatus
- string lastError
- string rateLimitedUntil
- json providerSpecificData
- }
-
- PROVIDER_NODE {
- string id
- string type
- string name
- string prefix
- string apiType
- string baseUrl
- }
-
- MODEL_ALIAS {
- string alias
- string targetModel
- }
-
- COMBO {
- string id
- string name
- string[] models
- }
-
- API_KEY {
- string id
- string name
- string key
- string machineId
- }
-
- USAGE_ENTRY {
- string provider
- string model
- number prompt_tokens
- number completion_tokens
- string connectionId
- string timestamp
- }
-
- CUSTOM_MODEL {
- string id
- string name
- string providerId
- }
-
- PROXY_CONFIG {
- string global
- json providers
- }
-
- IP_FILTER {
- string mode
- string[] allowlist
- string[] blocklist
- }
-
- THINKING_BUDGET {
- string mode
- number customBudget
- string effortLevel
- }
-
- SYSTEM_PROMPT {
- boolean enabled
- string prompt
- string position
- }
-```
-
-Physical storage files:
-
-- primary runtime DB: `${DATA_DIR}/storage.sqlite`
-- request log lines: `${DATA_DIR}/log.txt` (compat/debug artifact)
-- structured call payload archives: `${DATA_DIR}/call_logs/`
-- optional translator/request debug sessions: `/logs/...`
-
-## Deployment Topology
-
-```mermaid
-flowchart LR
- subgraph LocalHost[Developer Host]
- CLI[CLI Tools]
- Browser[Dashboard Browser]
- end
-
- subgraph ContainerOrProcess[OmniRoute Runtime]
- Next[Next.js Server\nPORT=20128]
- Core[SSE Core + Executors]
- MainDB[(storage.sqlite)]
- UsageDB[(usage tables + log artifacts)]
- end
-
- subgraph External[External Services]
- Providers[AI Providers]
- SyncCloud[Cloud Sync Service]
- end
-
- CLI --> Next
- Browser --> Next
- Next --> Core
- Next --> MainDB
- Core --> MainDB
- Core --> UsageDB
- Core --> Providers
- Next --> SyncCloud
-```
-
-## Module Mapping (Decision-Critical)
-
-### Route and API Modules
-
-- `src/app/api/v1/*`, `src/app/api/v1beta/*`: compatibility APIs
-- `src/app/api/v1/providers/[provider]/*`: dedicated per-provider routes (chat, embeddings, images)
-- `src/app/api/providers*`: provider CRUD, validation, testing
-- `src/app/api/provider-nodes*`: custom compatible node management
-- `src/app/api/provider-models`: custom model management (CRUD)
-- `src/app/api/models/route.ts`: model catalog API (aliases + custom models)
-- `src/app/api/oauth/*`: OAuth/device-code flows
-- `src/app/api/keys*`: local API key lifecycle
-- `src/app/api/models/alias`: alias management
-- `src/app/api/combos*`: fallback combo management
-- `src/app/api/pricing`: pricing overrides for cost calculation
-- `src/app/api/settings/proxy`: proxy configuration (GET/PUT/DELETE)
-- `src/app/api/settings/proxy/test`: outbound proxy connectivity test (POST)
-- `src/app/api/usage/*`: usage and logs APIs
-- `src/app/api/sync/*` + `src/app/api/cloud/*`: cloud sync and cloud-facing helpers
-- `src/app/api/cli-tools/*`: local CLI config writers/checkers
-- `src/app/api/settings/ip-filter`: IP allowlist/blocklist (GET/PUT)
-- `src/app/api/settings/thinking-budget`: thinking token budget config (GET/PUT)
-- `src/app/api/settings/system-prompt`: global system prompt (GET/PUT)
-- `src/app/api/sessions`: active session listing (GET)
-- `src/app/api/rate-limits`: per-account rate limit status (GET)
-
-### Routing and Execution Core
-
-- `src/sse/handlers/chat.ts`: request parse, combo handling, account selection loop
-- `open-sse/handlers/chatCore.ts`: translation, executor dispatch, retry/refresh handling, stream setup
-- `open-sse/executors/*`: provider-specific network and format behavior
-
-### Translation Registry and Format Converters
-
-- `open-sse/translator/index.ts`: translator registry and orchestration
-- Request translators: `open-sse/translator/request/*`
-- Response translators: `open-sse/translator/response/*`
-- Format constants: `open-sse/translator/formats.ts`
-
-### Persistence
-
-- `src/lib/db/*`: persistent config/state and domain persistence on SQLite
-- `src/lib/localDb.ts`: compatibility re-export for DB modules
-- `src/lib/usageDb.ts`: usage history/call logs facade on top of SQLite tables
-
-## Provider Executor Coverage (Strategy Pattern)
-
-Each provider has a specialized executor extending `BaseExecutor` (in `open-sse/executors/base.ts`), which provides URL building, header construction, retry with exponential backoff, credential refresh hooks, and the `execute()` orchestration method.
-
-| Executor | Provider(s) | Special Handling |
-| --------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------ | -------------------------------------------------------------------- |
-| `DefaultExecutor` | OpenAI, Claude, Gemini, Qwen, Qoder, OpenRouter, GLM, Kimi, MiniMax, DeepSeek, Groq, xAI, Mistral, Perplexity, Together, Fireworks, Cerebras, Cohere, NVIDIA | Dynamic URL/header config per provider |
-| `AntigravityExecutor` | Google Antigravity | Custom project/session IDs, Retry-After parsing |
-| `CodexExecutor` | OpenAI Codex | Injects system instructions, forces reasoning effort |
-| `CursorExecutor` | Cursor IDE | ConnectRPC protocol, Protobuf encoding, request signing via checksum |
-| `GithubExecutor` | GitHub Copilot | Copilot token refresh, VSCode-mimicking headers |
-| `KiroExecutor` | AWS CodeWhisperer/Kiro | AWS EventStream binary format → SSE conversion |
-| `GeminiCLIExecutor` | Gemini CLI | Google OAuth token refresh cycle |
-
-All other providers (including custom compatible nodes) use the `DefaultExecutor`.
-
-## Provider Compatibility Matrix
-
-| Provider | Format | Auth | Stream | Non-Stream | Token Refresh | Usage API |
-| ---------------- | ---------------- | --------------------- | ---------------- | ---------- | ------------- | ------------------ |
-| Claude | claude | API Key / OAuth | ✅ | ✅ | ✅ | ⚠️ Admin only |
-| Gemini | gemini | API Key / OAuth | ✅ | ✅ | ✅ | ⚠️ Cloud Console |
-| Gemini CLI | gemini-cli | OAuth | ✅ | ✅ | ✅ | ⚠️ Cloud Console |
-| Antigravity | antigravity | OAuth | ✅ | ✅ | ✅ | ✅ Full quota API |
-| OpenAI | openai | API Key | ✅ | ✅ | ❌ | ❌ |
-| Codex | openai-responses | OAuth | ✅ forced | ❌ | ✅ | ✅ Rate limits |
-| GitHub Copilot | openai | OAuth + Copilot Token | ✅ | ✅ | ✅ | ✅ Quota snapshots |
-| Cursor | cursor | Custom checksum | ✅ | ✅ | ❌ | ❌ |
-| Kiro | kiro | AWS SSO OIDC | ✅ (EventStream) | ❌ | ✅ | ✅ Usage limits |
-| Qwen | openai | OAuth | ✅ | ✅ | ✅ | ⚠️ Per request |
-| Qoder | openai | OAuth (Basic) | ✅ | ✅ | ✅ | ⚠️ Per request |
-| OpenRouter | openai | API Key | ✅ | ✅ | ❌ | ❌ |
-| GLM/Kimi/MiniMax | claude | API Key | ✅ | ✅ | ❌ | ❌ |
-| DeepSeek | openai | API Key | ✅ | ✅ | ❌ | ❌ |
-| Groq | openai | API Key | ✅ | ✅ | ❌ | ❌ |
-| xAI (Grok) | openai | API Key | ✅ | ✅ | ❌ | ❌ |
-| Mistral | openai | API Key | ✅ | ✅ | ❌ | ❌ |
-| Perplexity | openai | API Key | ✅ | ✅ | ❌ | ❌ |
-| Together AI | openai | API Key | ✅ | ✅ | ❌ | ❌ |
-| Fireworks AI | openai | API Key | ✅ | ✅ | ❌ | ❌ |
-| Cerebras | openai | API Key | ✅ | ✅ | ❌ | ❌ |
-| Cohere | openai | API Key | ✅ | ✅ | ❌ | ❌ |
-| NVIDIA NIM | openai | API Key | ✅ | ✅ | ❌ | ❌ |
-
-## Format Translation Coverage
-
-Detected source formats include:
-
-- `openai`
-- `openai-responses`
-- `claude`
-- `gemini`
-
-Target formats include:
-
-- OpenAI chat/Responses
-- Claude
-- Gemini/Gemini-CLI/Antigravity envelope
-- Kiro
-- Cursor
-
-Translations use **OpenAI as the hub format** — all conversions go through OpenAI as intermediate:
-
-```
-Source Format → OpenAI (hub) → Target Format
-```
-
-Translations are selected dynamically based on source payload shape and provider target format.
-
-Additional processing layers in the translation pipeline:
-
-- **Response sanitization** — Strips non-standard fields from OpenAI-format responses (both streaming and non-streaming) to ensure strict SDK compliance
-- **Role normalization** — Converts `developer` → `system` for non-OpenAI targets; merges `system` → `user` for models that reject the system role (GLM, ERNIE)
-- **Think tag extraction** — Parses `...` blocks from content into `reasoning_content` field
-- **Structured output** — Converts OpenAI `response_format.json_schema` to Gemini's `responseMimeType` + `responseSchema`
-
-## Supported API Endpoints
-
-| Endpoint | Format | Handler |
-| -------------------------------------------------- | ------------------ | ---------------------------------------------------- |
-| `POST /v1/chat/completions` | OpenAI Chat | `src/sse/handlers/chat.ts` |
-| `POST /v1/messages` | Claude Messages | Same handler (auto-detected) |
-| `POST /v1/responses` | OpenAI Responses | `open-sse/handlers/responsesHandler.ts` |
-| `POST /v1/embeddings` | OpenAI Embeddings | `open-sse/handlers/embeddings.ts` |
-| `GET /v1/embeddings` | Model listing | API route |
-| `POST /v1/images/generations` | OpenAI Images | `open-sse/handlers/imageGeneration.ts` |
-| `GET /v1/images/generations` | Model listing | API route |
-| `POST /v1/providers/{provider}/chat/completions` | OpenAI Chat | Dedicated per-provider with model validation |
-| `POST /v1/providers/{provider}/embeddings` | OpenAI Embeddings | Dedicated per-provider with model validation |
-| `POST /v1/providers/{provider}/images/generations` | OpenAI Images | Dedicated per-provider with model validation |
-| `POST /v1/messages/count_tokens` | Claude Token Count | API route |
-| `GET /v1/models` | OpenAI Models list | API route (chat + embedding + image + custom models) |
-| `GET /api/models/catalog` | Catalog | All models grouped by provider + type |
-| `POST /v1beta/models/*:streamGenerateContent` | Gemini native | API route |
-| `GET/PUT/DELETE /api/settings/proxy` | Proxy Config | Network proxy configuration |
-| `POST /api/settings/proxy/test` | Proxy Connectivity | Proxy health/connectivity test endpoint |
-| `GET/POST/DELETE /api/provider-models` | Custom Models | Custom model management per provider |
-
-## Bypass Handler
-
-The bypass handler (`open-sse/utils/bypassHandler.ts`) intercepts known "throwaway" requests from Claude CLI — warmup pings, title extractions, and token counts — and returns a **fake response** without consuming upstream provider tokens. This is triggered only when `User-Agent` contains `claude-cli`.
-
-## Request Logger Pipeline
-
-The request logger (`open-sse/utils/requestLogger.ts`) provides a 7-stage debug logging pipeline, disabled by default, enabled via `ENABLE_REQUEST_LOGS=true`:
-
-```
-1_req_client.json → 2_req_source.json → 3_req_openai.json → 4_req_target.json
-→ 5_res_provider.txt → 6_res_openai.txt → 7_res_client.txt
-```
-
-Files are written to `/logs//` for each request session.
-
-## Failure Modes and Resilience
-
-## 1) Account/Provider Availability
-
-- provider account cooldown on transient/rate/auth errors
-- account fallback before failing request
-- combo model fallback when current model/provider path is exhausted
-
-## 2) Token Expiry
-
-- pre-check and refresh with retry for refreshable providers
-- 401/403 retry after refresh attempt in core path
-
-## 3) Stream Safety
-
-- disconnect-aware stream controller
-- translation stream with end-of-stream flush and `[DONE]` handling
-- usage estimation fallback when provider usage metadata is missing
-
-## 4) Cloud Sync Degradation
-
-- sync errors are surfaced but local runtime continues
-- scheduler has retry-capable logic, but periodic execution currently calls single-attempt sync by default
-
-## 5) Data Integrity
-
-- SQLite schema migrations and auto-upgrade hooks at startup
-- legacy JSON → SQLite migration compatibility path
-
-## Observability and Operational Signals
-
-Runtime visibility sources:
-
-- console logs from `src/sse/utils/logger.ts`
-- per-request usage aggregates in SQLite (`usage_history`, `call_logs`, `proxy_logs`)
-- textual request status log in `log.txt` (optional/compat)
-- optional deep request/translation logs under `logs/` when `ENABLE_REQUEST_LOGS=true`
-- dashboard usage endpoints (`/api/usage/*`) for UI consumption
-
-## Security-Sensitive Boundaries
-
-- JWT secret (`JWT_SECRET`) secures dashboard session cookie verification/signing
-- Initial password bootstrap (`INITIAL_PASSWORD`) should be explicitly configured for first-run provisioning
-- API key HMAC secret (`API_KEY_SECRET`) secures generated local API key format
-- Provider secrets (API keys/tokens) are persisted in local DB and should be protected at filesystem level
-- Cloud sync endpoints rely on API key auth + machine id semantics
-
-## Environment and Runtime Matrix
-
-Environment variables actively used by code:
-
-- App/auth: `JWT_SECRET`, `INITIAL_PASSWORD`
-- Storage: `DATA_DIR`
-- Compatible node behavior: `ALLOW_MULTI_CONNECTIONS_PER_COMPAT_NODE`
-- Optional storage base override (Linux/macOS when `DATA_DIR` unset): `XDG_CONFIG_HOME`
-- Security hashing: `API_KEY_SECRET`, `MACHINE_ID_SALT`
-- Logging: `ENABLE_REQUEST_LOGS`
-- Sync/cloud URLing: `NEXT_PUBLIC_BASE_URL`, `NEXT_PUBLIC_CLOUD_URL`
-- Outbound proxy: `HTTP_PROXY`, `HTTPS_PROXY`, `ALL_PROXY`, `NO_PROXY` and lowercase variants
-- SOCKS5 feature flags: `ENABLE_SOCKS5_PROXY`, `NEXT_PUBLIC_ENABLE_SOCKS5_PROXY`
-- Platform/runtime helpers (not app-specific config): `APPDATA`, `NODE_ENV`, `PORT`, `HOSTNAME`
-
-## Known Architectural Notes
-
-1. `usageDb` and `localDb` share the same base directory policy (`DATA_DIR` -> `XDG_CONFIG_HOME/omniroute` -> `~/.omniroute`) with legacy file migration.
-2. `/api/v1/route.ts` delegates to the same unified catalog builder used by `/api/v1/models` (`src/app/api/v1/models/catalog.ts`) to avoid semantic drift.
-3. Request logger writes full headers/body when enabled; treat log directory as sensitive.
-4. Cloud behavior depends on correct `NEXT_PUBLIC_BASE_URL` and cloud endpoint reachability.
-5. The `open-sse/` directory is published as the `@omniroute/open-sse` **npm workspace package**. Source code imports it via `@omniroute/open-sse/...` (resolved by Next.js `transpilePackages`). File paths in this document still use the directory name `open-sse/` for consistency.
-6. Charts in the dashboard use **Recharts** (SVG-based) for accessible, interactive analytics visualizations (model usage bar charts, provider breakdown tables with success rates).
-7. E2E tests use **Playwright** (`tests/e2e/`), run via `npm run test:e2e`. Unit tests use **Node.js test runner** (`tests/unit/`), run via `npm run test:unit`. Source code under `src/` is **TypeScript** (`.ts`/`.tsx`); the `open-sse/` workspace remains JavaScript (`.js`).
-8. Settings page is organized into 5 tabs: Security, Routing (6 global strategies: fill-first, round-robin, p2c, random, least-used, cost-optimized), Resilience (editable rate limits, circuit breaker, policies), AI (thinking budget, system prompt, prompt cache), Advanced (proxy).
-
-## Operational Verification Checklist
-
-- Build from source: `npm run build`
-- Build Docker image: `docker build -t omniroute .`
-- Start service and verify:
-- `GET /api/settings`
-- `GET /api/v1/models`
-- CLI target base URL should be `http://:20128/v1` when `PORT=20128`
diff --git a/docs/i18n/id/AUTO-COMBO.md b/docs/i18n/id/AUTO-COMBO.md
deleted file mode 100644
index 2166e41dff..0000000000
--- a/docs/i18n/id/AUTO-COMBO.md
+++ /dev/null
@@ -1,67 +0,0 @@
-🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/AUTO-COMBO.md) · 🇪🇸 [es](../es/AUTO-COMBO.md) · 🇫🇷 [fr](../fr/AUTO-COMBO.md) · 🇩🇪 [de](../de/AUTO-COMBO.md) · 🇮🇹 [it](../it/AUTO-COMBO.md) · 🇷🇺 [ru](../ru/AUTO-COMBO.md) · 🇨🇳 [zh-CN](../zh-CN/AUTO-COMBO.md) · 🇯🇵 [ja](../ja/AUTO-COMBO.md) · 🇰🇷 [ko](../ko/AUTO-COMBO.md) · 🇸🇦 [ar](../ar/AUTO-COMBO.md) · 🇮🇳 [in](../in/AUTO-COMBO.md) · 🇹🇭 [th](../th/AUTO-COMBO.md) · 🇻🇳 [vi](../vi/AUTO-COMBO.md) · 🇮🇩 [id](../id/AUTO-COMBO.md) · 🇲🇾 [ms](../ms/AUTO-COMBO.md) · 🇳🇱 [nl](../nl/AUTO-COMBO.md) · 🇵🇱 [pl](../pl/AUTO-COMBO.md) · 🇸🇪 [sv](../sv/AUTO-COMBO.md) · 🇳🇴 [no](../no/AUTO-COMBO.md) · 🇩🇰 [da](../da/AUTO-COMBO.md) · 🇫🇮 [fi](../fi/AUTO-COMBO.md) · 🇵🇹 [pt](../pt/AUTO-COMBO.md) · 🇷🇴 [ro](../ro/AUTO-COMBO.md) · 🇭🇺 [hu](../hu/AUTO-COMBO.md) · 🇧🇬 [bg](../bg/AUTO-COMBO.md) · 🇸🇰 [sk](../sk/AUTO-COMBO.md) · 🇺🇦 [uk-UA](../uk-UA/AUTO-COMBO.md) · 🇮🇱 [he](../he/AUTO-COMBO.md) · 🇵🇭 [phi](../phi/AUTO-COMBO.md)
-
----
-
-# OmniRoute Auto-Combo Engine
-
-> Self-managing model chains with adaptive scoring
-
-## How It Works
-
-The Auto-Combo Engine dynamically selects the best provider/model for each request using a **6-factor scoring function**:
-
-| Factor | Weight | Description |
-| :--------- | :----- | :---------------------------------------------- |
-| Quota | 0.20 | Remaining capacity [0..1] |
-| Health | 0.25 | Circuit breaker: CLOSED=1.0, HALF=0.5, OPEN=0.0 |
-| CostInv | 0.20 | Inverse cost (cheaper = higher score) |
-| LatencyInv | 0.15 | Inverse p95 latency (faster = higher) |
-| TaskFit | 0.10 | Model × task type fitness score |
-| Stability | 0.10 | Low variance in latency/errors |
-
-## Mode Packs
-
-| Pack | Focus | Key Weight |
-| :---------------------- | :----------- | :--------------- |
-| 🚀 **Ship Fast** | Speed | latencyInv: 0.35 |
-| 💰 **Cost Saver** | Economy | costInv: 0.40 |
-| 🎯 **Quality First** | Best model | taskFit: 0.40 |
-| 📡 **Offline Friendly** | Availability | quota: 0.40 |
-
-## Self-Healing
-
-- **Temporary exclusion**: Score < 0.2 → excluded for 5 min (progressive backoff, max 30 min)
-- **Circuit breaker awareness**: OPEN → auto-excluded; HALF_OPEN → probe requests
-- **Incident mode**: >50% OPEN → disable exploration, maximize stability
-- **Cooldown recovery**: After exclusion, first request is a "probe" with reduced timeout
-
-## Bandit Exploration
-
-5% of requests (configurable) are routed to random providers for exploration. Disabled in incident mode.
-
-## API
-
-```bash
-# Create auto-combo
-curl -X POST http://localhost:20128/api/combos/auto \
- -H "Content-Type: application/json" \
- -d '{"id":"my-auto","name":"Auto Coder","candidatePool":["anthropic","google","openai"],"modePack":"ship-fast"}'
-
-# List auto-combos
-curl http://localhost:20128/api/combos/auto
-```
-
-## Task Fitness
-
-30+ models scored across 6 task types (`coding`, `review`, `planning`, `analysis`, `debugging`, `documentation`). Supports wildcard patterns (e.g., `*-coder` → high coding score).
-
-## Files
-
-| File | Purpose |
-| :------------------------------------------- | :------------------------------------ |
-| `open-sse/services/autoCombo/scoring.ts` | Scoring function & pool normalization |
-| `open-sse/services/autoCombo/taskFitness.ts` | Model × task fitness lookup |
-| `open-sse/services/autoCombo/engine.ts` | Selection logic, bandit, budget cap |
-| `open-sse/services/autoCombo/selfHealing.ts` | Exclusion, probes, incident mode |
-| `open-sse/services/autoCombo/modePacks.ts` | 4 weight profiles |
-| `src/app/api/combos/auto/route.ts` | REST API |
diff --git a/docs/i18n/id/CHANGELOG.md b/docs/i18n/id/CHANGELOG.md
index ef6f4a3bb1..df974ced96 100644
--- a/docs/i18n/id/CHANGELOG.md
+++ b/docs/i18n/id/CHANGELOG.md
@@ -1,12 +1,92 @@
# Changelog (Bahasa Indonesia)
-🌐 **Languages:** 🇺🇸 [English](../../../CHANGELOG.md) · 🇪🇸 [es](../es/CHANGELOG.md) · 🇫🇷 [fr](../fr/CHANGELOG.md) · 🇩🇪 [de](../de/CHANGELOG.md) · 🇮🇹 [it](../it/CHANGELOG.md) · 🇷🇺 [ru](../ru/CHANGELOG.md) · 🇨🇳 [zh-CN](../zh-CN/CHANGELOG.md) · 🇯🇵 [ja](../ja/CHANGELOG.md) · 🇰🇷 [ko](../ko/CHANGELOG.md) · 🇸🇦 [ar](../ar/CHANGELOG.md) · 🇮🇳 [in](../in/CHANGELOG.md) · 🇹🇭 [th](../th/CHANGELOG.md) · 🇻🇳 [vi](../vi/CHANGELOG.md) · 🇮🇩 [id](../id/CHANGELOG.md) · 🇲🇾 [ms](../ms/CHANGELOG.md) · 🇳🇱 [nl](../nl/CHANGELOG.md) · 🇵🇱 [pl](../pl/CHANGELOG.md) · 🇸🇪 [sv](../sv/CHANGELOG.md) · 🇳🇴 [no](../no/CHANGELOG.md) · 🇩🇰 [da](../da/CHANGELOG.md) · 🇫🇮 [fi](../fi/CHANGELOG.md) · 🇵🇹 [pt](../pt/CHANGELOG.md) · 🇷🇴 [ro](../ro/CHANGELOG.md) · 🇭🇺 [hu](../hu/CHANGELOG.md) · 🇧🇬 [bg](../bg/CHANGELOG.md) · 🇸🇰 [sk](../sk/CHANGELOG.md) · 🇺🇦 [uk-UA](../uk-UA/CHANGELOG.md) · 🇮🇱 [he](../he/CHANGELOG.md) · 🇵🇭 [phi](../phi/CHANGELOG.md) · 🇧🇷 [pt-BR](../pt-BR/CHANGELOG.md)
+🌐 **Languages:** 🇺🇸 [English](../../../CHANGELOG.md) · 🇪🇸 [es](../es/CHANGELOG.md) · 🇫🇷 [fr](../fr/CHANGELOG.md) · 🇩🇪 [de](../de/CHANGELOG.md) · 🇮🇹 [it](../it/CHANGELOG.md) · 🇷🇺 [ru](../ru/CHANGELOG.md) · 🇨🇳 [zh-CN](../zh-CN/CHANGELOG.md) · 🇯🇵 [ja](../ja/CHANGELOG.md) · 🇰🇷 [ko](../ko/CHANGELOG.md) · 🇸🇦 [ar](../ar/CHANGELOG.md) · 🇮🇳 [in](../in/CHANGELOG.md) · 🇹🇭 [th](../th/CHANGELOG.md) · 🇻🇳 [vi](../vi/CHANGELOG.md) · 🇮🇩 [id](../id/CHANGELOG.md) · 🇲🇾 [ms](../ms/CHANGELOG.md) · 🇳🇱 [nl](../nl/CHANGELOG.md) · 🇵🇱 [pl](../pl/CHANGELOG.md) · 🇸🇪 [sv](../sv/CHANGELOG.md) · 🇳🇴 [no](../no/CHANGELOG.md) · 🇩🇰 [da](../da/CHANGELOG.md) · 🇫🇮 [fi](../fi/CHANGELOG.md) · 🇵🇹 [pt](../pt/CHANGELOG.md) · 🇷🇴 [ro](../ro/CHANGELOG.md) · 🇭🇺 [hu](../hu/CHANGELOG.md) · 🇧🇬 [bg](../bg/CHANGELOG.md) · 🇸🇰 [sk](../sk/CHANGELOG.md) · 🇺🇦 [uk-UA](../uk-UA/CHANGELOG.md) · 🇮🇱 [he](../he/CHANGELOG.md) · 🇵🇭 [phi](../phi/CHANGELOG.md) · 🇧🇷 [pt-BR](../pt-BR/CHANGELOG.md) · 🇨🇿 [cs](../cs/CHANGELOG.md)
---
-
## [Unreleased]
+### 🛠️ Maintenance
+
+- **AGENTS.md rewrite:** Condensed from 297→153 lines. Added build/lint/test commands (including single-test execution), code style guidelines (Prettier, TypeScript, ESLint, naming, imports, error handling, security), and trimmed verbose architecture tables for AI agent consumption.
+
+## [3.4.2] - 2026-04-01
+
+### 🐛 Bug Fixes
+
+- **CI Stabilization:** Fixed failing analytics/settings Playwright selectors and request assertions so GitHub Actions E2E runs pass reliably across localized UIs and switch-based controls.
+- **Deterministic Tests:** Removed date-sensitive quota fixtures from Copilot usage tests and aligned idempotency/model catalog tests with the merged runtime behavior.
+- **MCP Type Hardening:** Removed zero-budget explicit `any` regressions from the MCP server tool registration path, restoring the `check:any-budget:t11` workflow gate.
+
+### 🛠️ Maintenance
+
+- **Release Branch Integration:** Consolidated the active feature branches into `release/v3.4.2` on top of current `main` and validated the branch with lint, unit, coverage, build, and CI-mode E2E runs.
+
+## [3.4.1] - 2026-03-31
+
+> [!WARNING]
+> **BREAKING CHANGE: request logging, retention, and logging environment variables have been redesigned.**
+> On the first startup after upgrading, OmniRoute archives legacy request logs from `DATA_DIR/logs/`, legacy `DATA_DIR/call_logs/`, and `DATA_DIR/log.txt` into `DATA_DIR/log_archives/*.zip`, then removes the deprecated layout and switches to the new unified artifact format under `DATA_DIR/call_logs/`.
+
+### ✨ New Features
+
+- **.ENV Migration Utility:** Included `scripts/migrate-env.mjs` to seamlessly migrate ` Your key looks like: `sk-xxxxxxxxxxxxxxxx-xxxxxxxxx`
-
----
-
-## Step 2 — Install CLI Tools
-
-All npm-based tools require Node.js 18+:
-
-```bash
-# Claude Code (Anthropic)
-npm install -g @anthropic-ai/claude-code
-
-# OpenAI Codex
-npm install -g @openai/codex
-
-# Gemini CLI (Google)
-npm install -g @google/gemini-cli
-
-# OpenCode
-npm install -g opencode-ai
-
-# Cline
-npm install -g cline
-
-# KiloCode
-npm install -g kilecode
-
-# Kiro CLI (Amazon — requires curl + unzip)
-apt-get install -y unzip # on Debian/Ubuntu
-curl -fsSL https://cli.kiro.dev/install | bash
-export PATH="$HOME/.local/bin:$PATH" # add to ~/.bashrc
-```
-
-**Verify:**
-
-```bash
-claude --version # 2.x.x
-codex --version # 0.x.x
-gemini --version # 0.x.x
-opencode --version # x.x.x
-cline --version # 2.x.x
-kilocode --version # x.x.x (or: kilo --version)
-kiro-cli --version # 1.x.x
-```
-
----
-
-## Step 3 — Set Global Environment Variables
-
-Add to `~/.bashrc` (or `~/.zshrc`), then run `source ~/.bashrc`:
-
-```bash
-# OmniRoute Universal Endpoint
-export OPENAI_BASE_URL="http://localhost:20128/v1"
-export OPENAI_API_KEY="sk-your-omniroute-key"
-export ANTHROPIC_BASE_URL="http://localhost:20128/v1"
-export ANTHROPIC_API_KEY="sk-your-omniroute-key"
-export GEMINI_BASE_URL="http://localhost:20128/v1"
-export GEMINI_API_KEY="sk-your-omniroute-key"
-```
-
-> For a **remote server** replace `localhost:20128` with the server IP or domain,
-> e.g. `http://192.168.0.15:20128`.
-
----
-
-## Step 4 — Configure Each Tool
-
-### Claude Code
-
-```bash
-# Via CLI:
-claude config set --global api-base-url http://localhost:20128/v1
-
-# Or create ~/.claude/settings.json:
-mkdir -p ~/.claude && cat > ~/.claude/settings.json << EOF
-{
- "apiBaseUrl": "http://localhost:20128/v1",
- "apiKey": "sk-your-omniroute-key"
-}
-EOF
-```
-
-**Test:** `claude "say hello"`
-
----
-
-### OpenAI Codex
-
-```bash
-mkdir -p ~/.codex && cat > ~/.codex/config.yaml << EOF
-model: auto
-apiKey: sk-your-omniroute-key
-apiBaseUrl: http://localhost:20128/v1
-EOF
-```
-
-**Test:** `codex "what is 2+2?"`
-
----
-
-### Gemini CLI
-
-```bash
-mkdir -p ~/.gemini && cat > ~/.gemini/settings.json << EOF
-{
- "apiKey": "sk-your-omniroute-key",
- "baseUrl": "http://localhost:20128/v1"
-}
-EOF
-```
-
-**Test:** `gemini "hello"`
-
----
-
-### OpenCode
-
-```bash
-mkdir -p ~/.config/opencode && cat > ~/.config/opencode/config.toml << EOF
-[provider.openai]
-base_url = "http://localhost:20128/v1"
-api_key = "sk-your-omniroute-key"
-EOF
-```
-
-**Test:** `opencode`
-
----
-
-### Cline (CLI or VS Code)
-
-**CLI mode:**
-
-```bash
-mkdir -p ~/.cline/data && cat > ~/.cline/data/globalState.json << EOF
-{
- "apiProvider": "openai",
- "openAiBaseUrl": "http://localhost:20128/v1",
- "openAiApiKey": "sk-your-omniroute-key"
-}
-EOF
-```
-
-**VS Code mode:**
-Cline extension settings → API Provider: `OpenAI Compatible` → Base URL: `http://localhost:20128/v1`
-
-Or use the OmniRoute dashboard → **CLI Tools → Cline → Apply Config**.
-
----
-
-### KiloCode (CLI or VS Code)
-
-**CLI mode:**
-
-```bash
-kilocode --api-base http://localhost:20128/v1 --api-key sk-your-omniroute-key
-```
-
-**VS Code settings:**
-
-```json
-{
- "kilo-code.openAiBaseUrl": "http://localhost:20128/v1",
- "kilo-code.apiKey": "sk-your-omniroute-key"
-}
-```
-
-Or use the OmniRoute dashboard → **CLI Tools → KiloCode → Apply Config**.
-
----
-
-### Continue (VS Code Extension)
-
-Edit `~/.continue/config.yaml`:
-
-```yaml
-models:
- - name: OmniRoute
- provider: openai
- model: auto
- apiBase: http://localhost:20128/v1
- apiKey: sk-your-omniroute-key
- default: true
-```
-
-Restart VS Code after editing.
-
----
-
-### Kiro CLI (Amazon)
-
-```bash
-# Login to your AWS/Kiro account:
-kiro-cli login
-
-# The CLI uses its own auth — OmniRoute is not needed as backend for Kiro CLI itself.
-# Use kiro-cli alongside OmniRoute for other tools.
-kiro-cli status
-```
-
----
-
-### Cursor (Desktop App)
-
-> **Note:** Cursor routes requests through its cloud. For OmniRoute integration,
-> enable **Cloud Endpoint** in OmniRoute Settings and use your public domain URL.
-
-Via GUI: **Settings → Models → OpenAI API Key**
-
-- Base URL: `https://your-domain.com/v1`
-- API Key: your OmniRoute key
-
----
-
-## Dashboard Auto-Configuration
-
-The OmniRoute dashboard automates configuration for most tools:
-
-1. Go to `http://localhost:20128/dashboard/cli-tools`
-2. Expand any tool card
-3. Select your API key from the dropdown
-4. Click **Apply Config** (if tool is detected as installed)
-5. Or copy the generated config snippet manually
-
----
-
-## Built-in Agents: Droid & OpenClaw
-
-**Droid** and **OpenClaw** are AI agents built directly into OmniRoute — no installation needed.
-They run as internal routes and use OmniRoute's model routing automatically.
-
-- Access: `http://localhost:20128/dashboard/agents`
-- Configure: same combos and providers as all other tools
-- No API key or CLI install required
-
----
-
-## Available API Endpoints
-
-| Endpoint | Description | Use For |
-| -------------------------- | ----------------------------- | --------------------------- |
-| `/v1/chat/completions` | Standard chat (all providers) | All modern tools |
-| `/v1/responses` | Responses API (OpenAI format) | Codex, agentic workflows |
-| `/v1/completions` | Legacy text completions | Older tools using `prompt:` |
-| `/v1/embeddings` | Text embeddings | RAG, search |
-| `/v1/images/generations` | Image generation | DALL-E, Flux, etc. |
-| `/v1/audio/speech` | Text-to-speech | ElevenLabs, OpenAI TTS |
-| `/v1/audio/transcriptions` | Speech-to-text | Deepgram, AssemblyAI |
-
----
-
-## Troubleshooting
-
-| Error | Cause | Fix |
-| ------------------------- | ----------------------- | ------------------------------------------ |
-| `Connection refused` | OmniRoute not running | `pm2 start omniroute` |
-| `401 Unauthorized` | Wrong API key | Check in `/dashboard/api-manager` |
-| `No combo configured` | No active routing combo | Set up in `/dashboard/combos` |
-| `invalid model` | Model not in catalog | Use `auto` or check `/dashboard/providers` |
-| CLI shows "not installed" | Binary not in PATH | Check `which ` |
-| `kiro-cli: not found` | Not in PATH | `export PATH="$HOME/.local/bin:$PATH"` |
-
----
-
-## Quick Setup Script (One Command)
-
-```bash
-# Install all CLIs and configure for OmniRoute (replace with your key and server URL)
-OMNIROUTE_URL="http://localhost:20128/v1"
-OMNIROUTE_KEY="sk-your-omniroute-key"
-
-npm install -g @anthropic-ai/claude-code @openai/codex @google/gemini-cli opencode-ai cline kilecode
-
-# Kiro CLI
-apt-get install -y unzip 2>/dev/null; curl -fsSL https://cli.kiro.dev/install | bash
-
-# Write configs
-mkdir -p ~/.claude ~/.codex ~/.gemini ~/.config/opencode ~/.continue
-
-cat > ~/.claude/settings.json <<< "{\"apiBaseUrl\":\"$OMNIROUTE_URL\",\"apiKey\":\"$OMNIROUTE_KEY\"}"
-cat > ~/.codex/config.yaml <<< "model: auto\napiKey: $OMNIROUTE_KEY\napiBaseUrl: $OMNIROUTE_URL"
-cat > ~/.gemini/settings.json <<< "{\"apiKey\":\"$OMNIROUTE_KEY\",\"baseUrl\":\"$OMNIROUTE_URL\"}"
-cat >> ~/.bashrc << EOF
-export OPENAI_BASE_URL="$OMNIROUTE_URL"
-export OPENAI_API_KEY="$OMNIROUTE_KEY"
-export ANTHROPIC_BASE_URL="$OMNIROUTE_URL"
-export ANTHROPIC_API_KEY="$OMNIROUTE_KEY"
-EOF
-
-source ~/.bashrc
-echo "✅ All CLIs installed and configured for OmniRoute"
-```
diff --git a/docs/i18n/id/CODEBASE_DOCUMENTATION.md b/docs/i18n/id/CODEBASE_DOCUMENTATION.md
deleted file mode 100644
index e2d7950052..0000000000
--- a/docs/i18n/id/CODEBASE_DOCUMENTATION.md
+++ /dev/null
@@ -1,593 +0,0 @@
-🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/CODEBASE_DOCUMENTATION.md) · 🇪🇸 [es](../es/CODEBASE_DOCUMENTATION.md) · 🇫🇷 [fr](../fr/CODEBASE_DOCUMENTATION.md) · 🇩🇪 [de](../de/CODEBASE_DOCUMENTATION.md) · 🇮🇹 [it](../it/CODEBASE_DOCUMENTATION.md) · 🇷🇺 [ru](../ru/CODEBASE_DOCUMENTATION.md) · 🇨🇳 [zh-CN](../zh-CN/CODEBASE_DOCUMENTATION.md) · 🇯🇵 [ja](../ja/CODEBASE_DOCUMENTATION.md) · 🇰🇷 [ko](../ko/CODEBASE_DOCUMENTATION.md) · 🇸🇦 [ar](../ar/CODEBASE_DOCUMENTATION.md) · 🇮🇳 [in](../in/CODEBASE_DOCUMENTATION.md) · 🇹🇭 [th](../th/CODEBASE_DOCUMENTATION.md) · 🇻🇳 [vi](../vi/CODEBASE_DOCUMENTATION.md) · 🇮🇩 [id](../id/CODEBASE_DOCUMENTATION.md) · 🇲🇾 [ms](../ms/CODEBASE_DOCUMENTATION.md) · 🇳🇱 [nl](../nl/CODEBASE_DOCUMENTATION.md) · 🇵🇱 [pl](../pl/CODEBASE_DOCUMENTATION.md) · 🇸🇪 [sv](../sv/CODEBASE_DOCUMENTATION.md) · 🇳🇴 [no](../no/CODEBASE_DOCUMENTATION.md) · 🇩🇰 [da](../da/CODEBASE_DOCUMENTATION.md) · 🇫🇮 [fi](../fi/CODEBASE_DOCUMENTATION.md) · 🇵🇹 [pt](../pt/CODEBASE_DOCUMENTATION.md) · 🇷🇴 [ro](../ro/CODEBASE_DOCUMENTATION.md) · 🇭🇺 [hu](../hu/CODEBASE_DOCUMENTATION.md) · 🇧🇬 [bg](../bg/CODEBASE_DOCUMENTATION.md) · 🇸🇰 [sk](../sk/CODEBASE_DOCUMENTATION.md) · 🇺🇦 [uk-UA](../uk-UA/CODEBASE_DOCUMENTATION.md) · 🇮🇱 [he](../he/CODEBASE_DOCUMENTATION.md) · 🇵🇭 [phi](../phi/CODEBASE_DOCUMENTATION.md)
-
----
-
-# omniroute — Codebase Documentation
-
-🌐 **Languages:** 🇺🇸 [English](CODEBASE_DOCUMENTATION.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/CODEBASE_DOCUMENTATION.md) | 🇪🇸 [Español](i18n/es/CODEBASE_DOCUMENTATION.md) | 🇫🇷 [Français](i18n/fr/CODEBASE_DOCUMENTATION.md) | 🇮🇹 [Italiano](i18n/it/CODEBASE_DOCUMENTATION.md) | 🇷🇺 [Русский](i18n/ru/CODEBASE_DOCUMENTATION.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/CODEBASE_DOCUMENTATION.md) | 🇩🇪 [Deutsch](i18n/de/CODEBASE_DOCUMENTATION.md) | 🇮🇳 [हिन्दी](i18n/in/CODEBASE_DOCUMENTATION.md) | 🇹🇭 [ไทย](i18n/th/CODEBASE_DOCUMENTATION.md) | 🇺🇦 [Українська](i18n/uk-UA/CODEBASE_DOCUMENTATION.md) | 🇸🇦 [العربية](i18n/ar/CODEBASE_DOCUMENTATION.md) | 🇯🇵 [日本語](i18n/ja/CODEBASE_DOCUMENTATION.md) | 🇻🇳 [Tiếng Việt](i18n/vi/CODEBASE_DOCUMENTATION.md) | 🇧🇬 [Български](i18n/bg/CODEBASE_DOCUMENTATION.md) | 🇩🇰 [Dansk](i18n/da/CODEBASE_DOCUMENTATION.md) | 🇫🇮 [Suomi](i18n/fi/CODEBASE_DOCUMENTATION.md) | 🇮🇱 [עברית](i18n/he/CODEBASE_DOCUMENTATION.md) | 🇭🇺 [Magyar](i18n/hu/CODEBASE_DOCUMENTATION.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/CODEBASE_DOCUMENTATION.md) | 🇰🇷 [한국어](i18n/ko/CODEBASE_DOCUMENTATION.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/CODEBASE_DOCUMENTATION.md) | 🇳🇱 [Nederlands](i18n/nl/CODEBASE_DOCUMENTATION.md) | 🇳🇴 [Norsk](i18n/no/CODEBASE_DOCUMENTATION.md) | 🇵🇹 [Português (Portugal)](i18n/pt/CODEBASE_DOCUMENTATION.md) | 🇷🇴 [Română](i18n/ro/CODEBASE_DOCUMENTATION.md) | 🇵🇱 [Polski](i18n/pl/CODEBASE_DOCUMENTATION.md) | 🇸🇰 [Slovenčina](i18n/sk/CODEBASE_DOCUMENTATION.md) | 🇸🇪 [Svenska](i18n/sv/CODEBASE_DOCUMENTATION.md) | 🇵🇭 [Filipino](i18n/phi/CODEBASE_DOCUMENTATION.md)
-
-> A comprehensive, beginner-friendly guide to the **omniroute** multi-provider AI proxy router.
-
----
-
-## 1. What Is omniroute?
-
-omniroute is a **proxy router** that sits between AI clients (Claude CLI, Codex, Cursor IDE, etc.) and AI providers (Anthropic, Google, OpenAI, AWS, GitHub, etc.). It solves one big problem:
-
-> **Different AI clients speak different "languages" (API formats), and different AI providers expect different "languages" too.** omniroute translates between them automatically.
-
-Think of it like a universal translator at the United Nations — any delegate can speak any language, and the translator converts it for any other delegate.
-
----
-
-## 2. Architecture Overview
-
-```mermaid
-graph LR
- subgraph Clients
- A[Claude CLI]
- B[Codex]
- C[Cursor IDE]
- D[OpenAI-compatible]
- end
-
- subgraph omniroute
- E[Handler Layer]
- F[Translator Layer]
- G[Executor Layer]
- H[Services Layer]
- end
-
- subgraph Providers
- I[Anthropic Claude]
- J[Google Gemini]
- K[OpenAI / Codex]
- L[GitHub Copilot]
- M[AWS Kiro]
- N[Antigravity]
- O[Cursor API]
- end
-
- A --> E
- B --> E
- C --> E
- D --> E
- E --> F
- F --> G
- G --> I
- G --> J
- G --> K
- G --> L
- G --> M
- G --> N
- G --> O
- H -.-> E
- H -.-> G
-```
-
-### Core Principle: Hub-and-Spoke Translation
-
-All format translation passes through **OpenAI format as the hub**:
-
-```
-Client Format → [OpenAI Hub] → Provider Format (request)
-Provider Format → [OpenAI Hub] → Client Format (response)
-```
-
-This means you only need **N translators** (one per format) instead of **N²** (every pair).
-
----
-
-## 3. Project Structure
-
-```
-omniroute/
-├── open-sse/ ← Core proxy library (portable, framework-agnostic)
-│ ├── index.js ← Main entry point, exports everything
-│ ├── config/ ← Configuration & constants
-│ ├── executors/ ← Provider-specific request execution
-│ ├── handlers/ ← Request handling orchestration
-│ ├── services/ ← Business logic (auth, models, fallback, usage)
-│ ├── translator/ ← Format translation engine
-│ │ ├── request/ ← Request translators (8 files)
-│ │ ├── response/ ← Response translators (7 files)
-│ │ └── helpers/ ← Shared translation utilities (6 files)
-│ └── utils/ ← Utility functions
-├── src/ ← Application layer (Express/Worker runtime)
-│ ├── app/ ← Web UI, API routes, middleware
-│ ├── lib/ ← Database, auth, and shared library code
-│ ├── mitm/ ← Man-in-the-middle proxy utilities
-│ ├── models/ ← Database models
-│ ├── shared/ ← Shared utilities (wrappers around open-sse)
-│ ├── sse/ ← SSE endpoint handlers
-│ └── store/ ← State management
-├── data/ ← Runtime data (credentials, logs)
-│ └── provider-credentials.json (external credentials override, gitignored)
-└── tester/ ← Test utilities
-```
-
----
-
-## 4. Module-by-Module Breakdown
-
-### 4.1 Config (`open-sse/config/`)
-
-The **single source of truth** for all provider configuration.
-
-| File | Purpose |
-| ----------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| `constants.ts` | `PROVIDERS` object with base URLs, OAuth credentials (defaults), headers, and default system prompts for every provider. Also defines `HTTP_STATUS`, `ERROR_TYPES`, `COOLDOWN_MS`, `BACKOFF_CONFIG`, and `SKIP_PATTERNS`. |
-| `credentialLoader.ts` | Loads external credentials from `data/provider-credentials.json` and merges them over the hardcoded defaults in `PROVIDERS`. Keeps secrets out of source control while maintaining backwards compatibility. |
-| `providerModels.ts` | Central model registry: maps provider aliases → model IDs. Functions like `getModels()`, `getProviderByAlias()`. |
-| `codexInstructions.ts` | System instructions injected into Codex requests (editing constraints, sandbox rules, approval policies). |
-| `defaultThinkingSignature.ts` | Default "thinking" signatures for Claude and Gemini models. |
-| `ollamaModels.ts` | Schema definition for local Ollama models (name, size, family, quantization). |
-
-#### Credential Loading Flow
-
-```mermaid
-flowchart TD
- A["App starts"] --> B["constants.ts defines PROVIDERS\nwith hardcoded defaults"]
- B --> C{"data/provider-credentials.json\nexists?"}
- C -->|Yes| D["credentialLoader reads JSON"]
- C -->|No| E["Use hardcoded defaults"]
- D --> F{"For each provider in JSON"}
- F --> G{"Provider exists\nin PROVIDERS?"}
- G -->|No| H["Log warning, skip"]
- G -->|Yes| I{"Value is object?"}
- I -->|No| J["Log warning, skip"]
- I -->|Yes| K["Merge clientId, clientSecret,\ntokenUrl, authUrl, refreshUrl"]
- K --> F
- H --> F
- J --> F
- F -->|Done| L["PROVIDERS ready with\nmerged credentials"]
- E --> L
-```
-
----
-
-### 4.2 Executors (`open-sse/executors/`)
-
-Executors encapsulate **provider-specific logic** using the **Strategy Pattern**. Each executor overrides base methods as needed.
-
-```mermaid
-classDiagram
- class BaseExecutor {
- +buildUrl(model, stream, options)
- +buildHeaders(credentials, stream, body)
- +transformRequest(body, model, stream, credentials)
- +execute(url, options)
- +shouldRetry(status, error)
- +refreshCredentials(credentials, log)
- }
-
- class DefaultExecutor {
- +refreshCredentials()
- }
-
- class AntigravityExecutor {
- +buildUrl()
- +buildHeaders()
- +transformRequest()
- +shouldRetry()
- +refreshCredentials()
- }
-
- class CursorExecutor {
- +buildUrl()
- +buildHeaders()
- +transformRequest()
- +parseResponse()
- +generateChecksum()
- }
-
- class KiroExecutor {
- +buildUrl()
- +buildHeaders()
- +transformRequest()
- +parseEventStream()
- +refreshCredentials()
- }
-
- BaseExecutor <|-- DefaultExecutor
- BaseExecutor <|-- AntigravityExecutor
- BaseExecutor <|-- CursorExecutor
- BaseExecutor <|-- KiroExecutor
- BaseExecutor <|-- CodexExecutor
- BaseExecutor <|-- GeminiCLIExecutor
- BaseExecutor <|-- GithubExecutor
-```
-
-| Executor | Provider | Key Specializations |
-| ---------------- | ------------------------------------------ | ------------------------------------------------------------------------------------------------------------------- |
-| `base.ts` | — | Abstract base: URL building, headers, retry logic, credential refresh |
-| `default.ts` | Claude, Gemini, OpenAI, GLM, Kimi, MiniMax | Generic OAuth token refresh for standard providers |
-| `antigravity.ts` | Google Cloud Code | Project/session ID generation, multi-URL fallback, custom retry parsing from error messages ("reset after 2h7m23s") |
-| `cursor.ts` | Cursor IDE | **Most complex**: SHA-256 checksum auth, Protobuf request encoding, binary EventStream → SSE response parsing |
-| `codex.ts` | OpenAI Codex | Injects system instructions, manages thinking levels, removes unsupported parameters |
-| `gemini-cli.ts` | Google Gemini CLI | Custom URL building (`streamGenerateContent`), Google OAuth token refresh |
-| `github.ts` | GitHub Copilot | Dual token system (GitHub OAuth + Copilot token), VSCode header mimicking |
-| `kiro.ts` | AWS CodeWhisperer | AWS EventStream binary parsing, AMZN event frames, token estimation |
-| `index.ts` | — | Factory: maps provider name → executor class, with default fallback |
-
----
-
-### 4.3 Handlers (`open-sse/handlers/`)
-
-The **orchestration layer** — coordinates translation, execution, streaming, and error handling.
-
-| File | Purpose |
-| --------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| `chatCore.ts` | **Central orchestrator** (~600 lines). Handles the complete request lifecycle: format detection → translation → executor dispatch → streaming/non-streaming response → token refresh → error handling → usage logging. |
-| `responsesHandler.ts` | Adapter for OpenAI's Responses API: converts Responses format → Chat Completions → sends to `chatCore` → converts SSE back to Responses format. |
-| `embeddings.ts` | Embedding generation handler: resolves embedding model → provider, dispatches to provider API, returns OpenAI-compatible embedding response. Supports 6+ providers. |
-| `imageGeneration.ts` | Image generation handler: resolves image model → provider, supports OpenAI-compatible, Gemini-image (Antigravity), and fallback (Nebius) modes. Returns base64 or URL images. |
-
-#### Request Lifecycle (chatCore.ts)
-
-```mermaid
-sequenceDiagram
- participant Client
- participant chatCore
- participant Translator
- participant Executor
- participant Provider
-
- Client->>chatCore: Request (any format)
- chatCore->>chatCore: Detect source format
- chatCore->>chatCore: Check bypass patterns
- chatCore->>chatCore: Resolve model & provider
- chatCore->>Translator: Translate request (source → OpenAI → target)
- chatCore->>Executor: Get executor for provider
- Executor->>Executor: Build URL, headers, transform request
- Executor->>Executor: Refresh credentials if needed
- Executor->>Provider: HTTP fetch (streaming or non-streaming)
-
- alt Streaming
- Provider-->>chatCore: SSE stream
- chatCore->>chatCore: Pipe through SSE transform stream
- Note over chatCore: Transform stream translates
each chunk: target → OpenAI → source
- chatCore-->>Client: Translated SSE stream
- else Non-streaming
- Provider-->>chatCore: JSON response
- chatCore->>Translator: Translate response
- chatCore-->>Client: Translated JSON
- end
-
- alt Error (401, 429, 500...)
- chatCore->>Executor: Retry with credential refresh
- chatCore->>chatCore: Account fallback logic
- end
-```
-
----
-
-### 4.4 Services (`open-sse/services/`)
-
-Business logic that supports the handlers and executors.
-
-| File | Purpose |
-| -------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| `provider.ts` | **Format detection** (`detectFormat`): analyzes request body structure to identify Claude/OpenAI/Gemini/Antigravity/Responses formats (includes `max_tokens` heuristic for Claude). Also: URL building, header building, thinking config normalization. Supports `openai-compatible-*` and `anthropic-compatible-*` dynamic providers. |
-| `model.ts` | Model string parsing (`claude/model-name` → `{provider: "claude", model: "model-name"}`), alias resolution with collision detection, input sanitization (rejects path traversal/control chars), and model info resolution with async alias getter support. |
-| `accountFallback.ts` | Rate-limit handling: exponential backoff (1s → 2s → 4s → max 2min), account cooldown management, error classification (which errors trigger fallback vs. not). |
-| `tokenRefresh.ts` | OAuth token refresh for **every provider**: Google (Gemini, Antigravity), Claude, Codex, Qwen, Qoder, GitHub (OAuth + Copilot dual-token), Kiro (AWS SSO OIDC + Social Auth). Includes in-flight promise deduplication cache and retry with exponential backoff. |
-| `combo.ts` | **Combo models**: chains of fallback models. If model A fails with a fallback-eligible error, try model B, then C, etc. Returns actual upstream status codes. |
-| `usage.ts` | Fetches quota/usage data from provider APIs (GitHub Copilot quotas, Antigravity model quotas, Codex rate limits, Kiro usage breakdowns, Claude settings). |
-| `accountSelector.ts` | Smart account selection with scoring algorithm: considers priority, health status, round-robin position, and cooldown state to pick the optimal account for each request. |
-| `contextManager.ts` | Request context lifecycle management: creates and tracks per-request context objects with metadata (request ID, timestamps, provider info) for debugging and logging. |
-| `ipFilter.ts` | IP-based access control: supports allowlist and blocklist modes. Validates client IP against configured rules before processing API requests. |
-| `sessionManager.ts` | Session tracking with client fingerprinting: tracks active sessions using hashed client identifiers, monitors request counts, and provides session metrics. |
-| `signatureCache.ts` | Request signature-based deduplication cache: prevents duplicate requests by caching recent request signatures and returning cached responses for identical requests within a time window. |
-| `systemPrompt.ts` | Global system prompt injection: prepends or appends a configurable system prompt to all requests, with per-provider compatibility handling. |
-| `thinkingBudget.ts` | Reasoning token budget management: supports passthrough, auto (strip thinking config), custom (fixed budget), and adaptive (complexity-scaled) modes for controlling thinking/reasoning tokens. |
-| `wildcardRouter.ts` | Wildcard model pattern routing: resolves wildcard patterns (e.g., `*/claude-*`) to concrete provider/model pairs based on availability and priority. |
-
-#### Token Refresh Deduplication
-
-```mermaid
-sequenceDiagram
- participant R1 as Request 1
- participant R2 as Request 2
- participant Cache as refreshPromiseCache
- participant OAuth as OAuth Provider
-
- R1->>Cache: getAccessToken("gemini", token)
- Cache->>Cache: No in-flight promise
- Cache->>OAuth: Start refresh
- R2->>Cache: getAccessToken("gemini", token)
- Cache->>Cache: Found in-flight promise
- Cache-->>R2: Return existing promise
- OAuth-->>Cache: New access token
- Cache-->>R1: New access token
- Cache-->>R2: Same access token (shared)
- Cache->>Cache: Delete cache entry
-```
-
-#### Account Fallback State Machine
-
-```mermaid
-stateDiagram-v2
- [*] --> Active
- Active --> Error: Request fails (401/429/500)
- Error --> Cooldown: Apply backoff
- Cooldown --> Active: Cooldown expires
- Active --> Active: Request succeeds (reset backoff)
-
- state Error {
- [*] --> ClassifyError
- ClassifyError --> ShouldFallback: Rate limit / Auth / Transient
- ClassifyError --> NoFallback: 400 Bad Request
- }
-
- state Cooldown {
- [*] --> ExponentialBackoff
- ExponentialBackoff: Level 0 = 1s
- ExponentialBackoff: Level 1 = 2s
- ExponentialBackoff: Level 2 = 4s
- ExponentialBackoff: Max = 2min
- }
-```
-
-#### Combo Model Chain
-
-```mermaid
-flowchart LR
- A["Request with\ncombo model"] --> B["Model A"]
- B -->|"2xx Success"| C["Return response"]
- B -->|"429/401/500"| D{"Fallback\neligible?"}
- D -->|Yes| E["Model B"]
- D -->|No| F["Return error"]
- E -->|"2xx Success"| C
- E -->|"429/401/500"| G{"Fallback\neligible?"}
- G -->|Yes| H["Model C"]
- G -->|No| F
- H -->|"2xx Success"| C
- H -->|"Fail"| I["All failed →\nReturn last status"]
-```
-
----
-
-### 4.5 Translator (`open-sse/translator/`)
-
-The **format translation engine** using a self-registering plugin system.
-
-#### Architecture
-
-```mermaid
-graph TD
- subgraph "Request Translation"
- A["Claude → OpenAI"]
- B["Gemini → OpenAI"]
- C["Antigravity → OpenAI"]
- D["OpenAI Responses → OpenAI"]
- E["OpenAI → Claude"]
- F["OpenAI → Gemini"]
- G["OpenAI → Kiro"]
- H["OpenAI → Cursor"]
- end
-
- subgraph "Response Translation"
- I["Claude → OpenAI"]
- J["Gemini → OpenAI"]
- K["Kiro → OpenAI"]
- L["Cursor → OpenAI"]
- M["OpenAI → Claude"]
- N["OpenAI → Antigravity"]
- O["OpenAI → Responses"]
- end
-```
-
-| Directory | Files | Description |
-| ------------ | ------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| `request/` | 8 translators | Convert request bodies between formats. Each file self-registers via `register(from, to, fn)` on import. |
-| `response/` | 7 translators | Convert streaming response chunks between formats. Handles SSE event types, thinking blocks, tool calls. |
-| `helpers/` | 6 helpers | Shared utilities: `claudeHelper` (system prompt extraction, thinking config), `geminiHelper` (parts/contents mapping), `openaiHelper` (format filtering), `toolCallHelper` (ID generation, missing response injection), `maxTokensHelper`, `responsesApiHelper`. |
-| `index.ts` | — | Translation engine: `translateRequest()`, `translateResponse()`, state management, registry. |
-| `formats.ts` | — | Format constants: `OPENAI`, `CLAUDE`, `GEMINI`, `ANTIGRAVITY`, `KIRO`, `CURSOR`, `OPENAI_RESPONSES`. |
-
-#### Key Design: Self-Registering Plugins
-
-```javascript
-// Each translator file calls register() on import:
-import { register } from "../index.js";
-register("claude", "openai", translateClaudeToOpenAI);
-
-// The index.js imports all translator files, triggering registration:
-import "./request/claude-to-openai.js"; // ← self-registers
-```
-
----
-
-### 4.6 Utils (`open-sse/utils/`)
-
-| File | Purpose |
-| ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
-| `error.ts` | Error response building (OpenAI-compatible format), upstream error parsing, Antigravity retry-time extraction from error messages, SSE error streaming. |
-| `stream.ts` | **SSE Transform Stream** — the core streaming pipeline. Two modes: `TRANSLATE` (full format translation) and `PASSTHROUGH` (normalize + extract usage). Handles chunk buffering, usage estimation, content length tracking. Per-stream encoder/decoder instances avoid shared state. |
-| `streamHelpers.ts` | Low-level SSE utilities: `parseSSELine` (whitespace-tolerant), `hasValuableContent` (filters empty chunks for OpenAI/Claude/Gemini), `fixInvalidId`, `formatSSE` (format-aware SSE serialization with `perf_metrics` cleanup). |
-| `usageTracking.ts` | Token usage extraction from any format (Claude/OpenAI/Gemini/Responses), estimation with separate tool/message char-per-token ratios, buffer addition (2000 tokens safety margin), format-specific field filtering, console logging with ANSI colors. |
-| `requestLogger.ts` | File-based request logging (opt-in via `ENABLE_REQUEST_LOGS=true`). Creates session folders with numbered files: `1_req_client.json` → `7_res_client.txt`. All I/O is async (fire-and-forget). Masks sensitive headers. |
-| `bypassHandler.ts` | Intercepts specific patterns from Claude CLI (title extraction, warmup, count) and returns fake responses without calling any provider. Supports both streaming and non-streaming. Intentionally limited to Claude CLI scope. |
-| `networkProxy.ts` | Resolves outbound proxy URL for a given provider with precedence: provider-specific config → global config → environment variables (`HTTPS_PROXY`/`HTTP_PROXY`/`ALL_PROXY`). Supports `NO_PROXY` exclusions. Caches config for 30s. |
-
-#### SSE Streaming Pipeline
-
-```mermaid
-flowchart TD
- A["Provider SSE stream"] --> B["TextDecoder\n(per-stream instance)"]
- B --> C["Buffer lines\n(split on newline)"]
- C --> D["parseSSELine()\n(trim whitespace, parse JSON)"]
- D --> E{"Mode?"}
- E -->|TRANSLATE| F["translateResponse()\ntarget → OpenAI → source"]
- E -->|PASSTHROUGH| G["fixInvalidId()\nnormalize chunk"]
- F --> H["hasValuableContent()\nfilter empty chunks"]
- G --> H
- H -->|"Has content"| I["extractUsage()\ntrack token counts"]
- H -->|"Empty"| J["Skip chunk"]
- I --> K["formatSSE()\nserialize + clean perf_metrics"]
- K --> L["TextEncoder\n(per-stream instance)"]
- L --> M["Enqueue to\nclient stream"]
-
- style A fill:#f9f,stroke:#333
- style M fill:#9f9,stroke:#333
-```
-
-#### Request Logger Session Structure
-
-```
-logs/
-└── claude_gemini_claude-sonnet_20260208_143045/
- ├── 1_req_client.json ← Raw client request
- ├── 2_req_source.json ← After initial conversion
- ├── 3_req_openai.json ← OpenAI intermediate format
- ├── 4_req_target.json ← Final target format
- ├── 5_res_provider.txt ← Provider SSE chunks (streaming)
- ├── 5_res_provider.json ← Provider response (non-streaming)
- ├── 6_res_openai.txt ← OpenAI intermediate chunks
- ├── 7_res_client.txt ← Client-facing SSE chunks
- └── 6_error.json ← Error details (if any)
-```
-
----
-
-### 4.7 Application Layer (`src/`)
-
-| Directory | Purpose |
-| ------------- | ---------------------------------------------------------------------- |
-| `src/app/` | Web UI, API routes, Express middleware, OAuth callback handlers |
-| `src/lib/` | Database access (`localDb.ts`, `usageDb.ts`), authentication, shared |
-| `src/mitm/` | Man-in-the-middle proxy utilities for intercepting provider traffic |
-| `src/models/` | Database model definitions |
-| `src/shared/` | Wrappers around open-sse functions (provider, stream, error, etc.) |
-| `src/sse/` | SSE endpoint handlers that wire the open-sse library to Express routes |
-| `src/store/` | Application state management |
-
-#### Notable API Routes
-
-| Route | Methods | Purpose |
-| --------------------------------------------- | --------------- | ------------------------------------------------------------------------------------- |
-| `/api/provider-models` | GET/POST/DELETE | CRUD for custom models per provider |
-| `/api/models/catalog` | GET | Aggregated catalog of all models (chat, embedding, image, custom) grouped by provider |
-| `/api/settings/proxy` | GET/PUT/DELETE | Hierarchical outbound proxy configuration (`global/providers/combos/keys`) |
-| `/api/settings/proxy/test` | POST | Validates proxy connectivity and returns public IP/latency |
-| `/v1/providers/[provider]/chat/completions` | POST | Dedicated per-provider chat completions with model validation |
-| `/v1/providers/[provider]/embeddings` | POST | Dedicated per-provider embeddings with model validation |
-| `/v1/providers/[provider]/images/generations` | POST | Dedicated per-provider image generation with model validation |
-| `/api/settings/ip-filter` | GET/PUT | IP allowlist/blocklist management |
-| `/api/settings/thinking-budget` | GET/PUT | Reasoning token budget configuration (passthrough/auto/custom/adaptive) |
-| `/api/settings/system-prompt` | GET/PUT | Global system prompt injection for all requests |
-| `/api/sessions` | GET | Active session tracking and metrics |
-| `/api/rate-limits` | GET | Per-account rate limit status |
-
----
-
-## 5. Key Design Patterns
-
-### 5.1 Hub-and-Spoke Translation
-
-All formats translate through **OpenAI format as the hub**. Adding a new provider only requires writing **one pair** of translators (to/from OpenAI), not N pairs.
-
-### 5.2 Executor Strategy Pattern
-
-Each provider has a dedicated executor class inheriting from `BaseExecutor`. The factory in `executors/index.ts` selects the right one at runtime.
-
-### 5.3 Self-Registering Plugin System
-
-Translator modules register themselves on import via `register()`. Adding a new translator is just creating a file and importing it.
-
-### 5.4 Account Fallback with Exponential Backoff
-
-When a provider returns 429/401/500, the system can switch to the next account, applying exponential cooldowns (1s → 2s → 4s → max 2min).
-
-### 5.5 Combo Model Chains
-
-A "combo" groups multiple `provider/model` strings. If the first fails, fallback to the next automatically.
-
-### 5.6 Stateful Streaming Translation
-
-Response translation maintains state across SSE chunks (thinking block tracking, tool call accumulation, content block indexing) via the `initState()` mechanism.
-
-### 5.7 Usage Safety Buffer
-
-A 2000-token buffer is added to reported usage to prevent clients from hitting context window limits due to overhead from system prompts and format translation.
-
----
-
-## 6. Supported Formats
-
-| Format | Direction | Identifier |
-| ----------------------- | --------------- | ------------------ |
-| OpenAI Chat Completions | source + target | `openai` |
-| OpenAI Responses API | source + target | `openai-responses` |
-| Anthropic Claude | source + target | `claude` |
-| Google Gemini | source + target | `gemini` |
-| Google Gemini CLI | target only | `gemini-cli` |
-| Antigravity | source + target | `antigravity` |
-| AWS Kiro | target only | `kiro` |
-| Cursor | target only | `cursor` |
-
----
-
-## 7. Supported Providers
-
-| Provider | Auth Method | Executor | Key Notes |
-| ------------------------ | ---------------------- | ----------- | --------------------------------------------- |
-| Anthropic Claude | API key or OAuth | Default | Uses `x-api-key` header |
-| Google Gemini | API key or OAuth | Default | Uses `x-goog-api-key` header |
-| Google Gemini CLI | OAuth | GeminiCLI | Uses `streamGenerateContent` endpoint |
-| Antigravity | OAuth | Antigravity | Multi-URL fallback, custom retry parsing |
-| OpenAI | API key | Default | Standard Bearer auth |
-| Codex | OAuth | Codex | Injects system instructions, manages thinking |
-| GitHub Copilot | OAuth + Copilot token | Github | Dual token, VSCode header mimicking |
-| Kiro (AWS) | AWS SSO OIDC or Social | Kiro | Binary EventStream parsing |
-| Cursor IDE | Checksum auth | Cursor | Protobuf encoding, SHA-256 checksums |
-| Qwen | OAuth | Default | Standard auth |
-| Qoder | OAuth (Basic + Bearer) | Default | Dual auth header |
-| OpenRouter | API key | Default | Standard Bearer auth |
-| GLM, Kimi, MiniMax | API key | Default | Claude-compatible, use `x-api-key` |
-| `openai-compatible-*` | API key | Default | Dynamic: any OpenAI-compatible endpoint |
-| `anthropic-compatible-*` | API key | Default | Dynamic: any Claude-compatible endpoint |
-
----
-
-## 8. Data Flow Summary
-
-### Streaming Request
-
-```mermaid
-flowchart LR
- A["Client"] --> B["detectFormat()"]
- B --> C["translateRequest()\nsource → OpenAI → target"]
- C --> D["Executor\nbuildUrl + buildHeaders"]
- D --> E["fetch(providerURL)"]
- E --> F["createSSEStream()\nTRANSLATE mode"]
- F --> G["parseSSELine()"]
- G --> H["translateResponse()\ntarget → OpenAI → source"]
- H --> I["extractUsage()\n+ addBuffer"]
- I --> J["formatSSE()"]
- J --> K["Client receives\ntranslated SSE"]
- K --> L["logUsage()\nsaveRequestUsage()"]
-```
-
-### Non-Streaming Request
-
-```mermaid
-flowchart LR
- A["Client"] --> B["detectFormat()"]
- B --> C["translateRequest()\nsource → OpenAI → target"]
- C --> D["Executor.execute()"]
- D --> E["translateResponse()\ntarget → OpenAI → source"]
- E --> F["Return JSON\nresponse"]
-```
-
-### Bypass Flow (Claude CLI)
-
-```mermaid
-flowchart LR
- A["Claude CLI request"] --> B{"Match bypass\npattern?"}
- B -->|"Title/Warmup/Count"| C["Generate fake\nOpenAI response"]
- B -->|"No match"| D["Normal flow"]
- C --> E["Translate to\nsource format"]
- E --> F["Return without\ncalling provider"]
-```
diff --git a/docs/i18n/id/CONTRIBUTING.md b/docs/i18n/id/CONTRIBUTING.md
new file mode 100644
index 0000000000..97ec4be241
--- /dev/null
+++ b/docs/i18n/id/CONTRIBUTING.md
@@ -0,0 +1,299 @@
+# Contributing to OmniRoute (Bahasa Indonesia)
+
+🌐 **Languages:** 🇺🇸 [English](../../../CONTRIBUTING.md) · 🇪🇸 [es](../es/CONTRIBUTING.md) · 🇫🇷 [fr](../fr/CONTRIBUTING.md) · 🇩🇪 [de](../de/CONTRIBUTING.md) · 🇮🇹 [it](../it/CONTRIBUTING.md) · 🇷🇺 [ru](../ru/CONTRIBUTING.md) · 🇨🇳 [zh-CN](../zh-CN/CONTRIBUTING.md) · 🇯🇵 [ja](../ja/CONTRIBUTING.md) · 🇰🇷 [ko](../ko/CONTRIBUTING.md) · 🇸🇦 [ar](../ar/CONTRIBUTING.md) · 🇮🇳 [in](../in/CONTRIBUTING.md) · 🇹🇭 [th](../th/CONTRIBUTING.md) · 🇻🇳 [vi](../vi/CONTRIBUTING.md) · 🇮🇩 [id](../id/CONTRIBUTING.md) · 🇲🇾 [ms](../ms/CONTRIBUTING.md) · 🇳🇱 [nl](../nl/CONTRIBUTING.md) · 🇵🇱 [pl](../pl/CONTRIBUTING.md) · 🇸🇪 [sv](../sv/CONTRIBUTING.md) · 🇳🇴 [no](../no/CONTRIBUTING.md) · 🇩🇰 [da](../da/CONTRIBUTING.md) · 🇫🇮 [fi](../fi/CONTRIBUTING.md) · 🇵🇹 [pt](../pt/CONTRIBUTING.md) · 🇷🇴 [ro](../ro/CONTRIBUTING.md) · 🇭🇺 [hu](../hu/CONTRIBUTING.md) · 🇧🇬 [bg](../bg/CONTRIBUTING.md) · 🇸🇰 [sk](../sk/CONTRIBUTING.md) · 🇺🇦 [uk-UA](../uk-UA/CONTRIBUTING.md) · 🇮🇱 [he](../he/CONTRIBUTING.md) · 🇵🇭 [phi](../phi/CONTRIBUTING.md) · 🇧🇷 [pt-BR](../pt-BR/CONTRIBUTING.md) · 🇨🇿 [cs](../cs/CONTRIBUTING.md)
+
+---
+
+Thank you for your interest in contributing! This guide covers everything you need to get started.
+
+---
+
+## Development Setup
+
+### Prerequisites
+
+- **Node.js** >= 18 < 24 (recommended: 22 LTS)
+- **npm** 10+
+- **Git**
+
+### Clone & Install
+
+```bash
+git clone https://github.com/diegosouzapw/OmniRoute.git
+cd OmniRoute
+npm install
+```
+
+### Environment Variables
+
+```bash
+# Create your .env from the template
+cp .env.example .env
+
+# Generate required secrets
+echo "JWT_SECRET=$(openssl rand -base64 48)" >> .env
+echo "API_KEY_SECRET=$(openssl rand -hex 32)" >> .env
+```
+
+Key variables for development:
+
+| Variable | Development Default | Description |
+| ---------------------- | ------------------------ | --------------------- |
+| `PORT` | `20128` | Server port |
+| `NEXT_PUBLIC_BASE_URL` | `http://localhost:20128` | Base URL for frontend |
+| `JWT_SECRET` | (generate above) | JWT signing secret |
+| `INITIAL_PASSWORD` | `CHANGEME` | First login password |
+| `APP_LOG_LEVEL` | `info` | Log verbosity level |
+
+### Dashboard Settings
+
+The dashboard provides UI toggles for features that can also be configured via environment variables:
+
+| Setting Location | Toggle | Description |
+| ------------------- | ------------------ | ------------------------------ |
+| Settings → Advanced | Debug Mode | Enable debug request logs (UI) |
+| Settings → General | Sidebar Visibility | Show/hide sidebar sections |
+
+These settings are stored in the database and persist across restarts, overriding env var defaults when set.
+
+### Running Locally
+
+```bash
+# Development mode (hot reload)
+npm run dev
+
+# Production build
+npm run build
+npm run start
+
+# Common port configuration
+PORT=20128 NEXT_PUBLIC_BASE_URL=http://localhost:20128 npm run dev
+```
+
+Default URLs:
+
+- **Dashboard**: `http://localhost:20128/dashboard`
+- **API**: `http://localhost:20128/v1`
+
+---
+
+## Git Workflow
+
+> ⚠️ **NEVER commit directly to `main`.** Always use feature branches.
+
+```bash
+git checkout -b feat/your-feature-name
+# ... make changes ...
+git commit -m "feat: describe your change"
+git push -u origin feat/your-feature-name
+# Open a Pull Request on GitHub
+```
+
+### Branch Naming
+
+| Prefix | Purpose |
+| ----------- | ------------------------- |
+| `feat/` | New features |
+| `fix/` | Bug fixes |
+| `refactor/` | Code restructuring |
+| `docs/` | Documentation changes |
+| `test/` | Test additions/fixes |
+| `chore/` | Tooling, CI, dependencies |
+
+### Commit Messages
+
+Follow [Conventional Commits](https://www.conventionalcommits.org/):
+
+```
+feat: add circuit breaker for provider calls
+fix: resolve JWT secret validation edge case
+docs: update SECURITY.md with PII protection
+test: add observability unit tests
+refactor(db): consolidate rate limit tables
+```
+
+Scopes: `db`, `sse`, `oauth`, `dashboard`, `api`, `cli`, `docker`, `ci`, `mcp`, `a2a`, `memory`, `skills`.
+
+---
+
+## Running Tests
+
+```bash
+# All tests (unit + vitest + ecosystem + e2e)
+npm run test:all
+
+# Single test file (Node.js native test runner — most tests use this)
+node --import tsx/esm --test tests/unit/your-file.test.mjs
+
+# Vitest (MCP server, autoCombo, cache)
+npm run test:vitest
+
+# E2E tests (requires Playwright)
+npm run test:e2e
+
+# Protocol clients E2E (MCP transports, A2A)
+npm run test:protocols:e2e
+
+# Ecosystem compatibility tests
+npm run test:ecosystem
+
+# Coverage (55% min statements/lines/functions; 60% branches)
+npm run test:coverage
+npm run coverage:report
+
+# Lint + format check
+npm run lint
+npm run check
+```
+
+Coverage notes:
+
+- `npm run test:coverage` measures source coverage for the main unit test suite, excludes `tests/**`, and includes `open-sse/**`
+- `npm run coverage:report` prints the detailed file-by-file report from the latest coverage run
+- `npm run test:coverage:legacy` preserves the older metric for historical comparison
+- See `docs/COVERAGE_PLAN.md` for the phased coverage improvement roadmap
+
+Current test status: **122 unit test files** covering:
+
+- Provider translators and format conversion
+- Rate limiting, circuit breaker, and resilience
+- Semantic cache, idempotency, progress tracking
+- Database operations and schema (21 DB modules)
+- OAuth flows and authentication
+- API endpoint validation (Zod v4)
+- MCP server tools and scope enforcement
+- Memory and Skills systems
+
+---
+
+## Code Style
+
+- **ESLint** — Run `npm run lint` before committing
+- **Prettier** — Auto-formatted via `lint-staged` on commit (2 spaces, semicolons, double quotes, 100 char width, es5 trailing commas)
+- **TypeScript** — All `src/` code uses `.ts`/`.tsx`; `open-sse/` uses `.ts`/`.js`; document with TSDoc (`@param`, `@returns`, `@throws`)
+- **No `eval()`** — ESLint enforces `no-eval`, `no-implied-eval`, `no-new-func`
+- **Zod validation** — Use Zod v4 schemas for all API input validation
+- **Naming**: Files = camelCase/kebab-case, components = PascalCase, constants = UPPER_SNAKE
+
+---
+
+## Project Structure
+
+```
+src/ # TypeScript (.ts / .tsx)
+├── app/ # Next.js 16 App Router
+│ ├── (dashboard)/ # Dashboard pages (23 sections)
+│ ├── api/ # API routes (51 directories)
+│ └── login/ # Auth pages (.tsx)
+├── domain/ # Policy engine (policyEngine, comboResolver, costRules, etc.)
+├── lib/ # Core business logic (.ts)
+│ ├── a2a/ # Agent-to-Agent v0.3 protocol server
+│ ├── acp/ # Agent Communication Protocol registry
+│ ├── compliance/ # Compliance policy engine
+│ ├── db/ # SQLite database layer (21 modules + 16 migrations)
+│ ├── memory/ # Persistent conversational memory
+│ ├── oauth/ # OAuth providers, services, and utilities
+│ ├── skills/ # Extensible skill framework
+│ ├── usage/ # Usage tracking and cost calculation
+│ └── localDb.ts # Re-export layer only — never add logic here
+├── middleware/ # Request middleware (promptInjectionGuard)
+├── mitm/ # MITM proxy (cert, DNS, target routing)
+├── shared/
+│ ├── components/ # React components (.tsx)
+│ ├── constants/ # Provider definitions (60+), MCP scopes, routing strategies
+│ ├── utils/ # Circuit breaker, sanitizer, auth helpers
+│ └── validation/ # Zod v4 schemas
+└── sse/ # SSE proxy pipeline
+
+open-sse/ # @omniroute/open-sse workspace
+├── executors/ # 14 provider-specific request executors
+├── handlers/ # 11 request handlers (chat, responses, embeddings, images, etc.)
+├── mcp-server/ # MCP server (25 tools, 3 transports, 10 scopes)
+├── services/ # 36+ services (combo, autoCombo, rateLimitManager, etc.)
+├── translator/ # Format translators (OpenAI ↔ Claude ↔ Gemini ↔ Responses ↔ Ollama)
+├── transformer/ # Responses API transformer
+└── utils/ # 22 utility modules (stream, TLS, proxy, logging)
+
+electron/ # Electron desktop app (cross-platform)
+
+tests/
+├── unit/ # Node.js test runner (122 test files)
+├── integration/ # Integration tests
+├── e2e/ # Playwright tests
+├── security/ # Security tests
+├── translator/ # Translator-specific tests
+└── load/ # Load tests
+
+docs/ # Documentation
+├── ARCHITECTURE.md # System architecture
+├── API_REFERENCE.md # All endpoints
+├── USER_GUIDE.md # Provider setup, CLI integration
+├── TROUBLESHOOTING.md # Common issues
+├── MCP-SERVER.md # MCP server (25 tools)
+├── A2A-SERVER.md # A2A agent protocol
+├── AUTO-COMBO.md # Auto-combo engine
+├── CLI-TOOLS.md # CLI tools integration
+├── COVERAGE_PLAN.md # Test coverage improvement plan
+├── openapi.yaml # OpenAPI specification
+└── adr/ # Architecture Decision Records
+```
+
+---
+
+## Adding a New Provider
+
+### Step 1: Register Provider Constants
+
+Add to `src/shared/constants/providers.ts` — Zod-validated at module load.
+
+### Step 2: Add Executor (if custom logic needed)
+
+Create executor in `open-sse/executors/your-provider.ts` extending the base executor.
+
+### Step 3: Add Translator (if non-OpenAI format)
+
+Create request/response translators in `open-sse/translator/`.
+
+### Step 4: Add OAuth Config (if OAuth-based)
+
+Add OAuth credentials in `src/lib/oauth/constants/oauth.ts` and service in `src/lib/oauth/services/`.
+
+### Step 5: Register Models
+
+Add model definitions in `open-sse/config/providerRegistry.ts`.
+
+### Step 6: Add Tests
+
+Write unit tests in `tests/unit/` covering at minimum:
+
+- Provider registration
+- Request/response translation
+- Error handling
+
+---
+
+## Pull Request Checklist
+
+- [ ] Tests pass (`npm test`)
+- [ ] Linting passes (`npm run lint`)
+- [ ] Build succeeds (`npm run build`)
+- [ ] TypeScript types added for new public functions and interfaces
+- [ ] No hardcoded secrets or fallback values
+- [ ] All inputs validated with Zod schemas
+- [ ] CHANGELOG updated (if user-facing change)
+- [ ] Documentation updated (if applicable)
+
+---
+
+## Releasing
+
+Releases are managed via the `/generate-release` workflow. When a new GitHub Release is created, the package is **automatically published to npm** via GitHub Actions.
+
+---
+
+## Getting Help
+
+- **Architecture**: See [`docs/ARCHITECTURE.md`](docs/ARCHITECTURE.md)
+- **API Reference**: See [`docs/API_REFERENCE.md`](docs/API_REFERENCE.md)
+- **Issues**: [github.com/diegosouzapw/OmniRoute/issues](https://github.com/diegosouzapw/OmniRoute/issues)
+- **ADRs**: See `docs/adr/` for architectural decision records
diff --git a/docs/i18n/id/FEATURES.md b/docs/i18n/id/FEATURES.md
deleted file mode 100644
index 1993515728..0000000000
--- a/docs/i18n/id/FEATURES.md
+++ /dev/null
@@ -1,147 +0,0 @@
-# OmniRoute — Dashboard Features Gallery (Bahasa Indonesia)
-
-🌐 **Languages:** 🇺🇸 [English](../../../README.md) · 🇧🇷 [pt-BR](../pt-BR/README.md) · 🇪🇸 [es](../es/README.md) · 🇫🇷 [fr](../fr/README.md) · 🇩🇪 [de](../de/README.md) · 🇮🇹 [it](../it/README.md) · 🇷🇺 [ru](../ru/README.md) · 🇨🇳 [zh-CN](../zh-CN/README.md) · 🇯🇵 [ja](../ja/README.md) · 🇰🇷 [ko](../ko/README.md) · 🇸🇦 [ar](../ar/README.md) · 🇮🇳 [in](../in/README.md) · 🇹🇭 [th](../th/README.md) · 🇻🇳 [vi](../vi/README.md) · 🇮🇩 [id](../id/README.md) · 🇲🇾 [ms](../ms/README.md) · 🇳🇱 [nl](../nl/README.md) · 🇵🇱 [pl](../pl/README.md) · 🇸🇪 [sv](../sv/README.md) · 🇳🇴 [no](../no/README.md) · 🇩🇰 [da](../da/README.md) · 🇫🇮 [fi](../fi/README.md) · 🇵🇹 [pt](../pt/README.md) · 🇷🇴 [ro](../ro/README.md) · 🇭🇺 [hu](../hu/README.md) · 🇧🇬 [bg](../bg/README.md) · 🇸🇰 [sk](../sk/README.md) · 🇺🇦 [uk-UA](../uk-UA/README.md) · 🇮🇱 [he](../he/README.md) · 🇵🇭 [phi](../phi/README.md)
-
-> 🇺🇸 [English](../../../docs/FEATURES.md)
-
----
-
-Visual guide to every section of the OmniRoute dashboard.
-
----
-
-## 🔌 Providers
-
-Manage AI provider connections: OAuth providers (Claude Code, Codex, Gemini CLI), API key providers (Groq, DeepSeek, OpenRouter), and free providers (Qoder, Qwen, Kiro). Kiro accounts include credit balance tracking — remaining credits, total allowance, and renewal date visible in Dashboard → Usage.
-
-
-
----
-
-## 🎨 Combos
-
-Create model routing combos with 6 strategies: priority, weighted, round-robin, random, least-used, and cost-optimized. Each combo chains multiple models with automatic fallback and includes quick templates and readiness checks.
-
-
-
----
-
-## 📊 Analytics
-
-Comprehensive usage analytics with token consumption, cost estimates, activity heatmaps, weekly distribution charts, and per-provider breakdowns.
-
-
-
----
-
-## 🏥 System Health
-
-Real-time monitoring: uptime, memory, version, latency percentiles (p50/p95/p99), cache statistics, and provider circuit breaker states.
-
-
-
----
-
-## 🔧 Translator Playground
-
-Four modes for debugging API translations: **Playground** (format converter), **Chat Tester** (live requests), **Test Bench** (batch tests), and **Live Monitor** (real-time stream).
-
-
-
----
-
-## 🎮 Model Playground _(v2.0.9+)_
-
-Test any model directly from the dashboard. Select provider, model, and endpoint, write prompts with Monaco Editor, stream responses in real-time, abort mid-stream, and view timing metrics.
-
----
-
-## 🎨 Themes _(v2.0.5+)_
-
-Customizable color themes for the entire dashboard. Choose from 7 preset colors (Coral, Blue, Red, Green, Violet, Orange, Cyan) or create a custom theme by picking any hex color. Supports light, dark, and system mode.
-
----
-
-## ⚙️ Settings
-
-Comprehensive settings panel with tabs:
-
-- **General** — System storage, backup management (export/import database)
-- **Appearance** — Theme selector (dark/light/system), color theme presets and custom colors, health log visibility, sidebar item visibility controls
-- **Security** — API endpoint protection, custom provider blocking, IP filtering, session info
-- **Routing** — Model aliases, background task degradation
-- **Resilience** — Rate limit persistence, circuit breaker tuning
-- **Advanced** — Configuration overrides
-
-
-
----
-
-## 🔧 CLI Tools
-
-One-click configuration for AI coding tools: Claude Code, Codex CLI, Gemini CLI, OpenClaw, Kilo Code, Antigravity, Cline, Continue, Cursor, and Factory Droid. Features automated config apply/reset, connection profiles, and model mapping.
-
-
-
----
-
-## 🤖 CLI Agents _(v2.0.11+)_
-
-Dashboard for discovering and managing CLI agents. Shows a grid of 14 built-in agents (Codex, Claude, Goose, Gemini CLI, OpenClaw, Aider, OpenCode, Cline, Qwen Code, ForgeCode, Amazon Q, Open Interpreter, Cursor CLI, Warp) with:
-
-- **Installation status** — Installed / Not Found with version detection
-- **Protocol badges** — stdio, HTTP, etc.
-- **Custom agents** — Register any CLI tool via form (name, binary, version command, spawn args)
-- **CLI Fingerprint Matching** — Per-provider toggle to match native CLI request signatures, reducing ban risk while preserving proxy IP
-
----
-
-## 🖼️ Media _(v2.0.3+)_
-
-Generate images, videos, and music from the dashboard. Supports OpenAI, xAI, Together, Hyperbolic, SD WebUI, ComfyUI, AnimateDiff, Stable Audio Open, and MusicGen.
-
----
-
-## 📝 Request Logs
-
-Real-time request logging with filtering by provider, model, account, and API key. Shows status codes, token usage, latency, and response details.
-
-
-
----
-
-## 🌐 API Endpoint
-
-Your unified API endpoint with capability breakdown: Chat Completions, Responses API, Embeddings, Image Generation, Reranking, Audio Transcription, Text-to-Speech, Moderations, and registered API keys. Cloud proxy support for remote access.
-
-
-
----
-
-## 🔑 API Key Management
-
-Create, scope, and revoke API keys. Each key can be restricted to specific models/providers with full access or read-only permissions. Visual key management with usage tracking.
-
----
-
-## 📋 Audit Log
-
-Administrative action tracking with filtering by action type, actor, target, IP address, and timestamp. Full security event history.
-
----
-
-## 🖥️ Desktop Application
-
-Native Electron desktop app for Windows, macOS, and Linux. Run OmniRoute as a standalone application with system tray integration, offline support, auto-update, and one-click install.
-
-Key features:
-
-- Server readiness polling (no blank screen on cold start)
-- System tray with port management
-- Content Security Policy
-- Single-instance lock
-- Auto-update on restart
-- Platform-conditional UI (macOS traffic lights, Windows/Linux default titlebar)
-- Hardened Electron build packaging — symlinked `node_modules` in the standalone bundle is detected and rejected before packaging, preventing runtime dependency on the build machine (v2.5.5+)
-
-📖 See [`electron/README.md`](../electron/README.md) for full documentation.
diff --git a/docs/i18n/id/MCP-SERVER.md b/docs/i18n/id/MCP-SERVER.md
deleted file mode 100644
index 829acd30b1..0000000000
--- a/docs/i18n/id/MCP-SERVER.md
+++ /dev/null
@@ -1,87 +0,0 @@
-🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/MCP-SERVER.md) · 🇪🇸 [es](../es/MCP-SERVER.md) · 🇫🇷 [fr](../fr/MCP-SERVER.md) · 🇩🇪 [de](../de/MCP-SERVER.md) · 🇮🇹 [it](../it/MCP-SERVER.md) · 🇷🇺 [ru](../ru/MCP-SERVER.md) · 🇨🇳 [zh-CN](../zh-CN/MCP-SERVER.md) · 🇯🇵 [ja](../ja/MCP-SERVER.md) · 🇰🇷 [ko](../ko/MCP-SERVER.md) · 🇸🇦 [ar](../ar/MCP-SERVER.md) · 🇮🇳 [in](../in/MCP-SERVER.md) · 🇹🇭 [th](../th/MCP-SERVER.md) · 🇻🇳 [vi](../vi/MCP-SERVER.md) · 🇮🇩 [id](../id/MCP-SERVER.md) · 🇲🇾 [ms](../ms/MCP-SERVER.md) · 🇳🇱 [nl](../nl/MCP-SERVER.md) · 🇵🇱 [pl](../pl/MCP-SERVER.md) · 🇸🇪 [sv](../sv/MCP-SERVER.md) · 🇳🇴 [no](../no/MCP-SERVER.md) · 🇩🇰 [da](../da/MCP-SERVER.md) · 🇫🇮 [fi](../fi/MCP-SERVER.md) · 🇵🇹 [pt](../pt/MCP-SERVER.md) · 🇷🇴 [ro](../ro/MCP-SERVER.md) · 🇭🇺 [hu](../hu/MCP-SERVER.md) · 🇧🇬 [bg](../bg/MCP-SERVER.md) · 🇸🇰 [sk](../sk/MCP-SERVER.md) · 🇺🇦 [uk-UA](../uk-UA/MCP-SERVER.md) · 🇮🇱 [he](../he/MCP-SERVER.md) · 🇵🇭 [phi](../phi/MCP-SERVER.md)
-
----
-
-# OmniRoute MCP Server Documentation
-
-> Model Context Protocol server with 16 intelligent tools
-
-## Installation
-
-OmniRoute MCP is built-in. Start it with:
-
-```bash
-omniroute --mcp
-```
-
-Or via the open-sse transport:
-
-```bash
-# HTTP streamable transport (port 20130)
-omniroute --dev # MCP auto-starts on /mcp endpoint
-```
-
-## IDE Configuration
-
-See [IDE Configs](integrations/ide-configs.md) for Antigravity, Cursor, Copilot, and Claude Desktop setup.
-
----
-
-## Essential Tools (8)
-
-| Tool | Description |
-| :------------------------------ | :--------------------------------------- |
-| `omniroute_get_health` | Gateway health, circuit breakers, uptime |
-| `omniroute_list_combos` | All configured combos with models |
-| `omniroute_get_combo_metrics` | Performance metrics for a specific combo |
-| `omniroute_switch_combo` | Switch active combo by ID/name |
-| `omniroute_check_quota` | Quota status per provider or all |
-| `omniroute_route_request` | Send a chat completion through OmniRoute |
-| `omniroute_cost_report` | Cost analytics for a time period |
-| `omniroute_list_models_catalog` | Full model catalog with capabilities |
-
-## Advanced Tools (8)
-
-| Tool | Description |
-| :--------------------------------- | :---------------------------------------------- |
-| `omniroute_simulate_route` | Dry-run routing simulation with fallback tree |
-| `omniroute_set_budget_guard` | Session budget with degrade/block/alert actions |
-| `omniroute_set_resilience_profile` | Apply conservative/balanced/aggressive preset |
-| `omniroute_test_combo` | Live-test all models in a combo |
-| `omniroute_get_provider_metrics` | Detailed metrics for one provider |
-| `omniroute_best_combo_for_task` | Task-fitness recommendation with alternatives |
-| `omniroute_explain_route` | Explain a past routing decision |
-| `omniroute_get_session_snapshot` | Full session state: costs, tokens, errors |
-
-## Authentication
-
-MCP tools are authenticated via API key scopes. Each tool requires specific scopes:
-
-| Scope | Tools |
-| :------------- | :----------------------------------------------- |
-| `read:health` | get_health, get_provider_metrics |
-| `read:combos` | list_combos, get_combo_metrics |
-| `write:combos` | switch_combo |
-| `read:quota` | check_quota |
-| `write:route` | route_request, simulate_route, test_combo |
-| `read:usage` | cost_report, get_session_snapshot, explain_route |
-| `write:config` | set_budget_guard, set_resilience_profile |
-| `read:models` | list_models_catalog, best_combo_for_task |
-
-## Audit Logging
-
-Every tool call is logged to `mcp_tool_audit` with:
-
-- Tool name, arguments, result
-- Duration (ms), success/failure
-- API key hash, timestamp
-
-## Files
-
-| File | Purpose |
-| :------------------------------------------- | :------------------------------------------ |
-| `open-sse/mcp-server/server.ts` | MCP server creation + 16 tool registrations |
-| `open-sse/mcp-server/transport.ts` | Stdio + HTTP transport |
-| `open-sse/mcp-server/auth.ts` | API key + scope validation |
-| `open-sse/mcp-server/audit.ts` | Tool call audit logging |
-| `open-sse/mcp-server/tools/advancedTools.ts` | 8 advanced tool handlers |
diff --git a/docs/i18n/id/README.md b/docs/i18n/id/README.md
index e5145fcd6e..e6b86b8748 100644
--- a/docs/i18n/id/README.md
+++ b/docs/i18n/id/README.md
@@ -1,13 +1,12 @@
# 🚀 OmniRoute — The Free AI Gateway (Bahasa Indonesia)
-🌐 **Languages:** 🇺🇸 [English](../../../README.md) · 🇪🇸 [es](../es/README.md) · 🇫🇷 [fr](../fr/README.md) · 🇩🇪 [de](../de/README.md) · 🇮🇹 [it](../it/README.md) · 🇷🇺 [ru](../ru/README.md) · 🇨🇳 [zh-CN](../zh-CN/README.md) · 🇯🇵 [ja](../ja/README.md) · 🇰🇷 [ko](../ko/README.md) · 🇸🇦 [ar](../ar/README.md) · 🇮🇳 [in](../in/README.md) · 🇹🇭 [th](../th/README.md) · 🇻🇳 [vi](../vi/README.md) · 🇮🇩 [id](../id/README.md) · 🇲🇾 [ms](../ms/README.md) · 🇳🇱 [nl](../nl/README.md) · 🇵🇱 [pl](../pl/README.md) · 🇸🇪 [sv](../sv/README.md) · 🇳🇴 [no](../no/README.md) · 🇩🇰 [da](../da/README.md) · 🇫🇮 [fi](../fi/README.md) · 🇵🇹 [pt](../pt/README.md) · 🇷🇴 [ro](../ro/README.md) · 🇭🇺 [hu](../hu/README.md) · 🇧🇬 [bg](../bg/README.md) · 🇸🇰 [sk](../sk/README.md) · 🇺🇦 [uk-UA](../uk-UA/README.md) · 🇮🇱 [he](../he/README.md) · 🇵🇭 [phi](../phi/README.md) · 🇧🇷 [pt-BR](../pt-BR/README.md)
+🌐 **Languages:** 🇺🇸 [English](../../../README.md) · 🇪🇸 [es](../es/README.md) · 🇫🇷 [fr](../fr/README.md) · 🇩🇪 [de](../de/README.md) · 🇮🇹 [it](../it/README.md) · 🇷🇺 [ru](../ru/README.md) · 🇨🇳 [zh-CN](../zh-CN/README.md) · 🇯🇵 [ja](../ja/README.md) · 🇰🇷 [ko](../ko/README.md) · 🇸🇦 [ar](../ar/README.md) · 🇮🇳 [in](../in/README.md) · 🇹🇭 [th](../th/README.md) · 🇻🇳 [vi](../vi/README.md) · 🇮🇩 [id](../id/README.md) · 🇲🇾 [ms](../ms/README.md) · 🇳🇱 [nl](../nl/README.md) · 🇵🇱 [pl](../pl/README.md) · 🇸🇪 [sv](../sv/README.md) · 🇳🇴 [no](../no/README.md) · 🇩🇰 [da](../da/README.md) · 🇫🇮 [fi](../fi/README.md) · 🇵🇹 [pt](../pt/README.md) · 🇷🇴 [ro](../ro/README.md) · 🇭🇺 [hu](../hu/README.md) · 🇧🇬 [bg](../bg/README.md) · 🇸🇰 [sk](../sk/README.md) · 🇺🇦 [uk-UA](../uk-UA/README.md) · 🇮🇱 [he](../he/README.md) · 🇵🇭 [phi](../phi/README.md) · 🇧🇷 [pt-BR](../pt-BR/README.md) · 🇨🇿 [cs](../cs/README.md)
---
-
### Never stop coding. Smart routing to **FREE & low-cost AI models** with automatic fallback.
-_Your universal API proxy — one endpoint, 67+ providers, zero downtime. Now with **MCP & A2A** agent orchestration._
+_Your universal API proxy — one endpoint, 60+ providers, zero downtime. Now with **MCP Server (25 tools)**, **A2A Protocol**, **Memory/Skills Systems** & **Electron Desktop App**._
**Chat Completions • Embeddings • Image Generation • Video • Music • Audio • Reranking • **Web Search** • MCP Server • A2A Protocol • 100% TypeScript**
@@ -47,15 +46,17 @@ _Your universal API proxy — one endpoint, 67+ providers, zero downtime. Now wi
> - `APP_LOG_FILE_PATH`
> - `APP_LOG_MAX_FILE_SIZE`
> - `APP_LOG_RETENTION_DAYS`
+> - `APP_LOG_MAX_FILES`
> - `APP_LOG_LEVEL`
> - `APP_LOG_FORMAT`
> - `CALL_LOG_RETENTION_DAYS`
+> - `CALL_LOG_MAX_ENTRIES`
>
> For release details and upgrade notes, see the [CHANGELOG](CHANGELOG.md).
---
-## 🆕 What's New in v3.0.0
+## 🆕 What's New
> **Upgrading from v2.9.5?** — See the [full CHANGELOG](CHANGELOG.md#300--2026-03-22-release-candidate--not-yet-merged-to-main) for all changes.
@@ -275,7 +276,7 @@ Developers pay $20–200/month for Claude Pro, Codex Pro, or GitHub Copilot. Eve
- **Smart 4-Tier Fallback** — If subscription quota runs out, automatically redirects to API Key → Cheap → Free with zero manual intervention
- **Real-Time Quota Tracking** — Shows token consumption in real-time with reset countdown (5h, daily, weekly)
- **Multi-Account Support** — Multiple accounts per provider with auto round-robin — when one runs out, switches to the next
-- **Custom Combos** — Customizable fallback chains with 6 balancing strategies (fill-first, round-robin, P2C, random, least-used, cost-optimized)
+- **Custom Combos** — Customizable fallback chains with 9 balancing strategies (priority, weighted, fill-first, round-robin, P2C, random, least-used, cost-optimized, strict-random)
- **Codex Business Quotas** — Business/Team workspace quota monitoring directly in the dashboard
@@ -287,7 +288,7 @@ OpenAI uses one format, Claude (Anthropic) uses another, Gemini yet another. If
**How OmniRoute solves it:**
-- **Unified Endpoint** — A single `http://localhost:20128/v1` serves as proxy for all 67+ providers
+- **Unified Endpoint** — A single `http://localhost:20128/v1` serves as proxy for all 60+ providers
- **Format Translation** — Automatic and transparent: OpenAI ↔ Claude ↔ Gemini ↔ Responses API
- **Response Sanitization** — Strips non-standard fields (`x_groq`, `usage_breakdown`, `service_tier`) that break OpenAI SDK v1.83+
- **Role Normalization** — Converts `developer` → `system` for non-OpenAI providers; `system` → `user` for GLM/ERNIE
@@ -373,7 +374,7 @@ Developers use Cursor, Claude Code, Codex CLI, OpenClaw, Gemini CLI, Kilo Code..
- **CLI Tools Dashboard** — Dedicated page with one-click setup for Claude Code, Codex CLI, OpenClaw, Kilo Code, Antigravity, Cline
- **GitHub Copilot Config Generator** — Generates `chatLanguageModels.json` for VS Code with bulk model selection
- **Onboarding Wizard** — Guided 4-step setup for first-time users
-- **One endpoint, all models** — Configure `http://localhost:20128/v1` once, access 67+ providers
+- **One endpoint, all models** — Configure `http://localhost:20128/v1` once, access 60+ providers
@@ -420,7 +421,7 @@ When a call fails, the dev doesn't know if it was a rate limit, expired token, w
- **SQLite Proxy Logs** — Persistent logs that survive server restarts
- **Translator Playground** — 4 debugging modes: Playground (format translation), Chat Tester (round-trip), Test Bench (batch), Live Monitor (real-time)
- **Request Telemetry** — p50/p95/p99 latency + X-Request-Id tracing
-- **File-Based Logging with Rotation** — Console interceptor captures everything to JSON log with size-based rotation
+- **File-Based Logging with Rotation** — App logs rotate by size, retention days, and archive count; call log artifacts rotate by retention days and file count
- **System Info Report** — `npm run system-info` generates `system-info.txt` with your full environment (Node version, OmniRoute version, OS, CLI tools, Docker/PM2 status). Attach it when reporting issues for instant triage.
@@ -515,7 +516,7 @@ Developers who want all responses in a specific language, with a specific tone,
- **System Prompt Injection** — Global prompt applied to all requests
- **Thinking Budget Validation** — Reasoning token allocation control per request (passthrough, auto, custom, adaptive)
-- **6 Routing Strategies** — Global strategies that determine how requests are distributed
+- **9 Routing Strategies** — Global strategies that determine how requests are distributed
- **Wildcard Router** — `provider/*` patterns route dynamically to any provider
- **Combo Enable/Disable Toggle** — Toggle combos directly from the dashboard
- **Provider Toggle** — Enable/disable all connections for a provider with one click
@@ -582,7 +583,7 @@ Different clients should have least-privilege access to tool categories.
**How OmniRoute solves it:**
-- 9 granular MCP scopes for controlled tool access
+- 10 granular MCP scopes for controlled tool access
- Scope enforcement and visibility in MCP management UI
- Safe default posture for operational tooling
@@ -1326,19 +1327,19 @@ OmniRoute v2.0 is built as an operational platform, not just a relay proxy.
### 🤖 Agent & Protocol Operations (v2.0)
-| Feature | What It Does |
-| ------------------------------------- | -------------------------------------------------------------------------------------------------- |
-| 🔧 **MCP Server (16 tools)** | IDE/agent tools via 3 transports: stdio, SSE (`/api/mcp/sse`), Streamable HTTP (`/api/mcp/stream`) |
-| 🤝 **A2A Server (JSON-RPC + SSE)** | Agent-to-agent task execution with sync and streaming flows |
-| 🧭 **Consolidated Endpoints Page** | Tabbed management page with Endpoint Proxy, MCP, A2A, and API Endpoints tabs |
-| 🎚️ **Service Enable/Disable Toggles** | ON/OFF switches for MCP and A2A with settings persistence (default: OFF) |
-| 🛰️ **MCP Runtime Heartbeat** | Real process status (pid, uptime, heartbeat age, transport, scope mode) |
-| 📋 **MCP Audit Trail** | Filterable audit logs with success/failure and key attribution |
-| 🔐 **MCP Scope Enforcement** | 9 granular scope permissions for controlled tool access |
-| 📡 **A2A Task Lifecycle Management** | List/filter tasks, inspect events/artifacts, cancel running tasks |
-| 📋 **Agent Card Discovery** | `/.well-known/agent.json` for client auto-discovery |
-| 🧪 **Protocol E2E Test Harness** | Real MCP SDK + A2A client flows in `test:protocols:e2e` |
-| ⚙️ **Operational Controls** | Switch combo, apply resilience profiles, reset breakers from one control surface |
+| Feature | What It Does |
+| ------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------- |
+| 🔧 **MCP Server (25 tools)** | IDE/agent tools via 3 transports: stdio, SSE (`/api/mcp/sse`), Streamable HTTP (`/api/mcp/stream`). 18 core + 3 memory + 4 skill tools |
+| 🤝 **A2A Server (JSON-RPC + SSE)** | Agent-to-agent task execution with sync and streaming flows |
+| 🧭 **Consolidated Endpoints Page** | Tabbed management page with Endpoint Proxy, MCP, A2A, and API Endpoints tabs |
+| 🎚️ **Service Enable/Disable Toggles** | ON/OFF switches for MCP and A2A with settings persistence (default: OFF) |
+| 🛰️ **MCP Runtime Heartbeat** | Real process status (pid, uptime, heartbeat age, transport, scope mode) |
+| 📋 **MCP Audit Trail** | Filterable audit logs with success/failure and key attribution |
+| 🔐 **MCP Scope Enforcement** | 10 granular scope permissions for controlled tool access |
+| 📡 **A2A Task Lifecycle Management** | List/filter tasks, inspect events/artifacts, cancel running tasks |
+| 📋 **Agent Card Discovery** | `/.well-known/agent.json` for client auto-discovery |
+| 🧪 **Protocol E2E Test Harness** | Real MCP SDK + A2A client flows in `test:protocols:e2e` |
+| ⚙️ **Operational Controls** | Switch combo, apply resilience profiles, reset breakers from one control surface |
### 🧠 Routing & Intelligence
@@ -1349,7 +1350,7 @@ OmniRoute v2.0 is built as an operational platform, not just a relay proxy.
| 🔄 **Format Translation** | OpenAI ↔ Claude ↔ Gemini ↔ Responses with schema-safe conversions |
| 👥 **Multi-Account Support** | Multiple accounts per provider with intelligent selection |
| 🔄 **Auto Token Refresh** | OAuth tokens refresh automatically with retry |
-| 🎨 **Custom Combos** | 6 balancing strategies + fallback chain control |
+| 🎨 **Custom Combos** | 9 balancing strategies + fallback chain control |
| 🌐 **Wildcard Router** | `provider/*` dynamic routing |
| 🧠 **Thinking Budget Controls** | Passthrough, auto, custom, and adaptive reasoning limits |
| 🔀 **Model Aliases** | Built-in + custom model aliasing and migration safety |
@@ -1950,6 +1951,7 @@ opencode
- Request artifacts are written to `DATA_DIR/call_logs/` as one JSON file per request
- Enable pipeline capture from Dashboard → Logs → Request Logs if you need detailed per-stage payloads
- Set `APP_LOG_TO_FILE=true` if you also want application console logs in `logs/application/app.log`
+- Adjust `APP_LOG_MAX_FILE_SIZE`, `APP_LOG_RETENTION_DAYS`, `APP_LOG_MAX_FILES`, and `CALL_LOG_MAX_ENTRIES` as needed
**Connection test shows "Invalid" for OpenAI-compatible providers**
diff --git a/docs/i18n/id/RELEASE_CHECKLIST.md b/docs/i18n/id/RELEASE_CHECKLIST.md
deleted file mode 100644
index 903e812c3f..0000000000
--- a/docs/i18n/id/RELEASE_CHECKLIST.md
+++ /dev/null
@@ -1,37 +0,0 @@
-🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/RELEASE_CHECKLIST.md) · 🇪🇸 [es](../es/RELEASE_CHECKLIST.md) · 🇫🇷 [fr](../fr/RELEASE_CHECKLIST.md) · 🇩🇪 [de](../de/RELEASE_CHECKLIST.md) · 🇮🇹 [it](../it/RELEASE_CHECKLIST.md) · 🇷🇺 [ru](../ru/RELEASE_CHECKLIST.md) · 🇨🇳 [zh-CN](../zh-CN/RELEASE_CHECKLIST.md) · 🇯🇵 [ja](../ja/RELEASE_CHECKLIST.md) · 🇰🇷 [ko](../ko/RELEASE_CHECKLIST.md) · 🇸🇦 [ar](../ar/RELEASE_CHECKLIST.md) · 🇮🇳 [in](../in/RELEASE_CHECKLIST.md) · 🇹🇭 [th](../th/RELEASE_CHECKLIST.md) · 🇻🇳 [vi](../vi/RELEASE_CHECKLIST.md) · 🇮🇩 [id](../id/RELEASE_CHECKLIST.md) · 🇲🇾 [ms](../ms/RELEASE_CHECKLIST.md) · 🇳🇱 [nl](../nl/RELEASE_CHECKLIST.md) · 🇵🇱 [pl](../pl/RELEASE_CHECKLIST.md) · 🇸🇪 [sv](../sv/RELEASE_CHECKLIST.md) · 🇳🇴 [no](../no/RELEASE_CHECKLIST.md) · 🇩🇰 [da](../da/RELEASE_CHECKLIST.md) · 🇫🇮 [fi](../fi/RELEASE_CHECKLIST.md) · 🇵🇹 [pt](../pt/RELEASE_CHECKLIST.md) · 🇷🇴 [ro](../ro/RELEASE_CHECKLIST.md) · 🇭🇺 [hu](../hu/RELEASE_CHECKLIST.md) · 🇧🇬 [bg](../bg/RELEASE_CHECKLIST.md) · 🇸🇰 [sk](../sk/RELEASE_CHECKLIST.md) · 🇺🇦 [uk-UA](../uk-UA/RELEASE_CHECKLIST.md) · 🇮🇱 [he](../he/RELEASE_CHECKLIST.md) · 🇵🇭 [phi](../phi/RELEASE_CHECKLIST.md)
-
----
-
-# Release Checklist
-
-Use this checklist before tagging or publishing a new OmniRoute release.
-
-## Version and Changelog
-
-1. Bump `package.json` version (`x.y.z`) in the release branch.
-2. Move release notes from `## [Unreleased]` in `CHANGELOG.md` to a dated section:
- - `## [x.y.z] — YYYY-MM-DD`
-3. Keep `## [Unreleased]` as the first changelog section for upcoming work.
-4. Ensure the latest semver section in `CHANGELOG.md` equals `package.json` version.
-
-## API Docs
-
-1. Update `docs/openapi.yaml`:
- - `info.version` must equal `package.json` version.
-2. Validate endpoint examples if API contracts changed.
-
-## Runtime Docs
-
-1. Review `docs/ARCHITECTURE.md` for storage/runtime drift.
-2. Review `docs/TROUBLESHOOTING.md` for env var and operational drift.
-3. Update localized docs if source docs changed significantly.
-
-## Automated Check
-
-Run the sync guard locally before opening PR:
-
-```bash
-npm run check:docs-sync
-```
-
-CI also runs this check in `.github/workflows/ci.yml` (lint job).
diff --git a/docs/i18n/id/SECURITY.md b/docs/i18n/id/SECURITY.md
new file mode 100644
index 0000000000..6085c0e84a
--- /dev/null
+++ b/docs/i18n/id/SECURITY.md
@@ -0,0 +1,179 @@
+# Security Policy (Bahasa Indonesia)
+
+🌐 **Languages:** 🇺🇸 [English](../../../SECURITY.md) · 🇪🇸 [es](../es/SECURITY.md) · 🇫🇷 [fr](../fr/SECURITY.md) · 🇩🇪 [de](../de/SECURITY.md) · 🇮🇹 [it](../it/SECURITY.md) · 🇷🇺 [ru](../ru/SECURITY.md) · 🇨🇳 [zh-CN](../zh-CN/SECURITY.md) · 🇯🇵 [ja](../ja/SECURITY.md) · 🇰🇷 [ko](../ko/SECURITY.md) · 🇸🇦 [ar](../ar/SECURITY.md) · 🇮🇳 [in](../in/SECURITY.md) · 🇹🇭 [th](../th/SECURITY.md) · 🇻🇳 [vi](../vi/SECURITY.md) · 🇮🇩 [id](../id/SECURITY.md) · 🇲🇾 [ms](../ms/SECURITY.md) · 🇳🇱 [nl](../nl/SECURITY.md) · 🇵🇱 [pl](../pl/SECURITY.md) · 🇸🇪 [sv](../sv/SECURITY.md) · 🇳🇴 [no](../no/SECURITY.md) · 🇩🇰 [da](../da/SECURITY.md) · 🇫🇮 [fi](../fi/SECURITY.md) · 🇵🇹 [pt](../pt/SECURITY.md) · 🇷🇴 [ro](../ro/SECURITY.md) · 🇭🇺 [hu](../hu/SECURITY.md) · 🇧🇬 [bg](../bg/SECURITY.md) · 🇸🇰 [sk](../sk/SECURITY.md) · 🇺🇦 [uk-UA](../uk-UA/SECURITY.md) · 🇮🇱 [he](../he/SECURITY.md) · 🇵🇭 [phi](../phi/SECURITY.md) · 🇧🇷 [pt-BR](../pt-BR/SECURITY.md) · 🇨🇿 [cs](../cs/SECURITY.md)
+
+---
+
+## Reporting Vulnerabilities
+
+If you discover a security vulnerability in OmniRoute, please report it responsibly:
+
+1. **DO NOT** open a public GitHub issue
+2. Use [GitHub Security Advisories](https://github.com/diegosouzapw/OmniRoute/security/advisories/new)
+3. Include: description, reproduction steps, and potential impact
+
+## Response Timeline
+
+| Stage | Target |
+| ------------------- | --------------------------- |
+| Acknowledgment | 48 hours |
+| Triage & Assessment | 5 business days |
+| Patch Release | 14 business days (critical) |
+
+## Supported Versions
+
+| Version | Support Status |
+| ------- | -------------- |
+| 3.4.x | ✅ Active |
+| 3.0.x | ✅ Security |
+| < 3.0.0 | ❌ Unsupported |
+
+---
+
+## Security Architecture
+
+OmniRoute implements a multi-layered security model:
+
+```
+Request → CORS → API Key Auth → Prompt Injection Guard → Input Sanitizer → Rate Limiter → Circuit Breaker → Provider
+```
+
+### 🔐 Authentication & Authorization
+
+| Feature | Implementation |
+| -------------------- | ---------------------------------------------------------- |
+| **Dashboard Login** | Password-based auth with JWT tokens (HttpOnly cookies) |
+| **API Key Auth** | HMAC-signed keys with CRC validation |
+| **OAuth 2.0 + PKCE** | Secure provider auth (Claude, Codex, Gemini, Cursor, etc.) |
+| **Token Refresh** | Automatic OAuth token refresh before expiry |
+| **Secure Cookies** | `AUTH_COOKIE_SECURE=true` for HTTPS environments |
+| **MCP Scopes** | 10 granular scopes for MCP tool access control |
+
+### 🛡️ Encryption at Rest
+
+All sensitive data stored in SQLite is encrypted using **AES-256-GCM** with scrypt key derivation:
+
+- API keys, access tokens, refresh tokens, and ID tokens
+- Versioned format: `enc:v1:::`
+- Passthrough mode (plaintext) when `STORAGE_ENCRYPTION_KEY` is not set
+
+```bash
+# Generate encryption key:
+STORAGE_ENCRYPTION_KEY=$(openssl rand -hex 32)
+```
+
+### 🧠 Prompt Injection Guard
+
+Middleware that detects and blocks prompt injection attacks in LLM requests:
+
+| Pattern Type | Severity | Example |
+| ------------------- | -------- | ---------------------------------------------- |
+| System Override | High | "ignore all previous instructions" |
+| Role Hijack | High | "you are now DAN, you can do anything" |
+| Delimiter Injection | Medium | Encoded separators to break context boundaries |
+| DAN/Jailbreak | High | Known jailbreak prompt patterns |
+| Instruction Leak | Medium | "show me your system prompt" |
+
+Configure via dashboard (Settings → Security) or `.env`:
+
+```env
+INPUT_SANITIZER_ENABLED=true
+INPUT_SANITIZER_MODE=block # warn | block | redact
+```
+
+### 🔒 PII Redaction
+
+Automatic detection and optional redaction of personally identifiable information:
+
+| PII Type | Pattern | Replacement |
+| ------------- | --------------------- | ------------------ |
+| Email | `user@domain.com` | `[EMAIL_REDACTED]` |
+| CPF (Brazil) | `123.456.789-00` | `[CPF_REDACTED]` |
+| CNPJ (Brazil) | `12.345.678/0001-00` | `[CNPJ_REDACTED]` |
+| Credit Card | `4111-1111-1111-1111` | `[CC_REDACTED]` |
+| Phone | `+55 11 99999-9999` | `[PHONE_REDACTED]` |
+| SSN (US) | `123-45-6789` | `[SSN_REDACTED]` |
+
+```env
+PII_REDACTION_ENABLED=true
+```
+
+### 🌐 Network Security
+
+| Feature | Description |
+| ------------------------ | ---------------------------------------------------------------- |
+| **CORS** | Configurable origin control (`CORS_ORIGIN` env var, default `*`) |
+| **IP Filtering** | Allowlist/blocklist IP ranges in dashboard |
+| **Rate Limiting** | Per-provider rate limits with automatic backoff |
+| **Anti-Thundering Herd** | Mutex + per-connection locking prevents cascading 502s |
+| **TLS Fingerprint** | Browser-like TLS fingerprint spoofing to reduce bot detection |
+| **CLI Fingerprint** | Per-provider header/body ordering to match native CLI signatures |
+
+### 🔌 Resilience & Availability
+
+| Feature | Description |
+| ----------------------- | ------------------------------------------------------------------ |
+| **Circuit Breaker** | 3-state (Closed → Open → Half-Open) per provider, SQLite-persisted |
+| **Request Idempotency** | 5-second dedup window for duplicate requests |
+| **Exponential Backoff** | Automatic retry with increasing delays |
+| **Health Dashboard** | Real-time provider health monitoring |
+
+### 📋 Compliance
+
+| Feature | Description |
+| ------------------ | ----------------------------------------------------------- |
+| **Log Retention** | Automatic cleanup after `CALL_LOG_RETENTION_DAYS` |
+| **No-Log Opt-out** | Per API key `noLog` flag disables request logging |
+| **Audit Log** | Administrative actions tracked in `audit_log` table |
+| **MCP Audit** | SQLite-backed audit logging for all MCP tool calls |
+| **Zod Validation** | All API inputs validated with Zod v4 schemas at module load |
+
+---
+
+## Required Environment Variables
+
+All secrets must be set before starting the server. The server will **fail fast** if they are missing or weak.
+
+```bash
+# REQUIRED — server will not start without these:
+JWT_SECRET=$(openssl rand -base64 48) # min 32 chars
+API_KEY_SECRET=$(openssl rand -hex 32) # min 16 chars
+
+# RECOMMENDED — enables encryption at rest:
+STORAGE_ENCRYPTION_KEY=$(openssl rand -hex 32)
+```
+
+The server actively rejects known-weak values like `changeme`, `secret`, or `password`.
+
+---
+
+## Docker Security
+
+- Use non-root user in production
+- Mount secrets as read-only volumes
+- Never copy `.env` files into Docker images
+- Use `.dockerignore` to exclude sensitive files
+- Set `AUTH_COOKIE_SECURE=true` when behind HTTPS
+
+```bash
+docker run -d \
+ --name omniroute \
+ --restart unless-stopped \
+ --read-only \
+ -p 20128:20128 \
+ -v omniroute-data:/app/data \
+ -e JWT_SECRET="$(openssl rand -base64 48)" \
+ -e API_KEY_SECRET="$(openssl rand -hex 32)" \
+ -e STORAGE_ENCRYPTION_KEY="$(openssl rand -hex 32)" \
+ diegosouzapw/omniroute:latest
+```
+
+---
+
+## Dependencies
+
+- Run `npm audit` regularly
+- Keep dependencies updated
+- The project uses `husky` + `lint-staged` for pre-commit checks
+- CI pipeline runs ESLint security rules on every push
+- Provider constants validated at module load via Zod (`src/shared/validation/providerSchema.ts`)
diff --git a/docs/i18n/id/TROUBLESHOOTING.md b/docs/i18n/id/TROUBLESHOOTING.md
deleted file mode 100644
index 63c148000a..0000000000
--- a/docs/i18n/id/TROUBLESHOOTING.md
+++ /dev/null
@@ -1,258 +0,0 @@
-🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/TROUBLESHOOTING.md) · 🇪🇸 [es](../es/TROUBLESHOOTING.md) · 🇫🇷 [fr](../fr/TROUBLESHOOTING.md) · 🇩🇪 [de](../de/TROUBLESHOOTING.md) · 🇮🇹 [it](../it/TROUBLESHOOTING.md) · 🇷🇺 [ru](../ru/TROUBLESHOOTING.md) · 🇨🇳 [zh-CN](../zh-CN/TROUBLESHOOTING.md) · 🇯🇵 [ja](../ja/TROUBLESHOOTING.md) · 🇰🇷 [ko](../ko/TROUBLESHOOTING.md) · 🇸🇦 [ar](../ar/TROUBLESHOOTING.md) · 🇮🇳 [in](../in/TROUBLESHOOTING.md) · 🇹🇭 [th](../th/TROUBLESHOOTING.md) · 🇻🇳 [vi](../vi/TROUBLESHOOTING.md) · 🇮🇩 [id](../id/TROUBLESHOOTING.md) · 🇲🇾 [ms](../ms/TROUBLESHOOTING.md) · 🇳🇱 [nl](../nl/TROUBLESHOOTING.md) · 🇵🇱 [pl](../pl/TROUBLESHOOTING.md) · 🇸🇪 [sv](../sv/TROUBLESHOOTING.md) · 🇳🇴 [no](../no/TROUBLESHOOTING.md) · 🇩🇰 [da](../da/TROUBLESHOOTING.md) · 🇫🇮 [fi](../fi/TROUBLESHOOTING.md) · 🇵🇹 [pt](../pt/TROUBLESHOOTING.md) · 🇷🇴 [ro](../ro/TROUBLESHOOTING.md) · 🇭🇺 [hu](../hu/TROUBLESHOOTING.md) · 🇧🇬 [bg](../bg/TROUBLESHOOTING.md) · 🇸🇰 [sk](../sk/TROUBLESHOOTING.md) · 🇺🇦 [uk-UA](../uk-UA/TROUBLESHOOTING.md) · 🇮🇱 [he](../he/TROUBLESHOOTING.md) · 🇵🇭 [phi](../phi/TROUBLESHOOTING.md)
-
----
-
-# Troubleshooting
-
-🌐 **Languages:** 🇺🇸 [English](TROUBLESHOOTING.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/TROUBLESHOOTING.md) | 🇪🇸 [Español](i18n/es/TROUBLESHOOTING.md) | 🇫🇷 [Français](i18n/fr/TROUBLESHOOTING.md) | 🇮🇹 [Italiano](i18n/it/TROUBLESHOOTING.md) | 🇷🇺 [Русский](i18n/ru/TROUBLESHOOTING.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/TROUBLESHOOTING.md) | 🇩🇪 [Deutsch](i18n/de/TROUBLESHOOTING.md) | 🇮🇳 [हिन्दी](i18n/in/TROUBLESHOOTING.md) | 🇹🇭 [ไทย](i18n/th/TROUBLESHOOTING.md) | 🇺🇦 [Українська](i18n/uk-UA/TROUBLESHOOTING.md) | 🇸🇦 [العربية](i18n/ar/TROUBLESHOOTING.md) | 🇯🇵 [日本語](i18n/ja/TROUBLESHOOTING.md) | 🇻🇳 [Tiếng Việt](i18n/vi/TROUBLESHOOTING.md) | 🇧🇬 [Български](i18n/bg/TROUBLESHOOTING.md) | 🇩🇰 [Dansk](i18n/da/TROUBLESHOOTING.md) | 🇫🇮 [Suomi](i18n/fi/TROUBLESHOOTING.md) | 🇮🇱 [עברית](i18n/he/TROUBLESHOOTING.md) | 🇭🇺 [Magyar](i18n/hu/TROUBLESHOOTING.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/TROUBLESHOOTING.md) | 🇰🇷 [한국어](i18n/ko/TROUBLESHOOTING.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/TROUBLESHOOTING.md) | 🇳🇱 [Nederlands](i18n/nl/TROUBLESHOOTING.md) | 🇳🇴 [Norsk](i18n/no/TROUBLESHOOTING.md) | 🇵🇹 [Português (Portugal)](i18n/pt/TROUBLESHOOTING.md) | 🇷🇴 [Română](i18n/ro/TROUBLESHOOTING.md) | 🇵🇱 [Polski](i18n/pl/TROUBLESHOOTING.md) | 🇸🇰 [Slovenčina](i18n/sk/TROUBLESHOOTING.md) | 🇸🇪 [Svenska](i18n/sv/TROUBLESHOOTING.md) | 🇵🇭 [Filipino](i18n/phi/TROUBLESHOOTING.md)
-
-Common problems and solutions for OmniRoute.
-
----
-
-## Quick Fixes
-
-| Problem | Solution |
-| ----------------------------- | ------------------------------------------------------------------ |
-| First login not working | Set `INITIAL_PASSWORD` in `.env` (no hardcoded default) |
-| Dashboard opens on wrong port | Set `PORT=20128` and `NEXT_PUBLIC_BASE_URL=http://localhost:20128` |
-| No request logs under `logs/` | Set `ENABLE_REQUEST_LOGS=true` |
-| EACCES: permission denied | Set `DATA_DIR=/path/to/writable/dir` to override `~/.omniroute` |
-| Routing strategy not saving | Update to v1.4.11+ (Zod schema fix for settings persistence) |
-
----
-
-## Provider Issues
-
-### "Language model did not provide messages"
-
-**Cause:** Provider quota exhausted.
-
-**Fix:**
-
-1. Check dashboard quota tracker
-2. Use a combo with fallback tiers
-3. Switch to cheaper/free tier
-
-### Rate Limiting
-
-**Cause:** Subscription quota exhausted.
-
-**Fix:**
-
-- Add fallback: `cc/claude-opus-4-6 → glm/glm-4.7 → if/kimi-k2-thinking`
-- Use GLM/MiniMax as cheap backup
-
-### OAuth Token Expired
-
-OmniRoute auto-refreshes tokens. If issues persist:
-
-1. Dashboard → Provider → Reconnect
-2. Delete and re-add the provider connection
-
----
-
-## Cloud Issues
-
-### Cloud Sync Errors
-
-1. Verify `BASE_URL` points to your running instance (e.g., `http://localhost:20128`)
-2. Verify `CLOUD_URL` points to your cloud endpoint (e.g., `https://omniroute.dev`)
-3. Keep `NEXT_PUBLIC_*` values aligned with server-side values
-
-### Cloud `stream=false` Returns 500
-
-**Symptom:** `Unexpected token 'd'...` on cloud endpoint for non-streaming calls.
-
-**Cause:** Upstream returns SSE payload while client expects JSON.
-
-**Workaround:** Use `stream=true` for cloud direct calls. Local runtime includes SSE→JSON fallback.
-
-### Cloud Says Connected but "Invalid API key"
-
-1. Create a fresh key from local dashboard (`/api/keys`)
-2. Run cloud sync: Enable Cloud → Sync Now
-3. Old/non-synced keys can still return `401` on cloud
-
----
-
-## Docker Issues
-
-### CLI Tool Shows Not Installed
-
-1. Check runtime fields: `curl http://localhost:20128/api/cli-tools/runtime/codex | jq`
-2. For portable mode: use image target `runner-cli` (bundled CLIs)
-3. For host mount mode: set `CLI_EXTRA_PATHS` and mount host bin directory as read-only
-4. If `installed=true` and `runnable=false`: binary was found but failed healthcheck
-
-### Quick Runtime Validation
-
-```bash
-curl -s http://localhost:20128/api/cli-tools/codex-settings | jq '{installed,runnable,commandPath,runtimeMode,reason}'
-curl -s http://localhost:20128/api/cli-tools/claude-settings | jq '{installed,runnable,commandPath,runtimeMode,reason}'
-curl -s http://localhost:20128/api/cli-tools/openclaw-settings | jq '{installed,runnable,commandPath,runtimeMode,reason}'
-```
-
----
-
-## Cost Issues
-
-### High Costs
-
-1. Check usage stats in Dashboard → Usage
-2. Switch primary model to GLM/MiniMax
-3. Use free tier (Gemini CLI, Qoder) for non-critical tasks
-4. Set cost budgets per API key: Dashboard → API Keys → Budget
-
----
-
-## Debugging
-
-### Enable Request Logs
-
-Set `ENABLE_REQUEST_LOGS=true` in your `.env` file. Logs appear under `logs/` directory.
-
-### Check Provider Health
-
-```bash
-# Health dashboard
-http://localhost:20128/dashboard/health
-
-# API health check
-curl http://localhost:20128/api/monitoring/health
-```
-
-### Runtime Storage
-
-- Main state: `${DATA_DIR}/storage.sqlite` (providers, combos, aliases, keys, settings)
-- Usage: SQLite tables in `storage.sqlite` (`usage_history`, `call_logs`, `proxy_logs`) + optional `${DATA_DIR}/log.txt` and `${DATA_DIR}/call_logs/`
-- Request logs: `/logs/...` (when `ENABLE_REQUEST_LOGS=true`)
-
----
-
-## Circuit Breaker Issues
-
-### Provider stuck in OPEN state
-
-When a provider's circuit breaker is OPEN, requests are blocked until the cooldown expires.
-
-**Fix:**
-
-1. Go to **Dashboard → Settings → Resilience**
-2. Check the circuit breaker card for the affected provider
-3. Click **Reset All** to clear all breakers, or wait for the cooldown to expire
-4. Verify the provider is actually available before resetting
-
-### Provider keeps tripping the circuit breaker
-
-If a provider repeatedly enters OPEN state:
-
-1. Check **Dashboard → Health → Provider Health** for the failure pattern
-2. Go to **Settings → Resilience → Provider Profiles** and increase the failure threshold
-3. Check if the provider has changed API limits or requires re-authentication
-4. Review latency telemetry — high latency may cause timeout-based failures
-
----
-
-## Audio Transcription Issues
-
-### "Unsupported model" error
-
-- Ensure you're using the correct prefix: `deepgram/nova-3` or `assemblyai/best`
-- Verify the provider is connected in **Dashboard → Providers**
-
-### Transcription returns empty or fails
-
-- Check supported audio formats: `mp3`, `wav`, `m4a`, `flac`, `ogg`, `webm`
-- Verify file size is within provider limits (typically < 25MB)
-- Check provider API key validity in the provider card
-
----
-
-## Translator Debugging
-
-Use **Dashboard → Translator** to debug format translation issues:
-
-| Mode | When to Use |
-| ---------------- | -------------------------------------------------------------------------------------------- |
-| **Playground** | Compare input/output formats side by side — paste a failing request to see how it translates |
-| **Chat Tester** | Send live messages and inspect the full request/response payload including headers |
-| **Test Bench** | Run batch tests across format combinations to find which translations are broken |
-| **Live Monitor** | Watch real-time request flow to catch intermittent translation issues |
-
-### Common format issues
-
-- **Thinking tags not appearing** — Check if the target provider supports thinking and the thinking budget setting
-- **Tool calls dropping** — Some format translations may strip unsupported fields; verify in Playground mode
-- **System prompt missing** — Claude and Gemini handle system prompts differently; check translation output
-- **SDK returns raw string instead of object** — Fixed in v1.1.0: response sanitizer now strips non-standard fields (`x_groq`, `usage_breakdown`, etc.) that cause OpenAI SDK Pydantic validation failures
-- **GLM/ERNIE rejects `system` role** — Fixed in v1.1.0: role normalizer automatically merges system messages into user messages for incompatible models
-- **`developer` role not recognized** — Fixed in v1.1.0: automatically converted to `system` for non-OpenAI providers
-- **`json_schema` not working with Gemini** — Fixed in v1.1.0: `response_format` is now converted to Gemini's `responseMimeType` + `responseSchema`
-
----
-
-## Resilience Settings
-
-### Auto rate-limit not triggering
-
-- Auto rate-limit only applies to API key providers (not OAuth/subscription)
-- Verify **Settings → Resilience → Provider Profiles** has auto-rate-limit enabled
-- Check if the provider returns `429` status codes or `Retry-After` headers
-
-### Tuning exponential backoff
-
-Provider profiles support these settings:
-
-- **Base delay** — Initial wait time after first failure (default: 1s)
-- **Max delay** — Maximum wait time cap (default: 30s)
-- **Multiplier** — How much to increase delay per consecutive failure (default: 2x)
-
-### Anti-thundering herd
-
-When many concurrent requests hit a rate-limited provider, OmniRoute uses mutex + auto rate-limiting to serialize requests and prevent cascading failures. This is automatic for API key providers.
-
----
-
-## Optional RAG / LLM failure taxonomy (16 problems)
-
-Some OmniRoute users place the gateway in front of RAG or agent stacks. In those setups it is common to see a strange pattern: OmniRoute looks healthy (providers up, routing profiles ok, no rate limit alerts) but the final answer is still wrong.
-
-In practice these incidents usually come from the downstream RAG pipeline, not from the gateway itself.
-
-If you want a shared vocabulary to describe those failures you can use the WFGY ProblemMap, an external MIT license text resource that defines sixteen recurring RAG / LLM failure patterns. At a high level it covers:
-
-- retrieval drift and broken context boundaries
-- empty or stale indexes and vector stores
-- embedding versus semantic mismatch
-- prompt assembly and context window issues
-- logic collapse and overconfident answers
-- long chain and agent coordination failures
-- multi agent memory and role drift
-- deployment and bootstrap ordering problems
-
-The idea is simple:
-
-1. When you investigate a bad response, capture:
- - user task and request
- - route or provider combo in OmniRoute
- - any RAG context used downstream (retrieved documents, tool calls, etc)
-2. Map the incident to one or two WFGY ProblemMap numbers (`No.1` … `No.16`).
-3. Store the number in your own dashboard, runbook, or incident tracker next to the OmniRoute logs.
-4. Use the corresponding WFGY page to decide whether you need to change your RAG stack, retriever, or routing strategy.
-
-Full text and concrete recipes live here (MIT license, text only):
-
-[WFGY ProblemMap README](https://github.com/onestardao/WFGY/blob/main/ProblemMap/README.md)
-
-You can ignore this section if you do not run RAG or agent pipelines behind OmniRoute.
-
----
-
-## Still Stuck?
-
-- **GitHub Issues**: [github.com/diegosouzapw/OmniRoute/issues](https://github.com/diegosouzapw/OmniRoute/issues)
-- **Architecture**: See [`docs/ARCHITECTURE.md`](ARCHITECTURE.md) for internal details
-- **API Reference**: See [`docs/API_REFERENCE.md`](API_REFERENCE.md) for all endpoints
-- **Health Dashboard**: Check **Dashboard → Health** for real-time system status
-- **Translator**: Use **Dashboard → Translator** to debug format issues
diff --git a/docs/i18n/id/VM_DEPLOYMENT_GUIDE.md b/docs/i18n/id/VM_DEPLOYMENT_GUIDE.md
deleted file mode 100644
index ff32516444..0000000000
--- a/docs/i18n/id/VM_DEPLOYMENT_GUIDE.md
+++ /dev/null
@@ -1,401 +0,0 @@
-# OmniRoute — Panduan Penerapan pada VM dengan Cloudflare
-
-🌐 **Languages:** 🇺🇸 [English](../../VM_DEPLOYMENT_GUIDE.md) | 🇧🇷 [Português (Brasil)](../pt-BR/VM_DEPLOYMENT_GUIDE.md) | 🇪🇸 [Español](../es/VM_DEPLOYMENT_GUIDE.md) | 🇫🇷 [Français](../fr/VM_DEPLOYMENT_GUIDE.md) | 🇮🇹 [Italiano](../it/VM_DEPLOYMENT_GUIDE.md) | 🇷🇺 [Русский](../ru/VM_DEPLOYMENT_GUIDE.md) | 🇨🇳 [中文 (简体)](../zh-CN/VM_DEPLOYMENT_GUIDE.md) | 🇩🇪 [Deutsch](../de/VM_DEPLOYMENT_GUIDE.md) | 🇮🇳 [हिन्दी](../in/VM_DEPLOYMENT_GUIDE.md) | 🇹🇭 [ไทย](../th/VM_DEPLOYMENT_GUIDE.md) | 🇺🇦 [Українська](../uk-UA/VM_DEPLOYMENT_GUIDE.md) | 🇸🇦 [العربية](../ar/VM_DEPLOYMENT_GUIDE.md) | 🇯🇵 [日本語](../ja/VM_DEPLOYMENT_GUIDE.md) | 🇻🇳 [Tiếng Việt](../vi/VM_DEPLOYMENT_GUIDE.md) | 🇧🇬 [Български](../bg/VM_DEPLOYMENT_GUIDE.md) | 🇩🇰 [Dansk](../da/VM_DEPLOYMENT_GUIDE.md) | 🇫🇮 [Suomi](../fi/VM_DEPLOYMENT_GUIDE.md) | 🇮🇱 [עברית](../he/VM_DEPLOYMENT_GUIDE.md) | 🇭🇺 [Magyar](../hu/VM_DEPLOYMENT_GUIDE.md) | 🇮🇩 [Bahasa Indonesia](../id/VM_DEPLOYMENT_GUIDE.md) | 🇰🇷 [한국어](../ko/VM_DEPLOYMENT_GUIDE.md) | 🇲🇾 [Bahasa Melayu](../ms/VM_DEPLOYMENT_GUIDE.md) | 🇳🇱 [Nederlands](../nl/VM_DEPLOYMENT_GUIDE.md) | 🇳🇴 [Norsk](../no/VM_DEPLOYMENT_GUIDE.md) | 🇵🇹 [Português (Portugal)](../pt/VM_DEPLOYMENT_GUIDE.md) | 🇷🇴 [Română](../ro/VM_DEPLOYMENT_GUIDE.md) | 🇵🇱 [Polski](../pl/VM_DEPLOYMENT_GUIDE.md) | 🇸🇰 [Slovenčina](../sk/VM_DEPLOYMENT_GUIDE.md) | 🇸🇪 [Svenska](../sv/VM_DEPLOYMENT_GUIDE.md) | 🇵🇭 [Filipino](../phi/VM_DEPLOYMENT_GUIDE.md) | 🇨🇿 [Čeština](../cs/VM_DEPLOYMENT_GUIDE.md)
-
-Panduan lengkap untuk menginstal dan mengkonfigurasi OmniRoute pada VM (VPS) dengan domain yang dikelola melalui Cloudflare.
-
----
-
-## Prasyarat
-
-| Barang | Minimal | Direkomendasikan |
-| ------------------- | ----------------------- | ------------------- |
-| **CPU** | 1vCPU | 2vCPU |
-| **RAM** | 1 GB | 2 GB |
-| **Disk** | SSD 10 GB | SSD 25GB |
-| **OS** | Ubuntu 22.04 LTS | Ubuntu 24.04 LTS |
-| **Domain** | Terdaftar di Cloudflare | — |
-| **Buruh pelabuhan** | Mesin Docker 24+ | buruh pelabuhan 27+ |
-
-**Penyedia teruji**: Akamai (Linode), DigitalOcean, Vultr, Hetzner, AWS Lightsail.
-
----
-
-## 1. Konfigurasikan VM
-
-### 1.1 Membuat instance
-
-Pada penyedia VPS pilihan Anda:
-
-- Pilih Ubuntu 24.04 LTS
-- Pilih paket minimum (1 vCPU / 1 GB RAM)
-- Tetapkan kata sandi root yang kuat atau konfigurasikan kunci SSH
-- Catat **IP publik** (mis., `203.0.113.10`)
-
-### 1.2 Terhubung melalui SSH
-
-```bash
-ssh root@203.0.113.10
-```
-
-### 1.3 Perbarui sistem
-
-```bash
-apt update && apt upgrade -y
-```
-
-### 1.4 Instal Docker
-
-```bash
-# Install dependencies
-apt install -y ca-certificates curl gnupg
-
-# Add official Docker repository
-install -m 0755 -d /etc/apt/keyrings
-curl -fsSL https://download.docker.com/linux/ubuntu/gpg | gpg --dearmor -o /etc/apt/keyrings/docker.gpg
-chmod a+r /etc/apt/keyrings/docker.gpg
-echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu $ (. /etc/os-release && echo “$VERSION_CODENAME”) stable" | tee /etc/apt/sources.list.d/docker.list > /dev/null
-apt update
-apt install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin
-```
-
-### 1.5 Instal nginx
-
-```bash
-apt install -y nginx
-```
-
-### 1.6 Konfigurasi Firewall (UFW)
-
-```bash
-ufw default deny incoming
-ufw default allow outgoing
-ufw allow 22/tcp # SSH
-ufw allow 80/tcp # HTTP (redirect)
-ufw allow 443/tcp # HTTPS
-ufw enable
-```
-
-> **Tips**: Untuk keamanan maksimum, batasi port 80 dan 443 hanya untuk IP Cloudflare. Lihat bagian [Advanced Security](#advanced-security).
-
----
-
-## 2. Instal OmniRoute
-
-### 2.1 Membuat direktori konfigurasi
-
-```bash
-mkdir -p /opt/omniroute
-```
-
-### 2.2 Membuat file variabel lingkungan
-
-```bash
-cat > /opt/omniroute/.env << ‘EOF’
-# === Security ===
-JWT_SECRET=CHANGE-TO-A-UNIQUE-64-CHAR-SECRET-KEY
-INITIAL_PASSWORD=YourSecurePassword123!
-API_KEY_SECRET=REPLACE-WITH-ANOTHER-SECRET-KEY
-STORAGE_ENCRYPTION_KEY=REPLACE-WITH-THIRD-SECRET-KEY
-STORAGE_ENCRYPTION_KEY_VERSION=v1
-MACHINE_ID_SALT=CHANGE-TO-A-UNIQUE-SALT
-
-# === App ===
-PORT=20128
-NODE_ENV=production
-HOSTNAME=0.0.0.0
-DATA_DIR=/app/data
-STORAGE_DRIVER=sqlite
-ENABLE_REQUEST_LOGS=true
-AUTH_COOKIE_SECURE=false
-REQUIRE_API_KEY=false
-
-# === Domain (change to your domain) ===
-BASE_URL=https://llms.seudominio.com
-NEXT_PUBLIC_BASE_URL=https://llms.seudominio.com
-
-# === Cloud Sync (optional) ===
-# CLOUD_URL=https://cloud.omniroute.online
-# NEXT_PUBLIC_CLOUD_URL=https://cloud.omniroute.online
-EOF
-```
-
-> ⚠️ **PENTING**: Hasilkan kunci rahasia unik! Gunakan `openssl rand -hex 32` untuk setiap kunci.
-
-### 2.3 Mulai penampung
-
-```bash
-docker pull diegosouzapw/omniroute:latest
-
-docker run -d \
- --name omniroute \
- --restart unless-stopped \
- --env-file /opt/omniroute/.env \
- -p 20128:20128 \
- -v omniroute-data:/app/data \
- diegosouzapw/omniroute:latest
-```
-
-### 2.4 Pastikan itu sedang berjalan
-
-```bash
-docker ps | grep omniroute
-docker logs omniroute --tail 20
-```
-
-Seharusnya menampilkan: `[DB] SQLite database ready` dan `listening on port 20128`.
-
----
-
-## 3. Konfigurasikan nginx (Proxy Terbalik)
-
-### 3.1 Menghasilkan sertifikat SSL (Cloudflare Origin)
-
-Di dasbor Cloudflare:
-
-1. Buka **SSL/TLS → Server Asal**
-2. Klik **Buat Sertifikat**
-3. Pertahankan default (15 tahun, \*.domainanda.com)
-4. Salin **Sertifikat Asal** dan **Kunci Pribadi**
-
-```bash
-mkdir -p /etc/nginx/ssl
-
-# Paste the certificate
-nano /etc/nginx/ssl/origin.crt
-
-# Paste the private key
-nano /etc/nginx/ssl/origin.key
-
-chmod 600 /etc/nginx/ssl/origin.key
-```
-
-### 3.2 Konfigurasi Nginx
-
-```bash
-cat > /etc/nginx/sites-available/omniroute << ‘NGINX’
-# Default server — blocks direct access via IP
-server {
- listen 80 default_server;
- listen [::]:80 default_server;
- listen 443 ssl default_server;
- listen [::]:443 ssl default_server;
- ssl_certificate /etc/nginx/ssl/origin.crt;
- ssl_certificate_key /etc/nginx/ssl/origin.key;
- server_name _;
- return 444;
-}
-
-# OmniRoute — HTTPS
-server {
- listen 443 ssl;
- listen [::]:443 ssl;
- server_name llms.yourdomain.com; # Change to your domain
-
- ssl_certificate /etc/nginx/ssl/origin.crt;
- ssl_certificate_key /etc/nginx/ssl/origin.key;
- ssl_protocols TLSv1.2 TLSv1.3;
-
- client_max_body_size 100M;
-
- location / {
- proxy_pass http://127.0.0.1:20128;
- proxy_set_header Host $host;
- proxy_set_header X-Real-IP $remote_addr;
- proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
- proxy_set_header X-Forwarded-Proto $scheme;
-
- # WebSocket support
- proxy_http_version 1.1;
- proxy_set_header Upgrade $http_upgrade;
- proxy_set_header Connection “upgrade”;
-
- # SSE (Server-Sent Events) — streaming AI responses
- proxy_buffering off;
- proxy_cache off;
- proxy_read_timeout 300s;
- proxy_send_timeout 300s;
- }
-}
-
-# HTTP → HTTPS redirect
-server {
- listen 80;
- listen [::]:80;
- server_name llms.yourdomain.com;
- return 301 https://$server_name$request_uri;
-}
-NGINX
-```
-
-### 3.3 Aktifkan dan Uji
-
-```bash
-# Remove default configuration
-rm -f /etc/nginx/sites-enabled/default
-
-# Enable OmniRoute
-ln -sf /etc/nginx/sites-available/omniroute /etc/nginx/sites-enabled/omniroute
-
-# Test and reload
-nginx -t && systemctl reload nginx
-```
-
----
-
-## 4. Konfigurasikan DNS Cloudflare
-
-### 4.1 Tambahkan data DNS
-
-Di dasbor Cloudflare → DNS:
-
-| Ketik | Nama | Konten | Proksi |
-| ------ | ------ | ---------------------- | ----------- |
-| SEBUAH | `llms` | `203.0.113.10` (IP VM) | ✅ Diproksi |
-
-### 4.2 Konfigurasikan SSL
-
-Di bawah **SSL/TLS → Ikhtisar**:
-
-- Mode: **Penuh (Ketat)**
-
-Di bawah **SSL/TLS → Sertifikat Edge**:
-
-- Selalu Gunakan HTTPS: ✅ Aktif
-- Versi TLS Minimum: TLS 1.2
-- Penulisan Ulang HTTPS Otomatis: ✅ Aktif
-
-### 4.3 Pengujian
-
-```bash
-curl -sI https://llms.seudominio.com/health
-# Should return HTTP/2 200
-```
-
----
-
-## 5. Pengoperasian dan Pemeliharaan
-
-### Tingkatkan ke versi baru
-
-```bash
-docker pull diegosouzapw/omniroute:latest
-docker stop omniroute && docker rm omniroute
-docker run -d --name omniroute --restart unless-stopped \
- --env-file /opt/omniroute/.env \
- -p 20128:20128 \
- -v omniroute-data:/app/data \
- diegosouzapw/omniroute:latest
-```
-
-### Lihat log
-
-```bash
-docker logs -f omniroute # Real-time stream
-docker logs omniroute --tail 50 # Last 50 lines
-```
-
-### Pencadangan basis data manual
-
-```bash
-# Copy data from the volume to the host
-docker cp omniroute:/app/data ./backup-$(date +%F)
-
-# Or compress the entire volume
-docker run --rm -v omniroute-data:/data -v $(pwd):/backup \
- alpine tar czf /backup/omniroute-data-$(date +%F).tar.gz /data
-```
-
-### Pulihkan dari cadangan
-
-```bash
-docker stop omniroute
-docker run --rm -v omniroute-data:/data -v $(pwd):/backup \
- alpine sh -c “rm -rf /data/* && tar xzf /backup/omniroute-data-YYYY-MM-DD.tar.gz -C /”
-docker start omniroute
-```
-
----
-
-## 6. Keamanan Tingkat Lanjut
-
-### Batasi nginx ke IP Cloudflare
-
-```bash
-cat > /etc/nginx/cloudflare-ips.conf << ‘CF’
-# Cloudflare IPv4 ranges — update periodically
-# https://www.cloudflare.com/ips-v4/
-set_real_ip_from 173.245.48.0/20;
-set_real_ip_from 103.21.244.0/22;
-set_real_ip_from 103.22.200.0/22;
-set_real_ip_from 103.31.4.0/22;
-set_real_ip_from 141.101.64.0/18;
-set_real_ip_from 108.162.192.0/18;
-set_real_ip_from 190.93.240.0/20;
-set_real_ip_from 188.114.96.0/20;
-set_real_ip_from 197.234.240.0/22;
-set_real_ip_from 198.41.128.0/17;
-set_real_ip_from 162.158.0.0/15;
-set_real_ip_from 104.16.0.0/13;
-set_real_ip_from 104.24.0.0/14;
-set_real_ip_from 172.64.0.0/13;
-set_real_ip_from 131.0.72.0/22;
-real_ip_header CF-Connecting-IP;
-CF
-```
-
-Tambahkan yang berikut ini ke `nginx.conf` di dalam blok `http {}`:
-
-```nginx
-include /etc/nginx/cloudflare-ips.conf;
-```
-
-### Instal fail2ban
-
-```bash
-apt install -y fail2ban
-systemctl enable fail2ban
-systemctl start fail2ban
-
-# Check status
-fail2ban-client status sshd
-```
-
-### Blokir akses langsung ke port Docker
-
-```bash
-# Prevent direct external access to port 20128
-iptables -I DOCKER-USER -p tcp --dport 20128 -j DROP
-iptables -I DOCKER-USER -i lo -p tcp --dport 20128 -j ACCEPT
-
-# Persist the rules
-apt install -y iptables-persistent
-netfilter-persistent save
-```
-
----
-
-## 7. Deploy ke Cloudflare Worker (Opsional)
-
-Untuk akses jarak jauh melalui Cloudflare Workers (tanpa mengekspos VM secara langsung):
-
-```bash
-# In the local repository
-cd omnirouteCloud
-npm install
-npx wrangler login
-npx wrangler deploy
-```
-
-Lihat dokumentasi selengkapnya di [omnirouteCloud/README.md](../omnirouteCloud/README.md).
-
----
-
-## Ringkasan Pelabuhan
-
-| Pelabuhan | Layanan | Akses |
-| --------- | ----------- | ------------------------------- |
-| 22 | SSH | Publik (dengan fail2ban) |
-| 80 | nginx HTTP | Pengalihan → HTTPS |
-| 443 | nginx HTTPS | Melalui Proksi Cloudflare |
-| 20128 | OmniRoute | Hanya localhost (melalui nginx) |
diff --git a/docs/i18n/id/docs/A2A-SERVER.md b/docs/i18n/id/docs/A2A-SERVER.md
new file mode 100644
index 0000000000..a0b8279ad9
--- /dev/null
+++ b/docs/i18n/id/docs/A2A-SERVER.md
@@ -0,0 +1,200 @@
+# OmniRoute A2A Server Documentation (Bahasa Indonesia)
+
+🌐 **Languages:** 🇺🇸 [English](../../../../docs/A2A-SERVER.md) · 🇪🇸 [es](../../es/docs/A2A-SERVER.md) · 🇫🇷 [fr](../../fr/docs/A2A-SERVER.md) · 🇩🇪 [de](../../de/docs/A2A-SERVER.md) · 🇮🇹 [it](../../it/docs/A2A-SERVER.md) · 🇷🇺 [ru](../../ru/docs/A2A-SERVER.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/A2A-SERVER.md) · 🇯🇵 [ja](../../ja/docs/A2A-SERVER.md) · 🇰🇷 [ko](../../ko/docs/A2A-SERVER.md) · 🇸🇦 [ar](../../ar/docs/A2A-SERVER.md) · 🇮🇳 [in](../../in/docs/A2A-SERVER.md) · 🇹🇭 [th](../../th/docs/A2A-SERVER.md) · 🇻🇳 [vi](../../vi/docs/A2A-SERVER.md) · 🇮🇩 [id](../../id/docs/A2A-SERVER.md) · 🇲🇾 [ms](../../ms/docs/A2A-SERVER.md) · 🇳🇱 [nl](../../nl/docs/A2A-SERVER.md) · 🇵🇱 [pl](../../pl/docs/A2A-SERVER.md) · 🇸🇪 [sv](../../sv/docs/A2A-SERVER.md) · 🇳🇴 [no](../../no/docs/A2A-SERVER.md) · 🇩🇰 [da](../../da/docs/A2A-SERVER.md) · 🇫🇮 [fi](../../fi/docs/A2A-SERVER.md) · 🇵🇹 [pt](../../pt/docs/A2A-SERVER.md) · 🇷🇴 [ro](../../ro/docs/A2A-SERVER.md) · 🇭🇺 [hu](../../hu/docs/A2A-SERVER.md) · 🇧🇬 [bg](../../bg/docs/A2A-SERVER.md) · 🇸🇰 [sk](../../sk/docs/A2A-SERVER.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/A2A-SERVER.md) · 🇮🇱 [he](../../he/docs/A2A-SERVER.md) · 🇵🇭 [phi](../../phi/docs/A2A-SERVER.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/A2A-SERVER.md) · 🇨🇿 [cs](../../cs/docs/A2A-SERVER.md)
+
+---
+
+> Agent-to-Agent Protocol v0.3 — OmniRoute as an intelligent routing agent
+
+## Agent Discovery
+
+```bash
+curl http://localhost:20128/.well-known/agent.json
+```
+
+Returns the Agent Card describing OmniRoute's capabilities, skills, and authentication requirements.
+
+---
+
+## Authentication
+
+All `/a2a` requests require an API key via the `Authorization` header:
+
+```
+Authorization: Bearer YOUR_OMNIROUTE_API_KEY
+```
+
+If no API key is configured on the server, authentication is bypassed.
+
+---
+
+## JSON-RPC 2.0 Methods
+
+### `message/send` — Synchronous Execution
+
+Sends a message to a skill and waits for the complete response.
+
+```bash
+curl -X POST http://localhost:20128/a2a \
+ -H "Content-Type: application/json" \
+ -H "Authorization: Bearer YOUR_KEY" \
+ -d '{
+ "jsonrpc": "2.0",
+ "id": "1",
+ "method": "message/send",
+ "params": {
+ "skill": "smart-routing",
+ "messages": [{"role": "user", "content": "Write a hello world in Python"}],
+ "metadata": {"model": "auto", "combo": "fast-coding"}
+ }
+ }'
+```
+
+**Response:**
+
+```json
+{
+ "jsonrpc": "2.0",
+ "id": "1",
+ "result": {
+ "task": { "id": "uuid", "state": "completed" },
+ "artifacts": [{ "type": "text", "content": "..." }],
+ "metadata": {
+ "routing_explanation": "Selected claude-sonnet via provider \"anthropic\" (latency: 1200ms, cost: $0.003)",
+ "cost_envelope": { "estimated": 0.005, "actual": 0.003, "currency": "USD" },
+ "resilience_trace": [
+ { "event": "primary_selected", "provider": "anthropic", "timestamp": "..." }
+ ],
+ "policy_verdict": { "allowed": true, "reason": "within budget and quota limits" }
+ }
+ }
+}
+```
+
+### `message/stream` — SSE Streaming
+
+Same as `message/send` but returns Server-Sent Events for real-time streaming.
+
+```bash
+curl -N -X POST http://localhost:20128/a2a \
+ -H "Content-Type: application/json" \
+ -H "Authorization: Bearer YOUR_KEY" \
+ -d '{
+ "jsonrpc": "2.0",
+ "id": "1",
+ "method": "message/stream",
+ "params": {
+ "skill": "smart-routing",
+ "messages": [{"role": "user", "content": "Explain quantum computing"}]
+ }
+ }'
+```
+
+**SSE Events:**
+
+```
+data: {"jsonrpc":"2.0","method":"message/stream","params":{"task":{"id":"...","state":"working"},"chunk":{"type":"text","content":"..."}}}
+
+: heartbeat 2026-03-03T17:00:00Z
+
+data: {"jsonrpc":"2.0","method":"message/stream","params":{"task":{"id":"...","state":"completed"},"metadata":{...}}}
+```
+
+### `tasks/get` — Query Task Status
+
+```bash
+curl -X POST http://localhost:20128/a2a \
+ -H "Content-Type: application/json" \
+ -H "Authorization: Bearer YOUR_KEY" \
+ -d '{"jsonrpc":"2.0","id":"2","method":"tasks/get","params":{"taskId":"TASK_UUID"}}'
+```
+
+### `tasks/cancel` — Cancel a Task
+
+```bash
+curl -X POST http://localhost:20128/a2a \
+ -H "Content-Type: application/json" \
+ -H "Authorization: Bearer YOUR_KEY" \
+ -d '{"jsonrpc":"2.0","id":"3","method":"tasks/cancel","params":{"taskId":"TASK_UUID"}}'
+```
+
+---
+
+## Available Skills
+
+| Skill | Description |
+| :----------------- | :------------------------------------------------------------------------------------------------------------------------------ |
+| `smart-routing` | Routes prompts through OmniRoute's intelligent pipeline. Returns response with routing explanation, cost, and resilience trace. |
+| `quota-management` | Answers natural-language queries about provider quotas, suggests free combos, and provides quota rankings. |
+
+---
+
+## Task Lifecycle
+
+```
+submitted → working → completed
+ → failed
+ → cancelled
+```
+
+- Tasks expire after 5 minutes (configurable)
+- Terminal states: `completed`, `failed`, `cancelled`
+- Event log tracks every state transition
+
+---
+
+## Error Codes
+
+| Code | Meaning |
+| :----- | :----------------------------- |
+| -32700 | Parse error (invalid JSON) |
+| -32600 | Invalid request / Unauthorized |
+| -32601 | Method or skill not found |
+| -32602 | Invalid params |
+| -32603 | Internal error |
+
+---
+
+## Integration Examples
+
+### Python (requests)
+
+```python
+import requests
+
+resp = requests.post("http://localhost:20128/a2a", json={
+ "jsonrpc": "2.0", "id": "1",
+ "method": "message/send",
+ "params": {
+ "skill": "smart-routing",
+ "messages": [{"role": "user", "content": "Hello"}]
+ }
+}, headers={"Authorization": "Bearer YOUR_KEY"})
+
+result = resp.json()["result"]
+print(result["artifacts"][0]["content"])
+print(result["metadata"]["routing_explanation"])
+```
+
+### TypeScript (fetch)
+
+```typescript
+const resp = await fetch("http://localhost:20128/a2a", {
+ method: "POST",
+ headers: {
+ "Content-Type": "application/json",
+ Authorization: "Bearer YOUR_KEY",
+ },
+ body: JSON.stringify({
+ jsonrpc: "2.0",
+ id: "1",
+ method: "message/send",
+ params: {
+ skill: "smart-routing",
+ messages: [{ role: "user", content: "Hello" }],
+ },
+ }),
+});
+const { result } = await resp.json();
+console.log(result.metadata.routing_explanation);
+```
diff --git a/docs/i18n/id/docs/API_REFERENCE.md b/docs/i18n/id/docs/API_REFERENCE.md
new file mode 100644
index 0000000000..46432baedc
--- /dev/null
+++ b/docs/i18n/id/docs/API_REFERENCE.md
@@ -0,0 +1,465 @@
+# API Reference (Bahasa Indonesia)
+
+🌐 **Languages:** 🇺🇸 [English](../../../../docs/API_REFERENCE.md) · 🇪🇸 [es](../../es/docs/API_REFERENCE.md) · 🇫🇷 [fr](../../fr/docs/API_REFERENCE.md) · 🇩🇪 [de](../../de/docs/API_REFERENCE.md) · 🇮🇹 [it](../../it/docs/API_REFERENCE.md) · 🇷🇺 [ru](../../ru/docs/API_REFERENCE.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/API_REFERENCE.md) · 🇯🇵 [ja](../../ja/docs/API_REFERENCE.md) · 🇰🇷 [ko](../../ko/docs/API_REFERENCE.md) · 🇸🇦 [ar](../../ar/docs/API_REFERENCE.md) · 🇮🇳 [in](../../in/docs/API_REFERENCE.md) · 🇹🇭 [th](../../th/docs/API_REFERENCE.md) · 🇻🇳 [vi](../../vi/docs/API_REFERENCE.md) · 🇮🇩 [id](../../id/docs/API_REFERENCE.md) · 🇲🇾 [ms](../../ms/docs/API_REFERENCE.md) · 🇳🇱 [nl](../../nl/docs/API_REFERENCE.md) · 🇵🇱 [pl](../../pl/docs/API_REFERENCE.md) · 🇸🇪 [sv](../../sv/docs/API_REFERENCE.md) · 🇳🇴 [no](../../no/docs/API_REFERENCE.md) · 🇩🇰 [da](../../da/docs/API_REFERENCE.md) · 🇫🇮 [fi](../../fi/docs/API_REFERENCE.md) · 🇵🇹 [pt](../../pt/docs/API_REFERENCE.md) · 🇷🇴 [ro](../../ro/docs/API_REFERENCE.md) · 🇭🇺 [hu](../../hu/docs/API_REFERENCE.md) · 🇧🇬 [bg](../../bg/docs/API_REFERENCE.md) · 🇸🇰 [sk](../../sk/docs/API_REFERENCE.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/API_REFERENCE.md) · 🇮🇱 [he](../../he/docs/API_REFERENCE.md) · 🇵🇭 [phi](../../phi/docs/API_REFERENCE.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/API_REFERENCE.md) · 🇨🇿 [cs](../../cs/docs/API_REFERENCE.md)
+
+---
+
+Complete reference for all OmniRoute API endpoints.
+
+---
+
+## Table of Contents
+
+- [Chat Completions](#chat-completions)
+- [Embeddings](#embeddings)
+- [Image Generation](#image-generation)
+- [List Models](#list-models)
+- [Compatibility Endpoints](#compatibility-endpoints)
+- [Semantic Cache](#semantic-cache)
+- [Dashboard & Management](#dashboard--management)
+- [Request Processing](#request-processing)
+- [Authentication](#authentication)
+
+---
+
+## Chat Completions
+
+```bash
+POST /v1/chat/completions
+Authorization: Bearer your-api-key
+Content-Type: application/json
+
+{
+ "model": "cc/claude-opus-4-6",
+ "messages": [
+ {"role": "user", "content": "Write a function to..."}
+ ],
+ "stream": true
+}
+```
+
+### Custom Headers
+
+| Header | Direction | Description |
+| ------------------------ | --------- | ------------------------------------------------ |
+| `X-OmniRoute-No-Cache` | Request | Set to `true` to bypass cache |
+| `X-OmniRoute-Progress` | Request | Set to `true` for progress events |
+| `X-Session-Id` | Request | Sticky session key for external session affinity |
+| `x_session_id` | Request | Underscore variant also accepted (direct HTTP) |
+| `Idempotency-Key` | Request | Dedup key (5s window) |
+| `X-Request-Id` | Request | Alternative dedup key |
+| `X-OmniRoute-Cache` | Response | `HIT` or `MISS` (non-streaming) |
+| `X-OmniRoute-Idempotent` | Response | `true` if deduplicated |
+| `X-OmniRoute-Progress` | Response | `enabled` if progress tracking on |
+| `X-OmniRoute-Session-Id` | Response | Effective session ID used by OmniRoute |
+
+> Nginx note: if you rely on underscore headers (for example `x_session_id`), enable `underscores_in_headers on;`.
+
+---
+
+## Embeddings
+
+```bash
+POST /v1/embeddings
+Authorization: Bearer your-api-key
+Content-Type: application/json
+
+{
+ "model": "nebius/Qwen/Qwen3-Embedding-8B",
+ "input": "The food was delicious"
+}
+```
+
+Available providers: Nebius, OpenAI, Mistral, Together AI, Fireworks, NVIDIA.
+
+```bash
+# List all embedding models
+GET /v1/embeddings
+```
+
+---
+
+## Image Generation
+
+```bash
+POST /v1/images/generations
+Authorization: Bearer your-api-key
+Content-Type: application/json
+
+{
+ "model": "openai/dall-e-3",
+ "prompt": "A beautiful sunset over mountains",
+ "size": "1024x1024"
+}
+```
+
+Available providers: OpenAI (DALL-E), xAI (Grok Image), Together AI (FLUX), Fireworks AI.
+
+```bash
+# List all image models
+GET /v1/images/generations
+```
+
+---
+
+## List Models
+
+```bash
+GET /v1/models
+Authorization: Bearer your-api-key
+
+→ Returns all chat, embedding, and image models + combos in OpenAI format
+```
+
+---
+
+## Compatibility Endpoints
+
+| Method | Path | Format |
+| ------ | --------------------------- | ---------------------- |
+| POST | `/v1/chat/completions` | OpenAI |
+| POST | `/v1/messages` | Anthropic |
+| POST | `/v1/responses` | OpenAI Responses |
+| POST | `/v1/embeddings` | OpenAI |
+| POST | `/v1/images/generations` | OpenAI |
+| GET | `/v1/models` | OpenAI |
+| POST | `/v1/messages/count_tokens` | Anthropic |
+| GET | `/v1beta/models` | Gemini |
+| POST | `/v1beta/models/{...path}` | Gemini generateContent |
+| POST | `/v1/api/chat` | Ollama |
+
+### Dedicated Provider Routes
+
+```bash
+POST /v1/providers/{provider}/chat/completions
+POST /v1/providers/{provider}/embeddings
+POST /v1/providers/{provider}/images/generations
+```
+
+The provider prefix is auto-added if missing. Mismatched models return `400`.
+
+---
+
+## Semantic Cache
+
+```bash
+# Get cache stats
+GET /api/cache/stats
+
+# Clear all caches
+DELETE /api/cache/stats
+```
+
+Response example:
+
+```json
+{
+ "semanticCache": {
+ "memorySize": 42,
+ "memoryMaxSize": 500,
+ "dbSize": 128,
+ "hitRate": 0.65
+ },
+ "idempotency": {
+ "activeKeys": 3,
+ "windowMs": 5000
+ }
+}
+```
+
+---
+
+## Dashboard & Management
+
+### Authentication
+
+| Endpoint | Method | Description |
+| ----------------------------- | ------- | --------------------- |
+| `/api/auth/login` | POST | Login |
+| `/api/auth/logout` | POST | Logout |
+| `/api/settings/require-login` | GET/PUT | Toggle login required |
+
+### Provider Management
+
+| Endpoint | Method | Description |
+| ---------------------------- | --------------- | ------------------------ |
+| `/api/providers` | GET/POST | List / create providers |
+| `/api/providers/[id]` | GET/PUT/DELETE | Manage a provider |
+| `/api/providers/[id]/test` | POST | Test provider connection |
+| `/api/providers/[id]/models` | GET | List provider models |
+| `/api/providers/validate` | POST | Validate provider config |
+| `/api/provider-nodes*` | Various | Provider node management |
+| `/api/provider-models` | GET/POST/DELETE | Custom models |
+
+### OAuth Flows
+
+| Endpoint | Method | Description |
+| -------------------------------- | ------- | ----------------------- |
+| `/api/oauth/[provider]/[action]` | Various | Provider-specific OAuth |
+
+### Routing & Config
+
+| Endpoint | Method | Description |
+| --------------------- | -------- | ----------------------------- |
+| `/api/models/alias` | GET/POST | Model aliases |
+| `/api/models/catalog` | GET | All models by provider + type |
+| `/api/combos*` | Various | Combo management |
+| `/api/keys*` | Various | API key management |
+| `/api/pricing` | GET | Model pricing |
+
+### Usage & Analytics
+
+| Endpoint | Method | Description |
+| --------------------------- | ------ | -------------------- |
+| `/api/usage/history` | GET | Usage history |
+| `/api/usage/logs` | GET | Usage logs |
+| `/api/usage/request-logs` | GET | Request-level logs |
+| `/api/usage/[connectionId]` | GET | Per-connection usage |
+
+### Settings
+
+| Endpoint | Method | Description |
+| ------------------------------- | ------------- | ---------------------- |
+| `/api/settings` | GET/PUT/PATCH | General settings |
+| `/api/settings/proxy` | GET/PUT | Network proxy config |
+| `/api/settings/proxy/test` | POST | Test proxy connection |
+| `/api/settings/ip-filter` | GET/PUT | IP allowlist/blocklist |
+| `/api/settings/thinking-budget` | GET/PUT | Reasoning token budget |
+| `/api/settings/system-prompt` | GET/PUT | Global system prompt |
+
+### Monitoring
+
+| Endpoint | Method | Description |
+| ------------------------ | ---------- | ---------------------------------------------------------------------------------------------------- |
+| `/api/sessions` | GET | Active session tracking |
+| `/api/rate-limits` | GET | Per-account rate limits |
+| `/api/monitoring/health` | GET | Health check + provider summary (`catalogCount`, `configuredCount`, `activeCount`, `monitoredCount`) |
+| `/api/cache/stats` | GET/DELETE | Cache stats / clear |
+
+### Backup & Export/Import
+
+| Endpoint | Method | Description |
+| --------------------------- | ------ | --------------------------------------- |
+| `/api/db-backups` | GET | List available backups |
+| `/api/db-backups` | PUT | Create a manual backup |
+| `/api/db-backups` | POST | Restore from a specific backup |
+| `/api/db-backups/export` | GET | Download database as .sqlite file |
+| `/api/db-backups/import` | POST | Upload .sqlite file to replace database |
+| `/api/db-backups/exportAll` | GET | Download full backup as .tar.gz archive |
+
+### Cloud Sync
+
+| Endpoint | Method | Description |
+| ---------------------- | ------- | --------------------- |
+| `/api/sync/cloud` | Various | Cloud sync operations |
+| `/api/sync/initialize` | POST | Initialize sync |
+| `/api/cloud/*` | Various | Cloud management |
+
+### Tunnels
+
+| Endpoint | Method | Description |
+| -------------------------- | ------ | ----------------------------------------------------------------------- |
+| `/api/tunnels/cloudflared` | GET | Read Cloudflare Quick Tunnel install/runtime status for the dashboard |
+| `/api/tunnels/cloudflared` | POST | Enable or disable the Cloudflare Quick Tunnel (`action=enable/disable`) |
+
+### CLI Tools
+
+| Endpoint | Method | Description |
+| ---------------------------------- | ------ | ------------------- |
+| `/api/cli-tools/claude-settings` | GET | Claude CLI status |
+| `/api/cli-tools/codex-settings` | GET | Codex CLI status |
+| `/api/cli-tools/droid-settings` | GET | Droid CLI status |
+| `/api/cli-tools/openclaw-settings` | GET | OpenClaw CLI status |
+| `/api/cli-tools/runtime/[toolId]` | GET | Generic CLI runtime |
+
+CLI responses include: `installed`, `runnable`, `command`, `commandPath`, `runtimeMode`, `reason`.
+
+### ACP Agents
+
+| Endpoint | Method | Description |
+| ----------------- | ------ | -------------------------------------------------------- |
+| `/api/acp/agents` | GET | List all detected agents (built-in + custom) with status |
+| `/api/acp/agents` | POST | Add custom agent or refresh detection cache |
+| `/api/acp/agents` | DELETE | Remove a custom agent by `id` query param |
+
+GET response includes `agents[]` (id, name, binary, version, installed, protocol, isCustom) and `summary` (total, installed, notFound, builtIn, custom).
+
+### Resilience & Rate Limits
+
+| Endpoint | Method | Description |
+| ----------------------- | --------- | ------------------------------- |
+| `/api/resilience` | GET/PATCH | Get/update resilience profiles |
+| `/api/resilience/reset` | POST | Reset circuit breakers |
+| `/api/rate-limits` | GET | Per-account rate limit status |
+| `/api/rate-limit` | GET | Global rate limit configuration |
+
+### Evals
+
+| Endpoint | Method | Description |
+| ------------ | -------- | --------------------------------- |
+| `/api/evals` | GET/POST | List eval suites / run evaluation |
+
+### Policies
+
+| Endpoint | Method | Description |
+| --------------- | --------------- | ----------------------- |
+| `/api/policies` | GET/POST/DELETE | Manage routing policies |
+
+### Compliance
+
+| Endpoint | Method | Description |
+| --------------------------- | ------ | ----------------------------- |
+| `/api/compliance/audit-log` | GET | Compliance audit log (last N) |
+
+### v1beta (Gemini-Compatible)
+
+| Endpoint | Method | Description |
+| -------------------------- | ------ | --------------------------------- |
+| `/v1beta/models` | GET | List models in Gemini format |
+| `/v1beta/models/{...path}` | POST | Gemini `generateContent` endpoint |
+
+These endpoints mirror Gemini's API format for clients that expect native Gemini SDK compatibility.
+
+### Internal / System APIs
+
+| Endpoint | Method | Description |
+| --------------- | ------ | ---------------------------------------------------- |
+| `/api/init` | GET | Application initialization check (used on first run) |
+| `/api/tags` | GET | Ollama-compatible model tags (for Ollama clients) |
+| `/api/restart` | POST | Trigger graceful server restart |
+| `/api/shutdown` | POST | Trigger graceful server shutdown |
+
+> **Note:** These endpoints are used internally by the system or for Ollama client compatibility. They are not typically called by end users.
+
+---
+
+## Audio Transcription
+
+```bash
+POST /v1/audio/transcriptions
+Authorization: Bearer your-api-key
+Content-Type: multipart/form-data
+```
+
+Transcribe audio files using Deepgram or AssemblyAI.
+
+**Request:**
+
+```bash
+curl -X POST http://localhost:20128/v1/audio/transcriptions \
+ -H "Authorization: Bearer your-api-key" \
+ -F "file=@recording.mp3" \
+ -F "model=deepgram/nova-3"
+```
+
+**Response:**
+
+```json
+{
+ "text": "Hello, this is the transcribed audio content.",
+ "task": "transcribe",
+ "language": "en",
+ "duration": 12.5
+}
+```
+
+**Supported providers:** `deepgram/nova-3`, `assemblyai/best`.
+
+**Supported formats:** `mp3`, `wav`, `m4a`, `flac`, `ogg`, `webm`.
+
+---
+
+## Ollama Compatibility
+
+For clients that use Ollama's API format:
+
+```bash
+# Chat endpoint (Ollama format)
+POST /v1/api/chat
+
+# Model listing (Ollama format)
+GET /api/tags
+```
+
+Requests are automatically translated between Ollama and internal formats.
+
+---
+
+## Telemetry
+
+```bash
+# Get latency telemetry summary (p50/p95/p99 per provider)
+GET /api/telemetry/summary
+```
+
+**Response:**
+
+```json
+{
+ "providers": {
+ "claudeCode": { "p50": 245, "p95": 890, "p99": 1200, "count": 150 },
+ "github": { "p50": 180, "p95": 620, "p99": 950, "count": 320 }
+ }
+}
+```
+
+---
+
+## Budget
+
+```bash
+# Get budget status for all API keys
+GET /api/usage/budget
+
+# Set or update a budget
+POST /api/usage/budget
+Content-Type: application/json
+
+{
+ "keyId": "key-123",
+ "limit": 50.00,
+ "period": "monthly"
+}
+```
+
+---
+
+## Model Availability
+
+```bash
+# Get real-time model availability across all providers
+GET /api/models/availability
+
+# Check availability for a specific model
+POST /api/models/availability
+Content-Type: application/json
+
+{
+ "model": "claude-sonnet-4-5-20250929"
+}
+```
+
+---
+
+## Request Processing
+
+1. Client sends request to `/v1/*`
+2. Route handler calls `handleChat`, `handleEmbedding`, `handleAudioTranscription`, or `handleImageGeneration`
+3. Model is resolved (direct provider/model or alias/combo)
+4. Credentials selected from local DB with account availability filtering
+5. For chat: `handleChatCore` — format detection, translation, cache check, idempotency check
+6. Provider executor sends upstream request
+7. Response translated back to client format (chat) or returned as-is (embeddings/images/audio)
+8. Usage/logging recorded
+9. Fallback applies on errors according to combo rules
+
+Full architecture reference: [`ARCHITECTURE.md`](ARCHITECTURE.md)
+
+---
+
+## Authentication
+
+- Dashboard routes (`/dashboard/*`) use `auth_token` cookie
+- Login uses saved password hash; fallback to `INITIAL_PASSWORD`
+- `requireLogin` toggleable via `/api/settings/require-login`
+- `/v1/*` routes optionally require Bearer API key when `REQUIRE_API_KEY=true`
diff --git a/docs/i18n/id/docs/ARCHITECTURE.md b/docs/i18n/id/docs/ARCHITECTURE.md
new file mode 100644
index 0000000000..f8d0862c0c
--- /dev/null
+++ b/docs/i18n/id/docs/ARCHITECTURE.md
@@ -0,0 +1,814 @@
+# OmniRoute Architecture (Bahasa Indonesia)
+
+🌐 **Languages:** 🇺🇸 [English](../../../../docs/ARCHITECTURE.md) · 🇪🇸 [es](../../es/docs/ARCHITECTURE.md) · 🇫🇷 [fr](../../fr/docs/ARCHITECTURE.md) · 🇩🇪 [de](../../de/docs/ARCHITECTURE.md) · 🇮🇹 [it](../../it/docs/ARCHITECTURE.md) · 🇷🇺 [ru](../../ru/docs/ARCHITECTURE.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/ARCHITECTURE.md) · 🇯🇵 [ja](../../ja/docs/ARCHITECTURE.md) · 🇰🇷 [ko](../../ko/docs/ARCHITECTURE.md) · 🇸🇦 [ar](../../ar/docs/ARCHITECTURE.md) · 🇮🇳 [in](../../in/docs/ARCHITECTURE.md) · 🇹🇭 [th](../../th/docs/ARCHITECTURE.md) · 🇻🇳 [vi](../../vi/docs/ARCHITECTURE.md) · 🇮🇩 [id](../../id/docs/ARCHITECTURE.md) · 🇲🇾 [ms](../../ms/docs/ARCHITECTURE.md) · 🇳🇱 [nl](../../nl/docs/ARCHITECTURE.md) · 🇵🇱 [pl](../../pl/docs/ARCHITECTURE.md) · 🇸🇪 [sv](../../sv/docs/ARCHITECTURE.md) · 🇳🇴 [no](../../no/docs/ARCHITECTURE.md) · 🇩🇰 [da](../../da/docs/ARCHITECTURE.md) · 🇫🇮 [fi](../../fi/docs/ARCHITECTURE.md) · 🇵🇹 [pt](../../pt/docs/ARCHITECTURE.md) · 🇷🇴 [ro](../../ro/docs/ARCHITECTURE.md) · 🇭🇺 [hu](../../hu/docs/ARCHITECTURE.md) · 🇧🇬 [bg](../../bg/docs/ARCHITECTURE.md) · 🇸🇰 [sk](../../sk/docs/ARCHITECTURE.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/ARCHITECTURE.md) · 🇮🇱 [he](../../he/docs/ARCHITECTURE.md) · 🇵🇭 [phi](../../phi/docs/ARCHITECTURE.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/ARCHITECTURE.md) · 🇨🇿 [cs](../../cs/docs/ARCHITECTURE.md)
+
+---
+
+_Last updated: 2026-03-28_
+
+## Executive Summary
+
+OmniRoute is a local AI routing gateway and dashboard built on Next.js.
+It provides a single OpenAI-compatible endpoint (`/v1/*`) and routes traffic across multiple upstream providers with translation, fallback, token refresh, and usage tracking.
+
+Core capabilities:
+
+- OpenAI-compatible API surface for CLI/tools (28 providers)
+- Request/response translation across provider formats
+- Model combo fallback (multi-model sequence)
+- Account-level fallback (multi-account per provider)
+- OAuth + API-key provider connection management
+- Embedding generation via `/v1/embeddings` (6 providers, 9 models)
+- Image generation via `/v1/images/generations` (4 providers, 9 models)
+- Think tag parsing (`...`) for reasoning models
+- Response sanitization for strict OpenAI SDK compatibility
+- Role normalization (developer→system, system→user) for cross-provider compatibility
+- Structured output conversion (json_schema → Gemini responseSchema)
+- Local persistence for providers, keys, aliases, combos, settings, pricing
+- Usage/cost tracking and request logging
+- Optional cloud sync for multi-device/state sync
+- IP allowlist/blocklist for API access control
+- Thinking budget management (passthrough/auto/custom/adaptive)
+- Global system prompt injection
+- Session tracking and fingerprinting
+- Per-account enhanced rate limiting with provider-specific profiles
+- Circuit breaker pattern for provider resilience
+- Anti-thundering herd protection with mutex locking
+- Signature-based request deduplication cache
+- Domain layer: model availability, cost rules, fallback policy, lockout policy
+- Domain state persistence (SQLite write-through cache for fallbacks, budgets, lockouts, circuit breakers)
+- Policy engine for centralized request evaluation (lockout → budget → fallback)
+- Request telemetry with p50/p95/p99 latency aggregation
+- Correlation ID (X-Request-Id) for end-to-end tracing
+- Compliance audit logging with opt-out per API key
+- Eval framework for LLM quality assurance
+- Resilience UI dashboard with real-time circuit breaker status
+- Modular OAuth providers (12 individual modules under `src/lib/oauth/providers/`)
+
+Primary runtime model:
+
+- Next.js app routes under `src/app/api/*` implement both dashboard APIs and compatibility APIs
+- A shared SSE/routing core in `src/sse/*` + `open-sse/*` handles provider execution, translation, streaming, fallback, and usage
+
+## Scope and Boundaries
+
+### In Scope
+
+- Local gateway runtime
+- Dashboard management APIs
+- Provider authentication and token refresh
+- Request translation and SSE streaming
+- Local state + usage persistence
+- Optional cloud sync orchestration
+
+### Out of Scope
+
+- Cloud service implementation behind `NEXT_PUBLIC_CLOUD_URL`
+- Provider SLA/control plane outside local process
+- External CLI binaries themselves (Claude CLI, Codex CLI, etc.)
+
+## Dashboard Surface (Current)
+
+Main pages under `src/app/(dashboard)/dashboard/`:
+
+- `/dashboard` — quick start + provider overview
+- `/dashboard/endpoint` — endpoint proxy + MCP + A2A + API endpoint tabs
+- `/dashboard/providers` — provider connections and credentials
+- `/dashboard/combos` — combo strategies, templates, model routing rules
+- `/dashboard/costs` — cost aggregation and pricing visibility
+- `/dashboard/analytics` — usage analytics and evaluations
+- `/dashboard/limits` — quota/rate controls
+- `/dashboard/cli-tools` — CLI onboarding, runtime detection, config generation
+- `/dashboard/agents` — detected ACP agents + custom agent registration
+- `/dashboard/media` — image/video/music playground
+- `/dashboard/search-tools` — search provider testing and history
+- `/dashboard/health` — uptime, circuit breakers, rate limits
+- `/dashboard/logs` — request/proxy/audit/console logs
+- `/dashboard/settings` — system settings tabs (general, routing, combo defaults, etc.)
+- `/dashboard/api-manager` — API key lifecycle and model permissions
+
+## High-Level System Context
+
+```mermaid
+flowchart LR
+ subgraph Clients[Developer Clients]
+ C1[Claude Code]
+ C2[Codex CLI]
+ C3[OpenClaw / Droid / Cline / Continue / Roo]
+ C4[Custom OpenAI-compatible clients]
+ BROWSER[Browser Dashboard]
+ end
+
+ subgraph Router[OmniRoute Local Process]
+ API[V1 Compatibility API\n/v1/*]
+ DASH[Dashboard + Management API\n/api/*]
+ CORE[SSE + Translation Core\nopen-sse + src/sse]
+ DB[(storage.sqlite)]
+ UDB[(usage tables + log artifacts)]
+ end
+
+ subgraph Upstreams[Upstream Providers]
+ P1[OAuth Providers\nClaude/Codex/Gemini/Qwen/Qoder/GitHub/Kiro/Cursor/Antigravity]
+ P2[API Key Providers\nOpenAI/Anthropic/OpenRouter/GLM/Kimi/MiniMax\nDeepSeek/Groq/xAI/Mistral/Perplexity\nTogether/Fireworks/Cerebras/Cohere/NVIDIA]
+ P3[Compatible Nodes\nOpenAI-compatible / Anthropic-compatible]
+ end
+
+ subgraph Cloud[Optional Cloud Sync]
+ CLOUD[Cloud Sync Endpoint\nNEXT_PUBLIC_CLOUD_URL]
+ end
+
+ C1 --> API
+ C2 --> API
+ C3 --> API
+ C4 --> API
+ BROWSER --> DASH
+
+ API --> CORE
+ DASH --> DB
+ CORE --> DB
+ CORE --> UDB
+
+ CORE --> P1
+ CORE --> P2
+ CORE --> P3
+
+ DASH --> CLOUD
+```
+
+## Core Runtime Components
+
+## 1) API and Routing Layer (Next.js App Routes)
+
+Main directories:
+
+- `src/app/api/v1/*` and `src/app/api/v1beta/*` for compatibility APIs
+- `src/app/api/*` for management/configuration APIs
+- Next rewrites in `next.config.mjs` map `/v1/*` to `/api/v1/*`
+
+Important compatibility routes:
+
+- `src/app/api/v1/chat/completions/route.ts`
+- `src/app/api/v1/messages/route.ts`
+- `src/app/api/v1/responses/route.ts`
+- `src/app/api/v1/models/route.ts` — includes custom models with `custom: true`
+- `src/app/api/v1/embeddings/route.ts` — embedding generation (6 providers)
+- `src/app/api/v1/images/generations/route.ts` — image generation (4+ providers incl. Antigravity/Nebius)
+- `src/app/api/v1/messages/count_tokens/route.ts`
+- `src/app/api/v1/providers/[provider]/chat/completions/route.ts` — dedicated per-provider chat
+- `src/app/api/v1/providers/[provider]/embeddings/route.ts` — dedicated per-provider embeddings
+- `src/app/api/v1/providers/[provider]/images/generations/route.ts` — dedicated per-provider images
+- `src/app/api/v1beta/models/route.ts`
+- `src/app/api/v1beta/models/[...path]/route.ts`
+
+Management domains:
+
+- Auth/settings: `src/app/api/auth/*`, `src/app/api/settings/*`
+- Providers/connections: `src/app/api/providers*`
+- Provider nodes: `src/app/api/provider-nodes*`
+- Custom models: `src/app/api/provider-models` (GET/POST/DELETE)
+- Model catalog: `src/app/api/models/route.ts` (GET)
+- Proxy config: `src/app/api/settings/proxy` (GET/PUT/DELETE) + `src/app/api/settings/proxy/test` (POST)
+- OAuth: `src/app/api/oauth/*`
+- Keys/aliases/combos/pricing: `src/app/api/keys*`, `src/app/api/models/alias`, `src/app/api/combos*`, `src/app/api/pricing`
+- Usage: `src/app/api/usage/*`
+- Sync/cloud: `src/app/api/sync/*`, `src/app/api/cloud/*`
+- CLI tooling helpers: `src/app/api/cli-tools/*`
+- IP filter: `src/app/api/settings/ip-filter` (GET/PUT)
+- Thinking budget: `src/app/api/settings/thinking-budget` (GET/PUT)
+- System prompt: `src/app/api/settings/system-prompt` (GET/PUT)
+- Sessions: `src/app/api/sessions` (GET)
+- Rate limits: `src/app/api/rate-limits` (GET)
+- Resilience: `src/app/api/resilience` (GET/PATCH) — provider profiles, circuit breaker, rate limit state
+- Resilience reset: `src/app/api/resilience/reset` (POST) — reset breakers + cooldowns
+- Cache stats: `src/app/api/cache/stats` (GET/DELETE)
+- Model availability: `src/app/api/models/availability` (GET/POST)
+- Telemetry: `src/app/api/telemetry/summary` (GET)
+- Budget: `src/app/api/usage/budget` (GET/POST)
+- Fallback chains: `src/app/api/fallback/chains` (GET/POST/DELETE)
+- Compliance audit: `src/app/api/compliance/audit-log` (GET)
+- Evals: `src/app/api/evals` (GET/POST), `src/app/api/evals/[suiteId]` (GET)
+- Policies: `src/app/api/policies` (GET/POST)
+
+## 2) SSE + Translation Core
+
+Main flow modules:
+
+- Entry: `src/sse/handlers/chat.ts`
+- Core orchestration: `open-sse/handlers/chatCore.ts`
+- Provider execution adapters: `open-sse/executors/*`
+- Format detection/provider config: `open-sse/services/provider.ts`
+- Model parse/resolve: `src/sse/services/model.ts`, `open-sse/services/model.ts`
+- Account fallback logic: `open-sse/services/accountFallback.ts`
+- Translation registry: `open-sse/translator/index.ts`
+- Stream transformations: `open-sse/utils/stream.ts`, `open-sse/utils/streamHandler.ts`
+- Usage extraction/normalization: `open-sse/utils/usageTracking.ts`
+- Think tag parser: `open-sse/utils/thinkTagParser.ts`
+- Embedding handler: `open-sse/handlers/embeddings.ts`
+- Embedding provider registry: `open-sse/config/embeddingRegistry.ts`
+- Image generation handler: `open-sse/handlers/imageGeneration.ts`
+- Image provider registry: `open-sse/config/imageRegistry.ts`
+- Response sanitization: `open-sse/handlers/responseSanitizer.ts`
+- Role normalization: `open-sse/services/roleNormalizer.ts`
+
+Services (business logic):
+
+- Account selection/scoring: `open-sse/services/accountSelector.ts`
+- Context lifecycle management: `open-sse/services/contextManager.ts`
+- IP filter enforcement: `open-sse/services/ipFilter.ts`
+- Session tracking: `open-sse/services/sessionManager.ts`
+- Request deduplication: `open-sse/services/signatureCache.ts`
+- System prompt injection: `open-sse/services/systemPrompt.ts`
+- Thinking budget management: `open-sse/services/thinkingBudget.ts`
+- Wildcard model routing: `open-sse/services/wildcardRouter.ts`
+- Rate limit management: `open-sse/services/rateLimitManager.ts`
+- Circuit breaker: `open-sse/services/circuitBreaker.ts`
+
+Domain layer modules:
+
+- Model availability: `src/lib/domain/modelAvailability.ts`
+- Cost rules/budgets: `src/lib/domain/costRules.ts`
+- Fallback policy: `src/lib/domain/fallbackPolicy.ts`
+- Combo resolver: `src/lib/domain/comboResolver.ts`
+- Lockout policy: `src/lib/domain/lockoutPolicy.ts`
+- Policy engine: `src/domain/policyEngine.ts` — centralized lockout → budget → fallback evaluation
+- Error codes catalog: `src/lib/domain/errorCodes.ts`
+- Request ID: `src/lib/domain/requestId.ts`
+- Fetch timeout: `src/lib/domain/fetchTimeout.ts`
+- Request telemetry: `src/lib/domain/requestTelemetry.ts`
+- Compliance/audit: `src/lib/domain/compliance/index.ts`
+- Eval runner: `src/lib/domain/evalRunner.ts`
+- Domain state persistence: `src/lib/db/domainState.ts` — SQLite CRUD for fallback chains, budgets, cost history, lockout state, circuit breakers
+
+OAuth provider modules (12 individual files under `src/lib/oauth/providers/`):
+
+- Registry index: `src/lib/oauth/providers/index.ts`
+- Individual providers: `claude.ts`, `codex.ts`, `gemini.ts`, `antigravity.ts`, `qoder.ts`, `qwen.ts`, `kimi-coding.ts`, `github.ts`, `kiro.ts`, `cursor.ts`, `kilocode.ts`, `cline.ts`
+- Thin wrapper: `src/lib/oauth/providers.ts` — re-exports from individual modules
+
+## 3) Persistence Layer
+
+Primary state DB (SQLite):
+
+- Core infra: `src/lib/db/core.ts` (better-sqlite3, migrations, WAL)
+- Re-export facade: `src/lib/localDb.ts` (thin compatibility layer for callers)
+- file: `${DATA_DIR}/storage.sqlite` (or `$XDG_CONFIG_HOME/omniroute/storage.sqlite` when set, else `~/.omniroute/storage.sqlite`)
+- entities (tables + KV namespaces): providerConnections, providerNodes, modelAliases, combos, apiKeys, settings, pricing, **customModels**, **proxyConfig**, **ipFilter**, **thinkingBudget**, **systemPrompt**
+
+Usage persistence:
+
+- facade: `src/lib/usageDb.ts` (decomposed modules in `src/lib/usage/*`)
+- SQLite tables in `storage.sqlite`: `usage_history`, `call_logs`, `proxy_logs`
+- optional file artifacts remain for compatibility/debug (`${DATA_DIR}/log.txt`, `${DATA_DIR}/call_logs/`, `/logs/...`)
+- legacy JSON files are migrated to SQLite by startup migrations when present
+
+Domain State DB (SQLite):
+
+- `src/lib/db/domainState.ts` — CRUD operations for domain state
+- Tables (created in `src/lib/db/core.ts`): `domain_fallback_chains`, `domain_budgets`, `domain_cost_history`, `domain_lockout_state`, `domain_circuit_breakers`
+- Write-through cache pattern: in-memory Maps are authoritative at runtime; mutations are written synchronously to SQLite; state is restored from DB on cold start
+
+## 4) Auth + Security Surfaces
+
+- Dashboard cookie auth: `src/proxy.ts`, `src/app/api/auth/login/route.ts`
+- API key generation/verification: `src/shared/utils/apiKey.ts`
+- Provider secrets persisted in `providerConnections` entries
+- Outbound proxy support via `open-sse/utils/proxyFetch.ts` (env vars) and `open-sse/utils/networkProxy.ts` (configurable per-provider or global)
+
+## 5) Cloud Sync
+
+- Scheduler init: `src/lib/initCloudSync.ts`, `src/shared/services/initializeCloudSync.ts`, `src/shared/services/modelSyncScheduler.ts`
+- Periodic task: `src/shared/services/cloudSyncScheduler.ts`
+- Periodic task: `src/shared/services/modelSyncScheduler.ts`
+- Control route: `src/app/api/sync/cloud/route.ts`
+
+## Request Lifecycle (`/v1/chat/completions`)
+
+```mermaid
+sequenceDiagram
+ autonumber
+ participant Client as CLI/SDK Client
+ participant Route as /api/v1/chat/completions
+ participant Chat as src/sse/handlers/chat
+ participant Core as open-sse/handlers/chatCore
+ participant Model as Model Resolver
+ participant Auth as Credential Selector
+ participant Exec as Provider Executor
+ participant Prov as Upstream Provider
+ participant Stream as Stream Translator
+ participant Usage as usageDb
+
+ Client->>Route: POST /v1/chat/completions
+ Route->>Chat: handleChat(request)
+ Chat->>Model: parse/resolve model or combo
+
+ alt Combo model
+ Chat->>Chat: iterate combo models (handleComboChat)
+ end
+
+ Chat->>Auth: getProviderCredentials(provider)
+ Auth-->>Chat: active account + tokens/api key
+
+ Chat->>Core: handleChatCore(body, modelInfo, credentials)
+ Core->>Core: detect source format
+ Core->>Core: translate request to target format
+ Core->>Exec: execute(provider, transformedBody)
+ Exec->>Prov: upstream API call
+ Prov-->>Exec: SSE/JSON response
+ Exec-->>Core: response + metadata
+
+ alt 401/403
+ Core->>Exec: refreshCredentials()
+ Exec-->>Core: updated tokens
+ Core->>Exec: retry request
+ end
+
+ Core->>Stream: translate/normalize stream to client format
+ Stream-->>Client: SSE chunks / JSON response
+
+ Stream->>Usage: extract usage + persist history/log
+```
+
+## Combo + Account Fallback Flow
+
+```mermaid
+flowchart TD
+ A[Incoming model string] --> B{Is combo name?}
+ B -- Yes --> C[Load combo models sequence]
+ B -- No --> D[Single model path]
+
+ C --> E[Try model N]
+ E --> F[Resolve provider/model]
+ D --> F
+
+ F --> G[Select account credentials]
+ G --> H{Credentials available?}
+ H -- No --> I[Return provider unavailable]
+ H -- Yes --> J[Execute request]
+
+ J --> K{Success?}
+ K -- Yes --> L[Return response]
+ K -- No --> M{Fallback-eligible error?}
+
+ M -- No --> N[Return error]
+ M -- Yes --> O[Mark account unavailable cooldown]
+ O --> P{Another account for provider?}
+ P -- Yes --> G
+ P -- No --> Q{In combo with next model?}
+ Q -- Yes --> E
+ Q -- No --> R[Return all unavailable]
+```
+
+Fallback decisions are driven by `open-sse/services/accountFallback.ts` using status codes and error-message heuristics. Combo routing adds one extra guard: provider-scoped 400s such as upstream content-block and role-validation failures are treated as model-local failures so later combo targets can still run.
+
+## OAuth Onboarding and Token Refresh Lifecycle
+
+```mermaid
+sequenceDiagram
+ autonumber
+ participant UI as Dashboard UI
+ participant OAuth as /api/oauth/[provider]/[action]
+ participant ProvAuth as Provider Auth Server
+ participant DB as localDb
+ participant Test as /api/providers/[id]/test
+ participant Exec as Provider Executor
+
+ UI->>OAuth: GET authorize or device-code
+ OAuth->>ProvAuth: create auth/device flow
+ ProvAuth-->>OAuth: auth URL or device code payload
+ OAuth-->>UI: flow data
+
+ UI->>OAuth: POST exchange or poll
+ OAuth->>ProvAuth: token exchange/poll
+ ProvAuth-->>OAuth: access/refresh tokens
+ OAuth->>DB: createProviderConnection(oauth data)
+ OAuth-->>UI: success + connection id
+
+ UI->>Test: POST /api/providers/[id]/test
+ Test->>Exec: validate credentials / optional refresh
+ Exec-->>Test: valid or refreshed token info
+ Test->>DB: update status/tokens/errors
+ Test-->>UI: validation result
+```
+
+Refresh during live traffic is executed inside `open-sse/handlers/chatCore.ts` via executor `refreshCredentials()`.
+
+## Cloud Sync Lifecycle (Enable / Sync / Disable)
+
+```mermaid
+sequenceDiagram
+ autonumber
+ participant UI as Endpoint Page UI
+ participant Sync as /api/sync/cloud
+ participant DB as localDb
+ participant Cloud as External Cloud Sync
+ participant Claude as ~/.claude/settings.json
+
+ UI->>Sync: POST action=enable
+ Sync->>DB: set cloudEnabled=true
+ Sync->>DB: ensure API key exists
+ Sync->>Cloud: POST /sync/{machineId} (providers/aliases/combos/keys)
+ Cloud-->>Sync: sync result
+ Sync->>Cloud: GET /{machineId}/v1/verify
+ Sync-->>UI: enabled + verification status
+
+ UI->>Sync: POST action=sync
+ Sync->>Cloud: POST /sync/{machineId}
+ Cloud-->>Sync: remote data
+ Sync->>DB: update newer local tokens/status
+ Sync-->>UI: synced
+
+ UI->>Sync: POST action=disable
+ Sync->>DB: set cloudEnabled=false
+ Sync->>Cloud: DELETE /sync/{machineId}
+ Sync->>Claude: switch ANTHROPIC_BASE_URL back to local (if needed)
+ Sync-->>UI: disabled
+```
+
+Periodic sync is triggered by `CloudSyncScheduler` when cloud is enabled.
+
+## Data Model and Storage Map
+
+```mermaid
+erDiagram
+ SETTINGS ||--o{ PROVIDER_CONNECTION : controls
+ PROVIDER_NODE ||--o{ PROVIDER_CONNECTION : backs_compatible_provider
+ PROVIDER_CONNECTION ||--o{ USAGE_ENTRY : emits_usage
+
+ SETTINGS {
+ boolean cloudEnabled
+ number stickyRoundRobinLimit
+ boolean requireLogin
+ string password_hash
+ string fallbackStrategy
+ json rateLimitDefaults
+ json providerProfiles
+ }
+
+ PROVIDER_CONNECTION {
+ string id
+ string provider
+ string authType
+ string name
+ number priority
+ boolean isActive
+ string apiKey
+ string accessToken
+ string refreshToken
+ string expiresAt
+ string testStatus
+ string lastError
+ string rateLimitedUntil
+ json providerSpecificData
+ }
+
+ PROVIDER_NODE {
+ string id
+ string type
+ string name
+ string prefix
+ string apiType
+ string baseUrl
+ }
+
+ MODEL_ALIAS {
+ string alias
+ string targetModel
+ }
+
+ COMBO {
+ string id
+ string name
+ string[] models
+ }
+
+ API_KEY {
+ string id
+ string name
+ string key
+ string machineId
+ }
+
+ USAGE_ENTRY {
+ string provider
+ string model
+ number prompt_tokens
+ number completion_tokens
+ string connectionId
+ string timestamp
+ }
+
+ CUSTOM_MODEL {
+ string id
+ string name
+ string providerId
+ }
+
+ PROXY_CONFIG {
+ string global
+ json providers
+ }
+
+ IP_FILTER {
+ string mode
+ string[] allowlist
+ string[] blocklist
+ }
+
+ THINKING_BUDGET {
+ string mode
+ number customBudget
+ string effortLevel
+ }
+
+ SYSTEM_PROMPT {
+ boolean enabled
+ string prompt
+ string position
+ }
+```
+
+Physical storage files:
+
+- primary runtime DB: `${DATA_DIR}/storage.sqlite`
+- request log lines: `${DATA_DIR}/log.txt` (compat/debug artifact)
+- structured call payload archives: `${DATA_DIR}/call_logs/`
+- optional translator/request debug sessions: `/logs/...`
+
+## Deployment Topology
+
+```mermaid
+flowchart LR
+ subgraph LocalHost[Developer Host]
+ CLI[CLI Tools]
+ Browser[Dashboard Browser]
+ end
+
+ subgraph ContainerOrProcess[OmniRoute Runtime]
+ Next[Next.js Server\nPORT=20128]
+ Core[SSE Core + Executors]
+ MainDB[(storage.sqlite)]
+ UsageDB[(usage tables + log artifacts)]
+ end
+
+ subgraph External[External Services]
+ Providers[AI Providers]
+ SyncCloud[Cloud Sync Service]
+ end
+
+ CLI --> Next
+ Browser --> Next
+ Next --> Core
+ Next --> MainDB
+ Core --> MainDB
+ Core --> UsageDB
+ Core --> Providers
+ Next --> SyncCloud
+```
+
+## Module Mapping (Decision-Critical)
+
+### Route and API Modules
+
+- `src/app/api/v1/*`, `src/app/api/v1beta/*`: compatibility APIs
+- `src/app/api/v1/providers/[provider]/*`: dedicated per-provider routes (chat, embeddings, images)
+- `src/app/api/providers*`: provider CRUD, validation, testing
+- `src/app/api/provider-nodes*`: custom compatible node management
+- `src/app/api/provider-models`: custom model management (CRUD)
+- `src/app/api/models/route.ts`: model catalog API (aliases + custom models)
+- `src/app/api/oauth/*`: OAuth/device-code flows
+- `src/app/api/keys*`: local API key lifecycle
+- `src/app/api/models/alias`: alias management
+- `src/app/api/combos*`: fallback combo management
+- `src/app/api/pricing`: pricing overrides for cost calculation
+- `src/app/api/settings/proxy`: proxy configuration (GET/PUT/DELETE)
+- `src/app/api/settings/proxy/test`: outbound proxy connectivity test (POST)
+- `src/app/api/usage/*`: usage and logs APIs
+- `src/app/api/sync/*` + `src/app/api/cloud/*`: cloud sync and cloud-facing helpers
+- `src/app/api/cli-tools/*`: local CLI config writers/checkers
+- `src/app/api/settings/ip-filter`: IP allowlist/blocklist (GET/PUT)
+- `src/app/api/settings/thinking-budget`: thinking token budget config (GET/PUT)
+- `src/app/api/settings/system-prompt`: global system prompt (GET/PUT)
+- `src/app/api/sessions`: active session listing (GET)
+- `src/app/api/rate-limits`: per-account rate limit status (GET)
+
+### Routing and Execution Core
+
+- `src/sse/handlers/chat.ts`: request parse, combo handling, account selection loop
+- `open-sse/handlers/chatCore.ts`: translation, executor dispatch, retry/refresh handling, stream setup
+- `open-sse/executors/*`: provider-specific network and format behavior
+
+### Translation Registry and Format Converters
+
+- `open-sse/translator/index.ts`: translator registry and orchestration
+- Request translators: `open-sse/translator/request/*`
+- Response translators: `open-sse/translator/response/*`
+- Format constants: `open-sse/translator/formats.ts`
+
+### Persistence
+
+- `src/lib/db/*`: persistent config/state and domain persistence on SQLite
+- `src/lib/localDb.ts`: compatibility re-export for DB modules
+- `src/lib/usageDb.ts`: usage history/call logs facade on top of SQLite tables
+
+## Provider Executor Coverage (Strategy Pattern)
+
+Each provider has a specialized executor extending `BaseExecutor` (in `open-sse/executors/base.ts`), which provides URL building, header construction, retry with exponential backoff, credential refresh hooks, and the `execute()` orchestration method.
+
+| Executor | Provider(s) | Special Handling |
+| --------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------ | -------------------------------------------------------------------- |
+| `DefaultExecutor` | OpenAI, Claude, Gemini, Qwen, Qoder, OpenRouter, GLM, Kimi, MiniMax, DeepSeek, Groq, xAI, Mistral, Perplexity, Together, Fireworks, Cerebras, Cohere, NVIDIA | Dynamic URL/header config per provider |
+| `AntigravityExecutor` | Google Antigravity | Custom project/session IDs, Retry-After parsing |
+| `CodexExecutor` | OpenAI Codex | Injects system instructions, forces reasoning effort |
+| `CursorExecutor` | Cursor IDE | ConnectRPC protocol, Protobuf encoding, request signing via checksum |
+| `GithubExecutor` | GitHub Copilot | Copilot token refresh, VSCode-mimicking headers |
+| `KiroExecutor` | AWS CodeWhisperer/Kiro | AWS EventStream binary format → SSE conversion |
+| `GeminiCLIExecutor` | Gemini CLI | Google OAuth token refresh cycle |
+
+All other providers (including custom compatible nodes) use the `DefaultExecutor`.
+
+## Provider Compatibility Matrix
+
+| Provider | Format | Auth | Stream | Non-Stream | Token Refresh | Usage API |
+| ---------------- | ---------------- | --------------------- | ---------------- | ---------- | ------------- | ------------------ |
+| Claude | claude | API Key / OAuth | ✅ | ✅ | ✅ | ⚠️ Admin only |
+| Gemini | gemini | API Key / OAuth | ✅ | ✅ | ✅ | ⚠️ Cloud Console |
+| Gemini CLI | gemini-cli | OAuth | ✅ | ✅ | ✅ | ⚠️ Cloud Console |
+| Antigravity | antigravity | OAuth | ✅ | ✅ | ✅ | ✅ Full quota API |
+| OpenAI | openai | API Key | ✅ | ✅ | ❌ | ❌ |
+| Codex | openai-responses | OAuth | ✅ forced | ❌ | ✅ | ✅ Rate limits |
+| GitHub Copilot | openai | OAuth + Copilot Token | ✅ | ✅ | ✅ | ✅ Quota snapshots |
+| Cursor | cursor | Custom checksum | ✅ | ✅ | ❌ | ❌ |
+| Kiro | kiro | AWS SSO OIDC | ✅ (EventStream) | ❌ | ✅ | ✅ Usage limits |
+| Qwen | openai | OAuth | ✅ | ✅ | ✅ | ⚠️ Per request |
+| Qoder | openai | OAuth (Basic) | ✅ | ✅ | ✅ | ⚠️ Per request |
+| OpenRouter | openai | API Key | ✅ | ✅ | ❌ | ❌ |
+| GLM/Kimi/MiniMax | claude | API Key | ✅ | ✅ | ❌ | ❌ |
+| DeepSeek | openai | API Key | ✅ | ✅ | ❌ | ❌ |
+| Groq | openai | API Key | ✅ | ✅ | ❌ | ❌ |
+| xAI (Grok) | openai | API Key | ✅ | ✅ | ❌ | ❌ |
+| Mistral | openai | API Key | ✅ | ✅ | ❌ | ❌ |
+| Perplexity | openai | API Key | ✅ | ✅ | ❌ | ❌ |
+| Together AI | openai | API Key | ✅ | ✅ | ❌ | ❌ |
+| Fireworks AI | openai | API Key | ✅ | ✅ | ❌ | ❌ |
+| Cerebras | openai | API Key | ✅ | ✅ | ❌ | ❌ |
+| Cohere | openai | API Key | ✅ | ✅ | ❌ | ❌ |
+| NVIDIA NIM | openai | API Key | ✅ | ✅ | ❌ | ❌ |
+
+## Format Translation Coverage
+
+Detected source formats include:
+
+- `openai`
+- `openai-responses`
+- `claude`
+- `gemini`
+
+Target formats include:
+
+- OpenAI chat/Responses
+- Claude
+- Gemini/Gemini-CLI/Antigravity envelope
+- Kiro
+- Cursor
+
+Translations use **OpenAI as the hub format** — all conversions go through OpenAI as intermediate:
+
+```
+Source Format → OpenAI (hub) → Target Format
+```
+
+Translations are selected dynamically based on source payload shape and provider target format.
+
+Additional processing layers in the translation pipeline:
+
+- **Response sanitization** — Strips non-standard fields from OpenAI-format responses (both streaming and non-streaming) to ensure strict SDK compliance
+- **Role normalization** — Converts `developer` → `system` for non-OpenAI targets; merges `system` → `user` for models that reject the system role (GLM, ERNIE)
+- **Think tag extraction** — Parses `...` blocks from content into `reasoning_content` field
+- **Structured output** — Converts OpenAI `response_format.json_schema` to Gemini's `responseMimeType` + `responseSchema`
+
+## Supported API Endpoints
+
+| Endpoint | Format | Handler |
+| -------------------------------------------------- | ------------------ | ------------------------------------------------------------------- |
+| `POST /v1/chat/completions` | OpenAI Chat | `src/sse/handlers/chat.ts` |
+| `POST /v1/messages` | Claude Messages | Same handler (auto-detected) |
+| `POST /v1/responses` | OpenAI Responses | `open-sse/handlers/responsesHandler.ts` |
+| `POST /v1/embeddings` | OpenAI Embeddings | `open-sse/handlers/embeddings.ts` |
+| `GET /v1/embeddings` | Model listing | API route |
+| `POST /v1/images/generations` | OpenAI Images | `open-sse/handlers/imageGeneration.ts` |
+| `GET /v1/images/generations` | Model listing | API route |
+| `POST /v1/providers/{provider}/chat/completions` | OpenAI Chat | Dedicated per-provider with model validation |
+| `POST /v1/providers/{provider}/embeddings` | OpenAI Embeddings | Dedicated per-provider with model validation |
+| `POST /v1/providers/{provider}/images/generations` | OpenAI Images | Dedicated per-provider with model validation |
+| `POST /v1/messages/count_tokens` | Claude Token Count | API route |
+| `GET /v1/models` | OpenAI Models list | API route (chat + embedding + image + custom models) |
+| `GET /api/models/catalog` | Catalog | All models grouped by provider + type |
+| `POST /v1beta/models/*:streamGenerateContent` | Gemini native | API route |
+| `GET/PUT/DELETE /api/settings/proxy` | Proxy Config | Network proxy configuration |
+| `POST /api/settings/proxy/test` | Proxy Connectivity | Proxy health/connectivity test endpoint |
+| `GET/POST/DELETE /api/provider-models` | Provider Models | Provider model metadata backing custom and managed available models |
+
+## Bypass Handler
+
+The bypass handler (`open-sse/utils/bypassHandler.ts`) intercepts known "throwaway" requests from Claude CLI — warmup pings, title extractions, and token counts — and returns a **fake response** without consuming upstream provider tokens. This is triggered only when `User-Agent` contains `claude-cli`.
+
+## Request Logger Pipeline
+
+The request logger (`open-sse/utils/requestLogger.ts`) provides a 7-stage debug logging pipeline, disabled by default, enabled via `ENABLE_REQUEST_LOGS=true`:
+
+```
+1_req_client.json → 2_req_source.json → 3_req_openai.json → 4_req_target.json
+→ 5_res_provider.txt → 6_res_openai.txt → 7_res_client.txt
+```
+
+Files are written to `/logs//` for each request session.
+
+## Failure Modes and Resilience
+
+## 1) Account/Provider Availability
+
+- provider account cooldown on transient/rate/auth errors
+- account fallback before failing request
+- combo model fallback when current model/provider path is exhausted
+
+## 2) Token Expiry
+
+- pre-check and refresh with retry for refreshable providers
+- 401/403 retry after refresh attempt in core path
+
+## 3) Stream Safety
+
+- disconnect-aware stream controller
+- translation stream with end-of-stream flush and `[DONE]` handling
+- usage estimation fallback when provider usage metadata is missing
+
+## 4) Cloud Sync Degradation
+
+- sync errors are surfaced but local runtime continues
+- scheduler has retry-capable logic, but periodic execution currently calls single-attempt sync by default
+
+## 5) Data Integrity
+
+- SQLite schema migrations and auto-upgrade hooks at startup
+- legacy JSON → SQLite migration compatibility path
+
+## Observability and Operational Signals
+
+Runtime visibility sources:
+
+- console logs from `src/sse/utils/logger.ts`
+- per-request usage aggregates in SQLite (`usage_history`, `call_logs`, `proxy_logs`)
+- four-stage detailed payload captures in SQLite (`request_detail_logs`) when `settings.detailed_logs_enabled=true`
+- textual request status log in `log.txt` (optional/compat)
+- optional deep request/translation logs under `logs/` when `ENABLE_REQUEST_LOGS=true`
+- dashboard usage endpoints (`/api/usage/*`) for UI consumption
+
+Detailed request payload capture stores up to four JSON payload stages per routed call:
+
+- raw request received from the client
+- translated request actually sent upstream
+- provider response reconstructed as JSON; streamed responses are compacted to the final summary plus stream metadata
+- final client response returned by OmniRoute; streamed responses are stored in the same compact summary form
+
+## Security-Sensitive Boundaries
+
+- JWT secret (`JWT_SECRET`) secures dashboard session cookie verification/signing
+- Initial password bootstrap (`INITIAL_PASSWORD`) should be explicitly configured for first-run provisioning
+- API key HMAC secret (`API_KEY_SECRET`) secures generated local API key format
+- Provider secrets (API keys/tokens) are persisted in local DB and should be protected at filesystem level
+- Cloud sync endpoints rely on API key auth + machine id semantics
+
+## Environment and Runtime Matrix
+
+Environment variables actively used by code:
+
+- App/auth: `JWT_SECRET`, `INITIAL_PASSWORD`
+- Storage: `DATA_DIR`
+- Compatible node behavior: `ALLOW_MULTI_CONNECTIONS_PER_COMPAT_NODE`
+- Optional storage base override (Linux/macOS when `DATA_DIR` unset): `XDG_CONFIG_HOME`
+- Security hashing: `API_KEY_SECRET`, `MACHINE_ID_SALT`
+- Logging: `ENABLE_REQUEST_LOGS`
+- Sync/cloud URLing: `NEXT_PUBLIC_BASE_URL`, `NEXT_PUBLIC_CLOUD_URL`
+- Outbound proxy: `HTTP_PROXY`, `HTTPS_PROXY`, `ALL_PROXY`, `NO_PROXY` and lowercase variants
+- SOCKS5 feature flags: `ENABLE_SOCKS5_PROXY`, `NEXT_PUBLIC_ENABLE_SOCKS5_PROXY`
+- Platform/runtime helpers (not app-specific config): `APPDATA`, `NODE_ENV`, `PORT`, `HOSTNAME`
+
+## Known Architectural Notes
+
+1. `usageDb` and `localDb` share the same base directory policy (`DATA_DIR` -> `XDG_CONFIG_HOME/omniroute` -> `~/.omniroute`) with legacy file migration.
+2. `/api/v1/route.ts` delegates to the same unified catalog builder used by `/api/v1/models` (`src/app/api/v1/models/catalog.ts`) to avoid semantic drift.
+3. Request logger writes full headers/body when enabled; treat log directory as sensitive.
+4. Cloud behavior depends on correct `NEXT_PUBLIC_BASE_URL` and cloud endpoint reachability.
+5. The `open-sse/` directory is published as the `@omniroute/open-sse` **npm workspace package**. Source code imports it via `@omniroute/open-sse/...` (resolved by Next.js `transpilePackages`). File paths in this document still use the directory name `open-sse/` for consistency.
+6. Charts in the dashboard use **Recharts** (SVG-based) for accessible, interactive analytics visualizations (model usage bar charts, provider breakdown tables with success rates).
+7. E2E tests use **Playwright** (`tests/e2e/`), run via `npm run test:e2e`. Unit tests use **Node.js test runner** (`tests/unit/`), run via `npm run test:unit`. Source code under `src/` is **TypeScript** (`.ts`/`.tsx`); the `open-sse/` workspace remains JavaScript (`.js`).
+8. Settings page is organized into 5 tabs: Security, Routing (6 global strategies: fill-first, round-robin, p2c, random, least-used, cost-optimized), Resilience (editable rate limits, circuit breaker, policies), AI (thinking budget, system prompt, prompt cache), Advanced (proxy).
+
+## Operational Verification Checklist
+
+- Build from source: `npm run build`
+- Build Docker image: `docker build -t omniroute .`
+- Start service and verify:
+- `GET /api/settings`
+- `GET /api/v1/models`
+- CLI target base URL should be `http://:20128/v1` when `PORT=20128`
diff --git a/docs/i18n/id/docs/AUTO-COMBO.md b/docs/i18n/id/docs/AUTO-COMBO.md
new file mode 100644
index 0000000000..93ab4073c9
--- /dev/null
+++ b/docs/i18n/id/docs/AUTO-COMBO.md
@@ -0,0 +1,67 @@
+# OmniRoute Auto-Combo Engine (Bahasa Indonesia)
+
+🌐 **Languages:** 🇺🇸 [English](../../../../docs/AUTO-COMBO.md) · 🇪🇸 [es](../../es/docs/AUTO-COMBO.md) · 🇫🇷 [fr](../../fr/docs/AUTO-COMBO.md) · 🇩🇪 [de](../../de/docs/AUTO-COMBO.md) · 🇮🇹 [it](../../it/docs/AUTO-COMBO.md) · 🇷🇺 [ru](../../ru/docs/AUTO-COMBO.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/AUTO-COMBO.md) · 🇯🇵 [ja](../../ja/docs/AUTO-COMBO.md) · 🇰🇷 [ko](../../ko/docs/AUTO-COMBO.md) · 🇸🇦 [ar](../../ar/docs/AUTO-COMBO.md) · 🇮🇳 [in](../../in/docs/AUTO-COMBO.md) · 🇹🇭 [th](../../th/docs/AUTO-COMBO.md) · 🇻🇳 [vi](../../vi/docs/AUTO-COMBO.md) · 🇮🇩 [id](../../id/docs/AUTO-COMBO.md) · 🇲🇾 [ms](../../ms/docs/AUTO-COMBO.md) · 🇳🇱 [nl](../../nl/docs/AUTO-COMBO.md) · 🇵🇱 [pl](../../pl/docs/AUTO-COMBO.md) · 🇸🇪 [sv](../../sv/docs/AUTO-COMBO.md) · 🇳🇴 [no](../../no/docs/AUTO-COMBO.md) · 🇩🇰 [da](../../da/docs/AUTO-COMBO.md) · 🇫🇮 [fi](../../fi/docs/AUTO-COMBO.md) · 🇵🇹 [pt](../../pt/docs/AUTO-COMBO.md) · 🇷🇴 [ro](../../ro/docs/AUTO-COMBO.md) · 🇭🇺 [hu](../../hu/docs/AUTO-COMBO.md) · 🇧🇬 [bg](../../bg/docs/AUTO-COMBO.md) · 🇸🇰 [sk](../../sk/docs/AUTO-COMBO.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/AUTO-COMBO.md) · 🇮🇱 [he](../../he/docs/AUTO-COMBO.md) · 🇵🇭 [phi](../../phi/docs/AUTO-COMBO.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/AUTO-COMBO.md) · 🇨🇿 [cs](../../cs/docs/AUTO-COMBO.md)
+
+---
+
+> Self-managing model chains with adaptive scoring
+
+## How It Works
+
+The Auto-Combo Engine dynamically selects the best provider/model for each request using a **6-factor scoring function**:
+
+| Factor | Weight | Description |
+| :--------- | :----- | :---------------------------------------------- |
+| Quota | 0.20 | Remaining capacity [0..1] |
+| Health | 0.25 | Circuit breaker: CLOSED=1.0, HALF=0.5, OPEN=0.0 |
+| CostInv | 0.20 | Inverse cost (cheaper = higher score) |
+| LatencyInv | 0.15 | Inverse p95 latency (faster = higher) |
+| TaskFit | 0.10 | Model × task type fitness score |
+| Stability | 0.10 | Low variance in latency/errors |
+
+## Mode Packs
+
+| Pack | Focus | Key Weight |
+| :---------------------- | :----------- | :--------------- |
+| 🚀 **Ship Fast** | Speed | latencyInv: 0.35 |
+| 💰 **Cost Saver** | Economy | costInv: 0.40 |
+| 🎯 **Quality First** | Best model | taskFit: 0.40 |
+| 📡 **Offline Friendly** | Availability | quota: 0.40 |
+
+## Self-Healing
+
+- **Temporary exclusion**: Score < 0.2 → excluded for 5 min (progressive backoff, max 30 min)
+- **Circuit breaker awareness**: OPEN → auto-excluded; HALF_OPEN → probe requests
+- **Incident mode**: >50% OPEN → disable exploration, maximize stability
+- **Cooldown recovery**: After exclusion, first request is a "probe" with reduced timeout
+
+## Bandit Exploration
+
+5% of requests (configurable) are routed to random providers for exploration. Disabled in incident mode.
+
+## API
+
+```bash
+# Create auto-combo
+curl -X POST http://localhost:20128/api/combos/auto \
+ -H "Content-Type: application/json" \
+ -d '{"id":"my-auto","name":"Auto Coder","candidatePool":["anthropic","google","openai"],"modePack":"ship-fast"}'
+
+# List auto-combos
+curl http://localhost:20128/api/combos/auto
+```
+
+## Task Fitness
+
+30+ models scored across 6 task types (`coding`, `review`, `planning`, `analysis`, `debugging`, `documentation`). Supports wildcard patterns (e.g., `*-coder` → high coding score).
+
+## Files
+
+| File | Purpose |
+| :------------------------------------------- | :------------------------------------ |
+| `open-sse/services/autoCombo/scoring.ts` | Scoring function & pool normalization |
+| `open-sse/services/autoCombo/taskFitness.ts` | Model × task fitness lookup |
+| `open-sse/services/autoCombo/engine.ts` | Selection logic, bandit, budget cap |
+| `open-sse/services/autoCombo/selfHealing.ts` | Exclusion, probes, incident mode |
+| `open-sse/services/autoCombo/modePacks.ts` | 4 weight profiles |
+| `src/app/api/combos/auto/route.ts` | REST API |
diff --git a/docs/i18n/id/docs/CLI-TOOLS.md b/docs/i18n/id/docs/CLI-TOOLS.md
new file mode 100644
index 0000000000..b5bc640f08
--- /dev/null
+++ b/docs/i18n/id/docs/CLI-TOOLS.md
@@ -0,0 +1,348 @@
+# CLI Tools Setup Guide — OmniRoute (Bahasa Indonesia)
+
+🌐 **Languages:** 🇺🇸 [English](../../../../docs/CLI-TOOLS.md) · 🇪🇸 [es](../../es/docs/CLI-TOOLS.md) · 🇫🇷 [fr](../../fr/docs/CLI-TOOLS.md) · 🇩🇪 [de](../../de/docs/CLI-TOOLS.md) · 🇮🇹 [it](../../it/docs/CLI-TOOLS.md) · 🇷🇺 [ru](../../ru/docs/CLI-TOOLS.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/CLI-TOOLS.md) · 🇯🇵 [ja](../../ja/docs/CLI-TOOLS.md) · 🇰🇷 [ko](../../ko/docs/CLI-TOOLS.md) · 🇸🇦 [ar](../../ar/docs/CLI-TOOLS.md) · 🇮🇳 [in](../../in/docs/CLI-TOOLS.md) · 🇹🇭 [th](../../th/docs/CLI-TOOLS.md) · 🇻🇳 [vi](../../vi/docs/CLI-TOOLS.md) · 🇮🇩 [id](../../id/docs/CLI-TOOLS.md) · 🇲🇾 [ms](../../ms/docs/CLI-TOOLS.md) · 🇳🇱 [nl](../../nl/docs/CLI-TOOLS.md) · 🇵🇱 [pl](../../pl/docs/CLI-TOOLS.md) · 🇸🇪 [sv](../../sv/docs/CLI-TOOLS.md) · 🇳🇴 [no](../../no/docs/CLI-TOOLS.md) · 🇩🇰 [da](../../da/docs/CLI-TOOLS.md) · 🇫🇮 [fi](../../fi/docs/CLI-TOOLS.md) · 🇵🇹 [pt](../../pt/docs/CLI-TOOLS.md) · 🇷🇴 [ro](../../ro/docs/CLI-TOOLS.md) · 🇭🇺 [hu](../../hu/docs/CLI-TOOLS.md) · 🇧🇬 [bg](../../bg/docs/CLI-TOOLS.md) · 🇸🇰 [sk](../../sk/docs/CLI-TOOLS.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/CLI-TOOLS.md) · 🇮🇱 [he](../../he/docs/CLI-TOOLS.md) · 🇵🇭 [phi](../../phi/docs/CLI-TOOLS.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/CLI-TOOLS.md) · 🇨🇿 [cs](../../cs/docs/CLI-TOOLS.md)
+
+---
+
+This guide explains how to install and configure all supported AI coding CLI tools
+to use **OmniRoute** as the unified backend, giving you centralized key management,
+cost tracking, model switching, and request logging across every tool.
+
+---
+
+## How It Works
+
+```
+Claude / Codex / OpenCode / Cline / KiloCode / Continue / Kiro / Cursor / Copilot
+ │
+ ▼ (all point to OmniRoute)
+ http://YOUR_SERVER:20128/v1
+ │
+ ▼ (OmniRoute routes to the right provider)
+ Anthropic / OpenAI / Gemini / DeepSeek / Groq / Mistral / ...
+```
+
+**Benefits:**
+
+- One API key to manage all tools
+- Cost tracking across all CLIs in the dashboard
+- Model switching without reconfiguring every tool
+- Works locally and on remote servers (VPS)
+
+---
+
+## Supported Tools (Dashboard Source of Truth)
+
+The dashboard cards in `/dashboard/cli-tools` are generated from `src/shared/constants/cliTools.ts`.
+Current list (v3.0.0-rc.16):
+
+| Tool | ID | Command | Setup Mode | Install Method |
+| ------------------ | ------------- | ---------- | ---------- | -------------- |
+| **Claude Code** | `claude` | `claude` | env | npm |
+| **OpenAI Codex** | `codex` | `codex` | custom | npm |
+| **Factory Droid** | `droid` | `droid` | custom | bundled/CLI |
+| **OpenClaw** | `openclaw` | `openclaw` | custom | bundled/CLI |
+| **Cursor** | `cursor` | app | guide | desktop app |
+| **Cline** | `cline` | `cline` | custom | npm |
+| **Kilo Code** | `kilo` | `kilocode` | custom | npm |
+| **Continue** | `continue` | extension | guide | VS Code |
+| **Antigravity** | `antigravity` | internal | mitm | OmniRoute |
+| **GitHub Copilot** | `copilot` | extension | custom | VS Code |
+| **OpenCode** | `opencode` | `opencode` | guide | npm |
+| **Kiro AI** | `kiro` | app/cli | mitm | desktop/CLI |
+
+### CLI fingerprint sync (Agents + Settings)
+
+`/dashboard/agents` and `Settings > CLI Fingerprint` use `src/shared/constants/cliCompatProviders.ts`.
+This keeps provider IDs aligned with CLI cards and legacy IDs.
+
+| CLI ID | Fingerprint Provider ID |
+| ---------------------------------------------------------------------------------------------------- | ----------------------- |
+| `kilo` | `kilocode` |
+| `copilot` | `github` |
+| `claude` / `codex` / `antigravity` / `kiro` / `cursor` / `cline` / `opencode` / `droid` / `openclaw` | same ID |
+
+Legacy IDs still accepted for compatibility: `copilot`, `kimi-coding`, `qwen`.
+
+---
+
+## Step 1 — Get an OmniRoute API Key
+
+1. Open the OmniRoute dashboard → **API Manager** (`/dashboard/api-manager`)
+2. Click **Create API Key**
+3. Give it a name (e.g. `cli-tools`) and select all permissions
+4. Copy the key — you'll need it for every CLI below
+
+> Your key looks like: `sk-xxxxxxxxxxxxxxxx-xxxxxxxxx`
+
+---
+
+## Step 2 — Install CLI Tools
+
+All npm-based tools require Node.js 18+:
+
+```bash
+# Claude Code (Anthropic)
+npm install -g @anthropic-ai/claude-code
+
+# OpenAI Codex
+npm install -g @openai/codex
+
+# OpenCode
+npm install -g opencode-ai
+
+# Cline
+npm install -g cline
+
+# KiloCode
+npm install -g kilocode
+
+# Kiro CLI (Amazon — requires curl + unzip)
+apt-get install -y unzip # on Debian/Ubuntu
+curl -fsSL https://cli.kiro.dev/install | bash
+export PATH="$HOME/.local/bin:$PATH" # add to ~/.bashrc
+```
+
+**Verify:**
+
+```bash
+claude --version # 2.x.x
+codex --version # 0.x.x
+opencode --version # x.x.x
+cline --version # 2.x.x
+kilocode --version # x.x.x (or: kilo --version)
+kiro-cli --version # 1.x.x
+```
+
+---
+
+## Step 3 — Set Global Environment Variables
+
+Add to `~/.bashrc` (or `~/.zshrc`), then run `source ~/.bashrc`:
+
+```bash
+# OmniRoute Universal Endpoint
+export OPENAI_BASE_URL="http://localhost:20128/v1"
+export OPENAI_API_KEY="sk-your-omniroute-key"
+export ANTHROPIC_BASE_URL="http://localhost:20128/v1"
+export ANTHROPIC_API_KEY="sk-your-omniroute-key"
+export GEMINI_BASE_URL="http://localhost:20128/v1"
+export GEMINI_API_KEY="sk-your-omniroute-key"
+```
+
+> For a **remote server** replace `localhost:20128` with the server IP or domain,
+> e.g. `http://192.168.0.15:20128`.
+
+---
+
+## Step 4 — Configure Each Tool
+
+### Claude Code
+
+```bash
+# Via CLI:
+claude config set --global api-base-url http://localhost:20128/v1
+
+# Or create ~/.claude/settings.json:
+mkdir -p ~/.claude && cat > ~/.claude/settings.json << EOF
+{
+ "apiBaseUrl": "http://localhost:20128/v1",
+ "apiKey": "sk-your-omniroute-key"
+}
+EOF
+```
+
+**Test:** `claude "say hello"`
+
+---
+
+### OpenAI Codex
+
+```bash
+mkdir -p ~/.codex && cat > ~/.codex/config.yaml << EOF
+model: auto
+apiKey: sk-your-omniroute-key
+apiBaseUrl: http://localhost:20128/v1
+EOF
+```
+
+**Test:** `codex "what is 2+2?"`
+
+---
+
+### OpenCode
+
+```bash
+mkdir -p ~/.config/opencode && cat > ~/.config/opencode/config.toml << EOF
+[provider.openai]
+base_url = "http://localhost:20128/v1"
+api_key = "sk-your-omniroute-key"
+EOF
+```
+
+**Test:** `opencode`
+
+---
+
+### Cline (CLI or VS Code)
+
+**CLI mode:**
+
+```bash
+mkdir -p ~/.cline/data && cat > ~/.cline/data/globalState.json << EOF
+{
+ "apiProvider": "openai",
+ "openAiBaseUrl": "http://localhost:20128/v1",
+ "openAiApiKey": "sk-your-omniroute-key"
+}
+EOF
+```
+
+**VS Code mode:**
+Cline extension settings → API Provider: `OpenAI Compatible` → Base URL: `http://localhost:20128/v1`
+
+Or use the OmniRoute dashboard → **CLI Tools → Cline → Apply Config**.
+
+---
+
+### KiloCode (CLI or VS Code)
+
+**CLI mode:**
+
+```bash
+kilocode --api-base http://localhost:20128/v1 --api-key sk-your-omniroute-key
+```
+
+**VS Code settings:**
+
+```json
+{
+ "kilo-code.openAiBaseUrl": "http://localhost:20128/v1",
+ "kilo-code.apiKey": "sk-your-omniroute-key"
+}
+```
+
+Or use the OmniRoute dashboard → **CLI Tools → KiloCode → Apply Config**.
+
+---
+
+### Continue (VS Code Extension)
+
+Edit `~/.continue/config.yaml`:
+
+```yaml
+models:
+ - name: OmniRoute
+ provider: openai
+ model: auto
+ apiBase: http://localhost:20128/v1
+ apiKey: sk-your-omniroute-key
+ default: true
+```
+
+Restart VS Code after editing.
+
+---
+
+### Kiro CLI (Amazon)
+
+```bash
+# Login to your AWS/Kiro account:
+kiro-cli login
+
+# The CLI uses its own auth — OmniRoute is not needed as backend for Kiro CLI itself.
+# Use kiro-cli alongside OmniRoute for other tools.
+kiro-cli status
+```
+
+---
+
+### Cursor (Desktop App)
+
+> **Note:** Cursor routes requests through its cloud. For OmniRoute integration,
+> enable **Cloud Endpoint** in OmniRoute Settings and use your public domain URL.
+
+Via GUI: **Settings → Models → OpenAI API Key**
+
+- Base URL: `https://your-domain.com/v1`
+- API Key: your OmniRoute key
+
+---
+
+## Dashboard Auto-Configuration
+
+The OmniRoute dashboard automates configuration for most tools:
+
+1. Go to `http://localhost:20128/dashboard/cli-tools`
+2. Expand any tool card
+3. Select your API key from the dropdown
+4. Click **Apply Config** (if tool is detected as installed)
+5. Or copy the generated config snippet manually
+
+---
+
+## Built-in Agents: Droid & OpenClaw
+
+**Droid** and **OpenClaw** are AI agents built directly into OmniRoute — no installation needed.
+They run as internal routes and use OmniRoute's model routing automatically.
+
+- Access: `http://localhost:20128/dashboard/agents`
+- Configure: same combos and providers as all other tools
+- No API key or CLI install required
+
+---
+
+## Available API Endpoints
+
+| Endpoint | Description | Use For |
+| -------------------------- | ----------------------------- | --------------------------- |
+| `/v1/chat/completions` | Standard chat (all providers) | All modern tools |
+| `/v1/responses` | Responses API (OpenAI format) | Codex, agentic workflows |
+| `/v1/completions` | Legacy text completions | Older tools using `prompt:` |
+| `/v1/embeddings` | Text embeddings | RAG, search |
+| `/v1/images/generations` | Image generation | DALL-E, Flux, etc. |
+| `/v1/audio/speech` | Text-to-speech | ElevenLabs, OpenAI TTS |
+| `/v1/audio/transcriptions` | Speech-to-text | Deepgram, AssemblyAI |
+
+---
+
+## Pemecahan Masalah
+
+| Error | Cause | Fix |
+| ------------------------- | ----------------------- | ------------------------------------------ |
+| `Connection refused` | OmniRoute not running | `pm2 start omniroute` |
+| `401 Unauthorized` | Wrong API key | Check in `/dashboard/api-manager` |
+| `No combo configured` | No active routing combo | Set up in `/dashboard/combos` |
+| `invalid model` | Model not in catalog | Use `auto` or check `/dashboard/providers` |
+| CLI shows "not installed" | Binary not in PATH | Check `which ` |
+| `kiro-cli: not found` | Not in PATH | `export PATH="$HOME/.local/bin:$PATH"` |
+
+---
+
+## Quick Setup Script (One Command)
+
+```bash
+# Install all CLIs and configure for OmniRoute (replace with your key and server URL)
+OMNIROUTE_URL="http://localhost:20128/v1"
+OMNIROUTE_KEY="sk-your-omniroute-key"
+
+npm install -g @anthropic-ai/claude-code @openai/codex opencode-ai cline kilocode
+
+# Kiro CLI
+apt-get install -y unzip 2>/dev/null; curl -fsSL https://cli.kiro.dev/install | bash
+
+# Write configs
+mkdir -p ~/.claude ~/.codex ~/.config/opencode ~/.continue
+
+cat > ~/.claude/settings.json <<< "{\"apiBaseUrl\":\"$OMNIROUTE_URL\",\"apiKey\":\"$OMNIROUTE_KEY\"}"
+cat > ~/.codex/config.yaml <<< "model: auto\napiKey: $OMNIROUTE_KEY\napiBaseUrl: $OMNIROUTE_URL"
+cat >> ~/.bashrc << EOF
+export OPENAI_BASE_URL="$OMNIROUTE_URL"
+export OPENAI_API_KEY="$OMNIROUTE_KEY"
+export ANTHROPIC_BASE_URL="$OMNIROUTE_URL"
+export ANTHROPIC_API_KEY="$OMNIROUTE_KEY"
+EOF
+
+source ~/.bashrc
+echo "✅ All CLIs installed and configured for OmniRoute"
+```
diff --git a/docs/i18n/id/docs/CODEBASE_DOCUMENTATION.md b/docs/i18n/id/docs/CODEBASE_DOCUMENTATION.md
new file mode 100644
index 0000000000..5520de1fbf
--- /dev/null
+++ b/docs/i18n/id/docs/CODEBASE_DOCUMENTATION.md
@@ -0,0 +1,591 @@
+# omniroute — Codebase Documentation (Bahasa Indonesia)
+
+🌐 **Languages:** 🇺🇸 [English](../../../../docs/CODEBASE_DOCUMENTATION.md) · 🇪🇸 [es](../../es/docs/CODEBASE_DOCUMENTATION.md) · 🇫🇷 [fr](../../fr/docs/CODEBASE_DOCUMENTATION.md) · 🇩🇪 [de](../../de/docs/CODEBASE_DOCUMENTATION.md) · 🇮🇹 [it](../../it/docs/CODEBASE_DOCUMENTATION.md) · 🇷🇺 [ru](../../ru/docs/CODEBASE_DOCUMENTATION.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/CODEBASE_DOCUMENTATION.md) · 🇯🇵 [ja](../../ja/docs/CODEBASE_DOCUMENTATION.md) · 🇰🇷 [ko](../../ko/docs/CODEBASE_DOCUMENTATION.md) · 🇸🇦 [ar](../../ar/docs/CODEBASE_DOCUMENTATION.md) · 🇮🇳 [in](../../in/docs/CODEBASE_DOCUMENTATION.md) · 🇹🇭 [th](../../th/docs/CODEBASE_DOCUMENTATION.md) · 🇻🇳 [vi](../../vi/docs/CODEBASE_DOCUMENTATION.md) · 🇮🇩 [id](../../id/docs/CODEBASE_DOCUMENTATION.md) · 🇲🇾 [ms](../../ms/docs/CODEBASE_DOCUMENTATION.md) · 🇳🇱 [nl](../../nl/docs/CODEBASE_DOCUMENTATION.md) · 🇵🇱 [pl](../../pl/docs/CODEBASE_DOCUMENTATION.md) · 🇸🇪 [sv](../../sv/docs/CODEBASE_DOCUMENTATION.md) · 🇳🇴 [no](../../no/docs/CODEBASE_DOCUMENTATION.md) · 🇩🇰 [da](../../da/docs/CODEBASE_DOCUMENTATION.md) · 🇫🇮 [fi](../../fi/docs/CODEBASE_DOCUMENTATION.md) · 🇵🇹 [pt](../../pt/docs/CODEBASE_DOCUMENTATION.md) · 🇷🇴 [ro](../../ro/docs/CODEBASE_DOCUMENTATION.md) · 🇭🇺 [hu](../../hu/docs/CODEBASE_DOCUMENTATION.md) · 🇧🇬 [bg](../../bg/docs/CODEBASE_DOCUMENTATION.md) · 🇸🇰 [sk](../../sk/docs/CODEBASE_DOCUMENTATION.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/CODEBASE_DOCUMENTATION.md) · 🇮🇱 [he](../../he/docs/CODEBASE_DOCUMENTATION.md) · 🇵🇭 [phi](../../phi/docs/CODEBASE_DOCUMENTATION.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/CODEBASE_DOCUMENTATION.md) · 🇨🇿 [cs](../../cs/docs/CODEBASE_DOCUMENTATION.md)
+
+---
+
+> A comprehensive, beginner-friendly guide to the **omniroute** multi-provider AI proxy router.
+
+---
+
+## 1. What Is omniroute?
+
+omniroute is a **proxy router** that sits between AI clients (Claude CLI, Codex, Cursor IDE, etc.) and AI providers (Anthropic, Google, OpenAI, AWS, GitHub, etc.). It solves one big problem:
+
+> **Different AI clients speak different "languages" (API formats), and different AI providers expect different "languages" too.** omniroute translates between them automatically.
+
+Think of it like a universal translator at the United Nations — any delegate can speak any language, and the translator converts it for any other delegate.
+
+---
+
+## 2. Architecture Overview
+
+```mermaid
+graph LR
+ subgraph Clients
+ A[Claude CLI]
+ B[Codex]
+ C[Cursor IDE]
+ D[OpenAI-compatible]
+ end
+
+ subgraph omniroute
+ E[Handler Layer]
+ F[Translator Layer]
+ G[Executor Layer]
+ H[Services Layer]
+ end
+
+ subgraph Providers
+ I[Anthropic Claude]
+ J[Google Gemini]
+ K[OpenAI / Codex]
+ L[GitHub Copilot]
+ M[AWS Kiro]
+ N[Antigravity]
+ O[Cursor API]
+ end
+
+ A --> E
+ B --> E
+ C --> E
+ D --> E
+ E --> F
+ F --> G
+ G --> I
+ G --> J
+ G --> K
+ G --> L
+ G --> M
+ G --> N
+ G --> O
+ H -.-> E
+ H -.-> G
+```
+
+### Core Principle: Hub-and-Spoke Translation
+
+All format translation passes through **OpenAI format as the hub**:
+
+```
+Client Format → [OpenAI Hub] → Provider Format (request)
+Provider Format → [OpenAI Hub] → Client Format (response)
+```
+
+This means you only need **N translators** (one per format) instead of **N²** (every pair).
+
+---
+
+## 3. Project Structure
+
+```
+omniroute/
+├── open-sse/ ← Core proxy library (portable, framework-agnostic)
+│ ├── index.js ← Main entry point, exports everything
+│ ├── config/ ← Configuration & constants
+│ ├── executors/ ← Provider-specific request execution
+│ ├── handlers/ ← Request handling orchestration
+│ ├── services/ ← Business logic (auth, models, fallback, usage)
+│ ├── translator/ ← Format translation engine
+│ │ ├── request/ ← Request translators (8 files)
+│ │ ├── response/ ← Response translators (7 files)
+│ │ └── helpers/ ← Shared translation utilities (6 files)
+│ └── utils/ ← Utility functions
+├── src/ ← Application layer (Express/Worker runtime)
+│ ├── app/ ← Web UI, API routes, middleware
+│ ├── lib/ ← Database, auth, and shared library code
+│ ├── mitm/ ← Man-in-the-middle proxy utilities
+│ ├── models/ ← Database models
+│ ├── shared/ ← Shared utilities (wrappers around open-sse)
+│ ├── sse/ ← SSE endpoint handlers
+│ └── store/ ← State management
+├── data/ ← Runtime data (credentials, logs)
+│ └── provider-credentials.json (external credentials override, gitignored)
+└── tester/ ← Test utilities
+```
+
+---
+
+## 4. Module-by-Module Breakdown
+
+### 4.1 Config (`open-sse/config/`)
+
+The **single source of truth** for all provider configuration.
+
+| File | Purpose |
+| ----------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| `constants.ts` | `PROVIDERS` object with base URLs, OAuth credentials (defaults), headers, and default system prompts for every provider. Also defines `HTTP_STATUS`, `ERROR_TYPES`, `COOLDOWN_MS`, `BACKOFF_CONFIG`, and `SKIP_PATTERNS`. |
+| `credentialLoader.ts` | Loads external credentials from `data/provider-credentials.json` and merges them over the hardcoded defaults in `PROVIDERS`. Keeps secrets out of source control while maintaining backwards compatibility. |
+| `providerModels.ts` | Central model registry: maps provider aliases → model IDs. Functions like `getModels()`, `getProviderByAlias()`. |
+| `codexInstructions.ts` | System instructions injected into Codex requests (editing constraints, sandbox rules, approval policies). |
+| `defaultThinkingSignature.ts` | Default "thinking" signatures for Claude and Gemini models. |
+| `ollamaModels.ts` | Schema definition for local Ollama models (name, size, family, quantization). |
+
+#### Credential Loading Flow
+
+```mermaid
+flowchart TD
+ A["App starts"] --> B["constants.ts defines PROVIDERS\nwith hardcoded defaults"]
+ B --> C{"data/provider-credentials.json\nexists?"}
+ C -->|Yes| D["credentialLoader reads JSON"]
+ C -->|No| E["Use hardcoded defaults"]
+ D --> F{"For each provider in JSON"}
+ F --> G{"Provider exists\nin PROVIDERS?"}
+ G -->|No| H["Log warning, skip"]
+ G -->|Yes| I{"Value is object?"}
+ I -->|No| J["Log warning, skip"]
+ I -->|Yes| K["Merge clientId, clientSecret,\ntokenUrl, authUrl, refreshUrl"]
+ K --> F
+ H --> F
+ J --> F
+ F -->|Done| L["PROVIDERS ready with\nmerged credentials"]
+ E --> L
+```
+
+---
+
+### 4.2 Executors (`open-sse/executors/`)
+
+Executors encapsulate **provider-specific logic** using the **Strategy Pattern**. Each executor overrides base methods as needed.
+
+```mermaid
+classDiagram
+ class BaseExecutor {
+ +buildUrl(model, stream, options)
+ +buildHeaders(credentials, stream, body)
+ +transformRequest(body, model, stream, credentials)
+ +execute(url, options)
+ +shouldRetry(status, error)
+ +refreshCredentials(credentials, log)
+ }
+
+ class DefaultExecutor {
+ +refreshCredentials()
+ }
+
+ class AntigravityExecutor {
+ +buildUrl()
+ +buildHeaders()
+ +transformRequest()
+ +shouldRetry()
+ +refreshCredentials()
+ }
+
+ class CursorExecutor {
+ +buildUrl()
+ +buildHeaders()
+ +transformRequest()
+ +parseResponse()
+ +generateChecksum()
+ }
+
+ class KiroExecutor {
+ +buildUrl()
+ +buildHeaders()
+ +transformRequest()
+ +parseEventStream()
+ +refreshCredentials()
+ }
+
+ BaseExecutor <|-- DefaultExecutor
+ BaseExecutor <|-- AntigravityExecutor
+ BaseExecutor <|-- CursorExecutor
+ BaseExecutor <|-- KiroExecutor
+ BaseExecutor <|-- CodexExecutor
+ BaseExecutor <|-- GeminiCLIExecutor
+ BaseExecutor <|-- GithubExecutor
+```
+
+| Executor | Provider | Key Specializations |
+| ---------------- | ------------------------------------------ | ------------------------------------------------------------------------------------------------------------------- |
+| `base.ts` | — | Abstract base: URL building, headers, retry logic, credential refresh |
+| `default.ts` | Claude, Gemini, OpenAI, GLM, Kimi, MiniMax | Generic OAuth token refresh for standard providers |
+| `antigravity.ts` | Google Cloud Code | Project/session ID generation, multi-URL fallback, custom retry parsing from error messages ("reset after 2h7m23s") |
+| `cursor.ts` | Cursor IDE | **Most complex**: SHA-256 checksum auth, Protobuf request encoding, binary EventStream → SSE response parsing |
+| `codex.ts` | OpenAI Codex | Injects system instructions, manages thinking levels, removes unsupported parameters |
+| `gemini-cli.ts` | Google Gemini CLI | Custom URL building (`streamGenerateContent`), Google OAuth token refresh |
+| `github.ts` | GitHub Copilot | Dual token system (GitHub OAuth + Copilot token), VSCode header mimicking |
+| `kiro.ts` | AWS CodeWhisperer | AWS EventStream binary parsing, AMZN event frames, token estimation |
+| `index.ts` | — | Factory: maps provider name → executor class, with default fallback |
+
+---
+
+### 4.3 Handlers (`open-sse/handlers/`)
+
+The **orchestration layer** — coordinates translation, execution, streaming, and error handling.
+
+| File | Purpose |
+| --------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| `chatCore.ts` | **Central orchestrator** (~600 lines). Handles the complete request lifecycle: format detection → translation → executor dispatch → streaming/non-streaming response → token refresh → error handling → usage logging. |
+| `responsesHandler.ts` | Adapter for OpenAI's Responses API: converts Responses format → Chat Completions → sends to `chatCore` → converts SSE back to Responses format. |
+| `embeddings.ts` | Embedding generation handler: resolves embedding model → provider, dispatches to provider API, returns OpenAI-compatible embedding response. Supports 6+ providers. |
+| `imageGeneration.ts` | Image generation handler: resolves image model → provider, supports OpenAI-compatible, Gemini-image (Antigravity), and fallback (Nebius) modes. Returns base64 or URL images. |
+
+#### Request Lifecycle (chatCore.ts)
+
+```mermaid
+sequenceDiagram
+ participant Client
+ participant chatCore
+ participant Translator
+ participant Executor
+ participant Provider
+
+ Client->>chatCore: Request (any format)
+ chatCore->>chatCore: Detect source format
+ chatCore->>chatCore: Check bypass patterns
+ chatCore->>chatCore: Resolve model & provider
+ chatCore->>Translator: Translate request (source → OpenAI → target)
+ chatCore->>Executor: Get executor for provider
+ Executor->>Executor: Build URL, headers, transform request
+ Executor->>Executor: Refresh credentials if needed
+ Executor->>Provider: HTTP fetch (streaming or non-streaming)
+
+ alt Streaming
+ Provider-->>chatCore: SSE stream
+ chatCore->>chatCore: Pipe through SSE transform stream
+ Note over chatCore: Transform stream translates
each chunk: target → OpenAI → source
+ chatCore-->>Client: Translated SSE stream
+ else Non-streaming
+ Provider-->>chatCore: JSON response
+ chatCore->>Translator: Translate response
+ chatCore-->>Client: Translated JSON
+ end
+
+ alt Error (401, 429, 500...)
+ chatCore->>Executor: Retry with credential refresh
+ chatCore->>chatCore: Account fallback logic
+ end
+```
+
+---
+
+### 4.4 Services (`open-sse/services/`)
+
+Business logic that supports the handlers and executors.
+
+| File | Purpose |
+| -------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| `provider.ts` | **Format detection** (`detectFormat`): analyzes request body structure to identify Claude/OpenAI/Gemini/Antigravity/Responses formats (includes `max_tokens` heuristic for Claude). Also: URL building, header building, thinking config normalization. Supports `openai-compatible-*` and `anthropic-compatible-*` dynamic providers. |
+| `model.ts` | Model string parsing (`claude/model-name` → `{provider: "claude", model: "model-name"}`), alias resolution with collision detection, input sanitization (rejects path traversal/control chars), and model info resolution with async alias getter support. |
+| `accountFallback.ts` | Rate-limit handling: exponential backoff (1s → 2s → 4s → max 2min), account cooldown management, error classification (which errors trigger fallback vs. not). |
+| `tokenRefresh.ts` | OAuth token refresh for **every provider**: Google (Gemini, Antigravity), Claude, Codex, Qwen, Qoder, GitHub (OAuth + Copilot dual-token), Kiro (AWS SSO OIDC + Social Auth). Includes in-flight promise deduplication cache and retry with exponential backoff. |
+| `combo.ts` | **Combo models**: chains of fallback models. If model A fails with a fallback-eligible error, try model B, then C, etc. Returns actual upstream status codes. |
+| `usage.ts` | Fetches quota/usage data from provider APIs (GitHub Copilot quotas, Antigravity model quotas, Codex rate limits, Kiro usage breakdowns, Claude settings). |
+| `accountSelector.ts` | Smart account selection with scoring algorithm: considers priority, health status, round-robin position, and cooldown state to pick the optimal account for each request. |
+| `contextManager.ts` | Request context lifecycle management: creates and tracks per-request context objects with metadata (request ID, timestamps, provider info) for debugging and logging. |
+| `ipFilter.ts` | IP-based access control: supports allowlist and blocklist modes. Validates client IP against configured rules before processing API requests. |
+| `sessionManager.ts` | Session tracking with client fingerprinting: tracks active sessions using hashed client identifiers, monitors request counts, and provides session metrics. |
+| `signatureCache.ts` | Request signature-based deduplication cache: prevents duplicate requests by caching recent request signatures and returning cached responses for identical requests within a time window. |
+| `systemPrompt.ts` | Global system prompt injection: prepends or appends a configurable system prompt to all requests, with per-provider compatibility handling. |
+| `thinkingBudget.ts` | Reasoning token budget management: supports passthrough, auto (strip thinking config), custom (fixed budget), and adaptive (complexity-scaled) modes for controlling thinking/reasoning tokens. |
+| `wildcardRouter.ts` | Wildcard model pattern routing: resolves wildcard patterns (e.g., `*/claude-*`) to concrete provider/model pairs based on availability and priority. |
+
+#### Token Refresh Deduplication
+
+```mermaid
+sequenceDiagram
+ participant R1 as Request 1
+ participant R2 as Request 2
+ participant Cache as refreshPromiseCache
+ participant OAuth as OAuth Provider
+
+ R1->>Cache: getAccessToken("gemini", token)
+ Cache->>Cache: No in-flight promise
+ Cache->>OAuth: Start refresh
+ R2->>Cache: getAccessToken("gemini", token)
+ Cache->>Cache: Found in-flight promise
+ Cache-->>R2: Return existing promise
+ OAuth-->>Cache: New access token
+ Cache-->>R1: New access token
+ Cache-->>R2: Same access token (shared)
+ Cache->>Cache: Delete cache entry
+```
+
+#### Account Fallback State Machine
+
+```mermaid
+stateDiagram-v2
+ [*] --> Active
+ Active --> Error: Request fails (401/429/500)
+ Error --> Cooldown: Apply backoff
+ Cooldown --> Active: Cooldown expires
+ Active --> Active: Request succeeds (reset backoff)
+
+ state Error {
+ [*] --> ClassifyError
+ ClassifyError --> ShouldFallback: Rate limit / Auth / Transient
+ ClassifyError --> NoFallback: 400 Bad Request
+ }
+
+ state Cooldown {
+ [*] --> ExponentialBackoff
+ ExponentialBackoff: Level 0 = 1s
+ ExponentialBackoff: Level 1 = 2s
+ ExponentialBackoff: Level 2 = 4s
+ ExponentialBackoff: Max = 2min
+ }
+```
+
+#### Combo Model Chain
+
+```mermaid
+flowchart LR
+ A["Request with\ncombo model"] --> B["Model A"]
+ B -->|"2xx Success"| C["Return response"]
+ B -->|"429/401/500"| D{"Fallback\neligible?"}
+ D -->|Yes| E["Model B"]
+ D -->|No| F["Return error"]
+ E -->|"2xx Success"| C
+ E -->|"429/401/500"| G{"Fallback\neligible?"}
+ G -->|Yes| H["Model C"]
+ G -->|No| F
+ H -->|"2xx Success"| C
+ H -->|"Fail"| I["All failed →\nReturn last status"]
+```
+
+---
+
+### 4.5 Translator (`open-sse/translator/`)
+
+The **format translation engine** using a self-registering plugin system.
+
+#### Arsitektur
+
+```mermaid
+graph TD
+ subgraph "Request Translation"
+ A["Claude → OpenAI"]
+ B["Gemini → OpenAI"]
+ C["Antigravity → OpenAI"]
+ D["OpenAI Responses → OpenAI"]
+ E["OpenAI → Claude"]
+ F["OpenAI → Gemini"]
+ G["OpenAI → Kiro"]
+ H["OpenAI → Cursor"]
+ end
+
+ subgraph "Response Translation"
+ I["Claude → OpenAI"]
+ J["Gemini → OpenAI"]
+ K["Kiro → OpenAI"]
+ L["Cursor → OpenAI"]
+ M["OpenAI → Claude"]
+ N["OpenAI → Antigravity"]
+ O["OpenAI → Responses"]
+ end
+```
+
+| Directory | Files | Description |
+| ------------ | ------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| `request/` | 8 translators | Convert request bodies between formats. Each file self-registers via `register(from, to, fn)` on import. |
+| `response/` | 7 translators | Convert streaming response chunks between formats. Handles SSE event types, thinking blocks, tool calls. |
+| `helpers/` | 6 helpers | Shared utilities: `claudeHelper` (system prompt extraction, thinking config), `geminiHelper` (parts/contents mapping), `openaiHelper` (format filtering), `toolCallHelper` (ID generation, missing response injection), `maxTokensHelper`, `responsesApiHelper`. |
+| `index.ts` | — | Translation engine: `translateRequest()`, `translateResponse()`, state management, registry. |
+| `formats.ts` | — | Format constants: `OPENAI`, `CLAUDE`, `GEMINI`, `ANTIGRAVITY`, `KIRO`, `CURSOR`, `OPENAI_RESPONSES`. |
+
+#### Key Design: Self-Registering Plugins
+
+```javascript
+// Each translator file calls register() on import:
+import { register } from "../index.js";
+register("claude", "openai", translateClaudeToOpenAI);
+
+// The index.js imports all translator files, triggering registration:
+import "./request/claude-to-openai.js"; // ← self-registers
+```
+
+---
+
+### 4.6 Utils (`open-sse/utils/`)
+
+| File | Purpose |
+| ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
+| `error.ts` | Error response building (OpenAI-compatible format), upstream error parsing, Antigravity retry-time extraction from error messages, SSE error streaming. |
+| `stream.ts` | **SSE Transform Stream** — the core streaming pipeline. Two modes: `TRANSLATE` (full format translation) and `PASSTHROUGH` (normalize + extract usage). Handles chunk buffering, usage estimation, content length tracking. Per-stream encoder/decoder instances avoid shared state. |
+| `streamHelpers.ts` | Low-level SSE utilities: `parseSSELine` (whitespace-tolerant), `hasValuableContent` (filters empty chunks for OpenAI/Claude/Gemini), `fixInvalidId`, `formatSSE` (format-aware SSE serialization with `perf_metrics` cleanup). |
+| `usageTracking.ts` | Token usage extraction from any format (Claude/OpenAI/Gemini/Responses), estimation with separate tool/message char-per-token ratios, buffer addition (2000 tokens safety margin), format-specific field filtering, console logging with ANSI colors. |
+| `requestLogger.ts` | File-based request logging (opt-in via `ENABLE_REQUEST_LOGS=true`). Creates session folders with numbered files: `1_req_client.json` → `7_res_client.txt`. All I/O is async (fire-and-forget). Masks sensitive headers. |
+| `bypassHandler.ts` | Intercepts specific patterns from Claude CLI (title extraction, warmup, count) and returns fake responses without calling any provider. Supports both streaming and non-streaming. Intentionally limited to Claude CLI scope. |
+| `networkProxy.ts` | Resolves outbound proxy URL for a given provider with precedence: provider-specific config → global config → environment variables (`HTTPS_PROXY`/`HTTP_PROXY`/`ALL_PROXY`). Supports `NO_PROXY` exclusions. Caches config for 30s. |
+
+#### SSE Streaming Pipeline
+
+```mermaid
+flowchart TD
+ A["Provider SSE stream"] --> B["TextDecoder\n(per-stream instance)"]
+ B --> C["Buffer lines\n(split on newline)"]
+ C --> D["parseSSELine()\n(trim whitespace, parse JSON)"]
+ D --> E{"Mode?"}
+ E -->|TRANSLATE| F["translateResponse()\ntarget → OpenAI → source"]
+ E -->|PASSTHROUGH| G["fixInvalidId()\nnormalize chunk"]
+ F --> H["hasValuableContent()\nfilter empty chunks"]
+ G --> H
+ H -->|"Has content"| I["extractUsage()\ntrack token counts"]
+ H -->|"Empty"| J["Skip chunk"]
+ I --> K["formatSSE()\nserialize + clean perf_metrics"]
+ K --> L["TextEncoder\n(per-stream instance)"]
+ L --> M["Enqueue to\nclient stream"]
+
+ style A fill:#f9f,stroke:#333
+ style M fill:#9f9,stroke:#333
+```
+
+#### Request Logger Session Structure
+
+```
+logs/
+└── claude_gemini_claude-sonnet_20260208_143045/
+ ├── 1_req_client.json ← Raw client request
+ ├── 2_req_source.json ← After initial conversion
+ ├── 3_req_openai.json ← OpenAI intermediate format
+ ├── 4_req_target.json ← Final target format
+ ├── 5_res_provider.txt ← Provider SSE chunks (streaming)
+ ├── 5_res_provider.json ← Provider response (non-streaming)
+ ├── 6_res_openai.txt ← OpenAI intermediate chunks
+ ├── 7_res_client.txt ← Client-facing SSE chunks
+ └── 6_error.json ← Error details (if any)
+```
+
+---
+
+### 4.7 Application Layer (`src/`)
+
+| Directory | Purpose |
+| ------------- | ---------------------------------------------------------------------- |
+| `src/app/` | Web UI, API routes, Express middleware, OAuth callback handlers |
+| `src/lib/` | Database access (`localDb.ts`, `usageDb.ts`), authentication, shared |
+| `src/mitm/` | Man-in-the-middle proxy utilities for intercepting provider traffic |
+| `src/models/` | Database model definitions |
+| `src/shared/` | Wrappers around open-sse functions (provider, stream, error, etc.) |
+| `src/sse/` | SSE endpoint handlers that wire the open-sse library to Express routes |
+| `src/store/` | Application state management |
+
+#### Notable API Routes
+
+| Route | Methods | Purpose |
+| --------------------------------------------- | --------------- | ------------------------------------------------------------------------------------- |
+| `/api/provider-models` | GET/POST/DELETE | CRUD for custom models per provider |
+| `/api/models/catalog` | GET | Aggregated catalog of all models (chat, embedding, image, custom) grouped by provider |
+| `/api/settings/proxy` | GET/PUT/DELETE | Hierarchical outbound proxy configuration (`global/providers/combos/keys`) |
+| `/api/settings/proxy/test` | POST | Validates proxy connectivity and returns public IP/latency |
+| `/v1/providers/[provider]/chat/completions` | POST | Dedicated per-provider chat completions with model validation |
+| `/v1/providers/[provider]/embeddings` | POST | Dedicated per-provider embeddings with model validation |
+| `/v1/providers/[provider]/images/generations` | POST | Dedicated per-provider image generation with model validation |
+| `/api/settings/ip-filter` | GET/PUT | IP allowlist/blocklist management |
+| `/api/settings/thinking-budget` | GET/PUT | Reasoning token budget configuration (passthrough/auto/custom/adaptive) |
+| `/api/settings/system-prompt` | GET/PUT | Global system prompt injection for all requests |
+| `/api/sessions` | GET | Active session tracking and metrics |
+| `/api/rate-limits` | GET | Per-account rate limit status |
+
+---
+
+## 5. Key Design Patterns
+
+### 5.1 Hub-and-Spoke Translation
+
+All formats translate through **OpenAI format as the hub**. Adding a new provider only requires writing **one pair** of translators (to/from OpenAI), not N pairs.
+
+### 5.2 Executor Strategy Pattern
+
+Each provider has a dedicated executor class inheriting from `BaseExecutor`. The factory in `executors/index.ts` selects the right one at runtime.
+
+### 5.3 Self-Registering Plugin System
+
+Translator modules register themselves on import via `register()`. Adding a new translator is just creating a file and importing it.
+
+### 5.4 Account Fallback with Exponential Backoff
+
+When a provider returns 429/401/500, the system can switch to the next account, applying exponential cooldowns (1s → 2s → 4s → max 2min).
+
+### 5.5 Combo Model Chains
+
+A "combo" groups multiple `provider/model` strings. If the first fails, fallback to the next automatically.
+
+### 5.6 Stateful Streaming Translation
+
+Response translation maintains state across SSE chunks (thinking block tracking, tool call accumulation, content block indexing) via the `initState()` mechanism.
+
+### 5.7 Usage Safety Buffer
+
+A 2000-token buffer is added to reported usage to prevent clients from hitting context window limits due to overhead from system prompts and format translation.
+
+---
+
+## 6. Supported Formats
+
+| Format | Direction | Identifier |
+| ----------------------- | --------------- | ------------------ |
+| OpenAI Chat Completions | source + target | `openai` |
+| OpenAI Responses API | source + target | `openai-responses` |
+| Anthropic Claude | source + target | `claude` |
+| Google Gemini | source + target | `gemini` |
+| Google Gemini CLI | target only | `gemini-cli` |
+| Antigravity | source + target | `antigravity` |
+| AWS Kiro | target only | `kiro` |
+| Cursor | target only | `cursor` |
+
+---
+
+## 7. Supported Providers
+
+| Provider | Auth Method | Executor | Key Notes |
+| ------------------------ | ---------------------- | ----------- | --------------------------------------------- |
+| Anthropic Claude | API key or OAuth | Default | Uses `x-api-key` header |
+| Google Gemini | API key or OAuth | Default | Uses `x-goog-api-key` header |
+| Google Gemini CLI | OAuth | GeminiCLI | Uses `streamGenerateContent` endpoint |
+| Antigravity | OAuth | Antigravity | Multi-URL fallback, custom retry parsing |
+| OpenAI | API key | Default | Standard Bearer auth |
+| Codex | OAuth | Codex | Injects system instructions, manages thinking |
+| GitHub Copilot | OAuth + Copilot token | Github | Dual token, VSCode header mimicking |
+| Kiro (AWS) | AWS SSO OIDC or Social | Kiro | Binary EventStream parsing |
+| Cursor IDE | Checksum auth | Cursor | Protobuf encoding, SHA-256 checksums |
+| Qwen | OAuth | Default | Standard auth |
+| Qoder | OAuth (Basic + Bearer) | Default | Dual auth header |
+| OpenRouter | API key | Default | Standard Bearer auth |
+| GLM, Kimi, MiniMax | API key | Default | Claude-compatible, use `x-api-key` |
+| `openai-compatible-*` | API key | Default | Dynamic: any OpenAI-compatible endpoint |
+| `anthropic-compatible-*` | API key | Default | Dynamic: any Claude-compatible endpoint |
+
+---
+
+## 8. Data Flow Summary
+
+### Streaming Request
+
+```mermaid
+flowchart LR
+ A["Client"] --> B["detectFormat()"]
+ B --> C["translateRequest()\nsource → OpenAI → target"]
+ C --> D["Executor\nbuildUrl + buildHeaders"]
+ D --> E["fetch(providerURL)"]
+ E --> F["createSSEStream()\nTRANSLATE mode"]
+ F --> G["parseSSELine()"]
+ G --> H["translateResponse()\ntarget → OpenAI → source"]
+ H --> I["extractUsage()\n+ addBuffer"]
+ I --> J["formatSSE()"]
+ J --> K["Client receives\ntranslated SSE"]
+ K --> L["logUsage()\nsaveRequestUsage()"]
+```
+
+### Non-Streaming Request
+
+```mermaid
+flowchart LR
+ A["Client"] --> B["detectFormat()"]
+ B --> C["translateRequest()\nsource → OpenAI → target"]
+ C --> D["Executor.execute()"]
+ D --> E["translateResponse()\ntarget → OpenAI → source"]
+ E --> F["Return JSON\nresponse"]
+```
+
+### Bypass Flow (Claude CLI)
+
+```mermaid
+flowchart LR
+ A["Claude CLI request"] --> B{"Match bypass\npattern?"}
+ B -->|"Title/Warmup/Count"| C["Generate fake\nOpenAI response"]
+ B -->|"No match"| D["Normal flow"]
+ C --> E["Translate to\nsource format"]
+ E --> F["Return without\ncalling provider"]
+```
diff --git a/docs/i18n/id/docs/COVERAGE_PLAN.md b/docs/i18n/id/docs/COVERAGE_PLAN.md
new file mode 100644
index 0000000000..bf1879e447
--- /dev/null
+++ b/docs/i18n/id/docs/COVERAGE_PLAN.md
@@ -0,0 +1,170 @@
+# Test Coverage Plan (Bahasa Indonesia)
+
+🌐 **Languages:** 🇺🇸 [English](../../../../docs/COVERAGE_PLAN.md) · 🇪🇸 [es](../../es/docs/COVERAGE_PLAN.md) · 🇫🇷 [fr](../../fr/docs/COVERAGE_PLAN.md) · 🇩🇪 [de](../../de/docs/COVERAGE_PLAN.md) · 🇮🇹 [it](../../it/docs/COVERAGE_PLAN.md) · 🇷🇺 [ru](../../ru/docs/COVERAGE_PLAN.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/COVERAGE_PLAN.md) · 🇯🇵 [ja](../../ja/docs/COVERAGE_PLAN.md) · 🇰🇷 [ko](../../ko/docs/COVERAGE_PLAN.md) · 🇸🇦 [ar](../../ar/docs/COVERAGE_PLAN.md) · 🇮🇳 [in](../../in/docs/COVERAGE_PLAN.md) · 🇹🇭 [th](../../th/docs/COVERAGE_PLAN.md) · 🇻🇳 [vi](../../vi/docs/COVERAGE_PLAN.md) · 🇮🇩 [id](../../id/docs/COVERAGE_PLAN.md) · 🇲🇾 [ms](../../ms/docs/COVERAGE_PLAN.md) · 🇳🇱 [nl](../../nl/docs/COVERAGE_PLAN.md) · 🇵🇱 [pl](../../pl/docs/COVERAGE_PLAN.md) · 🇸🇪 [sv](../../sv/docs/COVERAGE_PLAN.md) · 🇳🇴 [no](../../no/docs/COVERAGE_PLAN.md) · 🇩🇰 [da](../../da/docs/COVERAGE_PLAN.md) · 🇫🇮 [fi](../../fi/docs/COVERAGE_PLAN.md) · 🇵🇹 [pt](../../pt/docs/COVERAGE_PLAN.md) · 🇷🇴 [ro](../../ro/docs/COVERAGE_PLAN.md) · 🇭🇺 [hu](../../hu/docs/COVERAGE_PLAN.md) · 🇧🇬 [bg](../../bg/docs/COVERAGE_PLAN.md) · 🇸🇰 [sk](../../sk/docs/COVERAGE_PLAN.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/COVERAGE_PLAN.md) · 🇮🇱 [he](../../he/docs/COVERAGE_PLAN.md) · 🇵🇭 [phi](../../phi/docs/COVERAGE_PLAN.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/COVERAGE_PLAN.md) · 🇨🇿 [cs](../../cs/docs/COVERAGE_PLAN.md)
+
+---
+
+Last updated: 2026-03-28
+
+## Baseline
+
+There are multiple coverage numbers depending on how the report is computed. For planning, only one of them is useful.
+
+| Metric | Scope | Statements / Lines | Branches | Functions | Notes |
+| -------------------- | ----------------------------------------------------- | -----------------: | -------: | --------: | --------------------------------------------------- |
+| Legacy | Old `npm run test:coverage` | 79.42% | 75.15% | 67.94% | Inflated: counts test files and excludes `open-sse` |
+| Diagnostic | Source-only, excluding tests and excluding `open-sse` | 68.16% | 63.55% | 64.06% | Useful only to isolate `src/**` |
+| Recommended baseline | Source-only, excluding tests and including `open-sse` | 56.95% | 66.05% | 57.80% | This is the project-wide baseline to improve |
+
+The recommended baseline is the number to optimize against.
+
+## Rules
+
+- Coverage targets apply to source files, not to `tests/**`.
+- `open-sse/**` is part of the product and must remain in scope.
+- New code should not reduce coverage in touched areas.
+- Prefer testing behavior and branch outcomes over implementation details.
+- Prefer temp SQLite databases and small fixtures over broad mocks for `src/lib/db/**`.
+
+## Current command set
+
+- `npm run test:coverage`
+ - Main source coverage gate for the unit test suite
+ - Generates `text-summary`, `html`, `json-summary`, and `lcov`
+- `npm run coverage:report`
+ - Detailed file-by-file report from the latest run
+- `npm run test:coverage:legacy`
+ - Historical comparison only
+
+## Milestones
+
+| Phase | Target | Focus |
+| ------- | ---------------------: | ------------------------------------------------- |
+| Phase 1 | 60% statements / lines | Quick wins and low-risk utility coverage |
+| Phase 2 | 65% statements / lines | DB and route foundations |
+| Phase 3 | 70% statements / lines | Provider validation and usage analytics |
+| Phase 4 | 75% statements / lines | `open-sse` translators and helpers |
+| Phase 5 | 80% statements / lines | `open-sse` handlers and executor branches |
+| Phase 6 | 85% statements / lines | Harder edge cases, branch debt, regression suites |
+| Phase 7 | 90% statements / lines | Final sweep, gap closure, strict ratchet |
+
+Branches and functions should ratchet upward with each phase, but the primary hard target is statements / lines.
+
+## Priority hotspots
+
+These files or areas offer the best return for the next phases:
+
+1. `open-sse/handlers`
+ - `chatCore.ts` at 7.57%
+ - Overall directory at 29.07%
+2. `open-sse/translator/request`
+ - Overall directory at 36.39%
+ - Many translators are still near single-digit coverage
+3. `open-sse/translator/response`
+ - Overall directory at 8.07%
+4. `open-sse/executors`
+ - Overall directory at 36.62%
+5. `src/lib/db`
+ - `models.ts` at 20.66%
+ - `registeredKeys.ts` at 34.46%
+ - `modelComboMappings.ts` at 36.25%
+ - `settings.ts` at 46.40%
+ - `webhooks.ts` at 33.33%
+6. `src/lib/usage`
+ - `usageHistory.ts` at 21.12%
+ - `usageStats.ts` at 9.56%
+ - `costCalculator.ts` at 30.00%
+7. `src/lib/providers`
+ - `validation.ts` at 41.16%
+8. Low-risk utility and API files for early gains
+ - `src/shared/utils/upstreamError.ts`
+ - `src/shared/utils/apiAuth.ts`
+ - `src/lib/api/errorResponse.ts`
+ - `src/app/api/settings/require-login/route.ts`
+ - `src/app/api/providers/[id]/models/route.ts`
+
+## Execution checklist
+
+### Phase 1: 56.95% -> 60%
+
+- [x] Fix coverage metric so it reflects source code instead of test files
+- [x] Keep a legacy coverage script for comparison
+- [x] Record the baseline and hotspots in-repo
+- [ ] Add focused tests for low-risk utilities:
+ - `src/shared/utils/upstreamError.ts`
+ - `src/shared/utils/fetchTimeout.ts`
+ - `src/lib/api/errorResponse.ts`
+ - `src/shared/utils/apiAuth.ts`
+ - `src/lib/display/names.ts`
+- [ ] Add route tests for:
+ - `src/app/api/settings/require-login/route.ts`
+ - `src/app/api/providers/[id]/models/route.ts`
+
+### Phase 2: 60% -> 65%
+
+- [ ] Add DB-backed tests for:
+ - `src/lib/db/modelComboMappings.ts`
+ - `src/lib/db/settings.ts`
+ - `src/lib/db/registeredKeys.ts`
+- [ ] Cover branch behavior in:
+ - `src/lib/providers/validation.ts`
+ - `src/app/api/v1/embeddings/route.ts`
+ - `src/app/api/v1/moderations/route.ts`
+
+### Phase 3: 65% -> 70%
+
+- [ ] Add usage analytics tests for:
+ - `src/lib/usage/usageHistory.ts`
+ - `src/lib/usage/usageStats.ts`
+ - `src/lib/usage/costCalculator.ts`
+- [ ] Expand route coverage for proxy management and settings branches
+
+### Phase 4: 70% -> 75%
+
+- [ ] Cover translator helpers and central translation paths:
+ - `open-sse/translator/index.ts`
+ - `open-sse/translator/helpers/*`
+ - `open-sse/translator/request/*`
+ - `open-sse/translator/response/*`
+
+### Phase 5: 75% -> 80%
+
+- [ ] Add handler-level tests for:
+ - `open-sse/handlers/chatCore.ts`
+ - `open-sse/handlers/responsesHandler.js`
+ - `open-sse/handlers/imageGeneration.js`
+ - `open-sse/handlers/embeddings.js`
+- [ ] Add executor branch coverage for provider-specific auth, retries, and endpoint overrides
+
+### Phase 6: 80% -> 85%
+
+- [ ] Merge more edge-case suites into the main coverage path
+- [ ] Increase function coverage for DB modules with weak constructor/helper coverage
+- [ ] Close branch gaps in `settings.ts`, `registeredKeys.ts`, `validation.ts`, and translator helpers
+
+### Phase 7: 85% -> 90%
+
+- [ ] Treat the remaining low-coverage files as blockers
+- [ ] Add regression tests for every uncovered production bug fixed during the push to 90%
+- [ ] Raise the coverage gate in CI only after the local baseline is stable for at least two consecutive runs
+
+## Ratchet policy
+
+Update `npm run test:coverage` thresholds only after the project actually exceeds the next milestone with a comfortable buffer.
+
+Recommended ratchet sequence:
+
+1. 55/60/55
+2. 60/62/58
+3. 65/64/62
+4. 70/66/66
+5. 75/70/72
+6. 80/75/78
+7. 85/80/84
+8. 90/85/88
+
+Order is `statements-lines / branches / functions`.
+
+## Known gap
+
+The current coverage command measures the main Node unit suite and includes source reached from it, including `open-sse`. It does not yet merge Vitest coverage into a single unified report. That merge is worth doing later, but it is not a blocker for starting the 60% -> 80% climb.
diff --git a/docs/i18n/id/docs/FEATURES.md b/docs/i18n/id/docs/FEATURES.md
index e8d75290d9..a64cb87fa3 100644
--- a/docs/i18n/id/docs/FEATURES.md
+++ b/docs/i18n/id/docs/FEATURES.md
@@ -1,6 +1,6 @@
# OmniRoute — Dashboard Features Gallery (Bahasa Indonesia)
-🌐 **Languages:** 🇺🇸 [English](../../../../docs/FEATURES.md) · 🇪🇸 [es](../../es/docs/FEATURES.md) · 🇫🇷 [fr](../../fr/docs/FEATURES.md) · 🇩🇪 [de](../../de/docs/FEATURES.md) · 🇮🇹 [it](../../it/docs/FEATURES.md) · 🇷🇺 [ru](../../ru/docs/FEATURES.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/FEATURES.md) · 🇯🇵 [ja](../../ja/docs/FEATURES.md) · 🇰🇷 [ko](../../ko/docs/FEATURES.md) · 🇸🇦 [ar](../../ar/docs/FEATURES.md) · 🇮🇳 [in](../../in/docs/FEATURES.md) · 🇹🇭 [th](../../th/docs/FEATURES.md) · 🇻🇳 [vi](../../vi/docs/FEATURES.md) · 🇮🇩 [id](../../id/docs/FEATURES.md) · 🇲🇾 [ms](../../ms/docs/FEATURES.md) · 🇳🇱 [nl](../../nl/docs/FEATURES.md) · 🇵🇱 [pl](../../pl/docs/FEATURES.md) · 🇸🇪 [sv](../../sv/docs/FEATURES.md) · 🇳🇴 [no](../../no/docs/FEATURES.md) · 🇩🇰 [da](../../da/docs/FEATURES.md) · 🇫🇮 [fi](../../fi/docs/FEATURES.md) · 🇵🇹 [pt](../../pt/docs/FEATURES.md) · 🇷🇴 [ro](../../ro/docs/FEATURES.md) · 🇭🇺 [hu](../../hu/docs/FEATURES.md) · 🇧🇬 [bg](../../bg/docs/FEATURES.md) · 🇸🇰 [sk](../../sk/docs/FEATURES.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/FEATURES.md) · 🇮🇱 [he](../../he/docs/FEATURES.md) · 🇵🇭 [phi](../../phi/docs/FEATURES.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/FEATURES.md)
+🌐 **Languages:** 🇺🇸 [English](../../../../docs/FEATURES.md) · 🇪🇸 [es](../../es/docs/FEATURES.md) · 🇫🇷 [fr](../../fr/docs/FEATURES.md) · 🇩🇪 [de](../../de/docs/FEATURES.md) · 🇮🇹 [it](../../it/docs/FEATURES.md) · 🇷🇺 [ru](../../ru/docs/FEATURES.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/FEATURES.md) · 🇯🇵 [ja](../../ja/docs/FEATURES.md) · 🇰🇷 [ko](../../ko/docs/FEATURES.md) · 🇸🇦 [ar](../../ar/docs/FEATURES.md) · 🇮🇳 [in](../../in/docs/FEATURES.md) · 🇹🇭 [th](../../th/docs/FEATURES.md) · 🇻🇳 [vi](../../vi/docs/FEATURES.md) · 🇮🇩 [id](../../id/docs/FEATURES.md) · 🇲🇾 [ms](../../ms/docs/FEATURES.md) · 🇳🇱 [nl](../../nl/docs/FEATURES.md) · 🇵🇱 [pl](../../pl/docs/FEATURES.md) · 🇸🇪 [sv](../../sv/docs/FEATURES.md) · 🇳🇴 [no](../../no/docs/FEATURES.md) · 🇩🇰 [da](../../da/docs/FEATURES.md) · 🇫🇮 [fi](../../fi/docs/FEATURES.md) · 🇵🇹 [pt](../../pt/docs/FEATURES.md) · 🇷🇴 [ro](../../ro/docs/FEATURES.md) · 🇭🇺 [hu](../../hu/docs/FEATURES.md) · 🇧🇬 [bg](../../bg/docs/FEATURES.md) · 🇸🇰 [sk](../../sk/docs/FEATURES.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/FEATURES.md) · 🇮🇱 [he](../../he/docs/FEATURES.md) · 🇵🇭 [phi](../../phi/docs/FEATURES.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/FEATURES.md) · 🇨🇿 [cs](../../cs/docs/FEATURES.md)
---
@@ -10,7 +10,7 @@ Visual guide to every section of the OmniRoute dashboard.
## 🔌 Providers
-Manage AI provider connections: OAuth providers (Claude Code, Codex, Gemini CLI), API key providers (Groq, DeepSeek, OpenRouter), and free providers (iFlow, Qwen, Kiro). Kiro accounts include credit balance tracking — remaining credits, total allowance, and renewal date visible in Dashboard → Usage.
+Manage AI provider connections: OAuth providers (Claude Code, Codex, Gemini CLI), API key providers (Groq, DeepSeek, OpenRouter), and free providers (Qoder, Qwen, Kiro). Kiro accounts include credit balance tracking — remaining credits, total allowance, and renewal date visible in Dashboard → Usage.

diff --git a/docs/i18n/id/docs/MCP-SERVER.md b/docs/i18n/id/docs/MCP-SERVER.md
new file mode 100644
index 0000000000..e4f6380858
--- /dev/null
+++ b/docs/i18n/id/docs/MCP-SERVER.md
@@ -0,0 +1,87 @@
+# OmniRoute MCP Server Documentation (Bahasa Indonesia)
+
+🌐 **Languages:** 🇺🇸 [English](../../../../docs/MCP-SERVER.md) · 🇪🇸 [es](../../es/docs/MCP-SERVER.md) · 🇫🇷 [fr](../../fr/docs/MCP-SERVER.md) · 🇩🇪 [de](../../de/docs/MCP-SERVER.md) · 🇮🇹 [it](../../it/docs/MCP-SERVER.md) · 🇷🇺 [ru](../../ru/docs/MCP-SERVER.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/MCP-SERVER.md) · 🇯🇵 [ja](../../ja/docs/MCP-SERVER.md) · 🇰🇷 [ko](../../ko/docs/MCP-SERVER.md) · 🇸🇦 [ar](../../ar/docs/MCP-SERVER.md) · 🇮🇳 [in](../../in/docs/MCP-SERVER.md) · 🇹🇭 [th](../../th/docs/MCP-SERVER.md) · 🇻🇳 [vi](../../vi/docs/MCP-SERVER.md) · 🇮🇩 [id](../../id/docs/MCP-SERVER.md) · 🇲🇾 [ms](../../ms/docs/MCP-SERVER.md) · 🇳🇱 [nl](../../nl/docs/MCP-SERVER.md) · 🇵🇱 [pl](../../pl/docs/MCP-SERVER.md) · 🇸🇪 [sv](../../sv/docs/MCP-SERVER.md) · 🇳🇴 [no](../../no/docs/MCP-SERVER.md) · 🇩🇰 [da](../../da/docs/MCP-SERVER.md) · 🇫🇮 [fi](../../fi/docs/MCP-SERVER.md) · 🇵🇹 [pt](../../pt/docs/MCP-SERVER.md) · 🇷🇴 [ro](../../ro/docs/MCP-SERVER.md) · 🇭🇺 [hu](../../hu/docs/MCP-SERVER.md) · 🇧🇬 [bg](../../bg/docs/MCP-SERVER.md) · 🇸🇰 [sk](../../sk/docs/MCP-SERVER.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/MCP-SERVER.md) · 🇮🇱 [he](../../he/docs/MCP-SERVER.md) · 🇵🇭 [phi](../../phi/docs/MCP-SERVER.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/MCP-SERVER.md) · 🇨🇿 [cs](../../cs/docs/MCP-SERVER.md)
+
+---
+
+> Model Context Protocol server with 16 intelligent tools
+
+## Instal
+
+OmniRoute MCP is built-in. Start it with:
+
+```bash
+omniroute --mcp
+```
+
+Or via the open-sse transport:
+
+```bash
+# HTTP streamable transport (port 20130)
+omniroute --dev # MCP auto-starts on /mcp endpoint
+```
+
+## IDE Configuration
+
+See [IDE Configs](integrations/ide-configs.md) for Antigravity, Cursor, Copilot, and Claude Desktop setup.
+
+---
+
+## Essential Tools (8)
+
+| Tool | Description |
+| :------------------------------ | :--------------------------------------- |
+| `omniroute_get_health` | Gateway health, circuit breakers, uptime |
+| `omniroute_list_combos` | All configured combos with models |
+| `omniroute_get_combo_metrics` | Performance metrics for a specific combo |
+| `omniroute_switch_combo` | Switch active combo by ID/name |
+| `omniroute_check_quota` | Quota status per provider or all |
+| `omniroute_route_request` | Send a chat completion through OmniRoute |
+| `omniroute_cost_report` | Cost analytics for a time period |
+| `omniroute_list_models_catalog` | Full model catalog with capabilities |
+
+## Advanced Tools (8)
+
+| Tool | Description |
+| :--------------------------------- | :---------------------------------------------------------- |
+| `omniroute_simulate_route` | Dry-run routing simulation with fallback tree |
+| `omniroute_set_budget_guard` | Session budget with degrade/block/alert actions |
+| `omniroute_set_resilience_profile` | Apply conservative/balanced/aggressive preset |
+| `omniroute_test_combo` | Live-test all models in a combo via a real upstream request |
+| `omniroute_get_provider_metrics` | Detailed metrics for one provider |
+| `omniroute_best_combo_for_task` | Task-fitness recommendation with alternatives |
+| `omniroute_explain_route` | Explain a past routing decision |
+| `omniroute_get_session_snapshot` | Full session state: costs, tokens, errors |
+
+## Authentication
+
+MCP tools are authenticated via API key scopes. Each tool requires specific scopes:
+
+| Scope | Tools |
+| :------------- | :----------------------------------------------- |
+| `read:health` | get_health, get_provider_metrics |
+| `read:combos` | list_combos, get_combo_metrics |
+| `write:combos` | switch_combo |
+| `read:quota` | check_quota |
+| `write:route` | route_request, simulate_route, test_combo |
+| `read:usage` | cost_report, get_session_snapshot, explain_route |
+| `write:config` | set_budget_guard, set_resilience_profile |
+| `read:models` | list_models_catalog, best_combo_for_task |
+
+## Audit Logging
+
+Every tool call is logged to `mcp_tool_audit` with:
+
+- Tool name, arguments, result
+- Duration (ms), success/failure
+- API key hash, timestamp
+
+## Files
+
+| File | Purpose |
+| :------------------------------------------- | :------------------------------------------ |
+| `open-sse/mcp-server/server.ts` | MCP server creation + 16 tool registrations |
+| `open-sse/mcp-server/transport.ts` | Stdio + HTTP transport |
+| `open-sse/mcp-server/auth.ts` | API key + scope validation |
+| `open-sse/mcp-server/audit.ts` | Tool call audit logging |
+| `open-sse/mcp-server/tools/advancedTools.ts` | 8 advanced tool handlers |
diff --git a/docs/i18n/id/docs/RELEASE_CHECKLIST.md b/docs/i18n/id/docs/RELEASE_CHECKLIST.md
new file mode 100644
index 0000000000..93b8734624
--- /dev/null
+++ b/docs/i18n/id/docs/RELEASE_CHECKLIST.md
@@ -0,0 +1,37 @@
+# Release Checklist (Bahasa Indonesia)
+
+🌐 **Languages:** 🇺🇸 [English](../../../../docs/RELEASE_CHECKLIST.md) · 🇪🇸 [es](../../es/docs/RELEASE_CHECKLIST.md) · 🇫🇷 [fr](../../fr/docs/RELEASE_CHECKLIST.md) · 🇩🇪 [de](../../de/docs/RELEASE_CHECKLIST.md) · 🇮🇹 [it](../../it/docs/RELEASE_CHECKLIST.md) · 🇷🇺 [ru](../../ru/docs/RELEASE_CHECKLIST.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/RELEASE_CHECKLIST.md) · 🇯🇵 [ja](../../ja/docs/RELEASE_CHECKLIST.md) · 🇰🇷 [ko](../../ko/docs/RELEASE_CHECKLIST.md) · 🇸🇦 [ar](../../ar/docs/RELEASE_CHECKLIST.md) · 🇮🇳 [in](../../in/docs/RELEASE_CHECKLIST.md) · 🇹🇭 [th](../../th/docs/RELEASE_CHECKLIST.md) · 🇻🇳 [vi](../../vi/docs/RELEASE_CHECKLIST.md) · 🇮🇩 [id](../../id/docs/RELEASE_CHECKLIST.md) · 🇲🇾 [ms](../../ms/docs/RELEASE_CHECKLIST.md) · 🇳🇱 [nl](../../nl/docs/RELEASE_CHECKLIST.md) · 🇵🇱 [pl](../../pl/docs/RELEASE_CHECKLIST.md) · 🇸🇪 [sv](../../sv/docs/RELEASE_CHECKLIST.md) · 🇳🇴 [no](../../no/docs/RELEASE_CHECKLIST.md) · 🇩🇰 [da](../../da/docs/RELEASE_CHECKLIST.md) · 🇫🇮 [fi](../../fi/docs/RELEASE_CHECKLIST.md) · 🇵🇹 [pt](../../pt/docs/RELEASE_CHECKLIST.md) · 🇷🇴 [ro](../../ro/docs/RELEASE_CHECKLIST.md) · 🇭🇺 [hu](../../hu/docs/RELEASE_CHECKLIST.md) · 🇧🇬 [bg](../../bg/docs/RELEASE_CHECKLIST.md) · 🇸🇰 [sk](../../sk/docs/RELEASE_CHECKLIST.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/RELEASE_CHECKLIST.md) · 🇮🇱 [he](../../he/docs/RELEASE_CHECKLIST.md) · 🇵🇭 [phi](../../phi/docs/RELEASE_CHECKLIST.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/RELEASE_CHECKLIST.md) · 🇨🇿 [cs](../../cs/docs/RELEASE_CHECKLIST.md)
+
+---
+
+Use this checklist before tagging or publishing a new OmniRoute release.
+
+## Version and Changelog
+
+1. Bump `package.json` version (`x.y.z`) in the release branch.
+2. Move release notes from `## [Unreleased]` in `CHANGELOG.md` to a dated section:
+ - `## [x.y.z] — YYYY-MM-DD`
+3. Keep `## [Unreleased]` as the first changelog section for upcoming work.
+4. Ensure the latest semver section in `CHANGELOG.md` equals `package.json` version.
+
+## API Docs
+
+1. Update `docs/openapi.yaml`:
+ - `info.version` must equal `package.json` version.
+2. Validate endpoint examples if API contracts changed.
+
+## Runtime Docs
+
+1. Review `docs/ARCHITECTURE.md` for storage/runtime drift.
+2. Review `docs/TROUBLESHOOTING.md` for env var and operational drift.
+3. Update localized docs if source docs changed significantly.
+
+## Automated Check
+
+Run the sync guard locally before opening PR:
+
+```bash
+npm run check:docs-sync
+```
+
+CI also runs this check in `.github/workflows/ci.yml` (lint job).
diff --git a/docs/i18n/id/docs/TROUBLESHOOTING.md b/docs/i18n/id/docs/TROUBLESHOOTING.md
new file mode 100644
index 0000000000..9589c02040
--- /dev/null
+++ b/docs/i18n/id/docs/TROUBLESHOOTING.md
@@ -0,0 +1,256 @@
+# Troubleshooting (Bahasa Indonesia)
+
+🌐 **Languages:** 🇺🇸 [English](../../../../docs/TROUBLESHOOTING.md) · 🇪🇸 [es](../../es/docs/TROUBLESHOOTING.md) · 🇫🇷 [fr](../../fr/docs/TROUBLESHOOTING.md) · 🇩🇪 [de](../../de/docs/TROUBLESHOOTING.md) · 🇮🇹 [it](../../it/docs/TROUBLESHOOTING.md) · 🇷🇺 [ru](../../ru/docs/TROUBLESHOOTING.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/TROUBLESHOOTING.md) · 🇯🇵 [ja](../../ja/docs/TROUBLESHOOTING.md) · 🇰🇷 [ko](../../ko/docs/TROUBLESHOOTING.md) · 🇸🇦 [ar](../../ar/docs/TROUBLESHOOTING.md) · 🇮🇳 [in](../../in/docs/TROUBLESHOOTING.md) · 🇹🇭 [th](../../th/docs/TROUBLESHOOTING.md) · 🇻🇳 [vi](../../vi/docs/TROUBLESHOOTING.md) · 🇮🇩 [id](../../id/docs/TROUBLESHOOTING.md) · 🇲🇾 [ms](../../ms/docs/TROUBLESHOOTING.md) · 🇳🇱 [nl](../../nl/docs/TROUBLESHOOTING.md) · 🇵🇱 [pl](../../pl/docs/TROUBLESHOOTING.md) · 🇸🇪 [sv](../../sv/docs/TROUBLESHOOTING.md) · 🇳🇴 [no](../../no/docs/TROUBLESHOOTING.md) · 🇩🇰 [da](../../da/docs/TROUBLESHOOTING.md) · 🇫🇮 [fi](../../fi/docs/TROUBLESHOOTING.md) · 🇵🇹 [pt](../../pt/docs/TROUBLESHOOTING.md) · 🇷🇴 [ro](../../ro/docs/TROUBLESHOOTING.md) · 🇭🇺 [hu](../../hu/docs/TROUBLESHOOTING.md) · 🇧🇬 [bg](../../bg/docs/TROUBLESHOOTING.md) · 🇸🇰 [sk](../../sk/docs/TROUBLESHOOTING.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/TROUBLESHOOTING.md) · 🇮🇱 [he](../../he/docs/TROUBLESHOOTING.md) · 🇵🇭 [phi](../../phi/docs/TROUBLESHOOTING.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/TROUBLESHOOTING.md) · 🇨🇿 [cs](../../cs/docs/TROUBLESHOOTING.md)
+
+---
+
+Common problems and solutions for OmniRoute.
+
+---
+
+## Quick Fixes
+
+| Problem | Solution |
+| ----------------------------- | ------------------------------------------------------------------ |
+| First login not working | Set `INITIAL_PASSWORD` in `.env` (no hardcoded default) |
+| Dashboard opens on wrong port | Set `PORT=20128` and `NEXT_PUBLIC_BASE_URL=http://localhost:20128` |
+| No request logs under `logs/` | Set `ENABLE_REQUEST_LOGS=true` |
+| EACCES: permission denied | Set `DATA_DIR=/path/to/writable/dir` to override `~/.omniroute` |
+| Routing strategy not saving | Update to v1.4.11+ (Zod schema fix for settings persistence) |
+
+---
+
+## Provider Issues
+
+### "Language model did not provide messages"
+
+**Cause:** Provider quota exhausted.
+
+**Fix:**
+
+1. Check dashboard quota tracker
+2. Use a combo with fallback tiers
+3. Switch to cheaper/free tier
+
+### Rate Limiting
+
+**Cause:** Subscription quota exhausted.
+
+**Fix:**
+
+- Add fallback: `cc/claude-opus-4-6 → glm/glm-4.7 → if/kimi-k2-thinking`
+- Use GLM/MiniMax as cheap backup
+
+### OAuth Token Expired
+
+OmniRoute auto-refreshes tokens. If issues persist:
+
+1. Dashboard → Provider → Reconnect
+2. Delete and re-add the provider connection
+
+---
+
+## Cloud Issues
+
+### Cloud Sync Errors
+
+1. Verify `BASE_URL` points to your running instance (e.g., `http://localhost:20128`)
+2. Verify `CLOUD_URL` points to your cloud endpoint (e.g., `https://omniroute.dev`)
+3. Keep `NEXT_PUBLIC_*` values aligned with server-side values
+
+### Cloud `stream=false` Returns 500
+
+**Symptom:** `Unexpected token 'd'...` on cloud endpoint for non-streaming calls.
+
+**Cause:** Upstream returns SSE payload while client expects JSON.
+
+**Workaround:** Use `stream=true` for cloud direct calls. Local runtime includes SSE→JSON fallback.
+
+### Cloud Says Connected but "Invalid API key"
+
+1. Create a fresh key from local dashboard (`/api/keys`)
+2. Run cloud sync: Enable Cloud → Sync Now
+3. Old/non-synced keys can still return `401` on cloud
+
+---
+
+## Docker Issues
+
+### CLI Tool Shows Not Installed
+
+1. Check runtime fields: `curl http://localhost:20128/api/cli-tools/runtime/codex | jq`
+2. For portable mode: use image target `runner-cli` (bundled CLIs)
+3. For host mount mode: set `CLI_EXTRA_PATHS` and mount host bin directory as read-only
+4. If `installed=true` and `runnable=false`: binary was found but failed healthcheck
+
+### Quick Runtime Validation
+
+```bash
+curl -s http://localhost:20128/api/cli-tools/codex-settings | jq '{installed,runnable,commandPath,runtimeMode,reason}'
+curl -s http://localhost:20128/api/cli-tools/claude-settings | jq '{installed,runnable,commandPath,runtimeMode,reason}'
+curl -s http://localhost:20128/api/cli-tools/openclaw-settings | jq '{installed,runnable,commandPath,runtimeMode,reason}'
+```
+
+---
+
+## Cost Issues
+
+### High Costs
+
+1. Check usage stats in Dashboard → Usage
+2. Switch primary model to GLM/MiniMax
+3. Use free tier (Gemini CLI, Qoder) for non-critical tasks
+4. Set cost budgets per API key: Dashboard → API Keys → Budget
+
+---
+
+## Debugging
+
+### Enable Request Logs
+
+Set `ENABLE_REQUEST_LOGS=true` in your `.env` file. Logs appear under `logs/` directory.
+
+### Check Provider Health
+
+```bash
+# Health dashboard
+http://localhost:20128/dashboard/health
+
+# API health check
+curl http://localhost:20128/api/monitoring/health
+```
+
+### Runtime Storage
+
+- Main state: `${DATA_DIR}/storage.sqlite` (providers, combos, aliases, keys, settings)
+- Usage: SQLite tables in `storage.sqlite` (`usage_history`, `call_logs`, `proxy_logs`) + optional `${DATA_DIR}/log.txt` and `${DATA_DIR}/call_logs/`
+- Request logs: `/logs/...` (when `ENABLE_REQUEST_LOGS=true`)
+
+---
+
+## Circuit Breaker Issues
+
+### Provider stuck in OPEN state
+
+When a provider's circuit breaker is OPEN, requests are blocked until the cooldown expires.
+
+**Fix:**
+
+1. Go to **Dashboard → Settings → Resilience**
+2. Check the circuit breaker card for the affected provider
+3. Click **Reset All** to clear all breakers, or wait for the cooldown to expire
+4. Verify the provider is actually available before resetting
+
+### Provider keeps tripping the circuit breaker
+
+If a provider repeatedly enters OPEN state:
+
+1. Check **Dashboard → Health → Provider Health** for the failure pattern
+2. Go to **Settings → Resilience → Provider Profiles** and increase the failure threshold
+3. Check if the provider has changed API limits or requires re-authentication
+4. Review latency telemetry — high latency may cause timeout-based failures
+
+---
+
+## Audio Transcription Issues
+
+### "Unsupported model" error
+
+- Ensure you're using the correct prefix: `deepgram/nova-3` or `assemblyai/best`
+- Verify the provider is connected in **Dashboard → Providers**
+
+### Transcription returns empty or fails
+
+- Check supported audio formats: `mp3`, `wav`, `m4a`, `flac`, `ogg`, `webm`
+- Verify file size is within provider limits (typically < 25MB)
+- Check provider API key validity in the provider card
+
+---
+
+## Translator Debugging
+
+Use **Dashboard → Translator** to debug format translation issues:
+
+| Mode | When to Use |
+| ---------------- | -------------------------------------------------------------------------------------------- |
+| **Playground** | Compare input/output formats side by side — paste a failing request to see how it translates |
+| **Chat Tester** | Send live messages and inspect the full request/response payload including headers |
+| **Test Bench** | Run batch tests across format combinations to find which translations are broken |
+| **Live Monitor** | Watch real-time request flow to catch intermittent translation issues |
+
+### Common format issues
+
+- **Thinking tags not appearing** — Check if the target provider supports thinking and the thinking budget setting
+- **Tool calls dropping** — Some format translations may strip unsupported fields; verify in Playground mode
+- **System prompt missing** — Claude and Gemini handle system prompts differently; check translation output
+- **SDK returns raw string instead of object** — Fixed in v1.1.0: response sanitizer now strips non-standard fields (`x_groq`, `usage_breakdown`, etc.) that cause OpenAI SDK Pydantic validation failures
+- **GLM/ERNIE rejects `system` role** — Fixed in v1.1.0: role normalizer automatically merges system messages into user messages for incompatible models
+- **`developer` role not recognized** — Fixed in v1.1.0: automatically converted to `system` for non-OpenAI providers
+- **`json_schema` not working with Gemini** — Fixed in v1.1.0: `response_format` is now converted to Gemini's `responseMimeType` + `responseSchema`
+
+---
+
+## Resilience Settings
+
+### Auto rate-limit not triggering
+
+- Auto rate-limit only applies to API key providers (not OAuth/subscription)
+- Verify **Settings → Resilience → Provider Profiles** has auto-rate-limit enabled
+- Check if the provider returns `429` status codes or `Retry-After` headers
+
+### Tuning exponential backoff
+
+Provider profiles support these settings:
+
+- **Base delay** — Initial wait time after first failure (default: 1s)
+- **Max delay** — Maximum wait time cap (default: 30s)
+- **Multiplier** — How much to increase delay per consecutive failure (default: 2x)
+
+### Anti-thundering herd
+
+When many concurrent requests hit a rate-limited provider, OmniRoute uses mutex + auto rate-limiting to serialize requests and prevent cascading failures. This is automatic for API key providers.
+
+---
+
+## Optional RAG / LLM failure taxonomy (16 problems)
+
+Some OmniRoute users place the gateway in front of RAG or agent stacks. In those setups it is common to see a strange pattern: OmniRoute looks healthy (providers up, routing profiles ok, no rate limit alerts) but the final answer is still wrong.
+
+In practice these incidents usually come from the downstream RAG pipeline, not from the gateway itself.
+
+If you want a shared vocabulary to describe those failures you can use the WFGY ProblemMap, an external MIT license text resource that defines sixteen recurring RAG / LLM failure patterns. At a high level it covers:
+
+- retrieval drift and broken context boundaries
+- empty or stale indexes and vector stores
+- embedding versus semantic mismatch
+- prompt assembly and context window issues
+- logic collapse and overconfident answers
+- long chain and agent coordination failures
+- multi agent memory and role drift
+- deployment and bootstrap ordering problems
+
+The idea is simple:
+
+1. When you investigate a bad response, capture:
+ - user task and request
+ - route or provider combo in OmniRoute
+ - any RAG context used downstream (retrieved documents, tool calls, etc)
+2. Map the incident to one or two WFGY ProblemMap numbers (`No.1` … `No.16`).
+3. Store the number in your own dashboard, runbook, or incident tracker next to the OmniRoute logs.
+4. Use the corresponding WFGY page to decide whether you need to change your RAG stack, retriever, or routing strategy.
+
+Full text and concrete recipes live here (MIT license, text only):
+
+[WFGY ProblemMap README](https://github.com/onestardao/WFGY/blob/main/ProblemMap/README.md)
+
+You can ignore this section if you do not run RAG or agent pipelines behind OmniRoute.
+
+---
+
+## Still Stuck?
+
+- **GitHub Issues**: [github.com/diegosouzapw/OmniRoute/issues](https://github.com/diegosouzapw/OmniRoute/issues)
+- **Architecture**: See [`docs/ARCHITECTURE.md`](ARCHITECTURE.md) for internal details
+- **API Reference**: See [`docs/API_REFERENCE.md`](API_REFERENCE.md) for all endpoints
+- **Health Dashboard**: Check **Dashboard → Health** for real-time system status
+- **Translator**: Use **Dashboard → Translator** to debug format issues
diff --git a/docs/i18n/id/USER_GUIDE.md b/docs/i18n/id/docs/USER_GUIDE.md
similarity index 82%
rename from docs/i18n/id/USER_GUIDE.md
rename to docs/i18n/id/docs/USER_GUIDE.md
index 0814b5ba82..c30d2ac6ed 100644
--- a/docs/i18n/id/USER_GUIDE.md
+++ b/docs/i18n/id/docs/USER_GUIDE.md
@@ -1,8 +1,6 @@
# User Guide (Bahasa Indonesia)
-🌐 **Languages:** 🇺🇸 [English](../../USER_GUIDE.md) · 🇧🇷 [pt-BR](../pt-BR/USER_GUIDE.md) · 🇪🇸 [es](../es/USER_GUIDE.md) · 🇫🇷 [fr](../fr/USER_GUIDE.md) · 🇩🇪 [de](../de/USER_GUIDE.md) · 🇮🇹 [it](../it/USER_GUIDE.md) · 🇷🇺 [ru](../ru/USER_GUIDE.md) · 🇨🇳 [zh-CN](../zh-CN/USER_GUIDE.md) · 🇯🇵 [ja](../ja/USER_GUIDE.md) · 🇰🇷 [ko](../ko/USER_GUIDE.md) · 🇸🇦 [ar](../ar/USER_GUIDE.md) · 🇮🇳 [in](../in/USER_GUIDE.md) · 🇹🇭 [th](../th/USER_GUIDE.md) · 🇻🇳 [vi](../vi/USER_GUIDE.md) · 🇮🇩 [id](../id/USER_GUIDE.md) · 🇲🇾 [ms](../ms/USER_GUIDE.md) · 🇳🇱 [nl](../nl/USER_GUIDE.md) · 🇵🇱 [pl](../pl/USER_GUIDE.md) · 🇸🇪 [sv](../sv/USER_GUIDE.md) · 🇳🇴 [no](../no/USER_GUIDE.md) · 🇩🇰 [da](../da/USER_GUIDE.md) · 🇫🇮 [fi](../fi/USER_GUIDE.md) · 🇵🇹 [pt](../pt/USER_GUIDE.md) · 🇷🇴 [ro](../ro/USER_GUIDE.md) · 🇭🇺 [hu](../hu/USER_GUIDE.md) · 🇧🇬 [bg](../bg/USER_GUIDE.md) · 🇸🇰 [sk](../sk/USER_GUIDE.md) · 🇺🇦 [uk-UA](../uk-UA/USER_GUIDE.md) · 🇮🇱 [he](../he/USER_GUIDE.md) · 🇵🇭 [phi](../phi/USER_GUIDE.md)
-
-> 🇺🇸 [English](../../USER_GUIDE.md)
+🌐 **Languages:** 🇺🇸 [English](../../../../docs/USER_GUIDE.md) · 🇪🇸 [es](../../es/docs/USER_GUIDE.md) · 🇫🇷 [fr](../../fr/docs/USER_GUIDE.md) · 🇩🇪 [de](../../de/docs/USER_GUIDE.md) · 🇮🇹 [it](../../it/docs/USER_GUIDE.md) · 🇷🇺 [ru](../../ru/docs/USER_GUIDE.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/USER_GUIDE.md) · 🇯🇵 [ja](../../ja/docs/USER_GUIDE.md) · 🇰🇷 [ko](../../ko/docs/USER_GUIDE.md) · 🇸🇦 [ar](../../ar/docs/USER_GUIDE.md) · 🇮🇳 [in](../../in/docs/USER_GUIDE.md) · 🇹🇭 [th](../../th/docs/USER_GUIDE.md) · 🇻🇳 [vi](../../vi/docs/USER_GUIDE.md) · 🇮🇩 [id](../../id/docs/USER_GUIDE.md) · 🇲🇾 [ms](../../ms/docs/USER_GUIDE.md) · 🇳🇱 [nl](../../nl/docs/USER_GUIDE.md) · 🇵🇱 [pl](../../pl/docs/USER_GUIDE.md) · 🇸🇪 [sv](../../sv/docs/USER_GUIDE.md) · 🇳🇴 [no](../../no/docs/USER_GUIDE.md) · 🇩🇰 [da](../../da/docs/USER_GUIDE.md) · 🇫🇮 [fi](../../fi/docs/USER_GUIDE.md) · 🇵🇹 [pt](../../pt/docs/USER_GUIDE.md) · 🇷🇴 [ro](../../ro/docs/USER_GUIDE.md) · 🇭🇺 [hu](../../hu/docs/USER_GUIDE.md) · 🇧🇬 [bg](../../bg/docs/USER_GUIDE.md) · 🇸🇰 [sk](../../sk/docs/USER_GUIDE.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/USER_GUIDE.md) · 🇮🇱 [he](../../he/docs/USER_GUIDE.md) · 🇵🇭 [phi](../../phi/docs/USER_GUIDE.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/USER_GUIDE.md) · 🇨🇿 [cs](../../cs/docs/USER_GUIDE.md)
---
@@ -320,7 +318,7 @@ Model: cc/claude-opus-4-6
---
-## 🚀 Deployment
+## Penerapan
### Global npm install (Recommended)
@@ -511,23 +509,26 @@ post_install() {
### Environment Variables
-| Variable | Default | Description |
-| ------------------------- | ------------------------------------ | ------------------------------------------------------- |
-| `JWT_SECRET` | `omniroute-default-secret-change-me` | JWT signing secret (**change in production**) |
-| `INITIAL_PASSWORD` | `123456` | First login password |
-| `DATA_DIR` | `~/.omniroute` | Data directory (db, usage, logs) |
-| `PORT` | framework default | Service port (`20128` in examples) |
-| `HOSTNAME` | framework default | Bind host (Docker defaults to `0.0.0.0`) |
-| `NODE_ENV` | runtime default | Set `production` for deploy |
-| `BASE_URL` | `http://localhost:20128` | Server-side internal base URL |
-| `CLOUD_URL` | `https://omniroute.dev` | Cloud sync endpoint base URL |
-| `API_KEY_SECRET` | `endpoint-proxy-api-key-secret` | HMAC secret for generated API keys |
-| `REQUIRE_API_KEY` | `false` | Enforce Bearer API key on `/v1/*` |
-| `ENABLE_REQUEST_LOGS` | `false` | Enables request/response logs |
-| `AUTH_COOKIE_SECURE` | `false` | Force `Secure` auth cookie (behind HTTPS reverse proxy) |
-| `OMNIROUTE_MEMORY_MB` | `512` | Node.js heap limit in MB |
-| `PROMPT_CACHE_MAX_SIZE` | `50` | Max prompt cache entries |
-| `SEMANTIC_CACHE_MAX_SIZE` | `100` | Max semantic cache entries |
+| Variable | Default | Description |
+| ---------------------------- | ------------------------------------ | ------------------------------------------------------------------------------------------ |
+| `JWT_SECRET` | `omniroute-default-secret-change-me` | JWT signing secret (**change in production**) |
+| `INITIAL_PASSWORD` | `123456` | First login password |
+| `DATA_DIR` | `~/.omniroute` | Data directory (db, usage, logs) |
+| `PORT` | framework default | Service port (`20128` in examples) |
+| `HOSTNAME` | framework default | Bind host (Docker defaults to `0.0.0.0`) |
+| `NODE_ENV` | runtime default | Set `production` for deploy |
+| `BASE_URL` | `http://localhost:20128` | Server-side internal base URL |
+| `CLOUD_URL` | `https://omniroute.dev` | Cloud sync endpoint base URL |
+| `API_KEY_SECRET` | `endpoint-proxy-api-key-secret` | HMAC secret for generated API keys |
+| `REQUIRE_API_KEY` | `false` | Enforce Bearer API key on `/v1/*` |
+| `ALLOW_API_KEY_REVEAL` | `false` | Allow Api Manager to copy full API keys on demand |
+| `DISABLE_SQLITE_AUTO_BACKUP` | `false` | Disable automatic SQLite snapshots before writes/import/restore; manual backups still work |
+| `ENABLE_REQUEST_LOGS` | `false` | Enables request/response logs |
+| `AUTH_COOKIE_SECURE` | `false` | Force `Secure` auth cookie (behind HTTPS reverse proxy) |
+| `CLOUDFLARED_BIN` | unset | Use an existing `cloudflared` binary instead of managed download |
+| `OMNIROUTE_MEMORY_MB` | `512` | Node.js heap limit in MB |
+| `PROMPT_CACHE_MAX_SIZE` | `50` | Max prompt cache entries |
+| `SEMANTIC_CACHE_MAX_SIZE` | `100` | Max semantic cache entries |
For the full environment variable reference, see the [README](../README.md).
@@ -598,6 +599,11 @@ curl -X POST http://localhost:20128/api/provider-models \
Or use Dashboard: **Providers → [Provider] → Custom Models**.
+Notes:
+
+- OpenRouter and OpenAI/Anthropic-compatible providers are managed from **Available Models** only. Manual add, import, and auto-sync all land in the same available-model list, so there is no separate Custom Models section for those providers.
+- The **Custom Models** section is intended for providers that do not expose managed available-model imports.
+
### Dedicated Provider Routes
Route requests directly to a specific provider with model validation:
@@ -642,6 +648,14 @@ Returns models grouped by provider with types (`chat`, `embedding`, `image`).
- Automatic background sync with timeout + fail-fast
- Prefer server-side `BASE_URL`/`CLOUD_URL` in production
+### Cloudflare Quick Tunnel
+
+- Available in **Dashboard → Endpoints** for Docker and other self-hosted deployments
+- Creates a temporary `https://*.trycloudflare.com` URL that forwards to your current OpenAI-compatible `/v1` endpoint
+- First enable installs `cloudflared` only when needed; later restarts reuse the same managed binary
+- Tunnel URLs are ephemeral and change every time you stop/start the tunnel
+- Set `CLOUDFLARED_BIN` if you prefer using a preinstalled `cloudflared` binary instead of the managed download
+
### LLM Gateway Intelligence (Phase 9)
- **Semantic Cache** — Auto-caches non-streaming, temperature=0 responses (bypass with `X-OmniRoute-No-Cache: true`)
@@ -757,11 +771,11 @@ OmniRoute implements provider-level resilience with four components:
Manage database backups in **Dashboard → Settings → System & Storage**.
-| Action | Description |
-| ------------------------ | ------------------------------------------------------------------------------------------------------------------------------ |
-| **Export Database** | Downloads the current SQLite database as a `.sqlite` file |
-| **Export All (.tar.gz)** | Downloads a full backup archive including: database, settings, combos, provider connections (no credentials), API key metadata |
-| **Import Database** | Upload a `.sqlite` file to replace the current database. A pre-import backup is automatically created |
+| Action | Description |
+| ------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------- |
+| **Export Database** | Downloads the current SQLite database as a `.sqlite` file |
+| **Export All (.tar.gz)** | Downloads a full backup archive including: database, settings, combos, provider connections (no credentials), API key metadata |
+| **Import Database** | Upload a `.sqlite` file to replace the current database. A pre-import backup is automatically created unless `DISABLE_SQLITE_AUTO_BACKUP=true` |
```bash
# API: Export database
@@ -787,10 +801,11 @@ curl -X POST http://localhost:20128/api/db-backups/import \
### Settings Dashboard
-The settings page is organized into 5 tabs for easy navigation:
+The settings page is organized into 6 tabs for easy navigation:
| Tab | Contents |
| -------------- | ---------------------------------------------------------------------------------------------- |
+| **General** | System storage tools, appearance settings, theme controls, and per-item sidebar visibility |
| **Security** | Login/Password settings, IP Access Control, API auth for `/models`, and Provider Blocking |
| **Routing** | Global routing strategy (6 options), wildcard model aliases, fallback chains, combo defaults |
| **Resilience** | Provider profiles, editable rate limits, circuit breaker status, policies & locked identifiers |
diff --git a/docs/i18n/id/docs/VM_DEPLOYMENT_GUIDE.md b/docs/i18n/id/docs/VM_DEPLOYMENT_GUIDE.md
new file mode 100644
index 0000000000..0a649b4978
--- /dev/null
+++ b/docs/i18n/id/docs/VM_DEPLOYMENT_GUIDE.md
@@ -0,0 +1,403 @@
+# OmniRoute — Deployment Guide on VM with Cloudflare (Bahasa Indonesia)
+
+🌐 **Languages:** 🇺🇸 [English](../../../../docs/VM_DEPLOYMENT_GUIDE.md) · 🇪🇸 [es](../../es/docs/VM_DEPLOYMENT_GUIDE.md) · 🇫🇷 [fr](../../fr/docs/VM_DEPLOYMENT_GUIDE.md) · 🇩🇪 [de](../../de/docs/VM_DEPLOYMENT_GUIDE.md) · 🇮🇹 [it](../../it/docs/VM_DEPLOYMENT_GUIDE.md) · 🇷🇺 [ru](../../ru/docs/VM_DEPLOYMENT_GUIDE.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/VM_DEPLOYMENT_GUIDE.md) · 🇯🇵 [ja](../../ja/docs/VM_DEPLOYMENT_GUIDE.md) · 🇰🇷 [ko](../../ko/docs/VM_DEPLOYMENT_GUIDE.md) · 🇸🇦 [ar](../../ar/docs/VM_DEPLOYMENT_GUIDE.md) · 🇮🇳 [in](../../in/docs/VM_DEPLOYMENT_GUIDE.md) · 🇹🇭 [th](../../th/docs/VM_DEPLOYMENT_GUIDE.md) · 🇻🇳 [vi](../../vi/docs/VM_DEPLOYMENT_GUIDE.md) · 🇮🇩 [id](../../id/docs/VM_DEPLOYMENT_GUIDE.md) · 🇲🇾 [ms](../../ms/docs/VM_DEPLOYMENT_GUIDE.md) · 🇳🇱 [nl](../../nl/docs/VM_DEPLOYMENT_GUIDE.md) · 🇵🇱 [pl](../../pl/docs/VM_DEPLOYMENT_GUIDE.md) · 🇸🇪 [sv](../../sv/docs/VM_DEPLOYMENT_GUIDE.md) · 🇳🇴 [no](../../no/docs/VM_DEPLOYMENT_GUIDE.md) · 🇩🇰 [da](../../da/docs/VM_DEPLOYMENT_GUIDE.md) · 🇫🇮 [fi](../../fi/docs/VM_DEPLOYMENT_GUIDE.md) · 🇵🇹 [pt](../../pt/docs/VM_DEPLOYMENT_GUIDE.md) · 🇷🇴 [ro](../../ro/docs/VM_DEPLOYMENT_GUIDE.md) · 🇭🇺 [hu](../../hu/docs/VM_DEPLOYMENT_GUIDE.md) · 🇧🇬 [bg](../../bg/docs/VM_DEPLOYMENT_GUIDE.md) · 🇸🇰 [sk](../../sk/docs/VM_DEPLOYMENT_GUIDE.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/VM_DEPLOYMENT_GUIDE.md) · 🇮🇱 [he](../../he/docs/VM_DEPLOYMENT_GUIDE.md) · 🇵🇭 [phi](../../phi/docs/VM_DEPLOYMENT_GUIDE.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/VM_DEPLOYMENT_GUIDE.md) · 🇨🇿 [cs](../../cs/docs/VM_DEPLOYMENT_GUIDE.md)
+
+---
+
+Complete guide to install and configure OmniRoute on a VM (VPS) with domain managed via Cloudflare.
+
+---
+
+## Prerequisites
+
+| Item | Minimum | Recommended |
+| ---------- | ------------------------ | ---------------- |
+| **CPU** | 1 vCPU | 2 vCPU |
+| **RAM** | 1 GB | 2 GB |
+| **Disk** | 10 GB SSD | 25 GB SSD |
+| **OS** | Ubuntu 22.04 LTS | Ubuntu 24.04 LTS |
+| **Domain** | Registered on Cloudflare | — |
+| **Docker** | Docker Engine 24+ | Docker 27+ |
+
+**Tested providers**: Akamai (Linode), DigitalOcean, Vultr, Hetzner, AWS Lightsail.
+
+---
+
+## 1. Configure the VM
+
+### 1.1 Create the instance
+
+On your preferred VPS provider:
+
+- Choose Ubuntu 24.04 LTS
+- Select the minimum plan (1 vCPU / 1 GB RAM)
+- Set a strong root password or configure SSH key
+- Note the **public IP** (e.g., `203.0.113.10`)
+
+### 1.2 Connect via SSH
+
+```bash
+ssh root@203.0.113.10
+```
+
+### 1.3 Update the system
+
+```bash
+apt update && apt upgrade -y
+```
+
+### 1.4 Install Docker
+
+```bash
+# Install dependencies
+apt install -y ca-certificates curl gnupg
+
+# Add official Docker repository
+install -m 0755 -d /etc/apt/keyrings
+curl -fsSL https://download.docker.com/linux/ubuntu/gpg | gpg --dearmor -o /etc/apt/keyrings/docker.gpg
+chmod a+r /etc/apt/keyrings/docker.gpg
+echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu $ (. /etc/os-release && echo “$VERSION_CODENAME”) stable" | tee /etc/apt/sources.list.d/docker.list > /dev/null
+apt update
+apt install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin
+```
+
+### 1.5 Install nginx
+
+```bash
+apt install -y nginx
+```
+
+### 1.6 Configure Firewall (UFW)
+
+```bash
+ufw default deny incoming
+ufw default allow outgoing
+ufw allow 22/tcp # SSH
+ufw allow 80/tcp # HTTP (redirect)
+ufw allow 443/tcp # HTTPS
+ufw enable
+```
+
+> **Tip**: For maximum security, restrict ports 80 and 443 to Cloudflare IPs only. See the [Advanced Security](#advanced-security) section.
+
+---
+
+## 2. Install OmniRoute
+
+### 2.1 Create configuration directory
+
+```bash
+mkdir -p /opt/omniroute
+```
+
+### 2.2 Create environment variables file
+
+```bash
+cat > /opt/omniroute/.env << ‘EOF’
+# === Security ===
+JWT_SECRET=CHANGE-TO-A-UNIQUE-64-CHAR-SECRET-KEY
+INITIAL_PASSWORD=YourSecurePassword123!
+API_KEY_SECRET=REPLACE-WITH-ANOTHER-SECRET-KEY
+STORAGE_ENCRYPTION_KEY=REPLACE-WITH-THIRD-SECRET-KEY
+STORAGE_ENCRYPTION_KEY_VERSION=v1
+MACHINE_ID_SALT=CHANGE-TO-A-UNIQUE-SALT
+
+# === App ===
+PORT=20128
+NODE_ENV=production
+HOSTNAME=0.0.0.0
+DATA_DIR=/app/data
+STORAGE_DRIVER=sqlite
+ENABLE_REQUEST_LOGS=true
+AUTH_COOKIE_SECURE=false
+REQUIRE_API_KEY=false
+
+# === Domain (change to your domain) ===
+BASE_URL=https://llms.seudominio.com
+NEXT_PUBLIC_BASE_URL=https://llms.seudominio.com
+
+# === Cloud Sync (optional) ===
+# CLOUD_URL=https://cloud.omniroute.online
+# NEXT_PUBLIC_CLOUD_URL=https://cloud.omniroute.online
+EOF
+```
+
+> ⚠️ **IMPORTANT**: Generate unique secret keys! Use `openssl rand -hex 32` for each key.
+
+### 2.3 Start the container
+
+```bash
+docker pull diegosouzapw/omniroute:latest
+
+docker run -d \
+ --name omniroute \
+ --restart unless-stopped \
+ --env-file /opt/omniroute/.env \
+ -p 20128:20128 \
+ -v omniroute-data:/app/data \
+ diegosouzapw/omniroute:latest
+```
+
+### 2.4 Verify that it is running
+
+```bash
+docker ps | grep omniroute
+docker logs omniroute --tail 20
+```
+
+It should display: `[DB] SQLite database ready` and `listening on port 20128`.
+
+---
+
+## 3. Configure nginx (Reverse Proxy)
+
+### 3.1 Generate SSL certificate (Cloudflare Origin)
+
+In the Cloudflare dashboard:
+
+1. Go to **SSL/TLS → Origin Server**
+2. Click **Create Certificate**
+3. Keep the defaults (15 years, \*.yourdomain.com)
+4. Copy the **Origin Certificate** and the **Private Key**
+
+```bash
+mkdir -p /etc/nginx/ssl
+
+# Paste the certificate
+nano /etc/nginx/ssl/origin.crt
+
+# Paste the private key
+nano /etc/nginx/ssl/origin.key
+
+chmod 600 /etc/nginx/ssl/origin.key
+```
+
+### 3.2 Nginx Configuration
+
+```bash
+cat > /etc/nginx/sites-available/omniroute << ‘NGINX’
+# Default server — blocks direct access via IP
+server {
+ listen 80 default_server;
+ listen [::]:80 default_server;
+ listen 443 ssl default_server;
+ listen [::]:443 ssl default_server;
+ ssl_certificate /etc/nginx/ssl/origin.crt;
+ ssl_certificate_key /etc/nginx/ssl/origin.key;
+ server_name _;
+ return 444;
+}
+
+# OmniRoute — HTTPS
+server {
+ listen 443 ssl;
+ listen [::]:443 ssl;
+ server_name llms.yourdomain.com; # Change to your domain
+
+ ssl_certificate /etc/nginx/ssl/origin.crt;
+ ssl_certificate_key /etc/nginx/ssl/origin.key;
+ ssl_protocols TLSv1.2 TLSv1.3;
+
+ client_max_body_size 100M;
+
+ location / {
+ proxy_pass http://127.0.0.1:20128;
+ proxy_set_header Host $host;
+ proxy_set_header X-Real-IP $remote_addr;
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
+ proxy_set_header X-Forwarded-Proto $scheme;
+
+ # WebSocket support
+ proxy_http_version 1.1;
+ proxy_set_header Upgrade $http_upgrade;
+ proxy_set_header Connection “upgrade”;
+
+ # SSE (Server-Sent Events) — streaming AI responses
+ proxy_buffering off;
+ proxy_cache off;
+ proxy_read_timeout 300s;
+ proxy_send_timeout 300s;
+ }
+}
+
+# HTTP → HTTPS redirect
+server {
+ listen 80;
+ listen [::]:80;
+ server_name llms.yourdomain.com;
+ return 301 https://$server_name$request_uri;
+}
+NGINX
+```
+
+### 3.3 Enable and Test
+
+```bash
+# Remove default configuration
+rm -f /etc/nginx/sites-enabled/default
+
+# Enable OmniRoute
+ln -sf /etc/nginx/sites-available/omniroute /etc/nginx/sites-enabled/omniroute
+
+# Test and reload
+nginx -t && systemctl reload nginx
+```
+
+---
+
+## 4. Configure Cloudflare DNS
+
+### 4.1 Add DNS record
+
+In the Cloudflare dashboard → DNS:
+
+| Type | Name | Content | Proxy |
+| ---- | ------ | ---------------------- | ---------- |
+| A | `llms` | `203.0.113.10` (VM IP) | ✅ Proxied |
+
+### 4.2 Configure SSL
+
+Under **SSL/TLS → Overview**:
+
+- Mode: **Full (Strict)**
+
+Under **SSL/TLS → Edge Certificates**:
+
+- Always Use HTTPS: ✅ On
+- Minimum TLS Version: TLS 1.2
+- Automatic HTTPS Rewrites: ✅ On
+
+### 4.3 Testing
+
+```bash
+curl -sI https://llms.seudominio.com/health
+# Should return HTTP/2 200
+```
+
+---
+
+## 5. Operations and Maintenance
+
+### Upgrade to a new version
+
+```bash
+docker pull diegosouzapw/omniroute:latest
+docker stop omniroute && docker rm omniroute
+docker run -d --name omniroute --restart unless-stopped \
+ --env-file /opt/omniroute/.env \
+ -p 20128:20128 \
+ -v omniroute-data:/app/data \
+ diegosouzapw/omniroute:latest
+```
+
+### View logs
+
+```bash
+docker logs -f omniroute # Real-time stream
+docker logs omniroute --tail 50 # Last 50 lines
+```
+
+### Manual database backup
+
+```bash
+# Copy data from the volume to the host
+docker cp omniroute:/app/data ./backup-$(date +%F)
+
+# Or compress the entire volume
+docker run --rm -v omniroute-data:/data -v $(pwd):/backup \
+ alpine tar czf /backup/omniroute-data-$(date +%F).tar.gz /data
+```
+
+### Restore from backup
+
+```bash
+docker stop omniroute
+docker run --rm -v omniroute-data:/data -v $(pwd):/backup \
+ alpine sh -c “rm -rf /data/* && tar xzf /backup/omniroute-data-YYYY-MM-DD.tar.gz -C /”
+docker start omniroute
+```
+
+---
+
+## 6. Advanced Security
+
+### Restrict nginx to Cloudflare IPs
+
+```bash
+cat > /etc/nginx/cloudflare-ips.conf << ‘CF’
+# Cloudflare IPv4 ranges — update periodically
+# https://www.cloudflare.com/ips-v4/
+set_real_ip_from 173.245.48.0/20;
+set_real_ip_from 103.21.244.0/22;
+set_real_ip_from 103.22.200.0/22;
+set_real_ip_from 103.31.4.0/22;
+set_real_ip_from 141.101.64.0/18;
+set_real_ip_from 108.162.192.0/18;
+set_real_ip_from 190.93.240.0/20;
+set_real_ip_from 188.114.96.0/20;
+set_real_ip_from 197.234.240.0/22;
+set_real_ip_from 198.41.128.0/17;
+set_real_ip_from 162.158.0.0/15;
+set_real_ip_from 104.16.0.0/13;
+set_real_ip_from 104.24.0.0/14;
+set_real_ip_from 172.64.0.0/13;
+set_real_ip_from 131.0.72.0/22;
+real_ip_header CF-Connecting-IP;
+CF
+```
+
+Add the following to `nginx.conf` inside the `http {}` block:
+
+```nginx
+include /etc/nginx/cloudflare-ips.conf;
+```
+
+### Install fail2ban
+
+```bash
+apt install -y fail2ban
+systemctl enable fail2ban
+systemctl start fail2ban
+
+# Check status
+fail2ban-client status sshd
+```
+
+### Block direct access to the Docker port
+
+```bash
+# Prevent direct external access to port 20128
+iptables -I DOCKER-USER -p tcp --dport 20128 -j DROP
+iptables -I DOCKER-USER -i lo -p tcp --dport 20128 -j ACCEPT
+
+# Persist the rules
+apt install -y iptables-persistent
+netfilter-persistent save
+```
+
+---
+
+## 7. Deploy to Cloudflare Workers (Optional)
+
+For remote access via Cloudflare Workers (without exposing the VM directly):
+
+```bash
+# In the local repository
+cd omnirouteCloud
+npm install
+npx wrangler login
+npx wrangler deploy
+```
+
+See the full documentation at [omnirouteCloud/README.md](../omnirouteCloud/README.md).
+
+---
+
+## Port Summary
+
+| Port | Service | Access |
+| ----- | ----------- | -------------------------- |
+| 22 | SSH | Public (with fail2ban) |
+| 80 | nginx HTTP | Redirect → HTTPS |
+| 443 | nginx HTTPS | Via Cloudflare Proxy |
+| 20128 | OmniRoute | Localhost only (via nginx) |
diff --git a/docs/i18n/id/src/lib/a2a/README.md b/docs/i18n/id/src/lib/a2a/README.md
new file mode 100644
index 0000000000..54f6d52556
--- /dev/null
+++ b/docs/i18n/id/src/lib/a2a/README.md
@@ -0,0 +1,752 @@
+# OmniRoute A2A Server (Bahasa Indonesia)
+
+🌐 **Languages:** 🇺🇸 [English](../../../../../../src/lib/a2a/README.md) · 🇪🇸 [es](../../../../es/src/lib/a2a/README.md) · 🇫🇷 [fr](../../../../fr/src/lib/a2a/README.md) · 🇩🇪 [de](../../../../de/src/lib/a2a/README.md) · 🇮🇹 [it](../../../../it/src/lib/a2a/README.md) · 🇷🇺 [ru](../../../../ru/src/lib/a2a/README.md) · 🇨🇳 [zh-CN](../../../../zh-CN/src/lib/a2a/README.md) · 🇯🇵 [ja](../../../../ja/src/lib/a2a/README.md) · 🇰🇷 [ko](../../../../ko/src/lib/a2a/README.md) · 🇸🇦 [ar](../../../../ar/src/lib/a2a/README.md) · 🇮🇳 [in](../../../../in/src/lib/a2a/README.md) · 🇹🇭 [th](../../../../th/src/lib/a2a/README.md) · 🇻🇳 [vi](../../../../vi/src/lib/a2a/README.md) · 🇮🇩 [id](../../../../id/src/lib/a2a/README.md) · 🇲🇾 [ms](../../../../ms/src/lib/a2a/README.md) · 🇳🇱 [nl](../../../../nl/src/lib/a2a/README.md) · 🇵🇱 [pl](../../../../pl/src/lib/a2a/README.md) · 🇸🇪 [sv](../../../../sv/src/lib/a2a/README.md) · 🇳🇴 [no](../../../../no/src/lib/a2a/README.md) · 🇩🇰 [da](../../../../da/src/lib/a2a/README.md) · 🇫🇮 [fi](../../../../fi/src/lib/a2a/README.md) · 🇵🇹 [pt](../../../../pt/src/lib/a2a/README.md) · 🇷🇴 [ro](../../../../ro/src/lib/a2a/README.md) · 🇭🇺 [hu](../../../../hu/src/lib/a2a/README.md) · 🇧🇬 [bg](../../../../bg/src/lib/a2a/README.md) · 🇸🇰 [sk](../../../../sk/src/lib/a2a/README.md) · 🇺🇦 [uk-UA](../../../../uk-UA/src/lib/a2a/README.md) · 🇮🇱 [he](../../../../he/src/lib/a2a/README.md) · 🇵🇭 [phi](../../../../phi/src/lib/a2a/README.md) · 🇧🇷 [pt-BR](../../../../pt-BR/src/lib/a2a/README.md) · 🇨🇿 [cs](../../../../cs/src/lib/a2a/README.md)
+
+---
+
+> **Agent-to-Agent Protocol v0.3** — Enables any AI agent to use OmniRoute as an intelligent routing agent via JSON-RPC 2.0.
+
+The A2A Server exposes OmniRoute as a **first-class agent** that other agents can discover, delegate tasks to, and collaborate with using the [A2A Protocol](https://google.github.io/A2A/).
+
+---
+
+## Arsitektur
+
+```
+┌──────────────────────────────────────────────────────────────────┐
+│ Orchestrator Agent │
+│ (LangChain, CrewAI, AutoGen, Custom Agent) │
+└──────────────────────┬───────────────────────────────────────────┘
+ │ 1. GET /.well-known/agent.json (discover)
+ │ 2. POST /a2a (JSON-RPC 2.0)
+ ▼
+┌──────────────────────────────────────────────────────────────────┐
+│ OmniRoute A2A Server │
+│ ┌────────────────┐ ┌────────────────┐ ┌───────────────────┐ │
+│ │ Task Manager │ │ Skill Engine │ │ SSE Streaming │ │
+│ │ (lifecycle) │──│ (registry) │──│ (real-time) │ │
+│ └────────────────┘ └────────┬───────┘ └───────────────────┘ │
+│ │ │
+│ Skills: │ │
+│ ├─ smart-routing ──────────┤ ┌────────────────────────────┐ │
+│ └─ quota-management ───────┘ │ Routing Decision Logger │ │
+│ └────────────────────────────┘ │
+└──────────────────────────────────────────────────────────────────┘
+ │
+ ▼ OmniRoute Gateway (internal)
+ /v1/chat/completions, /api/combos, /api/usage/quota
+```
+
+---
+
+## Mulai Cepat
+
+### Agent Discovery
+
+Every A2A-compatible agent exposes an **Agent Card** at `/.well-known/agent.json`:
+
+```bash
+curl http://localhost:20128/.well-known/agent.json
+```
+
+**Response:**
+
+```json
+{
+ "name": "OmniRoute",
+ "description": "Intelligent AI gateway with auto-routing across 50+ providers",
+ "url": "http://localhost:20128/a2a",
+ "version": "1.8.1",
+ "capabilities": {
+ "streaming": true,
+ "pushNotifications": false
+ },
+ "skills": [
+ {
+ "id": "smart-routing",
+ "name": "Smart Routing",
+ "description": "Routes prompts through OmniRoute intelligent pipeline",
+ "tags": ["routing", "llm", "multi-provider", "cost-optimization"],
+ "examples": [
+ "Write a hello world in Python",
+ "Explain quantum computing using the cheapest provider"
+ ]
+ },
+ {
+ "id": "quota-management",
+ "name": "Quota Management",
+ "description": "Natural-language queries about provider quotas",
+ "tags": ["quota", "analytics", "cost"],
+ "examples": [
+ "Which provider has the most quota remaining?",
+ "Suggest a free combo for coding"
+ ]
+ }
+ ],
+ "authentication": {
+ "schemes": ["bearer"],
+ "apiKeyHeader": "Authorization"
+ }
+}
+```
+
+---
+
+## JSON-RPC 2.0 Methods
+
+### `message/send` — Synchronous Execution
+
+Send a message to a skill and receive the complete response.
+
+```bash
+curl -X POST http://localhost:20128/a2a \
+ -H "Content-Type: application/json" \
+ -H "Authorization: Bearer YOUR_KEY" \
+ -d '{
+ "jsonrpc": "2.0",
+ "id": "1",
+ "method": "message/send",
+ "params": {
+ "skill": "smart-routing",
+ "messages": [{"role": "user", "content": "Write a Python hello world"}],
+ "metadata": {"model": "auto", "combo": "fast-coding"}
+ }
+ }'
+```
+
+**Response:**
+
+```json
+{
+ "jsonrpc": "2.0",
+ "id": "1",
+ "result": {
+ "task": { "id": "a1b2c3d4-...", "state": "completed" },
+ "artifacts": [{ "type": "text", "content": "print('Hello, World!')" }],
+ "metadata": {
+ "routing_explanation": "Selected claude-sonnet via provider \"anthropic\" (latency: 1200ms, cost: $0.0030)",
+ "cost_envelope": { "estimated": 0.005, "actual": 0.003, "currency": "USD" },
+ "resilience_trace": [
+ { "event": "primary_selected", "provider": "anthropic", "timestamp": "2026-03-04T..." }
+ ],
+ "policy_verdict": { "allowed": true, "reason": "within budget and quota limits" }
+ }
+ }
+}
+```
+
+### `message/stream` — SSE Streaming
+
+Same as `message/send` but returns Server-Sent Events for real-time streaming.
+
+```bash
+curl -N -X POST http://localhost:20128/a2a \
+ -H "Content-Type: application/json" \
+ -H "Authorization: Bearer YOUR_KEY" \
+ -d '{
+ "jsonrpc": "2.0",
+ "id": "1",
+ "method": "message/stream",
+ "params": {
+ "skill": "smart-routing",
+ "messages": [{"role": "user", "content": "Explain quantum computing"}]
+ }
+ }'
+```
+
+**SSE Events:**
+
+```
+data: {"jsonrpc":"2.0","method":"message/stream","params":{"task":{"id":"...","state":"working"},"chunk":{"type":"text","content":"Quantum computing..."}}}
+
+: heartbeat 2026-03-04T21:00:00Z
+
+data: {"jsonrpc":"2.0","method":"message/stream","params":{"task":{"id":"...","state":"completed"},"metadata":{...}}}
+```
+
+### `tasks/get` — Query Task Status
+
+```bash
+curl -X POST http://localhost:20128/a2a \
+ -H "Content-Type: application/json" \
+ -H "Authorization: Bearer YOUR_KEY" \
+ -d '{"jsonrpc":"2.0","id":"2","method":"tasks/get","params":{"taskId":"TASK_UUID"}}'
+```
+
+### `tasks/cancel` — Cancel a Running Task
+
+```bash
+curl -X POST http://localhost:20128/a2a \
+ -H "Content-Type: application/json" \
+ -H "Authorization: Bearer YOUR_KEY" \
+ -d '{"jsonrpc":"2.0","id":"3","method":"tasks/cancel","params":{"taskId":"TASK_UUID"}}'
+```
+
+---
+
+## Skills Reference
+
+### `smart-routing`
+
+Routes prompts through OmniRoute's intelligent pipeline with full observability.
+
+**Parameters (in `metadata`):**
+
+| Parameter | Type | Default | Description |
+| --------- | -------- | ------------ | ---------------------------------------------------------------------------------------- |
+| `model` | `string` | `"auto"` | Target model (e.g., `claude-sonnet-4`, `gpt-4o`, `auto`) |
+| `combo` | `string` | active combo | Specific combo to route through |
+| `budget` | `number` | none | Maximum cost in USD for this request |
+| `role` | `string` | none | Task role hint: `coding`, `review`, `planning`, `analysis`, `debugging`, `documentation` |
+
+**Returns:**
+
+| Field | Description |
+| ------------------------------ | --------------------------------------------------------- |
+| `artifacts[].content` | The LLM response text |
+| `metadata.routing_explanation` | Human-readable explanation of routing decision |
+| `metadata.cost_envelope` | Estimated vs actual cost with currency |
+| `metadata.resilience_trace` | Array of events (primary_selected, fallback_needed, etc.) |
+| `metadata.policy_verdict` | Whether the request was allowed and why |
+
+### `quota-management`
+
+Answers natural-language queries about provider quotas.
+
+**Query types (inferred from message content):**
+
+| Query Pattern | Response Type |
+| ---------------------------------------------- | -------------------------------------------------------- |
+| Contains `"ranking"`, `"most quota"`, `"best"` | Providers ranked by remaining quota |
+| Contains `"free"`, `"suggest"` | Lists free combos or suggests free-tier providers |
+| Default | Full quota summary with warnings for low-quota providers |
+
+---
+
+## Task Lifecycle
+
+```
+submitted ──→ working ──→ completed
+ ──→ failed
+ ──────────→ cancelled
+```
+
+| State | Description |
+| ----------- | ----------------------------------------------------- |
+| `submitted` | Task created, queued for execution |
+| `working` | Skill handler is executing |
+| `completed` | Execution succeeded, artifacts available |
+| `failed` | Execution failed or task expired (TTL: 5 min default) |
+| `cancelled` | Cancelled by client via `tasks/cancel` |
+
+- Terminal states: `completed`, `failed`, `cancelled` (no further transitions)
+- Expired tasks in `submitted` or `working` are auto-marked as `failed`
+- Tasks are garbage-collected after 2× TTL
+
+---
+
+## Client Examples
+
+### Python — Orchestrator Agent
+
+```python
+"""
+A2A Client — Python example.
+Discovers OmniRoute agent, sends a task, and processes the result.
+"""
+import requests
+import json
+
+BASE_URL = "http://localhost:20128"
+API_KEY = "your-api-key"
+HEADERS = {
+ "Content-Type": "application/json",
+ "Authorization": f"Bearer {API_KEY}",
+}
+
+# 1. Discover agent capabilities
+agent_card = requests.get(f"{BASE_URL}/.well-known/agent.json").json()
+print(f"Agent: {agent_card['name']} v{agent_card['version']}")
+print(f"Skills: {[s['id'] for s in agent_card['skills']]}")
+
+# 2. Send a smart-routing task
+response = requests.post(f"{BASE_URL}/a2a", headers=HEADERS, json={
+ "jsonrpc": "2.0",
+ "id": "task-1",
+ "method": "message/send",
+ "params": {
+ "skill": "smart-routing",
+ "messages": [{"role": "user", "content": "Write a Python quicksort implementation"}],
+ "metadata": {
+ "model": "auto",
+ "combo": "fast-coding",
+ "budget": 0.10,
+ }
+ }
+})
+result = response.json()["result"]
+print(f"\n📝 Response: {result['artifacts'][0]['content'][:200]}...")
+print(f"🔀 Routing: {result['metadata']['routing_explanation']}")
+print(f"💰 Cost: ${result['metadata']['cost_envelope']['actual']}")
+print(f"🛡️ Policy: {result['metadata']['policy_verdict']['reason']}")
+
+# 3. Query quota status
+quota_resp = requests.post(f"{BASE_URL}/a2a", headers=HEADERS, json={
+ "jsonrpc": "2.0",
+ "id": "task-2",
+ "method": "message/send",
+ "params": {
+ "skill": "quota-management",
+ "messages": [{"role": "user", "content": "Which provider has the most quota remaining?"}],
+ }
+})
+quota_result = quota_resp.json()["result"]
+print(f"\n📊 Quota: {quota_result['artifacts'][0]['content']}")
+```
+
+### TypeScript — Multi-Agent Orchestrator
+
+```typescript
+/**
+ * A2A Client — TypeScript example.
+ * Shows agent discovery, task delegation, and streaming.
+ */
+
+const BASE_URL = "http://localhost:20128";
+const API_KEY = "your-api-key";
+
+interface JsonRpcResponse {
+ jsonrpc: "2.0";
+ id: string | number;
+ result?: T;
+ error?: { code: number; message: string };
+}
+
+async function a2aCall(method: string, params: Record): Promise {
+ const resp = await fetch(`${BASE_URL}/a2a`, {
+ method: "POST",
+ headers: {
+ "Content-Type": "application/json",
+ Authorization: `Bearer ${API_KEY}`,
+ },
+ body: JSON.stringify({
+ jsonrpc: "2.0",
+ id: `${method}-${Date.now()}`,
+ method,
+ params,
+ }),
+ });
+ const json: JsonRpcResponse = await resp.json();
+ if (json.error) throw new Error(`[${json.error.code}] ${json.error.message}`);
+ return json.result!;
+}
+
+// ── Agent Discovery ──
+const agentCard = await fetch(`${BASE_URL}/.well-known/agent.json`).then((r) => r.json());
+console.log(`Connected to: ${agentCard.name} (${agentCard.skills.length} skills)`);
+
+// ── Smart Routing: Send a coding task ──
+const routingResult = await a2aCall("message/send", {
+ skill: "smart-routing",
+ messages: [{ role: "user", content: "Implement a Redis cache wrapper in TypeScript" }],
+ metadata: { model: "claude-sonnet-4", role: "coding" },
+});
+console.log("Response:", routingResult.artifacts[0].content);
+console.log("Provider:", routingResult.metadata.routing_explanation);
+
+// ── Quota Management: Find free alternatives ──
+const quotaResult = await a2aCall("message/send", {
+ skill: "quota-management",
+ messages: [{ role: "user", content: "Suggest free combos for documentation" }],
+});
+console.log("Free combos:", quotaResult.artifacts[0].content);
+
+// ── Streaming: Real-time response ──
+const streamResp = await fetch(`${BASE_URL}/a2a`, {
+ method: "POST",
+ headers: {
+ "Content-Type": "application/json",
+ Authorization: `Bearer ${API_KEY}`,
+ },
+ body: JSON.stringify({
+ jsonrpc: "2.0",
+ id: "stream-1",
+ method: "message/stream",
+ params: {
+ skill: "smart-routing",
+ messages: [{ role: "user", content: "Explain microservices architecture" }],
+ },
+ }),
+});
+
+const reader = streamResp.body!.getReader();
+const decoder = new TextDecoder();
+while (true) {
+ const { done, value } = await reader.read();
+ if (done) break;
+ const chunk = decoder.decode(value);
+ for (const line of chunk.split("\n")) {
+ if (line.startsWith("data: ")) {
+ const event = JSON.parse(line.slice(6));
+ if (event.params.chunk) {
+ process.stdout.write(event.params.chunk.content);
+ }
+ if (event.params.task.state === "completed") {
+ console.log("\n✅ Stream completed");
+ }
+ }
+ }
+}
+```
+
+### Python — LangChain A2A Integration
+
+```python
+"""
+LangChain integration — Use OmniRoute A2A as a custom LLM.
+"""
+from langchain.llms.base import BaseLLM
+from langchain.schema import LLMResult, Generation
+import requests
+from typing import List, Optional
+
+class OmniRouteA2A(BaseLLM):
+ base_url: str = "http://localhost:20128"
+ api_key: str = ""
+ model: str = "auto"
+ combo: Optional[str] = None
+
+ @property
+ def _llm_type(self) -> str:
+ return "omniroute-a2a"
+
+ def _call(self, prompt: str, stop: Optional[List[str]] = None, **kwargs) -> str:
+ response = requests.post(
+ f"{self.base_url}/a2a",
+ headers={
+ "Content-Type": "application/json",
+ "Authorization": f"Bearer {self.api_key}",
+ },
+ json={
+ "jsonrpc": "2.0",
+ "id": "langchain-1",
+ "method": "message/send",
+ "params": {
+ "skill": "smart-routing",
+ "messages": [{"role": "user", "content": prompt}],
+ "metadata": {
+ "model": self.model,
+ **({"combo": self.combo} if self.combo else {}),
+ },
+ },
+ },
+ )
+ result = response.json()["result"]
+ return result["artifacts"][0]["content"]
+
+ def _generate(self, prompts: List[str], stop=None, **kwargs) -> LLMResult:
+ return LLMResult(
+ generations=[[Generation(text=self._call(p, stop))] for p in prompts]
+ )
+
+# Usage
+llm = OmniRouteA2A(
+ base_url="http://localhost:20128",
+ api_key="your-key",
+ model="auto",
+ combo="fast-coding",
+)
+result = llm("Write a Python function to merge two sorted lists")
+print(result)
+```
+
+### Go — A2A Client
+
+```go
+package main
+
+import (
+ "bytes"
+ "encoding/json"
+ "fmt"
+ "io"
+ "net/http"
+)
+
+const baseURL = "http://localhost:20128"
+const apiKey = "your-api-key"
+
+type JsonRpcRequest struct {
+ Jsonrpc string `json:"jsonrpc"`
+ ID string `json:"id"`
+ Method string `json:"method"`
+ Params interface{} `json:"params"`
+}
+
+type JsonRpcResponse struct {
+ Jsonrpc string `json:"jsonrpc"`
+ ID string `json:"id"`
+ Result interface{} `json:"result"`
+ Error *struct {
+ Code int `json:"code"`
+ Message string `json:"message"`
+ } `json:"error"`
+}
+
+func a2aCall(method string, params interface{}) (*JsonRpcResponse, error) {
+ body, _ := json.Marshal(JsonRpcRequest{
+ Jsonrpc: "2.0",
+ ID: "go-1",
+ Method: method,
+ Params: params,
+ })
+
+ req, _ := http.NewRequest("POST", baseURL+"/a2a", bytes.NewReader(body))
+ req.Header.Set("Content-Type", "application/json")
+ req.Header.Set("Authorization", "Bearer "+apiKey)
+
+ resp, err := http.DefaultClient.Do(req)
+ if err != nil {
+ return nil, err
+ }
+ defer resp.Body.Close()
+ data, _ := io.ReadAll(resp.Body)
+
+ var result JsonRpcResponse
+ json.Unmarshal(data, &result)
+ return &result, nil
+}
+
+func main() {
+ // Discover agent
+ resp, _ := http.Get(baseURL + "/.well-known/agent.json")
+ defer resp.Body.Close()
+ body, _ := io.ReadAll(resp.Body)
+ fmt.Println("Agent Card:", string(body))
+
+ // Send smart-routing task
+ result, _ := a2aCall("message/send", map[string]interface{}{
+ "skill": "smart-routing",
+ "messages": []map[string]string{{"role": "user", "content": "Hello from Go!"}},
+ "metadata": map[string]interface{}{"model": "auto"},
+ })
+ out, _ := json.MarshalIndent(result.Result, "", " ")
+ fmt.Println("Result:", string(out))
+}
+```
+
+---
+
+## Use Cases
+
+### 🤖 Use Case 1: Multi-Agent Coding Pipeline
+
+An orchestrator agent delegates code generation to OmniRoute, then passes the output to a review agent.
+
+```python
+def coding_pipeline(task: str):
+ # Step 1: Generate code via OmniRoute A2A
+ code_result = a2a_send("smart-routing", [
+ {"role": "user", "content": f"Write production-quality code: {task}"}
+ ], metadata={"model": "auto", "role": "coding"})
+ code = code_result["artifacts"][0]["content"]
+
+ # Step 2: Review the code via OmniRoute A2A (different model)
+ review_result = a2a_send("smart-routing", [
+ {"role": "user", "content": f"Review this code for bugs and improvements:\n\n{code}"}
+ ], metadata={"model": "auto", "role": "review"})
+ review = review_result["artifacts"][0]["content"]
+
+ # Step 3: Check costs
+ print(f"Code cost: ${code_result['metadata']['cost_envelope']['actual']}")
+ print(f"Review cost: ${review_result['metadata']['cost_envelope']['actual']}")
+
+ return {"code": code, "review": review}
+```
+
+### 💡 Use Case 2: Quota-Aware Agent Swarm
+
+Multiple agents share quota through OmniRoute, using the quota skill to coordinate.
+
+```python
+async def quota_aware_agent(agent_name: str, task: str):
+ # Check quota before starting
+ quota = a2a_send("quota-management", [
+ {"role": "user", "content": "Which provider has the most quota remaining?"}
+ ])
+ print(f"[{agent_name}] {quota['artifacts'][0]['content']}")
+
+ # Send request with budget constraint
+ result = a2a_send("smart-routing", [
+ {"role": "user", "content": task}
+ ], metadata={"budget": 0.05})
+
+ policy = result["metadata"]["policy_verdict"]
+ if not policy["allowed"]:
+ print(f"[{agent_name}] ⚠️ Budget exceeded: {policy['reason']}")
+ # Fall back to free combo
+ quota = a2a_send("quota-management", [
+ {"role": "user", "content": "Suggest free combos"}
+ ])
+ print(f"[{agent_name}] Free alternatives: {quota['artifacts'][0]['content']}")
+
+ return result
+```
+
+### 📊 Use Case 3: Real-Time Streaming Dashboard
+
+A monitoring agent streams responses and displays progress in real-time.
+
+```typescript
+async function streamingDashboard(prompt: string) {
+ const response = await fetch(`${BASE_URL}/a2a`, {
+ method: "POST",
+ headers: { "Content-Type": "application/json", Authorization: `Bearer ${API_KEY}` },
+ body: JSON.stringify({
+ jsonrpc: "2.0",
+ id: "dash-1",
+ method: "message/stream",
+ params: { skill: "smart-routing", messages: [{ role: "user", content: prompt }] },
+ }),
+ });
+
+ let totalChunks = 0;
+ const reader = response.body!.getReader();
+ const decoder = new TextDecoder();
+
+ while (true) {
+ const { done, value } = await reader.read();
+ if (done) break;
+
+ for (const line of decoder.decode(value).split("\n")) {
+ if (line.startsWith("data: ")) {
+ const event = JSON.parse(line.slice(6));
+ const state = event.params.task.state;
+
+ if (state === "working" && event.params.chunk) {
+ totalChunks++;
+ process.stdout.write(
+ `\r[Chunk ${totalChunks}] ${event.params.chunk.content.slice(0, 50)}...`
+ );
+ }
+ if (state === "completed") {
+ const meta = event.params.metadata;
+ console.log(
+ `\n✅ Done | Cost: $${meta?.cost_envelope?.actual || 0} | Route: ${meta?.routing_explanation || "N/A"}`
+ );
+ }
+ if (state === "failed") {
+ console.error(`\n❌ Failed: ${event.params.metadata?.error}`);
+ }
+ }
+ }
+ }
+}
+```
+
+### 🔁 Use Case 4: Task Polling Pattern
+
+For long-running tasks, poll the task status instead of waiting synchronously.
+
+```python
+import time
+
+def poll_task(task_id: str, timeout: int = 60):
+ """Poll task status until completion or timeout."""
+ start = time.time()
+ while time.time() - start < timeout:
+ result = requests.post(f"{BASE_URL}/a2a", headers=HEADERS, json={
+ "jsonrpc": "2.0",
+ "id": "poll-1",
+ "method": "tasks/get",
+ "params": {"taskId": task_id},
+ }).json()
+
+ task = result["result"]["task"]
+ state = task["state"]
+ print(f" Task {task_id[:8]}... state={state}")
+
+ if state in ("completed", "failed", "cancelled"):
+ return task
+ time.sleep(2)
+
+ # Timeout — cancel the task
+ requests.post(f"{BASE_URL}/a2a", headers=HEADERS, json={
+ "jsonrpc": "2.0",
+ "id": "cancel-1",
+ "method": "tasks/cancel",
+ "params": {"taskId": task_id},
+ })
+ raise TimeoutError(f"Task {task_id} timed out after {timeout}s")
+```
+
+---
+
+## Error Codes
+
+| Code | Constant | Meaning |
+| ------ | ------------------------ | ---------------------------------------- |
+| -32700 | — | Parse error (invalid JSON) |
+| -32600 | `INVALID_REQUEST` | Invalid JSON-RPC request or unauthorized |
+| -32601 | `METHOD_NOT_FOUND` | Unknown method or skill |
+| -32602 | `INVALID_PARAMS` | Missing or invalid parameters |
+| -32603 | `INTERNAL_ERROR` | Skill execution failed |
+| -32001 | `TASK_NOT_FOUND` | Task ID not found |
+| -32002 | `TASK_ALREADY_COMPLETED` | Cannot modify a completed task |
+| -32003 | `UNAUTHORIZED` | Invalid or missing API key |
+| -32004 | `BUDGET_EXCEEDED` | Request exceeds configured budget |
+| -32005 | `PROVIDER_UNAVAILABLE` | No available providers |
+
+---
+
+## Authentication
+
+All `/a2a` requests require a Bearer token via the `Authorization` header:
+
+```
+Authorization: Bearer YOUR_OMNIROUTE_API_KEY
+```
+
+If no API key is configured on the server (`OMNIROUTE_API_KEY` is empty), authentication is bypassed.
+
+---
+
+## File Structure
+
+```
+src/lib/a2a/
+├── taskManager.ts # Task lifecycle (create/update/cancel/list), TTL, cleanup
+├── taskExecution.ts # Generic task executor with state management
+├── streaming.ts # SSE stream formatting, heartbeat, chunk/completion events
+├── routingLogger.ts # Routing decision logger (stats, history, retention)
+└── skills/
+ ├── smartRouting.ts # Smart routing skill (routes via /v1/chat/completions)
+ └── quotaManagement.ts # Quota management skill (natural-language quota queries)
+
+src/app/a2a/
+└── route.ts # Next.js API route handler (JSON-RPC 2.0 dispatch)
+
+open-sse/mcp-server/
+└── schemas/a2a.ts # Zod schemas (AgentCard, Task, JSON-RPC, SSE events)
+```
+
+---
+
+## Comparison: MCP vs A2A
+
+| Feature | MCP Server | A2A Server |
+| ----------------- | ---------------------------- | ------------------------------------------------- |
+| **Protocol** | Model Context Protocol | Agent-to-Agent Protocol v0.3 |
+| **Transport** | stdio / HTTP | HTTP (JSON-RPC 2.0) |
+| **Discovery** | Tool listing via MCP | `/.well-known/agent.json` |
+| **Granularity** | 16 individual tools | 2 high-level skills |
+| **Best for** | IDE agents (Cursor, VS Code) | Multi-agent systems (LangChain, CrewAI) |
+| **Streaming** | Not supported | SSE via `message/stream` |
+| **Task tracking** | No | Full lifecycle (submitted → completed) |
+| **Observability** | Audit log per tool call | Cost envelope + resilience trace + policy verdict |
+
+---
+
+## Lisensi
+
+Part of [OmniRoute](https://github.com/diegosouzapw/OmniRoute) — MIT License.
diff --git a/docs/i18n/in/A2A-SERVER.md b/docs/i18n/in/A2A-SERVER.md
deleted file mode 100644
index 01531ff482..0000000000
--- a/docs/i18n/in/A2A-SERVER.md
+++ /dev/null
@@ -1,200 +0,0 @@
-🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/A2A-SERVER.md) · 🇪🇸 [es](../es/A2A-SERVER.md) · 🇫🇷 [fr](../fr/A2A-SERVER.md) · 🇩🇪 [de](../de/A2A-SERVER.md) · 🇮🇹 [it](../it/A2A-SERVER.md) · 🇷🇺 [ru](../ru/A2A-SERVER.md) · 🇨🇳 [zh-CN](../zh-CN/A2A-SERVER.md) · 🇯🇵 [ja](../ja/A2A-SERVER.md) · 🇰🇷 [ko](../ko/A2A-SERVER.md) · 🇸🇦 [ar](../ar/A2A-SERVER.md) · 🇮🇳 [in](../in/A2A-SERVER.md) · 🇹🇭 [th](../th/A2A-SERVER.md) · 🇻🇳 [vi](../vi/A2A-SERVER.md) · 🇮🇩 [id](../id/A2A-SERVER.md) · 🇲🇾 [ms](../ms/A2A-SERVER.md) · 🇳🇱 [nl](../nl/A2A-SERVER.md) · 🇵🇱 [pl](../pl/A2A-SERVER.md) · 🇸🇪 [sv](../sv/A2A-SERVER.md) · 🇳🇴 [no](../no/A2A-SERVER.md) · 🇩🇰 [da](../da/A2A-SERVER.md) · 🇫🇮 [fi](../fi/A2A-SERVER.md) · 🇵🇹 [pt](../pt/A2A-SERVER.md) · 🇷🇴 [ro](../ro/A2A-SERVER.md) · 🇭🇺 [hu](../hu/A2A-SERVER.md) · 🇧🇬 [bg](../bg/A2A-SERVER.md) · 🇸🇰 [sk](../sk/A2A-SERVER.md) · 🇺🇦 [uk-UA](../uk-UA/A2A-SERVER.md) · 🇮🇱 [he](../he/A2A-SERVER.md) · 🇵🇭 [phi](../phi/A2A-SERVER.md)
-
----
-
-# OmniRoute A2A Server Documentation
-
-> Agent-to-Agent Protocol v0.3 — OmniRoute as an intelligent routing agent
-
-## Agent Discovery
-
-```bash
-curl http://localhost:20128/.well-known/agent.json
-```
-
-Returns the Agent Card describing OmniRoute's capabilities, skills, and authentication requirements.
-
----
-
-## Authentication
-
-All `/a2a` requests require an API key via the `Authorization` header:
-
-```
-Authorization: Bearer YOUR_OMNIROUTE_API_KEY
-```
-
-If no API key is configured on the server, authentication is bypassed.
-
----
-
-## JSON-RPC 2.0 Methods
-
-### `message/send` — Synchronous Execution
-
-Sends a message to a skill and waits for the complete response.
-
-```bash
-curl -X POST http://localhost:20128/a2a \
- -H "Content-Type: application/json" \
- -H "Authorization: Bearer YOUR_KEY" \
- -d '{
- "jsonrpc": "2.0",
- "id": "1",
- "method": "message/send",
- "params": {
- "skill": "smart-routing",
- "messages": [{"role": "user", "content": "Write a hello world in Python"}],
- "metadata": {"model": "auto", "combo": "fast-coding"}
- }
- }'
-```
-
-**Response:**
-
-```json
-{
- "jsonrpc": "2.0",
- "id": "1",
- "result": {
- "task": { "id": "uuid", "state": "completed" },
- "artifacts": [{ "type": "text", "content": "..." }],
- "metadata": {
- "routing_explanation": "Selected claude-sonnet via provider \"anthropic\" (latency: 1200ms, cost: $0.003)",
- "cost_envelope": { "estimated": 0.005, "actual": 0.003, "currency": "USD" },
- "resilience_trace": [
- { "event": "primary_selected", "provider": "anthropic", "timestamp": "..." }
- ],
- "policy_verdict": { "allowed": true, "reason": "within budget and quota limits" }
- }
- }
-}
-```
-
-### `message/stream` — SSE Streaming
-
-Same as `message/send` but returns Server-Sent Events for real-time streaming.
-
-```bash
-curl -N -X POST http://localhost:20128/a2a \
- -H "Content-Type: application/json" \
- -H "Authorization: Bearer YOUR_KEY" \
- -d '{
- "jsonrpc": "2.0",
- "id": "1",
- "method": "message/stream",
- "params": {
- "skill": "smart-routing",
- "messages": [{"role": "user", "content": "Explain quantum computing"}]
- }
- }'
-```
-
-**SSE Events:**
-
-```
-data: {"jsonrpc":"2.0","method":"message/stream","params":{"task":{"id":"...","state":"working"},"chunk":{"type":"text","content":"..."}}}
-
-: heartbeat 2026-03-03T17:00:00Z
-
-data: {"jsonrpc":"2.0","method":"message/stream","params":{"task":{"id":"...","state":"completed"},"metadata":{...}}}
-```
-
-### `tasks/get` — Query Task Status
-
-```bash
-curl -X POST http://localhost:20128/a2a \
- -H "Content-Type: application/json" \
- -H "Authorization: Bearer YOUR_KEY" \
- -d '{"jsonrpc":"2.0","id":"2","method":"tasks/get","params":{"taskId":"TASK_UUID"}}'
-```
-
-### `tasks/cancel` — Cancel a Task
-
-```bash
-curl -X POST http://localhost:20128/a2a \
- -H "Content-Type: application/json" \
- -H "Authorization: Bearer YOUR_KEY" \
- -d '{"jsonrpc":"2.0","id":"3","method":"tasks/cancel","params":{"taskId":"TASK_UUID"}}'
-```
-
----
-
-## Available Skills
-
-| Skill | Description |
-| :----------------- | :------------------------------------------------------------------------------------------------------------------------------ |
-| `smart-routing` | Routes prompts through OmniRoute's intelligent pipeline. Returns response with routing explanation, cost, and resilience trace. |
-| `quota-management` | Answers natural-language queries about provider quotas, suggests free combos, and provides quota rankings. |
-
----
-
-## Task Lifecycle
-
-```
-submitted → working → completed
- → failed
- → cancelled
-```
-
-- Tasks expire after 5 minutes (configurable)
-- Terminal states: `completed`, `failed`, `cancelled`
-- Event log tracks every state transition
-
----
-
-## Error Codes
-
-| Code | Meaning |
-| :----- | :----------------------------- |
-| -32700 | Parse error (invalid JSON) |
-| -32600 | Invalid request / Unauthorized |
-| -32601 | Method or skill not found |
-| -32602 | Invalid params |
-| -32603 | Internal error |
-
----
-
-## Integration Examples
-
-### Python (requests)
-
-```python
-import requests
-
-resp = requests.post("http://localhost:20128/a2a", json={
- "jsonrpc": "2.0", "id": "1",
- "method": "message/send",
- "params": {
- "skill": "smart-routing",
- "messages": [{"role": "user", "content": "Hello"}]
- }
-}, headers={"Authorization": "Bearer YOUR_KEY"})
-
-result = resp.json()["result"]
-print(result["artifacts"][0]["content"])
-print(result["metadata"]["routing_explanation"])
-```
-
-### TypeScript (fetch)
-
-```typescript
-const resp = await fetch("http://localhost:20128/a2a", {
- method: "POST",
- headers: {
- "Content-Type": "application/json",
- Authorization: "Bearer YOUR_KEY",
- },
- body: JSON.stringify({
- jsonrpc: "2.0",
- id: "1",
- method: "message/send",
- params: {
- skill: "smart-routing",
- messages: [{ role: "user", content: "Hello" }],
- },
- }),
-});
-const { result } = await resp.json();
-console.log(result.metadata.routing_explanation);
-```
diff --git a/docs/i18n/in/API_REFERENCE.md b/docs/i18n/in/API_REFERENCE.md
deleted file mode 100644
index b878605221..0000000000
--- a/docs/i18n/in/API_REFERENCE.md
+++ /dev/null
@@ -1,455 +0,0 @@
-🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/API_REFERENCE.md) · 🇪🇸 [es](../es/API_REFERENCE.md) · 🇫🇷 [fr](../fr/API_REFERENCE.md) · 🇩🇪 [de](../de/API_REFERENCE.md) · 🇮🇹 [it](../it/API_REFERENCE.md) · 🇷🇺 [ru](../ru/API_REFERENCE.md) · 🇨🇳 [zh-CN](../zh-CN/API_REFERENCE.md) · 🇯🇵 [ja](../ja/API_REFERENCE.md) · 🇰🇷 [ko](../ko/API_REFERENCE.md) · 🇸🇦 [ar](../ar/API_REFERENCE.md) · 🇮🇳 [in](../in/API_REFERENCE.md) · 🇹🇭 [th](../th/API_REFERENCE.md) · 🇻🇳 [vi](../vi/API_REFERENCE.md) · 🇮🇩 [id](../id/API_REFERENCE.md) · 🇲🇾 [ms](../ms/API_REFERENCE.md) · 🇳🇱 [nl](../nl/API_REFERENCE.md) · 🇵🇱 [pl](../pl/API_REFERENCE.md) · 🇸🇪 [sv](../sv/API_REFERENCE.md) · 🇳🇴 [no](../no/API_REFERENCE.md) · 🇩🇰 [da](../da/API_REFERENCE.md) · 🇫🇮 [fi](../fi/API_REFERENCE.md) · 🇵🇹 [pt](../pt/API_REFERENCE.md) · 🇷🇴 [ro](../ro/API_REFERENCE.md) · 🇭🇺 [hu](../hu/API_REFERENCE.md) · 🇧🇬 [bg](../bg/API_REFERENCE.md) · 🇸🇰 [sk](../sk/API_REFERENCE.md) · 🇺🇦 [uk-UA](../uk-UA/API_REFERENCE.md) · 🇮🇱 [he](../he/API_REFERENCE.md) · 🇵🇭 [phi](../phi/API_REFERENCE.md)
-
----
-
-# API Reference
-
-🌐 **Languages:** 🇺🇸 [English](API_REFERENCE.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/API_REFERENCE.md) | 🇪🇸 [Español](i18n/es/API_REFERENCE.md) | 🇫🇷 [Français](i18n/fr/API_REFERENCE.md) | 🇮🇹 [Italiano](i18n/it/API_REFERENCE.md) | 🇷🇺 [Русский](i18n/ru/API_REFERENCE.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/API_REFERENCE.md) | 🇩🇪 [Deutsch](i18n/de/API_REFERENCE.md) | 🇮🇳 [हिन्दी](i18n/in/API_REFERENCE.md) | 🇹🇭 [ไทย](i18n/th/API_REFERENCE.md) | 🇺🇦 [Українська](i18n/uk-UA/API_REFERENCE.md) | 🇸🇦 [العربية](i18n/ar/API_REFERENCE.md) | 🇯🇵 [日本語](i18n/ja/API_REFERENCE.md) | 🇻🇳 [Tiếng Việt](i18n/vi/API_REFERENCE.md) | 🇧🇬 [Български](i18n/bg/API_REFERENCE.md) | 🇩🇰 [Dansk](i18n/da/API_REFERENCE.md) | 🇫🇮 [Suomi](i18n/fi/API_REFERENCE.md) | 🇮🇱 [עברית](i18n/he/API_REFERENCE.md) | 🇭🇺 [Magyar](i18n/hu/API_REFERENCE.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/API_REFERENCE.md) | 🇰🇷 [한국어](i18n/ko/API_REFERENCE.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/API_REFERENCE.md) | 🇳🇱 [Nederlands](i18n/nl/API_REFERENCE.md) | 🇳🇴 [Norsk](i18n/no/API_REFERENCE.md) | 🇵🇹 [Português (Portugal)](i18n/pt/API_REFERENCE.md) | 🇷🇴 [Română](i18n/ro/API_REFERENCE.md) | 🇵🇱 [Polski](i18n/pl/API_REFERENCE.md) | 🇸🇰 [Slovenčina](i18n/sk/API_REFERENCE.md) | 🇸🇪 [Svenska](i18n/sv/API_REFERENCE.md) | 🇵🇭 [Filipino](i18n/phi/API_REFERENCE.md)
-
-Complete reference for all OmniRoute API endpoints.
-
----
-
-## Table of Contents
-
-- [Chat Completions](#chat-completions)
-- [Embeddings](#embeddings)
-- [Image Generation](#image-generation)
-- [List Models](#list-models)
-- [Compatibility Endpoints](#compatibility-endpoints)
-- [Semantic Cache](#semantic-cache)
-- [Dashboard & Management](#dashboard--management)
-- [Request Processing](#request-processing)
-- [Authentication](#authentication)
-
----
-
-## Chat Completions
-
-```bash
-POST /v1/chat/completions
-Authorization: Bearer your-api-key
-Content-Type: application/json
-
-{
- "model": "cc/claude-opus-4-6",
- "messages": [
- {"role": "user", "content": "Write a function to..."}
- ],
- "stream": true
-}
-```
-
-### Custom Headers
-
-| Header | Direction | Description |
-| ------------------------ | --------- | --------------------------------- |
-| `X-OmniRoute-No-Cache` | Request | Set to `true` to bypass cache |
-| `X-OmniRoute-Progress` | Request | Set to `true` for progress events |
-| `Idempotency-Key` | Request | Dedup key (5s window) |
-| `X-Request-Id` | Request | Alternative dedup key |
-| `X-OmniRoute-Cache` | Response | `HIT` or `MISS` (non-streaming) |
-| `X-OmniRoute-Idempotent` | Response | `true` if deduplicated |
-| `X-OmniRoute-Progress` | Response | `enabled` if progress tracking on |
-
----
-
-## Embeddings
-
-```bash
-POST /v1/embeddings
-Authorization: Bearer your-api-key
-Content-Type: application/json
-
-{
- "model": "nebius/Qwen/Qwen3-Embedding-8B",
- "input": "The food was delicious"
-}
-```
-
-Available providers: Nebius, OpenAI, Mistral, Together AI, Fireworks, NVIDIA.
-
-```bash
-# List all embedding models
-GET /v1/embeddings
-```
-
----
-
-## Image Generation
-
-```bash
-POST /v1/images/generations
-Authorization: Bearer your-api-key
-Content-Type: application/json
-
-{
- "model": "openai/dall-e-3",
- "prompt": "A beautiful sunset over mountains",
- "size": "1024x1024"
-}
-```
-
-Available providers: OpenAI (DALL-E), xAI (Grok Image), Together AI (FLUX), Fireworks AI.
-
-```bash
-# List all image models
-GET /v1/images/generations
-```
-
----
-
-## List Models
-
-```bash
-GET /v1/models
-Authorization: Bearer your-api-key
-
-→ Returns all chat, embedding, and image models + combos in OpenAI format
-```
-
----
-
-## Compatibility Endpoints
-
-| Method | Path | Format |
-| ------ | --------------------------- | ---------------------- |
-| POST | `/v1/chat/completions` | OpenAI |
-| POST | `/v1/messages` | Anthropic |
-| POST | `/v1/responses` | OpenAI Responses |
-| POST | `/v1/embeddings` | OpenAI |
-| POST | `/v1/images/generations` | OpenAI |
-| GET | `/v1/models` | OpenAI |
-| POST | `/v1/messages/count_tokens` | Anthropic |
-| GET | `/v1beta/models` | Gemini |
-| POST | `/v1beta/models/{...path}` | Gemini generateContent |
-| POST | `/v1/api/chat` | Ollama |
-
-### Dedicated Provider Routes
-
-```bash
-POST /v1/providers/{provider}/chat/completions
-POST /v1/providers/{provider}/embeddings
-POST /v1/providers/{provider}/images/generations
-```
-
-The provider prefix is auto-added if missing. Mismatched models return `400`.
-
----
-
-## Semantic Cache
-
-```bash
-# Get cache stats
-GET /api/cache
-
-# Clear all caches
-DELETE /api/cache
-```
-
-Response example:
-
-```json
-{
- "semanticCache": {
- "memorySize": 42,
- "memoryMaxSize": 500,
- "dbSize": 128,
- "hitRate": 0.65
- },
- "idempotency": {
- "activeKeys": 3,
- "windowMs": 5000
- }
-}
-```
-
----
-
-## Dashboard & Management
-
-### Authentication
-
-| Endpoint | Method | Description |
-| ----------------------------- | ------- | --------------------- |
-| `/api/auth/login` | POST | Login |
-| `/api/auth/logout` | POST | Logout |
-| `/api/settings/require-login` | GET/PUT | Toggle login required |
-
-### Provider Management
-
-| Endpoint | Method | Description |
-| ---------------------------- | --------------- | ------------------------ |
-| `/api/providers` | GET/POST | List / create providers |
-| `/api/providers/[id]` | GET/PUT/DELETE | Manage a provider |
-| `/api/providers/[id]/test` | POST | Test provider connection |
-| `/api/providers/[id]/models` | GET | List provider models |
-| `/api/providers/validate` | POST | Validate provider config |
-| `/api/provider-nodes*` | Various | Provider node management |
-| `/api/provider-models` | GET/POST/DELETE | Custom models |
-
-### OAuth Flows
-
-| Endpoint | Method | Description |
-| -------------------------------- | ------- | ----------------------- |
-| `/api/oauth/[provider]/[action]` | Various | Provider-specific OAuth |
-
-### Routing & Config
-
-| Endpoint | Method | Description |
-| --------------------- | -------- | ----------------------------- |
-| `/api/models/alias` | GET/POST | Model aliases |
-| `/api/models/catalog` | GET | All models by provider + type |
-| `/api/combos*` | Various | Combo management |
-| `/api/keys*` | Various | API key management |
-| `/api/pricing` | GET | Model pricing |
-
-### Usage & Analytics
-
-| Endpoint | Method | Description |
-| --------------------------- | ------ | -------------------- |
-| `/api/usage/history` | GET | Usage history |
-| `/api/usage/logs` | GET | Usage logs |
-| `/api/usage/request-logs` | GET | Request-level logs |
-| `/api/usage/[connectionId]` | GET | Per-connection usage |
-
-### Settings
-
-| Endpoint | Method | Description |
-| ------------------------------- | ------- | ---------------------- |
-| `/api/settings` | GET/PUT | General settings |
-| `/api/settings/proxy` | GET/PUT | Network proxy config |
-| `/api/settings/proxy/test` | POST | Test proxy connection |
-| `/api/settings/ip-filter` | GET/PUT | IP allowlist/blocklist |
-| `/api/settings/thinking-budget` | GET/PUT | Reasoning token budget |
-| `/api/settings/system-prompt` | GET/PUT | Global system prompt |
-
-### Monitoring
-
-| Endpoint | Method | Description |
-| ------------------------ | ---------- | ----------------------- |
-| `/api/sessions` | GET | Active session tracking |
-| `/api/rate-limits` | GET | Per-account rate limits |
-| `/api/monitoring/health` | GET | Health check |
-| `/api/cache` | GET/DELETE | Cache stats / clear |
-
-### Backup & Export/Import
-
-| Endpoint | Method | Description |
-| --------------------------- | ------ | --------------------------------------- |
-| `/api/db-backups` | GET | List available backups |
-| `/api/db-backups` | PUT | Create a manual backup |
-| `/api/db-backups` | POST | Restore from a specific backup |
-| `/api/db-backups/export` | GET | Download database as .sqlite file |
-| `/api/db-backups/import` | POST | Upload .sqlite file to replace database |
-| `/api/db-backups/exportAll` | GET | Download full backup as .tar.gz archive |
-
-### Cloud Sync
-
-| Endpoint | Method | Description |
-| ---------------------- | ------- | --------------------- |
-| `/api/sync/cloud` | Various | Cloud sync operations |
-| `/api/sync/initialize` | POST | Initialize sync |
-| `/api/cloud/*` | Various | Cloud management |
-
-### CLI Tools
-
-| Endpoint | Method | Description |
-| ---------------------------------- | ------ | ------------------- |
-| `/api/cli-tools/claude-settings` | GET | Claude CLI status |
-| `/api/cli-tools/codex-settings` | GET | Codex CLI status |
-| `/api/cli-tools/droid-settings` | GET | Droid CLI status |
-| `/api/cli-tools/openclaw-settings` | GET | OpenClaw CLI status |
-| `/api/cli-tools/runtime/[toolId]` | GET | Generic CLI runtime |
-
-CLI responses include: `installed`, `runnable`, `command`, `commandPath`, `runtimeMode`, `reason`.
-
-### ACP Agents
-
-| Endpoint | Method | Description |
-| ----------------- | ------ | -------------------------------------------------------- |
-| `/api/acp/agents` | GET | List all detected agents (built-in + custom) with status |
-| `/api/acp/agents` | POST | Add custom agent or refresh detection cache |
-| `/api/acp/agents` | DELETE | Remove a custom agent by `id` query param |
-
-GET response includes `agents[]` (id, name, binary, version, installed, protocol, isCustom) and `summary` (total, installed, notFound, builtIn, custom).
-
-### Resilience & Rate Limits
-
-| Endpoint | Method | Description |
-| ----------------------- | ------- | ------------------------------- |
-| `/api/resilience` | GET/PUT | Get/update resilience profiles |
-| `/api/resilience/reset` | POST | Reset circuit breakers |
-| `/api/rate-limits` | GET | Per-account rate limit status |
-| `/api/rate-limit` | GET | Global rate limit configuration |
-
-### Evals
-
-| Endpoint | Method | Description |
-| ------------ | -------- | --------------------------------- |
-| `/api/evals` | GET/POST | List eval suites / run evaluation |
-
-### Policies
-
-| Endpoint | Method | Description |
-| --------------- | --------------- | ----------------------- |
-| `/api/policies` | GET/POST/DELETE | Manage routing policies |
-
-### Compliance
-
-| Endpoint | Method | Description |
-| --------------------------- | ------ | ----------------------------- |
-| `/api/compliance/audit-log` | GET | Compliance audit log (last N) |
-
-### v1beta (Gemini-Compatible)
-
-| Endpoint | Method | Description |
-| -------------------------- | ------ | --------------------------------- |
-| `/v1beta/models` | GET | List models in Gemini format |
-| `/v1beta/models/{...path}` | POST | Gemini `generateContent` endpoint |
-
-These endpoints mirror Gemini's API format for clients that expect native Gemini SDK compatibility.
-
-### Internal / System APIs
-
-| Endpoint | Method | Description |
-| --------------- | ------ | ---------------------------------------------------- |
-| `/api/init` | GET | Application initialization check (used on first run) |
-| `/api/tags` | GET | Ollama-compatible model tags (for Ollama clients) |
-| `/api/restart` | POST | Trigger graceful server restart |
-| `/api/shutdown` | POST | Trigger graceful server shutdown |
-
-> **Note:** These endpoints are used internally by the system or for Ollama client compatibility. They are not typically called by end users.
-
----
-
-## Audio Transcription
-
-```bash
-POST /v1/audio/transcriptions
-Authorization: Bearer your-api-key
-Content-Type: multipart/form-data
-```
-
-Transcribe audio files using Deepgram or AssemblyAI.
-
-**Request:**
-
-```bash
-curl -X POST http://localhost:20128/v1/audio/transcriptions \
- -H "Authorization: Bearer your-api-key" \
- -F "file=@recording.mp3" \
- -F "model=deepgram/nova-3"
-```
-
-**Response:**
-
-```json
-{
- "text": "Hello, this is the transcribed audio content.",
- "task": "transcribe",
- "language": "en",
- "duration": 12.5
-}
-```
-
-**Supported providers:** `deepgram/nova-3`, `assemblyai/best`.
-
-**Supported formats:** `mp3`, `wav`, `m4a`, `flac`, `ogg`, `webm`.
-
----
-
-## Ollama Compatibility
-
-For clients that use Ollama's API format:
-
-```bash
-# Chat endpoint (Ollama format)
-POST /v1/api/chat
-
-# Model listing (Ollama format)
-GET /api/tags
-```
-
-Requests are automatically translated between Ollama and internal formats.
-
----
-
-## Telemetry
-
-```bash
-# Get latency telemetry summary (p50/p95/p99 per provider)
-GET /api/telemetry/summary
-```
-
-**Response:**
-
-```json
-{
- "providers": {
- "claudeCode": { "p50": 245, "p95": 890, "p99": 1200, "count": 150 },
- "github": { "p50": 180, "p95": 620, "p99": 950, "count": 320 }
- }
-}
-```
-
----
-
-## Budget
-
-```bash
-# Get budget status for all API keys
-GET /api/usage/budget
-
-# Set or update a budget
-POST /api/usage/budget
-Content-Type: application/json
-
-{
- "keyId": "key-123",
- "limit": 50.00,
- "period": "monthly"
-}
-```
-
----
-
-## Model Availability
-
-```bash
-# Get real-time model availability across all providers
-GET /api/models/availability
-
-# Check availability for a specific model
-POST /api/models/availability
-Content-Type: application/json
-
-{
- "model": "claude-sonnet-4-5-20250929"
-}
-```
-
----
-
-## Request Processing
-
-1. Client sends request to `/v1/*`
-2. Route handler calls `handleChat`, `handleEmbedding`, `handleAudioTranscription`, or `handleImageGeneration`
-3. Model is resolved (direct provider/model or alias/combo)
-4. Credentials selected from local DB with account availability filtering
-5. For chat: `handleChatCore` — format detection, translation, cache check, idempotency check
-6. Provider executor sends upstream request
-7. Response translated back to client format (chat) or returned as-is (embeddings/images/audio)
-8. Usage/logging recorded
-9. Fallback applies on errors according to combo rules
-
-Full architecture reference: [`ARCHITECTURE.md`](ARCHITECTURE.md)
-
----
-
-## Authentication
-
-- Dashboard routes (`/dashboard/*`) use `auth_token` cookie
-- Login uses saved password hash; fallback to `INITIAL_PASSWORD`
-- `requireLogin` toggleable via `/api/settings/require-login`
-- `/v1/*` routes optionally require Bearer API key when `REQUIRE_API_KEY=true`
diff --git a/docs/i18n/in/ARCHITECTURE.md b/docs/i18n/in/ARCHITECTURE.md
deleted file mode 100644
index 4ea06a29f2..0000000000
--- a/docs/i18n/in/ARCHITECTURE.md
+++ /dev/null
@@ -1,787 +0,0 @@
-🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/ARCHITECTURE.md) · 🇪🇸 [es](../es/ARCHITECTURE.md) · 🇫🇷 [fr](../fr/ARCHITECTURE.md) · 🇩🇪 [de](../de/ARCHITECTURE.md) · 🇮🇹 [it](../it/ARCHITECTURE.md) · 🇷🇺 [ru](../ru/ARCHITECTURE.md) · 🇨🇳 [zh-CN](../zh-CN/ARCHITECTURE.md) · 🇯🇵 [ja](../ja/ARCHITECTURE.md) · 🇰🇷 [ko](../ko/ARCHITECTURE.md) · 🇸🇦 [ar](../ar/ARCHITECTURE.md) · 🇮🇳 [in](../in/ARCHITECTURE.md) · 🇹🇭 [th](../th/ARCHITECTURE.md) · 🇻🇳 [vi](../vi/ARCHITECTURE.md) · 🇮🇩 [id](../id/ARCHITECTURE.md) · 🇲🇾 [ms](../ms/ARCHITECTURE.md) · 🇳🇱 [nl](../nl/ARCHITECTURE.md) · 🇵🇱 [pl](../pl/ARCHITECTURE.md) · 🇸🇪 [sv](../sv/ARCHITECTURE.md) · 🇳🇴 [no](../no/ARCHITECTURE.md) · 🇩🇰 [da](../da/ARCHITECTURE.md) · 🇫🇮 [fi](../fi/ARCHITECTURE.md) · 🇵🇹 [pt](../pt/ARCHITECTURE.md) · 🇷🇴 [ro](../ro/ARCHITECTURE.md) · 🇭🇺 [hu](../hu/ARCHITECTURE.md) · 🇧🇬 [bg](../bg/ARCHITECTURE.md) · 🇸🇰 [sk](../sk/ARCHITECTURE.md) · 🇺🇦 [uk-UA](../uk-UA/ARCHITECTURE.md) · 🇮🇱 [he](../he/ARCHITECTURE.md) · 🇵🇭 [phi](../phi/ARCHITECTURE.md)
-
----
-
-# OmniRoute Architecture
-
-🌐 **Languages:** 🇺🇸 [English](ARCHITECTURE.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/ARCHITECTURE.md) | 🇪🇸 [Español](i18n/es/ARCHITECTURE.md) | 🇫🇷 [Français](i18n/fr/ARCHITECTURE.md) | 🇮🇹 [Italiano](i18n/it/ARCHITECTURE.md) | 🇷🇺 [Русский](i18n/ru/ARCHITECTURE.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/ARCHITECTURE.md) | 🇩🇪 [Deutsch](i18n/de/ARCHITECTURE.md) | 🇮🇳 [हिन्दी](i18n/in/ARCHITECTURE.md) | 🇹🇭 [ไทย](i18n/th/ARCHITECTURE.md) | 🇺🇦 [Українська](i18n/uk-UA/ARCHITECTURE.md) | 🇸🇦 [العربية](i18n/ar/ARCHITECTURE.md) | 🇯🇵 [日本語](i18n/ja/ARCHITECTURE.md) | 🇻🇳 [Tiếng Việt](i18n/vi/ARCHITECTURE.md) | 🇧🇬 [Български](i18n/bg/ARCHITECTURE.md) | 🇩🇰 [Dansk](i18n/da/ARCHITECTURE.md) | 🇫🇮 [Suomi](i18n/fi/ARCHITECTURE.md) | 🇮🇱 [עברית](i18n/he/ARCHITECTURE.md) | 🇭🇺 [Magyar](i18n/hu/ARCHITECTURE.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/ARCHITECTURE.md) | 🇰🇷 [한국어](i18n/ko/ARCHITECTURE.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/ARCHITECTURE.md) | 🇳🇱 [Nederlands](i18n/nl/ARCHITECTURE.md) | 🇳🇴 [Norsk](i18n/no/ARCHITECTURE.md) | 🇵🇹 [Português (Portugal)](i18n/pt/ARCHITECTURE.md) | 🇷🇴 [Română](i18n/ro/ARCHITECTURE.md) | 🇵🇱 [Polski](i18n/pl/ARCHITECTURE.md) | 🇸🇰 [Slovenčina](i18n/sk/ARCHITECTURE.md) | 🇸🇪 [Svenska](i18n/sv/ARCHITECTURE.md) | 🇵🇭 [Filipino](i18n/phi/ARCHITECTURE.md)
-
-_Last updated: 2026-03-04_
-
-## Executive Summary
-
-OmniRoute is a local AI routing gateway and dashboard built on Next.js.
-It provides a single OpenAI-compatible endpoint (`/v1/*`) and routes traffic across multiple upstream providers with translation, fallback, token refresh, and usage tracking.
-
-Core capabilities:
-
-- OpenAI-compatible API surface for CLI/tools (28 providers)
-- Request/response translation across provider formats
-- Model combo fallback (multi-model sequence)
-- Account-level fallback (multi-account per provider)
-- OAuth + API-key provider connection management
-- Embedding generation via `/v1/embeddings` (6 providers, 9 models)
-- Image generation via `/v1/images/generations` (4 providers, 9 models)
-- Think tag parsing (`...`) for reasoning models
-- Response sanitization for strict OpenAI SDK compatibility
-- Role normalization (developer→system, system→user) for cross-provider compatibility
-- Structured output conversion (json_schema → Gemini responseSchema)
-- Local persistence for providers, keys, aliases, combos, settings, pricing
-- Usage/cost tracking and request logging
-- Optional cloud sync for multi-device/state sync
-- IP allowlist/blocklist for API access control
-- Thinking budget management (passthrough/auto/custom/adaptive)
-- Global system prompt injection
-- Session tracking and fingerprinting
-- Per-account enhanced rate limiting with provider-specific profiles
-- Circuit breaker pattern for provider resilience
-- Anti-thundering herd protection with mutex locking
-- Signature-based request deduplication cache
-- Domain layer: model availability, cost rules, fallback policy, lockout policy
-- Domain state persistence (SQLite write-through cache for fallbacks, budgets, lockouts, circuit breakers)
-- Policy engine for centralized request evaluation (lockout → budget → fallback)
-- Request telemetry with p50/p95/p99 latency aggregation
-- Correlation ID (X-Request-Id) for end-to-end tracing
-- Compliance audit logging with opt-out per API key
-- Eval framework for LLM quality assurance
-- Resilience UI dashboard with real-time circuit breaker status
-- Modular OAuth providers (12 individual modules under `src/lib/oauth/providers/`)
-
-Primary runtime model:
-
-- Next.js app routes under `src/app/api/*` implement both dashboard APIs and compatibility APIs
-- A shared SSE/routing core in `src/sse/*` + `open-sse/*` handles provider execution, translation, streaming, fallback, and usage
-
-## Scope and Boundaries
-
-### In Scope
-
-- Local gateway runtime
-- Dashboard management APIs
-- Provider authentication and token refresh
-- Request translation and SSE streaming
-- Local state + usage persistence
-- Optional cloud sync orchestration
-
-### Out of Scope
-
-- Cloud service implementation behind `NEXT_PUBLIC_CLOUD_URL`
-- Provider SLA/control plane outside local process
-- External CLI binaries themselves (Claude CLI, Codex CLI, etc.)
-
-## High-Level System Context
-
-```mermaid
-flowchart LR
- subgraph Clients[Developer Clients]
- C1[Claude Code]
- C2[Codex CLI]
- C3[OpenClaw / Droid / Cline / Continue / Roo]
- C4[Custom OpenAI-compatible clients]
- BROWSER[Browser Dashboard]
- end
-
- subgraph Router[OmniRoute Local Process]
- API[V1 Compatibility API\n/v1/*]
- DASH[Dashboard + Management API\n/api/*]
- CORE[SSE + Translation Core\nopen-sse + src/sse]
- DB[(storage.sqlite)]
- UDB[(usage tables + log artifacts)]
- end
-
- subgraph Upstreams[Upstream Providers]
- P1[OAuth Providers\nClaude/Codex/Gemini/Qwen/Qoder/GitHub/Kiro/Cursor/Antigravity]
- P2[API Key Providers\nOpenAI/Anthropic/OpenRouter/GLM/Kimi/MiniMax\nDeepSeek/Groq/xAI/Mistral/Perplexity\nTogether/Fireworks/Cerebras/Cohere/NVIDIA]
- P3[Compatible Nodes\nOpenAI-compatible / Anthropic-compatible]
- end
-
- subgraph Cloud[Optional Cloud Sync]
- CLOUD[Cloud Sync Endpoint\nNEXT_PUBLIC_CLOUD_URL]
- end
-
- C1 --> API
- C2 --> API
- C3 --> API
- C4 --> API
- BROWSER --> DASH
-
- API --> CORE
- DASH --> DB
- CORE --> DB
- CORE --> UDB
-
- CORE --> P1
- CORE --> P2
- CORE --> P3
-
- DASH --> CLOUD
-```
-
-## Core Runtime Components
-
-## 1) API and Routing Layer (Next.js App Routes)
-
-Main directories:
-
-- `src/app/api/v1/*` and `src/app/api/v1beta/*` for compatibility APIs
-- `src/app/api/*` for management/configuration APIs
-- Next rewrites in `next.config.mjs` map `/v1/*` to `/api/v1/*`
-
-Important compatibility routes:
-
-- `src/app/api/v1/chat/completions/route.ts`
-- `src/app/api/v1/messages/route.ts`
-- `src/app/api/v1/responses/route.ts`
-- `src/app/api/v1/models/route.ts` — includes custom models with `custom: true`
-- `src/app/api/v1/embeddings/route.ts` — embedding generation (6 providers)
-- `src/app/api/v1/images/generations/route.ts` — image generation (4+ providers incl. Antigravity/Nebius)
-- `src/app/api/v1/messages/count_tokens/route.ts`
-- `src/app/api/v1/providers/[provider]/chat/completions/route.ts` — dedicated per-provider chat
-- `src/app/api/v1/providers/[provider]/embeddings/route.ts` — dedicated per-provider embeddings
-- `src/app/api/v1/providers/[provider]/images/generations/route.ts` — dedicated per-provider images
-- `src/app/api/v1beta/models/route.ts`
-- `src/app/api/v1beta/models/[...path]/route.ts`
-
-Management domains:
-
-- Auth/settings: `src/app/api/auth/*`, `src/app/api/settings/*`
-- Providers/connections: `src/app/api/providers*`
-- Provider nodes: `src/app/api/provider-nodes*`
-- Custom models: `src/app/api/provider-models` (GET/POST/DELETE)
-- Model catalog: `src/app/api/models/route.ts` (GET)
-- Proxy config: `src/app/api/settings/proxy` (GET/PUT/DELETE) + `src/app/api/settings/proxy/test` (POST)
-- OAuth: `src/app/api/oauth/*`
-- Keys/aliases/combos/pricing: `src/app/api/keys*`, `src/app/api/models/alias`, `src/app/api/combos*`, `src/app/api/pricing`
-- Usage: `src/app/api/usage/*`
-- Sync/cloud: `src/app/api/sync/*`, `src/app/api/cloud/*`
-- CLI tooling helpers: `src/app/api/cli-tools/*`
-- IP filter: `src/app/api/settings/ip-filter` (GET/PUT)
-- Thinking budget: `src/app/api/settings/thinking-budget` (GET/PUT)
-- System prompt: `src/app/api/settings/system-prompt` (GET/PUT)
-- Sessions: `src/app/api/sessions` (GET)
-- Rate limits: `src/app/api/rate-limits` (GET)
-- Resilience: `src/app/api/resilience` (GET/PATCH) — provider profiles, circuit breaker, rate limit state
-- Resilience reset: `src/app/api/resilience/reset` (POST) — reset breakers + cooldowns
-- Cache stats: `src/app/api/cache/stats` (GET/DELETE)
-- Model availability: `src/app/api/models/availability` (GET/POST)
-- Telemetry: `src/app/api/telemetry/summary` (GET)
-- Budget: `src/app/api/usage/budget` (GET/POST)
-- Fallback chains: `src/app/api/fallback/chains` (GET/POST/DELETE)
-- Compliance audit: `src/app/api/compliance/audit-log` (GET)
-- Evals: `src/app/api/evals` (GET/POST), `src/app/api/evals/[suiteId]` (GET)
-- Policies: `src/app/api/policies` (GET/POST)
-
-## 2) SSE + Translation Core
-
-Main flow modules:
-
-- Entry: `src/sse/handlers/chat.ts`
-- Core orchestration: `open-sse/handlers/chatCore.ts`
-- Provider execution adapters: `open-sse/executors/*`
-- Format detection/provider config: `open-sse/services/provider.ts`
-- Model parse/resolve: `src/sse/services/model.ts`, `open-sse/services/model.ts`
-- Account fallback logic: `open-sse/services/accountFallback.ts`
-- Translation registry: `open-sse/translator/index.ts`
-- Stream transformations: `open-sse/utils/stream.ts`, `open-sse/utils/streamHandler.ts`
-- Usage extraction/normalization: `open-sse/utils/usageTracking.ts`
-- Think tag parser: `open-sse/utils/thinkTagParser.ts`
-- Embedding handler: `open-sse/handlers/embeddings.ts`
-- Embedding provider registry: `open-sse/config/embeddingRegistry.ts`
-- Image generation handler: `open-sse/handlers/imageGeneration.ts`
-- Image provider registry: `open-sse/config/imageRegistry.ts`
-- Response sanitization: `open-sse/handlers/responseSanitizer.ts`
-- Role normalization: `open-sse/services/roleNormalizer.ts`
-
-Services (business logic):
-
-- Account selection/scoring: `open-sse/services/accountSelector.ts`
-- Context lifecycle management: `open-sse/services/contextManager.ts`
-- IP filter enforcement: `open-sse/services/ipFilter.ts`
-- Session tracking: `open-sse/services/sessionManager.ts`
-- Request deduplication: `open-sse/services/signatureCache.ts`
-- System prompt injection: `open-sse/services/systemPrompt.ts`
-- Thinking budget management: `open-sse/services/thinkingBudget.ts`
-- Wildcard model routing: `open-sse/services/wildcardRouter.ts`
-- Rate limit management: `open-sse/services/rateLimitManager.ts`
-- Circuit breaker: `open-sse/services/circuitBreaker.ts`
-
-Domain layer modules:
-
-- Model availability: `src/lib/domain/modelAvailability.ts`
-- Cost rules/budgets: `src/lib/domain/costRules.ts`
-- Fallback policy: `src/lib/domain/fallbackPolicy.ts`
-- Combo resolver: `src/lib/domain/comboResolver.ts`
-- Lockout policy: `src/lib/domain/lockoutPolicy.ts`
-- Policy engine: `src/domain/policyEngine.ts` — centralized lockout → budget → fallback evaluation
-- Error codes catalog: `src/lib/domain/errorCodes.ts`
-- Request ID: `src/lib/domain/requestId.ts`
-- Fetch timeout: `src/lib/domain/fetchTimeout.ts`
-- Request telemetry: `src/lib/domain/requestTelemetry.ts`
-- Compliance/audit: `src/lib/domain/compliance/index.ts`
-- Eval runner: `src/lib/domain/evalRunner.ts`
-- Domain state persistence: `src/lib/db/domainState.ts` — SQLite CRUD for fallback chains, budgets, cost history, lockout state, circuit breakers
-
-OAuth provider modules (12 individual files under `src/lib/oauth/providers/`):
-
-- Registry index: `src/lib/oauth/providers/index.ts`
-- Individual providers: `claude.ts`, `codex.ts`, `gemini.ts`, `antigravity.ts`, `qoder.ts`, `qwen.ts`, `kimi-coding.ts`, `github.ts`, `kiro.ts`, `cursor.ts`, `kilocode.ts`, `cline.ts`
-- Thin wrapper: `src/lib/oauth/providers.ts` — re-exports from individual modules
-
-## 3) Persistence Layer
-
-Primary state DB (SQLite):
-
-- Core infra: `src/lib/db/core.ts` (better-sqlite3, migrations, WAL)
-- Re-export facade: `src/lib/localDb.ts` (thin compatibility layer for callers)
-- file: `${DATA_DIR}/storage.sqlite` (or `$XDG_CONFIG_HOME/omniroute/storage.sqlite` when set, else `~/.omniroute/storage.sqlite`)
-- entities (tables + KV namespaces): providerConnections, providerNodes, modelAliases, combos, apiKeys, settings, pricing, **customModels**, **proxyConfig**, **ipFilter**, **thinkingBudget**, **systemPrompt**
-
-Usage persistence:
-
-- facade: `src/lib/usageDb.ts` (decomposed modules in `src/lib/usage/*`)
-- SQLite tables in `storage.sqlite`: `usage_history`, `call_logs`, `proxy_logs`
-- optional file artifacts remain for compatibility/debug (`${DATA_DIR}/log.txt`, `${DATA_DIR}/call_logs/`, `/logs/...`)
-- legacy JSON files are migrated to SQLite by startup migrations when present
-
-Domain State DB (SQLite):
-
-- `src/lib/db/domainState.ts` — CRUD operations for domain state
-- Tables (created in `src/lib/db/core.ts`): `domain_fallback_chains`, `domain_budgets`, `domain_cost_history`, `domain_lockout_state`, `domain_circuit_breakers`
-- Write-through cache pattern: in-memory Maps are authoritative at runtime; mutations are written synchronously to SQLite; state is restored from DB on cold start
-
-## 4) Auth + Security Surfaces
-
-- Dashboard cookie auth: `src/proxy.ts`, `src/app/api/auth/login/route.ts`
-- API key generation/verification: `src/shared/utils/apiKey.ts`
-- Provider secrets persisted in `providerConnections` entries
-- Outbound proxy support via `open-sse/utils/proxyFetch.ts` (env vars) and `open-sse/utils/networkProxy.ts` (configurable per-provider or global)
-
-## 5) Cloud Sync
-
-- Scheduler init: `src/lib/initCloudSync.ts`, `src/shared/services/initializeCloudSync.ts`
-- Periodic task: `src/shared/services/cloudSyncScheduler.ts`
-- Control route: `src/app/api/sync/cloud/route.ts`
-
-## Request Lifecycle (`/v1/chat/completions`)
-
-```mermaid
-sequenceDiagram
- autonumber
- participant Client as CLI/SDK Client
- participant Route as /api/v1/chat/completions
- participant Chat as src/sse/handlers/chat
- participant Core as open-sse/handlers/chatCore
- participant Model as Model Resolver
- participant Auth as Credential Selector
- participant Exec as Provider Executor
- participant Prov as Upstream Provider
- participant Stream as Stream Translator
- participant Usage as usageDb
-
- Client->>Route: POST /v1/chat/completions
- Route->>Chat: handleChat(request)
- Chat->>Model: parse/resolve model or combo
-
- alt Combo model
- Chat->>Chat: iterate combo models (handleComboChat)
- end
-
- Chat->>Auth: getProviderCredentials(provider)
- Auth-->>Chat: active account + tokens/api key
-
- Chat->>Core: handleChatCore(body, modelInfo, credentials)
- Core->>Core: detect source format
- Core->>Core: translate request to target format
- Core->>Exec: execute(provider, transformedBody)
- Exec->>Prov: upstream API call
- Prov-->>Exec: SSE/JSON response
- Exec-->>Core: response + metadata
-
- alt 401/403
- Core->>Exec: refreshCredentials()
- Exec-->>Core: updated tokens
- Core->>Exec: retry request
- end
-
- Core->>Stream: translate/normalize stream to client format
- Stream-->>Client: SSE chunks / JSON response
-
- Stream->>Usage: extract usage + persist history/log
-```
-
-## Combo + Account Fallback Flow
-
-```mermaid
-flowchart TD
- A[Incoming model string] --> B{Is combo name?}
- B -- Yes --> C[Load combo models sequence]
- B -- No --> D[Single model path]
-
- C --> E[Try model N]
- E --> F[Resolve provider/model]
- D --> F
-
- F --> G[Select account credentials]
- G --> H{Credentials available?}
- H -- No --> I[Return provider unavailable]
- H -- Yes --> J[Execute request]
-
- J --> K{Success?}
- K -- Yes --> L[Return response]
- K -- No --> M{Fallback-eligible error?}
-
- M -- No --> N[Return error]
- M -- Yes --> O[Mark account unavailable cooldown]
- O --> P{Another account for provider?}
- P -- Yes --> G
- P -- No --> Q{In combo with next model?}
- Q -- Yes --> E
- Q -- No --> R[Return all unavailable]
-```
-
-Fallback decisions are driven by `open-sse/services/accountFallback.ts` using status codes and error-message heuristics.
-
-## OAuth Onboarding and Token Refresh Lifecycle
-
-```mermaid
-sequenceDiagram
- autonumber
- participant UI as Dashboard UI
- participant OAuth as /api/oauth/[provider]/[action]
- participant ProvAuth as Provider Auth Server
- participant DB as localDb
- participant Test as /api/providers/[id]/test
- participant Exec as Provider Executor
-
- UI->>OAuth: GET authorize or device-code
- OAuth->>ProvAuth: create auth/device flow
- ProvAuth-->>OAuth: auth URL or device code payload
- OAuth-->>UI: flow data
-
- UI->>OAuth: POST exchange or poll
- OAuth->>ProvAuth: token exchange/poll
- ProvAuth-->>OAuth: access/refresh tokens
- OAuth->>DB: createProviderConnection(oauth data)
- OAuth-->>UI: success + connection id
-
- UI->>Test: POST /api/providers/[id]/test
- Test->>Exec: validate credentials / optional refresh
- Exec-->>Test: valid or refreshed token info
- Test->>DB: update status/tokens/errors
- Test-->>UI: validation result
-```
-
-Refresh during live traffic is executed inside `open-sse/handlers/chatCore.ts` via executor `refreshCredentials()`.
-
-## Cloud Sync Lifecycle (Enable / Sync / Disable)
-
-```mermaid
-sequenceDiagram
- autonumber
- participant UI as Endpoint Page UI
- participant Sync as /api/sync/cloud
- participant DB as localDb
- participant Cloud as External Cloud Sync
- participant Claude as ~/.claude/settings.json
-
- UI->>Sync: POST action=enable
- Sync->>DB: set cloudEnabled=true
- Sync->>DB: ensure API key exists
- Sync->>Cloud: POST /sync/{machineId} (providers/aliases/combos/keys)
- Cloud-->>Sync: sync result
- Sync->>Cloud: GET /{machineId}/v1/verify
- Sync-->>UI: enabled + verification status
-
- UI->>Sync: POST action=sync
- Sync->>Cloud: POST /sync/{machineId}
- Cloud-->>Sync: remote data
- Sync->>DB: update newer local tokens/status
- Sync-->>UI: synced
-
- UI->>Sync: POST action=disable
- Sync->>DB: set cloudEnabled=false
- Sync->>Cloud: DELETE /sync/{machineId}
- Sync->>Claude: switch ANTHROPIC_BASE_URL back to local (if needed)
- Sync-->>UI: disabled
-```
-
-Periodic sync is triggered by `CloudSyncScheduler` when cloud is enabled.
-
-## Data Model and Storage Map
-
-```mermaid
-erDiagram
- SETTINGS ||--o{ PROVIDER_CONNECTION : controls
- PROVIDER_NODE ||--o{ PROVIDER_CONNECTION : backs_compatible_provider
- PROVIDER_CONNECTION ||--o{ USAGE_ENTRY : emits_usage
-
- SETTINGS {
- boolean cloudEnabled
- number stickyRoundRobinLimit
- boolean requireLogin
- string password_hash
- string fallbackStrategy
- json rateLimitDefaults
- json providerProfiles
- }
-
- PROVIDER_CONNECTION {
- string id
- string provider
- string authType
- string name
- number priority
- boolean isActive
- string apiKey
- string accessToken
- string refreshToken
- string expiresAt
- string testStatus
- string lastError
- string rateLimitedUntil
- json providerSpecificData
- }
-
- PROVIDER_NODE {
- string id
- string type
- string name
- string prefix
- string apiType
- string baseUrl
- }
-
- MODEL_ALIAS {
- string alias
- string targetModel
- }
-
- COMBO {
- string id
- string name
- string[] models
- }
-
- API_KEY {
- string id
- string name
- string key
- string machineId
- }
-
- USAGE_ENTRY {
- string provider
- string model
- number prompt_tokens
- number completion_tokens
- string connectionId
- string timestamp
- }
-
- CUSTOM_MODEL {
- string id
- string name
- string providerId
- }
-
- PROXY_CONFIG {
- string global
- json providers
- }
-
- IP_FILTER {
- string mode
- string[] allowlist
- string[] blocklist
- }
-
- THINKING_BUDGET {
- string mode
- number customBudget
- string effortLevel
- }
-
- SYSTEM_PROMPT {
- boolean enabled
- string prompt
- string position
- }
-```
-
-Physical storage files:
-
-- primary runtime DB: `${DATA_DIR}/storage.sqlite`
-- request log lines: `${DATA_DIR}/log.txt` (compat/debug artifact)
-- structured call payload archives: `${DATA_DIR}/call_logs/`
-- optional translator/request debug sessions: `/logs/...`
-
-## Deployment Topology
-
-```mermaid
-flowchart LR
- subgraph LocalHost[Developer Host]
- CLI[CLI Tools]
- Browser[Dashboard Browser]
- end
-
- subgraph ContainerOrProcess[OmniRoute Runtime]
- Next[Next.js Server\nPORT=20128]
- Core[SSE Core + Executors]
- MainDB[(storage.sqlite)]
- UsageDB[(usage tables + log artifacts)]
- end
-
- subgraph External[External Services]
- Providers[AI Providers]
- SyncCloud[Cloud Sync Service]
- end
-
- CLI --> Next
- Browser --> Next
- Next --> Core
- Next --> MainDB
- Core --> MainDB
- Core --> UsageDB
- Core --> Providers
- Next --> SyncCloud
-```
-
-## Module Mapping (Decision-Critical)
-
-### Route and API Modules
-
-- `src/app/api/v1/*`, `src/app/api/v1beta/*`: compatibility APIs
-- `src/app/api/v1/providers/[provider]/*`: dedicated per-provider routes (chat, embeddings, images)
-- `src/app/api/providers*`: provider CRUD, validation, testing
-- `src/app/api/provider-nodes*`: custom compatible node management
-- `src/app/api/provider-models`: custom model management (CRUD)
-- `src/app/api/models/route.ts`: model catalog API (aliases + custom models)
-- `src/app/api/oauth/*`: OAuth/device-code flows
-- `src/app/api/keys*`: local API key lifecycle
-- `src/app/api/models/alias`: alias management
-- `src/app/api/combos*`: fallback combo management
-- `src/app/api/pricing`: pricing overrides for cost calculation
-- `src/app/api/settings/proxy`: proxy configuration (GET/PUT/DELETE)
-- `src/app/api/settings/proxy/test`: outbound proxy connectivity test (POST)
-- `src/app/api/usage/*`: usage and logs APIs
-- `src/app/api/sync/*` + `src/app/api/cloud/*`: cloud sync and cloud-facing helpers
-- `src/app/api/cli-tools/*`: local CLI config writers/checkers
-- `src/app/api/settings/ip-filter`: IP allowlist/blocklist (GET/PUT)
-- `src/app/api/settings/thinking-budget`: thinking token budget config (GET/PUT)
-- `src/app/api/settings/system-prompt`: global system prompt (GET/PUT)
-- `src/app/api/sessions`: active session listing (GET)
-- `src/app/api/rate-limits`: per-account rate limit status (GET)
-
-### Routing and Execution Core
-
-- `src/sse/handlers/chat.ts`: request parse, combo handling, account selection loop
-- `open-sse/handlers/chatCore.ts`: translation, executor dispatch, retry/refresh handling, stream setup
-- `open-sse/executors/*`: provider-specific network and format behavior
-
-### Translation Registry and Format Converters
-
-- `open-sse/translator/index.ts`: translator registry and orchestration
-- Request translators: `open-sse/translator/request/*`
-- Response translators: `open-sse/translator/response/*`
-- Format constants: `open-sse/translator/formats.ts`
-
-### Persistence
-
-- `src/lib/db/*`: persistent config/state and domain persistence on SQLite
-- `src/lib/localDb.ts`: compatibility re-export for DB modules
-- `src/lib/usageDb.ts`: usage history/call logs facade on top of SQLite tables
-
-## Provider Executor Coverage (Strategy Pattern)
-
-Each provider has a specialized executor extending `BaseExecutor` (in `open-sse/executors/base.ts`), which provides URL building, header construction, retry with exponential backoff, credential refresh hooks, and the `execute()` orchestration method.
-
-| Executor | Provider(s) | Special Handling |
-| --------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------ | -------------------------------------------------------------------- |
-| `DefaultExecutor` | OpenAI, Claude, Gemini, Qwen, Qoder, OpenRouter, GLM, Kimi, MiniMax, DeepSeek, Groq, xAI, Mistral, Perplexity, Together, Fireworks, Cerebras, Cohere, NVIDIA | Dynamic URL/header config per provider |
-| `AntigravityExecutor` | Google Antigravity | Custom project/session IDs, Retry-After parsing |
-| `CodexExecutor` | OpenAI Codex | Injects system instructions, forces reasoning effort |
-| `CursorExecutor` | Cursor IDE | ConnectRPC protocol, Protobuf encoding, request signing via checksum |
-| `GithubExecutor` | GitHub Copilot | Copilot token refresh, VSCode-mimicking headers |
-| `KiroExecutor` | AWS CodeWhisperer/Kiro | AWS EventStream binary format → SSE conversion |
-| `GeminiCLIExecutor` | Gemini CLI | Google OAuth token refresh cycle |
-
-All other providers (including custom compatible nodes) use the `DefaultExecutor`.
-
-## Provider Compatibility Matrix
-
-| Provider | Format | Auth | Stream | Non-Stream | Token Refresh | Usage API |
-| ---------------- | ---------------- | --------------------- | ---------------- | ---------- | ------------- | ------------------ |
-| Claude | claude | API Key / OAuth | ✅ | ✅ | ✅ | ⚠️ Admin only |
-| Gemini | gemini | API Key / OAuth | ✅ | ✅ | ✅ | ⚠️ Cloud Console |
-| Gemini CLI | gemini-cli | OAuth | ✅ | ✅ | ✅ | ⚠️ Cloud Console |
-| Antigravity | antigravity | OAuth | ✅ | ✅ | ✅ | ✅ Full quota API |
-| OpenAI | openai | API Key | ✅ | ✅ | ❌ | ❌ |
-| Codex | openai-responses | OAuth | ✅ forced | ❌ | ✅ | ✅ Rate limits |
-| GitHub Copilot | openai | OAuth + Copilot Token | ✅ | ✅ | ✅ | ✅ Quota snapshots |
-| Cursor | cursor | Custom checksum | ✅ | ✅ | ❌ | ❌ |
-| Kiro | kiro | AWS SSO OIDC | ✅ (EventStream) | ❌ | ✅ | ✅ Usage limits |
-| Qwen | openai | OAuth | ✅ | ✅ | ✅ | ⚠️ Per request |
-| Qoder | openai | OAuth (Basic) | ✅ | ✅ | ✅ | ⚠️ Per request |
-| OpenRouter | openai | API Key | ✅ | ✅ | ❌ | ❌ |
-| GLM/Kimi/MiniMax | claude | API Key | ✅ | ✅ | ❌ | ❌ |
-| DeepSeek | openai | API Key | ✅ | ✅ | ❌ | ❌ |
-| Groq | openai | API Key | ✅ | ✅ | ❌ | ❌ |
-| xAI (Grok) | openai | API Key | ✅ | ✅ | ❌ | ❌ |
-| Mistral | openai | API Key | ✅ | ✅ | ❌ | ❌ |
-| Perplexity | openai | API Key | ✅ | ✅ | ❌ | ❌ |
-| Together AI | openai | API Key | ✅ | ✅ | ❌ | ❌ |
-| Fireworks AI | openai | API Key | ✅ | ✅ | ❌ | ❌ |
-| Cerebras | openai | API Key | ✅ | ✅ | ❌ | ❌ |
-| Cohere | openai | API Key | ✅ | ✅ | ❌ | ❌ |
-| NVIDIA NIM | openai | API Key | ✅ | ✅ | ❌ | ❌ |
-
-## Format Translation Coverage
-
-Detected source formats include:
-
-- `openai`
-- `openai-responses`
-- `claude`
-- `gemini`
-
-Target formats include:
-
-- OpenAI chat/Responses
-- Claude
-- Gemini/Gemini-CLI/Antigravity envelope
-- Kiro
-- Cursor
-
-Translations use **OpenAI as the hub format** — all conversions go through OpenAI as intermediate:
-
-```
-Source Format → OpenAI (hub) → Target Format
-```
-
-Translations are selected dynamically based on source payload shape and provider target format.
-
-Additional processing layers in the translation pipeline:
-
-- **Response sanitization** — Strips non-standard fields from OpenAI-format responses (both streaming and non-streaming) to ensure strict SDK compliance
-- **Role normalization** — Converts `developer` → `system` for non-OpenAI targets; merges `system` → `user` for models that reject the system role (GLM, ERNIE)
-- **Think tag extraction** — Parses `...` blocks from content into `reasoning_content` field
-- **Structured output** — Converts OpenAI `response_format.json_schema` to Gemini's `responseMimeType` + `responseSchema`
-
-## Supported API Endpoints
-
-| Endpoint | Format | Handler |
-| -------------------------------------------------- | ------------------ | ---------------------------------------------------- |
-| `POST /v1/chat/completions` | OpenAI Chat | `src/sse/handlers/chat.ts` |
-| `POST /v1/messages` | Claude Messages | Same handler (auto-detected) |
-| `POST /v1/responses` | OpenAI Responses | `open-sse/handlers/responsesHandler.ts` |
-| `POST /v1/embeddings` | OpenAI Embeddings | `open-sse/handlers/embeddings.ts` |
-| `GET /v1/embeddings` | Model listing | API route |
-| `POST /v1/images/generations` | OpenAI Images | `open-sse/handlers/imageGeneration.ts` |
-| `GET /v1/images/generations` | Model listing | API route |
-| `POST /v1/providers/{provider}/chat/completions` | OpenAI Chat | Dedicated per-provider with model validation |
-| `POST /v1/providers/{provider}/embeddings` | OpenAI Embeddings | Dedicated per-provider with model validation |
-| `POST /v1/providers/{provider}/images/generations` | OpenAI Images | Dedicated per-provider with model validation |
-| `POST /v1/messages/count_tokens` | Claude Token Count | API route |
-| `GET /v1/models` | OpenAI Models list | API route (chat + embedding + image + custom models) |
-| `GET /api/models/catalog` | Catalog | All models grouped by provider + type |
-| `POST /v1beta/models/*:streamGenerateContent` | Gemini native | API route |
-| `GET/PUT/DELETE /api/settings/proxy` | Proxy Config | Network proxy configuration |
-| `POST /api/settings/proxy/test` | Proxy Connectivity | Proxy health/connectivity test endpoint |
-| `GET/POST/DELETE /api/provider-models` | Custom Models | Custom model management per provider |
-
-## Bypass Handler
-
-The bypass handler (`open-sse/utils/bypassHandler.ts`) intercepts known "throwaway" requests from Claude CLI — warmup pings, title extractions, and token counts — and returns a **fake response** without consuming upstream provider tokens. This is triggered only when `User-Agent` contains `claude-cli`.
-
-## Request Logger Pipeline
-
-The request logger (`open-sse/utils/requestLogger.ts`) provides a 7-stage debug logging pipeline, disabled by default, enabled via `ENABLE_REQUEST_LOGS=true`:
-
-```
-1_req_client.json → 2_req_source.json → 3_req_openai.json → 4_req_target.json
-→ 5_res_provider.txt → 6_res_openai.txt → 7_res_client.txt
-```
-
-Files are written to `/logs//` for each request session.
-
-## Failure Modes and Resilience
-
-## 1) Account/Provider Availability
-
-- provider account cooldown on transient/rate/auth errors
-- account fallback before failing request
-- combo model fallback when current model/provider path is exhausted
-
-## 2) Token Expiry
-
-- pre-check and refresh with retry for refreshable providers
-- 401/403 retry after refresh attempt in core path
-
-## 3) Stream Safety
-
-- disconnect-aware stream controller
-- translation stream with end-of-stream flush and `[DONE]` handling
-- usage estimation fallback when provider usage metadata is missing
-
-## 4) Cloud Sync Degradation
-
-- sync errors are surfaced but local runtime continues
-- scheduler has retry-capable logic, but periodic execution currently calls single-attempt sync by default
-
-## 5) Data Integrity
-
-- SQLite schema migrations and auto-upgrade hooks at startup
-- legacy JSON → SQLite migration compatibility path
-
-## Observability and Operational Signals
-
-Runtime visibility sources:
-
-- console logs from `src/sse/utils/logger.ts`
-- per-request usage aggregates in SQLite (`usage_history`, `call_logs`, `proxy_logs`)
-- textual request status log in `log.txt` (optional/compat)
-- optional deep request/translation logs under `logs/` when `ENABLE_REQUEST_LOGS=true`
-- dashboard usage endpoints (`/api/usage/*`) for UI consumption
-
-## Security-Sensitive Boundaries
-
-- JWT secret (`JWT_SECRET`) secures dashboard session cookie verification/signing
-- Initial password bootstrap (`INITIAL_PASSWORD`) should be explicitly configured for first-run provisioning
-- API key HMAC secret (`API_KEY_SECRET`) secures generated local API key format
-- Provider secrets (API keys/tokens) are persisted in local DB and should be protected at filesystem level
-- Cloud sync endpoints rely on API key auth + machine id semantics
-
-## Environment and Runtime Matrix
-
-Environment variables actively used by code:
-
-- App/auth: `JWT_SECRET`, `INITIAL_PASSWORD`
-- Storage: `DATA_DIR`
-- Compatible node behavior: `ALLOW_MULTI_CONNECTIONS_PER_COMPAT_NODE`
-- Optional storage base override (Linux/macOS when `DATA_DIR` unset): `XDG_CONFIG_HOME`
-- Security hashing: `API_KEY_SECRET`, `MACHINE_ID_SALT`
-- Logging: `ENABLE_REQUEST_LOGS`
-- Sync/cloud URLing: `NEXT_PUBLIC_BASE_URL`, `NEXT_PUBLIC_CLOUD_URL`
-- Outbound proxy: `HTTP_PROXY`, `HTTPS_PROXY`, `ALL_PROXY`, `NO_PROXY` and lowercase variants
-- SOCKS5 feature flags: `ENABLE_SOCKS5_PROXY`, `NEXT_PUBLIC_ENABLE_SOCKS5_PROXY`
-- Platform/runtime helpers (not app-specific config): `APPDATA`, `NODE_ENV`, `PORT`, `HOSTNAME`
-
-## Known Architectural Notes
-
-1. `usageDb` and `localDb` share the same base directory policy (`DATA_DIR` -> `XDG_CONFIG_HOME/omniroute` -> `~/.omniroute`) with legacy file migration.
-2. `/api/v1/route.ts` delegates to the same unified catalog builder used by `/api/v1/models` (`src/app/api/v1/models/catalog.ts`) to avoid semantic drift.
-3. Request logger writes full headers/body when enabled; treat log directory as sensitive.
-4. Cloud behavior depends on correct `NEXT_PUBLIC_BASE_URL` and cloud endpoint reachability.
-5. The `open-sse/` directory is published as the `@omniroute/open-sse` **npm workspace package**. Source code imports it via `@omniroute/open-sse/...` (resolved by Next.js `transpilePackages`). File paths in this document still use the directory name `open-sse/` for consistency.
-6. Charts in the dashboard use **Recharts** (SVG-based) for accessible, interactive analytics visualizations (model usage bar charts, provider breakdown tables with success rates).
-7. E2E tests use **Playwright** (`tests/e2e/`), run via `npm run test:e2e`. Unit tests use **Node.js test runner** (`tests/unit/`), run via `npm run test:unit`. Source code under `src/` is **TypeScript** (`.ts`/`.tsx`); the `open-sse/` workspace remains JavaScript (`.js`).
-8. Settings page is organized into 5 tabs: Security, Routing (6 global strategies: fill-first, round-robin, p2c, random, least-used, cost-optimized), Resilience (editable rate limits, circuit breaker, policies), AI (thinking budget, system prompt, prompt cache), Advanced (proxy).
-
-## Operational Verification Checklist
-
-- Build from source: `npm run build`
-- Build Docker image: `docker build -t omniroute .`
-- Start service and verify:
-- `GET /api/settings`
-- `GET /api/v1/models`
-- CLI target base URL should be `http://:20128/v1` when `PORT=20128`
diff --git a/docs/i18n/in/AUTO-COMBO.md b/docs/i18n/in/AUTO-COMBO.md
deleted file mode 100644
index 2166e41dff..0000000000
--- a/docs/i18n/in/AUTO-COMBO.md
+++ /dev/null
@@ -1,67 +0,0 @@
-🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/AUTO-COMBO.md) · 🇪🇸 [es](../es/AUTO-COMBO.md) · 🇫🇷 [fr](../fr/AUTO-COMBO.md) · 🇩🇪 [de](../de/AUTO-COMBO.md) · 🇮🇹 [it](../it/AUTO-COMBO.md) · 🇷🇺 [ru](../ru/AUTO-COMBO.md) · 🇨🇳 [zh-CN](../zh-CN/AUTO-COMBO.md) · 🇯🇵 [ja](../ja/AUTO-COMBO.md) · 🇰🇷 [ko](../ko/AUTO-COMBO.md) · 🇸🇦 [ar](../ar/AUTO-COMBO.md) · 🇮🇳 [in](../in/AUTO-COMBO.md) · 🇹🇭 [th](../th/AUTO-COMBO.md) · 🇻🇳 [vi](../vi/AUTO-COMBO.md) · 🇮🇩 [id](../id/AUTO-COMBO.md) · 🇲🇾 [ms](../ms/AUTO-COMBO.md) · 🇳🇱 [nl](../nl/AUTO-COMBO.md) · 🇵🇱 [pl](../pl/AUTO-COMBO.md) · 🇸🇪 [sv](../sv/AUTO-COMBO.md) · 🇳🇴 [no](../no/AUTO-COMBO.md) · 🇩🇰 [da](../da/AUTO-COMBO.md) · 🇫🇮 [fi](../fi/AUTO-COMBO.md) · 🇵🇹 [pt](../pt/AUTO-COMBO.md) · 🇷🇴 [ro](../ro/AUTO-COMBO.md) · 🇭🇺 [hu](../hu/AUTO-COMBO.md) · 🇧🇬 [bg](../bg/AUTO-COMBO.md) · 🇸🇰 [sk](../sk/AUTO-COMBO.md) · 🇺🇦 [uk-UA](../uk-UA/AUTO-COMBO.md) · 🇮🇱 [he](../he/AUTO-COMBO.md) · 🇵🇭 [phi](../phi/AUTO-COMBO.md)
-
----
-
-# OmniRoute Auto-Combo Engine
-
-> Self-managing model chains with adaptive scoring
-
-## How It Works
-
-The Auto-Combo Engine dynamically selects the best provider/model for each request using a **6-factor scoring function**:
-
-| Factor | Weight | Description |
-| :--------- | :----- | :---------------------------------------------- |
-| Quota | 0.20 | Remaining capacity [0..1] |
-| Health | 0.25 | Circuit breaker: CLOSED=1.0, HALF=0.5, OPEN=0.0 |
-| CostInv | 0.20 | Inverse cost (cheaper = higher score) |
-| LatencyInv | 0.15 | Inverse p95 latency (faster = higher) |
-| TaskFit | 0.10 | Model × task type fitness score |
-| Stability | 0.10 | Low variance in latency/errors |
-
-## Mode Packs
-
-| Pack | Focus | Key Weight |
-| :---------------------- | :----------- | :--------------- |
-| 🚀 **Ship Fast** | Speed | latencyInv: 0.35 |
-| 💰 **Cost Saver** | Economy | costInv: 0.40 |
-| 🎯 **Quality First** | Best model | taskFit: 0.40 |
-| 📡 **Offline Friendly** | Availability | quota: 0.40 |
-
-## Self-Healing
-
-- **Temporary exclusion**: Score < 0.2 → excluded for 5 min (progressive backoff, max 30 min)
-- **Circuit breaker awareness**: OPEN → auto-excluded; HALF_OPEN → probe requests
-- **Incident mode**: >50% OPEN → disable exploration, maximize stability
-- **Cooldown recovery**: After exclusion, first request is a "probe" with reduced timeout
-
-## Bandit Exploration
-
-5% of requests (configurable) are routed to random providers for exploration. Disabled in incident mode.
-
-## API
-
-```bash
-# Create auto-combo
-curl -X POST http://localhost:20128/api/combos/auto \
- -H "Content-Type: application/json" \
- -d '{"id":"my-auto","name":"Auto Coder","candidatePool":["anthropic","google","openai"],"modePack":"ship-fast"}'
-
-# List auto-combos
-curl http://localhost:20128/api/combos/auto
-```
-
-## Task Fitness
-
-30+ models scored across 6 task types (`coding`, `review`, `planning`, `analysis`, `debugging`, `documentation`). Supports wildcard patterns (e.g., `*-coder` → high coding score).
-
-## Files
-
-| File | Purpose |
-| :------------------------------------------- | :------------------------------------ |
-| `open-sse/services/autoCombo/scoring.ts` | Scoring function & pool normalization |
-| `open-sse/services/autoCombo/taskFitness.ts` | Model × task fitness lookup |
-| `open-sse/services/autoCombo/engine.ts` | Selection logic, bandit, budget cap |
-| `open-sse/services/autoCombo/selfHealing.ts` | Exclusion, probes, incident mode |
-| `open-sse/services/autoCombo/modePacks.ts` | 4 weight profiles |
-| `src/app/api/combos/auto/route.ts` | REST API |
diff --git a/docs/i18n/in/CHANGELOG.md b/docs/i18n/in/CHANGELOG.md
index 557613d375..9a6d1d31ce 100644
--- a/docs/i18n/in/CHANGELOG.md
+++ b/docs/i18n/in/CHANGELOG.md
@@ -1,12 +1,92 @@
# Changelog (हिन्दी)
-🌐 **Languages:** 🇺🇸 [English](../../../CHANGELOG.md) · 🇪🇸 [es](../es/CHANGELOG.md) · 🇫🇷 [fr](../fr/CHANGELOG.md) · 🇩🇪 [de](../de/CHANGELOG.md) · 🇮🇹 [it](../it/CHANGELOG.md) · 🇷🇺 [ru](../ru/CHANGELOG.md) · 🇨🇳 [zh-CN](../zh-CN/CHANGELOG.md) · 🇯🇵 [ja](../ja/CHANGELOG.md) · 🇰🇷 [ko](../ko/CHANGELOG.md) · 🇸🇦 [ar](../ar/CHANGELOG.md) · 🇮🇳 [in](../in/CHANGELOG.md) · 🇹🇭 [th](../th/CHANGELOG.md) · 🇻🇳 [vi](../vi/CHANGELOG.md) · 🇮🇩 [id](../id/CHANGELOG.md) · 🇲🇾 [ms](../ms/CHANGELOG.md) · 🇳🇱 [nl](../nl/CHANGELOG.md) · 🇵🇱 [pl](../pl/CHANGELOG.md) · 🇸🇪 [sv](../sv/CHANGELOG.md) · 🇳🇴 [no](../no/CHANGELOG.md) · 🇩🇰 [da](../da/CHANGELOG.md) · 🇫🇮 [fi](../fi/CHANGELOG.md) · 🇵🇹 [pt](../pt/CHANGELOG.md) · 🇷🇴 [ro](../ro/CHANGELOG.md) · 🇭🇺 [hu](../hu/CHANGELOG.md) · 🇧🇬 [bg](../bg/CHANGELOG.md) · 🇸🇰 [sk](../sk/CHANGELOG.md) · 🇺🇦 [uk-UA](../uk-UA/CHANGELOG.md) · 🇮🇱 [he](../he/CHANGELOG.md) · 🇵🇭 [phi](../phi/CHANGELOG.md) · 🇧🇷 [pt-BR](../pt-BR/CHANGELOG.md)
+🌐 **Languages:** 🇺🇸 [English](../../../CHANGELOG.md) · 🇪🇸 [es](../es/CHANGELOG.md) · 🇫🇷 [fr](../fr/CHANGELOG.md) · 🇩🇪 [de](../de/CHANGELOG.md) · 🇮🇹 [it](../it/CHANGELOG.md) · 🇷🇺 [ru](../ru/CHANGELOG.md) · 🇨🇳 [zh-CN](../zh-CN/CHANGELOG.md) · 🇯🇵 [ja](../ja/CHANGELOG.md) · 🇰🇷 [ko](../ko/CHANGELOG.md) · 🇸🇦 [ar](../ar/CHANGELOG.md) · 🇮🇳 [in](../in/CHANGELOG.md) · 🇹🇭 [th](../th/CHANGELOG.md) · 🇻🇳 [vi](../vi/CHANGELOG.md) · 🇮🇩 [id](../id/CHANGELOG.md) · 🇲🇾 [ms](../ms/CHANGELOG.md) · 🇳🇱 [nl](../nl/CHANGELOG.md) · 🇵🇱 [pl](../pl/CHANGELOG.md) · 🇸🇪 [sv](../sv/CHANGELOG.md) · 🇳🇴 [no](../no/CHANGELOG.md) · 🇩🇰 [da](../da/CHANGELOG.md) · 🇫🇮 [fi](../fi/CHANGELOG.md) · 🇵🇹 [pt](../pt/CHANGELOG.md) · 🇷🇴 [ro](../ro/CHANGELOG.md) · 🇭🇺 [hu](../hu/CHANGELOG.md) · 🇧🇬 [bg](../bg/CHANGELOG.md) · 🇸🇰 [sk](../sk/CHANGELOG.md) · 🇺🇦 [uk-UA](../uk-UA/CHANGELOG.md) · 🇮🇱 [he](../he/CHANGELOG.md) · 🇵🇭 [phi](../phi/CHANGELOG.md) · 🇧🇷 [pt-BR](../pt-BR/CHANGELOG.md) · 🇨🇿 [cs](../cs/CHANGELOG.md)
---
-
## [Unreleased]
+### 🛠️ Maintenance
+
+- **AGENTS.md rewrite:** Condensed from 297→153 lines. Added build/lint/test commands (including single-test execution), code style guidelines (Prettier, TypeScript, ESLint, naming, imports, error handling, security), and trimmed verbose architecture tables for AI agent consumption.
+
+## [3.4.2] - 2026-04-01
+
+### 🐛 Bug Fixes
+
+- **CI Stabilization:** Fixed failing analytics/settings Playwright selectors and request assertions so GitHub Actions E2E runs pass reliably across localized UIs and switch-based controls.
+- **Deterministic Tests:** Removed date-sensitive quota fixtures from Copilot usage tests and aligned idempotency/model catalog tests with the merged runtime behavior.
+- **MCP Type Hardening:** Removed zero-budget explicit `any` regressions from the MCP server tool registration path, restoring the `check:any-budget:t11` workflow gate.
+
+### 🛠️ Maintenance
+
+- **Release Branch Integration:** Consolidated the active feature branches into `release/v3.4.2` on top of current `main` and validated the branch with lint, unit, coverage, build, and CI-mode E2E runs.
+
+## [3.4.1] - 2026-03-31
+
+> [!WARNING]
+> **BREAKING CHANGE: request logging, retention, and logging environment variables have been redesigned.**
+> On the first startup after upgrading, OmniRoute archives legacy request logs from `DATA_DIR/logs/`, legacy `DATA_DIR/call_logs/`, and `DATA_DIR/log.txt` into `DATA_DIR/log_archives/*.zip`, then removes the deprecated layout and switches to the new unified artifact format under `DATA_DIR/call_logs/`.
+
+### ✨ New Features
+
+- **.ENV Migration Utility:** Included `scripts/migrate-env.mjs` to seamlessly migrate ` Your key looks like: `sk-xxxxxxxxxxxxxxxx-xxxxxxxxx`
-
----
-
-## Step 2 — Install CLI Tools
-
-All npm-based tools require Node.js 18+:
-
-```bash
-# Claude Code (Anthropic)
-npm install -g @anthropic-ai/claude-code
-
-# OpenAI Codex
-npm install -g @openai/codex
-
-# Gemini CLI (Google)
-npm install -g @google/gemini-cli
-
-# OpenCode
-npm install -g opencode-ai
-
-# Cline
-npm install -g cline
-
-# KiloCode
-npm install -g kilecode
-
-# Kiro CLI (Amazon — requires curl + unzip)
-apt-get install -y unzip # on Debian/Ubuntu
-curl -fsSL https://cli.kiro.dev/install | bash
-export PATH="$HOME/.local/bin:$PATH" # add to ~/.bashrc
-```
-
-**Verify:**
-
-```bash
-claude --version # 2.x.x
-codex --version # 0.x.x
-gemini --version # 0.x.x
-opencode --version # x.x.x
-cline --version # 2.x.x
-kilocode --version # x.x.x (or: kilo --version)
-kiro-cli --version # 1.x.x
-```
-
----
-
-## Step 3 — Set Global Environment Variables
-
-Add to `~/.bashrc` (or `~/.zshrc`), then run `source ~/.bashrc`:
-
-```bash
-# OmniRoute Universal Endpoint
-export OPENAI_BASE_URL="http://localhost:20128/v1"
-export OPENAI_API_KEY="sk-your-omniroute-key"
-export ANTHROPIC_BASE_URL="http://localhost:20128/v1"
-export ANTHROPIC_API_KEY="sk-your-omniroute-key"
-export GEMINI_BASE_URL="http://localhost:20128/v1"
-export GEMINI_API_KEY="sk-your-omniroute-key"
-```
-
-> For a **remote server** replace `localhost:20128` with the server IP or domain,
-> e.g. `http://192.168.0.15:20128`.
-
----
-
-## Step 4 — Configure Each Tool
-
-### Claude Code
-
-```bash
-# Via CLI:
-claude config set --global api-base-url http://localhost:20128/v1
-
-# Or create ~/.claude/settings.json:
-mkdir -p ~/.claude && cat > ~/.claude/settings.json << EOF
-{
- "apiBaseUrl": "http://localhost:20128/v1",
- "apiKey": "sk-your-omniroute-key"
-}
-EOF
-```
-
-**Test:** `claude "say hello"`
-
----
-
-### OpenAI Codex
-
-```bash
-mkdir -p ~/.codex && cat > ~/.codex/config.yaml << EOF
-model: auto
-apiKey: sk-your-omniroute-key
-apiBaseUrl: http://localhost:20128/v1
-EOF
-```
-
-**Test:** `codex "what is 2+2?"`
-
----
-
-### Gemini CLI
-
-```bash
-mkdir -p ~/.gemini && cat > ~/.gemini/settings.json << EOF
-{
- "apiKey": "sk-your-omniroute-key",
- "baseUrl": "http://localhost:20128/v1"
-}
-EOF
-```
-
-**Test:** `gemini "hello"`
-
----
-
-### OpenCode
-
-```bash
-mkdir -p ~/.config/opencode && cat > ~/.config/opencode/config.toml << EOF
-[provider.openai]
-base_url = "http://localhost:20128/v1"
-api_key = "sk-your-omniroute-key"
-EOF
-```
-
-**Test:** `opencode`
-
----
-
-### Cline (CLI or VS Code)
-
-**CLI mode:**
-
-```bash
-mkdir -p ~/.cline/data && cat > ~/.cline/data/globalState.json << EOF
-{
- "apiProvider": "openai",
- "openAiBaseUrl": "http://localhost:20128/v1",
- "openAiApiKey": "sk-your-omniroute-key"
-}
-EOF
-```
-
-**VS Code mode:**
-Cline extension settings → API Provider: `OpenAI Compatible` → Base URL: `http://localhost:20128/v1`
-
-Or use the OmniRoute dashboard → **CLI Tools → Cline → Apply Config**.
-
----
-
-### KiloCode (CLI or VS Code)
-
-**CLI mode:**
-
-```bash
-kilocode --api-base http://localhost:20128/v1 --api-key sk-your-omniroute-key
-```
-
-**VS Code settings:**
-
-```json
-{
- "kilo-code.openAiBaseUrl": "http://localhost:20128/v1",
- "kilo-code.apiKey": "sk-your-omniroute-key"
-}
-```
-
-Or use the OmniRoute dashboard → **CLI Tools → KiloCode → Apply Config**.
-
----
-
-### Continue (VS Code Extension)
-
-Edit `~/.continue/config.yaml`:
-
-```yaml
-models:
- - name: OmniRoute
- provider: openai
- model: auto
- apiBase: http://localhost:20128/v1
- apiKey: sk-your-omniroute-key
- default: true
-```
-
-Restart VS Code after editing.
-
----
-
-### Kiro CLI (Amazon)
-
-```bash
-# Login to your AWS/Kiro account:
-kiro-cli login
-
-# The CLI uses its own auth — OmniRoute is not needed as backend for Kiro CLI itself.
-# Use kiro-cli alongside OmniRoute for other tools.
-kiro-cli status
-```
-
----
-
-### Cursor (Desktop App)
-
-> **Note:** Cursor routes requests through its cloud. For OmniRoute integration,
-> enable **Cloud Endpoint** in OmniRoute Settings and use your public domain URL.
-
-Via GUI: **Settings → Models → OpenAI API Key**
-
-- Base URL: `https://your-domain.com/v1`
-- API Key: your OmniRoute key
-
----
-
-## Dashboard Auto-Configuration
-
-The OmniRoute dashboard automates configuration for most tools:
-
-1. Go to `http://localhost:20128/dashboard/cli-tools`
-2. Expand any tool card
-3. Select your API key from the dropdown
-4. Click **Apply Config** (if tool is detected as installed)
-5. Or copy the generated config snippet manually
-
----
-
-## Built-in Agents: Droid & OpenClaw
-
-**Droid** and **OpenClaw** are AI agents built directly into OmniRoute — no installation needed.
-They run as internal routes and use OmniRoute's model routing automatically.
-
-- Access: `http://localhost:20128/dashboard/agents`
-- Configure: same combos and providers as all other tools
-- No API key or CLI install required
-
----
-
-## Available API Endpoints
-
-| Endpoint | Description | Use For |
-| -------------------------- | ----------------------------- | --------------------------- |
-| `/v1/chat/completions` | Standard chat (all providers) | All modern tools |
-| `/v1/responses` | Responses API (OpenAI format) | Codex, agentic workflows |
-| `/v1/completions` | Legacy text completions | Older tools using `prompt:` |
-| `/v1/embeddings` | Text embeddings | RAG, search |
-| `/v1/images/generations` | Image generation | DALL-E, Flux, etc. |
-| `/v1/audio/speech` | Text-to-speech | ElevenLabs, OpenAI TTS |
-| `/v1/audio/transcriptions` | Speech-to-text | Deepgram, AssemblyAI |
-
----
-
-## Troubleshooting
-
-| Error | Cause | Fix |
-| ------------------------- | ----------------------- | ------------------------------------------ |
-| `Connection refused` | OmniRoute not running | `pm2 start omniroute` |
-| `401 Unauthorized` | Wrong API key | Check in `/dashboard/api-manager` |
-| `No combo configured` | No active routing combo | Set up in `/dashboard/combos` |
-| `invalid model` | Model not in catalog | Use `auto` or check `/dashboard/providers` |
-| CLI shows "not installed" | Binary not in PATH | Check `which ` |
-| `kiro-cli: not found` | Not in PATH | `export PATH="$HOME/.local/bin:$PATH"` |
-
----
-
-## Quick Setup Script (One Command)
-
-```bash
-# Install all CLIs and configure for OmniRoute (replace with your key and server URL)
-OMNIROUTE_URL="http://localhost:20128/v1"
-OMNIROUTE_KEY="sk-your-omniroute-key"
-
-npm install -g @anthropic-ai/claude-code @openai/codex @google/gemini-cli opencode-ai cline kilecode
-
-# Kiro CLI
-apt-get install -y unzip 2>/dev/null; curl -fsSL https://cli.kiro.dev/install | bash
-
-# Write configs
-mkdir -p ~/.claude ~/.codex ~/.gemini ~/.config/opencode ~/.continue
-
-cat > ~/.claude/settings.json <<< "{\"apiBaseUrl\":\"$OMNIROUTE_URL\",\"apiKey\":\"$OMNIROUTE_KEY\"}"
-cat > ~/.codex/config.yaml <<< "model: auto\napiKey: $OMNIROUTE_KEY\napiBaseUrl: $OMNIROUTE_URL"
-cat > ~/.gemini/settings.json <<< "{\"apiKey\":\"$OMNIROUTE_KEY\",\"baseUrl\":\"$OMNIROUTE_URL\"}"
-cat >> ~/.bashrc << EOF
-export OPENAI_BASE_URL="$OMNIROUTE_URL"
-export OPENAI_API_KEY="$OMNIROUTE_KEY"
-export ANTHROPIC_BASE_URL="$OMNIROUTE_URL"
-export ANTHROPIC_API_KEY="$OMNIROUTE_KEY"
-EOF
-
-source ~/.bashrc
-echo "✅ All CLIs installed and configured for OmniRoute"
-```
diff --git a/docs/i18n/in/CODEBASE_DOCUMENTATION.md b/docs/i18n/in/CODEBASE_DOCUMENTATION.md
deleted file mode 100644
index e2d7950052..0000000000
--- a/docs/i18n/in/CODEBASE_DOCUMENTATION.md
+++ /dev/null
@@ -1,593 +0,0 @@
-🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/CODEBASE_DOCUMENTATION.md) · 🇪🇸 [es](../es/CODEBASE_DOCUMENTATION.md) · 🇫🇷 [fr](../fr/CODEBASE_DOCUMENTATION.md) · 🇩🇪 [de](../de/CODEBASE_DOCUMENTATION.md) · 🇮🇹 [it](../it/CODEBASE_DOCUMENTATION.md) · 🇷🇺 [ru](../ru/CODEBASE_DOCUMENTATION.md) · 🇨🇳 [zh-CN](../zh-CN/CODEBASE_DOCUMENTATION.md) · 🇯🇵 [ja](../ja/CODEBASE_DOCUMENTATION.md) · 🇰🇷 [ko](../ko/CODEBASE_DOCUMENTATION.md) · 🇸🇦 [ar](../ar/CODEBASE_DOCUMENTATION.md) · 🇮🇳 [in](../in/CODEBASE_DOCUMENTATION.md) · 🇹🇭 [th](../th/CODEBASE_DOCUMENTATION.md) · 🇻🇳 [vi](../vi/CODEBASE_DOCUMENTATION.md) · 🇮🇩 [id](../id/CODEBASE_DOCUMENTATION.md) · 🇲🇾 [ms](../ms/CODEBASE_DOCUMENTATION.md) · 🇳🇱 [nl](../nl/CODEBASE_DOCUMENTATION.md) · 🇵🇱 [pl](../pl/CODEBASE_DOCUMENTATION.md) · 🇸🇪 [sv](../sv/CODEBASE_DOCUMENTATION.md) · 🇳🇴 [no](../no/CODEBASE_DOCUMENTATION.md) · 🇩🇰 [da](../da/CODEBASE_DOCUMENTATION.md) · 🇫🇮 [fi](../fi/CODEBASE_DOCUMENTATION.md) · 🇵🇹 [pt](../pt/CODEBASE_DOCUMENTATION.md) · 🇷🇴 [ro](../ro/CODEBASE_DOCUMENTATION.md) · 🇭🇺 [hu](../hu/CODEBASE_DOCUMENTATION.md) · 🇧🇬 [bg](../bg/CODEBASE_DOCUMENTATION.md) · 🇸🇰 [sk](../sk/CODEBASE_DOCUMENTATION.md) · 🇺🇦 [uk-UA](../uk-UA/CODEBASE_DOCUMENTATION.md) · 🇮🇱 [he](../he/CODEBASE_DOCUMENTATION.md) · 🇵🇭 [phi](../phi/CODEBASE_DOCUMENTATION.md)
-
----
-
-# omniroute — Codebase Documentation
-
-🌐 **Languages:** 🇺🇸 [English](CODEBASE_DOCUMENTATION.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/CODEBASE_DOCUMENTATION.md) | 🇪🇸 [Español](i18n/es/CODEBASE_DOCUMENTATION.md) | 🇫🇷 [Français](i18n/fr/CODEBASE_DOCUMENTATION.md) | 🇮🇹 [Italiano](i18n/it/CODEBASE_DOCUMENTATION.md) | 🇷🇺 [Русский](i18n/ru/CODEBASE_DOCUMENTATION.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/CODEBASE_DOCUMENTATION.md) | 🇩🇪 [Deutsch](i18n/de/CODEBASE_DOCUMENTATION.md) | 🇮🇳 [हिन्दी](i18n/in/CODEBASE_DOCUMENTATION.md) | 🇹🇭 [ไทย](i18n/th/CODEBASE_DOCUMENTATION.md) | 🇺🇦 [Українська](i18n/uk-UA/CODEBASE_DOCUMENTATION.md) | 🇸🇦 [العربية](i18n/ar/CODEBASE_DOCUMENTATION.md) | 🇯🇵 [日本語](i18n/ja/CODEBASE_DOCUMENTATION.md) | 🇻🇳 [Tiếng Việt](i18n/vi/CODEBASE_DOCUMENTATION.md) | 🇧🇬 [Български](i18n/bg/CODEBASE_DOCUMENTATION.md) | 🇩🇰 [Dansk](i18n/da/CODEBASE_DOCUMENTATION.md) | 🇫🇮 [Suomi](i18n/fi/CODEBASE_DOCUMENTATION.md) | 🇮🇱 [עברית](i18n/he/CODEBASE_DOCUMENTATION.md) | 🇭🇺 [Magyar](i18n/hu/CODEBASE_DOCUMENTATION.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/CODEBASE_DOCUMENTATION.md) | 🇰🇷 [한국어](i18n/ko/CODEBASE_DOCUMENTATION.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/CODEBASE_DOCUMENTATION.md) | 🇳🇱 [Nederlands](i18n/nl/CODEBASE_DOCUMENTATION.md) | 🇳🇴 [Norsk](i18n/no/CODEBASE_DOCUMENTATION.md) | 🇵🇹 [Português (Portugal)](i18n/pt/CODEBASE_DOCUMENTATION.md) | 🇷🇴 [Română](i18n/ro/CODEBASE_DOCUMENTATION.md) | 🇵🇱 [Polski](i18n/pl/CODEBASE_DOCUMENTATION.md) | 🇸🇰 [Slovenčina](i18n/sk/CODEBASE_DOCUMENTATION.md) | 🇸🇪 [Svenska](i18n/sv/CODEBASE_DOCUMENTATION.md) | 🇵🇭 [Filipino](i18n/phi/CODEBASE_DOCUMENTATION.md)
-
-> A comprehensive, beginner-friendly guide to the **omniroute** multi-provider AI proxy router.
-
----
-
-## 1. What Is omniroute?
-
-omniroute is a **proxy router** that sits between AI clients (Claude CLI, Codex, Cursor IDE, etc.) and AI providers (Anthropic, Google, OpenAI, AWS, GitHub, etc.). It solves one big problem:
-
-> **Different AI clients speak different "languages" (API formats), and different AI providers expect different "languages" too.** omniroute translates between them automatically.
-
-Think of it like a universal translator at the United Nations — any delegate can speak any language, and the translator converts it for any other delegate.
-
----
-
-## 2. Architecture Overview
-
-```mermaid
-graph LR
- subgraph Clients
- A[Claude CLI]
- B[Codex]
- C[Cursor IDE]
- D[OpenAI-compatible]
- end
-
- subgraph omniroute
- E[Handler Layer]
- F[Translator Layer]
- G[Executor Layer]
- H[Services Layer]
- end
-
- subgraph Providers
- I[Anthropic Claude]
- J[Google Gemini]
- K[OpenAI / Codex]
- L[GitHub Copilot]
- M[AWS Kiro]
- N[Antigravity]
- O[Cursor API]
- end
-
- A --> E
- B --> E
- C --> E
- D --> E
- E --> F
- F --> G
- G --> I
- G --> J
- G --> K
- G --> L
- G --> M
- G --> N
- G --> O
- H -.-> E
- H -.-> G
-```
-
-### Core Principle: Hub-and-Spoke Translation
-
-All format translation passes through **OpenAI format as the hub**:
-
-```
-Client Format → [OpenAI Hub] → Provider Format (request)
-Provider Format → [OpenAI Hub] → Client Format (response)
-```
-
-This means you only need **N translators** (one per format) instead of **N²** (every pair).
-
----
-
-## 3. Project Structure
-
-```
-omniroute/
-├── open-sse/ ← Core proxy library (portable, framework-agnostic)
-│ ├── index.js ← Main entry point, exports everything
-│ ├── config/ ← Configuration & constants
-│ ├── executors/ ← Provider-specific request execution
-│ ├── handlers/ ← Request handling orchestration
-│ ├── services/ ← Business logic (auth, models, fallback, usage)
-│ ├── translator/ ← Format translation engine
-│ │ ├── request/ ← Request translators (8 files)
-│ │ ├── response/ ← Response translators (7 files)
-│ │ └── helpers/ ← Shared translation utilities (6 files)
-│ └── utils/ ← Utility functions
-├── src/ ← Application layer (Express/Worker runtime)
-│ ├── app/ ← Web UI, API routes, middleware
-│ ├── lib/ ← Database, auth, and shared library code
-│ ├── mitm/ ← Man-in-the-middle proxy utilities
-│ ├── models/ ← Database models
-│ ├── shared/ ← Shared utilities (wrappers around open-sse)
-│ ├── sse/ ← SSE endpoint handlers
-│ └── store/ ← State management
-├── data/ ← Runtime data (credentials, logs)
-│ └── provider-credentials.json (external credentials override, gitignored)
-└── tester/ ← Test utilities
-```
-
----
-
-## 4. Module-by-Module Breakdown
-
-### 4.1 Config (`open-sse/config/`)
-
-The **single source of truth** for all provider configuration.
-
-| File | Purpose |
-| ----------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| `constants.ts` | `PROVIDERS` object with base URLs, OAuth credentials (defaults), headers, and default system prompts for every provider. Also defines `HTTP_STATUS`, `ERROR_TYPES`, `COOLDOWN_MS`, `BACKOFF_CONFIG`, and `SKIP_PATTERNS`. |
-| `credentialLoader.ts` | Loads external credentials from `data/provider-credentials.json` and merges them over the hardcoded defaults in `PROVIDERS`. Keeps secrets out of source control while maintaining backwards compatibility. |
-| `providerModels.ts` | Central model registry: maps provider aliases → model IDs. Functions like `getModels()`, `getProviderByAlias()`. |
-| `codexInstructions.ts` | System instructions injected into Codex requests (editing constraints, sandbox rules, approval policies). |
-| `defaultThinkingSignature.ts` | Default "thinking" signatures for Claude and Gemini models. |
-| `ollamaModels.ts` | Schema definition for local Ollama models (name, size, family, quantization). |
-
-#### Credential Loading Flow
-
-```mermaid
-flowchart TD
- A["App starts"] --> B["constants.ts defines PROVIDERS\nwith hardcoded defaults"]
- B --> C{"data/provider-credentials.json\nexists?"}
- C -->|Yes| D["credentialLoader reads JSON"]
- C -->|No| E["Use hardcoded defaults"]
- D --> F{"For each provider in JSON"}
- F --> G{"Provider exists\nin PROVIDERS?"}
- G -->|No| H["Log warning, skip"]
- G -->|Yes| I{"Value is object?"}
- I -->|No| J["Log warning, skip"]
- I -->|Yes| K["Merge clientId, clientSecret,\ntokenUrl, authUrl, refreshUrl"]
- K --> F
- H --> F
- J --> F
- F -->|Done| L["PROVIDERS ready with\nmerged credentials"]
- E --> L
-```
-
----
-
-### 4.2 Executors (`open-sse/executors/`)
-
-Executors encapsulate **provider-specific logic** using the **Strategy Pattern**. Each executor overrides base methods as needed.
-
-```mermaid
-classDiagram
- class BaseExecutor {
- +buildUrl(model, stream, options)
- +buildHeaders(credentials, stream, body)
- +transformRequest(body, model, stream, credentials)
- +execute(url, options)
- +shouldRetry(status, error)
- +refreshCredentials(credentials, log)
- }
-
- class DefaultExecutor {
- +refreshCredentials()
- }
-
- class AntigravityExecutor {
- +buildUrl()
- +buildHeaders()
- +transformRequest()
- +shouldRetry()
- +refreshCredentials()
- }
-
- class CursorExecutor {
- +buildUrl()
- +buildHeaders()
- +transformRequest()
- +parseResponse()
- +generateChecksum()
- }
-
- class KiroExecutor {
- +buildUrl()
- +buildHeaders()
- +transformRequest()
- +parseEventStream()
- +refreshCredentials()
- }
-
- BaseExecutor <|-- DefaultExecutor
- BaseExecutor <|-- AntigravityExecutor
- BaseExecutor <|-- CursorExecutor
- BaseExecutor <|-- KiroExecutor
- BaseExecutor <|-- CodexExecutor
- BaseExecutor <|-- GeminiCLIExecutor
- BaseExecutor <|-- GithubExecutor
-```
-
-| Executor | Provider | Key Specializations |
-| ---------------- | ------------------------------------------ | ------------------------------------------------------------------------------------------------------------------- |
-| `base.ts` | — | Abstract base: URL building, headers, retry logic, credential refresh |
-| `default.ts` | Claude, Gemini, OpenAI, GLM, Kimi, MiniMax | Generic OAuth token refresh for standard providers |
-| `antigravity.ts` | Google Cloud Code | Project/session ID generation, multi-URL fallback, custom retry parsing from error messages ("reset after 2h7m23s") |
-| `cursor.ts` | Cursor IDE | **Most complex**: SHA-256 checksum auth, Protobuf request encoding, binary EventStream → SSE response parsing |
-| `codex.ts` | OpenAI Codex | Injects system instructions, manages thinking levels, removes unsupported parameters |
-| `gemini-cli.ts` | Google Gemini CLI | Custom URL building (`streamGenerateContent`), Google OAuth token refresh |
-| `github.ts` | GitHub Copilot | Dual token system (GitHub OAuth + Copilot token), VSCode header mimicking |
-| `kiro.ts` | AWS CodeWhisperer | AWS EventStream binary parsing, AMZN event frames, token estimation |
-| `index.ts` | — | Factory: maps provider name → executor class, with default fallback |
-
----
-
-### 4.3 Handlers (`open-sse/handlers/`)
-
-The **orchestration layer** — coordinates translation, execution, streaming, and error handling.
-
-| File | Purpose |
-| --------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| `chatCore.ts` | **Central orchestrator** (~600 lines). Handles the complete request lifecycle: format detection → translation → executor dispatch → streaming/non-streaming response → token refresh → error handling → usage logging. |
-| `responsesHandler.ts` | Adapter for OpenAI's Responses API: converts Responses format → Chat Completions → sends to `chatCore` → converts SSE back to Responses format. |
-| `embeddings.ts` | Embedding generation handler: resolves embedding model → provider, dispatches to provider API, returns OpenAI-compatible embedding response. Supports 6+ providers. |
-| `imageGeneration.ts` | Image generation handler: resolves image model → provider, supports OpenAI-compatible, Gemini-image (Antigravity), and fallback (Nebius) modes. Returns base64 or URL images. |
-
-#### Request Lifecycle (chatCore.ts)
-
-```mermaid
-sequenceDiagram
- participant Client
- participant chatCore
- participant Translator
- participant Executor
- participant Provider
-
- Client->>chatCore: Request (any format)
- chatCore->>chatCore: Detect source format
- chatCore->>chatCore: Check bypass patterns
- chatCore->>chatCore: Resolve model & provider
- chatCore->>Translator: Translate request (source → OpenAI → target)
- chatCore->>Executor: Get executor for provider
- Executor->>Executor: Build URL, headers, transform request
- Executor->>Executor: Refresh credentials if needed
- Executor->>Provider: HTTP fetch (streaming or non-streaming)
-
- alt Streaming
- Provider-->>chatCore: SSE stream
- chatCore->>chatCore: Pipe through SSE transform stream
- Note over chatCore: Transform stream translates
each chunk: target → OpenAI → source
- chatCore-->>Client: Translated SSE stream
- else Non-streaming
- Provider-->>chatCore: JSON response
- chatCore->>Translator: Translate response
- chatCore-->>Client: Translated JSON
- end
-
- alt Error (401, 429, 500...)
- chatCore->>Executor: Retry with credential refresh
- chatCore->>chatCore: Account fallback logic
- end
-```
-
----
-
-### 4.4 Services (`open-sse/services/`)
-
-Business logic that supports the handlers and executors.
-
-| File | Purpose |
-| -------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| `provider.ts` | **Format detection** (`detectFormat`): analyzes request body structure to identify Claude/OpenAI/Gemini/Antigravity/Responses formats (includes `max_tokens` heuristic for Claude). Also: URL building, header building, thinking config normalization. Supports `openai-compatible-*` and `anthropic-compatible-*` dynamic providers. |
-| `model.ts` | Model string parsing (`claude/model-name` → `{provider: "claude", model: "model-name"}`), alias resolution with collision detection, input sanitization (rejects path traversal/control chars), and model info resolution with async alias getter support. |
-| `accountFallback.ts` | Rate-limit handling: exponential backoff (1s → 2s → 4s → max 2min), account cooldown management, error classification (which errors trigger fallback vs. not). |
-| `tokenRefresh.ts` | OAuth token refresh for **every provider**: Google (Gemini, Antigravity), Claude, Codex, Qwen, Qoder, GitHub (OAuth + Copilot dual-token), Kiro (AWS SSO OIDC + Social Auth). Includes in-flight promise deduplication cache and retry with exponential backoff. |
-| `combo.ts` | **Combo models**: chains of fallback models. If model A fails with a fallback-eligible error, try model B, then C, etc. Returns actual upstream status codes. |
-| `usage.ts` | Fetches quota/usage data from provider APIs (GitHub Copilot quotas, Antigravity model quotas, Codex rate limits, Kiro usage breakdowns, Claude settings). |
-| `accountSelector.ts` | Smart account selection with scoring algorithm: considers priority, health status, round-robin position, and cooldown state to pick the optimal account for each request. |
-| `contextManager.ts` | Request context lifecycle management: creates and tracks per-request context objects with metadata (request ID, timestamps, provider info) for debugging and logging. |
-| `ipFilter.ts` | IP-based access control: supports allowlist and blocklist modes. Validates client IP against configured rules before processing API requests. |
-| `sessionManager.ts` | Session tracking with client fingerprinting: tracks active sessions using hashed client identifiers, monitors request counts, and provides session metrics. |
-| `signatureCache.ts` | Request signature-based deduplication cache: prevents duplicate requests by caching recent request signatures and returning cached responses for identical requests within a time window. |
-| `systemPrompt.ts` | Global system prompt injection: prepends or appends a configurable system prompt to all requests, with per-provider compatibility handling. |
-| `thinkingBudget.ts` | Reasoning token budget management: supports passthrough, auto (strip thinking config), custom (fixed budget), and adaptive (complexity-scaled) modes for controlling thinking/reasoning tokens. |
-| `wildcardRouter.ts` | Wildcard model pattern routing: resolves wildcard patterns (e.g., `*/claude-*`) to concrete provider/model pairs based on availability and priority. |
-
-#### Token Refresh Deduplication
-
-```mermaid
-sequenceDiagram
- participant R1 as Request 1
- participant R2 as Request 2
- participant Cache as refreshPromiseCache
- participant OAuth as OAuth Provider
-
- R1->>Cache: getAccessToken("gemini", token)
- Cache->>Cache: No in-flight promise
- Cache->>OAuth: Start refresh
- R2->>Cache: getAccessToken("gemini", token)
- Cache->>Cache: Found in-flight promise
- Cache-->>R2: Return existing promise
- OAuth-->>Cache: New access token
- Cache-->>R1: New access token
- Cache-->>R2: Same access token (shared)
- Cache->>Cache: Delete cache entry
-```
-
-#### Account Fallback State Machine
-
-```mermaid
-stateDiagram-v2
- [*] --> Active
- Active --> Error: Request fails (401/429/500)
- Error --> Cooldown: Apply backoff
- Cooldown --> Active: Cooldown expires
- Active --> Active: Request succeeds (reset backoff)
-
- state Error {
- [*] --> ClassifyError
- ClassifyError --> ShouldFallback: Rate limit / Auth / Transient
- ClassifyError --> NoFallback: 400 Bad Request
- }
-
- state Cooldown {
- [*] --> ExponentialBackoff
- ExponentialBackoff: Level 0 = 1s
- ExponentialBackoff: Level 1 = 2s
- ExponentialBackoff: Level 2 = 4s
- ExponentialBackoff: Max = 2min
- }
-```
-
-#### Combo Model Chain
-
-```mermaid
-flowchart LR
- A["Request with\ncombo model"] --> B["Model A"]
- B -->|"2xx Success"| C["Return response"]
- B -->|"429/401/500"| D{"Fallback\neligible?"}
- D -->|Yes| E["Model B"]
- D -->|No| F["Return error"]
- E -->|"2xx Success"| C
- E -->|"429/401/500"| G{"Fallback\neligible?"}
- G -->|Yes| H["Model C"]
- G -->|No| F
- H -->|"2xx Success"| C
- H -->|"Fail"| I["All failed →\nReturn last status"]
-```
-
----
-
-### 4.5 Translator (`open-sse/translator/`)
-
-The **format translation engine** using a self-registering plugin system.
-
-#### Architecture
-
-```mermaid
-graph TD
- subgraph "Request Translation"
- A["Claude → OpenAI"]
- B["Gemini → OpenAI"]
- C["Antigravity → OpenAI"]
- D["OpenAI Responses → OpenAI"]
- E["OpenAI → Claude"]
- F["OpenAI → Gemini"]
- G["OpenAI → Kiro"]
- H["OpenAI → Cursor"]
- end
-
- subgraph "Response Translation"
- I["Claude → OpenAI"]
- J["Gemini → OpenAI"]
- K["Kiro → OpenAI"]
- L["Cursor → OpenAI"]
- M["OpenAI → Claude"]
- N["OpenAI → Antigravity"]
- O["OpenAI → Responses"]
- end
-```
-
-| Directory | Files | Description |
-| ------------ | ------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| `request/` | 8 translators | Convert request bodies between formats. Each file self-registers via `register(from, to, fn)` on import. |
-| `response/` | 7 translators | Convert streaming response chunks between formats. Handles SSE event types, thinking blocks, tool calls. |
-| `helpers/` | 6 helpers | Shared utilities: `claudeHelper` (system prompt extraction, thinking config), `geminiHelper` (parts/contents mapping), `openaiHelper` (format filtering), `toolCallHelper` (ID generation, missing response injection), `maxTokensHelper`, `responsesApiHelper`. |
-| `index.ts` | — | Translation engine: `translateRequest()`, `translateResponse()`, state management, registry. |
-| `formats.ts` | — | Format constants: `OPENAI`, `CLAUDE`, `GEMINI`, `ANTIGRAVITY`, `KIRO`, `CURSOR`, `OPENAI_RESPONSES`. |
-
-#### Key Design: Self-Registering Plugins
-
-```javascript
-// Each translator file calls register() on import:
-import { register } from "../index.js";
-register("claude", "openai", translateClaudeToOpenAI);
-
-// The index.js imports all translator files, triggering registration:
-import "./request/claude-to-openai.js"; // ← self-registers
-```
-
----
-
-### 4.6 Utils (`open-sse/utils/`)
-
-| File | Purpose |
-| ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
-| `error.ts` | Error response building (OpenAI-compatible format), upstream error parsing, Antigravity retry-time extraction from error messages, SSE error streaming. |
-| `stream.ts` | **SSE Transform Stream** — the core streaming pipeline. Two modes: `TRANSLATE` (full format translation) and `PASSTHROUGH` (normalize + extract usage). Handles chunk buffering, usage estimation, content length tracking. Per-stream encoder/decoder instances avoid shared state. |
-| `streamHelpers.ts` | Low-level SSE utilities: `parseSSELine` (whitespace-tolerant), `hasValuableContent` (filters empty chunks for OpenAI/Claude/Gemini), `fixInvalidId`, `formatSSE` (format-aware SSE serialization with `perf_metrics` cleanup). |
-| `usageTracking.ts` | Token usage extraction from any format (Claude/OpenAI/Gemini/Responses), estimation with separate tool/message char-per-token ratios, buffer addition (2000 tokens safety margin), format-specific field filtering, console logging with ANSI colors. |
-| `requestLogger.ts` | File-based request logging (opt-in via `ENABLE_REQUEST_LOGS=true`). Creates session folders with numbered files: `1_req_client.json` → `7_res_client.txt`. All I/O is async (fire-and-forget). Masks sensitive headers. |
-| `bypassHandler.ts` | Intercepts specific patterns from Claude CLI (title extraction, warmup, count) and returns fake responses without calling any provider. Supports both streaming and non-streaming. Intentionally limited to Claude CLI scope. |
-| `networkProxy.ts` | Resolves outbound proxy URL for a given provider with precedence: provider-specific config → global config → environment variables (`HTTPS_PROXY`/`HTTP_PROXY`/`ALL_PROXY`). Supports `NO_PROXY` exclusions. Caches config for 30s. |
-
-#### SSE Streaming Pipeline
-
-```mermaid
-flowchart TD
- A["Provider SSE stream"] --> B["TextDecoder\n(per-stream instance)"]
- B --> C["Buffer lines\n(split on newline)"]
- C --> D["parseSSELine()\n(trim whitespace, parse JSON)"]
- D --> E{"Mode?"}
- E -->|TRANSLATE| F["translateResponse()\ntarget → OpenAI → source"]
- E -->|PASSTHROUGH| G["fixInvalidId()\nnormalize chunk"]
- F --> H["hasValuableContent()\nfilter empty chunks"]
- G --> H
- H -->|"Has content"| I["extractUsage()\ntrack token counts"]
- H -->|"Empty"| J["Skip chunk"]
- I --> K["formatSSE()\nserialize + clean perf_metrics"]
- K --> L["TextEncoder\n(per-stream instance)"]
- L --> M["Enqueue to\nclient stream"]
-
- style A fill:#f9f,stroke:#333
- style M fill:#9f9,stroke:#333
-```
-
-#### Request Logger Session Structure
-
-```
-logs/
-└── claude_gemini_claude-sonnet_20260208_143045/
- ├── 1_req_client.json ← Raw client request
- ├── 2_req_source.json ← After initial conversion
- ├── 3_req_openai.json ← OpenAI intermediate format
- ├── 4_req_target.json ← Final target format
- ├── 5_res_provider.txt ← Provider SSE chunks (streaming)
- ├── 5_res_provider.json ← Provider response (non-streaming)
- ├── 6_res_openai.txt ← OpenAI intermediate chunks
- ├── 7_res_client.txt ← Client-facing SSE chunks
- └── 6_error.json ← Error details (if any)
-```
-
----
-
-### 4.7 Application Layer (`src/`)
-
-| Directory | Purpose |
-| ------------- | ---------------------------------------------------------------------- |
-| `src/app/` | Web UI, API routes, Express middleware, OAuth callback handlers |
-| `src/lib/` | Database access (`localDb.ts`, `usageDb.ts`), authentication, shared |
-| `src/mitm/` | Man-in-the-middle proxy utilities for intercepting provider traffic |
-| `src/models/` | Database model definitions |
-| `src/shared/` | Wrappers around open-sse functions (provider, stream, error, etc.) |
-| `src/sse/` | SSE endpoint handlers that wire the open-sse library to Express routes |
-| `src/store/` | Application state management |
-
-#### Notable API Routes
-
-| Route | Methods | Purpose |
-| --------------------------------------------- | --------------- | ------------------------------------------------------------------------------------- |
-| `/api/provider-models` | GET/POST/DELETE | CRUD for custom models per provider |
-| `/api/models/catalog` | GET | Aggregated catalog of all models (chat, embedding, image, custom) grouped by provider |
-| `/api/settings/proxy` | GET/PUT/DELETE | Hierarchical outbound proxy configuration (`global/providers/combos/keys`) |
-| `/api/settings/proxy/test` | POST | Validates proxy connectivity and returns public IP/latency |
-| `/v1/providers/[provider]/chat/completions` | POST | Dedicated per-provider chat completions with model validation |
-| `/v1/providers/[provider]/embeddings` | POST | Dedicated per-provider embeddings with model validation |
-| `/v1/providers/[provider]/images/generations` | POST | Dedicated per-provider image generation with model validation |
-| `/api/settings/ip-filter` | GET/PUT | IP allowlist/blocklist management |
-| `/api/settings/thinking-budget` | GET/PUT | Reasoning token budget configuration (passthrough/auto/custom/adaptive) |
-| `/api/settings/system-prompt` | GET/PUT | Global system prompt injection for all requests |
-| `/api/sessions` | GET | Active session tracking and metrics |
-| `/api/rate-limits` | GET | Per-account rate limit status |
-
----
-
-## 5. Key Design Patterns
-
-### 5.1 Hub-and-Spoke Translation
-
-All formats translate through **OpenAI format as the hub**. Adding a new provider only requires writing **one pair** of translators (to/from OpenAI), not N pairs.
-
-### 5.2 Executor Strategy Pattern
-
-Each provider has a dedicated executor class inheriting from `BaseExecutor`. The factory in `executors/index.ts` selects the right one at runtime.
-
-### 5.3 Self-Registering Plugin System
-
-Translator modules register themselves on import via `register()`. Adding a new translator is just creating a file and importing it.
-
-### 5.4 Account Fallback with Exponential Backoff
-
-When a provider returns 429/401/500, the system can switch to the next account, applying exponential cooldowns (1s → 2s → 4s → max 2min).
-
-### 5.5 Combo Model Chains
-
-A "combo" groups multiple `provider/model` strings. If the first fails, fallback to the next automatically.
-
-### 5.6 Stateful Streaming Translation
-
-Response translation maintains state across SSE chunks (thinking block tracking, tool call accumulation, content block indexing) via the `initState()` mechanism.
-
-### 5.7 Usage Safety Buffer
-
-A 2000-token buffer is added to reported usage to prevent clients from hitting context window limits due to overhead from system prompts and format translation.
-
----
-
-## 6. Supported Formats
-
-| Format | Direction | Identifier |
-| ----------------------- | --------------- | ------------------ |
-| OpenAI Chat Completions | source + target | `openai` |
-| OpenAI Responses API | source + target | `openai-responses` |
-| Anthropic Claude | source + target | `claude` |
-| Google Gemini | source + target | `gemini` |
-| Google Gemini CLI | target only | `gemini-cli` |
-| Antigravity | source + target | `antigravity` |
-| AWS Kiro | target only | `kiro` |
-| Cursor | target only | `cursor` |
-
----
-
-## 7. Supported Providers
-
-| Provider | Auth Method | Executor | Key Notes |
-| ------------------------ | ---------------------- | ----------- | --------------------------------------------- |
-| Anthropic Claude | API key or OAuth | Default | Uses `x-api-key` header |
-| Google Gemini | API key or OAuth | Default | Uses `x-goog-api-key` header |
-| Google Gemini CLI | OAuth | GeminiCLI | Uses `streamGenerateContent` endpoint |
-| Antigravity | OAuth | Antigravity | Multi-URL fallback, custom retry parsing |
-| OpenAI | API key | Default | Standard Bearer auth |
-| Codex | OAuth | Codex | Injects system instructions, manages thinking |
-| GitHub Copilot | OAuth + Copilot token | Github | Dual token, VSCode header mimicking |
-| Kiro (AWS) | AWS SSO OIDC or Social | Kiro | Binary EventStream parsing |
-| Cursor IDE | Checksum auth | Cursor | Protobuf encoding, SHA-256 checksums |
-| Qwen | OAuth | Default | Standard auth |
-| Qoder | OAuth (Basic + Bearer) | Default | Dual auth header |
-| OpenRouter | API key | Default | Standard Bearer auth |
-| GLM, Kimi, MiniMax | API key | Default | Claude-compatible, use `x-api-key` |
-| `openai-compatible-*` | API key | Default | Dynamic: any OpenAI-compatible endpoint |
-| `anthropic-compatible-*` | API key | Default | Dynamic: any Claude-compatible endpoint |
-
----
-
-## 8. Data Flow Summary
-
-### Streaming Request
-
-```mermaid
-flowchart LR
- A["Client"] --> B["detectFormat()"]
- B --> C["translateRequest()\nsource → OpenAI → target"]
- C --> D["Executor\nbuildUrl + buildHeaders"]
- D --> E["fetch(providerURL)"]
- E --> F["createSSEStream()\nTRANSLATE mode"]
- F --> G["parseSSELine()"]
- G --> H["translateResponse()\ntarget → OpenAI → source"]
- H --> I["extractUsage()\n+ addBuffer"]
- I --> J["formatSSE()"]
- J --> K["Client receives\ntranslated SSE"]
- K --> L["logUsage()\nsaveRequestUsage()"]
-```
-
-### Non-Streaming Request
-
-```mermaid
-flowchart LR
- A["Client"] --> B["detectFormat()"]
- B --> C["translateRequest()\nsource → OpenAI → target"]
- C --> D["Executor.execute()"]
- D --> E["translateResponse()\ntarget → OpenAI → source"]
- E --> F["Return JSON\nresponse"]
-```
-
-### Bypass Flow (Claude CLI)
-
-```mermaid
-flowchart LR
- A["Claude CLI request"] --> B{"Match bypass\npattern?"}
- B -->|"Title/Warmup/Count"| C["Generate fake\nOpenAI response"]
- B -->|"No match"| D["Normal flow"]
- C --> E["Translate to\nsource format"]
- E --> F["Return without\ncalling provider"]
-```
diff --git a/docs/i18n/in/CONTRIBUTING.md b/docs/i18n/in/CONTRIBUTING.md
new file mode 100644
index 0000000000..b9a4068f41
--- /dev/null
+++ b/docs/i18n/in/CONTRIBUTING.md
@@ -0,0 +1,299 @@
+# Contributing to OmniRoute (हिन्दी)
+
+🌐 **Languages:** 🇺🇸 [English](../../../CONTRIBUTING.md) · 🇪🇸 [es](../es/CONTRIBUTING.md) · 🇫🇷 [fr](../fr/CONTRIBUTING.md) · 🇩🇪 [de](../de/CONTRIBUTING.md) · 🇮🇹 [it](../it/CONTRIBUTING.md) · 🇷🇺 [ru](../ru/CONTRIBUTING.md) · 🇨🇳 [zh-CN](../zh-CN/CONTRIBUTING.md) · 🇯🇵 [ja](../ja/CONTRIBUTING.md) · 🇰🇷 [ko](../ko/CONTRIBUTING.md) · 🇸🇦 [ar](../ar/CONTRIBUTING.md) · 🇮🇳 [in](../in/CONTRIBUTING.md) · 🇹🇭 [th](../th/CONTRIBUTING.md) · 🇻🇳 [vi](../vi/CONTRIBUTING.md) · 🇮🇩 [id](../id/CONTRIBUTING.md) · 🇲🇾 [ms](../ms/CONTRIBUTING.md) · 🇳🇱 [nl](../nl/CONTRIBUTING.md) · 🇵🇱 [pl](../pl/CONTRIBUTING.md) · 🇸🇪 [sv](../sv/CONTRIBUTING.md) · 🇳🇴 [no](../no/CONTRIBUTING.md) · 🇩🇰 [da](../da/CONTRIBUTING.md) · 🇫🇮 [fi](../fi/CONTRIBUTING.md) · 🇵🇹 [pt](../pt/CONTRIBUTING.md) · 🇷🇴 [ro](../ro/CONTRIBUTING.md) · 🇭🇺 [hu](../hu/CONTRIBUTING.md) · 🇧🇬 [bg](../bg/CONTRIBUTING.md) · 🇸🇰 [sk](../sk/CONTRIBUTING.md) · 🇺🇦 [uk-UA](../uk-UA/CONTRIBUTING.md) · 🇮🇱 [he](../he/CONTRIBUTING.md) · 🇵🇭 [phi](../phi/CONTRIBUTING.md) · 🇧🇷 [pt-BR](../pt-BR/CONTRIBUTING.md) · 🇨🇿 [cs](../cs/CONTRIBUTING.md)
+
+---
+
+Thank you for your interest in contributing! This guide covers everything you need to get started.
+
+---
+
+## Development Setup
+
+### Prerequisites
+
+- **Node.js** >= 18 < 24 (recommended: 22 LTS)
+- **npm** 10+
+- **Git**
+
+### Clone & Install
+
+```bash
+git clone https://github.com/diegosouzapw/OmniRoute.git
+cd OmniRoute
+npm install
+```
+
+### Environment Variables
+
+```bash
+# Create your .env from the template
+cp .env.example .env
+
+# Generate required secrets
+echo "JWT_SECRET=$(openssl rand -base64 48)" >> .env
+echo "API_KEY_SECRET=$(openssl rand -hex 32)" >> .env
+```
+
+Key variables for development:
+
+| Variable | Development Default | Description |
+| ---------------------- | ------------------------ | --------------------- |
+| `PORT` | `20128` | Server port |
+| `NEXT_PUBLIC_BASE_URL` | `http://localhost:20128` | Base URL for frontend |
+| `JWT_SECRET` | (generate above) | JWT signing secret |
+| `INITIAL_PASSWORD` | `CHANGEME` | First login password |
+| `APP_LOG_LEVEL` | `info` | Log verbosity level |
+
+### Dashboard Settings
+
+The dashboard provides UI toggles for features that can also be configured via environment variables:
+
+| Setting Location | Toggle | Description |
+| ------------------- | ------------------ | ------------------------------ |
+| Settings → Advanced | Debug Mode | Enable debug request logs (UI) |
+| Settings → General | Sidebar Visibility | Show/hide sidebar sections |
+
+These settings are stored in the database and persist across restarts, overriding env var defaults when set.
+
+### Running Locally
+
+```bash
+# Development mode (hot reload)
+npm run dev
+
+# Production build
+npm run build
+npm run start
+
+# Common port configuration
+PORT=20128 NEXT_PUBLIC_BASE_URL=http://localhost:20128 npm run dev
+```
+
+Default URLs:
+
+- **Dashboard**: `http://localhost:20128/dashboard`
+- **API**: `http://localhost:20128/v1`
+
+---
+
+## Git Workflow
+
+> ⚠️ **NEVER commit directly to `main`.** Always use feature branches.
+
+```bash
+git checkout -b feat/your-feature-name
+# ... make changes ...
+git commit -m "feat: describe your change"
+git push -u origin feat/your-feature-name
+# Open a Pull Request on GitHub
+```
+
+### Branch Naming
+
+| Prefix | Purpose |
+| ----------- | ------------------------- |
+| `feat/` | New features |
+| `fix/` | Bug fixes |
+| `refactor/` | Code restructuring |
+| `docs/` | Documentation changes |
+| `test/` | Test additions/fixes |
+| `chore/` | Tooling, CI, dependencies |
+
+### Commit Messages
+
+Follow [Conventional Commits](https://www.conventionalcommits.org/):
+
+```
+feat: add circuit breaker for provider calls
+fix: resolve JWT secret validation edge case
+docs: update SECURITY.md with PII protection
+test: add observability unit tests
+refactor(db): consolidate rate limit tables
+```
+
+Scopes: `db`, `sse`, `oauth`, `dashboard`, `api`, `cli`, `docker`, `ci`, `mcp`, `a2a`, `memory`, `skills`.
+
+---
+
+## Running Tests
+
+```bash
+# All tests (unit + vitest + ecosystem + e2e)
+npm run test:all
+
+# Single test file (Node.js native test runner — most tests use this)
+node --import tsx/esm --test tests/unit/your-file.test.mjs
+
+# Vitest (MCP server, autoCombo, cache)
+npm run test:vitest
+
+# E2E tests (requires Playwright)
+npm run test:e2e
+
+# Protocol clients E2E (MCP transports, A2A)
+npm run test:protocols:e2e
+
+# Ecosystem compatibility tests
+npm run test:ecosystem
+
+# Coverage (55% min statements/lines/functions; 60% branches)
+npm run test:coverage
+npm run coverage:report
+
+# Lint + format check
+npm run lint
+npm run check
+```
+
+Coverage notes:
+
+- `npm run test:coverage` measures source coverage for the main unit test suite, excludes `tests/**`, and includes `open-sse/**`
+- `npm run coverage:report` prints the detailed file-by-file report from the latest coverage run
+- `npm run test:coverage:legacy` preserves the older metric for historical comparison
+- See `docs/COVERAGE_PLAN.md` for the phased coverage improvement roadmap
+
+Current test status: **122 unit test files** covering:
+
+- Provider translators and format conversion
+- Rate limiting, circuit breaker, and resilience
+- Semantic cache, idempotency, progress tracking
+- Database operations and schema (21 DB modules)
+- OAuth flows and authentication
+- API endpoint validation (Zod v4)
+- MCP server tools and scope enforcement
+- Memory and Skills systems
+
+---
+
+## Code Style
+
+- **ESLint** — Run `npm run lint` before committing
+- **Prettier** — Auto-formatted via `lint-staged` on commit (2 spaces, semicolons, double quotes, 100 char width, es5 trailing commas)
+- **TypeScript** — All `src/` code uses `.ts`/`.tsx`; `open-sse/` uses `.ts`/`.js`; document with TSDoc (`@param`, `@returns`, `@throws`)
+- **No `eval()`** — ESLint enforces `no-eval`, `no-implied-eval`, `no-new-func`
+- **Zod validation** — Use Zod v4 schemas for all API input validation
+- **Naming**: Files = camelCase/kebab-case, components = PascalCase, constants = UPPER_SNAKE
+
+---
+
+## Project Structure
+
+```
+src/ # TypeScript (.ts / .tsx)
+├── app/ # Next.js 16 App Router
+│ ├── (dashboard)/ # Dashboard pages (23 sections)
+│ ├── api/ # API routes (51 directories)
+│ └── login/ # Auth pages (.tsx)
+├── domain/ # Policy engine (policyEngine, comboResolver, costRules, etc.)
+├── lib/ # Core business logic (.ts)
+│ ├── a2a/ # Agent-to-Agent v0.3 protocol server
+│ ├── acp/ # Agent Communication Protocol registry
+│ ├── compliance/ # Compliance policy engine
+│ ├── db/ # SQLite database layer (21 modules + 16 migrations)
+│ ├── memory/ # Persistent conversational memory
+│ ├── oauth/ # OAuth providers, services, and utilities
+│ ├── skills/ # Extensible skill framework
+│ ├── usage/ # Usage tracking and cost calculation
+│ └── localDb.ts # Re-export layer only — never add logic here
+├── middleware/ # Request middleware (promptInjectionGuard)
+├── mitm/ # MITM proxy (cert, DNS, target routing)
+├── shared/
+│ ├── components/ # React components (.tsx)
+│ ├── constants/ # Provider definitions (60+), MCP scopes, routing strategies
+│ ├── utils/ # Circuit breaker, sanitizer, auth helpers
+│ └── validation/ # Zod v4 schemas
+└── sse/ # SSE proxy pipeline
+
+open-sse/ # @omniroute/open-sse workspace
+├── executors/ # 14 provider-specific request executors
+├── handlers/ # 11 request handlers (chat, responses, embeddings, images, etc.)
+├── mcp-server/ # MCP server (25 tools, 3 transports, 10 scopes)
+├── services/ # 36+ services (combo, autoCombo, rateLimitManager, etc.)
+├── translator/ # Format translators (OpenAI ↔ Claude ↔ Gemini ↔ Responses ↔ Ollama)
+├── transformer/ # Responses API transformer
+└── utils/ # 22 utility modules (stream, TLS, proxy, logging)
+
+electron/ # Electron desktop app (cross-platform)
+
+tests/
+├── unit/ # Node.js test runner (122 test files)
+├── integration/ # Integration tests
+├── e2e/ # Playwright tests
+├── security/ # Security tests
+├── translator/ # Translator-specific tests
+└── load/ # Load tests
+
+docs/ # Documentation
+├── ARCHITECTURE.md # System architecture
+├── API_REFERENCE.md # All endpoints
+├── USER_GUIDE.md # Provider setup, CLI integration
+├── TROUBLESHOOTING.md # Common issues
+├── MCP-SERVER.md # MCP server (25 tools)
+├── A2A-SERVER.md # A2A agent protocol
+├── AUTO-COMBO.md # Auto-combo engine
+├── CLI-TOOLS.md # CLI tools integration
+├── COVERAGE_PLAN.md # Test coverage improvement plan
+├── openapi.yaml # OpenAPI specification
+└── adr/ # Architecture Decision Records
+```
+
+---
+
+## Adding a New Provider
+
+### Step 1: Register Provider Constants
+
+Add to `src/shared/constants/providers.ts` — Zod-validated at module load.
+
+### Step 2: Add Executor (if custom logic needed)
+
+Create executor in `open-sse/executors/your-provider.ts` extending the base executor.
+
+### Step 3: Add Translator (if non-OpenAI format)
+
+Create request/response translators in `open-sse/translator/`.
+
+### Step 4: Add OAuth Config (if OAuth-based)
+
+Add OAuth credentials in `src/lib/oauth/constants/oauth.ts` and service in `src/lib/oauth/services/`.
+
+### Step 5: Register Models
+
+Add model definitions in `open-sse/config/providerRegistry.ts`.
+
+### Step 6: Add Tests
+
+Write unit tests in `tests/unit/` covering at minimum:
+
+- Provider registration
+- Request/response translation
+- Error handling
+
+---
+
+## Pull Request Checklist
+
+- [ ] Tests pass (`npm test`)
+- [ ] Linting passes (`npm run lint`)
+- [ ] Build succeeds (`npm run build`)
+- [ ] TypeScript types added for new public functions and interfaces
+- [ ] No hardcoded secrets or fallback values
+- [ ] All inputs validated with Zod schemas
+- [ ] CHANGELOG updated (if user-facing change)
+- [ ] Documentation updated (if applicable)
+
+---
+
+## Releasing
+
+Releases are managed via the `/generate-release` workflow. When a new GitHub Release is created, the package is **automatically published to npm** via GitHub Actions.
+
+---
+
+## Getting Help
+
+- **Architecture**: See [`docs/ARCHITECTURE.md`](docs/ARCHITECTURE.md)
+- **API Reference**: See [`docs/API_REFERENCE.md`](docs/API_REFERENCE.md)
+- **Issues**: [github.com/diegosouzapw/OmniRoute/issues](https://github.com/diegosouzapw/OmniRoute/issues)
+- **ADRs**: See `docs/adr/` for architectural decision records
diff --git a/docs/i18n/in/FEATURES.md b/docs/i18n/in/FEATURES.md
deleted file mode 100644
index 8f6537af4d..0000000000
--- a/docs/i18n/in/FEATURES.md
+++ /dev/null
@@ -1,147 +0,0 @@
-# OmniRoute — Dashboard Features Gallery (हिन्दी)
-
-🌐 **Languages:** 🇺🇸 [English](../../../README.md) · 🇧🇷 [pt-BR](../pt-BR/README.md) · 🇪🇸 [es](../es/README.md) · 🇫🇷 [fr](../fr/README.md) · 🇩🇪 [de](../de/README.md) · 🇮🇹 [it](../it/README.md) · 🇷🇺 [ru](../ru/README.md) · 🇨🇳 [zh-CN](../zh-CN/README.md) · 🇯🇵 [ja](../ja/README.md) · 🇰🇷 [ko](../ko/README.md) · 🇸🇦 [ar](../ar/README.md) · 🇮🇳 [in](../in/README.md) · 🇹🇭 [th](../th/README.md) · 🇻🇳 [vi](../vi/README.md) · 🇮🇩 [id](../id/README.md) · 🇲🇾 [ms](../ms/README.md) · 🇳🇱 [nl](../nl/README.md) · 🇵🇱 [pl](../pl/README.md) · 🇸🇪 [sv](../sv/README.md) · 🇳🇴 [no](../no/README.md) · 🇩🇰 [da](../da/README.md) · 🇫🇮 [fi](../fi/README.md) · 🇵🇹 [pt](../pt/README.md) · 🇷🇴 [ro](../ro/README.md) · 🇭🇺 [hu](../hu/README.md) · 🇧🇬 [bg](../bg/README.md) · 🇸🇰 [sk](../sk/README.md) · 🇺🇦 [uk-UA](../uk-UA/README.md) · 🇮🇱 [he](../he/README.md) · 🇵🇭 [phi](../phi/README.md)
-
-> 🇺🇸 [English](../../../docs/FEATURES.md)
-
----
-
-Visual guide to every section of the OmniRoute dashboard.
-
----
-
-## 🔌 Providers
-
-Manage AI provider connections: OAuth providers (Claude Code, Codex, Gemini CLI), API key providers (Groq, DeepSeek, OpenRouter), and free providers (Qoder, Qwen, Kiro). Kiro accounts include credit balance tracking — remaining credits, total allowance, and renewal date visible in Dashboard → Usage.
-
-
-
----
-
-## 🎨 Combos
-
-Create model routing combos with 6 strategies: priority, weighted, round-robin, random, least-used, and cost-optimized. Each combo chains multiple models with automatic fallback and includes quick templates and readiness checks.
-
-
-
----
-
-## 📊 Analytics
-
-Comprehensive usage analytics with token consumption, cost estimates, activity heatmaps, weekly distribution charts, and per-provider breakdowns.
-
-
-
----
-
-## 🏥 System Health
-
-Real-time monitoring: uptime, memory, version, latency percentiles (p50/p95/p99), cache statistics, and provider circuit breaker states.
-
-
-
----
-
-## 🔧 Translator Playground
-
-Four modes for debugging API translations: **Playground** (format converter), **Chat Tester** (live requests), **Test Bench** (batch tests), and **Live Monitor** (real-time stream).
-
-
-
----
-
-## 🎮 Model Playground _(v2.0.9+)_
-
-Test any model directly from the dashboard. Select provider, model, and endpoint, write prompts with Monaco Editor, stream responses in real-time, abort mid-stream, and view timing metrics.
-
----
-
-## 🎨 Themes _(v2.0.5+)_
-
-Customizable color themes for the entire dashboard. Choose from 7 preset colors (Coral, Blue, Red, Green, Violet, Orange, Cyan) or create a custom theme by picking any hex color. Supports light, dark, and system mode.
-
----
-
-## ⚙️ Settings
-
-Comprehensive settings panel with tabs:
-
-- **General** — System storage, backup management (export/import database)
-- **Appearance** — Theme selector (dark/light/system), color theme presets and custom colors, health log visibility, sidebar item visibility controls
-- **Security** — API endpoint protection, custom provider blocking, IP filtering, session info
-- **Routing** — Model aliases, background task degradation
-- **Resilience** — Rate limit persistence, circuit breaker tuning
-- **Advanced** — Configuration overrides
-
-
-
----
-
-## 🔧 CLI Tools
-
-One-click configuration for AI coding tools: Claude Code, Codex CLI, Gemini CLI, OpenClaw, Kilo Code, Antigravity, Cline, Continue, Cursor, and Factory Droid. Features automated config apply/reset, connection profiles, and model mapping.
-
-
-
----
-
-## 🤖 CLI Agents _(v2.0.11+)_
-
-Dashboard for discovering and managing CLI agents. Shows a grid of 14 built-in agents (Codex, Claude, Goose, Gemini CLI, OpenClaw, Aider, OpenCode, Cline, Qwen Code, ForgeCode, Amazon Q, Open Interpreter, Cursor CLI, Warp) with:
-
-- **Installation status** — Installed / Not Found with version detection
-- **Protocol badges** — stdio, HTTP, etc.
-- **Custom agents** — Register any CLI tool via form (name, binary, version command, spawn args)
-- **CLI Fingerprint Matching** — Per-provider toggle to match native CLI request signatures, reducing ban risk while preserving proxy IP
-
----
-
-## 🖼️ Media _(v2.0.3+)_
-
-Generate images, videos, and music from the dashboard. Supports OpenAI, xAI, Together, Hyperbolic, SD WebUI, ComfyUI, AnimateDiff, Stable Audio Open, and MusicGen.
-
----
-
-## 📝 Request Logs
-
-Real-time request logging with filtering by provider, model, account, and API key. Shows status codes, token usage, latency, and response details.
-
-
-
----
-
-## 🌐 API Endpoint
-
-Your unified API endpoint with capability breakdown: Chat Completions, Responses API, Embeddings, Image Generation, Reranking, Audio Transcription, Text-to-Speech, Moderations, and registered API keys. Cloud proxy support for remote access.
-
-
-
----
-
-## 🔑 API Key Management
-
-Create, scope, and revoke API keys. Each key can be restricted to specific models/providers with full access or read-only permissions. Visual key management with usage tracking.
-
----
-
-## 📋 Audit Log
-
-Administrative action tracking with filtering by action type, actor, target, IP address, and timestamp. Full security event history.
-
----
-
-## 🖥️ Desktop Application
-
-Native Electron desktop app for Windows, macOS, and Linux. Run OmniRoute as a standalone application with system tray integration, offline support, auto-update, and one-click install.
-
-Key features:
-
-- Server readiness polling (no blank screen on cold start)
-- System tray with port management
-- Content Security Policy
-- Single-instance lock
-- Auto-update on restart
-- Platform-conditional UI (macOS traffic lights, Windows/Linux default titlebar)
-- Hardened Electron build packaging — symlinked `node_modules` in the standalone bundle is detected and rejected before packaging, preventing runtime dependency on the build machine (v2.5.5+)
-
-📖 See [`electron/README.md`](../electron/README.md) for full documentation.
diff --git a/docs/i18n/in/MCP-SERVER.md b/docs/i18n/in/MCP-SERVER.md
deleted file mode 100644
index 829acd30b1..0000000000
--- a/docs/i18n/in/MCP-SERVER.md
+++ /dev/null
@@ -1,87 +0,0 @@
-🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/MCP-SERVER.md) · 🇪🇸 [es](../es/MCP-SERVER.md) · 🇫🇷 [fr](../fr/MCP-SERVER.md) · 🇩🇪 [de](../de/MCP-SERVER.md) · 🇮🇹 [it](../it/MCP-SERVER.md) · 🇷🇺 [ru](../ru/MCP-SERVER.md) · 🇨🇳 [zh-CN](../zh-CN/MCP-SERVER.md) · 🇯🇵 [ja](../ja/MCP-SERVER.md) · 🇰🇷 [ko](../ko/MCP-SERVER.md) · 🇸🇦 [ar](../ar/MCP-SERVER.md) · 🇮🇳 [in](../in/MCP-SERVER.md) · 🇹🇭 [th](../th/MCP-SERVER.md) · 🇻🇳 [vi](../vi/MCP-SERVER.md) · 🇮🇩 [id](../id/MCP-SERVER.md) · 🇲🇾 [ms](../ms/MCP-SERVER.md) · 🇳🇱 [nl](../nl/MCP-SERVER.md) · 🇵🇱 [pl](../pl/MCP-SERVER.md) · 🇸🇪 [sv](../sv/MCP-SERVER.md) · 🇳🇴 [no](../no/MCP-SERVER.md) · 🇩🇰 [da](../da/MCP-SERVER.md) · 🇫🇮 [fi](../fi/MCP-SERVER.md) · 🇵🇹 [pt](../pt/MCP-SERVER.md) · 🇷🇴 [ro](../ro/MCP-SERVER.md) · 🇭🇺 [hu](../hu/MCP-SERVER.md) · 🇧🇬 [bg](../bg/MCP-SERVER.md) · 🇸🇰 [sk](../sk/MCP-SERVER.md) · 🇺🇦 [uk-UA](../uk-UA/MCP-SERVER.md) · 🇮🇱 [he](../he/MCP-SERVER.md) · 🇵🇭 [phi](../phi/MCP-SERVER.md)
-
----
-
-# OmniRoute MCP Server Documentation
-
-> Model Context Protocol server with 16 intelligent tools
-
-## Installation
-
-OmniRoute MCP is built-in. Start it with:
-
-```bash
-omniroute --mcp
-```
-
-Or via the open-sse transport:
-
-```bash
-# HTTP streamable transport (port 20130)
-omniroute --dev # MCP auto-starts on /mcp endpoint
-```
-
-## IDE Configuration
-
-See [IDE Configs](integrations/ide-configs.md) for Antigravity, Cursor, Copilot, and Claude Desktop setup.
-
----
-
-## Essential Tools (8)
-
-| Tool | Description |
-| :------------------------------ | :--------------------------------------- |
-| `omniroute_get_health` | Gateway health, circuit breakers, uptime |
-| `omniroute_list_combos` | All configured combos with models |
-| `omniroute_get_combo_metrics` | Performance metrics for a specific combo |
-| `omniroute_switch_combo` | Switch active combo by ID/name |
-| `omniroute_check_quota` | Quota status per provider or all |
-| `omniroute_route_request` | Send a chat completion through OmniRoute |
-| `omniroute_cost_report` | Cost analytics for a time period |
-| `omniroute_list_models_catalog` | Full model catalog with capabilities |
-
-## Advanced Tools (8)
-
-| Tool | Description |
-| :--------------------------------- | :---------------------------------------------- |
-| `omniroute_simulate_route` | Dry-run routing simulation with fallback tree |
-| `omniroute_set_budget_guard` | Session budget with degrade/block/alert actions |
-| `omniroute_set_resilience_profile` | Apply conservative/balanced/aggressive preset |
-| `omniroute_test_combo` | Live-test all models in a combo |
-| `omniroute_get_provider_metrics` | Detailed metrics for one provider |
-| `omniroute_best_combo_for_task` | Task-fitness recommendation with alternatives |
-| `omniroute_explain_route` | Explain a past routing decision |
-| `omniroute_get_session_snapshot` | Full session state: costs, tokens, errors |
-
-## Authentication
-
-MCP tools are authenticated via API key scopes. Each tool requires specific scopes:
-
-| Scope | Tools |
-| :------------- | :----------------------------------------------- |
-| `read:health` | get_health, get_provider_metrics |
-| `read:combos` | list_combos, get_combo_metrics |
-| `write:combos` | switch_combo |
-| `read:quota` | check_quota |
-| `write:route` | route_request, simulate_route, test_combo |
-| `read:usage` | cost_report, get_session_snapshot, explain_route |
-| `write:config` | set_budget_guard, set_resilience_profile |
-| `read:models` | list_models_catalog, best_combo_for_task |
-
-## Audit Logging
-
-Every tool call is logged to `mcp_tool_audit` with:
-
-- Tool name, arguments, result
-- Duration (ms), success/failure
-- API key hash, timestamp
-
-## Files
-
-| File | Purpose |
-| :------------------------------------------- | :------------------------------------------ |
-| `open-sse/mcp-server/server.ts` | MCP server creation + 16 tool registrations |
-| `open-sse/mcp-server/transport.ts` | Stdio + HTTP transport |
-| `open-sse/mcp-server/auth.ts` | API key + scope validation |
-| `open-sse/mcp-server/audit.ts` | Tool call audit logging |
-| `open-sse/mcp-server/tools/advancedTools.ts` | 8 advanced tool handlers |
diff --git a/docs/i18n/in/README.md b/docs/i18n/in/README.md
index f575f62151..f2a089377a 100644
--- a/docs/i18n/in/README.md
+++ b/docs/i18n/in/README.md
@@ -1,13 +1,12 @@
# 🚀 OmniRoute — The Free AI Gateway (हिन्दी)
-🌐 **Languages:** 🇺🇸 [English](../../../README.md) · 🇪🇸 [es](../es/README.md) · 🇫🇷 [fr](../fr/README.md) · 🇩🇪 [de](../de/README.md) · 🇮🇹 [it](../it/README.md) · 🇷🇺 [ru](../ru/README.md) · 🇨🇳 [zh-CN](../zh-CN/README.md) · 🇯🇵 [ja](../ja/README.md) · 🇰🇷 [ko](../ko/README.md) · 🇸🇦 [ar](../ar/README.md) · 🇮🇳 [in](../in/README.md) · 🇹🇭 [th](../th/README.md) · 🇻🇳 [vi](../vi/README.md) · 🇮🇩 [id](../id/README.md) · 🇲🇾 [ms](../ms/README.md) · 🇳🇱 [nl](../nl/README.md) · 🇵🇱 [pl](../pl/README.md) · 🇸🇪 [sv](../sv/README.md) · 🇳🇴 [no](../no/README.md) · 🇩🇰 [da](../da/README.md) · 🇫🇮 [fi](../fi/README.md) · 🇵🇹 [pt](../pt/README.md) · 🇷🇴 [ro](../ro/README.md) · 🇭🇺 [hu](../hu/README.md) · 🇧🇬 [bg](../bg/README.md) · 🇸🇰 [sk](../sk/README.md) · 🇺🇦 [uk-UA](../uk-UA/README.md) · 🇮🇱 [he](../he/README.md) · 🇵🇭 [phi](../phi/README.md) · 🇧🇷 [pt-BR](../pt-BR/README.md)
+🌐 **Languages:** 🇺🇸 [English](../../../README.md) · 🇪🇸 [es](../es/README.md) · 🇫🇷 [fr](../fr/README.md) · 🇩🇪 [de](../de/README.md) · 🇮🇹 [it](../it/README.md) · 🇷🇺 [ru](../ru/README.md) · 🇨🇳 [zh-CN](../zh-CN/README.md) · 🇯🇵 [ja](../ja/README.md) · 🇰🇷 [ko](../ko/README.md) · 🇸🇦 [ar](../ar/README.md) · 🇮🇳 [in](../in/README.md) · 🇹🇭 [th](../th/README.md) · 🇻🇳 [vi](../vi/README.md) · 🇮🇩 [id](../id/README.md) · 🇲🇾 [ms](../ms/README.md) · 🇳🇱 [nl](../nl/README.md) · 🇵🇱 [pl](../pl/README.md) · 🇸🇪 [sv](../sv/README.md) · 🇳🇴 [no](../no/README.md) · 🇩🇰 [da](../da/README.md) · 🇫🇮 [fi](../fi/README.md) · 🇵🇹 [pt](../pt/README.md) · 🇷🇴 [ro](../ro/README.md) · 🇭🇺 [hu](../hu/README.md) · 🇧🇬 [bg](../bg/README.md) · 🇸🇰 [sk](../sk/README.md) · 🇺🇦 [uk-UA](../uk-UA/README.md) · 🇮🇱 [he](../he/README.md) · 🇵🇭 [phi](../phi/README.md) · 🇧🇷 [pt-BR](../pt-BR/README.md) · 🇨🇿 [cs](../cs/README.md)
---
-
### Never stop coding. Smart routing to **FREE & low-cost AI models** with automatic fallback.
-_Your universal API proxy — one endpoint, 67+ providers, zero downtime. Now with **MCP & A2A** agent orchestration._
+_Your universal API proxy — one endpoint, 60+ providers, zero downtime. Now with **MCP Server (25 tools)**, **A2A Protocol**, **Memory/Skills Systems** & **Electron Desktop App**._
**Chat Completions • Embeddings • Image Generation • Video • Music • Audio • Reranking • **Web Search** • MCP Server • A2A Protocol • 100% TypeScript**
@@ -47,15 +46,17 @@ _Your universal API proxy — one endpoint, 67+ providers, zero downtime. Now wi
> - `APP_LOG_FILE_PATH`
> - `APP_LOG_MAX_FILE_SIZE`
> - `APP_LOG_RETENTION_DAYS`
+> - `APP_LOG_MAX_FILES`
> - `APP_LOG_LEVEL`
> - `APP_LOG_FORMAT`
> - `CALL_LOG_RETENTION_DAYS`
+> - `CALL_LOG_MAX_ENTRIES`
>
> For release details and upgrade notes, see the [CHANGELOG](CHANGELOG.md).
---
-## 🆕 What's New in v3.0.0
+## 🆕 What's New
> **Upgrading from v2.9.5?** — See the [full CHANGELOG](CHANGELOG.md#300--2026-03-22-release-candidate--not-yet-merged-to-main) for all changes.
@@ -275,7 +276,7 @@ Developers pay $20–200/month for Claude Pro, Codex Pro, or GitHub Copilot. Eve
- **Smart 4-Tier Fallback** — If subscription quota runs out, automatically redirects to API Key → Cheap → Free with zero manual intervention
- **Real-Time Quota Tracking** — Shows token consumption in real-time with reset countdown (5h, daily, weekly)
- **Multi-Account Support** — Multiple accounts per provider with auto round-robin — when one runs out, switches to the next
-- **Custom Combos** — Customizable fallback chains with 6 balancing strategies (fill-first, round-robin, P2C, random, least-used, cost-optimized)
+- **Custom Combos** — Customizable fallback chains with 9 balancing strategies (priority, weighted, fill-first, round-robin, P2C, random, least-used, cost-optimized, strict-random)
- **Codex Business Quotas** — Business/Team workspace quota monitoring directly in the dashboard
@@ -287,7 +288,7 @@ OpenAI uses one format, Claude (Anthropic) uses another, Gemini yet another. If
**How OmniRoute solves it:**
-- **Unified Endpoint** — A single `http://localhost:20128/v1` serves as proxy for all 67+ providers
+- **Unified Endpoint** — A single `http://localhost:20128/v1` serves as proxy for all 60+ providers
- **Format Translation** — Automatic and transparent: OpenAI ↔ Claude ↔ Gemini ↔ Responses API
- **Response Sanitization** — Strips non-standard fields (`x_groq`, `usage_breakdown`, `service_tier`) that break OpenAI SDK v1.83+
- **Role Normalization** — Converts `developer` → `system` for non-OpenAI providers; `system` → `user` for GLM/ERNIE
@@ -373,7 +374,7 @@ Developers use Cursor, Claude Code, Codex CLI, OpenClaw, Gemini CLI, Kilo Code..
- **CLI Tools Dashboard** — Dedicated page with one-click setup for Claude Code, Codex CLI, OpenClaw, Kilo Code, Antigravity, Cline
- **GitHub Copilot Config Generator** — Generates `chatLanguageModels.json` for VS Code with bulk model selection
- **Onboarding Wizard** — Guided 4-step setup for first-time users
-- **One endpoint, all models** — Configure `http://localhost:20128/v1` once, access 67+ providers
+- **One endpoint, all models** — Configure `http://localhost:20128/v1` once, access 60+ providers
@@ -420,7 +421,7 @@ When a call fails, the dev doesn't know if it was a rate limit, expired token, w
- **SQLite Proxy Logs** — Persistent logs that survive server restarts
- **Translator Playground** — 4 debugging modes: Playground (format translation), Chat Tester (round-trip), Test Bench (batch), Live Monitor (real-time)
- **Request Telemetry** — p50/p95/p99 latency + X-Request-Id tracing
-- **File-Based Logging with Rotation** — Console interceptor captures everything to JSON log with size-based rotation
+- **File-Based Logging with Rotation** — App logs rotate by size, retention days, and archive count; call log artifacts rotate by retention days and file count
- **System Info Report** — `npm run system-info` generates `system-info.txt` with your full environment (Node version, OmniRoute version, OS, CLI tools, Docker/PM2 status). Attach it when reporting issues for instant triage.
@@ -515,7 +516,7 @@ Developers who want all responses in a specific language, with a specific tone,
- **System Prompt Injection** — Global prompt applied to all requests
- **Thinking Budget Validation** — Reasoning token allocation control per request (passthrough, auto, custom, adaptive)
-- **6 Routing Strategies** — Global strategies that determine how requests are distributed
+- **9 Routing Strategies** — Global strategies that determine how requests are distributed
- **Wildcard Router** — `provider/*` patterns route dynamically to any provider
- **Combo Enable/Disable Toggle** — Toggle combos directly from the dashboard
- **Provider Toggle** — Enable/disable all connections for a provider with one click
@@ -582,7 +583,7 @@ Different clients should have least-privilege access to tool categories.
**How OmniRoute solves it:**
-- 9 granular MCP scopes for controlled tool access
+- 10 granular MCP scopes for controlled tool access
- Scope enforcement and visibility in MCP management UI
- Safe default posture for operational tooling
@@ -1326,19 +1327,19 @@ OmniRoute v2.0 is built as an operational platform, not just a relay proxy.
### 🤖 Agent & Protocol Operations (v2.0)
-| Feature | What It Does |
-| ------------------------------------- | -------------------------------------------------------------------------------------------------- |
-| 🔧 **MCP Server (16 tools)** | IDE/agent tools via 3 transports: stdio, SSE (`/api/mcp/sse`), Streamable HTTP (`/api/mcp/stream`) |
-| 🤝 **A2A Server (JSON-RPC + SSE)** | Agent-to-agent task execution with sync and streaming flows |
-| 🧭 **Consolidated Endpoints Page** | Tabbed management page with Endpoint Proxy, MCP, A2A, and API Endpoints tabs |
-| 🎚️ **Service Enable/Disable Toggles** | ON/OFF switches for MCP and A2A with settings persistence (default: OFF) |
-| 🛰️ **MCP Runtime Heartbeat** | Real process status (pid, uptime, heartbeat age, transport, scope mode) |
-| 📋 **MCP Audit Trail** | Filterable audit logs with success/failure and key attribution |
-| 🔐 **MCP Scope Enforcement** | 9 granular scope permissions for controlled tool access |
-| 📡 **A2A Task Lifecycle Management** | List/filter tasks, inspect events/artifacts, cancel running tasks |
-| 📋 **Agent Card Discovery** | `/.well-known/agent.json` for client auto-discovery |
-| 🧪 **Protocol E2E Test Harness** | Real MCP SDK + A2A client flows in `test:protocols:e2e` |
-| ⚙️ **Operational Controls** | Switch combo, apply resilience profiles, reset breakers from one control surface |
+| Feature | What It Does |
+| ------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------- |
+| 🔧 **MCP Server (25 tools)** | IDE/agent tools via 3 transports: stdio, SSE (`/api/mcp/sse`), Streamable HTTP (`/api/mcp/stream`). 18 core + 3 memory + 4 skill tools |
+| 🤝 **A2A Server (JSON-RPC + SSE)** | Agent-to-agent task execution with sync and streaming flows |
+| 🧭 **Consolidated Endpoints Page** | Tabbed management page with Endpoint Proxy, MCP, A2A, and API Endpoints tabs |
+| 🎚️ **Service Enable/Disable Toggles** | ON/OFF switches for MCP and A2A with settings persistence (default: OFF) |
+| 🛰️ **MCP Runtime Heartbeat** | Real process status (pid, uptime, heartbeat age, transport, scope mode) |
+| 📋 **MCP Audit Trail** | Filterable audit logs with success/failure and key attribution |
+| 🔐 **MCP Scope Enforcement** | 10 granular scope permissions for controlled tool access |
+| 📡 **A2A Task Lifecycle Management** | List/filter tasks, inspect events/artifacts, cancel running tasks |
+| 📋 **Agent Card Discovery** | `/.well-known/agent.json` for client auto-discovery |
+| 🧪 **Protocol E2E Test Harness** | Real MCP SDK + A2A client flows in `test:protocols:e2e` |
+| ⚙️ **Operational Controls** | Switch combo, apply resilience profiles, reset breakers from one control surface |
### 🧠 Routing & Intelligence
@@ -1349,7 +1350,7 @@ OmniRoute v2.0 is built as an operational platform, not just a relay proxy.
| 🔄 **Format Translation** | OpenAI ↔ Claude ↔ Gemini ↔ Responses with schema-safe conversions |
| 👥 **Multi-Account Support** | Multiple accounts per provider with intelligent selection |
| 🔄 **Auto Token Refresh** | OAuth tokens refresh automatically with retry |
-| 🎨 **Custom Combos** | 6 balancing strategies + fallback chain control |
+| 🎨 **Custom Combos** | 9 balancing strategies + fallback chain control |
| 🌐 **Wildcard Router** | `provider/*` dynamic routing |
| 🧠 **Thinking Budget Controls** | Passthrough, auto, custom, and adaptive reasoning limits |
| 🔀 **Model Aliases** | Built-in + custom model aliasing and migration safety |
@@ -1950,6 +1951,7 @@ opencode
- Request artifacts are written to `DATA_DIR/call_logs/` as one JSON file per request
- Enable pipeline capture from Dashboard → Logs → Request Logs if you need detailed per-stage payloads
- Set `APP_LOG_TO_FILE=true` if you also want application console logs in `logs/application/app.log`
+- Adjust `APP_LOG_MAX_FILE_SIZE`, `APP_LOG_RETENTION_DAYS`, `APP_LOG_MAX_FILES`, and `CALL_LOG_MAX_ENTRIES` as needed
**Connection test shows "Invalid" for OpenAI-compatible providers**
diff --git a/docs/i18n/in/RELEASE_CHECKLIST.md b/docs/i18n/in/RELEASE_CHECKLIST.md
deleted file mode 100644
index 903e812c3f..0000000000
--- a/docs/i18n/in/RELEASE_CHECKLIST.md
+++ /dev/null
@@ -1,37 +0,0 @@
-🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/RELEASE_CHECKLIST.md) · 🇪🇸 [es](../es/RELEASE_CHECKLIST.md) · 🇫🇷 [fr](../fr/RELEASE_CHECKLIST.md) · 🇩🇪 [de](../de/RELEASE_CHECKLIST.md) · 🇮🇹 [it](../it/RELEASE_CHECKLIST.md) · 🇷🇺 [ru](../ru/RELEASE_CHECKLIST.md) · 🇨🇳 [zh-CN](../zh-CN/RELEASE_CHECKLIST.md) · 🇯🇵 [ja](../ja/RELEASE_CHECKLIST.md) · 🇰🇷 [ko](../ko/RELEASE_CHECKLIST.md) · 🇸🇦 [ar](../ar/RELEASE_CHECKLIST.md) · 🇮🇳 [in](../in/RELEASE_CHECKLIST.md) · 🇹🇭 [th](../th/RELEASE_CHECKLIST.md) · 🇻🇳 [vi](../vi/RELEASE_CHECKLIST.md) · 🇮🇩 [id](../id/RELEASE_CHECKLIST.md) · 🇲🇾 [ms](../ms/RELEASE_CHECKLIST.md) · 🇳🇱 [nl](../nl/RELEASE_CHECKLIST.md) · 🇵🇱 [pl](../pl/RELEASE_CHECKLIST.md) · 🇸🇪 [sv](../sv/RELEASE_CHECKLIST.md) · 🇳🇴 [no](../no/RELEASE_CHECKLIST.md) · 🇩🇰 [da](../da/RELEASE_CHECKLIST.md) · 🇫🇮 [fi](../fi/RELEASE_CHECKLIST.md) · 🇵🇹 [pt](../pt/RELEASE_CHECKLIST.md) · 🇷🇴 [ro](../ro/RELEASE_CHECKLIST.md) · 🇭🇺 [hu](../hu/RELEASE_CHECKLIST.md) · 🇧🇬 [bg](../bg/RELEASE_CHECKLIST.md) · 🇸🇰 [sk](../sk/RELEASE_CHECKLIST.md) · 🇺🇦 [uk-UA](../uk-UA/RELEASE_CHECKLIST.md) · 🇮🇱 [he](../he/RELEASE_CHECKLIST.md) · 🇵🇭 [phi](../phi/RELEASE_CHECKLIST.md)
-
----
-
-# Release Checklist
-
-Use this checklist before tagging or publishing a new OmniRoute release.
-
-## Version and Changelog
-
-1. Bump `package.json` version (`x.y.z`) in the release branch.
-2. Move release notes from `## [Unreleased]` in `CHANGELOG.md` to a dated section:
- - `## [x.y.z] — YYYY-MM-DD`
-3. Keep `## [Unreleased]` as the first changelog section for upcoming work.
-4. Ensure the latest semver section in `CHANGELOG.md` equals `package.json` version.
-
-## API Docs
-
-1. Update `docs/openapi.yaml`:
- - `info.version` must equal `package.json` version.
-2. Validate endpoint examples if API contracts changed.
-
-## Runtime Docs
-
-1. Review `docs/ARCHITECTURE.md` for storage/runtime drift.
-2. Review `docs/TROUBLESHOOTING.md` for env var and operational drift.
-3. Update localized docs if source docs changed significantly.
-
-## Automated Check
-
-Run the sync guard locally before opening PR:
-
-```bash
-npm run check:docs-sync
-```
-
-CI also runs this check in `.github/workflows/ci.yml` (lint job).
diff --git a/docs/i18n/in/SECURITY.md b/docs/i18n/in/SECURITY.md
new file mode 100644
index 0000000000..391241bc39
--- /dev/null
+++ b/docs/i18n/in/SECURITY.md
@@ -0,0 +1,179 @@
+# Security Policy (हिन्दी)
+
+🌐 **Languages:** 🇺🇸 [English](../../../SECURITY.md) · 🇪🇸 [es](../es/SECURITY.md) · 🇫🇷 [fr](../fr/SECURITY.md) · 🇩🇪 [de](../de/SECURITY.md) · 🇮🇹 [it](../it/SECURITY.md) · 🇷🇺 [ru](../ru/SECURITY.md) · 🇨🇳 [zh-CN](../zh-CN/SECURITY.md) · 🇯🇵 [ja](../ja/SECURITY.md) · 🇰🇷 [ko](../ko/SECURITY.md) · 🇸🇦 [ar](../ar/SECURITY.md) · 🇮🇳 [in](../in/SECURITY.md) · 🇹🇭 [th](../th/SECURITY.md) · 🇻🇳 [vi](../vi/SECURITY.md) · 🇮🇩 [id](../id/SECURITY.md) · 🇲🇾 [ms](../ms/SECURITY.md) · 🇳🇱 [nl](../nl/SECURITY.md) · 🇵🇱 [pl](../pl/SECURITY.md) · 🇸🇪 [sv](../sv/SECURITY.md) · 🇳🇴 [no](../no/SECURITY.md) · 🇩🇰 [da](../da/SECURITY.md) · 🇫🇮 [fi](../fi/SECURITY.md) · 🇵🇹 [pt](../pt/SECURITY.md) · 🇷🇴 [ro](../ro/SECURITY.md) · 🇭🇺 [hu](../hu/SECURITY.md) · 🇧🇬 [bg](../bg/SECURITY.md) · 🇸🇰 [sk](../sk/SECURITY.md) · 🇺🇦 [uk-UA](../uk-UA/SECURITY.md) · 🇮🇱 [he](../he/SECURITY.md) · 🇵🇭 [phi](../phi/SECURITY.md) · 🇧🇷 [pt-BR](../pt-BR/SECURITY.md) · 🇨🇿 [cs](../cs/SECURITY.md)
+
+---
+
+## Reporting Vulnerabilities
+
+If you discover a security vulnerability in OmniRoute, please report it responsibly:
+
+1. **DO NOT** open a public GitHub issue
+2. Use [GitHub Security Advisories](https://github.com/diegosouzapw/OmniRoute/security/advisories/new)
+3. Include: description, reproduction steps, and potential impact
+
+## Response Timeline
+
+| Stage | Target |
+| ------------------- | --------------------------- |
+| Acknowledgment | 48 hours |
+| Triage & Assessment | 5 business days |
+| Patch Release | 14 business days (critical) |
+
+## Supported Versions
+
+| Version | Support Status |
+| ------- | -------------- |
+| 3.4.x | ✅ Active |
+| 3.0.x | ✅ Security |
+| < 3.0.0 | ❌ Unsupported |
+
+---
+
+## Security Architecture
+
+OmniRoute implements a multi-layered security model:
+
+```
+Request → CORS → API Key Auth → Prompt Injection Guard → Input Sanitizer → Rate Limiter → Circuit Breaker → Provider
+```
+
+### 🔐 Authentication & Authorization
+
+| Feature | Implementation |
+| -------------------- | ---------------------------------------------------------- |
+| **Dashboard Login** | Password-based auth with JWT tokens (HttpOnly cookies) |
+| **API Key Auth** | HMAC-signed keys with CRC validation |
+| **OAuth 2.0 + PKCE** | Secure provider auth (Claude, Codex, Gemini, Cursor, etc.) |
+| **Token Refresh** | Automatic OAuth token refresh before expiry |
+| **Secure Cookies** | `AUTH_COOKIE_SECURE=true` for HTTPS environments |
+| **MCP Scopes** | 10 granular scopes for MCP tool access control |
+
+### 🛡️ Encryption at Rest
+
+All sensitive data stored in SQLite is encrypted using **AES-256-GCM** with scrypt key derivation:
+
+- API keys, access tokens, refresh tokens, and ID tokens
+- Versioned format: `enc:v1:::`
+- Passthrough mode (plaintext) when `STORAGE_ENCRYPTION_KEY` is not set
+
+```bash
+# Generate encryption key:
+STORAGE_ENCRYPTION_KEY=$(openssl rand -hex 32)
+```
+
+### 🧠 Prompt Injection Guard
+
+Middleware that detects and blocks prompt injection attacks in LLM requests:
+
+| Pattern Type | Severity | Example |
+| ------------------- | -------- | ---------------------------------------------- |
+| System Override | High | "ignore all previous instructions" |
+| Role Hijack | High | "you are now DAN, you can do anything" |
+| Delimiter Injection | Medium | Encoded separators to break context boundaries |
+| DAN/Jailbreak | High | Known jailbreak prompt patterns |
+| Instruction Leak | Medium | "show me your system prompt" |
+
+Configure via dashboard (Settings → Security) or `.env`:
+
+```env
+INPUT_SANITIZER_ENABLED=true
+INPUT_SANITIZER_MODE=block # warn | block | redact
+```
+
+### 🔒 PII Redaction
+
+Automatic detection and optional redaction of personally identifiable information:
+
+| PII Type | Pattern | Replacement |
+| ------------- | --------------------- | ------------------ |
+| Email | `user@domain.com` | `[EMAIL_REDACTED]` |
+| CPF (Brazil) | `123.456.789-00` | `[CPF_REDACTED]` |
+| CNPJ (Brazil) | `12.345.678/0001-00` | `[CNPJ_REDACTED]` |
+| Credit Card | `4111-1111-1111-1111` | `[CC_REDACTED]` |
+| Phone | `+55 11 99999-9999` | `[PHONE_REDACTED]` |
+| SSN (US) | `123-45-6789` | `[SSN_REDACTED]` |
+
+```env
+PII_REDACTION_ENABLED=true
+```
+
+### 🌐 Network Security
+
+| Feature | Description |
+| ------------------------ | ---------------------------------------------------------------- |
+| **CORS** | Configurable origin control (`CORS_ORIGIN` env var, default `*`) |
+| **IP Filtering** | Allowlist/blocklist IP ranges in dashboard |
+| **Rate Limiting** | Per-provider rate limits with automatic backoff |
+| **Anti-Thundering Herd** | Mutex + per-connection locking prevents cascading 502s |
+| **TLS Fingerprint** | Browser-like TLS fingerprint spoofing to reduce bot detection |
+| **CLI Fingerprint** | Per-provider header/body ordering to match native CLI signatures |
+
+### 🔌 Resilience & Availability
+
+| Feature | Description |
+| ----------------------- | ------------------------------------------------------------------ |
+| **Circuit Breaker** | 3-state (Closed → Open → Half-Open) per provider, SQLite-persisted |
+| **Request Idempotency** | 5-second dedup window for duplicate requests |
+| **Exponential Backoff** | Automatic retry with increasing delays |
+| **Health Dashboard** | Real-time provider health monitoring |
+
+### 📋 Compliance
+
+| Feature | Description |
+| ------------------ | ----------------------------------------------------------- |
+| **Log Retention** | Automatic cleanup after `CALL_LOG_RETENTION_DAYS` |
+| **No-Log Opt-out** | Per API key `noLog` flag disables request logging |
+| **Audit Log** | Administrative actions tracked in `audit_log` table |
+| **MCP Audit** | SQLite-backed audit logging for all MCP tool calls |
+| **Zod Validation** | All API inputs validated with Zod v4 schemas at module load |
+
+---
+
+## Required Environment Variables
+
+All secrets must be set before starting the server. The server will **fail fast** if they are missing or weak.
+
+```bash
+# REQUIRED — server will not start without these:
+JWT_SECRET=$(openssl rand -base64 48) # min 32 chars
+API_KEY_SECRET=$(openssl rand -hex 32) # min 16 chars
+
+# RECOMMENDED — enables encryption at rest:
+STORAGE_ENCRYPTION_KEY=$(openssl rand -hex 32)
+```
+
+The server actively rejects known-weak values like `changeme`, `secret`, or `password`.
+
+---
+
+## Docker Security
+
+- Use non-root user in production
+- Mount secrets as read-only volumes
+- Never copy `.env` files into Docker images
+- Use `.dockerignore` to exclude sensitive files
+- Set `AUTH_COOKIE_SECURE=true` when behind HTTPS
+
+```bash
+docker run -d \
+ --name omniroute \
+ --restart unless-stopped \
+ --read-only \
+ -p 20128:20128 \
+ -v omniroute-data:/app/data \
+ -e JWT_SECRET="$(openssl rand -base64 48)" \
+ -e API_KEY_SECRET="$(openssl rand -hex 32)" \
+ -e STORAGE_ENCRYPTION_KEY="$(openssl rand -hex 32)" \
+ diegosouzapw/omniroute:latest
+```
+
+---
+
+## Dependencies
+
+- Run `npm audit` regularly
+- Keep dependencies updated
+- The project uses `husky` + `lint-staged` for pre-commit checks
+- CI pipeline runs ESLint security rules on every push
+- Provider constants validated at module load via Zod (`src/shared/validation/providerSchema.ts`)
diff --git a/docs/i18n/in/TROUBLESHOOTING.md b/docs/i18n/in/TROUBLESHOOTING.md
deleted file mode 100644
index 63c148000a..0000000000
--- a/docs/i18n/in/TROUBLESHOOTING.md
+++ /dev/null
@@ -1,258 +0,0 @@
-🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/TROUBLESHOOTING.md) · 🇪🇸 [es](../es/TROUBLESHOOTING.md) · 🇫🇷 [fr](../fr/TROUBLESHOOTING.md) · 🇩🇪 [de](../de/TROUBLESHOOTING.md) · 🇮🇹 [it](../it/TROUBLESHOOTING.md) · 🇷🇺 [ru](../ru/TROUBLESHOOTING.md) · 🇨🇳 [zh-CN](../zh-CN/TROUBLESHOOTING.md) · 🇯🇵 [ja](../ja/TROUBLESHOOTING.md) · 🇰🇷 [ko](../ko/TROUBLESHOOTING.md) · 🇸🇦 [ar](../ar/TROUBLESHOOTING.md) · 🇮🇳 [in](../in/TROUBLESHOOTING.md) · 🇹🇭 [th](../th/TROUBLESHOOTING.md) · 🇻🇳 [vi](../vi/TROUBLESHOOTING.md) · 🇮🇩 [id](../id/TROUBLESHOOTING.md) · 🇲🇾 [ms](../ms/TROUBLESHOOTING.md) · 🇳🇱 [nl](../nl/TROUBLESHOOTING.md) · 🇵🇱 [pl](../pl/TROUBLESHOOTING.md) · 🇸🇪 [sv](../sv/TROUBLESHOOTING.md) · 🇳🇴 [no](../no/TROUBLESHOOTING.md) · 🇩🇰 [da](../da/TROUBLESHOOTING.md) · 🇫🇮 [fi](../fi/TROUBLESHOOTING.md) · 🇵🇹 [pt](../pt/TROUBLESHOOTING.md) · 🇷🇴 [ro](../ro/TROUBLESHOOTING.md) · 🇭🇺 [hu](../hu/TROUBLESHOOTING.md) · 🇧🇬 [bg](../bg/TROUBLESHOOTING.md) · 🇸🇰 [sk](../sk/TROUBLESHOOTING.md) · 🇺🇦 [uk-UA](../uk-UA/TROUBLESHOOTING.md) · 🇮🇱 [he](../he/TROUBLESHOOTING.md) · 🇵🇭 [phi](../phi/TROUBLESHOOTING.md)
-
----
-
-# Troubleshooting
-
-🌐 **Languages:** 🇺🇸 [English](TROUBLESHOOTING.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/TROUBLESHOOTING.md) | 🇪🇸 [Español](i18n/es/TROUBLESHOOTING.md) | 🇫🇷 [Français](i18n/fr/TROUBLESHOOTING.md) | 🇮🇹 [Italiano](i18n/it/TROUBLESHOOTING.md) | 🇷🇺 [Русский](i18n/ru/TROUBLESHOOTING.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/TROUBLESHOOTING.md) | 🇩🇪 [Deutsch](i18n/de/TROUBLESHOOTING.md) | 🇮🇳 [हिन्दी](i18n/in/TROUBLESHOOTING.md) | 🇹🇭 [ไทย](i18n/th/TROUBLESHOOTING.md) | 🇺🇦 [Українська](i18n/uk-UA/TROUBLESHOOTING.md) | 🇸🇦 [العربية](i18n/ar/TROUBLESHOOTING.md) | 🇯🇵 [日本語](i18n/ja/TROUBLESHOOTING.md) | 🇻🇳 [Tiếng Việt](i18n/vi/TROUBLESHOOTING.md) | 🇧🇬 [Български](i18n/bg/TROUBLESHOOTING.md) | 🇩🇰 [Dansk](i18n/da/TROUBLESHOOTING.md) | 🇫🇮 [Suomi](i18n/fi/TROUBLESHOOTING.md) | 🇮🇱 [עברית](i18n/he/TROUBLESHOOTING.md) | 🇭🇺 [Magyar](i18n/hu/TROUBLESHOOTING.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/TROUBLESHOOTING.md) | 🇰🇷 [한국어](i18n/ko/TROUBLESHOOTING.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/TROUBLESHOOTING.md) | 🇳🇱 [Nederlands](i18n/nl/TROUBLESHOOTING.md) | 🇳🇴 [Norsk](i18n/no/TROUBLESHOOTING.md) | 🇵🇹 [Português (Portugal)](i18n/pt/TROUBLESHOOTING.md) | 🇷🇴 [Română](i18n/ro/TROUBLESHOOTING.md) | 🇵🇱 [Polski](i18n/pl/TROUBLESHOOTING.md) | 🇸🇰 [Slovenčina](i18n/sk/TROUBLESHOOTING.md) | 🇸🇪 [Svenska](i18n/sv/TROUBLESHOOTING.md) | 🇵🇭 [Filipino](i18n/phi/TROUBLESHOOTING.md)
-
-Common problems and solutions for OmniRoute.
-
----
-
-## Quick Fixes
-
-| Problem | Solution |
-| ----------------------------- | ------------------------------------------------------------------ |
-| First login not working | Set `INITIAL_PASSWORD` in `.env` (no hardcoded default) |
-| Dashboard opens on wrong port | Set `PORT=20128` and `NEXT_PUBLIC_BASE_URL=http://localhost:20128` |
-| No request logs under `logs/` | Set `ENABLE_REQUEST_LOGS=true` |
-| EACCES: permission denied | Set `DATA_DIR=/path/to/writable/dir` to override `~/.omniroute` |
-| Routing strategy not saving | Update to v1.4.11+ (Zod schema fix for settings persistence) |
-
----
-
-## Provider Issues
-
-### "Language model did not provide messages"
-
-**Cause:** Provider quota exhausted.
-
-**Fix:**
-
-1. Check dashboard quota tracker
-2. Use a combo with fallback tiers
-3. Switch to cheaper/free tier
-
-### Rate Limiting
-
-**Cause:** Subscription quota exhausted.
-
-**Fix:**
-
-- Add fallback: `cc/claude-opus-4-6 → glm/glm-4.7 → if/kimi-k2-thinking`
-- Use GLM/MiniMax as cheap backup
-
-### OAuth Token Expired
-
-OmniRoute auto-refreshes tokens. If issues persist:
-
-1. Dashboard → Provider → Reconnect
-2. Delete and re-add the provider connection
-
----
-
-## Cloud Issues
-
-### Cloud Sync Errors
-
-1. Verify `BASE_URL` points to your running instance (e.g., `http://localhost:20128`)
-2. Verify `CLOUD_URL` points to your cloud endpoint (e.g., `https://omniroute.dev`)
-3. Keep `NEXT_PUBLIC_*` values aligned with server-side values
-
-### Cloud `stream=false` Returns 500
-
-**Symptom:** `Unexpected token 'd'...` on cloud endpoint for non-streaming calls.
-
-**Cause:** Upstream returns SSE payload while client expects JSON.
-
-**Workaround:** Use `stream=true` for cloud direct calls. Local runtime includes SSE→JSON fallback.
-
-### Cloud Says Connected but "Invalid API key"
-
-1. Create a fresh key from local dashboard (`/api/keys`)
-2. Run cloud sync: Enable Cloud → Sync Now
-3. Old/non-synced keys can still return `401` on cloud
-
----
-
-## Docker Issues
-
-### CLI Tool Shows Not Installed
-
-1. Check runtime fields: `curl http://localhost:20128/api/cli-tools/runtime/codex | jq`
-2. For portable mode: use image target `runner-cli` (bundled CLIs)
-3. For host mount mode: set `CLI_EXTRA_PATHS` and mount host bin directory as read-only
-4. If `installed=true` and `runnable=false`: binary was found but failed healthcheck
-
-### Quick Runtime Validation
-
-```bash
-curl -s http://localhost:20128/api/cli-tools/codex-settings | jq '{installed,runnable,commandPath,runtimeMode,reason}'
-curl -s http://localhost:20128/api/cli-tools/claude-settings | jq '{installed,runnable,commandPath,runtimeMode,reason}'
-curl -s http://localhost:20128/api/cli-tools/openclaw-settings | jq '{installed,runnable,commandPath,runtimeMode,reason}'
-```
-
----
-
-## Cost Issues
-
-### High Costs
-
-1. Check usage stats in Dashboard → Usage
-2. Switch primary model to GLM/MiniMax
-3. Use free tier (Gemini CLI, Qoder) for non-critical tasks
-4. Set cost budgets per API key: Dashboard → API Keys → Budget
-
----
-
-## Debugging
-
-### Enable Request Logs
-
-Set `ENABLE_REQUEST_LOGS=true` in your `.env` file. Logs appear under `logs/` directory.
-
-### Check Provider Health
-
-```bash
-# Health dashboard
-http://localhost:20128/dashboard/health
-
-# API health check
-curl http://localhost:20128/api/monitoring/health
-```
-
-### Runtime Storage
-
-- Main state: `${DATA_DIR}/storage.sqlite` (providers, combos, aliases, keys, settings)
-- Usage: SQLite tables in `storage.sqlite` (`usage_history`, `call_logs`, `proxy_logs`) + optional `${DATA_DIR}/log.txt` and `${DATA_DIR}/call_logs/`
-- Request logs: `/logs/...` (when `ENABLE_REQUEST_LOGS=true`)
-
----
-
-## Circuit Breaker Issues
-
-### Provider stuck in OPEN state
-
-When a provider's circuit breaker is OPEN, requests are blocked until the cooldown expires.
-
-**Fix:**
-
-1. Go to **Dashboard → Settings → Resilience**
-2. Check the circuit breaker card for the affected provider
-3. Click **Reset All** to clear all breakers, or wait for the cooldown to expire
-4. Verify the provider is actually available before resetting
-
-### Provider keeps tripping the circuit breaker
-
-If a provider repeatedly enters OPEN state:
-
-1. Check **Dashboard → Health → Provider Health** for the failure pattern
-2. Go to **Settings → Resilience → Provider Profiles** and increase the failure threshold
-3. Check if the provider has changed API limits or requires re-authentication
-4. Review latency telemetry — high latency may cause timeout-based failures
-
----
-
-## Audio Transcription Issues
-
-### "Unsupported model" error
-
-- Ensure you're using the correct prefix: `deepgram/nova-3` or `assemblyai/best`
-- Verify the provider is connected in **Dashboard → Providers**
-
-### Transcription returns empty or fails
-
-- Check supported audio formats: `mp3`, `wav`, `m4a`, `flac`, `ogg`, `webm`
-- Verify file size is within provider limits (typically < 25MB)
-- Check provider API key validity in the provider card
-
----
-
-## Translator Debugging
-
-Use **Dashboard → Translator** to debug format translation issues:
-
-| Mode | When to Use |
-| ---------------- | -------------------------------------------------------------------------------------------- |
-| **Playground** | Compare input/output formats side by side — paste a failing request to see how it translates |
-| **Chat Tester** | Send live messages and inspect the full request/response payload including headers |
-| **Test Bench** | Run batch tests across format combinations to find which translations are broken |
-| **Live Monitor** | Watch real-time request flow to catch intermittent translation issues |
-
-### Common format issues
-
-- **Thinking tags not appearing** — Check if the target provider supports thinking and the thinking budget setting
-- **Tool calls dropping** — Some format translations may strip unsupported fields; verify in Playground mode
-- **System prompt missing** — Claude and Gemini handle system prompts differently; check translation output
-- **SDK returns raw string instead of object** — Fixed in v1.1.0: response sanitizer now strips non-standard fields (`x_groq`, `usage_breakdown`, etc.) that cause OpenAI SDK Pydantic validation failures
-- **GLM/ERNIE rejects `system` role** — Fixed in v1.1.0: role normalizer automatically merges system messages into user messages for incompatible models
-- **`developer` role not recognized** — Fixed in v1.1.0: automatically converted to `system` for non-OpenAI providers
-- **`json_schema` not working with Gemini** — Fixed in v1.1.0: `response_format` is now converted to Gemini's `responseMimeType` + `responseSchema`
-
----
-
-## Resilience Settings
-
-### Auto rate-limit not triggering
-
-- Auto rate-limit only applies to API key providers (not OAuth/subscription)
-- Verify **Settings → Resilience → Provider Profiles** has auto-rate-limit enabled
-- Check if the provider returns `429` status codes or `Retry-After` headers
-
-### Tuning exponential backoff
-
-Provider profiles support these settings:
-
-- **Base delay** — Initial wait time after first failure (default: 1s)
-- **Max delay** — Maximum wait time cap (default: 30s)
-- **Multiplier** — How much to increase delay per consecutive failure (default: 2x)
-
-### Anti-thundering herd
-
-When many concurrent requests hit a rate-limited provider, OmniRoute uses mutex + auto rate-limiting to serialize requests and prevent cascading failures. This is automatic for API key providers.
-
----
-
-## Optional RAG / LLM failure taxonomy (16 problems)
-
-Some OmniRoute users place the gateway in front of RAG or agent stacks. In those setups it is common to see a strange pattern: OmniRoute looks healthy (providers up, routing profiles ok, no rate limit alerts) but the final answer is still wrong.
-
-In practice these incidents usually come from the downstream RAG pipeline, not from the gateway itself.
-
-If you want a shared vocabulary to describe those failures you can use the WFGY ProblemMap, an external MIT license text resource that defines sixteen recurring RAG / LLM failure patterns. At a high level it covers:
-
-- retrieval drift and broken context boundaries
-- empty or stale indexes and vector stores
-- embedding versus semantic mismatch
-- prompt assembly and context window issues
-- logic collapse and overconfident answers
-- long chain and agent coordination failures
-- multi agent memory and role drift
-- deployment and bootstrap ordering problems
-
-The idea is simple:
-
-1. When you investigate a bad response, capture:
- - user task and request
- - route or provider combo in OmniRoute
- - any RAG context used downstream (retrieved documents, tool calls, etc)
-2. Map the incident to one or two WFGY ProblemMap numbers (`No.1` … `No.16`).
-3. Store the number in your own dashboard, runbook, or incident tracker next to the OmniRoute logs.
-4. Use the corresponding WFGY page to decide whether you need to change your RAG stack, retriever, or routing strategy.
-
-Full text and concrete recipes live here (MIT license, text only):
-
-[WFGY ProblemMap README](https://github.com/onestardao/WFGY/blob/main/ProblemMap/README.md)
-
-You can ignore this section if you do not run RAG or agent pipelines behind OmniRoute.
-
----
-
-## Still Stuck?
-
-- **GitHub Issues**: [github.com/diegosouzapw/OmniRoute/issues](https://github.com/diegosouzapw/OmniRoute/issues)
-- **Architecture**: See [`docs/ARCHITECTURE.md`](ARCHITECTURE.md) for internal details
-- **API Reference**: See [`docs/API_REFERENCE.md`](API_REFERENCE.md) for all endpoints
-- **Health Dashboard**: Check **Dashboard → Health** for real-time system status
-- **Translator**: Use **Dashboard → Translator** to debug format issues
diff --git a/docs/i18n/in/VM_DEPLOYMENT_GUIDE.md b/docs/i18n/in/VM_DEPLOYMENT_GUIDE.md
deleted file mode 100644
index a428fbe33b..0000000000
--- a/docs/i18n/in/VM_DEPLOYMENT_GUIDE.md
+++ /dev/null
@@ -1,295 +0,0 @@
-# ओमनीरूट - क्लाउडफ्लेयर के साथ वीएम पर परिनियोजन गाइड
-
-🌐 **Languages:** 🇺🇸 [English](../../VM_DEPLOYMENT_GUIDE.md) | 🇧🇷 [Português (Brasil)](../pt-BR/VM_DEPLOYMENT_GUIDE.md) | 🇪🇸 [Español](../es/VM_DEPLOYMENT_GUIDE.md) | 🇫🇷 [Français](../fr/VM_DEPLOYMENT_GUIDE.md) | 🇮🇹 [Italiano](../it/VM_DEPLOYMENT_GUIDE.md) | 🇷🇺 [Русский](../ru/VM_DEPLOYMENT_GUIDE.md) | 🇨🇳 [中文 (简体)](../zh-CN/VM_DEPLOYMENT_GUIDE.md) | 🇩🇪 [Deutsch](../de/VM_DEPLOYMENT_GUIDE.md) | 🇮🇳 [हिन्दी](../in/VM_DEPLOYMENT_GUIDE.md) | 🇹🇭 [ไทย](../th/VM_DEPLOYMENT_GUIDE.md) | 🇺🇦 [Українська](../uk-UA/VM_DEPLOYMENT_GUIDE.md) | 🇸🇦 [العربية](../ar/VM_DEPLOYMENT_GUIDE.md) | 🇯🇵 [日本語](../ja/VM_DEPLOYMENT_GUIDE.md) | 🇻🇳 [Tiếng Việt](../vi/VM_DEPLOYMENT_GUIDE.md) | 🇧🇬 [Български](../bg/VM_DEPLOYMENT_GUIDE.md) | 🇩🇰 [Dansk](../da/VM_DEPLOYMENT_GUIDE.md) | 🇫🇮 [Suomi](../fi/VM_DEPLOYMENT_GUIDE.md) | 🇮🇱 [עברית](../he/VM_DEPLOYMENT_GUIDE.md) | 🇭🇺 [Magyar](../hu/VM_DEPLOYMENT_GUIDE.md) | 🇮🇩 [Bahasa Indonesia](../id/VM_DEPLOYMENT_GUIDE.md) | 🇰🇷 [한국어](../ko/VM_DEPLOYMENT_GUIDE.md) | 🇲🇾 [Bahasa Melayu](../ms/VM_DEPLOYMENT_GUIDE.md) | 🇳🇱 [Nederlands](../nl/VM_DEPLOYMENT_GUIDE.md) | 🇳🇴 [Norsk](../no/VM_DEPLOYMENT_GUIDE.md) | 🇵🇹 [Português (Portugal)](../pt/VM_DEPLOYMENT_GUIDE.md) | 🇷🇴 [Română](../ro/VM_DEPLOYMENT_GUIDE.md) | 🇵🇱 [Polski](../pl/VM_DEPLOYMENT_GUIDE.md) | 🇸🇰 [Slovenčina](../sk/VM_DEPLOYMENT_GUIDE.md) | 🇸🇪 [Svenska](../sv/VM_DEPLOYMENT_GUIDE.md) | 🇵🇭 [Filipino](../phi/VM_DEPLOYMENT_GUIDE.md) | 🇨🇿 [Čeština](../cs/VM_DEPLOYMENT_GUIDE.md)
-
-क्लाउडफ्लेयर के माध्यम से प्रबंधित डोमेन के साथ वीएम (वीपीएस) पर ओमनीरूट को स्थापित और कॉन्फ़िगर करने के लिए पूरी गाइड।
-
----
-
-## पूर्वावश्यकताएँ
-
-| आइटम | न्यूनतम | अनुशंसित |
-| ---------- | --------------------- | ------------------ |
-| **सीपीयू** | 1 वीसीपीयू | 2 वीसीपीयू |
-| **राम** | 1 जीबी | 2 जीबी |
-| **डिस्क** | 10 जीबी एसएसडी | 25 जीबी एसएसडी |
-| **ओएस** | उबंटू 22.04 एलटीएस | उबंटू 24.04 एलटीएस |
-| **डोमेन** | Cloudflare पर पंजीकृत | — |
-| **डॉकर** | डॉकर इंजन 24+ | डॉकर 27+ |
-
-**परीक्षित प्रदाता**: अकामाई (लिनोड), डिजिटलओशन, वल्चर, हेट्ज़नर, एडब्ल्यूएस लाइटसेल।
-
----
-
-## 1. वीएम को कॉन्फ़िगर करें
-
-### 1.1 उदाहरण बनाएँ
-
-आपके पसंदीदा VPS प्रदाता पर:
-
-- उबंटू 24.04 एलटीएस चुनें
-- न्यूनतम योजना चुनें (1 वीसीपीयू / 1 जीबी रैम)
-- एक मजबूत रूट पासवर्ड सेट करें या SSH कुंजी कॉन्फ़िगर करें
-- **सार्वजनिक आईपी** पर ध्यान दें (जैसे, `203.0.113.10`)
-
-### 1.2 एसएसएच के माध्यम से कनेक्ट करें
-
-```bash
-ssh root@203.0.113.10
-```
-
-### 1.3 सिस्टम को अपडेट करें
-
-**OMNI_टोकन_1**
-
-### 1.4 डॉकर स्थापित करें
-
-```bash
-# Install dependencies
-apt install -y ca-certificates curl gnupg
-
-# Add official Docker repository
-install -m 0755 -d /etc/apt/keyrings
-curl -fsSL https://download.docker.com/linux/ubuntu/gpg | gpg --dearmor -o /etc/apt/keyrings/docker.gpg
-chmod a+r /etc/apt/keyrings/docker.gpg
-echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu $ (. /etc/os-release && echo “$VERSION_CODENAME”) stable" | tee /etc/apt/sources.list.d/docker.list > /dev/null
-apt update
-apt install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin
-```
-
-### 1.5 nginx स्थापित करें
-
-```bash
-apt install -y nginx
-```
-
-### 1.6 फ़ायरवॉल कॉन्फ़िगर करें (UFW)
-
-```bash
-ufw default deny incoming
-ufw default allow outgoing
-ufw allow 22/tcp # SSH
-ufw allow 80/tcp # HTTP (redirect)
-ufw allow 443/tcp # HTTPS
-ufw enable
-```
-
-> **टिप**: अधिकतम सुरक्षा के लिए, पोर्ट 80 और 443 को केवल क्लाउडफ़ेयर आईपी तक सीमित रखें। [Advanced Security](#advanced-security) अनुभाग देखें।
-
----
-
-## 2. ओमनीरूट स्थापित करें
-
-### 2.1 कॉन्फ़िगरेशन निर्देशिका बनाएं
-
-**OMNI_टोकन_5**
-
-### 2.2 पर्यावरण चर फ़ाइल बनाएँ
-
-**OMNI_टोकन_6**
-
-> ⚠️ **महत्वपूर्ण**: अद्वितीय गुप्त कुंजियाँ उत्पन्न करें! प्रत्येक कुंजी के लिए `openssl rand -hex 32` का उपयोग करें।
-
-### 2.3 कंटेनर प्रारंभ करें
-
-```bash
-docker pull diegosouzapw/omniroute:latest
-
-docker run -d \
- --name omniroute \
- --restart unless-stopped \
- --env-file /opt/omniroute/.env \
- -p 20128:20128 \
- -v omniroute-data:/app/data \
- diegosouzapw/omniroute:latest
-```
-
-### 2.4 सत्यापित करें कि यह चल रहा है
-
-**OMNI_टोकन_8**
-
-इसे प्रदर्शित करना चाहिए: `[DB] SQLite database ready` और `listening on port 20128`।
-
----
-
-## 3. nginx कॉन्फ़िगर करें (रिवर्स प्रॉक्सी)
-
-### 3.1 एसएसएल प्रमाणपत्र उत्पन्न करें (क्लाउडफ्लेयर ओरिजिन)
-
-क्लाउडफ्लेयर डैशबोर्ड में:
-
-1. **एसएसएल/टीएलएस → ओरिजिन सर्वर** पर जाएं
-2. **प्रमाणपत्र बनाएं** पर क्लिक करें
-3. डिफ़ॉल्ट रखें (15 वर्ष, \*.yourdomain.com)
-4. **मूल प्रमाणपत्र** और **निजी कुंजी** की प्रतिलिपि बनाएँ
-
-```bash
-mkdir -p /etc/nginx/ssl
-
-# Paste the certificate
-nano /etc/nginx/ssl/origin.crt
-
-# Paste the private key
-nano /etc/nginx/ssl/origin.key
-
-chmod 600 /etc/nginx/ssl/origin.key
-```
-
-### 3.2 नगनेक्स कॉन्फ़िगरेशन
-
-```bash
-cat > /etc/nginx/sites-available/omniroute << ‘NGINX’
-# Default server — blocks direct access via IP
-server {
- listen 80 default_server;
- listen [::]:80 default_server;
- listen 443 ssl default_server;
- listen [::]:443 ssl default_server;
- ssl_certificate /etc/nginx/ssl/origin.crt;
- ssl_certificate_key /etc/nginx/ssl/origin.key;
- server_name _;
- return 444;
-}
-
-# OmniRoute — HTTPS
-server {
- listen 443 ssl;
- listen [::]:443 ssl;
- server_name llms.yourdomain.com; # Change to your domain
-
- ssl_certificate /etc/nginx/ssl/origin.crt;
- ssl_certificate_key /etc/nginx/ssl/origin.key;
- ssl_protocols TLSv1.2 TLSv1.3;
-
- client_max_body_size 100M;
-
- location / {
- proxy_pass http://127.0.0.1:20128;
- proxy_set_header Host $host;
- proxy_set_header X-Real-IP $remote_addr;
- proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
- proxy_set_header X-Forwarded-Proto $scheme;
-
- # WebSocket support
- proxy_http_version 1.1;
- proxy_set_header Upgrade $http_upgrade;
- proxy_set_header Connection “upgrade”;
-
- # SSE (Server-Sent Events) — streaming AI responses
- proxy_buffering off;
- proxy_cache off;
- proxy_read_timeout 300s;
- proxy_send_timeout 300s;
- }
-}
-
-# HTTP → HTTPS redirect
-server {
- listen 80;
- listen [::]:80;
- server_name llms.yourdomain.com;
- return 301 https://$server_name$request_uri;
-}
-NGINX
-```
-
-### 3.3 सक्षम करें और परीक्षण करें
-
-**OMNI_टोकन_11**
-
----
-
-## 4. क्लाउडफ्लेयर डीएनएस कॉन्फ़िगर करें
-
-### 4.1 डीएनएस रिकॉर्ड जोड़ें
-
-क्लाउडफ़ेयर डैशबोर्ड में → DNS:
-
-| प्रकार | नाम | सामग्री | प्रॉक्सी |
-| ------ | ------ | ---------------------- | ----------- |
-| ए | `llms` | `203.0.113.10` (VM IP) | ✅ प्रॉक्सी |
-
-### 4.2 एसएसएल कॉन्फ़िगर करें
-
-**एसएसएल/टीएलएस → अवलोकन** के अंतर्गत:
-
-- मोड: **पूर्ण (सख्त)**
-
-**एसएसएल/टीएलएस → एज सर्टिफिकेट** के अंतर्गत:
-
-- हमेशा HTTPS का उपयोग करें: ✅ चालू
-- न्यूनतम टीएलएस संस्करण: टीएलएस 1.2
-- स्वचालित HTTPS पुनर्लेखन: ✅ चालू
-
-### 4.3 परीक्षण
-
-**OMNI_टोकन_12**
-
----
-
-## 5. संचालन एवं रखरखाव
-
-### नए संस्करण में अपग्रेड करें
-
-**OMNI_टोकन_13**
-
-### लॉग देखें
-
-**OMNI_टोकन_14**
-
-### मैनुअल डेटाबेस बैकअप
-
-**OMNI_टोकन_15**
-
-### बैकअप से पुनर्स्थापित करें
-
-**OMNI_टोकन_16**
-
----
-
-## 6. उन्नत सुरक्षा
-
-### nginx को Cloudflare IP तक सीमित करें
-
-**OMNI_टोकन_17**
-
-निम्नलिखित को `http {}` ब्लॉक के अंदर `nginx.conf` में जोड़ें:
-
-**OMNI_टोकन_18**
-
-### फेल2बैन स्थापित करें
-
-**OMNI_टोकन_19**
-
-### डॉकर पोर्ट तक सीधी पहुंच को अवरुद्ध करें
-
-```bash
-# Prevent direct external access to port 20128
-iptables -I DOCKER-USER -p tcp --dport 20128 -j DROP
-iptables -I DOCKER-USER -i lo -p tcp --dport 20128 -j ACCEPT
-
-# Persist the rules
-apt install -y iptables-persistent
-netfilter-persistent save
-```
-
----
-
-## 7. क्लाउडफ्लेयर श्रमिकों की तैनाती (वैकल्पिक)
-
-क्लाउडफ्लेयर वर्कर्स के माध्यम से रिमोट एक्सेस के लिए (वीएम को सीधे उजागर किए बिना):
-
-**OMNI_टोकन_21**
-
-पूरा दस्तावेज़ [omnirouteCloud/README.md](../omnirouteCloud/README.md) पर देखें।
-
----
-
-## पोर्ट सारांश
-
-| बंदरगाह | सेवा | पहुंच |
-| ------- | ----------- | ----------------------------------- |
-| 22 | एसएसएच | सार्वजनिक (fail2ban के साथ) |
-| 80 | nginx HTTP | रीडायरेक्ट → HTTPS |
-| 443 | nginx HTTPS | क्लाउडफ्लेयर प्रॉक्सी के माध्यम से |
-| 20128 | ओमनीरूट | केवल लोकलहोस्ट (nginx के माध्यम से) |
diff --git a/docs/i18n/in/docs/A2A-SERVER.md b/docs/i18n/in/docs/A2A-SERVER.md
new file mode 100644
index 0000000000..601cd603c0
--- /dev/null
+++ b/docs/i18n/in/docs/A2A-SERVER.md
@@ -0,0 +1,200 @@
+# OmniRoute A2A Server Documentation (हिन्दी)
+
+🌐 **Languages:** 🇺🇸 [English](../../../../docs/A2A-SERVER.md) · 🇪🇸 [es](../../es/docs/A2A-SERVER.md) · 🇫🇷 [fr](../../fr/docs/A2A-SERVER.md) · 🇩🇪 [de](../../de/docs/A2A-SERVER.md) · 🇮🇹 [it](../../it/docs/A2A-SERVER.md) · 🇷🇺 [ru](../../ru/docs/A2A-SERVER.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/A2A-SERVER.md) · 🇯🇵 [ja](../../ja/docs/A2A-SERVER.md) · 🇰🇷 [ko](../../ko/docs/A2A-SERVER.md) · 🇸🇦 [ar](../../ar/docs/A2A-SERVER.md) · 🇮🇳 [in](../../in/docs/A2A-SERVER.md) · 🇹🇭 [th](../../th/docs/A2A-SERVER.md) · 🇻🇳 [vi](../../vi/docs/A2A-SERVER.md) · 🇮🇩 [id](../../id/docs/A2A-SERVER.md) · 🇲🇾 [ms](../../ms/docs/A2A-SERVER.md) · 🇳🇱 [nl](../../nl/docs/A2A-SERVER.md) · 🇵🇱 [pl](../../pl/docs/A2A-SERVER.md) · 🇸🇪 [sv](../../sv/docs/A2A-SERVER.md) · 🇳🇴 [no](../../no/docs/A2A-SERVER.md) · 🇩🇰 [da](../../da/docs/A2A-SERVER.md) · 🇫🇮 [fi](../../fi/docs/A2A-SERVER.md) · 🇵🇹 [pt](../../pt/docs/A2A-SERVER.md) · 🇷🇴 [ro](../../ro/docs/A2A-SERVER.md) · 🇭🇺 [hu](../../hu/docs/A2A-SERVER.md) · 🇧🇬 [bg](../../bg/docs/A2A-SERVER.md) · 🇸🇰 [sk](../../sk/docs/A2A-SERVER.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/A2A-SERVER.md) · 🇮🇱 [he](../../he/docs/A2A-SERVER.md) · 🇵🇭 [phi](../../phi/docs/A2A-SERVER.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/A2A-SERVER.md) · 🇨🇿 [cs](../../cs/docs/A2A-SERVER.md)
+
+---
+
+> Agent-to-Agent Protocol v0.3 — OmniRoute as an intelligent routing agent
+
+## Agent Discovery
+
+```bash
+curl http://localhost:20128/.well-known/agent.json
+```
+
+Returns the Agent Card describing OmniRoute's capabilities, skills, and authentication requirements.
+
+---
+
+## Authentication
+
+All `/a2a` requests require an API key via the `Authorization` header:
+
+```
+Authorization: Bearer YOUR_OMNIROUTE_API_KEY
+```
+
+If no API key is configured on the server, authentication is bypassed.
+
+---
+
+## JSON-RPC 2.0 Methods
+
+### `message/send` — Synchronous Execution
+
+Sends a message to a skill and waits for the complete response.
+
+```bash
+curl -X POST http://localhost:20128/a2a \
+ -H "Content-Type: application/json" \
+ -H "Authorization: Bearer YOUR_KEY" \
+ -d '{
+ "jsonrpc": "2.0",
+ "id": "1",
+ "method": "message/send",
+ "params": {
+ "skill": "smart-routing",
+ "messages": [{"role": "user", "content": "Write a hello world in Python"}],
+ "metadata": {"model": "auto", "combo": "fast-coding"}
+ }
+ }'
+```
+
+**Response:**
+
+```json
+{
+ "jsonrpc": "2.0",
+ "id": "1",
+ "result": {
+ "task": { "id": "uuid", "state": "completed" },
+ "artifacts": [{ "type": "text", "content": "..." }],
+ "metadata": {
+ "routing_explanation": "Selected claude-sonnet via provider \"anthropic\" (latency: 1200ms, cost: $0.003)",
+ "cost_envelope": { "estimated": 0.005, "actual": 0.003, "currency": "USD" },
+ "resilience_trace": [
+ { "event": "primary_selected", "provider": "anthropic", "timestamp": "..." }
+ ],
+ "policy_verdict": { "allowed": true, "reason": "within budget and quota limits" }
+ }
+ }
+}
+```
+
+### `message/stream` — SSE Streaming
+
+Same as `message/send` but returns Server-Sent Events for real-time streaming.
+
+```bash
+curl -N -X POST http://localhost:20128/a2a \
+ -H "Content-Type: application/json" \
+ -H "Authorization: Bearer YOUR_KEY" \
+ -d '{
+ "jsonrpc": "2.0",
+ "id": "1",
+ "method": "message/stream",
+ "params": {
+ "skill": "smart-routing",
+ "messages": [{"role": "user", "content": "Explain quantum computing"}]
+ }
+ }'
+```
+
+**SSE Events:**
+
+```
+data: {"jsonrpc":"2.0","method":"message/stream","params":{"task":{"id":"...","state":"working"},"chunk":{"type":"text","content":"..."}}}
+
+: heartbeat 2026-03-03T17:00:00Z
+
+data: {"jsonrpc":"2.0","method":"message/stream","params":{"task":{"id":"...","state":"completed"},"metadata":{...}}}
+```
+
+### `tasks/get` — Query Task Status
+
+```bash
+curl -X POST http://localhost:20128/a2a \
+ -H "Content-Type: application/json" \
+ -H "Authorization: Bearer YOUR_KEY" \
+ -d '{"jsonrpc":"2.0","id":"2","method":"tasks/get","params":{"taskId":"TASK_UUID"}}'
+```
+
+### `tasks/cancel` — Cancel a Task
+
+```bash
+curl -X POST http://localhost:20128/a2a \
+ -H "Content-Type: application/json" \
+ -H "Authorization: Bearer YOUR_KEY" \
+ -d '{"jsonrpc":"2.0","id":"3","method":"tasks/cancel","params":{"taskId":"TASK_UUID"}}'
+```
+
+---
+
+## Available Skills
+
+| Skill | Description |
+| :----------------- | :------------------------------------------------------------------------------------------------------------------------------ |
+| `smart-routing` | Routes prompts through OmniRoute's intelligent pipeline. Returns response with routing explanation, cost, and resilience trace. |
+| `quota-management` | Answers natural-language queries about provider quotas, suggests free combos, and provides quota rankings. |
+
+---
+
+## Task Lifecycle
+
+```
+submitted → working → completed
+ → failed
+ → cancelled
+```
+
+- Tasks expire after 5 minutes (configurable)
+- Terminal states: `completed`, `failed`, `cancelled`
+- Event log tracks every state transition
+
+---
+
+## Error Codes
+
+| Code | Meaning |
+| :----- | :----------------------------- |
+| -32700 | Parse error (invalid JSON) |
+| -32600 | Invalid request / Unauthorized |
+| -32601 | Method or skill not found |
+| -32602 | Invalid params |
+| -32603 | Internal error |
+
+---
+
+## Integration Examples
+
+### Python (requests)
+
+```python
+import requests
+
+resp = requests.post("http://localhost:20128/a2a", json={
+ "jsonrpc": "2.0", "id": "1",
+ "method": "message/send",
+ "params": {
+ "skill": "smart-routing",
+ "messages": [{"role": "user", "content": "Hello"}]
+ }
+}, headers={"Authorization": "Bearer YOUR_KEY"})
+
+result = resp.json()["result"]
+print(result["artifacts"][0]["content"])
+print(result["metadata"]["routing_explanation"])
+```
+
+### TypeScript (fetch)
+
+```typescript
+const resp = await fetch("http://localhost:20128/a2a", {
+ method: "POST",
+ headers: {
+ "Content-Type": "application/json",
+ Authorization: "Bearer YOUR_KEY",
+ },
+ body: JSON.stringify({
+ jsonrpc: "2.0",
+ id: "1",
+ method: "message/send",
+ params: {
+ skill: "smart-routing",
+ messages: [{ role: "user", content: "Hello" }],
+ },
+ }),
+});
+const { result } = await resp.json();
+console.log(result.metadata.routing_explanation);
+```
diff --git a/docs/i18n/in/docs/API_REFERENCE.md b/docs/i18n/in/docs/API_REFERENCE.md
new file mode 100644
index 0000000000..a1e8f1b6bb
--- /dev/null
+++ b/docs/i18n/in/docs/API_REFERENCE.md
@@ -0,0 +1,465 @@
+# API Reference (हिन्दी)
+
+🌐 **Languages:** 🇺🇸 [English](../../../../docs/API_REFERENCE.md) · 🇪🇸 [es](../../es/docs/API_REFERENCE.md) · 🇫🇷 [fr](../../fr/docs/API_REFERENCE.md) · 🇩🇪 [de](../../de/docs/API_REFERENCE.md) · 🇮🇹 [it](../../it/docs/API_REFERENCE.md) · 🇷🇺 [ru](../../ru/docs/API_REFERENCE.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/API_REFERENCE.md) · 🇯🇵 [ja](../../ja/docs/API_REFERENCE.md) · 🇰🇷 [ko](../../ko/docs/API_REFERENCE.md) · 🇸🇦 [ar](../../ar/docs/API_REFERENCE.md) · 🇮🇳 [in](../../in/docs/API_REFERENCE.md) · 🇹🇭 [th](../../th/docs/API_REFERENCE.md) · 🇻🇳 [vi](../../vi/docs/API_REFERENCE.md) · 🇮🇩 [id](../../id/docs/API_REFERENCE.md) · 🇲🇾 [ms](../../ms/docs/API_REFERENCE.md) · 🇳🇱 [nl](../../nl/docs/API_REFERENCE.md) · 🇵🇱 [pl](../../pl/docs/API_REFERENCE.md) · 🇸🇪 [sv](../../sv/docs/API_REFERENCE.md) · 🇳🇴 [no](../../no/docs/API_REFERENCE.md) · 🇩🇰 [da](../../da/docs/API_REFERENCE.md) · 🇫🇮 [fi](../../fi/docs/API_REFERENCE.md) · 🇵🇹 [pt](../../pt/docs/API_REFERENCE.md) · 🇷🇴 [ro](../../ro/docs/API_REFERENCE.md) · 🇭🇺 [hu](../../hu/docs/API_REFERENCE.md) · 🇧🇬 [bg](../../bg/docs/API_REFERENCE.md) · 🇸🇰 [sk](../../sk/docs/API_REFERENCE.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/API_REFERENCE.md) · 🇮🇱 [he](../../he/docs/API_REFERENCE.md) · 🇵🇭 [phi](../../phi/docs/API_REFERENCE.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/API_REFERENCE.md) · 🇨🇿 [cs](../../cs/docs/API_REFERENCE.md)
+
+---
+
+Complete reference for all OmniRoute API endpoints.
+
+---
+
+## Table of Contents
+
+- [Chat Completions](#chat-completions)
+- [Embeddings](#embeddings)
+- [Image Generation](#image-generation)
+- [List Models](#list-models)
+- [Compatibility Endpoints](#compatibility-endpoints)
+- [Semantic Cache](#semantic-cache)
+- [Dashboard & Management](#dashboard--management)
+- [Request Processing](#request-processing)
+- [Authentication](#authentication)
+
+---
+
+## Chat Completions
+
+```bash
+POST /v1/chat/completions
+Authorization: Bearer your-api-key
+Content-Type: application/json
+
+{
+ "model": "cc/claude-opus-4-6",
+ "messages": [
+ {"role": "user", "content": "Write a function to..."}
+ ],
+ "stream": true
+}
+```
+
+### Custom Headers
+
+| Header | Direction | Description |
+| ------------------------ | --------- | ------------------------------------------------ |
+| `X-OmniRoute-No-Cache` | Request | Set to `true` to bypass cache |
+| `X-OmniRoute-Progress` | Request | Set to `true` for progress events |
+| `X-Session-Id` | Request | Sticky session key for external session affinity |
+| `x_session_id` | Request | Underscore variant also accepted (direct HTTP) |
+| `Idempotency-Key` | Request | Dedup key (5s window) |
+| `X-Request-Id` | Request | Alternative dedup key |
+| `X-OmniRoute-Cache` | Response | `HIT` or `MISS` (non-streaming) |
+| `X-OmniRoute-Idempotent` | Response | `true` if deduplicated |
+| `X-OmniRoute-Progress` | Response | `enabled` if progress tracking on |
+| `X-OmniRoute-Session-Id` | Response | Effective session ID used by OmniRoute |
+
+> Nginx note: if you rely on underscore headers (for example `x_session_id`), enable `underscores_in_headers on;`.
+
+---
+
+## Embeddings
+
+```bash
+POST /v1/embeddings
+Authorization: Bearer your-api-key
+Content-Type: application/json
+
+{
+ "model": "nebius/Qwen/Qwen3-Embedding-8B",
+ "input": "The food was delicious"
+}
+```
+
+Available providers: Nebius, OpenAI, Mistral, Together AI, Fireworks, NVIDIA.
+
+```bash
+# List all embedding models
+GET /v1/embeddings
+```
+
+---
+
+## Image Generation
+
+```bash
+POST /v1/images/generations
+Authorization: Bearer your-api-key
+Content-Type: application/json
+
+{
+ "model": "openai/dall-e-3",
+ "prompt": "A beautiful sunset over mountains",
+ "size": "1024x1024"
+}
+```
+
+Available providers: OpenAI (DALL-E), xAI (Grok Image), Together AI (FLUX), Fireworks AI.
+
+```bash
+# List all image models
+GET /v1/images/generations
+```
+
+---
+
+## List Models
+
+```bash
+GET /v1/models
+Authorization: Bearer your-api-key
+
+→ Returns all chat, embedding, and image models + combos in OpenAI format
+```
+
+---
+
+## Compatibility Endpoints
+
+| Method | Path | Format |
+| ------ | --------------------------- | ---------------------- |
+| POST | `/v1/chat/completions` | OpenAI |
+| POST | `/v1/messages` | Anthropic |
+| POST | `/v1/responses` | OpenAI Responses |
+| POST | `/v1/embeddings` | OpenAI |
+| POST | `/v1/images/generations` | OpenAI |
+| GET | `/v1/models` | OpenAI |
+| POST | `/v1/messages/count_tokens` | Anthropic |
+| GET | `/v1beta/models` | Gemini |
+| POST | `/v1beta/models/{...path}` | Gemini generateContent |
+| POST | `/v1/api/chat` | Ollama |
+
+### Dedicated Provider Routes
+
+```bash
+POST /v1/providers/{provider}/chat/completions
+POST /v1/providers/{provider}/embeddings
+POST /v1/providers/{provider}/images/generations
+```
+
+The provider prefix is auto-added if missing. Mismatched models return `400`.
+
+---
+
+## Semantic Cache
+
+```bash
+# Get cache stats
+GET /api/cache/stats
+
+# Clear all caches
+DELETE /api/cache/stats
+```
+
+Response example:
+
+```json
+{
+ "semanticCache": {
+ "memorySize": 42,
+ "memoryMaxSize": 500,
+ "dbSize": 128,
+ "hitRate": 0.65
+ },
+ "idempotency": {
+ "activeKeys": 3,
+ "windowMs": 5000
+ }
+}
+```
+
+---
+
+## Dashboard & Management
+
+### Authentication
+
+| Endpoint | Method | Description |
+| ----------------------------- | ------- | --------------------- |
+| `/api/auth/login` | POST | Login |
+| `/api/auth/logout` | POST | Logout |
+| `/api/settings/require-login` | GET/PUT | Toggle login required |
+
+### Provider Management
+
+| Endpoint | Method | Description |
+| ---------------------------- | --------------- | ------------------------ |
+| `/api/providers` | GET/POST | List / create providers |
+| `/api/providers/[id]` | GET/PUT/DELETE | Manage a provider |
+| `/api/providers/[id]/test` | POST | Test provider connection |
+| `/api/providers/[id]/models` | GET | List provider models |
+| `/api/providers/validate` | POST | Validate provider config |
+| `/api/provider-nodes*` | Various | Provider node management |
+| `/api/provider-models` | GET/POST/DELETE | Custom models |
+
+### OAuth Flows
+
+| Endpoint | Method | Description |
+| -------------------------------- | ------- | ----------------------- |
+| `/api/oauth/[provider]/[action]` | Various | Provider-specific OAuth |
+
+### Routing & Config
+
+| Endpoint | Method | Description |
+| --------------------- | -------- | ----------------------------- |
+| `/api/models/alias` | GET/POST | Model aliases |
+| `/api/models/catalog` | GET | All models by provider + type |
+| `/api/combos*` | Various | Combo management |
+| `/api/keys*` | Various | API key management |
+| `/api/pricing` | GET | Model pricing |
+
+### Usage & Analytics
+
+| Endpoint | Method | Description |
+| --------------------------- | ------ | -------------------- |
+| `/api/usage/history` | GET | Usage history |
+| `/api/usage/logs` | GET | Usage logs |
+| `/api/usage/request-logs` | GET | Request-level logs |
+| `/api/usage/[connectionId]` | GET | Per-connection usage |
+
+### Settings
+
+| Endpoint | Method | Description |
+| ------------------------------- | ------------- | ---------------------- |
+| `/api/settings` | GET/PUT/PATCH | General settings |
+| `/api/settings/proxy` | GET/PUT | Network proxy config |
+| `/api/settings/proxy/test` | POST | Test proxy connection |
+| `/api/settings/ip-filter` | GET/PUT | IP allowlist/blocklist |
+| `/api/settings/thinking-budget` | GET/PUT | Reasoning token budget |
+| `/api/settings/system-prompt` | GET/PUT | Global system prompt |
+
+### Monitoring
+
+| Endpoint | Method | Description |
+| ------------------------ | ---------- | ---------------------------------------------------------------------------------------------------- |
+| `/api/sessions` | GET | Active session tracking |
+| `/api/rate-limits` | GET | Per-account rate limits |
+| `/api/monitoring/health` | GET | Health check + provider summary (`catalogCount`, `configuredCount`, `activeCount`, `monitoredCount`) |
+| `/api/cache/stats` | GET/DELETE | Cache stats / clear |
+
+### Backup & Export/Import
+
+| Endpoint | Method | Description |
+| --------------------------- | ------ | --------------------------------------- |
+| `/api/db-backups` | GET | List available backups |
+| `/api/db-backups` | PUT | Create a manual backup |
+| `/api/db-backups` | POST | Restore from a specific backup |
+| `/api/db-backups/export` | GET | Download database as .sqlite file |
+| `/api/db-backups/import` | POST | Upload .sqlite file to replace database |
+| `/api/db-backups/exportAll` | GET | Download full backup as .tar.gz archive |
+
+### Cloud Sync
+
+| Endpoint | Method | Description |
+| ---------------------- | ------- | --------------------- |
+| `/api/sync/cloud` | Various | Cloud sync operations |
+| `/api/sync/initialize` | POST | Initialize sync |
+| `/api/cloud/*` | Various | Cloud management |
+
+### Tunnels
+
+| Endpoint | Method | Description |
+| -------------------------- | ------ | ----------------------------------------------------------------------- |
+| `/api/tunnels/cloudflared` | GET | Read Cloudflare Quick Tunnel install/runtime status for the dashboard |
+| `/api/tunnels/cloudflared` | POST | Enable or disable the Cloudflare Quick Tunnel (`action=enable/disable`) |
+
+### CLI Tools
+
+| Endpoint | Method | Description |
+| ---------------------------------- | ------ | ------------------- |
+| `/api/cli-tools/claude-settings` | GET | Claude CLI status |
+| `/api/cli-tools/codex-settings` | GET | Codex CLI status |
+| `/api/cli-tools/droid-settings` | GET | Droid CLI status |
+| `/api/cli-tools/openclaw-settings` | GET | OpenClaw CLI status |
+| `/api/cli-tools/runtime/[toolId]` | GET | Generic CLI runtime |
+
+CLI responses include: `installed`, `runnable`, `command`, `commandPath`, `runtimeMode`, `reason`.
+
+### ACP Agents
+
+| Endpoint | Method | Description |
+| ----------------- | ------ | -------------------------------------------------------- |
+| `/api/acp/agents` | GET | List all detected agents (built-in + custom) with status |
+| `/api/acp/agents` | POST | Add custom agent or refresh detection cache |
+| `/api/acp/agents` | DELETE | Remove a custom agent by `id` query param |
+
+GET response includes `agents[]` (id, name, binary, version, installed, protocol, isCustom) and `summary` (total, installed, notFound, builtIn, custom).
+
+### Resilience & Rate Limits
+
+| Endpoint | Method | Description |
+| ----------------------- | --------- | ------------------------------- |
+| `/api/resilience` | GET/PATCH | Get/update resilience profiles |
+| `/api/resilience/reset` | POST | Reset circuit breakers |
+| `/api/rate-limits` | GET | Per-account rate limit status |
+| `/api/rate-limit` | GET | Global rate limit configuration |
+
+### Evals
+
+| Endpoint | Method | Description |
+| ------------ | -------- | --------------------------------- |
+| `/api/evals` | GET/POST | List eval suites / run evaluation |
+
+### Policies
+
+| Endpoint | Method | Description |
+| --------------- | --------------- | ----------------------- |
+| `/api/policies` | GET/POST/DELETE | Manage routing policies |
+
+### Compliance
+
+| Endpoint | Method | Description |
+| --------------------------- | ------ | ----------------------------- |
+| `/api/compliance/audit-log` | GET | Compliance audit log (last N) |
+
+### v1beta (Gemini-Compatible)
+
+| Endpoint | Method | Description |
+| -------------------------- | ------ | --------------------------------- |
+| `/v1beta/models` | GET | List models in Gemini format |
+| `/v1beta/models/{...path}` | POST | Gemini `generateContent` endpoint |
+
+These endpoints mirror Gemini's API format for clients that expect native Gemini SDK compatibility.
+
+### Internal / System APIs
+
+| Endpoint | Method | Description |
+| --------------- | ------ | ---------------------------------------------------- |
+| `/api/init` | GET | Application initialization check (used on first run) |
+| `/api/tags` | GET | Ollama-compatible model tags (for Ollama clients) |
+| `/api/restart` | POST | Trigger graceful server restart |
+| `/api/shutdown` | POST | Trigger graceful server shutdown |
+
+> **Note:** These endpoints are used internally by the system or for Ollama client compatibility. They are not typically called by end users.
+
+---
+
+## Audio Transcription
+
+```bash
+POST /v1/audio/transcriptions
+Authorization: Bearer your-api-key
+Content-Type: multipart/form-data
+```
+
+Transcribe audio files using Deepgram or AssemblyAI.
+
+**Request:**
+
+```bash
+curl -X POST http://localhost:20128/v1/audio/transcriptions \
+ -H "Authorization: Bearer your-api-key" \
+ -F "file=@recording.mp3" \
+ -F "model=deepgram/nova-3"
+```
+
+**Response:**
+
+```json
+{
+ "text": "Hello, this is the transcribed audio content.",
+ "task": "transcribe",
+ "language": "en",
+ "duration": 12.5
+}
+```
+
+**Supported providers:** `deepgram/nova-3`, `assemblyai/best`.
+
+**Supported formats:** `mp3`, `wav`, `m4a`, `flac`, `ogg`, `webm`.
+
+---
+
+## Ollama Compatibility
+
+For clients that use Ollama's API format:
+
+```bash
+# Chat endpoint (Ollama format)
+POST /v1/api/chat
+
+# Model listing (Ollama format)
+GET /api/tags
+```
+
+Requests are automatically translated between Ollama and internal formats.
+
+---
+
+## Telemetry
+
+```bash
+# Get latency telemetry summary (p50/p95/p99 per provider)
+GET /api/telemetry/summary
+```
+
+**Response:**
+
+```json
+{
+ "providers": {
+ "claudeCode": { "p50": 245, "p95": 890, "p99": 1200, "count": 150 },
+ "github": { "p50": 180, "p95": 620, "p99": 950, "count": 320 }
+ }
+}
+```
+
+---
+
+## Budget
+
+```bash
+# Get budget status for all API keys
+GET /api/usage/budget
+
+# Set or update a budget
+POST /api/usage/budget
+Content-Type: application/json
+
+{
+ "keyId": "key-123",
+ "limit": 50.00,
+ "period": "monthly"
+}
+```
+
+---
+
+## Model Availability
+
+```bash
+# Get real-time model availability across all providers
+GET /api/models/availability
+
+# Check availability for a specific model
+POST /api/models/availability
+Content-Type: application/json
+
+{
+ "model": "claude-sonnet-4-5-20250929"
+}
+```
+
+---
+
+## Request Processing
+
+1. Client sends request to `/v1/*`
+2. Route handler calls `handleChat`, `handleEmbedding`, `handleAudioTranscription`, or `handleImageGeneration`
+3. Model is resolved (direct provider/model or alias/combo)
+4. Credentials selected from local DB with account availability filtering
+5. For chat: `handleChatCore` — format detection, translation, cache check, idempotency check
+6. Provider executor sends upstream request
+7. Response translated back to client format (chat) or returned as-is (embeddings/images/audio)
+8. Usage/logging recorded
+9. Fallback applies on errors according to combo rules
+
+Full architecture reference: [`ARCHITECTURE.md`](ARCHITECTURE.md)
+
+---
+
+## Authentication
+
+- Dashboard routes (`/dashboard/*`) use `auth_token` cookie
+- Login uses saved password hash; fallback to `INITIAL_PASSWORD`
+- `requireLogin` toggleable via `/api/settings/require-login`
+- `/v1/*` routes optionally require Bearer API key when `REQUIRE_API_KEY=true`
diff --git a/docs/i18n/in/docs/ARCHITECTURE.md b/docs/i18n/in/docs/ARCHITECTURE.md
new file mode 100644
index 0000000000..4a6db73760
--- /dev/null
+++ b/docs/i18n/in/docs/ARCHITECTURE.md
@@ -0,0 +1,814 @@
+# OmniRoute Architecture (हिन्दी)
+
+🌐 **Languages:** 🇺🇸 [English](../../../../docs/ARCHITECTURE.md) · 🇪🇸 [es](../../es/docs/ARCHITECTURE.md) · 🇫🇷 [fr](../../fr/docs/ARCHITECTURE.md) · 🇩🇪 [de](../../de/docs/ARCHITECTURE.md) · 🇮🇹 [it](../../it/docs/ARCHITECTURE.md) · 🇷🇺 [ru](../../ru/docs/ARCHITECTURE.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/ARCHITECTURE.md) · 🇯🇵 [ja](../../ja/docs/ARCHITECTURE.md) · 🇰🇷 [ko](../../ko/docs/ARCHITECTURE.md) · 🇸🇦 [ar](../../ar/docs/ARCHITECTURE.md) · 🇮🇳 [in](../../in/docs/ARCHITECTURE.md) · 🇹🇭 [th](../../th/docs/ARCHITECTURE.md) · 🇻🇳 [vi](../../vi/docs/ARCHITECTURE.md) · 🇮🇩 [id](../../id/docs/ARCHITECTURE.md) · 🇲🇾 [ms](../../ms/docs/ARCHITECTURE.md) · 🇳🇱 [nl](../../nl/docs/ARCHITECTURE.md) · 🇵🇱 [pl](../../pl/docs/ARCHITECTURE.md) · 🇸🇪 [sv](../../sv/docs/ARCHITECTURE.md) · 🇳🇴 [no](../../no/docs/ARCHITECTURE.md) · 🇩🇰 [da](../../da/docs/ARCHITECTURE.md) · 🇫🇮 [fi](../../fi/docs/ARCHITECTURE.md) · 🇵🇹 [pt](../../pt/docs/ARCHITECTURE.md) · 🇷🇴 [ro](../../ro/docs/ARCHITECTURE.md) · 🇭🇺 [hu](../../hu/docs/ARCHITECTURE.md) · 🇧🇬 [bg](../../bg/docs/ARCHITECTURE.md) · 🇸🇰 [sk](../../sk/docs/ARCHITECTURE.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/ARCHITECTURE.md) · 🇮🇱 [he](../../he/docs/ARCHITECTURE.md) · 🇵🇭 [phi](../../phi/docs/ARCHITECTURE.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/ARCHITECTURE.md) · 🇨🇿 [cs](../../cs/docs/ARCHITECTURE.md)
+
+---
+
+_Last updated: 2026-03-28_
+
+## Executive Summary
+
+OmniRoute is a local AI routing gateway and dashboard built on Next.js.
+It provides a single OpenAI-compatible endpoint (`/v1/*`) and routes traffic across multiple upstream providers with translation, fallback, token refresh, and usage tracking.
+
+Core capabilities:
+
+- OpenAI-compatible API surface for CLI/tools (28 providers)
+- Request/response translation across provider formats
+- Model combo fallback (multi-model sequence)
+- Account-level fallback (multi-account per provider)
+- OAuth + API-key provider connection management
+- Embedding generation via `/v1/embeddings` (6 providers, 9 models)
+- Image generation via `/v1/images/generations` (4 providers, 9 models)
+- Think tag parsing (`...`) for reasoning models
+- Response sanitization for strict OpenAI SDK compatibility
+- Role normalization (developer→system, system→user) for cross-provider compatibility
+- Structured output conversion (json_schema → Gemini responseSchema)
+- Local persistence for providers, keys, aliases, combos, settings, pricing
+- Usage/cost tracking and request logging
+- Optional cloud sync for multi-device/state sync
+- IP allowlist/blocklist for API access control
+- Thinking budget management (passthrough/auto/custom/adaptive)
+- Global system prompt injection
+- Session tracking and fingerprinting
+- Per-account enhanced rate limiting with provider-specific profiles
+- Circuit breaker pattern for provider resilience
+- Anti-thundering herd protection with mutex locking
+- Signature-based request deduplication cache
+- Domain layer: model availability, cost rules, fallback policy, lockout policy
+- Domain state persistence (SQLite write-through cache for fallbacks, budgets, lockouts, circuit breakers)
+- Policy engine for centralized request evaluation (lockout → budget → fallback)
+- Request telemetry with p50/p95/p99 latency aggregation
+- Correlation ID (X-Request-Id) for end-to-end tracing
+- Compliance audit logging with opt-out per API key
+- Eval framework for LLM quality assurance
+- Resilience UI dashboard with real-time circuit breaker status
+- Modular OAuth providers (12 individual modules under `src/lib/oauth/providers/`)
+
+Primary runtime model:
+
+- Next.js app routes under `src/app/api/*` implement both dashboard APIs and compatibility APIs
+- A shared SSE/routing core in `src/sse/*` + `open-sse/*` handles provider execution, translation, streaming, fallback, and usage
+
+## Scope and Boundaries
+
+### In Scope
+
+- Local gateway runtime
+- Dashboard management APIs
+- Provider authentication and token refresh
+- Request translation and SSE streaming
+- Local state + usage persistence
+- Optional cloud sync orchestration
+
+### Out of Scope
+
+- Cloud service implementation behind `NEXT_PUBLIC_CLOUD_URL`
+- Provider SLA/control plane outside local process
+- External CLI binaries themselves (Claude CLI, Codex CLI, etc.)
+
+## Dashboard Surface (Current)
+
+Main pages under `src/app/(dashboard)/dashboard/`:
+
+- `/dashboard` — quick start + provider overview
+- `/dashboard/endpoint` — endpoint proxy + MCP + A2A + API endpoint tabs
+- `/dashboard/providers` — provider connections and credentials
+- `/dashboard/combos` — combo strategies, templates, model routing rules
+- `/dashboard/costs` — cost aggregation and pricing visibility
+- `/dashboard/analytics` — usage analytics and evaluations
+- `/dashboard/limits` — quota/rate controls
+- `/dashboard/cli-tools` — CLI onboarding, runtime detection, config generation
+- `/dashboard/agents` — detected ACP agents + custom agent registration
+- `/dashboard/media` — image/video/music playground
+- `/dashboard/search-tools` — search provider testing and history
+- `/dashboard/health` — uptime, circuit breakers, rate limits
+- `/dashboard/logs` — request/proxy/audit/console logs
+- `/dashboard/settings` — system settings tabs (general, routing, combo defaults, etc.)
+- `/dashboard/api-manager` — API key lifecycle and model permissions
+
+## High-Level System Context
+
+```mermaid
+flowchart LR
+ subgraph Clients[Developer Clients]
+ C1[Claude Code]
+ C2[Codex CLI]
+ C3[OpenClaw / Droid / Cline / Continue / Roo]
+ C4[Custom OpenAI-compatible clients]
+ BROWSER[Browser Dashboard]
+ end
+
+ subgraph Router[OmniRoute Local Process]
+ API[V1 Compatibility API\n/v1/*]
+ DASH[Dashboard + Management API\n/api/*]
+ CORE[SSE + Translation Core\nopen-sse + src/sse]
+ DB[(storage.sqlite)]
+ UDB[(usage tables + log artifacts)]
+ end
+
+ subgraph Upstreams[Upstream Providers]
+ P1[OAuth Providers\nClaude/Codex/Gemini/Qwen/Qoder/GitHub/Kiro/Cursor/Antigravity]
+ P2[API Key Providers\nOpenAI/Anthropic/OpenRouter/GLM/Kimi/MiniMax\nDeepSeek/Groq/xAI/Mistral/Perplexity\nTogether/Fireworks/Cerebras/Cohere/NVIDIA]
+ P3[Compatible Nodes\nOpenAI-compatible / Anthropic-compatible]
+ end
+
+ subgraph Cloud[Optional Cloud Sync]
+ CLOUD[Cloud Sync Endpoint\nNEXT_PUBLIC_CLOUD_URL]
+ end
+
+ C1 --> API
+ C2 --> API
+ C3 --> API
+ C4 --> API
+ BROWSER --> DASH
+
+ API --> CORE
+ DASH --> DB
+ CORE --> DB
+ CORE --> UDB
+
+ CORE --> P1
+ CORE --> P2
+ CORE --> P3
+
+ DASH --> CLOUD
+```
+
+## Core Runtime Components
+
+## 1) API and Routing Layer (Next.js App Routes)
+
+Main directories:
+
+- `src/app/api/v1/*` and `src/app/api/v1beta/*` for compatibility APIs
+- `src/app/api/*` for management/configuration APIs
+- Next rewrites in `next.config.mjs` map `/v1/*` to `/api/v1/*`
+
+Important compatibility routes:
+
+- `src/app/api/v1/chat/completions/route.ts`
+- `src/app/api/v1/messages/route.ts`
+- `src/app/api/v1/responses/route.ts`
+- `src/app/api/v1/models/route.ts` — includes custom models with `custom: true`
+- `src/app/api/v1/embeddings/route.ts` — embedding generation (6 providers)
+- `src/app/api/v1/images/generations/route.ts` — image generation (4+ providers incl. Antigravity/Nebius)
+- `src/app/api/v1/messages/count_tokens/route.ts`
+- `src/app/api/v1/providers/[provider]/chat/completions/route.ts` — dedicated per-provider chat
+- `src/app/api/v1/providers/[provider]/embeddings/route.ts` — dedicated per-provider embeddings
+- `src/app/api/v1/providers/[provider]/images/generations/route.ts` — dedicated per-provider images
+- `src/app/api/v1beta/models/route.ts`
+- `src/app/api/v1beta/models/[...path]/route.ts`
+
+Management domains:
+
+- Auth/settings: `src/app/api/auth/*`, `src/app/api/settings/*`
+- Providers/connections: `src/app/api/providers*`
+- Provider nodes: `src/app/api/provider-nodes*`
+- Custom models: `src/app/api/provider-models` (GET/POST/DELETE)
+- Model catalog: `src/app/api/models/route.ts` (GET)
+- Proxy config: `src/app/api/settings/proxy` (GET/PUT/DELETE) + `src/app/api/settings/proxy/test` (POST)
+- OAuth: `src/app/api/oauth/*`
+- Keys/aliases/combos/pricing: `src/app/api/keys*`, `src/app/api/models/alias`, `src/app/api/combos*`, `src/app/api/pricing`
+- Usage: `src/app/api/usage/*`
+- Sync/cloud: `src/app/api/sync/*`, `src/app/api/cloud/*`
+- CLI tooling helpers: `src/app/api/cli-tools/*`
+- IP filter: `src/app/api/settings/ip-filter` (GET/PUT)
+- Thinking budget: `src/app/api/settings/thinking-budget` (GET/PUT)
+- System prompt: `src/app/api/settings/system-prompt` (GET/PUT)
+- Sessions: `src/app/api/sessions` (GET)
+- Rate limits: `src/app/api/rate-limits` (GET)
+- Resilience: `src/app/api/resilience` (GET/PATCH) — provider profiles, circuit breaker, rate limit state
+- Resilience reset: `src/app/api/resilience/reset` (POST) — reset breakers + cooldowns
+- Cache stats: `src/app/api/cache/stats` (GET/DELETE)
+- Model availability: `src/app/api/models/availability` (GET/POST)
+- Telemetry: `src/app/api/telemetry/summary` (GET)
+- Budget: `src/app/api/usage/budget` (GET/POST)
+- Fallback chains: `src/app/api/fallback/chains` (GET/POST/DELETE)
+- Compliance audit: `src/app/api/compliance/audit-log` (GET)
+- Evals: `src/app/api/evals` (GET/POST), `src/app/api/evals/[suiteId]` (GET)
+- Policies: `src/app/api/policies` (GET/POST)
+
+## 2) SSE + Translation Core
+
+Main flow modules:
+
+- Entry: `src/sse/handlers/chat.ts`
+- Core orchestration: `open-sse/handlers/chatCore.ts`
+- Provider execution adapters: `open-sse/executors/*`
+- Format detection/provider config: `open-sse/services/provider.ts`
+- Model parse/resolve: `src/sse/services/model.ts`, `open-sse/services/model.ts`
+- Account fallback logic: `open-sse/services/accountFallback.ts`
+- Translation registry: `open-sse/translator/index.ts`
+- Stream transformations: `open-sse/utils/stream.ts`, `open-sse/utils/streamHandler.ts`
+- Usage extraction/normalization: `open-sse/utils/usageTracking.ts`
+- Think tag parser: `open-sse/utils/thinkTagParser.ts`
+- Embedding handler: `open-sse/handlers/embeddings.ts`
+- Embedding provider registry: `open-sse/config/embeddingRegistry.ts`
+- Image generation handler: `open-sse/handlers/imageGeneration.ts`
+- Image provider registry: `open-sse/config/imageRegistry.ts`
+- Response sanitization: `open-sse/handlers/responseSanitizer.ts`
+- Role normalization: `open-sse/services/roleNormalizer.ts`
+
+Services (business logic):
+
+- Account selection/scoring: `open-sse/services/accountSelector.ts`
+- Context lifecycle management: `open-sse/services/contextManager.ts`
+- IP filter enforcement: `open-sse/services/ipFilter.ts`
+- Session tracking: `open-sse/services/sessionManager.ts`
+- Request deduplication: `open-sse/services/signatureCache.ts`
+- System prompt injection: `open-sse/services/systemPrompt.ts`
+- Thinking budget management: `open-sse/services/thinkingBudget.ts`
+- Wildcard model routing: `open-sse/services/wildcardRouter.ts`
+- Rate limit management: `open-sse/services/rateLimitManager.ts`
+- Circuit breaker: `open-sse/services/circuitBreaker.ts`
+
+Domain layer modules:
+
+- Model availability: `src/lib/domain/modelAvailability.ts`
+- Cost rules/budgets: `src/lib/domain/costRules.ts`
+- Fallback policy: `src/lib/domain/fallbackPolicy.ts`
+- Combo resolver: `src/lib/domain/comboResolver.ts`
+- Lockout policy: `src/lib/domain/lockoutPolicy.ts`
+- Policy engine: `src/domain/policyEngine.ts` — centralized lockout → budget → fallback evaluation
+- Error codes catalog: `src/lib/domain/errorCodes.ts`
+- Request ID: `src/lib/domain/requestId.ts`
+- Fetch timeout: `src/lib/domain/fetchTimeout.ts`
+- Request telemetry: `src/lib/domain/requestTelemetry.ts`
+- Compliance/audit: `src/lib/domain/compliance/index.ts`
+- Eval runner: `src/lib/domain/evalRunner.ts`
+- Domain state persistence: `src/lib/db/domainState.ts` — SQLite CRUD for fallback chains, budgets, cost history, lockout state, circuit breakers
+
+OAuth provider modules (12 individual files under `src/lib/oauth/providers/`):
+
+- Registry index: `src/lib/oauth/providers/index.ts`
+- Individual providers: `claude.ts`, `codex.ts`, `gemini.ts`, `antigravity.ts`, `qoder.ts`, `qwen.ts`, `kimi-coding.ts`, `github.ts`, `kiro.ts`, `cursor.ts`, `kilocode.ts`, `cline.ts`
+- Thin wrapper: `src/lib/oauth/providers.ts` — re-exports from individual modules
+
+## 3) Persistence Layer
+
+Primary state DB (SQLite):
+
+- Core infra: `src/lib/db/core.ts` (better-sqlite3, migrations, WAL)
+- Re-export facade: `src/lib/localDb.ts` (thin compatibility layer for callers)
+- file: `${DATA_DIR}/storage.sqlite` (or `$XDG_CONFIG_HOME/omniroute/storage.sqlite` when set, else `~/.omniroute/storage.sqlite`)
+- entities (tables + KV namespaces): providerConnections, providerNodes, modelAliases, combos, apiKeys, settings, pricing, **customModels**, **proxyConfig**, **ipFilter**, **thinkingBudget**, **systemPrompt**
+
+Usage persistence:
+
+- facade: `src/lib/usageDb.ts` (decomposed modules in `src/lib/usage/*`)
+- SQLite tables in `storage.sqlite`: `usage_history`, `call_logs`, `proxy_logs`
+- optional file artifacts remain for compatibility/debug (`${DATA_DIR}/log.txt`, `${DATA_DIR}/call_logs/`, `/logs/...`)
+- legacy JSON files are migrated to SQLite by startup migrations when present
+
+Domain State DB (SQLite):
+
+- `src/lib/db/domainState.ts` — CRUD operations for domain state
+- Tables (created in `src/lib/db/core.ts`): `domain_fallback_chains`, `domain_budgets`, `domain_cost_history`, `domain_lockout_state`, `domain_circuit_breakers`
+- Write-through cache pattern: in-memory Maps are authoritative at runtime; mutations are written synchronously to SQLite; state is restored from DB on cold start
+
+## 4) Auth + Security Surfaces
+
+- Dashboard cookie auth: `src/proxy.ts`, `src/app/api/auth/login/route.ts`
+- API key generation/verification: `src/shared/utils/apiKey.ts`
+- Provider secrets persisted in `providerConnections` entries
+- Outbound proxy support via `open-sse/utils/proxyFetch.ts` (env vars) and `open-sse/utils/networkProxy.ts` (configurable per-provider or global)
+
+## 5) Cloud Sync
+
+- Scheduler init: `src/lib/initCloudSync.ts`, `src/shared/services/initializeCloudSync.ts`, `src/shared/services/modelSyncScheduler.ts`
+- Periodic task: `src/shared/services/cloudSyncScheduler.ts`
+- Periodic task: `src/shared/services/modelSyncScheduler.ts`
+- Control route: `src/app/api/sync/cloud/route.ts`
+
+## Request Lifecycle (`/v1/chat/completions`)
+
+```mermaid
+sequenceDiagram
+ autonumber
+ participant Client as CLI/SDK Client
+ participant Route as /api/v1/chat/completions
+ participant Chat as src/sse/handlers/chat
+ participant Core as open-sse/handlers/chatCore
+ participant Model as Model Resolver
+ participant Auth as Credential Selector
+ participant Exec as Provider Executor
+ participant Prov as Upstream Provider
+ participant Stream as Stream Translator
+ participant Usage as usageDb
+
+ Client->>Route: POST /v1/chat/completions
+ Route->>Chat: handleChat(request)
+ Chat->>Model: parse/resolve model or combo
+
+ alt Combo model
+ Chat->>Chat: iterate combo models (handleComboChat)
+ end
+
+ Chat->>Auth: getProviderCredentials(provider)
+ Auth-->>Chat: active account + tokens/api key
+
+ Chat->>Core: handleChatCore(body, modelInfo, credentials)
+ Core->>Core: detect source format
+ Core->>Core: translate request to target format
+ Core->>Exec: execute(provider, transformedBody)
+ Exec->>Prov: upstream API call
+ Prov-->>Exec: SSE/JSON response
+ Exec-->>Core: response + metadata
+
+ alt 401/403
+ Core->>Exec: refreshCredentials()
+ Exec-->>Core: updated tokens
+ Core->>Exec: retry request
+ end
+
+ Core->>Stream: translate/normalize stream to client format
+ Stream-->>Client: SSE chunks / JSON response
+
+ Stream->>Usage: extract usage + persist history/log
+```
+
+## Combo + Account Fallback Flow
+
+```mermaid
+flowchart TD
+ A[Incoming model string] --> B{Is combo name?}
+ B -- Yes --> C[Load combo models sequence]
+ B -- No --> D[Single model path]
+
+ C --> E[Try model N]
+ E --> F[Resolve provider/model]
+ D --> F
+
+ F --> G[Select account credentials]
+ G --> H{Credentials available?}
+ H -- No --> I[Return provider unavailable]
+ H -- Yes --> J[Execute request]
+
+ J --> K{Success?}
+ K -- Yes --> L[Return response]
+ K -- No --> M{Fallback-eligible error?}
+
+ M -- No --> N[Return error]
+ M -- Yes --> O[Mark account unavailable cooldown]
+ O --> P{Another account for provider?}
+ P -- Yes --> G
+ P -- No --> Q{In combo with next model?}
+ Q -- Yes --> E
+ Q -- No --> R[Return all unavailable]
+```
+
+Fallback decisions are driven by `open-sse/services/accountFallback.ts` using status codes and error-message heuristics. Combo routing adds one extra guard: provider-scoped 400s such as upstream content-block and role-validation failures are treated as model-local failures so later combo targets can still run.
+
+## OAuth Onboarding and Token Refresh Lifecycle
+
+```mermaid
+sequenceDiagram
+ autonumber
+ participant UI as Dashboard UI
+ participant OAuth as /api/oauth/[provider]/[action]
+ participant ProvAuth as Provider Auth Server
+ participant DB as localDb
+ participant Test as /api/providers/[id]/test
+ participant Exec as Provider Executor
+
+ UI->>OAuth: GET authorize or device-code
+ OAuth->>ProvAuth: create auth/device flow
+ ProvAuth-->>OAuth: auth URL or device code payload
+ OAuth-->>UI: flow data
+
+ UI->>OAuth: POST exchange or poll
+ OAuth->>ProvAuth: token exchange/poll
+ ProvAuth-->>OAuth: access/refresh tokens
+ OAuth->>DB: createProviderConnection(oauth data)
+ OAuth-->>UI: success + connection id
+
+ UI->>Test: POST /api/providers/[id]/test
+ Test->>Exec: validate credentials / optional refresh
+ Exec-->>Test: valid or refreshed token info
+ Test->>DB: update status/tokens/errors
+ Test-->>UI: validation result
+```
+
+Refresh during live traffic is executed inside `open-sse/handlers/chatCore.ts` via executor `refreshCredentials()`.
+
+## Cloud Sync Lifecycle (Enable / Sync / Disable)
+
+```mermaid
+sequenceDiagram
+ autonumber
+ participant UI as Endpoint Page UI
+ participant Sync as /api/sync/cloud
+ participant DB as localDb
+ participant Cloud as External Cloud Sync
+ participant Claude as ~/.claude/settings.json
+
+ UI->>Sync: POST action=enable
+ Sync->>DB: set cloudEnabled=true
+ Sync->>DB: ensure API key exists
+ Sync->>Cloud: POST /sync/{machineId} (providers/aliases/combos/keys)
+ Cloud-->>Sync: sync result
+ Sync->>Cloud: GET /{machineId}/v1/verify
+ Sync-->>UI: enabled + verification status
+
+ UI->>Sync: POST action=sync
+ Sync->>Cloud: POST /sync/{machineId}
+ Cloud-->>Sync: remote data
+ Sync->>DB: update newer local tokens/status
+ Sync-->>UI: synced
+
+ UI->>Sync: POST action=disable
+ Sync->>DB: set cloudEnabled=false
+ Sync->>Cloud: DELETE /sync/{machineId}
+ Sync->>Claude: switch ANTHROPIC_BASE_URL back to local (if needed)
+ Sync-->>UI: disabled
+```
+
+Periodic sync is triggered by `CloudSyncScheduler` when cloud is enabled.
+
+## Data Model and Storage Map
+
+```mermaid
+erDiagram
+ SETTINGS ||--o{ PROVIDER_CONNECTION : controls
+ PROVIDER_NODE ||--o{ PROVIDER_CONNECTION : backs_compatible_provider
+ PROVIDER_CONNECTION ||--o{ USAGE_ENTRY : emits_usage
+
+ SETTINGS {
+ boolean cloudEnabled
+ number stickyRoundRobinLimit
+ boolean requireLogin
+ string password_hash
+ string fallbackStrategy
+ json rateLimitDefaults
+ json providerProfiles
+ }
+
+ PROVIDER_CONNECTION {
+ string id
+ string provider
+ string authType
+ string name
+ number priority
+ boolean isActive
+ string apiKey
+ string accessToken
+ string refreshToken
+ string expiresAt
+ string testStatus
+ string lastError
+ string rateLimitedUntil
+ json providerSpecificData
+ }
+
+ PROVIDER_NODE {
+ string id
+ string type
+ string name
+ string prefix
+ string apiType
+ string baseUrl
+ }
+
+ MODEL_ALIAS {
+ string alias
+ string targetModel
+ }
+
+ COMBO {
+ string id
+ string name
+ string[] models
+ }
+
+ API_KEY {
+ string id
+ string name
+ string key
+ string machineId
+ }
+
+ USAGE_ENTRY {
+ string provider
+ string model
+ number prompt_tokens
+ number completion_tokens
+ string connectionId
+ string timestamp
+ }
+
+ CUSTOM_MODEL {
+ string id
+ string name
+ string providerId
+ }
+
+ PROXY_CONFIG {
+ string global
+ json providers
+ }
+
+ IP_FILTER {
+ string mode
+ string[] allowlist
+ string[] blocklist
+ }
+
+ THINKING_BUDGET {
+ string mode
+ number customBudget
+ string effortLevel
+ }
+
+ SYSTEM_PROMPT {
+ boolean enabled
+ string prompt
+ string position
+ }
+```
+
+Physical storage files:
+
+- primary runtime DB: `${DATA_DIR}/storage.sqlite`
+- request log lines: `${DATA_DIR}/log.txt` (compat/debug artifact)
+- structured call payload archives: `${DATA_DIR}/call_logs/`
+- optional translator/request debug sessions: `/logs/...`
+
+## Deployment Topology
+
+```mermaid
+flowchart LR
+ subgraph LocalHost[Developer Host]
+ CLI[CLI Tools]
+ Browser[Dashboard Browser]
+ end
+
+ subgraph ContainerOrProcess[OmniRoute Runtime]
+ Next[Next.js Server\nPORT=20128]
+ Core[SSE Core + Executors]
+ MainDB[(storage.sqlite)]
+ UsageDB[(usage tables + log artifacts)]
+ end
+
+ subgraph External[External Services]
+ Providers[AI Providers]
+ SyncCloud[Cloud Sync Service]
+ end
+
+ CLI --> Next
+ Browser --> Next
+ Next --> Core
+ Next --> MainDB
+ Core --> MainDB
+ Core --> UsageDB
+ Core --> Providers
+ Next --> SyncCloud
+```
+
+## Module Mapping (Decision-Critical)
+
+### Route and API Modules
+
+- `src/app/api/v1/*`, `src/app/api/v1beta/*`: compatibility APIs
+- `src/app/api/v1/providers/[provider]/*`: dedicated per-provider routes (chat, embeddings, images)
+- `src/app/api/providers*`: provider CRUD, validation, testing
+- `src/app/api/provider-nodes*`: custom compatible node management
+- `src/app/api/provider-models`: custom model management (CRUD)
+- `src/app/api/models/route.ts`: model catalog API (aliases + custom models)
+- `src/app/api/oauth/*`: OAuth/device-code flows
+- `src/app/api/keys*`: local API key lifecycle
+- `src/app/api/models/alias`: alias management
+- `src/app/api/combos*`: fallback combo management
+- `src/app/api/pricing`: pricing overrides for cost calculation
+- `src/app/api/settings/proxy`: proxy configuration (GET/PUT/DELETE)
+- `src/app/api/settings/proxy/test`: outbound proxy connectivity test (POST)
+- `src/app/api/usage/*`: usage and logs APIs
+- `src/app/api/sync/*` + `src/app/api/cloud/*`: cloud sync and cloud-facing helpers
+- `src/app/api/cli-tools/*`: local CLI config writers/checkers
+- `src/app/api/settings/ip-filter`: IP allowlist/blocklist (GET/PUT)
+- `src/app/api/settings/thinking-budget`: thinking token budget config (GET/PUT)
+- `src/app/api/settings/system-prompt`: global system prompt (GET/PUT)
+- `src/app/api/sessions`: active session listing (GET)
+- `src/app/api/rate-limits`: per-account rate limit status (GET)
+
+### Routing and Execution Core
+
+- `src/sse/handlers/chat.ts`: request parse, combo handling, account selection loop
+- `open-sse/handlers/chatCore.ts`: translation, executor dispatch, retry/refresh handling, stream setup
+- `open-sse/executors/*`: provider-specific network and format behavior
+
+### Translation Registry and Format Converters
+
+- `open-sse/translator/index.ts`: translator registry and orchestration
+- Request translators: `open-sse/translator/request/*`
+- Response translators: `open-sse/translator/response/*`
+- Format constants: `open-sse/translator/formats.ts`
+
+### Persistence
+
+- `src/lib/db/*`: persistent config/state and domain persistence on SQLite
+- `src/lib/localDb.ts`: compatibility re-export for DB modules
+- `src/lib/usageDb.ts`: usage history/call logs facade on top of SQLite tables
+
+## Provider Executor Coverage (Strategy Pattern)
+
+Each provider has a specialized executor extending `BaseExecutor` (in `open-sse/executors/base.ts`), which provides URL building, header construction, retry with exponential backoff, credential refresh hooks, and the `execute()` orchestration method.
+
+| Executor | Provider(s) | Special Handling |
+| --------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------ | -------------------------------------------------------------------- |
+| `DefaultExecutor` | OpenAI, Claude, Gemini, Qwen, Qoder, OpenRouter, GLM, Kimi, MiniMax, DeepSeek, Groq, xAI, Mistral, Perplexity, Together, Fireworks, Cerebras, Cohere, NVIDIA | Dynamic URL/header config per provider |
+| `AntigravityExecutor` | Google Antigravity | Custom project/session IDs, Retry-After parsing |
+| `CodexExecutor` | OpenAI Codex | Injects system instructions, forces reasoning effort |
+| `CursorExecutor` | Cursor IDE | ConnectRPC protocol, Protobuf encoding, request signing via checksum |
+| `GithubExecutor` | GitHub Copilot | Copilot token refresh, VSCode-mimicking headers |
+| `KiroExecutor` | AWS CodeWhisperer/Kiro | AWS EventStream binary format → SSE conversion |
+| `GeminiCLIExecutor` | Gemini CLI | Google OAuth token refresh cycle |
+
+All other providers (including custom compatible nodes) use the `DefaultExecutor`.
+
+## Provider Compatibility Matrix
+
+| Provider | Format | Auth | Stream | Non-Stream | Token Refresh | Usage API |
+| ---------------- | ---------------- | --------------------- | ---------------- | ---------- | ------------- | ------------------ |
+| Claude | claude | API Key / OAuth | ✅ | ✅ | ✅ | ⚠️ Admin only |
+| Gemini | gemini | API Key / OAuth | ✅ | ✅ | ✅ | ⚠️ Cloud Console |
+| Gemini CLI | gemini-cli | OAuth | ✅ | ✅ | ✅ | ⚠️ Cloud Console |
+| Antigravity | antigravity | OAuth | ✅ | ✅ | ✅ | ✅ Full quota API |
+| OpenAI | openai | API Key | ✅ | ✅ | ❌ | ❌ |
+| Codex | openai-responses | OAuth | ✅ forced | ❌ | ✅ | ✅ Rate limits |
+| GitHub Copilot | openai | OAuth + Copilot Token | ✅ | ✅ | ✅ | ✅ Quota snapshots |
+| Cursor | cursor | Custom checksum | ✅ | ✅ | ❌ | ❌ |
+| Kiro | kiro | AWS SSO OIDC | ✅ (EventStream) | ❌ | ✅ | ✅ Usage limits |
+| Qwen | openai | OAuth | ✅ | ✅ | ✅ | ⚠️ Per request |
+| Qoder | openai | OAuth (Basic) | ✅ | ✅ | ✅ | ⚠️ Per request |
+| OpenRouter | openai | API Key | ✅ | ✅ | ❌ | ❌ |
+| GLM/Kimi/MiniMax | claude | API Key | ✅ | ✅ | ❌ | ❌ |
+| DeepSeek | openai | API Key | ✅ | ✅ | ❌ | ❌ |
+| Groq | openai | API Key | ✅ | ✅ | ❌ | ❌ |
+| xAI (Grok) | openai | API Key | ✅ | ✅ | ❌ | ❌ |
+| Mistral | openai | API Key | ✅ | ✅ | ❌ | ❌ |
+| Perplexity | openai | API Key | ✅ | ✅ | ❌ | ❌ |
+| Together AI | openai | API Key | ✅ | ✅ | ❌ | ❌ |
+| Fireworks AI | openai | API Key | ✅ | ✅ | ❌ | ❌ |
+| Cerebras | openai | API Key | ✅ | ✅ | ❌ | ❌ |
+| Cohere | openai | API Key | ✅ | ✅ | ❌ | ❌ |
+| NVIDIA NIM | openai | API Key | ✅ | ✅ | ❌ | ❌ |
+
+## Format Translation Coverage
+
+Detected source formats include:
+
+- `openai`
+- `openai-responses`
+- `claude`
+- `gemini`
+
+Target formats include:
+
+- OpenAI chat/Responses
+- Claude
+- Gemini/Gemini-CLI/Antigravity envelope
+- Kiro
+- Cursor
+
+Translations use **OpenAI as the hub format** — all conversions go through OpenAI as intermediate:
+
+```
+Source Format → OpenAI (hub) → Target Format
+```
+
+Translations are selected dynamically based on source payload shape and provider target format.
+
+Additional processing layers in the translation pipeline:
+
+- **Response sanitization** — Strips non-standard fields from OpenAI-format responses (both streaming and non-streaming) to ensure strict SDK compliance
+- **Role normalization** — Converts `developer` → `system` for non-OpenAI targets; merges `system` → `user` for models that reject the system role (GLM, ERNIE)
+- **Think tag extraction** — Parses `...` blocks from content into `reasoning_content` field
+- **Structured output** — Converts OpenAI `response_format.json_schema` to Gemini's `responseMimeType` + `responseSchema`
+
+## Supported API Endpoints
+
+| Endpoint | Format | Handler |
+| -------------------------------------------------- | ------------------ | ------------------------------------------------------------------- |
+| `POST /v1/chat/completions` | OpenAI Chat | `src/sse/handlers/chat.ts` |
+| `POST /v1/messages` | Claude Messages | Same handler (auto-detected) |
+| `POST /v1/responses` | OpenAI Responses | `open-sse/handlers/responsesHandler.ts` |
+| `POST /v1/embeddings` | OpenAI Embeddings | `open-sse/handlers/embeddings.ts` |
+| `GET /v1/embeddings` | Model listing | API route |
+| `POST /v1/images/generations` | OpenAI Images | `open-sse/handlers/imageGeneration.ts` |
+| `GET /v1/images/generations` | Model listing | API route |
+| `POST /v1/providers/{provider}/chat/completions` | OpenAI Chat | Dedicated per-provider with model validation |
+| `POST /v1/providers/{provider}/embeddings` | OpenAI Embeddings | Dedicated per-provider with model validation |
+| `POST /v1/providers/{provider}/images/generations` | OpenAI Images | Dedicated per-provider with model validation |
+| `POST /v1/messages/count_tokens` | Claude Token Count | API route |
+| `GET /v1/models` | OpenAI Models list | API route (chat + embedding + image + custom models) |
+| `GET /api/models/catalog` | Catalog | All models grouped by provider + type |
+| `POST /v1beta/models/*:streamGenerateContent` | Gemini native | API route |
+| `GET/PUT/DELETE /api/settings/proxy` | Proxy Config | Network proxy configuration |
+| `POST /api/settings/proxy/test` | Proxy Connectivity | Proxy health/connectivity test endpoint |
+| `GET/POST/DELETE /api/provider-models` | Provider Models | Provider model metadata backing custom and managed available models |
+
+## Bypass Handler
+
+The bypass handler (`open-sse/utils/bypassHandler.ts`) intercepts known "throwaway" requests from Claude CLI — warmup pings, title extractions, and token counts — and returns a **fake response** without consuming upstream provider tokens. This is triggered only when `User-Agent` contains `claude-cli`.
+
+## Request Logger Pipeline
+
+The request logger (`open-sse/utils/requestLogger.ts`) provides a 7-stage debug logging pipeline, disabled by default, enabled via `ENABLE_REQUEST_LOGS=true`:
+
+```
+1_req_client.json → 2_req_source.json → 3_req_openai.json → 4_req_target.json
+→ 5_res_provider.txt → 6_res_openai.txt → 7_res_client.txt
+```
+
+Files are written to `/logs//` for each request session.
+
+## Failure Modes and Resilience
+
+## 1) Account/Provider Availability
+
+- provider account cooldown on transient/rate/auth errors
+- account fallback before failing request
+- combo model fallback when current model/provider path is exhausted
+
+## 2) Token Expiry
+
+- pre-check and refresh with retry for refreshable providers
+- 401/403 retry after refresh attempt in core path
+
+## 3) Stream Safety
+
+- disconnect-aware stream controller
+- translation stream with end-of-stream flush and `[DONE]` handling
+- usage estimation fallback when provider usage metadata is missing
+
+## 4) Cloud Sync Degradation
+
+- sync errors are surfaced but local runtime continues
+- scheduler has retry-capable logic, but periodic execution currently calls single-attempt sync by default
+
+## 5) Data Integrity
+
+- SQLite schema migrations and auto-upgrade hooks at startup
+- legacy JSON → SQLite migration compatibility path
+
+## Observability and Operational Signals
+
+Runtime visibility sources:
+
+- console logs from `src/sse/utils/logger.ts`
+- per-request usage aggregates in SQLite (`usage_history`, `call_logs`, `proxy_logs`)
+- four-stage detailed payload captures in SQLite (`request_detail_logs`) when `settings.detailed_logs_enabled=true`
+- textual request status log in `log.txt` (optional/compat)
+- optional deep request/translation logs under `logs/` when `ENABLE_REQUEST_LOGS=true`
+- dashboard usage endpoints (`/api/usage/*`) for UI consumption
+
+Detailed request payload capture stores up to four JSON payload stages per routed call:
+
+- raw request received from the client
+- translated request actually sent upstream
+- provider response reconstructed as JSON; streamed responses are compacted to the final summary plus stream metadata
+- final client response returned by OmniRoute; streamed responses are stored in the same compact summary form
+
+## Security-Sensitive Boundaries
+
+- JWT secret (`JWT_SECRET`) secures dashboard session cookie verification/signing
+- Initial password bootstrap (`INITIAL_PASSWORD`) should be explicitly configured for first-run provisioning
+- API key HMAC secret (`API_KEY_SECRET`) secures generated local API key format
+- Provider secrets (API keys/tokens) are persisted in local DB and should be protected at filesystem level
+- Cloud sync endpoints rely on API key auth + machine id semantics
+
+## Environment and Runtime Matrix
+
+Environment variables actively used by code:
+
+- App/auth: `JWT_SECRET`, `INITIAL_PASSWORD`
+- Storage: `DATA_DIR`
+- Compatible node behavior: `ALLOW_MULTI_CONNECTIONS_PER_COMPAT_NODE`
+- Optional storage base override (Linux/macOS when `DATA_DIR` unset): `XDG_CONFIG_HOME`
+- Security hashing: `API_KEY_SECRET`, `MACHINE_ID_SALT`
+- Logging: `ENABLE_REQUEST_LOGS`
+- Sync/cloud URLing: `NEXT_PUBLIC_BASE_URL`, `NEXT_PUBLIC_CLOUD_URL`
+- Outbound proxy: `HTTP_PROXY`, `HTTPS_PROXY`, `ALL_PROXY`, `NO_PROXY` and lowercase variants
+- SOCKS5 feature flags: `ENABLE_SOCKS5_PROXY`, `NEXT_PUBLIC_ENABLE_SOCKS5_PROXY`
+- Platform/runtime helpers (not app-specific config): `APPDATA`, `NODE_ENV`, `PORT`, `HOSTNAME`
+
+## Known Architectural Notes
+
+1. `usageDb` and `localDb` share the same base directory policy (`DATA_DIR` -> `XDG_CONFIG_HOME/omniroute` -> `~/.omniroute`) with legacy file migration.
+2. `/api/v1/route.ts` delegates to the same unified catalog builder used by `/api/v1/models` (`src/app/api/v1/models/catalog.ts`) to avoid semantic drift.
+3. Request logger writes full headers/body when enabled; treat log directory as sensitive.
+4. Cloud behavior depends on correct `NEXT_PUBLIC_BASE_URL` and cloud endpoint reachability.
+5. The `open-sse/` directory is published as the `@omniroute/open-sse` **npm workspace package**. Source code imports it via `@omniroute/open-sse/...` (resolved by Next.js `transpilePackages`). File paths in this document still use the directory name `open-sse/` for consistency.
+6. Charts in the dashboard use **Recharts** (SVG-based) for accessible, interactive analytics visualizations (model usage bar charts, provider breakdown tables with success rates).
+7. E2E tests use **Playwright** (`tests/e2e/`), run via `npm run test:e2e`. Unit tests use **Node.js test runner** (`tests/unit/`), run via `npm run test:unit`. Source code under `src/` is **TypeScript** (`.ts`/`.tsx`); the `open-sse/` workspace remains JavaScript (`.js`).
+8. Settings page is organized into 5 tabs: Security, Routing (6 global strategies: fill-first, round-robin, p2c, random, least-used, cost-optimized), Resilience (editable rate limits, circuit breaker, policies), AI (thinking budget, system prompt, prompt cache), Advanced (proxy).
+
+## Operational Verification Checklist
+
+- Build from source: `npm run build`
+- Build Docker image: `docker build -t omniroute .`
+- Start service and verify:
+- `GET /api/settings`
+- `GET /api/v1/models`
+- CLI target base URL should be `http://:20128/v1` when `PORT=20128`
diff --git a/docs/i18n/in/docs/AUTO-COMBO.md b/docs/i18n/in/docs/AUTO-COMBO.md
new file mode 100644
index 0000000000..3126d79b3b
--- /dev/null
+++ b/docs/i18n/in/docs/AUTO-COMBO.md
@@ -0,0 +1,67 @@
+# OmniRoute Auto-Combo Engine (हिन्दी)
+
+🌐 **Languages:** 🇺🇸 [English](../../../../docs/AUTO-COMBO.md) · 🇪🇸 [es](../../es/docs/AUTO-COMBO.md) · 🇫🇷 [fr](../../fr/docs/AUTO-COMBO.md) · 🇩🇪 [de](../../de/docs/AUTO-COMBO.md) · 🇮🇹 [it](../../it/docs/AUTO-COMBO.md) · 🇷🇺 [ru](../../ru/docs/AUTO-COMBO.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/AUTO-COMBO.md) · 🇯🇵 [ja](../../ja/docs/AUTO-COMBO.md) · 🇰🇷 [ko](../../ko/docs/AUTO-COMBO.md) · 🇸🇦 [ar](../../ar/docs/AUTO-COMBO.md) · 🇮🇳 [in](../../in/docs/AUTO-COMBO.md) · 🇹🇭 [th](../../th/docs/AUTO-COMBO.md) · 🇻🇳 [vi](../../vi/docs/AUTO-COMBO.md) · 🇮🇩 [id](../../id/docs/AUTO-COMBO.md) · 🇲🇾 [ms](../../ms/docs/AUTO-COMBO.md) · 🇳🇱 [nl](../../nl/docs/AUTO-COMBO.md) · 🇵🇱 [pl](../../pl/docs/AUTO-COMBO.md) · 🇸🇪 [sv](../../sv/docs/AUTO-COMBO.md) · 🇳🇴 [no](../../no/docs/AUTO-COMBO.md) · 🇩🇰 [da](../../da/docs/AUTO-COMBO.md) · 🇫🇮 [fi](../../fi/docs/AUTO-COMBO.md) · 🇵🇹 [pt](../../pt/docs/AUTO-COMBO.md) · 🇷🇴 [ro](../../ro/docs/AUTO-COMBO.md) · 🇭🇺 [hu](../../hu/docs/AUTO-COMBO.md) · 🇧🇬 [bg](../../bg/docs/AUTO-COMBO.md) · 🇸🇰 [sk](../../sk/docs/AUTO-COMBO.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/AUTO-COMBO.md) · 🇮🇱 [he](../../he/docs/AUTO-COMBO.md) · 🇵🇭 [phi](../../phi/docs/AUTO-COMBO.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/AUTO-COMBO.md) · 🇨🇿 [cs](../../cs/docs/AUTO-COMBO.md)
+
+---
+
+> Self-managing model chains with adaptive scoring
+
+## How It Works
+
+The Auto-Combo Engine dynamically selects the best provider/model for each request using a **6-factor scoring function**:
+
+| Factor | Weight | Description |
+| :--------- | :----- | :---------------------------------------------- |
+| Quota | 0.20 | Remaining capacity [0..1] |
+| Health | 0.25 | Circuit breaker: CLOSED=1.0, HALF=0.5, OPEN=0.0 |
+| CostInv | 0.20 | Inverse cost (cheaper = higher score) |
+| LatencyInv | 0.15 | Inverse p95 latency (faster = higher) |
+| TaskFit | 0.10 | Model × task type fitness score |
+| Stability | 0.10 | Low variance in latency/errors |
+
+## Mode Packs
+
+| Pack | Focus | Key Weight |
+| :---------------------- | :----------- | :--------------- |
+| 🚀 **Ship Fast** | Speed | latencyInv: 0.35 |
+| 💰 **Cost Saver** | Economy | costInv: 0.40 |
+| 🎯 **Quality First** | Best model | taskFit: 0.40 |
+| 📡 **Offline Friendly** | Availability | quota: 0.40 |
+
+## Self-Healing
+
+- **Temporary exclusion**: Score < 0.2 → excluded for 5 min (progressive backoff, max 30 min)
+- **Circuit breaker awareness**: OPEN → auto-excluded; HALF_OPEN → probe requests
+- **Incident mode**: >50% OPEN → disable exploration, maximize stability
+- **Cooldown recovery**: After exclusion, first request is a "probe" with reduced timeout
+
+## Bandit Exploration
+
+5% of requests (configurable) are routed to random providers for exploration. Disabled in incident mode.
+
+## API
+
+```bash
+# Create auto-combo
+curl -X POST http://localhost:20128/api/combos/auto \
+ -H "Content-Type: application/json" \
+ -d '{"id":"my-auto","name":"Auto Coder","candidatePool":["anthropic","google","openai"],"modePack":"ship-fast"}'
+
+# List auto-combos
+curl http://localhost:20128/api/combos/auto
+```
+
+## Task Fitness
+
+30+ models scored across 6 task types (`coding`, `review`, `planning`, `analysis`, `debugging`, `documentation`). Supports wildcard patterns (e.g., `*-coder` → high coding score).
+
+## Files
+
+| File | Purpose |
+| :------------------------------------------- | :------------------------------------ |
+| `open-sse/services/autoCombo/scoring.ts` | Scoring function & pool normalization |
+| `open-sse/services/autoCombo/taskFitness.ts` | Model × task fitness lookup |
+| `open-sse/services/autoCombo/engine.ts` | Selection logic, bandit, budget cap |
+| `open-sse/services/autoCombo/selfHealing.ts` | Exclusion, probes, incident mode |
+| `open-sse/services/autoCombo/modePacks.ts` | 4 weight profiles |
+| `src/app/api/combos/auto/route.ts` | REST API |
diff --git a/docs/i18n/in/docs/CLI-TOOLS.md b/docs/i18n/in/docs/CLI-TOOLS.md
new file mode 100644
index 0000000000..c1f87f62f8
--- /dev/null
+++ b/docs/i18n/in/docs/CLI-TOOLS.md
@@ -0,0 +1,348 @@
+# CLI Tools Setup Guide — OmniRoute (हिन्दी)
+
+🌐 **Languages:** 🇺🇸 [English](../../../../docs/CLI-TOOLS.md) · 🇪🇸 [es](../../es/docs/CLI-TOOLS.md) · 🇫🇷 [fr](../../fr/docs/CLI-TOOLS.md) · 🇩🇪 [de](../../de/docs/CLI-TOOLS.md) · 🇮🇹 [it](../../it/docs/CLI-TOOLS.md) · 🇷🇺 [ru](../../ru/docs/CLI-TOOLS.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/CLI-TOOLS.md) · 🇯🇵 [ja](../../ja/docs/CLI-TOOLS.md) · 🇰🇷 [ko](../../ko/docs/CLI-TOOLS.md) · 🇸🇦 [ar](../../ar/docs/CLI-TOOLS.md) · 🇮🇳 [in](../../in/docs/CLI-TOOLS.md) · 🇹🇭 [th](../../th/docs/CLI-TOOLS.md) · 🇻🇳 [vi](../../vi/docs/CLI-TOOLS.md) · 🇮🇩 [id](../../id/docs/CLI-TOOLS.md) · 🇲🇾 [ms](../../ms/docs/CLI-TOOLS.md) · 🇳🇱 [nl](../../nl/docs/CLI-TOOLS.md) · 🇵🇱 [pl](../../pl/docs/CLI-TOOLS.md) · 🇸🇪 [sv](../../sv/docs/CLI-TOOLS.md) · 🇳🇴 [no](../../no/docs/CLI-TOOLS.md) · 🇩🇰 [da](../../da/docs/CLI-TOOLS.md) · 🇫🇮 [fi](../../fi/docs/CLI-TOOLS.md) · 🇵🇹 [pt](../../pt/docs/CLI-TOOLS.md) · 🇷🇴 [ro](../../ro/docs/CLI-TOOLS.md) · 🇭🇺 [hu](../../hu/docs/CLI-TOOLS.md) · 🇧🇬 [bg](../../bg/docs/CLI-TOOLS.md) · 🇸🇰 [sk](../../sk/docs/CLI-TOOLS.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/CLI-TOOLS.md) · 🇮🇱 [he](../../he/docs/CLI-TOOLS.md) · 🇵🇭 [phi](../../phi/docs/CLI-TOOLS.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/CLI-TOOLS.md) · 🇨🇿 [cs](../../cs/docs/CLI-TOOLS.md)
+
+---
+
+This guide explains how to install and configure all supported AI coding CLI tools
+to use **OmniRoute** as the unified backend, giving you centralized key management,
+cost tracking, model switching, and request logging across every tool.
+
+---
+
+## How It Works
+
+```
+Claude / Codex / OpenCode / Cline / KiloCode / Continue / Kiro / Cursor / Copilot
+ │
+ ▼ (all point to OmniRoute)
+ http://YOUR_SERVER:20128/v1
+ │
+ ▼ (OmniRoute routes to the right provider)
+ Anthropic / OpenAI / Gemini / DeepSeek / Groq / Mistral / ...
+```
+
+**Benefits:**
+
+- One API key to manage all tools
+- Cost tracking across all CLIs in the dashboard
+- Model switching without reconfiguring every tool
+- Works locally and on remote servers (VPS)
+
+---
+
+## Supported Tools (Dashboard Source of Truth)
+
+The dashboard cards in `/dashboard/cli-tools` are generated from `src/shared/constants/cliTools.ts`.
+Current list (v3.0.0-rc.16):
+
+| Tool | ID | Command | Setup Mode | Install Method |
+| ------------------ | ------------- | ---------- | ---------- | -------------- |
+| **Claude Code** | `claude` | `claude` | env | npm |
+| **OpenAI Codex** | `codex` | `codex` | custom | npm |
+| **Factory Droid** | `droid` | `droid` | custom | bundled/CLI |
+| **OpenClaw** | `openclaw` | `openclaw` | custom | bundled/CLI |
+| **Cursor** | `cursor` | app | guide | desktop app |
+| **Cline** | `cline` | `cline` | custom | npm |
+| **Kilo Code** | `kilo` | `kilocode` | custom | npm |
+| **Continue** | `continue` | extension | guide | VS Code |
+| **Antigravity** | `antigravity` | internal | mitm | OmniRoute |
+| **GitHub Copilot** | `copilot` | extension | custom | VS Code |
+| **OpenCode** | `opencode` | `opencode` | guide | npm |
+| **Kiro AI** | `kiro` | app/cli | mitm | desktop/CLI |
+
+### CLI fingerprint sync (Agents + Settings)
+
+`/dashboard/agents` and `Settings > CLI Fingerprint` use `src/shared/constants/cliCompatProviders.ts`.
+This keeps provider IDs aligned with CLI cards and legacy IDs.
+
+| CLI ID | Fingerprint Provider ID |
+| ---------------------------------------------------------------------------------------------------- | ----------------------- |
+| `kilo` | `kilocode` |
+| `copilot` | `github` |
+| `claude` / `codex` / `antigravity` / `kiro` / `cursor` / `cline` / `opencode` / `droid` / `openclaw` | same ID |
+
+Legacy IDs still accepted for compatibility: `copilot`, `kimi-coding`, `qwen`.
+
+---
+
+## Step 1 — Get an OmniRoute API Key
+
+1. Open the OmniRoute dashboard → **API Manager** (`/dashboard/api-manager`)
+2. Click **Create API Key**
+3. Give it a name (e.g. `cli-tools`) and select all permissions
+4. Copy the key — you'll need it for every CLI below
+
+> Your key looks like: `sk-xxxxxxxxxxxxxxxx-xxxxxxxxx`
+
+---
+
+## Step 2 — Install CLI Tools
+
+All npm-based tools require Node.js 18+:
+
+```bash
+# Claude Code (Anthropic)
+npm install -g @anthropic-ai/claude-code
+
+# OpenAI Codex
+npm install -g @openai/codex
+
+# OpenCode
+npm install -g opencode-ai
+
+# Cline
+npm install -g cline
+
+# KiloCode
+npm install -g kilocode
+
+# Kiro CLI (Amazon — requires curl + unzip)
+apt-get install -y unzip # on Debian/Ubuntu
+curl -fsSL https://cli.kiro.dev/install | bash
+export PATH="$HOME/.local/bin:$PATH" # add to ~/.bashrc
+```
+
+**Verify:**
+
+```bash
+claude --version # 2.x.x
+codex --version # 0.x.x
+opencode --version # x.x.x
+cline --version # 2.x.x
+kilocode --version # x.x.x (or: kilo --version)
+kiro-cli --version # 1.x.x
+```
+
+---
+
+## Step 3 — Set Global Environment Variables
+
+Add to `~/.bashrc` (or `~/.zshrc`), then run `source ~/.bashrc`:
+
+```bash
+# OmniRoute Universal Endpoint
+export OPENAI_BASE_URL="http://localhost:20128/v1"
+export OPENAI_API_KEY="sk-your-omniroute-key"
+export ANTHROPIC_BASE_URL="http://localhost:20128/v1"
+export ANTHROPIC_API_KEY="sk-your-omniroute-key"
+export GEMINI_BASE_URL="http://localhost:20128/v1"
+export GEMINI_API_KEY="sk-your-omniroute-key"
+```
+
+> For a **remote server** replace `localhost:20128` with the server IP or domain,
+> e.g. `http://192.168.0.15:20128`.
+
+---
+
+## Step 4 — Configure Each Tool
+
+### Claude Code
+
+```bash
+# Via CLI:
+claude config set --global api-base-url http://localhost:20128/v1
+
+# Or create ~/.claude/settings.json:
+mkdir -p ~/.claude && cat > ~/.claude/settings.json << EOF
+{
+ "apiBaseUrl": "http://localhost:20128/v1",
+ "apiKey": "sk-your-omniroute-key"
+}
+EOF
+```
+
+**Test:** `claude "say hello"`
+
+---
+
+### OpenAI Codex
+
+```bash
+mkdir -p ~/.codex && cat > ~/.codex/config.yaml << EOF
+model: auto
+apiKey: sk-your-omniroute-key
+apiBaseUrl: http://localhost:20128/v1
+EOF
+```
+
+**Test:** `codex "what is 2+2?"`
+
+---
+
+### OpenCode
+
+```bash
+mkdir -p ~/.config/opencode && cat > ~/.config/opencode/config.toml << EOF
+[provider.openai]
+base_url = "http://localhost:20128/v1"
+api_key = "sk-your-omniroute-key"
+EOF
+```
+
+**Test:** `opencode`
+
+---
+
+### Cline (CLI or VS Code)
+
+**CLI mode:**
+
+```bash
+mkdir -p ~/.cline/data && cat > ~/.cline/data/globalState.json << EOF
+{
+ "apiProvider": "openai",
+ "openAiBaseUrl": "http://localhost:20128/v1",
+ "openAiApiKey": "sk-your-omniroute-key"
+}
+EOF
+```
+
+**VS Code mode:**
+Cline extension settings → API Provider: `OpenAI Compatible` → Base URL: `http://localhost:20128/v1`
+
+Or use the OmniRoute dashboard → **CLI Tools → Cline → Apply Config**.
+
+---
+
+### KiloCode (CLI or VS Code)
+
+**CLI mode:**
+
+```bash
+kilocode --api-base http://localhost:20128/v1 --api-key sk-your-omniroute-key
+```
+
+**VS Code settings:**
+
+```json
+{
+ "kilo-code.openAiBaseUrl": "http://localhost:20128/v1",
+ "kilo-code.apiKey": "sk-your-omniroute-key"
+}
+```
+
+Or use the OmniRoute dashboard → **CLI Tools → KiloCode → Apply Config**.
+
+---
+
+### Continue (VS Code Extension)
+
+Edit `~/.continue/config.yaml`:
+
+```yaml
+models:
+ - name: OmniRoute
+ provider: openai
+ model: auto
+ apiBase: http://localhost:20128/v1
+ apiKey: sk-your-omniroute-key
+ default: true
+```
+
+Restart VS Code after editing.
+
+---
+
+### Kiro CLI (Amazon)
+
+```bash
+# Login to your AWS/Kiro account:
+kiro-cli login
+
+# The CLI uses its own auth — OmniRoute is not needed as backend for Kiro CLI itself.
+# Use kiro-cli alongside OmniRoute for other tools.
+kiro-cli status
+```
+
+---
+
+### Cursor (Desktop App)
+
+> **Note:** Cursor routes requests through its cloud. For OmniRoute integration,
+> enable **Cloud Endpoint** in OmniRoute Settings and use your public domain URL.
+
+Via GUI: **Settings → Models → OpenAI API Key**
+
+- Base URL: `https://your-domain.com/v1`
+- API Key: your OmniRoute key
+
+---
+
+## Dashboard Auto-Configuration
+
+The OmniRoute dashboard automates configuration for most tools:
+
+1. Go to `http://localhost:20128/dashboard/cli-tools`
+2. Expand any tool card
+3. Select your API key from the dropdown
+4. Click **Apply Config** (if tool is detected as installed)
+5. Or copy the generated config snippet manually
+
+---
+
+## Built-in Agents: Droid & OpenClaw
+
+**Droid** and **OpenClaw** are AI agents built directly into OmniRoute — no installation needed.
+They run as internal routes and use OmniRoute's model routing automatically.
+
+- Access: `http://localhost:20128/dashboard/agents`
+- Configure: same combos and providers as all other tools
+- No API key or CLI install required
+
+---
+
+## Available API Endpoints
+
+| Endpoint | Description | Use For |
+| -------------------------- | ----------------------------- | --------------------------- |
+| `/v1/chat/completions` | Standard chat (all providers) | All modern tools |
+| `/v1/responses` | Responses API (OpenAI format) | Codex, agentic workflows |
+| `/v1/completions` | Legacy text completions | Older tools using `prompt:` |
+| `/v1/embeddings` | Text embeddings | RAG, search |
+| `/v1/images/generations` | Image generation | DALL-E, Flux, etc. |
+| `/v1/audio/speech` | Text-to-speech | ElevenLabs, OpenAI TTS |
+| `/v1/audio/transcriptions` | Speech-to-text | Deepgram, AssemblyAI |
+
+---
+
+## समस्या निवारण
+
+| Error | Cause | Fix |
+| ------------------------- | ----------------------- | ------------------------------------------ |
+| `Connection refused` | OmniRoute not running | `pm2 start omniroute` |
+| `401 Unauthorized` | Wrong API key | Check in `/dashboard/api-manager` |
+| `No combo configured` | No active routing combo | Set up in `/dashboard/combos` |
+| `invalid model` | Model not in catalog | Use `auto` or check `/dashboard/providers` |
+| CLI shows "not installed" | Binary not in PATH | Check `which ` |
+| `kiro-cli: not found` | Not in PATH | `export PATH="$HOME/.local/bin:$PATH"` |
+
+---
+
+## Quick Setup Script (One Command)
+
+```bash
+# Install all CLIs and configure for OmniRoute (replace with your key and server URL)
+OMNIROUTE_URL="http://localhost:20128/v1"
+OMNIROUTE_KEY="sk-your-omniroute-key"
+
+npm install -g @anthropic-ai/claude-code @openai/codex opencode-ai cline kilocode
+
+# Kiro CLI
+apt-get install -y unzip 2>/dev/null; curl -fsSL https://cli.kiro.dev/install | bash
+
+# Write configs
+mkdir -p ~/.claude ~/.codex ~/.config/opencode ~/.continue
+
+cat > ~/.claude/settings.json <<< "{\"apiBaseUrl\":\"$OMNIROUTE_URL\",\"apiKey\":\"$OMNIROUTE_KEY\"}"
+cat > ~/.codex/config.yaml <<< "model: auto\napiKey: $OMNIROUTE_KEY\napiBaseUrl: $OMNIROUTE_URL"
+cat >> ~/.bashrc << EOF
+export OPENAI_BASE_URL="$OMNIROUTE_URL"
+export OPENAI_API_KEY="$OMNIROUTE_KEY"
+export ANTHROPIC_BASE_URL="$OMNIROUTE_URL"
+export ANTHROPIC_API_KEY="$OMNIROUTE_KEY"
+EOF
+
+source ~/.bashrc
+echo "✅ All CLIs installed and configured for OmniRoute"
+```
diff --git a/docs/i18n/in/docs/CODEBASE_DOCUMENTATION.md b/docs/i18n/in/docs/CODEBASE_DOCUMENTATION.md
new file mode 100644
index 0000000000..56ae66a8fb
--- /dev/null
+++ b/docs/i18n/in/docs/CODEBASE_DOCUMENTATION.md
@@ -0,0 +1,591 @@
+# omniroute — Codebase Documentation (हिन्दी)
+
+🌐 **Languages:** 🇺🇸 [English](../../../../docs/CODEBASE_DOCUMENTATION.md) · 🇪🇸 [es](../../es/docs/CODEBASE_DOCUMENTATION.md) · 🇫🇷 [fr](../../fr/docs/CODEBASE_DOCUMENTATION.md) · 🇩🇪 [de](../../de/docs/CODEBASE_DOCUMENTATION.md) · 🇮🇹 [it](../../it/docs/CODEBASE_DOCUMENTATION.md) · 🇷🇺 [ru](../../ru/docs/CODEBASE_DOCUMENTATION.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/CODEBASE_DOCUMENTATION.md) · 🇯🇵 [ja](../../ja/docs/CODEBASE_DOCUMENTATION.md) · 🇰🇷 [ko](../../ko/docs/CODEBASE_DOCUMENTATION.md) · 🇸🇦 [ar](../../ar/docs/CODEBASE_DOCUMENTATION.md) · 🇮🇳 [in](../../in/docs/CODEBASE_DOCUMENTATION.md) · 🇹🇭 [th](../../th/docs/CODEBASE_DOCUMENTATION.md) · 🇻🇳 [vi](../../vi/docs/CODEBASE_DOCUMENTATION.md) · 🇮🇩 [id](../../id/docs/CODEBASE_DOCUMENTATION.md) · 🇲🇾 [ms](../../ms/docs/CODEBASE_DOCUMENTATION.md) · 🇳🇱 [nl](../../nl/docs/CODEBASE_DOCUMENTATION.md) · 🇵🇱 [pl](../../pl/docs/CODEBASE_DOCUMENTATION.md) · 🇸🇪 [sv](../../sv/docs/CODEBASE_DOCUMENTATION.md) · 🇳🇴 [no](../../no/docs/CODEBASE_DOCUMENTATION.md) · 🇩🇰 [da](../../da/docs/CODEBASE_DOCUMENTATION.md) · 🇫🇮 [fi](../../fi/docs/CODEBASE_DOCUMENTATION.md) · 🇵🇹 [pt](../../pt/docs/CODEBASE_DOCUMENTATION.md) · 🇷🇴 [ro](../../ro/docs/CODEBASE_DOCUMENTATION.md) · 🇭🇺 [hu](../../hu/docs/CODEBASE_DOCUMENTATION.md) · 🇧🇬 [bg](../../bg/docs/CODEBASE_DOCUMENTATION.md) · 🇸🇰 [sk](../../sk/docs/CODEBASE_DOCUMENTATION.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/CODEBASE_DOCUMENTATION.md) · 🇮🇱 [he](../../he/docs/CODEBASE_DOCUMENTATION.md) · 🇵🇭 [phi](../../phi/docs/CODEBASE_DOCUMENTATION.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/CODEBASE_DOCUMENTATION.md) · 🇨🇿 [cs](../../cs/docs/CODEBASE_DOCUMENTATION.md)
+
+---
+
+> A comprehensive, beginner-friendly guide to the **omniroute** multi-provider AI proxy router.
+
+---
+
+## 1. What Is omniroute?
+
+omniroute is a **proxy router** that sits between AI clients (Claude CLI, Codex, Cursor IDE, etc.) and AI providers (Anthropic, Google, OpenAI, AWS, GitHub, etc.). It solves one big problem:
+
+> **Different AI clients speak different "languages" (API formats), and different AI providers expect different "languages" too.** omniroute translates between them automatically.
+
+Think of it like a universal translator at the United Nations — any delegate can speak any language, and the translator converts it for any other delegate.
+
+---
+
+## 2. Architecture Overview
+
+```mermaid
+graph LR
+ subgraph Clients
+ A[Claude CLI]
+ B[Codex]
+ C[Cursor IDE]
+ D[OpenAI-compatible]
+ end
+
+ subgraph omniroute
+ E[Handler Layer]
+ F[Translator Layer]
+ G[Executor Layer]
+ H[Services Layer]
+ end
+
+ subgraph Providers
+ I[Anthropic Claude]
+ J[Google Gemini]
+ K[OpenAI / Codex]
+ L[GitHub Copilot]
+ M[AWS Kiro]
+ N[Antigravity]
+ O[Cursor API]
+ end
+
+ A --> E
+ B --> E
+ C --> E
+ D --> E
+ E --> F
+ F --> G
+ G --> I
+ G --> J
+ G --> K
+ G --> L
+ G --> M
+ G --> N
+ G --> O
+ H -.-> E
+ H -.-> G
+```
+
+### Core Principle: Hub-and-Spoke Translation
+
+All format translation passes through **OpenAI format as the hub**:
+
+```
+Client Format → [OpenAI Hub] → Provider Format (request)
+Provider Format → [OpenAI Hub] → Client Format (response)
+```
+
+This means you only need **N translators** (one per format) instead of **N²** (every pair).
+
+---
+
+## 3. Project Structure
+
+```
+omniroute/
+├── open-sse/ ← Core proxy library (portable, framework-agnostic)
+│ ├── index.js ← Main entry point, exports everything
+│ ├── config/ ← Configuration & constants
+│ ├── executors/ ← Provider-specific request execution
+│ ├── handlers/ ← Request handling orchestration
+│ ├── services/ ← Business logic (auth, models, fallback, usage)
+│ ├── translator/ ← Format translation engine
+│ │ ├── request/ ← Request translators (8 files)
+│ │ ├── response/ ← Response translators (7 files)
+│ │ └── helpers/ ← Shared translation utilities (6 files)
+│ └── utils/ ← Utility functions
+├── src/ ← Application layer (Express/Worker runtime)
+│ ├── app/ ← Web UI, API routes, middleware
+│ ├── lib/ ← Database, auth, and shared library code
+│ ├── mitm/ ← Man-in-the-middle proxy utilities
+│ ├── models/ ← Database models
+│ ├── shared/ ← Shared utilities (wrappers around open-sse)
+│ ├── sse/ ← SSE endpoint handlers
+│ └── store/ ← State management
+├── data/ ← Runtime data (credentials, logs)
+│ └── provider-credentials.json (external credentials override, gitignored)
+└── tester/ ← Test utilities
+```
+
+---
+
+## 4. Module-by-Module Breakdown
+
+### 4.1 Config (`open-sse/config/`)
+
+The **single source of truth** for all provider configuration.
+
+| File | Purpose |
+| ----------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| `constants.ts` | `PROVIDERS` object with base URLs, OAuth credentials (defaults), headers, and default system prompts for every provider. Also defines `HTTP_STATUS`, `ERROR_TYPES`, `COOLDOWN_MS`, `BACKOFF_CONFIG`, and `SKIP_PATTERNS`. |
+| `credentialLoader.ts` | Loads external credentials from `data/provider-credentials.json` and merges them over the hardcoded defaults in `PROVIDERS`. Keeps secrets out of source control while maintaining backwards compatibility. |
+| `providerModels.ts` | Central model registry: maps provider aliases → model IDs. Functions like `getModels()`, `getProviderByAlias()`. |
+| `codexInstructions.ts` | System instructions injected into Codex requests (editing constraints, sandbox rules, approval policies). |
+| `defaultThinkingSignature.ts` | Default "thinking" signatures for Claude and Gemini models. |
+| `ollamaModels.ts` | Schema definition for local Ollama models (name, size, family, quantization). |
+
+#### Credential Loading Flow
+
+```mermaid
+flowchart TD
+ A["App starts"] --> B["constants.ts defines PROVIDERS\nwith hardcoded defaults"]
+ B --> C{"data/provider-credentials.json\nexists?"}
+ C -->|Yes| D["credentialLoader reads JSON"]
+ C -->|No| E["Use hardcoded defaults"]
+ D --> F{"For each provider in JSON"}
+ F --> G{"Provider exists\nin PROVIDERS?"}
+ G -->|No| H["Log warning, skip"]
+ G -->|Yes| I{"Value is object?"}
+ I -->|No| J["Log warning, skip"]
+ I -->|Yes| K["Merge clientId, clientSecret,\ntokenUrl, authUrl, refreshUrl"]
+ K --> F
+ H --> F
+ J --> F
+ F -->|Done| L["PROVIDERS ready with\nmerged credentials"]
+ E --> L
+```
+
+---
+
+### 4.2 Executors (`open-sse/executors/`)
+
+Executors encapsulate **provider-specific logic** using the **Strategy Pattern**. Each executor overrides base methods as needed.
+
+```mermaid
+classDiagram
+ class BaseExecutor {
+ +buildUrl(model, stream, options)
+ +buildHeaders(credentials, stream, body)
+ +transformRequest(body, model, stream, credentials)
+ +execute(url, options)
+ +shouldRetry(status, error)
+ +refreshCredentials(credentials, log)
+ }
+
+ class DefaultExecutor {
+ +refreshCredentials()
+ }
+
+ class AntigravityExecutor {
+ +buildUrl()
+ +buildHeaders()
+ +transformRequest()
+ +shouldRetry()
+ +refreshCredentials()
+ }
+
+ class CursorExecutor {
+ +buildUrl()
+ +buildHeaders()
+ +transformRequest()
+ +parseResponse()
+ +generateChecksum()
+ }
+
+ class KiroExecutor {
+ +buildUrl()
+ +buildHeaders()
+ +transformRequest()
+ +parseEventStream()
+ +refreshCredentials()
+ }
+
+ BaseExecutor <|-- DefaultExecutor
+ BaseExecutor <|-- AntigravityExecutor
+ BaseExecutor <|-- CursorExecutor
+ BaseExecutor <|-- KiroExecutor
+ BaseExecutor <|-- CodexExecutor
+ BaseExecutor <|-- GeminiCLIExecutor
+ BaseExecutor <|-- GithubExecutor
+```
+
+| Executor | Provider | Key Specializations |
+| ---------------- | ------------------------------------------ | ------------------------------------------------------------------------------------------------------------------- |
+| `base.ts` | — | Abstract base: URL building, headers, retry logic, credential refresh |
+| `default.ts` | Claude, Gemini, OpenAI, GLM, Kimi, MiniMax | Generic OAuth token refresh for standard providers |
+| `antigravity.ts` | Google Cloud Code | Project/session ID generation, multi-URL fallback, custom retry parsing from error messages ("reset after 2h7m23s") |
+| `cursor.ts` | Cursor IDE | **Most complex**: SHA-256 checksum auth, Protobuf request encoding, binary EventStream → SSE response parsing |
+| `codex.ts` | OpenAI Codex | Injects system instructions, manages thinking levels, removes unsupported parameters |
+| `gemini-cli.ts` | Google Gemini CLI | Custom URL building (`streamGenerateContent`), Google OAuth token refresh |
+| `github.ts` | GitHub Copilot | Dual token system (GitHub OAuth + Copilot token), VSCode header mimicking |
+| `kiro.ts` | AWS CodeWhisperer | AWS EventStream binary parsing, AMZN event frames, token estimation |
+| `index.ts` | — | Factory: maps provider name → executor class, with default fallback |
+
+---
+
+### 4.3 Handlers (`open-sse/handlers/`)
+
+The **orchestration layer** — coordinates translation, execution, streaming, and error handling.
+
+| File | Purpose |
+| --------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| `chatCore.ts` | **Central orchestrator** (~600 lines). Handles the complete request lifecycle: format detection → translation → executor dispatch → streaming/non-streaming response → token refresh → error handling → usage logging. |
+| `responsesHandler.ts` | Adapter for OpenAI's Responses API: converts Responses format → Chat Completions → sends to `chatCore` → converts SSE back to Responses format. |
+| `embeddings.ts` | Embedding generation handler: resolves embedding model → provider, dispatches to provider API, returns OpenAI-compatible embedding response. Supports 6+ providers. |
+| `imageGeneration.ts` | Image generation handler: resolves image model → provider, supports OpenAI-compatible, Gemini-image (Antigravity), and fallback (Nebius) modes. Returns base64 or URL images. |
+
+#### Request Lifecycle (chatCore.ts)
+
+```mermaid
+sequenceDiagram
+ participant Client
+ participant chatCore
+ participant Translator
+ participant Executor
+ participant Provider
+
+ Client->>chatCore: Request (any format)
+ chatCore->>chatCore: Detect source format
+ chatCore->>chatCore: Check bypass patterns
+ chatCore->>chatCore: Resolve model & provider
+ chatCore->>Translator: Translate request (source → OpenAI → target)
+ chatCore->>Executor: Get executor for provider
+ Executor->>Executor: Build URL, headers, transform request
+ Executor->>Executor: Refresh credentials if needed
+ Executor->>Provider: HTTP fetch (streaming or non-streaming)
+
+ alt Streaming
+ Provider-->>chatCore: SSE stream
+ chatCore->>chatCore: Pipe through SSE transform stream
+ Note over chatCore: Transform stream translates
each chunk: target → OpenAI → source
+ chatCore-->>Client: Translated SSE stream
+ else Non-streaming
+ Provider-->>chatCore: JSON response
+ chatCore->>Translator: Translate response
+ chatCore-->>Client: Translated JSON
+ end
+
+ alt Error (401, 429, 500...)
+ chatCore->>Executor: Retry with credential refresh
+ chatCore->>chatCore: Account fallback logic
+ end
+```
+
+---
+
+### 4.4 Services (`open-sse/services/`)
+
+Business logic that supports the handlers and executors.
+
+| File | Purpose |
+| -------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| `provider.ts` | **Format detection** (`detectFormat`): analyzes request body structure to identify Claude/OpenAI/Gemini/Antigravity/Responses formats (includes `max_tokens` heuristic for Claude). Also: URL building, header building, thinking config normalization. Supports `openai-compatible-*` and `anthropic-compatible-*` dynamic providers. |
+| `model.ts` | Model string parsing (`claude/model-name` → `{provider: "claude", model: "model-name"}`), alias resolution with collision detection, input sanitization (rejects path traversal/control chars), and model info resolution with async alias getter support. |
+| `accountFallback.ts` | Rate-limit handling: exponential backoff (1s → 2s → 4s → max 2min), account cooldown management, error classification (which errors trigger fallback vs. not). |
+| `tokenRefresh.ts` | OAuth token refresh for **every provider**: Google (Gemini, Antigravity), Claude, Codex, Qwen, Qoder, GitHub (OAuth + Copilot dual-token), Kiro (AWS SSO OIDC + Social Auth). Includes in-flight promise deduplication cache and retry with exponential backoff. |
+| `combo.ts` | **Combo models**: chains of fallback models. If model A fails with a fallback-eligible error, try model B, then C, etc. Returns actual upstream status codes. |
+| `usage.ts` | Fetches quota/usage data from provider APIs (GitHub Copilot quotas, Antigravity model quotas, Codex rate limits, Kiro usage breakdowns, Claude settings). |
+| `accountSelector.ts` | Smart account selection with scoring algorithm: considers priority, health status, round-robin position, and cooldown state to pick the optimal account for each request. |
+| `contextManager.ts` | Request context lifecycle management: creates and tracks per-request context objects with metadata (request ID, timestamps, provider info) for debugging and logging. |
+| `ipFilter.ts` | IP-based access control: supports allowlist and blocklist modes. Validates client IP against configured rules before processing API requests. |
+| `sessionManager.ts` | Session tracking with client fingerprinting: tracks active sessions using hashed client identifiers, monitors request counts, and provides session metrics. |
+| `signatureCache.ts` | Request signature-based deduplication cache: prevents duplicate requests by caching recent request signatures and returning cached responses for identical requests within a time window. |
+| `systemPrompt.ts` | Global system prompt injection: prepends or appends a configurable system prompt to all requests, with per-provider compatibility handling. |
+| `thinkingBudget.ts` | Reasoning token budget management: supports passthrough, auto (strip thinking config), custom (fixed budget), and adaptive (complexity-scaled) modes for controlling thinking/reasoning tokens. |
+| `wildcardRouter.ts` | Wildcard model pattern routing: resolves wildcard patterns (e.g., `*/claude-*`) to concrete provider/model pairs based on availability and priority. |
+
+#### Token Refresh Deduplication
+
+```mermaid
+sequenceDiagram
+ participant R1 as Request 1
+ participant R2 as Request 2
+ participant Cache as refreshPromiseCache
+ participant OAuth as OAuth Provider
+
+ R1->>Cache: getAccessToken("gemini", token)
+ Cache->>Cache: No in-flight promise
+ Cache->>OAuth: Start refresh
+ R2->>Cache: getAccessToken("gemini", token)
+ Cache->>Cache: Found in-flight promise
+ Cache-->>R2: Return existing promise
+ OAuth-->>Cache: New access token
+ Cache-->>R1: New access token
+ Cache-->>R2: Same access token (shared)
+ Cache->>Cache: Delete cache entry
+```
+
+#### Account Fallback State Machine
+
+```mermaid
+stateDiagram-v2
+ [*] --> Active
+ Active --> Error: Request fails (401/429/500)
+ Error --> Cooldown: Apply backoff
+ Cooldown --> Active: Cooldown expires
+ Active --> Active: Request succeeds (reset backoff)
+
+ state Error {
+ [*] --> ClassifyError
+ ClassifyError --> ShouldFallback: Rate limit / Auth / Transient
+ ClassifyError --> NoFallback: 400 Bad Request
+ }
+
+ state Cooldown {
+ [*] --> ExponentialBackoff
+ ExponentialBackoff: Level 0 = 1s
+ ExponentialBackoff: Level 1 = 2s
+ ExponentialBackoff: Level 2 = 4s
+ ExponentialBackoff: Max = 2min
+ }
+```
+
+#### Combo Model Chain
+
+```mermaid
+flowchart LR
+ A["Request with\ncombo model"] --> B["Model A"]
+ B -->|"2xx Success"| C["Return response"]
+ B -->|"429/401/500"| D{"Fallback\neligible?"}
+ D -->|Yes| E["Model B"]
+ D -->|No| F["Return error"]
+ E -->|"2xx Success"| C
+ E -->|"429/401/500"| G{"Fallback\neligible?"}
+ G -->|Yes| H["Model C"]
+ G -->|No| F
+ H -->|"2xx Success"| C
+ H -->|"Fail"| I["All failed →\nReturn last status"]
+```
+
+---
+
+### 4.5 Translator (`open-sse/translator/`)
+
+The **format translation engine** using a self-registering plugin system.
+
+#### आर्किटेक्चर
+
+```mermaid
+graph TD
+ subgraph "Request Translation"
+ A["Claude → OpenAI"]
+ B["Gemini → OpenAI"]
+ C["Antigravity → OpenAI"]
+ D["OpenAI Responses → OpenAI"]
+ E["OpenAI → Claude"]
+ F["OpenAI → Gemini"]
+ G["OpenAI → Kiro"]
+ H["OpenAI → Cursor"]
+ end
+
+ subgraph "Response Translation"
+ I["Claude → OpenAI"]
+ J["Gemini → OpenAI"]
+ K["Kiro → OpenAI"]
+ L["Cursor → OpenAI"]
+ M["OpenAI → Claude"]
+ N["OpenAI → Antigravity"]
+ O["OpenAI → Responses"]
+ end
+```
+
+| Directory | Files | Description |
+| ------------ | ------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| `request/` | 8 translators | Convert request bodies between formats. Each file self-registers via `register(from, to, fn)` on import. |
+| `response/` | 7 translators | Convert streaming response chunks between formats. Handles SSE event types, thinking blocks, tool calls. |
+| `helpers/` | 6 helpers | Shared utilities: `claudeHelper` (system prompt extraction, thinking config), `geminiHelper` (parts/contents mapping), `openaiHelper` (format filtering), `toolCallHelper` (ID generation, missing response injection), `maxTokensHelper`, `responsesApiHelper`. |
+| `index.ts` | — | Translation engine: `translateRequest()`, `translateResponse()`, state management, registry. |
+| `formats.ts` | — | Format constants: `OPENAI`, `CLAUDE`, `GEMINI`, `ANTIGRAVITY`, `KIRO`, `CURSOR`, `OPENAI_RESPONSES`. |
+
+#### Key Design: Self-Registering Plugins
+
+```javascript
+// Each translator file calls register() on import:
+import { register } from "../index.js";
+register("claude", "openai", translateClaudeToOpenAI);
+
+// The index.js imports all translator files, triggering registration:
+import "./request/claude-to-openai.js"; // ← self-registers
+```
+
+---
+
+### 4.6 Utils (`open-sse/utils/`)
+
+| File | Purpose |
+| ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
+| `error.ts` | Error response building (OpenAI-compatible format), upstream error parsing, Antigravity retry-time extraction from error messages, SSE error streaming. |
+| `stream.ts` | **SSE Transform Stream** — the core streaming pipeline. Two modes: `TRANSLATE` (full format translation) and `PASSTHROUGH` (normalize + extract usage). Handles chunk buffering, usage estimation, content length tracking. Per-stream encoder/decoder instances avoid shared state. |
+| `streamHelpers.ts` | Low-level SSE utilities: `parseSSELine` (whitespace-tolerant), `hasValuableContent` (filters empty chunks for OpenAI/Claude/Gemini), `fixInvalidId`, `formatSSE` (format-aware SSE serialization with `perf_metrics` cleanup). |
+| `usageTracking.ts` | Token usage extraction from any format (Claude/OpenAI/Gemini/Responses), estimation with separate tool/message char-per-token ratios, buffer addition (2000 tokens safety margin), format-specific field filtering, console logging with ANSI colors. |
+| `requestLogger.ts` | File-based request logging (opt-in via `ENABLE_REQUEST_LOGS=true`). Creates session folders with numbered files: `1_req_client.json` → `7_res_client.txt`. All I/O is async (fire-and-forget). Masks sensitive headers. |
+| `bypassHandler.ts` | Intercepts specific patterns from Claude CLI (title extraction, warmup, count) and returns fake responses without calling any provider. Supports both streaming and non-streaming. Intentionally limited to Claude CLI scope. |
+| `networkProxy.ts` | Resolves outbound proxy URL for a given provider with precedence: provider-specific config → global config → environment variables (`HTTPS_PROXY`/`HTTP_PROXY`/`ALL_PROXY`). Supports `NO_PROXY` exclusions. Caches config for 30s. |
+
+#### SSE Streaming Pipeline
+
+```mermaid
+flowchart TD
+ A["Provider SSE stream"] --> B["TextDecoder\n(per-stream instance)"]
+ B --> C["Buffer lines\n(split on newline)"]
+ C --> D["parseSSELine()\n(trim whitespace, parse JSON)"]
+ D --> E{"Mode?"}
+ E -->|TRANSLATE| F["translateResponse()\ntarget → OpenAI → source"]
+ E -->|PASSTHROUGH| G["fixInvalidId()\nnormalize chunk"]
+ F --> H["hasValuableContent()\nfilter empty chunks"]
+ G --> H
+ H -->|"Has content"| I["extractUsage()\ntrack token counts"]
+ H -->|"Empty"| J["Skip chunk"]
+ I --> K["formatSSE()\nserialize + clean perf_metrics"]
+ K --> L["TextEncoder\n(per-stream instance)"]
+ L --> M["Enqueue to\nclient stream"]
+
+ style A fill:#f9f,stroke:#333
+ style M fill:#9f9,stroke:#333
+```
+
+#### Request Logger Session Structure
+
+```
+logs/
+└── claude_gemini_claude-sonnet_20260208_143045/
+ ├── 1_req_client.json ← Raw client request
+ ├── 2_req_source.json ← After initial conversion
+ ├── 3_req_openai.json ← OpenAI intermediate format
+ ├── 4_req_target.json ← Final target format
+ ├── 5_res_provider.txt ← Provider SSE chunks (streaming)
+ ├── 5_res_provider.json ← Provider response (non-streaming)
+ ├── 6_res_openai.txt ← OpenAI intermediate chunks
+ ├── 7_res_client.txt ← Client-facing SSE chunks
+ └── 6_error.json ← Error details (if any)
+```
+
+---
+
+### 4.7 Application Layer (`src/`)
+
+| Directory | Purpose |
+| ------------- | ---------------------------------------------------------------------- |
+| `src/app/` | Web UI, API routes, Express middleware, OAuth callback handlers |
+| `src/lib/` | Database access (`localDb.ts`, `usageDb.ts`), authentication, shared |
+| `src/mitm/` | Man-in-the-middle proxy utilities for intercepting provider traffic |
+| `src/models/` | Database model definitions |
+| `src/shared/` | Wrappers around open-sse functions (provider, stream, error, etc.) |
+| `src/sse/` | SSE endpoint handlers that wire the open-sse library to Express routes |
+| `src/store/` | Application state management |
+
+#### Notable API Routes
+
+| Route | Methods | Purpose |
+| --------------------------------------------- | --------------- | ------------------------------------------------------------------------------------- |
+| `/api/provider-models` | GET/POST/DELETE | CRUD for custom models per provider |
+| `/api/models/catalog` | GET | Aggregated catalog of all models (chat, embedding, image, custom) grouped by provider |
+| `/api/settings/proxy` | GET/PUT/DELETE | Hierarchical outbound proxy configuration (`global/providers/combos/keys`) |
+| `/api/settings/proxy/test` | POST | Validates proxy connectivity and returns public IP/latency |
+| `/v1/providers/[provider]/chat/completions` | POST | Dedicated per-provider chat completions with model validation |
+| `/v1/providers/[provider]/embeddings` | POST | Dedicated per-provider embeddings with model validation |
+| `/v1/providers/[provider]/images/generations` | POST | Dedicated per-provider image generation with model validation |
+| `/api/settings/ip-filter` | GET/PUT | IP allowlist/blocklist management |
+| `/api/settings/thinking-budget` | GET/PUT | Reasoning token budget configuration (passthrough/auto/custom/adaptive) |
+| `/api/settings/system-prompt` | GET/PUT | Global system prompt injection for all requests |
+| `/api/sessions` | GET | Active session tracking and metrics |
+| `/api/rate-limits` | GET | Per-account rate limit status |
+
+---
+
+## 5. Key Design Patterns
+
+### 5.1 Hub-and-Spoke Translation
+
+All formats translate through **OpenAI format as the hub**. Adding a new provider only requires writing **one pair** of translators (to/from OpenAI), not N pairs.
+
+### 5.2 Executor Strategy Pattern
+
+Each provider has a dedicated executor class inheriting from `BaseExecutor`. The factory in `executors/index.ts` selects the right one at runtime.
+
+### 5.3 Self-Registering Plugin System
+
+Translator modules register themselves on import via `register()`. Adding a new translator is just creating a file and importing it.
+
+### 5.4 Account Fallback with Exponential Backoff
+
+When a provider returns 429/401/500, the system can switch to the next account, applying exponential cooldowns (1s → 2s → 4s → max 2min).
+
+### 5.5 Combo Model Chains
+
+A "combo" groups multiple `provider/model` strings. If the first fails, fallback to the next automatically.
+
+### 5.6 Stateful Streaming Translation
+
+Response translation maintains state across SSE chunks (thinking block tracking, tool call accumulation, content block indexing) via the `initState()` mechanism.
+
+### 5.7 Usage Safety Buffer
+
+A 2000-token buffer is added to reported usage to prevent clients from hitting context window limits due to overhead from system prompts and format translation.
+
+---
+
+## 6. Supported Formats
+
+| Format | Direction | Identifier |
+| ----------------------- | --------------- | ------------------ |
+| OpenAI Chat Completions | source + target | `openai` |
+| OpenAI Responses API | source + target | `openai-responses` |
+| Anthropic Claude | source + target | `claude` |
+| Google Gemini | source + target | `gemini` |
+| Google Gemini CLI | target only | `gemini-cli` |
+| Antigravity | source + target | `antigravity` |
+| AWS Kiro | target only | `kiro` |
+| Cursor | target only | `cursor` |
+
+---
+
+## 7. Supported Providers
+
+| Provider | Auth Method | Executor | Key Notes |
+| ------------------------ | ---------------------- | ----------- | --------------------------------------------- |
+| Anthropic Claude | API key or OAuth | Default | Uses `x-api-key` header |
+| Google Gemini | API key or OAuth | Default | Uses `x-goog-api-key` header |
+| Google Gemini CLI | OAuth | GeminiCLI | Uses `streamGenerateContent` endpoint |
+| Antigravity | OAuth | Antigravity | Multi-URL fallback, custom retry parsing |
+| OpenAI | API key | Default | Standard Bearer auth |
+| Codex | OAuth | Codex | Injects system instructions, manages thinking |
+| GitHub Copilot | OAuth + Copilot token | Github | Dual token, VSCode header mimicking |
+| Kiro (AWS) | AWS SSO OIDC or Social | Kiro | Binary EventStream parsing |
+| Cursor IDE | Checksum auth | Cursor | Protobuf encoding, SHA-256 checksums |
+| Qwen | OAuth | Default | Standard auth |
+| Qoder | OAuth (Basic + Bearer) | Default | Dual auth header |
+| OpenRouter | API key | Default | Standard Bearer auth |
+| GLM, Kimi, MiniMax | API key | Default | Claude-compatible, use `x-api-key` |
+| `openai-compatible-*` | API key | Default | Dynamic: any OpenAI-compatible endpoint |
+| `anthropic-compatible-*` | API key | Default | Dynamic: any Claude-compatible endpoint |
+
+---
+
+## 8. Data Flow Summary
+
+### Streaming Request
+
+```mermaid
+flowchart LR
+ A["Client"] --> B["detectFormat()"]
+ B --> C["translateRequest()\nsource → OpenAI → target"]
+ C --> D["Executor\nbuildUrl + buildHeaders"]
+ D --> E["fetch(providerURL)"]
+ E --> F["createSSEStream()\nTRANSLATE mode"]
+ F --> G["parseSSELine()"]
+ G --> H["translateResponse()\ntarget → OpenAI → source"]
+ H --> I["extractUsage()\n+ addBuffer"]
+ I --> J["formatSSE()"]
+ J --> K["Client receives\ntranslated SSE"]
+ K --> L["logUsage()\nsaveRequestUsage()"]
+```
+
+### Non-Streaming Request
+
+```mermaid
+flowchart LR
+ A["Client"] --> B["detectFormat()"]
+ B --> C["translateRequest()\nsource → OpenAI → target"]
+ C --> D["Executor.execute()"]
+ D --> E["translateResponse()\ntarget → OpenAI → source"]
+ E --> F["Return JSON\nresponse"]
+```
+
+### Bypass Flow (Claude CLI)
+
+```mermaid
+flowchart LR
+ A["Claude CLI request"] --> B{"Match bypass\npattern?"}
+ B -->|"Title/Warmup/Count"| C["Generate fake\nOpenAI response"]
+ B -->|"No match"| D["Normal flow"]
+ C --> E["Translate to\nsource format"]
+ E --> F["Return without\ncalling provider"]
+```
diff --git a/docs/i18n/in/docs/COVERAGE_PLAN.md b/docs/i18n/in/docs/COVERAGE_PLAN.md
new file mode 100644
index 0000000000..4484ddc962
--- /dev/null
+++ b/docs/i18n/in/docs/COVERAGE_PLAN.md
@@ -0,0 +1,170 @@
+# Test Coverage Plan (हिन्दी)
+
+🌐 **Languages:** 🇺🇸 [English](../../../../docs/COVERAGE_PLAN.md) · 🇪🇸 [es](../../es/docs/COVERAGE_PLAN.md) · 🇫🇷 [fr](../../fr/docs/COVERAGE_PLAN.md) · 🇩🇪 [de](../../de/docs/COVERAGE_PLAN.md) · 🇮🇹 [it](../../it/docs/COVERAGE_PLAN.md) · 🇷🇺 [ru](../../ru/docs/COVERAGE_PLAN.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/COVERAGE_PLAN.md) · 🇯🇵 [ja](../../ja/docs/COVERAGE_PLAN.md) · 🇰🇷 [ko](../../ko/docs/COVERAGE_PLAN.md) · 🇸🇦 [ar](../../ar/docs/COVERAGE_PLAN.md) · 🇮🇳 [in](../../in/docs/COVERAGE_PLAN.md) · 🇹🇭 [th](../../th/docs/COVERAGE_PLAN.md) · 🇻🇳 [vi](../../vi/docs/COVERAGE_PLAN.md) · 🇮🇩 [id](../../id/docs/COVERAGE_PLAN.md) · 🇲🇾 [ms](../../ms/docs/COVERAGE_PLAN.md) · 🇳🇱 [nl](../../nl/docs/COVERAGE_PLAN.md) · 🇵🇱 [pl](../../pl/docs/COVERAGE_PLAN.md) · 🇸🇪 [sv](../../sv/docs/COVERAGE_PLAN.md) · 🇳🇴 [no](../../no/docs/COVERAGE_PLAN.md) · 🇩🇰 [da](../../da/docs/COVERAGE_PLAN.md) · 🇫🇮 [fi](../../fi/docs/COVERAGE_PLAN.md) · 🇵🇹 [pt](../../pt/docs/COVERAGE_PLAN.md) · 🇷🇴 [ro](../../ro/docs/COVERAGE_PLAN.md) · 🇭🇺 [hu](../../hu/docs/COVERAGE_PLAN.md) · 🇧🇬 [bg](../../bg/docs/COVERAGE_PLAN.md) · 🇸🇰 [sk](../../sk/docs/COVERAGE_PLAN.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/COVERAGE_PLAN.md) · 🇮🇱 [he](../../he/docs/COVERAGE_PLAN.md) · 🇵🇭 [phi](../../phi/docs/COVERAGE_PLAN.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/COVERAGE_PLAN.md) · 🇨🇿 [cs](../../cs/docs/COVERAGE_PLAN.md)
+
+---
+
+Last updated: 2026-03-28
+
+## Baseline
+
+There are multiple coverage numbers depending on how the report is computed. For planning, only one of them is useful.
+
+| Metric | Scope | Statements / Lines | Branches | Functions | Notes |
+| -------------------- | ----------------------------------------------------- | -----------------: | -------: | --------: | --------------------------------------------------- |
+| Legacy | Old `npm run test:coverage` | 79.42% | 75.15% | 67.94% | Inflated: counts test files and excludes `open-sse` |
+| Diagnostic | Source-only, excluding tests and excluding `open-sse` | 68.16% | 63.55% | 64.06% | Useful only to isolate `src/**` |
+| Recommended baseline | Source-only, excluding tests and including `open-sse` | 56.95% | 66.05% | 57.80% | This is the project-wide baseline to improve |
+
+The recommended baseline is the number to optimize against.
+
+## Rules
+
+- Coverage targets apply to source files, not to `tests/**`.
+- `open-sse/**` is part of the product and must remain in scope.
+- New code should not reduce coverage in touched areas.
+- Prefer testing behavior and branch outcomes over implementation details.
+- Prefer temp SQLite databases and small fixtures over broad mocks for `src/lib/db/**`.
+
+## Current command set
+
+- `npm run test:coverage`
+ - Main source coverage gate for the unit test suite
+ - Generates `text-summary`, `html`, `json-summary`, and `lcov`
+- `npm run coverage:report`
+ - Detailed file-by-file report from the latest run
+- `npm run test:coverage:legacy`
+ - Historical comparison only
+
+## Milestones
+
+| Phase | Target | Focus |
+| ------- | ---------------------: | ------------------------------------------------- |
+| Phase 1 | 60% statements / lines | Quick wins and low-risk utility coverage |
+| Phase 2 | 65% statements / lines | DB and route foundations |
+| Phase 3 | 70% statements / lines | Provider validation and usage analytics |
+| Phase 4 | 75% statements / lines | `open-sse` translators and helpers |
+| Phase 5 | 80% statements / lines | `open-sse` handlers and executor branches |
+| Phase 6 | 85% statements / lines | Harder edge cases, branch debt, regression suites |
+| Phase 7 | 90% statements / lines | Final sweep, gap closure, strict ratchet |
+
+Branches and functions should ratchet upward with each phase, but the primary hard target is statements / lines.
+
+## Priority hotspots
+
+These files or areas offer the best return for the next phases:
+
+1. `open-sse/handlers`
+ - `chatCore.ts` at 7.57%
+ - Overall directory at 29.07%
+2. `open-sse/translator/request`
+ - Overall directory at 36.39%
+ - Many translators are still near single-digit coverage
+3. `open-sse/translator/response`
+ - Overall directory at 8.07%
+4. `open-sse/executors`
+ - Overall directory at 36.62%
+5. `src/lib/db`
+ - `models.ts` at 20.66%
+ - `registeredKeys.ts` at 34.46%
+ - `modelComboMappings.ts` at 36.25%
+ - `settings.ts` at 46.40%
+ - `webhooks.ts` at 33.33%
+6. `src/lib/usage`
+ - `usageHistory.ts` at 21.12%
+ - `usageStats.ts` at 9.56%
+ - `costCalculator.ts` at 30.00%
+7. `src/lib/providers`
+ - `validation.ts` at 41.16%
+8. Low-risk utility and API files for early gains
+ - `src/shared/utils/upstreamError.ts`
+ - `src/shared/utils/apiAuth.ts`
+ - `src/lib/api/errorResponse.ts`
+ - `src/app/api/settings/require-login/route.ts`
+ - `src/app/api/providers/[id]/models/route.ts`
+
+## Execution checklist
+
+### Phase 1: 56.95% -> 60%
+
+- [x] Fix coverage metric so it reflects source code instead of test files
+- [x] Keep a legacy coverage script for comparison
+- [x] Record the baseline and hotspots in-repo
+- [ ] Add focused tests for low-risk utilities:
+ - `src/shared/utils/upstreamError.ts`
+ - `src/shared/utils/fetchTimeout.ts`
+ - `src/lib/api/errorResponse.ts`
+ - `src/shared/utils/apiAuth.ts`
+ - `src/lib/display/names.ts`
+- [ ] Add route tests for:
+ - `src/app/api/settings/require-login/route.ts`
+ - `src/app/api/providers/[id]/models/route.ts`
+
+### Phase 2: 60% -> 65%
+
+- [ ] Add DB-backed tests for:
+ - `src/lib/db/modelComboMappings.ts`
+ - `src/lib/db/settings.ts`
+ - `src/lib/db/registeredKeys.ts`
+- [ ] Cover branch behavior in:
+ - `src/lib/providers/validation.ts`
+ - `src/app/api/v1/embeddings/route.ts`
+ - `src/app/api/v1/moderations/route.ts`
+
+### Phase 3: 65% -> 70%
+
+- [ ] Add usage analytics tests for:
+ - `src/lib/usage/usageHistory.ts`
+ - `src/lib/usage/usageStats.ts`
+ - `src/lib/usage/costCalculator.ts`
+- [ ] Expand route coverage for proxy management and settings branches
+
+### Phase 4: 70% -> 75%
+
+- [ ] Cover translator helpers and central translation paths:
+ - `open-sse/translator/index.ts`
+ - `open-sse/translator/helpers/*`
+ - `open-sse/translator/request/*`
+ - `open-sse/translator/response/*`
+
+### Phase 5: 75% -> 80%
+
+- [ ] Add handler-level tests for:
+ - `open-sse/handlers/chatCore.ts`
+ - `open-sse/handlers/responsesHandler.js`
+ - `open-sse/handlers/imageGeneration.js`
+ - `open-sse/handlers/embeddings.js`
+- [ ] Add executor branch coverage for provider-specific auth, retries, and endpoint overrides
+
+### Phase 6: 80% -> 85%
+
+- [ ] Merge more edge-case suites into the main coverage path
+- [ ] Increase function coverage for DB modules with weak constructor/helper coverage
+- [ ] Close branch gaps in `settings.ts`, `registeredKeys.ts`, `validation.ts`, and translator helpers
+
+### Phase 7: 85% -> 90%
+
+- [ ] Treat the remaining low-coverage files as blockers
+- [ ] Add regression tests for every uncovered production bug fixed during the push to 90%
+- [ ] Raise the coverage gate in CI only after the local baseline is stable for at least two consecutive runs
+
+## Ratchet policy
+
+Update `npm run test:coverage` thresholds only after the project actually exceeds the next milestone with a comfortable buffer.
+
+Recommended ratchet sequence:
+
+1. 55/60/55
+2. 60/62/58
+3. 65/64/62
+4. 70/66/66
+5. 75/70/72
+6. 80/75/78
+7. 85/80/84
+8. 90/85/88
+
+Order is `statements-lines / branches / functions`.
+
+## Known gap
+
+The current coverage command measures the main Node unit suite and includes source reached from it, including `open-sse`. It does not yet merge Vitest coverage into a single unified report. That merge is worth doing later, but it is not a blocker for starting the 60% -> 80% climb.
diff --git a/docs/i18n/in/docs/FEATURES.md b/docs/i18n/in/docs/FEATURES.md
index 0e00239bb6..f3c8dcdd2b 100644
--- a/docs/i18n/in/docs/FEATURES.md
+++ b/docs/i18n/in/docs/FEATURES.md
@@ -1,6 +1,6 @@
# OmniRoute — Dashboard Features Gallery (हिन्दी)
-🌐 **Languages:** 🇺🇸 [English](../../../../docs/FEATURES.md) · 🇪🇸 [es](../../es/docs/FEATURES.md) · 🇫🇷 [fr](../../fr/docs/FEATURES.md) · 🇩🇪 [de](../../de/docs/FEATURES.md) · 🇮🇹 [it](../../it/docs/FEATURES.md) · 🇷🇺 [ru](../../ru/docs/FEATURES.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/FEATURES.md) · 🇯🇵 [ja](../../ja/docs/FEATURES.md) · 🇰🇷 [ko](../../ko/docs/FEATURES.md) · 🇸🇦 [ar](../../ar/docs/FEATURES.md) · 🇮🇳 [in](../../in/docs/FEATURES.md) · 🇹🇭 [th](../../th/docs/FEATURES.md) · 🇻🇳 [vi](../../vi/docs/FEATURES.md) · 🇮🇩 [id](../../id/docs/FEATURES.md) · 🇲🇾 [ms](../../ms/docs/FEATURES.md) · 🇳🇱 [nl](../../nl/docs/FEATURES.md) · 🇵🇱 [pl](../../pl/docs/FEATURES.md) · 🇸🇪 [sv](../../sv/docs/FEATURES.md) · 🇳🇴 [no](../../no/docs/FEATURES.md) · 🇩🇰 [da](../../da/docs/FEATURES.md) · 🇫🇮 [fi](../../fi/docs/FEATURES.md) · 🇵🇹 [pt](../../pt/docs/FEATURES.md) · 🇷🇴 [ro](../../ro/docs/FEATURES.md) · 🇭🇺 [hu](../../hu/docs/FEATURES.md) · 🇧🇬 [bg](../../bg/docs/FEATURES.md) · 🇸🇰 [sk](../../sk/docs/FEATURES.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/FEATURES.md) · 🇮🇱 [he](../../he/docs/FEATURES.md) · 🇵🇭 [phi](../../phi/docs/FEATURES.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/FEATURES.md)
+🌐 **Languages:** 🇺🇸 [English](../../../../docs/FEATURES.md) · 🇪🇸 [es](../../es/docs/FEATURES.md) · 🇫🇷 [fr](../../fr/docs/FEATURES.md) · 🇩🇪 [de](../../de/docs/FEATURES.md) · 🇮🇹 [it](../../it/docs/FEATURES.md) · 🇷🇺 [ru](../../ru/docs/FEATURES.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/FEATURES.md) · 🇯🇵 [ja](../../ja/docs/FEATURES.md) · 🇰🇷 [ko](../../ko/docs/FEATURES.md) · 🇸🇦 [ar](../../ar/docs/FEATURES.md) · 🇮🇳 [in](../../in/docs/FEATURES.md) · 🇹🇭 [th](../../th/docs/FEATURES.md) · 🇻🇳 [vi](../../vi/docs/FEATURES.md) · 🇮🇩 [id](../../id/docs/FEATURES.md) · 🇲🇾 [ms](../../ms/docs/FEATURES.md) · 🇳🇱 [nl](../../nl/docs/FEATURES.md) · 🇵🇱 [pl](../../pl/docs/FEATURES.md) · 🇸🇪 [sv](../../sv/docs/FEATURES.md) · 🇳🇴 [no](../../no/docs/FEATURES.md) · 🇩🇰 [da](../../da/docs/FEATURES.md) · 🇫🇮 [fi](../../fi/docs/FEATURES.md) · 🇵🇹 [pt](../../pt/docs/FEATURES.md) · 🇷🇴 [ro](../../ro/docs/FEATURES.md) · 🇭🇺 [hu](../../hu/docs/FEATURES.md) · 🇧🇬 [bg](../../bg/docs/FEATURES.md) · 🇸🇰 [sk](../../sk/docs/FEATURES.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/FEATURES.md) · 🇮🇱 [he](../../he/docs/FEATURES.md) · 🇵🇭 [phi](../../phi/docs/FEATURES.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/FEATURES.md) · 🇨🇿 [cs](../../cs/docs/FEATURES.md)
---
@@ -10,7 +10,7 @@ Visual guide to every section of the OmniRoute dashboard.
## 🔌 Providers
-Manage AI provider connections: OAuth providers (Claude Code, Codex, Gemini CLI), API key providers (Groq, DeepSeek, OpenRouter), and free providers (iFlow, Qwen, Kiro). Kiro accounts include credit balance tracking — remaining credits, total allowance, and renewal date visible in Dashboard → Usage.
+Manage AI provider connections: OAuth providers (Claude Code, Codex, Gemini CLI), API key providers (Groq, DeepSeek, OpenRouter), and free providers (Qoder, Qwen, Kiro). Kiro accounts include credit balance tracking — remaining credits, total allowance, and renewal date visible in Dashboard → Usage.

diff --git a/docs/i18n/in/docs/MCP-SERVER.md b/docs/i18n/in/docs/MCP-SERVER.md
new file mode 100644
index 0000000000..8310a87704
--- /dev/null
+++ b/docs/i18n/in/docs/MCP-SERVER.md
@@ -0,0 +1,87 @@
+# OmniRoute MCP Server Documentation (हिन्दी)
+
+🌐 **Languages:** 🇺🇸 [English](../../../../docs/MCP-SERVER.md) · 🇪🇸 [es](../../es/docs/MCP-SERVER.md) · 🇫🇷 [fr](../../fr/docs/MCP-SERVER.md) · 🇩🇪 [de](../../de/docs/MCP-SERVER.md) · 🇮🇹 [it](../../it/docs/MCP-SERVER.md) · 🇷🇺 [ru](../../ru/docs/MCP-SERVER.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/MCP-SERVER.md) · 🇯🇵 [ja](../../ja/docs/MCP-SERVER.md) · 🇰🇷 [ko](../../ko/docs/MCP-SERVER.md) · 🇸🇦 [ar](../../ar/docs/MCP-SERVER.md) · 🇮🇳 [in](../../in/docs/MCP-SERVER.md) · 🇹🇭 [th](../../th/docs/MCP-SERVER.md) · 🇻🇳 [vi](../../vi/docs/MCP-SERVER.md) · 🇮🇩 [id](../../id/docs/MCP-SERVER.md) · 🇲🇾 [ms](../../ms/docs/MCP-SERVER.md) · 🇳🇱 [nl](../../nl/docs/MCP-SERVER.md) · 🇵🇱 [pl](../../pl/docs/MCP-SERVER.md) · 🇸🇪 [sv](../../sv/docs/MCP-SERVER.md) · 🇳🇴 [no](../../no/docs/MCP-SERVER.md) · 🇩🇰 [da](../../da/docs/MCP-SERVER.md) · 🇫🇮 [fi](../../fi/docs/MCP-SERVER.md) · 🇵🇹 [pt](../../pt/docs/MCP-SERVER.md) · 🇷🇴 [ro](../../ro/docs/MCP-SERVER.md) · 🇭🇺 [hu](../../hu/docs/MCP-SERVER.md) · 🇧🇬 [bg](../../bg/docs/MCP-SERVER.md) · 🇸🇰 [sk](../../sk/docs/MCP-SERVER.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/MCP-SERVER.md) · 🇮🇱 [he](../../he/docs/MCP-SERVER.md) · 🇵🇭 [phi](../../phi/docs/MCP-SERVER.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/MCP-SERVER.md) · 🇨🇿 [cs](../../cs/docs/MCP-SERVER.md)
+
+---
+
+> Model Context Protocol server with 16 intelligent tools
+
+## स्थापित करें
+
+OmniRoute MCP is built-in. Start it with:
+
+```bash
+omniroute --mcp
+```
+
+Or via the open-sse transport:
+
+```bash
+# HTTP streamable transport (port 20130)
+omniroute --dev # MCP auto-starts on /mcp endpoint
+```
+
+## IDE Configuration
+
+See [IDE Configs](integrations/ide-configs.md) for Antigravity, Cursor, Copilot, and Claude Desktop setup.
+
+---
+
+## Essential Tools (8)
+
+| Tool | Description |
+| :------------------------------ | :--------------------------------------- |
+| `omniroute_get_health` | Gateway health, circuit breakers, uptime |
+| `omniroute_list_combos` | All configured combos with models |
+| `omniroute_get_combo_metrics` | Performance metrics for a specific combo |
+| `omniroute_switch_combo` | Switch active combo by ID/name |
+| `omniroute_check_quota` | Quota status per provider or all |
+| `omniroute_route_request` | Send a chat completion through OmniRoute |
+| `omniroute_cost_report` | Cost analytics for a time period |
+| `omniroute_list_models_catalog` | Full model catalog with capabilities |
+
+## Advanced Tools (8)
+
+| Tool | Description |
+| :--------------------------------- | :---------------------------------------------------------- |
+| `omniroute_simulate_route` | Dry-run routing simulation with fallback tree |
+| `omniroute_set_budget_guard` | Session budget with degrade/block/alert actions |
+| `omniroute_set_resilience_profile` | Apply conservative/balanced/aggressive preset |
+| `omniroute_test_combo` | Live-test all models in a combo via a real upstream request |
+| `omniroute_get_provider_metrics` | Detailed metrics for one provider |
+| `omniroute_best_combo_for_task` | Task-fitness recommendation with alternatives |
+| `omniroute_explain_route` | Explain a past routing decision |
+| `omniroute_get_session_snapshot` | Full session state: costs, tokens, errors |
+
+## Authentication
+
+MCP tools are authenticated via API key scopes. Each tool requires specific scopes:
+
+| Scope | Tools |
+| :------------- | :----------------------------------------------- |
+| `read:health` | get_health, get_provider_metrics |
+| `read:combos` | list_combos, get_combo_metrics |
+| `write:combos` | switch_combo |
+| `read:quota` | check_quota |
+| `write:route` | route_request, simulate_route, test_combo |
+| `read:usage` | cost_report, get_session_snapshot, explain_route |
+| `write:config` | set_budget_guard, set_resilience_profile |
+| `read:models` | list_models_catalog, best_combo_for_task |
+
+## Audit Logging
+
+Every tool call is logged to `mcp_tool_audit` with:
+
+- Tool name, arguments, result
+- Duration (ms), success/failure
+- API key hash, timestamp
+
+## Files
+
+| File | Purpose |
+| :------------------------------------------- | :------------------------------------------ |
+| `open-sse/mcp-server/server.ts` | MCP server creation + 16 tool registrations |
+| `open-sse/mcp-server/transport.ts` | Stdio + HTTP transport |
+| `open-sse/mcp-server/auth.ts` | API key + scope validation |
+| `open-sse/mcp-server/audit.ts` | Tool call audit logging |
+| `open-sse/mcp-server/tools/advancedTools.ts` | 8 advanced tool handlers |
diff --git a/docs/i18n/in/docs/RELEASE_CHECKLIST.md b/docs/i18n/in/docs/RELEASE_CHECKLIST.md
new file mode 100644
index 0000000000..e55e6d7533
--- /dev/null
+++ b/docs/i18n/in/docs/RELEASE_CHECKLIST.md
@@ -0,0 +1,37 @@
+# Release Checklist (हिन्दी)
+
+🌐 **Languages:** 🇺🇸 [English](../../../../docs/RELEASE_CHECKLIST.md) · 🇪🇸 [es](../../es/docs/RELEASE_CHECKLIST.md) · 🇫🇷 [fr](../../fr/docs/RELEASE_CHECKLIST.md) · 🇩🇪 [de](../../de/docs/RELEASE_CHECKLIST.md) · 🇮🇹 [it](../../it/docs/RELEASE_CHECKLIST.md) · 🇷🇺 [ru](../../ru/docs/RELEASE_CHECKLIST.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/RELEASE_CHECKLIST.md) · 🇯🇵 [ja](../../ja/docs/RELEASE_CHECKLIST.md) · 🇰🇷 [ko](../../ko/docs/RELEASE_CHECKLIST.md) · 🇸🇦 [ar](../../ar/docs/RELEASE_CHECKLIST.md) · 🇮🇳 [in](../../in/docs/RELEASE_CHECKLIST.md) · 🇹🇭 [th](../../th/docs/RELEASE_CHECKLIST.md) · 🇻🇳 [vi](../../vi/docs/RELEASE_CHECKLIST.md) · 🇮🇩 [id](../../id/docs/RELEASE_CHECKLIST.md) · 🇲🇾 [ms](../../ms/docs/RELEASE_CHECKLIST.md) · 🇳🇱 [nl](../../nl/docs/RELEASE_CHECKLIST.md) · 🇵🇱 [pl](../../pl/docs/RELEASE_CHECKLIST.md) · 🇸🇪 [sv](../../sv/docs/RELEASE_CHECKLIST.md) · 🇳🇴 [no](../../no/docs/RELEASE_CHECKLIST.md) · 🇩🇰 [da](../../da/docs/RELEASE_CHECKLIST.md) · 🇫🇮 [fi](../../fi/docs/RELEASE_CHECKLIST.md) · 🇵🇹 [pt](../../pt/docs/RELEASE_CHECKLIST.md) · 🇷🇴 [ro](../../ro/docs/RELEASE_CHECKLIST.md) · 🇭🇺 [hu](../../hu/docs/RELEASE_CHECKLIST.md) · 🇧🇬 [bg](../../bg/docs/RELEASE_CHECKLIST.md) · 🇸🇰 [sk](../../sk/docs/RELEASE_CHECKLIST.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/RELEASE_CHECKLIST.md) · 🇮🇱 [he](../../he/docs/RELEASE_CHECKLIST.md) · 🇵🇭 [phi](../../phi/docs/RELEASE_CHECKLIST.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/RELEASE_CHECKLIST.md) · 🇨🇿 [cs](../../cs/docs/RELEASE_CHECKLIST.md)
+
+---
+
+Use this checklist before tagging or publishing a new OmniRoute release.
+
+## Version and Changelog
+
+1. Bump `package.json` version (`x.y.z`) in the release branch.
+2. Move release notes from `## [Unreleased]` in `CHANGELOG.md` to a dated section:
+ - `## [x.y.z] — YYYY-MM-DD`
+3. Keep `## [Unreleased]` as the first changelog section for upcoming work.
+4. Ensure the latest semver section in `CHANGELOG.md` equals `package.json` version.
+
+## API Docs
+
+1. Update `docs/openapi.yaml`:
+ - `info.version` must equal `package.json` version.
+2. Validate endpoint examples if API contracts changed.
+
+## Runtime Docs
+
+1. Review `docs/ARCHITECTURE.md` for storage/runtime drift.
+2. Review `docs/TROUBLESHOOTING.md` for env var and operational drift.
+3. Update localized docs if source docs changed significantly.
+
+## Automated Check
+
+Run the sync guard locally before opening PR:
+
+```bash
+npm run check:docs-sync
+```
+
+CI also runs this check in `.github/workflows/ci.yml` (lint job).
diff --git a/docs/i18n/in/docs/TROUBLESHOOTING.md b/docs/i18n/in/docs/TROUBLESHOOTING.md
new file mode 100644
index 0000000000..4c397b471f
--- /dev/null
+++ b/docs/i18n/in/docs/TROUBLESHOOTING.md
@@ -0,0 +1,256 @@
+# Troubleshooting (हिन्दी)
+
+🌐 **Languages:** 🇺🇸 [English](../../../../docs/TROUBLESHOOTING.md) · 🇪🇸 [es](../../es/docs/TROUBLESHOOTING.md) · 🇫🇷 [fr](../../fr/docs/TROUBLESHOOTING.md) · 🇩🇪 [de](../../de/docs/TROUBLESHOOTING.md) · 🇮🇹 [it](../../it/docs/TROUBLESHOOTING.md) · 🇷🇺 [ru](../../ru/docs/TROUBLESHOOTING.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/TROUBLESHOOTING.md) · 🇯🇵 [ja](../../ja/docs/TROUBLESHOOTING.md) · 🇰🇷 [ko](../../ko/docs/TROUBLESHOOTING.md) · 🇸🇦 [ar](../../ar/docs/TROUBLESHOOTING.md) · 🇮🇳 [in](../../in/docs/TROUBLESHOOTING.md) · 🇹🇭 [th](../../th/docs/TROUBLESHOOTING.md) · 🇻🇳 [vi](../../vi/docs/TROUBLESHOOTING.md) · 🇮🇩 [id](../../id/docs/TROUBLESHOOTING.md) · 🇲🇾 [ms](../../ms/docs/TROUBLESHOOTING.md) · 🇳🇱 [nl](../../nl/docs/TROUBLESHOOTING.md) · 🇵🇱 [pl](../../pl/docs/TROUBLESHOOTING.md) · 🇸🇪 [sv](../../sv/docs/TROUBLESHOOTING.md) · 🇳🇴 [no](../../no/docs/TROUBLESHOOTING.md) · 🇩🇰 [da](../../da/docs/TROUBLESHOOTING.md) · 🇫🇮 [fi](../../fi/docs/TROUBLESHOOTING.md) · 🇵🇹 [pt](../../pt/docs/TROUBLESHOOTING.md) · 🇷🇴 [ro](../../ro/docs/TROUBLESHOOTING.md) · 🇭🇺 [hu](../../hu/docs/TROUBLESHOOTING.md) · 🇧🇬 [bg](../../bg/docs/TROUBLESHOOTING.md) · 🇸🇰 [sk](../../sk/docs/TROUBLESHOOTING.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/TROUBLESHOOTING.md) · 🇮🇱 [he](../../he/docs/TROUBLESHOOTING.md) · 🇵🇭 [phi](../../phi/docs/TROUBLESHOOTING.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/TROUBLESHOOTING.md) · 🇨🇿 [cs](../../cs/docs/TROUBLESHOOTING.md)
+
+---
+
+Common problems and solutions for OmniRoute.
+
+---
+
+## Quick Fixes
+
+| Problem | Solution |
+| ----------------------------- | ------------------------------------------------------------------ |
+| First login not working | Set `INITIAL_PASSWORD` in `.env` (no hardcoded default) |
+| Dashboard opens on wrong port | Set `PORT=20128` and `NEXT_PUBLIC_BASE_URL=http://localhost:20128` |
+| No request logs under `logs/` | Set `ENABLE_REQUEST_LOGS=true` |
+| EACCES: permission denied | Set `DATA_DIR=/path/to/writable/dir` to override `~/.omniroute` |
+| Routing strategy not saving | Update to v1.4.11+ (Zod schema fix for settings persistence) |
+
+---
+
+## Provider Issues
+
+### "Language model did not provide messages"
+
+**Cause:** Provider quota exhausted.
+
+**Fix:**
+
+1. Check dashboard quota tracker
+2. Use a combo with fallback tiers
+3. Switch to cheaper/free tier
+
+### Rate Limiting
+
+**Cause:** Subscription quota exhausted.
+
+**Fix:**
+
+- Add fallback: `cc/claude-opus-4-6 → glm/glm-4.7 → if/kimi-k2-thinking`
+- Use GLM/MiniMax as cheap backup
+
+### OAuth Token Expired
+
+OmniRoute auto-refreshes tokens. If issues persist:
+
+1. Dashboard → Provider → Reconnect
+2. Delete and re-add the provider connection
+
+---
+
+## Cloud Issues
+
+### Cloud Sync Errors
+
+1. Verify `BASE_URL` points to your running instance (e.g., `http://localhost:20128`)
+2. Verify `CLOUD_URL` points to your cloud endpoint (e.g., `https://omniroute.dev`)
+3. Keep `NEXT_PUBLIC_*` values aligned with server-side values
+
+### Cloud `stream=false` Returns 500
+
+**Symptom:** `Unexpected token 'd'...` on cloud endpoint for non-streaming calls.
+
+**Cause:** Upstream returns SSE payload while client expects JSON.
+
+**Workaround:** Use `stream=true` for cloud direct calls. Local runtime includes SSE→JSON fallback.
+
+### Cloud Says Connected but "Invalid API key"
+
+1. Create a fresh key from local dashboard (`/api/keys`)
+2. Run cloud sync: Enable Cloud → Sync Now
+3. Old/non-synced keys can still return `401` on cloud
+
+---
+
+## Docker Issues
+
+### CLI Tool Shows Not Installed
+
+1. Check runtime fields: `curl http://localhost:20128/api/cli-tools/runtime/codex | jq`
+2. For portable mode: use image target `runner-cli` (bundled CLIs)
+3. For host mount mode: set `CLI_EXTRA_PATHS` and mount host bin directory as read-only
+4. If `installed=true` and `runnable=false`: binary was found but failed healthcheck
+
+### Quick Runtime Validation
+
+```bash
+curl -s http://localhost:20128/api/cli-tools/codex-settings | jq '{installed,runnable,commandPath,runtimeMode,reason}'
+curl -s http://localhost:20128/api/cli-tools/claude-settings | jq '{installed,runnable,commandPath,runtimeMode,reason}'
+curl -s http://localhost:20128/api/cli-tools/openclaw-settings | jq '{installed,runnable,commandPath,runtimeMode,reason}'
+```
+
+---
+
+## Cost Issues
+
+### High Costs
+
+1. Check usage stats in Dashboard → Usage
+2. Switch primary model to GLM/MiniMax
+3. Use free tier (Gemini CLI, Qoder) for non-critical tasks
+4. Set cost budgets per API key: Dashboard → API Keys → Budget
+
+---
+
+## Debugging
+
+### Enable Request Logs
+
+Set `ENABLE_REQUEST_LOGS=true` in your `.env` file. Logs appear under `logs/` directory.
+
+### Check Provider Health
+
+```bash
+# Health dashboard
+http://localhost:20128/dashboard/health
+
+# API health check
+curl http://localhost:20128/api/monitoring/health
+```
+
+### Runtime Storage
+
+- Main state: `${DATA_DIR}/storage.sqlite` (providers, combos, aliases, keys, settings)
+- Usage: SQLite tables in `storage.sqlite` (`usage_history`, `call_logs`, `proxy_logs`) + optional `${DATA_DIR}/log.txt` and `${DATA_DIR}/call_logs/`
+- Request logs: `/logs/...` (when `ENABLE_REQUEST_LOGS=true`)
+
+---
+
+## Circuit Breaker Issues
+
+### Provider stuck in OPEN state
+
+When a provider's circuit breaker is OPEN, requests are blocked until the cooldown expires.
+
+**Fix:**
+
+1. Go to **Dashboard → Settings → Resilience**
+2. Check the circuit breaker card for the affected provider
+3. Click **Reset All** to clear all breakers, or wait for the cooldown to expire
+4. Verify the provider is actually available before resetting
+
+### Provider keeps tripping the circuit breaker
+
+If a provider repeatedly enters OPEN state:
+
+1. Check **Dashboard → Health → Provider Health** for the failure pattern
+2. Go to **Settings → Resilience → Provider Profiles** and increase the failure threshold
+3. Check if the provider has changed API limits or requires re-authentication
+4. Review latency telemetry — high latency may cause timeout-based failures
+
+---
+
+## Audio Transcription Issues
+
+### "Unsupported model" error
+
+- Ensure you're using the correct prefix: `deepgram/nova-3` or `assemblyai/best`
+- Verify the provider is connected in **Dashboard → Providers**
+
+### Transcription returns empty or fails
+
+- Check supported audio formats: `mp3`, `wav`, `m4a`, `flac`, `ogg`, `webm`
+- Verify file size is within provider limits (typically < 25MB)
+- Check provider API key validity in the provider card
+
+---
+
+## Translator Debugging
+
+Use **Dashboard → Translator** to debug format translation issues:
+
+| Mode | When to Use |
+| ---------------- | -------------------------------------------------------------------------------------------- |
+| **Playground** | Compare input/output formats side by side — paste a failing request to see how it translates |
+| **Chat Tester** | Send live messages and inspect the full request/response payload including headers |
+| **Test Bench** | Run batch tests across format combinations to find which translations are broken |
+| **Live Monitor** | Watch real-time request flow to catch intermittent translation issues |
+
+### Common format issues
+
+- **Thinking tags not appearing** — Check if the target provider supports thinking and the thinking budget setting
+- **Tool calls dropping** — Some format translations may strip unsupported fields; verify in Playground mode
+- **System prompt missing** — Claude and Gemini handle system prompts differently; check translation output
+- **SDK returns raw string instead of object** — Fixed in v1.1.0: response sanitizer now strips non-standard fields (`x_groq`, `usage_breakdown`, etc.) that cause OpenAI SDK Pydantic validation failures
+- **GLM/ERNIE rejects `system` role** — Fixed in v1.1.0: role normalizer automatically merges system messages into user messages for incompatible models
+- **`developer` role not recognized** — Fixed in v1.1.0: automatically converted to `system` for non-OpenAI providers
+- **`json_schema` not working with Gemini** — Fixed in v1.1.0: `response_format` is now converted to Gemini's `responseMimeType` + `responseSchema`
+
+---
+
+## Resilience Settings
+
+### Auto rate-limit not triggering
+
+- Auto rate-limit only applies to API key providers (not OAuth/subscription)
+- Verify **Settings → Resilience → Provider Profiles** has auto-rate-limit enabled
+- Check if the provider returns `429` status codes or `Retry-After` headers
+
+### Tuning exponential backoff
+
+Provider profiles support these settings:
+
+- **Base delay** — Initial wait time after first failure (default: 1s)
+- **Max delay** — Maximum wait time cap (default: 30s)
+- **Multiplier** — How much to increase delay per consecutive failure (default: 2x)
+
+### Anti-thundering herd
+
+When many concurrent requests hit a rate-limited provider, OmniRoute uses mutex + auto rate-limiting to serialize requests and prevent cascading failures. This is automatic for API key providers.
+
+---
+
+## Optional RAG / LLM failure taxonomy (16 problems)
+
+Some OmniRoute users place the gateway in front of RAG or agent stacks. In those setups it is common to see a strange pattern: OmniRoute looks healthy (providers up, routing profiles ok, no rate limit alerts) but the final answer is still wrong.
+
+In practice these incidents usually come from the downstream RAG pipeline, not from the gateway itself.
+
+If you want a shared vocabulary to describe those failures you can use the WFGY ProblemMap, an external MIT license text resource that defines sixteen recurring RAG / LLM failure patterns. At a high level it covers:
+
+- retrieval drift and broken context boundaries
+- empty or stale indexes and vector stores
+- embedding versus semantic mismatch
+- prompt assembly and context window issues
+- logic collapse and overconfident answers
+- long chain and agent coordination failures
+- multi agent memory and role drift
+- deployment and bootstrap ordering problems
+
+The idea is simple:
+
+1. When you investigate a bad response, capture:
+ - user task and request
+ - route or provider combo in OmniRoute
+ - any RAG context used downstream (retrieved documents, tool calls, etc)
+2. Map the incident to one or two WFGY ProblemMap numbers (`No.1` … `No.16`).
+3. Store the number in your own dashboard, runbook, or incident tracker next to the OmniRoute logs.
+4. Use the corresponding WFGY page to decide whether you need to change your RAG stack, retriever, or routing strategy.
+
+Full text and concrete recipes live here (MIT license, text only):
+
+[WFGY ProblemMap README](https://github.com/onestardao/WFGY/blob/main/ProblemMap/README.md)
+
+You can ignore this section if you do not run RAG or agent pipelines behind OmniRoute.
+
+---
+
+## Still Stuck?
+
+- **GitHub Issues**: [github.com/diegosouzapw/OmniRoute/issues](https://github.com/diegosouzapw/OmniRoute/issues)
+- **Architecture**: See [`docs/ARCHITECTURE.md`](ARCHITECTURE.md) for internal details
+- **API Reference**: See [`docs/API_REFERENCE.md`](API_REFERENCE.md) for all endpoints
+- **Health Dashboard**: Check **Dashboard → Health** for real-time system status
+- **Translator**: Use **Dashboard → Translator** to debug format issues
diff --git a/docs/i18n/in/USER_GUIDE.md b/docs/i18n/in/docs/USER_GUIDE.md
similarity index 82%
rename from docs/i18n/in/USER_GUIDE.md
rename to docs/i18n/in/docs/USER_GUIDE.md
index f7f12c7965..389d00cb69 100644
--- a/docs/i18n/in/USER_GUIDE.md
+++ b/docs/i18n/in/docs/USER_GUIDE.md
@@ -1,8 +1,6 @@
# User Guide (हिन्दी)
-🌐 **Languages:** 🇺🇸 [English](../../USER_GUIDE.md) · 🇧🇷 [pt-BR](../pt-BR/USER_GUIDE.md) · 🇪🇸 [es](../es/USER_GUIDE.md) · 🇫🇷 [fr](../fr/USER_GUIDE.md) · 🇩🇪 [de](../de/USER_GUIDE.md) · 🇮🇹 [it](../it/USER_GUIDE.md) · 🇷🇺 [ru](../ru/USER_GUIDE.md) · 🇨🇳 [zh-CN](../zh-CN/USER_GUIDE.md) · 🇯🇵 [ja](../ja/USER_GUIDE.md) · 🇰🇷 [ko](../ko/USER_GUIDE.md) · 🇸🇦 [ar](../ar/USER_GUIDE.md) · 🇮🇳 [in](../in/USER_GUIDE.md) · 🇹🇭 [th](../th/USER_GUIDE.md) · 🇻🇳 [vi](../vi/USER_GUIDE.md) · 🇮🇩 [id](../id/USER_GUIDE.md) · 🇲🇾 [ms](../ms/USER_GUIDE.md) · 🇳🇱 [nl](../nl/USER_GUIDE.md) · 🇵🇱 [pl](../pl/USER_GUIDE.md) · 🇸🇪 [sv](../sv/USER_GUIDE.md) · 🇳🇴 [no](../no/USER_GUIDE.md) · 🇩🇰 [da](../da/USER_GUIDE.md) · 🇫🇮 [fi](../fi/USER_GUIDE.md) · 🇵🇹 [pt](../pt/USER_GUIDE.md) · 🇷🇴 [ro](../ro/USER_GUIDE.md) · 🇭🇺 [hu](../hu/USER_GUIDE.md) · 🇧🇬 [bg](../bg/USER_GUIDE.md) · 🇸🇰 [sk](../sk/USER_GUIDE.md) · 🇺🇦 [uk-UA](../uk-UA/USER_GUIDE.md) · 🇮🇱 [he](../he/USER_GUIDE.md) · 🇵🇭 [phi](../phi/USER_GUIDE.md)
-
-> 🇺🇸 [English](../../USER_GUIDE.md)
+🌐 **Languages:** 🇺🇸 [English](../../../../docs/USER_GUIDE.md) · 🇪🇸 [es](../../es/docs/USER_GUIDE.md) · 🇫🇷 [fr](../../fr/docs/USER_GUIDE.md) · 🇩🇪 [de](../../de/docs/USER_GUIDE.md) · 🇮🇹 [it](../../it/docs/USER_GUIDE.md) · 🇷🇺 [ru](../../ru/docs/USER_GUIDE.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/USER_GUIDE.md) · 🇯🇵 [ja](../../ja/docs/USER_GUIDE.md) · 🇰🇷 [ko](../../ko/docs/USER_GUIDE.md) · 🇸🇦 [ar](../../ar/docs/USER_GUIDE.md) · 🇮🇳 [in](../../in/docs/USER_GUIDE.md) · 🇹🇭 [th](../../th/docs/USER_GUIDE.md) · 🇻🇳 [vi](../../vi/docs/USER_GUIDE.md) · 🇮🇩 [id](../../id/docs/USER_GUIDE.md) · 🇲🇾 [ms](../../ms/docs/USER_GUIDE.md) · 🇳🇱 [nl](../../nl/docs/USER_GUIDE.md) · 🇵🇱 [pl](../../pl/docs/USER_GUIDE.md) · 🇸🇪 [sv](../../sv/docs/USER_GUIDE.md) · 🇳🇴 [no](../../no/docs/USER_GUIDE.md) · 🇩🇰 [da](../../da/docs/USER_GUIDE.md) · 🇫🇮 [fi](../../fi/docs/USER_GUIDE.md) · 🇵🇹 [pt](../../pt/docs/USER_GUIDE.md) · 🇷🇴 [ro](../../ro/docs/USER_GUIDE.md) · 🇭🇺 [hu](../../hu/docs/USER_GUIDE.md) · 🇧🇬 [bg](../../bg/docs/USER_GUIDE.md) · 🇸🇰 [sk](../../sk/docs/USER_GUIDE.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/USER_GUIDE.md) · 🇮🇱 [he](../../he/docs/USER_GUIDE.md) · 🇵🇭 [phi](../../phi/docs/USER_GUIDE.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/USER_GUIDE.md) · 🇨🇿 [cs](../../cs/docs/USER_GUIDE.md)
---
@@ -320,7 +318,7 @@ Model: cc/claude-opus-4-6
---
-## 🚀 Deployment
+## तैनाती
### Global npm install (Recommended)
@@ -511,23 +509,26 @@ post_install() {
### Environment Variables
-| Variable | Default | Description |
-| ------------------------- | ------------------------------------ | ------------------------------------------------------- |
-| `JWT_SECRET` | `omniroute-default-secret-change-me` | JWT signing secret (**change in production**) |
-| `INITIAL_PASSWORD` | `123456` | First login password |
-| `DATA_DIR` | `~/.omniroute` | Data directory (db, usage, logs) |
-| `PORT` | framework default | Service port (`20128` in examples) |
-| `HOSTNAME` | framework default | Bind host (Docker defaults to `0.0.0.0`) |
-| `NODE_ENV` | runtime default | Set `production` for deploy |
-| `BASE_URL` | `http://localhost:20128` | Server-side internal base URL |
-| `CLOUD_URL` | `https://omniroute.dev` | Cloud sync endpoint base URL |
-| `API_KEY_SECRET` | `endpoint-proxy-api-key-secret` | HMAC secret for generated API keys |
-| `REQUIRE_API_KEY` | `false` | Enforce Bearer API key on `/v1/*` |
-| `ENABLE_REQUEST_LOGS` | `false` | Enables request/response logs |
-| `AUTH_COOKIE_SECURE` | `false` | Force `Secure` auth cookie (behind HTTPS reverse proxy) |
-| `OMNIROUTE_MEMORY_MB` | `512` | Node.js heap limit in MB |
-| `PROMPT_CACHE_MAX_SIZE` | `50` | Max prompt cache entries |
-| `SEMANTIC_CACHE_MAX_SIZE` | `100` | Max semantic cache entries |
+| Variable | Default | Description |
+| ---------------------------- | ------------------------------------ | ------------------------------------------------------------------------------------------ |
+| `JWT_SECRET` | `omniroute-default-secret-change-me` | JWT signing secret (**change in production**) |
+| `INITIAL_PASSWORD` | `123456` | First login password |
+| `DATA_DIR` | `~/.omniroute` | Data directory (db, usage, logs) |
+| `PORT` | framework default | Service port (`20128` in examples) |
+| `HOSTNAME` | framework default | Bind host (Docker defaults to `0.0.0.0`) |
+| `NODE_ENV` | runtime default | Set `production` for deploy |
+| `BASE_URL` | `http://localhost:20128` | Server-side internal base URL |
+| `CLOUD_URL` | `https://omniroute.dev` | Cloud sync endpoint base URL |
+| `API_KEY_SECRET` | `endpoint-proxy-api-key-secret` | HMAC secret for generated API keys |
+| `REQUIRE_API_KEY` | `false` | Enforce Bearer API key on `/v1/*` |
+| `ALLOW_API_KEY_REVEAL` | `false` | Allow Api Manager to copy full API keys on demand |
+| `DISABLE_SQLITE_AUTO_BACKUP` | `false` | Disable automatic SQLite snapshots before writes/import/restore; manual backups still work |
+| `ENABLE_REQUEST_LOGS` | `false` | Enables request/response logs |
+| `AUTH_COOKIE_SECURE` | `false` | Force `Secure` auth cookie (behind HTTPS reverse proxy) |
+| `CLOUDFLARED_BIN` | unset | Use an existing `cloudflared` binary instead of managed download |
+| `OMNIROUTE_MEMORY_MB` | `512` | Node.js heap limit in MB |
+| `PROMPT_CACHE_MAX_SIZE` | `50` | Max prompt cache entries |
+| `SEMANTIC_CACHE_MAX_SIZE` | `100` | Max semantic cache entries |
For the full environment variable reference, see the [README](../README.md).
@@ -598,6 +599,11 @@ curl -X POST http://localhost:20128/api/provider-models \
Or use Dashboard: **Providers → [Provider] → Custom Models**.
+Notes:
+
+- OpenRouter and OpenAI/Anthropic-compatible providers are managed from **Available Models** only. Manual add, import, and auto-sync all land in the same available-model list, so there is no separate Custom Models section for those providers.
+- The **Custom Models** section is intended for providers that do not expose managed available-model imports.
+
### Dedicated Provider Routes
Route requests directly to a specific provider with model validation:
@@ -642,6 +648,14 @@ Returns models grouped by provider with types (`chat`, `embedding`, `image`).
- Automatic background sync with timeout + fail-fast
- Prefer server-side `BASE_URL`/`CLOUD_URL` in production
+### Cloudflare Quick Tunnel
+
+- Available in **Dashboard → Endpoints** for Docker and other self-hosted deployments
+- Creates a temporary `https://*.trycloudflare.com` URL that forwards to your current OpenAI-compatible `/v1` endpoint
+- First enable installs `cloudflared` only when needed; later restarts reuse the same managed binary
+- Tunnel URLs are ephemeral and change every time you stop/start the tunnel
+- Set `CLOUDFLARED_BIN` if you prefer using a preinstalled `cloudflared` binary instead of the managed download
+
### LLM Gateway Intelligence (Phase 9)
- **Semantic Cache** — Auto-caches non-streaming, temperature=0 responses (bypass with `X-OmniRoute-No-Cache: true`)
@@ -757,11 +771,11 @@ OmniRoute implements provider-level resilience with four components:
Manage database backups in **Dashboard → Settings → System & Storage**.
-| Action | Description |
-| ------------------------ | ------------------------------------------------------------------------------------------------------------------------------ |
-| **Export Database** | Downloads the current SQLite database as a `.sqlite` file |
-| **Export All (.tar.gz)** | Downloads a full backup archive including: database, settings, combos, provider connections (no credentials), API key metadata |
-| **Import Database** | Upload a `.sqlite` file to replace the current database. A pre-import backup is automatically created |
+| Action | Description |
+| ------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------- |
+| **Export Database** | Downloads the current SQLite database as a `.sqlite` file |
+| **Export All (.tar.gz)** | Downloads a full backup archive including: database, settings, combos, provider connections (no credentials), API key metadata |
+| **Import Database** | Upload a `.sqlite` file to replace the current database. A pre-import backup is automatically created unless `DISABLE_SQLITE_AUTO_BACKUP=true` |
```bash
# API: Export database
@@ -787,10 +801,11 @@ curl -X POST http://localhost:20128/api/db-backups/import \
### Settings Dashboard
-The settings page is organized into 5 tabs for easy navigation:
+The settings page is organized into 6 tabs for easy navigation:
| Tab | Contents |
| -------------- | ---------------------------------------------------------------------------------------------- |
+| **General** | System storage tools, appearance settings, theme controls, and per-item sidebar visibility |
| **Security** | Login/Password settings, IP Access Control, API auth for `/models`, and Provider Blocking |
| **Routing** | Global routing strategy (6 options), wildcard model aliases, fallback chains, combo defaults |
| **Resilience** | Provider profiles, editable rate limits, circuit breaker status, policies & locked identifiers |
diff --git a/docs/i18n/in/docs/VM_DEPLOYMENT_GUIDE.md b/docs/i18n/in/docs/VM_DEPLOYMENT_GUIDE.md
new file mode 100644
index 0000000000..8ed764b802
--- /dev/null
+++ b/docs/i18n/in/docs/VM_DEPLOYMENT_GUIDE.md
@@ -0,0 +1,403 @@
+# OmniRoute — Deployment Guide on VM with Cloudflare (हिन्दी)
+
+🌐 **Languages:** 🇺🇸 [English](../../../../docs/VM_DEPLOYMENT_GUIDE.md) · 🇪🇸 [es](../../es/docs/VM_DEPLOYMENT_GUIDE.md) · 🇫🇷 [fr](../../fr/docs/VM_DEPLOYMENT_GUIDE.md) · 🇩🇪 [de](../../de/docs/VM_DEPLOYMENT_GUIDE.md) · 🇮🇹 [it](../../it/docs/VM_DEPLOYMENT_GUIDE.md) · 🇷🇺 [ru](../../ru/docs/VM_DEPLOYMENT_GUIDE.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/VM_DEPLOYMENT_GUIDE.md) · 🇯🇵 [ja](../../ja/docs/VM_DEPLOYMENT_GUIDE.md) · 🇰🇷 [ko](../../ko/docs/VM_DEPLOYMENT_GUIDE.md) · 🇸🇦 [ar](../../ar/docs/VM_DEPLOYMENT_GUIDE.md) · 🇮🇳 [in](../../in/docs/VM_DEPLOYMENT_GUIDE.md) · 🇹🇭 [th](../../th/docs/VM_DEPLOYMENT_GUIDE.md) · 🇻🇳 [vi](../../vi/docs/VM_DEPLOYMENT_GUIDE.md) · 🇮🇩 [id](../../id/docs/VM_DEPLOYMENT_GUIDE.md) · 🇲🇾 [ms](../../ms/docs/VM_DEPLOYMENT_GUIDE.md) · 🇳🇱 [nl](../../nl/docs/VM_DEPLOYMENT_GUIDE.md) · 🇵🇱 [pl](../../pl/docs/VM_DEPLOYMENT_GUIDE.md) · 🇸🇪 [sv](../../sv/docs/VM_DEPLOYMENT_GUIDE.md) · 🇳🇴 [no](../../no/docs/VM_DEPLOYMENT_GUIDE.md) · 🇩🇰 [da](../../da/docs/VM_DEPLOYMENT_GUIDE.md) · 🇫🇮 [fi](../../fi/docs/VM_DEPLOYMENT_GUIDE.md) · 🇵🇹 [pt](../../pt/docs/VM_DEPLOYMENT_GUIDE.md) · 🇷🇴 [ro](../../ro/docs/VM_DEPLOYMENT_GUIDE.md) · 🇭🇺 [hu](../../hu/docs/VM_DEPLOYMENT_GUIDE.md) · 🇧🇬 [bg](../../bg/docs/VM_DEPLOYMENT_GUIDE.md) · 🇸🇰 [sk](../../sk/docs/VM_DEPLOYMENT_GUIDE.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/VM_DEPLOYMENT_GUIDE.md) · 🇮🇱 [he](../../he/docs/VM_DEPLOYMENT_GUIDE.md) · 🇵🇭 [phi](../../phi/docs/VM_DEPLOYMENT_GUIDE.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/VM_DEPLOYMENT_GUIDE.md) · 🇨🇿 [cs](../../cs/docs/VM_DEPLOYMENT_GUIDE.md)
+
+---
+
+Complete guide to install and configure OmniRoute on a VM (VPS) with domain managed via Cloudflare.
+
+---
+
+## Prerequisites
+
+| Item | Minimum | Recommended |
+| ---------- | ------------------------ | ---------------- |
+| **CPU** | 1 vCPU | 2 vCPU |
+| **RAM** | 1 GB | 2 GB |
+| **Disk** | 10 GB SSD | 25 GB SSD |
+| **OS** | Ubuntu 22.04 LTS | Ubuntu 24.04 LTS |
+| **Domain** | Registered on Cloudflare | — |
+| **Docker** | Docker Engine 24+ | Docker 27+ |
+
+**Tested providers**: Akamai (Linode), DigitalOcean, Vultr, Hetzner, AWS Lightsail.
+
+---
+
+## 1. Configure the VM
+
+### 1.1 Create the instance
+
+On your preferred VPS provider:
+
+- Choose Ubuntu 24.04 LTS
+- Select the minimum plan (1 vCPU / 1 GB RAM)
+- Set a strong root password or configure SSH key
+- Note the **public IP** (e.g., `203.0.113.10`)
+
+### 1.2 Connect via SSH
+
+```bash
+ssh root@203.0.113.10
+```
+
+### 1.3 Update the system
+
+```bash
+apt update && apt upgrade -y
+```
+
+### 1.4 Install Docker
+
+```bash
+# Install dependencies
+apt install -y ca-certificates curl gnupg
+
+# Add official Docker repository
+install -m 0755 -d /etc/apt/keyrings
+curl -fsSL https://download.docker.com/linux/ubuntu/gpg | gpg --dearmor -o /etc/apt/keyrings/docker.gpg
+chmod a+r /etc/apt/keyrings/docker.gpg
+echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu $ (. /etc/os-release && echo “$VERSION_CODENAME”) stable" | tee /etc/apt/sources.list.d/docker.list > /dev/null
+apt update
+apt install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin
+```
+
+### 1.5 Install nginx
+
+```bash
+apt install -y nginx
+```
+
+### 1.6 Configure Firewall (UFW)
+
+```bash
+ufw default deny incoming
+ufw default allow outgoing
+ufw allow 22/tcp # SSH
+ufw allow 80/tcp # HTTP (redirect)
+ufw allow 443/tcp # HTTPS
+ufw enable
+```
+
+> **Tip**: For maximum security, restrict ports 80 and 443 to Cloudflare IPs only. See the [Advanced Security](#advanced-security) section.
+
+---
+
+## 2. Install OmniRoute
+
+### 2.1 Create configuration directory
+
+```bash
+mkdir -p /opt/omniroute
+```
+
+### 2.2 Create environment variables file
+
+```bash
+cat > /opt/omniroute/.env << ‘EOF’
+# === Security ===
+JWT_SECRET=CHANGE-TO-A-UNIQUE-64-CHAR-SECRET-KEY
+INITIAL_PASSWORD=YourSecurePassword123!
+API_KEY_SECRET=REPLACE-WITH-ANOTHER-SECRET-KEY
+STORAGE_ENCRYPTION_KEY=REPLACE-WITH-THIRD-SECRET-KEY
+STORAGE_ENCRYPTION_KEY_VERSION=v1
+MACHINE_ID_SALT=CHANGE-TO-A-UNIQUE-SALT
+
+# === App ===
+PORT=20128
+NODE_ENV=production
+HOSTNAME=0.0.0.0
+DATA_DIR=/app/data
+STORAGE_DRIVER=sqlite
+ENABLE_REQUEST_LOGS=true
+AUTH_COOKIE_SECURE=false
+REQUIRE_API_KEY=false
+
+# === Domain (change to your domain) ===
+BASE_URL=https://llms.seudominio.com
+NEXT_PUBLIC_BASE_URL=https://llms.seudominio.com
+
+# === Cloud Sync (optional) ===
+# CLOUD_URL=https://cloud.omniroute.online
+# NEXT_PUBLIC_CLOUD_URL=https://cloud.omniroute.online
+EOF
+```
+
+> ⚠️ **IMPORTANT**: Generate unique secret keys! Use `openssl rand -hex 32` for each key.
+
+### 2.3 Start the container
+
+```bash
+docker pull diegosouzapw/omniroute:latest
+
+docker run -d \
+ --name omniroute \
+ --restart unless-stopped \
+ --env-file /opt/omniroute/.env \
+ -p 20128:20128 \
+ -v omniroute-data:/app/data \
+ diegosouzapw/omniroute:latest
+```
+
+### 2.4 Verify that it is running
+
+```bash
+docker ps | grep omniroute
+docker logs omniroute --tail 20
+```
+
+It should display: `[DB] SQLite database ready` and `listening on port 20128`.
+
+---
+
+## 3. Configure nginx (Reverse Proxy)
+
+### 3.1 Generate SSL certificate (Cloudflare Origin)
+
+In the Cloudflare dashboard:
+
+1. Go to **SSL/TLS → Origin Server**
+2. Click **Create Certificate**
+3. Keep the defaults (15 years, \*.yourdomain.com)
+4. Copy the **Origin Certificate** and the **Private Key**
+
+```bash
+mkdir -p /etc/nginx/ssl
+
+# Paste the certificate
+nano /etc/nginx/ssl/origin.crt
+
+# Paste the private key
+nano /etc/nginx/ssl/origin.key
+
+chmod 600 /etc/nginx/ssl/origin.key
+```
+
+### 3.2 Nginx Configuration
+
+```bash
+cat > /etc/nginx/sites-available/omniroute << ‘NGINX’
+# Default server — blocks direct access via IP
+server {
+ listen 80 default_server;
+ listen [::]:80 default_server;
+ listen 443 ssl default_server;
+ listen [::]:443 ssl default_server;
+ ssl_certificate /etc/nginx/ssl/origin.crt;
+ ssl_certificate_key /etc/nginx/ssl/origin.key;
+ server_name _;
+ return 444;
+}
+
+# OmniRoute — HTTPS
+server {
+ listen 443 ssl;
+ listen [::]:443 ssl;
+ server_name llms.yourdomain.com; # Change to your domain
+
+ ssl_certificate /etc/nginx/ssl/origin.crt;
+ ssl_certificate_key /etc/nginx/ssl/origin.key;
+ ssl_protocols TLSv1.2 TLSv1.3;
+
+ client_max_body_size 100M;
+
+ location / {
+ proxy_pass http://127.0.0.1:20128;
+ proxy_set_header Host $host;
+ proxy_set_header X-Real-IP $remote_addr;
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
+ proxy_set_header X-Forwarded-Proto $scheme;
+
+ # WebSocket support
+ proxy_http_version 1.1;
+ proxy_set_header Upgrade $http_upgrade;
+ proxy_set_header Connection “upgrade”;
+
+ # SSE (Server-Sent Events) — streaming AI responses
+ proxy_buffering off;
+ proxy_cache off;
+ proxy_read_timeout 300s;
+ proxy_send_timeout 300s;
+ }
+}
+
+# HTTP → HTTPS redirect
+server {
+ listen 80;
+ listen [::]:80;
+ server_name llms.yourdomain.com;
+ return 301 https://$server_name$request_uri;
+}
+NGINX
+```
+
+### 3.3 Enable and Test
+
+```bash
+# Remove default configuration
+rm -f /etc/nginx/sites-enabled/default
+
+# Enable OmniRoute
+ln -sf /etc/nginx/sites-available/omniroute /etc/nginx/sites-enabled/omniroute
+
+# Test and reload
+nginx -t && systemctl reload nginx
+```
+
+---
+
+## 4. Configure Cloudflare DNS
+
+### 4.1 Add DNS record
+
+In the Cloudflare dashboard → DNS:
+
+| Type | Name | Content | Proxy |
+| ---- | ------ | ---------------------- | ---------- |
+| A | `llms` | `203.0.113.10` (VM IP) | ✅ Proxied |
+
+### 4.2 Configure SSL
+
+Under **SSL/TLS → Overview**:
+
+- Mode: **Full (Strict)**
+
+Under **SSL/TLS → Edge Certificates**:
+
+- Always Use HTTPS: ✅ On
+- Minimum TLS Version: TLS 1.2
+- Automatic HTTPS Rewrites: ✅ On
+
+### 4.3 Testing
+
+```bash
+curl -sI https://llms.seudominio.com/health
+# Should return HTTP/2 200
+```
+
+---
+
+## 5. Operations and Maintenance
+
+### Upgrade to a new version
+
+```bash
+docker pull diegosouzapw/omniroute:latest
+docker stop omniroute && docker rm omniroute
+docker run -d --name omniroute --restart unless-stopped \
+ --env-file /opt/omniroute/.env \
+ -p 20128:20128 \
+ -v omniroute-data:/app/data \
+ diegosouzapw/omniroute:latest
+```
+
+### View logs
+
+```bash
+docker logs -f omniroute # Real-time stream
+docker logs omniroute --tail 50 # Last 50 lines
+```
+
+### Manual database backup
+
+```bash
+# Copy data from the volume to the host
+docker cp omniroute:/app/data ./backup-$(date +%F)
+
+# Or compress the entire volume
+docker run --rm -v omniroute-data:/data -v $(pwd):/backup \
+ alpine tar czf /backup/omniroute-data-$(date +%F).tar.gz /data
+```
+
+### Restore from backup
+
+```bash
+docker stop omniroute
+docker run --rm -v omniroute-data:/data -v $(pwd):/backup \
+ alpine sh -c “rm -rf /data/* && tar xzf /backup/omniroute-data-YYYY-MM-DD.tar.gz -C /”
+docker start omniroute
+```
+
+---
+
+## 6. Advanced Security
+
+### Restrict nginx to Cloudflare IPs
+
+```bash
+cat > /etc/nginx/cloudflare-ips.conf << ‘CF’
+# Cloudflare IPv4 ranges — update periodically
+# https://www.cloudflare.com/ips-v4/
+set_real_ip_from 173.245.48.0/20;
+set_real_ip_from 103.21.244.0/22;
+set_real_ip_from 103.22.200.0/22;
+set_real_ip_from 103.31.4.0/22;
+set_real_ip_from 141.101.64.0/18;
+set_real_ip_from 108.162.192.0/18;
+set_real_ip_from 190.93.240.0/20;
+set_real_ip_from 188.114.96.0/20;
+set_real_ip_from 197.234.240.0/22;
+set_real_ip_from 198.41.128.0/17;
+set_real_ip_from 162.158.0.0/15;
+set_real_ip_from 104.16.0.0/13;
+set_real_ip_from 104.24.0.0/14;
+set_real_ip_from 172.64.0.0/13;
+set_real_ip_from 131.0.72.0/22;
+real_ip_header CF-Connecting-IP;
+CF
+```
+
+Add the following to `nginx.conf` inside the `http {}` block:
+
+```nginx
+include /etc/nginx/cloudflare-ips.conf;
+```
+
+### Install fail2ban
+
+```bash
+apt install -y fail2ban
+systemctl enable fail2ban
+systemctl start fail2ban
+
+# Check status
+fail2ban-client status sshd
+```
+
+### Block direct access to the Docker port
+
+```bash
+# Prevent direct external access to port 20128
+iptables -I DOCKER-USER -p tcp --dport 20128 -j DROP
+iptables -I DOCKER-USER -i lo -p tcp --dport 20128 -j ACCEPT
+
+# Persist the rules
+apt install -y iptables-persistent
+netfilter-persistent save
+```
+
+---
+
+## 7. Deploy to Cloudflare Workers (Optional)
+
+For remote access via Cloudflare Workers (without exposing the VM directly):
+
+```bash
+# In the local repository
+cd omnirouteCloud
+npm install
+npx wrangler login
+npx wrangler deploy
+```
+
+See the full documentation at [omnirouteCloud/README.md](../omnirouteCloud/README.md).
+
+---
+
+## Port Summary
+
+| Port | Service | Access |
+| ----- | ----------- | -------------------------- |
+| 22 | SSH | Public (with fail2ban) |
+| 80 | nginx HTTP | Redirect → HTTPS |
+| 443 | nginx HTTPS | Via Cloudflare Proxy |
+| 20128 | OmniRoute | Localhost only (via nginx) |
diff --git a/docs/i18n/in/src/lib/a2a/README.md b/docs/i18n/in/src/lib/a2a/README.md
new file mode 100644
index 0000000000..4d1bbde8ef
--- /dev/null
+++ b/docs/i18n/in/src/lib/a2a/README.md
@@ -0,0 +1,752 @@
+# OmniRoute A2A Server (हिन्दी)
+
+🌐 **Languages:** 🇺🇸 [English](../../../../../../src/lib/a2a/README.md) · 🇪🇸 [es](../../../../es/src/lib/a2a/README.md) · 🇫🇷 [fr](../../../../fr/src/lib/a2a/README.md) · 🇩🇪 [de](../../../../de/src/lib/a2a/README.md) · 🇮🇹 [it](../../../../it/src/lib/a2a/README.md) · 🇷🇺 [ru](../../../../ru/src/lib/a2a/README.md) · 🇨🇳 [zh-CN](../../../../zh-CN/src/lib/a2a/README.md) · 🇯🇵 [ja](../../../../ja/src/lib/a2a/README.md) · 🇰🇷 [ko](../../../../ko/src/lib/a2a/README.md) · 🇸🇦 [ar](../../../../ar/src/lib/a2a/README.md) · 🇮🇳 [in](../../../../in/src/lib/a2a/README.md) · 🇹🇭 [th](../../../../th/src/lib/a2a/README.md) · 🇻🇳 [vi](../../../../vi/src/lib/a2a/README.md) · 🇮🇩 [id](../../../../id/src/lib/a2a/README.md) · 🇲🇾 [ms](../../../../ms/src/lib/a2a/README.md) · 🇳🇱 [nl](../../../../nl/src/lib/a2a/README.md) · 🇵🇱 [pl](../../../../pl/src/lib/a2a/README.md) · 🇸🇪 [sv](../../../../sv/src/lib/a2a/README.md) · 🇳🇴 [no](../../../../no/src/lib/a2a/README.md) · 🇩🇰 [da](../../../../da/src/lib/a2a/README.md) · 🇫🇮 [fi](../../../../fi/src/lib/a2a/README.md) · 🇵🇹 [pt](../../../../pt/src/lib/a2a/README.md) · 🇷🇴 [ro](../../../../ro/src/lib/a2a/README.md) · 🇭🇺 [hu](../../../../hu/src/lib/a2a/README.md) · 🇧🇬 [bg](../../../../bg/src/lib/a2a/README.md) · 🇸🇰 [sk](../../../../sk/src/lib/a2a/README.md) · 🇺🇦 [uk-UA](../../../../uk-UA/src/lib/a2a/README.md) · 🇮🇱 [he](../../../../he/src/lib/a2a/README.md) · 🇵🇭 [phi](../../../../phi/src/lib/a2a/README.md) · 🇧🇷 [pt-BR](../../../../pt-BR/src/lib/a2a/README.md) · 🇨🇿 [cs](../../../../cs/src/lib/a2a/README.md)
+
+---
+
+> **Agent-to-Agent Protocol v0.3** — Enables any AI agent to use OmniRoute as an intelligent routing agent via JSON-RPC 2.0.
+
+The A2A Server exposes OmniRoute as a **first-class agent** that other agents can discover, delegate tasks to, and collaborate with using the [A2A Protocol](https://google.github.io/A2A/).
+
+---
+
+## आर्किटेक्चर
+
+```
+┌──────────────────────────────────────────────────────────────────┐
+│ Orchestrator Agent │
+│ (LangChain, CrewAI, AutoGen, Custom Agent) │
+└──────────────────────┬───────────────────────────────────────────┘
+ │ 1. GET /.well-known/agent.json (discover)
+ │ 2. POST /a2a (JSON-RPC 2.0)
+ ▼
+┌──────────────────────────────────────────────────────────────────┐
+│ OmniRoute A2A Server │
+│ ┌────────────────┐ ┌────────────────┐ ┌───────────────────┐ │
+│ │ Task Manager │ │ Skill Engine │ │ SSE Streaming │ │
+│ │ (lifecycle) │──│ (registry) │──│ (real-time) │ │
+│ └────────────────┘ └────────┬───────┘ └───────────────────┘ │
+│ │ │
+│ Skills: │ │
+│ ├─ smart-routing ──────────┤ ┌────────────────────────────┐ │
+│ └─ quota-management ───────┘ │ Routing Decision Logger │ │
+│ └────────────────────────────┘ │
+└──────────────────────────────────────────────────────────────────┘
+ │
+ ▼ OmniRoute Gateway (internal)
+ /v1/chat/completions, /api/combos, /api/usage/quota
+```
+
+---
+
+## त्वरित प्रारंभ
+
+### Agent Discovery
+
+Every A2A-compatible agent exposes an **Agent Card** at `/.well-known/agent.json`:
+
+```bash
+curl http://localhost:20128/.well-known/agent.json
+```
+
+**Response:**
+
+```json
+{
+ "name": "OmniRoute",
+ "description": "Intelligent AI gateway with auto-routing across 50+ providers",
+ "url": "http://localhost:20128/a2a",
+ "version": "1.8.1",
+ "capabilities": {
+ "streaming": true,
+ "pushNotifications": false
+ },
+ "skills": [
+ {
+ "id": "smart-routing",
+ "name": "Smart Routing",
+ "description": "Routes prompts through OmniRoute intelligent pipeline",
+ "tags": ["routing", "llm", "multi-provider", "cost-optimization"],
+ "examples": [
+ "Write a hello world in Python",
+ "Explain quantum computing using the cheapest provider"
+ ]
+ },
+ {
+ "id": "quota-management",
+ "name": "Quota Management",
+ "description": "Natural-language queries about provider quotas",
+ "tags": ["quota", "analytics", "cost"],
+ "examples": [
+ "Which provider has the most quota remaining?",
+ "Suggest a free combo for coding"
+ ]
+ }
+ ],
+ "authentication": {
+ "schemes": ["bearer"],
+ "apiKeyHeader": "Authorization"
+ }
+}
+```
+
+---
+
+## JSON-RPC 2.0 Methods
+
+### `message/send` — Synchronous Execution
+
+Send a message to a skill and receive the complete response.
+
+```bash
+curl -X POST http://localhost:20128/a2a \
+ -H "Content-Type: application/json" \
+ -H "Authorization: Bearer YOUR_KEY" \
+ -d '{
+ "jsonrpc": "2.0",
+ "id": "1",
+ "method": "message/send",
+ "params": {
+ "skill": "smart-routing",
+ "messages": [{"role": "user", "content": "Write a Python hello world"}],
+ "metadata": {"model": "auto", "combo": "fast-coding"}
+ }
+ }'
+```
+
+**Response:**
+
+```json
+{
+ "jsonrpc": "2.0",
+ "id": "1",
+ "result": {
+ "task": { "id": "a1b2c3d4-...", "state": "completed" },
+ "artifacts": [{ "type": "text", "content": "print('Hello, World!')" }],
+ "metadata": {
+ "routing_explanation": "Selected claude-sonnet via provider \"anthropic\" (latency: 1200ms, cost: $0.0030)",
+ "cost_envelope": { "estimated": 0.005, "actual": 0.003, "currency": "USD" },
+ "resilience_trace": [
+ { "event": "primary_selected", "provider": "anthropic", "timestamp": "2026-03-04T..." }
+ ],
+ "policy_verdict": { "allowed": true, "reason": "within budget and quota limits" }
+ }
+ }
+}
+```
+
+### `message/stream` — SSE Streaming
+
+Same as `message/send` but returns Server-Sent Events for real-time streaming.
+
+```bash
+curl -N -X POST http://localhost:20128/a2a \
+ -H "Content-Type: application/json" \
+ -H "Authorization: Bearer YOUR_KEY" \
+ -d '{
+ "jsonrpc": "2.0",
+ "id": "1",
+ "method": "message/stream",
+ "params": {
+ "skill": "smart-routing",
+ "messages": [{"role": "user", "content": "Explain quantum computing"}]
+ }
+ }'
+```
+
+**SSE Events:**
+
+```
+data: {"jsonrpc":"2.0","method":"message/stream","params":{"task":{"id":"...","state":"working"},"chunk":{"type":"text","content":"Quantum computing..."}}}
+
+: heartbeat 2026-03-04T21:00:00Z
+
+data: {"jsonrpc":"2.0","method":"message/stream","params":{"task":{"id":"...","state":"completed"},"metadata":{...}}}
+```
+
+### `tasks/get` — Query Task Status
+
+```bash
+curl -X POST http://localhost:20128/a2a \
+ -H "Content-Type: application/json" \
+ -H "Authorization: Bearer YOUR_KEY" \
+ -d '{"jsonrpc":"2.0","id":"2","method":"tasks/get","params":{"taskId":"TASK_UUID"}}'
+```
+
+### `tasks/cancel` — Cancel a Running Task
+
+```bash
+curl -X POST http://localhost:20128/a2a \
+ -H "Content-Type: application/json" \
+ -H "Authorization: Bearer YOUR_KEY" \
+ -d '{"jsonrpc":"2.0","id":"3","method":"tasks/cancel","params":{"taskId":"TASK_UUID"}}'
+```
+
+---
+
+## Skills Reference
+
+### `smart-routing`
+
+Routes prompts through OmniRoute's intelligent pipeline with full observability.
+
+**Parameters (in `metadata`):**
+
+| Parameter | Type | Default | Description |
+| --------- | -------- | ------------ | ---------------------------------------------------------------------------------------- |
+| `model` | `string` | `"auto"` | Target model (e.g., `claude-sonnet-4`, `gpt-4o`, `auto`) |
+| `combo` | `string` | active combo | Specific combo to route through |
+| `budget` | `number` | none | Maximum cost in USD for this request |
+| `role` | `string` | none | Task role hint: `coding`, `review`, `planning`, `analysis`, `debugging`, `documentation` |
+
+**Returns:**
+
+| Field | Description |
+| ------------------------------ | --------------------------------------------------------- |
+| `artifacts[].content` | The LLM response text |
+| `metadata.routing_explanation` | Human-readable explanation of routing decision |
+| `metadata.cost_envelope` | Estimated vs actual cost with currency |
+| `metadata.resilience_trace` | Array of events (primary_selected, fallback_needed, etc.) |
+| `metadata.policy_verdict` | Whether the request was allowed and why |
+
+### `quota-management`
+
+Answers natural-language queries about provider quotas.
+
+**Query types (inferred from message content):**
+
+| Query Pattern | Response Type |
+| ---------------------------------------------- | -------------------------------------------------------- |
+| Contains `"ranking"`, `"most quota"`, `"best"` | Providers ranked by remaining quota |
+| Contains `"free"`, `"suggest"` | Lists free combos or suggests free-tier providers |
+| Default | Full quota summary with warnings for low-quota providers |
+
+---
+
+## Task Lifecycle
+
+```
+submitted ──→ working ──→ completed
+ ──→ failed
+ ──────────→ cancelled
+```
+
+| State | Description |
+| ----------- | ----------------------------------------------------- |
+| `submitted` | Task created, queued for execution |
+| `working` | Skill handler is executing |
+| `completed` | Execution succeeded, artifacts available |
+| `failed` | Execution failed or task expired (TTL: 5 min default) |
+| `cancelled` | Cancelled by client via `tasks/cancel` |
+
+- Terminal states: `completed`, `failed`, `cancelled` (no further transitions)
+- Expired tasks in `submitted` or `working` are auto-marked as `failed`
+- Tasks are garbage-collected after 2× TTL
+
+---
+
+## Client Examples
+
+### Python — Orchestrator Agent
+
+```python
+"""
+A2A Client — Python example.
+Discovers OmniRoute agent, sends a task, and processes the result.
+"""
+import requests
+import json
+
+BASE_URL = "http://localhost:20128"
+API_KEY = "your-api-key"
+HEADERS = {
+ "Content-Type": "application/json",
+ "Authorization": f"Bearer {API_KEY}",
+}
+
+# 1. Discover agent capabilities
+agent_card = requests.get(f"{BASE_URL}/.well-known/agent.json").json()
+print(f"Agent: {agent_card['name']} v{agent_card['version']}")
+print(f"Skills: {[s['id'] for s in agent_card['skills']]}")
+
+# 2. Send a smart-routing task
+response = requests.post(f"{BASE_URL}/a2a", headers=HEADERS, json={
+ "jsonrpc": "2.0",
+ "id": "task-1",
+ "method": "message/send",
+ "params": {
+ "skill": "smart-routing",
+ "messages": [{"role": "user", "content": "Write a Python quicksort implementation"}],
+ "metadata": {
+ "model": "auto",
+ "combo": "fast-coding",
+ "budget": 0.10,
+ }
+ }
+})
+result = response.json()["result"]
+print(f"\n📝 Response: {result['artifacts'][0]['content'][:200]}...")
+print(f"🔀 Routing: {result['metadata']['routing_explanation']}")
+print(f"💰 Cost: ${result['metadata']['cost_envelope']['actual']}")
+print(f"🛡️ Policy: {result['metadata']['policy_verdict']['reason']}")
+
+# 3. Query quota status
+quota_resp = requests.post(f"{BASE_URL}/a2a", headers=HEADERS, json={
+ "jsonrpc": "2.0",
+ "id": "task-2",
+ "method": "message/send",
+ "params": {
+ "skill": "quota-management",
+ "messages": [{"role": "user", "content": "Which provider has the most quota remaining?"}],
+ }
+})
+quota_result = quota_resp.json()["result"]
+print(f"\n📊 Quota: {quota_result['artifacts'][0]['content']}")
+```
+
+### TypeScript — Multi-Agent Orchestrator
+
+```typescript
+/**
+ * A2A Client — TypeScript example.
+ * Shows agent discovery, task delegation, and streaming.
+ */
+
+const BASE_URL = "http://localhost:20128";
+const API_KEY = "your-api-key";
+
+interface JsonRpcResponse {
+ jsonrpc: "2.0";
+ id: string | number;
+ result?: T;
+ error?: { code: number; message: string };
+}
+
+async function a2aCall(method: string, params: Record): Promise {
+ const resp = await fetch(`${BASE_URL}/a2a`, {
+ method: "POST",
+ headers: {
+ "Content-Type": "application/json",
+ Authorization: `Bearer ${API_KEY}`,
+ },
+ body: JSON.stringify({
+ jsonrpc: "2.0",
+ id: `${method}-${Date.now()}`,
+ method,
+ params,
+ }),
+ });
+ const json: JsonRpcResponse = await resp.json();
+ if (json.error) throw new Error(`[${json.error.code}] ${json.error.message}`);
+ return json.result!;
+}
+
+// ── Agent Discovery ──
+const agentCard = await fetch(`${BASE_URL}/.well-known/agent.json`).then((r) => r.json());
+console.log(`Connected to: ${agentCard.name} (${agentCard.skills.length} skills)`);
+
+// ── Smart Routing: Send a coding task ──
+const routingResult = await a2aCall("message/send", {
+ skill: "smart-routing",
+ messages: [{ role: "user", content: "Implement a Redis cache wrapper in TypeScript" }],
+ metadata: { model: "claude-sonnet-4", role: "coding" },
+});
+console.log("Response:", routingResult.artifacts[0].content);
+console.log("Provider:", routingResult.metadata.routing_explanation);
+
+// ── Quota Management: Find free alternatives ──
+const quotaResult = await a2aCall("message/send", {
+ skill: "quota-management",
+ messages: [{ role: "user", content: "Suggest free combos for documentation" }],
+});
+console.log("Free combos:", quotaResult.artifacts[0].content);
+
+// ── Streaming: Real-time response ──
+const streamResp = await fetch(`${BASE_URL}/a2a`, {
+ method: "POST",
+ headers: {
+ "Content-Type": "application/json",
+ Authorization: `Bearer ${API_KEY}`,
+ },
+ body: JSON.stringify({
+ jsonrpc: "2.0",
+ id: "stream-1",
+ method: "message/stream",
+ params: {
+ skill: "smart-routing",
+ messages: [{ role: "user", content: "Explain microservices architecture" }],
+ },
+ }),
+});
+
+const reader = streamResp.body!.getReader();
+const decoder = new TextDecoder();
+while (true) {
+ const { done, value } = await reader.read();
+ if (done) break;
+ const chunk = decoder.decode(value);
+ for (const line of chunk.split("\n")) {
+ if (line.startsWith("data: ")) {
+ const event = JSON.parse(line.slice(6));
+ if (event.params.chunk) {
+ process.stdout.write(event.params.chunk.content);
+ }
+ if (event.params.task.state === "completed") {
+ console.log("\n✅ Stream completed");
+ }
+ }
+ }
+}
+```
+
+### Python — LangChain A2A Integration
+
+```python
+"""
+LangChain integration — Use OmniRoute A2A as a custom LLM.
+"""
+from langchain.llms.base import BaseLLM
+from langchain.schema import LLMResult, Generation
+import requests
+from typing import List, Optional
+
+class OmniRouteA2A(BaseLLM):
+ base_url: str = "http://localhost:20128"
+ api_key: str = ""
+ model: str = "auto"
+ combo: Optional[str] = None
+
+ @property
+ def _llm_type(self) -> str:
+ return "omniroute-a2a"
+
+ def _call(self, prompt: str, stop: Optional[List[str]] = None, **kwargs) -> str:
+ response = requests.post(
+ f"{self.base_url}/a2a",
+ headers={
+ "Content-Type": "application/json",
+ "Authorization": f"Bearer {self.api_key}",
+ },
+ json={
+ "jsonrpc": "2.0",
+ "id": "langchain-1",
+ "method": "message/send",
+ "params": {
+ "skill": "smart-routing",
+ "messages": [{"role": "user", "content": prompt}],
+ "metadata": {
+ "model": self.model,
+ **({"combo": self.combo} if self.combo else {}),
+ },
+ },
+ },
+ )
+ result = response.json()["result"]
+ return result["artifacts"][0]["content"]
+
+ def _generate(self, prompts: List[str], stop=None, **kwargs) -> LLMResult:
+ return LLMResult(
+ generations=[[Generation(text=self._call(p, stop))] for p in prompts]
+ )
+
+# Usage
+llm = OmniRouteA2A(
+ base_url="http://localhost:20128",
+ api_key="your-key",
+ model="auto",
+ combo="fast-coding",
+)
+result = llm("Write a Python function to merge two sorted lists")
+print(result)
+```
+
+### Go — A2A Client
+
+```go
+package main
+
+import (
+ "bytes"
+ "encoding/json"
+ "fmt"
+ "io"
+ "net/http"
+)
+
+const baseURL = "http://localhost:20128"
+const apiKey = "your-api-key"
+
+type JsonRpcRequest struct {
+ Jsonrpc string `json:"jsonrpc"`
+ ID string `json:"id"`
+ Method string `json:"method"`
+ Params interface{} `json:"params"`
+}
+
+type JsonRpcResponse struct {
+ Jsonrpc string `json:"jsonrpc"`
+ ID string `json:"id"`
+ Result interface{} `json:"result"`
+ Error *struct {
+ Code int `json:"code"`
+ Message string `json:"message"`
+ } `json:"error"`
+}
+
+func a2aCall(method string, params interface{}) (*JsonRpcResponse, error) {
+ body, _ := json.Marshal(JsonRpcRequest{
+ Jsonrpc: "2.0",
+ ID: "go-1",
+ Method: method,
+ Params: params,
+ })
+
+ req, _ := http.NewRequest("POST", baseURL+"/a2a", bytes.NewReader(body))
+ req.Header.Set("Content-Type", "application/json")
+ req.Header.Set("Authorization", "Bearer "+apiKey)
+
+ resp, err := http.DefaultClient.Do(req)
+ if err != nil {
+ return nil, err
+ }
+ defer resp.Body.Close()
+ data, _ := io.ReadAll(resp.Body)
+
+ var result JsonRpcResponse
+ json.Unmarshal(data, &result)
+ return &result, nil
+}
+
+func main() {
+ // Discover agent
+ resp, _ := http.Get(baseURL + "/.well-known/agent.json")
+ defer resp.Body.Close()
+ body, _ := io.ReadAll(resp.Body)
+ fmt.Println("Agent Card:", string(body))
+
+ // Send smart-routing task
+ result, _ := a2aCall("message/send", map[string]interface{}{
+ "skill": "smart-routing",
+ "messages": []map[string]string{{"role": "user", "content": "Hello from Go!"}},
+ "metadata": map[string]interface{}{"model": "auto"},
+ })
+ out, _ := json.MarshalIndent(result.Result, "", " ")
+ fmt.Println("Result:", string(out))
+}
+```
+
+---
+
+## Use Cases
+
+### 🤖 Use Case 1: Multi-Agent Coding Pipeline
+
+An orchestrator agent delegates code generation to OmniRoute, then passes the output to a review agent.
+
+```python
+def coding_pipeline(task: str):
+ # Step 1: Generate code via OmniRoute A2A
+ code_result = a2a_send("smart-routing", [
+ {"role": "user", "content": f"Write production-quality code: {task}"}
+ ], metadata={"model": "auto", "role": "coding"})
+ code = code_result["artifacts"][0]["content"]
+
+ # Step 2: Review the code via OmniRoute A2A (different model)
+ review_result = a2a_send("smart-routing", [
+ {"role": "user", "content": f"Review this code for bugs and improvements:\n\n{code}"}
+ ], metadata={"model": "auto", "role": "review"})
+ review = review_result["artifacts"][0]["content"]
+
+ # Step 3: Check costs
+ print(f"Code cost: ${code_result['metadata']['cost_envelope']['actual']}")
+ print(f"Review cost: ${review_result['metadata']['cost_envelope']['actual']}")
+
+ return {"code": code, "review": review}
+```
+
+### 💡 Use Case 2: Quota-Aware Agent Swarm
+
+Multiple agents share quota through OmniRoute, using the quota skill to coordinate.
+
+```python
+async def quota_aware_agent(agent_name: str, task: str):
+ # Check quota before starting
+ quota = a2a_send("quota-management", [
+ {"role": "user", "content": "Which provider has the most quota remaining?"}
+ ])
+ print(f"[{agent_name}] {quota['artifacts'][0]['content']}")
+
+ # Send request with budget constraint
+ result = a2a_send("smart-routing", [
+ {"role": "user", "content": task}
+ ], metadata={"budget": 0.05})
+
+ policy = result["metadata"]["policy_verdict"]
+ if not policy["allowed"]:
+ print(f"[{agent_name}] ⚠️ Budget exceeded: {policy['reason']}")
+ # Fall back to free combo
+ quota = a2a_send("quota-management", [
+ {"role": "user", "content": "Suggest free combos"}
+ ])
+ print(f"[{agent_name}] Free alternatives: {quota['artifacts'][0]['content']}")
+
+ return result
+```
+
+### 📊 Use Case 3: Real-Time Streaming Dashboard
+
+A monitoring agent streams responses and displays progress in real-time.
+
+```typescript
+async function streamingDashboard(prompt: string) {
+ const response = await fetch(`${BASE_URL}/a2a`, {
+ method: "POST",
+ headers: { "Content-Type": "application/json", Authorization: `Bearer ${API_KEY}` },
+ body: JSON.stringify({
+ jsonrpc: "2.0",
+ id: "dash-1",
+ method: "message/stream",
+ params: { skill: "smart-routing", messages: [{ role: "user", content: prompt }] },
+ }),
+ });
+
+ let totalChunks = 0;
+ const reader = response.body!.getReader();
+ const decoder = new TextDecoder();
+
+ while (true) {
+ const { done, value } = await reader.read();
+ if (done) break;
+
+ for (const line of decoder.decode(value).split("\n")) {
+ if (line.startsWith("data: ")) {
+ const event = JSON.parse(line.slice(6));
+ const state = event.params.task.state;
+
+ if (state === "working" && event.params.chunk) {
+ totalChunks++;
+ process.stdout.write(
+ `\r[Chunk ${totalChunks}] ${event.params.chunk.content.slice(0, 50)}...`
+ );
+ }
+ if (state === "completed") {
+ const meta = event.params.metadata;
+ console.log(
+ `\n✅ Done | Cost: $${meta?.cost_envelope?.actual || 0} | Route: ${meta?.routing_explanation || "N/A"}`
+ );
+ }
+ if (state === "failed") {
+ console.error(`\n❌ Failed: ${event.params.metadata?.error}`);
+ }
+ }
+ }
+ }
+}
+```
+
+### 🔁 Use Case 4: Task Polling Pattern
+
+For long-running tasks, poll the task status instead of waiting synchronously.
+
+```python
+import time
+
+def poll_task(task_id: str, timeout: int = 60):
+ """Poll task status until completion or timeout."""
+ start = time.time()
+ while time.time() - start < timeout:
+ result = requests.post(f"{BASE_URL}/a2a", headers=HEADERS, json={
+ "jsonrpc": "2.0",
+ "id": "poll-1",
+ "method": "tasks/get",
+ "params": {"taskId": task_id},
+ }).json()
+
+ task = result["result"]["task"]
+ state = task["state"]
+ print(f" Task {task_id[:8]}... state={state}")
+
+ if state in ("completed", "failed", "cancelled"):
+ return task
+ time.sleep(2)
+
+ # Timeout — cancel the task
+ requests.post(f"{BASE_URL}/a2a", headers=HEADERS, json={
+ "jsonrpc": "2.0",
+ "id": "cancel-1",
+ "method": "tasks/cancel",
+ "params": {"taskId": task_id},
+ })
+ raise TimeoutError(f"Task {task_id} timed out after {timeout}s")
+```
+
+---
+
+## Error Codes
+
+| Code | Constant | Meaning |
+| ------ | ------------------------ | ---------------------------------------- |
+| -32700 | — | Parse error (invalid JSON) |
+| -32600 | `INVALID_REQUEST` | Invalid JSON-RPC request or unauthorized |
+| -32601 | `METHOD_NOT_FOUND` | Unknown method or skill |
+| -32602 | `INVALID_PARAMS` | Missing or invalid parameters |
+| -32603 | `INTERNAL_ERROR` | Skill execution failed |
+| -32001 | `TASK_NOT_FOUND` | Task ID not found |
+| -32002 | `TASK_ALREADY_COMPLETED` | Cannot modify a completed task |
+| -32003 | `UNAUTHORIZED` | Invalid or missing API key |
+| -32004 | `BUDGET_EXCEEDED` | Request exceeds configured budget |
+| -32005 | `PROVIDER_UNAVAILABLE` | No available providers |
+
+---
+
+## Authentication
+
+All `/a2a` requests require a Bearer token via the `Authorization` header:
+
+```
+Authorization: Bearer YOUR_OMNIROUTE_API_KEY
+```
+
+If no API key is configured on the server (`OMNIROUTE_API_KEY` is empty), authentication is bypassed.
+
+---
+
+## File Structure
+
+```
+src/lib/a2a/
+├── taskManager.ts # Task lifecycle (create/update/cancel/list), TTL, cleanup
+├── taskExecution.ts # Generic task executor with state management
+├── streaming.ts # SSE stream formatting, heartbeat, chunk/completion events
+├── routingLogger.ts # Routing decision logger (stats, history, retention)
+└── skills/
+ ├── smartRouting.ts # Smart routing skill (routes via /v1/chat/completions)
+ └── quotaManagement.ts # Quota management skill (natural-language quota queries)
+
+src/app/a2a/
+└── route.ts # Next.js API route handler (JSON-RPC 2.0 dispatch)
+
+open-sse/mcp-server/
+└── schemas/a2a.ts # Zod schemas (AgentCard, Task, JSON-RPC, SSE events)
+```
+
+---
+
+## Comparison: MCP vs A2A
+
+| Feature | MCP Server | A2A Server |
+| ----------------- | ---------------------------- | ------------------------------------------------- |
+| **Protocol** | Model Context Protocol | Agent-to-Agent Protocol v0.3 |
+| **Transport** | stdio / HTTP | HTTP (JSON-RPC 2.0) |
+| **Discovery** | Tool listing via MCP | `/.well-known/agent.json` |
+| **Granularity** | 16 individual tools | 2 high-level skills |
+| **Best for** | IDE agents (Cursor, VS Code) | Multi-agent systems (LangChain, CrewAI) |
+| **Streaming** | Not supported | SSE via `message/stream` |
+| **Task tracking** | No | Full lifecycle (submitted → completed) |
+| **Observability** | Audit log per tool call | Cost envelope + resilience trace + policy verdict |
+
+---
+
+## लाइसेंस
+
+Part of [OmniRoute](https://github.com/diegosouzapw/OmniRoute) — MIT License.
diff --git a/docs/i18n/it/A2A-SERVER.md b/docs/i18n/it/A2A-SERVER.md
deleted file mode 100644
index 01531ff482..0000000000
--- a/docs/i18n/it/A2A-SERVER.md
+++ /dev/null
@@ -1,200 +0,0 @@
-🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/A2A-SERVER.md) · 🇪🇸 [es](../es/A2A-SERVER.md) · 🇫🇷 [fr](../fr/A2A-SERVER.md) · 🇩🇪 [de](../de/A2A-SERVER.md) · 🇮🇹 [it](../it/A2A-SERVER.md) · 🇷🇺 [ru](../ru/A2A-SERVER.md) · 🇨🇳 [zh-CN](../zh-CN/A2A-SERVER.md) · 🇯🇵 [ja](../ja/A2A-SERVER.md) · 🇰🇷 [ko](../ko/A2A-SERVER.md) · 🇸🇦 [ar](../ar/A2A-SERVER.md) · 🇮🇳 [in](../in/A2A-SERVER.md) · 🇹🇭 [th](../th/A2A-SERVER.md) · 🇻🇳 [vi](../vi/A2A-SERVER.md) · 🇮🇩 [id](../id/A2A-SERVER.md) · 🇲🇾 [ms](../ms/A2A-SERVER.md) · 🇳🇱 [nl](../nl/A2A-SERVER.md) · 🇵🇱 [pl](../pl/A2A-SERVER.md) · 🇸🇪 [sv](../sv/A2A-SERVER.md) · 🇳🇴 [no](../no/A2A-SERVER.md) · 🇩🇰 [da](../da/A2A-SERVER.md) · 🇫🇮 [fi](../fi/A2A-SERVER.md) · 🇵🇹 [pt](../pt/A2A-SERVER.md) · 🇷🇴 [ro](../ro/A2A-SERVER.md) · 🇭🇺 [hu](../hu/A2A-SERVER.md) · 🇧🇬 [bg](../bg/A2A-SERVER.md) · 🇸🇰 [sk](../sk/A2A-SERVER.md) · 🇺🇦 [uk-UA](../uk-UA/A2A-SERVER.md) · 🇮🇱 [he](../he/A2A-SERVER.md) · 🇵🇭 [phi](../phi/A2A-SERVER.md)
-
----
-
-# OmniRoute A2A Server Documentation
-
-> Agent-to-Agent Protocol v0.3 — OmniRoute as an intelligent routing agent
-
-## Agent Discovery
-
-```bash
-curl http://localhost:20128/.well-known/agent.json
-```
-
-Returns the Agent Card describing OmniRoute's capabilities, skills, and authentication requirements.
-
----
-
-## Authentication
-
-All `/a2a` requests require an API key via the `Authorization` header:
-
-```
-Authorization: Bearer YOUR_OMNIROUTE_API_KEY
-```
-
-If no API key is configured on the server, authentication is bypassed.
-
----
-
-## JSON-RPC 2.0 Methods
-
-### `message/send` — Synchronous Execution
-
-Sends a message to a skill and waits for the complete response.
-
-```bash
-curl -X POST http://localhost:20128/a2a \
- -H "Content-Type: application/json" \
- -H "Authorization: Bearer YOUR_KEY" \
- -d '{
- "jsonrpc": "2.0",
- "id": "1",
- "method": "message/send",
- "params": {
- "skill": "smart-routing",
- "messages": [{"role": "user", "content": "Write a hello world in Python"}],
- "metadata": {"model": "auto", "combo": "fast-coding"}
- }
- }'
-```
-
-**Response:**
-
-```json
-{
- "jsonrpc": "2.0",
- "id": "1",
- "result": {
- "task": { "id": "uuid", "state": "completed" },
- "artifacts": [{ "type": "text", "content": "..." }],
- "metadata": {
- "routing_explanation": "Selected claude-sonnet via provider \"anthropic\" (latency: 1200ms, cost: $0.003)",
- "cost_envelope": { "estimated": 0.005, "actual": 0.003, "currency": "USD" },
- "resilience_trace": [
- { "event": "primary_selected", "provider": "anthropic", "timestamp": "..." }
- ],
- "policy_verdict": { "allowed": true, "reason": "within budget and quota limits" }
- }
- }
-}
-```
-
-### `message/stream` — SSE Streaming
-
-Same as `message/send` but returns Server-Sent Events for real-time streaming.
-
-```bash
-curl -N -X POST http://localhost:20128/a2a \
- -H "Content-Type: application/json" \
- -H "Authorization: Bearer YOUR_KEY" \
- -d '{
- "jsonrpc": "2.0",
- "id": "1",
- "method": "message/stream",
- "params": {
- "skill": "smart-routing",
- "messages": [{"role": "user", "content": "Explain quantum computing"}]
- }
- }'
-```
-
-**SSE Events:**
-
-```
-data: {"jsonrpc":"2.0","method":"message/stream","params":{"task":{"id":"...","state":"working"},"chunk":{"type":"text","content":"..."}}}
-
-: heartbeat 2026-03-03T17:00:00Z
-
-data: {"jsonrpc":"2.0","method":"message/stream","params":{"task":{"id":"...","state":"completed"},"metadata":{...}}}
-```
-
-### `tasks/get` — Query Task Status
-
-```bash
-curl -X POST http://localhost:20128/a2a \
- -H "Content-Type: application/json" \
- -H "Authorization: Bearer YOUR_KEY" \
- -d '{"jsonrpc":"2.0","id":"2","method":"tasks/get","params":{"taskId":"TASK_UUID"}}'
-```
-
-### `tasks/cancel` — Cancel a Task
-
-```bash
-curl -X POST http://localhost:20128/a2a \
- -H "Content-Type: application/json" \
- -H "Authorization: Bearer YOUR_KEY" \
- -d '{"jsonrpc":"2.0","id":"3","method":"tasks/cancel","params":{"taskId":"TASK_UUID"}}'
-```
-
----
-
-## Available Skills
-
-| Skill | Description |
-| :----------------- | :------------------------------------------------------------------------------------------------------------------------------ |
-| `smart-routing` | Routes prompts through OmniRoute's intelligent pipeline. Returns response with routing explanation, cost, and resilience trace. |
-| `quota-management` | Answers natural-language queries about provider quotas, suggests free combos, and provides quota rankings. |
-
----
-
-## Task Lifecycle
-
-```
-submitted → working → completed
- → failed
- → cancelled
-```
-
-- Tasks expire after 5 minutes (configurable)
-- Terminal states: `completed`, `failed`, `cancelled`
-- Event log tracks every state transition
-
----
-
-## Error Codes
-
-| Code | Meaning |
-| :----- | :----------------------------- |
-| -32700 | Parse error (invalid JSON) |
-| -32600 | Invalid request / Unauthorized |
-| -32601 | Method or skill not found |
-| -32602 | Invalid params |
-| -32603 | Internal error |
-
----
-
-## Integration Examples
-
-### Python (requests)
-
-```python
-import requests
-
-resp = requests.post("http://localhost:20128/a2a", json={
- "jsonrpc": "2.0", "id": "1",
- "method": "message/send",
- "params": {
- "skill": "smart-routing",
- "messages": [{"role": "user", "content": "Hello"}]
- }
-}, headers={"Authorization": "Bearer YOUR_KEY"})
-
-result = resp.json()["result"]
-print(result["artifacts"][0]["content"])
-print(result["metadata"]["routing_explanation"])
-```
-
-### TypeScript (fetch)
-
-```typescript
-const resp = await fetch("http://localhost:20128/a2a", {
- method: "POST",
- headers: {
- "Content-Type": "application/json",
- Authorization: "Bearer YOUR_KEY",
- },
- body: JSON.stringify({
- jsonrpc: "2.0",
- id: "1",
- method: "message/send",
- params: {
- skill: "smart-routing",
- messages: [{ role: "user", content: "Hello" }],
- },
- }),
-});
-const { result } = await resp.json();
-console.log(result.metadata.routing_explanation);
-```
diff --git a/docs/i18n/it/API_REFERENCE.md b/docs/i18n/it/API_REFERENCE.md
deleted file mode 100644
index b878605221..0000000000
--- a/docs/i18n/it/API_REFERENCE.md
+++ /dev/null
@@ -1,455 +0,0 @@
-🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/API_REFERENCE.md) · 🇪🇸 [es](../es/API_REFERENCE.md) · 🇫🇷 [fr](../fr/API_REFERENCE.md) · 🇩🇪 [de](../de/API_REFERENCE.md) · 🇮🇹 [it](../it/API_REFERENCE.md) · 🇷🇺 [ru](../ru/API_REFERENCE.md) · 🇨🇳 [zh-CN](../zh-CN/API_REFERENCE.md) · 🇯🇵 [ja](../ja/API_REFERENCE.md) · 🇰🇷 [ko](../ko/API_REFERENCE.md) · 🇸🇦 [ar](../ar/API_REFERENCE.md) · 🇮🇳 [in](../in/API_REFERENCE.md) · 🇹🇭 [th](../th/API_REFERENCE.md) · 🇻🇳 [vi](../vi/API_REFERENCE.md) · 🇮🇩 [id](../id/API_REFERENCE.md) · 🇲🇾 [ms](../ms/API_REFERENCE.md) · 🇳🇱 [nl](../nl/API_REFERENCE.md) · 🇵🇱 [pl](../pl/API_REFERENCE.md) · 🇸🇪 [sv](../sv/API_REFERENCE.md) · 🇳🇴 [no](../no/API_REFERENCE.md) · 🇩🇰 [da](../da/API_REFERENCE.md) · 🇫🇮 [fi](../fi/API_REFERENCE.md) · 🇵🇹 [pt](../pt/API_REFERENCE.md) · 🇷🇴 [ro](../ro/API_REFERENCE.md) · 🇭🇺 [hu](../hu/API_REFERENCE.md) · 🇧🇬 [bg](../bg/API_REFERENCE.md) · 🇸🇰 [sk](../sk/API_REFERENCE.md) · 🇺🇦 [uk-UA](../uk-UA/API_REFERENCE.md) · 🇮🇱 [he](../he/API_REFERENCE.md) · 🇵🇭 [phi](../phi/API_REFERENCE.md)
-
----
-
-# API Reference
-
-🌐 **Languages:** 🇺🇸 [English](API_REFERENCE.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/API_REFERENCE.md) | 🇪🇸 [Español](i18n/es/API_REFERENCE.md) | 🇫🇷 [Français](i18n/fr/API_REFERENCE.md) | 🇮🇹 [Italiano](i18n/it/API_REFERENCE.md) | 🇷🇺 [Русский](i18n/ru/API_REFERENCE.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/API_REFERENCE.md) | 🇩🇪 [Deutsch](i18n/de/API_REFERENCE.md) | 🇮🇳 [हिन्दी](i18n/in/API_REFERENCE.md) | 🇹🇭 [ไทย](i18n/th/API_REFERENCE.md) | 🇺🇦 [Українська](i18n/uk-UA/API_REFERENCE.md) | 🇸🇦 [العربية](i18n/ar/API_REFERENCE.md) | 🇯🇵 [日本語](i18n/ja/API_REFERENCE.md) | 🇻🇳 [Tiếng Việt](i18n/vi/API_REFERENCE.md) | 🇧🇬 [Български](i18n/bg/API_REFERENCE.md) | 🇩🇰 [Dansk](i18n/da/API_REFERENCE.md) | 🇫🇮 [Suomi](i18n/fi/API_REFERENCE.md) | 🇮🇱 [עברית](i18n/he/API_REFERENCE.md) | 🇭🇺 [Magyar](i18n/hu/API_REFERENCE.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/API_REFERENCE.md) | 🇰🇷 [한국어](i18n/ko/API_REFERENCE.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/API_REFERENCE.md) | 🇳🇱 [Nederlands](i18n/nl/API_REFERENCE.md) | 🇳🇴 [Norsk](i18n/no/API_REFERENCE.md) | 🇵🇹 [Português (Portugal)](i18n/pt/API_REFERENCE.md) | 🇷🇴 [Română](i18n/ro/API_REFERENCE.md) | 🇵🇱 [Polski](i18n/pl/API_REFERENCE.md) | 🇸🇰 [Slovenčina](i18n/sk/API_REFERENCE.md) | 🇸🇪 [Svenska](i18n/sv/API_REFERENCE.md) | 🇵🇭 [Filipino](i18n/phi/API_REFERENCE.md)
-
-Complete reference for all OmniRoute API endpoints.
-
----
-
-## Table of Contents
-
-- [Chat Completions](#chat-completions)
-- [Embeddings](#embeddings)
-- [Image Generation](#image-generation)
-- [List Models](#list-models)
-- [Compatibility Endpoints](#compatibility-endpoints)
-- [Semantic Cache](#semantic-cache)
-- [Dashboard & Management](#dashboard--management)
-- [Request Processing](#request-processing)
-- [Authentication](#authentication)
-
----
-
-## Chat Completions
-
-```bash
-POST /v1/chat/completions
-Authorization: Bearer your-api-key
-Content-Type: application/json
-
-{
- "model": "cc/claude-opus-4-6",
- "messages": [
- {"role": "user", "content": "Write a function to..."}
- ],
- "stream": true
-}
-```
-
-### Custom Headers
-
-| Header | Direction | Description |
-| ------------------------ | --------- | --------------------------------- |
-| `X-OmniRoute-No-Cache` | Request | Set to `true` to bypass cache |
-| `X-OmniRoute-Progress` | Request | Set to `true` for progress events |
-| `Idempotency-Key` | Request | Dedup key (5s window) |
-| `X-Request-Id` | Request | Alternative dedup key |
-| `X-OmniRoute-Cache` | Response | `HIT` or `MISS` (non-streaming) |
-| `X-OmniRoute-Idempotent` | Response | `true` if deduplicated |
-| `X-OmniRoute-Progress` | Response | `enabled` if progress tracking on |
-
----
-
-## Embeddings
-
-```bash
-POST /v1/embeddings
-Authorization: Bearer your-api-key
-Content-Type: application/json
-
-{
- "model": "nebius/Qwen/Qwen3-Embedding-8B",
- "input": "The food was delicious"
-}
-```
-
-Available providers: Nebius, OpenAI, Mistral, Together AI, Fireworks, NVIDIA.
-
-```bash
-# List all embedding models
-GET /v1/embeddings
-```
-
----
-
-## Image Generation
-
-```bash
-POST /v1/images/generations
-Authorization: Bearer your-api-key
-Content-Type: application/json
-
-{
- "model": "openai/dall-e-3",
- "prompt": "A beautiful sunset over mountains",
- "size": "1024x1024"
-}
-```
-
-Available providers: OpenAI (DALL-E), xAI (Grok Image), Together AI (FLUX), Fireworks AI.
-
-```bash
-# List all image models
-GET /v1/images/generations
-```
-
----
-
-## List Models
-
-```bash
-GET /v1/models
-Authorization: Bearer your-api-key
-
-→ Returns all chat, embedding, and image models + combos in OpenAI format
-```
-
----
-
-## Compatibility Endpoints
-
-| Method | Path | Format |
-| ------ | --------------------------- | ---------------------- |
-| POST | `/v1/chat/completions` | OpenAI |
-| POST | `/v1/messages` | Anthropic |
-| POST | `/v1/responses` | OpenAI Responses |
-| POST | `/v1/embeddings` | OpenAI |
-| POST | `/v1/images/generations` | OpenAI |
-| GET | `/v1/models` | OpenAI |
-| POST | `/v1/messages/count_tokens` | Anthropic |
-| GET | `/v1beta/models` | Gemini |
-| POST | `/v1beta/models/{...path}` | Gemini generateContent |
-| POST | `/v1/api/chat` | Ollama |
-
-### Dedicated Provider Routes
-
-```bash
-POST /v1/providers/{provider}/chat/completions
-POST /v1/providers/{provider}/embeddings
-POST /v1/providers/{provider}/images/generations
-```
-
-The provider prefix is auto-added if missing. Mismatched models return `400`.
-
----
-
-## Semantic Cache
-
-```bash
-# Get cache stats
-GET /api/cache
-
-# Clear all caches
-DELETE /api/cache
-```
-
-Response example:
-
-```json
-{
- "semanticCache": {
- "memorySize": 42,
- "memoryMaxSize": 500,
- "dbSize": 128,
- "hitRate": 0.65
- },
- "idempotency": {
- "activeKeys": 3,
- "windowMs": 5000
- }
-}
-```
-
----
-
-## Dashboard & Management
-
-### Authentication
-
-| Endpoint | Method | Description |
-| ----------------------------- | ------- | --------------------- |
-| `/api/auth/login` | POST | Login |
-| `/api/auth/logout` | POST | Logout |
-| `/api/settings/require-login` | GET/PUT | Toggle login required |
-
-### Provider Management
-
-| Endpoint | Method | Description |
-| ---------------------------- | --------------- | ------------------------ |
-| `/api/providers` | GET/POST | List / create providers |
-| `/api/providers/[id]` | GET/PUT/DELETE | Manage a provider |
-| `/api/providers/[id]/test` | POST | Test provider connection |
-| `/api/providers/[id]/models` | GET | List provider models |
-| `/api/providers/validate` | POST | Validate provider config |
-| `/api/provider-nodes*` | Various | Provider node management |
-| `/api/provider-models` | GET/POST/DELETE | Custom models |
-
-### OAuth Flows
-
-| Endpoint | Method | Description |
-| -------------------------------- | ------- | ----------------------- |
-| `/api/oauth/[provider]/[action]` | Various | Provider-specific OAuth |
-
-### Routing & Config
-
-| Endpoint | Method | Description |
-| --------------------- | -------- | ----------------------------- |
-| `/api/models/alias` | GET/POST | Model aliases |
-| `/api/models/catalog` | GET | All models by provider + type |
-| `/api/combos*` | Various | Combo management |
-| `/api/keys*` | Various | API key management |
-| `/api/pricing` | GET | Model pricing |
-
-### Usage & Analytics
-
-| Endpoint | Method | Description |
-| --------------------------- | ------ | -------------------- |
-| `/api/usage/history` | GET | Usage history |
-| `/api/usage/logs` | GET | Usage logs |
-| `/api/usage/request-logs` | GET | Request-level logs |
-| `/api/usage/[connectionId]` | GET | Per-connection usage |
-
-### Settings
-
-| Endpoint | Method | Description |
-| ------------------------------- | ------- | ---------------------- |
-| `/api/settings` | GET/PUT | General settings |
-| `/api/settings/proxy` | GET/PUT | Network proxy config |
-| `/api/settings/proxy/test` | POST | Test proxy connection |
-| `/api/settings/ip-filter` | GET/PUT | IP allowlist/blocklist |
-| `/api/settings/thinking-budget` | GET/PUT | Reasoning token budget |
-| `/api/settings/system-prompt` | GET/PUT | Global system prompt |
-
-### Monitoring
-
-| Endpoint | Method | Description |
-| ------------------------ | ---------- | ----------------------- |
-| `/api/sessions` | GET | Active session tracking |
-| `/api/rate-limits` | GET | Per-account rate limits |
-| `/api/monitoring/health` | GET | Health check |
-| `/api/cache` | GET/DELETE | Cache stats / clear |
-
-### Backup & Export/Import
-
-| Endpoint | Method | Description |
-| --------------------------- | ------ | --------------------------------------- |
-| `/api/db-backups` | GET | List available backups |
-| `/api/db-backups` | PUT | Create a manual backup |
-| `/api/db-backups` | POST | Restore from a specific backup |
-| `/api/db-backups/export` | GET | Download database as .sqlite file |
-| `/api/db-backups/import` | POST | Upload .sqlite file to replace database |
-| `/api/db-backups/exportAll` | GET | Download full backup as .tar.gz archive |
-
-### Cloud Sync
-
-| Endpoint | Method | Description |
-| ---------------------- | ------- | --------------------- |
-| `/api/sync/cloud` | Various | Cloud sync operations |
-| `/api/sync/initialize` | POST | Initialize sync |
-| `/api/cloud/*` | Various | Cloud management |
-
-### CLI Tools
-
-| Endpoint | Method | Description |
-| ---------------------------------- | ------ | ------------------- |
-| `/api/cli-tools/claude-settings` | GET | Claude CLI status |
-| `/api/cli-tools/codex-settings` | GET | Codex CLI status |
-| `/api/cli-tools/droid-settings` | GET | Droid CLI status |
-| `/api/cli-tools/openclaw-settings` | GET | OpenClaw CLI status |
-| `/api/cli-tools/runtime/[toolId]` | GET | Generic CLI runtime |
-
-CLI responses include: `installed`, `runnable`, `command`, `commandPath`, `runtimeMode`, `reason`.
-
-### ACP Agents
-
-| Endpoint | Method | Description |
-| ----------------- | ------ | -------------------------------------------------------- |
-| `/api/acp/agents` | GET | List all detected agents (built-in + custom) with status |
-| `/api/acp/agents` | POST | Add custom agent or refresh detection cache |
-| `/api/acp/agents` | DELETE | Remove a custom agent by `id` query param |
-
-GET response includes `agents[]` (id, name, binary, version, installed, protocol, isCustom) and `summary` (total, installed, notFound, builtIn, custom).
-
-### Resilience & Rate Limits
-
-| Endpoint | Method | Description |
-| ----------------------- | ------- | ------------------------------- |
-| `/api/resilience` | GET/PUT | Get/update resilience profiles |
-| `/api/resilience/reset` | POST | Reset circuit breakers |
-| `/api/rate-limits` | GET | Per-account rate limit status |
-| `/api/rate-limit` | GET | Global rate limit configuration |
-
-### Evals
-
-| Endpoint | Method | Description |
-| ------------ | -------- | --------------------------------- |
-| `/api/evals` | GET/POST | List eval suites / run evaluation |
-
-### Policies
-
-| Endpoint | Method | Description |
-| --------------- | --------------- | ----------------------- |
-| `/api/policies` | GET/POST/DELETE | Manage routing policies |
-
-### Compliance
-
-| Endpoint | Method | Description |
-| --------------------------- | ------ | ----------------------------- |
-| `/api/compliance/audit-log` | GET | Compliance audit log (last N) |
-
-### v1beta (Gemini-Compatible)
-
-| Endpoint | Method | Description |
-| -------------------------- | ------ | --------------------------------- |
-| `/v1beta/models` | GET | List models in Gemini format |
-| `/v1beta/models/{...path}` | POST | Gemini `generateContent` endpoint |
-
-These endpoints mirror Gemini's API format for clients that expect native Gemini SDK compatibility.
-
-### Internal / System APIs
-
-| Endpoint | Method | Description |
-| --------------- | ------ | ---------------------------------------------------- |
-| `/api/init` | GET | Application initialization check (used on first run) |
-| `/api/tags` | GET | Ollama-compatible model tags (for Ollama clients) |
-| `/api/restart` | POST | Trigger graceful server restart |
-| `/api/shutdown` | POST | Trigger graceful server shutdown |
-
-> **Note:** These endpoints are used internally by the system or for Ollama client compatibility. They are not typically called by end users.
-
----
-
-## Audio Transcription
-
-```bash
-POST /v1/audio/transcriptions
-Authorization: Bearer your-api-key
-Content-Type: multipart/form-data
-```
-
-Transcribe audio files using Deepgram or AssemblyAI.
-
-**Request:**
-
-```bash
-curl -X POST http://localhost:20128/v1/audio/transcriptions \
- -H "Authorization: Bearer your-api-key" \
- -F "file=@recording.mp3" \
- -F "model=deepgram/nova-3"
-```
-
-**Response:**
-
-```json
-{
- "text": "Hello, this is the transcribed audio content.",
- "task": "transcribe",
- "language": "en",
- "duration": 12.5
-}
-```
-
-**Supported providers:** `deepgram/nova-3`, `assemblyai/best`.
-
-**Supported formats:** `mp3`, `wav`, `m4a`, `flac`, `ogg`, `webm`.
-
----
-
-## Ollama Compatibility
-
-For clients that use Ollama's API format:
-
-```bash
-# Chat endpoint (Ollama format)
-POST /v1/api/chat
-
-# Model listing (Ollama format)
-GET /api/tags
-```
-
-Requests are automatically translated between Ollama and internal formats.
-
----
-
-## Telemetry
-
-```bash
-# Get latency telemetry summary (p50/p95/p99 per provider)
-GET /api/telemetry/summary
-```
-
-**Response:**
-
-```json
-{
- "providers": {
- "claudeCode": { "p50": 245, "p95": 890, "p99": 1200, "count": 150 },
- "github": { "p50": 180, "p95": 620, "p99": 950, "count": 320 }
- }
-}
-```
-
----
-
-## Budget
-
-```bash
-# Get budget status for all API keys
-GET /api/usage/budget
-
-# Set or update a budget
-POST /api/usage/budget
-Content-Type: application/json
-
-{
- "keyId": "key-123",
- "limit": 50.00,
- "period": "monthly"
-}
-```
-
----
-
-## Model Availability
-
-```bash
-# Get real-time model availability across all providers
-GET /api/models/availability
-
-# Check availability for a specific model
-POST /api/models/availability
-Content-Type: application/json
-
-{
- "model": "claude-sonnet-4-5-20250929"
-}
-```
-
----
-
-## Request Processing
-
-1. Client sends request to `/v1/*`
-2. Route handler calls `handleChat`, `handleEmbedding`, `handleAudioTranscription`, or `handleImageGeneration`
-3. Model is resolved (direct provider/model or alias/combo)
-4. Credentials selected from local DB with account availability filtering
-5. For chat: `handleChatCore` — format detection, translation, cache check, idempotency check
-6. Provider executor sends upstream request
-7. Response translated back to client format (chat) or returned as-is (embeddings/images/audio)
-8. Usage/logging recorded
-9. Fallback applies on errors according to combo rules
-
-Full architecture reference: [`ARCHITECTURE.md`](ARCHITECTURE.md)
-
----
-
-## Authentication
-
-- Dashboard routes (`/dashboard/*`) use `auth_token` cookie
-- Login uses saved password hash; fallback to `INITIAL_PASSWORD`
-- `requireLogin` toggleable via `/api/settings/require-login`
-- `/v1/*` routes optionally require Bearer API key when `REQUIRE_API_KEY=true`
diff --git a/docs/i18n/it/ARCHITECTURE.md b/docs/i18n/it/ARCHITECTURE.md
deleted file mode 100644
index 4ea06a29f2..0000000000
--- a/docs/i18n/it/ARCHITECTURE.md
+++ /dev/null
@@ -1,787 +0,0 @@
-🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/ARCHITECTURE.md) · 🇪🇸 [es](../es/ARCHITECTURE.md) · 🇫🇷 [fr](../fr/ARCHITECTURE.md) · 🇩🇪 [de](../de/ARCHITECTURE.md) · 🇮🇹 [it](../it/ARCHITECTURE.md) · 🇷🇺 [ru](../ru/ARCHITECTURE.md) · 🇨🇳 [zh-CN](../zh-CN/ARCHITECTURE.md) · 🇯🇵 [ja](../ja/ARCHITECTURE.md) · 🇰🇷 [ko](../ko/ARCHITECTURE.md) · 🇸🇦 [ar](../ar/ARCHITECTURE.md) · 🇮🇳 [in](../in/ARCHITECTURE.md) · 🇹🇭 [th](../th/ARCHITECTURE.md) · 🇻🇳 [vi](../vi/ARCHITECTURE.md) · 🇮🇩 [id](../id/ARCHITECTURE.md) · 🇲🇾 [ms](../ms/ARCHITECTURE.md) · 🇳🇱 [nl](../nl/ARCHITECTURE.md) · 🇵🇱 [pl](../pl/ARCHITECTURE.md) · 🇸🇪 [sv](../sv/ARCHITECTURE.md) · 🇳🇴 [no](../no/ARCHITECTURE.md) · 🇩🇰 [da](../da/ARCHITECTURE.md) · 🇫🇮 [fi](../fi/ARCHITECTURE.md) · 🇵🇹 [pt](../pt/ARCHITECTURE.md) · 🇷🇴 [ro](../ro/ARCHITECTURE.md) · 🇭🇺 [hu](../hu/ARCHITECTURE.md) · 🇧🇬 [bg](../bg/ARCHITECTURE.md) · 🇸🇰 [sk](../sk/ARCHITECTURE.md) · 🇺🇦 [uk-UA](../uk-UA/ARCHITECTURE.md) · 🇮🇱 [he](../he/ARCHITECTURE.md) · 🇵🇭 [phi](../phi/ARCHITECTURE.md)
-
----
-
-# OmniRoute Architecture
-
-🌐 **Languages:** 🇺🇸 [English](ARCHITECTURE.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/ARCHITECTURE.md) | 🇪🇸 [Español](i18n/es/ARCHITECTURE.md) | 🇫🇷 [Français](i18n/fr/ARCHITECTURE.md) | 🇮🇹 [Italiano](i18n/it/ARCHITECTURE.md) | 🇷🇺 [Русский](i18n/ru/ARCHITECTURE.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/ARCHITECTURE.md) | 🇩🇪 [Deutsch](i18n/de/ARCHITECTURE.md) | 🇮🇳 [हिन्दी](i18n/in/ARCHITECTURE.md) | 🇹🇭 [ไทย](i18n/th/ARCHITECTURE.md) | 🇺🇦 [Українська](i18n/uk-UA/ARCHITECTURE.md) | 🇸🇦 [العربية](i18n/ar/ARCHITECTURE.md) | 🇯🇵 [日本語](i18n/ja/ARCHITECTURE.md) | 🇻🇳 [Tiếng Việt](i18n/vi/ARCHITECTURE.md) | 🇧🇬 [Български](i18n/bg/ARCHITECTURE.md) | 🇩🇰 [Dansk](i18n/da/ARCHITECTURE.md) | 🇫🇮 [Suomi](i18n/fi/ARCHITECTURE.md) | 🇮🇱 [עברית](i18n/he/ARCHITECTURE.md) | 🇭🇺 [Magyar](i18n/hu/ARCHITECTURE.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/ARCHITECTURE.md) | 🇰🇷 [한국어](i18n/ko/ARCHITECTURE.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/ARCHITECTURE.md) | 🇳🇱 [Nederlands](i18n/nl/ARCHITECTURE.md) | 🇳🇴 [Norsk](i18n/no/ARCHITECTURE.md) | 🇵🇹 [Português (Portugal)](i18n/pt/ARCHITECTURE.md) | 🇷🇴 [Română](i18n/ro/ARCHITECTURE.md) | 🇵🇱 [Polski](i18n/pl/ARCHITECTURE.md) | 🇸🇰 [Slovenčina](i18n/sk/ARCHITECTURE.md) | 🇸🇪 [Svenska](i18n/sv/ARCHITECTURE.md) | 🇵🇭 [Filipino](i18n/phi/ARCHITECTURE.md)
-
-_Last updated: 2026-03-04_
-
-## Executive Summary
-
-OmniRoute is a local AI routing gateway and dashboard built on Next.js.
-It provides a single OpenAI-compatible endpoint (`/v1/*`) and routes traffic across multiple upstream providers with translation, fallback, token refresh, and usage tracking.
-
-Core capabilities:
-
-- OpenAI-compatible API surface for CLI/tools (28 providers)
-- Request/response translation across provider formats
-- Model combo fallback (multi-model sequence)
-- Account-level fallback (multi-account per provider)
-- OAuth + API-key provider connection management
-- Embedding generation via `/v1/embeddings` (6 providers, 9 models)
-- Image generation via `/v1/images/generations` (4 providers, 9 models)
-- Think tag parsing (`...`) for reasoning models
-- Response sanitization for strict OpenAI SDK compatibility
-- Role normalization (developer→system, system→user) for cross-provider compatibility
-- Structured output conversion (json_schema → Gemini responseSchema)
-- Local persistence for providers, keys, aliases, combos, settings, pricing
-- Usage/cost tracking and request logging
-- Optional cloud sync for multi-device/state sync
-- IP allowlist/blocklist for API access control
-- Thinking budget management (passthrough/auto/custom/adaptive)
-- Global system prompt injection
-- Session tracking and fingerprinting
-- Per-account enhanced rate limiting with provider-specific profiles
-- Circuit breaker pattern for provider resilience
-- Anti-thundering herd protection with mutex locking
-- Signature-based request deduplication cache
-- Domain layer: model availability, cost rules, fallback policy, lockout policy
-- Domain state persistence (SQLite write-through cache for fallbacks, budgets, lockouts, circuit breakers)
-- Policy engine for centralized request evaluation (lockout → budget → fallback)
-- Request telemetry with p50/p95/p99 latency aggregation
-- Correlation ID (X-Request-Id) for end-to-end tracing
-- Compliance audit logging with opt-out per API key
-- Eval framework for LLM quality assurance
-- Resilience UI dashboard with real-time circuit breaker status
-- Modular OAuth providers (12 individual modules under `src/lib/oauth/providers/`)
-
-Primary runtime model:
-
-- Next.js app routes under `src/app/api/*` implement both dashboard APIs and compatibility APIs
-- A shared SSE/routing core in `src/sse/*` + `open-sse/*` handles provider execution, translation, streaming, fallback, and usage
-
-## Scope and Boundaries
-
-### In Scope
-
-- Local gateway runtime
-- Dashboard management APIs
-- Provider authentication and token refresh
-- Request translation and SSE streaming
-- Local state + usage persistence
-- Optional cloud sync orchestration
-
-### Out of Scope
-
-- Cloud service implementation behind `NEXT_PUBLIC_CLOUD_URL`
-- Provider SLA/control plane outside local process
-- External CLI binaries themselves (Claude CLI, Codex CLI, etc.)
-
-## High-Level System Context
-
-```mermaid
-flowchart LR
- subgraph Clients[Developer Clients]
- C1[Claude Code]
- C2[Codex CLI]
- C3[OpenClaw / Droid / Cline / Continue / Roo]
- C4[Custom OpenAI-compatible clients]
- BROWSER[Browser Dashboard]
- end
-
- subgraph Router[OmniRoute Local Process]
- API[V1 Compatibility API\n/v1/*]
- DASH[Dashboard + Management API\n/api/*]
- CORE[SSE + Translation Core\nopen-sse + src/sse]
- DB[(storage.sqlite)]
- UDB[(usage tables + log artifacts)]
- end
-
- subgraph Upstreams[Upstream Providers]
- P1[OAuth Providers\nClaude/Codex/Gemini/Qwen/Qoder/GitHub/Kiro/Cursor/Antigravity]
- P2[API Key Providers\nOpenAI/Anthropic/OpenRouter/GLM/Kimi/MiniMax\nDeepSeek/Groq/xAI/Mistral/Perplexity\nTogether/Fireworks/Cerebras/Cohere/NVIDIA]
- P3[Compatible Nodes\nOpenAI-compatible / Anthropic-compatible]
- end
-
- subgraph Cloud[Optional Cloud Sync]
- CLOUD[Cloud Sync Endpoint\nNEXT_PUBLIC_CLOUD_URL]
- end
-
- C1 --> API
- C2 --> API
- C3 --> API
- C4 --> API
- BROWSER --> DASH
-
- API --> CORE
- DASH --> DB
- CORE --> DB
- CORE --> UDB
-
- CORE --> P1
- CORE --> P2
- CORE --> P3
-
- DASH --> CLOUD
-```
-
-## Core Runtime Components
-
-## 1) API and Routing Layer (Next.js App Routes)
-
-Main directories:
-
-- `src/app/api/v1/*` and `src/app/api/v1beta/*` for compatibility APIs
-- `src/app/api/*` for management/configuration APIs
-- Next rewrites in `next.config.mjs` map `/v1/*` to `/api/v1/*`
-
-Important compatibility routes:
-
-- `src/app/api/v1/chat/completions/route.ts`
-- `src/app/api/v1/messages/route.ts`
-- `src/app/api/v1/responses/route.ts`
-- `src/app/api/v1/models/route.ts` — includes custom models with `custom: true`
-- `src/app/api/v1/embeddings/route.ts` — embedding generation (6 providers)
-- `src/app/api/v1/images/generations/route.ts` — image generation (4+ providers incl. Antigravity/Nebius)
-- `src/app/api/v1/messages/count_tokens/route.ts`
-- `src/app/api/v1/providers/[provider]/chat/completions/route.ts` — dedicated per-provider chat
-- `src/app/api/v1/providers/[provider]/embeddings/route.ts` — dedicated per-provider embeddings
-- `src/app/api/v1/providers/[provider]/images/generations/route.ts` — dedicated per-provider images
-- `src/app/api/v1beta/models/route.ts`
-- `src/app/api/v1beta/models/[...path]/route.ts`
-
-Management domains:
-
-- Auth/settings: `src/app/api/auth/*`, `src/app/api/settings/*`
-- Providers/connections: `src/app/api/providers*`
-- Provider nodes: `src/app/api/provider-nodes*`
-- Custom models: `src/app/api/provider-models` (GET/POST/DELETE)
-- Model catalog: `src/app/api/models/route.ts` (GET)
-- Proxy config: `src/app/api/settings/proxy` (GET/PUT/DELETE) + `src/app/api/settings/proxy/test` (POST)
-- OAuth: `src/app/api/oauth/*`
-- Keys/aliases/combos/pricing: `src/app/api/keys*`, `src/app/api/models/alias`, `src/app/api/combos*`, `src/app/api/pricing`
-- Usage: `src/app/api/usage/*`
-- Sync/cloud: `src/app/api/sync/*`, `src/app/api/cloud/*`
-- CLI tooling helpers: `src/app/api/cli-tools/*`
-- IP filter: `src/app/api/settings/ip-filter` (GET/PUT)
-- Thinking budget: `src/app/api/settings/thinking-budget` (GET/PUT)
-- System prompt: `src/app/api/settings/system-prompt` (GET/PUT)
-- Sessions: `src/app/api/sessions` (GET)
-- Rate limits: `src/app/api/rate-limits` (GET)
-- Resilience: `src/app/api/resilience` (GET/PATCH) — provider profiles, circuit breaker, rate limit state
-- Resilience reset: `src/app/api/resilience/reset` (POST) — reset breakers + cooldowns
-- Cache stats: `src/app/api/cache/stats` (GET/DELETE)
-- Model availability: `src/app/api/models/availability` (GET/POST)
-- Telemetry: `src/app/api/telemetry/summary` (GET)
-- Budget: `src/app/api/usage/budget` (GET/POST)
-- Fallback chains: `src/app/api/fallback/chains` (GET/POST/DELETE)
-- Compliance audit: `src/app/api/compliance/audit-log` (GET)
-- Evals: `src/app/api/evals` (GET/POST), `src/app/api/evals/[suiteId]` (GET)
-- Policies: `src/app/api/policies` (GET/POST)
-
-## 2) SSE + Translation Core
-
-Main flow modules:
-
-- Entry: `src/sse/handlers/chat.ts`
-- Core orchestration: `open-sse/handlers/chatCore.ts`
-- Provider execution adapters: `open-sse/executors/*`
-- Format detection/provider config: `open-sse/services/provider.ts`
-- Model parse/resolve: `src/sse/services/model.ts`, `open-sse/services/model.ts`
-- Account fallback logic: `open-sse/services/accountFallback.ts`
-- Translation registry: `open-sse/translator/index.ts`
-- Stream transformations: `open-sse/utils/stream.ts`, `open-sse/utils/streamHandler.ts`
-- Usage extraction/normalization: `open-sse/utils/usageTracking.ts`
-- Think tag parser: `open-sse/utils/thinkTagParser.ts`
-- Embedding handler: `open-sse/handlers/embeddings.ts`
-- Embedding provider registry: `open-sse/config/embeddingRegistry.ts`
-- Image generation handler: `open-sse/handlers/imageGeneration.ts`
-- Image provider registry: `open-sse/config/imageRegistry.ts`
-- Response sanitization: `open-sse/handlers/responseSanitizer.ts`
-- Role normalization: `open-sse/services/roleNormalizer.ts`
-
-Services (business logic):
-
-- Account selection/scoring: `open-sse/services/accountSelector.ts`
-- Context lifecycle management: `open-sse/services/contextManager.ts`
-- IP filter enforcement: `open-sse/services/ipFilter.ts`
-- Session tracking: `open-sse/services/sessionManager.ts`
-- Request deduplication: `open-sse/services/signatureCache.ts`
-- System prompt injection: `open-sse/services/systemPrompt.ts`
-- Thinking budget management: `open-sse/services/thinkingBudget.ts`
-- Wildcard model routing: `open-sse/services/wildcardRouter.ts`
-- Rate limit management: `open-sse/services/rateLimitManager.ts`
-- Circuit breaker: `open-sse/services/circuitBreaker.ts`
-
-Domain layer modules:
-
-- Model availability: `src/lib/domain/modelAvailability.ts`
-- Cost rules/budgets: `src/lib/domain/costRules.ts`
-- Fallback policy: `src/lib/domain/fallbackPolicy.ts`
-- Combo resolver: `src/lib/domain/comboResolver.ts`
-- Lockout policy: `src/lib/domain/lockoutPolicy.ts`
-- Policy engine: `src/domain/policyEngine.ts` — centralized lockout → budget → fallback evaluation
-- Error codes catalog: `src/lib/domain/errorCodes.ts`
-- Request ID: `src/lib/domain/requestId.ts`
-- Fetch timeout: `src/lib/domain/fetchTimeout.ts`
-- Request telemetry: `src/lib/domain/requestTelemetry.ts`
-- Compliance/audit: `src/lib/domain/compliance/index.ts`
-- Eval runner: `src/lib/domain/evalRunner.ts`
-- Domain state persistence: `src/lib/db/domainState.ts` — SQLite CRUD for fallback chains, budgets, cost history, lockout state, circuit breakers
-
-OAuth provider modules (12 individual files under `src/lib/oauth/providers/`):
-
-- Registry index: `src/lib/oauth/providers/index.ts`
-- Individual providers: `claude.ts`, `codex.ts`, `gemini.ts`, `antigravity.ts`, `qoder.ts`, `qwen.ts`, `kimi-coding.ts`, `github.ts`, `kiro.ts`, `cursor.ts`, `kilocode.ts`, `cline.ts`
-- Thin wrapper: `src/lib/oauth/providers.ts` — re-exports from individual modules
-
-## 3) Persistence Layer
-
-Primary state DB (SQLite):
-
-- Core infra: `src/lib/db/core.ts` (better-sqlite3, migrations, WAL)
-- Re-export facade: `src/lib/localDb.ts` (thin compatibility layer for callers)
-- file: `${DATA_DIR}/storage.sqlite` (or `$XDG_CONFIG_HOME/omniroute/storage.sqlite` when set, else `~/.omniroute/storage.sqlite`)
-- entities (tables + KV namespaces): providerConnections, providerNodes, modelAliases, combos, apiKeys, settings, pricing, **customModels**, **proxyConfig**, **ipFilter**, **thinkingBudget**, **systemPrompt**
-
-Usage persistence:
-
-- facade: `src/lib/usageDb.ts` (decomposed modules in `src/lib/usage/*`)
-- SQLite tables in `storage.sqlite`: `usage_history`, `call_logs`, `proxy_logs`
-- optional file artifacts remain for compatibility/debug (`${DATA_DIR}/log.txt`, `${DATA_DIR}/call_logs/`, `/logs/...`)
-- legacy JSON files are migrated to SQLite by startup migrations when present
-
-Domain State DB (SQLite):
-
-- `src/lib/db/domainState.ts` — CRUD operations for domain state
-- Tables (created in `src/lib/db/core.ts`): `domain_fallback_chains`, `domain_budgets`, `domain_cost_history`, `domain_lockout_state`, `domain_circuit_breakers`
-- Write-through cache pattern: in-memory Maps are authoritative at runtime; mutations are written synchronously to SQLite; state is restored from DB on cold start
-
-## 4) Auth + Security Surfaces
-
-- Dashboard cookie auth: `src/proxy.ts`, `src/app/api/auth/login/route.ts`
-- API key generation/verification: `src/shared/utils/apiKey.ts`
-- Provider secrets persisted in `providerConnections` entries
-- Outbound proxy support via `open-sse/utils/proxyFetch.ts` (env vars) and `open-sse/utils/networkProxy.ts` (configurable per-provider or global)
-
-## 5) Cloud Sync
-
-- Scheduler init: `src/lib/initCloudSync.ts`, `src/shared/services/initializeCloudSync.ts`
-- Periodic task: `src/shared/services/cloudSyncScheduler.ts`
-- Control route: `src/app/api/sync/cloud/route.ts`
-
-## Request Lifecycle (`/v1/chat/completions`)
-
-```mermaid
-sequenceDiagram
- autonumber
- participant Client as CLI/SDK Client
- participant Route as /api/v1/chat/completions
- participant Chat as src/sse/handlers/chat
- participant Core as open-sse/handlers/chatCore
- participant Model as Model Resolver
- participant Auth as Credential Selector
- participant Exec as Provider Executor
- participant Prov as Upstream Provider
- participant Stream as Stream Translator
- participant Usage as usageDb
-
- Client->>Route: POST /v1/chat/completions
- Route->>Chat: handleChat(request)
- Chat->>Model: parse/resolve model or combo
-
- alt Combo model
- Chat->>Chat: iterate combo models (handleComboChat)
- end
-
- Chat->>Auth: getProviderCredentials(provider)
- Auth-->>Chat: active account + tokens/api key
-
- Chat->>Core: handleChatCore(body, modelInfo, credentials)
- Core->>Core: detect source format
- Core->>Core: translate request to target format
- Core->>Exec: execute(provider, transformedBody)
- Exec->>Prov: upstream API call
- Prov-->>Exec: SSE/JSON response
- Exec-->>Core: response + metadata
-
- alt 401/403
- Core->>Exec: refreshCredentials()
- Exec-->>Core: updated tokens
- Core->>Exec: retry request
- end
-
- Core->>Stream: translate/normalize stream to client format
- Stream-->>Client: SSE chunks / JSON response
-
- Stream->>Usage: extract usage + persist history/log
-```
-
-## Combo + Account Fallback Flow
-
-```mermaid
-flowchart TD
- A[Incoming model string] --> B{Is combo name?}
- B -- Yes --> C[Load combo models sequence]
- B -- No --> D[Single model path]
-
- C --> E[Try model N]
- E --> F[Resolve provider/model]
- D --> F
-
- F --> G[Select account credentials]
- G --> H{Credentials available?}
- H -- No --> I[Return provider unavailable]
- H -- Yes --> J[Execute request]
-
- J --> K{Success?}
- K -- Yes --> L[Return response]
- K -- No --> M{Fallback-eligible error?}
-
- M -- No --> N[Return error]
- M -- Yes --> O[Mark account unavailable cooldown]
- O --> P{Another account for provider?}
- P -- Yes --> G
- P -- No --> Q{In combo with next model?}
- Q -- Yes --> E
- Q -- No --> R[Return all unavailable]
-```
-
-Fallback decisions are driven by `open-sse/services/accountFallback.ts` using status codes and error-message heuristics.
-
-## OAuth Onboarding and Token Refresh Lifecycle
-
-```mermaid
-sequenceDiagram
- autonumber
- participant UI as Dashboard UI
- participant OAuth as /api/oauth/[provider]/[action]
- participant ProvAuth as Provider Auth Server
- participant DB as localDb
- participant Test as /api/providers/[id]/test
- participant Exec as Provider Executor
-
- UI->>OAuth: GET authorize or device-code
- OAuth->>ProvAuth: create auth/device flow
- ProvAuth-->>OAuth: auth URL or device code payload
- OAuth-->>UI: flow data
-
- UI->>OAuth: POST exchange or poll
- OAuth->>ProvAuth: token exchange/poll
- ProvAuth-->>OAuth: access/refresh tokens
- OAuth->>DB: createProviderConnection(oauth data)
- OAuth-->>UI: success + connection id
-
- UI->>Test: POST /api/providers/[id]/test
- Test->>Exec: validate credentials / optional refresh
- Exec-->>Test: valid or refreshed token info
- Test->>DB: update status/tokens/errors
- Test-->>UI: validation result
-```
-
-Refresh during live traffic is executed inside `open-sse/handlers/chatCore.ts` via executor `refreshCredentials()`.
-
-## Cloud Sync Lifecycle (Enable / Sync / Disable)
-
-```mermaid
-sequenceDiagram
- autonumber
- participant UI as Endpoint Page UI
- participant Sync as /api/sync/cloud
- participant DB as localDb
- participant Cloud as External Cloud Sync
- participant Claude as ~/.claude/settings.json
-
- UI->>Sync: POST action=enable
- Sync->>DB: set cloudEnabled=true
- Sync->>DB: ensure API key exists
- Sync->>Cloud: POST /sync/{machineId} (providers/aliases/combos/keys)
- Cloud-->>Sync: sync result
- Sync->>Cloud: GET /{machineId}/v1/verify
- Sync-->>UI: enabled + verification status
-
- UI->>Sync: POST action=sync
- Sync->>Cloud: POST /sync/{machineId}
- Cloud-->>Sync: remote data
- Sync->>DB: update newer local tokens/status
- Sync-->>UI: synced
-
- UI->>Sync: POST action=disable
- Sync->>DB: set cloudEnabled=false
- Sync->>Cloud: DELETE /sync/{machineId}
- Sync->>Claude: switch ANTHROPIC_BASE_URL back to local (if needed)
- Sync-->>UI: disabled
-```
-
-Periodic sync is triggered by `CloudSyncScheduler` when cloud is enabled.
-
-## Data Model and Storage Map
-
-```mermaid
-erDiagram
- SETTINGS ||--o{ PROVIDER_CONNECTION : controls
- PROVIDER_NODE ||--o{ PROVIDER_CONNECTION : backs_compatible_provider
- PROVIDER_CONNECTION ||--o{ USAGE_ENTRY : emits_usage
-
- SETTINGS {
- boolean cloudEnabled
- number stickyRoundRobinLimit
- boolean requireLogin
- string password_hash
- string fallbackStrategy
- json rateLimitDefaults
- json providerProfiles
- }
-
- PROVIDER_CONNECTION {
- string id
- string provider
- string authType
- string name
- number priority
- boolean isActive
- string apiKey
- string accessToken
- string refreshToken
- string expiresAt
- string testStatus
- string lastError
- string rateLimitedUntil
- json providerSpecificData
- }
-
- PROVIDER_NODE {
- string id
- string type
- string name
- string prefix
- string apiType
- string baseUrl
- }
-
- MODEL_ALIAS {
- string alias
- string targetModel
- }
-
- COMBO {
- string id
- string name
- string[] models
- }
-
- API_KEY {
- string id
- string name
- string key
- string machineId
- }
-
- USAGE_ENTRY {
- string provider
- string model
- number prompt_tokens
- number completion_tokens
- string connectionId
- string timestamp
- }
-
- CUSTOM_MODEL {
- string id
- string name
- string providerId
- }
-
- PROXY_CONFIG {
- string global
- json providers
- }
-
- IP_FILTER {
- string mode
- string[] allowlist
- string[] blocklist
- }
-
- THINKING_BUDGET {
- string mode
- number customBudget
- string effortLevel
- }
-
- SYSTEM_PROMPT {
- boolean enabled
- string prompt
- string position
- }
-```
-
-Physical storage files:
-
-- primary runtime DB: `${DATA_DIR}/storage.sqlite`
-- request log lines: `${DATA_DIR}/log.txt` (compat/debug artifact)
-- structured call payload archives: `${DATA_DIR}/call_logs/`
-- optional translator/request debug sessions: `/logs/...`
-
-## Deployment Topology
-
-```mermaid
-flowchart LR
- subgraph LocalHost[Developer Host]
- CLI[CLI Tools]
- Browser[Dashboard Browser]
- end
-
- subgraph ContainerOrProcess[OmniRoute Runtime]
- Next[Next.js Server\nPORT=20128]
- Core[SSE Core + Executors]
- MainDB[(storage.sqlite)]
- UsageDB[(usage tables + log artifacts)]
- end
-
- subgraph External[External Services]
- Providers[AI Providers]
- SyncCloud[Cloud Sync Service]
- end
-
- CLI --> Next
- Browser --> Next
- Next --> Core
- Next --> MainDB
- Core --> MainDB
- Core --> UsageDB
- Core --> Providers
- Next --> SyncCloud
-```
-
-## Module Mapping (Decision-Critical)
-
-### Route and API Modules
-
-- `src/app/api/v1/*`, `src/app/api/v1beta/*`: compatibility APIs
-- `src/app/api/v1/providers/[provider]/*`: dedicated per-provider routes (chat, embeddings, images)
-- `src/app/api/providers*`: provider CRUD, validation, testing
-- `src/app/api/provider-nodes*`: custom compatible node management
-- `src/app/api/provider-models`: custom model management (CRUD)
-- `src/app/api/models/route.ts`: model catalog API (aliases + custom models)
-- `src/app/api/oauth/*`: OAuth/device-code flows
-- `src/app/api/keys*`: local API key lifecycle
-- `src/app/api/models/alias`: alias management
-- `src/app/api/combos*`: fallback combo management
-- `src/app/api/pricing`: pricing overrides for cost calculation
-- `src/app/api/settings/proxy`: proxy configuration (GET/PUT/DELETE)
-- `src/app/api/settings/proxy/test`: outbound proxy connectivity test (POST)
-- `src/app/api/usage/*`: usage and logs APIs
-- `src/app/api/sync/*` + `src/app/api/cloud/*`: cloud sync and cloud-facing helpers
-- `src/app/api/cli-tools/*`: local CLI config writers/checkers
-- `src/app/api/settings/ip-filter`: IP allowlist/blocklist (GET/PUT)
-- `src/app/api/settings/thinking-budget`: thinking token budget config (GET/PUT)
-- `src/app/api/settings/system-prompt`: global system prompt (GET/PUT)
-- `src/app/api/sessions`: active session listing (GET)
-- `src/app/api/rate-limits`: per-account rate limit status (GET)
-
-### Routing and Execution Core
-
-- `src/sse/handlers/chat.ts`: request parse, combo handling, account selection loop
-- `open-sse/handlers/chatCore.ts`: translation, executor dispatch, retry/refresh handling, stream setup
-- `open-sse/executors/*`: provider-specific network and format behavior
-
-### Translation Registry and Format Converters
-
-- `open-sse/translator/index.ts`: translator registry and orchestration
-- Request translators: `open-sse/translator/request/*`
-- Response translators: `open-sse/translator/response/*`
-- Format constants: `open-sse/translator/formats.ts`
-
-### Persistence
-
-- `src/lib/db/*`: persistent config/state and domain persistence on SQLite
-- `src/lib/localDb.ts`: compatibility re-export for DB modules
-- `src/lib/usageDb.ts`: usage history/call logs facade on top of SQLite tables
-
-## Provider Executor Coverage (Strategy Pattern)
-
-Each provider has a specialized executor extending `BaseExecutor` (in `open-sse/executors/base.ts`), which provides URL building, header construction, retry with exponential backoff, credential refresh hooks, and the `execute()` orchestration method.
-
-| Executor | Provider(s) | Special Handling |
-| --------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------ | -------------------------------------------------------------------- |
-| `DefaultExecutor` | OpenAI, Claude, Gemini, Qwen, Qoder, OpenRouter, GLM, Kimi, MiniMax, DeepSeek, Groq, xAI, Mistral, Perplexity, Together, Fireworks, Cerebras, Cohere, NVIDIA | Dynamic URL/header config per provider |
-| `AntigravityExecutor` | Google Antigravity | Custom project/session IDs, Retry-After parsing |
-| `CodexExecutor` | OpenAI Codex | Injects system instructions, forces reasoning effort |
-| `CursorExecutor` | Cursor IDE | ConnectRPC protocol, Protobuf encoding, request signing via checksum |
-| `GithubExecutor` | GitHub Copilot | Copilot token refresh, VSCode-mimicking headers |
-| `KiroExecutor` | AWS CodeWhisperer/Kiro | AWS EventStream binary format → SSE conversion |
-| `GeminiCLIExecutor` | Gemini CLI | Google OAuth token refresh cycle |
-
-All other providers (including custom compatible nodes) use the `DefaultExecutor`.
-
-## Provider Compatibility Matrix
-
-| Provider | Format | Auth | Stream | Non-Stream | Token Refresh | Usage API |
-| ---------------- | ---------------- | --------------------- | ---------------- | ---------- | ------------- | ------------------ |
-| Claude | claude | API Key / OAuth | ✅ | ✅ | ✅ | ⚠️ Admin only |
-| Gemini | gemini | API Key / OAuth | ✅ | ✅ | ✅ | ⚠️ Cloud Console |
-| Gemini CLI | gemini-cli | OAuth | ✅ | ✅ | ✅ | ⚠️ Cloud Console |
-| Antigravity | antigravity | OAuth | ✅ | ✅ | ✅ | ✅ Full quota API |
-| OpenAI | openai | API Key | ✅ | ✅ | ❌ | ❌ |
-| Codex | openai-responses | OAuth | ✅ forced | ❌ | ✅ | ✅ Rate limits |
-| GitHub Copilot | openai | OAuth + Copilot Token | ✅ | ✅ | ✅ | ✅ Quota snapshots |
-| Cursor | cursor | Custom checksum | ✅ | ✅ | ❌ | ❌ |
-| Kiro | kiro | AWS SSO OIDC | ✅ (EventStream) | ❌ | ✅ | ✅ Usage limits |
-| Qwen | openai | OAuth | ✅ | ✅ | ✅ | ⚠️ Per request |
-| Qoder | openai | OAuth (Basic) | ✅ | ✅ | ✅ | ⚠️ Per request |
-| OpenRouter | openai | API Key | ✅ | ✅ | ❌ | ❌ |
-| GLM/Kimi/MiniMax | claude | API Key | ✅ | ✅ | ❌ | ❌ |
-| DeepSeek | openai | API Key | ✅ | ✅ | ❌ | ❌ |
-| Groq | openai | API Key | ✅ | ✅ | ❌ | ❌ |
-| xAI (Grok) | openai | API Key | ✅ | ✅ | ❌ | ❌ |
-| Mistral | openai | API Key | ✅ | ✅ | ❌ | ❌ |
-| Perplexity | openai | API Key | ✅ | ✅ | ❌ | ❌ |
-| Together AI | openai | API Key | ✅ | ✅ | ❌ | ❌ |
-| Fireworks AI | openai | API Key | ✅ | ✅ | ❌ | ❌ |
-| Cerebras | openai | API Key | ✅ | ✅ | ❌ | ❌ |
-| Cohere | openai | API Key | ✅ | ✅ | ❌ | ❌ |
-| NVIDIA NIM | openai | API Key | ✅ | ✅ | ❌ | ❌ |
-
-## Format Translation Coverage
-
-Detected source formats include:
-
-- `openai`
-- `openai-responses`
-- `claude`
-- `gemini`
-
-Target formats include:
-
-- OpenAI chat/Responses
-- Claude
-- Gemini/Gemini-CLI/Antigravity envelope
-- Kiro
-- Cursor
-
-Translations use **OpenAI as the hub format** — all conversions go through OpenAI as intermediate:
-
-```
-Source Format → OpenAI (hub) → Target Format
-```
-
-Translations are selected dynamically based on source payload shape and provider target format.
-
-Additional processing layers in the translation pipeline:
-
-- **Response sanitization** — Strips non-standard fields from OpenAI-format responses (both streaming and non-streaming) to ensure strict SDK compliance
-- **Role normalization** — Converts `developer` → `system` for non-OpenAI targets; merges `system` → `user` for models that reject the system role (GLM, ERNIE)
-- **Think tag extraction** — Parses `...` blocks from content into `reasoning_content` field
-- **Structured output** — Converts OpenAI `response_format.json_schema` to Gemini's `responseMimeType` + `responseSchema`
-
-## Supported API Endpoints
-
-| Endpoint | Format | Handler |
-| -------------------------------------------------- | ------------------ | ---------------------------------------------------- |
-| `POST /v1/chat/completions` | OpenAI Chat | `src/sse/handlers/chat.ts` |
-| `POST /v1/messages` | Claude Messages | Same handler (auto-detected) |
-| `POST /v1/responses` | OpenAI Responses | `open-sse/handlers/responsesHandler.ts` |
-| `POST /v1/embeddings` | OpenAI Embeddings | `open-sse/handlers/embeddings.ts` |
-| `GET /v1/embeddings` | Model listing | API route |
-| `POST /v1/images/generations` | OpenAI Images | `open-sse/handlers/imageGeneration.ts` |
-| `GET /v1/images/generations` | Model listing | API route |
-| `POST /v1/providers/{provider}/chat/completions` | OpenAI Chat | Dedicated per-provider with model validation |
-| `POST /v1/providers/{provider}/embeddings` | OpenAI Embeddings | Dedicated per-provider with model validation |
-| `POST /v1/providers/{provider}/images/generations` | OpenAI Images | Dedicated per-provider with model validation |
-| `POST /v1/messages/count_tokens` | Claude Token Count | API route |
-| `GET /v1/models` | OpenAI Models list | API route (chat + embedding + image + custom models) |
-| `GET /api/models/catalog` | Catalog | All models grouped by provider + type |
-| `POST /v1beta/models/*:streamGenerateContent` | Gemini native | API route |
-| `GET/PUT/DELETE /api/settings/proxy` | Proxy Config | Network proxy configuration |
-| `POST /api/settings/proxy/test` | Proxy Connectivity | Proxy health/connectivity test endpoint |
-| `GET/POST/DELETE /api/provider-models` | Custom Models | Custom model management per provider |
-
-## Bypass Handler
-
-The bypass handler (`open-sse/utils/bypassHandler.ts`) intercepts known "throwaway" requests from Claude CLI — warmup pings, title extractions, and token counts — and returns a **fake response** without consuming upstream provider tokens. This is triggered only when `User-Agent` contains `claude-cli`.
-
-## Request Logger Pipeline
-
-The request logger (`open-sse/utils/requestLogger.ts`) provides a 7-stage debug logging pipeline, disabled by default, enabled via `ENABLE_REQUEST_LOGS=true`:
-
-```
-1_req_client.json → 2_req_source.json → 3_req_openai.json → 4_req_target.json
-→ 5_res_provider.txt → 6_res_openai.txt → 7_res_client.txt
-```
-
-Files are written to `/logs//` for each request session.
-
-## Failure Modes and Resilience
-
-## 1) Account/Provider Availability
-
-- provider account cooldown on transient/rate/auth errors
-- account fallback before failing request
-- combo model fallback when current model/provider path is exhausted
-
-## 2) Token Expiry
-
-- pre-check and refresh with retry for refreshable providers
-- 401/403 retry after refresh attempt in core path
-
-## 3) Stream Safety
-
-- disconnect-aware stream controller
-- translation stream with end-of-stream flush and `[DONE]` handling
-- usage estimation fallback when provider usage metadata is missing
-
-## 4) Cloud Sync Degradation
-
-- sync errors are surfaced but local runtime continues
-- scheduler has retry-capable logic, but periodic execution currently calls single-attempt sync by default
-
-## 5) Data Integrity
-
-- SQLite schema migrations and auto-upgrade hooks at startup
-- legacy JSON → SQLite migration compatibility path
-
-## Observability and Operational Signals
-
-Runtime visibility sources:
-
-- console logs from `src/sse/utils/logger.ts`
-- per-request usage aggregates in SQLite (`usage_history`, `call_logs`, `proxy_logs`)
-- textual request status log in `log.txt` (optional/compat)
-- optional deep request/translation logs under `logs/` when `ENABLE_REQUEST_LOGS=true`
-- dashboard usage endpoints (`/api/usage/*`) for UI consumption
-
-## Security-Sensitive Boundaries
-
-- JWT secret (`JWT_SECRET`) secures dashboard session cookie verification/signing
-- Initial password bootstrap (`INITIAL_PASSWORD`) should be explicitly configured for first-run provisioning
-- API key HMAC secret (`API_KEY_SECRET`) secures generated local API key format
-- Provider secrets (API keys/tokens) are persisted in local DB and should be protected at filesystem level
-- Cloud sync endpoints rely on API key auth + machine id semantics
-
-## Environment and Runtime Matrix
-
-Environment variables actively used by code:
-
-- App/auth: `JWT_SECRET`, `INITIAL_PASSWORD`
-- Storage: `DATA_DIR`
-- Compatible node behavior: `ALLOW_MULTI_CONNECTIONS_PER_COMPAT_NODE`
-- Optional storage base override (Linux/macOS when `DATA_DIR` unset): `XDG_CONFIG_HOME`
-- Security hashing: `API_KEY_SECRET`, `MACHINE_ID_SALT`
-- Logging: `ENABLE_REQUEST_LOGS`
-- Sync/cloud URLing: `NEXT_PUBLIC_BASE_URL`, `NEXT_PUBLIC_CLOUD_URL`
-- Outbound proxy: `HTTP_PROXY`, `HTTPS_PROXY`, `ALL_PROXY`, `NO_PROXY` and lowercase variants
-- SOCKS5 feature flags: `ENABLE_SOCKS5_PROXY`, `NEXT_PUBLIC_ENABLE_SOCKS5_PROXY`
-- Platform/runtime helpers (not app-specific config): `APPDATA`, `NODE_ENV`, `PORT`, `HOSTNAME`
-
-## Known Architectural Notes
-
-1. `usageDb` and `localDb` share the same base directory policy (`DATA_DIR` -> `XDG_CONFIG_HOME/omniroute` -> `~/.omniroute`) with legacy file migration.
-2. `/api/v1/route.ts` delegates to the same unified catalog builder used by `/api/v1/models` (`src/app/api/v1/models/catalog.ts`) to avoid semantic drift.
-3. Request logger writes full headers/body when enabled; treat log directory as sensitive.
-4. Cloud behavior depends on correct `NEXT_PUBLIC_BASE_URL` and cloud endpoint reachability.
-5. The `open-sse/` directory is published as the `@omniroute/open-sse` **npm workspace package**. Source code imports it via `@omniroute/open-sse/...` (resolved by Next.js `transpilePackages`). File paths in this document still use the directory name `open-sse/` for consistency.
-6. Charts in the dashboard use **Recharts** (SVG-based) for accessible, interactive analytics visualizations (model usage bar charts, provider breakdown tables with success rates).
-7. E2E tests use **Playwright** (`tests/e2e/`), run via `npm run test:e2e`. Unit tests use **Node.js test runner** (`tests/unit/`), run via `npm run test:unit`. Source code under `src/` is **TypeScript** (`.ts`/`.tsx`); the `open-sse/` workspace remains JavaScript (`.js`).
-8. Settings page is organized into 5 tabs: Security, Routing (6 global strategies: fill-first, round-robin, p2c, random, least-used, cost-optimized), Resilience (editable rate limits, circuit breaker, policies), AI (thinking budget, system prompt, prompt cache), Advanced (proxy).
-
-## Operational Verification Checklist
-
-- Build from source: `npm run build`
-- Build Docker image: `docker build -t omniroute .`
-- Start service and verify:
-- `GET /api/settings`
-- `GET /api/v1/models`
-- CLI target base URL should be `http://:20128/v1` when `PORT=20128`
diff --git a/docs/i18n/it/AUTO-COMBO.md b/docs/i18n/it/AUTO-COMBO.md
deleted file mode 100644
index 2166e41dff..0000000000
--- a/docs/i18n/it/AUTO-COMBO.md
+++ /dev/null
@@ -1,67 +0,0 @@
-🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/AUTO-COMBO.md) · 🇪🇸 [es](../es/AUTO-COMBO.md) · 🇫🇷 [fr](../fr/AUTO-COMBO.md) · 🇩🇪 [de](../de/AUTO-COMBO.md) · 🇮🇹 [it](../it/AUTO-COMBO.md) · 🇷🇺 [ru](../ru/AUTO-COMBO.md) · 🇨🇳 [zh-CN](../zh-CN/AUTO-COMBO.md) · 🇯🇵 [ja](../ja/AUTO-COMBO.md) · 🇰🇷 [ko](../ko/AUTO-COMBO.md) · 🇸🇦 [ar](../ar/AUTO-COMBO.md) · 🇮🇳 [in](../in/AUTO-COMBO.md) · 🇹🇭 [th](../th/AUTO-COMBO.md) · 🇻🇳 [vi](../vi/AUTO-COMBO.md) · 🇮🇩 [id](../id/AUTO-COMBO.md) · 🇲🇾 [ms](../ms/AUTO-COMBO.md) · 🇳🇱 [nl](../nl/AUTO-COMBO.md) · 🇵🇱 [pl](../pl/AUTO-COMBO.md) · 🇸🇪 [sv](../sv/AUTO-COMBO.md) · 🇳🇴 [no](../no/AUTO-COMBO.md) · 🇩🇰 [da](../da/AUTO-COMBO.md) · 🇫🇮 [fi](../fi/AUTO-COMBO.md) · 🇵🇹 [pt](../pt/AUTO-COMBO.md) · 🇷🇴 [ro](../ro/AUTO-COMBO.md) · 🇭🇺 [hu](../hu/AUTO-COMBO.md) · 🇧🇬 [bg](../bg/AUTO-COMBO.md) · 🇸🇰 [sk](../sk/AUTO-COMBO.md) · 🇺🇦 [uk-UA](../uk-UA/AUTO-COMBO.md) · 🇮🇱 [he](../he/AUTO-COMBO.md) · 🇵🇭 [phi](../phi/AUTO-COMBO.md)
-
----
-
-# OmniRoute Auto-Combo Engine
-
-> Self-managing model chains with adaptive scoring
-
-## How It Works
-
-The Auto-Combo Engine dynamically selects the best provider/model for each request using a **6-factor scoring function**:
-
-| Factor | Weight | Description |
-| :--------- | :----- | :---------------------------------------------- |
-| Quota | 0.20 | Remaining capacity [0..1] |
-| Health | 0.25 | Circuit breaker: CLOSED=1.0, HALF=0.5, OPEN=0.0 |
-| CostInv | 0.20 | Inverse cost (cheaper = higher score) |
-| LatencyInv | 0.15 | Inverse p95 latency (faster = higher) |
-| TaskFit | 0.10 | Model × task type fitness score |
-| Stability | 0.10 | Low variance in latency/errors |
-
-## Mode Packs
-
-| Pack | Focus | Key Weight |
-| :---------------------- | :----------- | :--------------- |
-| 🚀 **Ship Fast** | Speed | latencyInv: 0.35 |
-| 💰 **Cost Saver** | Economy | costInv: 0.40 |
-| 🎯 **Quality First** | Best model | taskFit: 0.40 |
-| 📡 **Offline Friendly** | Availability | quota: 0.40 |
-
-## Self-Healing
-
-- **Temporary exclusion**: Score < 0.2 → excluded for 5 min (progressive backoff, max 30 min)
-- **Circuit breaker awareness**: OPEN → auto-excluded; HALF_OPEN → probe requests
-- **Incident mode**: >50% OPEN → disable exploration, maximize stability
-- **Cooldown recovery**: After exclusion, first request is a "probe" with reduced timeout
-
-## Bandit Exploration
-
-5% of requests (configurable) are routed to random providers for exploration. Disabled in incident mode.
-
-## API
-
-```bash
-# Create auto-combo
-curl -X POST http://localhost:20128/api/combos/auto \
- -H "Content-Type: application/json" \
- -d '{"id":"my-auto","name":"Auto Coder","candidatePool":["anthropic","google","openai"],"modePack":"ship-fast"}'
-
-# List auto-combos
-curl http://localhost:20128/api/combos/auto
-```
-
-## Task Fitness
-
-30+ models scored across 6 task types (`coding`, `review`, `planning`, `analysis`, `debugging`, `documentation`). Supports wildcard patterns (e.g., `*-coder` → high coding score).
-
-## Files
-
-| File | Purpose |
-| :------------------------------------------- | :------------------------------------ |
-| `open-sse/services/autoCombo/scoring.ts` | Scoring function & pool normalization |
-| `open-sse/services/autoCombo/taskFitness.ts` | Model × task fitness lookup |
-| `open-sse/services/autoCombo/engine.ts` | Selection logic, bandit, budget cap |
-| `open-sse/services/autoCombo/selfHealing.ts` | Exclusion, probes, incident mode |
-| `open-sse/services/autoCombo/modePacks.ts` | 4 weight profiles |
-| `src/app/api/combos/auto/route.ts` | REST API |
diff --git a/docs/i18n/it/CHANGELOG.md b/docs/i18n/it/CHANGELOG.md
index bbe64fcbb5..f167a83689 100644
--- a/docs/i18n/it/CHANGELOG.md
+++ b/docs/i18n/it/CHANGELOG.md
@@ -1,12 +1,92 @@
# Changelog (Italiano)
-🌐 **Languages:** 🇺🇸 [English](../../../CHANGELOG.md) · 🇪🇸 [es](../es/CHANGELOG.md) · 🇫🇷 [fr](../fr/CHANGELOG.md) · 🇩🇪 [de](../de/CHANGELOG.md) · 🇮🇹 [it](../it/CHANGELOG.md) · 🇷🇺 [ru](../ru/CHANGELOG.md) · 🇨🇳 [zh-CN](../zh-CN/CHANGELOG.md) · 🇯🇵 [ja](../ja/CHANGELOG.md) · 🇰🇷 [ko](../ko/CHANGELOG.md) · 🇸🇦 [ar](../ar/CHANGELOG.md) · 🇮🇳 [in](../in/CHANGELOG.md) · 🇹🇭 [th](../th/CHANGELOG.md) · 🇻🇳 [vi](../vi/CHANGELOG.md) · 🇮🇩 [id](../id/CHANGELOG.md) · 🇲🇾 [ms](../ms/CHANGELOG.md) · 🇳🇱 [nl](../nl/CHANGELOG.md) · 🇵🇱 [pl](../pl/CHANGELOG.md) · 🇸🇪 [sv](../sv/CHANGELOG.md) · 🇳🇴 [no](../no/CHANGELOG.md) · 🇩🇰 [da](../da/CHANGELOG.md) · 🇫🇮 [fi](../fi/CHANGELOG.md) · 🇵🇹 [pt](../pt/CHANGELOG.md) · 🇷🇴 [ro](../ro/CHANGELOG.md) · 🇭🇺 [hu](../hu/CHANGELOG.md) · 🇧🇬 [bg](../bg/CHANGELOG.md) · 🇸🇰 [sk](../sk/CHANGELOG.md) · 🇺🇦 [uk-UA](../uk-UA/CHANGELOG.md) · 🇮🇱 [he](../he/CHANGELOG.md) · 🇵🇭 [phi](../phi/CHANGELOG.md) · 🇧🇷 [pt-BR](../pt-BR/CHANGELOG.md)
+🌐 **Languages:** 🇺🇸 [English](../../../CHANGELOG.md) · 🇪🇸 [es](../es/CHANGELOG.md) · 🇫🇷 [fr](../fr/CHANGELOG.md) · 🇩🇪 [de](../de/CHANGELOG.md) · 🇮🇹 [it](../it/CHANGELOG.md) · 🇷🇺 [ru](../ru/CHANGELOG.md) · 🇨🇳 [zh-CN](../zh-CN/CHANGELOG.md) · 🇯🇵 [ja](../ja/CHANGELOG.md) · 🇰🇷 [ko](../ko/CHANGELOG.md) · 🇸🇦 [ar](../ar/CHANGELOG.md) · 🇮🇳 [in](../in/CHANGELOG.md) · 🇹🇭 [th](../th/CHANGELOG.md) · 🇻🇳 [vi](../vi/CHANGELOG.md) · 🇮🇩 [id](../id/CHANGELOG.md) · 🇲🇾 [ms](../ms/CHANGELOG.md) · 🇳🇱 [nl](../nl/CHANGELOG.md) · 🇵🇱 [pl](../pl/CHANGELOG.md) · 🇸🇪 [sv](../sv/CHANGELOG.md) · 🇳🇴 [no](../no/CHANGELOG.md) · 🇩🇰 [da](../da/CHANGELOG.md) · 🇫🇮 [fi](../fi/CHANGELOG.md) · 🇵🇹 [pt](../pt/CHANGELOG.md) · 🇷🇴 [ro](../ro/CHANGELOG.md) · 🇭🇺 [hu](../hu/CHANGELOG.md) · 🇧🇬 [bg](../bg/CHANGELOG.md) · 🇸🇰 [sk](../sk/CHANGELOG.md) · 🇺🇦 [uk-UA](../uk-UA/CHANGELOG.md) · 🇮🇱 [he](../he/CHANGELOG.md) · 🇵🇭 [phi](../phi/CHANGELOG.md) · 🇧🇷 [pt-BR](../pt-BR/CHANGELOG.md) · 🇨🇿 [cs](../cs/CHANGELOG.md)
---
-
## [Unreleased]
+### 🛠️ Maintenance
+
+- **AGENTS.md rewrite:** Condensed from 297→153 lines. Added build/lint/test commands (including single-test execution), code style guidelines (Prettier, TypeScript, ESLint, naming, imports, error handling, security), and trimmed verbose architecture tables for AI agent consumption.
+
+## [3.4.2] - 2026-04-01
+
+### 🐛 Bug Fixes
+
+- **CI Stabilization:** Fixed failing analytics/settings Playwright selectors and request assertions so GitHub Actions E2E runs pass reliably across localized UIs and switch-based controls.
+- **Deterministic Tests:** Removed date-sensitive quota fixtures from Copilot usage tests and aligned idempotency/model catalog tests with the merged runtime behavior.
+- **MCP Type Hardening:** Removed zero-budget explicit `any` regressions from the MCP server tool registration path, restoring the `check:any-budget:t11` workflow gate.
+
+### 🛠️ Maintenance
+
+- **Release Branch Integration:** Consolidated the active feature branches into `release/v3.4.2` on top of current `main` and validated the branch with lint, unit, coverage, build, and CI-mode E2E runs.
+
+## [3.4.1] - 2026-03-31
+
+> [!WARNING]
+> **BREAKING CHANGE: request logging, retention, and logging environment variables have been redesigned.**
+> On the first startup after upgrading, OmniRoute archives legacy request logs from `DATA_DIR/logs/`, legacy `DATA_DIR/call_logs/`, and `DATA_DIR/log.txt` into `DATA_DIR/log_archives/*.zip`, then removes the deprecated layout and switches to the new unified artifact format under `DATA_DIR/call_logs/`.
+
+### ✨ New Features
+
+- **.ENV Migration Utility:** Included `scripts/migrate-env.mjs` to seamlessly migrate ` Your key looks like: `sk-xxxxxxxxxxxxxxxx-xxxxxxxxx`
-
----
-
-## Step 2 — Install CLI Tools
-
-All npm-based tools require Node.js 18+:
-
-```bash
-# Claude Code (Anthropic)
-npm install -g @anthropic-ai/claude-code
-
-# OpenAI Codex
-npm install -g @openai/codex
-
-# Gemini CLI (Google)
-npm install -g @google/gemini-cli
-
-# OpenCode
-npm install -g opencode-ai
-
-# Cline
-npm install -g cline
-
-# KiloCode
-npm install -g kilecode
-
-# Kiro CLI (Amazon — requires curl + unzip)
-apt-get install -y unzip # on Debian/Ubuntu
-curl -fsSL https://cli.kiro.dev/install | bash
-export PATH="$HOME/.local/bin:$PATH" # add to ~/.bashrc
-```
-
-**Verify:**
-
-```bash
-claude --version # 2.x.x
-codex --version # 0.x.x
-gemini --version # 0.x.x
-opencode --version # x.x.x
-cline --version # 2.x.x
-kilocode --version # x.x.x (or: kilo --version)
-kiro-cli --version # 1.x.x
-```
-
----
-
-## Step 3 — Set Global Environment Variables
-
-Add to `~/.bashrc` (or `~/.zshrc`), then run `source ~/.bashrc`:
-
-```bash
-# OmniRoute Universal Endpoint
-export OPENAI_BASE_URL="http://localhost:20128/v1"
-export OPENAI_API_KEY="sk-your-omniroute-key"
-export ANTHROPIC_BASE_URL="http://localhost:20128/v1"
-export ANTHROPIC_API_KEY="sk-your-omniroute-key"
-export GEMINI_BASE_URL="http://localhost:20128/v1"
-export GEMINI_API_KEY="sk-your-omniroute-key"
-```
-
-> For a **remote server** replace `localhost:20128` with the server IP or domain,
-> e.g. `http://192.168.0.15:20128`.
-
----
-
-## Step 4 — Configure Each Tool
-
-### Claude Code
-
-```bash
-# Via CLI:
-claude config set --global api-base-url http://localhost:20128/v1
-
-# Or create ~/.claude/settings.json:
-mkdir -p ~/.claude && cat > ~/.claude/settings.json << EOF
-{
- "apiBaseUrl": "http://localhost:20128/v1",
- "apiKey": "sk-your-omniroute-key"
-}
-EOF
-```
-
-**Test:** `claude "say hello"`
-
----
-
-### OpenAI Codex
-
-```bash
-mkdir -p ~/.codex && cat > ~/.codex/config.yaml << EOF
-model: auto
-apiKey: sk-your-omniroute-key
-apiBaseUrl: http://localhost:20128/v1
-EOF
-```
-
-**Test:** `codex "what is 2+2?"`
-
----
-
-### Gemini CLI
-
-```bash
-mkdir -p ~/.gemini && cat > ~/.gemini/settings.json << EOF
-{
- "apiKey": "sk-your-omniroute-key",
- "baseUrl": "http://localhost:20128/v1"
-}
-EOF
-```
-
-**Test:** `gemini "hello"`
-
----
-
-### OpenCode
-
-```bash
-mkdir -p ~/.config/opencode && cat > ~/.config/opencode/config.toml << EOF
-[provider.openai]
-base_url = "http://localhost:20128/v1"
-api_key = "sk-your-omniroute-key"
-EOF
-```
-
-**Test:** `opencode`
-
----
-
-### Cline (CLI or VS Code)
-
-**CLI mode:**
-
-```bash
-mkdir -p ~/.cline/data && cat > ~/.cline/data/globalState.json << EOF
-{
- "apiProvider": "openai",
- "openAiBaseUrl": "http://localhost:20128/v1",
- "openAiApiKey": "sk-your-omniroute-key"
-}
-EOF
-```
-
-**VS Code mode:**
-Cline extension settings → API Provider: `OpenAI Compatible` → Base URL: `http://localhost:20128/v1`
-
-Or use the OmniRoute dashboard → **CLI Tools → Cline → Apply Config**.
-
----
-
-### KiloCode (CLI or VS Code)
-
-**CLI mode:**
-
-```bash
-kilocode --api-base http://localhost:20128/v1 --api-key sk-your-omniroute-key
-```
-
-**VS Code settings:**
-
-```json
-{
- "kilo-code.openAiBaseUrl": "http://localhost:20128/v1",
- "kilo-code.apiKey": "sk-your-omniroute-key"
-}
-```
-
-Or use the OmniRoute dashboard → **CLI Tools → KiloCode → Apply Config**.
-
----
-
-### Continue (VS Code Extension)
-
-Edit `~/.continue/config.yaml`:
-
-```yaml
-models:
- - name: OmniRoute
- provider: openai
- model: auto
- apiBase: http://localhost:20128/v1
- apiKey: sk-your-omniroute-key
- default: true
-```
-
-Restart VS Code after editing.
-
----
-
-### Kiro CLI (Amazon)
-
-```bash
-# Login to your AWS/Kiro account:
-kiro-cli login
-
-# The CLI uses its own auth — OmniRoute is not needed as backend for Kiro CLI itself.
-# Use kiro-cli alongside OmniRoute for other tools.
-kiro-cli status
-```
-
----
-
-### Cursor (Desktop App)
-
-> **Note:** Cursor routes requests through its cloud. For OmniRoute integration,
-> enable **Cloud Endpoint** in OmniRoute Settings and use your public domain URL.
-
-Via GUI: **Settings → Models → OpenAI API Key**
-
-- Base URL: `https://your-domain.com/v1`
-- API Key: your OmniRoute key
-
----
-
-## Dashboard Auto-Configuration
-
-The OmniRoute dashboard automates configuration for most tools:
-
-1. Go to `http://localhost:20128/dashboard/cli-tools`
-2. Expand any tool card
-3. Select your API key from the dropdown
-4. Click **Apply Config** (if tool is detected as installed)
-5. Or copy the generated config snippet manually
-
----
-
-## Built-in Agents: Droid & OpenClaw
-
-**Droid** and **OpenClaw** are AI agents built directly into OmniRoute — no installation needed.
-They run as internal routes and use OmniRoute's model routing automatically.
-
-- Access: `http://localhost:20128/dashboard/agents`
-- Configure: same combos and providers as all other tools
-- No API key or CLI install required
-
----
-
-## Available API Endpoints
-
-| Endpoint | Description | Use For |
-| -------------------------- | ----------------------------- | --------------------------- |
-| `/v1/chat/completions` | Standard chat (all providers) | All modern tools |
-| `/v1/responses` | Responses API (OpenAI format) | Codex, agentic workflows |
-| `/v1/completions` | Legacy text completions | Older tools using `prompt:` |
-| `/v1/embeddings` | Text embeddings | RAG, search |
-| `/v1/images/generations` | Image generation | DALL-E, Flux, etc. |
-| `/v1/audio/speech` | Text-to-speech | ElevenLabs, OpenAI TTS |
-| `/v1/audio/transcriptions` | Speech-to-text | Deepgram, AssemblyAI |
-
----
-
-## Troubleshooting
-
-| Error | Cause | Fix |
-| ------------------------- | ----------------------- | ------------------------------------------ |
-| `Connection refused` | OmniRoute not running | `pm2 start omniroute` |
-| `401 Unauthorized` | Wrong API key | Check in `/dashboard/api-manager` |
-| `No combo configured` | No active routing combo | Set up in `/dashboard/combos` |
-| `invalid model` | Model not in catalog | Use `auto` or check `/dashboard/providers` |
-| CLI shows "not installed" | Binary not in PATH | Check `which ` |
-| `kiro-cli: not found` | Not in PATH | `export PATH="$HOME/.local/bin:$PATH"` |
-
----
-
-## Quick Setup Script (One Command)
-
-```bash
-# Install all CLIs and configure for OmniRoute (replace with your key and server URL)
-OMNIROUTE_URL="http://localhost:20128/v1"
-OMNIROUTE_KEY="sk-your-omniroute-key"
-
-npm install -g @anthropic-ai/claude-code @openai/codex @google/gemini-cli opencode-ai cline kilecode
-
-# Kiro CLI
-apt-get install -y unzip 2>/dev/null; curl -fsSL https://cli.kiro.dev/install | bash
-
-# Write configs
-mkdir -p ~/.claude ~/.codex ~/.gemini ~/.config/opencode ~/.continue
-
-cat > ~/.claude/settings.json <<< "{\"apiBaseUrl\":\"$OMNIROUTE_URL\",\"apiKey\":\"$OMNIROUTE_KEY\"}"
-cat > ~/.codex/config.yaml <<< "model: auto\napiKey: $OMNIROUTE_KEY\napiBaseUrl: $OMNIROUTE_URL"
-cat > ~/.gemini/settings.json <<< "{\"apiKey\":\"$OMNIROUTE_KEY\",\"baseUrl\":\"$OMNIROUTE_URL\"}"
-cat >> ~/.bashrc << EOF
-export OPENAI_BASE_URL="$OMNIROUTE_URL"
-export OPENAI_API_KEY="$OMNIROUTE_KEY"
-export ANTHROPIC_BASE_URL="$OMNIROUTE_URL"
-export ANTHROPIC_API_KEY="$OMNIROUTE_KEY"
-EOF
-
-source ~/.bashrc
-echo "✅ All CLIs installed and configured for OmniRoute"
-```
diff --git a/docs/i18n/it/CODEBASE_DOCUMENTATION.md b/docs/i18n/it/CODEBASE_DOCUMENTATION.md
deleted file mode 100644
index e2d7950052..0000000000
--- a/docs/i18n/it/CODEBASE_DOCUMENTATION.md
+++ /dev/null
@@ -1,593 +0,0 @@
-🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/CODEBASE_DOCUMENTATION.md) · 🇪🇸 [es](../es/CODEBASE_DOCUMENTATION.md) · 🇫🇷 [fr](../fr/CODEBASE_DOCUMENTATION.md) · 🇩🇪 [de](../de/CODEBASE_DOCUMENTATION.md) · 🇮🇹 [it](../it/CODEBASE_DOCUMENTATION.md) · 🇷🇺 [ru](../ru/CODEBASE_DOCUMENTATION.md) · 🇨🇳 [zh-CN](../zh-CN/CODEBASE_DOCUMENTATION.md) · 🇯🇵 [ja](../ja/CODEBASE_DOCUMENTATION.md) · 🇰🇷 [ko](../ko/CODEBASE_DOCUMENTATION.md) · 🇸🇦 [ar](../ar/CODEBASE_DOCUMENTATION.md) · 🇮🇳 [in](../in/CODEBASE_DOCUMENTATION.md) · 🇹🇭 [th](../th/CODEBASE_DOCUMENTATION.md) · 🇻🇳 [vi](../vi/CODEBASE_DOCUMENTATION.md) · 🇮🇩 [id](../id/CODEBASE_DOCUMENTATION.md) · 🇲🇾 [ms](../ms/CODEBASE_DOCUMENTATION.md) · 🇳🇱 [nl](../nl/CODEBASE_DOCUMENTATION.md) · 🇵🇱 [pl](../pl/CODEBASE_DOCUMENTATION.md) · 🇸🇪 [sv](../sv/CODEBASE_DOCUMENTATION.md) · 🇳🇴 [no](../no/CODEBASE_DOCUMENTATION.md) · 🇩🇰 [da](../da/CODEBASE_DOCUMENTATION.md) · 🇫🇮 [fi](../fi/CODEBASE_DOCUMENTATION.md) · 🇵🇹 [pt](../pt/CODEBASE_DOCUMENTATION.md) · 🇷🇴 [ro](../ro/CODEBASE_DOCUMENTATION.md) · 🇭🇺 [hu](../hu/CODEBASE_DOCUMENTATION.md) · 🇧🇬 [bg](../bg/CODEBASE_DOCUMENTATION.md) · 🇸🇰 [sk](../sk/CODEBASE_DOCUMENTATION.md) · 🇺🇦 [uk-UA](../uk-UA/CODEBASE_DOCUMENTATION.md) · 🇮🇱 [he](../he/CODEBASE_DOCUMENTATION.md) · 🇵🇭 [phi](../phi/CODEBASE_DOCUMENTATION.md)
-
----
-
-# omniroute — Codebase Documentation
-
-🌐 **Languages:** 🇺🇸 [English](CODEBASE_DOCUMENTATION.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/CODEBASE_DOCUMENTATION.md) | 🇪🇸 [Español](i18n/es/CODEBASE_DOCUMENTATION.md) | 🇫🇷 [Français](i18n/fr/CODEBASE_DOCUMENTATION.md) | 🇮🇹 [Italiano](i18n/it/CODEBASE_DOCUMENTATION.md) | 🇷🇺 [Русский](i18n/ru/CODEBASE_DOCUMENTATION.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/CODEBASE_DOCUMENTATION.md) | 🇩🇪 [Deutsch](i18n/de/CODEBASE_DOCUMENTATION.md) | 🇮🇳 [हिन्दी](i18n/in/CODEBASE_DOCUMENTATION.md) | 🇹🇭 [ไทย](i18n/th/CODEBASE_DOCUMENTATION.md) | 🇺🇦 [Українська](i18n/uk-UA/CODEBASE_DOCUMENTATION.md) | 🇸🇦 [العربية](i18n/ar/CODEBASE_DOCUMENTATION.md) | 🇯🇵 [日本語](i18n/ja/CODEBASE_DOCUMENTATION.md) | 🇻🇳 [Tiếng Việt](i18n/vi/CODEBASE_DOCUMENTATION.md) | 🇧🇬 [Български](i18n/bg/CODEBASE_DOCUMENTATION.md) | 🇩🇰 [Dansk](i18n/da/CODEBASE_DOCUMENTATION.md) | 🇫🇮 [Suomi](i18n/fi/CODEBASE_DOCUMENTATION.md) | 🇮🇱 [עברית](i18n/he/CODEBASE_DOCUMENTATION.md) | 🇭🇺 [Magyar](i18n/hu/CODEBASE_DOCUMENTATION.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/CODEBASE_DOCUMENTATION.md) | 🇰🇷 [한국어](i18n/ko/CODEBASE_DOCUMENTATION.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/CODEBASE_DOCUMENTATION.md) | 🇳🇱 [Nederlands](i18n/nl/CODEBASE_DOCUMENTATION.md) | 🇳🇴 [Norsk](i18n/no/CODEBASE_DOCUMENTATION.md) | 🇵🇹 [Português (Portugal)](i18n/pt/CODEBASE_DOCUMENTATION.md) | 🇷🇴 [Română](i18n/ro/CODEBASE_DOCUMENTATION.md) | 🇵🇱 [Polski](i18n/pl/CODEBASE_DOCUMENTATION.md) | 🇸🇰 [Slovenčina](i18n/sk/CODEBASE_DOCUMENTATION.md) | 🇸🇪 [Svenska](i18n/sv/CODEBASE_DOCUMENTATION.md) | 🇵🇭 [Filipino](i18n/phi/CODEBASE_DOCUMENTATION.md)
-
-> A comprehensive, beginner-friendly guide to the **omniroute** multi-provider AI proxy router.
-
----
-
-## 1. What Is omniroute?
-
-omniroute is a **proxy router** that sits between AI clients (Claude CLI, Codex, Cursor IDE, etc.) and AI providers (Anthropic, Google, OpenAI, AWS, GitHub, etc.). It solves one big problem:
-
-> **Different AI clients speak different "languages" (API formats), and different AI providers expect different "languages" too.** omniroute translates between them automatically.
-
-Think of it like a universal translator at the United Nations — any delegate can speak any language, and the translator converts it for any other delegate.
-
----
-
-## 2. Architecture Overview
-
-```mermaid
-graph LR
- subgraph Clients
- A[Claude CLI]
- B[Codex]
- C[Cursor IDE]
- D[OpenAI-compatible]
- end
-
- subgraph omniroute
- E[Handler Layer]
- F[Translator Layer]
- G[Executor Layer]
- H[Services Layer]
- end
-
- subgraph Providers
- I[Anthropic Claude]
- J[Google Gemini]
- K[OpenAI / Codex]
- L[GitHub Copilot]
- M[AWS Kiro]
- N[Antigravity]
- O[Cursor API]
- end
-
- A --> E
- B --> E
- C --> E
- D --> E
- E --> F
- F --> G
- G --> I
- G --> J
- G --> K
- G --> L
- G --> M
- G --> N
- G --> O
- H -.-> E
- H -.-> G
-```
-
-### Core Principle: Hub-and-Spoke Translation
-
-All format translation passes through **OpenAI format as the hub**:
-
-```
-Client Format → [OpenAI Hub] → Provider Format (request)
-Provider Format → [OpenAI Hub] → Client Format (response)
-```
-
-This means you only need **N translators** (one per format) instead of **N²** (every pair).
-
----
-
-## 3. Project Structure
-
-```
-omniroute/
-├── open-sse/ ← Core proxy library (portable, framework-agnostic)
-│ ├── index.js ← Main entry point, exports everything
-│ ├── config/ ← Configuration & constants
-│ ├── executors/ ← Provider-specific request execution
-│ ├── handlers/ ← Request handling orchestration
-│ ├── services/ ← Business logic (auth, models, fallback, usage)
-│ ├── translator/ ← Format translation engine
-│ │ ├── request/ ← Request translators (8 files)
-│ │ ├── response/ ← Response translators (7 files)
-│ │ └── helpers/ ← Shared translation utilities (6 files)
-│ └── utils/ ← Utility functions
-├── src/ ← Application layer (Express/Worker runtime)
-│ ├── app/ ← Web UI, API routes, middleware
-│ ├── lib/ ← Database, auth, and shared library code
-│ ├── mitm/ ← Man-in-the-middle proxy utilities
-│ ├── models/ ← Database models
-│ ├── shared/ ← Shared utilities (wrappers around open-sse)
-│ ├── sse/ ← SSE endpoint handlers
-│ └── store/ ← State management
-├── data/ ← Runtime data (credentials, logs)
-│ └── provider-credentials.json (external credentials override, gitignored)
-└── tester/ ← Test utilities
-```
-
----
-
-## 4. Module-by-Module Breakdown
-
-### 4.1 Config (`open-sse/config/`)
-
-The **single source of truth** for all provider configuration.
-
-| File | Purpose |
-| ----------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| `constants.ts` | `PROVIDERS` object with base URLs, OAuth credentials (defaults), headers, and default system prompts for every provider. Also defines `HTTP_STATUS`, `ERROR_TYPES`, `COOLDOWN_MS`, `BACKOFF_CONFIG`, and `SKIP_PATTERNS`. |
-| `credentialLoader.ts` | Loads external credentials from `data/provider-credentials.json` and merges them over the hardcoded defaults in `PROVIDERS`. Keeps secrets out of source control while maintaining backwards compatibility. |
-| `providerModels.ts` | Central model registry: maps provider aliases → model IDs. Functions like `getModels()`, `getProviderByAlias()`. |
-| `codexInstructions.ts` | System instructions injected into Codex requests (editing constraints, sandbox rules, approval policies). |
-| `defaultThinkingSignature.ts` | Default "thinking" signatures for Claude and Gemini models. |
-| `ollamaModels.ts` | Schema definition for local Ollama models (name, size, family, quantization). |
-
-#### Credential Loading Flow
-
-```mermaid
-flowchart TD
- A["App starts"] --> B["constants.ts defines PROVIDERS\nwith hardcoded defaults"]
- B --> C{"data/provider-credentials.json\nexists?"}
- C -->|Yes| D["credentialLoader reads JSON"]
- C -->|No| E["Use hardcoded defaults"]
- D --> F{"For each provider in JSON"}
- F --> G{"Provider exists\nin PROVIDERS?"}
- G -->|No| H["Log warning, skip"]
- G -->|Yes| I{"Value is object?"}
- I -->|No| J["Log warning, skip"]
- I -->|Yes| K["Merge clientId, clientSecret,\ntokenUrl, authUrl, refreshUrl"]
- K --> F
- H --> F
- J --> F
- F -->|Done| L["PROVIDERS ready with\nmerged credentials"]
- E --> L
-```
-
----
-
-### 4.2 Executors (`open-sse/executors/`)
-
-Executors encapsulate **provider-specific logic** using the **Strategy Pattern**. Each executor overrides base methods as needed.
-
-```mermaid
-classDiagram
- class BaseExecutor {
- +buildUrl(model, stream, options)
- +buildHeaders(credentials, stream, body)
- +transformRequest(body, model, stream, credentials)
- +execute(url, options)
- +shouldRetry(status, error)
- +refreshCredentials(credentials, log)
- }
-
- class DefaultExecutor {
- +refreshCredentials()
- }
-
- class AntigravityExecutor {
- +buildUrl()
- +buildHeaders()
- +transformRequest()
- +shouldRetry()
- +refreshCredentials()
- }
-
- class CursorExecutor {
- +buildUrl()
- +buildHeaders()
- +transformRequest()
- +parseResponse()
- +generateChecksum()
- }
-
- class KiroExecutor {
- +buildUrl()
- +buildHeaders()
- +transformRequest()
- +parseEventStream()
- +refreshCredentials()
- }
-
- BaseExecutor <|-- DefaultExecutor
- BaseExecutor <|-- AntigravityExecutor
- BaseExecutor <|-- CursorExecutor
- BaseExecutor <|-- KiroExecutor
- BaseExecutor <|-- CodexExecutor
- BaseExecutor <|-- GeminiCLIExecutor
- BaseExecutor <|-- GithubExecutor
-```
-
-| Executor | Provider | Key Specializations |
-| ---------------- | ------------------------------------------ | ------------------------------------------------------------------------------------------------------------------- |
-| `base.ts` | — | Abstract base: URL building, headers, retry logic, credential refresh |
-| `default.ts` | Claude, Gemini, OpenAI, GLM, Kimi, MiniMax | Generic OAuth token refresh for standard providers |
-| `antigravity.ts` | Google Cloud Code | Project/session ID generation, multi-URL fallback, custom retry parsing from error messages ("reset after 2h7m23s") |
-| `cursor.ts` | Cursor IDE | **Most complex**: SHA-256 checksum auth, Protobuf request encoding, binary EventStream → SSE response parsing |
-| `codex.ts` | OpenAI Codex | Injects system instructions, manages thinking levels, removes unsupported parameters |
-| `gemini-cli.ts` | Google Gemini CLI | Custom URL building (`streamGenerateContent`), Google OAuth token refresh |
-| `github.ts` | GitHub Copilot | Dual token system (GitHub OAuth + Copilot token), VSCode header mimicking |
-| `kiro.ts` | AWS CodeWhisperer | AWS EventStream binary parsing, AMZN event frames, token estimation |
-| `index.ts` | — | Factory: maps provider name → executor class, with default fallback |
-
----
-
-### 4.3 Handlers (`open-sse/handlers/`)
-
-The **orchestration layer** — coordinates translation, execution, streaming, and error handling.
-
-| File | Purpose |
-| --------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| `chatCore.ts` | **Central orchestrator** (~600 lines). Handles the complete request lifecycle: format detection → translation → executor dispatch → streaming/non-streaming response → token refresh → error handling → usage logging. |
-| `responsesHandler.ts` | Adapter for OpenAI's Responses API: converts Responses format → Chat Completions → sends to `chatCore` → converts SSE back to Responses format. |
-| `embeddings.ts` | Embedding generation handler: resolves embedding model → provider, dispatches to provider API, returns OpenAI-compatible embedding response. Supports 6+ providers. |
-| `imageGeneration.ts` | Image generation handler: resolves image model → provider, supports OpenAI-compatible, Gemini-image (Antigravity), and fallback (Nebius) modes. Returns base64 or URL images. |
-
-#### Request Lifecycle (chatCore.ts)
-
-```mermaid
-sequenceDiagram
- participant Client
- participant chatCore
- participant Translator
- participant Executor
- participant Provider
-
- Client->>chatCore: Request (any format)
- chatCore->>chatCore: Detect source format
- chatCore->>chatCore: Check bypass patterns
- chatCore->>chatCore: Resolve model & provider
- chatCore->>Translator: Translate request (source → OpenAI → target)
- chatCore->>Executor: Get executor for provider
- Executor->>Executor: Build URL, headers, transform request
- Executor->>Executor: Refresh credentials if needed
- Executor->>Provider: HTTP fetch (streaming or non-streaming)
-
- alt Streaming
- Provider-->>chatCore: SSE stream
- chatCore->>chatCore: Pipe through SSE transform stream
- Note over chatCore: Transform stream translates
each chunk: target → OpenAI → source
- chatCore-->>Client: Translated SSE stream
- else Non-streaming
- Provider-->>chatCore: JSON response
- chatCore->>Translator: Translate response
- chatCore-->>Client: Translated JSON
- end
-
- alt Error (401, 429, 500...)
- chatCore->>Executor: Retry with credential refresh
- chatCore->>chatCore: Account fallback logic
- end
-```
-
----
-
-### 4.4 Services (`open-sse/services/`)
-
-Business logic that supports the handlers and executors.
-
-| File | Purpose |
-| -------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| `provider.ts` | **Format detection** (`detectFormat`): analyzes request body structure to identify Claude/OpenAI/Gemini/Antigravity/Responses formats (includes `max_tokens` heuristic for Claude). Also: URL building, header building, thinking config normalization. Supports `openai-compatible-*` and `anthropic-compatible-*` dynamic providers. |
-| `model.ts` | Model string parsing (`claude/model-name` → `{provider: "claude", model: "model-name"}`), alias resolution with collision detection, input sanitization (rejects path traversal/control chars), and model info resolution with async alias getter support. |
-| `accountFallback.ts` | Rate-limit handling: exponential backoff (1s → 2s → 4s → max 2min), account cooldown management, error classification (which errors trigger fallback vs. not). |
-| `tokenRefresh.ts` | OAuth token refresh for **every provider**: Google (Gemini, Antigravity), Claude, Codex, Qwen, Qoder, GitHub (OAuth + Copilot dual-token), Kiro (AWS SSO OIDC + Social Auth). Includes in-flight promise deduplication cache and retry with exponential backoff. |
-| `combo.ts` | **Combo models**: chains of fallback models. If model A fails with a fallback-eligible error, try model B, then C, etc. Returns actual upstream status codes. |
-| `usage.ts` | Fetches quota/usage data from provider APIs (GitHub Copilot quotas, Antigravity model quotas, Codex rate limits, Kiro usage breakdowns, Claude settings). |
-| `accountSelector.ts` | Smart account selection with scoring algorithm: considers priority, health status, round-robin position, and cooldown state to pick the optimal account for each request. |
-| `contextManager.ts` | Request context lifecycle management: creates and tracks per-request context objects with metadata (request ID, timestamps, provider info) for debugging and logging. |
-| `ipFilter.ts` | IP-based access control: supports allowlist and blocklist modes. Validates client IP against configured rules before processing API requests. |
-| `sessionManager.ts` | Session tracking with client fingerprinting: tracks active sessions using hashed client identifiers, monitors request counts, and provides session metrics. |
-| `signatureCache.ts` | Request signature-based deduplication cache: prevents duplicate requests by caching recent request signatures and returning cached responses for identical requests within a time window. |
-| `systemPrompt.ts` | Global system prompt injection: prepends or appends a configurable system prompt to all requests, with per-provider compatibility handling. |
-| `thinkingBudget.ts` | Reasoning token budget management: supports passthrough, auto (strip thinking config), custom (fixed budget), and adaptive (complexity-scaled) modes for controlling thinking/reasoning tokens. |
-| `wildcardRouter.ts` | Wildcard model pattern routing: resolves wildcard patterns (e.g., `*/claude-*`) to concrete provider/model pairs based on availability and priority. |
-
-#### Token Refresh Deduplication
-
-```mermaid
-sequenceDiagram
- participant R1 as Request 1
- participant R2 as Request 2
- participant Cache as refreshPromiseCache
- participant OAuth as OAuth Provider
-
- R1->>Cache: getAccessToken("gemini", token)
- Cache->>Cache: No in-flight promise
- Cache->>OAuth: Start refresh
- R2->>Cache: getAccessToken("gemini", token)
- Cache->>Cache: Found in-flight promise
- Cache-->>R2: Return existing promise
- OAuth-->>Cache: New access token
- Cache-->>R1: New access token
- Cache-->>R2: Same access token (shared)
- Cache->>Cache: Delete cache entry
-```
-
-#### Account Fallback State Machine
-
-```mermaid
-stateDiagram-v2
- [*] --> Active
- Active --> Error: Request fails (401/429/500)
- Error --> Cooldown: Apply backoff
- Cooldown --> Active: Cooldown expires
- Active --> Active: Request succeeds (reset backoff)
-
- state Error {
- [*] --> ClassifyError
- ClassifyError --> ShouldFallback: Rate limit / Auth / Transient
- ClassifyError --> NoFallback: 400 Bad Request
- }
-
- state Cooldown {
- [*] --> ExponentialBackoff
- ExponentialBackoff: Level 0 = 1s
- ExponentialBackoff: Level 1 = 2s
- ExponentialBackoff: Level 2 = 4s
- ExponentialBackoff: Max = 2min
- }
-```
-
-#### Combo Model Chain
-
-```mermaid
-flowchart LR
- A["Request with\ncombo model"] --> B["Model A"]
- B -->|"2xx Success"| C["Return response"]
- B -->|"429/401/500"| D{"Fallback\neligible?"}
- D -->|Yes| E["Model B"]
- D -->|No| F["Return error"]
- E -->|"2xx Success"| C
- E -->|"429/401/500"| G{"Fallback\neligible?"}
- G -->|Yes| H["Model C"]
- G -->|No| F
- H -->|"2xx Success"| C
- H -->|"Fail"| I["All failed →\nReturn last status"]
-```
-
----
-
-### 4.5 Translator (`open-sse/translator/`)
-
-The **format translation engine** using a self-registering plugin system.
-
-#### Architecture
-
-```mermaid
-graph TD
- subgraph "Request Translation"
- A["Claude → OpenAI"]
- B["Gemini → OpenAI"]
- C["Antigravity → OpenAI"]
- D["OpenAI Responses → OpenAI"]
- E["OpenAI → Claude"]
- F["OpenAI → Gemini"]
- G["OpenAI → Kiro"]
- H["OpenAI → Cursor"]
- end
-
- subgraph "Response Translation"
- I["Claude → OpenAI"]
- J["Gemini → OpenAI"]
- K["Kiro → OpenAI"]
- L["Cursor → OpenAI"]
- M["OpenAI → Claude"]
- N["OpenAI → Antigravity"]
- O["OpenAI → Responses"]
- end
-```
-
-| Directory | Files | Description |
-| ------------ | ------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| `request/` | 8 translators | Convert request bodies between formats. Each file self-registers via `register(from, to, fn)` on import. |
-| `response/` | 7 translators | Convert streaming response chunks between formats. Handles SSE event types, thinking blocks, tool calls. |
-| `helpers/` | 6 helpers | Shared utilities: `claudeHelper` (system prompt extraction, thinking config), `geminiHelper` (parts/contents mapping), `openaiHelper` (format filtering), `toolCallHelper` (ID generation, missing response injection), `maxTokensHelper`, `responsesApiHelper`. |
-| `index.ts` | — | Translation engine: `translateRequest()`, `translateResponse()`, state management, registry. |
-| `formats.ts` | — | Format constants: `OPENAI`, `CLAUDE`, `GEMINI`, `ANTIGRAVITY`, `KIRO`, `CURSOR`, `OPENAI_RESPONSES`. |
-
-#### Key Design: Self-Registering Plugins
-
-```javascript
-// Each translator file calls register() on import:
-import { register } from "../index.js";
-register("claude", "openai", translateClaudeToOpenAI);
-
-// The index.js imports all translator files, triggering registration:
-import "./request/claude-to-openai.js"; // ← self-registers
-```
-
----
-
-### 4.6 Utils (`open-sse/utils/`)
-
-| File | Purpose |
-| ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
-| `error.ts` | Error response building (OpenAI-compatible format), upstream error parsing, Antigravity retry-time extraction from error messages, SSE error streaming. |
-| `stream.ts` | **SSE Transform Stream** — the core streaming pipeline. Two modes: `TRANSLATE` (full format translation) and `PASSTHROUGH` (normalize + extract usage). Handles chunk buffering, usage estimation, content length tracking. Per-stream encoder/decoder instances avoid shared state. |
-| `streamHelpers.ts` | Low-level SSE utilities: `parseSSELine` (whitespace-tolerant), `hasValuableContent` (filters empty chunks for OpenAI/Claude/Gemini), `fixInvalidId`, `formatSSE` (format-aware SSE serialization with `perf_metrics` cleanup). |
-| `usageTracking.ts` | Token usage extraction from any format (Claude/OpenAI/Gemini/Responses), estimation with separate tool/message char-per-token ratios, buffer addition (2000 tokens safety margin), format-specific field filtering, console logging with ANSI colors. |
-| `requestLogger.ts` | File-based request logging (opt-in via `ENABLE_REQUEST_LOGS=true`). Creates session folders with numbered files: `1_req_client.json` → `7_res_client.txt`. All I/O is async (fire-and-forget). Masks sensitive headers. |
-| `bypassHandler.ts` | Intercepts specific patterns from Claude CLI (title extraction, warmup, count) and returns fake responses without calling any provider. Supports both streaming and non-streaming. Intentionally limited to Claude CLI scope. |
-| `networkProxy.ts` | Resolves outbound proxy URL for a given provider with precedence: provider-specific config → global config → environment variables (`HTTPS_PROXY`/`HTTP_PROXY`/`ALL_PROXY`). Supports `NO_PROXY` exclusions. Caches config for 30s. |
-
-#### SSE Streaming Pipeline
-
-```mermaid
-flowchart TD
- A["Provider SSE stream"] --> B["TextDecoder\n(per-stream instance)"]
- B --> C["Buffer lines\n(split on newline)"]
- C --> D["parseSSELine()\n(trim whitespace, parse JSON)"]
- D --> E{"Mode?"}
- E -->|TRANSLATE| F["translateResponse()\ntarget → OpenAI → source"]
- E -->|PASSTHROUGH| G["fixInvalidId()\nnormalize chunk"]
- F --> H["hasValuableContent()\nfilter empty chunks"]
- G --> H
- H -->|"Has content"| I["extractUsage()\ntrack token counts"]
- H -->|"Empty"| J["Skip chunk"]
- I --> K["formatSSE()\nserialize + clean perf_metrics"]
- K --> L["TextEncoder\n(per-stream instance)"]
- L --> M["Enqueue to\nclient stream"]
-
- style A fill:#f9f,stroke:#333
- style M fill:#9f9,stroke:#333
-```
-
-#### Request Logger Session Structure
-
-```
-logs/
-└── claude_gemini_claude-sonnet_20260208_143045/
- ├── 1_req_client.json ← Raw client request
- ├── 2_req_source.json ← After initial conversion
- ├── 3_req_openai.json ← OpenAI intermediate format
- ├── 4_req_target.json ← Final target format
- ├── 5_res_provider.txt ← Provider SSE chunks (streaming)
- ├── 5_res_provider.json ← Provider response (non-streaming)
- ├── 6_res_openai.txt ← OpenAI intermediate chunks
- ├── 7_res_client.txt ← Client-facing SSE chunks
- └── 6_error.json ← Error details (if any)
-```
-
----
-
-### 4.7 Application Layer (`src/`)
-
-| Directory | Purpose |
-| ------------- | ---------------------------------------------------------------------- |
-| `src/app/` | Web UI, API routes, Express middleware, OAuth callback handlers |
-| `src/lib/` | Database access (`localDb.ts`, `usageDb.ts`), authentication, shared |
-| `src/mitm/` | Man-in-the-middle proxy utilities for intercepting provider traffic |
-| `src/models/` | Database model definitions |
-| `src/shared/` | Wrappers around open-sse functions (provider, stream, error, etc.) |
-| `src/sse/` | SSE endpoint handlers that wire the open-sse library to Express routes |
-| `src/store/` | Application state management |
-
-#### Notable API Routes
-
-| Route | Methods | Purpose |
-| --------------------------------------------- | --------------- | ------------------------------------------------------------------------------------- |
-| `/api/provider-models` | GET/POST/DELETE | CRUD for custom models per provider |
-| `/api/models/catalog` | GET | Aggregated catalog of all models (chat, embedding, image, custom) grouped by provider |
-| `/api/settings/proxy` | GET/PUT/DELETE | Hierarchical outbound proxy configuration (`global/providers/combos/keys`) |
-| `/api/settings/proxy/test` | POST | Validates proxy connectivity and returns public IP/latency |
-| `/v1/providers/[provider]/chat/completions` | POST | Dedicated per-provider chat completions with model validation |
-| `/v1/providers/[provider]/embeddings` | POST | Dedicated per-provider embeddings with model validation |
-| `/v1/providers/[provider]/images/generations` | POST | Dedicated per-provider image generation with model validation |
-| `/api/settings/ip-filter` | GET/PUT | IP allowlist/blocklist management |
-| `/api/settings/thinking-budget` | GET/PUT | Reasoning token budget configuration (passthrough/auto/custom/adaptive) |
-| `/api/settings/system-prompt` | GET/PUT | Global system prompt injection for all requests |
-| `/api/sessions` | GET | Active session tracking and metrics |
-| `/api/rate-limits` | GET | Per-account rate limit status |
-
----
-
-## 5. Key Design Patterns
-
-### 5.1 Hub-and-Spoke Translation
-
-All formats translate through **OpenAI format as the hub**. Adding a new provider only requires writing **one pair** of translators (to/from OpenAI), not N pairs.
-
-### 5.2 Executor Strategy Pattern
-
-Each provider has a dedicated executor class inheriting from `BaseExecutor`. The factory in `executors/index.ts` selects the right one at runtime.
-
-### 5.3 Self-Registering Plugin System
-
-Translator modules register themselves on import via `register()`. Adding a new translator is just creating a file and importing it.
-
-### 5.4 Account Fallback with Exponential Backoff
-
-When a provider returns 429/401/500, the system can switch to the next account, applying exponential cooldowns (1s → 2s → 4s → max 2min).
-
-### 5.5 Combo Model Chains
-
-A "combo" groups multiple `provider/model` strings. If the first fails, fallback to the next automatically.
-
-### 5.6 Stateful Streaming Translation
-
-Response translation maintains state across SSE chunks (thinking block tracking, tool call accumulation, content block indexing) via the `initState()` mechanism.
-
-### 5.7 Usage Safety Buffer
-
-A 2000-token buffer is added to reported usage to prevent clients from hitting context window limits due to overhead from system prompts and format translation.
-
----
-
-## 6. Supported Formats
-
-| Format | Direction | Identifier |
-| ----------------------- | --------------- | ------------------ |
-| OpenAI Chat Completions | source + target | `openai` |
-| OpenAI Responses API | source + target | `openai-responses` |
-| Anthropic Claude | source + target | `claude` |
-| Google Gemini | source + target | `gemini` |
-| Google Gemini CLI | target only | `gemini-cli` |
-| Antigravity | source + target | `antigravity` |
-| AWS Kiro | target only | `kiro` |
-| Cursor | target only | `cursor` |
-
----
-
-## 7. Supported Providers
-
-| Provider | Auth Method | Executor | Key Notes |
-| ------------------------ | ---------------------- | ----------- | --------------------------------------------- |
-| Anthropic Claude | API key or OAuth | Default | Uses `x-api-key` header |
-| Google Gemini | API key or OAuth | Default | Uses `x-goog-api-key` header |
-| Google Gemini CLI | OAuth | GeminiCLI | Uses `streamGenerateContent` endpoint |
-| Antigravity | OAuth | Antigravity | Multi-URL fallback, custom retry parsing |
-| OpenAI | API key | Default | Standard Bearer auth |
-| Codex | OAuth | Codex | Injects system instructions, manages thinking |
-| GitHub Copilot | OAuth + Copilot token | Github | Dual token, VSCode header mimicking |
-| Kiro (AWS) | AWS SSO OIDC or Social | Kiro | Binary EventStream parsing |
-| Cursor IDE | Checksum auth | Cursor | Protobuf encoding, SHA-256 checksums |
-| Qwen | OAuth | Default | Standard auth |
-| Qoder | OAuth (Basic + Bearer) | Default | Dual auth header |
-| OpenRouter | API key | Default | Standard Bearer auth |
-| GLM, Kimi, MiniMax | API key | Default | Claude-compatible, use `x-api-key` |
-| `openai-compatible-*` | API key | Default | Dynamic: any OpenAI-compatible endpoint |
-| `anthropic-compatible-*` | API key | Default | Dynamic: any Claude-compatible endpoint |
-
----
-
-## 8. Data Flow Summary
-
-### Streaming Request
-
-```mermaid
-flowchart LR
- A["Client"] --> B["detectFormat()"]
- B --> C["translateRequest()\nsource → OpenAI → target"]
- C --> D["Executor\nbuildUrl + buildHeaders"]
- D --> E["fetch(providerURL)"]
- E --> F["createSSEStream()\nTRANSLATE mode"]
- F --> G["parseSSELine()"]
- G --> H["translateResponse()\ntarget → OpenAI → source"]
- H --> I["extractUsage()\n+ addBuffer"]
- I --> J["formatSSE()"]
- J --> K["Client receives\ntranslated SSE"]
- K --> L["logUsage()\nsaveRequestUsage()"]
-```
-
-### Non-Streaming Request
-
-```mermaid
-flowchart LR
- A["Client"] --> B["detectFormat()"]
- B --> C["translateRequest()\nsource → OpenAI → target"]
- C --> D["Executor.execute()"]
- D --> E["translateResponse()\ntarget → OpenAI → source"]
- E --> F["Return JSON\nresponse"]
-```
-
-### Bypass Flow (Claude CLI)
-
-```mermaid
-flowchart LR
- A["Claude CLI request"] --> B{"Match bypass\npattern?"}
- B -->|"Title/Warmup/Count"| C["Generate fake\nOpenAI response"]
- B -->|"No match"| D["Normal flow"]
- C --> E["Translate to\nsource format"]
- E --> F["Return without\ncalling provider"]
-```
diff --git a/docs/i18n/it/CONTRIBUTING.md b/docs/i18n/it/CONTRIBUTING.md
new file mode 100644
index 0000000000..a0c326c9f7
--- /dev/null
+++ b/docs/i18n/it/CONTRIBUTING.md
@@ -0,0 +1,299 @@
+# Contributing to OmniRoute (Italiano)
+
+🌐 **Languages:** 🇺🇸 [English](../../../CONTRIBUTING.md) · 🇪🇸 [es](../es/CONTRIBUTING.md) · 🇫🇷 [fr](../fr/CONTRIBUTING.md) · 🇩🇪 [de](../de/CONTRIBUTING.md) · 🇮🇹 [it](../it/CONTRIBUTING.md) · 🇷🇺 [ru](../ru/CONTRIBUTING.md) · 🇨🇳 [zh-CN](../zh-CN/CONTRIBUTING.md) · 🇯🇵 [ja](../ja/CONTRIBUTING.md) · 🇰🇷 [ko](../ko/CONTRIBUTING.md) · 🇸🇦 [ar](../ar/CONTRIBUTING.md) · 🇮🇳 [in](../in/CONTRIBUTING.md) · 🇹🇭 [th](../th/CONTRIBUTING.md) · 🇻🇳 [vi](../vi/CONTRIBUTING.md) · 🇮🇩 [id](../id/CONTRIBUTING.md) · 🇲🇾 [ms](../ms/CONTRIBUTING.md) · 🇳🇱 [nl](../nl/CONTRIBUTING.md) · 🇵🇱 [pl](../pl/CONTRIBUTING.md) · 🇸🇪 [sv](../sv/CONTRIBUTING.md) · 🇳🇴 [no](../no/CONTRIBUTING.md) · 🇩🇰 [da](../da/CONTRIBUTING.md) · 🇫🇮 [fi](../fi/CONTRIBUTING.md) · 🇵🇹 [pt](../pt/CONTRIBUTING.md) · 🇷🇴 [ro](../ro/CONTRIBUTING.md) · 🇭🇺 [hu](../hu/CONTRIBUTING.md) · 🇧🇬 [bg](../bg/CONTRIBUTING.md) · 🇸🇰 [sk](../sk/CONTRIBUTING.md) · 🇺🇦 [uk-UA](../uk-UA/CONTRIBUTING.md) · 🇮🇱 [he](../he/CONTRIBUTING.md) · 🇵🇭 [phi](../phi/CONTRIBUTING.md) · 🇧🇷 [pt-BR](../pt-BR/CONTRIBUTING.md) · 🇨🇿 [cs](../cs/CONTRIBUTING.md)
+
+---
+
+Thank you for your interest in contributing! This guide covers everything you need to get started.
+
+---
+
+## Development Setup
+
+### Prerequisites
+
+- **Node.js** >= 18 < 24 (recommended: 22 LTS)
+- **npm** 10+
+- **Git**
+
+### Clone & Install
+
+```bash
+git clone https://github.com/diegosouzapw/OmniRoute.git
+cd OmniRoute
+npm install
+```
+
+### Environment Variables
+
+```bash
+# Create your .env from the template
+cp .env.example .env
+
+# Generate required secrets
+echo "JWT_SECRET=$(openssl rand -base64 48)" >> .env
+echo "API_KEY_SECRET=$(openssl rand -hex 32)" >> .env
+```
+
+Key variables for development:
+
+| Variable | Development Default | Description |
+| ---------------------- | ------------------------ | --------------------- |
+| `PORT` | `20128` | Server port |
+| `NEXT_PUBLIC_BASE_URL` | `http://localhost:20128` | Base URL for frontend |
+| `JWT_SECRET` | (generate above) | JWT signing secret |
+| `INITIAL_PASSWORD` | `CHANGEME` | First login password |
+| `APP_LOG_LEVEL` | `info` | Log verbosity level |
+
+### Dashboard Settings
+
+The dashboard provides UI toggles for features that can also be configured via environment variables:
+
+| Setting Location | Toggle | Description |
+| ------------------- | ------------------ | ------------------------------ |
+| Settings → Advanced | Debug Mode | Enable debug request logs (UI) |
+| Settings → General | Sidebar Visibility | Show/hide sidebar sections |
+
+These settings are stored in the database and persist across restarts, overriding env var defaults when set.
+
+### Running Locally
+
+```bash
+# Development mode (hot reload)
+npm run dev
+
+# Production build
+npm run build
+npm run start
+
+# Common port configuration
+PORT=20128 NEXT_PUBLIC_BASE_URL=http://localhost:20128 npm run dev
+```
+
+Default URLs:
+
+- **Dashboard**: `http://localhost:20128/dashboard`
+- **API**: `http://localhost:20128/v1`
+
+---
+
+## Git Workflow
+
+> ⚠️ **NEVER commit directly to `main`.** Always use feature branches.
+
+```bash
+git checkout -b feat/your-feature-name
+# ... make changes ...
+git commit -m "feat: describe your change"
+git push -u origin feat/your-feature-name
+# Open a Pull Request on GitHub
+```
+
+### Branch Naming
+
+| Prefix | Purpose |
+| ----------- | ------------------------- |
+| `feat/` | New features |
+| `fix/` | Bug fixes |
+| `refactor/` | Code restructuring |
+| `docs/` | Documentation changes |
+| `test/` | Test additions/fixes |
+| `chore/` | Tooling, CI, dependencies |
+
+### Commit Messages
+
+Follow [Conventional Commits](https://www.conventionalcommits.org/):
+
+```
+feat: add circuit breaker for provider calls
+fix: resolve JWT secret validation edge case
+docs: update SECURITY.md with PII protection
+test: add observability unit tests
+refactor(db): consolidate rate limit tables
+```
+
+Scopes: `db`, `sse`, `oauth`, `dashboard`, `api`, `cli`, `docker`, `ci`, `mcp`, `a2a`, `memory`, `skills`.
+
+---
+
+## Running Tests
+
+```bash
+# All tests (unit + vitest + ecosystem + e2e)
+npm run test:all
+
+# Single test file (Node.js native test runner — most tests use this)
+node --import tsx/esm --test tests/unit/your-file.test.mjs
+
+# Vitest (MCP server, autoCombo, cache)
+npm run test:vitest
+
+# E2E tests (requires Playwright)
+npm run test:e2e
+
+# Protocol clients E2E (MCP transports, A2A)
+npm run test:protocols:e2e
+
+# Ecosystem compatibility tests
+npm run test:ecosystem
+
+# Coverage (55% min statements/lines/functions; 60% branches)
+npm run test:coverage
+npm run coverage:report
+
+# Lint + format check
+npm run lint
+npm run check
+```
+
+Coverage notes:
+
+- `npm run test:coverage` measures source coverage for the main unit test suite, excludes `tests/**`, and includes `open-sse/**`
+- `npm run coverage:report` prints the detailed file-by-file report from the latest coverage run
+- `npm run test:coverage:legacy` preserves the older metric for historical comparison
+- See `docs/COVERAGE_PLAN.md` for the phased coverage improvement roadmap
+
+Current test status: **122 unit test files** covering:
+
+- Provider translators and format conversion
+- Rate limiting, circuit breaker, and resilience
+- Semantic cache, idempotency, progress tracking
+- Database operations and schema (21 DB modules)
+- OAuth flows and authentication
+- API endpoint validation (Zod v4)
+- MCP server tools and scope enforcement
+- Memory and Skills systems
+
+---
+
+## Code Style
+
+- **ESLint** — Run `npm run lint` before committing
+- **Prettier** — Auto-formatted via `lint-staged` on commit (2 spaces, semicolons, double quotes, 100 char width, es5 trailing commas)
+- **TypeScript** — All `src/` code uses `.ts`/`.tsx`; `open-sse/` uses `.ts`/`.js`; document with TSDoc (`@param`, `@returns`, `@throws`)
+- **No `eval()`** — ESLint enforces `no-eval`, `no-implied-eval`, `no-new-func`
+- **Zod validation** — Use Zod v4 schemas for all API input validation
+- **Naming**: Files = camelCase/kebab-case, components = PascalCase, constants = UPPER_SNAKE
+
+---
+
+## Project Structure
+
+```
+src/ # TypeScript (.ts / .tsx)
+├── app/ # Next.js 16 App Router
+│ ├── (dashboard)/ # Dashboard pages (23 sections)
+│ ├── api/ # API routes (51 directories)
+│ └── login/ # Auth pages (.tsx)
+├── domain/ # Policy engine (policyEngine, comboResolver, costRules, etc.)
+├── lib/ # Core business logic (.ts)
+│ ├── a2a/ # Agent-to-Agent v0.3 protocol server
+│ ├── acp/ # Agent Communication Protocol registry
+│ ├── compliance/ # Compliance policy engine
+│ ├── db/ # SQLite database layer (21 modules + 16 migrations)
+│ ├── memory/ # Persistent conversational memory
+│ ├── oauth/ # OAuth providers, services, and utilities
+│ ├── skills/ # Extensible skill framework
+│ ├── usage/ # Usage tracking and cost calculation
+│ └── localDb.ts # Re-export layer only — never add logic here
+├── middleware/ # Request middleware (promptInjectionGuard)
+├── mitm/ # MITM proxy (cert, DNS, target routing)
+├── shared/
+│ ├── components/ # React components (.tsx)
+│ ├── constants/ # Provider definitions (60+), MCP scopes, routing strategies
+│ ├── utils/ # Circuit breaker, sanitizer, auth helpers
+│ └── validation/ # Zod v4 schemas
+└── sse/ # SSE proxy pipeline
+
+open-sse/ # @omniroute/open-sse workspace
+├── executors/ # 14 provider-specific request executors
+├── handlers/ # 11 request handlers (chat, responses, embeddings, images, etc.)
+├── mcp-server/ # MCP server (25 tools, 3 transports, 10 scopes)
+├── services/ # 36+ services (combo, autoCombo, rateLimitManager, etc.)
+├── translator/ # Format translators (OpenAI ↔ Claude ↔ Gemini ↔ Responses ↔ Ollama)
+├── transformer/ # Responses API transformer
+└── utils/ # 22 utility modules (stream, TLS, proxy, logging)
+
+electron/ # Electron desktop app (cross-platform)
+
+tests/
+├── unit/ # Node.js test runner (122 test files)
+├── integration/ # Integration tests
+├── e2e/ # Playwright tests
+├── security/ # Security tests
+├── translator/ # Translator-specific tests
+└── load/ # Load tests
+
+docs/ # Documentation
+├── ARCHITECTURE.md # System architecture
+├── API_REFERENCE.md # All endpoints
+├── USER_GUIDE.md # Provider setup, CLI integration
+├── TROUBLESHOOTING.md # Common issues
+├── MCP-SERVER.md # MCP server (25 tools)
+├── A2A-SERVER.md # A2A agent protocol
+├── AUTO-COMBO.md # Auto-combo engine
+├── CLI-TOOLS.md # CLI tools integration
+├── COVERAGE_PLAN.md # Test coverage improvement plan
+├── openapi.yaml # OpenAPI specification
+└── adr/ # Architecture Decision Records
+```
+
+---
+
+## Adding a New Provider
+
+### Step 1: Register Provider Constants
+
+Add to `src/shared/constants/providers.ts` — Zod-validated at module load.
+
+### Step 2: Add Executor (if custom logic needed)
+
+Create executor in `open-sse/executors/your-provider.ts` extending the base executor.
+
+### Step 3: Add Translator (if non-OpenAI format)
+
+Create request/response translators in `open-sse/translator/`.
+
+### Step 4: Add OAuth Config (if OAuth-based)
+
+Add OAuth credentials in `src/lib/oauth/constants/oauth.ts` and service in `src/lib/oauth/services/`.
+
+### Step 5: Register Models
+
+Add model definitions in `open-sse/config/providerRegistry.ts`.
+
+### Step 6: Add Tests
+
+Write unit tests in `tests/unit/` covering at minimum:
+
+- Provider registration
+- Request/response translation
+- Error handling
+
+---
+
+## Pull Request Checklist
+
+- [ ] Tests pass (`npm test`)
+- [ ] Linting passes (`npm run lint`)
+- [ ] Build succeeds (`npm run build`)
+- [ ] TypeScript types added for new public functions and interfaces
+- [ ] No hardcoded secrets or fallback values
+- [ ] All inputs validated with Zod schemas
+- [ ] CHANGELOG updated (if user-facing change)
+- [ ] Documentation updated (if applicable)
+
+---
+
+## Releasing
+
+Releases are managed via the `/generate-release` workflow. When a new GitHub Release is created, the package is **automatically published to npm** via GitHub Actions.
+
+---
+
+## Getting Help
+
+- **Architecture**: See [`docs/ARCHITECTURE.md`](docs/ARCHITECTURE.md)
+- **API Reference**: See [`docs/API_REFERENCE.md`](docs/API_REFERENCE.md)
+- **Issues**: [github.com/diegosouzapw/OmniRoute/issues](https://github.com/diegosouzapw/OmniRoute/issues)
+- **ADRs**: See `docs/adr/` for architectural decision records
diff --git a/docs/i18n/it/FEATURES.md b/docs/i18n/it/FEATURES.md
deleted file mode 100644
index d1b056ddc4..0000000000
--- a/docs/i18n/it/FEATURES.md
+++ /dev/null
@@ -1,147 +0,0 @@
-# OmniRoute — Dashboard Features Gallery (Italiano)
-
-🌐 **Languages:** 🇺🇸 [English](../../../README.md) · 🇧🇷 [pt-BR](../pt-BR/README.md) · 🇪🇸 [es](../es/README.md) · 🇫🇷 [fr](../fr/README.md) · 🇩🇪 [de](../de/README.md) · 🇮🇹 [it](../it/README.md) · 🇷🇺 [ru](../ru/README.md) · 🇨🇳 [zh-CN](../zh-CN/README.md) · 🇯🇵 [ja](../ja/README.md) · 🇰🇷 [ko](../ko/README.md) · 🇸🇦 [ar](../ar/README.md) · 🇮🇳 [in](../in/README.md) · 🇹🇭 [th](../th/README.md) · 🇻🇳 [vi](../vi/README.md) · 🇮🇩 [id](../id/README.md) · 🇲🇾 [ms](../ms/README.md) · 🇳🇱 [nl](../nl/README.md) · 🇵🇱 [pl](../pl/README.md) · 🇸🇪 [sv](../sv/README.md) · 🇳🇴 [no](../no/README.md) · 🇩🇰 [da](../da/README.md) · 🇫🇮 [fi](../fi/README.md) · 🇵🇹 [pt](../pt/README.md) · 🇷🇴 [ro](../ro/README.md) · 🇭🇺 [hu](../hu/README.md) · 🇧🇬 [bg](../bg/README.md) · 🇸🇰 [sk](../sk/README.md) · 🇺🇦 [uk-UA](../uk-UA/README.md) · 🇮🇱 [he](../he/README.md) · 🇵🇭 [phi](../phi/README.md)
-
-> 🇺🇸 [English](../../../docs/FEATURES.md)
-
----
-
-Visual guide to every section of the OmniRoute dashboard.
-
----
-
-## 🔌 Providers
-
-Manage AI provider connections: OAuth providers (Claude Code, Codex, Gemini CLI), API key providers (Groq, DeepSeek, OpenRouter), and free providers (Qoder, Qwen, Kiro). Kiro accounts include credit balance tracking — remaining credits, total allowance, and renewal date visible in Dashboard → Usage.
-
-
-
----
-
-## 🎨 Combos
-
-Create model routing combos with 6 strategies: priority, weighted, round-robin, random, least-used, and cost-optimized. Each combo chains multiple models with automatic fallback and includes quick templates and readiness checks.
-
-
-
----
-
-## 📊 Analytics
-
-Comprehensive usage analytics with token consumption, cost estimates, activity heatmaps, weekly distribution charts, and per-provider breakdowns.
-
-
-
----
-
-## 🏥 System Health
-
-Real-time monitoring: uptime, memory, version, latency percentiles (p50/p95/p99), cache statistics, and provider circuit breaker states.
-
-
-
----
-
-## 🔧 Translator Playground
-
-Four modes for debugging API translations: **Playground** (format converter), **Chat Tester** (live requests), **Test Bench** (batch tests), and **Live Monitor** (real-time stream).
-
-
-
----
-
-## 🎮 Model Playground _(v2.0.9+)_
-
-Test any model directly from the dashboard. Select provider, model, and endpoint, write prompts with Monaco Editor, stream responses in real-time, abort mid-stream, and view timing metrics.
-
----
-
-## 🎨 Themes _(v2.0.5+)_
-
-Customizable color themes for the entire dashboard. Choose from 7 preset colors (Coral, Blue, Red, Green, Violet, Orange, Cyan) or create a custom theme by picking any hex color. Supports light, dark, and system mode.
-
----
-
-## ⚙️ Settings
-
-Comprehensive settings panel with tabs:
-
-- **General** — System storage, backup management (export/import database)
-- **Appearance** — Theme selector (dark/light/system), color theme presets and custom colors, health log visibility, sidebar item visibility controls
-- **Security** — API endpoint protection, custom provider blocking, IP filtering, session info
-- **Routing** — Model aliases, background task degradation
-- **Resilience** — Rate limit persistence, circuit breaker tuning
-- **Advanced** — Configuration overrides
-
-
-
----
-
-## 🔧 CLI Tools
-
-One-click configuration for AI coding tools: Claude Code, Codex CLI, Gemini CLI, OpenClaw, Kilo Code, Antigravity, Cline, Continue, Cursor, and Factory Droid. Features automated config apply/reset, connection profiles, and model mapping.
-
-
-
----
-
-## 🤖 CLI Agents _(v2.0.11+)_
-
-Dashboard for discovering and managing CLI agents. Shows a grid of 14 built-in agents (Codex, Claude, Goose, Gemini CLI, OpenClaw, Aider, OpenCode, Cline, Qwen Code, ForgeCode, Amazon Q, Open Interpreter, Cursor CLI, Warp) with:
-
-- **Installation status** — Installed / Not Found with version detection
-- **Protocol badges** — stdio, HTTP, etc.
-- **Custom agents** — Register any CLI tool via form (name, binary, version command, spawn args)
-- **CLI Fingerprint Matching** — Per-provider toggle to match native CLI request signatures, reducing ban risk while preserving proxy IP
-
----
-
-## 🖼️ Media _(v2.0.3+)_
-
-Generate images, videos, and music from the dashboard. Supports OpenAI, xAI, Together, Hyperbolic, SD WebUI, ComfyUI, AnimateDiff, Stable Audio Open, and MusicGen.
-
----
-
-## 📝 Request Logs
-
-Real-time request logging with filtering by provider, model, account, and API key. Shows status codes, token usage, latency, and response details.
-
-
-
----
-
-## 🌐 API Endpoint
-
-Your unified API endpoint with capability breakdown: Chat Completions, Responses API, Embeddings, Image Generation, Reranking, Audio Transcription, Text-to-Speech, Moderations, and registered API keys. Cloud proxy support for remote access.
-
-
-
----
-
-## 🔑 API Key Management
-
-Create, scope, and revoke API keys. Each key can be restricted to specific models/providers with full access or read-only permissions. Visual key management with usage tracking.
-
----
-
-## 📋 Audit Log
-
-Administrative action tracking with filtering by action type, actor, target, IP address, and timestamp. Full security event history.
-
----
-
-## 🖥️ Desktop Application
-
-Native Electron desktop app for Windows, macOS, and Linux. Run OmniRoute as a standalone application with system tray integration, offline support, auto-update, and one-click install.
-
-Key features:
-
-- Server readiness polling (no blank screen on cold start)
-- System tray with port management
-- Content Security Policy
-- Single-instance lock
-- Auto-update on restart
-- Platform-conditional UI (macOS traffic lights, Windows/Linux default titlebar)
-- Hardened Electron build packaging — symlinked `node_modules` in the standalone bundle is detected and rejected before packaging, preventing runtime dependency on the build machine (v2.5.5+)
-
-📖 See [`electron/README.md`](../electron/README.md) for full documentation.
diff --git a/docs/i18n/it/MCP-SERVER.md b/docs/i18n/it/MCP-SERVER.md
deleted file mode 100644
index 829acd30b1..0000000000
--- a/docs/i18n/it/MCP-SERVER.md
+++ /dev/null
@@ -1,87 +0,0 @@
-🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/MCP-SERVER.md) · 🇪🇸 [es](../es/MCP-SERVER.md) · 🇫🇷 [fr](../fr/MCP-SERVER.md) · 🇩🇪 [de](../de/MCP-SERVER.md) · 🇮🇹 [it](../it/MCP-SERVER.md) · 🇷🇺 [ru](../ru/MCP-SERVER.md) · 🇨🇳 [zh-CN](../zh-CN/MCP-SERVER.md) · 🇯🇵 [ja](../ja/MCP-SERVER.md) · 🇰🇷 [ko](../ko/MCP-SERVER.md) · 🇸🇦 [ar](../ar/MCP-SERVER.md) · 🇮🇳 [in](../in/MCP-SERVER.md) · 🇹🇭 [th](../th/MCP-SERVER.md) · 🇻🇳 [vi](../vi/MCP-SERVER.md) · 🇮🇩 [id](../id/MCP-SERVER.md) · 🇲🇾 [ms](../ms/MCP-SERVER.md) · 🇳🇱 [nl](../nl/MCP-SERVER.md) · 🇵🇱 [pl](../pl/MCP-SERVER.md) · 🇸🇪 [sv](../sv/MCP-SERVER.md) · 🇳🇴 [no](../no/MCP-SERVER.md) · 🇩🇰 [da](../da/MCP-SERVER.md) · 🇫🇮 [fi](../fi/MCP-SERVER.md) · 🇵🇹 [pt](../pt/MCP-SERVER.md) · 🇷🇴 [ro](../ro/MCP-SERVER.md) · 🇭🇺 [hu](../hu/MCP-SERVER.md) · 🇧🇬 [bg](../bg/MCP-SERVER.md) · 🇸🇰 [sk](../sk/MCP-SERVER.md) · 🇺🇦 [uk-UA](../uk-UA/MCP-SERVER.md) · 🇮🇱 [he](../he/MCP-SERVER.md) · 🇵🇭 [phi](../phi/MCP-SERVER.md)
-
----
-
-# OmniRoute MCP Server Documentation
-
-> Model Context Protocol server with 16 intelligent tools
-
-## Installation
-
-OmniRoute MCP is built-in. Start it with:
-
-```bash
-omniroute --mcp
-```
-
-Or via the open-sse transport:
-
-```bash
-# HTTP streamable transport (port 20130)
-omniroute --dev # MCP auto-starts on /mcp endpoint
-```
-
-## IDE Configuration
-
-See [IDE Configs](integrations/ide-configs.md) for Antigravity, Cursor, Copilot, and Claude Desktop setup.
-
----
-
-## Essential Tools (8)
-
-| Tool | Description |
-| :------------------------------ | :--------------------------------------- |
-| `omniroute_get_health` | Gateway health, circuit breakers, uptime |
-| `omniroute_list_combos` | All configured combos with models |
-| `omniroute_get_combo_metrics` | Performance metrics for a specific combo |
-| `omniroute_switch_combo` | Switch active combo by ID/name |
-| `omniroute_check_quota` | Quota status per provider or all |
-| `omniroute_route_request` | Send a chat completion through OmniRoute |
-| `omniroute_cost_report` | Cost analytics for a time period |
-| `omniroute_list_models_catalog` | Full model catalog with capabilities |
-
-## Advanced Tools (8)
-
-| Tool | Description |
-| :--------------------------------- | :---------------------------------------------- |
-| `omniroute_simulate_route` | Dry-run routing simulation with fallback tree |
-| `omniroute_set_budget_guard` | Session budget with degrade/block/alert actions |
-| `omniroute_set_resilience_profile` | Apply conservative/balanced/aggressive preset |
-| `omniroute_test_combo` | Live-test all models in a combo |
-| `omniroute_get_provider_metrics` | Detailed metrics for one provider |
-| `omniroute_best_combo_for_task` | Task-fitness recommendation with alternatives |
-| `omniroute_explain_route` | Explain a past routing decision |
-| `omniroute_get_session_snapshot` | Full session state: costs, tokens, errors |
-
-## Authentication
-
-MCP tools are authenticated via API key scopes. Each tool requires specific scopes:
-
-| Scope | Tools |
-| :------------- | :----------------------------------------------- |
-| `read:health` | get_health, get_provider_metrics |
-| `read:combos` | list_combos, get_combo_metrics |
-| `write:combos` | switch_combo |
-| `read:quota` | check_quota |
-| `write:route` | route_request, simulate_route, test_combo |
-| `read:usage` | cost_report, get_session_snapshot, explain_route |
-| `write:config` | set_budget_guard, set_resilience_profile |
-| `read:models` | list_models_catalog, best_combo_for_task |
-
-## Audit Logging
-
-Every tool call is logged to `mcp_tool_audit` with:
-
-- Tool name, arguments, result
-- Duration (ms), success/failure
-- API key hash, timestamp
-
-## Files
-
-| File | Purpose |
-| :------------------------------------------- | :------------------------------------------ |
-| `open-sse/mcp-server/server.ts` | MCP server creation + 16 tool registrations |
-| `open-sse/mcp-server/transport.ts` | Stdio + HTTP transport |
-| `open-sse/mcp-server/auth.ts` | API key + scope validation |
-| `open-sse/mcp-server/audit.ts` | Tool call audit logging |
-| `open-sse/mcp-server/tools/advancedTools.ts` | 8 advanced tool handlers |
diff --git a/docs/i18n/it/README.md b/docs/i18n/it/README.md
index 49f14cb11e..794557cd73 100644
--- a/docs/i18n/it/README.md
+++ b/docs/i18n/it/README.md
@@ -1,13 +1,12 @@
# 🚀 OmniRoute — The Free AI Gateway (Italiano)
-🌐 **Languages:** 🇺🇸 [English](../../../README.md) · 🇪🇸 [es](../es/README.md) · 🇫🇷 [fr](../fr/README.md) · 🇩🇪 [de](../de/README.md) · 🇮🇹 [it](../it/README.md) · 🇷🇺 [ru](../ru/README.md) · 🇨🇳 [zh-CN](../zh-CN/README.md) · 🇯🇵 [ja](../ja/README.md) · 🇰🇷 [ko](../ko/README.md) · 🇸🇦 [ar](../ar/README.md) · 🇮🇳 [in](../in/README.md) · 🇹🇭 [th](../th/README.md) · 🇻🇳 [vi](../vi/README.md) · 🇮🇩 [id](../id/README.md) · 🇲🇾 [ms](../ms/README.md) · 🇳🇱 [nl](../nl/README.md) · 🇵🇱 [pl](../pl/README.md) · 🇸🇪 [sv](../sv/README.md) · 🇳🇴 [no](../no/README.md) · 🇩🇰 [da](../da/README.md) · 🇫🇮 [fi](../fi/README.md) · 🇵🇹 [pt](../pt/README.md) · 🇷🇴 [ro](../ro/README.md) · 🇭🇺 [hu](../hu/README.md) · 🇧🇬 [bg](../bg/README.md) · 🇸🇰 [sk](../sk/README.md) · 🇺🇦 [uk-UA](../uk-UA/README.md) · 🇮🇱 [he](../he/README.md) · 🇵🇭 [phi](../phi/README.md) · 🇧🇷 [pt-BR](../pt-BR/README.md)
+🌐 **Languages:** 🇺🇸 [English](../../../README.md) · 🇪🇸 [es](../es/README.md) · 🇫🇷 [fr](../fr/README.md) · 🇩🇪 [de](../de/README.md) · 🇮🇹 [it](../it/README.md) · 🇷🇺 [ru](../ru/README.md) · 🇨🇳 [zh-CN](../zh-CN/README.md) · 🇯🇵 [ja](../ja/README.md) · 🇰🇷 [ko](../ko/README.md) · 🇸🇦 [ar](../ar/README.md) · 🇮🇳 [in](../in/README.md) · 🇹🇭 [th](../th/README.md) · 🇻🇳 [vi](../vi/README.md) · 🇮🇩 [id](../id/README.md) · 🇲🇾 [ms](../ms/README.md) · 🇳🇱 [nl](../nl/README.md) · 🇵🇱 [pl](../pl/README.md) · 🇸🇪 [sv](../sv/README.md) · 🇳🇴 [no](../no/README.md) · 🇩🇰 [da](../da/README.md) · 🇫🇮 [fi](../fi/README.md) · 🇵🇹 [pt](../pt/README.md) · 🇷🇴 [ro](../ro/README.md) · 🇭🇺 [hu](../hu/README.md) · 🇧🇬 [bg](../bg/README.md) · 🇸🇰 [sk](../sk/README.md) · 🇺🇦 [uk-UA](../uk-UA/README.md) · 🇮🇱 [he](../he/README.md) · 🇵🇭 [phi](../phi/README.md) · 🇧🇷 [pt-BR](../pt-BR/README.md) · 🇨🇿 [cs](../cs/README.md)
---
-
### Never stop coding. Smart routing to **FREE & low-cost AI models** with automatic fallback.
-_Your universal API proxy — one endpoint, 67+ providers, zero downtime. Now with **MCP & A2A** agent orchestration._
+_Your universal API proxy — one endpoint, 60+ providers, zero downtime. Now with **MCP Server (25 tools)**, **A2A Protocol**, **Memory/Skills Systems** & **Electron Desktop App**._
**Chat Completions • Embeddings • Image Generation • Video • Music • Audio • Reranking • **Web Search** • MCP Server • A2A Protocol • 100% TypeScript**
@@ -47,15 +46,17 @@ _Your universal API proxy — one endpoint, 67+ providers, zero downtime. Now wi
> - `APP_LOG_FILE_PATH`
> - `APP_LOG_MAX_FILE_SIZE`
> - `APP_LOG_RETENTION_DAYS`
+> - `APP_LOG_MAX_FILES`
> - `APP_LOG_LEVEL`
> - `APP_LOG_FORMAT`
> - `CALL_LOG_RETENTION_DAYS`
+> - `CALL_LOG_MAX_ENTRIES`
>
> For release details and upgrade notes, see the [CHANGELOG](CHANGELOG.md).
---
-## 🆕 What's New in v3.0.0
+## 🆕 What's New
> **Upgrading from v2.9.5?** — See the [full CHANGELOG](CHANGELOG.md#300--2026-03-22-release-candidate--not-yet-merged-to-main) for all changes.
@@ -275,7 +276,7 @@ Developers pay $20–200/month for Claude Pro, Codex Pro, or GitHub Copilot. Eve
- **Smart 4-Tier Fallback** — If subscription quota runs out, automatically redirects to API Key → Cheap → Free with zero manual intervention
- **Real-Time Quota Tracking** — Shows token consumption in real-time with reset countdown (5h, daily, weekly)
- **Multi-Account Support** — Multiple accounts per provider with auto round-robin — when one runs out, switches to the next
-- **Custom Combos** — Customizable fallback chains with 6 balancing strategies (fill-first, round-robin, P2C, random, least-used, cost-optimized)
+- **Custom Combos** — Customizable fallback chains with 9 balancing strategies (priority, weighted, fill-first, round-robin, P2C, random, least-used, cost-optimized, strict-random)
- **Codex Business Quotas** — Business/Team workspace quota monitoring directly in the dashboard
@@ -287,7 +288,7 @@ OpenAI uses one format, Claude (Anthropic) uses another, Gemini yet another. If
**How OmniRoute solves it:**
-- **Unified Endpoint** — A single `http://localhost:20128/v1` serves as proxy for all 67+ providers
+- **Unified Endpoint** — A single `http://localhost:20128/v1` serves as proxy for all 60+ providers
- **Format Translation** — Automatic and transparent: OpenAI ↔ Claude ↔ Gemini ↔ Responses API
- **Response Sanitization** — Strips non-standard fields (`x_groq`, `usage_breakdown`, `service_tier`) that break OpenAI SDK v1.83+
- **Role Normalization** — Converts `developer` → `system` for non-OpenAI providers; `system` → `user` for GLM/ERNIE
@@ -373,7 +374,7 @@ Developers use Cursor, Claude Code, Codex CLI, OpenClaw, Gemini CLI, Kilo Code..
- **CLI Tools Dashboard** — Dedicated page with one-click setup for Claude Code, Codex CLI, OpenClaw, Kilo Code, Antigravity, Cline
- **GitHub Copilot Config Generator** — Generates `chatLanguageModels.json` for VS Code with bulk model selection
- **Onboarding Wizard** — Guided 4-step setup for first-time users
-- **One endpoint, all models** — Configure `http://localhost:20128/v1` once, access 67+ providers
+- **One endpoint, all models** — Configure `http://localhost:20128/v1` once, access 60+ providers
@@ -420,7 +421,7 @@ When a call fails, the dev doesn't know if it was a rate limit, expired token, w
- **SQLite Proxy Logs** — Persistent logs that survive server restarts
- **Translator Playground** — 4 debugging modes: Playground (format translation), Chat Tester (round-trip), Test Bench (batch), Live Monitor (real-time)
- **Request Telemetry** — p50/p95/p99 latency + X-Request-Id tracing
-- **File-Based Logging with Rotation** — Console interceptor captures everything to JSON log with size-based rotation
+- **File-Based Logging with Rotation** — App logs rotate by size, retention days, and archive count; call log artifacts rotate by retention days and file count
- **System Info Report** — `npm run system-info` generates `system-info.txt` with your full environment (Node version, OmniRoute version, OS, CLI tools, Docker/PM2 status). Attach it when reporting issues for instant triage.
@@ -515,7 +516,7 @@ Developers who want all responses in a specific language, with a specific tone,
- **System Prompt Injection** — Global prompt applied to all requests
- **Thinking Budget Validation** — Reasoning token allocation control per request (passthrough, auto, custom, adaptive)
-- **6 Routing Strategies** — Global strategies that determine how requests are distributed
+- **9 Routing Strategies** — Global strategies that determine how requests are distributed
- **Wildcard Router** — `provider/*` patterns route dynamically to any provider
- **Combo Enable/Disable Toggle** — Toggle combos directly from the dashboard
- **Provider Toggle** — Enable/disable all connections for a provider with one click
@@ -582,7 +583,7 @@ Different clients should have least-privilege access to tool categories.
**How OmniRoute solves it:**
-- 9 granular MCP scopes for controlled tool access
+- 10 granular MCP scopes for controlled tool access
- Scope enforcement and visibility in MCP management UI
- Safe default posture for operational tooling
@@ -1326,19 +1327,19 @@ OmniRoute v2.0 is built as an operational platform, not just a relay proxy.
### 🤖 Agent & Protocol Operations (v2.0)
-| Feature | What It Does |
-| ------------------------------------- | -------------------------------------------------------------------------------------------------- |
-| 🔧 **MCP Server (16 tools)** | IDE/agent tools via 3 transports: stdio, SSE (`/api/mcp/sse`), Streamable HTTP (`/api/mcp/stream`) |
-| 🤝 **A2A Server (JSON-RPC + SSE)** | Agent-to-agent task execution with sync and streaming flows |
-| 🧭 **Consolidated Endpoints Page** | Tabbed management page with Endpoint Proxy, MCP, A2A, and API Endpoints tabs |
-| 🎚️ **Service Enable/Disable Toggles** | ON/OFF switches for MCP and A2A with settings persistence (default: OFF) |
-| 🛰️ **MCP Runtime Heartbeat** | Real process status (pid, uptime, heartbeat age, transport, scope mode) |
-| 📋 **MCP Audit Trail** | Filterable audit logs with success/failure and key attribution |
-| 🔐 **MCP Scope Enforcement** | 9 granular scope permissions for controlled tool access |
-| 📡 **A2A Task Lifecycle Management** | List/filter tasks, inspect events/artifacts, cancel running tasks |
-| 📋 **Agent Card Discovery** | `/.well-known/agent.json` for client auto-discovery |
-| 🧪 **Protocol E2E Test Harness** | Real MCP SDK + A2A client flows in `test:protocols:e2e` |
-| ⚙️ **Operational Controls** | Switch combo, apply resilience profiles, reset breakers from one control surface |
+| Feature | What It Does |
+| ------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------- |
+| 🔧 **MCP Server (25 tools)** | IDE/agent tools via 3 transports: stdio, SSE (`/api/mcp/sse`), Streamable HTTP (`/api/mcp/stream`). 18 core + 3 memory + 4 skill tools |
+| 🤝 **A2A Server (JSON-RPC + SSE)** | Agent-to-agent task execution with sync and streaming flows |
+| 🧭 **Consolidated Endpoints Page** | Tabbed management page with Endpoint Proxy, MCP, A2A, and API Endpoints tabs |
+| 🎚️ **Service Enable/Disable Toggles** | ON/OFF switches for MCP and A2A with settings persistence (default: OFF) |
+| 🛰️ **MCP Runtime Heartbeat** | Real process status (pid, uptime, heartbeat age, transport, scope mode) |
+| 📋 **MCP Audit Trail** | Filterable audit logs with success/failure and key attribution |
+| 🔐 **MCP Scope Enforcement** | 10 granular scope permissions for controlled tool access |
+| 📡 **A2A Task Lifecycle Management** | List/filter tasks, inspect events/artifacts, cancel running tasks |
+| 📋 **Agent Card Discovery** | `/.well-known/agent.json` for client auto-discovery |
+| 🧪 **Protocol E2E Test Harness** | Real MCP SDK + A2A client flows in `test:protocols:e2e` |
+| ⚙️ **Operational Controls** | Switch combo, apply resilience profiles, reset breakers from one control surface |
### 🧠 Routing & Intelligence
@@ -1349,7 +1350,7 @@ OmniRoute v2.0 is built as an operational platform, not just a relay proxy.
| 🔄 **Format Translation** | OpenAI ↔ Claude ↔ Gemini ↔ Responses with schema-safe conversions |
| 👥 **Multi-Account Support** | Multiple accounts per provider with intelligent selection |
| 🔄 **Auto Token Refresh** | OAuth tokens refresh automatically with retry |
-| 🎨 **Custom Combos** | 6 balancing strategies + fallback chain control |
+| 🎨 **Custom Combos** | 9 balancing strategies + fallback chain control |
| 🌐 **Wildcard Router** | `provider/*` dynamic routing |
| 🧠 **Thinking Budget Controls** | Passthrough, auto, custom, and adaptive reasoning limits |
| 🔀 **Model Aliases** | Built-in + custom model aliasing and migration safety |
@@ -1950,6 +1951,7 @@ opencode
- Request artifacts are written to `DATA_DIR/call_logs/` as one JSON file per request
- Enable pipeline capture from Dashboard → Logs → Request Logs if you need detailed per-stage payloads
- Set `APP_LOG_TO_FILE=true` if you also want application console logs in `logs/application/app.log`
+- Adjust `APP_LOG_MAX_FILE_SIZE`, `APP_LOG_RETENTION_DAYS`, `APP_LOG_MAX_FILES`, and `CALL_LOG_MAX_ENTRIES` as needed
**Connection test shows "Invalid" for OpenAI-compatible providers**
diff --git a/docs/i18n/it/RELEASE_CHECKLIST.md b/docs/i18n/it/RELEASE_CHECKLIST.md
deleted file mode 100644
index 903e812c3f..0000000000
--- a/docs/i18n/it/RELEASE_CHECKLIST.md
+++ /dev/null
@@ -1,37 +0,0 @@
-🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/RELEASE_CHECKLIST.md) · 🇪🇸 [es](../es/RELEASE_CHECKLIST.md) · 🇫🇷 [fr](../fr/RELEASE_CHECKLIST.md) · 🇩🇪 [de](../de/RELEASE_CHECKLIST.md) · 🇮🇹 [it](../it/RELEASE_CHECKLIST.md) · 🇷🇺 [ru](../ru/RELEASE_CHECKLIST.md) · 🇨🇳 [zh-CN](../zh-CN/RELEASE_CHECKLIST.md) · 🇯🇵 [ja](../ja/RELEASE_CHECKLIST.md) · 🇰🇷 [ko](../ko/RELEASE_CHECKLIST.md) · 🇸🇦 [ar](../ar/RELEASE_CHECKLIST.md) · 🇮🇳 [in](../in/RELEASE_CHECKLIST.md) · 🇹🇭 [th](../th/RELEASE_CHECKLIST.md) · 🇻🇳 [vi](../vi/RELEASE_CHECKLIST.md) · 🇮🇩 [id](../id/RELEASE_CHECKLIST.md) · 🇲🇾 [ms](../ms/RELEASE_CHECKLIST.md) · 🇳🇱 [nl](../nl/RELEASE_CHECKLIST.md) · 🇵🇱 [pl](../pl/RELEASE_CHECKLIST.md) · 🇸🇪 [sv](../sv/RELEASE_CHECKLIST.md) · 🇳🇴 [no](../no/RELEASE_CHECKLIST.md) · 🇩🇰 [da](../da/RELEASE_CHECKLIST.md) · 🇫🇮 [fi](../fi/RELEASE_CHECKLIST.md) · 🇵🇹 [pt](../pt/RELEASE_CHECKLIST.md) · 🇷🇴 [ro](../ro/RELEASE_CHECKLIST.md) · 🇭🇺 [hu](../hu/RELEASE_CHECKLIST.md) · 🇧🇬 [bg](../bg/RELEASE_CHECKLIST.md) · 🇸🇰 [sk](../sk/RELEASE_CHECKLIST.md) · 🇺🇦 [uk-UA](../uk-UA/RELEASE_CHECKLIST.md) · 🇮🇱 [he](../he/RELEASE_CHECKLIST.md) · 🇵🇭 [phi](../phi/RELEASE_CHECKLIST.md)
-
----
-
-# Release Checklist
-
-Use this checklist before tagging or publishing a new OmniRoute release.
-
-## Version and Changelog
-
-1. Bump `package.json` version (`x.y.z`) in the release branch.
-2. Move release notes from `## [Unreleased]` in `CHANGELOG.md` to a dated section:
- - `## [x.y.z] — YYYY-MM-DD`
-3. Keep `## [Unreleased]` as the first changelog section for upcoming work.
-4. Ensure the latest semver section in `CHANGELOG.md` equals `package.json` version.
-
-## API Docs
-
-1. Update `docs/openapi.yaml`:
- - `info.version` must equal `package.json` version.
-2. Validate endpoint examples if API contracts changed.
-
-## Runtime Docs
-
-1. Review `docs/ARCHITECTURE.md` for storage/runtime drift.
-2. Review `docs/TROUBLESHOOTING.md` for env var and operational drift.
-3. Update localized docs if source docs changed significantly.
-
-## Automated Check
-
-Run the sync guard locally before opening PR:
-
-```bash
-npm run check:docs-sync
-```
-
-CI also runs this check in `.github/workflows/ci.yml` (lint job).
diff --git a/docs/i18n/it/SECURITY.md b/docs/i18n/it/SECURITY.md
new file mode 100644
index 0000000000..8cba79cba0
--- /dev/null
+++ b/docs/i18n/it/SECURITY.md
@@ -0,0 +1,179 @@
+# Security Policy (Italiano)
+
+🌐 **Languages:** 🇺🇸 [English](../../../SECURITY.md) · 🇪🇸 [es](../es/SECURITY.md) · 🇫🇷 [fr](../fr/SECURITY.md) · 🇩🇪 [de](../de/SECURITY.md) · 🇮🇹 [it](../it/SECURITY.md) · 🇷🇺 [ru](../ru/SECURITY.md) · 🇨🇳 [zh-CN](../zh-CN/SECURITY.md) · 🇯🇵 [ja](../ja/SECURITY.md) · 🇰🇷 [ko](../ko/SECURITY.md) · 🇸🇦 [ar](../ar/SECURITY.md) · 🇮🇳 [in](../in/SECURITY.md) · 🇹🇭 [th](../th/SECURITY.md) · 🇻🇳 [vi](../vi/SECURITY.md) · 🇮🇩 [id](../id/SECURITY.md) · 🇲🇾 [ms](../ms/SECURITY.md) · 🇳🇱 [nl](../nl/SECURITY.md) · 🇵🇱 [pl](../pl/SECURITY.md) · 🇸🇪 [sv](../sv/SECURITY.md) · 🇳🇴 [no](../no/SECURITY.md) · 🇩🇰 [da](../da/SECURITY.md) · 🇫🇮 [fi](../fi/SECURITY.md) · 🇵🇹 [pt](../pt/SECURITY.md) · 🇷🇴 [ro](../ro/SECURITY.md) · 🇭🇺 [hu](../hu/SECURITY.md) · 🇧🇬 [bg](../bg/SECURITY.md) · 🇸🇰 [sk](../sk/SECURITY.md) · 🇺🇦 [uk-UA](../uk-UA/SECURITY.md) · 🇮🇱 [he](../he/SECURITY.md) · 🇵🇭 [phi](../phi/SECURITY.md) · 🇧🇷 [pt-BR](../pt-BR/SECURITY.md) · 🇨🇿 [cs](../cs/SECURITY.md)
+
+---
+
+## Reporting Vulnerabilities
+
+If you discover a security vulnerability in OmniRoute, please report it responsibly:
+
+1. **DO NOT** open a public GitHub issue
+2. Use [GitHub Security Advisories](https://github.com/diegosouzapw/OmniRoute/security/advisories/new)
+3. Include: description, reproduction steps, and potential impact
+
+## Response Timeline
+
+| Stage | Target |
+| ------------------- | --------------------------- |
+| Acknowledgment | 48 hours |
+| Triage & Assessment | 5 business days |
+| Patch Release | 14 business days (critical) |
+
+## Supported Versions
+
+| Version | Support Status |
+| ------- | -------------- |
+| 3.4.x | ✅ Active |
+| 3.0.x | ✅ Security |
+| < 3.0.0 | ❌ Unsupported |
+
+---
+
+## Security Architecture
+
+OmniRoute implements a multi-layered security model:
+
+```
+Request → CORS → API Key Auth → Prompt Injection Guard → Input Sanitizer → Rate Limiter → Circuit Breaker → Provider
+```
+
+### 🔐 Authentication & Authorization
+
+| Feature | Implementation |
+| -------------------- | ---------------------------------------------------------- |
+| **Dashboard Login** | Password-based auth with JWT tokens (HttpOnly cookies) |
+| **API Key Auth** | HMAC-signed keys with CRC validation |
+| **OAuth 2.0 + PKCE** | Secure provider auth (Claude, Codex, Gemini, Cursor, etc.) |
+| **Token Refresh** | Automatic OAuth token refresh before expiry |
+| **Secure Cookies** | `AUTH_COOKIE_SECURE=true` for HTTPS environments |
+| **MCP Scopes** | 10 granular scopes for MCP tool access control |
+
+### 🛡️ Encryption at Rest
+
+All sensitive data stored in SQLite is encrypted using **AES-256-GCM** with scrypt key derivation:
+
+- API keys, access tokens, refresh tokens, and ID tokens
+- Versioned format: `enc:v1:::`
+- Passthrough mode (plaintext) when `STORAGE_ENCRYPTION_KEY` is not set
+
+```bash
+# Generate encryption key:
+STORAGE_ENCRYPTION_KEY=$(openssl rand -hex 32)
+```
+
+### 🧠 Prompt Injection Guard
+
+Middleware that detects and blocks prompt injection attacks in LLM requests:
+
+| Pattern Type | Severity | Example |
+| ------------------- | -------- | ---------------------------------------------- |
+| System Override | High | "ignore all previous instructions" |
+| Role Hijack | High | "you are now DAN, you can do anything" |
+| Delimiter Injection | Medium | Encoded separators to break context boundaries |
+| DAN/Jailbreak | High | Known jailbreak prompt patterns |
+| Instruction Leak | Medium | "show me your system prompt" |
+
+Configure via dashboard (Settings → Security) or `.env`:
+
+```env
+INPUT_SANITIZER_ENABLED=true
+INPUT_SANITIZER_MODE=block # warn | block | redact
+```
+
+### 🔒 PII Redaction
+
+Automatic detection and optional redaction of personally identifiable information:
+
+| PII Type | Pattern | Replacement |
+| ------------- | --------------------- | ------------------ |
+| Email | `user@domain.com` | `[EMAIL_REDACTED]` |
+| CPF (Brazil) | `123.456.789-00` | `[CPF_REDACTED]` |
+| CNPJ (Brazil) | `12.345.678/0001-00` | `[CNPJ_REDACTED]` |
+| Credit Card | `4111-1111-1111-1111` | `[CC_REDACTED]` |
+| Phone | `+55 11 99999-9999` | `[PHONE_REDACTED]` |
+| SSN (US) | `123-45-6789` | `[SSN_REDACTED]` |
+
+```env
+PII_REDACTION_ENABLED=true
+```
+
+### 🌐 Network Security
+
+| Feature | Description |
+| ------------------------ | ---------------------------------------------------------------- |
+| **CORS** | Configurable origin control (`CORS_ORIGIN` env var, default `*`) |
+| **IP Filtering** | Allowlist/blocklist IP ranges in dashboard |
+| **Rate Limiting** | Per-provider rate limits with automatic backoff |
+| **Anti-Thundering Herd** | Mutex + per-connection locking prevents cascading 502s |
+| **TLS Fingerprint** | Browser-like TLS fingerprint spoofing to reduce bot detection |
+| **CLI Fingerprint** | Per-provider header/body ordering to match native CLI signatures |
+
+### 🔌 Resilience & Availability
+
+| Feature | Description |
+| ----------------------- | ------------------------------------------------------------------ |
+| **Circuit Breaker** | 3-state (Closed → Open → Half-Open) per provider, SQLite-persisted |
+| **Request Idempotency** | 5-second dedup window for duplicate requests |
+| **Exponential Backoff** | Automatic retry with increasing delays |
+| **Health Dashboard** | Real-time provider health monitoring |
+
+### 📋 Compliance
+
+| Feature | Description |
+| ------------------ | ----------------------------------------------------------- |
+| **Log Retention** | Automatic cleanup after `CALL_LOG_RETENTION_DAYS` |
+| **No-Log Opt-out** | Per API key `noLog` flag disables request logging |
+| **Audit Log** | Administrative actions tracked in `audit_log` table |
+| **MCP Audit** | SQLite-backed audit logging for all MCP tool calls |
+| **Zod Validation** | All API inputs validated with Zod v4 schemas at module load |
+
+---
+
+## Required Environment Variables
+
+All secrets must be set before starting the server. The server will **fail fast** if they are missing or weak.
+
+```bash
+# REQUIRED — server will not start without these:
+JWT_SECRET=$(openssl rand -base64 48) # min 32 chars
+API_KEY_SECRET=$(openssl rand -hex 32) # min 16 chars
+
+# RECOMMENDED — enables encryption at rest:
+STORAGE_ENCRYPTION_KEY=$(openssl rand -hex 32)
+```
+
+The server actively rejects known-weak values like `changeme`, `secret`, or `password`.
+
+---
+
+## Docker Security
+
+- Use non-root user in production
+- Mount secrets as read-only volumes
+- Never copy `.env` files into Docker images
+- Use `.dockerignore` to exclude sensitive files
+- Set `AUTH_COOKIE_SECURE=true` when behind HTTPS
+
+```bash
+docker run -d \
+ --name omniroute \
+ --restart unless-stopped \
+ --read-only \
+ -p 20128:20128 \
+ -v omniroute-data:/app/data \
+ -e JWT_SECRET="$(openssl rand -base64 48)" \
+ -e API_KEY_SECRET="$(openssl rand -hex 32)" \
+ -e STORAGE_ENCRYPTION_KEY="$(openssl rand -hex 32)" \
+ diegosouzapw/omniroute:latest
+```
+
+---
+
+## Dependencies
+
+- Run `npm audit` regularly
+- Keep dependencies updated
+- The project uses `husky` + `lint-staged` for pre-commit checks
+- CI pipeline runs ESLint security rules on every push
+- Provider constants validated at module load via Zod (`src/shared/validation/providerSchema.ts`)
diff --git a/docs/i18n/it/TROUBLESHOOTING.md b/docs/i18n/it/TROUBLESHOOTING.md
deleted file mode 100644
index 63c148000a..0000000000
--- a/docs/i18n/it/TROUBLESHOOTING.md
+++ /dev/null
@@ -1,258 +0,0 @@
-🌐 **Languages:** 🇺🇸 [English](../../README.md) · 🇧🇷 [pt-BR](../pt-BR/TROUBLESHOOTING.md) · 🇪🇸 [es](../es/TROUBLESHOOTING.md) · 🇫🇷 [fr](../fr/TROUBLESHOOTING.md) · 🇩🇪 [de](../de/TROUBLESHOOTING.md) · 🇮🇹 [it](../it/TROUBLESHOOTING.md) · 🇷🇺 [ru](../ru/TROUBLESHOOTING.md) · 🇨🇳 [zh-CN](../zh-CN/TROUBLESHOOTING.md) · 🇯🇵 [ja](../ja/TROUBLESHOOTING.md) · 🇰🇷 [ko](../ko/TROUBLESHOOTING.md) · 🇸🇦 [ar](../ar/TROUBLESHOOTING.md) · 🇮🇳 [in](../in/TROUBLESHOOTING.md) · 🇹🇭 [th](../th/TROUBLESHOOTING.md) · 🇻🇳 [vi](../vi/TROUBLESHOOTING.md) · 🇮🇩 [id](../id/TROUBLESHOOTING.md) · 🇲🇾 [ms](../ms/TROUBLESHOOTING.md) · 🇳🇱 [nl](../nl/TROUBLESHOOTING.md) · 🇵🇱 [pl](../pl/TROUBLESHOOTING.md) · 🇸🇪 [sv](../sv/TROUBLESHOOTING.md) · 🇳🇴 [no](../no/TROUBLESHOOTING.md) · 🇩🇰 [da](../da/TROUBLESHOOTING.md) · 🇫🇮 [fi](../fi/TROUBLESHOOTING.md) · 🇵🇹 [pt](../pt/TROUBLESHOOTING.md) · 🇷🇴 [ro](../ro/TROUBLESHOOTING.md) · 🇭🇺 [hu](../hu/TROUBLESHOOTING.md) · 🇧🇬 [bg](../bg/TROUBLESHOOTING.md) · 🇸🇰 [sk](../sk/TROUBLESHOOTING.md) · 🇺🇦 [uk-UA](../uk-UA/TROUBLESHOOTING.md) · 🇮🇱 [he](../he/TROUBLESHOOTING.md) · 🇵🇭 [phi](../phi/TROUBLESHOOTING.md)
-
----
-
-# Troubleshooting
-
-🌐 **Languages:** 🇺🇸 [English](TROUBLESHOOTING.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/TROUBLESHOOTING.md) | 🇪🇸 [Español](i18n/es/TROUBLESHOOTING.md) | 🇫🇷 [Français](i18n/fr/TROUBLESHOOTING.md) | 🇮🇹 [Italiano](i18n/it/TROUBLESHOOTING.md) | 🇷🇺 [Русский](i18n/ru/TROUBLESHOOTING.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/TROUBLESHOOTING.md) | 🇩🇪 [Deutsch](i18n/de/TROUBLESHOOTING.md) | 🇮🇳 [हिन्दी](i18n/in/TROUBLESHOOTING.md) | 🇹🇭 [ไทย](i18n/th/TROUBLESHOOTING.md) | 🇺🇦 [Українська](i18n/uk-UA/TROUBLESHOOTING.md) | 🇸🇦 [العربية](i18n/ar/TROUBLESHOOTING.md) | 🇯🇵 [日本語](i18n/ja/TROUBLESHOOTING.md) | 🇻🇳 [Tiếng Việt](i18n/vi/TROUBLESHOOTING.md) | 🇧🇬 [Български](i18n/bg/TROUBLESHOOTING.md) | 🇩🇰 [Dansk](i18n/da/TROUBLESHOOTING.md) | 🇫🇮 [Suomi](i18n/fi/TROUBLESHOOTING.md) | 🇮🇱 [עברית](i18n/he/TROUBLESHOOTING.md) | 🇭🇺 [Magyar](i18n/hu/TROUBLESHOOTING.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/TROUBLESHOOTING.md) | 🇰🇷 [한국어](i18n/ko/TROUBLESHOOTING.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/TROUBLESHOOTING.md) | 🇳🇱 [Nederlands](i18n/nl/TROUBLESHOOTING.md) | 🇳🇴 [Norsk](i18n/no/TROUBLESHOOTING.md) | 🇵🇹 [Português (Portugal)](i18n/pt/TROUBLESHOOTING.md) | 🇷🇴 [Română](i18n/ro/TROUBLESHOOTING.md) | 🇵🇱 [Polski](i18n/pl/TROUBLESHOOTING.md) | 🇸🇰 [Slovenčina](i18n/sk/TROUBLESHOOTING.md) | 🇸🇪 [Svenska](i18n/sv/TROUBLESHOOTING.md) | 🇵🇭 [Filipino](i18n/phi/TROUBLESHOOTING.md)
-
-Common problems and solutions for OmniRoute.
-
----
-
-## Quick Fixes
-
-| Problem | Solution |
-| ----------------------------- | ------------------------------------------------------------------ |
-| First login not working | Set `INITIAL_PASSWORD` in `.env` (no hardcoded default) |
-| Dashboard opens on wrong port | Set `PORT=20128` and `NEXT_PUBLIC_BASE_URL=http://localhost:20128` |
-| No request logs under `logs/` | Set `ENABLE_REQUEST_LOGS=true` |
-| EACCES: permission denied | Set `DATA_DIR=/path/to/writable/dir` to override `~/.omniroute` |
-| Routing strategy not saving | Update to v1.4.11+ (Zod schema fix for settings persistence) |
-
----
-
-## Provider Issues
-
-### "Language model did not provide messages"
-
-**Cause:** Provider quota exhausted.
-
-**Fix:**
-
-1. Check dashboard quota tracker
-2. Use a combo with fallback tiers
-3. Switch to cheaper/free tier
-
-### Rate Limiting
-
-**Cause:** Subscription quota exhausted.
-
-**Fix:**
-
-- Add fallback: `cc/claude-opus-4-6 → glm/glm-4.7 → if/kimi-k2-thinking`
-- Use GLM/MiniMax as cheap backup
-
-### OAuth Token Expired
-
-OmniRoute auto-refreshes tokens. If issues persist:
-
-1. Dashboard → Provider → Reconnect
-2. Delete and re-add the provider connection
-
----
-
-## Cloud Issues
-
-### Cloud Sync Errors
-
-1. Verify `BASE_URL` points to your running instance (e.g., `http://localhost:20128`)
-2. Verify `CLOUD_URL` points to your cloud endpoint (e.g., `https://omniroute.dev`)
-3. Keep `NEXT_PUBLIC_*` values aligned with server-side values
-
-### Cloud `stream=false` Returns 500
-
-**Symptom:** `Unexpected token 'd'...` on cloud endpoint for non-streaming calls.
-
-**Cause:** Upstream returns SSE payload while client expects JSON.
-
-**Workaround:** Use `stream=true` for cloud direct calls. Local runtime includes SSE→JSON fallback.
-
-### Cloud Says Connected but "Invalid API key"
-
-1. Create a fresh key from local dashboard (`/api/keys`)
-2. Run cloud sync: Enable Cloud → Sync Now
-3. Old/non-synced keys can still return `401` on cloud
-
----
-
-## Docker Issues
-
-### CLI Tool Shows Not Installed
-
-1. Check runtime fields: `curl http://localhost:20128/api/cli-tools/runtime/codex | jq`
-2. For portable mode: use image target `runner-cli` (bundled CLIs)
-3. For host mount mode: set `CLI_EXTRA_PATHS` and mount host bin directory as read-only
-4. If `installed=true` and `runnable=false`: binary was found but failed healthcheck
-
-### Quick Runtime Validation
-
-```bash
-curl -s http://localhost:20128/api/cli-tools/codex-settings | jq '{installed,runnable,commandPath,runtimeMode,reason}'
-curl -s http://localhost:20128/api/cli-tools/claude-settings | jq '{installed,runnable,commandPath,runtimeMode,reason}'
-curl -s http://localhost:20128/api/cli-tools/openclaw-settings | jq '{installed,runnable,commandPath,runtimeMode,reason}'
-```
-
----
-
-## Cost Issues
-
-### High Costs
-
-1. Check usage stats in Dashboard → Usage
-2. Switch primary model to GLM/MiniMax
-3. Use free tier (Gemini CLI, Qoder) for non-critical tasks
-4. Set cost budgets per API key: Dashboard → API Keys → Budget
-
----
-
-## Debugging
-
-### Enable Request Logs
-
-Set `ENABLE_REQUEST_LOGS=true` in your `.env` file. Logs appear under `logs/` directory.
-
-### Check Provider Health
-
-```bash
-# Health dashboard
-http://localhost:20128/dashboard/health
-
-# API health check
-curl http://localhost:20128/api/monitoring/health
-```
-
-### Runtime Storage
-
-- Main state: `${DATA_DIR}/storage.sqlite` (providers, combos, aliases, keys, settings)
-- Usage: SQLite tables in `storage.sqlite` (`usage_history`, `call_logs`, `proxy_logs`) + optional `${DATA_DIR}/log.txt` and `${DATA_DIR}/call_logs/`
-- Request logs: `/logs/...` (when `ENABLE_REQUEST_LOGS=true`)
-
----
-
-## Circuit Breaker Issues
-
-### Provider stuck in OPEN state
-
-When a provider's circuit breaker is OPEN, requests are blocked until the cooldown expires.
-
-**Fix:**
-
-1. Go to **Dashboard → Settings → Resilience**
-2. Check the circuit breaker card for the affected provider
-3. Click **Reset All** to clear all breakers, or wait for the cooldown to expire
-4. Verify the provider is actually available before resetting
-
-### Provider keeps tripping the circuit breaker
-
-If a provider repeatedly enters OPEN state:
-
-1. Check **Dashboard → Health → Provider Health** for the failure pattern
-2. Go to **Settings → Resilience → Provider Profiles** and increase the failure threshold
-3. Check if the provider has changed API limits or requires re-authentication
-4. Review latency telemetry — high latency may cause timeout-based failures
-
----
-
-## Audio Transcription Issues
-
-### "Unsupported model" error
-
-- Ensure you're using the correct prefix: `deepgram/nova-3` or `assemblyai/best`
-- Verify the provider is connected in **Dashboard → Providers**
-
-### Transcription returns empty or fails
-
-- Check supported audio formats: `mp3`, `wav`, `m4a`, `flac`, `ogg`, `webm`
-- Verify file size is within provider limits (typically < 25MB)
-- Check provider API key validity in the provider card
-
----
-
-## Translator Debugging
-
-Use **Dashboard → Translator** to debug format translation issues:
-
-| Mode | When to Use |
-| ---------------- | -------------------------------------------------------------------------------------------- |
-| **Playground** | Compare input/output formats side by side — paste a failing request to see how it translates |
-| **Chat Tester** | Send live messages and inspect the full request/response payload including headers |
-| **Test Bench** | Run batch tests across format combinations to find which translations are broken |
-| **Live Monitor** | Watch real-time request flow to catch intermittent translation issues |
-
-### Common format issues
-
-- **Thinking tags not appearing** — Check if the target provider supports thinking and the thinking budget setting
-- **Tool calls dropping** — Some format translations may strip unsupported fields; verify in Playground mode
-- **System prompt missing** — Claude and Gemini handle system prompts differently; check translation output
-- **SDK returns raw string instead of object** — Fixed in v1.1.0: response sanitizer now strips non-standard fields (`x_groq`, `usage_breakdown`, etc.) that cause OpenAI SDK Pydantic validation failures
-- **GLM/ERNIE rejects `system` role** — Fixed in v1.1.0: role normalizer automatically merges system messages into user messages for incompatible models
-- **`developer` role not recognized** — Fixed in v1.1.0: automatically converted to `system` for non-OpenAI providers
-- **`json_schema` not working with Gemini** — Fixed in v1.1.0: `response_format` is now converted to Gemini's `responseMimeType` + `responseSchema`
-
----
-
-## Resilience Settings
-
-### Auto rate-limit not triggering
-
-- Auto rate-limit only applies to API key providers (not OAuth/subscription)
-- Verify **Settings → Resilience → Provider Profiles** has auto-rate-limit enabled
-- Check if the provider returns `429` status codes or `Retry-After` headers
-
-### Tuning exponential backoff
-
-Provider profiles support these settings:
-
-- **Base delay** — Initial wait time after first failure (default: 1s)
-- **Max delay** — Maximum wait time cap (default: 30s)
-- **Multiplier** — How much to increase delay per consecutive failure (default: 2x)
-
-### Anti-thundering herd
-
-When many concurrent requests hit a rate-limited provider, OmniRoute uses mutex + auto rate-limiting to serialize requests and prevent cascading failures. This is automatic for API key providers.
-
----
-
-## Optional RAG / LLM failure taxonomy (16 problems)
-
-Some OmniRoute users place the gateway in front of RAG or agent stacks. In those setups it is common to see a strange pattern: OmniRoute looks healthy (providers up, routing profiles ok, no rate limit alerts) but the final answer is still wrong.
-
-In practice these incidents usually come from the downstream RAG pipeline, not from the gateway itself.
-
-If you want a shared vocabulary to describe those failures you can use the WFGY ProblemMap, an external MIT license text resource that defines sixteen recurring RAG / LLM failure patterns. At a high level it covers:
-
-- retrieval drift and broken context boundaries
-- empty or stale indexes and vector stores
-- embedding versus semantic mismatch
-- prompt assembly and context window issues
-- logic collapse and overconfident answers
-- long chain and agent coordination failures
-- multi agent memory and role drift
-- deployment and bootstrap ordering problems
-
-The idea is simple:
-
-1. When you investigate a bad response, capture:
- - user task and request
- - route or provider combo in OmniRoute
- - any RAG context used downstream (retrieved documents, tool calls, etc)
-2. Map the incident to one or two WFGY ProblemMap numbers (`No.1` … `No.16`).
-3. Store the number in your own dashboard, runbook, or incident tracker next to the OmniRoute logs.
-4. Use the corresponding WFGY page to decide whether you need to change your RAG stack, retriever, or routing strategy.
-
-Full text and concrete recipes live here (MIT license, text only):
-
-[WFGY ProblemMap README](https://github.com/onestardao/WFGY/blob/main/ProblemMap/README.md)
-
-You can ignore this section if you do not run RAG or agent pipelines behind OmniRoute.
-
----
-
-## Still Stuck?
-
-- **GitHub Issues**: [github.com/diegosouzapw/OmniRoute/issues](https://github.com/diegosouzapw/OmniRoute/issues)
-- **Architecture**: See [`docs/ARCHITECTURE.md`](ARCHITECTURE.md) for internal details
-- **API Reference**: See [`docs/API_REFERENCE.md`](API_REFERENCE.md) for all endpoints
-- **Health Dashboard**: Check **Dashboard → Health** for real-time system status
-- **Translator**: Use **Dashboard → Translator** to debug format issues
diff --git a/docs/i18n/it/VM_DEPLOYMENT_GUIDE.md b/docs/i18n/it/VM_DEPLOYMENT_GUIDE.md
deleted file mode 100644
index c0581b1777..0000000000
--- a/docs/i18n/it/VM_DEPLOYMENT_GUIDE.md
+++ /dev/null
@@ -1,401 +0,0 @@
-# OmniRoute: guida alla distribuzione su VM con Cloudflare
-
-🌐 **Languages:** 🇺🇸 [English](../../VM_DEPLOYMENT_GUIDE.md) | 🇧🇷 [Português (Brasil)](../pt-BR/VM_DEPLOYMENT_GUIDE.md) | 🇪🇸 [Español](../es/VM_DEPLOYMENT_GUIDE.md) | 🇫🇷 [Français](../fr/VM_DEPLOYMENT_GUIDE.md) | 🇮🇹 [Italiano](../it/VM_DEPLOYMENT_GUIDE.md) | 🇷🇺 [Русский](../ru/VM_DEPLOYMENT_GUIDE.md) | 🇨🇳 [中文 (简体)](../zh-CN/VM_DEPLOYMENT_GUIDE.md) | 🇩🇪 [Deutsch](../de/VM_DEPLOYMENT_GUIDE.md) | 🇮🇳 [हिन्दी](../in/VM_DEPLOYMENT_GUIDE.md) | 🇹🇭 [ไทย](../th/VM_DEPLOYMENT_GUIDE.md) | 🇺🇦 [Українська](../uk-UA/VM_DEPLOYMENT_GUIDE.md) | 🇸🇦 [العربية](../ar/VM_DEPLOYMENT_GUIDE.md) | 🇯🇵 [日本語](../ja/VM_DEPLOYMENT_GUIDE.md) | 🇻🇳 [Tiếng Việt](../vi/VM_DEPLOYMENT_GUIDE.md) | 🇧🇬 [Български](../bg/VM_DEPLOYMENT_GUIDE.md) | 🇩🇰 [Dansk](../da/VM_DEPLOYMENT_GUIDE.md) | 🇫🇮 [Suomi](../fi/VM_DEPLOYMENT_GUIDE.md) | 🇮🇱 [עברית](../he/VM_DEPLOYMENT_GUIDE.md) | 🇭🇺 [Magyar](../hu/VM_DEPLOYMENT_GUIDE.md) | 🇮🇩 [Bahasa Indonesia](../id/VM_DEPLOYMENT_GUIDE.md) | 🇰🇷 [한국어](../ko/VM_DEPLOYMENT_GUIDE.md) | 🇲🇾 [Bahasa Melayu](../ms/VM_DEPLOYMENT_GUIDE.md) | 🇳🇱 [Nederlands](../nl/VM_DEPLOYMENT_GUIDE.md) | 🇳🇴 [Norsk](../no/VM_DEPLOYMENT_GUIDE.md) | 🇵🇹 [Português (Portugal)](../pt/VM_DEPLOYMENT_GUIDE.md) | 🇷🇴 [Română](../ro/VM_DEPLOYMENT_GUIDE.md) | 🇵🇱 [Polski](../pl/VM_DEPLOYMENT_GUIDE.md) | 🇸🇰 [Slovenčina](../sk/VM_DEPLOYMENT_GUIDE.md) | 🇸🇪 [Svenska](../sv/VM_DEPLOYMENT_GUIDE.md) | 🇵🇭 [Filipino](../phi/VM_DEPLOYMENT_GUIDE.md) | 🇨🇿 [Čeština](../cs/VM_DEPLOYMENT_GUIDE.md)
-
-Guida completa per installare e configurare OmniRoute su una VM (VPS) con dominio gestito tramite Cloudflare.
-
----
-
-## Prerequisiti
-
-| Articolo | Minimo | Consigliato |
-| --------------------- | ------------------------ | ---------------- |
-| **CPU** | 1 CPU virtuale | 2 vCPU |
-| **RAM** | 1GB | 2GB |
-| **Disco** | SSD da 10GB | SSD da 25GB |
-| **Sistema operativo** | Ubuntu 22.04 LTS | Ubuntu 24.04 LTS |
-| **Dominio** | Registrato su Cloudflare | — |
-| **Docker** | Motore Docker24+ | Docker27+ |
-
-**Fornitori testati**: Akamai (Linode), DigitalOcean, Vultr, Hetzner, AWS Lightsail.
-
----
-
-## 1. Configura la VM
-
-### 1.1 Creare l'istanza
-
-Sul tuo provider VPS preferito:
-
-- Scegli Ubuntu 24.04 LTS
-- Seleziona il piano minimo (1 vCPU / 1 GB RAM)
-- Imposta una password root complessa o configura la chiave SSH
-- Prendi nota dell'**IP pubblico** (ad esempio, `203.0.113.10`)
-
-### 1.2 Connetti tramite SSH
-
-```bash
-ssh root@203.0.113.10
-```
-
-### 1.3 Aggiornare il sistema
-
-```bash
-apt update && apt upgrade -y
-```
-
-### 1.4 Installa Docker
-
-```bash
-# Install dependencies
-apt install -y ca-certificates curl gnupg
-
-# Add official Docker repository
-install -m 0755 -d /etc/apt/keyrings
-curl -fsSL https://download.docker.com/linux/ubuntu/gpg | gpg --dearmor -o /etc/apt/keyrings/docker.gpg
-chmod a+r /etc/apt/keyrings/docker.gpg
-echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu $ (. /etc/os-release && echo “$VERSION_CODENAME”) stable" | tee /etc/apt/sources.list.d/docker.list > /dev/null
-apt update
-apt install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin
-```
-
-### 1.5 Installa nginx
-
-```bash
-apt install -y nginx
-```
-
-### 1.6 Configurazione del firewall (UFW)
-
-```bash
-ufw default deny incoming
-ufw default allow outgoing
-ufw allow 22/tcp # SSH
-ufw allow 80/tcp # HTTP (redirect)
-ufw allow 443/tcp # HTTPS
-ufw enable
-```
-
-> **Suggerimento**: per la massima sicurezza, limita le porte 80 e 443 solo agli IP Cloudflare. Consulta la sezione [Advanced Security](#advanced-security).
-
----
-
-## 2. Installa OmniRoute
-
-### 2.1 Creare la directory di configurazione
-
-```bash
-mkdir -p /opt/omniroute
-```
-
-### 2.2 Creare il file delle variabili d'ambiente
-
-```bash
-cat > /opt/omniroute/.env << ‘EOF’
-# === Security ===
-JWT_SECRET=CHANGE-TO-A-UNIQUE-64-CHAR-SECRET-KEY
-INITIAL_PASSWORD=YourSecurePassword123!
-API_KEY_SECRET=REPLACE-WITH-ANOTHER-SECRET-KEY
-STORAGE_ENCRYPTION_KEY=REPLACE-WITH-THIRD-SECRET-KEY
-STORAGE_ENCRYPTION_KEY_VERSION=v1
-MACHINE_ID_SALT=CHANGE-TO-A-UNIQUE-SALT
-
-# === App ===
-PORT=20128
-NODE_ENV=production
-HOSTNAME=0.0.0.0
-DATA_DIR=/app/data
-STORAGE_DRIVER=sqlite
-ENABLE_REQUEST_LOGS=true
-AUTH_COOKIE_SECURE=false
-REQUIRE_API_KEY=false
-
-# === Domain (change to your domain) ===
-BASE_URL=https://llms.seudominio.com
-NEXT_PUBLIC_BASE_URL=https://llms.seudominio.com
-
-# === Cloud Sync (optional) ===
-# CLOUD_URL=https://cloud.omniroute.online
-# NEXT_PUBLIC_CLOUD_URL=https://cloud.omniroute.online
-EOF
-```
-
-> ⚠️ **IMPORTANTE**: genera chiavi segrete uniche! Utilizza `openssl rand -hex 32` per ciascuna chiave.
-
-### 2.3 Avviare il contenitore
-
-```bash
-docker pull diegosouzapw/omniroute:latest
-
-docker run -d \
- --name omniroute \
- --restart unless-stopped \
- --env-file /opt/omniroute/.env \
- -p 20128:20128 \
- -v omniroute-data:/app/data \
- diegosouzapw/omniroute:latest
-```
-
-### 2.4 Verificare che sia in esecuzione
-
-```bash
-docker ps | grep omniroute
-docker logs omniroute --tail 20
-```
-
-Dovrebbe essere visualizzato: `[DB] SQLite database ready` e `listening on port 20128`.
-
----
-
-## 3. Configura nginx (proxy inverso)
-
-### 3.1 Genera certificato SSL (Cloudflare Origin)
-
-Nella dashboard di Cloudflare:
-
-1. Vai su **SSL/TLS → Server di origine**
-2. Fai clic su **Crea certificato**
-3. Mantieni le impostazioni predefinite (15 anni, \*.tuodominio.com)
-4. Copia il **Certificato di Origine** e la **Chiave Privata**
-
-```bash
-mkdir -p /etc/nginx/ssl
-
-# Paste the certificate
-nano /etc/nginx/ssl/origin.crt
-
-# Paste the private key
-nano /etc/nginx/ssl/origin.key
-
-chmod 600 /etc/nginx/ssl/origin.key
-```
-
-### 3.2 Configurazione Nginx
-
-```bash
-cat > /etc/nginx/sites-available/omniroute << ‘NGINX’
-# Default server — blocks direct access via IP
-server {
- listen 80 default_server;
- listen [::]:80 default_server;
- listen 443 ssl default_server;
- listen [::]:443 ssl default_server;
- ssl_certificate /etc/nginx/ssl/origin.crt;
- ssl_certificate_key /etc/nginx/ssl/origin.key;
- server_name _;
- return 444;
-}
-
-# OmniRoute — HTTPS
-server {
- listen 443 ssl;
- listen [::]:443 ssl;
- server_name llms.yourdomain.com; # Change to your domain
-
- ssl_certificate /etc/nginx/ssl/origin.crt;
- ssl_certificate_key /etc/nginx/ssl/origin.key;
- ssl_protocols TLSv1.2 TLSv1.3;
-
- client_max_body_size 100M;
-
- location / {
- proxy_pass http://127.0.0.1:20128;
- proxy_set_header Host $host;
- proxy_set_header X-Real-IP $remote_addr;
- proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
- proxy_set_header X-Forwarded-Proto $scheme;
-
- # WebSocket support
- proxy_http_version 1.1;
- proxy_set_header Upgrade $http_upgrade;
- proxy_set_header Connection “upgrade”;
-
- # SSE (Server-Sent Events) — streaming AI responses
- proxy_buffering off;
- proxy_cache off;
- proxy_read_timeout 300s;
- proxy_send_timeout 300s;
- }
-}
-
-# HTTP → HTTPS redirect
-server {
- listen 80;
- listen [::]:80;
- server_name llms.yourdomain.com;
- return 301 https://$server_name$request_uri;
-}
-NGINX
-```
-
-### 3.3 Abilita e prova
-
-```bash
-# Remove default configuration
-rm -f /etc/nginx/sites-enabled/default
-
-# Enable OmniRoute
-ln -sf /etc/nginx/sites-available/omniroute /etc/nginx/sites-enabled/omniroute
-
-# Test and reload
-nginx -t && systemctl reload nginx
-```
-
----
-
-## 4. Configura il DNS di Cloudflare
-
-### 4.1 Aggiungi record DNS
-
-Nella dashboard di Cloudflare → DNS:
-
-| Digitare | Nome | Contenuto | Procura |
-| -------- | ------ | ------------------------------------------- | ---------- |
-| A | `llms` | `203.0.113.10` (IP della macchina virtuale) | ✅ Procura |
-
-### 4.2 Configurare SSL
-
-In **SSL/TLS → Panoramica**:
-
-- Modalità: **Completa (Ristretta)**
-
-In **SSL/TLS → Certificati Edge**:
-
-- Usa sempre HTTPS: ✅ Attivo
-- Versione TLS minima: TLS 1.2
-- Riscritture HTTPS automatiche: ✅ On
-
-### 4.3 Test
-
-```bash
-curl -sI https://llms.seudominio.com/health
-# Should return HTTP/2 200
-```
-
----
-
-## 5. Operazioni e manutenzione
-
-### Aggiorna a una nuova versione
-
-```bash
-docker pull diegosouzapw/omniroute:latest
-docker stop omniroute && docker rm omniroute
-docker run -d --name omniroute --restart unless-stopped \
- --env-file /opt/omniroute/.env \
- -p 20128:20128 \
- -v omniroute-data:/app/data \
- diegosouzapw/omniroute:latest
-```
-
-### Visualizza i registri
-
-```bash
-docker logs -f omniroute # Real-time stream
-docker logs omniroute --tail 50 # Last 50 lines
-```
-
-### Backup manuale del database
-
-```bash
-# Copy data from the volume to the host
-docker cp omniroute:/app/data ./backup-$(date +%F)
-
-# Or compress the entire volume
-docker run --rm -v omniroute-data:/data -v $(pwd):/backup \
- alpine tar czf /backup/omniroute-data-$(date +%F).tar.gz /data
-```
-
-### Ripristina dal backup
-
-```bash
-docker stop omniroute
-docker run --rm -v omniroute-data:/data -v $(pwd):/backup \
- alpine sh -c “rm -rf /data/* && tar xzf /backup/omniroute-data-YYYY-MM-DD.tar.gz -C /”
-docker start omniroute
-```
-
----
-
-## 6. Sicurezza avanzata
-
-### Limita nginx agli IP Cloudflare
-
-```bash
-cat > /etc/nginx/cloudflare-ips.conf << ‘CF’
-# Cloudflare IPv4 ranges — update periodically
-# https://www.cloudflare.com/ips-v4/
-set_real_ip_from 173.245.48.0/20;
-set_real_ip_from 103.21.244.0/22;
-set_real_ip_from 103.22.200.0/22;
-set_real_ip_from 103.31.4.0/22;
-set_real_ip_from 141.101.64.0/18;
-set_real_ip_from 108.162.192.0/18;
-set_real_ip_from 190.93.240.0/20;
-set_real_ip_from 188.114.96.0/20;
-set_real_ip_from 197.234.240.0/22;
-set_real_ip_from 198.41.128.0/17;
-set_real_ip_from 162.158.0.0/15;
-set_real_ip_from 104.16.0.0/13;
-set_real_ip_from 104.24.0.0/14;
-set_real_ip_from 172.64.0.0/13;
-set_real_ip_from 131.0.72.0/22;
-real_ip_header CF-Connecting-IP;
-CF
-```
-
-Aggiungi quanto segue a `nginx.conf` all'interno del blocco `http {}`:
-
-```nginx
-include /etc/nginx/cloudflare-ips.conf;
-```
-
-### Installa fail2ban
-
-```bash
-apt install -y fail2ban
-systemctl enable fail2ban
-systemctl start fail2ban
-
-# Check status
-fail2ban-client status sshd
-```
-
-### Blocca l'accesso diretto alla porta Docker
-
-```bash
-# Prevent direct external access to port 20128
-iptables -I DOCKER-USER -p tcp --dport 20128 -j DROP
-iptables -I DOCKER-USER -i lo -p tcp --dport 20128 -j ACCEPT
-
-# Persist the rules
-apt install -y iptables-persistent
-netfilter-persistent save
-```
-
----
-
-## 7. Distribuzione ai dipendenti Cloudflare (facoltativo)
-
-Per l'accesso remoto tramite Cloudflare Workers (senza esporre direttamente la VM):
-
-```bash
-# In the local repository
-cd omnirouteCloud
-npm install
-npx wrangler login
-npx wrangler deploy
-```
-
-Consulta la documentazione completa su [omnirouteCloud/README.md](../omnirouteCloud/README.md).
-
----
-
-## Riepilogo delle porte
-
-| Porto | Servizio | Accesso |
-| ----- | ----------- | -------------------------------- |
-| 22 | SSH | Pubblico (con fail2ban) |
-| 80 | nginxHTTP | Reindirizzamento → HTTPS |
-| 443 | nginx HTTPS | Tramite proxy Cloudflare |
-| 20128 | OmniRoute | Solo host locale (tramite nginx) |
diff --git a/docs/i18n/it/docs/A2A-SERVER.md b/docs/i18n/it/docs/A2A-SERVER.md
new file mode 100644
index 0000000000..98d12968b4
--- /dev/null
+++ b/docs/i18n/it/docs/A2A-SERVER.md
@@ -0,0 +1,200 @@
+# OmniRoute A2A Server Documentation (Italiano)
+
+🌐 **Languages:** 🇺🇸 [English](../../../../docs/A2A-SERVER.md) · 🇪🇸 [es](../../es/docs/A2A-SERVER.md) · 🇫🇷 [fr](../../fr/docs/A2A-SERVER.md) · 🇩🇪 [de](../../de/docs/A2A-SERVER.md) · 🇮🇹 [it](../../it/docs/A2A-SERVER.md) · 🇷🇺 [ru](../../ru/docs/A2A-SERVER.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/A2A-SERVER.md) · 🇯🇵 [ja](../../ja/docs/A2A-SERVER.md) · 🇰🇷 [ko](../../ko/docs/A2A-SERVER.md) · 🇸🇦 [ar](../../ar/docs/A2A-SERVER.md) · 🇮🇳 [in](../../in/docs/A2A-SERVER.md) · 🇹🇭 [th](../../th/docs/A2A-SERVER.md) · 🇻🇳 [vi](../../vi/docs/A2A-SERVER.md) · 🇮🇩 [id](../../id/docs/A2A-SERVER.md) · 🇲🇾 [ms](../../ms/docs/A2A-SERVER.md) · 🇳🇱 [nl](../../nl/docs/A2A-SERVER.md) · 🇵🇱 [pl](../../pl/docs/A2A-SERVER.md) · 🇸🇪 [sv](../../sv/docs/A2A-SERVER.md) · 🇳🇴 [no](../../no/docs/A2A-SERVER.md) · 🇩🇰 [da](../../da/docs/A2A-SERVER.md) · 🇫🇮 [fi](../../fi/docs/A2A-SERVER.md) · 🇵🇹 [pt](../../pt/docs/A2A-SERVER.md) · 🇷🇴 [ro](../../ro/docs/A2A-SERVER.md) · 🇭🇺 [hu](../../hu/docs/A2A-SERVER.md) · 🇧🇬 [bg](../../bg/docs/A2A-SERVER.md) · 🇸🇰 [sk](../../sk/docs/A2A-SERVER.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/A2A-SERVER.md) · 🇮🇱 [he](../../he/docs/A2A-SERVER.md) · 🇵🇭 [phi](../../phi/docs/A2A-SERVER.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/A2A-SERVER.md) · 🇨🇿 [cs](../../cs/docs/A2A-SERVER.md)
+
+---
+
+> Agent-to-Agent Protocol v0.3 — OmniRoute as an intelligent routing agent
+
+## Agent Discovery
+
+```bash
+curl http://localhost:20128/.well-known/agent.json
+```
+
+Returns the Agent Card describing OmniRoute's capabilities, skills, and authentication requirements.
+
+---
+
+## Authentication
+
+All `/a2a` requests require an API key via the `Authorization` header:
+
+```
+Authorization: Bearer YOUR_OMNIROUTE_API_KEY
+```
+
+If no API key is configured on the server, authentication is bypassed.
+
+---
+
+## JSON-RPC 2.0 Methods
+
+### `message/send` — Synchronous Execution
+
+Sends a message to a skill and waits for the complete response.
+
+```bash
+curl -X POST http://localhost:20128/a2a \
+ -H "Content-Type: application/json" \
+ -H "Authorization: Bearer YOUR_KEY" \
+ -d '{
+ "jsonrpc": "2.0",
+ "id": "1",
+ "method": "message/send",
+ "params": {
+ "skill": "smart-routing",
+ "messages": [{"role": "user", "content": "Write a hello world in Python"}],
+ "metadata": {"model": "auto", "combo": "fast-coding"}
+ }
+ }'
+```
+
+**Response:**
+
+```json
+{
+ "jsonrpc": "2.0",
+ "id": "1",
+ "result": {
+ "task": { "id": "uuid", "state": "completed" },
+ "artifacts": [{ "type": "text", "content": "..." }],
+ "metadata": {
+ "routing_explanation": "Selected claude-sonnet via provider \"anthropic\" (latency: 1200ms, cost: $0.003)",
+ "cost_envelope": { "estimated": 0.005, "actual": 0.003, "currency": "USD" },
+ "resilience_trace": [
+ { "event": "primary_selected", "provider": "anthropic", "timestamp": "..." }
+ ],
+ "policy_verdict": { "allowed": true, "reason": "within budget and quota limits" }
+ }
+ }
+}
+```
+
+### `message/stream` — SSE Streaming
+
+Same as `message/send` but returns Server-Sent Events for real-time streaming.
+
+```bash
+curl -N -X POST http://localhost:20128/a2a \
+ -H "Content-Type: application/json" \
+ -H "Authorization: Bearer YOUR_KEY" \
+ -d '{
+ "jsonrpc": "2.0",
+ "id": "1",
+ "method": "message/stream",
+ "params": {
+ "skill": "smart-routing",
+ "messages": [{"role": "user", "content": "Explain quantum computing"}]
+ }
+ }'
+```
+
+**SSE Events:**
+
+```
+data: {"jsonrpc":"2.0","method":"message/stream","params":{"task":{"id":"...","state":"working"},"chunk":{"type":"text","content":"..."}}}
+
+: heartbeat 2026-03-03T17:00:00Z
+
+data: {"jsonrpc":"2.0","method":"message/stream","params":{"task":{"id":"...","state":"completed"},"metadata":{...}}}
+```
+
+### `tasks/get` — Query Task Status
+
+```bash
+curl -X POST http://localhost:20128/a2a \
+ -H "Content-Type: application/json" \
+ -H "Authorization: Bearer YOUR_KEY" \
+ -d '{"jsonrpc":"2.0","id":"2","method":"tasks/get","params":{"taskId":"TASK_UUID"}}'
+```
+
+### `tasks/cancel` — Cancel a Task
+
+```bash
+curl -X POST http://localhost:20128/a2a \
+ -H "Content-Type: application/json" \
+ -H "Authorization: Bearer YOUR_KEY" \
+ -d '{"jsonrpc":"2.0","id":"3","method":"tasks/cancel","params":{"taskId":"TASK_UUID"}}'
+```
+
+---
+
+## Available Skills
+
+| Skill | Description |
+| :----------------- | :------------------------------------------------------------------------------------------------------------------------------ |
+| `smart-routing` | Routes prompts through OmniRoute's intelligent pipeline. Returns response with routing explanation, cost, and resilience trace. |
+| `quota-management` | Answers natural-language queries about provider quotas, suggests free combos, and provides quota rankings. |
+
+---
+
+## Task Lifecycle
+
+```
+submitted → working → completed
+ → failed
+ → cancelled
+```
+
+- Tasks expire after 5 minutes (configurable)
+- Terminal states: `completed`, `failed`, `cancelled`
+- Event log tracks every state transition
+
+---
+
+## Error Codes
+
+| Code | Meaning |
+| :----- | :----------------------------- |
+| -32700 | Parse error (invalid JSON) |
+| -32600 | Invalid request / Unauthorized |
+| -32601 | Method or skill not found |
+| -32602 | Invalid params |
+| -32603 | Internal error |
+
+---
+
+## Integration Examples
+
+### Python (requests)
+
+```python
+import requests
+
+resp = requests.post("http://localhost:20128/a2a", json={
+ "jsonrpc": "2.0", "id": "1",
+ "method": "message/send",
+ "params": {
+ "skill": "smart-routing",
+ "messages": [{"role": "user", "content": "Hello"}]
+ }
+}, headers={"Authorization": "Bearer YOUR_KEY"})
+
+result = resp.json()["result"]
+print(result["artifacts"][0]["content"])
+print(result["metadata"]["routing_explanation"])
+```
+
+### TypeScript (fetch)
+
+```typescript
+const resp = await fetch("http://localhost:20128/a2a", {
+ method: "POST",
+ headers: {
+ "Content-Type": "application/json",
+ Authorization: "Bearer YOUR_KEY",
+ },
+ body: JSON.stringify({
+ jsonrpc: "2.0",
+ id: "1",
+ method: "message/send",
+ params: {
+ skill: "smart-routing",
+ messages: [{ role: "user", content: "Hello" }],
+ },
+ }),
+});
+const { result } = await resp.json();
+console.log(result.metadata.routing_explanation);
+```
diff --git a/docs/i18n/it/docs/API_REFERENCE.md b/docs/i18n/it/docs/API_REFERENCE.md
new file mode 100644
index 0000000000..1d31c2fef1
--- /dev/null
+++ b/docs/i18n/it/docs/API_REFERENCE.md
@@ -0,0 +1,465 @@
+# API Reference (Italiano)
+
+🌐 **Languages:** 🇺🇸 [English](../../../../docs/API_REFERENCE.md) · 🇪🇸 [es](../../es/docs/API_REFERENCE.md) · 🇫🇷 [fr](../../fr/docs/API_REFERENCE.md) · 🇩🇪 [de](../../de/docs/API_REFERENCE.md) · 🇮🇹 [it](../../it/docs/API_REFERENCE.md) · 🇷🇺 [ru](../../ru/docs/API_REFERENCE.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/API_REFERENCE.md) · 🇯🇵 [ja](../../ja/docs/API_REFERENCE.md) · 🇰🇷 [ko](../../ko/docs/API_REFERENCE.md) · 🇸🇦 [ar](../../ar/docs/API_REFERENCE.md) · 🇮🇳 [in](../../in/docs/API_REFERENCE.md) · 🇹🇭 [th](../../th/docs/API_REFERENCE.md) · 🇻🇳 [vi](../../vi/docs/API_REFERENCE.md) · 🇮🇩 [id](../../id/docs/API_REFERENCE.md) · 🇲🇾 [ms](../../ms/docs/API_REFERENCE.md) · 🇳🇱 [nl](../../nl/docs/API_REFERENCE.md) · 🇵🇱 [pl](../../pl/docs/API_REFERENCE.md) · 🇸🇪 [sv](../../sv/docs/API_REFERENCE.md) · 🇳🇴 [no](../../no/docs/API_REFERENCE.md) · 🇩🇰 [da](../../da/docs/API_REFERENCE.md) · 🇫🇮 [fi](../../fi/docs/API_REFERENCE.md) · 🇵🇹 [pt](../../pt/docs/API_REFERENCE.md) · 🇷🇴 [ro](../../ro/docs/API_REFERENCE.md) · 🇭🇺 [hu](../../hu/docs/API_REFERENCE.md) · 🇧🇬 [bg](../../bg/docs/API_REFERENCE.md) · 🇸🇰 [sk](../../sk/docs/API_REFERENCE.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/API_REFERENCE.md) · 🇮🇱 [he](../../he/docs/API_REFERENCE.md) · 🇵🇭 [phi](../../phi/docs/API_REFERENCE.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/API_REFERENCE.md) · 🇨🇿 [cs](../../cs/docs/API_REFERENCE.md)
+
+---
+
+Complete reference for all OmniRoute API endpoints.
+
+---
+
+## Table of Contents
+
+- [Chat Completions](#chat-completions)
+- [Embeddings](#embeddings)
+- [Image Generation](#image-generation)
+- [List Models](#list-models)
+- [Compatibility Endpoints](#compatibility-endpoints)
+- [Semantic Cache](#semantic-cache)
+- [Dashboard & Management](#dashboard--management)
+- [Request Processing](#request-processing)
+- [Authentication](#authentication)
+
+---
+
+## Chat Completions
+
+```bash
+POST /v1/chat/completions
+Authorization: Bearer your-api-key
+Content-Type: application/json
+
+{
+ "model": "cc/claude-opus-4-6",
+ "messages": [
+ {"role": "user", "content": "Write a function to..."}
+ ],
+ "stream": true
+}
+```
+
+### Custom Headers
+
+| Header | Direction | Description |
+| ------------------------ | --------- | ------------------------------------------------ |
+| `X-OmniRoute-No-Cache` | Request | Set to `true` to bypass cache |
+| `X-OmniRoute-Progress` | Request | Set to `true` for progress events |
+| `X-Session-Id` | Request | Sticky session key for external session affinity |
+| `x_session_id` | Request | Underscore variant also accepted (direct HTTP) |
+| `Idempotency-Key` | Request | Dedup key (5s window) |
+| `X-Request-Id` | Request | Alternative dedup key |
+| `X-OmniRoute-Cache` | Response | `HIT` or `MISS` (non-streaming) |
+| `X-OmniRoute-Idempotent` | Response | `true` if deduplicated |
+| `X-OmniRoute-Progress` | Response | `enabled` if progress tracking on |
+| `X-OmniRoute-Session-Id` | Response | Effective session ID used by OmniRoute |
+
+> Nginx note: if you rely on underscore headers (for example `x_session_id`), enable `underscores_in_headers on;`.
+
+---
+
+## Embeddings
+
+```bash
+POST /v1/embeddings
+Authorization: Bearer your-api-key
+Content-Type: application/json
+
+{
+ "model": "nebius/Qwen/Qwen3-Embedding-8B",
+ "input": "The food was delicious"
+}
+```
+
+Available providers: Nebius, OpenAI, Mistral, Together AI, Fireworks, NVIDIA.
+
+```bash
+# List all embedding models
+GET /v1/embeddings
+```
+
+---
+
+## Image Generation
+
+```bash
+POST /v1/images/generations
+Authorization: Bearer your-api-key
+Content-Type: application/json
+
+{
+ "model": "openai/dall-e-3",
+ "prompt": "A beautiful sunset over mountains",
+ "size": "1024x1024"
+}
+```
+
+Available providers: OpenAI (DALL-E), xAI (Grok Image), Together AI (FLUX), Fireworks AI.
+
+```bash
+# List all image models
+GET /v1/images/generations
+```
+
+---
+
+## List Models
+
+```bash
+GET /v1/models
+Authorization: Bearer your-api-key
+
+→ Returns all chat, embedding, and image models + combos in OpenAI format
+```
+
+---
+
+## Compatibility Endpoints
+
+| Method | Path | Format |
+| ------ | --------------------------- | ---------------------- |
+| POST | `/v1/chat/completions` | OpenAI |
+| POST | `/v1/messages` | Anthropic |
+| POST | `/v1/responses` | OpenAI Responses |
+| POST | `/v1/embeddings` | OpenAI |
+| POST | `/v1/images/generations` | OpenAI |
+| GET | `/v1/models` | OpenAI |
+| POST | `/v1/messages/count_tokens` | Anthropic |
+| GET | `/v1beta/models` | Gemini |
+| POST | `/v1beta/models/{...path}` | Gemini generateContent |
+| POST | `/v1/api/chat` | Ollama |
+
+### Dedicated Provider Routes
+
+```bash
+POST /v1/providers/{provider}/chat/completions
+POST /v1/providers/{provider}/embeddings
+POST /v1/providers/{provider}/images/generations
+```
+
+The provider prefix is auto-added if missing. Mismatched models return `400`.
+
+---
+
+## Semantic Cache
+
+```bash
+# Get cache stats
+GET /api/cache/stats
+
+# Clear all caches
+DELETE /api/cache/stats
+```
+
+Response example:
+
+```json
+{
+ "semanticCache": {
+ "memorySize": 42,
+ "memoryMaxSize": 500,
+ "dbSize": 128,
+ "hitRate": 0.65
+ },
+ "idempotency": {
+ "activeKeys": 3,
+ "windowMs": 5000
+ }
+}
+```
+
+---
+
+## Dashboard & Management
+
+### Authentication
+
+| Endpoint | Method | Description |
+| ----------------------------- | ------- | --------------------- |
+| `/api/auth/login` | POST | Login |
+| `/api/auth/logout` | POST | Logout |
+| `/api/settings/require-login` | GET/PUT | Toggle login required |
+
+### Provider Management
+
+| Endpoint | Method | Description |
+| ---------------------------- | --------------- | ------------------------ |
+| `/api/providers` | GET/POST | List / create providers |
+| `/api/providers/[id]` | GET/PUT/DELETE | Manage a provider |
+| `/api/providers/[id]/test` | POST | Test provider connection |
+| `/api/providers/[id]/models` | GET | List provider models |
+| `/api/providers/validate` | POST | Validate provider config |
+| `/api/provider-nodes*` | Various | Provider node management |
+| `/api/provider-models` | GET/POST/DELETE | Custom models |
+
+### OAuth Flows
+
+| Endpoint | Method | Description |
+| -------------------------------- | ------- | ----------------------- |
+| `/api/oauth/[provider]/[action]` | Various | Provider-specific OAuth |
+
+### Routing & Config
+
+| Endpoint | Method | Description |
+| --------------------- | -------- | ----------------------------- |
+| `/api/models/alias` | GET/POST | Model aliases |
+| `/api/models/catalog` | GET | All models by provider + type |
+| `/api/combos*` | Various | Combo management |
+| `/api/keys*` | Various | API key management |
+| `/api/pricing` | GET | Model pricing |
+
+### Usage & Analytics
+
+| Endpoint | Method | Description |
+| --------------------------- | ------ | -------------------- |
+| `/api/usage/history` | GET | Usage history |
+| `/api/usage/logs` | GET | Usage logs |
+| `/api/usage/request-logs` | GET | Request-level logs |
+| `/api/usage/[connectionId]` | GET | Per-connection usage |
+
+### Settings
+
+| Endpoint | Method | Description |
+| ------------------------------- | ------------- | ---------------------- |
+| `/api/settings` | GET/PUT/PATCH | General settings |
+| `/api/settings/proxy` | GET/PUT | Network proxy config |
+| `/api/settings/proxy/test` | POST | Test proxy connection |
+| `/api/settings/ip-filter` | GET/PUT | IP allowlist/blocklist |
+| `/api/settings/thinking-budget` | GET/PUT | Reasoning token budget |
+| `/api/settings/system-prompt` | GET/PUT | Global system prompt |
+
+### Monitoring
+
+| Endpoint | Method | Description |
+| ------------------------ | ---------- | ---------------------------------------------------------------------------------------------------- |
+| `/api/sessions` | GET | Active session tracking |
+| `/api/rate-limits` | GET | Per-account rate limits |
+| `/api/monitoring/health` | GET | Health check + provider summary (`catalogCount`, `configuredCount`, `activeCount`, `monitoredCount`) |
+| `/api/cache/stats` | GET/DELETE | Cache stats / clear |
+
+### Backup & Export/Import
+
+| Endpoint | Method | Description |
+| --------------------------- | ------ | --------------------------------------- |
+| `/api/db-backups` | GET | List available backups |
+| `/api/db-backups` | PUT | Create a manual backup |
+| `/api/db-backups` | POST | Restore from a specific backup |
+| `/api/db-backups/export` | GET | Download database as .sqlite file |
+| `/api/db-backups/import` | POST | Upload .sqlite file to replace database |
+| `/api/db-backups/exportAll` | GET | Download full backup as .tar.gz archive |
+
+### Cloud Sync
+
+| Endpoint | Method | Description |
+| ---------------------- | ------- | --------------------- |
+| `/api/sync/cloud` | Various | Cloud sync operations |
+| `/api/sync/initialize` | POST | Initialize sync |
+| `/api/cloud/*` | Various | Cloud management |
+
+### Tunnels
+
+| Endpoint | Method | Description |
+| -------------------------- | ------ | ----------------------------------------------------------------------- |
+| `/api/tunnels/cloudflared` | GET | Read Cloudflare Quick Tunnel install/runtime status for the dashboard |
+| `/api/tunnels/cloudflared` | POST | Enable or disable the Cloudflare Quick Tunnel (`action=enable/disable`) |
+
+### CLI Tools
+
+| Endpoint | Method | Description |
+| ---------------------------------- | ------ | ------------------- |
+| `/api/cli-tools/claude-settings` | GET | Claude CLI status |
+| `/api/cli-tools/codex-settings` | GET | Codex CLI status |
+| `/api/cli-tools/droid-settings` | GET | Droid CLI status |
+| `/api/cli-tools/openclaw-settings` | GET | OpenClaw CLI status |
+| `/api/cli-tools/runtime/[toolId]` | GET | Generic CLI runtime |
+
+CLI responses include: `installed`, `runnable`, `command`, `commandPath`, `runtimeMode`, `reason`.
+
+### ACP Agents
+
+| Endpoint | Method | Description |
+| ----------------- | ------ | -------------------------------------------------------- |
+| `/api/acp/agents` | GET | List all detected agents (built-in + custom) with status |
+| `/api/acp/agents` | POST | Add custom agent or refresh detection cache |
+| `/api/acp/agents` | DELETE | Remove a custom agent by `id` query param |
+
+GET response includes `agents[]` (id, name, binary, version, installed, protocol, isCustom) and `summary` (total, installed, notFound, builtIn, custom).
+
+### Resilience & Rate Limits
+
+| Endpoint | Method | Description |
+| ----------------------- | --------- | ------------------------------- |
+| `/api/resilience` | GET/PATCH | Get/update resilience profiles |
+| `/api/resilience/reset` | POST | Reset circuit breakers |
+| `/api/rate-limits` | GET | Per-account rate limit status |
+| `/api/rate-limit` | GET | Global rate limit configuration |
+
+### Evals
+
+| Endpoint | Method | Description |
+| ------------ | -------- | --------------------------------- |
+| `/api/evals` | GET/POST | List eval suites / run evaluation |
+
+### Policies
+
+| Endpoint | Method | Description |
+| --------------- | --------------- | ----------------------- |
+| `/api/policies` | GET/POST/DELETE | Manage routing policies |
+
+### Compliance
+
+| Endpoint | Method | Description |
+| --------------------------- | ------ | ----------------------------- |
+| `/api/compliance/audit-log` | GET | Compliance audit log (last N) |
+
+### v1beta (Gemini-Compatible)
+
+| Endpoint | Method | Description |
+| -------------------------- | ------ | --------------------------------- |
+| `/v1beta/models` | GET | List models in Gemini format |
+| `/v1beta/models/{...path}` | POST | Gemini `generateContent` endpoint |
+
+These endpoints mirror Gemini's API format for clients that expect native Gemini SDK compatibility.
+
+### Internal / System APIs
+
+| Endpoint | Method | Description |
+| --------------- | ------ | ---------------------------------------------------- |
+| `/api/init` | GET | Application initialization check (used on first run) |
+| `/api/tags` | GET | Ollama-compatible model tags (for Ollama clients) |
+| `/api/restart` | POST | Trigger graceful server restart |
+| `/api/shutdown` | POST | Trigger graceful server shutdown |
+
+> **Note:** These endpoints are used internally by the system or for Ollama client compatibility. They are not typically called by end users.
+
+---
+
+## Audio Transcription
+
+```bash
+POST /v1/audio/transcriptions
+Authorization: Bearer your-api-key
+Content-Type: multipart/form-data
+```
+
+Transcribe audio files using Deepgram or AssemblyAI.
+
+**Request:**
+
+```bash
+curl -X POST http://localhost:20128/v1/audio/transcriptions \
+ -H "Authorization: Bearer your-api-key" \
+ -F "file=@recording.mp3" \
+ -F "model=deepgram/nova-3"
+```
+
+**Response:**
+
+```json
+{
+ "text": "Hello, this is the transcribed audio content.",
+ "task": "transcribe",
+ "language": "en",
+ "duration": 12.5
+}
+```
+
+**Supported providers:** `deepgram/nova-3`, `assemblyai/best`.
+
+**Supported formats:** `mp3`, `wav`, `m4a`, `flac`, `ogg`, `webm`.
+
+---
+
+## Ollama Compatibility
+
+For clients that use Ollama's API format:
+
+```bash
+# Chat endpoint (Ollama format)
+POST /v1/api/chat
+
+# Model listing (Ollama format)
+GET /api/tags
+```
+
+Requests are automatically translated between Ollama and internal formats.
+
+---
+
+## Telemetry
+
+```bash
+# Get latency telemetry summary (p50/p95/p99 per provider)
+GET /api/telemetry/summary
+```
+
+**Response:**
+
+```json
+{
+ "providers": {
+ "claudeCode": { "p50": 245, "p95": 890, "p99": 1200, "count": 150 },
+ "github": { "p50": 180, "p95": 620, "p99": 950, "count": 320 }
+ }
+}
+```
+
+---
+
+## Budget
+
+```bash
+# Get budget status for all API keys
+GET /api/usage/budget
+
+# Set or update a budget
+POST /api/usage/budget
+Content-Type: application/json
+
+{
+ "keyId": "key-123",
+ "limit": 50.00,
+ "period": "monthly"
+}
+```
+
+---
+
+## Model Availability
+
+```bash
+# Get real-time model availability across all providers
+GET /api/models/availability
+
+# Check availability for a specific model
+POST /api/models/availability
+Content-Type: application/json
+
+{
+ "model": "claude-sonnet-4-5-20250929"
+}
+```
+
+---
+
+## Request Processing
+
+1. Client sends request to `/v1/*`
+2. Route handler calls `handleChat`, `handleEmbedding`, `handleAudioTranscription`, or `handleImageGeneration`
+3. Model is resolved (direct provider/model or alias/combo)
+4. Credentials selected from local DB with account availability filtering
+5. For chat: `handleChatCore` — format detection, translation, cache check, idempotency check
+6. Provider executor sends upstream request
+7. Response translated back to client format (chat) or returned as-is (embeddings/images/audio)
+8. Usage/logging recorded
+9. Fallback applies on errors according to combo rules
+
+Full architecture reference: [`ARCHITECTURE.md`](ARCHITECTURE.md)
+
+---
+
+## Authentication
+
+- Dashboard routes (`/dashboard/*`) use `auth_token` cookie
+- Login uses saved password hash; fallback to `INITIAL_PASSWORD`
+- `requireLogin` toggleable via `/api/settings/require-login`
+- `/v1/*` routes optionally require Bearer API key when `REQUIRE_API_KEY=true`
diff --git a/docs/i18n/it/docs/ARCHITECTURE.md b/docs/i18n/it/docs/ARCHITECTURE.md
new file mode 100644
index 0000000000..591ddf3418
--- /dev/null
+++ b/docs/i18n/it/docs/ARCHITECTURE.md
@@ -0,0 +1,814 @@
+# OmniRoute Architecture (Italiano)
+
+🌐 **Languages:** 🇺🇸 [English](../../../../docs/ARCHITECTURE.md) · 🇪🇸 [es](../../es/docs/ARCHITECTURE.md) · 🇫🇷 [fr](../../fr/docs/ARCHITECTURE.md) · 🇩🇪 [de](../../de/docs/ARCHITECTURE.md) · 🇮🇹 [it](../../it/docs/ARCHITECTURE.md) · 🇷🇺 [ru](../../ru/docs/ARCHITECTURE.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/ARCHITECTURE.md) · 🇯🇵 [ja](../../ja/docs/ARCHITECTURE.md) · 🇰🇷 [ko](../../ko/docs/ARCHITECTURE.md) · 🇸🇦 [ar](../../ar/docs/ARCHITECTURE.md) · 🇮🇳 [in](../../in/docs/ARCHITECTURE.md) · 🇹🇭 [th](../../th/docs/ARCHITECTURE.md) · 🇻🇳 [vi](../../vi/docs/ARCHITECTURE.md) · 🇮🇩 [id](../../id/docs/ARCHITECTURE.md) · 🇲🇾 [ms](../../ms/docs/ARCHITECTURE.md) · 🇳🇱 [nl](../../nl/docs/ARCHITECTURE.md) · 🇵🇱 [pl](../../pl/docs/ARCHITECTURE.md) · 🇸🇪 [sv](../../sv/docs/ARCHITECTURE.md) · 🇳🇴 [no](../../no/docs/ARCHITECTURE.md) · 🇩🇰 [da](../../da/docs/ARCHITECTURE.md) · 🇫🇮 [fi](../../fi/docs/ARCHITECTURE.md) · 🇵🇹 [pt](../../pt/docs/ARCHITECTURE.md) · 🇷🇴 [ro](../../ro/docs/ARCHITECTURE.md) · 🇭🇺 [hu](../../hu/docs/ARCHITECTURE.md) · 🇧🇬 [bg](../../bg/docs/ARCHITECTURE.md) · 🇸🇰 [sk](../../sk/docs/ARCHITECTURE.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/ARCHITECTURE.md) · 🇮🇱 [he](../../he/docs/ARCHITECTURE.md) · 🇵🇭 [phi](../../phi/docs/ARCHITECTURE.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/ARCHITECTURE.md) · 🇨🇿 [cs](../../cs/docs/ARCHITECTURE.md)
+
+---
+
+_Last updated: 2026-03-28_
+
+## Executive Summary
+
+OmniRoute is a local AI routing gateway and dashboard built on Next.js.
+It provides a single OpenAI-compatible endpoint (`/v1/*`) and routes traffic across multiple upstream providers with translation, fallback, token refresh, and usage tracking.
+
+Core capabilities:
+
+- OpenAI-compatible API surface for CLI/tools (28 providers)
+- Request/response translation across provider formats
+- Model combo fallback (multi-model sequence)
+- Account-level fallback (multi-account per provider)
+- OAuth + API-key provider connection management
+- Embedding generation via `/v1/embeddings` (6 providers, 9 models)
+- Image generation via `/v1/images/generations` (4 providers, 9 models)
+- Think tag parsing (`...`) for reasoning models
+- Response sanitization for strict OpenAI SDK compatibility
+- Role normalization (developer→system, system→user) for cross-provider compatibility
+- Structured output conversion (json_schema → Gemini responseSchema)
+- Local persistence for providers, keys, aliases, combos, settings, pricing
+- Usage/cost tracking and request logging
+- Optional cloud sync for multi-device/state sync
+- IP allowlist/blocklist for API access control
+- Thinking budget management (passthrough/auto/custom/adaptive)
+- Global system prompt injection
+- Session tracking and fingerprinting
+- Per-account enhanced rate limiting with provider-specific profiles
+- Circuit breaker pattern for provider resilience
+- Anti-thundering herd protection with mutex locking
+- Signature-based request deduplication cache
+- Domain layer: model availability, cost rules, fallback policy, lockout policy
+- Domain state persistence (SQLite write-through cache for fallbacks, budgets, lockouts, circuit breakers)
+- Policy engine for centralized request evaluation (lockout → budget → fallback)
+- Request telemetry with p50/p95/p99 latency aggregation
+- Correlation ID (X-Request-Id) for end-to-end tracing
+- Compliance audit logging with opt-out per API key
+- Eval framework for LLM quality assurance
+- Resilience UI dashboard with real-time circuit breaker status
+- Modular OAuth providers (12 individual modules under `src/lib/oauth/providers/`)
+
+Primary runtime model:
+
+- Next.js app routes under `src/app/api/*` implement both dashboard APIs and compatibility APIs
+- A shared SSE/routing core in `src/sse/*` + `open-sse/*` handles provider execution, translation, streaming, fallback, and usage
+
+## Scope and Boundaries
+
+### In Scope
+
+- Local gateway runtime
+- Dashboard management APIs
+- Provider authentication and token refresh
+- Request translation and SSE streaming
+- Local state + usage persistence
+- Optional cloud sync orchestration
+
+### Out of Scope
+
+- Cloud service implementation behind `NEXT_PUBLIC_CLOUD_URL`
+- Provider SLA/control plane outside local process
+- External CLI binaries themselves (Claude CLI, Codex CLI, etc.)
+
+## Dashboard Surface (Current)
+
+Main pages under `src/app/(dashboard)/dashboard/`:
+
+- `/dashboard` — quick start + provider overview
+- `/dashboard/endpoint` — endpoint proxy + MCP + A2A + API endpoint tabs
+- `/dashboard/providers` — provider connections and credentials
+- `/dashboard/combos` — combo strategies, templates, model routing rules
+- `/dashboard/costs` — cost aggregation and pricing visibility
+- `/dashboard/analytics` — usage analytics and evaluations
+- `/dashboard/limits` — quota/rate controls
+- `/dashboard/cli-tools` — CLI onboarding, runtime detection, config generation
+- `/dashboard/agents` — detected ACP agents + custom agent registration
+- `/dashboard/media` — image/video/music playground
+- `/dashboard/search-tools` — search provider testing and history
+- `/dashboard/health` — uptime, circuit breakers, rate limits
+- `/dashboard/logs` — request/proxy/audit/console logs
+- `/dashboard/settings` — system settings tabs (general, routing, combo defaults, etc.)
+- `/dashboard/api-manager` — API key lifecycle and model permissions
+
+## High-Level System Context
+
+```mermaid
+flowchart LR
+ subgraph Clients[Developer Clients]
+ C1[Claude Code]
+ C2[Codex CLI]
+ C3[OpenClaw / Droid / Cline / Continue / Roo]
+ C4[Custom OpenAI-compatible clients]
+ BROWSER[Browser Dashboard]
+ end
+
+ subgraph Router[OmniRoute Local Process]
+ API[V1 Compatibility API\n/v1/*]
+ DASH[Dashboard + Management API\n/api/*]
+ CORE[SSE + Translation Core\nopen-sse + src/sse]
+ DB[(storage.sqlite)]
+ UDB[(usage tables + log artifacts)]
+ end
+
+ subgraph Upstreams[Upstream Providers]
+ P1[OAuth Providers\nClaude/Codex/Gemini/Qwen/Qoder/GitHub/Kiro/Cursor/Antigravity]
+ P2[API Key Providers\nOpenAI/Anthropic/OpenRouter/GLM/Kimi/MiniMax\nDeepSeek/Groq/xAI/Mistral/Perplexity\nTogether/Fireworks/Cerebras/Cohere/NVIDIA]
+ P3[Compatible Nodes\nOpenAI-compatible / Anthropic-compatible]
+ end
+
+ subgraph Cloud[Optional Cloud Sync]
+ CLOUD[Cloud Sync Endpoint\nNEXT_PUBLIC_CLOUD_URL]
+ end
+
+ C1 --> API
+ C2 --> API
+ C3 --> API
+ C4 --> API
+ BROWSER --> DASH
+
+ API --> CORE
+ DASH --> DB
+ CORE --> DB
+ CORE --> UDB
+
+ CORE --> P1
+ CORE --> P2
+ CORE --> P3
+
+ DASH --> CLOUD
+```
+
+## Core Runtime Components
+
+## 1) API and Routing Layer (Next.js App Routes)
+
+Main directories:
+
+- `src/app/api/v1/*` and `src/app/api/v1beta/*` for compatibility APIs
+- `src/app/api/*` for management/configuration APIs
+- Next rewrites in `next.config.mjs` map `/v1/*` to `/api/v1/*`
+
+Important compatibility routes:
+
+- `src/app/api/v1/chat/completions/route.ts`
+- `src/app/api/v1/messages/route.ts`
+- `src/app/api/v1/responses/route.ts`
+- `src/app/api/v1/models/route.ts` — includes custom models with `custom: true`
+- `src/app/api/v1/embeddings/route.ts` — embedding generation (6 providers)
+- `src/app/api/v1/images/generations/route.ts` — image generation (4+ providers incl. Antigravity/Nebius)
+- `src/app/api/v1/messages/count_tokens/route.ts`
+- `src/app/api/v1/providers/[provider]/chat/completions/route.ts` — dedicated per-provider chat
+- `src/app/api/v1/providers/[provider]/embeddings/route.ts` — dedicated per-provider embeddings
+- `src/app/api/v1/providers/[provider]/images/generations/route.ts` — dedicated per-provider images
+- `src/app/api/v1beta/models/route.ts`
+- `src/app/api/v1beta/models/[...path]/route.ts`
+
+Management domains:
+
+- Auth/settings: `src/app/api/auth/*`, `src/app/api/settings/*`
+- Providers/connections: `src/app/api/providers*`
+- Provider nodes: `src/app/api/provider-nodes*`
+- Custom models: `src/app/api/provider-models` (GET/POST/DELETE)
+- Model catalog: `src/app/api/models/route.ts` (GET)
+- Proxy config: `src/app/api/settings/proxy` (GET/PUT/DELETE) + `src/app/api/settings/proxy/test` (POST)
+- OAuth: `src/app/api/oauth/*`
+- Keys/aliases/combos/pricing: `src/app/api/keys*`, `src/app/api/models/alias`, `src/app/api/combos*`, `src/app/api/pricing`
+- Usage: `src/app/api/usage/*`
+- Sync/cloud: `src/app/api/sync/*`, `src/app/api/cloud/*`
+- CLI tooling helpers: `src/app/api/cli-tools/*`
+- IP filter: `src/app/api/settings/ip-filter` (GET/PUT)
+- Thinking budget: `src/app/api/settings/thinking-budget` (GET/PUT)
+- System prompt: `src/app/api/settings/system-prompt` (GET/PUT)
+- Sessions: `src/app/api/sessions` (GET)
+- Rate limits: `src/app/api/rate-limits` (GET)
+- Resilience: `src/app/api/resilience` (GET/PATCH) — provider profiles, circuit breaker, rate limit state
+- Resilience reset: `src/app/api/resilience/reset` (POST) — reset breakers + cooldowns
+- Cache stats: `src/app/api/cache/stats` (GET/DELETE)
+- Model availability: `src/app/api/models/availability` (GET/POST)
+- Telemetry: `src/app/api/telemetry/summary` (GET)
+- Budget: `src/app/api/usage/budget` (GET/POST)
+- Fallback chains: `src/app/api/fallback/chains` (GET/POST/DELETE)
+- Compliance audit: `src/app/api/compliance/audit-log` (GET)
+- Evals: `src/app/api/evals` (GET/POST), `src/app/api/evals/[suiteId]` (GET)
+- Policies: `src/app/api/policies` (GET/POST)
+
+## 2) SSE + Translation Core
+
+Main flow modules:
+
+- Entry: `src/sse/handlers/chat.ts`
+- Core orchestration: `open-sse/handlers/chatCore.ts`
+- Provider execution adapters: `open-sse/executors/*`
+- Format detection/provider config: `open-sse/services/provider.ts`
+- Model parse/resolve: `src/sse/services/model.ts`, `open-sse/services/model.ts`
+- Account fallback logic: `open-sse/services/accountFallback.ts`
+- Translation registry: `open-sse/translator/index.ts`
+- Stream transformations: `open-sse/utils/stream.ts`, `open-sse/utils/streamHandler.ts`
+- Usage extraction/normalization: `open-sse/utils/usageTracking.ts`
+- Think tag parser: `open-sse/utils/thinkTagParser.ts`
+- Embedding handler: `open-sse/handlers/embeddings.ts`
+- Embedding provider registry: `open-sse/config/embeddingRegistry.ts`
+- Image generation handler: `open-sse/handlers/imageGeneration.ts`
+- Image provider registry: `open-sse/config/imageRegistry.ts`
+- Response sanitization: `open-sse/handlers/responseSanitizer.ts`
+- Role normalization: `open-sse/services/roleNormalizer.ts`
+
+Services (business logic):
+
+- Account selection/scoring: `open-sse/services/accountSelector.ts`
+- Context lifecycle management: `open-sse/services/contextManager.ts`
+- IP filter enforcement: `open-sse/services/ipFilter.ts`
+- Session tracking: `open-sse/services/sessionManager.ts`
+- Request deduplication: `open-sse/services/signatureCache.ts`
+- System prompt injection: `open-sse/services/systemPrompt.ts`
+- Thinking budget management: `open-sse/services/thinkingBudget.ts`
+- Wildcard model routing: `open-sse/services/wildcardRouter.ts`
+- Rate limit management: `open-sse/services/rateLimitManager.ts`
+- Circuit breaker: `open-sse/services/circuitBreaker.ts`
+
+Domain layer modules:
+
+- Model availability: `src/lib/domain/modelAvailability.ts`
+- Cost rules/budgets: `src/lib/domain/costRules.ts`
+- Fallback policy: `src/lib/domain/fallbackPolicy.ts`
+- Combo resolver: `src/lib/domain/comboResolver.ts`
+- Lockout policy: `src/lib/domain/lockoutPolicy.ts`
+- Policy engine: `src/domain/policyEngine.ts` — centralized lockout → budget → fallback evaluation
+- Error codes catalog: `src/lib/domain/errorCodes.ts`
+- Request ID: `src/lib/domain/requestId.ts`
+- Fetch timeout: `src/lib/domain/fetchTimeout.ts`
+- Request telemetry: `src/lib/domain/requestTelemetry.ts`
+- Compliance/audit: `src/lib/domain/compliance/index.ts`
+- Eval runner: `src/lib/domain/evalRunner.ts`
+- Domain state persistence: `src/lib/db/domainState.ts` — SQLite CRUD for fallback chains, budgets, cost history, lockout state, circuit breakers
+
+OAuth provider modules (12 individual files under `src/lib/oauth/providers/`):
+
+- Registry index: `src/lib/oauth/providers/index.ts`
+- Individual providers: `claude.ts`, `codex.ts`, `gemini.ts`, `antigravity.ts`, `qoder.ts`, `qwen.ts`, `kimi-coding.ts`, `github.ts`, `kiro.ts`, `cursor.ts`, `kilocode.ts`, `cline.ts`
+- Thin wrapper: `src/lib/oauth/providers.ts` — re-exports from individual modules
+
+## 3) Persistence Layer
+
+Primary state DB (SQLite):
+
+- Core infra: `src/lib/db/core.ts` (better-sqlite3, migrations, WAL)
+- Re-export facade: `src/lib/localDb.ts` (thin compatibility layer for callers)
+- file: `${DATA_DIR}/storage.sqlite` (or `$XDG_CONFIG_HOME/omniroute/storage.sqlite` when set, else `~/.omniroute/storage.sqlite`)
+- entities (tables + KV namespaces): providerConnections, providerNodes, modelAliases, combos, apiKeys, settings, pricing, **customModels**, **proxyConfig**, **ipFilter**, **thinkingBudget**, **systemPrompt**
+
+Usage persistence:
+
+- facade: `src/lib/usageDb.ts` (decomposed modules in `src/lib/usage/*`)
+- SQLite tables in `storage.sqlite`: `usage_history`, `call_logs`, `proxy_logs`
+- optional file artifacts remain for compatibility/debug (`${DATA_DIR}/log.txt`, `${DATA_DIR}/call_logs/`, `/logs/...`)
+- legacy JSON files are migrated to SQLite by startup migrations when present
+
+Domain State DB (SQLite):
+
+- `src/lib/db/domainState.ts` — CRUD operations for domain state
+- Tables (created in `src/lib/db/core.ts`): `domain_fallback_chains`, `domain_budgets`, `domain_cost_history`, `domain_lockout_state`, `domain_circuit_breakers`
+- Write-through cache pattern: in-memory Maps are authoritative at runtime; mutations are written synchronously to SQLite; state is restored from DB on cold start
+
+## 4) Auth + Security Surfaces
+
+- Dashboard cookie auth: `src/proxy.ts`, `src/app/api/auth/login/route.ts`
+- API key generation/verification: `src/shared/utils/apiKey.ts`
+- Provider secrets persisted in `providerConnections` entries
+- Outbound proxy support via `open-sse/utils/proxyFetch.ts` (env vars) and `open-sse/utils/networkProxy.ts` (configurable per-provider or global)
+
+## 5) Cloud Sync
+
+- Scheduler init: `src/lib/initCloudSync.ts`, `src/shared/services/initializeCloudSync.ts`, `src/shared/services/modelSyncScheduler.ts`
+- Periodic task: `src/shared/services/cloudSyncScheduler.ts`
+- Periodic task: `src/shared/services/modelSyncScheduler.ts`
+- Control route: `src/app/api/sync/cloud/route.ts`
+
+## Request Lifecycle (`/v1/chat/completions`)
+
+```mermaid
+sequenceDiagram
+ autonumber
+ participant Client as CLI/SDK Client
+ participant Route as /api/v1/chat/completions
+ participant Chat as src/sse/handlers/chat
+ participant Core as open-sse/handlers/chatCore
+ participant Model as Model Resolver
+ participant Auth as Credential Selector
+ participant Exec as Provider Executor
+ participant Prov as Upstream Provider
+ participant Stream as Stream Translator
+ participant Usage as usageDb
+
+ Client->>Route: POST /v1/chat/completions
+ Route->>Chat: handleChat(request)
+ Chat->>Model: parse/resolve model or combo
+
+ alt Combo model
+ Chat->>Chat: iterate combo models (handleComboChat)
+ end
+
+ Chat->>Auth: getProviderCredentials(provider)
+ Auth-->>Chat: active account + tokens/api key
+
+ Chat->>Core: handleChatCore(body, modelInfo, credentials)
+ Core->>Core: detect source format
+ Core->>Core: translate request to target format
+ Core->>Exec: execute(provider, transformedBody)
+ Exec->>Prov: upstream API call
+ Prov-->>Exec: SSE/JSON response
+ Exec-->>Core: response + metadata
+
+ alt 401/403
+ Core->>Exec: refreshCredentials()
+ Exec-->>Core: updated tokens
+ Core->>Exec: retry request
+ end
+
+ Core->>Stream: translate/normalize stream to client format
+ Stream-->>Client: SSE chunks / JSON response
+
+ Stream->>Usage: extract usage + persist history/log
+```
+
+## Combo + Account Fallback Flow
+
+```mermaid
+flowchart TD
+ A[Incoming model string] --> B{Is combo name?}
+ B -- Yes --> C[Load combo models sequence]
+ B -- No --> D[Single model path]
+
+ C --> E[Try model N]
+ E --> F[Resolve provider/model]
+ D --> F
+
+ F --> G[Select account credentials]
+ G --> H{Credentials available?}
+ H -- No --> I[Return provider unavailable]
+ H -- Yes --> J[Execute request]
+
+ J --> K{Success?}
+ K -- Yes --> L[Return response]
+ K -- No --> M{Fallback-eligible error?}
+
+ M -- No --> N[Return error]
+ M -- Yes --> O[Mark account unavailable cooldown]
+ O --> P{Another account for provider?}
+ P -- Yes --> G
+ P -- No --> Q{In combo with next model?}
+ Q -- Yes --> E
+ Q -- No --> R[Return all unavailable]
+```
+
+Fallback decisions are driven by `open-sse/services/accountFallback.ts` using status codes and error-message heuristics. Combo routing adds one extra guard: provider-scoped 400s such as upstream content-block and role-validation failures are treated as model-local failures so later combo targets can still run.
+
+## OAuth Onboarding and Token Refresh Lifecycle
+
+```mermaid
+sequenceDiagram
+ autonumber
+ participant UI as Dashboard UI
+ participant OAuth as /api/oauth/[provider]/[action]
+ participant ProvAuth as Provider Auth Server
+ participant DB as localDb
+ participant Test as /api/providers/[id]/test
+ participant Exec as Provider Executor
+
+ UI->>OAuth: GET authorize or device-code
+ OAuth->>ProvAuth: create auth/device flow
+ ProvAuth-->>OAuth: auth URL or device code payload
+ OAuth-->>UI: flow data
+
+ UI->>OAuth: POST exchange or poll
+ OAuth->>ProvAuth: token exchange/poll
+ ProvAuth-->>OAuth: access/refresh tokens
+ OAuth->>DB: createProviderConnection(oauth data)
+ OAuth-->>UI: success + connection id
+
+ UI->>Test: POST /api/providers/[id]/test
+ Test->>Exec: validate credentials / optional refresh
+ Exec-->>Test: valid or refreshed token info
+ Test->>DB: update status/tokens/errors
+ Test-->>UI: validation result
+```
+
+Refresh during live traffic is executed inside `open-sse/handlers/chatCore.ts` via executor `refreshCredentials()`.
+
+## Cloud Sync Lifecycle (Enable / Sync / Disable)
+
+```mermaid
+sequenceDiagram
+ autonumber
+ participant UI as Endpoint Page UI
+ participant Sync as /api/sync/cloud
+ participant DB as localDb
+ participant Cloud as External Cloud Sync
+ participant Claude as ~/.claude/settings.json
+
+ UI->>Sync: POST action=enable
+ Sync->>DB: set cloudEnabled=true
+ Sync->>DB: ensure API key exists
+ Sync->>Cloud: POST /sync/{machineId} (providers/aliases/combos/keys)
+ Cloud-->>Sync: sync result
+ Sync->>Cloud: GET /{machineId}/v1/verify
+ Sync-->>UI: enabled + verification status
+
+ UI->>Sync: POST action=sync
+ Sync->>Cloud: POST /sync/{machineId}
+ Cloud-->>Sync: remote data
+ Sync->>DB: update newer local tokens/status
+ Sync-->>UI: synced
+
+ UI->>Sync: POST action=disable
+ Sync->>DB: set cloudEnabled=false
+ Sync->>Cloud: DELETE /sync/{machineId}
+ Sync->>Claude: switch ANTHROPIC_BASE_URL back to local (if needed)
+ Sync-->>UI: disabled
+```
+
+Periodic sync is triggered by `CloudSyncScheduler` when cloud is enabled.
+
+## Data Model and Storage Map
+
+```mermaid
+erDiagram
+ SETTINGS ||--o{ PROVIDER_CONNECTION : controls
+ PROVIDER_NODE ||--o{ PROVIDER_CONNECTION : backs_compatible_provider
+ PROVIDER_CONNECTION ||--o{ USAGE_ENTRY : emits_usage
+
+ SETTINGS {
+ boolean cloudEnabled
+ number stickyRoundRobinLimit
+ boolean requireLogin
+ string password_hash
+ string fallbackStrategy
+ json rateLimitDefaults
+ json providerProfiles
+ }
+
+ PROVIDER_CONNECTION {
+ string id
+ string provider
+ string authType
+ string name
+ number priority
+ boolean isActive
+ string apiKey
+ string accessToken
+ string refreshToken
+ string expiresAt
+ string testStatus
+ string lastError
+ string rateLimitedUntil
+ json providerSpecificData
+ }
+
+ PROVIDER_NODE {
+ string id
+ string type
+ string name
+ string prefix
+ string apiType
+ string baseUrl
+ }
+
+ MODEL_ALIAS {
+ string alias
+ string targetModel
+ }
+
+ COMBO {
+ string id
+ string name
+ string[] models
+ }
+
+ API_KEY {
+ string id
+ string name
+ string key
+ string machineId
+ }
+
+ USAGE_ENTRY {
+ string provider
+ string model
+ number prompt_tokens
+ number completion_tokens
+ string connectionId
+ string timestamp
+ }
+
+ CUSTOM_MODEL {
+ string id
+ string name
+ string providerId
+ }
+
+ PROXY_CONFIG {
+ string global
+ json providers
+ }
+
+ IP_FILTER {
+ string mode
+ string[] allowlist
+ string[] blocklist
+ }
+
+ THINKING_BUDGET {
+ string mode
+ number customBudget
+ string effortLevel
+ }
+
+ SYSTEM_PROMPT {
+ boolean enabled
+ string prompt
+ string position
+ }
+```
+
+Physical storage files:
+
+- primary runtime DB: `${DATA_DIR}/storage.sqlite`
+- request log lines: `${DATA_DIR}/log.txt` (compat/debug artifact)
+- structured call payload archives: `${DATA_DIR}/call_logs/`
+- optional translator/request debug sessions: `/logs/...`
+
+## Deployment Topology
+
+```mermaid
+flowchart LR
+ subgraph LocalHost[Developer Host]
+ CLI[CLI Tools]
+ Browser[Dashboard Browser]
+ end
+
+ subgraph ContainerOrProcess[OmniRoute Runtime]
+ Next[Next.js Server\nPORT=20128]
+ Core[SSE Core + Executors]
+ MainDB[(storage.sqlite)]
+ UsageDB[(usage tables + log artifacts)]
+ end
+
+ subgraph External[External Services]
+ Providers[AI Providers]
+ SyncCloud[Cloud Sync Service]
+ end
+
+ CLI --> Next
+ Browser --> Next
+ Next --> Core
+ Next --> MainDB
+ Core --> MainDB
+ Core --> UsageDB
+ Core --> Providers
+ Next --> SyncCloud
+```
+
+## Module Mapping (Decision-Critical)
+
+### Route and API Modules
+
+- `src/app/api/v1/*`, `src/app/api/v1beta/*`: compatibility APIs
+- `src/app/api/v1/providers/[provider]/*`: dedicated per-provider routes (chat, embeddings, images)
+- `src/app/api/providers*`: provider CRUD, validation, testing
+- `src/app/api/provider-nodes*`: custom compatible node management
+- `src/app/api/provider-models`: custom model management (CRUD)
+- `src/app/api/models/route.ts`: model catalog API (aliases + custom models)
+- `src/app/api/oauth/*`: OAuth/device-code flows
+- `src/app/api/keys*`: local API key lifecycle
+- `src/app/api/models/alias`: alias management
+- `src/app/api/combos*`: fallback combo management
+- `src/app/api/pricing`: pricing overrides for cost calculation
+- `src/app/api/settings/proxy`: proxy configuration (GET/PUT/DELETE)
+- `src/app/api/settings/proxy/test`: outbound proxy connectivity test (POST)
+- `src/app/api/usage/*`: usage and logs APIs
+- `src/app/api/sync/*` + `src/app/api/cloud/*`: cloud sync and cloud-facing helpers
+- `src/app/api/cli-tools/*`: local CLI config writers/checkers
+- `src/app/api/settings/ip-filter`: IP allowlist/blocklist (GET/PUT)
+- `src/app/api/settings/thinking-budget`: thinking token budget config (GET/PUT)
+- `src/app/api/settings/system-prompt`: global system prompt (GET/PUT)
+- `src/app/api/sessions`: active session listing (GET)
+- `src/app/api/rate-limits`: per-account rate limit status (GET)
+
+### Routing and Execution Core
+
+- `src/sse/handlers/chat.ts`: request parse, combo handling, account selection loop
+- `open-sse/handlers/chatCore.ts`: translation, executor dispatch, retry/refresh handling, stream setup
+- `open-sse/executors/*`: provider-specific network and format behavior
+
+### Translation Registry and Format Converters
+
+- `open-sse/translator/index.ts`: translator registry and orchestration
+- Request translators: `open-sse/translator/request/*`
+- Response translators: `open-sse/translator/response/*`
+- Format constants: `open-sse/translator/formats.ts`
+
+### Persistence
+
+- `src/lib/db/*`: persistent config/state and domain persistence on SQLite
+- `src/lib/localDb.ts`: compatibility re-export for DB modules
+- `src/lib/usageDb.ts`: usage history/call logs facade on top of SQLite tables
+
+## Provider Executor Coverage (Strategy Pattern)
+
+Each provider has a specialized executor extending `BaseExecutor` (in `open-sse/executors/base.ts`), which provides URL building, header construction, retry with exponential backoff, credential refresh hooks, and the `execute()` orchestration method.
+
+| Executor | Provider(s) | Special Handling |
+| --------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------ | -------------------------------------------------------------------- |
+| `DefaultExecutor` | OpenAI, Claude, Gemini, Qwen, Qoder, OpenRouter, GLM, Kimi, MiniMax, DeepSeek, Groq, xAI, Mistral, Perplexity, Together, Fireworks, Cerebras, Cohere, NVIDIA | Dynamic URL/header config per provider |
+| `AntigravityExecutor` | Google Antigravity | Custom project/session IDs, Retry-After parsing |
+| `CodexExecutor` | OpenAI Codex | Injects system instructions, forces reasoning effort |
+| `CursorExecutor` | Cursor IDE | ConnectRPC protocol, Protobuf encoding, request signing via checksum |
+| `GithubExecutor` | GitHub Copilot | Copilot token refresh, VSCode-mimicking headers |
+| `KiroExecutor` | AWS CodeWhisperer/Kiro | AWS EventStream binary format → SSE conversion |
+| `GeminiCLIExecutor` | Gemini CLI | Google OAuth token refresh cycle |
+
+All other providers (including custom compatible nodes) use the `DefaultExecutor`.
+
+## Provider Compatibility Matrix
+
+| Provider | Format | Auth | Stream | Non-Stream | Token Refresh | Usage API |
+| ---------------- | ---------------- | --------------------- | ---------------- | ---------- | ------------- | ------------------ |
+| Claude | claude | API Key / OAuth | ✅ | ✅ | ✅ | ⚠️ Admin only |
+| Gemini | gemini | API Key / OAuth | ✅ | ✅ | ✅ | ⚠️ Cloud Console |
+| Gemini CLI | gemini-cli | OAuth | ✅ | ✅ | ✅ | ⚠️ Cloud Console |
+| Antigravity | antigravity | OAuth | ✅ | ✅ | ✅ | ✅ Full quota API |
+| OpenAI | openai | API Key | ✅ | ✅ | ❌ | ❌ |
+| Codex | openai-responses | OAuth | ✅ forced | ❌ | ✅ | ✅ Rate limits |
+| GitHub Copilot | openai | OAuth + Copilot Token | ✅ | ✅ | ✅ | ✅ Quota snapshots |
+| Cursor | cursor | Custom checksum | ✅ | ✅ | ❌ | ❌ |
+| Kiro | kiro | AWS SSO OIDC | ✅ (EventStream) | ❌ | ✅ | ✅ Usage limits |
+| Qwen | openai | OAuth | ✅ | ✅ | ✅ | ⚠️ Per request |
+| Qoder | openai | OAuth (Basic) | ✅ | ✅ | ✅ | ⚠️ Per request |
+| OpenRouter | openai | API Key | ✅ | ✅ | ❌ | ❌ |
+| GLM/Kimi/MiniMax | claude | API Key | ✅ | ✅ | ❌ | ❌ |
+| DeepSeek | openai | API Key | ✅ | ✅ | ❌ | ❌ |
+| Groq | openai | API Key | ✅ | ✅ | ❌ | ❌ |
+| xAI (Grok) | openai | API Key | ✅ | ✅ | ❌ | ❌ |
+| Mistral | openai | API Key | ✅ | ✅ | ❌ | ❌ |
+| Perplexity | openai | API Key | ✅ | ✅ | ❌ | ❌ |
+| Together AI | openai | API Key | ✅ | ✅ | ❌ | ❌ |
+| Fireworks AI | openai | API Key | ✅ | ✅ | ❌ | ❌ |
+| Cerebras | openai | API Key | ✅ | ✅ | ❌ | ❌ |
+| Cohere | openai | API Key | ✅ | ✅ | ❌ | ❌ |
+| NVIDIA NIM | openai | API Key | ✅ | ✅ | ❌ | ❌ |
+
+## Format Translation Coverage
+
+Detected source formats include:
+
+- `openai`
+- `openai-responses`
+- `claude`
+- `gemini`
+
+Target formats include:
+
+- OpenAI chat/Responses
+- Claude
+- Gemini/Gemini-CLI/Antigravity envelope
+- Kiro
+- Cursor
+
+Translations use **OpenAI as the hub format** — all conversions go through OpenAI as intermediate:
+
+```
+Source Format → OpenAI (hub) → Target Format
+```
+
+Translations are selected dynamically based on source payload shape and provider target format.
+
+Additional processing layers in the translation pipeline:
+
+- **Response sanitization** — Strips non-standard fields from OpenAI-format responses (both streaming and non-streaming) to ensure strict SDK compliance
+- **Role normalization** — Converts `developer` → `system` for non-OpenAI targets; merges `system` → `user` for models that reject the system role (GLM, ERNIE)
+- **Think tag extraction** — Parses `...` blocks from content into `reasoning_content` field
+- **Structured output** — Converts OpenAI `response_format.json_schema` to Gemini's `responseMimeType` + `responseSchema`
+
+## Supported API Endpoints
+
+| Endpoint | Format | Handler |
+| -------------------------------------------------- | ------------------ | ------------------------------------------------------------------- |
+| `POST /v1/chat/completions` | OpenAI Chat | `src/sse/handlers/chat.ts` |
+| `POST /v1/messages` | Claude Messages | Same handler (auto-detected) |
+| `POST /v1/responses` | OpenAI Responses | `open-sse/handlers/responsesHandler.ts` |
+| `POST /v1/embeddings` | OpenAI Embeddings | `open-sse/handlers/embeddings.ts` |
+| `GET /v1/embeddings` | Model listing | API route |
+| `POST /v1/images/generations` | OpenAI Images | `open-sse/handlers/imageGeneration.ts` |
+| `GET /v1/images/generations` | Model listing | API route |
+| `POST /v1/providers/{provider}/chat/completions` | OpenAI Chat | Dedicated per-provider with model validation |
+| `POST /v1/providers/{provider}/embeddings` | OpenAI Embeddings | Dedicated per-provider with model validation |
+| `POST /v1/providers/{provider}/images/generations` | OpenAI Images | Dedicated per-provider with model validation |
+| `POST /v1/messages/count_tokens` | Claude Token Count | API route |
+| `GET /v1/models` | OpenAI Models list | API route (chat + embedding + image + custom models) |
+| `GET /api/models/catalog` | Catalog | All models grouped by provider + type |
+| `POST /v1beta/models/*:streamGenerateContent` | Gemini native | API route |
+| `GET/PUT/DELETE /api/settings/proxy` | Proxy Config | Network proxy configuration |
+| `POST /api/settings/proxy/test` | Proxy Connectivity | Proxy health/connectivity test endpoint |
+| `GET/POST/DELETE /api/provider-models` | Provider Models | Provider model metadata backing custom and managed available models |
+
+## Bypass Handler
+
+The bypass handler (`open-sse/utils/bypassHandler.ts`) intercepts known "throwaway" requests from Claude CLI — warmup pings, title extractions, and token counts — and returns a **fake response** without consuming upstream provider tokens. This is triggered only when `User-Agent` contains `claude-cli`.
+
+## Request Logger Pipeline
+
+The request logger (`open-sse/utils/requestLogger.ts`) provides a 7-stage debug logging pipeline, disabled by default, enabled via `ENABLE_REQUEST_LOGS=true`:
+
+```
+1_req_client.json → 2_req_source.json → 3_req_openai.json → 4_req_target.json
+→ 5_res_provider.txt → 6_res_openai.txt → 7_res_client.txt
+```
+
+Files are written to `/logs//` for each request session.
+
+## Failure Modes and Resilience
+
+## 1) Account/Provider Availability
+
+- provider account cooldown on transient/rate/auth errors
+- account fallback before failing request
+- combo model fallback when current model/provider path is exhausted
+
+## 2) Token Expiry
+
+- pre-check and refresh with retry for refreshable providers
+- 401/403 retry after refresh attempt in core path
+
+## 3) Stream Safety
+
+- disconnect-aware stream controller
+- translation stream with end-of-stream flush and `[DONE]` handling
+- usage estimation fallback when provider usage metadata is missing
+
+## 4) Cloud Sync Degradation
+
+- sync errors are surfaced but local runtime continues
+- scheduler has retry-capable logic, but periodic execution currently calls single-attempt sync by default
+
+## 5) Data Integrity
+
+- SQLite schema migrations and auto-upgrade hooks at startup
+- legacy JSON → SQLite migration compatibility path
+
+## Observability and Operational Signals
+
+Runtime visibility sources:
+
+- console logs from `src/sse/utils/logger.ts`
+- per-request usage aggregates in SQLite (`usage_history`, `call_logs`, `proxy_logs`)
+- four-stage detailed payload captures in SQLite (`request_detail_logs`) when `settings.detailed_logs_enabled=true`
+- textual request status log in `log.txt` (optional/compat)
+- optional deep request/translation logs under `logs/` when `ENABLE_REQUEST_LOGS=true`
+- dashboard usage endpoints (`/api/usage/*`) for UI consumption
+
+Detailed request payload capture stores up to four JSON payload stages per routed call:
+
+- raw request received from the client
+- translated request actually sent upstream
+- provider response reconstructed as JSON; streamed responses are compacted to the final summary plus stream metadata
+- final client response returned by OmniRoute; streamed responses are stored in the same compact summary form
+
+## Security-Sensitive Boundaries
+
+- JWT secret (`JWT_SECRET`) secures dashboard session cookie verification/signing
+- Initial password bootstrap (`INITIAL_PASSWORD`) should be explicitly configured for first-run provisioning
+- API key HMAC secret (`API_KEY_SECRET`) secures generated local API key format
+- Provider secrets (API keys/tokens) are persisted in local DB and should be protected at filesystem level
+- Cloud sync endpoints rely on API key auth + machine id semantics
+
+## Environment and Runtime Matrix
+
+Environment variables actively used by code:
+
+- App/auth: `JWT_SECRET`, `INITIAL_PASSWORD`
+- Storage: `DATA_DIR`
+- Compatible node behavior: `ALLOW_MULTI_CONNECTIONS_PER_COMPAT_NODE`
+- Optional storage base override (Linux/macOS when `DATA_DIR` unset): `XDG_CONFIG_HOME`
+- Security hashing: `API_KEY_SECRET`, `MACHINE_ID_SALT`
+- Logging: `ENABLE_REQUEST_LOGS`
+- Sync/cloud URLing: `NEXT_PUBLIC_BASE_URL`, `NEXT_PUBLIC_CLOUD_URL`
+- Outbound proxy: `HTTP_PROXY`, `HTTPS_PROXY`, `ALL_PROXY`, `NO_PROXY` and lowercase variants
+- SOCKS5 feature flags: `ENABLE_SOCKS5_PROXY`, `NEXT_PUBLIC_ENABLE_SOCKS5_PROXY`
+- Platform/runtime helpers (not app-specific config): `APPDATA`, `NODE_ENV`, `PORT`, `HOSTNAME`
+
+## Known Architectural Notes
+
+1. `usageDb` and `localDb` share the same base directory policy (`DATA_DIR` -> `XDG_CONFIG_HOME/omniroute` -> `~/.omniroute`) with legacy file migration.
+2. `/api/v1/route.ts` delegates to the same unified catalog builder used by `/api/v1/models` (`src/app/api/v1/models/catalog.ts`) to avoid semantic drift.
+3. Request logger writes full headers/body when enabled; treat log directory as sensitive.
+4. Cloud behavior depends on correct `NEXT_PUBLIC_BASE_URL` and cloud endpoint reachability.
+5. The `open-sse/` directory is published as the `@omniroute/open-sse` **npm workspace package**. Source code imports it via `@omniroute/open-sse/...` (resolved by Next.js `transpilePackages`). File paths in this document still use the directory name `open-sse/` for consistency.
+6. Charts in the dashboard use **Recharts** (SVG-based) for accessible, interactive analytics visualizations (model usage bar charts, provider breakdown tables with success rates).
+7. E2E tests use **Playwright** (`tests/e2e/`), run via `npm run test:e2e`. Unit tests use **Node.js test runner** (`tests/unit/`), run via `npm run test:unit`. Source code under `src/` is **TypeScript** (`.ts`/`.tsx`); the `open-sse/` workspace remains JavaScript (`.js`).
+8. Settings page is organized into 5 tabs: Security, Routing (6 global strategies: fill-first, round-robin, p2c, random, least-used, cost-optimized), Resilience (editable rate limits, circuit breaker, policies), AI (thinking budget, system prompt, prompt cache), Advanced (proxy).
+
+## Operational Verification Checklist
+
+- Build from source: `npm run build`
+- Build Docker image: `docker build -t omniroute .`
+- Start service and verify:
+- `GET /api/settings`
+- `GET /api/v1/models`
+- CLI target base URL should be `http://:20128/v1` when `PORT=20128`
diff --git a/docs/i18n/it/docs/AUTO-COMBO.md b/docs/i18n/it/docs/AUTO-COMBO.md
new file mode 100644
index 0000000000..c4e91ca086
--- /dev/null
+++ b/docs/i18n/it/docs/AUTO-COMBO.md
@@ -0,0 +1,67 @@
+# OmniRoute Auto-Combo Engine (Italiano)
+
+🌐 **Languages:** 🇺🇸 [English](../../../../docs/AUTO-COMBO.md) · 🇪🇸 [es](../../es/docs/AUTO-COMBO.md) · 🇫🇷 [fr](../../fr/docs/AUTO-COMBO.md) · 🇩🇪 [de](../../de/docs/AUTO-COMBO.md) · 🇮🇹 [it](../../it/docs/AUTO-COMBO.md) · 🇷🇺 [ru](../../ru/docs/AUTO-COMBO.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/AUTO-COMBO.md) · 🇯🇵 [ja](../../ja/docs/AUTO-COMBO.md) · 🇰🇷 [ko](../../ko/docs/AUTO-COMBO.md) · 🇸🇦 [ar](../../ar/docs/AUTO-COMBO.md) · 🇮🇳 [in](../../in/docs/AUTO-COMBO.md) · 🇹🇭 [th](../../th/docs/AUTO-COMBO.md) · 🇻🇳 [vi](../../vi/docs/AUTO-COMBO.md) · 🇮🇩 [id](../../id/docs/AUTO-COMBO.md) · 🇲🇾 [ms](../../ms/docs/AUTO-COMBO.md) · 🇳🇱 [nl](../../nl/docs/AUTO-COMBO.md) · 🇵🇱 [pl](../../pl/docs/AUTO-COMBO.md) · 🇸🇪 [sv](../../sv/docs/AUTO-COMBO.md) · 🇳🇴 [no](../../no/docs/AUTO-COMBO.md) · 🇩🇰 [da](../../da/docs/AUTO-COMBO.md) · 🇫🇮 [fi](../../fi/docs/AUTO-COMBO.md) · 🇵🇹 [pt](../../pt/docs/AUTO-COMBO.md) · 🇷🇴 [ro](../../ro/docs/AUTO-COMBO.md) · 🇭🇺 [hu](../../hu/docs/AUTO-COMBO.md) · 🇧🇬 [bg](../../bg/docs/AUTO-COMBO.md) · 🇸🇰 [sk](../../sk/docs/AUTO-COMBO.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/AUTO-COMBO.md) · 🇮🇱 [he](../../he/docs/AUTO-COMBO.md) · 🇵🇭 [phi](../../phi/docs/AUTO-COMBO.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/AUTO-COMBO.md) · 🇨🇿 [cs](../../cs/docs/AUTO-COMBO.md)
+
+---
+
+> Self-managing model chains with adaptive scoring
+
+## How It Works
+
+The Auto-Combo Engine dynamically selects the best provider/model for each request using a **6-factor scoring function**:
+
+| Factor | Weight | Description |
+| :--------- | :----- | :---------------------------------------------- |
+| Quota | 0.20 | Remaining capacity [0..1] |
+| Health | 0.25 | Circuit breaker: CLOSED=1.0, HALF=0.5, OPEN=0.0 |
+| CostInv | 0.20 | Inverse cost (cheaper = higher score) |
+| LatencyInv | 0.15 | Inverse p95 latency (faster = higher) |
+| TaskFit | 0.10 | Model × task type fitness score |
+| Stability | 0.10 | Low variance in latency/errors |
+
+## Mode Packs
+
+| Pack | Focus | Key Weight |
+| :---------------------- | :----------- | :--------------- |
+| 🚀 **Ship Fast** | Speed | latencyInv: 0.35 |
+| 💰 **Cost Saver** | Economy | costInv: 0.40 |
+| 🎯 **Quality First** | Best model | taskFit: 0.40 |
+| 📡 **Offline Friendly** | Availability | quota: 0.40 |
+
+## Self-Healing
+
+- **Temporary exclusion**: Score < 0.2 → excluded for 5 min (progressive backoff, max 30 min)
+- **Circuit breaker awareness**: OPEN → auto-excluded; HALF_OPEN → probe requests
+- **Incident mode**: >50% OPEN → disable exploration, maximize stability
+- **Cooldown recovery**: After exclusion, first request is a "probe" with reduced timeout
+
+## Bandit Exploration
+
+5% of requests (configurable) are routed to random providers for exploration. Disabled in incident mode.
+
+## API
+
+```bash
+# Create auto-combo
+curl -X POST http://localhost:20128/api/combos/auto \
+ -H "Content-Type: application/json" \
+ -d '{"id":"my-auto","name":"Auto Coder","candidatePool":["anthropic","google","openai"],"modePack":"ship-fast"}'
+
+# List auto-combos
+curl http://localhost:20128/api/combos/auto
+```
+
+## Task Fitness
+
+30+ models scored across 6 task types (`coding`, `review`, `planning`, `analysis`, `debugging`, `documentation`). Supports wildcard patterns (e.g., `*-coder` → high coding score).
+
+## Files
+
+| File | Purpose |
+| :------------------------------------------- | :------------------------------------ |
+| `open-sse/services/autoCombo/scoring.ts` | Scoring function & pool normalization |
+| `open-sse/services/autoCombo/taskFitness.ts` | Model × task fitness lookup |
+| `open-sse/services/autoCombo/engine.ts` | Selection logic, bandit, budget cap |
+| `open-sse/services/autoCombo/selfHealing.ts` | Exclusion, probes, incident mode |
+| `open-sse/services/autoCombo/modePacks.ts` | 4 weight profiles |
+| `src/app/api/combos/auto/route.ts` | REST API |
diff --git a/docs/i18n/it/docs/CLI-TOOLS.md b/docs/i18n/it/docs/CLI-TOOLS.md
new file mode 100644
index 0000000000..248f4e1cdb
--- /dev/null
+++ b/docs/i18n/it/docs/CLI-TOOLS.md
@@ -0,0 +1,348 @@
+# CLI Tools Setup Guide — OmniRoute (Italiano)
+
+🌐 **Languages:** 🇺🇸 [English](../../../../docs/CLI-TOOLS.md) · 🇪🇸 [es](../../es/docs/CLI-TOOLS.md) · 🇫🇷 [fr](../../fr/docs/CLI-TOOLS.md) · 🇩🇪 [de](../../de/docs/CLI-TOOLS.md) · 🇮🇹 [it](../../it/docs/CLI-TOOLS.md) · 🇷🇺 [ru](../../ru/docs/CLI-TOOLS.md) · 🇨🇳 [zh-CN](../../zh-CN/docs/CLI-TOOLS.md) · 🇯🇵 [ja](../../ja/docs/CLI-TOOLS.md) · 🇰🇷 [ko](../../ko/docs/CLI-TOOLS.md) · 🇸🇦 [ar](../../ar/docs/CLI-TOOLS.md) · 🇮🇳 [in](../../in/docs/CLI-TOOLS.md) · 🇹🇭 [th](../../th/docs/CLI-TOOLS.md) · 🇻🇳 [vi](../../vi/docs/CLI-TOOLS.md) · 🇮🇩 [id](../../id/docs/CLI-TOOLS.md) · 🇲🇾 [ms](../../ms/docs/CLI-TOOLS.md) · 🇳🇱 [nl](../../nl/docs/CLI-TOOLS.md) · 🇵🇱 [pl](../../pl/docs/CLI-TOOLS.md) · 🇸🇪 [sv](../../sv/docs/CLI-TOOLS.md) · 🇳🇴 [no](../../no/docs/CLI-TOOLS.md) · 🇩🇰 [da](../../da/docs/CLI-TOOLS.md) · 🇫🇮 [fi](../../fi/docs/CLI-TOOLS.md) · 🇵🇹 [pt](../../pt/docs/CLI-TOOLS.md) · 🇷🇴 [ro](../../ro/docs/CLI-TOOLS.md) · 🇭🇺 [hu](../../hu/docs/CLI-TOOLS.md) · 🇧🇬 [bg](../../bg/docs/CLI-TOOLS.md) · 🇸🇰 [sk](../../sk/docs/CLI-TOOLS.md) · 🇺🇦 [uk-UA](../../uk-UA/docs/CLI-TOOLS.md) · 🇮🇱 [he](../../he/docs/CLI-TOOLS.md) · 🇵🇭 [phi](../../phi/docs/CLI-TOOLS.md) · 🇧🇷 [pt-BR](../../pt-BR/docs/CLI-TOOLS.md) · 🇨🇿 [cs](../../cs/docs/CLI-TOOLS.md)
+
+---
+
+This guide explains how to install and configure all supported AI coding CLI tools
+to use **OmniRoute** as the unified backend, giving you centralized key management,
+cost tracking, model switching, and request logging across every tool.
+
+---
+
+## How It Works
+
+```
+Claude / Codex / OpenCode / Cline / KiloCode / Continue / Kiro / Cursor / Copilot
+ │
+ ▼ (all point to OmniRoute)
+ http://YOUR_SERVER:20128/v1
+ │
+ ▼ (OmniRoute routes to the right provider)
+ Anthropic / OpenAI / Gemini / DeepSeek / Groq / Mistral / ...
+```
+
+**Benefits:**
+
+- One API key to manage all tools
+- Cost tracking across all CLIs in the dashboard
+- Model switching without reconfiguring every tool
+- Works locally and on remote servers (VPS)
+
+---
+
+## Supported Tools (Dashboard Source of Truth)
+
+The dashboard cards in `/dashboard/cli-tools` are generated from `src/shared/constants/cliTools.ts`.
+Current list (v3.0.0-rc.16):
+
+| Tool | ID | Command | Setup Mode | Install Method |
+| ------------------ | ------------- | ---------- | ---------- | -------------- |
+| **Claude Code** | `claude` | `claude` | env | npm |
+| **OpenAI Codex** | `codex` | `codex` | custom | npm |
+| **Factory Droid** | `droid` | `droid` | custom | bundled/CLI |
+| **OpenClaw** | `openclaw` | `openclaw` | custom | bundled/CLI |
+| **Cursor** | `cursor` | app | guide | desktop app |
+| **Cline** | `cline` | `cline` | custom | npm |
+| **Kilo Code** | `kilo` | `kilocode` | custom | npm |
+| **Continue** | `continue` | extension | guide | VS Code |
+| **Antigravity** | `antigravity` | internal | mitm | OmniRoute |
+| **GitHub Copilot** | `copilot` | extension | custom | VS Code |
+| **OpenCode** | `opencode` | `opencode` | guide | npm |
+| **Kiro AI** | `kiro` | app/cli | mitm | desktop/CLI |
+
+### CLI fingerprint sync (Agents + Settings)
+
+`/dashboard/agents` and `Settings > CLI Fingerprint` use `src/shared/constants/cliCompatProviders.ts`.
+This keeps provider IDs aligned with CLI cards and legacy IDs.
+
+| CLI ID | Fingerprint Provider ID |
+| ---------------------------------------------------------------------------------------------------- | ----------------------- |
+| `kilo` | `kilocode` |
+| `copilot` | `github` |
+| `claude` / `codex` / `antigravity` / `kiro` / `cursor` / `cline` / `opencode` / `droid` / `openclaw` | same ID |
+
+Legacy IDs still accepted for compatibility: `copilot`, `kimi-coding`, `qwen`.
+
+---
+
+## Step 1 — Get an OmniRoute API Key
+
+1. Open the OmniRoute dashboard → **API Manager** (`/dashboard/api-manager`)
+2. Click **Create API Key**
+3. Give it a name (e.g. `cli-tools`) and select all permissions
+4. Copy the key — you'll need it for every CLI below
+
+> Your key looks like: `sk-xxxxxxxxxxxxxxxx-xxxxxxxxx`
+
+---
+
+## Step 2 — Install CLI Tools
+
+All npm-based tools require Node.js 18+:
+
+```bash
+# Claude Code (Anthropic)
+npm install -g @anthropic-ai/claude-code
+
+# OpenAI Codex
+npm install -g @openai/codex
+
+# OpenCode
+npm install -g opencode-ai
+
+# Cline
+npm install -g cline
+
+# KiloCode
+npm install -g kilocode
+
+# Kiro CLI (Amazon — requires curl + unzip)
+apt-get install -y unzip # on Debian/Ubuntu
+curl -fsSL https://cli.kiro.dev/install | bash
+export PATH="$HOME/.local/bin:$PATH" # add to ~/.bashrc
+```
+
+**Verify:**
+
+```bash
+claude --version # 2.x.x
+codex --version # 0.x.x
+opencode --version # x.x.x
+cline --version # 2.x.x
+kilocode --version # x.x.x (or: kilo --version)
+kiro-cli --version # 1.x.x
+```
+
+---
+
+## Step 3 — Set Global Environment Variables
+
+Add to `~/.bashrc` (or `~/.zshrc`), then run `source ~/.bashrc`:
+
+```bash
+# OmniRoute Universal Endpoint
+export OPENAI_BASE_URL="http://localhost:20128/v1"
+export OPENAI_API_KEY="sk-your-omniroute-key"
+export ANTHROPIC_BASE_URL="http://localhost:20128/v1"
+export ANTHROPIC_API_KEY="sk-your-omniroute-key"
+export GEMINI_BASE_URL="http://localhost:20128/v1"
+export GEMINI_API_KEY="sk-your-omniroute-key"
+```
+
+> For a **remote server** replace `localhost:20128` with the server IP or domain,
+> e.g. `http://192.168.0.15:20128`.
+
+---
+
+## Step 4 — Configure Each Tool
+
+### Claude Code
+
+```bash
+# Via CLI:
+claude config set --global api-base-url http://localhost:20128/v1
+
+# Or create ~/.claude/settings.json:
+mkdir -p ~/.claude && cat > ~/.claude/settings.json << EOF
+{
+ "apiBaseUrl": "http://localhost:20128/v1",
+ "apiKey": "sk-your-omniroute-key"
+}
+EOF
+```
+
+**Test:** `claude "say hello"`
+
+---
+
+### OpenAI Codex
+
+```bash
+mkdir -p ~/.codex && cat > ~/.codex/config.yaml << EOF
+model: auto
+apiKey: sk-your-omniroute-key
+apiBaseUrl: http://localhost:20128/v1
+EOF
+```
+
+**Test:** `codex "what is 2+2?"`
+
+---
+
+### OpenCode
+
+```bash
+mkdir -p ~/.config/opencode && cat > ~/.config/opencode/config.toml << EOF
+[provider.openai]
+base_url = "http://localhost:20128/v1"
+api_key = "sk-your-omniroute-key"
+EOF
+```
+
+**Test:** `opencode`
+
+---
+
+### Cline (CLI or VS Code)
+
+**CLI mode:**
+
+```bash
+mkdir -p ~/.cline/data && cat > ~/.cline/data/globalState.json << EOF
+{
+ "apiProvider": "openai",
+ "openAiBaseUrl": "http://localhost:20128/v1",
+ "openAiApiKey": "sk-your-omniroute-key"
+}
+EOF
+```
+
+**VS Code mode:**
+Cline extension settings → API Provider: `OpenAI Compatible` → Base URL: `http://localhost:20128/v1`
+
+Or use the OmniRoute dashboard → **CLI Tools → Cline → Apply Config**.
+
+---
+
+### KiloCode (CLI or VS Code)
+
+**CLI mode:**
+
+```bash
+kilocode --api-base http://localhost:20128/v1 --api-key sk-your-omniroute-key
+```
+
+**VS Code settings:**
+
+```json
+{
+ "kilo-code.openAiBaseUrl": "http://localhost:20128/v1",
+ "kilo-code.apiKey": "sk-your-omniroute-key"
+}
+```
+
+Or use the OmniRoute dashboard → **CLI Tools → KiloCode → Apply Config**.
+
+---
+
+### Continue (VS Code Extension)
+
+Edit `~/.continue/config.yaml`:
+
+```yaml
+models:
+ - name: OmniRoute
+ provider: openai
+ model: auto
+ apiBase: http://localhost:20128/v1
+ apiKey: sk-your-omniroute-key
+ default: true
+```
+
+Restart VS Code after editing.
+
+---
+
+### Kiro CLI (Amazon)
+
+```bash
+# Login to your AWS/Kiro account:
+kiro-cli login
+
+# The CLI uses its own auth — OmniRoute is not needed as backend for Kiro CLI itself.
+# Use kiro-cli alongside OmniRoute for other tools.
+kiro-cli status
+```
+
+---
+
+### Cursor (Desktop App)
+
+> **Note:** Cursor routes requests through its cloud. For OmniRoute integration,
+> enable **Cloud Endpoint** in OmniRoute Settings and use your public domain URL.
+
+Via GUI: **Settings → Models → OpenAI API Key**
+
+- Base URL: `https://your-domain.com/v1`
+- API Key: your OmniRoute key
+
+---
+
+## Dashboard Auto-Configuration
+
+The OmniRoute dashboard automates configuration for most tools:
+
+1. Go to `http://localhost:20128/dashboard/cli-tools`
+2. Expand any tool card
+3. Select your API key from the dropdown
+4. Click **Apply Config** (if tool is detected as installed)
+5. Or copy the generated config snippet manually
+
+---
+
+## Built-in Agents: Droid & OpenClaw
+
+**Droid** and **OpenClaw** are AI agents built directly into OmniRoute — no installation needed.
+They run as internal routes and use OmniRoute's model routing automatically.
+
+- Access: `http://localhost:20128/dashboard/agents`
+- Configure: same combos and providers as all other tools
+- No API key or CLI install required
+
+---
+
+## Available API Endpoints
+
+| Endpoint | Description | Use For |
+| -------------------------- | ----------------------------- | --------------------------- |
+| `/v1/chat/completions` | Standard chat (all providers) | All modern tools |
+| `/v1/responses` | Responses API (OpenAI format) | Codex, agentic workflows |
+| `/v1/completions` | Legacy text completions | Older tools using `prompt:` |
+| `/v1/embeddings` | Text embeddings | RAG, search |
+| `/v1/images/generations` | Image generation | DALL-E, Flux, etc. |
+| `/v1/audio/speech` | Text-to-speech | ElevenLabs, OpenAI TTS |
+| `/v1/audio/transcriptions` | Speech-to-text | Deepgram, AssemblyAI |
+
+---
+
+## Risoluzione dei Problemi
+
+| Error | Cause | Fix |
+| ------------------------- | ----------------------- | ------------------------------------------ |
+| `Connection refused` | OmniRoute not running | `pm2 start omniroute` |
+| `401 Unauthorized` | Wrong API key | Check in `/dashboard/api-manager` |
+| `No combo configured` | No active routing combo | Set up in `/dashboard/combos` |
+| `invalid model` | Model not in catalog | Use `auto` or check `/dashboard/providers` |
+| CLI shows "not installed" | Binary not in PATH | Check `which