Compare commits

...

678 Commits

Author SHA1 Message Date
Diego Rodrigues de Sa e Souza 6acd36e374 Merge pull request #655 from oSoWoSo/dev
Build Electron Desktop App / Validate version (push) Failing after 34s
Build Electron Desktop App / Build Electron (macos-arm64) (push) Has been skipped
Build Electron Desktop App / Build Electron (linux) (push) Has been skipped
Build Electron Desktop App / Build Electron (macos-intel) (push) Has been skipped
Build Electron Desktop App / Build Electron (windows) (push) Has been skipped
Build Electron Desktop App / Create Release (push) Has been skipped
Build Electron Desktop App / Publish to npm (push) Has been skipped
Merged! Thanks @zen0bit for polishing the Czech translations 🇨🇿
2026-03-26 23:50:54 -03:00
zenobit af51eecbac i18n: Improve some strings 2026-03-27 03:33:53 +01:00
diegosouzapw 3a23dc8b04 release: v3.1.3 — community i18n contributions (#652, #651)
Build Electron Desktop App / Validate version (push) Failing after 43s
Build Electron Desktop App / Build Electron (macos-arm64) (push) Has been skipped
Build Electron Desktop App / Build Electron (linux) (push) Has been skipped
Build Electron Desktop App / Build Electron (macos-intel) (push) Has been skipped
Build Electron Desktop App / Build Electron (windows) (push) Has been skipped
Build Electron Desktop App / Create Release (push) Has been skipped
Build Electron Desktop App / Publish to npm (push) Has been skipped
Changes:
- i18n: ~70 missing translation keys for en.json + 12 languages (PR #652 by @zen0bit)
- i18n: Czech documentation updates — CLI-TOOLS, API_REFERENCE, VM_DEPLOYMENT (PR #652)
- feat: translation validation scripts for CI/QA (PR #651 by @zen0bit)
- docs: update CHANGELOG and OpenAPI spec
2026-03-26 21:32:52 -03:00
Diego Rodrigues de Sa e Souza ba13e44720 Merge pull request #651 from oSoWoSo/main-scripts
Merged! 🎉 Thank you @zen0bit for the translation validation tooling.
2026-03-26 21:31:48 -03:00
Diego Rodrigues de Sa e Souza e80420f6db Merge pull request #652 from oSoWoSo/main-i18n-fixes
Merged! 🎉 Thank you @zen0bit for the comprehensive i18n contribution — ~70 missing keys + Czech docs updates.
2026-03-26 21:31:42 -03:00
zenobit 21ddcfc866 feat: make validate_translation.py support any language
- Add --lang / -l argument for target language
- Add TRANSLATION_LANG environment variable support
- Default to cs for backwards compatibility
- Validate language file exists before processing

Usage:
  python validate_translation.py -l de
  TRANSLATION_LANG=fr python validate_translation.py
  python validate_translation.py --lang cs quick

Co-authored-by: openhands <openhands@all-hands.dev>
2026-03-27 01:24:18 +01:00
zenobit 20f82cb22c Apply suggestions from code review
Co-authored-by: zenobit <zenobit@disroot.org>
2026-03-27 01:15:45 +01:00
zenobit 7ef75bab23 Apply suggestions from code review
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
2026-03-27 01:13:13 +01:00
zenobit 7224e03590 Add check_translations and validate_translations scripts 2026-03-27 01:05:40 +01:00
zenobit cf4f2991a5 i18n: add missing translation keys, Czech docs, and validation scripts
- Added ~70 common keys and auth keys to en.json
- Added cliTools.toolDescriptions for CLI tools
- Updated Czech documentation (CLI-TOOLS.md, API_REFERENCE.md, VM_DEPLOYMENT_GUIDE.md)
- Added check_translations.py and validate-translation.sh scripts
- Refactored auth keys from full sentences to structured keys (auth.waitingForAuthorization)
- Fixed grammatical error (své cloud -> svůj cloud)
- Removed duplicate toolDescriptions from common namespace
- Improved error handling with specific exceptions
- OAuth services use hardcoded English strings as fallback (when i18n unavailable)
- Fixed capitalization: Antigravity, iFlow

Co-authored-by: openhands <openhands@all-hands.dev>
2026-03-27 00:37:21 +01:00
zenobit 9eb3c23494 Improve 2026-03-27 00:37:21 +01:00
zenobit c80d8898cc Fix toolDescriptions and remaining auth keys
Co-authored-by: openhands <openhands@all-hands.dev>
2026-03-27 00:37:21 +01:00
zenobit bc74dd88e0 Add missing translation keys: common, auth, templates, toolDescriptions
- Added ~70 common keys (id, authorization, proxy, etc.)
- Added auth keys for OAuth waiting messages
- Added templateNames, templateDescriptions, templatePayloads
- Added toolDescriptions for CLI tools
- Added TOOL_ALLOWLIST, TOOL_DENYLIST
- Added pricing error messages

Co-authored-by: openhands <openhands@all-hands.dev>
2026-03-27 00:37:21 +01:00
zenobit da87c461ef Add missing home.updateNow, updating, updateAvailableDesc, updateStarted
Co-authored-by: openhands <openhands@all-hands.dev>
2026-03-27 00:37:21 +01:00
zenobit bf2e694f2c cs.json: Add missing translations for notes and providers
- cliTools.guides.continue.notes
- cliTools.guides.opencode.notes (2 entries)
- cliTools.guides.kiro.notes
- providers.autoSync (7 new keys)

Co-authored-by: openhands <openhands@all-hands.dev>
2026-03-27 00:37:21 +01:00
zenobit e5150487c4 Add missing notes to cliTools.guides for continue, opencode, kiro
- continue: 'Continue uses JSON config file.'
- opencode: 'OpenCode requires API key configuration.', 'Set the base URL to your OmniRoute endpoint.'
- kiro: 'Kiro requires Amazon account.'

Co-authored-by: openhands <openhands@all-hands.dev>
2026-03-27 00:37:21 +01:00
diegosouzapw 9ff6353b88 release: v3.1.2 — fix critical tool calling regression (#618)
Build Electron Desktop App / Validate version (push) Failing after 28s
Build Electron Desktop App / Build Electron (macos-arm64) (push) Has been skipped
Build Electron Desktop App / Build Electron (linux) (push) Has been skipped
Build Electron Desktop App / Build Electron (macos-intel) (push) Has been skipped
Build Electron Desktop App / Build Electron (windows) (push) Has been skipped
Build Electron Desktop App / Create Release (push) Has been skipped
Build Electron Desktop App / Publish to npm (push) Has been skipped
Changes:
- fix: disable proxy_ tool prefix for Claude passthrough (Bash → proxy_Bash)
- docs: document Kiro account ban as upstream AWS issue (#649)
- docs: update CHANGELOG and OpenAPI spec

Fixes #618, closes #649, closes #615
2026-03-26 19:49:45 -03:00
diegosouzapw 926fd8abf4 fix: disable proxy_ tool prefix for all Claude-target passthrough (#618)
The openai-to-claude translator was prefixing tool names with 'proxy_'
(e.g. Bash → proxy_Bash) even when routing Claude-format requests to
native Claude/Anthropic providers. Claude rejects unknown tool names,
causing 'No such tool available: proxy_Bash' errors.

Root cause: the _disableToolPrefix condition only disabled the prefix
for non-Claude providers, but it should be disabled for ALL providers
in the Claude passthrough path since tools are already in Claude format.

Fixes #618
2026-03-26 19:44:44 -03:00
diegosouzapw 211a7a4cfe release: v3.1.1 — Ollama Cloud fix, Gemini 3.1, vision metadata, token retry
Build Electron Desktop App / Validate version (push) Failing after 27s
Build Electron Desktop App / Build Electron (macos-arm64) (push) Has been skipped
Build Electron Desktop App / Build Electron (linux) (push) Has been skipped
Build Electron Desktop App / Build Electron (macos-intel) (push) Has been skipped
Build Electron Desktop App / Build Electron (windows) (push) Has been skipped
Build Electron Desktop App / Create Release (push) Has been skipped
Build Electron Desktop App / Publish to npm (push) Has been skipped
Changes:
- fix: Ollama Cloud 401 — wrong base URL (api.ollama.com → ollama.com) (#643)
- fix: Add Gemini 3.1 Pro/Flash to Antigravity provider (#645)
- feat: Vision capability metadata in /v1/models (PR #646)
- feat: Exponential backoff retry for expired OAuth tokens (PR #647)

Closes #643, closes #645
2026-03-26 15:56:44 -03:00
diegosouzapw c1835cd9cc fix: correct Ollama Cloud URL and add Gemini 3.1 to Antigravity (#643, #645)
- Fix Ollama Cloud base URL from api.ollama.com to ollama.com/v1/chat/completions
- Fix Ollama Cloud models URL to ollama.com/api/tags
- Add gemini-3.1-pro-preview and gemini-3.1-flash-lite-preview to Antigravity provider

Closes #643, closes #645
2026-03-26 15:53:31 -03:00
Diego Rodrigues de Sa e Souza 5700044393 Merge pull request #646 from brendandebeasi/feat/vision-capability-metadata
Thanks @brendandebeasi for another great contribution! 🎉 Vision capability metadata fixes real client compat issues. Merged for v3.1.1.
2026-03-26 15:49:54 -03:00
Diego Rodrigues de Sa e Souza 36fbd3d018 Merge pull request #647 from brendandebeasi/fix/expired-token-retry-healthcheck
Thanks @brendandebeasi for this excellent contribution! 🎉 The bounded retry with exponential backoff is exactly the right approach for expired connections. Merged and will be included in v3.1.1.
2026-03-26 15:49:52 -03:00
Diego Rodrigues de Sa e Souza d1178390a9 Merge pull request #648 from diegosouzapw/release/v3.0.10
Build Electron Desktop App / Validate version (push) Failing after 34s
Build Electron Desktop App / Build Electron (macos-arm64) (push) Has been skipped
Build Electron Desktop App / Build Electron (linux) (push) Has been skipped
Build Electron Desktop App / Build Electron (macos-intel) (push) Has been skipped
Build Electron Desktop App / Build Electron (windows) (push) Has been skipped
Build Electron Desktop App / Create Release (push) Has been skipped
Build Electron Desktop App / Publish to npm (push) Has been skipped
chore(release): v3.1.0 — bug fixes, new features, i18n updates
2026-03-26 15:20:56 -03:00
diegosouzapw 8182825e92 chore(release): v3.1.0 — bug fixes, new features, i18n updates
Bug Fixes:
- #642: Locale conflict (in.json → hi.json for Hindi)
- #637: Codex empty tool names causing 400 errors
- #638: Streaming newline artifacts from thinking models
- #627: Claude reasoning effort parameter conversion
- #631: Qwen proactive token refresh (5-min buffer)

Features:
- #641: GitHub issue templates (bug, feature, config/proxy)
- #634: Clear All Models button with i18n (29 languages)

Docs:
- Updated README.md and 30 i18n translations with new features
- CHANGELOG.md finalized for v3.1.0

Tests: 936/936 pass (+10 since v3.0.9)
2026-03-26 15:18:06 -03:00
Brendan DeBeasi 2392006246 fix: retry expired connections in token health check instead of permanently skipping
Connections marked as 'expired' were permanently skipped by the health check scheduler (line 176: if testStatus === "expired" return). A single transient refresh failure could permanently disable auto-refresh, requiring manual re-authentication.

Replace the hard skip with a bounded retry mechanism: up to 3 attempts with exponential backoff (5min, 10min, 20min). On success, the connection is fully restored to active. On exhaustion, it remains expired (same as before). The existing circuit breaker (5 failures → 30min pause) provides additional protection.

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
2026-03-26 11:11:49 -07:00
Brendan DeBeasi a6e78cd5dc feat: add vision capability metadata to /v1/models response
OpenAI-compatible clients (OpenCode, etc.) check capabilities/input_modalities fields on the /v1/models response to determine if a model supports image input. Omniroute was not emitting these fields, causing clients to assume text-only for all models routed through the proxy.

Add keyword-based vision detection (matching the existing playground heuristic) that annotates model entries with capabilities:{vision:true}, input_modalities:["text","image"], and output_modalities:["text"] for known multimodal models (GPT-4o/4-turbo, Claude 3+, Gemini, Pixtral, Qwen-VL, etc.).

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
2026-03-26 11:00:29 -07:00
diegosouzapw 8752790352 fix: rename Hindi locale in→hi, global tool name filter, collapse \n artifacts (#642, #637, #638)
- Rename in.json → hi.json: 'in' is Indonesian (ISO 639-1), Hindi is 'hi'.
  Fixes Weblate locale conflict where id.json and in.json both claimed Indonesian.
- Move empty tool name filter before Codex passthrough: nativeCodexPassthrough
  skipped all input sanitization, causing 400 'empty tool name' from upstream.
- Collapse 3+ consecutive newlines to \n\n in response sanitizer: thinking
  models accumulate excessive line breaks between tool call blocks.
2026-03-26 09:22:10 -03:00
diegosouzapw 3976c79e12 fix: convert reasoning_effort to Claude thinking format & proactive token refresh (#627, #631)
- OpenAI-to-Claude translator now maps reasoning_effort (low/medium/high/max)
  to Claude's thinking.budget_tokens. Fixes clients like OpenCode sending
  reasoning_effort via @ai-sdk/openai-compatible losing thinking configuration.
- Ensures max_tokens > budget_tokens for all thinking configs.
- Token health check now proactively refreshes tokens within 5 min of expiry,
  regardless of the configured health check interval — addresses Qwen OAuth
  token refresh failures between scheduled checks.
2026-03-26 08:59:21 -03:00
Diego Rodrigues de Sa e Souza 5c1cf7f4ac Merge pull request #634 from rdself/feat/clear-all-models-button
feat: add Clear All Models button on provider detail page
2026-03-26 08:45:58 -03:00
Diego Rodrigues de Sa e Souza 912321a030 Merge pull request #641 from ardaaltinors/feat/issue-templates
Add issue templates for bug reports and feature requests
2026-03-26 08:42:21 -03:00
ardaaltinors ab0a905499 feat: add GitHub issue templates for bug reports and feature requests
Adds structured YAML-based issue templates to improve issue quality.
Bug reports require version, install method, OS, repro steps, and
expected/actual behavior. Feature requests require use case and
proposed solution. Blank issues are still allowed for edge cases.
2026-03-26 13:54:01 +03:00
Diego Rodrigues de Sa e Souza 3c6b3c02df Merge pull request #636 from diegosouzapw/release/v3.0.9
Build Electron Desktop App / Validate version (push) Failing after 34s
Build Electron Desktop App / Build Electron (macos-arm64) (push) Has been skipped
Build Electron Desktop App / Build Electron (linux) (push) Has been skipped
Build Electron Desktop App / Build Electron (macos-intel) (push) Has been skipped
Build Electron Desktop App / Build Electron (windows) (push) Has been skipped
Build Electron Desktop App / Create Release (push) Has been skipped
Build Electron Desktop App / Publish to npm (push) Has been skipped
chore(release): v3.0.9
2026-03-26 00:28:34 -03:00
diegosouzapw bcb2e91d97 chore(release): v3.0.9 — fix NaN tokens in sanitizeUsage, yaml security update (#617) 2026-03-26 00:26:22 -03:00
Diego Rodrigues de Sa e Souza 766ef94605 Merge pull request #635 from diegosouzapw/fix/sanitize-usage-crossmap-security
fix: sanitizeUsage cross-maps input_tokens→prompt_tokens; update yaml vulnerability (#617)
2026-03-26 00:25:21 -03:00
diegosouzapw e3f016e262 fix: sanitizeUsage cross-maps input_tokens→prompt_tokens; update yaml vulnerability (#617) 2026-03-25 23:53:29 -03:00
Diego Rodrigues de Sa e Souza 65833f1ae0 Merge pull request #633 from diegosouzapw/release/v3.0.8
Build Electron Desktop App / Validate version (push) Failing after 42s
Build Electron Desktop App / Build Electron (macos-arm64) (push) Has been skipped
Build Electron Desktop App / Build Electron (linux) (push) Has been skipped
Build Electron Desktop App / Build Electron (macos-intel) (push) Has been skipped
Build Electron Desktop App / Build Electron (windows) (push) Has been skipped
Build Electron Desktop App / Create Release (push) Has been skipped
Build Electron Desktop App / Publish to npm (push) Has been skipped
chore(release): v3.0.8 — fix translation failures for OpenAI-format providers (#632)
2026-03-25 23:30:48 -03:00
diegosouzapw 2602cd9ab2 chore(release): v3.0.8 — fix translation failures for OpenAI-format providers (#632) 2026-03-25 23:30:35 -03:00
R.D. 8333f3d9de feat: add "Clear All Models" button on provider detail page
Adds a button next to the Auto-Sync toggle to clear all custom models
for a provider. Extends DELETE /api/provider-models to support ?all=true
parameter for bulk deletion.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-25 21:11:17 -04:00
diegosouzapw dee1d9ba74 fix: translation failures for OpenAI-format providers in Claude CLI (#632)
- Handle reasoning_details[] array (StepFun/OpenRouter format) in sanitizer and translator
- Handle 'reasoning' field alias → reasoning_content in streaming and non-streaming paths
- Cross-map input_tokens/output_tokens ↔ prompt_tokens/completion_tokens in filterUsageForFormat
- Fix extractUsage to accept input_tokens/output_tokens as alternative field names
- All 936 tests pass
2026-03-25 22:01:29 -03:00
Diego Rodrigues de Sa e Souza ed2e0c5080 Merge pull request #630 from diegosouzapw/dependabot/npm_and_yarn/multi-bf05dc1ecf
deps: bump picomatch
2026-03-25 21:11:21 -03:00
dependabot[bot] 7db810d7d0 deps: bump picomatch
Bumps  and [picomatch](https://github.com/micromatch/picomatch). These dependencies needed to be updated together.

Updates `picomatch` from 2.3.1 to 2.3.2
- [Release notes](https://github.com/micromatch/picomatch/releases)
- [Changelog](https://github.com/micromatch/picomatch/blob/master/CHANGELOG.md)
- [Commits](https://github.com/micromatch/picomatch/compare/2.3.1...2.3.2)

Updates `picomatch` from 4.0.3 to 4.0.4
- [Release notes](https://github.com/micromatch/picomatch/releases)
- [Changelog](https://github.com/micromatch/picomatch/blob/master/CHANGELOG.md)
- [Commits](https://github.com/micromatch/picomatch/compare/2.3.1...2.3.2)

---
updated-dependencies:
- dependency-name: picomatch
  dependency-version: 2.3.2
  dependency-type: indirect
- dependency-name: picomatch
  dependency-version: 4.0.4
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-03-25 22:51:05 +00:00
Diego Rodrigues de Sa e Souza 8dae4e5038 Merge pull request #629 from diegosouzapw/release/v3.0.7
Build Electron Desktop App / Validate version (push) Failing after 23s
Build Electron Desktop App / Build Electron (macos-arm64) (push) Has been skipped
Build Electron Desktop App / Build Electron (linux) (push) Has been skipped
Build Electron Desktop App / Build Electron (macos-intel) (push) Has been skipped
Build Electron Desktop App / Build Electron (windows) (push) Has been skipped
Build Electron Desktop App / Create Release (push) Has been skipped
Build Electron Desktop App / Publish to npm (push) Has been skipped
chore(release): v3.0.7 — Antigravity token fix, Playground selector, CLI models
2026-03-25 19:30:06 -03:00
diegosouzapw b9b28edefe chore(release): v3.0.7 — Antigravity token fix, Playground selector, CLI models
Bug Fixes:
- Antigravity token refresh clientSecret (#588)
- OpenCode Zen modelsUrl (#612)
- Streaming artifacts newline collapse (#626)
- Proxy fallback and test credential resolution

Features:
- Playground persistent Account/Key selector
- CLI Tools dynamic model listing
- Antigravity model list update + passthroughModels (#628)
2026-03-25 19:27:40 -03:00
diegosouzapw 58120f435f Merge feat/issue-628: Update Antigravity model list + passthroughModels (#628) 2026-03-25 19:24:16 -03:00
diegosouzapw 027b8e52da Merge fix/issue-588-612: Antigravity clientSecret + OpenCode Zen modelsUrl (#588, #612) 2026-03-25 19:24:07 -03:00
diegosouzapw aad510a9d5 feat: update Antigravity model list and enable passthrough (#628)
- Add Claude Sonnet 4.5, Claude Sonnet 4, GPT 5, GPT 5 Mini
- Enable passthroughModels: true so users can access any model
  Antigravity supports without waiting for registry updates
2026-03-25 19:18:00 -03:00
diegosouzapw 9852a805a1 fix: Antigravity token refresh clientSecret and OpenCode Zen modelsUrl (#588, #612)
- Set clientSecretDefault for Antigravity provider (was empty, causing
  'client_secret is missing' on token refresh for npm users)
- Add modelsUrl to opencode-zen registry for 'Import from /models'
2026-03-25 19:13:29 -03:00
diegosouzapw b2cabf0122 feat(playground): add persistent Account/Key selector
Rewrote the account selector with a simpler, reliable approach:
- Fetch ALL connections once at startup (not per-provider)
- Filter by selectedProvider using ALIAS_TO_ID mapping
- Account/Key dropdown always visible when provider selected
- Shows 'Auto (N accounts)' default or individual account names
- Works for both OAuth accounts and API key providers
2026-03-25 19:00:13 -03:00
diegosouzapw 521ce15f86 fix(playground): resolve provider alias-to-ID for account selector
Import ALIAS_TO_ID mapping and resolve provider aliases (cx→codex,
kr→kiro, etc.) in loadConnections before filtering connections from
the API. The /v1/models endpoint returns alias-prefixed model IDs
but /api/providers/client returns provider IDs.
2026-03-25 18:54:49 -03:00
diegosouzapw fb97c11140 feat(dashboard): fix Playground account selector & CLI Tools dynamic model listing
Playground:
- loadConnections() was parsing wrong API response shape (expected
  providers[].connections[] but API returns flat connections[])
- Account selector now shows for any provider with ≥1 connection
- Uses conn.email as name fallback for OAuth providers

CLI Tools:
- getAllAvailableModels() now also fetches from /v1/models API
- Dynamic models supplement static PROVIDER_MODELS definitions
- Fixes providers like Kiro, OpenCode Zen showing 0 models
2026-03-25 18:17:48 -03:00
diegosouzapw 1c5c62e311 fix(streaming): collapse excessive newlines after thinking tag removal (#626)
After stripping <antThinking>/<thinking> tags from streaming responses, the
surrounding newlines were left as artifacts (e.g. \n\n\n\n). Now collapses 3+
consecutive newlines to double-newline after any tag removal.

Also fixes PR #625 merge (Provider Limits light mode background).
2026-03-25 18:10:19 -03:00
diegosouzapw 77148f7f97 Merge pull request #625 from rdself/fix/provider-limits-light-mode-bg
fix: Provider Limits table background in light mode
2026-03-25 18:05:22 -03:00
diegosouzapw a329d2f2bc fix(proxy): test endpoint resolves real credentials from DB via proxyId
The proxy test button in Settings was always failing with 'Socks5 Authentication
failed' because the frontend sent redacted credentials (***) from listProxies().
The backend received '***' as the password and tried to authenticate with it.

Fix: Frontend now sends proxyId in the test request body. The test endpoint
looks up the proxy from the DB with includeSecrets: true and uses the real
stored credentials for the SOCKS5 handshake.

Also: removed username/password from the frontend test payload since they
are always redacted and useless for testing.
2026-03-25 17:54:19 -03:00
diegosouzapw 39e9e4446b fix(usage): proxy fallback — retry without proxy when SOCKS5 relay fails
Root cause: SOCKS5 proxies accept TCP connections (pass health check) but
can't relay HTTPS traffic. getCodexUsage() catches fetch errors internally
and returns {message: 'Failed to fetch...'} instead of throwing, so the
previous catch-based fallback never triggered.

Fix: After the initial proxied fetch, check the returned usage object for
network error indicators. If a proxy was active and the result contains
'fetch failed' / 'ECONNREFUSED' / etc., retry the entire operation
(credential refresh + usage fetch) without proxy context.

This is safe because usage fetching is read-only — showing limits data
without proxy is better than showing nothing.
2026-03-25 17:20:25 -03:00
R.D. b32de54944 fix: use bg-surface for Provider Limits table to match Card components in light mode
bg-bg-subtle (#f0f0f5) appears gray against the page background in
light mode. Changed to bg-surface (#ffffff) for consistency with other
Card-based UI sections.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-25 12:46:28 -04:00
Diego Rodrigues de Sa e Souza 071b874e1b Merge pull request #624 from diegosouzapw/release/v3.0.6
Build Electron Desktop App / Validate version (push) Failing after 34s
Build Electron Desktop App / Build Electron (macos-arm64) (push) Has been skipped
Build Electron Desktop App / Build Electron (linux) (push) Has been skipped
Build Electron Desktop App / Build Electron (macos-intel) (push) Has been skipped
Build Electron Desktop App / Build Electron (windows) (push) Has been skipped
Build Electron Desktop App / Create Release (push) Has been skipped
Build Electron Desktop App / Publish to npm (push) Has been skipped
Release v3.0.6 — Proxy Context, Playground Selector, CI Fix
2026-03-25 13:11:18 -03:00
diegosouzapw 9ba65d3323 fix(release): v3.0.6 — proxy context, playground selector, CI fix
- Fix: Limits usage fetch wraps BOTH token refresh and usage call inside proxy context (fixes SOCKS5 Codex accounts)
- Fix: CI integration test v1/models gracefully handles empty models list
- Fix: Settings proxy test button results now render with priority over health data
- Feat: Playground account selector dropdown for testing specific connections
- Merge: PR #623 LongCat API base URL path correction
2026-03-25 13:08:44 -03:00
Diego Rodrigues de Sa e Souza 890a851bbf Merge pull request #623 from razllivan/fix/longcat-base-url
fix: Correct LongCat API base URL path
2026-03-25 12:59:36 -03:00
Diego Rodrigues de Sa e Souza 5f6ca23da4 Merge pull request #620 from diegosouzapw/release/v3.0.5
Build Electron Desktop App / Validate version (push) Failing after 40s
Build Electron Desktop App / Build Electron (macos-arm64) (push) Has been skipped
Build Electron Desktop App / Build Electron (linux) (push) Has been skipped
Build Electron Desktop App / Build Electron (macos-intel) (push) Has been skipped
Build Electron Desktop App / Build Electron (windows) (push) Has been skipped
Build Electron Desktop App / Create Release (push) Has been skipped
Build Electron Desktop App / Publish to npm (push) Has been skipped
chore(release): v3.0.5 — Tags Grouping UI and Triage
2026-03-25 12:14:20 -03:00
Ivan 58df1c06ee fix: correct LongCat API base URL path 2026-03-25 18:14:19 +03:00
diegosouzapw 95f8599dc2 chore(release): v3.0.5 2026-03-25 12:11:46 -03:00
diegosouzapw 8a11242d7f feat(ui): group limits dashboard connections by tag field to improve configuration visibility 2026-03-25 12:08:05 -03:00
Diego Rodrigues de Sa e Souza 948513ef5f Merge pull request #619 from diegosouzapw/release/v3.0.4
Build Electron Desktop App / Validate version (push) Failing after 27s
Build Electron Desktop App / Build Electron (macos-arm64) (push) Has been skipped
Build Electron Desktop App / Build Electron (linux) (push) Has been skipped
Build Electron Desktop App / Build Electron (macos-intel) (push) Has been skipped
Build Electron Desktop App / Build Electron (windows) (push) Has been skipped
Build Electron Desktop App / Create Release (push) Has been skipped
Build Electron Desktop App / Publish to npm (push) Has been skipped
chore(release): v3.0.4 — TextDecoder corruption fix and dashboard regression fixes
2026-03-25 11:35:22 -03:00
diegosouzapw c497a35d21 chore(release): v3.0.4 — TextDecoder corruption fix and dashboard regression fixes 2026-03-25 11:33:21 -03:00
diegosouzapw e0a539bc64 fix(dashboard): post-release UI and proxy connection regressions 2026-03-25 11:31:05 -03:00
Diego Rodrigues de Sa e Souza 44b8395ead Merge pull request #614 from hijak/fix/combo-sanitize-textdecoder-corruption
fix(combo): sanitize TransformStream TextDecoder state corruption
2026-03-25 11:28:37 -03:00
Diego Rodrigues de Sa e Souza 1bc8878490 Merge pull request #616 from diegosouzapw/release/v3.0.3
Build Electron Desktop App / Validate version (push) Failing after 36s
Build Electron Desktop App / Build Electron (macos-arm64) (push) Has been skipped
Build Electron Desktop App / Build Electron (linux) (push) Has been skipped
Build Electron Desktop App / Build Electron (macos-intel) (push) Has been skipped
Build Electron Desktop App / Build Electron (windows) (push) Has been skipped
Build Electron Desktop App / Create Release (push) Has been skipped
Build Electron Desktop App / Publish to npm (push) Has been skipped
chore(release): v3.0.3 — Target Fixes & Feature Rollup
2026-03-25 10:54:25 -03:00
diegosouzapw ded2ac493d chore(release): v3.0.3 — Bump timeouts, auto-sync models, and CLI tool detection 2026-03-25 10:52:32 -03:00
Diego Rodrigues de Sa e Souza 57b3319ac0 Merge pull request #597 from rdself/feat/auto-sync-models
feat: add per-provider auto-sync for model lists
2026-03-25 10:47:30 -03:00
Diego Rodrigues de Sa e Souza eba7ba25b8 Merge pull request #598 from razllivan/fix/cli-tools-detection
fix(cli): cross-platform CLI tool detection for custom npm prefixes
2026-03-25 10:47:27 -03:00
Diego Rodrigues de Sa e Souza df774892c8 Merge pull request #599 from rdself/fix/hide-unconfigured-comfyui-sdwebui
fix: hide comfyui/sdwebui models when no provider configured
2026-03-25 10:47:24 -03:00
Diego Rodrigues de Sa e Souza f3b4ce6b67 Merge pull request #601 from oSoWoSo/cz
Improve Czech translation
2026-03-25 10:47:21 -03:00
Diego Rodrigues de Sa e Souza bb8545b3e1 Merge pull request #603 from ardaaltinors/fix/streaming-tool-calls-in-logs
fix(stream): include tool_calls in streaming response call logs
2026-03-25 10:47:18 -03:00
Jack Cowey 600149fc2b fix(combo): guard against empty text in sanitize transform
Aligns transform logic with flush — skip enqueuing when decoded text
is empty. Addresses review feedback on PR #614.
2026-03-25 13:28:34 +00:00
Jack Cowey f4de3c8748 fix(combo): sanitize TransformStream TextDecoder state corruption
The sanitize TransformStream (commit 5a8c644) shared the same TextDecoder
instance with the upstream transform stream. This corrupted UTF-8 state
when decoding SSE chunks, producing garbled output that broke clients
like openclaw that parse the stream.

- Use a separate TextDecoder for the sanitize stream
- Always decode→encode in sanitize (don't mix raw passthrough with decoded text)
- Add flush() handler to emit remaining buffered bytes
- Fix double-escaped regex (\\n → \n) for tag stripping
2026-03-25 13:23:04 +00:00
Diego Rodrigues de Sa e Souza 6e7e04839f Merge pull request #610 from diegosouzapw/release/v3.0.2
Build Electron Desktop App / Validate version (push) Failing after 31s
Build Electron Desktop App / Build Electron (macos-arm64) (push) Has been skipped
Build Electron Desktop App / Build Electron (linux) (push) Has been skipped
Build Electron Desktop App / Build Electron (macos-intel) (push) Has been skipped
Build Electron Desktop App / Build Electron (windows) (push) Has been skipped
Build Electron Desktop App / Create Release (push) Has been skipped
Build Electron Desktop App / Publish to npm (push) Has been skipped
chore(release): v3.0.2 — Proxy UI fixes & Connection Tag Grouping
2026-03-25 09:08:24 -03:00
Diego Rodrigues de Sa e Souza f62dcc12a0 Merge pull request #608 from diegosouzapw/release/v3.0.1
Build Electron Desktop App / Validate version (push) Failing after 26s
Build Electron Desktop App / Build Electron (macos-arm64) (push) Has been skipped
Build Electron Desktop App / Build Electron (linux) (push) Has been skipped
Build Electron Desktop App / Build Electron (macos-intel) (push) Has been skipped
Build Electron Desktop App / Build Electron (windows) (push) Has been skipped
Build Electron Desktop App / Create Release (push) Has been skipped
Build Electron Desktop App / Publish to npm (push) Has been skipped
chore(release): v3.0.1 — hotfix for proxy_ prefix, LongCat validation, and MCP tool schemas
2026-03-25 09:07:27 -03:00
diegosouzapw bef591c2e6 chore(release): v3.0.2 — proxy ui fixes and connection tag grouping 2026-03-25 09:02:38 -03:00
diegosouzapw 5907296d36 fix: proxy UI bugs, connection tag grouping, and function_call prefix stripping
## Proxy UI Bug Fixes
- fix: proxy badge on connection cards now uses resolveProxyForConnection()
  per-connection (covers registry + config-file assignments)
- fix: Test Connection button now works in 'saved' proxy mode by resolving
  proxy config from savedProxies list
- fix: ProxyConfigModal now calls onClose() after save/clear (fixes UI freeze)
- fix: ProxyRegistryManager loads usage eagerly on mount with deduplication
  by scope+scopeId to prevent double-counting; adds per-row Test button

## Connection Tag Grouping (new feature)
- feat: add Tag/Group field to EditConnectionModal (stored in
  providerSpecificData.tag, no DB schema change)
- feat: connections list groups by tag with visual dividers when any account
  has a tag; untagged accounts appear first without header

## Post-merge fix from PR #607 review
- fix: function_call blocks in translateNonStreamingResponse now also strip
  Claude OAuth proxy_ prefix via toolNameMap (kilo-code-bot #607 warning)
  Affects OpenAI Responses API format path — tool_use was fixed in PR #607
  but function_call was missed
2026-03-25 08:54:46 -03:00
diegosouzapw aa2a7d12be chore(release): v3.0.1 — hotfix for proxy_ prefix, LongCat validation, and MCP tool schemas 2026-03-25 08:20:04 -03:00
Diego Rodrigues de Sa e Souza 33fee5dcc5 fix: strip proxy_ prefix in non-streaming Claude responses & fix LongCat validation (#605, #592) (#607)
- fix(translator): pass toolNameMap to translateNonStreamingResponse so Claude
  OAuth proxy_ prefix is correctly stripped from tool_use block names in
  non-streaming responses (was only stripped in streaming path)
- fix(validation): add LongCat specialty validator that probes /chat/completions
  directly, bypassing the /v1/models endpoint that LongCat does not expose (#592)

Co-authored-by: diegosouzapw <diegosouzapw@users.noreply.github.com>
2026-03-25 08:16:46 -03:00
Randi e9ae50be0c fix: improve Provider Limits light mode contrast and Claude plan tier display (#591)
- Replace hardcoded rgba(255,255,255,...) borders/backgrounds with theme-aware
  CSS variables (--color-border, --color-bg-subtle) for proper light mode contrast
- Add dark: variants for hover states and progress bar backgrounds
- Fix Claude plan tier: try to extract actual plan from OAuth response instead
  of hardcoding "Claude Code"
- Recognize provider names (Claude Code, Kimi Coding, Kiro) as non-plan-tier
  values in normalizePlanTier() to avoid showing them as tier badges

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-25 08:16:28 -03:00
Flo 5886c0fd5e docs(i18n): fix russian translation for playground and testbed (#589)
Co-authored-by: Vladimir Alabov <vladimir.alabov@bsc-ideas.com>
2026-03-25 08:15:59 -03:00
ardaaltinors 35538e6f77 refactor(stream): add ToolCall type, replace any, simplify ternary 2026-03-25 10:57:09 +03:00
ardaaltinors ea924f3bbf fix(stream): correct tool_calls delta keying and normalize shapes 2026-03-25 10:18:41 +03:00
zenobit 7bc15a2fc9 Improve Czech translation 2026-03-25 08:16:57 +01:00
ardaaltinors 2bf7db92ee fix: include tool_calls in streaming response call logs 2026-03-25 10:06:20 +03:00
Ivan 95260f56ba fix: address PR review comments
- Fix test to verify >=30 bytes detection
- Add fs.existsSync checks for /usr paths
2026-03-25 07:22:40 +03:00
Ivan c5ace0376a test(cli): add unit tests for CLI tool detection
Add 10 tests covering:
- CLI_TOOL_IDS completeness
- Size threshold (files < 30B rejected, >= 30B detected)
- Healthcheck (--version runnable, exit 1 not runnable)
- Unknown tool handling
- requiresBinary: false tools
- resolveOpencodeConfigPath cross-platform
2026-03-25 07:01:18 +03:00
Ivan 7ee09388fa fix(cli): cross-platform CLI tool detection
- Add dynamic npm prefix detection via getNpmGlobalPrefix()
- Supports custom prefixes (e.g., pnpm .npm-global)
- Add npm prefix to EXPECTED_PARENT_PATHS
- Rewrite getKnownToolPaths() for cross-platform support
  - Windows: checks dynamic npm prefix, APPDATA\npm, NVM
  - Linux/macOS: checks node bin dir, npm prefix, ~/.local/bin, ~/.opencode/bin
- Remove isWindows() gate - known paths checked on all platforms
- Lower size threshold from 1024 to 30 bytes (Linux JS wrappers ~44B)
- Add PATHEXT to healthcheck env for .cmd/.bat resolution
- Cache npm prefix to avoid duplicate execFileSync calls
- Deduplicate paths when npmPrefix equals APPDATA\npm
2026-03-25 07:01:18 +03:00
R.D. a15b0ef060 fix: hide comfyui/sdwebui models from /v1/models when no provider configured
Video and music models had a special exemption for authType="none" providers
(comfyui, sdwebui), causing them to appear in the models list even without
any active provider connection. Now all model types consistently use
isProviderActive() filtering, matching the behavior of image models.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-24 23:57:51 -04:00
R.D. 57cfd9a315 fix: show provider name and dash protocol in model-sync logs
Provider field shows connection name (e.g. "BltCy API"),
Protocol (sourceFormat) shows "-" since model-sync is not
a chat/completion request.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-24 21:49:32 -04:00
R.D. 5fb4149c32 fix: show dash instead of provider node ID in model-sync logs
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-24 21:42:27 -04:00
R.D. 03d97ba617 fix: show readable provider name in model-sync logs
Use connection.name instead of the raw provider node ID
(e.g. "BltCy API" instead of "openai-compatible-chat-09fdb807-...")
in call logs and scheduler console output.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-24 21:40:13 -04:00
R.D. 5205f5f4b4 fix: show auto-sync toggle for OpenAI/Anthropic compatible providers
The autoSyncToggle was defined after the isCompatible early return,
so it never rendered for compatible provider types. Move the toggle
definition before the isCompatible branch so it appears for all
provider types including third-party OpenAI-compatible ones.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-24 21:29:14 -04:00
R.D. 6eda0f4d00 feat: add per-provider auto-sync for model lists
- Add POST /api/providers/[id]/sync-models endpoint that fetches models
  from a provider's /models API and replaces the full custom models list,
  preserving per-model compatibility overrides
- Rewrite modelSyncScheduler to dynamically discover connections with
  autoSync enabled in providerSpecificData instead of a hardcoded list
- Add replaceCustomModels() to db/models.ts for full list replacement
  while preserving existing compat flags
- Log each model sync operation to call_logs for visibility in the
  Logs page
- Add Auto-Sync toggle button next to "Import from /models" in the
  provider detail page UI
- Add en/zh-CN i18n translations for auto-sync strings

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-24 21:16:09 -04:00
diegosouzapw 9e640cac6b chore: merge remaining 3.0.0-rc.17 commits into main (ProviderIcon, docs, provider counts)
Build Electron Desktop App / Validate version (push) Failing after 38s
Build Electron Desktop App / Build Electron (macos-arm64) (push) Has been skipped
Build Electron Desktop App / Build Electron (linux) (push) Has been skipped
Build Electron Desktop App / Build Electron (macos-intel) (push) Has been skipped
Build Electron Desktop App / Build Electron (windows) (push) Has been skipped
Build Electron Desktop App / Create Release (push) Has been skipped
Build Electron Desktop App / Publish to npm (push) Has been skipped
2026-03-24 18:46:43 -03:00
diegosouzapw 061521f87f docs: comprehensive v3.0.0 CHANGELOG + fix all version references
- Consolidated all 17 RC entries (rc.1 through rc.17) into single v3.0.0 entry
- 31 new providers, 9 major features, 40+ bug fixes, 19 community PRs
- Fixed llm.txt: version 2.0.13 → 3.0.0, provider count 36+ → 67+
- package.json: 3.0.0, openapi.yaml: 3.0.0
2026-03-24 18:42:39 -03:00
diegosouzapw b15eb278e1 chore: bump version to 3.0.0, update openapi.yaml and CHANGELOG 2026-03-24 18:38:35 -03:00
diegosouzapw 142ac8eb96 Merge PR #587: fix(sse): revert resolveDataDir import for Workers compat 2026-03-24 18:32:21 -03:00
diegosouzapw 88705bb6e9 docs: update provider count to 67+ across all documentation
- README.md: 44+ → 67+ (3 occurrences)
- llm.txt: 40+ → 67+ (2 occurrences)
- 21 i18n READMEs: 44+ → 67+
- 3 i18n READMEs (it/nl/phi): 36+ → 67+
- Actual count: FREE=4, OAUTH=8, APIKEY=55, TOTAL=67
2026-03-24 18:05:19 -03:00
k0valik 60d4fcfe7e update the comments
**1. `open-sse/transformer/responsesTransformer.ts`**
- Removed `import { resolveDataDir } from "../../src/lib/dataPaths"`
- Restored: `typeof process !== "undefined" ? process.cwd() : "."`
- Added history comment: `// previous: const baseDir = logsDir || resolveDataDir(); — reverted in #555 for Workers compat`

**2. `open-sse/config/credentialLoader.ts`**
- Updated JSDoc with `resolveDataDir()` description
- Added history: `previous: Priority: DATA_DIR env → ./data (project root)`
2026-03-24 21:40:08 +01:00
diegosouzapw 038d19ec98 docs: update llm.txt to v3.0.0, add embeddings+speech to docs page
- llm.txt: complete rewrite for v3.0.0-rc.17 (40+ providers, 9 strategies,
  MCP/A2A/ACP, ProviderIcon, auto-combo, 926 tests, CodeQL fixes)
- docs/page.tsx: add /v1/embeddings and /v1/audio/speech to API reference
- en.json: add i18n keys for new endpoint descriptions
2026-03-24 17:31:47 -03:00
k0valik e1b98768c7 fix(sse): revert resolveDataDir import in responsesTransformer for Workers compat 2026-03-24 21:29:08 +01:00
diegosouzapw b82af2b849 fix(ui): add ProviderIcon to agents page CLI tools + maxDuration for transcription
- Agents page: use ProviderIcon with 21-entry AGENT_ICON_MAP for CLI tool
  icons (claude→anthropic, codex→openai, gemini-cli→google, etc.)
- Transcription route: add maxDuration=300 for large audio/video uploads
- Combos: verified all 4 templates + 9 strategies present in UI
2026-03-24 17:21:25 -03:00
diegosouzapw 703591d76a fix(ui): use ProviderIcon component on dashboard home page
Replace Image-based provider icons in ProviderOverviewCard with the same
ProviderIcon component used on the providers page (@lobehub/icons SVG
with PNG → generic fallback chain).
2026-03-24 17:11:34 -03:00
diegosouzapw 7142688a77 fix(types): Zod 4 z.record 2-arg form + header type cast in openapi/try 2026-03-24 17:01:56 -03:00
diegosouzapw a12622b3d8 docs: update CHANGELOG, README, and sync i18n for v3.0.0-rc.17
- CHANGELOG.md: add rc.17 entry (CodeQL, route validation, omniModel tag, Docker)
- README.md: add 3 new rows to What's New table (CodeQL, validation, #585)
- docs/i18n: sync What's New v3.0.0 section to all 30 translated READMEs
  (replacing outdated v2.7.0/v2.0.9 sections)
2026-03-24 16:44:38 -03:00
diegosouzapw 9248ab4dfd fix(ci): route validation, CodeQL alerts, Docker workflow
- Add Zod schemas + validateBody() to 5 routes missing validation:
  model-combo-mappings (POST, PUT), webhooks (POST, PUT), openapi/try (POST)
- Fix 6 polynomial-redos CodeQL alerts in provider.ts and chatCore.ts
  by replacing (?:^|/) alternation patterns with segment-based matching
- Fix insecure-randomness in acp/manager.ts (crypto.randomUUID)
- Fix shell-command-injection in prepublish.mjs (JSON.stringify)
- Upgrade docker/setup-buildx-action from v3 to v4 (Node.js 20 deprecation)

CI check:route-validation:t06 PASS (176/176 routes validated)
Tests: 926/926 pass
2026-03-24 16:08:02 -03:00
diegosouzapw 5a8c6440f0 fix(combo): strip omniModel tags from outbound streaming responses (#585)
The <omniModel> tag was leaking into user-visible content when
context_cache_protection was enabled on a combo. The tag is an internal
marker for model pinning across conversation turns.

Fix: Add a second TransformStream pass (sanitize) that strips the tag
from SSE chunk content before delivery to the client. The tag is still
injected for round-trip context pinning but cleaned from visible output.

Also adds X-OmniRoute-Model response header as a cleaner metadata channel.

Closes #585
2026-03-24 15:49:26 -03:00
diegosouzapw 74b694a4dd chore: bump version to 3.0.0-rc.17 2026-03-24 15:24:46 -03:00
diegosouzapw 896b52d5fb Merge branch '3.0.0-rc.16' into main
RC16 Sprint:
- feat(media): 4GB transcription file limit with validation
- feat: configurable context length in model metadata (PR #578)
- feat: per-model upstream headers, compat PATCH (PR #575)
- feat: model name prefix stripping option (PR #582)
- fix(npm): link electron-release to npm-publish (PR #581)
- fix(routing): unprefixed claude models now resolve to anthropic (#570)
- 12 issues resolved, 4 PRs merged
2026-03-24 15:23:08 -03:00
diegosouzapw 1429fea27a fix(routing): unprefixed claude models now resolve to anthropic provider (#570)
Build Electron Desktop App / Validate version (push) Failing after 30s
Build Electron Desktop App / Build Electron (macos-arm64) (push) Has been skipped
Build Electron Desktop App / Build Electron (linux) (push) Has been skipped
Build Electron Desktop App / Build Electron (macos-intel) (push) Has been skipped
Build Electron Desktop App / Build Electron (windows) (push) Has been skipped
Build Electron Desktop App / Create Release (push) Has been skipped
Build Electron Desktop App / Publish to npm (push) Has been skipped
Changed the heuristic fallback for claude-* models from 'antigravity' to 'anthropic'
as the canonical provider. Users without Antigravity credentials were getting
'No credentials for provider: antigravity' errors when sending unprefixed
Claude model names like 'claude-sonnet-4-5'.

Closes #570
2026-03-24 14:11:13 -03:00
diegosouzapw 3218563f32 chore: merge PRs #581, #582 + local improvements for rc16
Merged PRs:
- #582 — model prefix stripping option (closes #568)
- #581 — npm publish workflow fix (refs #579)

Local changes:
- Restored stashed i18n, CLI tools, and maintenance banner updates
- 926 tests passing
2026-03-24 13:32:05 -03:00
diegosouzapw d412edbbe1 Merge PR #581: fix(npm) — link electron-release to npm-publish via workflow_call (by @jay77721, refs #579) 2026-03-24 13:28:25 -03:00
diegosouzapw 968159a85d Merge PR #582: feat(proxy) — add model name prefix stripping option (by @jay77721, closes #568) 2026-03-24 13:27:59 -03:00
jay77721 18a3741fc2 feat(proxy): add model name prefix stripping option (#568)
Add stripModelPrefix boolean setting that, when enabled, strips
provider prefixes (e.g. openai/, anthropic/) from incoming model
names and re-resolves the bare model name using existing heuristics.

This allows tools to send prefixed model names while OmniRoute
handles provider routing at the proxy layer.

- Add stripModelPrefix to settings validation schema (Zod)
- Check setting in getModelInfo() after custom node matching fails
- Falls through to normal resolution on error or when disabled
- Backward compatible: opt-in, default behavior unchanged
2026-03-24 21:52:43 +08:00
jay77721 f1be3e6bb0 fix(npm): link electron-release to npm-publish via workflow_call
- Add workflow_call trigger to npm-publish.yml for direct cross-workflow invocation
- Add publish-npm job to electron-release.yml that calls npm-publish after release
- Add dist-tag support: prerelease versions auto-get 'next' tag, stable gets 'latest'
- Add v-prefix stripping for robust version handling
- Fixes issue where GitHub releases created by bots don't reliably trigger npm-publish
- Refs #579
2026-03-24 21:52:34 +08:00
diegosouzapw b717a02394 chore: remove PR documentation and unnecessary markdown files 2026-03-24 10:33:25 -03:00
diegosouzapw d68143e63d Merge PR #575: feat(dashboard,sse,api) — per-model upstream headers, compat PATCH, chat alignment (by @zhangqiang8vip) 2026-03-24 09:46:59 -03:00
diegosouzapw 0d306b8b1c Merge PR #578: feat — add configurable context length to model metadata (by @hijak) 2026-03-24 09:46:32 -03:00
diegosouzapw a655863855 feat(media): increase transcription file limit to 4GB with validation
- Added MAX_TRANSCRIPTION_FILE_SIZE constant (4GB)
- Added formatFileSize() helper for human-readable display (KB/MB/GB)
- Frontend validation rejects files > 4GB with error message
- Changed label from 'Audio File' to 'Audio / Video File'
- Shows 'Supports audio and video files up to 4 GB' hint
2026-03-24 09:42:36 -03:00
Jack Cowey 58264c80dd feat: add configurable context length to model metadata
- Add contextLength field to RegistryModel interface for per-model overrides
- Add defaultContextLength to RegistryEntry for provider-level defaults
- Set context lengths for major providers:
  - Claude: 200k
  - Codex: 400k (fixes combo context display)
  - Gemini: 1M
  - OpenAI: 128k
  - GitHub Copilot: 128k
  - Kiro/Cursor: 200k
  - OpenCode: 200k
- Include context_length in /v1/models API response
- Add context_length field to combo schema for custom combo context
- Update contextManager to use registry defaults and support env overrides
  - CONTEXT_LENGTH_<PROVIDER> for per-provider override
  - CONTEXT_LENGTH_DEFAULT for global override

This allows clients like OpenClaw to display accurate context windows
for combo models instead of guessing based on model name patterns.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-24 12:29:34 +00:00
diegosouzapw 6f9f1aec65 chore(release): v3.0.0-rc.15 — CHANGELOG + openapi version sync
Build Electron Desktop App / Validate version (push) Failing after 32s
Build Electron Desktop App / Build Electron (macos-arm64) (push) Has been skipped
Build Electron Desktop App / Build Electron (linux) (push) Has been skipped
Build Electron Desktop App / Build Electron (macos-intel) (push) Has been skipped
Build Electron Desktop App / Build Electron (windows) (push) Has been skipped
Build Electron Desktop App / Create Release (push) Has been skipped
Updated CHANGELOG with sprint results:
- i18n: 2,788 keys synced across 30 languages
- 16 provider icons + SVG fallback in ProviderIcon
- Agents fingerprint synced (14 providers)
- dompurify XSS vulnerability fixed (0 npm vulns)
- openapi.yaml version synced
2026-03-24 09:22:02 -03:00
diegosouzapw 97b1ee5b02 fix: sync CLI agents fingerprinting + fix dompurify XSS vulnerability
- Agents page: Added droid, openclaw, copilot, opencode to fingerprinting list
  (synced with CLI Tools — now 14 providers total)
- Fixed dompurify XSS vulnerability (GHSA-v2wj-7wpq-c8vv) via npm overrides
  forcing dompurify ^3.3.2 across all transitive deps (monaco-editor)
- npm audit now reports 0 vulnerabilities
2026-03-24 08:14:24 -03:00
diegosouzapw fe033cd0b3 fix: add SVG fallback to ProviderIcon component
ProviderIcon now tries: Lobehub → PNG → SVG → GenericIcon.
This resolves 11 providers that only have SVG icons
(comfyui, sdwebui, vertex, cartesia, zai, synthetic,
opencode-go/zen, puter, apikey, oauth).
2026-03-24 07:52:07 -03:00
diegosouzapw afbd07c62a fix: sync i18n keys across 30 languages + add 16 missing provider icons
Task 01 - i18n:
- Synced 2,788 missing keys across 30 language files (all now at 100%)
- Added 6 new agents namespace keys for OpenCode Integration
- i18n-ified agents page OpenCode section (was hardcoded English)
- Added scanning progress text during agents page loading

Task 02 - Provider Icons:
- Added 16 missing provider icons:
  - 3 copied from existing (alibaba, kimi-coding-apikey, bailian-coding-plan)
  - 2 downloaded (huggingface, deepgram)
  - 11 created as SVG (comfyui, sdwebui, vertex, cartesia, zai,
    synthetic, opencode-go/zen, puter, apikey, oauth)
- Total: 86 icon files covering all 69 providers
2026-03-24 07:34:07 -03:00
diegosouzapw 9b15996545 fix: prevent login lockout when skipping wizard password setup (#574)
When users skip password setup during onboarding (either via 'Skip Password'
checkbox or 'Skip Wizard' button), the app now explicitly sets requireLogin=false.

Previously, requireLogin defaulted to true with no password hash stored,
leaving users permanently stuck on the login page.

Two code paths fixed in onboarding/page.tsx:
- handleSetPassword() with skipSecurity=true
- handleFinish() when no password was configured
2026-03-24 07:06:54 -03:00
zhang-qiang 1dbbd7241d fix(mcp-server): type list-models locals for typecheck:core
Annotate rawModels as unknown[] and warning as string | undefined (avoid never[] / undefined-only inference)

Made-with: Cursor
2026-03-24 17:50:13 +08:00
zhang-qiang 6c0ef48d45 docs(zws_docs): archive PR memory and CI notes in README
Upstream PR context: #575, T06/T11/keytar, commit hygiene, links to V8 and PR draft

Made-with: Cursor
2026-03-24 17:45:34 +08:00
zhang-qiang 8b57f88ca3 fix(open-sse): satisfy T11 explicit-any budget (regex counts word any)
- Reword comments that contained the token any; replace any types with typed shapes

- stream.ts: passthrough tool-call flag via local boolean (state is null in passthrough)

- Document T11 in zws_docs/ZWS_README_V8.md

Made-with: Cursor
2026-03-24 17:42:52 +08:00
zhang-qiang 3e9fdc777e fix(api,zed): T06 validateBody on JSON routes; lazy-load keytar for CI build
- Add validateBody() alongside request.json() on 5 routes (t06:route-validation)

- Dynamic import keytar in zed keychain-reader to avoid libsecret/keytar load during next build

- Document in zws_docs/ZWS_README_V8.md section 9

Made-with: Cursor
2026-03-24 17:36:55 +08:00
zhang-qiang a8ca88797a feat(dashboard,sse,api): per-model upstream headers, compat PATCH, chat alignment
- Store/sanitize upstreamHeaders; shared forbidden header names (upstreamHeaders.ts)

- chatCore: buildUpstreamHeadersForExecute; T5 recomputes; 401 retry uses translatedBody.model

- Dashboard compat popover + i18n; Zod partialRecord + header value newline guard

- Executors merge upstreamExtraHeaders; sanitize unit tests

- Dev: bootstrap env in run-next, instrumentation-node import, credentialLoader dedupe

Made-with: Cursor
2026-03-24 17:24:11 +08:00
zhang-qiang 71540b5dc0 merge: sync upstream/main (diegosouzapw/OmniRoute) 2026-03-24 13:01:08 +08:00
diegosouzapw b5a145d7b3 Merge branch 'pr-565' into 3.0.0-rc.14
Build Electron Desktop App / Validate version (push) Failing after 30s
Build Electron Desktop App / Build Electron (macos-arm64) (push) Has been skipped
Build Electron Desktop App / Build Electron (linux) (push) Has been skipped
Build Electron Desktop App / Build Electron (macos-intel) (push) Has been skipped
Build Electron Desktop App / Build Electron (windows) (push) Has been skipped
Build Electron Desktop App / Create Release (push) Has been skipped
# Conflicts:
#	docs/i18n/cs/API_REFERENCE.md
#	docs/i18n/cs/CODEBASE_DOCUMENTATION.md
#	docs/i18n/cs/README.md
#	src/i18n/messages/cs.json
2026-03-24 00:19:01 -03:00
diegosouzapw 21d6a0a2dd fix: replace custom YAML parser with js-yaml for correct OpenAPI spec parsing 2026-03-23 22:18:04 -03:00
diegosouzapw 80cc7340ac feat: API Endpoints dashboard — interactive catalog, webhooks, OpenAPI viewer
Phase 1: Interactive REST API Catalog
- GET /api/openapi/spec: serves parsed openapi.yaml as JSON catalog
- POST /api/openapi/try: Try It proxy for inline endpoint testing
- Endpoint catalog with tag grouping, search, method badges
- Expand: schemas, auth, curl examples, Try It panel

Phase 2: OpenAPI Spec Viewer
- Spec info header with version, download YAML/JSON, schema browser

Phase 3: Webhooks & Event Subscriptions
- Migration 011: webhooks table
- src/lib/db/webhooks.ts: CRUD + delivery tracking + auto-disable
- src/lib/webhookDispatcher.ts: HMAC-SHA256, retries
- API: CRUD /api/webhooks + test delivery
- Dashboard: add/edit/toggle/test/delete webhook UI

923 tests pass, tsc clean
2026-03-23 22:07:10 -03:00
diegosouzapw 45b272ee2f chore: bump version to 3.0.0-rc.15
- CHANGELOG: add rc.14 (PRs #562, #561) and rc.15 (#563 per-model combo routing)
- package.json: 3.0.0-rc.13 → 3.0.0-rc.15
- openapi.yaml: version sync to 3.0.0-rc.15
2026-03-23 21:05:44 -03:00
zenobit f765664580 Update docs/i18n/cs/CLI-TOOLS.md
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
2026-03-24 00:47:41 +01:00
zenobit 10b44f036d Update docs/i18n/cs/USER_GUIDE.md
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
2026-03-24 00:47:25 +01:00
zenobit 1bf4ee3a3c Update docs/i18n/cs/CODEBASE_DOCUMENTATION.md
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
2026-03-24 00:46:58 +01:00
zenobit 5d82ffa503 fix(i18n): Improve Czech translation and variables 2026-03-24 00:43:47 +01:00
diegosouzapw 5dc3fd2ec0 feat: per-model combo routing support (#563)
Add model-pattern → combo mapping feature that automatically routes requests
to specific combos based on model name patterns (glob matching).

Implementation:
- New migration 010: model_combo_mappings table with pattern, combo_id, priority
- DB module with CRUD + resolveComboForModel() using glob-to-regex matching
- getComboForModel() in model.ts: augments getCombo() with pattern fallback
- chat.ts: replaced getCombo() → getComboForModel() at routing decision point
- API endpoints: GET/POST /api/model-combo-mappings, GET/PUT/DELETE by [id]
- ModelRoutingSection.tsx: dashboard UI with inline add/edit/toggle/delete
- Integrated into Combos page
- 15 new unit tests (glob matching, priority ordering, disabled filtering)
- Full test suite: 923/923 pass

Examples:
  claude-sonnet* → code-combo
  claude-*-opus* → frontier-combo
  gpt-4o*       → openai-combo
  gemini-*      → google-combo

Resolves: #563
2026-03-23 20:36:00 -03:00
diegosouzapw 4562fdda92 fix(i18n): improve Czech translation — correct HTTP methods and documentation text
Squash-merge from PR #561 by @zen0bit:
- Replace machine-translated HTTP method names (ZÍSKAT→GET, ZVEŘEJNIT→POST, VLOŽIT→PUT, SMAZAT→DELETE)
- Fix Czech documentation text in API_REFERENCE.md and CODEBASE_DOCUMENTATION.md
- Clean up cs.json translation entries

PR: #561
2026-03-23 19:55:42 -03:00
diegosouzapw 18258b9b0d fix: merge PR #562 — MCP session management, Claude passthrough, OAuth modal, detectFormat fixes
Cherry-pick from codex/omniroute-fixes-20260324:
- Replace MCP singleton transport with per-session architecture for Streamable HTTP
- Fix Claude passthrough via OpenAI round-trip normalization
- Add detectFormatFromEndpoint() for endpoint-aware format detection
- Support raw code#state in OAuth modal for Claude Code remote auth
- Expose cloudConfigured/cloudUrl/machineId in settings API
- Switch docker-compose.prod.yml target to runner-cli
- Add 3 new tests for round-trip and detectFormat

PR: #562
2026-03-23 19:53:02 -03:00
diegosouzapw 92e0f242c7 fix(build): resolve all TypeScript compilation errors and Next.js 15 dynamic route slug conflicts
- Fix Next.js 15 async params in 4 API route handlers (accounts, providers, registered-keys)
- Move providers/[id]/limits → providers/[provider]/limits to resolve slug name conflict
- Add keytar to serverExternalPackages and KNOWN_EXTERNALS in next.config.mjs
- Fix Zod z.record() arity across a2a.ts and issues/report/route.ts
- Fix SearchResponse interface (optional answer property) in SearchTools and ResultsPanel
- Fix ProviderLimits implicit any types in index.tsx and utils.tsx
- Fix better-sqlite3 prepare<T> generic usage in secrets.ts
- Remove duplicate pricing keys (gemini-3-flash-preview)
- Cast analytics result, ApiErrorType import, TaskRoutingConfig type
- Remove rogue app/ duplicate directory from project root

Resolves: #560
2026-03-23 18:23:08 -03:00
diegosouzapw 428fa9404c Merge branch 'main' into 3.0.0-rc 2026-03-23 17:10:35 -03:00
diegosouzapw 3cccc480fb feat: add update notification banner to dashboard homepage (resolves #552) 2026-03-23 16:00:03 -03:00
diegosouzapw acb94216c8 fix(providers): secure Zed import route and add dashboard UI component 2026-03-23 15:58:18 -03:00
Abhinav 5fa97841b2 fix: Address all 4 bot review warnings
- FIX #1: Add null check for cred.password (prevent undefined access)
- FIX #2: Prioritize actual credentials over hardcoded account patterns
- FIX #3: Convert CommonJS require() to ES imports for consistency
- FIX #4: Move to App Router, add credential metadata response, document maintainer integration

Additional improvements:
- Better TypeScript error typing with optional chaining
- Improved error messages for missing dependencies
- Added maintainer TODO for provider system integration
- Proper Next.js App Router format (route.ts)

All bot warnings resolved. Ready for maintainer review.
2026-03-23 15:58:18 -03:00
Abhinav 4ad66bf7b9 feat: Add Zed IDE OAuth credential import support
- Implement keychain-based credential extractor for Zed IDE
- Support macOS (Keychain), Windows (Credential Manager), Linux (libsecret)
- Add API endpoint: POST /api/providers/zed/import
- Auto-discover OAuth tokens for OpenAI, Anthropic, Google, Mistral, xAI, etc.
- Cross-platform support via keytar library
- Complete documentation with security considerations

Closes community request from OmniRoute Telegram group.
Follows proven pattern used by VS Code, GitHub Copilot CLI, Claude Code.
2026-03-23 15:58:18 -03:00
Diego Rodrigues de Sa e Souza 64860ed5e5 Merge pull request #557 from diegosouzapw/dependabot/npm_and_yarn/production-834ce0f99d
deps: bump the production group with 4 updates
2026-03-23 15:47:48 -03:00
dependabot[bot] b17faf6e1e deps: bump the production group with 4 updates
Bumps the production group with 4 updates: [jose](https://github.com/panva/jose), [next](https://github.com/vercel/next.js), [undici](https://github.com/nodejs/undici) and [wreq-js](https://github.com/sqdshguy/wreq-js).


Updates `jose` from 6.2.1 to 6.2.2
- [Release notes](https://github.com/panva/jose/releases)
- [Changelog](https://github.com/panva/jose/blob/main/CHANGELOG.md)
- [Commits](https://github.com/panva/jose/compare/v6.2.1...v6.2.2)

Updates `next` from 16.1.7 to 16.2.1
- [Release notes](https://github.com/vercel/next.js/releases)
- [Changelog](https://github.com/vercel/next.js/blob/canary/release.js)
- [Commits](https://github.com/vercel/next.js/compare/v16.1.7...v16.2.1)

Updates `undici` from 7.24.4 to 7.24.5
- [Release notes](https://github.com/nodejs/undici/releases)
- [Commits](https://github.com/nodejs/undici/compare/v7.24.4...v7.24.5)

Updates `wreq-js` from 2.2.0 to 2.2.2
- [Release notes](https://github.com/sqdshguy/wreq-js/releases)
- [Commits](https://github.com/sqdshguy/wreq-js/compare/v2.2.0...v2.2.2)

---
updated-dependencies:
- dependency-name: jose
  dependency-version: 6.2.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: production
- dependency-name: next
  dependency-version: 16.2.1
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: production
- dependency-name: undici
  dependency-version: 7.24.5
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: production
- dependency-name: wreq-js
  dependency-version: 2.2.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: production
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-03-23 18:45:59 +00:00
diegosouzapw 0ea73bd527 chore(release): bump version to 3.0.0-rc.13
Build Electron Desktop App / Validate version (push) Failing after 28s
Build Electron Desktop App / Build Electron (macos-arm64) (push) Has been skipped
Build Electron Desktop App / Build Electron (linux) (push) Has been skipped
Build Electron Desktop App / Build Electron (macos-intel) (push) Has been skipped
Build Electron Desktop App / Build Electron (windows) (push) Has been skipped
Build Electron Desktop App / Create Release (push) Has been skipped
2026-03-23 15:39:11 -03:00
diegosouzapw b2f0820560 fix(#549): resolve real API key from keyId in codex/droid/kilo settings
CLI settings routes (codex-settings, droid-settings, kilo-settings) were
writing the masked API key string directly to config files when the
dashboard sent a keyId. Now resolves the real key from the database via
getApiKeyById() before writing, matching the pattern already implemented
in claude-settings, openclaw-settings, and cline-settings.

Closes #549
2026-03-23 15:31:34 -03:00
diegosouzapw 7ad5d42982 release: v3.0.0-rc.12 — merge PRs #542, #544, #546, #555 + TDZ fix + build fixes
Build Electron Desktop App / Validate version (push) Failing after 29s
Build Electron Desktop App / Build Electron (macos-arm64) (push) Has been skipped
Build Electron Desktop App / Build Electron (linux) (push) Has been skipped
Build Electron Desktop App / Build Electron (macos-intel) (push) Has been skipped
Build Electron Desktop App / Build Electron (windows) (push) Has been skipped
Build Electron Desktop App / Create Release (push) Has been skipped
Community PRs:
- #546: fix(cli): --version returning unknown on Windows
- #555: fix(sse): centralized resolveDataDir() for path resolution
- #544: fix(cli): secure CLI tool detection via known installation paths
- #542: fix(ui): light mode contrast — missing CSS theme variables

Additional:
- Fix TDZ error in cliRuntime.ts (validateEnvPath before getExpectedParentPaths)
- Add pino/pino-pretty to serverExternalPackages for build stability
- 905 tests passing
2026-03-23 15:11:18 -03:00
diegosouzapw 3912734498 fix: cherry-pick PR #542 (light mode contrast) + fix TDZ in cliRuntime.ts
- Add missing CSS theme variables (bg-primary, bg-subtle, text-primary)
- Fix hardcoded dark-mode-only colors with proper dark: variants
- Fix ReferenceError: move validateEnvPath before getExpectedParentPaths
2026-03-23 15:10:19 -03:00
k0valik 0fa3f9a057 fix: (cli) secure CLI tool detection via known installation paths (Win… (#544)
fix(cli): secure CLI tool detection via known installation paths with security hardening — symlink validation, file-type checks, size bounds, minimal env in healthcheck for 8 CLI tools
2026-03-23 15:04:14 -03:00
k0valik 0fbabdcf25 fix(sse): use centralized resolveDataDir() for path resolution (#555)
fix(sse): use centralized resolveDataDir() for path resolution in credentialLoader, autoCombo persistence, responsesTransformer, and requestLogger
2026-03-23 15:04:03 -03:00
k0valik 67b7ae98a6 fix(cli): resolve --version returning 'unknown' on Windows (#546)
fix(cli): resolve --version returning 'unknown' on Windows by using JSON.parse(readFileSync) instead of ESM import with { type: 'json' }
2026-03-23 15:03:51 -03:00
diegosouzapw 0f703c95dd fix(build): add pino and pino-pretty to serverExternalPackages 2026-03-23 11:19:53 -03:00
diegosouzapw c34b3f41bd feat: Add requested model to logs, enhance background task detection, and introduce AI SDK compatibility utilities.
Build Electron Desktop App / Validate version (push) Failing after 38s
Build Electron Desktop App / Build Electron (macos-arm64) (push) Has been skipped
Build Electron Desktop App / Build Electron (linux) (push) Has been skipped
Build Electron Desktop App / Build Electron (macos-intel) (push) Has been skipped
Build Electron Desktop App / Build Electron (windows) (push) Has been skipped
Build Electron Desktop App / Create Release (push) Has been skipped
2026-03-23 11:08:14 -03:00
diegosouzapw e003b17280 fix(build): add webpack IgnorePlugin for thread-stream test files; exclude compiled app/ dir from git
- thread-stream test fixtures (intentionally malformed) were being picked
  up by Turbopack during production build, causing 111 compile errors
- IgnorePlugin excludes /test/ within thread-stream context
- thread-stream added to serverExternalPackages to prevent bundling
- /app removed: it is a stale npm-package prebuild artifact, not source code
2026-03-23 09:50:21 -03:00
diegosouzapw e003d58c60 fix(types): cast providerSpecificData.validationModelId to string in EditConnectionModal 2026-03-23 09:23:34 -03:00
diegosouzapw 0546d06c0a fix(types): cast extracted usage to Record<string,number> in stream.ts to resolve TS property errors
Build Electron Desktop App / Validate version (push) Failing after 32s
Build Electron Desktop App / Build Electron (macos-arm64) (push) Has been skipped
Build Electron Desktop App / Build Electron (linux) (push) Has been skipped
Build Electron Desktop App / Build Electron (macos-intel) (push) Has been skipped
Build Electron Desktop App / Build Electron (windows) (push) Has been skipped
Build Electron Desktop App / Create Release (push) Has been skipped
Also fix syntax error in openai-to-claude-strip-empty.test.mjs (tool/assistant messages were incorrectly nested)
2026-03-23 09:21:03 -03:00
diegosouzapw 5337111990 chore(release): bump version to 3.0.0-rc.10
Build Electron Desktop App / Validate version (push) Failing after 35s
Build Electron Desktop App / Build Electron (macos-arm64) (push) Has been skipped
Build Electron Desktop App / Build Electron (linux) (push) Has been skipped
Build Electron Desktop App / Build Electron (macos-intel) (push) Has been skipped
Build Electron Desktop App / Build Electron (windows) (push) Has been skipped
Build Electron Desktop App / Create Release (push) Has been skipped
2026-03-23 08:35:43 -03:00
diegosouzapw bb06f8eb0c fix(deps): downgrade Next.js to 16.0.10 to fix turbopack hashing regression
Build Electron Desktop App / Validate version (push) Failing after 37s
Build Electron Desktop App / Build Electron (macos-arm64) (push) Has been skipped
Build Electron Desktop App / Build Electron (linux) (push) Has been skipped
Build Electron Desktop App / Build Electron (macos-intel) (push) Has been skipped
Build Electron Desktop App / Build Electron (windows) (push) Has been skipped
Build Electron Desktop App / Create Release (push) Has been skipped
Closes #509, #508

Docs: added rc.8 and rc.9 sprint summary to CHANGELOG.md
2026-03-23 08:20:54 -03:00
zhang-qiang 23e3a1c269 docs: move ZWS_README_V4/V5 into zws_docs/
Made-with: Cursor
2026-03-23 14:04:11 +08:00
diegosouzapw e47740e02e feat: sub2api T05/T08/T09/T13/T14 + bump to 3.0.0-rc.7
Build Electron Desktop App / Validate version (push) Failing after 34s
Build Electron Desktop App / Build Electron (macos-arm64) (push) Has been skipped
Build Electron Desktop App / Build Electron (linux) (push) Has been skipped
Build Electron Desktop App / Build Electron (macos-intel) (push) Has been skipped
Build Electron Desktop App / Build Electron (windows) (push) Has been skipped
Build Electron Desktop App / Create Release (push) Has been skipped
2026-03-22 23:17:52 -03:00
diegosouzapw d9ff0035f5 chore: bump version to 3.0.0-rc.6 (sub2api gap tasks T01-T15)
Build Electron Desktop App / Validate version (push) Failing after 29s
Build Electron Desktop App / Build Electron (macos-arm64) (push) Has been skipped
Build Electron Desktop App / Build Electron (linux) (push) Has been skipped
Build Electron Desktop App / Build Electron (macos-intel) (push) Has been skipped
Build Electron Desktop App / Build Electron (windows) (push) Has been skipped
Build Electron Desktop App / Create Release (push) Has been skipped
2026-03-22 21:01:33 -03:00
diegosouzapw 7a7f3be0d2 feat(sub2api): implement T01-T15 gap analysis tasks (3.0.0-rc.6)
T01 (P1): requested_model column in call_logs
- Migration 009_requested_model.sql: ALTER TABLE call_logs ADD COLUMN requested_model
- callLogs.ts: INSERT + SELECT updated to include requestedModel field

T02 (P1): Strip empty text blocks from nested tool_result.content
- New stripEmptyTextBlocks() recursive helper in openai-to-claude.ts
- Applied on tool_result content before forwarding to Anthropic
- Prevents 400 'text content blocks must be non-empty' errors

T03 (P1): Parse x-codex-5h-*/x-codex-7d-* headers for precise quota reset
- parseCodexQuotaHeaders() in codex.ts extracts usage/limit/resetAt
- getCodexResetTime() returns furthest-out reset timestamp for safe unblocking

T04 (P1): X-Session-Id header for external sticky routing
- extractExternalSessionId() in sessionManager.ts reads x-session-id,
  x-omniroute-session, session-id headers with 'ext:' prefix to avoid collisions

T06 (P2): account_deactivated permanent expired status on 401
- ACCOUNT_DEACTIVATED_SIGNALS constant + isAccountDeactivated() in accountFallback.ts
- Returns 1-year cooldown (effectively permanent) to prevent retrying dead accounts

T07 (P2): X-Forwarded-For IP validation
- New src/lib/ipUtils.ts with extractClientIp() and getClientIpFromRequest()
- Skips 'unknown'/non-IP entries in X-Forwarded-For chain

T10 (P2): credits_exhausted distinct account status
- CREDITS_EXHAUSTED_SIGNALS + isCreditsExhausted() in accountFallback.ts
- Returns 1h cooldown with creditsExhausted flag, distinct from rate_limit 429

T11 (P1): max reasoning_effort -> budget_tokens: 131072
- EFFORT_BUDGETS and THINKING_LEVEL_MAP updated with max: 131072, xhigh: 131072
- Reverse mapping now returns 'max' for full-budget responses
- Unit test updated to expect 'max' (was 'high')

T12 (P3): Model pricing updates
- MiniMax M2.7 / MiniMax-M2.7 / minimax-m2.7-highspeed pricing added

T15 (P1): Array content normalization for system/tool messages
- normalizeContentToString() helper exported from openai-to-claude.ts
- System messages with array content now correctly collapsed to string
2026-03-22 20:55:35 -03:00
diegosouzapw 91e45fbe95 chore: remover new-features-sub21 do tracking do git
Remover as exceções !docs/new-features-sub21/ do .gitignore para que
a pasta de tasks internas não seja mais rastreada pelo git.
2026-03-22 20:32:17 -03:00
diegosouzapw 7d7e9da28c feat(providers): adicionar provedor Puter AI com 500+ modelos
Registrar o provedor Puter como gateway OpenAI-compatible que expõe
modelos de múltiplos fornecedores (GPT, Claude, Gemini, Grok, DeepSeek,
Qwen, Mistral, Llama) através de um único endpoint REST.

- Criar PuterExecutor com autenticação Bearer token
- Adicionar entrada no providerRegistry com 40+ modelos curados
- Habilitar passthroughModels para acesso aos 500+ modelos do catálogo
- Registrar alias "pu" para acesso rápido
- Adicionar metadados do provedor em shared/constants/providers.ts
2026-03-22 20:29:06 -03:00
diegosouzapw 24a9739604 docs: add sub2api gap analysis + 15 implementation tasks
Add competitive analysis of sub2api (v0.1.104, 87 contributors)
comparing features, open PRs, and model pricing against OmniRoute.

Files:
- docs/new-features-sub21/gap-analysis.md — full analysis (commits + 38 open PRs)
- docs/new-features-sub21/implementation-plan.md — phased plan for all 15 gaps
- docs/new-features-sub21/tasks/T01-T15 — detailed task files with:
  - Problem description + sub2api PR references
  - Step-by-step implementation with code snippets
  - Affected files list
  - Acceptance criteria

Priority breakdown:
  P1 (4): requested_model logs, empty tool_result blocks, x-codex-* headers, X-Session-Id
  P2 (6): rate-limit persistence, account_deactivated, XFF validation, session limits, Codex/Spark scopes, credits_exhausted
  P3 (5): max reasoning effort, model pricing, stale quota display, proxy fast-fail, array content

Source: https://github.com/Wei-Shaw/sub2api
2026-03-22 18:12:50 -03:00
diegosouzapw 4fb9687782 docs(3.0.0-rc.5): comprehensive CHANGELOG and README vs v2.9.5
Build Electron Desktop App / Validate version (push) Failing after 31s
Build Electron Desktop App / Build Electron (macos-arm64) (push) Has been skipped
Build Electron Desktop App / Build Electron (linux) (push) Has been skipped
Build Electron Desktop App / Build Electron (macos-intel) (push) Has been skipped
Build Electron Desktop App / Build Electron (windows) (push) Has been skipped
Build Electron Desktop App / Create Release (push) Has been skipped
- CHANGELOG: [3.0.0-rc.5] section now serves as full 'What's New vs v2.9.5':
  * 2 new providers (OpenCode Zen/Go via PR #530)
  * 3 new features: Registered Keys API (#464), provider icons (#529), model auto-sync (#488)
  * 10 bug fixes (#521, #522, #524, #527, #532, #535, #536, #537, #489, #510, #492)
  * 16 issues resolved total, DB migration 008
- README: added 'What's New in v3.0.0' table section after badges
2026-03-22 15:51:54 -03:00
diegosouzapw 95ffc21b60 feat(3.0.0-rc.5): Registered Keys Provisioning API (#464)
Complete implementation of auto-provisioning API:
- DB migration 008: registered_keys, provider_key_limits, account_key_limits
- src/lib/db/registeredKeys.ts: full quota enforcement, idempotency, sha256
  hashing, budget tracking, window auto-reset
- POST /api/v1/registered-keys — issue with quota check
- GET /api/v1/registered-keys — list (masked)
- GET|DELETE /api/v1/registered-keys/[id] — get/revoke
- POST /api/v1/registered-keys/[id]/revoke — explicit revoke
- GET /api/v1/quotas/check — pre-validate without issuing
- GET|PUT /api/v1/providers/[id]/limits — provider limits CRUD
- GET|PUT /api/v1/accounts/[id]/limits — account limits CRUD
- POST /api/v1/issues/report — optional GitHub issue reporting
  (requires GITHUB_ISSUES_REPO + GITHUB_ISSUES_TOKEN env vars)
- Exported all from localDb.ts
2026-03-22 15:33:45 -03:00
diegosouzapw f3c5e55b26 feat(3.0.0-rc.4): merge PR #530 — OpenCode Zen and Go providers
Build Electron Desktop App / Validate version (push) Failing after 39s
Build Electron Desktop App / Build Electron (macos-arm64) (push) Has been skipped
Build Electron Desktop App / Build Electron (linux) (push) Has been skipped
Build Electron Desktop App / Build Electron (macos-intel) (push) Has been skipped
Build Electron Desktop App / Build Electron (windows) (push) Has been skipped
Build Electron Desktop App / Create Release (push) Has been skipped
Includes all commits from @kang-heewon's PR #530:
- OpencodeExecutor with multi-format routing
- opencode-zen + opencode-go registered in provider registry
- UI metadata added to providers.ts
- Unit tests for OpencodeExecutor (improved to avoid state coupling)

Cherry-picked from add-opencode-providers into 3.0.0-rc.
Conflicts resolved: executors/index.ts (merged pollinations+cloudflare-ai),
providerRegistry.ts (kept testKeyBaseUrl from rc.2 + PR's authType/models).
2026-03-22 15:23:00 -03:00
kang-heewon 40183c6a5c test(providers): improve OpencodeExecutor tests to avoid internal state coupling 2026-03-22 15:22:38 -03:00
kang-heewon 457c59e38a test(providers): add unit tests for OpencodeExecutor 2026-03-22 15:22:38 -03:00
diegosouzapw aa93a3f2e2 feat(3.0.0-rc.3): provider icons, model auto-sync, Gemini OAuth fix
Build Electron Desktop App / Validate version (push) Failing after 40s
Build Electron Desktop App / Build Electron (macos-arm64) (push) Has been skipped
Build Electron Desktop App / Build Electron (linux) (push) Has been skipped
Build Electron Desktop App / Build Electron (macos-intel) (push) Has been skipped
Build Electron Desktop App / Build Electron (windows) (push) Has been skipped
Build Electron Desktop App / Create Release (push) Has been skipped
feat(ui): ProviderIcon component with @lobehub/icons + PNG fallback (#529)
  - 130+ providers covered by Lobehub SVG components via LobehubErrorBoundary
  - Falls back to existing /providers/{id}.png, then generic icon
  - Replaces manual img state machine in ProviderCard + ApiKeyProviderCard

feat(scheduler): modelSyncScheduler — 24h model list auto-update (#488)
  - Syncs 16 major providers every 24h (MODEL_SYNC_INTERVAL_HOURS configurable)
  - Wired into POST /api/sync/initialize startup hook

fix(oauth): Gemini CLI — clear error when client_secret missing in Docker (#537)
2026-03-22 15:01:38 -03:00
diegosouzapw 8b9abcb6cc fix(3.0.0-rc.2): resolve issues #536, #535, #524
Build Electron Desktop App / Validate version (push) Failing after 34s
Build Electron Desktop App / Build Electron (macos-arm64) (push) Has been skipped
Build Electron Desktop App / Build Electron (linux) (push) Has been skipped
Build Electron Desktop App / Build Electron (macos-intel) (push) Has been skipped
Build Electron Desktop App / Build Electron (windows) (push) Has been skipped
Build Electron Desktop App / Create Release (push) Has been skipped
fix(providers): LongCat AI key validation — correct base URL and auth header (#536)
  - baseUrl: longcat.chat/api/v1/chat/completions -> api.longcat.chat/openai
  - authHeader: 'bearer' -> 'Authorization' + authPrefix: 'Bearer'

fix(combo): implement pinnedModel override in comboAgentMiddleware (#535)
  - Previously: pinnedModel was detected but body.model was never updated
  - Now: body = { ...body, model: pinnedModel } when context_cache_protection fires

fix(cli-tools): add OpenCode config save to guide-settings endpoint (#524)
  - Added 'opencode' case to switch in guide-settings/[toolId]/route.ts
  - saveOpenCodeConfig(): XDG_CONFIG_HOME aware, writes [provider.omniroute] TOML block
2026-03-22 13:31:56 -03:00
diegosouzapw 1ecc1908c7 chore(3.0.0-rc.1): bump version to 3.0.0-rc.1, close resolved issues, update CHANGELOG
Build Electron Desktop App / Validate version (push) Failing after 30s
Build Electron Desktop App / Build Electron (macos-arm64) (push) Has been skipped
Build Electron Desktop App / Build Electron (linux) (push) Has been skipped
Build Electron Desktop App / Build Electron (macos-intel) (push) Has been skipped
Build Electron Desktop App / Build Electron (windows) (push) Has been skipped
Build Electron Desktop App / Create Release (push) Has been skipped
- package.json: 2.9.5 → 3.0.0-rc.1
- docs/openapi.yaml: version → 3.0.0-rc.1
- CHANGELOG.md: add [3.0.0-rc.1] section with all batch1-3 fixes
- scripts/check-docs-sync.mjs: isSemver now accepts pre-release versions (X.Y.Z-prerelease.N)

Closed issues: #489, #492, #510, #513, #520, #521, #522, #525, #527, #532
RC versioning: rc.1 → rc.2 → rc.N on each VPS deploy until v3.0.0 is approved
2026-03-22 12:25:30 -03:00
diegosouzapw 6a2c7b467d fix(3.0.0-rc/batch3): convert tool_result blocks to text to stop Codex loop (#527)
fix(chat): convert tool_result content blocks to [Tool Result: id] text (#527)
  - Previously, tool_result blocks in user messages were silently dropped
  - This caused an infinite loop when Claude Code + superpowers routed to Codex:
    Codex never received the tool response and kept re-requesting the tool
  - Now: tool_result → text block '[Tool Result: {id}]\n{content}'
  - Handles string, array-of-text, and JSON-serialized content types

docs(issues): add Turbopack postinstall workaround on #509 and #508
docs(issues): note that #464 (API key provisioning) is on the v3.0 roadmap
2026-03-22 11:47:39 -03:00
diegosouzapw 0acef57865 fix(3.0.0-rc/batch2): resolve issues #510, #492, and improve #520, #529
fix(cli): normalize MSYS2/Git-Bash paths in cliRuntime.ts (#510)
  - Add normalizeMsys2Path() helper: /c/Program Files/... → C:\Program Files\...
  - Apply to both Windows 'where' and Unix 'command -v' path resolution
  - Fixes 'CLI not detected' on Windows when running Git Bash / MSYS2

fix(cli-launcher): detect mise/nvm on server.js not found error (#492)
  - Show targeted fix instructions based on which Node manager is in use
  - mise users: told to use npx or mise exec
  - nvm users: reminded to nvm use --lts before reinstalling

docs(issues): add pnpm bindings workaround comment (#520)
docs(issues): note OpenCode/Lobehub icons coming in v3.0.0 (#529)
2026-03-22 11:41:04 -03:00
diegosouzapw 43046ee649 fix(3.0.0-rc/batch1): resolve issues #521, #522, #525, #532, #489
fix(login): redirect to /dashboard/onboarding when API returns needsSetup:true (#521)
  - Handle the case where user skips password setup and lands on login
  - Instead of showing a cryptic error, redirect to onboarding flow

fix(api-manager): replace useless 'copy masked key' button with lock tooltip (#522)
  - Copying a masked key (sk-proj123****abcd) is misleading and useless
  - Show a lock icon on hover explaining key is only available at creation time
  - Add i18n key 'keyOnlyAvailableAtCreation'

fix(opencode-go): use zen/v1 for API key validation, not zen/go/v1 (#532)
  - Added testKeyBaseUrl field to RegistryEntry interface
  - opencode-go: testKeyBaseUrl → zen/v1 (same key authenticates both tiers)
  - validation.ts: resolveBaseUrl for key testing now prefers testKeyBaseUrl

fix(antigravity): return structured 422 error when projectId is missing (#489)
  - Instead of throwing (crash), executor returns an OpenAI-format error JSON
  - Client receives message with instruction to reconnect OAuth
  - Prevents opaque 500 errors in the proxy logs

chore: close #525 (OmniRoute = 9router — same project, different name)
docs: add Docker password reset comment on #513 with INITIAL_PASSWORD workaround
2026-03-22 11:31:34 -03:00
Diego Rodrigues de Sa e Souza a15fda0c08 Merge pull request #534 from diegosouzapw/release/v2.9.5
Build Electron Desktop App / Validate version (push) Failing after 33s
Build Electron Desktop App / Build Electron (macos-arm64) (push) Has been skipped
Build Electron Desktop App / Build Electron (linux) (push) Has been skipped
Build Electron Desktop App / Build Electron (macos-intel) (push) Has been skipped
Build Electron Desktop App / Build Electron (windows) (push) Has been skipped
Build Electron Desktop App / Create Release (push) Has been skipped
chore(release): v2.9.5 — OpenCode providers, embedding fix, CLI masked key fix
2026-03-22 10:32:33 -03:00
diegosouzapw e5988764ce chore(release): v2.9.5 — OpenCode providers, embedding credentials fix, CLI masked key fix, CACHE_TAG_PATTERN fix
- feat(providers): add OpenCode Zen and Go providers with multi-format executor (PR #530 by @kang-heewon)
- fix(embeddings): use provider node ID for custom embedding provider credential lookup (PR #528 by @jacob2826)
- fix(cli-tools): resolve real API key from DB (keyId) before writing to CLI config files (#523, #526)
- fix(combo): update CACHE_TAG_PATTERN to match literal \\n prefix/suffix around omniModel tag (#531)
- chore: bump version to 2.9.5 in package.json + docs/openapi.yaml
- docs: update CHANGELOG.md with v2.9.5 release notes
2026-03-22 10:30:04 -03:00
diegosouzapw 9c9d9b5a8d feat(providers): add OpenCode Zen and Go providers (#530) 2026-03-22 10:25:15 -03:00
kang-heewon 44dc564d85 chore: remove GHCR workflow from upstream PR 2026-03-22 10:24:50 -03:00
kang-heewon 83e367afab ci: add GHCR publish workflow for fork deployments 2026-03-22 10:24:50 -03:00
kang-heewon 8b7e7c2669 test(providers): improve OpencodeExecutor tests to avoid internal state coupling 2026-03-22 10:24:50 -03:00
kang-heewon 53474021b7 test(providers): add unit tests for OpencodeExecutor 2026-03-22 10:24:50 -03:00
kang-heewon da1ed1b5b2 feat(providers): register opencode-zen and opencode-go in provider registry 2026-03-22 10:24:50 -03:00
kang-heewon e08d661600 feat(providers): register opencode executors and add UI metadata
- Register OpencodeExecutor for 'opencode-zen' and 'opencode-go' in executors map
- Add OpencodeExecutor export in index.ts
- Add UI metadata for both providers in APIKEY_PROVIDERS:
  - OpenCode Zen: https://opencode.ai/zen
  - OpenCode Go: https://opencode.ai/zen/go
- Both use 'opencode' icon with #6366f1 color
2026-03-22 10:24:50 -03:00
kang-heewon 1aa1bc7a26 feat(providers): add OpencodeExecutor for opencode-zen/go multi-format routing 2026-03-22 10:23:32 -03:00
Diego Rodrigues de Sa e Souza 47634e942e Merge pull request #533 from diegosouzapw/fix/issues-521-523-526-531
fix: resolve masked key in CLI config saves + CACHE_TAG_PATTERN \n handling (#523, #526, #531)
2026-03-22 10:23:19 -03:00
Diego Rodrigues de Sa e Souza 15466cbf1a Merge pull request #528 from jacob2826/codex/fix-embedding-compatible-provider-credentials
fix: use provider node credentials for custom embedding providers
2026-03-22 10:23:16 -03:00
diegosouzapw 2a749db427 fix: resolve masked key bug in CLI config saves, fix CACHE_TAG_PATTERN for \n prefix (#523, #526, #531)
fix(cli-tools): save real API key to CLI config files instead of masked string (#523, #526)
  - claude-settings/route.ts: accept keyId, look up real key from DB (getApiKeyById)
  - cline-settings/route.ts: same keyId resolution pattern
  - openclaw-settings/route.ts: same keyId resolution pattern
  - ClaudeToolCard.tsx: store key.id as selected value, send keyId in POST body
  The /api/keys endpoint returns masked strings (first8+****+last4) which were being
  written verbatim to ~/.claude/settings.json and similar config files, causing auth
  failures on CLI tool launch.

fix(combo): update CACHE_TAG_PATTERN to strip surrounding \\n sequences (#531)
  - comboAgentMiddleware.ts: non-global regex now matches literal \\n (backslash-n)
    and actual newline U+000A that combo.ts injects around the <omniModel> tag.
2026-03-22 09:49:03 -03:00
jacob2826 ecccce86e4 fix: use provider node credentials for embeddings 2026-03-22 16:22:58 +08:00
Diego Rodrigues de Sa e Souza bf3f64bea4 Merge pull request #519 from diegosouzapw/release/2.9.4
Build Electron Desktop App / Validate version (push) Failing after 32s
Build Electron Desktop App / Build Electron (macos-arm64) (push) Has been skipped
Build Electron Desktop App / Build Electron (linux) (push) Has been skipped
Build Electron Desktop App / Build Electron (macos-intel) (push) Has been skipped
Build Electron Desktop App / Build Electron (windows) (push) Has been skipped
Build Electron Desktop App / Create Release (push) Has been skipped
chore(release): v2.9.4 — bug fixes (#491, #515, #517)
2026-03-21 17:40:23 -03:00
diegosouzapw 2f2d6b8535 chore(release): v2.9.4 — bug fixes (#491, #515, #517)
- fix(translator): preserve prompt_cache_key in Responses API translation (#517)
- fix(combo): escape \n in tagContent for valid JSON injection (#515)
- fix(usage): sync expired token status back to DB on live auth failure (#491)
- chore: bump version to 2.9.4 in package.json + docs/openapi.yaml
- docs: update CHANGELOG.md with v2.9.4 release notes
2026-03-21 17:37:51 -03:00
Diego Rodrigues de Sa e Souza d68c884649 Merge pull request #518 from diegosouzapw/fix/issue-517-515-prompt-cache-key-tagcontent
fix: preserve prompt_cache_key in Responses API, escape \n in tagContent (#517, #515)
2026-03-21 17:32:24 -03:00
diegosouzapw 8b556de03b fix: preserve prompt_cache_key in Responses API translation, escape \n in tagContent (#517, #515)
fix(translator): preserve prompt_cache_key when translating Responses API requests
  (#517) — prompt_cache_key is an account-affinity signal used by Codex for
  prompt cache routing. Deleting it from the translated request prevented full
  cache effectiveness. Removed delete from openai-responses.ts and
  responsesApiHelper.ts cleanup blocks.

fix(combo): escape \n in tagContent so injected JSON string is valid (#515)
  — omniModel tag content used template literal newlines (U+000A) which produce
  unescaped newline chars inside a JSON string value. Replaced with literal \n
  escape sequences for valid JSON injection in streaming SSE content chunks.
2026-03-21 17:09:13 -03:00
Diego Rodrigues de Sa e Souza 7229af53c3 Merge pull request #516 from diegosouzapw/release/2.9.3
Build Electron Desktop App / Validate version (push) Failing after 25s
Build Electron Desktop App / Build Electron (macos-arm64) (push) Has been skipped
Build Electron Desktop App / Build Electron (linux) (push) Has been skipped
Build Electron Desktop App / Build Electron (macos-intel) (push) Has been skipped
Build Electron Desktop App / Build Electron (windows) (push) Has been skipped
Build Electron Desktop App / Create Release (push) Has been skipped
feat(providers): 5 new free AI providers — v2.9.3
2026-03-21 16:55:29 -03:00
diegosouzapw 81b3034c2f feat(providers/logos): add logos for 5 new free providers
- public/providers/longcat.png — pink cat icon (generated)
- public/providers/pollinations.png — pixel bee icon (generated)
- public/providers/aimlapi.png — indigo neural network icon (generated)
- public/providers/cloudflare-ai.svg — Cloudflare official SVG (simpleicons.org)
- public/providers/scaleway.svg — Scaleway official SVG (simpleicons.org)

Icons serve at /providers/{id}.png (PNG fallback to SVG)
2026-03-21 16:47:49 -03:00
diegosouzapw f0419396b5 chore(release): bump version to 2.9.3, update CHANGELOG
- Version bumped from 2.9.2 → 2.9.3 in package.json + docs/openapi.yaml
- CHANGELOG.md updated with full release notes for 2.9.3
  (5 new free providers, 2 metadata updates, 2 custom executors, docs)
2026-03-21 15:44:35 -03:00
diegosouzapw 6b9c2754e8 feat(providers): add LongCat AI, Pollinations, Cloudflare AI, Scaleway, AI/ML API
New free providers:
- LongCat AI (lc/): 50M tokens/day free during public beta
- Pollinations AI (pol/): no API key needed, GPT-5/Claude/DeepSeek/Llama free
- Cloudflare Workers AI (cf/): 10K Neurons/day, ~150 LLM responses, Whisper free
- Scaleway AI (scw/): 1M free tokens for new accounts (EU/GDPR, Paris)
- AI/ML API (aiml/): $0.025/day credits, 200+ models via single endpoint

Provider metadata updates:
- Together AI: hasFree=true + 3 permanently free model IDs (Llama 70B, Vision, DeepSeek)
- Gemini: hasFree=true + freeNote (1,500 req/day free, no credit card)
- NVIDIA NIM: already had hasFree=true, confirmed correct

New executors:
- open-sse/executors/pollinations.ts: optional auth (no key support)
- open-sse/executors/cloudflare-ai.ts: dynamic URL with accountId credential

Documentation:
- README.md: 11-provider Ultimate Free Stack, 4 new pricing table rows
- README.md: LongCat/Pollinations/Cloudflare AI/Scaleway provider detail sections
- docs/i18n/pt-BR/README.md: updated pricing table + 4 new free provider sections
- docs/i18n/cs/README.md: combo stack updated

Tests: 821/821 pass (no regressions)
2026-03-21 15:40:05 -03:00
diegosouzapw 8edb131f8b docs: add npm downloads and Docker Hub pulls badges to README 2026-03-21 14:48:48 -03:00
Diego Rodrigues de Sa e Souza d6f6520a79 Merge pull request #514 from diegosouzapw/release/v2.9.2
Build Electron Desktop App / Validate version (push) Failing after 35s
Build Electron Desktop App / Build Electron (macos-arm64) (push) Has been skipped
Build Electron Desktop App / Build Electron (linux) (push) Has been skipped
Build Electron Desktop App / Build Electron (macos-intel) (push) Has been skipped
Build Electron Desktop App / Build Electron (windows) (push) Has been skipped
Build Electron Desktop App / Create Release (push) Has been skipped
chore(release): v2.9.2 — Transcription Content-Type fix, Deepgram language detection, TTS error display
2026-03-21 14:03:33 -03:00
diegosouzapw cc2bb4d719 chore: update generate-release workflow to two-phase PR-first flow
Phase 1: bump, docs, i18n, commit, push, open PR → STOP for user confirmation
Phase 2 (post-merge): tag, GitHub release, Docker Hub, deploy both VPS
2026-03-21 13:58:08 -03:00
diegosouzapw 3859f1c9ae chore(release): v2.9.2 — transcription Content-Type fix, Deepgram language detection, TTS error display
- fix(transcription): resolveAudioContentType() maps video/mp4 → audio/mp4 for Deepgram/HuggingFace
- fix(transcription): detect_language=true + punctuate=true for Deepgram auto-detection
- fix(tts): upstreamErrorResponse() correctly extracts string from nested error objects
- docs: README transcription/TTS rows updated with provider counts and capabilities
- i18n: sync 29/30 language README files with updated feature descriptions
- chore: bump version 2.9.1 → 2.9.2
2026-03-21 13:54:22 -03:00
diegosouzapw 5f8d774e19 fix: [object Object] error display in TTS/transcription upstream errors
upstreamErrorResponse() now guards against parsed.error being an
object (e.g. ElevenLabs { error: { message, status_code } }) instead
of blindly using it as the error message string.
Both audioSpeech.ts and audioTranscription.ts fixed.
2026-03-21 10:47:55 -03:00
diegosouzapw 538a3e855c fix: transcription Content-Type + language detection for Deepgram/HuggingFace
- Add resolveAudioContentType() to map video/* MIME to audio/* (fixes .mp4 uploads returning 'no speech detected')
- Add detect_language=true for Deepgram auto-language detection (fixes non-English audio)
- Add punctuate=true for better output quality
- Forward language form param to Deepgram when provided
- Apply same Content-Type fix to HuggingFace handler
2026-03-21 10:38:57 -03:00
diegosouzapw 03f2ef1e2b fix: omniModel SSE tag data loss + v2.9.1 release (#511)
Build Electron Desktop App / Validate version (push) Failing after 38s
Build Electron Desktop App / Build Electron (macos-arm64) (push) Has been skipped
Build Electron Desktop App / Build Electron (linux) (push) Has been skipped
Build Electron Desktop App / Build Electron (macos-intel) (push) Has been skipped
Build Electron Desktop App / Build Electron (windows) (push) Has been skipped
Build Electron Desktop App / Create Release (push) Has been skipped
2026-03-21 08:55:28 -03:00
Diego Rodrigues de Sa e Souza 237d0746cf Merge pull request #512 from zhangqiang8vip/feat/zws-v6
feat: per-protocol model compatibility, HMR leak fixes, and dev performance (V2-V5)
2026-03-21 08:53:54 -03:00
zhang-qiang 33b6c58087 fix(compat): store explicit false for per-protocol normalizeToolCallId
The truthy check treated false as falsy and deleted the property, preventing users from explicitly disabling normalization for a specific protocol when the top-level flag was true. Now stores both true and false values, consistent with preserveOpenAIDeveloperRole handling.

Made-with: Cursor
2026-03-21 16:38:46 +08:00
zhang-qiang e96b023d04 fix(ci): reword comment in default.ts to avoid t11 any-budget false positive
The word 'any' in a JSDoc comment was matched by the regex-based t11 checker. Reworded to 'prefixes' to eliminate the false positive.

Made-with: Cursor
2026-03-21 16:33:44 +08:00
zhang-qiang 7ac1d4621b Merge remote-tracking branch 'upstream/main' into feat/zws-v6 2026-03-21 16:32:57 +08:00
zhang-qiang a2d7cbe8fe feat(compat): per-protocol model compatibility config (V5)
Add per-protocol compatibility options (compatByProtocol) allowing users to configure normalizeToolCallId and preserveOpenAIDeveloperRole per client request protocol (OpenAI Chat, Responses API, Anthropic Messages) instead of globally. Includes frontend Map lookup optimization, type safety improvements, and client-safe constant extraction.

Made-with: Cursor
2026-03-21 15:23:42 +08:00
diegosouzapw c74ed29739 chore(release): v2.9.0 — cross-platform machineId, per-key rate limits, streaming cache, Alibaba DashScope, search analytics, ZWS v5, 8 issues closed
Build Electron Desktop App / Validate version (push) Failing after 33s
Build Electron Desktop App / Build Electron (macos-arm64) (push) Has been skipped
Build Electron Desktop App / Build Electron (linux) (push) Has been skipped
Build Electron Desktop App / Build Electron (macos-intel) (push) Has been skipped
Build Electron Desktop App / Build Electron (windows) (push) Has been skipped
Build Electron Desktop App / Create Release (push) Has been skipped
2026-03-20 20:12:34 -03:00
diegosouzapw 6c8501f122 fix: cross-platform machineId without process.platform branching (#506)
Rewrite getMachineIdRaw() to use a try/catch waterfall instead of
process.platform conditionals. Next.js SWC bundler evaluates
process.platform at BUILD time, so when built on Linux, the win32
branch was dead-code-eliminated — causing 'head is not recognized'
errors on Windows.

New approach:
1. Try Windows REG.exe (existsSync check, not platform check)
2. Try macOS ioreg command
3. Try reading /etc/machine-id directly (no head/pipe)
4. Try hostname command
5. Fallback to os.hostname()

Also eliminates the patch-machine-id.cjs post-install workaround.
2026-03-20 20:07:19 -03:00
diegosouzapw 941e945f74 Merge branch 'feat/zws-v5' 2026-03-20 19:36:25 -03:00
diegosouzapw f2844d59e4 Merge branch 'feat/search-provider-routing' 2026-03-20 19:36:17 -03:00
diegosouzapw 047ff187f6 Merge branch 'feat/custom-endpoint-paths'
# Conflicts:
#	src/shared/constants/providers.ts
2026-03-20 19:34:10 -03:00
diegosouzapw 1136c40811 Merge branch 'fix/tools-filter-claude-format' 2026-03-20 19:33:08 -03:00
diegosouzapw 5a78dc864f Merge branch 'fix/issue-456-458-combo-schema-mitm-windows' 2026-03-20 19:33:08 -03:00
diegosouzapw 15c98c3048 Merge branch 'fix/developer-role-param-error' 2026-03-20 19:33:07 -03:00
diegosouzapw 0a5b005ce5 fix: resolve multiple issues (#493, #490, #452)
- #493: Fix custom provider model naming — removed incorrect prefix
  stripping in DefaultExecutor.transformRequest() that broke org-scoped
  model IDs like 'zai-org/GLM-5-FP8'

- #490: Enable context cache protection for streaming responses using
  TransformStream to inject omniModel tag as final SSE content delta
  before [DONE] marker

- #452: Add per-API-key request-count limits (max_requests_per_day,
  max_requests_per_minute) with in-memory sliding window counter,
  schema auto-migration, and Check 5 in enforceApiKeyPolicy()
2026-03-20 19:26:21 -03:00
diegosouzapw 4d64e64127 fix: KIRO MITM card text + v2.8.9 release (#505)
Build Electron Desktop App / Validate version (push) Failing after 38s
Build Electron Desktop App / Build Electron (macos-arm64) (push) Has been skipped
Build Electron Desktop App / Build Electron (linux) (push) Has been skipped
Build Electron Desktop App / Build Electron (macos-intel) (push) Has been skipped
Build Electron Desktop App / Build Electron (windows) (push) Has been skipped
Build Electron Desktop App / Create Release (push) Has been skipped
2026-03-20 16:14:49 -03:00
Diego Rodrigues de Sa e Souza 5470c70cd0 Merge pull request #497 from zhangqiang8vip/feat/zws-v5
fix(perf): resolve dev-mode HMR resource leaks, Edge warnings, and Windows test stability
2026-03-20 16:13:27 -03:00
diegosouzapw 47959ee395 Merge branch 'main' into feat/zws-v5 2026-03-20 16:10:59 -03:00
Diego Rodrigues de Sa e Souza 7c34c178cd Merge pull request #503 from diegosouzapw/dependabot/github_actions/docker/login-action-4
chore(deps): bump docker/login-action from 3 to 4
2026-03-20 16:07:00 -03:00
Diego Rodrigues de Sa e Souza ac7cb41483 Merge pull request #502 from diegosouzapw/dependabot/github_actions/docker/setup-qemu-action-4
chore(deps): bump docker/setup-qemu-action from 3 to 4
2026-03-20 16:06:58 -03:00
Diego Rodrigues de Sa e Souza 0ab388b88e Merge pull request #501 from diegosouzapw/dependabot/github_actions/peter-evans/dockerhub-description-5
chore(deps): bump peter-evans/dockerhub-description from 4 to 5
2026-03-20 16:06:56 -03:00
Diego Rodrigues de Sa e Souza 54448902f1 Merge pull request #500 from diegosouzapw/dependabot/github_actions/actions/checkout-6
chore(deps): bump actions/checkout from 4 to 6
2026-03-20 16:06:53 -03:00
Diego Rodrigues de Sa e Souza 12107a02fd Merge pull request #499 from diegosouzapw/dependabot/github_actions/docker/build-push-action-7
chore(deps): bump docker/build-push-action from 6 to 7
2026-03-20 16:06:50 -03:00
Diego Rodrigues de Sa e Souza eace06efdc Merge pull request #498 from Sajid11194/fix/windows-machine-id-undefined-reg-exe
Thanks @Sajid11194 for fixing the Windows machine ID crash! Merged and will be part of v2.8.9. 🎉
2026-03-20 16:06:15 -03:00
dependabot[bot] ee0afa1eec chore(deps): bump docker/login-action from 3 to 4
Bumps [docker/login-action](https://github.com/docker/login-action) from 3 to 4.
- [Release notes](https://github.com/docker/login-action/releases)
- [Commits](https://github.com/docker/login-action/compare/v3...v4)

---
updated-dependencies:
- dependency-name: docker/login-action
  dependency-version: '4'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-03-20 18:26:04 +00:00
dependabot[bot] 83cdd0dafe chore(deps): bump docker/setup-qemu-action from 3 to 4
Bumps [docker/setup-qemu-action](https://github.com/docker/setup-qemu-action) from 3 to 4.
- [Release notes](https://github.com/docker/setup-qemu-action/releases)
- [Commits](https://github.com/docker/setup-qemu-action/compare/v3...v4)

---
updated-dependencies:
- dependency-name: docker/setup-qemu-action
  dependency-version: '4'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-03-20 18:25:58 +00:00
dependabot[bot] 5be025f1d1 chore(deps): bump peter-evans/dockerhub-description from 4 to 5
Bumps [peter-evans/dockerhub-description](https://github.com/peter-evans/dockerhub-description) from 4 to 5.
- [Release notes](https://github.com/peter-evans/dockerhub-description/releases)
- [Commits](https://github.com/peter-evans/dockerhub-description/compare/v4...v5)

---
updated-dependencies:
- dependency-name: peter-evans/dockerhub-description
  dependency-version: '5'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-03-20 18:25:55 +00:00
dependabot[bot] c651842ea1 chore(deps): bump actions/checkout from 4 to 6
Bumps [actions/checkout](https://github.com/actions/checkout) from 4 to 6.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/v4...v6)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-version: '6'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-03-20 18:25:51 +00:00
dependabot[bot] 423abe6788 chore(deps): bump docker/build-push-action from 6 to 7
Bumps [docker/build-push-action](https://github.com/docker/build-push-action) from 6 to 7.
- [Release notes](https://github.com/docker/build-push-action/releases)
- [Commits](https://github.com/docker/build-push-action/compare/v6...v7)

---
updated-dependencies:
- dependency-name: docker/build-push-action
  dependency-version: '7'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-03-20 18:25:45 +00:00
diegosouzapw 4003c38fd1 fix: OAuth batch test crash + Test All button on provider pages (v2.8.8)
Build Electron Desktop App / Validate version (push) Failing after 35s
Build Electron Desktop App / Build Electron (macos-arm64) (push) Has been skipped
Build Electron Desktop App / Build Electron (linux) (push) Has been skipped
Build Electron Desktop App / Build Electron (macos-intel) (push) Has been skipped
Build Electron Desktop App / Build Electron (windows) (push) Has been skipped
Build Electron Desktop App / Create Release (push) Has been skipped
2026-03-20 15:09:48 -03:00
Sajid 3e0c322fd4 fix: address Gemini code review — use execFileSync and optional chaining
- Replace execSync template string with execFileSync + args array on Windows
  to prevent command injection via SystemRoot/windir environment variables
- Add optional chaining (?.) and nullish coalescing (?? "") on Windows
  REG_SZ output parsing to prevent crash if REG.exe output is unexpected
- Add optional chaining on macOS IOPlatformUUID parsing for the same reason

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-20 23:44:15 +06:00
zhang-qiang 7fcdd4abdd fix(ci): resolve t11 any-budget false positive and e2e bailian validation test
- Replace 'any other path' with 'all other paths' in translator comment to avoid false match by the \bany\b regex in check-t11-any-budget

- Scope e2e error locator to dialog and use .first() to prevent Playwright strict-mode violations from broad page-level selectors

- Fix fallback logic: treat dialog-still-open as validation success signal

Made-with: Cursor
2026-03-21 01:19:44 +08:00
zhang-qiang 3f3280b2d4 Merge remote-tracking branch 'upstream/main' into feat/zws-v5 2026-03-21 00:55:57 +08:00
zhang-qiang aae2399631 fix(perf): resolve HMR singleton leaks, Edge warnings, and test stability
- Use globalThis singleton guards for DB connection, HealthCheck timers, console interceptor, and graceful shutdown to survive Webpack HMR re-evaluation (fixes 485+ leaked DB connections per session)

- Split instrumentation.ts into instrumentation-node.ts with computed import path to prevent Turbopack Edge bundler from tracing Node.js modules (eliminates 10+ spurious warnings per hot compile)

- Parallelize startup imports in instrumentation-node.ts (3 batch Promise.all instead of 9 serial awaits)

- Add OMNIROUTE_USE_TURBOPACK=1 env switch in run-next.mjs (default behavior unchanged)

- Replace node:crypto with crypto in proxies.ts and errorResponse.ts to fix UnhandledSchemeError

- Add unlinkFileWithRetry with EBUSY/EPERM retry for Windows file handle timing in backup restore

- Fix pre-restore backup to await completion before closing DB

- Fix bootstrap-env, domain-persistence, and fixes-p1 test stability on Windows

Made-with: Cursor
2026-03-21 00:50:07 +08:00
Sajid 03bd2b6803 fix: resolve Windows machine ID failure due to node-machine-id bundle-time platform detection
Problem:
node-machine-id constructs the REG.exe command path at module load time
using process.platform. When Next.js bundles this module, process.platform
is "" (not "win32") in the webpack/build context, so the lookup returns
undefined and bakes "undefined\REG.exe ..." permanently into the compiled
chunk. At runtime on Windows this causes:

  Error: Command failed: undefined\REG.exe QUERY HKEY_LOCAL_MACHINE\...
  The system cannot find the path specified.

Fix:
Remove the node-machine-id dependency from machineId.ts and replace it
with a direct execSync implementation that resolves process.env.SystemRoot
at call time (not load time), so the correct Windows path is always used
regardless of when or how the module was bundled.

Platform support is preserved for Windows, macOS, and Linux/FreeBSD using
the same underlying OS queries that node-machine-id used internally.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-20 22:01:48 +06:00
diegosouzapw 48754fd999 release: v2.8.7 — Bottleneck 429 drop (PR #495), custom embedding provider fix (#496)
Build Electron Desktop App / Validate version (push) Failing after 33s
Build Electron Desktop App / Build Electron (macos-arm64) (push) Has been skipped
Build Electron Desktop App / Build Electron (linux) (push) Has been skipped
Build Electron Desktop App / Build Electron (macos-intel) (push) Has been skipped
Build Electron Desktop App / Build Electron (windows) (push) Has been skipped
Build Electron Desktop App / Create Release (push) Has been skipped
2026-03-20 12:57:08 -03:00
Diego Rodrigues de Sa e Souza c496ebdef9 Merge pull request #495 from xandr0s/fix/429-drop-bottleneck-queue
fix: drop Bottleneck queue on 429 instead of infinite wait
2026-03-20 12:53:31 -03:00
Oleg Saprykin c009c40606 refactor: use .finally() to always delete limiter from Map
Address bot review feedback: use .finally() instead of .then()/.catch()
so limiters.delete() runs regardless of whether stop() succeeds or
throws (e.g. already stopped by concurrent 429).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-20 18:31:36 +03:00
Oleg Saprykin b29456c8e5 fix: catch stop() already called on concurrent 429s
Multiple concurrent requests can receive 429 simultaneously, causing
stop() to be called on an already-stopped limiter. Add .catch() to
prevent unhandled rejection.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-20 18:27:46 +03:00
diegosouzapw 38266bf2ff release: v2.8.6 — MiniMax role fix (PR #494), KIRO MITM card (#487), triage 8 issues
Build Electron Desktop App / Validate version (push) Failing after 29s
Build Electron Desktop App / Build Electron (macos-arm64) (push) Has been skipped
Build Electron Desktop App / Build Electron (linux) (push) Has been skipped
Build Electron Desktop App / Build Electron (macos-intel) (push) Has been skipped
Build Electron Desktop App / Build Electron (windows) (push) Has been skipped
Build Electron Desktop App / Create Release (push) Has been skipped
2026-03-20 12:26:27 -03:00
Diego Rodrigues de Sa e Souza c2e51f8948 Merge pull request #494 from zhangqiang8vip/fix/developer-role-param-error
fix: resolve 422 "role param error" when forwarding OpenAI Responses API to MiniMax (developer → system)
2026-03-20 12:21:57 -03:00
diegosouzapw c54a57838e fix: cleanup PR #494 — remove ZWS_README, fix KIRO MITM card (#487), generify AntigravityToolCard 2026-03-20 12:19:33 -03:00
Oleg Saprykin 64f040bddd fix: drop Bottleneck queue on 429 instead of waiting for reservoir refresh
When a provider returns 429 (rate limit exceeded), the rate limit manager
was setting reservoir=0 and waiting for reservoirRefreshInterval before
releasing queued requests. For providers with long rate limit windows
(e.g. Codex with hours-long resets), this caused all queued requests to
hang indefinitely — they never timed out or returned an error.

This prevented upstream callers (e.g. LiteLLM) from triggering fallback
to alternative providers, effectively making the entire model unavailable
until the rate limit window expired.

Fix: on 429, call limiter.stop({ dropWaitingJobs: true }) to immediately
fail all queued requests, then delete the limiter from the Map so
getLimiter() creates a fresh instance for subsequent requests.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-20 18:07:56 +03:00
zhang-qiang 1a099ea2f2 feat(zws-v2): model compat, provider-models hardening, provider page types
- roleNormalizer/translator: ZWS v2 role handling and comments

- models + schemas: compat overrides, nullable preserveOpenAIDeveloperRole

- provider-models API: generic GET 500; compatOnly validates known provider

- providers [id] page: typed props; minimal saveModelCompatFlags PATCH

Made-with: Cursor
2026-03-20 23:03:52 +08:00
zhang-qiang 13c45807ef feat: protocol-scoped model compat (V3)
- compatByProtocol per openai/openai-responses/claude

- getters take sourceFormat; chatCore passes it

- UI: protocol selector in compat popover, dark mode select

- shared/constants/modelCompat for client-safe import (fix node:crypto build)

- ZWS_README_V3.md

Made-with: Cursor
2026-03-20 22:06:03 +08:00
zhang-qiang dfbb9d5fff docs: add ZWS_README_V2 — developer role fix documentation
Made-with: Cursor
2026-03-20 21:47:02 +08:00
zhang-qiang a7fe369ea0 fix: resolve role param error for Responses API + MiniMax (developer→system)
- Add preserveDeveloperRole option and model compat override

- Normalize developer→system in roleNormalizer when not preserving

- Translator runs normalizeRoles for Responses API with option

- UI: ModelCompatPopover with do not preserve developer toggle

- Add ZWS_README_V2 documenting cause and fix

Made-with: Cursor
2026-03-20 21:06:10 +08:00
diegosouzapw b62e6c5a69 release: v2.8.5 — fix zombie SSE, context cache tag, KIRO MITM
Build Electron Desktop App / Validate version (push) Failing after 26s
Build Electron Desktop App / Build Electron (macos-arm64) (push) Has been skipped
Build Electron Desktop App / Build Electron (linux) (push) Has been skipped
Build Electron Desktop App / Build Electron (macos-intel) (push) Has been skipped
Build Electron Desktop App / Build Electron (windows) (push) Has been skipped
Build Electron Desktop App / Create Release (push) Has been skipped
Bug Fixes:
- #473: Reduce STREAM_IDLE_TIMEOUT_MS 300s→120s for faster zombie stream fallback
- #474: Fix injectModelTag() to handle first-turn (no assistant messages)
- #481: Change KIRO configType guide→mitm for dashboard MITM controls
- CI: Fix E2E test modal overlay interception

Closed External Issues:
- #468: Gemini CLI remote (superseded by #462 deprecation)
- #438: Claude write files (external CLI issue)
- #439: AppImage (documented libfuse2 workaround)
- #402: ARM64 DMG damaged (documented xattr -cr workaround)
- #460: Windows CLI PATH (documented fix)
2026-03-19 20:29:14 -03:00
diegosouzapw 92e29a6ad7 fix(e2e): dismiss pre-existing modal overlay in providers E2E test
The Bailian Coding Plan provider page may render a dialog on load
that blocks pointer events on the Add API Key button. Add pre-dialog
dismissal (Escape key) before attempting to click.

Also triages #485 (Claude Code tool calls — needs-info).
2026-03-19 20:05:51 -03:00
diegosouzapw eeb9c69aa3 chore(release): v2.8.4 — Gemini CLI deprecation, VM guide i18n, flatted security fix
Build Electron Desktop App / Validate version (push) Failing after 30s
Build Electron Desktop App / Build Electron (macos-arm64) (push) Has been skipped
Build Electron Desktop App / Build Electron (linux) (push) Has been skipped
Build Electron Desktop App / Build Electron (macos-intel) (push) Has been skipped
Build Electron Desktop App / Build Electron (windows) (push) Has been skipped
Build Electron Desktop App / Create Release (push) Has been skipped
- #462: gemini-cli marked deprecated, Zod schema expanded
- #471: VM guide added to i18n pipeline, 30 locale translations regenerated
- #484: bump flatted 3.3.3→3.4.2 (CWE-1321)
- Closed: #472, #471, #483
2026-03-19 16:32:23 -03:00
Diego Rodrigues de Sa e Souza b7662ed5a1 Merge pull request #484 from diegosouzapw/dependabot/npm_and_yarn/flatted-3.4.2
deps: bump flatted from 3.3.3 to 3.4.2
2026-03-19 16:31:14 -03:00
dependabot[bot] 9d6296f610 deps: bump flatted from 3.3.3 to 3.4.2
Bumps [flatted](https://github.com/WebReflection/flatted) from 3.3.3 to 3.4.2.
- [Commits](https://github.com/WebReflection/flatted/compare/v3.3.3...v3.4.2)

---
updated-dependencies:
- dependency-name: flatted
  dependency-version: 3.4.2
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-03-19 19:02:01 +00:00
diegosouzapw fd2a1320e0 fix: resolve issues #462, #471 — deprecate gemini-cli, regenerate VM guide i18n
- #462: Mark gemini-cli provider as deprecated in providers.ts
  Add deprecated, deprecationReason, hasFree, freeNote, authHint, apiHint
  to Zod provider schema
- #471: Add VM_DEPLOYMENT_GUIDE.md to DOC_SOURCE_FILES in generate-multilang.mjs
  Delete 29 stale PT-language copies and regenerate from EN source
  for all 30 locales (29 auto-translated + 1 Czech from PR #482)
2026-03-19 15:57:55 -03:00
diegosouzapw 8a8a6a4a82 chore(release): v2.8.3 — Czech i18n, SSE protocol fix
Build Electron Desktop App / Validate version (push) Failing after 25s
Build Electron Desktop App / Build Electron (macos-arm64) (push) Has been skipped
Build Electron Desktop App / Build Electron (linux) (push) Has been skipped
Build Electron Desktop App / Build Electron (macos-intel) (push) Has been skipped
Build Electron Desktop App / Build Electron (windows) (push) Has been skipped
Build Electron Desktop App / Create Release (push) Has been skipped
- #482: Czech language + VM guide EN translation (@zen0bit)
- #483: Stop sending trailing data: null after [DONE]
2026-03-19 14:00:18 -03:00
diegosouzapw 8cdc14eec1 Merge PR #482: Add Czech language + Fix VM_DEPLOYMENT_GUIDE.md English source 2026-03-19 13:59:28 -03:00
diegosouzapw a1200b2fb5 fix(docs): correct Czech link in USER_GUIDE.md language switcher
cs/.md → cs/USER_GUIDE.md
2026-03-19 13:57:29 -03:00
diegosouzapw c88c29eddc fix(streaming): stop sending trailing data: null after [DONE] (#483)
formatSSE() in streamHelpers.ts explicitly returned 'data: null' for
null/undefined data. This violates SSE protocol and causes
AI_TypeValidationError in strict clients (Zod-based AI SDKs).
Now returns empty string, silently skipping null chunks.
2026-03-19 12:58:16 -03:00
diegosouzapw 2845c4de98 docs(workflow): fix deploy-vps to use ecosystem.config.cjs + rebuild better-sqlite3
Previously pm2 restart dropped env vars, causing login failures.
Now uses pm2 delete + pm2 start ecosystem.config.cjs --update-env.
Also rebuilds better-sqlite3 native bindings in app/ subdir.
2026-03-19 12:12:27 -03:00
zenobit bfa9cd15b7 Add Czech language + Fix VM_DEPLOYMENT_GUIDE.md English source
Author: zenobit <zenobit@disroot.org>
2026-03-19 16:02:28 +01:00
diegosouzapw 659e2b414d feat(release): v2.8.2 — model alias routing fix, log export, 2 merged PRs
Build Electron Desktop App / Validate version (push) Failing after 25s
Build Electron Desktop App / Build Electron (macos-arm64) (push) Has been skipped
Build Electron Desktop App / Build Electron (linux) (push) Has been skipped
Build Electron Desktop App / Build Electron (macos-intel) (push) Has been skipped
Build Electron Desktop App / Build Electron (windows) (push) Has been skipped
Build Electron Desktop App / Create Release (push) Has been skipped
2026-03-19 11:13:49 -03:00
diegosouzapw 7bcb58e3db feat(logs): add export button with time range dropdown (1h, 6h, 12h, 24h)
- New API: /api/logs/export?hours=24&type=call-logs
- UI: Export button with dropdown on /dashboard/logs page
- Supports export of request-logs, proxy-logs, and call-logs
- Downloads as JSON file with Content-Disposition header
2026-03-19 11:11:07 -03:00
diegosouzapw 2d7d7776a6 fix(routing): model aliases now affect routing, not just format detection (#472)
Previously resolveModelAlias() output was used only for getModelTargetFormat()
but the original model was sent in translatedBody.model and to the executor.
Now effectiveModel is propagated to all downstream operations.
2026-03-19 11:07:29 -03:00
Prakersh Maheshwari c5f429521c fix(pricing): add missing Codex 5.3/5.4 and Anthropic model ID entries (#479)
* fix(pricing): add missing Codex 5.3/5.4 and Anthropic model ID entries

Missing pricing entries cause $0.00 cost for:
- GPT 5.3 Codex family (gpt-5.3-codex, -high, -xhigh, -low, -none)
- GPT 5.4 (with hyphen: gpt-5.4)
- GPT 5.1 Codex Mini High
- Common Anthropic model IDs without dates (claude-opus-4-6,
  claude-sonnet-4-6, claude-opus-4, claude-sonnet-4)
- Dated variants used by Claude Code (claude-opus-4-5-20251101,
  claude-sonnet-4-5-20250929)

* refactor: extract shared pricing constants to reduce duplication

Address review feedback: extract duplicated pricing objects into
named constants (GPT_5_3_CODEX_PRICING, CLAUDE_OPUS_4_PRICING, etc.)
and add clarifying comment about intentional hyphen/dot variant entries.
2026-03-19 11:04:30 -03:00
diegosouzapw 426d8636bc fix(stream): extract usage from remaining buffer in flush handler (#480) 2026-03-19 11:02:13 -03:00
diegosouzapw a265c7096e feat(release): v2.8.1 — streaming log fix, Kiro compat, cache tokens, Chinese i18n, configurable tool call ID
Build Electron Desktop App / Validate version (push) Failing after 31s
Build Electron Desktop App / Build Electron (macos-arm64) (push) Has been skipped
Build Electron Desktop App / Build Electron (linux) (push) Has been skipped
Build Electron Desktop App / Build Electron (macos-intel) (push) Has been skipped
Build Electron Desktop App / Build Electron (windows) (push) Has been skipped
Build Electron Desktop App / Create Release (push) Has been skipped
2026-03-19 08:45:54 -03:00
diegosouzapw 1c9953b1ba chore: remove ZWS_README_V1.md (internal contributor doc) 2026-03-19 08:43:17 -03:00
diegosouzapw 601cc21a44 feat: call log response content, per-model tool call ID, key PATCH & validation (#470) 2026-03-19 08:41:01 -03:00
Ethan Hunt 102c42dfe4 feat: Improve the Chinese translation (#475)
Co-authored-by: gmw <rorschach1167@qq.com>
2026-03-19 08:37:51 -03:00
Prakersh Maheshwari 4953727aa7 fix(callLogs): support Claude format usage and include cache tokens (#476)
saveCallLog only read prompt_tokens/completion_tokens (OpenAI format).
When sourceFormat=claude, the openai-to-claude translator writes
input_tokens/output_tokens instead, causing all cross-format requests
(Codex-via-Claude, Kiro-via-Claude, etc.) to show 0|0 tokens in
call_logs.

Also includes cache_read and cache_creation tokens in tokens_in total
so heavily-cached requests don't show misleadingly low input counts.

Changes:
- Read prompt_tokens || input_tokens (supports both formats)
- Read completion_tokens || output_tokens (supports both formats)
- Sum cache_read_input_tokens + cache_creation_input_tokens into total
2026-03-19 08:37:49 -03:00
Prakersh Maheshwari e6af874b47 fix(usage): include cache tokens in usage history input total (#477)
logUsage stored only non-cached input tokens in usage_history.tokens_input.
For heavily-cached Claude requests (common with Claude Code), this shows
near-zero input when the real total is 150K+, causing the analytics
dashboard to severely underreport input token usage.

Now sums: input = prompt_tokens + cache_read + cache_creation
2026-03-19 08:37:46 -03:00
Prakersh Maheshwari 801b4eef4c fix(kiro): strip injected model field from request body (#478)
chatCore.ts injects translatedBody.model for all providers after
translation. Kiro API (AWS CodeWhisperer) has strict schema validation
and rejects unknown top-level fields — only conversationState, profileArn,
and inferenceConfig are valid. This causes 100% of Kiro requests to fail
with "Improperly formed request".

Strip the injected model field in KiroExecutor.transformRequest().
2026-03-19 08:37:44 -03:00
diegosouzapw fe5c20a04e feat(release): v2.8.0 — Bailian Coding Plan, editable provider URLs, 812 tests
Build Electron Desktop App / Validate version (push) Failing after 34s
Build Electron Desktop App / Build Electron (macos-arm64) (push) Has been skipped
Build Electron Desktop App / Build Electron (linux) (push) Has been skipped
Build Electron Desktop App / Build Electron (macos-intel) (push) Has been skipped
Build Electron Desktop App / Build Electron (windows) (push) Has been skipped
Build Electron Desktop App / Create Release (push) Has been skipped
2026-03-19 02:28:45 -03:00
diegosouzapw 246fd05fae feat(providers): add Bailian Coding Plan provider with editable base URL (#467) 2026-03-19 02:25:29 -03:00
diegosouzapw a09b298127 feat(release): v2.7.10 — Alibaba Cloud Coding, Kimi Coding API-key, Docker pino fix
Build Electron Desktop App / Validate version (push) Failing after 34s
Build Electron Desktop App / Build Electron (macos-arm64) (push) Has been skipped
Build Electron Desktop App / Build Electron (linux) (push) Has been skipped
Build Electron Desktop App / Build Electron (macos-intel) (push) Has been skipped
Build Electron Desktop App / Build Electron (windows) (push) Has been skipped
Build Electron Desktop App / Create Release (push) Has been skipped
2026-03-19 01:50:00 -03:00
Jefferson Nunn f89f40778f feat: add API-key Kimi Coding provider path (#463)
* feat: add api-key Kimi Coding provider support

* fix(kimi-coding): honor apikey auth header in executor

Ensure DefaultExecutor sends x-api-key for kimi-coding-apikey at runtime
and deduplicate shared kimi coding config blocks in registry and models
config to reduce drift between oauth and apikey variants.

---------

Co-authored-by: OmniRoute Agent <agent@omniroute.local>
2026-03-19 01:48:26 -03:00
dtk 3d0c8d8d45 feat: add alibaba cloud coding plan provider support (#465)
Co-authored-by: dtk <git@derzsi.cloud>
2026-03-19 01:48:23 -03:00
diegosouzapw 0e5e8bf14e fix(docker): add missing split2 dependency to container image (#459) 2026-03-19 01:46:26 -03:00
diegosouzapw ce34d329d3 chore(release): v2.7.9
Build Electron Desktop App / Validate version (push) Failing after 28s
Build Electron Desktop App / Build Electron (macos-arm64) (push) Has been skipped
Build Electron Desktop App / Build Electron (linux) (push) Has been skipped
Build Electron Desktop App / Build Electron (macos-intel) (push) Has been skipped
Build Electron Desktop App / Build Electron (windows) (push) Has been skipped
Build Electron Desktop App / Create Release (push) Has been skipped
2026-03-18 17:19:42 -03:00
diegosouzapw eaf4a5805c "fix: resolved UI combo setting schema strip (#458)"
"fix: safe crypto fallback for MITM on windows (#456)"
2026-03-18 17:18:31 -03:00
Sergey Morozov 8420e565d4 feat: add responses subpath passthrough for codex (#457) 2026-03-18 17:18:29 -03:00
diegosouzapw 00df10c29a "fix: resolved UI combo setting schema strip (#458)"
"fix: safe crypto fallback for MITM on windows (#456)"
2026-03-18 17:16:30 -03:00
diegosouzapw 1b68deb0f6 feat(release): v2.7.8 — budget save fix + combo agent UI + omniModel tag strip
Build Electron Desktop App / Validate version (push) Failing after 32s
Build Electron Desktop App / Build Electron (macos-arm64) (push) Has been skipped
Build Electron Desktop App / Build Electron (linux) (push) Has been skipped
Build Electron Desktop App / Build Electron (macos-intel) (push) Has been skipped
Build Electron Desktop App / Build Electron (windows) (push) Has been skipped
Build Electron Desktop App / Create Release (push) Has been skipped
- fix(budget): warningThreshold sent as fraction 0-1 not percentage 0-100 (#451)
- feat(combos): Agent Features UI in combo modal (system_message, tool_filter_regex,
  context_cache_protection) — previously server-only (#454)
- fix(combos): strip <omniModel> tags before forwarding to provider (#454)
2026-03-18 15:38:04 -03:00
Diego Rodrigues de Sa e Souza d1497c9ac8 Merge pull request #455 from diegosouzapw/fix/issue-451-454-budget-combo-ui
fix: budget warningThreshold + combo agent UI fields + omniModel tag strip
2026-03-18 15:37:17 -03:00
diegosouzapw 03d4cbf6d5 fix: budget warningThreshold fraction mismatch + combo agent UI fields + omniModel tag strip
- fix(budget): BudgetTab sent integer percentage (80) but schema validated
  fraction (0-1). Now divides by 100 on POST and multiplies by 100 on GET (#451)

- fix(combos): expose Agent Features UI in combo create/edit modal — fields for
  system_message override, tool_filter_regex, and context_cache_protection were
  implemented server-side (#399/#401) but missing from the dashboard UI (#454)

- fix(combos): strip <omniModel> tags from messages before forwarding to provider.
  The internal cache-pinning tag was being sent to the provider, causing cache
  misses as providers treated each tagged request as a new session (#454)
2026-03-18 15:32:47 -03:00
diegosouzapw 718be831af feat(release): v2.7.7 — Docker pino crash fix + Codex responses worker fix
Build Electron Desktop App / Validate version (push) Failing after 35s
Build Electron Desktop App / Build Electron (macos-arm64) (push) Has been skipped
Build Electron Desktop App / Build Electron (linux) (push) Has been skipped
Build Electron Desktop App / Build Electron (macos-intel) (push) Has been skipped
Build Electron Desktop App / Build Electron (windows) (push) Has been skipped
Build Electron Desktop App / Create Release (push) Has been skipped
- fix(docker): copy pino-abstract-transport + pino-pretty in standalone (#449)
- fix(responses): remove initTranslators() from /v1/responses route (#450)
- chore(deps): commit package-lock.json with each version bump
2026-03-18 15:13:26 -03:00
Diego Rodrigues de Sa e Souza 9d5ec523be Merge pull request #453 from diegosouzapw/fix/issue-449-450-pino-docker-responses-worker
fix: pino Docker crash + Codex /v1/responses worker exit + package-lock sync
2026-03-18 15:11:38 -03:00
diegosouzapw 81c43b45fb fix: pino-abstract-transport missing in Docker + responses worker crash + lock sync
- fix(docker): copy pino-abstract-transport and pino-pretty explicitly in
  runner-base stage — Next.js standalone trace omits them, causing
  'Cannot find module pino-abstract-transport' crash on startup (#449)

- fix(responses): remove initTranslators() call from /v1/responses route —
  bootstrapping translator registry from a Next.js Route Handler worker
  caused 'the worker has exited' uncaughtException on Codex CLI requests.
  Translators are already bootstrapped server-side via open-sse (#450)

- chore: include package-lock.json in commit (was being left behind on
  version bumps, causing npm ci to install inconsistent deps in Docker)
2026-03-18 15:08:57 -03:00
diegosouzapw 146a491769 feat(release): v2.7.5 — login UX + Windows CLI healthcheck
Build Electron Desktop App / Validate version (push) Failing after 34s
Build Electron Desktop App / Build Electron (macos-arm64) (push) Has been skipped
Build Electron Desktop App / Build Electron (linux) (push) Has been skipped
Build Electron Desktop App / Build Electron (macos-intel) (push) Has been skipped
Build Electron Desktop App / Build Electron (windows) (push) Has been skipped
Build Electron Desktop App / Create Release (push) Has been skipped
- fix(ux): show default password hint on login page (#437)
- fix(cli): spawn shell:true on Windows for .cmd CLI resolution (#447)
2026-03-18 14:52:05 -03:00
Diego Rodrigues de Sa e Souza 4c53388579 Merge pull request #448 from diegosouzapw/fix/issue-437-447-435-login-healthcheck-gemini
fix: login default password hint + Windows CLI healthcheck shell resolution
2026-03-18 14:51:19 -03:00
diegosouzapw 3403ddcc6e fix: login password hint + Windows CLI healthcheck + i18n key
- fix(ux): add default password hint on login page for first-time users (#437)
  The fallback password (123456) is now shown as a hint below the
  password input so users don't get locked out during initial setup.

- fix(cli): add shell:true to spawn on Windows so .cmd wrappers are
  resolved correctly via PATHEXT (#447). Claude, opencode, and other
  npm-installed CLIs show as 'not runnable' on Windows even when
  installed because spawn() cannot find .cmd files without shell:true.

- i18n: add defaultPasswordHint key to en.json auth namespace
2026-03-18 14:44:49 -03:00
diegosouzapw 684b81d835 feat(release): v2.7.4 — search playground, i18n fixes, Copilot limits, Serper validation
Build Electron Desktop App / Validate version (push) Failing after 34s
Build Electron Desktop App / Build Electron (macos-arm64) (push) Has been skipped
Build Electron Desktop App / Build Electron (linux) (push) Has been skipped
Build Electron Desktop App / Build Electron (macos-intel) (push) Has been skipped
Build Electron Desktop App / Build Electron (windows) (push) Has been skipped
Build Electron Desktop App / Create Release (push) Has been skipped
- feat(search): search playground + search tools page + local rerank (#443 @Regis-RCR)
- fix(analytics): localize day/date labels with Intl.DateTimeFormat (#444 @hijak)
- fix(copilot): correct account type display, filter unlimited quotas (#445 @hijak)
- fix(providers): stop rejecting valid Serper API keys on non-4xx (#446 @hijak)
2026-03-18 12:11:00 -03:00
Diego Rodrigues de Sa e Souza 4f32da57fd Merge pull request #443 from Regis-RCR/feat/search-playground
feat(search): add search playground, search tools, and local rerank routing
2026-03-18 12:09:51 -03:00
Diego Rodrigues de Sa e Souza 97265e48b3 Merge pull request #444 from hijak/fix/analytics-day-date-translations
fix: localize analytics day and date labels
2026-03-18 12:07:03 -03:00
Diego Rodrigues de Sa e Souza 64797158e2 Merge pull request #445 from hijak/fix/copilot-account-type-limits
fix: correct GitHub Copilot account type and limits
2026-03-18 12:06:59 -03:00
Diego Rodrigues de Sa e Souza 8359293dcd Merge pull request #446 from hijak/fix/serper-api-key-validation
fix: stop rejecting valid Serper API keys
2026-03-18 12:06:36 -03:00
Jack Cowey b2dc53d18b fix(search): return consistent validation result shape
Keep search provider validation responses consistent with other validators so Serper regression tests and CI assertions can rely on unsupported=false.

Made-with: Cursor
2026-03-18 12:55:25 +00:00
Jack Cowey edf8dd2a12 fix(search): accept authenticated serper validation responses
Treat non-auth Serper validation errors as successful authentication so valid API keys are not rejected during provider setup.

Made-with: Cursor
2026-03-18 12:29:14 +00:00
Jack Cowey 5a777bd598 fix(github): correct copilot plan and quota mapping
Normalize GitHub Copilot account tiers from the usage payload and hide misleading unlimited buckets so account type and limits render correctly in the dashboard.

Made-with: Cursor
2026-03-18 12:25:17 +00:00
Jack Cowey bd39e01ee1 fix(analytics): localize most active day and weekly labels
Use the active app locale for analytics weekday and date formatting so the dashboard no longer shows hardcoded Portuguese labels.

Made-with: Cursor
2026-03-18 12:17:56 +00:00
Regis e3ed29aab6 feat(search): add search playground, search tools, and local rerank routing
Search Playground (Phase 1):
- Web Search as 10th endpoint in Playground with isolated SearchPlayground component
- Endpoint selector moved first; Provider/Model/Send hidden when search selected
- Provider dropdown via GET /api/search/providers, formatted results with cache indicator

Search Tools page (Phase 2) at /dashboard/search-tools:
- Split panel: SearchForm (left) with query, provider, filters + ResultsPanel (right)
- Compare Providers: parallel queries with latency, cost, response size, URL overlap
- Rerank Pipeline: model selector from /v1/models, results with position delta
- Search History: last 10 searches from call_logs with replay
- Sidebar entry under Debug section

Backend:
- GET /api/search/providers — list providers with auth guard + SEARCH_CREDENTIAL_FALLBACKS
- GET /api/search/stats — cache stats, provider aggregates, recent searches (auth guard)
- Add local provider_nodes routing for /v1/rerank (oMLX, vLLM support)

Bug fixes (from F-27 PR #432):
- Fix Brave news normalizer: data.results directly, not data.news.results
- Enforce max_results truncation after normalization for all providers
- Fix EndpointPageClient: use /api/search/providers instead of /api/v1/search
- Add isAuthenticated() guards on /api/search/providers and /api/search/stats

Response size metric in results meta bar and compare table.
i18n: 30+ keys in search namespace (en.json)
2026-03-18 12:43:24 +01:00
diegosouzapw 896ce9c0e2 feat(release): v2.7.3 — fix Codex direct API weekly quota fallback
Build Electron Desktop App / Validate version (push) Failing after 36s
Build Electron Desktop App / Build Electron (macos-arm64) (push) Has been skipped
Build Electron Desktop App / Build Electron (linux) (push) Has been skipped
Build Electron Desktop App / Build Electron (macos-intel) (push) Has been skipped
Build Electron Desktop App / Build Electron (windows) (push) Has been skipped
Build Electron Desktop App / Create Release (push) Has been skipped
- fix(codex): resolveQuotaWindow() prefix-matches 'weekly' → 'weekly (7d)' cache keys
- fix(codex): applyCodexWindowPolicy() enforces useWeekly/use5h toggles in direct API
- 4 new regression tests, 766 total passing
- Closes #440
2026-03-18 08:41:13 -03:00
Diego Rodrigues de Sa e Souza 82934132e9 Merge pull request #441 from rexname/fix/issue-440-direct-api-fallback
fix(codex): block weekly-exhausted accounts in direct API fallback
2026-03-18 08:40:19 -03:00
rexname a2012b70de chore(review): harden window normalization and deterministic quota matching 2026-03-18 14:17:37 +07:00
rexname bcfeba8a57 fix(codex): enforce weekly quota blocking for direct API fallback 2026-03-18 13:57:25 +07:00
diegosouzapw d3dfd9ce57 feat(release): v2.7.2 — fix light mode contrast in logs UI
Build Electron Desktop App / Validate version (push) Failing after 38s
Build Electron Desktop App / Build Electron (macos-arm64) (push) Has been skipped
Build Electron Desktop App / Build Electron (linux) (push) Has been skipped
Build Electron Desktop App / Build Electron (macos-intel) (push) Has been skipped
Build Electron Desktop App / Build Electron (windows) (push) Has been skipped
Build Electron Desktop App / Create Release (push) Has been skipped
- fix(logs): text colors in filter buttons + combo badge now have dark: variants
- Bumped version to 2.7.2
- Updated CHANGELOG and openapi.yaml
2026-03-18 00:42:22 -03:00
Diego Rodrigues de Sa e Souza aa06d5d356 Merge pull request #433 from diegosouzapw/fix/issue-378-logs-light-mode-contrast
Merged fix for light mode contrast in filter buttons and combo badge. Thanks @rdself for the great bug report!
2026-03-18 00:41:28 -03:00
diegosouzapw 448c8a29e1 fix(logs): fix light mode contrast in filter buttons and combo badge (#378)
- text-red-400 → text-red-700 dark:text-red-400 (error filter, recording button)
- text-emerald-400 → text-emerald-700 dark:text-emerald-400 (ok filter)
- text-violet-300 → text-violet-700 dark:text-violet-300 (combo filter)
- combo row badge: violet-700 → violet-800 dark:violet-300, stronger border

Fixes #378
2026-03-17 16:46:27 -03:00
diegosouzapw 928b7120f4 feat(release): v2.7.1 — unified web search routing + Next.js 16.1.7 security
Build Electron Desktop App / Validate version (push) Failing after 35s
Build Electron Desktop App / Build Electron (macos-arm64) (push) Has been skipped
Build Electron Desktop App / Build Electron (linux) (push) Has been skipped
Build Electron Desktop App / Build Electron (macos-intel) (push) Has been skipped
Build Electron Desktop App / Build Electron (windows) (push) Has been skipped
Build Electron Desktop App / Create Release (push) Has been skipped
- POST /v1/search: 5 providers (Serper, Brave, Perplexity, Exa, Tavily), 6,500+ free/mo
- Search analytics dashboard tab + GET /api/v1/search/analytics
- db: request_type column on call_logs (migration 007)
- Next.js 16.1.7: 6 CVEs fixed (critical: CVE-2026-29057 HTTP request smuggling)
- docs/openapi.yaml: bumped to 2.7.1
2026-03-17 16:27:31 -03:00
diegosouzapw a3deacd718 feat: Implement historical model latency and success rate tracking for auto-combo routing and update Claude and Deepseek pricing and model registrations. 2026-03-17 16:18:36 -03:00
diegosouzapw 78959fffbd Merge branch 'main' of https://github.com/diegosouzapw/OmniRoute 2026-03-17 16:18:12 -03:00
Diego Rodrigues de Sa e Souza 1788616e52 Merge pull request #431 from diegosouzapw/dependabot/npm_and_yarn/next-16.1.7
Security update merged: Next.js 16.1.7 fixes 6 CVEs including critical CVE-2026-29057 (HTTP request smuggling). No breaking changes.
2026-03-17 16:18:01 -03:00
Diego Rodrigues de Sa e Souza c61e6d0777 Merge pull request #432 from Regis-RCR/feat/search-provider-routing
Merged with dashboard improvements: SearchAnalyticsTab + /api/v1/search/analytics endpoint — PR review complete by Antigravity.
2026-03-17 16:17:39 -03:00
diegosouzapw 41d91d628a feat(search/analytics): add Search tab to analytics dashboard + GET /api/v1/search/analytics
- SearchAnalyticsTab: provider breakdown, cache hit rate, cost summary, KPI cards
- /api/v1/search/analytics: query call_logs (request_type='search') for stats
- analytics/page.tsx: added 'Search' tab alongside Overview and Evals

Closes missing dashboard tracking identified in PR review.
2026-03-17 16:15:28 -03:00
diegosouzapw a3bc7620b1 feat(integration): integrate ClawRouter services into active pipeline
- intentClassifier → engine.ts selectProvider()
  When taskType is 'default', classifies prompt via multilingual keyword
  detection (9 langs) and uses detected intent (code/reasoning/simple/medium)
  for 6-factor task fitness scoring.

- emergencyFallback → chatCore.ts error path (after T5 intra-family fallback)
  On HTTP 402 or budget-exhaustion keywords, attempts one redirect to
  nvidia/gpt-oss-120b ($0.00/M) before returning error to combo router.
  Skipped for streaming requests and tool-calling requests.

- AutoComboConfig.routerStrategy field added
  Allows per-combo strategy override ('rules' | 'cost' | 'latency')

Note: requestDedup was already integrated in chatCore.ts (line 387-430)
Branch: feat/clawrouter-improvements
2026-03-17 15:22:12 -03:00
diegosouzapw 8064c588dc docs(i18n): sync v2.7.0 release notes to 29 language READMEs
New in v2.7.0: pluggable RouterStrategy, multilingual intent detection,
request deduplication, new providers (Grok-4 Fast, GLM-5/Z.AI,
MiniMax M2.5, Kimi K2.5). Native translations for de/es/fr/it/ru/zh-CN/ja/ko/ar/pt-BR/pt.
2026-03-17 15:11:09 -03:00
Regis 564e983c68 feat(search): add unified web search routing with 5 providers
Add POST /v1/search — a unified search endpoint routing queries across
5 providers (Serper, Brave, Perplexity Search, Exa, Tavily) with
automatic failover, in-memory caching, and request coalescing.

No open-source AI gateway offers unified search routing. This chains
free tiers for 5,500+ searches/month with zero downtime.

Providers: Serper ($0.001/q, 2500/mo free), Brave ($0.005/q, 1000/mo),
Perplexity Search ($0.005/q), Exa ($0.007/q, 1000/mo), Tavily
($0.008/q, 1000/mo). Auto-select picks cheapest with credentials.

Architecture follows existing patterns:
- searchRegistry.ts (same as embeddingRegistry.ts)
- search.ts handler (same as embeddings.ts)
- route.ts (same as /v1/embeddings/route.ts)
- searchCache.ts (bounded TTL cache + request coalescing)

Schema finalized — all future fields defined as optional with safe
defaults. No breaking changes when implementing content extraction,
answer synthesis, or ranking.

Key features:
- Per-provider request builders and response normalizers
- Enriched response: display_url, score, favicon_url, content block,
  metadata, answer block, errors array, upstream_latency_ms metrics
- Cost-sorted auto-select with failover on 429/5xx/timeout
- Credential fallback (perplexity-search reuses perplexity chat key)
- Cache key includes all result-affecting parameters
- max_results clamped to provider limits, sanitized error responses
- Factored validators (validateSearchProvider factory)
- CORS headers on all responses
- Dashboard: Search & Discovery section, search provider template
- DB migration 007: request_type column in call_logs
- 28 unit tests (registry, cache, coalescing, validation)
2026-03-17 18:28:35 +01:00
diegosouzapw e1da181740 fix(publish): also remove app/electron/ (contains app.asar binary) to prevent Z_DATA_ERROR 2026-03-17 14:25:48 -03:00
diegosouzapw c63209200e fix(publish): remove app/vscode-extension/ after build to prevent Z_DATA_ERROR in npm pack 2026-03-17 14:13:15 -03:00
diegosouzapw 737808cf53 fix(npm): exclude app/vscode-extension/ from package to prevent Z_DATA_ERROR during publish 2026-03-17 13:50:06 -03:00
diegosouzapw a197bb7736 fix(routerStrategy): use .ts extension in imports for Next.js App Router bundle compatibility 2026-03-17 13:15:47 -03:00
dependabot[bot] f9dd967bc5 deps: bump next from 16.1.6 to 16.1.7
Bumps [next](https://github.com/vercel/next.js) from 16.1.6 to 16.1.7.
- [Release notes](https://github.com/vercel/next.js/releases)
- [Changelog](https://github.com/vercel/next.js/blob/canary/release.js)
- [Commits](https://github.com/vercel/next.js/compare/v16.1.6...v16.1.7)

---
updated-dependencies:
- dependency-name: next
  dependency-version: 16.1.7
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-03-17 16:14:44 +00:00
diegosouzapw 44e4d55a66 feat(release): merge feat/clawrouter-improvements — v2.7.0
Build Electron Desktop App / Validate version (push) Failing after 40s
Build Electron Desktop App / Build Electron (macos-arm64) (push) Has been skipped
Build Electron Desktop App / Build Electron (linux) (push) Has been skipped
Build Electron Desktop App / Build Electron (macos-intel) (push) Has been skipped
Build Electron Desktop App / Build Electron (windows) (push) Has been skipped
Build Electron Desktop App / Create Release (push) Has been skipped
2026-03-17 13:12:41 -03:00
diegosouzapw 095c84ac16 fix(providerRegistry): remove duplicate claude-haiku-4-5-20251001 from anthropic provider to prevent ambiguous model resolution 2026-03-17 13:10:23 -03:00
diegosouzapw e063eae727 feat(clawrouter): implement 14 ClawRouter-inspired features
PRICING UPDATES (01-09):
- xAI Grok-4 family: grok-4-fast-non-reasoning (/usr/bin/bash.20/$0.50/M, 1143ms),
  grok-4-fast-reasoning, grok-4-1-fast-*, grok-4-0709, grok-3, grok-3-mini
- Z.AI GLM-5 family: glm-5 + glm-5-turbo (128k maxOutput, $1.00/$3.20/M)
- Gemini Flash Lite: price corrected $0.15→$0.10 / $1.25→$0.40 (per ClawRouter)
- Gemini 3.1 Pro: new flagship (1.05M context, aliased as gemini-3.1-pro)
- Anthropic Claude 4.5/4.6: haiku-4.5 ($1/$5), sonnet-4.6 ($3/$15), opus-4.6 ($5/$25)
- DeepSeek native section: deepseek-chat/v3/v3.2 ($0.28/$0.42), deepseek-reasoner ($0.55/$2.19)
- Kimi K2.5 Moonshot: kimi-k2.5 ($0.60/$3.00, 262k ctx), moonshot-kimi-k2.5 alias
- MiniMax M2.5: minimax-m2.5 ($0.30/$1.20, 204k ctx, reasoning+tools)
- NVIDIA free tier: gpt-oss-120b at $0.00/M via emergencyFallback.ts

INFRASTRUCTURE FEATURES (10-14):
- feat(router): add intentClassifier.ts for multilingual intent detection (9 langs)
  Detects code/reasoning/simple in EN, PT-BR, ES, ZH, JA, RU, DE, KO, AR
- feat(dedup): add requestDedup.ts for concurrent request deduplication
  SHA-256 hash, skip streaming, skip high-temperature, 60s failsafe TTL
- feat(autoCombo): add routerStrategy.ts pluggable strategy system
  RouterStrategy interface, RulesStrategy (6-factor) + CostStrategy, registry
- feat(fallback): add emergencyFallback.ts budget-exhaustion detector
  Triggers on HTTP 402 or budget keywords, redirects to nvidia/gpt-oss-120b
- feat(taskFitness): add fitness scores for Grok-4, Kimi K2.5, GLM-5,
  MiniMax M2.5, DeepSeek V3.2, Gemini 3.1 Pro across all task categories

PROVIDERS:
- providers.ts: add Z.AI (zai) provider entry for GLM-5 API key connections

All features on branch: feat/clawrouter-improvements
Source: github.com/BlockRunAI/ClawRouter analysis (2026-03-17)
2026-03-17 10:43:12 -03:00
diegosouzapw f02c5b5c69 fix(install/v2.6.10): Windows better-sqlite3 prebuilt download (#426)
Build Electron Desktop App / Validate version (push) Failing after 35s
Build Electron Desktop App / Build Electron (macos-arm64) (push) Has been skipped
Build Electron Desktop App / Build Electron (linux) (push) Has been skipped
Build Electron Desktop App / Build Electron (macos-intel) (push) Has been skipped
Build Electron Desktop App / Build Electron (windows) (push) Has been skipped
Build Electron Desktop App / Create Release (push) Has been skipped
npm version patch run BEFORE staging files — this is an ATOMIC commit.

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 (win32-x64/arm64, darwin-x64/arm64)
  WITHOUT requiring node-gyp, Python, or MSVC build tools.
- Tries node-pre-gyp.cmd (Windows) or node-pre-gyp (Unix) from .bin/
  with fallback to direct path in @mapbox/node-pre-gyp/bin/
- Falls back to npm rebuild only if prebuilt download fails.
- Windows-specific error: shows Option A (npx node-pre-gyp) and
  Option B (rebuild) with Visual Studio Build Tools links.

Fixes: #426 (better_sqlite3.node is not a valid Win32 application)
2026-03-17 10:09:45 -03:00
diegosouzapw 838f1d645c fix(v2.6.9): CI budget checks, #409 file attachments, atomic release workflow
Build Electron Desktop App / Validate version (push) Failing after 38s
Build Electron Desktop App / Build Electron (macos-arm64) (push) Has been skipped
Build Electron Desktop App / Build Electron (linux) (push) Has been skipped
Build Electron Desktop App / Build Electron (macos-intel) (push) Has been skipped
Build Electron Desktop App / Build Electron (windows) (push) Has been skipped
Build Electron Desktop App / Create Release (push) Has been skipped
Includes version bump — v2.6.9 — committed ATOMICALLY with all changes:

fixes:
- fix(ci/t11): Remove 'any' from comments in openai-responses.ts + chatCore.ts
  (\bany\b regex counted comment text as explicit any violations)
- fix(chatCore/#409): Normalize unsupported content part types before forwarding
  Cursor sends {type:'file'} for .md attachments; Copilot/OpenAI providers reject
  with 'type has to be either image_url or text'. Now: file/document→text block,
  unknown types dropped with debug log. Fixes claude-* models via github-copilot.

workflow:
- chore(generate-release): ATOMIC COMMIT RULE — npm version patch MUST run before
  feature commits so the release tag always points to a commit with full changes
2026-03-17 09:09:01 -03:00
diegosouzapw ce2c30c437 chore(release): v2.6.8 — combo agents, auto-update, detailed logs, MITM Kiro
Build Electron Desktop App / Validate version (push) Failing after 31s
Build Electron Desktop App / Build Electron (macos-arm64) (push) Has been skipped
Build Electron Desktop App / Build Electron (linux) (push) Has been skipped
Build Electron Desktop App / Build Electron (macos-intel) (push) Has been skipped
Build Electron Desktop App / Build Electron (windows) (push) Has been skipped
Build Electron Desktop App / Create Release (push) Has been skipped
2026-03-17 08:58:03 -03:00
diegosouzapw d56fae0a7b feat: combo agents, auto-update UI, detailed logs, MITM Kiro (#399 #401 #320 #378 #336)
DB Migrations (zero-breaking, ADD COLUMN DEFAULT NULL + new table):
- 005_combo_agent_fields.sql: system_message, tool_filter_regex, context_cache_protection on combos
- 006_detailed_request_logs.sql: ring-buffer table (500 entries) for full pipeline body capture

Features:
- #399 System Message Override + Tool Filter Regex per Combo
  - applyComboAgentMiddleware() injected into handleComboChat/handleRoundRobinCombo
  - Supports both OpenAI and Anthropic tool name formats
- #401 Context Caching Protection (Stateless)
  - injectModelTag() appends <omniModel>provider/model</omniModel> to responses
  - extractPinnedModel() reads tag from history and pins model for session
- #320 Auto-Update via Settings
  - GET /api/system/version — current vs latest npm
  - POST /api/system/update — fire-and-forget npm install + pm2 restart
- #378 Detailed Request Logs
  - saveRequestDetailLog() captures bodies at 4 pipeline stages (opt-in toggle)
  - GET/POST /api/logs/detail — list logs + enable/disable toggle
- #336 MITM Kiro IDE
  - src/mitm/targets/kiro.ts: MitmTarget profile for api.anthropic.com interception
2026-03-17 08:53:41 -03:00
diegosouzapw e45ef00bef chore(release): v2.6.7 — SSE fixes, local provider_nodes, proxy registry
Build Electron Desktop App / Validate version (push) Failing after 32s
Build Electron Desktop App / Build Electron (macos-arm64) (push) Has been skipped
Build Electron Desktop App / Build Electron (linux) (push) Has been skipped
Build Electron Desktop App / Build Electron (macos-intel) (push) Has been skipped
Build Electron Desktop App / Build Electron (windows) (push) Has been skipped
Build Electron Desktop App / Create Release (push) Has been skipped
PRs merged: #414 (deps) #415 #417 #419 #420 #421 (SSE fixes)
            #418 (Claude passthrough) #422 #416 #423 (local nodes)
            #427 (strip empty blocks) #428 (OAuth refreshable)
            #429 (proxy registry)
Contributors: @prakersh, @Regis-RCR, @dependabot
2026-03-17 08:17:11 -03:00
diegosouzapw e9f31f7394 Merge pull request #429 from contributor branch 2026-03-17 08:14:05 -03:00
diegosouzapw 7c10a98eb2 Merge pull request #428 from contributor branch 2026-03-17 08:14:04 -03:00
diegosouzapw f260483101 Merge pull request #427 from contributor branch 2026-03-17 08:14:03 -03:00
diegosouzapw 389e6e5c9e Merge pull request #423 from contributor branch 2026-03-17 08:14:02 -03:00
diegosouzapw 1cfd5866be Merge pull request #422 from contributor branch 2026-03-17 08:14:02 -03:00
diegosouzapw c7ceac7f41 Merge pull request #421 from contributor branch 2026-03-17 08:14:01 -03:00
diegosouzapw cd6eca0424 Merge pull request #420 from contributor branch 2026-03-17 08:14:00 -03:00
diegosouzapw 8c6136fea0 fix(sse): generate fallback call_id for tool calls with missing IDs (#419)
Co-authored-by: Prakersh Maheshwari <prakersh@users.noreply.github.com>
2026-03-17 08:11:53 -03:00
Diego Rodrigues de Sa e Souza 9644444028 Merge pull request #418 from prakersh/fix/claude-to-claude-passthrough
fix(sse): add Claude-to-Claude passthrough for anthropic-compatible providers
2026-03-17 08:09:44 -03:00
Diego Rodrigues de Sa e Souza 9c4154291d Merge pull request #417 from prakersh/fix/orphaned-tool-result-filter
fix(sse): filter orphaned tool results after context compaction
2026-03-17 08:09:41 -03:00
Diego Rodrigues de Sa e Souza 533f5f6da6 Merge pull request #416 from Regis-RCR/feat/audio-provider-nodes
feat(audio): route audio requests to local provider_nodes
2026-03-17 08:09:38 -03:00
Diego Rodrigues de Sa e Souza 1b8de756cd Merge pull request #415 from prakersh/fix/empty-tool-name-loop
fix(sse): skip empty-name tool calls in Responses API translator
2026-03-17 08:09:28 -03:00
Diego Rodrigues de Sa e Souza 650b415537 Merge pull request #414 from diegosouzapw/dependabot/npm_and_yarn/development-cc00f57801
deps: bump the development group with 4 updates
2026-03-17 08:09:25 -03:00
rexname 04b50329fc fix(proxy): address PR review findings for auth, credentials, and health stats 2026-03-17 16:58:44 +07:00
Regis 25aab8c55c feat(audio): route audio requests to local provider_nodes
Audio endpoints (/v1/audio/speech and /v1/audio/transcriptions) only
supported hardcoded providers from audioRegistry.ts. Local inference
backends configured as provider_nodes (e.g., MLX-Audio, oMLX) could
not serve audio through OmniRoute.

This adds a Phase 3 fallback in the audio model parser that consults
provider_nodes from the database. Local providers with api_type=openai
are automatically available for audio routing via their prefix
(e.g., mlx-audio/tts-model, omlx/whisper-large-v3-turbo).

Design: injection pattern — Next.js route handlers load provider_nodes
(async DB query) and pass them to the sync parser as a parameter.
No cross-workspace imports, no breaking changes to existing parsers.

Changes:
- Add buildDynamicAudioProvider() in audioRegistry.ts
- Add Phase 3 (provider_nodes prefix match) to parseAudioModel()
- Extend parseSpeechModel/parseTranscriptionModel with optional
  dynamicProviders parameter (backward compatible)
- Load and inject provider_nodes in speech/transcription route handlers
- Dynamic providers use authType=none (local, no credentials needed)
2026-03-17 09:24:18 +01:00
Oleg Saprykin ceda2e70c1 fix(api): add refreshable: true to claude OAuth test config
Claude OAuth tokens are short-lived and require refresh. The runtime
HealthCheck (open-sse) already refreshes them successfully, but the
Dashboard test endpoint was missing `refreshable: true` in its config.

This caused the Dashboard to show "auth failed / Token expired" for
Claude providers even though the tokens were being refreshed correctly
at runtime. The codex provider already had this flag set.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-17 10:47:35 +03:00
Oleg Saprykin 2908303d4b fix(sse): strip empty text content blocks before translation
Anthropic API rejects requests containing {"type":"text","text":""} with
400 "text content blocks must be non-empty". Some clients like LiteLLM
passthrough and @ai-sdk/anthropic may forward empty text blocks as-is.

Filter out empty text content blocks from messages before calling
translateRequest, similar to how empty-name tools are already stripped.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-17 10:46:24 +03:00
diegosouzapw a9f69711c6 fix(build): remove node: protocol prefix from all src/ imports (#turbopack-compat)
Build Electron Desktop App / Validate version (push) Failing after 39s
Build Electron Desktop App / Build Electron (macos-arm64) (push) Has been skipped
Build Electron Desktop App / Build Electron (linux) (push) Has been skipped
Build Electron Desktop App / Build Electron (macos-intel) (push) Has been skipped
Build Electron Desktop App / Build Electron (windows) (push) Has been skipped
Build Electron Desktop App / Create Release (push) Has been skipped
Turbopack (Next.js 15) does not process node: URL prefixes correctly when
bundling server-side files that get transitively included. Removed the node:
prefix from 17 files:

- src/lib/db/migrationRunner.ts (node:fs, node:path, node:url)
- src/lib/db/core.ts (node:path, node:fs)
- src/lib/db/backup.ts (node:path, node:fs)
- src/lib/db/prompts.ts (node:fs)
- src/lib/dataPaths.ts (node:path, node:os)
- src/app/api/settings/route.ts
- src/app/api/storage/health/route.ts
- src/app/api/oauth/[provider]/[action]/route.ts
- src/app/api/db-backups/{exportAll,import,export}/route.ts
- src/shared/middleware/correlationId.ts
- src/shared/utils/requestId.ts
- src/lib/apiBridgeServer.ts
- src/lib/cacheLayer.ts
- src/lib/semanticCache.ts
- src/lib/oauth/providers/kimi-coding.ts

Also updated generate-release.md: Docker Hub sync and dual-VPS deploy
are now mandatory steps in every release.
2026-03-17 04:24:46 -03:00
diegosouzapw a8ab16a720 chore(release): v2.6.5 — reasoning params filter, local 404 fix, Kilo Gateway, dep bumps
Build Electron Desktop App / Validate version (push) Failing after 24s
Build Electron Desktop App / Build Electron (macos-arm64) (push) Has been skipped
Build Electron Desktop App / Build Electron (linux) (push) Has been skipped
Build Electron Desktop App / Build Electron (macos-intel) (push) Has been skipped
Build Electron Desktop App / Build Electron (windows) (push) Has been skipped
Build Electron Desktop App / Create Release (push) Has been skipped
- fix(sse): strip unsupported params for o1/o1-mini/o1-pro/o3/o3-mini (PR #412 @Regis-RCR)
- fix(sse): model-only lockout (5s) for local provider 404 (PR #410 @Regis-RCR)
- feat(api): Kilo Gateway provider — 335+ models, alias 'kg' (PR #408 @Regis-RCR)
- deps: better-sqlite3 12.8, undici 7.24.4, https-proxy-agent 8 (PR #413)
2026-03-17 03:05:45 -03:00
rexname 8091b6b508 feat: implement proxy registry, management APIs, docs, and test hardening 2026-03-17 13:05:27 +07:00
Diego Rodrigues de Sa e Souza a00ef0fc7e Merge pull request #413 from diegosouzapw/dependabot/npm_and_yarn/production-4d4ff746af
deps: bump the production group with 5 updates
2026-03-17 03:03:49 -03:00
Diego Rodrigues de Sa e Souza 5ce6d615a4 Merge pull request #408 from Regis-RCR/feat/kilo-gateway-provider
feat(api): add Kilo Gateway provider
2026-03-17 03:03:47 -03:00
Diego Rodrigues de Sa e Souza e06b69cdac Merge pull request #410 from Regis-RCR/fix/local-404-cascade
fix(sse): model-only lockout for local provider 404
2026-03-17 03:03:31 -03:00
Diego Rodrigues de Sa e Souza d261ae7883 Merge pull request #412 from Regis-RCR/fix/param-filter-reasoning
fix(sse): strip unsupported params for reasoning models (o1/o3)
2026-03-17 03:03:28 -03:00
diegosouzapw 6fa77a63d7 chore(release): v2.6.4 — model name fixes across providers 2026-03-17 01:59:25 -03:00
diegosouzapw f76c1b32d6 fix(providers): remove non-existent model names and fix incorrect model IDs
- gemini/gemini-cli: removed gemini-3.1-pro/flash/preview (don't exist in Google API v1beta),
  replaced with real models: gemini-2.5-pro, gemini-2.5-flash, gemini-2.0-flash, gemini-1.5-*
- antigravity: removed gemini-3.1-pro-high/low and gemini-3-flash (internal aliases invalid),
  replaced with gemini-2.5-pro, gemini-2.5-flash, gemini-2.0-flash
- github: removed gemini-3-flash-preview and gemini-3-pro-preview, replaced with gemini-2.5-flash
- nvidia: corrected 'nvidia/llama-3.3-70b-instruct' to 'meta/llama-3.3-70b-instruct'
  (NVIDIA NIM uses meta/ namespace, not nvidia/ namespace for Meta models)
- nvidia: added meta/llama-3.1-70b-instruct and nvidia/llama-3.1-405b-instruct

Also fixed free-stack combo on .15 DB:
- removed qw/qwen3-coder-plus (qwen provider has 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 as replacement for qw/qwen3-coder-plus
2026-03-17 01:48:40 -03:00
Regis 0aede2ef63 feat(health): background health check for local provider_nodes
Local inference backends (oMLX, Ollama, LM Studio) configured as
provider_nodes have no health monitoring. When a local provider is
down, OmniRoute waits the full timeout before failing.

This adds a background health check that polls local provider_nodes:
- GET /models with 5s timeout for each local node (localhost only)
- In-memory health cache (no DB migration needed)
- Promise.allSettled for parallel checks (one slow node doesn't block)
- Exponential backoff on failures: 30s → 60s → 120s → 300s max
- Reset to 30s on first success after failure
- State transition logging (healthy ↔ unhealthy)
- Expose health status via GET /api/monitoring/health (localProviders)
- Auto-init on first import (same pattern as tokenHealthCheck)
- 401 treated as healthy (server up, auth required)
- isNodeHealthy() returns true if never checked (optimistic default)
2026-03-16 22:44:43 +01:00
Regis 1e3a2e0a27 feat(embeddings): route embedding requests to local provider_nodes
Embedding endpoint (/v1/embeddings) only supports 6 hardcoded cloud
providers. Local inference backends (oMLX, Ollama) serving embeddings
via provider_nodes are inaccessible through OmniRoute.

This adds dynamic provider_node support for embeddings:
- Add EmbeddingProvider interface and buildDynamicEmbeddingProvider()
- Add Phase 2 (provider_nodes prefix match) in parseEmbeddingModel()
- Handler accepts resolvedProvider/resolvedModel from route (injection pattern)
- Handler supports authType=none for local providers (was missing — critical gap)
- Route loads local provider_nodes (localhost only — prevents auth bypass/SSRF)
- Route filters by apiType=chat|responses and localhost hostname
- buildDynamicEmbeddingProvider validates inputs (prefix + baseUrl required)
- Per-node try/catch in map — one bad row doesn't block all providers
- DB errors logged and fall back to hardcoded providers
2026-03-16 22:15:49 +01:00
Prakersh Maheshwari 1bdabf43db fix: prevent mutation of original request body in Claude passthrough
Use shallow copy ({ ...body }) instead of direct reference assignment
so that later translatedBody.model = model does not mutate the
caller's original body object.
2026-03-17 02:45:21 +05:30
Prakersh Maheshwari 05e568feb0 fix(sse): extract Claude SSE usage in passthrough stream mode 2026-03-17 02:41:54 +05:30
Prakersh Maheshwari 81e2519436 refactor: replace as any casts with explicit inline types
Addresses PR review: use `{ id?: string }[]` and
`{ type?: string; call_id?: string }` instead of `any`.
2026-03-17 02:40:36 +05:30
Prakersh Maheshwari ef623c9bb5 refactor: trim function name consistently in Responses-to-Chat direction
Addresses PR review: both translation directions now trim the function
name the same way, matching the Chat-to-Responses pattern.
2026-03-17 02:35:42 +05:30
Prakersh Maheshwari da581525a6 fix(sse): strip Claude-specific fields in OpenAI format cleanup 2026-03-17 02:16:26 +05:30
Prakersh Maheshwari 6ff7b6570c fix(sse): add Claude-to-Claude passthrough for anthropic-compatible providers
When both source and target formats are Claude, skip all request
modification and forward the body untouched. This prevents
prepareClaudeRequest from corrupting valid Claude-native requests
destined for anthropic-compatible provider nodes.
2026-03-17 02:03:45 +05:30
Prakersh Maheshwari 8b2081837e fix(sse): filter orphaned tool results after context compaction
When Claude Code compacts conversation context to fit within token
limits, it may remove assistant messages containing tool_use/tool_calls
while leaving the corresponding tool_result/function_call_output
messages intact. This creates orphaned tool results that cause
providers to reject requests with errors like "tool result's tool id
not found" or "No tool call found for function call output".
2026-03-17 01:59:40 +05:30
Prakersh Maheshwari ce978b602a fix(sse): skip empty-name tool calls in Responses API translator
Prevents infinite retry loops when models generate tool calls with
empty function names. The normalizeToolName function converted these
to "placeholder_tool" which does not exist in any client's tool
registry, causing repeated error-retry cycles.
2026-03-17 01:47:22 +05:30
dependabot[bot] 9b00f5d550 deps: bump the development group with 4 updates
Bumps the development group with 4 updates: [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node), [lint-staged](https://github.com/lint-staged/lint-staged), [typescript-eslint](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/typescript-eslint) and [vitest](https://github.com/vitest-dev/vitest/tree/HEAD/packages/vitest).


Updates `@types/node` from 25.4.0 to 25.5.0
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node)

Updates `lint-staged` from 16.3.2 to 16.4.0
- [Release notes](https://github.com/lint-staged/lint-staged/releases)
- [Changelog](https://github.com/lint-staged/lint-staged/blob/main/CHANGELOG.md)
- [Commits](https://github.com/lint-staged/lint-staged/compare/v16.3.2...v16.4.0)

Updates `typescript-eslint` from 8.57.0 to 8.57.1
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/typescript-eslint/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v8.57.1/packages/typescript-eslint)

Updates `vitest` from 4.0.18 to 4.1.0
- [Release notes](https://github.com/vitest-dev/vitest/releases)
- [Commits](https://github.com/vitest-dev/vitest/commits/v4.1.0/packages/vitest)

---
updated-dependencies:
- dependency-name: "@types/node"
  dependency-version: 25.5.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: development
- dependency-name: lint-staged
  dependency-version: 16.4.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: development
- dependency-name: typescript-eslint
  dependency-version: 8.57.1
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: development
- dependency-name: vitest
  dependency-version: 4.1.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: development
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-03-16 19:04:07 +00:00
dependabot[bot] d98ec59c79 deps: bump the production group with 5 updates
Bumps the production group with 5 updates:

| Package | From | To |
| --- | --- | --- |
| [better-sqlite3](https://github.com/WiseLibs/better-sqlite3) | `12.6.2` | `12.8.0` |
| [https-proxy-agent](https://github.com/TooTallNate/proxy-agents/tree/HEAD/packages/https-proxy-agent) | `7.0.6` | `8.0.0` |
| [undici](https://github.com/nodejs/undici) | `7.24.2` | `7.24.4` |
| [wreq-js](https://github.com/sqdshguy/wreq-js) | `2.1.1` | `2.2.0` |
| [zustand](https://github.com/pmndrs/zustand) | `5.0.11` | `5.0.12` |


Updates `better-sqlite3` from 12.6.2 to 12.8.0
- [Release notes](https://github.com/WiseLibs/better-sqlite3/releases)
- [Commits](https://github.com/WiseLibs/better-sqlite3/compare/v12.6.2...v12.8.0)

Updates `https-proxy-agent` from 7.0.6 to 8.0.0
- [Release notes](https://github.com/TooTallNate/proxy-agents/releases)
- [Changelog](https://github.com/TooTallNate/proxy-agents/blob/main/packages/https-proxy-agent/CHANGELOG.md)
- [Commits](https://github.com/TooTallNate/proxy-agents/commits/https-proxy-agent@8.0.0/packages/https-proxy-agent)

Updates `undici` from 7.24.2 to 7.24.4
- [Release notes](https://github.com/nodejs/undici/releases)
- [Commits](https://github.com/nodejs/undici/compare/v7.24.2...v7.24.4)

Updates `wreq-js` from 2.1.1 to 2.2.0
- [Release notes](https://github.com/sqdshguy/wreq-js/releases)
- [Commits](https://github.com/sqdshguy/wreq-js/compare/v2.1.1...v2.2.0)

Updates `zustand` from 5.0.11 to 5.0.12
- [Release notes](https://github.com/pmndrs/zustand/releases)
- [Commits](https://github.com/pmndrs/zustand/compare/v5.0.11...v5.0.12)

---
updated-dependencies:
- dependency-name: better-sqlite3
  dependency-version: 12.8.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: production
- dependency-name: https-proxy-agent
  dependency-version: 8.0.0
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: production
- dependency-name: undici
  dependency-version: 7.24.4
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: production
- dependency-name: wreq-js
  dependency-version: 2.2.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: production
- dependency-name: zustand
  dependency-version: 5.0.12
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: production
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-03-16 19:03:12 +00:00
Regis d79b55be5a fix(sse): strip unsupported params for reasoning models (o1/o3)
Reasoning models (o1, o1-pro, o3, o3-mini) reject standard parameters
like temperature and top_p with 400 Bad Request. OmniRoute's default
executor forwards all parameters without filtering.

This fix adds declarative parameter filtering:
- Add unsupportedParams[] field to RegistryModel interface
- Add REASONING_UNSUPPORTED frozen constant shared across entries
- Add o1-pro, o3, o3-mini to OpenAI registry (were missing)
- Add getUnsupportedParams() helper with:
  - O(1) precomputed map lookup (not O(N×M) scan)
  - Cross-provider routing support via precomputed map
  - Prefixed model ID support (e.g., "openai/o3" → "o3")
- Strip unsupported params in chatCore.ts before executor call
- Use Object.hasOwn() for safe property check (no prototype chain)
- Log stripped params at WARN level for visibility
2026-03-16 19:41:55 +01:00
Regis 1f9a402dcd fix(sse): address bot review — tighten local detection, guard null model
- Remove apiKey===null heuristic (too broad — could match cloud providers
  with non-standard auth). Use URL-based detection only.
- Guard local 404 branch with provider && model check — if either is null,
  fall through to standard connection lockout (safer behavior).
- Document LOCAL_HOSTNAMES as module-load-time constant (restart required).
- Document PROVIDER_PROFILES.local as intentionally not yet wired.
2026-03-16 19:03:47 +01:00
Regis f9bcc9418b fix(sse): model-only lockout for local provider 404 (connection stays active)
When a local inference backend (oMLX, Ollama, LM Studio) returns 404
for an unknown model, OmniRoute previously locked the entire connection
for 2 minutes — blocking all valid models on that connection.

This fix introduces local provider detection and changes the 404
behavior for local providers:
- Model-only lockout (5s) instead of connection-level lockout (2min)
- Connection stays active — other models continue working immediately
- Detection via URL heuristic (localhost/127.0.0.1) + apiKey===null fallback
- Configurable via LOCAL_HOSTNAMES env var for Docker setups

Also fixes a pre-existing bug where the model parameter was not passed
to markAccountUnavailable() from chat.ts, preventing per-model lockouts
from working at all.

Changes:
- Add isLocalProvider(baseUrl) helper in providerRegistry.ts
- Add COOLDOWN_MS.notFoundLocal (5s) and PROVIDER_PROFILES.local
- Add local 404 branch in markAccountUnavailable() in auth.ts
- Pass model param to markAccountUnavailable() in chat.ts (bug fix)
2026-03-16 18:55:41 +01:00
Regis 08256a3502 feat(api): add Kilo Gateway provider (335+ models, 6 free, auto-routing)
Kilo Gateway (api.kilo.ai/api/gateway) is an OpenAI-compatible API
offering 335+ models via a single API key, including 6 free models
and 3 auto-routing models (frontier/balanced/free).

This is distinct from the existing KiloCode provider which uses
OAuth + /api/openrouter/ endpoint.

- Register kilo-gateway in providerRegistry.ts (alias: kg)
- Add to APIKEY_PROVIDERS in providers.ts
- Add models endpoint config in route.ts
- Add official Kilo AI icon (favicon)
2026-03-16 17:26:27 +01:00
diegosouzapw 9b255e643a chore(release): v2.6.3 — compile-time hash-strip fix, Synthetic provider (PR #404), VPS PM2 path fix
Build Electron Desktop App / Validate version (push) Failing after 42s
Build Electron Desktop App / Build Electron (macos-arm64) (push) Has been skipped
Build Electron Desktop App / Build Electron (linux) (push) Has been skipped
Build Electron Desktop App / Build Electron (macos-intel) (push) Has been skipped
Build Electron Desktop App / Build Electron (windows) (push) Has been skipped
Build Electron Desktop App / Create Release (push) Has been skipped
2026-03-16 11:00:43 -03:00
Diego Rodrigues de Sa e Souza ca1f918e9e Merge pull request #404 from Regis-RCR/feat/synthetic-provider
feat(api): add Synthetic as a new API key provider
2026-03-16 10:59:13 -03:00
diegosouzapw bb3fe1cd48 fix(build): strip Turbopack hashed require() from compiled server chunks in prepublish
Even with EXPERIMENTAL_TURBOPACK=0 and NEXT_PRIVATE_BUILD_WORKER=0, Next.js 16
instrumentation chunks still emit require('better-sqlite3-<16hexchars>') and
require('zod-<16hexchars>') into the compiled .js files inside .next/server/.

The webpack externals function in next.config.mjs patches the runtime bundler
but does NOT rewrite already-compiled chunks. Added step 5.6 to prepublish.mjs:
walks all .js files in app/.next/server/ and strips the 16-char hex suffix from
any require() string that matches the Turbopack hash pattern.

Also updated deploy-vps workflow: npm registry rejects 299MB packages, so
deployment now uses npm pack + scp + npm install -g /tmp/omniroute-*.tgz.
PM2 entry point is app/server.js inside the npm global package.
2026-03-16 10:46:27 -03:00
diegosouzapw 5d7772ecb0 chore(release): v2.6.2 — fix all module hashing, Anthropic tools filter, custom endpoint paths, Alibaba Cloud provider
Build Electron Desktop App / Validate version (push) Failing after 33s
Build Electron Desktop App / Build Electron (macos-arm64) (push) Has been skipped
Build Electron Desktop App / Build Electron (linux) (push) Has been skipped
Build Electron Desktop App / Build Electron (macos-intel) (push) Has been skipped
Build Electron Desktop App / Build Electron (windows) (push) Has been skipped
Build Electron Desktop App / Create Release (push) Has been skipped
2026-03-16 09:53:32 -03:00
Diego Rodrigues de Sa e Souza 56ce618eca Merge pull request #400 from Regis-RCR/feat/custom-endpoint-paths
feat(api): custom endpoint paths for compatible provider nodes
2026-03-16 09:46:22 -03:00
diegosouzapw 605c3f9be1 feat(provider): add Alibaba Cloud DashScope + path validation for custom endpoint paths
- Add Alibaba Cloud (DashScope) as OpenAI-compatible provider with 12 Qwen models:
  qwen-max, qwen-plus, qwen-turbo, qwen3-coder-plus/flash, qwq-plus,
  qwq-32b, qwen3-32b, qwen3-235b-a22b
  International endpoint: dashscope-intl.aliyuncs.com/compatible-mode/v1
  Auth: Bearer API key (same as groq/xai/mistral)

- Add path traversal protection to custom endpoint paths (PR #400):
  sanitizePath() validates chatPath/modelsPath values:
  must start with '/', no '..' segments, no null bytes, max 512 chars

Closes #400 (custom endpoint paths), part of Alibaba provider integration
2026-03-16 09:44:17 -03:00
Diego Rodrigues de Sa e Souza b0381c7542 Merge pull request #397 from xandr0s/fix/tools-filter-claude-format
fix(chat): handle Anthropic-format tools in empty-name filter (#346)
2026-03-16 09:40:39 -03:00
diegosouzapw 2f0894c220 test: add unit tests for Anthropic-format tools filter fix (PR #397)
8 tests covering:
- Valid OpenAI format tools (tool.function.name) preserved
- Valid Anthropic format tools (tool.name) preserved
- Empty names in both formats filtered
- Mixed format array handling
- Null/whitespace edge cases

Regression tests verify the fix from PR #397 prevents all anthropic-
format tools from being silently dropped by the empty-name filter.
2026-03-16 09:38:34 -03:00
Diego Rodrigues de Sa e Souza b328ed5fa9 Merge pull request #403 from diegosouzapw/fix/issue-396-398-hashed-externals-all-packages
fix(build): extend externals hash-strip to cover ALL Turbopack-hashed packages (#396, #398)
2026-03-16 09:37:05 -03:00
diegosouzapw 7d72f1711f fix(build): extend externals hash-strip to cover ALL packages, not just better-sqlite3 (#396, #398)
Turbopack in Next.js 16 hashes ALL serverExternalPackages (not just better-sqlite3),
emitting require() calls like 'zod-dcb22c6336e0bc69', 'pino-28069d5257187539' etc.
that don't exist in node_modules.

Changes:
- next.config.mjs: Replace single-package check with a HASH_PATTERN regex
  that strips '<name>-<16hexchars>' suffix for any externalized package.
  Also adds KNOWN_EXTERNALS set for exact-name matching.
- scripts/prepublish.mjs: Add NEXT_PRIVATE_BUILD_WORKER=0 env to reinforce
  webpack mode. Add post-build scan that reports hashed refs so CI is visible.

Closes #396, addresses #398
2026-03-16 09:34:34 -03:00
Regis d139b4557f feat(api): add Synthetic as a new API key provider
Add Synthetic (synthetic.new) as a privacy-focused LLM provider
with OpenAI-compatible API, dynamic model catalog via /models
endpoint, and passthrough model support.

- Register provider in providerRegistry.ts with 6 initial models
- Add APIKEY_PROVIDERS entry with verified_user icon (#6366F1)
- Add models listing config for /api/providers/[id]/models endpoint
- passthroughModels enabled for dynamic model catalog
2026-03-16 12:39:23 +01:00
Regis cd05e03d63 fix(review): simplify cascade logic and add ARIA attributes
Address review feedback:
- Simplify providerSpecificData cascade for chatPath/modelsPath
  using `|| undefined` instead of conditional spreads (Gemini)
- Add aria-expanded, aria-controls, aria-hidden to Advanced
  Settings toggle buttons for accessibility (Copilot)
2026-03-16 11:29:06 +01:00
Regis e25029939d feat(api): add custom endpoint paths for compatible provider nodes
Allow provider_nodes to configure custom chat and models endpoint
paths via chatPath/modelsPath fields. This enables providers with
non-standard versioned APIs (e.g. /v4/chat/completions) to work
without embedding the version prefix in base_url.

- Add migration 003: chat_path and models_path columns
- Update Zod schemas (create, update, validate)
- Update CRUD in providers.ts (INSERT/UPDATE)
- Wire chatPath/modelsPath through API routes and providerSpecificData cascade
- Read chatPath in DefaultExecutor and BaseExecutor buildUrl()
- Use modelsPath in validate endpoint
- Add Advanced Settings UI section (collapsible) in create/edit modals
- Update base URL hint to reference Advanced Settings
- Add i18n keys across all 30 locales
- Add unit tests for buildUrl with custom paths

Backward compatible: NULL chatPath/modelsPath = default behavior.
2026-03-16 10:23:44 +01:00
Oleg Saprykin 53de27417d fix(chat): handle Anthropic-format tools in empty-name filter (#346)
The filter introduced in #346 only checked OpenAI-format tool names
(tool.function.name), silently dropping all tools when the request
arrives in Anthropic Messages API format (tool.name without .function).

This happens when LiteLLM proxies requests with anthropic/ model prefix —
it translates to Anthropic format before forwarding, so OmniRoute receives
Claude-format tools. The filter drops them all, causing Anthropic API to
return 400: 'tool_choice.any may only be specified while providing tools'.

Fix: check both formats with fn?.name ?? tool.name.
2026-03-16 11:37:40 +03:00
diegosouzapw 74d3374d5c chore(release): v2.6.1 — fix better-sqlite3 startup crash on npm global installs (#394)
Build Electron Desktop App / Validate version (push) Failing after 30s
Build Electron Desktop App / Build Electron (macos-arm64) (push) Has been skipped
Build Electron Desktop App / Build Electron (linux) (push) Has been skipped
Build Electron Desktop App / Build Electron (macos-intel) (push) Has been skipped
Build Electron Desktop App / Build Electron (windows) (push) Has been skipped
Build Electron Desktop App / Create Release (push) Has been skipped
2026-03-15 21:51:35 -03:00
Diego Rodrigues de Sa e Souza 3ae00bebe4 Merge pull request #395 from diegosouzapw/fix/issue-394-better-sqlite3-module-resolution
fix(build): force better-sqlite3 webpack external to prevent hash-based module name in instrumentation hook (#394)
2026-03-15 21:47:46 -03:00
diegosouzapw f9df72c4d7 fix(build): force better-sqlite3 webpack external to prevent hash-based module name in instrumentation hook (#394) 2026-03-15 21:45:19 -03:00
diegosouzapw d0fb4576a8 ci: add workflow_dispatch to npm-publish, fix version sync for manual triggers 2026-03-15 20:20:44 -03:00
Diego Rodrigues de Sa e Souza 0e4b0b3540 Merge pull request #393 from diegosouzapw/fix/issue-392-docker-workflow
fix: add workflow_dispatch to docker-publish, update action versions (#392)
2026-03-15 20:11:54 -03:00
diegosouzapw df1105d0c6 fix: add workflow_dispatch to docker-publish, update action versions (#392) 2026-03-15 20:06:49 -03:00
diegosouzapw 44478c36a3 chore(release): v2.6.0 — issue resolution sprint (#390 #340 #344 #377 #378 #337)
Build Electron Desktop App / Validate version (push) Failing after 35s
Build Electron Desktop App / Build Electron (macos-arm64) (push) Has been skipped
Build Electron Desktop App / Build Electron (linux) (push) Has been skipped
Build Electron Desktop App / Build Electron (macos-intel) (push) Has been skipped
Build Electron Desktop App / Build Electron (windows) (push) Has been skipped
Build Electron Desktop App / Create Release (push) Has been skipped
2026-03-15 19:15:38 -03:00
Diego Rodrigues de Sa e Souza fa267274b0 Merge pull request #386 from kfiramar/chore-test-script-loader-consistency
chore(tests): align targeted test runners
2026-03-15 19:08:47 -03:00
Diego Rodrigues de Sa e Souza 0db272946a Merge pull request #391 from diegosouzapw/fix/multi-issues-390-340-378
fix(media,auth,oauth): hide unconfigured local providers, round-robin improvement, OAuth popup fix
2026-03-15 19:08:45 -03:00
diegosouzapw 91015b6499 fix(media,auth,oauth): hide unconfigured local providers, improve round-robin, fix OAuth popup (#390 #340 #344) 2026-03-15 18:48:40 -03:00
diegosouzapw 2979a36a7c chore(release): v2.5.9 — codex passthrough + route validation + JWT persist
Build Electron Desktop App / Validate version (push) Failing after 33s
Build Electron Desktop App / Build Electron (macos-arm64) (push) Has been skipped
Build Electron Desktop App / Build Electron (linux) (push) Has been skipped
Build Electron Desktop App / Build Electron (macos-intel) (push) Has been skipped
Build Electron Desktop App / Build Electron (windows) (push) Has been skipped
Build Electron Desktop App / Create Release (push) Has been skipped
2026-03-15 15:46:06 -03:00
Diego Rodrigues de Sa e Souza 72f6d6b7b9 Merge pull request #388 from kfiramar/fix-route-validation-t06
fix(build,api): restore production build and validate route bodies
2026-03-15 15:43:32 -03:00
Diego Rodrigues de Sa e Souza d81a7bcedf Merge pull request #387 from kfiramar/feat-codex-native-responses-parity
All tests pass except pre-existing clearAccountError module resolution (dataPaths) which is unrelated to this PR. Merging codex native passthrough fix.
2026-03-15 15:43:11 -03:00
Kfir Amar 8fbbe8b82b Revert "fix(api): validate pricing sync and task routing routes"
This reverts commit 7c992ffd21.
2026-03-15 20:37:18 +02:00
Kfir Amar 271f5f9c64 Revert "fix(api): validate pricing sync and task routing routes"
This reverts commit fc2af8ba87.
2026-03-15 20:37:18 +02:00
Kfir Amar 7c992ffd21 fix(api): validate pricing sync and task routing routes 2026-03-15 20:30:00 +02:00
Kfir Amar fc2af8ba87 fix(api): validate pricing sync and task routing routes 2026-03-15 20:30:00 +02:00
Kfir Amar c8a539a6cb fix(review): surface secret fallback and tighten error typing 2026-03-15 20:25:12 +02:00
Kfir Amar b7cdaa662a fix(api): validate pricing sync and task routing routes 2026-03-15 20:25:12 +02:00
Kfir Amar 0a25930020 fix(mitm): use standalone-safe server entrypoint 2026-03-15 20:25:12 +02:00
Kfir Amar 8643f4015f fix(build): restore webpack production build 2026-03-15 20:25:11 +02:00
diegosouzapw 1854711aff fix(build): fix Next.js 16 Turbopack standalone build for npm publish
- instrumentation.ts: eval(require) → createRequire (banned in Turbopack edge runtime)
- mitm/manager.ts: static imports → lazy require getters to prevent Turbopack trace
- mitm/manager.stub.ts: build-time stub for turbopack.resolveAlias
- antigravity-mitm/route.ts: dynamic imports + nodejs runtime + remove use server
- next.config.mjs: turbopack.resolveAlias for mitm stub + expanded serverExternalPackages
- prepublish.mjs: remove --webpack flag (removed in Next.js 15+)
2026-03-15 15:18:00 -03:00
diegosouzapw c905119d82 fix(build): remove --webpack from prepublish.mjs — fixes VPS app/server.js missing in npm package
Build Electron Desktop App / Validate version (push) Failing after 41s
Build Electron Desktop App / Build Electron (macos-arm64) (push) Has been skipped
Build Electron Desktop App / Build Electron (linux) (push) Has been skipped
Build Electron Desktop App / Build Electron (macos-intel) (push) Has been skipped
Build Electron Desktop App / Build Electron (windows) (push) Has been skipped
Build Electron Desktop App / Create Release (push) Has been skipped
2026-03-15 14:56:20 -03:00
diegosouzapw c581ca8339 fix(build): remove deprecated --webpack flag from next build script 2026-03-15 14:05:46 -03:00
diegosouzapw ccf9d9214a chore(release): v2.5.7 — media playground error handling fixes
Build Electron Desktop App / Validate version (push) Failing after 29s
Build Electron Desktop App / Build Electron (macos-arm64) (push) Has been skipped
Build Electron Desktop App / Build Electron (linux) (push) Has been skipped
Build Electron Desktop App / Build Electron (macos-intel) (push) Has been skipped
Build Electron Desktop App / Build Electron (windows) (push) Has been skipped
Build Electron Desktop App / Create Release (push) Has been skipped
2026-03-15 13:55:28 -03:00
diegosouzapw d37c8b732f fix(media): proper JSON error responses + fix false-positive empty transcript credential error 2026-03-15 13:54:33 -03:00
diegosouzapw f707fc1cad fix(media): proper JSON error responses + fix false-positive empty transcript credential error 2026-03-15 13:52:34 -03:00
Kfir Amar b1c713de60 fix(codex): avoid mutating request body 2026-03-15 18:35:43 +02:00
Kfir Amar 0f13965391 chore(tests): align targeted test runners 2026-03-15 18:25:22 +02:00
Kfir Amar 8642e2b721 fix(codex): preserve native responses payloads 2026-03-15 18:25:22 +02:00
diegosouzapw 441534853b chore(release): v2.5.6 — Antigravity OAuth fix, JWT session persistence
Build Electron Desktop App / Validate version (push) Failing after 29s
Build Electron Desktop App / Build Electron (macos-arm64) (push) Has been skipped
Build Electron Desktop App / Build Electron (linux) (push) Has been skipped
Build Electron Desktop App / Build Electron (macos-intel) (push) Has been skipped
Build Electron Desktop App / Build Electron (windows) (push) Has been skipped
Build Electron Desktop App / Create Release (push) Has been skipped
2026-03-15 13:05:52 -03:00
Diego Rodrigues de Sa e Souza 82f42c8664 Merge pull request #385 from diegosouzapw/fix/issue-382-jwt-persistence
fix: persist JWT_SECRET to SQLite so restarts don't invalidate sessions (#382)
2026-03-15 13:04:57 -03:00
Diego Rodrigues de Sa e Souza 5cd318fa9a Merge pull request #384 from diegosouzapw/fix/issue-383-antigravity-oauth-secret
fix: add Antigravity OAuth clientSecret fallback (#383)
2026-03-15 13:04:55 -03:00
diegosouzapw 5506071e9a fix: add Antigravity OAuth clientSecret fallback — empty string caused 'client_secret is missing' (#383) 2026-03-15 12:58:51 -03:00
diegosouzapw ced98f2da7 fix: persist JWT_SECRET to SQLite so restarts don't invalidate sessions (#382) 2026-03-15 12:56:52 -03:00
diegosouzapw 282ec65e8b docs(i18n): sync FEATURES.md v2.5.5 update to 30 languages 2026-03-15 12:45:20 -03:00
diegosouzapw 8e06dc5ace chore(release): v2.5.5 — model list dedup, Electron build hardening, Kiro credit tracking
Build Electron Desktop App / Validate version (push) Failing after 25s
Build Electron Desktop App / Build Electron (macos-arm64) (push) Has been skipped
Build Electron Desktop App / Build Electron (linux) (push) Has been skipped
Build Electron Desktop App / Build Electron (macos-intel) (push) Has been skipped
Build Electron Desktop App / Build Electron (windows) (push) Has been skipped
Build Electron Desktop App / Create Release (push) Has been skipped
2026-03-15 12:34:58 -03:00
Diego Rodrigues de Sa e Souza bfd3e2c01b Merge pull request #381 from diegosouzapw/feat/issue-337-kiro-credits
feat: add Kiro credit tracking in usage fetcher (#337)
2026-03-15 12:33:14 -03:00
Diego Rodrigues de Sa e Souza a1957f0923 Merge pull request #380 from diegosouzapw/fix/issue-353-model-list-dedup
fix: include provider aliases in active provider filter (#353)
2026-03-15 12:33:13 -03:00
Diego Rodrigues de Sa e Souza 11a02ba361 Merge pull request #379 from kfiramar/fix/electron-standalone-bundle-pr
fix(electron): reject symlinked standalone bundles
2026-03-15 08:52:44 -03:00
diegosouzapw 4643c19abc feat: add Kiro credit tracking in usage fetcher (#337) 2026-03-15 08:47:27 -03:00
diegosouzapw a3369df62f fix: include provider aliases in active provider filter (#353) 2026-03-15 08:44:05 -03:00
Kfir Amar 4297c42597 chore(electron): add contextual staging errors 2026-03-15 12:33:16 +02:00
Kfir Amar e06e7157ac fix(electron): sanitize staged bundle paths cross-platform
Match both slash styles when removing build-machine paths from the
staged standalone bundle so the sanitization step works on Windows
and POSIX builds.

While touching the helper, replace the custom basename logic with
Node's built-in `path.basename` for clarity.
2026-03-15 12:26:23 +02:00
Kfir Amar 22f9e6f4c0 fix(electron): stage standalone bundle for desktop builds
Prepare a dedicated `.next/electron-standalone` bundle before
running electron-builder so desktop packaging operates on a stable,
Electron-specific server payload.

This also adds a preflight that rejects standalone bundles whose
top-level `node_modules` is a symlink, because electron-builder
preserves `extraResources` symlinks and would otherwise ship an app
that depends on the build machine at runtime.
2026-03-15 12:26:23 +02:00
diegosouzapw 4b7a9233e7 chore(release): v2.5.4 — logger fix, login bootstrap, HMR origins, CI hardening
Build Electron Desktop App / Validate version (push) Failing after 32s
Build Electron Desktop App / Build Electron (macos-arm64) (push) Has been skipped
Build Electron Desktop App / Build Electron (linux) (push) Has been skipped
Build Electron Desktop App / Build Electron (macos-intel) (push) Has been skipped
Build Electron Desktop App / Build Electron (windows) (push) Has been skipped
Build Electron Desktop App / Create Release (push) Has been skipped
2026-03-15 01:12:27 -03:00
Diego Rodrigues de Sa e Souza 204839f702 Merge pull request #374 from kfiramar/fix/dev-allowed-origins
fix(dev): allow loopback HMR origins
2026-03-15 01:10:56 -03:00
Diego Rodrigues de Sa e Souza d15e3109ee Merge pull request #375 from kfiramar/fix/login-bootstrap-metadata
fix(login): use public bootstrap route
2026-03-15 01:10:54 -03:00
Diego Rodrigues de Sa e Souza 8b513ee8f8 Merge pull request #376 from kfiramar/fix/logger-transport
fix(logger): restore transport logger path
2026-03-15 01:10:47 -03:00
diegosouzapw 2c1488e65a fix(ci): fix eslint OOM, failing tests, and strengthen pre-commit hook
- eslint.config.mjs: add missing ignores for vscode-extension/,
  electron/, docs/, app/.next/, clipr/ — ESLint was OOMing because
  it scanned huge VS Code binary blobs and build artifacts
- tests: remove stale ALTER TABLE 'group' statements — column is now
  part of the base schema in core.ts; tests were failing with
  SQLITE_ERROR: duplicate column name
- .husky/pre-commit: add npm run test:unit to block broken tests
  from reaching CI
2026-03-15 00:59:22 -03:00
Kfir Amar 8ebe1cc2d8 test(config): tighten dev origins assertion 2026-03-15 02:06:49 +02:00
Kfir Amar b0d6c15e63 fix(auth): harden login bootstrap checks
Stabilize the bootstrap metadata test by clearing
INITIAL_PASSWORD before each run and add focused coverage
for env-backed and stored-password states.

Log settings lookup failures before returning the
bootstrap-safe fallback payload so operational errors are
still visible on the server side.
2026-03-15 02:06:49 +02:00
Kfir Amar 3a3c7a7968 fix(logs): map numeric pino levels
Normalize numeric pino levels correctly in the console log API so the logger transport fix does not misclassify info, warn, and error entries in file-backed logs.

Add a targeted regression test for numeric log entries.
2026-03-15 01:51:59 +02:00
Kfir Amar 783d7ae605 test(dev): cover loopback dev origins
Add a focused config regression test that locks in localhost, 127.0.0.1, and the existing LAN dev origin allowlist.
2026-03-15 01:51:59 +02:00
Kfir Amar bbf7a6b2f8 test(login): cover bootstrap metadata route
Add a focused unit test for the public login bootstrap route so the branch is backed by the exact response contract the login page now relies on.
2026-03-15 01:51:59 +02:00
Kfir Amar 0fe6e24554 fix(logger): support transport targets
Keep the existing level formatter for direct logger paths, but drop
that formatter from transport-backed configs because pino rejects it
when transport.targets is used.

This restores the intended stdout+file transport path and avoids the
startup fallback warning on every boot.
2026-03-15 01:17:04 +02:00
Kfir Amar 4bbaf55586 fix(dev): allow localhost HMR origins
Add localhost and 127.0.0.1 to allowedDevOrigins so local dev
sessions opened on loopback addresses do not have their Next.js HMR
websocket blocked as cross-origin.
2026-03-15 01:17:04 +02:00
Kfir Amar cda765a02d fix(login): use public bootstrap settings
Point the login page at the existing public bootstrap endpoint
instead of the protected /api/settings route.

Also extend the public bootstrap response with hasPassword and
setupComplete so unauthenticated users get the correct first-run
or password-setup flow without triggering a 401.
2026-03-15 01:17:04 +02:00
diegosouzapw 36856b18db chore: release v2.5.3
Build Electron Desktop App / Validate version (push) Failing after 32s
Build Electron Desktop App / Build Electron (macos-arm64) (push) Has been skipped
Build Electron Desktop App / Build Electron (linux) (push) Has been skipped
Build Electron Desktop App / Build Electron (macos-intel) (push) Has been skipped
Build Electron Desktop App / Build Electron (windows) (push) Has been skipped
Build Electron Desktop App / Create Release (push) Has been skipped
bug fixes (PRs #373, #371, #372, #369 by @kfiramar):
- fix(db): provider_connections.group column migration for existing DBs
- fix(i18n): replace missing deleteConnection key with delete in tooltip
- fix(auth): clear stale error metadata on genuine provider recovery
- fix(startup): unify env loading across npm/electron startup paths

code quality improvements (per kilo-code-bot review):
- docs: document result.success vs response.ok patterns in auth.ts
- refactor: normalize overridePath?.trim() in electron/main.js
- docs: explain preferredEnv merge order intent
2026-03-14 19:53:59 -03:00
Diego Rodrigues de Sa e Souza 66f0a8f994 Merge pull request #369 from kfiramar/fix-startup-env-key-loading
Thanks @kfiramar! 🎉 Critical security fix — different startup paths were generating different `STORAGE_ENCRYPTION_KEY` values over the same SQLite database, causing `Unsupported state or unable to authenticate data` for all stored tokens.

Improvements added on top:
- Normalized `overridePath?.trim()` in `electron/main.js` to match `bootstrap-env.mjs` (addresses kilo-code-bot warning #1)
- Added explanatory comment documenting the `preferredEnv` merge order intent in Electron startup (addresses kilo-code-bot warning #3)

4 commits + 113-line test file. The fail-closed behaviour (refusing to mint a new key when encrypted rows exist) is an excellent safeguard. Merged!
2026-03-14 19:52:09 -03:00
Diego Rodrigues de Sa e Souza 455231170f Merge pull request #372 from kfiramar/fix/clear-provider-error-state
Thanks @kfiramar! 🎉 Critical fix — stale error metadata on recovered provider accounts was preventing valid accounts from being selected properly after recovery. 

Improvement added on top: documented the two valid success-check patterns (`result.success` for open-sse handlers vs `response?.ok` for fetch-based handlers) to address the kilo-code-bot review warning — both patterns are correct by design, now explicitly documented.

5 commits total, 2 test files (+168 lines of coverage). Merged!
2026-03-14 19:49:51 -03:00
Diego Rodrigues de Sa e Souza 5faeb58ab0 Merge pull request #371 from kfiramar/fix/provider-delete-tooltip-i18n
Thanks @kfiramar! Perfect minimal fix — `t("deleteConnection")` was requesting a non-existent key across all 30 locales, causing `MISSING_MESSAGE: providers.deleteConnection` runtime errors on every provider detail page load. Reusing the existing `providers.delete` key is the correct fix. Merged!
2026-03-14 19:48:01 -03:00
Diego Rodrigues de Sa e Souza 056e4a88ff Merge pull request #373 from kfiramar/fix/provider-connections-group-migration
Thanks @kfiramar! 🎉 Critical schema fix — the `group` column was used in all provider_connections queries but missing from the base schema and backfill migration. Databases upgraded from older versions were silently failing on group-related queries. Clean fix with regression test. Merged!
2026-03-14 19:47:58 -03:00
Kfir Amar 8fd944ccf7 fix(auth): type recovered state helpers
Tighten the helper signatures added for recovered provider cleanup.

This removes the new any-typed recovery parameters called out in
review without broadening the PR into unrelated auth typing work.
2026-03-14 23:11:59 +02:00
Kfir Amar 86105a547c fix(auth): clear stale state on non-chat success
Clear recovered provider error metadata after successful
credentialed requests in non-chat API routes as well.

Add route-level regression tests covering a Response-based
success path and a result-object success path.
2026-03-14 22:39:30 +02:00
Kfir Amar 9806648c07 test(auth): cover stale active error metadata path
Refine the recovered-account regression test to match the real
observed state: an account can remain active while still carrying
stale refresh-failure metadata.

This verifies that getProviderCredentials surfaces those fields
and that clearAccountError clears them through the real runtime
path.
2026-03-14 22:31:03 +02:00
Kfir Amar 6186babdb3 fix(auth): include error fields in recovery path
Pass errorCode, lastErrorType, and lastErrorSource through the
runtime credentials object so clearAccountError can clear stale
provider error metadata after a real successful request.

Also update the regression test to use getProviderCredentials,
matching the production call path.
2026-03-14 22:24:08 +02:00
Kfir Amar f2ecefb54a fix(i18n): use existing provider delete label
Replace a missing deleteConnection message lookup with the
existing delete label to avoid the provider-page runtime i18n
overlay.
2026-03-14 22:18:41 +02:00
Kfir Amar 43bd529b78 fix(db): add provider connection group migration
Add the missing provider_connections.group column to both the
base schema and the runtime column backfill path.

Also add a regression test covering upgrade from an older
database that does not yet have the column.
2026-03-14 22:18:41 +02:00
Kfir Amar 9c82b3d4ca fix(auth): clear stale provider error metadata
Clear errorCode, lastErrorType, and lastErrorSource when an
account recovers so provider state returns to a fully clean
active status.

Add a focused regression test for recovered-account cleanup.
2026-03-14 22:18:41 +02:00
Kfir Amar b19e6a8e87 fix(startup): pass env through env-file lookup
Keep getPreferredEnvFilePath consistent with its env parameter by
passing that env through resolveDataDir in both bootstrap and Electron.

This avoids silently falling back to process.env when a custom env map
is supplied.
2026-03-14 21:33:34 +02:00
Kfir Amar e3a2bd75f3 fix(startup): ignore blank data dir override
Treat empty or whitespace-only dataDirOverride values as unset so
bootstrapEnv keeps using the normal DATA_DIR and .env lookup path.

Adds a focused regression test for the whitespace override case.
2026-03-14 21:29:34 +02:00
Kfir Amar da39e1485f fix(startup): fail closed on key inspection errors
Propagate database inspection failures instead of treating them as
missing encrypted credentials.

This keeps startup from generating a fresh encryption key when an
existing database cannot be inspected and adds a regression test for
that path.
2026-03-14 21:23:07 +02:00
Kfir Amar 88cc53a4b0 fix(startup): honor documented env loading
Align the app bootstrap paths with the documented CLI env lookup.

The CLI wrapper already loads DATA_DIR/.env, ~/.omniroute/.env, or ./.env,
but run-next, run-standalone, and Electron were bypassing that behavior.
On machines with encrypted credentials, that could generate a fresh
STORAGE_ENCRYPTION_KEY in server.env and make existing tokens unreadable.

This change:
- uses the same preferred .env lookup in bootstrapEnv and Electron
- keeps Electron secrets rooted in DATA_DIR and passes DATA_DIR to the child
- refuses to mint a new encryption key over an existing encrypted database
- adds a focused regression test for env precedence and key safety
2026-03-14 21:14:19 +02:00
diegosouzapw 245243c7e7 chore: release v2.5.2 (version bump, npm conflict with 2.5.1)
Build Electron Desktop App / Validate version (push) Failing after 39s
Build Electron Desktop App / Build Electron (macos-arm64) (push) Has been skipped
Build Electron Desktop App / Build Electron (linux) (push) Has been skipped
Build Electron Desktop App / Build Electron (macos-intel) (push) Has been skipped
Build Electron Desktop App / Build Electron (windows) (push) Has been skipped
Build Electron Desktop App / Create Release (push) Has been skipped
2026-03-14 16:01:14 -03:00
diegosouzapw 759ac0df3d chore: release v2.5.1
Build Electron Desktop App / Validate version (push) Failing after 31s
Build Electron Desktop App / Build Electron (macos-arm64) (push) Has been skipped
Build Electron Desktop App / Build Electron (linux) (push) Has been skipped
Build Electron Desktop App / Build Electron (macos-intel) (push) Has been skipped
Build Electron Desktop App / Build Electron (windows) (push) Has been skipped
Build Electron Desktop App / Create Release (push) Has been skipped
- PR #368: gpt-5.4 in Codex model registry (cx/gpt-5.4, codex/gpt-5.4)
- PR #367: Codex fast tier toggle (default-off, full stack, 48 tests)
- PR #366: Codex quota policy 5h/weekly with auto-rotation
- fix #356: analytics charts show provider display names not raw IDs
2026-03-14 15:55:06 -03:00
Diego Rodrigues de Sa e Souza db8d97b6de Merge pull request #366 from rexname/feature/codex-account-limit-rotation
Thanks @rexname (Maulana Hasanudin)! 🎉 

Codex account quota policy (5h/weekly) with auto-rotation is now merged. Highlights:
- Per-account policy toggles (5h + weekly ON/OFF) in the Provider dashboard
- Accounts automatically skipped when enabled quota window reaches 90% threshold
- Auto re-eligibility when resetAt timestamp passes (no manual intervention needed)
- Side-effect free `getQuotaWindowStatus` getter design
- Safe partial merge of `codexLimitPolicy` on provider updates

Merged on top of main (v2.5.0) with no conflicts. Analytics label fix (#356) included. Thanks for the excellent quality and the 2-commit cleanup round! 🙏
2026-03-14 15:54:07 -03:00
Diego Rodrigues de Sa e Souza 27d66e4b3e Merge pull request #367 from kfiramar/feat-codex-fast-toggle
Thanks @kfiramar! Codex fast-tier toggle merged 🎉 — default-off, full stack (UI tab + API + executor injection + translator passthrough + startup restore). 48 tests passing. Users can now enable flex tier in Dashboard → Settings → Codex Service Tier.
2026-03-14 15:49:56 -03:00
Diego Rodrigues de Sa e Souza ca7854210d Merge pull request #368 from kfiramar/fix-codex-gpt54-models
Thanks @kfiramar! gpt-5.4 is now exposed in the model catalog as `cx/gpt-5.4` and `codex/gpt-5.4`. Minimal, tested fix — merged directly. 🙏
2026-03-14 15:49:54 -03:00
Kfir Amar c009c993c3 fix(codex): persist fast-tier toggle before applying runtime state 2026-03-14 20:48:19 +02:00
Kfir Amar 00188f75ae feat(codex): add fast tier settings toggle
Add a default-off dashboard setting that injects Codex fast service tier only when the request did not already specify one.

Also preserve service_tier through OpenAI-to-Responses translation and restore the setting at startup.
2026-03-14 20:41:49 +02:00
diegosouzapw 4d086542aa fix: getProviderCredentials missing allowedConnections param (#363 TS error)
PR #363 added allowedConnections as 3rd arg in chat.ts calls to
getProviderCredentials(), but the function signature in auth.ts
only declared 2 params. Adding the optional 3rd param and applying
the connection filter when provided.
2026-03-14 15:38:12 -03:00
rexname 1555883633 fix(codex): address PR review feedback for quota policy flow
- add user-facing success/error notifications for Codex limit toggle API calls
- deduplicate Codex policy default normalization in providers page
- make getQuotaWindowStatus side-effect free (no cache mutation in getter)
- avoid stale threshold blocking after resetAt has passed
- extract named Codex quota threshold constant
- extract helper for earliest future reset date selection
2026-03-15 01:35:19 +07:00
Kfir Amar 8f2c0acc7e fix(codex): advertise gpt-5.4 models
Add gpt-5.4 to the Codex model registry so OmniRoute exposes cx/gpt-5.4 and codex/gpt-5.4 in its model catalog.

Includes a focused regression test for model resolution.
2026-03-14 20:33:47 +02:00
rexname 0e30d15c01 feat(codex): add account-level 5h/weekly quota policy and auto-rotation
- add quota window status helper for Codex session (5h) and weekly windows
- enforce policy-based account filtering when enabled windows reach threshold
- return all-rate-limited metadata when no Codex account is eligible
- add per-account dashboard toggles for 5h and weekly policy controls
- merge codexLimitPolicy safely on provider updates to preserve partial settings
- document purpose and usage scenarios in README (EN + ID + i18n note)
2026-03-15 01:33:44 +07:00
diegosouzapw da14390fe0 chore: release v2.5.0
Build Electron Desktop App / Validate version (push) Failing after 37s
Build Electron Desktop App / Build Electron (macos-arm64) (push) Has been skipped
Build Electron Desktop App / Build Electron (linux) (push) Has been skipped
Build Electron Desktop App / Build Electron (macos-intel) (push) Has been skipped
Build Electron Desktop App / Build Electron (windows) (push) Has been skipped
Build Electron Desktop App / Create Release (push) Has been skipped
Includes:
- PR #363: strict-random strategy, API key controls, connection groups, Limits UX (AndersonFirmino)
- PR #365: external pricing sync with LiteLLM 3-tier resolution (Regis-RCR)
- fix #355: stream idle timeout 60s → 300s for thinking models
- fix #350: combo test bypasses REQUIRE_API_KEY via X-Internal-Test header
- fix #346: filter tools with empty function.name before forwarding upstream
2026-03-14 15:31:27 -03:00
diegosouzapw 11c0cff4ef merge: bug fixes for #355 #350 #346 into main 2026-03-14 15:30:36 -03:00
Diego Rodrigues de Sa e Souza e322376996 Merge pull request #363 from AndersonFirmino/feat/strict-random-i18n-ux
Merged! Excellent contribution @AndersonFirmino 🎉

This PR delivers four major improvements:
- **strict-random** strategy — Fisher-Yates shuffle deck with anti-repeat guarantee and mutex serialization for concurrent safety
- **API key controls** — allowedConnections, is_active, accessSchedule, autoResolve
- **Connection groups** — environment-based grouping view in Limits page with localStorage persistence  
- **i18n** — 30 languages fully updated, pt-BR fully translated

655 tests passing. Merged with main (v2.4.4) — no conflicts. Thank you for the exceptional quality!
2026-03-14 15:30:19 -03:00
diegosouzapw 4fbe45f30a fix: stream timeout, combo test auth, and empty tool name (#355 #350 #346)
- fix #355: increase STREAM_IDLE_TIMEOUT_MS from 60s to 300s to prevent
  premature stream abortion for extended-thinking models (claude-opus-4-6,
  o3, etc.) that can pause >60s during reasoning phases. Configurable via
  STREAM_IDLE_TIMEOUT_MS env var.

- fix #350: combo health check test now bypasses REQUIRE_API_KEY=true by
  sending X-Internal-Test header, recognized in chat.ts auth pipeline to
  skip API key validation for internal admin-side combo tests. Also
  extended test timeout from 15s to 20s. Uses OpenAI-compatible format
  universally (not Claude-style).

- fix #346: filter out tools with empty function.name before forwarding
  to upstream providers. Claude Code sends empty-name tool definitions
  that cause '400 Invalid input[N].name: empty string' on OpenAI-compat
  providers. Extends existing message/input empty-name filter.
2026-03-14 15:28:53 -03:00
Diego Rodrigues de Sa e Souza 2cd0f60c3c Merge pull request #365 from Regis-RCR/feat/pricing-sync
Merged via review workflow. Excellent contribution by @Regis-RCR — 3-tier pricing resolution with LiteLLM sync, 23 tests, fully opt-in. Minor improvement noted: dashboard UI for sync status will be added in a follow-up.
2026-03-14 15:23:48 -03:00
diegosouzapw 1b354be827 feat: T07 — API Key Round-Robin per provider connection
Build Electron Desktop App / Validate version (push) Failing after 42s
Build Electron Desktop App / Build Electron (macos-arm64) (push) Has been skipped
Build Electron Desktop App / Build Electron (linux) (push) Has been skipped
Build Electron Desktop App / Build Electron (macos-intel) (push) Has been skipped
Build Electron Desktop App / Build Electron (windows) (push) Has been skipped
Build Electron Desktop App / Create Release (push) Has been skipped
- New: open-sse/services/apiKeyRotator.ts — round-robin rotation
  between primary API key + providerSpecificData.extraApiKeys[]
- Modified: open-sse/executors/base.ts — buildHeaders() rotates key
  using getRotatingApiKey() when extraApiKeys configured
- Modified: open-sse/handlers/chatCore.ts — injects connectionId into
  credentials to enable per-connection rotation index tracking
- Modified: providers/[id]/page.tsx — 'Extra API Keys' UI section in
  EditConnectionModal: add/remove keys, persisted in providerSpecificData

T08 (quota window rolling) and T13 (wildcard model routing) confirmed
already implemented in accountFallback.ts and wildcardRouter.ts.
2026-03-14 15:03:54 -03:00
Regis 7db280ee64 fix(api): address review feedback on pricing sync
- Add .catch() to initial and periodic sync promises (Gemini, Kilo)
- Wrap JSON.parse in try-catch for corrupted DB data (Kilo)
- Wrap response.json() in try-catch for invalid LiteLLM JSON (Kilo)
- Validate PRICING_SYNC_INTERVAL (guard against NaN/0 → tight loop) (Copilot)
- Validate and allowlist sources — reject unknown, prevent empty sync
  from clearing pricing_synced data (Copilot, Kilo)
- Extract merge loop into shared iteration to reduce duplication (Gemini)
- Add data/warnings fields to MCP output schema (Copilot)
- Remove unused z import in vitest (Copilot)
- Filter non-string entries from sources array in API route (Copilot)
- Track active interval for accurate getSyncStatus().nextSync (Copilot)
2026-03-14 19:01:27 +01:00
Regis 192c06cadf feat(api): add external pricing sync with LiteLLM source
Add a 3-tier pricing resolution system: user overrides > synced external > hardcoded defaults.

New files:
- src/lib/pricingSync.ts: sync engine (fetch LiteLLM, transform, store in pricing_synced namespace)
- src/app/api/pricing/sync/route.ts: POST (trigger sync), GET (status), DELETE (clear synced)
- tests/unit/pricing-sync.test.mjs: 12 unit tests for transform logic
- open-sse/mcp-server/__tests__/pricingSync.test.ts: 11 vitest tests for MCP schema

Modified files:
- src/lib/db/settings.ts: getPricing() now merges 3 layers (defaults → synced → user)
- src/server-init.ts: init pricing sync on startup when PRICING_SYNC_ENABLED=true
- src/lib/localDb.ts: re-export pricing sync functions
- open-sse/mcp-server/schemas/tools.ts: add omniroute_sync_pricing tool definition
- open-sse/mcp-server/tools/advancedTools.ts: add handleSyncPricing handler
- open-sse/mcp-server/server.ts: register omniroute_sync_pricing tool

Opt-in (PRICING_SYNC_ENABLED=false by default), user overrides are never touched,
graceful fallback on fetch failure, zero new dependencies.
2026-03-14 18:49:35 +01:00
Anderson Firmino ad7e7abda0 🐛 fix: propagate allowedConnections from API key to credential selection
getProviderCredentials already filtered by allowedConnections, but
chat.ts never passed the field from apiKeyInfo. Now both call sites
(combo pre-check and credential retry loop) forward the restriction.
2026-03-14 14:03:08 -03:00
Anderson Firmino 02ccb35e80 ♻️ refactor: consolidate shuffle deck into shared utility with mutex protection
Fixes race condition in combo strict-random (concurrent requests could
reshuffle simultaneously). Eliminates code duplication between combo.ts
and auth.ts by extracting Fisher-Yates shuffle + deck logic into
src/shared/utils/shuffleDeck.ts with per-namespace mutex serialization.
2026-03-14 14:03:08 -03:00
Anderson Firmino a8a29e17c5 feat: strict-random strategy, API key management, connection groups, Limits UX
- Combo layer: strict-random in combo.ts rotates models uniformly
- Credential layer: strict-random in auth.ts rotates connections/accounts
- Anti-repeat guarantee: last of previous cycle ≠ first of next
- Mutex serialization for concurrent request safety
- Independent decks per combo name and per provider

- allowedConnections: restrict which connections a key can use
- autoResolve: per-key toggle for ambiguous model disambiguation
- is_active: enable/disable key instantly (403 on disabled)
- accessSchedule: time-based access control (hours, days, timezone)
- Rename keys via PATCH /api/keys/:id
- Connection restriction badge in API keys table
- Auto-migration for all new columns

- Connection group field on provider connections
- Environment grouping view in Limits page (group by environment)
- Accordion UI with expand/collapse per group
- localStorage persistence for groupBy, autoRefresh, expandedGroups
- Smart default: auto-switches to environment view when groups exist
- Swap SessionsTab above RateLimitStatus

- strict-random option added to combo strategy dropdown (30 languages)
- strategyGuide.strict-random (when/avoid/example)
- pt-BR: translated all strategyRecommendations from English to Portuguese
- en: added API key management strings (accessSchedule, isActive, etc.)

- 11 tests: shuffle deck mechanics (Fisher-Yates, anti-repeat, decks)
- 6 tests: allowedConnections (schema, DB persistence, cache invalidation)
- 12 tests: API key policy (isActive, accessSchedule, autoResolve, budget)
2026-03-14 14:03:08 -03:00
diegosouzapw 75a6d850fc chore: release v2.4.3
Build Electron Desktop App / Validate version (push) Failing after 31s
Build Electron Desktop App / Build Electron (macos-arm64) (push) Has been skipped
Build Electron Desktop App / Build Electron (linux) (push) Has been skipped
Build Electron Desktop App / Build Electron (macos-intel) (push) Has been skipped
Build Electron Desktop App / Build Electron (windows) (push) Has been skipped
Build Electron Desktop App / Create Release (push) Has been skipped
- fix: Codex/GitHub limits page HTTP 500 → graceful 401/403 messages
- fix: MaintenanceBanner false-positive on page load (stale closure)
- fix: add title tooltips to edit/delete buttons in ConnectionCard
- feat: add fill-first and p2c routing strategies to combo picker
- feat: Free Stack template pre-fills 7 free provider models
- feat: combo create/edit modal wider (max-w-4xl)
2026-03-14 12:49:36 -03:00
diegosouzapw b0f5f92f1a feat(release): v2.4.2 — task-aware routing, HuggingFace/Vertex providers, streaming fixes, token tracking, playground uploads
Build Electron Desktop App / Validate version (push) Failing after 43s
Build Electron Desktop App / Build Electron (macos-arm64) (push) Has been skipped
Build Electron Desktop App / Build Electron (linux) (push) Has been skipped
Build Electron Desktop App / Build Electron (macos-intel) (push) Has been skipped
Build Electron Desktop App / Build Electron (windows) (push) Has been skipped
Build Electron Desktop App / Create Release (push) Has been skipped
- feat: Task-Aware Smart Routing (T05) — auto-select model by task type
- feat: HuggingFace and Vertex AI provider support
- feat: Playground audio/image file uploads for transcription and vision
- feat: ModelSelectModal shows ✓ for already-added models (#180)
- fix: Claude Haiku routed to OpenAI without provider prefix (#73)
- fix: Token counts always 0 for Antigravity/Claude streaming (#74)
- fix: OpenAI SDK stream=False drops tool_calls (#302)
- fix: Media page generation errors — inline rendering for images/transcription
- fix: Round-robin state management for excluded accounts (#349)
- fix: Qwen user agent and CLI fingerprint compatibility (#352)
- deps: undici→7.24.2, dompurify→3.3.3, docker actions v4
- docs: CHANGELOG 2.4.2 with full feature/fix list
- docs: README with Task-Aware Routing table entry
2026-03-14 11:04:09 -03:00
Diego Rodrigues de Sa e Souza eaddb6f0fa feat: improvements from 9router analysis (T01/T08-T13) (#351)
* fix: tool description null sanitization, clipboard HTTP fallback fixes

T10 - Sanitize tool.description null in claude-to-openai translator
- claude-to-openai.ts: tool.description defaults to empty string when null/undefined
- claude-to-openai.ts: filter out tools with empty/missing names
- Prevents 400 validation errors on providers like NVIDIA NIM (issue #276)

T11 - Fix copy buttons to work on HTTP/non-HTTPS deployments
- Add src/shared/utils/clipboard.ts with HTTPS+HTTP (execCommand) dual fallback
- Migrate useCopyToClipboard.ts to use shared utility
- Migrate ConsoleLogViewer.tsx, RequestLoggerV2.tsx to shared utility
- Migrate HomePageClient.tsx, endpoint/page.tsx, GetStarted.tsx
- Migrate DefaultToolCard.tsx to shared utility
- Fixes copy buttons when OmniRoute runs behind HTTP proxy (issue #296)

T02 - Verified SSE [DONE] sentinel handling already correct
- sseParser.ts filters [DONE] on line 13 (no change needed)
- stream.ts uses doneSent flag to prevent duplicate sentinel
- bypassHandler.ts correctly separates streaming/non-streaming responses

Issue triage comments posted to #340, #341, #344

* feat: DB read cache + Accept header stream negotiation (T09/T01)

T09 - In-memory TTL cache for hot DB read paths
- Add src/lib/db/readCache.ts with TTL cache (5s settings/connections, 30s pricing)
- Eliminates redundant SQLite reads on concurrent requests
- Integrate invalidation in settings.ts updateSettings() and updatePricing()
- Integrate invalidation in providers.ts create/update/delete operations
- Export getCachedSettings, getCachedPricing, getCachedProviderConnections,
  invalidateDbCache via localDb.ts for consumer migration
- Cache auto-busts on any write, preserving data consistency

T01 - Accept header stream negotiation
- src/sse/handlers/chat.ts: detect Accept: text/event-stream header
- Override body.stream=true when Accept header indicates streaming client
- Enables curl, httpx and SDK clients that use HTTP headers instead of JSON
  body field to trigger streaming responses
- Logs Accept override at DEBUG level for observability

* fix: auto-advance quota window on expiry to prevent stale blocking (T08)

T08 - Quota Window Rolling Auto-Advance
- quotaCache.ts: add windowDurationMs field to QuotaCacheEntry interface
  (optional field that callers can set when they know the window duration)
- Add advancedWindowResetAt() helper: if entry.nextResetAt is in the past,
  eagerly returns { exhausted: false } so requests are unblocked immediately
- isAccountQuotaExhausted() now uses advancedWindowResetAt() instead of
  the previous inline date check, and optimistically clears entry.exhausted
  flag to avoid re-checking the same stale entry on the next request

Before: exhausted accounts with an expired resetAt would wait up to 5
minutes for the background refresh before accepting new requests.
After:  the first request after resetAt passes will be immediately accepted
and will trigger a quota refresh on the next background tick.

* feat: manual OAuth token refresh UI (T12)

T12 - Manual Token Refresh UI
- Add POST /api/providers/[id]/refresh endpoint
  - Validates connection exists and is OAuth type
  - Calls getAccessToken() (same helper used in auto-refresh)
  - Persists new credentials via updateProviderCredentials()
  - Returns { success, expiresAt, refreshedAt } on success

- Update providers/[id]/page.tsx
  - handleRefreshToken() with loading state (refreshingId)
  - Pass onRefreshToken + isRefreshing props to ConnectionRow
  - ConnectionRow: add optional onRefreshToken/isRefreshing props
  - ConnectionRow: tokenMinsLeft state via lazy init (Date.now() in
    getter fn, not in render body - satisfies react-hooks/purity)
  - Token expiry badge: red 'expired' | amber '~Xm' (<30min) | hidden
  - 'Token' button (amber) next to 'Retest' for OAuth connections

- Add en.json i18n: tokenRefreshed, tokenRefreshFailed

* Initial plan

* feat: integrate wildcardRouter into model alias resolution (T13)

T13 - Wildcard Model Routing
- Import resolveWildcardAlias from wildcardRouter.ts into model.ts
- In getModelInfoCore(), after exact alias check fails, try glob wildcard
  alias matching (e.g., 'claude-sonnet-*' alias → 'anthropic/claude-sonnet-4')
- Returns { provider, model, extendedContext, wildcardPattern } on match
- Falls back to MODEL_TO_PROVIDERS lookup and openai default as before

* fix: clipboard cleanup and tool validation

* feat: media page UX + T04 playground uploads + T03 HuggingFace/Vertex AI

Media Page (MediaPageClient.tsx):
- Render images inline (img tags from b64_json or url)
- Show transcription as plain readable text (not raw JSON)
- Amber banner for credential errors with link to /dashboard/providers
- Detect empty transcription result and show credentials hint
- Provider credential hint below selector for non-local providers
- Extended provider/model lists: HuggingFace, Qwen TTS, Inworld, Cartesia, PlayHT, AssemblyAI

T04 - Playground File Uploads (playground/page.tsx):
- Audio file upload panel for transcription endpoint (multipart/form-data)
- Image upload panel for vision models (gpt-4o, claude-3, gemini, pixtral, llava...)
- Auto-detect vision models by name heuristic
- Inject uploaded images as base64 image_url in chat messages
- Inline image rendering for image generation results
- Readable text view for transcription results with copy button
- Preview thumbnails for attached images with individual remove

T03 - HuggingFace + Vertex AI Providers:
- HuggingFace: frontend providers.ts + backend providerRegistry.ts
  Uses HuggingFace Router OpenAI-compatible endpoint
- Vertex AI: frontend providers.ts + backend providerRegistry.ts
  Uses gemini format with generateContent API (urlBuilder fallback)

T07 - API Key Round-Robin: VERIFIED already implemented in auth.ts
  fill-first, round-robin, p2c, random, least-used, cost-optimized strategies

* feat: T05 task-aware routing + fix #302 stream override + fix #73 claude provider fallback

T05 - Task-Aware Smart Routing:
- New open-sse/services/taskAwareRouter.ts:
  Detects 7 task types: coding, creative, analysis, vision, summarization,
  background, chat from system/user message content and images
  Configurable taskModelMap per task type, stats tracking
  applyTaskAwareRouting() integrates with existing chat pipeline
- New src/app/api/settings/task-routing/route.ts:
  GET/PUT/POST API for task routing config + reset-stats + detect action
  Persists config via updateSettings('taskRouting')
- Integration in src/sse/handlers/chat.ts:
  applyTaskAwareRouting() called after policy enforcement, before combo resolve
  Logs task type detection and model overrides

Fix #302 - OpenAI SDK stream=False drops tool_calls:
- src/sse/handlers/chat.ts T01 Accept header negotiation:
  Changed condition from 'body.stream !== true' to 'body.stream === undefined'
  OpenAI Python SDK sends 'Accept: application/json, text/event-stream' in every
  request, even stream=False — the old code was incorrectly forcing stream=true,
  causing tool_calls to be dropped from non-streaming responses

Fix #73 - Claude Haiku routed to OpenAI provider instead of Antigravity:
- open-sse/services/model.ts getModelInfoCore():
  Added heuristic prefix detection before the blind 'openai' fallback:
  claude-* models → antigravity (Anthropic) provider
  gemini-*/gemma-* models → gemini provider
  Closes: #73, partially addresses #302

* fix: token counts 0 (#74), model import dup (#180), model route fallback (#73)

fix #74 - Token counts always 0 for Antigravity/Claude streaming:
- open-sse/utils/usageTracking.ts extractUsage():
  Add handler for 'message_start' SSE event which carries INPUT tokens in
  Antigravity/Claude streaming:
  { type: 'message_start', message: { usage: { input_tokens: N } } }
  This event was completely unhandled, causing ALL input token counts to be
  dropped for every Antigravity/Claude streaming request

fix #180 - Model import shows duplicates with no visual feedback:
- src/shared/components/ModelSelectModal.tsx:
  Added addedModelValues prop (string[]) to receive already-added model values
  Models already in the combo now shown with ✓ indicator + green highlight
  Makes it visually clear which models are already added vs new
- src/app/(dashboard)/dashboard/combos/page.tsx:
  Pass addedModelValues={models.map(m => m.model)} to ModelSelectModal

* Harden clipboard UX and Claude tool normalization (#360)

* Initial plan

* chore: plan updates for clipboard and translator fixes

* fix: clipboard cleanup, copy feedback, and claude tool validation

---------

Co-authored-by: openai-code-agent[bot] <242516109+Codex@users.noreply.github.com>
Co-authored-by: diegosouzapw <diegosouzapw@users.noreply.github.com>

---------

Co-authored-by: diegosouzapw <diegosouzapw@users.noreply.github.com>
Co-authored-by: openai-code-agent[bot] <242516109+Codex@users.noreply.github.com>
2026-03-14 10:59:15 -03:00
Nyaru Toru 5cff98ea75 feat: add Qwen compatibility with updated user agent and CLI fingerprint settings (#352)
Co-authored-by: nyatoru <nyarutoru0002@outlook.co.th>
2026-03-14 10:58:50 -03:00
Nyaru Toru 76127415a4 fix(account-selector): enhance round-robin logic to handle excluded accounts and maintain state (#349)
Co-authored-by: nyatoru <nyarutoru0002@outlook.co.th>
2026-03-14 10:58:48 -03:00
dependabot[bot] 56936fe0e3 deps: bump undici from 7.24.1 to 7.24.2 (#361)
Bumps [undici](https://github.com/nodejs/undici) from 7.24.1 to 7.24.2.
- [Release notes](https://github.com/nodejs/undici/releases)
- [Commits](https://github.com/nodejs/undici/compare/v7.24.1...v7.24.2)

---
updated-dependencies:
- dependency-name: undici
  dependency-version: 7.24.2
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-14 10:58:46 -03:00
dependabot[bot] dfbbbeb1b4 chore(deps): bump docker/setup-buildx-action from 3 to 4 (#343)
* chore(deps): bump docker/setup-buildx-action from 3 to 4

Bumps [docker/setup-buildx-action](https://github.com/docker/setup-buildx-action) from 3 to 4.
- [Release notes](https://github.com/docker/setup-buildx-action/releases)
- [Commits](https://github.com/docker/setup-buildx-action/compare/v3...v4)

---
updated-dependencies:
- dependency-name: docker/setup-buildx-action
  dependency-version: '4'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>

* Initial plan

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: openai-code-agent[bot] <242516109+Codex@users.noreply.github.com>
Co-authored-by: Diego Rodrigues de Sa e Souza <8016841+diegosouzapw@users.noreply.github.com>
2026-03-14 10:56:20 -03:00
dependabot[bot] 7f3ffd935e chore(deps): bump docker/setup-qemu-action from 3 to 4 (#342)
Bumps [docker/setup-qemu-action](https://github.com/docker/setup-qemu-action) from 3 to 4.
- [Release notes](https://github.com/docker/setup-qemu-action/releases)
- [Commits](https://github.com/docker/setup-qemu-action/compare/v3...v4)

---
updated-dependencies:
- dependency-name: docker/setup-qemu-action
  dependency-version: '4'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-03-14 10:56:18 -03:00
dependabot[bot] 29cf462d8f deps: bump undici from 7.22.0 to 7.24.1 (#348)
* deps: bump undici from 7.22.0 to 7.24.1

Bumps [undici](https://github.com/nodejs/undici) from 7.22.0 to 7.24.1.
- [Release notes](https://github.com/nodejs/undici/releases)
- [Commits](https://github.com/nodejs/undici/compare/v7.22.0...v7.24.1)

---
updated-dependencies:
- dependency-name: undici
  dependency-version: 7.24.1
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>

* Initial plan

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: openai-code-agent[bot] <242516109+Codex@users.noreply.github.com>
Co-authored-by: Diego Rodrigues de Sa e Souza <8016841+diegosouzapw@users.noreply.github.com>
2026-03-14 10:56:16 -03:00
dependabot[bot] 5e1693e1f7 deps: bump dompurify from 3.3.2 to 3.3.3 (#347) 2026-03-14 10:55:45 -03:00
diegosouzapw 45424ca226 fix(ci): docs-sync, openapi version, changelog format, pre-commit hook
Build Electron Desktop App / Validate version (push) Failing after 38s
Build Electron Desktop App / Build Electron (macos-arm64) (push) Has been skipped
Build Electron Desktop App / Build Electron (linux) (push) Has been skipped
Build Electron Desktop App / Build Electron (macos-intel) (push) Has been skipped
Build Electron Desktop App / Build Electron (windows) (push) Has been skipped
Build Electron Desktop App / Create Release (push) Has been skipped
- docs/openapi.yaml: update info.version from 2.3.6 to 2.4.1 (fixes CI check)
- CHANGELOG.md: add '## [Unreleased]' section as first heading (required by check-docs-sync)
- scripts/check-docs-sync.mjs: fix regex to accept both hyphen (-) and em-dash (—)
  as date separators in changelog headings (standard Keep a Changelog format)
- .husky/pre-commit: add 'node scripts/check-docs-sync.mjs' to catch version
  mismatches locally before push
2026-03-13 11:45:32 -03:00
diegosouzapw d976abb5e0 chore: v2.4.1 — combos free-stack always visible 2026-03-13 11:29:51 -03:00
diegosouzapw 92d302aed3 fix(combos): free-stack template first, 2x2 grid, green highlight badge
- Move 'Free Stack ($0)' to position 1 in COMBO_TEMPLATES (was 4th, invisible in 3-col grid)
- Add isFeatured flag to free-stack for special styling
- Change template grid: grid-cols-3 → 2x2 (sm:grid-cols-2) — all 4 templates visible
- Free Stack: green border/bg (emerald), FREE badge, larger text size
- Other templates: hover styles preserved, → arrow on Apply link
- Increase templates section padding
2026-03-13 11:26:18 -03:00
diegosouzapw 1e93ee5c34 chore: release v2.4.0
Build Electron Desktop App / Validate version (push) Failing after 25s
Build Electron Desktop App / Build Electron (macos-arm64) (push) Has been skipped
Build Electron Desktop App / Build Electron (linux) (push) Has been skipped
Build Electron Desktop App / Build Electron (macos-intel) (push) Has been skipped
Build Electron Desktop App / Build Electron (windows) (push) Has been skipped
Build Electron Desktop App / Create Release (push) Has been skipped
Bump from 2.3.17 to 2.4.0 to reflect the significance of this release:
- Free Stack combo template ecosystem
- Transcription playground overhaul (Deepgram default, $200/$50 free badges)
- 44+ providers documented, hasFree badges on NVIDIA/Cerebras/Groq
- README: Start Free section, Free Models section, Free Transcription Combo
- tierPriority as 7th scoring factor in auto-combo UI
- i18n 30 languages fully synced
2026-03-13 11:20:31 -03:00
diegosouzapw 1b6c502c7f feat: free-stack combo, Deepgram transcription default, README free sections, provider hasFree badges
- Combos: add 'Free Stack ($0)' as 4th combo template (round-robin: Kiro+iFlow+Qwen+GeminiCLI)
- Media/Transcription: Deepgram (Nova 3) as default provider, show $200/$50/free badges
- providers.ts: hasFree + freeNote for NVIDIA NIM (40 RPM), Cerebras (1M tok/day), Groq (30 RPM)
- README: new early '🆓 Start Free' 5-step table before Quick Start
- README: new '🎙️ Free Transcription Combo' section (Deepgram/AssemblyAI/Groq)
- README: NVIDIA NIM model list updated (Kimi K2.5, GLM 4.7, DeepSeek V3.2)
- i18n: templateFreeStack + templateFreeStackDesc synced to 30 languages
- Bump version to 2.3.17
2026-03-13 11:13:02 -03:00
diegosouzapw 4e4532c057 docs(readme): 44+ providers, free models section, accurate free tier quotas
Build Electron Desktop App / Validate version (push) Failing after 43s
Build Electron Desktop App / Build Electron (macos-arm64) (push) Has been skipped
Build Electron Desktop App / Build Electron (linux) (push) Has been skipped
Build Electron Desktop App / Build Electron (macos-intel) (push) Has been skipped
Build Electron Desktop App / Build Electron (windows) (push) Has been skipped
Build Electron Desktop App / Create Release (push) Has been skipped
- Update provider count from 36+ to 44+ in 3 locations (line 5, unified endpoint, one-endpoint sections)
- Add new section '🆓 Free Models — What You Actually Get' with 7 provider tables:
  - Kiro: 3 Claude models (unlimited via AWS Builder ID)
  - iFlow: 5 models unlimited (kimi-k2-thinking, qwen3-coder-plus, deepseek-r1, minimax-m2.1, kimi-k2)
  - Qwen: 4 models unlimited (qwen3-coder-plus, qwen3-coder-flash, qwen3-coder-next, vision-model)
  - Gemini CLI: 180K/month + 1K/day
  - NVIDIA NIM: ~40 RPM dev-forever (70+ models), transitioning from credits to rate limits
  - Cerebras: 1M tokens/day, 60K TPM / 30 RPM
  - Groq: 30 RPM / 14.4K RPD
- Include $0 Ultimate Free Stack combo recommendation
- Update NVIDIA NIM from '1000 credits' to 'dev-forever free' (×3)
- Add Cerebras row to pricing table
- Fix iFlow 8→5 models (with names), Qwen 3→4 models (with names)
- Bump version to 2.3.16
2026-03-13 11:03:24 -03:00
diegosouzapw 1e57ae5923 docs: CHANGELOG v2.3.15
Build Electron Desktop App / Validate version (push) Failing after 31s
Build Electron Desktop App / Build Electron (macos-arm64) (push) Has been skipped
Build Electron Desktop App / Build Electron (linux) (push) Has been skipped
Build Electron Desktop App / Build Electron (macos-intel) (push) Has been skipped
Build Electron Desktop App / Build Electron (windows) (push) Has been skipped
Build Electron Desktop App / Create Release (push) Has been skipped
2026-03-13 10:41:24 -03:00
diegosouzapw 9055fc2129 feat(auto-combo): add tierPriority factor label + autoCombo i18n section (30 languages)
- Add 'tierPriority: 🏷️ Tier' to FACTOR_LABELS in auto-combo dashboard (7th scoring factor)
- Add 'autoCombo' i18n section with 20 keys to en.json
- Sync autoCombo i18n keys to 29 language files (ar, bg, da, de, es, fi, fr, hi, hu, id, it, ja, ko, nl, no, pl, pt-BR, pt, ro, ru, sk, sv, th, tr, uk, vi, zh-CN, zh-TW + all others)
- Bump version to 2.3.15
2026-03-13 10:40:59 -03:00
diegosouzapw b8fec94b0d feat(release): v2.3.14 — iFlow fix, MITM compile, GeminiCLI fallback, new models, tier scoring API
Build Electron Desktop App / Validate version (push) Failing after 28s
Build Electron Desktop App / Build Electron (macos-arm64) (push) Has been skipped
Build Electron Desktop App / Build Electron (linux) (push) Has been skipped
Build Electron Desktop App / Build Electron (macos-intel) (push) Has been skipped
Build Electron Desktop App / Build Electron (windows) (push) Has been skipped
Build Electron Desktop App / Create Release (push) Has been skipped
2026-03-13 10:19:38 -03:00
diegosouzapw 2b6c88cd26 fix: iFlow OAuth secret, MITM server compile, GeminiCLI projectId, model catalog, electron version, tierPriority schema
- fix(oauth): restore iFlow clientSecret default — was empty string, now uses the valid public key (#339)
- fix(mitm): compile src/mitm/*.ts to JS during prepublish so server.js exists in npm bundle (#335)
- fix(gemini-cli): graceful projectId fallback — warn + empty string instead of hard 500 error (#338)
- feat(models): add gpt5.4 to Codex; add claude-sonnet-4, claude-opus-4.6, deepseek-v3.2, minimax-m2.1, qwen3-coder-next, auto to Kiro (#334)
- fix(electron): sync electron/package.json version to 2.3.13 (#323)
- feat(scoring): add tierPriority (0.05) to ScoringWeights Zod schema and combos/auto API route
2026-03-13 10:18:44 -03:00
diegosouzapw f6c0744d67 feat(release): v2.3.13 — tiered quota scoring, model fallback, auth fixes, pnpm fix
Build Electron Desktop App / Validate version (push) Failing after 35s
Build Electron Desktop App / Build Electron (macos-arm64) (push) Has been skipped
Build Electron Desktop App / Build Electron (linux) (push) Has been skipped
Build Electron Desktop App / Build Electron (macos-intel) (push) Has been skipped
Build Electron Desktop App / Build Electron (windows) (push) Has been skipped
Build Electron Desktop App / Create Release (push) Has been skipped
- Tiered quota scoring (Ultra>Pro>Free) as 7th Auto-Combo factor
- Intra-family model fallback on 404/400/403 errors
- Configurable API bridge timeout (API_BRIDGE_PROXY_TIMEOUT_MS)
- INITIAL_PASSWORD accepted on first login with timingSafeEqual
- README </details> truncation fix (affects all GitHub renders)
- pnpm @swc/helpers override conflict removed
- CLI path injection hardening (isSafePath validator)
- 429 retry, Gemini CLI headers, Claude response_format injection
- deepseek-3.1/3.2, qwen3-coder-next pricing added
- starchart.cc star widget in all 30 READMEs
2026-03-12 18:18:53 -03:00
diegosouzapw 639b49fc5b fix(ci): regenerate package-lock.json after removing @swc/helpers override
The @swc/helpers override removal changed dependency resolution.
npm ci was failing with 'Missing: @swc/helpers@0.5.15 from lock file'.
Updated lock file with npm install --package-lock-only.
2026-03-12 18:17:45 -03:00
diegosouzapw c0252f7b13 docs: replace star-history.com widget with starchart.cc in all READMEs
star-history.com embeds are often cached and slow to update. The new
starchart.cc widget (variant=adaptive) renders better on both light and
dark themes and updates in real-time.

Updated: README.md + 29 i18n locale READMEs
2026-03-12 18:15:38 -03:00
diegosouzapw a87d64372f feat: Phase 1 & 2 implementation plan — T1-T10, T12
T1 (openai-to-claude.ts): response_format injection for json_schema/json_object
T2 (base.ts): intra-URL retry for 429 errors (2x, 2s delay)
T3 (gemini-cli.ts): CLI fingerprint headers (User-Agent, X-Goog-Api-Client)
T5 (modelFamilyFallback.ts + chatCore.ts): intra-family model fallback on 400/404
T9 (pricing.ts): deepseek-3.1, deepseek-3.2, qwen3-coder-next pricing
T10 (scoring.ts + modePacks.ts): tierPriority as 7th scoring factor (Ultra>Pro>Free)
T12 (cliRuntime.ts): isSafePath() guard for CLI_*_BIN env var paths
2026-03-12 18:06:53 -03:00
diegosouzapw 02b19e63e8 fix(pnpm): remove @swc/helpers override conflict, add pnpm build-scripts config (#328)
The @swc/helpers override in package.json duplicated the direct dependency
at the exact same version (0.5.19), causing 'EOVERRIDE' errors when pnpm
users tried to rebuild native modules like better-sqlite3.

Fixes:
- Remove redundant 'overrides' block (direct dep already pins 0.5.19)
- Add pnpm.onlyBuiltDependencies for @parcel/watcher, @swc/core,
  better-sqlite3, esbuild, omniroute, sharp (replaces pnpm approve-builds)
- Add pnpm usage note to README Quick Start

Closes #328
2026-03-12 18:06:27 -03:00
diegosouzapw dba16363b7 fix(api-bridge): make proxy timeout configurable via env (#332)
Add API_BRIDGE_PROXY_TIMEOUT_MS env var to configure the api-bridge
proxy timeout. Default remains 30000ms for backward compatibility.
Handles invalid values with a warning log.

Co-authored-by: hijak <54431520+hijak@users.noreply.github.com>
2026-03-12 18:04:44 -03:00
diegosouzapw d20a2b3e44 fix(auth): accept INITIAL_PASSWORD when changing first password (#333)
- Use timingSafeEqual for constant-time password comparison
- Require non-empty currentPassword when INITIAL_PASSWORD env is set
- Legacy fallback: allow empty or '123456' when no INITIAL_PASSWORD

Co-authored-by: hijak <54431520+hijak@users.noreply.github.com>
2026-03-12 18:04:20 -03:00
diegosouzapw 677f5f8713 fix(docs): add missing </details> closing tag in Troubleshooting section
The outer <details> block at line 1459 was never closed, causing GitHub
to stop rendering everything below Troubleshooting (Tech Stack, Docs,
Roadmap, Contributors, etc.).

Fixes: README truncation on GitHub
2026-03-12 18:03:43 -03:00
diegosouzapw 7da23a90d4 feat: Make providerId nullable in providersBatchTestSchema and update validation to treat null as an absent value. 2026-03-12 17:08:26 -03:00
diegosouzapw 8dad2d32b6 fix(cli-tools): add opencode to cliRuntime, increase timeouts for slow-start CLIs
Build Electron Desktop App / Validate version (push) Failing after 42s
Build Electron Desktop App / Build Electron (macos-arm64) (push) Has been skipped
Build Electron Desktop App / Build Electron (linux) (push) Has been skipped
Build Electron Desktop App / Build Electron (macos-intel) (push) Has been skipped
Build Electron Desktop App / Build Electron (windows) (push) Has been skipped
Build Electron Desktop App / Create Release (push) Has been skipped
- opencode: add to CLI_TOOLS registry with 15s healthcheck timeout
- openclaw/cursor: increase from 12s → 15s (cold-start on VPS)
- continue: add healthcheckTimeoutMs 15s
- VPS: activated CLI_EXTRA_PATHS=/root/.local/bin for kiro-cli visibility
- VPS: installed droid and openclaw npm packages
2026-03-12 16:42:43 -03:00
diegosouzapw d07a5f0df7 fix(cli-tools): increase kilocode healthcheck timeout from 4s to 15s
Build Electron Desktop App / Validate version (push) Failing after 35s
Build Electron Desktop App / Build Electron (macos-arm64) (push) Has been skipped
Build Electron Desktop App / Build Electron (linux) (push) Has been skipped
Build Electron Desktop App / Build Electron (macos-intel) (push) Has been skipped
Build Electron Desktop App / Build Electron (windows) (push) Has been skipped
Build Electron Desktop App / Create Release (push) Has been skipped
kilocode renders ASCII logo banner on startup causing false healthcheck_failed
timeouts on cold-start or low-resource environments (VPS, CI, dashboard)
2026-03-12 16:34:39 -03:00
jack 55a9e31932 fix(auth): use timing-safe compare for INITIAL_PASSWORD check 2026-03-12 17:28:04 +00:00
jack e62be7e6b3 fix(auth): require explicit INITIAL_PASSWORD match on first password change 2026-03-12 17:04:26 +00:00
jack 7f9ec724ae fix(api-bridge): validate configured proxy timeout value 2026-03-12 17:02:30 +00:00
jack daaa3a8782 fix(auth): allow INITIAL_PASSWORD when updating first password 2026-03-12 17:00:01 +00:00
jack d1c62420bf fix(api-bridge): make proxy timeout configurable via env 2026-03-12 16:59:10 +00:00
diegosouzapw 1c10cfe4bc fix(lint): replace as any with Record<string,unknown> in OAuthModal — passes check:any-budget:t11
Build Electron Desktop App / Validate version (push) Failing after 29s
Build Electron Desktop App / Build Electron (macos-arm64) (push) Has been skipped
Build Electron Desktop App / Build Electron (linux) (push) Has been skipped
Build Electron Desktop App / Build Electron (macos-intel) (push) Has been skipped
Build Electron Desktop App / Build Electron (windows) (push) Has been skipped
Build Electron Desktop App / Create Release (push) Has been skipped
Also bump version to 2.3.10
2026-03-12 13:48:30 -03:00
diegosouzapw a4252d52ce docs: add CLI-TOOLS.md guide with all 11 tools + i18n 30 languages
- docs/CLI-TOOLS.md: complete guide covering claude, codex, gemini, opencode,
  cline, kilocode, continue, kiro-cli, cursor, droid (built-in), openclaw (built-in)
- Includes: install commands, per-tool config, quick setup script, troubleshooting table
- All 3 endpoint types documented (/v1/chat/completions, /v1/responses, /v1/completions)
- docs/i18n/<lang>/CLI-TOOLS.md: synced to all 29 languages with translated title + intro
- .gitignore: added !docs/CLI-TOOLS.md to allowlist
2026-03-12 13:41:40 -03:00
diegosouzapw 1d7bc5fed7 feat: add /v1/completions legacy endpoint + show all 3 OpenAI endpoints in dashboard
Build Electron Desktop App / Validate version (push) Failing after 38s
Build Electron Desktop App / Build Electron (macos-arm64) (push) Has been skipped
Build Electron Desktop App / Build Electron (linux) (push) Has been skipped
Build Electron Desktop App / Build Electron (macos-intel) (push) Has been skipped
Build Electron Desktop App / Build Electron (windows) (push) Has been skipped
Build Electron Desktop App / Create Release (push) Has been skipped
- New route /v1/completions: accepts prompt string (legacy) + messages array
  Normalizes prompt format to chat/completions format automatically
- EndpointPageClient: Added 3rd card (Completions Legacy) in Core APIs section
  Dashboard now shows: /v1/chat/completions, /v1/responses, /v1/completions
- i18n: completionsLegacy/completionsLegacyDesc synced to 30 languages
2026-03-12 12:57:31 -03:00
diegosouzapw 763fdf3135 chore: release v2.3.8 — OAuthModal [object Object] fix
Build Electron Desktop App / Validate version (push) Failing after 39s
Build Electron Desktop App / Build Electron (macos-arm64) (push) Has been skipped
Build Electron Desktop App / Build Electron (linux) (push) Has been skipped
Build Electron Desktop App / Build Electron (macos-intel) (push) Has been skipped
Build Electron Desktop App / Build Electron (windows) (push) Has been skipped
Build Electron Desktop App / Create Release (push) Has been skipped
2026-03-12 12:42:40 -03:00
diegosouzapw 82314562e7 fix: OAuthModal [object Object] - extract message from error objects
All 3 throw new Error(data.error) replaced with proper extraction:
  typeof error === object ? error.message : error
Fixes Cline and other OAuth providers showing [object Object] on connection failure
2026-03-12 12:39:42 -03:00
diegosouzapw 69e9bd81e9 chore: release v2.3.7
Build Electron Desktop App / Validate version (push) Failing after 33s
Build Electron Desktop App / Build Electron (macos-arm64) (push) Has been skipped
Build Electron Desktop App / Build Electron (linux) (push) Has been skipped
Build Electron Desktop App / Build Electron (macos-intel) (push) Has been skipped
Build Electron Desktop App / Build Electron (windows) (push) Has been skipped
Build Electron Desktop App / Create Release (push) Has been skipped
- Cline OAuth base64 decodeURIComponent fix
- OAuth account name normalization (name=email fallback)
- Remove sequential Account N naming
2026-03-12 12:25:17 -03:00
diegosouzapw 26f927f798 fix: replace sequential Account N with stable ID-based fallback for OAuth accounts
Remove Account cntValue+1 sequential naming (confusing when accounts deleted)
Leave name=null when no email → getAccountDisplayName returns Account ID-based label
2026-03-12 12:23:51 -03:00
diegosouzapw 2042dcf991 fix: Cline OAuth base64 parsing + name=email fallback for all OAuth accounts
- cline.ts: add decodeURIComponent before base64 decode to handle URL-encoded codes
- cline.ts: populate name = firstName+lastName || email in mapTokens
- oauth/exchange route: normalize name=email for all providers on exchange/poll/poll-callback
- Fixes: accounts showing Account #ID instead of email in providers dashboard
2026-03-12 12:22:20 -03:00
diegosouzapw 87ffe41d8c fix: i18n sync 29 langs + provider test [object Object] fix
Build Electron Desktop App / Validate version (push) Failing after 32s
Build Electron Desktop App / Build Electron (macos-arm64) (push) Has been skipped
Build Electron Desktop App / Build Electron (linux) (push) Has been skipped
Build Electron Desktop App / Build Electron (macos-intel) (push) Has been skipped
Build Electron Desktop App / Build Electron (windows) (push) Has been skipped
Build Electron Desktop App / Create Release (push) Has been skipped
- Add cliTools.toolDescriptions.opencode, .kiro, guides.opencode, guides.kiro to en.json
- Sync 1111 missing keys across 29 language files (English fallbacks)
- Fix [object Object] in provider batch test modal:
  normalize data.error object to string before setTestResults()
  and in ProviderTestResultsView rendering
- Bump version to 2.3.6
2026-03-12 11:11:15 -03:00
diegosouzapw 943a9374b4 fix: permanent @swc/helpers MODULE_NOT_FOUND fix (#crash)
Build Electron Desktop App / Validate version (push) Failing after 28s
Build Electron Desktop App / Build Electron (macos-arm64) (push) Has been skipped
Build Electron Desktop App / Build Electron (linux) (push) Has been skipped
Build Electron Desktop App / Build Electron (macos-intel) (push) Has been skipped
Build Electron Desktop App / Build Electron (windows) (push) Has been skipped
Build Electron Desktop App / Create Release (push) Has been skipped
prepublish.mjs: explicitly copy @swc/helpers into standalone app/node_modules
before packaging. npm tarball will always include it.

postinstall.mjs: fallback copy of @swc/helpers from root node_modules into
app/node_modules/@swc/ when missing after npm install -g.

Fixes server crash after npm install -g omniroute.
2026-03-12 10:42:59 -03:00
diegosouzapw 8956ffef73 chore: release v2.3.4
Build Electron Desktop App / Validate version (push) Failing after 32s
Build Electron Desktop App / Build Electron (macos-arm64) (push) Has been skipped
Build Electron Desktop App / Build Electron (linux) (push) Has been skipped
Build Electron Desktop App / Build Electron (macos-intel) (push) Has been skipped
Build Electron Desktop App / Build Electron (windows) (push) Has been skipped
Build Electron Desktop App / Create Release (push) Has been skipped
2026-03-12 10:27:45 -03:00
diegosouzapw 4383e7d807 feat(ui): endpoint page music section, fixed action buttons, provider logos
Endpoints page:
- Add Music Generation section (/v1/music/generations) in Media & Multi-Modal category
- Include music models (type=music) in endpointData and total model count
- Transcription section already shows Deepgram/AssemblyAI via allModels filter

Provider action buttons:
- Remove hover-only behavior from connection action buttons (edit/delete/reauth/proxy)
- Remove hover-only behavior from combo action buttons (test/duplicate/proxy/edit/delete)
- Buttons now always visible for better UX

Provider logos (SVG fallback):
- ProviderCard now tries .svg before showing text initials when .png not found
- Add SVG logos: ElevenLabs, Hyperbolic, AssemblyAI, PlayHT, Inworld, NanoBanana
- Add ollama-cloud.png (official Ollama icon)
2026-03-12 10:21:05 -03:00
diegosouzapw 863055768e fix(docker): copy native-binary-compat.mjs into build image
postinstall.mjs imports native-binary-compat.mjs but the Dockerfile
only copied postinstall.mjs, causing ERR_MODULE_NOT_FOUND during npm ci:

  Cannot find module '/app/scripts/native-binary-compat.mjs'
  imported from /app/scripts/postinstall.mjs
2026-03-12 10:11:50 -03:00
diegosouzapw 2c1da9e146 fix(ci): resolve 3 GitHub Actions workflow failures
- docs/openapi.yaml: bump version 2.3.1 → 2.3.3 (fixes check:docs-sync CI step)
- tests/unit/model-parse.test.mjs: add missing 'import {test}' from node:test (fixes ReferenceError in unit tests)
- electron/package.json: convert author to object with email (fixes fpm .deb build: 'Please specify author email')
2026-03-12 10:10:45 -03:00
diegosouzapw 845787ab7f chore(release): v2.3.3
Build Electron Desktop App / Validate version (push) Failing after 37s
Build Electron Desktop App / Build Electron (macos-arm64) (push) Has been skipped
Build Electron Desktop App / Build Electron (linux) (push) Has been skipped
Build Electron Desktop App / Build Electron (macos-intel) (push) Has been skipped
Build Electron Desktop App / Build Electron (windows) (push) Has been skipped
Build Electron Desktop App / Create Release (push) Has been skipped
fix(providers): prevent error boundary crash when Test All fails or times out (PR #330)
2026-03-12 09:56:51 -03:00
Diego Rodrigues de Sa e Souza 1db948e9bb Merge pull request #330 from diegosouzapw/fix/providers-test-all-crash
fix(providers): prevent error boundary crash when Test All fails or times out
2026-03-12 09:56:25 -03:00
diegosouzapw f0d00bcee5 fix(providers): prevent error boundary when 'Test All' times out or returns bad JSON
- Add AbortController (90s timeout) to handleBatchTest fetch
- Add inner try/catch for res.json() — handles truncated/non-JSON responses
- Guard ProviderTestResultsView against null/undefined results (was crashing → error boundary)
- Improve error check: error path now also guards results.results.length === 0
- Add 'providerTestTimeout' i18n key for friendly timeout message
2026-03-12 09:38:40 -03:00
diegosouzapw 1e9a9adbad chore(release): v2.3.2
Build Electron Desktop App / Validate version (push) Failing after 38s
Build Electron Desktop App / Build Electron (macos-arm64) (push) Has been skipped
Build Electron Desktop App / Build Electron (linux) (push) Has been skipped
Build Electron Desktop App / Build Electron (macos-intel) (push) Has been skipped
Build Electron Desktop App / Build Electron (windows) (push) Has been skipped
Build Electron Desktop App / Create Release (push) Has been skipped
feat(claude): [1m] suffix for 1M extended context (PR #311 @DavyMassoneto)
feat(registry): new models for iFlow, Qwen, Kimi (PR #326 @nyatoru)
fix(cli): postinstall binary copy instead of rebuild (PR #327 @ardaaltinors, fixes #321)
docs: English Remote OAuth guide in README (PR #329, fixes #318)
test: 3 unit tests for parseModel [1m] suffix
2026-03-12 07:00:10 -03:00
Diego Rodrigues de Sa e Souza d87c7c3b8c Merge pull request #311 from DavyMassoneto/fix/merge-duplicates-and-lint-warnings
feat(claude): support [1m] suffix for 1M extended context window
2026-03-12 06:58:57 -03:00
Diego Rodrigues de Sa e Souza eb3c834609 Merge pull request #326 from nyatoru/update/sync-qwen-iflow-model
feat(registry): add new models to the provider registry
2026-03-12 06:58:12 -03:00
Diego Rodrigues de Sa e Souza e53c76081f Merge pull request #327 from ardaaltinors/fix/postinstall-copy-native-binary
fix(cli): fix postinstall native binary rebuild regression (#321)
2026-03-12 06:58:10 -03:00
Diego Rodrigues de Sa e Souza 134316328c Merge pull request #329 from diegosouzapw/fix/issue-318-readme-oauth-en
docs: add English Remote OAuth guide to README (#318)
2026-03-12 06:58:07 -03:00
diegosouzapw 4767561f02 docs: add English translation for Remote OAuth section in README (#318)
The '🔐 OAuth on a Remote Server' guide existed only in Portuguese (#oauth-em-servidor-remoto).
Multiple users (@hijak, @ldsgroups225, @vipinpg) couldn't find it in English.

Changes:
- Full English step-by-step guide added above the existing PT content
- Added 'oauth-on-a-remote-server' anchor (EN) alongside 'oauth-em-servidor-remoto' (PT)
- Portuguese version moved into a collapsible <details> section
- OAuthModal.tsx already updated in v2.3.1 to link to #oauth-on-a-remote-server
2026-03-12 06:56:05 -03:00
Nyaru Toru 2d6b31b606 Update open-sse/config/providerRegistry.ts
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
2026-03-12 15:08:05 +07:00
ardaaltinors a22f0a4e7b fix(cli): address review feedback on native binary detection and postinstall
- Read only first 4096 bytes of binary header instead of entire file
- Add error logging to all catch blocks with specific failure messages
- Separate copy vs dlopen catch blocks in postinstall Strategy 1
- Add archCount sanity cap (max 30) for fat Mach-O parsing
- Distinguish timeout vs rebuild failure in Strategy 2
2026-03-12 10:34:56 +03:00
ardaaltinors 5a244aa12a fix(cli): include native-binary-compat.mjs in published package files
The module is imported by bin/omniroute.mjs but was missing from the
files array in package.json, causing ERR_MODULE_NOT_FOUND on global
installs.
2026-03-12 10:26:16 +03:00
ardaaltinors 69d28bec4d feat(cli): detect native binary platform from file header instead of dlopen
Add native-binary-compat module that reads ELF/Mach-O/PE headers to
determine the actual target platform/arch of the .node binary. This
eliminates the macOS false-positive where dlopen loads a linux-x64
binary without throwing.

- Parse ELF (linux), Mach-O (darwin), and PE (win32) binary formats
- Use header-based check as primary signal, dlopen as secondary
- Update pre-flight check in CLI to use the new module
- Add unit tests for all binary formats and cross-platform scenarios
2026-03-12 10:20:08 +03:00
ardaaltinors c859665c6b fix(cli): copy native binary from root node_modules instead of rebuilding (#321)
The standalone app/ directory created by Next.js only contains runtime
files for better-sqlite3 (no binding.gyp, no source, no prebuild-install),
so `npm rebuild` inside app/ is a no-op. The previous fix (#312) added
exit(1) on rebuild failure, which caused npm to rollback the entire
package installation — leaving users with nothing to fix manually.

New approach:
1. Check if existing binary is already compatible (dlopen)
2. Copy the correctly-built binary from root node_modules/ (npm already
   compiles it for the correct platform during install)
3. Fall back to npm rebuild if root binary is unavailable
4. Warn but don't fail the install if nothing works — the package stays
   installed and the CLI pre-flight check gives a clear error at startup
2026-03-12 10:07:43 +03:00
nyatoru e7b19758f3 feat(registry): add new models to the provider registry 2026-03-12 11:18:16 +08:00
DavyMassoneto 623c63baf6 feat(claude): support [1m] suffix for 1M context window
Parse [1m] suffix from model name (e.g. claude-sonnet-4-6[1m]) and
propagate extendedContext flag through the request pipeline to append
context-1m-2025-08-07 to the Anthropic-Beta header.
2026-03-11 23:53:09 -03:00
diegosouzapw a3ad7c6c2e chore(release): v2.3.1
Build Electron Desktop App / Validate version (push) Failing after 39s
Build Electron Desktop App / Build Electron (macos-arm64) (push) Has been skipped
Build Electron Desktop App / Build Electron (linux) (push) Has been skipped
Build Electron Desktop App / Build Electron (macos-intel) (push) Has been skipped
Build Electron Desktop App / Build Electron (windows) (push) Has been skipped
Build Electron Desktop App / Create Release (push) Has been skipped
fix(ui): translate hardcoded PT-BR text in OAuthModal to English (#314, PR #325)
fix(ts): wrap unknown dataObj fields with toRecord() in usage.ts (Kimi parser)
fix(instrumentation): await getSettings() — property access on Promise (#316 follow-up)
2026-03-11 20:49:37 -03:00
Diego Rodrigues de Sa e Souza afc9362ca5 Merge pull request #325 from diegosouzapw/fix/issue-314-oauth-modal-pt-text
fix(ui): translate hardcoded PT-BR text in OAuthModal to English (#314)
2026-03-11 20:48:31 -03:00
diegosouzapw f6b125e8c2 fix(ui): translate hardcoded PT-BR text in OAuthModal to English (#314)
Two strings were hardcoded in Portuguese regardless of the user's language setting:
1. The redirect_uri_mismatch error message (line ~101)
2. The remote access info banner for Google OAuth providers (line ~515)

Both are now in English. The anchor href is updated from
'#oauth-em-servidor-remoto' to '#oauth-on-a-remote-server' to match
the EN README anchor.
2026-03-11 20:45:45 -03:00
diegosouzapw 5df3c22be8 fix(ts): wrap unknown dataObj fields with toRecord() in usage.ts (Kimi usage parser)
Six TypeScript errors on lines 921/922/925/926/939/948:
- dataObj.five_hour / seven_day are 'unknown', can't be passed directly to
  hasUtilization/createQuotaObject which expect JsonRecord — wrap with toRecord()
- dataObj.user is 'unknown', can't chain .membership?.level — use toRecord() first
2026-03-11 20:45:39 -03:00
diegosouzapw 11a0df5443 fix(instrumentation): await getSettings() — property access on Promise (#316 follow-up)
getSettings() is declared async so calling it without await left
settings as a Promise<Record<string, unknown>>, causing 4 TS errors
when accessing settings.modelAliases in the alias restore block.
2026-03-11 13:07:39 -03:00
diegosouzapw e27a2a0d55 chore(release): v2.3.0
Build Electron Desktop App / Validate version (push) Failing after 30s
Build Electron Desktop App / Build Electron (macos-arm64) (push) Has been skipped
Build Electron Desktop App / Build Electron (linux) (push) Has been skipped
Build Electron Desktop App / Build Electron (macos-intel) (push) Has been skipped
Build Electron Desktop App / Build Electron (windows) (push) Has been skipped
Build Electron Desktop App / Create Release (push) Has been skipped
fix(aliases): custom model aliases applied to routing + restored on startup (#315 #316, PR #317)
fix(cli): better-sqlite3 postinstall rebuild cross-platform macOS ARM (#312, PR #313 @ardaaltinors)
2026-03-11 12:43:50 -03:00
Diego Rodrigues de Sa e Souza dc8abe60ee Merge pull request #317 from diegosouzapw/fix/issue-315-316-alias-bugs
fix(aliases): resolve custom model aliases before routing + restore on startup (#315, #316)
2026-03-11 12:43:02 -03:00
diegosouzapw afe2ab37e4 fix(aliases): resolve custom model aliases before routing + restore on startup (#315, #316)
#315: Import and call resolveModelAlias() in chatCore.ts before the
getModelTargetFormat() lookup so that custom aliases configured in
Settings → Model Aliases → Pattern→Target are actually applied during
routing instead of being silently ignored.

#316: Load persisted custom model aliases from settings DB at server
startup (instrumentation.ts). Previously _customAliases started as an
empty object after every restart since setCustomAliases() was only
called by the PUT /api/settings/model-aliases handler — never at init.
Now aliases are restored from settings.modelAliases JSON field on boot.
2026-03-11 12:42:18 -03:00
Diego Rodrigues de Sa e Souza f7bd99f965 Merge pull request #313 from ardaaltinors/fix/better-sqlite3-postinstall-rebuild
fix(cli): improve better-sqlite3 postinstall rebuild for cross-platform installs
2026-03-11 12:39:03 -03:00
ardaaltinors f5238944b4 fix(cli): improve better-sqlite3 postinstall rebuild for cross-platform installs (#312)
Replace unreliable process.dlopen() platform detection with explicit
platform/arch comparison against the build target (linux-x64). On macOS,
dlopen can load an incompatible binary without throwing, causing the
postinstall script to skip the rebuild entirely.

- Detect platform mismatch via process.platform/arch instead of dlopen
- Fail the install (exit 1) if rebuild fails, instead of warning silently
- Verify rebuilt binary loads correctly after rebuild
- Add pre-flight binary check in CLI entry point as a safety net
2026-03-11 17:11:00 +03:00
diegosouzapw c7ae9c30c2 chore(release): v2.2.9
Build Electron Desktop App / Validate version (push) Failing after 36s
Build Electron Desktop App / Build Electron (macos-arm64) (push) Has been skipped
Build Electron Desktop App / Build Electron (linux) (push) Has been skipped
Build Electron Desktop App / Build Electron (macos-intel) (push) Has been skipped
Build Electron Desktop App / Build Electron (windows) (push) Has been skipped
Build Electron Desktop App / Create Release (push) Has been skipped
feat(providers): persist custom model endpoint edits (#307, PR #307 by @hijak)
fix(deps): add @swc/helpers as explicit dep to fix MODULE_NOT_FOUND (#306, PR #308)
fix(usage): correct Claude quota display — utilization = % used (#299, PR #309)
2026-03-11 08:46:16 -03:00
Diego Rodrigues de Sa e Souza 82f7a12a46 Merge pull request #309 from diegosouzapw/fix/issue-299-claude-quota-inversion
fix(usage): correct Claude quota display — utilization = % used (#299)
2026-03-11 08:45:05 -03:00
Diego Rodrigues de Sa e Souza f494a8531b Merge pull request #308 from diegosouzapw/fix/issue-306-swc-helpers-missing
fix(deps): add @swc/helpers as explicit dependency (#306)
2026-03-11 08:45:01 -03:00
Diego Rodrigues de Sa e Souza 36ed0499db Merge pull request #307 from hijak/fix/provider-model-endpoints-save
fix(providers): persist supported endpoints with explicit save
2026-03-11 08:44:58 -03:00
diegosouzapw 46cff2200d fix(usage): correct Claude quota display — utilization = % used, not % remaining (#299)
The Claude Code OAuth API returns 'utilization' as percent USED,
not percent remaining. The createQuotaObject function had them swapped:
it set remainingPercentage = utilization, which inverted the quota bar.

Confirmed by reporter: Claude.ai shows 87% used → OmniRoute was showing
87% remaining (green bar), should show 13% remaining (yellow/red bar).

Fix: used = utilization; remaining = 100 - utilization.
2026-03-11 08:42:44 -03:00
diegosouzapw 5ea6ad4a9e fix(deps): add @swc/helpers as explicit dependency (#306)
next@16 lists @swc/helpers@0.5.15 in its own dependencies but npm's
deduplication during global install fails to place it in the omniroute
app's node_modules when hoisted. This causes MODULE_NOT_FOUND for
@swc/helpers/esm/_interop_require_default.js on startup.

Fix: add @swc/helpers@0.5.19 to omniroute's top-level dependencies and
overrides so npm guarantees its presence regardless of hoisting strategy.
Reproducible on Windows (Node 22) and Linux.
2026-03-11 08:40:31 -03:00
jack 6cad4fae8e fix(providers): persist supported endpoints with explicit save for custom models 2026-03-11 11:20:25 +00:00
diegosouzapw 8df24c855b chore(release): v2.2.8
Build Electron Desktop App / Validate version (push) Failing after 32s
Build Electron Desktop App / Build Electron (macos-arm64) (push) Has been skipped
Build Electron Desktop App / Build Electron (linux) (push) Has been skipped
Build Electron Desktop App / Build Electron (macos-intel) (push) Has been skipped
Build Electron Desktop App / Build Electron (windows) (push) Has been skipped
Build Electron Desktop App / Create Release (push) Has been skipped
fix(docker): healthcheck now uses /api/monitoring/health (#296, PR #301)
fix(rate-limit): maxWait=120s on Bottleneck prevents endless queue (#297, PR #302)
2026-03-11 00:20:57 -03:00
Diego Rodrigues de Sa e Souza f25882c0e9 Merge pull request #302 from diegosouzapw/fix/issue-296-healthcheck-endpoint
fix(docker): use /api/monitoring/health for Docker healthcheck (#296)
2026-03-11 00:20:17 -03:00
Diego Rodrigues de Sa e Souza be6c769192 Merge pull request #301 from diegosouzapw/fix/issue-297-rate-limit-maxwait
fix(rate-limit): prevent endless queue with maxWait (#297)
2026-03-11 00:20:14 -03:00
diegosouzapw a4276444b5 fix(rate-limit): add maxWait to Bottleneck to prevent endless queuing (#297)
When all provider quotas are exhausted (reservoir=0 after repeated 429s),
Bottleneck's schedule() would queue requests indefinitely since no maxWait
was configured. Clients (Cursor, Claude Code, VS Code) would hang forever.

Fix: add maxWait=120000 (2min, configurable via RATE_LIMIT_MAX_WAIT_MS env)
to DEFAULT_SETTINGS and all three Bottleneck constructors. When a job waits
longer than maxWait, Bottleneck rejects with a BottleneckError which
propagates as a 502/503 error to the client — a clean fail-fast instead
of infinite hang.
2026-03-10 23:58:36 -03:00
diegosouzapw 0af27b8d8a fix(docker): use /api/monitoring/health for healthcheck (#296)
The healthcheck script was querying /api/settings which returns config
data rather than system health. Updated to /api/monitoring/health which
is the canonical health endpoint used across tests, SystemMonitor.tsx,
MaintenanceBanner.tsx, playwright config, and MCP tools.
2026-03-10 23:57:17 -03:00
diegosouzapw 542eb0e719 chore(release): v2.2.7
Build Electron Desktop App / Validate version (push) Failing after 31s
Build Electron Desktop App / Build Electron (macos-arm64) (push) Has been skipped
Build Electron Desktop App / Build Electron (linux) (push) Has been skipped
Build Electron Desktop App / Build Electron (macos-intel) (push) Has been skipped
Build Electron Desktop App / Build Electron (windows) (push) Has been skipped
Build Electron Desktop App / Create Release (push) Has been skipped
fix(docker): bootstrap-env.mjs missing in runtime image (#292, PR #293)
fix(google-cli): prefer OAuth projectId over stale body.project (PR #294)
fix(chat): strip empty name from messages/input before upstream (#291, PR #300)
deps: bump hono 4.12.4 → 4.12.7 (PR #298)
2026-03-10 23:34:19 -03:00
Diego Rodrigues de Sa e Souza c658b39270 Merge pull request #300 from diegosouzapw/fix/issue-291-strip-empty-name
fix(chat): strip empty name from messages/input before upstream (#291)
2026-03-10 23:33:04 -03:00
Diego Rodrigues de Sa e Souza 52ef3dfc7e Merge pull request #298 from diegosouzapw/dependabot/npm_and_yarn/hono-4.12.7
deps: bump hono from 4.12.4 to 4.12.7
2026-03-10 23:33:01 -03:00
Diego Rodrigues de Sa e Souza 57da407693 Merge pull request #294 from hijak/fix/google-cli-prefer-oauth-projectid
fix(google-cli): prefer OAuth projectId over request body project
2026-03-10 23:32:59 -03:00
Diego Rodrigues de Sa e Souza d2d6fc5883 Merge pull request #293 from hijak/fix/docker-bootstrap-env-missing
fix(docker): include bootstrap-env.mjs in runtime image
2026-03-10 23:32:57 -03:00
diegosouzapw 6a7a6022d4 fix(chat): strip empty name fields from messages/input before upstream (#291)
OpenAI-compatible providers (OpenAI, Codex) reject name:'' with 400 errors:
  - 'Unknown parameter: input[1].name'
  - 'Invalid tools[0].name: empty string'

Some clients (e.g. PocketPaw) forward assistant turns with name:'' in
the OpenAI Responses API input[] and chat completions messages[].

Fix: filter out name:'' from messages[] and input[] before translateRequest.
Non-empty non-null name values are preserved per OpenAI spec.
2026-03-10 23:31:31 -03:00
dependabot[bot] b53eafa615 deps: bump hono from 4.12.4 to 4.12.7
Bumps [hono](https://github.com/honojs/hono) from 4.12.4 to 4.12.7.
- [Release notes](https://github.com/honojs/hono/releases)
- [Commits](https://github.com/honojs/hono/compare/v4.12.4...v4.12.7)

---
updated-dependencies:
- dependency-name: hono
  dependency-version: 4.12.7
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-03-11 02:07:19 +00:00
jack c949214e99 feat(google-cli): add env escape hatch for body.project override 2026-03-10 22:15:26 +00:00
jack 887cf25b65 fix(google-cli): prefer OAuth projectId over client body project 2026-03-10 22:12:39 +00:00
jack dd6142196f fix(docker): copy bootstrap-env.mjs into runtime image 2026-03-10 21:55:21 +00:00
diegosouzapw 902c7244d1 chore(release): v2.2.6
Build Electron Desktop App / Validate version (push) Failing after 32s
Build Electron Desktop App / Build Electron (macos-arm64) (push) Has been skipped
Build Electron Desktop App / Build Electron (linux) (push) Has been skipped
Build Electron Desktop App / Build Electron (macos-intel) (push) Has been skipped
Build Electron Desktop App / Build Electron (windows) (push) Has been skipped
Build Electron Desktop App / Create Release (push) Has been skipped
fix(translator): map Claude thinking_delta to reasoning_content (#289)
- Close #289: thinking tokens now visible in Claude Code, Cursor, Windsurf
2026-03-10 16:21:20 -03:00
Diego Rodrigues de Sa e Souza 4f11762c68 Merge pull request #290 from diegosouzapw/fix/issue-289-thinking-tokens
fix(translator): map Claude thinking_delta to reasoning_content (#289)
2026-03-10 16:20:22 -03:00
diegosouzapw 8a7f7c1ba0 fix(translator): map Claude thinking_delta to reasoning_content not content (#289)
When proxying Claude responses through OmniRoute, thinking blocks were being
emitted as regular content (delta.content) with <think>...</think> XML tags.
Clients like Claude Code, Cursor, and Windsurf look for delta.reasoning_content
to render the thinking panel — not <think> tags inside content.

Root cause (claude-to-openai.ts):
  - content_block_start type:thinking → emitted { content: '<think>' }
  - content_block_delta thinking_delta → emitted { content: delta.thinking }
  - content_block_stop thinking block → emitted { content: '</think>' }

Fix:
  - content_block_start → emits { reasoning_content: '' } (signals block start)
  - thinking_delta → emits { reasoning_content: delta.thinking }
  - content_block_stop → no extra chunk needed (thinking streamed via reasoning_content)

This fix applies when sourceFormat=CLAUDE targetFormat=OPENAI (Antigravity OAuth,
direct Claude API providers). The user reported 'Thinking Budget: passthrough'
was enabled but thinking was invisible — this is the root cause.

Fixes #289
2026-03-10 15:25:31 -03:00
diegosouzapw af46f87eed feat(bootstrap): zero-config auto-generated secrets on first run
Build Electron Desktop App / Validate version (push) Failing after 33s
Build Electron Desktop App / Build Electron (macos-arm64) (push) Has been skipped
Build Electron Desktop App / Build Electron (linux) (push) Has been skipped
Build Electron Desktop App / Build Electron (macos-intel) (push) Has been skipped
Build Electron Desktop App / Build Electron (windows) (push) Has been skipped
Build Electron Desktop App / Create Release (push) Has been skipped
Resolves root cause of #252 (Electron black screen) and #249 (OAuth fail)
for users running with zero configuration (no .env needed).

New: scripts/bootstrap-env.mjs
- Auto-generates JWT_SECRET (64 bytes), STORAGE_ENCRYPTION_KEY (32 bytes),
  API_KEY_SECRET (32 bytes) if missing or empty
- Persists to {DATA_DIR}/server.env — survives restarts, Docker volume
  remounts, and upgrades without changing secrets
- Reads .env from CWD (user overrides), then merges process.env (highest prio)
- Logs friendly warnings for missing optional OAuth secrets

Updated: run-standalone.mjs + run-next.mjs
- Call bootstrapEnv() before spawning server — covers npm + Docker paths

Updated: electron/main.js (synchronous inline — CJS cannot await import ESM)
- Reads userData/server.env, generates missing secrets with crypto.randomBytes()
- Persists back to server.env, sets OMNIROUTE_BOOTSTRAPPED=true

New: BootstrapBanner.tsx + page.tsx update
- Dismissable amber banner on dashboard home when running in zero-config mode
- Shows where server.env is located and how to customize secrets
2026-03-10 15:15:07 -03:00
diegosouzapw fd749d1e0b fix(electron): auto-generate JWT_SECRET and STORAGE_ENCRYPTION_KEY if missing
In packaged Electron on macOS/Windows/Linux, there is no .env file.
The Next.js server needs JWT_SECRET and STORAGE_ENCRYPTION_KEY to start —
without them it crashes silently, causing ERR_CONNECTION_REFUSED
and a black screen in the Electron window.

Fix: Generate cryptographically random values with crypto.randomBytes()
on first launch, persist them in userData/electron-env.json, and pass
them to the spawned server.js process via the env option.

Root cause: macOS users reported 'app black screen' (#252) and
ERR_CONNECTION_REFUSED — this was the Next.js server crashing at startup
because these env vars don't exist in the desktop OS environment.
2026-03-10 15:06:57 -03:00
diegosouzapw 5046f90dfa docs(workflow): make openapi.yaml sync mandatory in generate-release
- Step 4 now marked ⚠️ MANDATORY with CI will fail warning
- Command is now auto-extracting version from package.json (no manual substitution)
- Step 4 has // turbo annotation for auto-execution
- Added 'Known CI Pitfalls' table: docs-sync failures, Electron fpm, Docker 502
2026-03-10 15:02:08 -03:00
diegosouzapw cf13e95610 fix(ci): bump openapi.yaml version to 2.2.4
check:docs-sync fails when openapi.yaml version != package.json version.
Updating to match after v2.2.4 release.

Systematic fix: openapi.yaml version must always be updated alongside
package.json during releases (see generate-release workflow step 4).
2026-03-10 14:43:17 -03:00
diegosouzapw 5763609008 feat(release): v2.2.4 — CI fixes (docs-sync, electron fpm, docker)
Build Electron Desktop App / Validate version (push) Failing after 26s
Build Electron Desktop App / Build Electron (macos-arm64) (push) Has been skipped
Build Electron Desktop App / Build Electron (linux) (push) Has been skipped
Build Electron Desktop App / Build Electron (macos-intel) (push) Has been skipped
Build Electron Desktop App / Build Electron (windows) (push) Has been skipped
Build Electron Desktop App / Create Release (push) Has been skipped
2026-03-10 14:37:04 -03:00
diegosouzapw 6d672ab09a fix(ci): docs-sync, electron linux fpm, docker cache env
CI Lint fixes:
- docs/openapi.yaml: bump version 2.2.0 → 2.2.3 (was out of sync with package.json)
- CHANGELOG.md: add '## [Unreleased]' as first section (required by check:docs-sync)

Electron Linux fix:
- electron-release.yml: add 'gem install fpm' step for Linux builds
  fpm is required by electron-builder to package .deb installers;
  ubuntu-latest runners don't have it pre-installed

Docker publish:
- docker-publish.yml: add DOCKER_BUILDKIT_INLINE_CACHE env; prev 502 was
  a transient Docker Hub network error, no code change needed
2026-03-10 14:31:48 -03:00
diegosouzapw ac68022233 feat(release): v2.2.3 — bug fixes from community PRs
Build Electron Desktop App / Validate version (push) Failing after 41s
Build Electron Desktop App / Build Electron (macos-arm64) (push) Has been skipped
Build Electron Desktop App / Build Electron (linux) (push) Has been skipped
Build Electron Desktop App / Build Electron (macos-intel) (push) Has been skipped
Build Electron Desktop App / Build Electron (windows) (push) Has been skipped
Build Electron Desktop App / Create Release (push) Has been skipped
fix(google-cli): remove fake projectId fallback causing permission/verification errors (#285)
- antigravity.ts, openai-to-gemini.ts, geminiHelper.ts
- Throws clear error instead of silently sending with random project IDs

fix(claude): extend empty tool name filter to all message roles (#288)
- Pass 1.4 now covers all roles, not just assistant
- Filters tool_result with missing tool_use_id
- Filters top-level body.tools with empty names
- Explicit @swc/helpers COPY in Dockerfile runner-base stage
2026-03-10 12:53:47 -03:00
Nina Gleichner c2b31f6b20 Fix empty tool name 400 errors from Claude API and missing @swc/helpers in Docker (#288)
* Initial plan

* fix: filter empty tool names and missing tool_use_id; add @swc/helpers to Docker

Co-authored-by: ngleichner1 <263653359+ngleichner1@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: ngleichner1 <263653359+ngleichner1@users.noreply.github.com>
2026-03-10 12:46:17 -03:00
Jack 54b1d8c8de fix(google-cli): stop random project fallback and require real OAuth projectId (#285)
Co-authored-by: jack <jack@plutus-32g.local>
2026-03-10 12:46:15 -03:00
diegosouzapw cd1ab696b2 docs: add npm run system-info to Support and troubleshooting sections
Users are now directed to run 'npm run system-info' when reporting bugs.
Added to:
- ## Support → '🐛 Reporting a Bug?' subsection
- Pain point #10 '🐛 I can't diagnose errors' bullet list
2026-03-10 12:45:20 -03:00
diegosouzapw d9d0640f6e feat(release): v2.2.2 — system-info script, Kimi/Mistral/Llama aliases
Build Electron Desktop App / Validate version (push) Failing after 28s
Build Electron Desktop App / Build Electron (macos-arm64) (push) Has been skipped
Build Electron Desktop App / Build Electron (linux) (push) Has been skipped
Build Electron Desktop App / Build Electron (macos-intel) (push) Has been skipped
Build Electron Desktop App / Build Electron (windows) (push) Has been skipped
Build Electron Desktop App / Create Release (push) Has been skipped
- New npm run system-info command (#280)
- Kimi K2/K2.5 Fireworks path aliases (#265)
- Mistral/Llama short aliases (#278)
- Custom alias instructions via Settings → Model Aliases
2026-03-10 11:00:20 -03:00
Diego Rodrigues de Sa e Souza e19046116a feat: system-info.mjs script + Kimi/Mistral/Llama model aliases (#280 #265 #278) (#284)
System Info Script (#280):
- New scripts/system-info.mjs: collects Node.js version, OmniRoute version,
  OS info, Agent CLI tool versions (iflow, gemini, claude, codex, antigravity,
  droid, openclaw, kilo, cursor, aider), Docker/PM2 status, system packages
- Outputs system-info.txt for easy attachment to bug reports
- Added npm script: 'npm run system-info'

Model Aliases (#265 #278):
- Added Kimi K2/K2.5 Fireworks path aliases to built-in alias map
  (fireworks/accounts/fireworks/models/kimi-k2p5 → moonshotai/Kimi-K2.5)
- Added short aliases: kimi-k2p5, kimi-k2, mistral-large, mistral-small,
  codestral, llama-3.3, llama-3-70b, llama-3-8b
- Custom aliases can be added via Settings → Model Aliases tab in dashboard

Co-authored-by: diegosouzapw <diegosouzapw@users.noreply.github.com>
2026-03-10 10:59:27 -03:00
diegosouzapw 82a621ec08 feat(release): v2.2.1 — bug fixes, security patches, CI hardening
Build Electron Desktop App / Validate version (push) Failing after 30s
Build Electron Desktop App / Build Electron (macos-arm64) (push) Has been skipped
Build Electron Desktop App / Build Electron (linux) (push) Has been skipped
Build Electron Desktop App / Build Electron (macos-intel) (push) Has been skipped
Build Electron Desktop App / Build Electron (windows) (push) Has been skipped
Build Electron Desktop App / Create Release (push) Has been skipped
Bug Fixes:
- fix(imageRegistry): add gemini-3.1-flash-image-preview to antigravity (#273)
- fix(models-route): add ollama-cloud to PROVIDER_MODELS_CONFIG (#276)
- fix(models-route): clear 400 error when no apiKey configured (#277)

Security:
- fix(mitm): TLS rejectUnauthorized defaults to true, opt-out via env var
- fix(backup): path traversal guards (safePath, safeProfilePath, safeLogPath)
- fix(usageHistory): prototype pollution via Object.create(null) + hasOwnProperty
- fix(deps): dompurify ^3.3.2 (CVE-2026-0540)
- fix(ci): add global permissions: contents: read to ci.yml

CI:
- fix(ci): @swc/helpers override + regenerated package-lock.json
- fix(ci): npm-publish skip if version already exists on npm
- fix(ci): npm-publish use npm install instead of npm ci
- fix(lint): cursor.ts isToolBoundaryAbort any → unknown
2026-03-10 09:50:19 -03:00
Diego Rodrigues de Sa e Souza ce560ebe9d fix: resolve issues #273, #276, #277 — image routing, models route, missing-key error (#282)
Squash merge PR #282: bug fixes for #273 (Gemini image routing), #276 (Ollama Cloud models), #277 (missing apiKey error), lint fix, and all security code-scanning patches.
2026-03-10 09:48:50 -03:00
diegosouzapw f900a81ec9 fix(ci): use npm install in npm-publish to survive lock file drift on old tags
npm ci fails if the tag commit's lock file is out of sync (as happened
with v2.2.0 when @swc/helpers was missing). npm install is safe here
because the publish workflow only needs deps to run prepublish.mjs —
strict lock enforcement is not required for the publish step.
2026-03-10 09:48:35 -03:00
diegosouzapw 2a620b178d fix(ci): skip npm publish if version already exists on npm registry
Prevents E403 failures when a release event fires more than once for the
same version (e.g. re-running a failed workflow or duplicate tag event).

The publish step now checks whether the version is already on npm and
exits cleanly with a warning instead of failing the workflow.
2026-03-10 09:46:14 -03:00
diegosouzapw 5aaaad529b fix(ci): sync package-lock.json — add @swc/helpers override + regenerate lock
All 3 CI workflows (CI, npm-publish, docker-publish) were failing with:
  'Missing: @swc/helpers@0.5.19 from lock file'

Root cause: npm version bump ran without npm install, causing the lock file
to be out of sync with CI's npm resolver (which resolves @swc/helpers@0.5.19
while local npm 10.9.4 resolves 0.5.15).

Fix: added 'overrides': { '@swc/helpers': '^0.5.19' } to package.json and
regenerated package-lock.json with npm install.

Also updated .agents/workflows/generate-release.md to enforce:
- Always use 'npm version patch --no-git-tag-version' (never minor/major)
- Always run 'npm install' after bumping to keep lock file in sync
- Version threshold: 2.x.10 → 2.(x+1).0 (manual)
2026-03-10 09:25:35 -03:00
diegosouzapw 4e15ca6bbd chore(release): v2.2.0
Build Electron Desktop App / Validate version (push) Failing after 32s
Build Electron Desktop App / Build Electron (macos-arm64) (push) Has been skipped
Build Electron Desktop App / Build Electron (linux) (push) Has been skipped
Build Electron Desktop App / Build Electron (macos-intel) (push) Has been skipped
Build Electron Desktop App / Build Electron (windows) (push) Has been skipped
Build Electron Desktop App / Create Release (push) Has been skipped
- Merge PR #275: fix(cursor): stabilize tool result handoff
- Merge PR #281: fix(validation): ElevenLabs + Inworld API key validation
- Merge PR #279: feat(kimi-coding): Kimi Coding plan quota display
- Merge PR #264: deps: bump dev group with 5 updates
- Merge PR #263: deps: bump prod group with 2 updates
- fix(ci): repair unit, e2e and i18n test failures
- fix(providers): Add Connection button for OpenAI-compatible providers (#272)
- docs: update CHANGELOG and bump openapi.yaml to 2.2.0
2026-03-10 09:12:27 -03:00
diegosouzapw 8555a3a106 fix(providers): show Add Connection button for OpenAI-compatible providers (#272)
When a manually created OpenAI/Anthropic-compatible provider has 0 connections,
the Add Connection button was hidden behind !isCompatible guard, making it
impossible to add a key. Button now appears in the Connections card header
for compatible providers too, limited to 1 connection (single key per node).
2026-03-10 09:09:18 -03:00
diegosouzapw 3a39ae6231 deps: bump the production group with 2 updates (#263) 2026-03-10 09:04:24 -03:00
diegosouzapw 00e6b7cf2c deps: bump the development group with 5 updates (#264) 2026-03-10 09:04:12 -03:00
diegosouzapw ebd1e5421b feat(kimi-coding): add Kimi Coding plan quota display (#279)
- Add getKimiUsage() with X-Msh-* device headers for Kimi API
- Parse weekly quota + rate-limit breakdown from /v1/usages endpoint
- Fix X-Msh-* headers in refreshKimiCodingToken (was missing)
- Wire kimi-coding into getUsageForProvider switch
- Add quota capability flag to providers.ts
- Remove console.warn/error (production-safe silent returns)

Co-authored-by: nyatoru <nyarutoru0002@outlook.co.th>
2026-03-10 09:04:03 -03:00
diegosouzapw 2feb2df30d refactor(kimi-usage): remove console.warn/error — use silent returns 2026-03-10 09:03:45 -03:00
diegosouzapw ba38dc738b fix(validation): support ElevenLabs and Inworld API key validation (#281)
- Add validateElevenLabsProvider (GET /v1/voices with xi-api-key)
- Add validateInworldProvider (POST /tts/v1/voice with Basic auth)
- Register both in SPECIALTY_VALIDATORS map
- Fixes false 400 errors for valid ElevenLabs/Inworld connections

Reviewed-by: Antigravity
2026-03-10 09:02:50 -03:00
diegosouzapw 9233edb6cd fix(cursor): stabilize tool result handoff for Cursor tool calls (#275)
- Stop double-translation in Cursor executor path (preserved tool_results)
- Normalize OpenAI+Anthropic tool flows into Cursor-compatible shapes
- escapeXml() prevents tag injection in tool_result blocks
- Set-based finalizedIds for O(1) deduplication (replaces O(n) .find)
- Byte guard (0x7b) before payload.toString on non-JSON frames
- Convert console.log noise to debugLog() (prod clean)

Fixes #274. Reviewed-by: Antigravity
2026-03-10 09:02:30 -03:00
diegosouzapw f697c56922 fix(ci): repair unit, e2e and i18n failures
- tests/unit/combo-circuit-breaker: use full model path keys
  (combo:groq/llama-3.3-70b) matching combo.ts implementation
- tests/e2e/protocol-visibility: click Protocols tab before asserting
  MCP/A2A links (they moved into tab panel, not header nav)
- src/i18n/messages/en.json: add missing header.mcp / header.a2a keys
  that caused MISSING_MESSAGE runtime errors during E2E boot
2026-03-10 08:47:06 -03:00
jack 5ab6a3b431 fix(validation): support elevenlabs and inworld API key checks 2026-03-10 11:20:19 +00:00
Rafael Calleja 25cd0b3612 refactor(cursor): simplify review — Set lookups, byte guards, XML escaping
- Replace O(n*k) chunks.some(includes) with emittedToolCallIds Set
- Replace O(n) toolCalls.find with finalizedIds Set (JSON + SSE paths)
- Add byte guard (0x7b check) before payload.toString on every frame
- Add escapeXml() to prevent tag injection in tool result blocks
- Reuse module-level TextDecoder in cursorProtobuf instead of per-call
- Replace [...Set].every() spread with for..of loop
2026-03-10 09:49:51 +01:00
nyatoru 6e1bf4652d feat(kimi-coding): update platform and version for Kimi Coding integration 2026-03-10 14:18:57 +07:00
nyatoru 3991c96c78 feat(kimi-coding): integrate Kimi Coding API for token refresh and usage tracking 2026-03-10 14:12:37 +07:00
Rafael Calleja 70008e67e4 refactor(cursor): remove debug artifacts after tool-result fix
Keep the Cursor tool-result reliability changes while cleaning temporary investigation notes, noisy logs, and unused imports to reduce runtime log spam.

Made-with: Cursor
2026-03-10 07:16:13 +01:00
Rafael Calleja 0d1e6685f6 chore(wip): snapshot working Cursor tool-result flow
Save the current functioning state that stops the protobuf wire-type crash and tool-call loop while we do a follow-up cleanup pass.

Made-with: Cursor
2026-03-10 07:13:47 +01:00
dependabot[bot] 60d1d13c6a deps: bump the development group with 5 updates
Bumps the development group with 5 updates:

| Package | From | To |
| --- | --- | --- |
| [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) | `25.3.3` | `25.4.0` |
| [eslint](https://github.com/eslint/eslint) | `9.39.3` | `9.39.4` |
| [lint-staged](https://github.com/lint-staged/lint-staged) | `16.3.1` | `16.3.2` |
| [typescript-eslint](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/typescript-eslint) | `8.56.1` | `8.57.0` |
| [vitest](https://github.com/vitest-dev/vitest/tree/HEAD/packages/vitest) | `3.2.4` | `4.0.18` |


Updates `@types/node` from 25.3.3 to 25.4.0
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node)

Updates `eslint` from 9.39.3 to 9.39.4
- [Release notes](https://github.com/eslint/eslint/releases)
- [Commits](https://github.com/eslint/eslint/compare/v9.39.3...v9.39.4)

Updates `lint-staged` from 16.3.1 to 16.3.2
- [Release notes](https://github.com/lint-staged/lint-staged/releases)
- [Changelog](https://github.com/lint-staged/lint-staged/blob/main/CHANGELOG.md)
- [Commits](https://github.com/lint-staged/lint-staged/compare/v16.3.1...v16.3.2)

Updates `typescript-eslint` from 8.56.1 to 8.57.0
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/typescript-eslint/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v8.57.0/packages/typescript-eslint)

Updates `vitest` from 3.2.4 to 4.0.18
- [Release notes](https://github.com/vitest-dev/vitest/releases)
- [Commits](https://github.com/vitest-dev/vitest/commits/v4.0.18/packages/vitest)

---
updated-dependencies:
- dependency-name: "@types/node"
  dependency-version: 25.4.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: development
- dependency-name: eslint
  dependency-version: 9.39.4
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: development
- dependency-name: lint-staged
  dependency-version: 16.3.2
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: development
- dependency-name: typescript-eslint
  dependency-version: 8.57.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: development
- dependency-name: vitest
  dependency-version: 4.0.18
  dependency-type: direct:development
  update-type: version-update:semver-major
  dependency-group: development
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-03-09 19:58:33 +00:00
dependabot[bot] ade1e5f345 deps: bump the production group with 2 updates
Bumps the production group with 2 updates: [jose](https://github.com/panva/jose) and [recharts](https://github.com/recharts/recharts).


Updates `jose` from 6.1.3 to 6.2.1
- [Release notes](https://github.com/panva/jose/releases)
- [Changelog](https://github.com/panva/jose/blob/main/CHANGELOG.md)
- [Commits](https://github.com/panva/jose/compare/v6.1.3...v6.2.1)

Updates `recharts` from 3.7.0 to 3.8.0
- [Release notes](https://github.com/recharts/recharts/releases)
- [Changelog](https://github.com/recharts/recharts/blob/main/CHANGELOG.md)
- [Commits](https://github.com/recharts/recharts/compare/v3.7.0...v3.8.0)

---
updated-dependencies:
- dependency-name: jose
  dependency-version: 6.2.1
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: production
- dependency-name: recharts
  dependency-version: 3.8.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: production
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-03-09 19:57:36 +00:00
diegosouzapw 0a59ef4996 feat(release): v2.1.2 — CI green: all 5 workflow fixes + .deb
Build Electron Desktop App / Validate version (push) Failing after 37s
Build Electron Desktop App / Build Electron (macos-arm64) (push) Has been skipped
Build Electron Desktop App / Build Electron (linux) (push) Has been skipped
Build Electron Desktop App / Build Electron (macos-intel) (push) Has been skipped
Build Electron Desktop App / Build Electron (windows) (push) Has been skipped
Build Electron Desktop App / Create Release (push) Has been skipped
## CI Fixes
- fix(lint): check:docs-sync — bump docs/openapi.yaml version to 2.1.2 + add [Unreleased] to CHANGELOG
- fix(ci): npm-publish.yml — use 'npm ci --ignore-scripts' to skip prepublishOnly during install, then run prepublish.mjs explicitly with JWT_SECRET; prevents double-build loop that caused all npm CI publishes to fail
- fix(ci): docker-publish.yml — replace two-job digest approach (required ubuntu-24.04-arm, unavailable on public repos) with single-job QEMU-based multi-arch build (linux/amd64 + linux/arm64 on standard ubuntu-latest)
- fix(ci): electron-release.yml — add .deb target to Linux electron-builder, collect .deb files in release-assets step, attach *.deb to GitHub release assets

## Documentation
- fix(docs): README.md language bar — fix 29 broken links (README.<lang>.md → docs/i18n/<lang>/README.md)
- fix(docs): docs/i18n/*/README.md — update back-links to ../../README.md and cross-links between languages
- fix(docs): electron/package.json — add deb target (x64+arm64) to linux build config
2026-03-09 15:53:14 -03:00
diegosouzapw ace3e47d22 feat(release): v2.1.1 — CI fix + docs reorganization
Build Electron Desktop App / Validate version (push) Failing after 38s
Build Electron Desktop App / Build Electron (macos-arm64) (push) Has been skipped
Build Electron Desktop App / Build Electron (linux) (push) Has been skipped
Build Electron Desktop App / Build Electron (macos-intel) (push) Has been skipped
Build Electron Desktop App / Build Electron (windows) (push) Has been skipped
Build Electron Desktop App / Create Release (push) Has been skipped
## Bug Fixes
- fix(lint): resolve 5 explicit 'any' violations in open-sse/services/usage.ts
  - quotas: Record<string,any> → Record<string,UsageQuota>
  - window: any → JsonRecord (hasUtilization + createQuotaObject)
  - (error as any) → (error as Error) in 2 catch blocks
  - valueRecord = toRecord(value) to safely pass unknown to JsonRecord fn

## Documentation
- docs: move 29 README.<lang>.md from root to docs/i18n/<lang>/README.md
  (root now contains only English README.md)
- docs(i18n): sync all 11 docs/*.md to 30 language folders (319 updates)
  Languages: ar bg 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

## Maintenance
- chore: delete all duplicate auto-generated draft GitHub releases (v2.0.17–v2.1.0)
2026-03-09 15:37:31 -03:00
diegosouzapw 9865401636 feat(release): v2.1.0 — Full Provider-UI Gap Audit
All backend providers now accessible from the dashboard UI:

- src/shared/constants/providers.ts: Add 7 missing APIKEY providers (ollama-cloud, elevenlabs, cartesia, playht, inworld, sdwebui, comfyui)
- src/shared/constants/cliTools.ts: Add opencode, kiro entries with guide steps
- src/app/(dashboard)/dashboard/media/MediaPageClient.tsx: Full rewrite with provider+model selectors for all 5 modalities + new Transcription tab with file upload
- src/app/(dashboard)/dashboard/playground/page.tsx: Add transcription, video, music, rerank endpoints
- src/app/(dashboard)/dashboard/agents/page.tsx: Expand cliCompatProviders to include kiro, cursor, kimi-coding, kilocode, cline
- src/app/{400-503}/layout.tsx: Minimal layouts to fix Next.js build
- CHANGELOG: v2.1.0 entry
2026-03-09 15:17:54 -03:00
diegosouzapw 1343768de1 feat(ui): full provider-UI gap fixes
## Providers page
- Add 7 missing APIKEY providers: ollama-cloud, elevenlabs, cartesia, playht, inworld, sdwebui, comfyui
- All audio TTS providers + local image providers now have key config screens

## Media page (major redesign)
- Add Transcription tab with file upload (multipart/form-data)
- Add Provider dropdown + Model dropdown to ALL 5 modalities (image, video, music, speech, transcription)
- Provider selection drives model list and voice presets dynamically
- Static PROVIDER_MODELS registry mirrors all backend audioRegistry/imageRegistry entries
- PROVIDER_VOICE_PRESETS now drives voice dropdown based on selected provider

## Playground
- Add 4 new endpoints: Audio Transcription (/v1/audio/transcriptions), Video (/v1/videos/generations), Music (/v1/music/generations), Rerank (/v1/rerank)

## CLI Tools
- Add opencode and kiro entries with guide-type setup instructions

## Agents
- Expand cliCompatProviders toggles: add kiro, cursor, kimi-coding, kilocode, cline
2026-03-09 15:12:51 -03:00
diegosouzapw 743cfcbb3c feat(release): v2.0.20 — TTS Expansion + Mobile UX + Friendly Names
- #248: Inworld, Cartesia, PlayHT TTS providers; provider-aware voice presets in /dashboard/media; Speech tab in media page; Speech endpoint in playground
- #260: getAccountDisplayName/getProviderDisplayName helpers; applied to usageStats and rate-limits
- #261: mobile sidebar h-dvh scroll fix; providers page flex-wrap action headers
- docs: CHANGELOG v2.0.20, README English + 25 translated READMEs updated
2026-03-09 13:46:06 -03:00
Diego Rodrigues de Sa e Souza 44ee62e391 feat(#248,#260): TTS provider support + friendly display names (#262)
* feat(#248,#260): TTS provider support + friendly display names

## #248 — Text to Speech endpoint expansion
- audioRegistry: add Inworld, Cartesia, PlayHT providers with correct auth/format tags
- audioSpeech handler: add handleInworldSpeech (base64 decode), handleCartesiaSpeech (X-API-Key + transcript), handlePlayHtSpeech (X-USER-ID)
- /dashboard/media: add Speech tab with voice selector, format selector, and inline <audio> player (Blob URL)
- /dashboard/playground: add Text to Speech option; detect audio/* Content-Type and render inline audio player

## #260 — Friendly provider/account display names
- src/lib/display/names.ts: new centralized helper module with getAccountDisplayName() and getProviderDisplayName()
- src/lib/usage/usageStats.ts: replace raw connectionId.slice(0,8) fallbacks with getAccountDisplayName()
- src/app/api/rate-limits/route.ts: replace raw connectionId.slice(0,8) fallback with getAccountDisplayName()

* feat(#248,#261): ElevenLabs voice presets + mobile UX fixes

## #248 — ElevenLabs/Cartesia/Deepgram/Inworld voice presets
- MediaPageClient: replace static SPEECH_VOICES with provider-aware PROVIDER_VOICE_PRESETS
  - ElevenLabs: 9 premade voices with name+type (Rachel, Domi, Bella, Antoni, Elli, Josh, Arnold, Adam, Sam)
  - Cartesia: 3 built-in voices (Barbershop Man, Friendly Reading Man, California Girl)
  - Deepgram: 5 Aura voices (Asteria, Luna, Stella, Zeus, Orion)
  - Inworld: 2 voices (Eva, Marcus)
  - default: OpenAI 6 standard voices (alloy, echo, fable, onyx, nova, shimmer)
- Voice dropdown updates automatically when model input prefix changes

## #261 — Mobile UX improvements
- DashboardLayout: add h-dvh to mobile sidebar wrapper for proper scroll containment
- Sidebar: add h-full to aside element so nav can scroll on short screens
- ProvidersPage: change all 4 section headers from flex justify-between to flex flex-wrap so actions wrap on narrow screens instead of overflowing

---------

Co-authored-by: diegosouzapw <diegosouzapw@users.noreply.github.com>
2026-03-09 13:43:48 -03:00
diegosouzapw 47445ebf5c feat(release): v2.0.19 — Ollama Cloud provider + security hardening
docs: update CHANGELOG, README (EN + 29 translations), and docs/i18n/ FEATURES.md
- Add Ollama Cloud (ollamacloud alias) bullet to all 30 README files
- Sync docs/i18n/*/FEATURES.md with Ollama Cloud mention
- Bump version to 2.0.19
2026-03-09 12:46:58 -03:00
Diego Rodrigues de Sa e Souza 6b0638da30 Merge pull request #259 from diegosouzapw/fix/issue-255-258-ollama-cloud-security
fix: Ollama Cloud provider + security hardening (#255 #258)
2026-03-09 12:43:03 -03:00
diegosouzapw 74a0585683 fix: add Ollama Cloud provider + security hardening (#255 #258)
feat(#255): add Ollama Cloud provider (api.ollama.com/v1)
- New registry entry 'ollama-cloud' (alias: ollamacloud)
- OpenAI-compatible, Bearer API key auth
- 7 pre-populated models: Gemma 3 27B, Llama 3.3 70B, Qwen3 72B,
  Devstral 24B, DeepSeek R2 671B, Phi 4 14B, Mistral Small 3.2 24B
- passthroughModels: true for dynamic model names

fix(#258): security hardening — all 9 findings addressed
- [CRITICAL] db-backups/export: add isAuthRequired + isAuthenticated guard
- [CRITICAL] db-backups/import: add isAuthRequired + isAuthenticated guard
- [HIGH] oauth/cursor/auto-import: add isAuthRequired + isAuthenticated guard
- [HIGH] oauth/kiro/auto-import: add isAuthRequired + isAuthenticated guard
- [LOW x4] oauth/[provider]/[action]: replace === with safeEqual()
  using crypto.timingSafeEqual() for CWE-208 (timing-oracle attacks)
  on email and workspaceId comparisons across all 3 handler branches
- [FALSE POSITIVE] Finding #1 (package.json 'reset-password' binary name)
  is not a hardcoded credential — no change needed

Tests: 590/594 pass (4 pre-existing failures in combo-circuit-breaker)
2026-03-09 12:42:17 -03:00
diegosouzapw 9aaebbcd2a feat(release): v2.0.18 — cursor decompression + codex token refresh + password setup fix 2026-03-09 10:50:16 -03:00
Diego Rodrigues de Sa e Souza 2348680a2b Merge pull request #257 from diegosouzapw/fix/issue-256-password-setup-bypass
fix: cursor decompression fallback + codex token refresh + password setup bypass (#250, #251, #256)
2026-03-09 10:48:04 -03:00
diegosouzapw 59a8b8db35 fix: cursor decompression fallback + codex token refresh + password setup bypass (#250, #251, #256)
fix(cursor): add zlib inflate/inflateRaw fallback for GZIP_ALT/GZIP_BOTH frames (#250)
- GZIP_ALT (0x02) and GZIP_BOTH (0x03) frames may use zlib deflate instead of gzip
- Now tries gunzipSync → inflateSync → inflateRawSync with verbose error logging

fix(codex): override refreshCredentials to enable automatic token refresh on 401 (#251)
- CodexExecutor was inheriting base class null return, blocking 401 recovery
- Now calls refreshCodexToken() from tokenRefresh.ts on 401 upstream response
- Handles rotating token errors and surfaces re-auth warning clearly

fix(auth): allow dashboard access when no password is set after onboarding skip (#256)
- isAuthRequired() was blocking /dashboard/settings when setupComplete=true but no password
- Removed setupComplete guard: if there's no password, auth cannot be required
- Configure Password button on login page now navigates correctly to security settings
2026-03-09 10:47:16 -03:00
diegosouzapw 2ba46a622b feat(release): v2.0.17 — Antigravity streaming fix + OpenCode integration + Electron CI
- fix(streaming): keep Gemini/Antigravity text block open across chunks (#253)
  Resolves Claude Code rendering each streaming delta on a separate line.
  The content_block is now kept open between chunks (openTextBlockIdx state)
  and only closed at finishReason or on block-type switch.

- feat(agents): Download opencode.json button (discussion #162)
  Dashboard › Agents shows a Download opencode.json button when opencode
  is detected. Fetches /v1/models and generates a ready-to-use config.

- fix(electron-ci): use macos-15-intel runner (replaces deprecated macos-13)
- fix(electron-ci): sync electron/package.json version before build
- fix(electron-ci): remove duplicate arm64 pattern from release assets
2026-03-09 08:49:13 -03:00
Diego Rodrigues de Sa e Souza 9013236718 Merge pull request #254 from diegosouzapw/fix/issue-253-antigravity-streaming
 Approved — fixes confirmed.

- Fix #253: Antigravity/Gemini streaming chunks now render as continuous text in Claude Code (content_block kept open across chunks)
- Bonus: Download opencode.json button in Agents dashboard
2026-03-09 08:47:41 -03:00
diegosouzapw eab96cc94b fix(streaming): keep Gemini/Antigravity text block open across chunks (#253)
Before this fix, geminiToClaudeResponse() called content_block_start +
content_block_stop on EVERY streaming chunk. Claude Code interprets each
content_block as a separate text element and renders them on separate
lines, making responses unreadable.

Fix: introduce state.openTextBlockIdx to track an open text block across
chunks. The block is opened on the first text chunk and only closed when:
- switching to a different block type (thinking, tool_use)
- the stream finishes (at finishReason)

All other block types (thinking, tool_use) are still opened+closed per
chunk as before since they are naturally atomic events.

Also: add 'Download opencode.json' button to the Agents dashboard.
The button appears when opencode is detected as installed and generates
a ready-to-use opencode.json config with the OmniRoute provider,
base URL and all models fetched from /v1/models.
2026-03-09 08:38:33 -03:00
diegosouzapw 7f66e82f16 fix(electron-ci): sync electron/package.json version + fix Create Release
- Add 'Sync version in electron/package.json' step before build so
  electron-builder names binaries with the correct release version
  (was generating OmniRoute-2.0.13.dmg for v2.0.16 release).
- Remove duplicate *-arm64.dmg pattern from release files (*.dmg
  already matches arm64 dmg files), which was causing 404 on
  overwrite-asset API call.
- Add fail_on_unmatched_files: false so missing .blockmap files
  don't fail the release step.
2026-03-08 18:45:51 -03:00
diegosouzapw c74054d928 fix(electron-ci): use macos-15-intel runner for Intel x64 macOS builds
GitHub retired all macos-13 variants. The new officially supported
Intel x64 runner is macos-15-intel (GA since April 2025, supported
until August 2027). This replaces the deprecated macos-13 runner.
2026-03-08 18:27:44 -03:00
diegosouzapw 5428c9b9a8 fix(electron-ci): replace deprecated macos-13 runner with macos-13-large
macos-13 runner was retired by GitHub Actions infrastructure.
All other platforms (linux, macos-arm64, windows) built successfully.
Using macos-13-large which maintains x64 Intel architecture.
2026-03-08 18:26:02 -03:00
diegosouzapw db0bda2810 feat(release): v2.0.16 — NanoBanana async polling + Electron CI fix + CI hardening
Build Electron Desktop App / Validate version (push) Failing after 26s
Build Electron Desktop App / Build Electron (macos-arm64) (push) Has been skipped
Build Electron Desktop App / Build Electron (linux) (push) Has been skipped
Build Electron Desktop App / Build Electron (macos-intel) (push) Has been skipped
Build Electron Desktop App / Build Electron (windows) (push) Has been skipped
Build Electron Desktop App / Create Release (push) Has been skipped
fix(electron-ci): add GH_TOKEN to Build Electron step
  - electron-builder requires GH_TOKEN env when publish.provider is
    'github'. Without it every build failed with 'GitHub Personal Access
    Token is not set'. This was blocking Electron binary generation since
    v2.0.11. Fixed by passing secrets.GITHUB_TOKEN to the build step.

fix(images): NanoBanana async task polling (PR #247 by @hijak)
  - NanoBanana returns taskId requiring /record-info polling until
    successFlag=1 instead of image payload on first response.
  - Backward compatible: sync payload path preserved.
  - Includes aspect ratio/resolution inference from size field.

fix(ci): security test import + route validation + deploy-vps
  - inputSanitizer.js → .ts fix
  - validateBody added to acp/agents POST (139 routes pass t06)
  - deploy-vps continue-on-error + command_timeout

Version: 2.0.15 → 2.0.16
2026-03-08 18:07:36 -03:00
Diego Rodrigues de Sa e Souza c4efad3ea7 Merge pull request #247 from hijak/fix/nanobanana-async
## Review

 **Aprovado** — implementação clara e bem estruturada.

**O que a PR faz:**
- Implementa o fluxo async correto da NanoBanana API: submit task → poll /record-info until successFlag=1
- Mantém backward compatibility para providers retornando payload síncrono
- Infere aspectRatio e resolution do campo size (padrão OpenAI)
- Permite tunagem via env vars (NANOBANANA_POLL_TIMEOUT_MS, NANOBANANA_POLL_INTERVAL_MS)
- Adiciona 2 arquivos de teste com cobertura específica

**Qualidade:**
- Código limpo e bem documentado
- Testes adicionados e passando localmente
- Não quebra implementações existentes (sync path preservado)

Obrigado pela contribuição @hijak! 🎉
2026-03-08 17:59:11 -03:00
diegosouzapw 62995b640d fix(ci): correct security test import, add validateBody to acp/agents, deploy-vps continue-on-error
fix(test): security-fase01.test.mjs imports inputSanitizer.js → .ts
  - The file is TypeScript-only (no compiled .js). Node was failing with
    ERR_MODULE_NOT_FOUND in CI because the import path pointed to a
    non-existent .js file.

fix(acp): add validateBody(jsonObjectSchema) to POST /api/acp/agents
  - Satisfies check:route-validation:t06 lint rule that requires all
    routes using request.json() to go through validateBody().
  - Uses jsonObjectSchema (passthrough) since body shape varies between
    the 'refresh' action and the custom agent creation payload.
  - Manual field validation below remains unchanged.
  - All 139 routes now pass the route-validation lint check.

fix(deploy-vps): add continue-on-error on SSH step + command_timeout
  - SSH connection failures (host unreachable / secrets not set) no
    longer mark the workflow run as failed.
  - The DEPLOY_ENABLED guard still prevents the job from running when
    the variable is not set to 'true'.
2026-03-08 17:58:42 -03:00
jack 9a476d310a fix(images): support async NanoBanana task polling 2026-03-08 20:47:17 +00:00
diegosouzapw bc09eb64a6 chore: bump version to 2.0.15 + update CHANGELOG
Build Electron Desktop App / Validate version (push) Failing after 30s
Build Electron Desktop App / Build Electron (macos-arm64) (push) Has been skipped
Build Electron Desktop App / Build Electron (linux) (push) Has been skipped
Build Electron Desktop App / Build Electron (macos-intel) (push) Has been skipped
Build Electron Desktop App / Build Electron (windows) (push) Has been skipped
Build Electron Desktop App / Create Release (push) Has been skipped
- Add v2.0.15 CHANGELOG entry (features 07/09/04/06 + fix #244)
- Version: 2.0.14 → 2.0.15
2026-03-08 17:40:00 -03:00
Diego Rodrigues de Sa e Souza 8e4873d53e Merge pull request #246 from diegosouzapw/feat/features-07-09-04-06-electron-release
feat: features 07/09/04/06 — Codex effort clamp, OpenRouter catalog cache, quota preflight & session monitor
2026-03-08 17:38:06 -03:00
Diego Rodrigues de Sa e Souza 5874bd3de6 Merge pull request #245 from diegosouzapw/fix/issue-244-optional-field-gemini-schema
fix(gemini): remove "optional" field from JSON schema — fixes #244
2026-03-08 17:38:05 -03:00
diegosouzapw a1dc2270a2 fix(gemini): remove "optional" field from schema to fix Gemini API rejection (#244)
The Gemini API rejects JSON schemas containing the "optional" field, returning
"400: Cannot find field: optional". Added "optional" to UNSUPPORTED_SCHEMA_CONSTRAINTS
in geminiHelper.ts so it is recursively stripped before sending to upstream.

Also: update star history section in README — embed replaced with live link
since api.star-history.com was suspended by GitHub in March 2025.

Closes #244
2026-03-08 17:36:58 -03:00
diegosouzapw 1c2f553a7c feat: features 07/09/04/06 — codex clamp, openrouter cache, quota preflight & monitor
feat(codex): clamp reasoning effort per model (feature-07)
- Add MAX_EFFORT_BY_MODEL table in CodexExecutor
- Add clampEffort() applied after effort derivation
- Logs debug when clamp is applied

feat(catalog): OpenRouter catalog with persistent cache (feature-09)
- New src/lib/catalog/openrouterCatalog.ts with TTL 24h + stale-if-error
- New GET /api/models/openrouter-catalog endpoint (authenticated)
- Reduces redundant OpenRouter API calls from dashboard

feat(quota): quota preflight with per-provider toggle (feature-04)
- New open-sse/services/quotaPreflight.ts
- Toggle: providerSpecificData.quotaPreflightEnabled (default: false)
- Extensible via registerQuotaFetcher() pattern
- Graceful degradation when no fetcher registered

feat(quota): quota session monitor with per-provider toggle (feature-06)
- New open-sse/services/quotaMonitor.ts
- Toggle: providerSpecificData.quotaMonitorEnabled (default: false)
- Adaptive polling: 60s normal / 15s critical
- Alert deduplication (5min suppression window)
- timer.unref() ensures clean process exit

feat(providers): support providerSpecificData patch in PUT /api/providers/[id]
- Partial merge of providerSpecificData (preserves existing keys)
- Schema updated to accept providerSpecificData in updateProviderConnectionSchema
2026-03-08 17:36:17 -03:00
diegosouzapw 049ddff6fe feat(release): v2.0.14 — fix model name stripping, multimodal image_url, electron release workflow
Build Electron Desktop App / Validate version (push) Failing after 30s
Build Electron Desktop App / Build Electron (macos-arm64) (push) Has been skipped
Build Electron Desktop App / Build Electron (linux) (push) Has been skipped
Build Electron Desktop App / Build Electron (macos-intel) (push) Has been skipped
Build Electron Desktop App / Build Electron (windows) (push) Has been skipped
Build Electron Desktop App / Create Release (push) Has been skipped
- Fix #243: model.split('/').pop() → slice(1).join('/') preserves vendor namespaces
- Fix #242: image_url → input_image conversion for Responses API backends
- Merge PR #241: electron release workflow (mac x64/arm64 separation, version sync)
- CHANGELOG updated
2026-03-08 02:19:36 -03:00
diegosouzapw 9429d1639e Merge PR #241: fix(electron): resolve release build workflow errors
- Sync electron package.json version with root (2.0.13)
- Separate mac x64 and arm64 into dedicated runner jobs
- Use macos-13 (Intel) runner for x64 build
- Thanks @benzntech for the contribution!
2026-03-08 02:17:46 -03:00
diegosouzapw af7ca4baf7 fix: strip only internal prefix from model name for compatible providers (#243)
- Changed model.split('/').pop() to model.split('/').slice(1).join('/')
- Preserves vendor namespace in model names (e.g. moonshotai/Kimi-K2-Instruct)
- Also fixes multimodal image_url → input_image conversion for Responses API (#242)
- image_url parts from Chat Completions are now properly converted to input_image format
2026-03-08 02:17:21 -03:00
benzntech 7906fdfc1d fix(electron): resolve release build workflow errors
- Sync electron package.json version with root to fix artifact collection

- Separate mac x64 and arm64 targets into dedicated runner jobs

- Use macos-13 (Intel) runner for x64 build to prevent cross-compilation timeouts
2026-03-07 23:46:59 +05:30
diegosouzapw 9911272898 chore: rename docs to uppercase + gitignore cleanup
- Rename a2a-server.md → A2A-SERVER.md, auto-combo.md → AUTO-COMBO.md, mcp-server.md → MCP-SERVER.md
- Update gitignore whitelist to match uppercase names
- Reddit Launch Plan v2 remains gitignored (local only)
2026-03-07 13:18:34 -03:00
diegosouzapw 8909ae041e chore: update llm.txt to v2.0.13 state
- Complete rewrite of llm.txt with current project structure
- Added ACP agents, CLI fingerprint, sidebar reorganization
- Added 30 languages, MCP/A2A servers, anti-ban features
- Updated project structure tree with all dashboard pages
2026-03-07 12:36:24 -03:00
diegosouzapw c9a15772b0 chore: remove docs/new-features from tracking + gitignore cleanup
- Remove docs/new-features/ from git index (224 leaked feature spec files)
- Remove docs/new-features/ from gitignore whitelist
- Add .omnivscodeagent/, omnirouteCloud/, omnirouteSite/ to gitignore
- Remove duplicate omnirouteCloud/omnirouteSite entries
2026-03-07 12:33:56 -03:00
diegosouzapw 91f3bd4056 docs: comprehensive docs review + i18n sync
Build Electron Desktop App / Validate version (push) Failing after 40s
Build Electron Desktop App / Build Electron (macos-arm64) (push) Has been skipped
Build Electron Desktop App / Build Electron (linux) (push) Has been skipped
Build Electron Desktop App / Build Electron (macos-intel) (push) Has been skipped
Build Electron Desktop App / Build Electron (windows) (push) Has been skipped
Build Electron Desktop App / Create Release (push) Has been skipped
- Fix .gitignore: add a2a-server.md, auto-combo.md, mcp-server.md, new-features/ to whitelist
- Rewrite FEATURES.md: 18 sections covering v2.0.12 state (Playground, Themes, CLI Agents, Media, API Keys, Audit Log)
- API_REFERENCE.md: add ACP Agents endpoints (/api/acp/agents GET/POST/DELETE)
- Sync all 6 root docs to 29 i18n directories (174 files)
- Remove stale git-tracked docs (adr/, i18n-tasks/)
2026-03-07 12:18:17 -03:00
diegosouzapw 2306081dab feat: sidebar reorganization + CLI fingerprint to Agents page
Build Electron Desktop App / Validate version (push) Failing after 32s
Build Electron Desktop App / Build Electron (macos-arm64) (push) Has been skipped
Build Electron Desktop App / Build Electron (linux) (push) Has been skipped
Build Electron Desktop App / Build Electron (macos-intel) (push) Has been skipped
Build Electron Desktop App / Build Electron (windows) (push) Has been skipped
Build Electron Desktop App / Create Release (push) Has been skipped
- New CLI sidebar section: Tools + Agents
- Move Media to Debug section
- Move Health + Logs to System section
- Move CLI Fingerprint card from Settings > Security to Agents page
- Add cliToolsShort i18n key to all 30 languages
2026-03-07 11:55:18 -03:00
diegosouzapw 8963c62adb feat(release): v2.0.11 — ACP Agents Dashboard + Anti-Ban Docs
Build Electron Desktop App / Validate version (push) Failing after 28s
Build Electron Desktop App / Build Electron (macos-arm64) (push) Has been skipped
Build Electron Desktop App / Build Electron (linux) (push) Has been skipped
Build Electron Desktop App / Build Electron (macos-intel) (push) Has been skipped
Build Electron Desktop App / Build Electron (windows) (push) Has been skipped
Build Electron Desktop App / Create Release (push) Has been skipped
- ACP Agents Dashboard: Debug > Agents page with 14 built-in CLI agents
- Custom agent support: register any CLI via dashboard form
- Fix themeCoral i18n in all 30 languages
- Improved anti-ban feature descriptions in README
- Sync all 29 translated READMEs with new features
- CHANGELOG entry for v2.0.11
2026-03-07 11:22:16 -03:00
diegosouzapw e4a11bd6d0 feat: ACP Agents dashboard + themeCoral i18n fix
- Add Dashboard > Debug > Agents page: grid of 14 built-in CLI agents
  with installation status, version detection, protocol badges
- Add custom agent support: users can register any CLI tool via form
- Expand registry from 5 to 14 built-in agents (aider, opencode, cline,
  qwen-code, forge, amazon-q, interpreter, cursor-cli, warp)
- Add 60-second detection cache to avoid repeated execSync calls
- API: GET lists all agents, POST adds custom/refreshes, DELETE removes
- Settings schema: add customAgents array field
- Fix missing themeCoral in settings namespace for all 30 languages
- Add agents sidebar key in all 30 languages
- Add agents page i18n namespace (en + pt-BR)
2026-03-07 11:19:12 -03:00
diegosouzapw 2f6e63771f docs: sync v2.0.9+ features across all 30 READMEs
Added new features table (Playground, CLI Fingerprints, ACP, Custom
apiFormat routing, Codex workspace isolation, Electron auto-update)
to all 29 translated READMEs + English source.
2026-03-07 11:05:40 -03:00
diegosouzapw cbd60c853e feat(release): v2.0.10 — CLI fingerprint UI toggle
Build Electron Desktop App / Validate version (push) Failing after 27s
Build Electron Desktop App / Build Electron (macos-arm64) (push) Has been skipped
Build Electron Desktop App / Build Electron (linux) (push) Has been skipped
Build Electron Desktop App / Build Electron (macos-intel) (push) Has been skipped
Build Electron Desktop App / Build Electron (windows) (push) Has been skipped
Build Electron Desktop App / Create Release (push) Has been skipped
2026-03-07 10:57:16 -03:00
diegosouzapw 2d8091340f feat: CLI fingerprint UI toggle + fix playground i18n (#223)
- Add CLI Fingerprint Matching card in Settings > Security tab
  - Per-provider toggle chips (codex, claude, github, antigravity)
  - Emerald-themed UI with fingerprint icon and active count
  - Settings synced to runtime cache via API
- Fix playground i18n missing from 29 non-English sidebar translations
- Add cliCompatProviders to settings schema (Zod validation)
- Add setCliCompatProviders/getCliCompatProviders to cliFingerprints.ts
- Add i18n keys for CLI fingerprint settings (en + pt-BR)
2026-03-07 10:56:58 -03:00
diegosouzapw 2025c16c82 fix: deploy workflow uses node app/server.js for pm2 2026-03-07 10:40:00 -03:00
diegosouzapw 811fb7f9b2 docs: fix deploy workflow to use npm-only approach
Old workflow used git clone at /opt/omniroute-app but recent releases
used npm install -g, causing version mismatch. PM2 now runs from
/usr/lib/node_modules/omniroute directly. Removed all references to
the stale local directory.
2026-03-07 10:38:49 -03:00
diegosouzapw a2bd32e76c feat(release): v2.0.9 — playground, CLI fingerprints, ACP
Build Electron Desktop App / Validate version (push) Failing after 27s
Build Electron Desktop App / Build Electron (macos-arm64) (push) Has been skipped
Build Electron Desktop App / Build Electron (linux) (push) Has been skipped
Build Electron Desktop App / Build Electron (macos-intel) (push) Has been skipped
Build Electron Desktop App / Build Electron (windows) (push) Has been skipped
Build Electron Desktop App / Create Release (push) Has been skipped
2026-03-07 10:26:34 -03:00
Diego Rodrigues de Sa e Souza 89c07f4e8a Merge pull request #240 from diegosouzapw/feat/all-features-234-223-235
feat: playground, CLI fingerprints, ACP support (#234, #223, #235)
2026-03-07 10:25:28 -03:00
diegosouzapw ac89069671 feat: playground, CLI fingerprints, ACP support (#234, #223, #235)
- Add model playground page to dashboard (provider/model/endpoint selectors, Monaco editor, streaming, abort)
- Add CLI fingerprint matching (per-provider header/body ordering to match native CLI binaries)
- Add ACP module (CLI agent discovery, process spawner, session manager, API endpoint)
- Add playground to sidebar debug section with i18n support
- Close #192 and #200 as stale (v1.8.1, no repro info)
2026-03-07 10:24:43 -03:00
diegosouzapw 7cb420d8e6 feat(release): v2.0.8 — custom image model handler resolution
Build Electron Desktop App / Validate version (push) Failing after 26s
Build Electron Desktop App / Build Electron (macos-arm64) (push) Has been skipped
Build Electron Desktop App / Build Electron (linux) (push) Has been skipped
Build Electron Desktop App / Build Electron (macos-intel) (push) Has been skipped
Build Electron Desktop App / Build Electron (windows) (push) Has been skipped
Build Electron Desktop App / Create Release (push) Has been skipped
2026-03-07 10:05:20 -03:00
Diego Rodrigues de Sa e Souza d3919d441f Merge pull request #239 from diegosouzapw/fix/issue-238-image-handler
fix: pass resolved provider to image handler for custom models (#238)
2026-03-07 10:04:24 -03:00
diegosouzapw 4b5824babc fix: pass resolved provider to image handler for custom models (#238) 2026-03-07 10:03:48 -03:00
997 changed files with 153874 additions and 39174 deletions
+39
View File
@@ -0,0 +1,39 @@
---
description: Deploy the latest OmniRoute code to the Akamai VPS (69.164.221.35)
---
# Deploy to Akamai VPS Workflow
Deploy OmniRoute to the Akamai VPS using `npm pack + scp` + PM2.
**Akamai VPS:** `69.164.221.35`
**Process manager:** PM2 (`omniroute`)
**Port:** `20128`
## Steps
### 1. Build + pack locally
// turbo
```bash
cd /home/diegosouzapw/dev/proxys/9router && npm run build:cli && npm pack --ignore-scripts
```
### 2. Copy to Akamai VPS and install
// turbo-all
```bash
scp omniroute-*.tgz root@69.164.221.35:/tmp/
```
```bash
ssh root@69.164.221.35 "npm install -g /tmp/omniroute-*.tgz --ignore-scripts && cd /usr/lib/node_modules/omniroute/app && npm rebuild better-sqlite3 && pm2 delete omniroute 2>/dev/null; pm2 start /root/.omniroute/ecosystem.config.cjs --update-env && pm2 save && echo '✅ Akamai done'"
```
### 3. Verify the deployment
```bash
curl -s -o /dev/null -w 'AKAMAI HTTP %{http_code}\n' http://69.164.221.35:20128/
```
+49
View File
@@ -0,0 +1,49 @@
---
description: Deploy the latest OmniRoute code to BOTH the Akamai VPS and the Local VPS
---
# Deploy to VPS (Both) Workflow
Deploy OmniRoute to the production VPSs using `npm pack + scp` + PM2.
**Akamai VPS:** `69.164.221.35`
**Local VPS:** `192.168.0.15`
**Process manager:** PM2 (`omniroute`)
**Port:** `20128`
**PM2 entry:** `/usr/lib/node_modules/omniroute/app/server.js`
> [!IMPORTANT]
> The npm registry rejects packages > 100MB, so deployment uses **npm pack + scp**.
## Steps
### 1. Build + pack locally
// turbo
```bash
cd /home/diegosouzapw/dev/proxys/9router && npm run build:cli && npm pack --ignore-scripts
```
### 2. Copy to both VPS and install
// turbo-all
```bash
scp omniroute-*.tgz root@69.164.221.35:/tmp/ && scp omniroute-*.tgz root@192.168.0.15:/tmp/
```
```bash
ssh root@69.164.221.35 "npm install -g /tmp/omniroute-*.tgz --ignore-scripts && cd /usr/lib/node_modules/omniroute/app && npm rebuild better-sqlite3 && pm2 delete omniroute 2>/dev/null; pm2 start /root/.omniroute/ecosystem.config.cjs --update-env && pm2 save && echo '✅ Akamai done'"
```
```bash
ssh root@192.168.0.15 "npm install -g /tmp/omniroute-*.tgz --ignore-scripts && cd /usr/lib/node_modules/omniroute/app && npm rebuild better-sqlite3 && pm2 delete omniroute 2>/dev/null; pm2 start /root/.omniroute/ecosystem.config.cjs --update-env && pm2 save && echo '✅ Local done'"
```
### 3. Verify the deployment
```bash
curl -s -o /dev/null -w 'AKAMAI HTTP %{http_code}\n' http://69.164.221.35:20128/
curl -s -o /dev/null -w 'LOCAL HTTP %{http_code}\n' http://192.168.0.15:20128/
```
+39
View File
@@ -0,0 +1,39 @@
---
description: Deploy the latest OmniRoute code to the Local VPS (192.168.0.15)
---
# Deploy to Local VPS Workflow
Deploy OmniRoute to the Local VPS using `npm pack + scp` + PM2.
**Local VPS:** `192.168.0.15`
**Process manager:** PM2 (`omniroute`)
**Port:** `20128`
## Steps
### 1. Build + pack locally
// turbo
```bash
cd /home/diegosouzapw/dev/proxys/9router && npm run build:cli && npm pack --ignore-scripts
```
### 2. Copy to Local VPS and install
// turbo-all
```bash
scp omniroute-*.tgz root@192.168.0.15:/tmp/
```
```bash
ssh root@192.168.0.15 "npm install -g /tmp/omniroute-*.tgz --ignore-scripts && cd /usr/lib/node_modules/omniroute/app && npm rebuild better-sqlite3 && pm2 delete omniroute 2>/dev/null; pm2 start /root/.omniroute/ecosystem.config.cjs --update-env && pm2 save && echo '✅ Local done'"
```
### 3. Verify the deployment
```bash
curl -s -o /dev/null -w 'LOCAL HTTP %{http_code}\n' http://192.168.0.15:20128/
```
-55
View File
@@ -1,55 +0,0 @@
---
description: Deploy the latest OmniRoute code to the Akamai VPS (69.164.221.35) via npm
---
# Deploy to VPS Workflow
Deploy OmniRoute to the production VPS using Node.js + PM2 (no Docker).
**VPS:** `69.164.221.35` (Akamai, Ubuntu 24.04, 1GB RAM + 2.5GB swap)
**App path:** `/opt/omniroute-app`
**Process manager:** PM2 (`omniroute`)
**Port:** `20128`
## Steps
### 1. Push to GitHub
Ensure all changes are committed and pushed:
```bash
git push origin main
```
### 2. SSH into VPS, pull latest code, rebuild, and restart
// turbo-all
```bash
ssh root@69.164.221.35 "
cd /opt/omniroute-app &&
git fetch origin &&
git reset --hard origin/main &&
export NODE_OPTIONS='--max-old-space-size=1536' &&
npm install --no-audit --no-fund &&
npm run build &&
pm2 restart omniroute &&
pm2 save &&
echo '✅ Deploy complete!'
"
```
### 3. Verify the deployment
```bash
ssh root@69.164.221.35 "pm2 list && curl -s -o /dev/null -w 'HTTP %{http_code}' http://localhost:20128/"
```
Expected: PM2 shows `online`, HTTP returns `307` (redirect to login).
## Notes
- The VPS has only 1GB RAM. `NODE_OPTIONS='--max-old-space-size=1536'` uses swap for the build.
- PM2 is configured with `pm2 startup` to auto-restart on reboot.
- The `.env` file is at `/opt/omniroute-app/.env` (copied from the old Docker setup at `/opt/omniroute/.env`).
- Nginx proxies `omniroute.online``localhost:20128`.
+206 -28
View File
@@ -4,75 +4,253 @@ description: Create a new release, bump version up to 1.x.10 threshold, update c
# Generate Release Workflow
Bump version, finalize CHANGELOG, commit, tag, push, publish to npm, and create GitHub release.
Bump version, finalize CHANGELOG, commit, open a **PR to main** and wait for user confirmation before tagging, publishing, and deploying.
## Steps
> **VERSION RULE: Always use PATCH bumps (2.x.y → 2.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 `2.(x+1).0` — e.g. `2.1.10` → `2.2.0`.
### 1. Determine new version
---
Check current version in `package.json` and increment the patch number:
## ⚠️ Two-Phase Flow
```
Phase 1 (automated): bump → docs → i18n → commit → push → open PR
↕ 🛑 STOP: Notify user, wait for PR confirmation
Phase 2 (post-merge): tag → publish → GitHub release → Docker → deploy
```
**NEVER push directly to main or create tags before the user confirms the PR.**
---
## Phase 1: Pre-Merge
### 1. Create release branch
```bash
git checkout -b release/v2.x.y
```
### 2. Determine new version
Check current version in `package.json` and increment the **patch** number only:
```bash
grep '"version"' package.json
```
Version format: `1.x.y`increment `y` for patch, `x` for minor (threshold: y=10 triggers x+1).
Version format: `2.x.y`examples:
### 2. Finalize CHANGELOG.md
- `2.1.2``2.1.3` (patch)
- `2.1.9``2.1.10` (patch)
- `2.1.10``2.2.0` (minor threshold — do manually with `sed`)
Replace `[Unreleased]` header with the new version and date:
> **⚠️ ATOMIC COMMIT RULE — Version bump MUST happen before committing feature files.**
>
> **CORRECT order:**
>
> 1. `npm version patch --no-git-tag-version` ← bump first
> 2. implement features / fix bugs
> 3. `git add -A && git commit -m "chore(release): v2.x.y — all changes in ONE commit"`
>
> **OR if features are already staged:**
>
> 1. implement features (do NOT commit yet)
> 2. `npm version patch --no-git-tag-version` ← bump before committing
> 3. `git add -A && git commit -m "chore(release): v2.x.y — all changes in ONE commit"`
>
> **NEVER do this (creates version mismatch in git history):**
>
> - ~~commit features → then bump version → commit package.json separately~~
>
> This ensures that `git show v2.x.y` always contains both code changes and the version bump together.
> The GitHub release tag will point to a commit that includes ALL changes for that version.
```markdown
## [1.x.y] — YYYY-MM-DD
```
### 3. Regenerate lock file (REQUIRED after version bump)
### 3. Bump version in package.json
**Mandatory** — skipping causes `@swc/helpers` lock mismatch and CI failures:
```bash
sed -i 's/"version": "OLD"/"version": "NEW"/' package.json
npm install
```
### 4. Stage, commit, and tag
### 4. Finalize CHANGELOG.md
Replace `[Unreleased]` header with the new version and date.
Keep an empty `## [Unreleased]` section above it.
```markdown
## [Unreleased]
---
## [2.x.y] — YYYY-MM-DD
```
### 5. Update openapi.yaml version ⚠️ MANDATORY
> **CI will fail** if `docs/openapi.yaml` version ≠ `package.json` version (`check:docs-sync` enforces this).
// turbo
```bash
VERSION=$(node -p "require('./package.json').version") && sed -i "s/ version: .*/ version: $VERSION/" docs/openapi.yaml && echo "✓ openapi.yaml → $VERSION"
```
### 6. Update README.md and i18n docs
Run `/update-docs` workflow steps to:
- Update feature table rows in `README.md`
- Sync changes to all 29 language `docs/i18n/*/README.md` files
- Update `docs/FEATURES.md` if Settings section changed
### 7. Run tests
// turbo
```bash
npm test
```
All tests must pass before creating the PR.
### 8. Stage, commit, and push
// turbo-all
```bash
git add -A
git commit -m "feat(release): vX.Y.Z — summary of changes"
git tag -a vX.Y.Z -m "Release vX.Y.Z — summary"
git commit -m "chore(release): v2.x.y — summary of changes"
git push origin release/v2.x.y
```
### 5. Push to GitHub
### 9. Open PR to main
```bash
git push origin main
git push origin vX.Y.Z
gh pr create \
--repo diegosouzapw/OmniRoute \
--base main \
--head release/v2.x.y \
--title "chore(release): v2.x.y — summary" \
--body "## 🚀 Release v2.x.y
### Changes
...
### Tests
- X/X tests pass
### ⚠️ After merging: run Phase 2 steps to tag, publish, and deploy."
```
### 6. Publish to npm
### 10. 🛑 STOP — Notify User & Await PR Confirmation
**This is a mandatory stop point.** Use `notify_user` with `BlockedOnUser: true`:
Inform the user:
- PR URL
- Summary of changes
- Test results
- List of files changed
**DO NOT proceed to Phase 2 until the user confirms the PR looks good and merges it.**
---
## Phase 2: Post-Merge (only after user confirms)
> Run these steps only AFTER the user has merged the PR.
### 11. Pull main and create tag
```bash
npm publish
git checkout main
git pull origin main
git tag -a v2.x.y -m "Release v2.x.y"
```
Wait for completion (prepublishOnly runs `npm run build:cli` automatically).
### 7. Create GitHub release
### 12. Push tag to GitHub
```bash
gh release create vX.Y.Z --title "Release vX.Y.Z" --notes-file /tmp/release_notes.md
git push origin --tags
```
### 8. Deploy to VPS (if requested)
See `/deploy-vps` workflow for Akamai VPS or use npm for local VPS:
### 13. Create GitHub release
```bash
ssh root@<VPS_IP> "npm install -g omniroute@X.Y.Z && pm2 restart omniroute"
gh release create v2.x.y --title "v2.x.y — summary" --notes "..."
```
### 14. 🐳 Trigger Docker Hub build (MANDATORY — keep npm and Docker in sync)
> **CRITICAL**: Docker Hub and npm MUST always publish the same version.
> The Docker image is built automatically via GitHub Actions when a new tag is pushed.
> After pushing the tag in step 11-12, **verify the workflow runs**:
```bash
# Verify the Docker workflow triggered
gh run list --repo diegosouzapw/OmniRoute --workflow docker-publish.yml --limit 3
# Wait for the Docker build to complete (usually 510 min)
gh run watch --repo diegosouzapw/OmniRoute
# After completion, verify on Docker Hub:
# https://hub.docker.com/r/diegosouzapw/omniroute/tags
```
If the Docker build was not triggered automatically, trigger it manually:
```bash
gh workflow run docker-publish.yml --repo diegosouzapw/OmniRoute --ref v2.x.y
```
### 15. Deploy to BOTH VPS environments (MANDATORY)
> Always deploy to **both** environments after every release.
> See `/deploy-vps` workflow for detailed steps.
```bash
# Build and pack locally
cd /home/diegosouzapw/dev/proxys/9router && npm run build:cli && npm pack --ignore-scripts
# Deploy to LOCAL VPS (192.168.0.15)
scp omniroute-*.tgz root@192.168.0.15:/tmp/
ssh root@192.168.0.15 "npm install -g /tmp/omniroute-*.tgz --ignore-scripts && pm2 restart omniroute && pm2 save"
# Deploy to AKAMAI VPS (69.164.221.35)
scp omniroute-*.tgz root@69.164.221.35:/tmp/
ssh root@69.164.221.35 "npm install -g /tmp/omniroute-*.tgz --ignore-scripts && pm2 restart omniroute && pm2 save"
# Verify both
curl -s -o /dev/null -w "LOCAL: HTTP %{http_code}\n" http://192.168.0.15:20128/
curl -s -o /dev/null -w "AKAMAI: HTTP %{http_code}\n" http://69.164.221.35:20128/
```
### 16. Clean up release branch
```bash
git branch -d release/v2.x.y
```
---
## Notes
- Always run `/update-docs` BEFORE this workflow (ensures CHANGELOG and README are current)
- The `prepublishOnly` script runs `npm run build:cli` automatically during `npm publish`
- After npm publish, verify with `npm info omniroute version`
- Lock file sync errors are caused by skipping `npm install` after version bump
- Use `gh auth switch -u diegosouzapw` if git push fails with wrong account
## Known CI Pitfalls
| CI failure | Cause | Fix |
| ------------------------------------------------------------------------- | -------------------------------------------------------- | ---------------------------------------------------------------------- |
| `[docs-sync] FAIL - OpenAPI version differs from package.json` | Skipped step 5 — `docs/openapi.yaml` version not updated | Run step 5 (`sed -i ...`) and commit |
| `[docs-sync] FAIL - CHANGELOG.md first section must be "## [Unreleased]"` | `## [Unreleased]` missing or not at top of CHANGELOG | Add `## [Unreleased]\n\n---\n` before the first versioned `## [x.y.z]` |
| Electron Linux `.deb` build fails (`FpmTarget` error) | `fpm` Ruby gem not installed on `ubuntu-latest` runner | Already fixed in `electron-release.yml` (`gem install fpm` step) |
| Docker Hub `502 error writing layer blob` | Transient Docker Hub network error during ARM64 push | Re-run the Docker publish workflow; no code change needed |
+2 -2
View File
@@ -21,8 +21,8 @@ This workflow fetches all open issues from the project's GitHub repository, clas
// turbo
- Run: `gh issue list --repo <owner>/<repo> --state open --limit 100 --json number,title,labels,body,comments,createdAt,author`
- Parse the JSON output to get a list of all open issues
- Run: `gh issue list --repo <owner>/<repo> --state open --limit 500 --json number,title,labels,body,comments,createdAt,author`
- Parse the JSON output to get a list of **all** open issues
- Sort by oldest first (FIFO)
### 3. Classify Each Issue
+118
View File
@@ -0,0 +1,118 @@
---
description: Read all open GitHub Discussions, summarize them, respond to pending ones, and create issues from actionable feature requests
---
# /review-discussions — GitHub Discussions Review & Response Workflow
## Overview
This workflow reads all open GitHub Discussions, generates a categorized summary, identifies which ones need a response, drafts and posts replies, and optionally creates issues from actionable feature requests. It follows the same flow used for Issues but adapted for the Discussions forum.
// turbo-all
## Steps
### 1. Identify the GitHub Repository
- Run: `git -C <project_root> remote get-url origin` to extract the owner/repo
- Parse the owner and repo name from the URL
### 2. Fetch All Open Discussions
- Use `read_url_content` to fetch `https://github.com/<owner>/<repo>/discussions`
- Parse the discussion list to get all discussion titles, IDs, authors, categories, and dates
- For each discussion, fetch the individual page to read the full content and all comments/replies
### 3. Summarize All Discussions
For each discussion, extract:
- **Title** and **#Number**
- **Author** (GitHub username)
- **Category** (Announcements, General, Ideas, Q&A, Show and tell)
- **Date** created
- **Summary** of the original post (1-2 sentences)
- **Comments count** and key participants
- **Your previous response** (if any)
- **Pending action** — whether a response or follow-up is needed
### 4. Present Summary Report to User
Present the full summary to the user organized by category, using a table:
| # | Category | Title | Author | Date | Status |
| --- | -------- | ----- | ------ | ------ | ----------------- |
| #N | Ideas | Title | @user | Mar 23 | ⚠️ Needs response |
| #N | Q&A | Title | @user | Mar 9 | ✅ Answered |
| #N | General | Title | @user | Mar 19 | ⚠️ Needs response |
Highlight:
- **⚠️ Needs response** — No reply from maintainer, or a follow-up comment was left unanswered
- **✅ Answered** — Maintainer already responded
- **🐛 Bug reported** — A bug was mentioned that needs tracking
- **💡 Actionable** — Contains a concrete feature request that could become an issue
### 5. Draft & Post Responses
For each discussion that needs a response, draft a reply following these guidelines:
#### Response Style
- **Friendly and professional** — Start with "Hey @username!"
- **Acknowledge the contribution** — Thank the user for their input
- **Be specific** — Reference existing features, settings, or dashboard pages if the feature already exists
- **Provide workarounds** — If the request isn't implemented yet, suggest current alternatives
- **Commit to action** — If the request is valid, state that you'll open an issue or add it to the roadmap
- **Keep it concise** — 3-5 paragraphs max
#### Posting via Browser
- Use `browser_subagent` to navigate to each discussion and post the comment
- **IMPORTANT**: When typing text in GitHub comment boxes via the browser, use only plain ASCII characters:
- Use regular hyphens `-` instead of em-dashes
- Use `->` instead of arrow symbols
- Do NOT use emoji Unicode characters (the browser keyboard may fail on them)
- Use `**bold**` and `\`code\`` markdown formatting
- Click the green "Comment" button (or "Reply" for threaded replies) after typing
- Verify the comment was posted by checking the page shows the new comment
### 6. Create Issues from Actionable Feature Requests
For discussions that contain concrete, actionable feature requests:
1. Ask the user which ones should become issues
2. For each approved request, create a GitHub issue via `browser_subagent`:
- Navigate to `https://github.com/<owner>/<repo>/issues/new`
- **Title**: `<Feature Name> - <Short description>`
- **Body** should include:
- `## Feature Request` header
- `**Source:** Discussion #N by @author`
- `## Problem` — What limitation the user hit
- `## Proposed Solution` — How it could work
- `### Implementation Ideas` — Technical approach
- `### Current Workarounds` — What users can do today
- `## Additional Context` — Links to related issues/discussions
- Add `enhancement` label
- Click "Submit new issue" / "Create"
3. After creation, go back to the original discussion and post a comment linking to the new issue:
- "I've opened Issue #N to track this feature request. Follow along there for updates!"
### 7. Final Report
Present a final summary to the user:
| Discussion | Action Taken |
| ---------- | ---------------------------------- |
| #N — Title | Responded with workarounds |
| #N — Title | Responded + created Issue #N |
| #N — Title | Already answered, no action needed |
| #N — Title | Responded to follow-up comment |
## Notes
- This workflow is **interactive** — always present the summary and wait for user approval before posting responses or creating issues
- If the user says "pode responder" (or similar approval), proceed with posting all drafted responses
- For discussions in non-English languages, respond in the same language as the original post
- Always reference specific dashboard paths, config options, or code files when explaining existing features
- When a discussion reveals a bug, note it separately from feature requests
+5 -1
View File
@@ -18,7 +18,11 @@ This workflow fetches all open PRs from the project's GitHub repository, perform
### 2. Fetch Open Pull Requests
- Navigate to `https://github.com/<owner>/<repo>/pulls` and scrape all open PRs
// turbo
- Run: `gh pr list --repo <owner>/<repo> --state open --limit 500 --json number,title,author,headRefName,body,createdAt,additions,deletions,files`
- This fetches **all** open PRs without restriction. Get the diff for each with:
`gh pr diff <NUMBER> --repo <owner>/<repo>`
- For each open PR, collect:
- PR number, title, author, branch, number of commits, date
- PR description/body
+2 -2
View File
@@ -56,13 +56,13 @@ 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.ja.md README.ko.md README.zh-CN.md README.phi.md README.cs.md
```
**docs/i18n/ directories (29 languages):**
```
docs/i18n/{ar,bg,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}/
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
```
+25 -1
View File
@@ -142,10 +142,32 @@ GITHUB_USER_AGENT=GitHubCopilotChat/0.26.7
ANTIGRAVITY_USER_AGENT=antigravity/1.104.0 darwin/arm64
KIRO_USER_AGENT=AWS-SDK-JS/3.0.0 kiro-ide/1.0.0
IFLOW_USER_AGENT=iFlow-Cli
QWEN_USER_AGENT=google-api-nodejs-client/9.15.1
QWEN_USER_AGENT=QwenCode/0.12.3 (linux; x64)
CURSOR_USER_AGENT=connect-es/1.6.1
GEMINI_CLI_USER_AGENT=google-api-nodejs-client/9.15.1
# ─────────────────────────────────────────────────────────────────────────────
# CLI Fingerprint Compatibility (optional — match native CLI binary signatures)
# ─────────────────────────────────────────────────────────────────────────────
# When enabled, OmniRoute reorders HTTP headers and JSON body fields to match
# the exact signature of official CLI tools, reducing account flagging risk.
# Your proxy IP is preserved — you get both stealth AND IP masking.
#
# Enable per-provider:
# CLI_COMPAT_CODEX=1
# CLI_COMPAT_CLAUDE=1
# CLI_COMPAT_GITHUB=1
# CLI_COMPAT_ANTIGRAVITY=1
# CLI_COMPAT_KIRO=1
# CLI_COMPAT_CURSOR=1
# CLI_COMPAT_KIMI_CODING=1
# CLI_COMPAT_KILOCODE=1
# CLI_COMPAT_CLINE=1
# CLI_COMPAT_QWEN=1
#
# Or enable for all providers at once:
# CLI_COMPAT_ALL=1
# API Key Providers (Phase 1 + Phase 4)
# Add via Dashboard → Providers → Add API Key, or set here
# DEEPSEEK_API_KEY=
@@ -166,6 +188,8 @@ GEMINI_CLI_USER_AGENT=google-api-nodejs-client/9.15.1
# Timeout settings
# FETCH_TIMEOUT_MS=120000
# STREAM_IDLE_TIMEOUT_MS=60000
# API bridge timeout for /v1 proxy requests (default: 30000)
# API_BRIDGE_PROXY_TIMEOUT_MS=120000
# CORS configuration (default: * allows all origins)
# CORS_ORIGINS=*
+145
View File
@@ -0,0 +1,145 @@
name: Bug Report
description: Report a bug or unexpected behavior in OmniRoute
title: "[BUG] "
labels: ["bug"]
body:
- type: markdown
attributes:
value: |
Thanks for taking the time to report a bug. Please fill out the sections below so we can reproduce and fix the issue.
- type: input
id: version
attributes:
label: OmniRoute Version
description: "Run `omniroute --version` or check the left sidebar in the dashboard."
placeholder: "e.g. 3.0.9"
validations:
required: true
- type: dropdown
id: install-method
attributes:
label: Installation Method
options:
- npm (global)
- Docker / Docker Compose
- Electron desktop app
- Built from source
validations:
required: true
- type: dropdown
id: os
attributes:
label: Operating System
options:
- Windows
- macOS
- Linux
validations:
required: true
- type: input
id: os-version
attributes:
label: OS Version
placeholder: "e.g. Windows 11 23H2, macOS 15.3, Ubuntu 24.04"
validations:
required: false
- type: input
id: node-version
attributes:
label: Node.js Version
description: "Run `node --version`. Skip if using Docker."
placeholder: "e.g. 22.12.0"
validations:
required: false
- type: input
id: provider
attributes:
label: Provider(s) Involved
description: "Which AI provider(s) does this affect?"
placeholder: "e.g. Antigravity, OpenRouter, Ollama, Qwen"
validations:
required: false
- type: input
id: model
attributes:
label: Model(s) Involved
placeholder: "e.g. claude-sonnet-4-20250514, gpt-4o, gemini-2.5-pro"
validations:
required: false
- type: input
id: client-tool
attributes:
label: Client Tool
description: "Which tool are you using OmniRoute with?"
placeholder: "e.g. Claude Code, Cursor, Roo Code, OpenClaw, Gemini CLI, cURL"
validations:
required: false
- type: textarea
id: description
attributes:
label: Description
description: "A clear description of what the bug is."
validations:
required: true
- type: textarea
id: steps
attributes:
label: Steps to Reproduce
description: "Step-by-step instructions to reproduce the behavior."
placeholder: |
1. Go to '...'
2. Click on '...'
3. See error
validations:
required: true
- type: textarea
id: expected
attributes:
label: Expected Behavior
description: "What did you expect to happen?"
validations:
required: true
- type: textarea
id: actual
attributes:
label: Actual Behavior
description: "What actually happened?"
validations:
required: true
- type: textarea
id: logs
attributes:
label: Error Logs / Output
description: "Paste any relevant error messages, logs, or terminal output. This will be automatically formatted as code."
render: shell
validations:
required: false
- type: textarea
id: screenshots
attributes:
label: Screenshots
description: "If applicable, add screenshots to help explain the problem. Please also include the text of any error messages above — screenshots alone are not searchable."
validations:
required: false
- type: textarea
id: additional
attributes:
label: Additional Context
description: "Any other context about the problem (e.g. proxy config, number of accounts, network setup)."
validations:
required: false
+5
View File
@@ -0,0 +1,5 @@
blank_issues_enabled: true
contact_links:
- name: Question / Help
url: https://github.com/diegosouzapw/OmniRoute/discussions
about: For questions or help with setup, please use GitHub Discussions instead of opening an issue.
@@ -0,0 +1,70 @@
name: Feature Request
description: Suggest a new feature or improvement for OmniRoute
title: "[Feature] "
labels: ["enhancement"]
body:
- type: markdown
attributes:
value: |
Thanks for suggesting a feature! Please describe the problem you're trying to solve and how you'd like it to work.
- type: textarea
id: problem
attributes:
label: Problem / Use Case
description: "What problem does this feature solve? Why do you need it?"
placeholder: "I'm trying to ... but currently ..."
validations:
required: true
- type: textarea
id: solution
attributes:
label: Proposed Solution
description: "How would you like this to work?"
validations:
required: true
- type: textarea
id: alternatives
attributes:
label: Alternatives Considered
description: "Have you considered any workarounds or alternative approaches?"
validations:
required: false
- type: dropdown
id: area
attributes:
label: Area
description: "Which part of OmniRoute does this relate to?"
multiple: true
options:
- Dashboard / UI
- Proxy / Routing
- Provider Support
- CLI Tools Integration
- OAuth / Authentication
- Analytics / Usage Tracking
- Docker / Deployment
- Documentation
- Other
validations:
required: true
- type: input
id: provider
attributes:
label: Related Provider(s)
description: "If this relates to specific providers, list them."
placeholder: "e.g. Antigravity, OpenRouter, Ollama"
validations:
required: false
- type: textarea
id: additional
attributes:
label: Additional Context
description: "Any other context, mockups, or references."
validations:
required: false
+3
View File
@@ -10,6 +10,9 @@ concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
permissions:
contents: read
jobs:
lint:
name: Lint
+2
View File
@@ -16,12 +16,14 @@ jobs:
steps:
- name: Deploy via SSH
uses: appleboy/ssh-action@v1
continue-on-error: true
with:
host: ${{ secrets.VPS_HOST }}
username: ${{ secrets.VPS_USER }}
key: ${{ secrets.VPS_SSH_KEY }}
port: 22
timeout: 30s
command_timeout: 5m
script: |
echo "=== Updating OmniRoute ==="
npm install -g omniroute@latest 2>&1
+38 -76
View File
@@ -3,32 +3,33 @@ name: Publish to Docker Hub
on:
release:
types: [published]
workflow_dispatch:
inputs:
version:
description: "Version tag to build (e.g. 2.6.0)"
required: true
type: string
permissions:
contents: read
jobs:
build:
name: Build (${{ matrix.platform }})
runs-on: ${{ matrix.runner }}
strategy:
fail-fast: false
matrix:
include:
- platform: linux/amd64
platform_pair: linux-amd64
runner: ubuntu-latest
- platform: linux/arm64
platform_pair: linux-arm64
runner: ubuntu-24.04-arm
docker:
name: Build and Push Docker (multi-arch)
runs-on: ubuntu-latest
env:
IMAGE_NAME: diegosouzapw/omniroute
steps:
- name: Checkout
uses: actions/checkout@v6
with:
ref: ${{ github.event_name == 'workflow_dispatch' && format('refs/tags/v{0}', inputs.version) || '' }}
- name: Set up QEMU (for multi-arch builds)
uses: docker/setup-qemu-action@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
uses: docker/setup-buildx-action@v4
- name: Login to Docker Hub
uses: docker/login-action@v4
@@ -36,72 +37,33 @@ jobs:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Build and push by digest
id: build
- name: Extract version from release tag or input
id: version
run: |
if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
VERSION="${{ inputs.version }}"
else
VERSION="${GITHUB_REF_NAME}"
VERSION="${VERSION#v}"
fi
echo "version=$VERSION" >> "$GITHUB_OUTPUT"
echo "Publishing Docker image: $IMAGE_NAME:$VERSION"
- name: Build and push multi-arch image
uses: docker/build-push-action@v7
with:
context: .
target: runner-base
platforms: ${{ matrix.platform }}
outputs: type=image,name=${{ env.IMAGE_NAME }},push-by-digest=true,name-canonical=true,push=true
cache-from: type=gha,scope=omniroute-runner-base-${{ matrix.platform_pair }}
cache-to: type=gha,mode=max,scope=omniroute-runner-base-${{ matrix.platform_pair }}
- name: Export digest
run: |
mkdir -p "${{ runner.temp }}/digests"
digest="${{ steps.build.outputs.digest }}"
touch "${{ runner.temp }}/digests/${digest#sha256:}"
- name: Upload digest
uses: actions/upload-artifact@v7
with:
name: digests-${{ matrix.platform_pair }}
path: ${{ runner.temp }}/digests/*
if-no-files-found: error
retention-days: 1
merge:
name: Merge manifest and publish tags
runs-on: ubuntu-latest
needs: build
env:
IMAGE_NAME: diegosouzapw/omniroute
steps:
- name: Checkout
uses: actions/checkout@v6
- name: Extract version from release tag
id: version
run: |
VERSION="${GITHUB_REF_NAME}"
VERSION="${VERSION#v}"
echo "version=$VERSION" >> "$GITHUB_OUTPUT"
echo "Publishing Docker image version: $VERSION"
- name: Download digests
uses: actions/download-artifact@v8
with:
path: ${{ runner.temp }}/digests
pattern: digests-*
merge-multiple: true
- name: Login to Docker Hub
uses: docker/login-action@v4
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Create manifest list and push
working-directory: ${{ runner.temp }}/digests
run: |
docker buildx imagetools create \
-t "${{ env.IMAGE_NAME }}:${{ steps.version.outputs.version }}" \
-t "${{ env.IMAGE_NAME }}:latest" \
$(printf '${{ env.IMAGE_NAME }}@sha256:%s ' *)
platforms: linux/amd64,linux/arm64
push: true
tags: |
${{ env.IMAGE_NAME }}:${{ steps.version.outputs.version }}
${{ env.IMAGE_NAME }}:latest
cache-from: type=gha
cache-to: type=gha,mode=max
no-cache: false
env:
DOCKER_BUILDKIT_INLINE_CACHE: 1
- name: Inspect image
run: |
+41 -4
View File
@@ -55,17 +55,18 @@ jobs:
target: win
ext: .exe
- platform: macos-intel
runner: macos-latest
target: mac
runner: macos-15-intel
target: mac-x64
ext: .dmg
- platform: macos-arm64
runner: macos-latest
target: mac
target: mac-arm64
ext: -arm64.dmg
- platform: linux
runner: ubuntu-latest
target: linux
ext: .AppImage
deb_ext: .deb
steps:
- name: Checkout
@@ -93,12 +94,31 @@ jobs:
JWT_SECRET: ci-build-secret-with-sufficient-length-for-validation
run: npm run build
- name: Sync version in electron/package.json
shell: bash
run: |
VERSION="${{ needs.validate.outputs.version }}"
VERSION_NO_V="${VERSION#v}"
node -e "
const fs = require('fs');
const pkg = JSON.parse(fs.readFileSync('electron/package.json'));
pkg.version = '$VERSION_NO_V';
fs.writeFileSync('electron/package.json', JSON.stringify(pkg, null, 2) + '\\n');
"
echo "✓ electron/package.json version set to $VERSION_NO_V"
- name: Install fpm (Linux .deb packaging tool)
if: matrix.platform == 'linux'
run: sudo gem install fpm --no-document
- name: Install Electron dependencies
working-directory: electron
run: npm install --no-audit --no-fund
- name: Build Electron for ${{ matrix.platform }}
working-directory: electron
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: npm run build:${{ matrix.target }}
- name: Collect installers
@@ -110,6 +130,12 @@ jobs:
for file in *${{ matrix.ext }}; do
[ -f "$file" ] && cp "$file" ../../release-assets/
done
# Linux: also copy .deb package
if [ "${{ matrix.platform }}" = "linux" ]; then
for file in *.deb; do
[ -f "$file" ] && cp "$file" ../../release-assets/
done
fi
# Windows: also copy portable standalone exe as OmniRoute.exe
if [ "${{ matrix.platform }}" = "windows" ]; then
for file in *.exe; do
@@ -164,13 +190,24 @@ jobs:
draft: false
prerelease: false
generate_release_notes: true
fail_on_unmatched_files: false
files: |
release-assets/*.dmg
release-assets/*-arm64.dmg
release-assets/*.exe
release-assets/*.AppImage
release-assets/*.deb
release-assets/*.blockmap
release-assets/*.source.tar.gz
release-assets/*.source.zip
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
publish-npm:
name: Publish to npm
needs: [validate, release]
uses: ./.github/workflows/npm-publish.yml
with:
version: ${{ needs.validate.outputs.version }}
tag: latest
secrets:
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
+76 -11
View File
@@ -3,6 +3,34 @@ name: Publish to npm
on:
release:
types: [published]
workflow_dispatch:
inputs:
version:
description: "Version to publish (e.g. 2.9.5 or 3.0.0-rc.15)"
required: true
type: string
tag:
description: "npm dist-tag (latest / next)"
required: false
default: "latest"
type: choice
options:
- latest
- next
workflow_call:
inputs:
version:
description: "Version to publish (without v prefix)"
required: true
type: string
tag:
description: "npm dist-tag (latest / next)"
required: false
default: "latest"
type: string
secrets:
NPM_TOKEN:
required: true
permissions:
contents: read
@@ -22,21 +50,58 @@ jobs:
node-version: 22
registry-url: https://registry.npmjs.org
- name: Install dependencies
run: npm ci
- name: Install dependencies (skip scripts to avoid heavy build)
run: npm install --ignore-scripts --no-audit --no-fund
- name: Build standalone app
run: npm run build:cli
- name: Sync version from release tag
- name: Resolve version and dist-tag
id: resolve
run: |
VERSION="${GITHUB_REF_NAME}"
# Remove 'v' prefix if present (v0.1.0 -> 0.1.0)
case "${{ github.event_name }}" in
workflow_dispatch|workflow_call)
VERSION="${{ inputs.version }}"
TAG="${{ inputs.tag }}"
;;
release)
VERSION="${GITHUB_REF_NAME}"
;;
esac
# Strip v prefix if present
VERSION="${VERSION#v}"
npm version "$VERSION" --no-git-tag-version --allow-same-version
echo "Publishing version: $VERSION"
# Default dist-tag logic
if [ -z "$TAG" ]; then
if [[ "$VERSION" == *-* ]]; then
TAG="next"
else
TAG="latest"
fi
fi
echo "version=$VERSION" >> $GITHUB_OUTPUT
echo "tag=$TAG" >> $GITHUB_OUTPUT
echo "📦 Publishing omniroute@$VERSION with tag=$TAG"
- name: Sync package.json version
run: |
npm version "${{ steps.resolve.outputs.version }}" --no-git-tag-version --allow-same-version
- name: Build CLI bundle (standalone app)
env:
JWT_SECRET: ci-build-secret-with-sufficient-length-for-validation
run: node scripts/prepublish.mjs
- name: Publish to npm
run: npm publish --access public
run: |
VERSION="${{ steps.resolve.outputs.version }}"
TAG="${{ steps.resolve.outputs.tag }}"
# Check if this version is already published — skip instead of failing with E403
if npm view "omniroute@${VERSION}" version --silent 2>/dev/null | grep -q "^${VERSION}$"; then
echo "⚠️ Version ${VERSION} is already published on npm — skipping."
exit 0
fi
if [ "$TAG" = "latest" ]; then
npm publish --access public
else
npm publish --access public --tag "$TAG"
fi
echo "✅ Published omniroute@$VERSION (tag: $TAG)"
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
+15 -3
View File
@@ -1,5 +1,10 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
# project-specific directories
.omnivscodeagent/
omnirouteCloud/
omnirouteSite/
# dependencies
node_modules/
/.pnp
@@ -50,6 +55,8 @@ logs/*
# analysis directories (generated, not tracked)
.analysis/
antigravity-manager-analysis/
.sisyphus/
.plans/
# docs (allow specific tracked files)
docs/*
@@ -77,6 +84,11 @@ docs/*
!docs/screenshots/
!docs/i18n/
!docs/i18n/**
!docs/A2A-SERVER.md
!docs/AUTO-COMBO.md
!docs/MCP-SERVER.md
!docs/CLI-TOOLS.md
# open-sse tests
open-sse/test/*
@@ -89,14 +101,11 @@ test-results/
playwright-report/
blob-report/
cloud/
omnirouteCloud/
omnirouteSite/
# Security Analysis (standalone project with own git)
security-analysis/
# Deploy workflow (contains sensitive VPS credentials)
.agent/workflows/deploy.md
clipr/
app.log
*.tgz
@@ -122,3 +131,6 @@ vscode-extension/
*.sqlite-shm
*.sqlite-wal
*.sqlite-journal
# Compiled npm-package build artifact (not source, should not be in git)
/app
+2
View File
@@ -1 +1,3 @@
npx lint-staged
node scripts/check-docs-sync.mjs
npm run test:unit
+5
View File
@@ -3,6 +3,11 @@ data/
**/data/
**/db.json
# VS Code extension test runtime (large binary, not needed in npm package)
app/vscode-extension/
**/data/
**/db.json
# Source code (pre-built app/ is published instead)
src/
open-sse/
+22 -18
View File
@@ -49,19 +49,22 @@ but the real logic lives in `src/lib/db/`.
Translation between provider formats: `open-sse/translator/`
**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 models 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.
### MCP Server (`open-sse/mcp-server/`)
16 tools for AI agent control via **3 transport modes**:
- **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`
HTTP transports run in-process via `httpTransport.ts` singleton using `WebStandardStreamableHTTPServerTransport`.
| 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` |
| 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
@@ -79,25 +82,26 @@ Agent-to-Agent v0.3 protocol:
### Auto-Combo Engine (`open-sse/services/autoCombo/`)
Self-healing routing optimization:
- 6-factor scoring, 4 mode packs, bandit exploration
- Progressive cooldown, probe-based re-admission
### Dashboard (`src/app/(dashboard)/`)
| 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 |
| 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 |
### OAuth & Tokens (`src/lib/oauth/`)
+1842 -1274
View File
File diff suppressed because it is too large Load Diff
+9
View File
@@ -3,6 +3,7 @@ WORKDIR /app
COPY package*.json ./
COPY scripts/postinstall.mjs ./scripts/postinstall.mjs
COPY scripts/native-binary-compat.mjs ./scripts/native-binary-compat.mjs
RUN if [ -f package-lock.json ]; then npm ci --no-audit --no-fund; else npm install --no-audit --no-fund; fi
COPY . ./
@@ -29,8 +30,16 @@ RUN mkdir -p /app/data
COPY --from=builder /app/public ./public
COPY --from=builder /app/.next/static ./.next/static
COPY --from=builder /app/.next/standalone ./
# Explicitly copy @swc/helpers — not always traced by standalone output but needed at runtime
COPY --from=builder /app/node_modules/@swc/helpers ./node_modules/@swc/helpers
# Explicitly copy pino transport dependencies — pino spawns a worker that requires
# pino-abstract-transport at runtime; Next.js standalone trace does not capture it (#449)
COPY --from=builder /app/node_modules/pino-abstract-transport ./node_modules/pino-abstract-transport
COPY --from=builder /app/node_modules/pino-pretty ./node_modules/pino-pretty
COPY --from=builder /app/node_modules/split2 ./node_modules/split2
COPY --from=builder /app/scripts/run-standalone.mjs ./run-standalone.mjs
COPY --from=builder /app/scripts/runtime-env.mjs ./runtime-env.mjs
COPY --from=builder /app/scripts/bootstrap-env.mjs ./bootstrap-env.mjs
COPY --from=builder /app/scripts/healthcheck.mjs ./healthcheck.mjs
EXPOSE 20128
+458 -85
View File
@@ -2,16 +2,18 @@
### Never stop coding. Smart routing to **FREE & low-cost AI models** with automatic fallback.
_Your universal API proxy — one endpoint, 36+ providers, zero downtime. Now with **MCP & A2A** agent orchestration._
_Your universal API proxy — one endpoint, 67+ providers, zero downtime. Now with **MCP & A2A** agent orchestration._
**Chat Completions • Embeddings • Image Generation • Video • Music • Audio • Reranking • MCP Server • A2A Protocol • 100% TypeScript**
**Chat Completions • Embeddings • Image Generation • Video • Music • Audio • Reranking • **Web Search** MCP Server • A2A Protocol • 100% TypeScript**
---
<div align="center">
[![npm version](https://img.shields.io/npm/v/omniroute?color=cb3837&logo=npm)](https://www.npmjs.com/package/omniroute)
[![npm downloads](https://img.shields.io/npm/dm/omniroute?color=cb3837&logo=npm&label=npm%20downloads)](https://www.npmjs.com/package/omniroute)
[![Docker Hub](https://img.shields.io/docker/v/diegosouzapw/omniroute?label=Docker%20Hub&logo=docker&color=2496ED)](https://hub.docker.com/r/diegosouzapw/omniroute)
[![Docker Pulls](https://img.shields.io/docker/pulls/diegosouzapw/omniroute?logo=docker&color=2496ED&label=docker%20pulls)](https://hub.docker.com/r/diegosouzapw/omniroute)
[![License](https://img.shields.io/github/license/diegosouzapw/OmniRoute)](https://github.com/diegosouzapw/OmniRoute/blob/main/LICENSE)
[![Website](https://img.shields.io/badge/Website-omniroute.online-blue?logo=google-chrome&logoColor=white)](https://omniroute.online)
[![WhatsApp](https://img.shields.io/badge/WhatsApp-Community-25D366?logo=whatsapp&logoColor=white)](https://chat.whatsapp.com/JI7cDQ1GyaiDHhVBpLxf8b?mode=gi_t)
@@ -20,7 +22,29 @@ _Your universal API proxy — one endpoint, 36+ providers, zero downtime. Now wi
</div>
🌐 **Available in:** 🇺🇸 [English](README.md) | 🇧🇷 [Português (Brasil)](README.pt-BR.md) | 🇪🇸 [Español](README.es.md) | 🇫🇷 [Français](README.fr.md) | 🇮🇹 [Italiano](README.it.md) | 🇷🇺 [Русский](README.ru.md) | 🇨🇳 [中文 (简体)](README.zh-CN.md) | 🇩🇪 [Deutsch](README.de.md) | 🇮🇳 [हिन्दी](README.in.md) | 🇹🇭 [ไทย](README.th.md) | 🇺🇦 [Українська](README.uk-UA.md) | 🇸🇦 [العربية](README.ar.md) | 🇯🇵 [日本語](README.ja.md) | 🇻🇳 [Tiếng Việt](README.vi.md) | 🇧🇬 [Български](README.bg.md) | 🇩🇰 [Dansk](README.da.md) | 🇫🇮 [Suomi](README.fi.md) | 🇮🇱 [עברית](README.he.md) | 🇭🇺 [Magyar](README.hu.md) | 🇮🇩 [Bahasa Indonesia](README.id.md) | 🇰🇷 [한국어](README.ko.md) | 🇲🇾 [Bahasa Melayu](README.ms.md) | 🇳🇱 [Nederlands](README.nl.md) | 🇳🇴 [Norsk](README.no.md) | 🇵🇹 [Português (Portugal)](README.pt.md) | 🇷🇴 [Română](README.ro.md) | 🇵🇱 [Polski](README.pl.md) | 🇸🇰 [Slovenčina](README.sk.md) | 🇸🇪 [Svenska](README.sv.md) | 🇵🇭 [Filipino](README.phi.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
> **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 `<omniModel>` 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 |
---
@@ -167,6 +191,16 @@ _Connect any AI-powered IDE or CLI tool through OmniRoute — free API gateway f
- **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)
### 🐛 Reporting a Bug?
When opening an issue, please run the system-info command and attach the generated file:
```bash
npm run system-info
```
This generates a `system-info.txt` with your Node.js version, OmniRoute version, OS details, installed CLI tools (iflow, 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.
---
## 🔄 How It Works
@@ -224,7 +258,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 36+ providers
- **Unified Endpoint** — A single `http://localhost:20128/v1` serves as proxy for all 67+ 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
@@ -247,6 +281,7 @@ Providers like OpenAI/Codex block access from certain geographic regions. Users
- **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
</details>
@@ -257,9 +292,10 @@ Not everyone can pay $20200/month for AI subscriptions. Students, devs from e
**How OmniRoute solves it:**
- **Free Tier Providers Built-in** — Native support for 100% free providers: iFlow (8 unlimited models), Qwen (3 unlimited models), Kiro (Claude for free), Gemini CLI (180K/month free)
- **Free Tier Providers Built-in** — Native support for 100% free providers: iFlow (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/<model>` 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 Credits** — 1000 free credits integrated
- **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
</details>
@@ -308,7 +344,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 36+ providers
- **One endpoint, all models** — Configure `http://localhost:20128/v1` once, access 67+ providers
</details>
@@ -356,6 +392,7 @@ When a call fails, the dev doesn't know if it was a rate limit, expired token, w
- **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
- **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.
</details>
@@ -402,7 +439,7 @@ AI isn't just chat completion. Devs need to generate images, transcribe audio, c
- **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, + existing providers
- **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
@@ -689,6 +726,22 @@ Outcome: deep fallback depth for deadline-critical workloads
---
## 🆓 Start Free — Zero Configuration Cost
> Setup AI coding in minutes at **$0/month**. Connect these free accounts and use the built-in **Free Stack** combo.
| Step | Action | Providers Unlocked |
| ---- | -------------------------------------------------- | ------------------------------------------------------------------ |
| 1 | Connect **Kiro** (AWS Builder ID OAuth) | Claude Sonnet 4.5, Haiku 4.5 — **unlimited** |
| 2 | Connect **iFlow** (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 |
**Point any IDE/CLI to:** `http://localhost:20128/v1` · API Key: `any-string` · Done.
> **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).
## ⚡ Quick Start
### 1) Install and run
@@ -698,6 +751,14 @@ npm install -g omniroute
omniroute
```
> **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
> pnpm approve-builds -g # Select all packages → approve
> omniroute
> ```
Dashboard opens at `http://localhost:20128` and API base URL is `http://localhost:20128/v1`.
| Command | Description |
@@ -861,33 +922,234 @@ When minimized, OmniRoute lives in your system tray with quick actions:
## 💰 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** | NVIDIA NIM | **FREE** (1000 credits) | One-time | Free tier testing |
| | DeepSeek | Pay-per-use | None | Best price/quality |
| | Groq | Free tier + paid | Rate limited | Ultra-fast inference |
| | xAI (Grok) | Pay-per-use | None | Grok models |
| | Mistral | Free tier + paid | Rate limited | European AI |
| | OpenRouter | Pay-per-use | None | 100+ 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** | iFlow | $0 | Unlimited | 8 models free |
| | Qwen | $0 | Unlimited | 3 models free |
| | Kiro | $0 | Unlimited | Claude free |
| 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** | iFlow | **$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 |
**💡 Pro Tip:** Start with Gemini CLI (180K free/month) + iFlow (unlimited free) combo = $0 cost!
> 🆕 **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.
**💡 $0 Combo Stack — The Complete Free Setup:**
```
# 🆓 Ultimate Free Stack 2026 — 11 Providers, $0 Forever
Kiro (kr/) → Claude Sonnet/Haiku UNLIMITED
iFlow (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
```
**Zero cost. Never stops coding.** Configure this as one OmniRoute combo and all fallbacks happen automatically — no manual switching ever.
---
---
## 🆓 Free Models — What You Actually Get
> 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 (via Kiro — AWS Builder ID)
| 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 |
### 🟢 IFLOW MODELS (Free OAuth — No Credit Card)
| 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 |
### 🟡 QWEN MODELS (Device Code Auth)
| 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) |
### 🟣 GEMINI CLI (Google OAuth)
| 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 (Free API Key — build.nvidia.com)
| Tier | Daily Limit | Rate Limit | Notes |
| ---------- | ------------ | ----------- | ------------------------------------------------------ |
| Free (Dev) | No token cap | **~40 RPM** | 70+ models; transitioning to pure rate limits mid-2025 |
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 (Free API Key — inference.cerebras.ai)
| Tier | Daily Limit | Rate Limit | Notes |
| ---- | ----------------- | ---------------- | ------------------------------------------- |
| Free | **1M tokens/day** | 60K TPM / 30 RPM | World's fastest LLM inference; resets daily |
Available free: `llama-3.3-70b`, `llama-3.1-8b`, `deepseek-r1-distill-llama-70b`
### 🔴 GROQ (Free API Key — console.groq.com)
| Tier | Daily Limit | Rate Limit | Notes |
| ---- | ------------- | ---------------- | ----------------------------------------- |
| Free | **14.4K RPD** | 30 RPM per model | No credit card; 429 on limit, not charged |
Available free: `llama-3.3-70b-versatile`, `gemma2-9b-it`, `mixtral-8x7b`, `whisper-large-v3`
### 🔴 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 (kr/) → Claude Sonnet/Haiku UNLIMITED
> iFlow (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
> ```
## 🎙️ Free Transcription Combo
> Transcribe any audio/video for **$0** — Deepgram leads with $200 free, AssemblyAI $50 fallback, Groq Whisper as unlimited emergency backup.
| 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) |
**Suggested combo in `/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
```
Then in `/dashboard/media`**Transcription** tab: upload any audio or video file → select your combo endpoint → get transcription in supported formats.
## 💡 Key Features
OmniRoute v2.0 is built as an operational platform, not just a relay proxy.
### 🆕 New — ClawRouter-Inspired Improvements (Mar 2026)
| 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 |
### 🚀 Previous v2.0.9+ — Playground, CLI Fingerprints & ACP
| 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 |
### 🤖 Agent & Protocol Operations (v2.0)
| Feature | What It Does |
@@ -906,48 +1168,51 @@ OmniRoute v2.0 is built as an operational platform, not just a relay proxy.
### 🧠 Routing & Intelligence
| 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** | 6 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 |
| 💬 **System Prompt Injection** | Global behavior controls applied consistently |
| 📄 **Responses API Compatibility** | Full `/v1/responses` support for Codex and advanced agentic workflows |
| 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** | 6 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) |
| 💬 **System Prompt Injection** | Global behavior controls applied consistently |
| 📄 **Responses API Compatibility** | Full `/v1/responses` support for Codex and advanced agentic workflows |
### 🎵 Multi-Modal APIs
| 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` (Whisper and additional providers) |
| 🔊 **Text-to-Speech** | `/v1/audio/speech` (multiple engines/providers) |
| 🎬 **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 |
| 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 |
### 🛡️ Resilience, Security & Governance
| 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** | Better compatibility with anti-bot filtered providers |
| 🌐 **IP Filtering** | Allowlist/blocklist control for exposed deployments |
| 📊 **Editable Rate Limits** | Configurable global/provider-level limits with persistence |
| 🔑 **API Key Management + Scoping** | Secure key issuance/rotation and model/provider controls |
| 🛡️ **Protected `/models`** | Optional auth gating and provider hiding for model catalog |
| 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 |
| 🔑 **API Key Management + Scoping** | Secure key issuance/rotation and model/provider controls |
| 🛡️ **Protected `/models`** | Optional auth gating and provider hiding for model catalog |
### 📊 Observability & Analytics
@@ -963,15 +1228,19 @@ OmniRoute v2.0 is built as an operational platform, not just a relay proxy.
### ☁️ Deployment & Platform
| Feature | What It Does |
| ---------------------------- | -------------------------------------------------------- |
| 🌐 **Deploy Anywhere** | Localhost, VPS, Docker, Cloud environments |
| 💾 **Cloud Sync** | Configuration sync via cloud worker |
| 🔄 **Backup/Restore** | Export/import and disaster recovery flows |
| 🧙 **Onboarding Wizard** | First-run guided setup |
| 🔧 **CLI Tools Dashboard** | One-click setup for popular coding tools |
| 🌐 **i18n (30 languages)** | Full dashboard + docs language support with RTL coverage |
| 📂 **Custom Data Directory** | `DATA_DIR` override for storage location |
| Feature | What It Does |
| ----------------------------- | -------------------------------------------------------- |
| 🌐 **Deploy Anywhere** | Localhost, VPS, Docker, Cloud environments |
| 💾 **Cloud Sync** | Configuration sync via cloud worker |
| 🔄 **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 |
| 📋 **Issue Templates** | Standardized GitHub templates for bugs and features |
| 📂 **Custom Data Directory** | `DATA_DIR` override for storage location |
### Feature Deep Dive
@@ -1137,6 +1406,23 @@ Models:
cx/gpt-5.1-codex-max
```
#### Codex Account Limit Management (5h + Weekly)
Each Codex account now has policy toggles in `Dashboard -> Providers`:
- `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.
Scenarios:
- `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 (FREE 180K/month!)
```bash
@@ -1169,7 +1455,7 @@ Models:
<details>
<summary><b>🔑 API Key Providers</b></summary>
### NVIDIA NIM (FREE 1000 credits!)
### 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)
@@ -1248,7 +1534,7 @@ Models:
<details>
<summary><b>🆓 FREE Providers (Emergency Backup)</b></summary>
### iFlow (8 FREE models)
### iFlow (5 FREE models via OAuth)
```bash
Dashboard → Connect iFlow
@@ -1263,7 +1549,7 @@ Models:
if/deepseek-r1
```
### Qwen (3 FREE models)
### Qwen (4 FREE models via Device Code)
```bash
Dashboard → Connect Qwen
@@ -1480,11 +1766,102 @@ opencode
- OmniRoute v1.0.6+ includes fallback validation via chat completions
- Ensure base URL includes `/v1` suffix
### 🔐 OAuth em Servidor Remoto (Remote OAuth Setup)
### 🔐 OAuth on a Remote Server
<a name="oauth-on-a-remote-server"></a>
<a name="oauth-em-servidor-remoto"></a>
> **⚠️ IMPORTANTE para usuários com OmniRoute em VPS/Docker/servidor remoto**
> **⚠️ Important for users running OmniRoute on a VPS, Docker, or any remote server**
#### Why does Antigravity / Gemini CLI OAuth fail on remote servers?
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.
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
```
#### Solution: Configure your own OAuth credentials
You need to create an **OAuth 2.0 Client ID** in Google Cloud Console with your server's URI.
#### Step-by-step
**1. Open Google Cloud Console**
Go to: [https://console.cloud.google.com/apis/credentials](https://console.cloud.google.com/apis/credentials)
**2. Create a new OAuth 2.0 Client ID**
- Click **"+ Create Credentials"** → **"OAuth client ID"**
- Application type: **"Web application"**
- Name: anything you like (e.g. `OmniRoute Remote`)
**3. Add Authorized Redirect URIs**
In the **"Authorized redirect URIs"** field, add:
```
https://your-server.com/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. Save and copy the credentials**
After creating, Google will show the **Client ID** and **Client Secret**.
**5. Set environment variables**
In your `.env` (or Docker environment variables):
```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. Restart OmniRoute**
```bash
# npm:
npm run dev
# Docker:
docker restart omniroute
```
**7. Try connecting again**
Dashboard → Providers → Antigravity (or Gemini CLI) → OAuth
Google will now redirect correctly to `https://your-server.com/callback`.
---
#### Temporary workaround (without custom credentials)
If you don't want to set up your own credentials right now, you can still use the **manual URL flow**:
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"**
> This works because the authorization code in the URL is valid regardless of whether the redirect page loaded.
---
<details>
<summary><b>🇧🇷 Versão em Português</b></summary>
#### Por que o OAuth do Antigravity / Gemini CLI falha em servidores remotos?
@@ -1575,6 +1952,8 @@ Se não quiser criar credenciais próprias agora, ainda é possível usar o flux
---
</details>
## 🛠️ Tech Stack
<details>
@@ -1669,15 +2048,9 @@ gh release create v2.0.0 --title "v2.0.0" --generate-notes
## 📊 Star History
<a href="https://star-history.com/#diegosouzapw/OmniRoute&Date">
<picture>
<source media="(prefers-color-scheme: dark)" srcset="https://api.star-history.com/svg?repos=diegosouzapw/OmniRoute&type=Date&theme=dark" />
<source media="(prefers-color-scheme: light)" srcset="https://api.star-history.com/svg?repos=diegosouzapw/OmniRoute&type=Date" />
<img alt="Star History Chart" src="https://api.star-history.com/svg?repos=diegosouzapw/OmniRoute&type=Date" />
</picture>
</a>
## Stargazers over time
---
## [![Stargazers over time](https://starchart.cc/diegosouzapw/OmniRoute.svg?variant=adaptive)](https://starchart.cc/diegosouzapw/OmniRoute)
## 🙏 Acknowledgments
+47 -6
View File
@@ -17,6 +17,7 @@ import { existsSync, readFileSync } from "node:fs";
import { join, dirname } from "node:path";
import { fileURLToPath } from "node:url";
import { homedir, platform } from "node:os";
import { isNativeBinaryCompatible } from "../scripts/native-binary-compat.mjs";
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
@@ -115,10 +116,8 @@ if (args.includes("--help") || args.includes("-h")) {
if (args.includes("--version") || args.includes("-v")) {
try {
const pkg = await import(join(ROOT, "package.json"), {
with: { type: "json" },
});
console.log(pkg.default.version);
const { version } = JSON.parse(readFileSync(join(ROOT, "package.json"), "utf8"));
console.log(version);
} catch {
console.log("unknown");
}
@@ -188,8 +187,50 @@ const serverJs = join(APP_DIR, "server.js");
if (!existsSync(serverJs)) {
console.error("\x1b[31m✖ Server not found at:\x1b[0m", serverJs);
console.error(" This usually means the package was not built correctly.");
console.error(" Try reinstalling: npm install -g omniroute");
console.error(" The package may not have been built correctly.");
console.error("");
// (#492) Detect common non-standard Node managers that cause this issue
const nodeExec = process.execPath || "";
const isMise = nodeExec.includes("mise") || nodeExec.includes(".local/share/mise");
const isNvm = nodeExec.includes(".nvm") || nodeExec.includes("nvm");
if (isMise) {
console.error(
" \x1b[33m⚠ mise detected:\x1b[0m If you installed via `npm install -g omniroute`,"
);
console.error(" try: \x1b[36mnpx omniroute@latest\x1b[0m (downloads a fresh copy)");
console.error(" or: \x1b[36mmise exec -- npx omniroute\x1b[0m");
} else if (isNvm) {
console.error(
" \x1b[33m⚠ nvm detected:\x1b[0m Try reinstalling after loading the correct Node version:"
);
console.error(" \x1b[36mnvm use --lts && npm install -g omniroute\x1b[0m");
} else {
console.error(" Try: \x1b[36mnpm install -g omniroute\x1b[0m (reinstall)");
console.error(" Or: \x1b[36mnpx omniroute@latest\x1b[0m");
}
process.exit(1);
}
// ── Pre-flight: verify better-sqlite3 native binary ───────
// Verify the binary's actual target platform/arch before trusting dlopen.
// This avoids the macOS false positive where a bundled linux-x64 addon can
// appear to load even though the runtime will fail when better-sqlite3 starts.
const sqliteBinary = join(
APP_DIR,
"node_modules",
"better-sqlite3",
"build",
"Release",
"better_sqlite3.node"
);
if (existsSync(sqliteBinary) && !isNativeBinaryCompatible(sqliteBinary)) {
console.error(
"\x1b[31m✖ better-sqlite3 native module is incompatible with this platform.\x1b[0m"
);
console.error(` Run: cd ${APP_DIR} && npm rebuild better-sqlite3`);
if (platform() === "darwin") {
console.error(" If build tools are missing: xcode-select --install");
}
process.exit(1);
}
+1 -1
View File
@@ -16,7 +16,7 @@ services:
container_name: omniroute-prod
build:
context: .
target: runner-base
target: runner-cli
image: omniroute:prod
restart: unless-stopped
env_file: .env
+196
View File
@@ -0,0 +1,196 @@
# 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);
```
+31 -16
View File
@@ -1,6 +1,6 @@
# 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)
🌐 **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) | 🇨🇿 [Čeština](i18n/cs/API_REFERENCE.md)
Complete reference for all OmniRoute API endpoints.
@@ -38,15 +38,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;`.
---
@@ -137,10 +142,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:
@@ -213,7 +218,7 @@ Response example:
| Endpoint | Method | Description |
| ------------------------------- | ------- | ---------------------- |
| `/api/settings` | GET/PUT | General settings |
| `/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 |
@@ -226,8 +231,8 @@ Response example:
| ------------------------ | ---------- | ----------------------- |
| `/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 |
| `/api/monitoring/health` | GET | Health check + provider summary (`catalogCount`, `configuredCount`, `activeCount`, `monitoredCount`) |
| `/api/cache/stats` | GET/DELETE | Cache stats / clear |
### Backup & Export/Import
@@ -260,11 +265,21 @@ Response example:
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` | 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 |
+22 -2
View File
@@ -1,8 +1,8 @@
# 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)
🌐 **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) | 🇨🇿 [Čeština](i18n/cs/ARCHITECTURE.md)
_Last updated: 2026-03-04_
_Last updated: 2026-03-24_
## Executive Summary
@@ -65,6 +65,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
+63
View File
@@ -0,0 +1,63 @@
# 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 |
+344
View File
@@ -0,0 +1,344 @@
# CLI Tools Setup Guide — OmniRoute
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 |
---
## 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 <command>` |
| `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"
```
+1 -1
View File
@@ -1,6 +1,6 @@
# 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)
🌐 **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) | 🇨🇿 [Čeština](i18n/cs/CODEBASE_DOCUMENTATION.md)
> A comprehensive, beginner-friendly guide to the **omniroute** multi-provider AI proxy router.
+57 -7
View File
@@ -1,6 +1,6 @@
# OmniRoute — Dashboard Features Gallery
🌐 **Languages:** 🇺🇸 [English](FEATURES.md) | 🇧🇷 [Português (Brasil)](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) | 🇩🇰 [Dansk](i18n/da/FEATURES.md) | 🇫🇮 [Suomi](i18n/fi/FEATURES.md) | 🇮🇱 [עברית](i18n/he/FEATURES.md) | 🇭🇺 [Magyar](i18n/hu/FEATURES.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/FEATURES.md) | 🇰🇷 [한국어](i18n/ko/FEATURES.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/FEATURES.md) | 🇳🇱 [Nederlands](i18n/nl/FEATURES.md) | 🇳🇴 [Norsk](i18n/no/FEATURES.md) | 🇵🇹 [Português (Portugal)](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) | 🇵🇭 [Filipino](i18n/phi/FEATURES.md)
🌐 **Languages:** 🇺🇸 [English](FEATURES.md) | 🇧🇷 [Português (Brasil)](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) | 🇩🇰 [Dansk](i18n/da/FEATURES.md) | 🇫🇮 [Suomi](i18n/fi/FEATURES.md) | 🇮🇱 [עברית](i18n/he/FEATURES.md) | 🇭🇺 [Magyar](i18n/hu/FEATURES.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/FEATURES.md) | 🇰🇷 [한국어](i18n/ko/FEATURES.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/FEATURES.md) | 🇳🇱 [Nederlands](i18n/nl/FEATURES.md) | 🇳🇴 [Norsk](i18n/no/FEATURES.md) | 🇵🇹 [Português (Portugal)](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) | 🇵🇭 [Filipino](i18n/phi/FEATURES.md) | 🇨🇿 [Čeština](i18n/cs/FEATURES.md)
Visual guide to every section of the OmniRoute dashboard.
@@ -8,7 +8,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).
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.
![Providers Dashboard](screenshots/01-providers.png)
@@ -16,7 +16,7 @@ Manage AI provider connections: OAuth providers (Claude Code, Codex, Gemini CLI)
## 🎨 Combos
Create model routing combos with 6 strategies: fill-first, round-robin, power-of-two-choices, random, least-used, and cost-optimized. Each combo chains multiple models with automatic fallback.
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.
![Combos Dashboard](screenshots/02-combos.png)
@@ -46,9 +46,28 @@ Four modes for debugging API translations: **Playground** (format converter), **
---
## 🎮 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
General settings, system storage, backup management (export/import database), appearance (dark/light mode), security (includes API endpoint protection and custom provider blocking), routing (model aliases, background task degradation), resilience (rate limit persistence), and advanced configuration.
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
- **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
![Settings Dashboard](screenshots/06-settings.png)
@@ -56,12 +75,29 @@ General settings, system storage, backup management (export/import database), ap
## 🔧 CLI Tools
One-click configuration for AI coding tools: Claude Code, Codex CLI, Gemini CLI, OpenClaw, Kilo Code, Antigravity, and **GitHub Copilot** (config generator for `chatLanguageModels.json`).
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 Tools Dashboard](screenshots/07-cli-tools.png)
---
## 🤖 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.
@@ -72,15 +108,27 @@ Real-time request logging with filtering by provider, model, account, and API ke
## 🌐 API Endpoint
Your unified API endpoint with capability breakdown: Chat Completions, Embeddings, Image Generation, Reranking, Audio Transcription, and registered API keys.
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.
![Endpoint Dashboard](screenshots/09-endpoint.png)
---
## 🔑 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, and one-click install.
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:
@@ -88,6 +136,8 @@ Key features:
- 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.
+83
View File
@@ -0,0 +1,83 @@
# 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 |
-113
View File
@@ -1,113 +0,0 @@
# Rate Limiting & Flow Control Overhaul — Tasks
> Referência: [Relatório de Análise](../walkthrough.md) · Fase docs em `/docs/phases/`
---
## Fase 1 — Error Classification & Provider Profiles
### Backend Core
- [x] `constants.ts` — Substituir `COOLDOWN_MS.transient` por `transientInitial` (5s) + `transientMax` (60s)
- [x] `constants.ts` — Adicionar `PROVIDER_PROFILES` (oauth / apikey) com cooldowns diferenciados
- [x] `constants.ts` — Adicionar `DEFAULT_API_LIMITS` (100 RPM, 200ms minTime)
- [x] `providerRegistry.ts` — Criar helper `getProviderCategory(providerId)``"oauth"` | `"apikey"`
- [x] `accountFallback.ts` — Aceitar `provider` como parâmetro em `checkFallbackError`
- [x] `accountFallback.ts` — Implementar backoff exponencial para 502/503/504 transientes
- [x] `accountFallback.ts` — Calcular cooldown baseado no perfil do provedor
- [x] `accountFallback.ts` — Adicionar helper `getProviderProfile(provider)`
### Callers (propagar `provider`)
- [x] `auth.ts``markAccountUnavailable` — Passar `provider` para `checkFallbackError`
- [x] `combo.ts``handleComboChat` / `handleRoundRobinCombo` — Passar `provider` nos erros
### Testes
- [x] Atualizar `rate-limit-enhanced.test.mjs` — Teste "transient errors don't increase backoff" → `newBackoffLevel = 1`
- [x] Criar `error-classification.test.mjs` — Cooldown exponencial 502, perfis OAuth/API, helper `getProviderCategory`
---
## Fase 2 — Circuit Breaker no Combo Pipeline
### Backend
- [x] `combo.ts` — Importar `getCircuitBreaker` e `CircuitBreakerOpenError`
- [x] `combo.ts``handleComboChat` — Verificar `breaker.canExecute()` antes de cada modelo
- [x] `combo.ts``handleRoundRobinCombo` — Integrar breaker per-model
- [x] `combo.ts` — Marcar `semaphore.markRateLimited` para 502/503/504 (não só 429)
- [x] `combo.ts` — Implementar early exit quando todos os modelos têm breaker OPEN
### Testes
- [x] Criar `combo-circuit-breaker.test.mjs` — Combo skip breaker OPEN, early exit, semáforo 502
---
## Fase 3 — Anti-Thundering Herd & Auto Rate Limit
### Backend
- [x] `rateLimitManager.ts` — Auto-enable para `apikey` providers com limites elevados
- [x] `rateLimitManager.ts` — Criar limiter com defaults (100 RPM) quando não configurado
- [x] `auth.ts` — Adicionar mutex na `markAccountUnavailable` para evitar marcação paralela
### Testes
- [x] Criar `thundering-herd.test.mjs` — Mutex, auto-enable, limites não restritivos
---
## Fase 4 — Frontend Resilience UI
### Settings Page
- [x] `settings/page.tsx` — Adicionar tab "Resilience" (icon: `health_and_safety`) entre Routing e Pricing
### Novos Componentes
- [x] Criar `ResilienceTab.tsx` — Layout com 4 cards (Provider Profiles → Rate Limiting → Circuit Breakers → Policies)
- [x] Criar `ProviderProfilesCard.tsx` — Toggle OAuth/API Key, inputs para cooldowns
- [x] Criar `CircuitBreakerCard.tsx` — Status real-time per-provider, auto-refresh 5s, botão reset
- [x] Criar `RateLimitOverviewCard.tsx` — Tabela providers × accounts × cooldown — **agora editável com RPM, Min Gap, Max Concurrent**
### API Routes
- [x] Criar `api/resilience/route.ts` — GET (estado completo + defaults mesclados) + PATCH (salvar perfis + defaults)
- [x] Criar `api/resilience/reset/route.ts` — POST (resetar breakers + cooldowns)
### Migração
- [x] `PoliciesPanel.tsx` movido de Security para Resilience tab
---
## Fase 5 — Settings Page Restructure (v0.9.0)
### Tab Reorganization
- [x] **Security** — Simplificado para Login/Password + IP Access Control
- [x] **Routing** — Expandido para 6 estratégias globais com descrições
- [x] **Resilience** — Reordenado: Provider Profiles → Rate Limiting (editável) → Circuit Breakers → Policies
- [x] **AI** — Thinking Budget + System Prompt + Prompt Cache (movido do Advanced)
- [x] **Advanced** — Simplificado para apenas Global Proxy
### Backend Routing Strategies
- [x] `auth.ts` — Implementar `random` (Fisher-Yates shuffle)
- [x] `auth.ts` — Implementar `least-used` (sorted by lastUsedAt)
- [x] `auth.ts` — Implementar `cost-optimized` (sorted by priority)
- [x] `auth.ts` — Corrigir `p2c` (power-of-two-choices com health scoring)
- [x] `settings.ts` — Expandir tipo `fallbackStrategy` para 6 valores
---
## Verificação Final
- [x] Rodar todos os testes unitários: `node --test tests/unit/*.test.mjs`
- [x] Build do Next.js: `npm run build`
- [x] Verificar aba Resilience no browser
- [x] Testar persistência dos perfis (salvar → reload)
- [x] Testar Reset All Breakers
- [x] Verificar todas as 5 tabs reestruturadas
+1 -1
View File
@@ -1,6 +1,6 @@
# 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)
🌐 **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) | 🇨🇿 [Čeština](i18n/cs/TROUBLESHOOTING.md)
Common problems and solutions for OmniRoute.
+17 -1
View File
@@ -1,6 +1,6 @@
# User Guide
🌐 **Languages:** 🇺🇸 [English](USER_GUIDE.md) | 🇧🇷 [Português (Brasil)](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) | 🇩🇰 [Dansk](i18n/da/USER_GUIDE.md) | 🇫🇮 [Suomi](i18n/fi/USER_GUIDE.md) | 🇮🇱 [עברית](i18n/he/USER_GUIDE.md) | 🇭🇺 [Magyar](i18n/hu/USER_GUIDE.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/USER_GUIDE.md) | 🇰🇷 [한국어](i18n/ko/USER_GUIDE.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/USER_GUIDE.md) | 🇳🇱 [Nederlands](i18n/nl/USER_GUIDE.md) | 🇳🇴 [Norsk](i18n/no/USER_GUIDE.md) | 🇵🇹 [Português (Portugal)](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) | 🇵🇭 [Filipino](i18n/phi/USER_GUIDE.md)
🌐 **Languages:** 🇺🇸 [English](USER_GUIDE.md) | 🇧🇷 [Português (Brasil)](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) | 🇩🇰 [Dansk](i18n/da/USER_GUIDE.md) | 🇫🇮 [Suomi](i18n/fi/USER_GUIDE.md) | 🇮🇱 [עברית](i18n/he/USER_GUIDE.md) | 🇭🇺 [Magyar](i18n/hu/USER_GUIDE.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/USER_GUIDE.md) | 🇰🇷 [한국어](i18n/ko/USER_GUIDE.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/USER_GUIDE.md) | 🇳🇱 [Nederlands](i18n/nl/USER_GUIDE.md) | 🇳🇴 [Norsk](i18n/no/USER_GUIDE.md) | 🇵🇹 [Português (Portugal)](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) | 🇵🇭 [Filipino](i18n/phi/USER_GUIDE.md) | 🇨🇿 [Čeština](i18n/cs/USER_GUIDE.md)
Complete guide for configuring providers, creating combos, integrating CLI tools, and deploying OmniRoute.
@@ -578,6 +578,22 @@ Configure via **Dashboard → Settings → Routing**.
| **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:
+107 -105
View File
@@ -1,69 +1,71 @@
# OmniRoute — Guia de Deploy em VM com Cloudflare
# OmniRoute — Deployment Guide on VM with Cloudflare
Guia completo para instalar e configurar o OmniRoute em uma VM (VPS) com domínio gerenciado via Cloudflare.
🌐 **Languages:** 🇺🇸 [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)
Complete guide to install and configure OmniRoute on a VM (VPS) with domain managed via Cloudflare.
---
## Pré-Requisitos
## Prerequisites
| Item | Mínimo | Recomendado |
| ----------- | ------------------------ | ---------------- |
| **CPU** | 1 vCPU | 2 vCPU |
| **RAM** | 1 GB | 2 GB |
| **Disco** | 10 GB SSD | 25 GB SSD |
| **SO** | Ubuntu 22.04 LTS | Ubuntu 24.04 LTS |
| **Domínio** | Registrado no Cloudflare | — |
| **Docker** | Docker Engine 24+ | Docker 27+ |
| 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+ |
**Providers testados**: Akamai (Linode), DigitalOcean, Vultr, Hetzner, AWS Lightsail.
**Tested providers**: Akamai (Linode), DigitalOcean, Vultr, Hetzner, AWS Lightsail.
---
## 1. Configurar a VM
## 1. Configure the VM
### 1.1 Criar a instância
### 1.1 Create the instance
No seu provider de VPS preferido:
On your preferred VPS provider:
- Escolha Ubuntu 24.04 LTS
- Selecione o plano mínimo (1 vCPU / 1 GB RAM)
- Defina uma senha forte para root ou configure SSH key
- Anote o **IP público** (ex: `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 Conectar via SSH
### 1.2 Connect via SSH
```bash
ssh root@203.0.113.10
```
### 1.3 Atualizar o sistema
### 1.3 Update the system
```bash
apt update && apt upgrade -y
```
### 1.4 Instalar Docker
### 1.4 Install Docker
```bash
# Instalar dependências
# Install dependencies
apt install -y ca-certificates curl gnupg
# Adicionar repositório oficial do Docker
# 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
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
### 1.5 Install nginx
```bash
apt install -y nginx
```
### 1.6 Configurar Firewall (UFW)
### 1.6 Configure Firewall (UFW)
```bash
ufw default deny incoming
@@ -74,29 +76,29 @@ ufw allow 443/tcp # HTTPS
ufw enable
```
> **Dica**: Para segurança máxima, restrinja as portas 80 e 443 apenas para IPs da Cloudflare. Veja a seção [Segurança Avançada](#segurança-avançada).
> **Tip**: For maximum security, restrict ports 80 and 443 to Cloudflare IPs only. See the [Advanced Security](#advanced-security) section.
---
## 2. Instalar o OmniRoute
## 2. Install OmniRoute
### 2.1 Criar diretório de configuração
### 2.1 Create configuration directory
```bash
mkdir -p /opt/omniroute
```
### 2.2 Criar arquivo de variáveis de ambiente
### 2.2 Create environment variables file
```bash
cat > /opt/omniroute/.env << 'EOF'
# === Segurança ===
JWT_SECRET=ALTERE-PARA-CHAVE-SECRETA-UNICA-64-CHARS
INITIAL_PASSWORD=SuaSenhaSegura123!
API_KEY_SECRET=ALTERE-PARA-OUTRA-CHAVE-SECRETA
STORAGE_ENCRYPTION_KEY=ALTERE-PARA-TERCEIRA-CHAVE-SECRETA
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=ALTERE-PARA-SALT-UNICO
MACHINE_ID_SALT=CHANGE-TO-A-UNIQUE-SALT
# === App ===
PORT=20128
@@ -108,19 +110,19 @@ ENABLE_REQUEST_LOGS=true
AUTH_COOKIE_SECURE=false
REQUIRE_API_KEY=false
# === Domain (altere para seu domínio) ===
# === Domain (change to your domain) ===
BASE_URL=https://llms.seudominio.com
NEXT_PUBLIC_BASE_URL=https://llms.seudominio.com
# === Cloud Sync (opcional) ===
# === Cloud Sync (optional) ===
# CLOUD_URL=https://cloud.omniroute.online
# NEXT_PUBLIC_CLOUD_URL=https://cloud.omniroute.online
EOF
```
> ⚠️ **IMPORTANTE**: Gere chaves secretas únicas! Use `openssl rand -hex 32` para cada chave.
> ⚠️ **IMPORTANT**: Generate unique secret keys! Use `openssl rand -hex 32` for each key.
### 2.3 Iniciar o container
### 2.3 Start the container
```bash
docker pull diegosouzapw/omniroute:latest
@@ -134,45 +136,45 @@ docker run -d \
diegosouzapw/omniroute:latest
```
### 2.4 Verificar se está rodando
### 2.4 Verify that it is running
```bash
docker ps | grep omniroute
docker logs omniroute --tail 20
```
Deve exibir: `[DB] SQLite database ready` e `listening on port 20128`.
It should display: `[DB] SQLite database ready` and `listening on port 20128`.
---
## 3. Configurar nginx (Reverse Proxy)
## 3. Configure nginx (Reverse Proxy)
### 3.1 Gerar certificado SSL (Cloudflare Origin)
### 3.1 Generate SSL certificate (Cloudflare Origin)
No painel da Cloudflare:
In the Cloudflare dashboard:
1. Vá em **SSL/TLS → Origin Server**
2. Clique **Create Certificate**
3. Deixe os padrões (15 anos, \*.seudominio.com)
4. Copie o **Origin Certificate** e a **Private Key**
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
# Colar o certificado
# Paste the certificate
nano /etc/nginx/ssl/origin.crt
# Colar a chave privada
# Paste the private key
nano /etc/nginx/ssl/origin.key
chmod 600 /etc/nginx/ssl/origin.key
```
### 3.2 Configuração do nginx
### 3.2 Nginx Configuration
```bash
cat > /etc/nginx/sites-available/omniroute << 'NGINX'
# Default server — bloqueia acesso direto por IP
cat > /etc/nginx/sites-available/omniroute << NGINX
# Default server — blocks direct access via IP
server {
listen 80 default_server;
listen [::]:80 default_server;
@@ -188,7 +190,7 @@ server {
server {
listen 443 ssl;
listen [::]:443 ssl;
server_name llms.seudominio.com; # Altere para seu domínio
server_name llms.yourdomain.com; # Change to your domain
ssl_certificate /etc/nginx/ssl/origin.crt;
ssl_certificate_key /etc/nginx/ssl/origin.key;
@@ -206,7 +208,7 @@ server {
# WebSocket support
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Connection upgrade;
# SSE (Server-Sent Events) — streaming AI responses
proxy_buffering off;
@@ -220,61 +222,61 @@ server {
server {
listen 80;
listen [::]:80;
server_name llms.seudominio.com;
server_name llms.yourdomain.com;
return 301 https://$server_name$request_uri;
}
NGINX
```
### 3.3 Ativar e testar
### 3.3 Enable and Test
```bash
# Remover config padrão
# Remove default configuration
rm -f /etc/nginx/sites-enabled/default
# Ativar OmniRoute
# Enable OmniRoute
ln -sf /etc/nginx/sites-available/omniroute /etc/nginx/sites-enabled/omniroute
# Testar e recarregar
# Test and reload
nginx -t && systemctl reload nginx
```
---
## 4. Configurar Cloudflare DNS
## 4. Configure Cloudflare DNS
### 4.1 Adicionar registro DNS
### 4.1 Add DNS record
No painel da Cloudflare → DNS:
In the Cloudflare dashboard → DNS:
| Type | Name | Content | Proxy |
| ---- | ------ | ------------------------- | ---------- |
| A | `llms` | `203.0.113.10` (IP da VM) | ✅ Proxied |
| Type | Name | Content | Proxy |
| ---- | ------ | ---------------------- | ---------- |
| A | `llms` | `203.0.113.10` (VM IP) | ✅ Proxied |
### 4.2 Configurar SSL
### 4.2 Configure SSL
Em **SSL/TLS → Overview**:
Under **SSL/TLS → Overview**:
- Modo: **Full (Strict)**
- Mode: **Full (Strict)**
Em **SSL/TLS → Edge Certificates**:
Under **SSL/TLS → Edge Certificates**:
- Always Use HTTPS: ✅ On
- Minimum TLS Version: TLS 1.2
- Automatic HTTPS Rewrites: ✅ On
### 4.3 Testar
### 4.3 Testing
```bash
curl -sI https://llms.seudominio.com/health
# Deve retornar HTTP/2 200
# Should return HTTP/2 200
```
---
## 5. Operações e Manutenção
## 5. Operations and Maintenance
### Atualizar para nova versão
### Upgrade to a new version
```bash
docker pull diegosouzapw/omniroute:latest
@@ -286,42 +288,42 @@ docker run -d --name omniroute --restart unless-stopped \
diegosouzapw/omniroute:latest
```
### Ver logs
### View logs
```bash
docker logs -f omniroute # Stream em tempo real
docker logs omniroute --tail 50 # Últimas 50 linhas
docker logs -f omniroute # Real-time stream
docker logs omniroute --tail 50 # Last 50 lines
```
### Backup manual do banco
### Manual database backup
```bash
# Copiar dados do volume para o host
# Copy data from the volume to the host
docker cp omniroute:/app/data ./backup-$(date +%F)
# Ou comprimir todo o volume
# 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 de backup
### 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 /"
alpine sh -c rm -rf /data/* && tar xzf /backup/omniroute-data-YYYY-MM-DD.tar.gz -C /
docker start omniroute
```
---
## 6. Segurança Avançada
## 6. Advanced Security
### Restringir nginx para Cloudflare IPs
### Restrict nginx to Cloudflare IPs
```bash
cat > /etc/nginx/cloudflare-ips.conf << 'CF'
# Cloudflare IPv4 ranges — atualizar periodicamente
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;
@@ -342,7 +344,7 @@ real_ip_header CF-Connecting-IP;
CF
```
Adicionar no `nginx.conf` dentro do bloco `http {}`:
Add the following to `nginx.conf` inside the `http {}` block:
```nginx
include /etc/nginx/cloudflare-ips.conf;
@@ -355,45 +357,45 @@ apt install -y fail2ban
systemctl enable fail2ban
systemctl start fail2ban
# Verificar status
# Check status
fail2ban-client status sshd
```
### Bloquear acesso direto na porta do Docker
### Block direct access to the Docker port
```bash
# Impedir acesso externo direto à porta 20128
# 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
# Persistir as regras
# Persist the rules
apt install -y iptables-persistent
netfilter-persistent save
```
---
## 7. Deploy do Cloud Worker (Opcional)
## 7. Deploy to Cloudflare Workers (Optional)
Para acesso remoto via Cloudflare Workers (sem expor a VM diretamente):
For remote access via Cloudflare Workers (without exposing the VM directly):
```bash
# No repositório local
# In the local repository
cd omnirouteCloud
npm install
npx wrangler login
npx wrangler deploy
```
Ver documentação completa em [omnirouteCloud/README.md](../omnirouteCloud/README.md).
See the full documentation at [omnirouteCloud/README.md](../omnirouteCloud/README.md).
---
## Resumo de Portas
## Port Summary
| Porta | Serviço | Acesso |
| ----- | ----------- | ----------------------------- |
| 22 | SSH | Público (com fail2ban) |
| 80 | nginx HTTP | Redirect → HTTPS |
| 443 | nginx HTTPS | Via Cloudflare Proxy |
| 20128 | OmniRoute | Somente localhost (via nginx) |
| 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) |
@@ -0,0 +1,46 @@
# 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.
@@ -0,0 +1,32 @@
# 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`.
@@ -0,0 +1,16 @@
# 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.
-37
View File
@@ -1,37 +0,0 @@
# ADR-001: Next.js as the Foundation for an AI Gateway
## Status: Accepted
## Context
OmniRoute is an AI routing gateway that translates, forwards, and manages requests across 20+ LLM providers. We needed a framework that could serve both the API proxy layer and a management dashboard from a single codebase.
**Alternatives considered:**
- **Express.js only** — Simpler proxy, but requires separate frontend tooling
- **Fastify** — Fast, but no built-in SSR/dashboard support
- **Next.js** — Unified full-stack framework with API routes, SSR, and static pages
## Decision
We chose Next.js because:
1. **Single deployment** — API routes (`/api/*`) and dashboard UI in one process
2. **Middleware layer** — Native request interception for auth guards and request tracing
3. **File-based routing** — Easy to map provider endpoints to handlers
4. **Built-in TypeScript** — Type safety across the entire codebase
## Consequences
**Positive:**
- One `npm run build` produces both API and UI
- Middleware provides centralized auth and request tracing
- Dashboard gets automatic code splitting and optimization
**Negative:**
- Next.js middleware has limitations (no heavy imports, edge runtime constraints)
- Serverless deployment model doesn't align with persistent WebSocket/SSE connections
- Build times are longer than Express-only setups
- The SSE proxy layer (`open-sse/`) operates outside Next.js conventions
-37
View File
@@ -1,37 +0,0 @@
# ADR-002: Hub-and-Spoke Translation with OpenAI as Intermediate Format
## Status: Accepted
## Context
OmniRoute routes requests across 20+ providers, each with its own API format (OpenAI, Anthropic Messages, Google Gemini, AWS Bedrock, etc.). Direct provider-to-provider translation would require O(n²) translators.
**Alternatives considered:**
- **Direct translation** — Each pair needs a dedicated translator (n² complexity)
- **Common intermediate format** — Translate to/from a canonical format (2n complexity)
- **Protocol buffers** — Strong typing but heavy overhead for a proxy
## Decision
We use the **OpenAI Chat Completions format** as the canonical intermediate representation. All incoming requests are normalized to OpenAI format, processed, then translated to the target provider's format.
```
Client → [any format] → OpenAI canonical → [target format] → Provider
Provider → [response] → OpenAI canonical → [original format] → Client
```
## Consequences
**Positive:**
- Only 2 translators per provider (inbound + outbound) instead of n² pairs
- OpenAI format is the de facto standard — most clients already use it
- Adding a new provider requires only implementing one translator pair
- Streaming (SSE) works consistently through the canonical format
**Negative:**
- Some provider-specific features may be lost in translation
- The double translation adds latency (typically < 5ms)
- OpenAI format changes require updating the canonical representation
-39
View File
@@ -1,39 +0,0 @@
# ADR-003: Dual Storage — SQLite Primary with JSON Migration Path
## Status: Accepted
## Context
OmniRoute originally used LowDB (JSON file) for all persistence. As the project grew, JSON-based storage became a bottleneck for concurrent access, querying, and data integrity.
**Alternatives considered:**
- **LowDB only** — Simple but no concurrent access, no ACID, no querying
- **SQLite only** — Fast, ACID-compliant, but breaks existing deployments
- **PostgreSQL** — Production-grade but requires external dependency
- **Dual storage with migration** — SQLite primary + automatic JSON migration
## Decision
We migrated to **SQLite as the primary store** with an automatic one-time migration from `db.json`:
1. On startup, if `db.json` exists and SQLite is empty, auto-migrate all data
2. All new reads/writes go through SQLite
3. The `db.json` file is preserved but no longer written to
Settings remain in a hybrid model where LowDB handles simple key-value configuration for backward compatibility.
## Consequences
**Positive:**
- ACID transactions for provider connections, API keys, and usage data
- Proper SQL queries for analytics and log filtering
- Concurrent read/write safety via WAL mode
- Zero-downtime migration from JSON — users upgrade transparently
**Negative:**
- Two storage engines to maintain (SQLite + LowDB for settings)
- Migration code must handle edge cases and partial data
- SQLite binary dependency needed in deployment environments
-36
View File
@@ -1,36 +0,0 @@
# Task 01 — Home Page (Dashboard)
**Status:** `[ ]` Não iniciado
**Namespace JSON:** `home`
## Arquivos
| Arquivo | Linhas | Strings |
|---------|--------|---------|
| `src/app/(dashboard)/dashboard/page.tsx` | 17 | 0 (wrapper) |
| `src/app/(dashboard)/dashboard/HomePageClient.tsx` | 500 | ~25 |
## Strings a Traduzir
### HomePageClient.tsx
| Linha | String EN | Chave i18n | String PT-BR |
|-------|-----------|------------|--------------|
| 138 | "Quick Start" | `home.quickStart` | "Início Rápido" |
| 242 | "Providers Overview" | `home.providersOverview` | "Visão Geral dos Provedores" |
| 436 | "No models available for this provider." | `home.noModelsAvailable` | "Nenhum modelo disponível para este provedor." |
| — | "Total Requests" | `home.totalRequests` | "Total de Requisições" |
| — | "Active Providers" | `home.activeProviders` | "Provedores Ativos" |
| — | "Success Rate" | `home.successRate` | "Taxa de Sucesso" |
| — | "Avg Latency" | `home.avgLatency` | "Latência Média" |
| — | "Configure Endpoint" | `home.configureEndpoint` | "Configurar Endpoint" |
| — | "Add Provider" | `home.addProvider` | "Adicionar Provedor" |
| — | "View Docs" | `home.viewDocs` | "Ver Documentação" |
| — | "Copied!" | `common.copied` | ✅ já existe |
| — | "requests" | `home.requests` | "requisições" |
| — | "models" | `home.models` | "modelos" |
| — | "accounts" | `home.accounts` | "contas" |
## Checklist
- [ ] Adicionar chaves no `en.json` (namespace `home`)
- [ ] Adicionar traduções no `pt-BR.json`
- [ ] Substituir strings por `t()` no `HomePageClient.tsx`
- [ ] Testar em EN e PT-BR
-25
View File
@@ -1,25 +0,0 @@
# Task 02 — Analytics Page
**Status:** `[ ]` Não iniciado
**Namespace JSON:** `analytics`
## Arquivos
| Arquivo | Linhas | Strings |
|---------|--------|---------|
| `src/app/(dashboard)/dashboard/analytics/page.tsx` | 46 | ~8 |
## Strings a Traduzir
| Linha | String EN | Chave i18n | String PT-BR |
|-------|-----------|------------|--------------|
| 11 | "Monitor your API usage patterns..." | `analytics.overviewDescription` | "Monitore padrões de uso da API..." |
| 13 | "Run evaluation suites to test..." | `analytics.evalsDescription` | "Execute suítes de avaliação..." |
| 24 | "Analytics" | `analytics.title` | "Análises" |
| 32 | "Overview" | `analytics.overview` | "Visão Geral" |
| 33 | "Evals" | `analytics.evals` | "Avaliações" |
## Checklist
- [ ] Adicionar chaves no `en.json`
- [ ] Adicionar traduções no `pt-BR.json`
- [ ] Substituir strings por `t()` em `page.tsx`
- [ ] Testar em EN e PT-BR
-31
View File
@@ -1,31 +0,0 @@
# Task 03 — API Manager Page
**Status:** `[ ]` Não iniciado
**Namespace JSON:** `apiManager`
## Arquivos
| Arquivo | Linhas | Strings |
|---------|--------|---------|
| `src/app/(dashboard)/dashboard/api-manager/ApiManagerPageClient.tsx` | ~400 | ~20 |
## Strings a Traduzir (levantamento parcial — abrir código para completar)
| String EN | Chave i18n | String PT-BR |
|-----------|------------|--------------|
| "API Keys" | `apiManager.title` | "Chaves de API" |
| "Create API Key" | `apiManager.createKey` | "Criar Chave de API" |
| "Name" | `apiManager.name` | "Nome" |
| "Key" | `apiManager.key` | "Chave" |
| "Created" | `apiManager.created` | "Criado em" |
| "Last Used" | `apiManager.lastUsed` | "Último Uso" |
| "Actions" | `apiManager.actions` | "Ações" |
| "Delete" | `common.delete` | ✅ já existe |
| "No API keys found" | `apiManager.noKeys` | "Nenhuma chave de API encontrada" |
| ~11 strings adicionais | — | Levantar no código |
## Checklist
- [ ] Levantar todas as strings do `ApiManagerPageClient.tsx`
- [ ] Adicionar chaves no `en.json`
- [ ] Adicionar traduções no `pt-BR.json`
- [ ] Substituir strings por `t()`
- [ ] Testar em EN e PT-BR
-31
View File
@@ -1,31 +0,0 @@
# Task 04 — Audit Log Page
**Status:** `[ ]` Não iniciado
**Namespace JSON:** `auditLog`
## Arquivos
| Arquivo | Linhas | Strings |
|---------|--------|---------|
| `src/app/(dashboard)/dashboard/audit-log/page.tsx` | 241 | ~12 |
| `src/app/(dashboard)/dashboard/logs/AuditLogTab.tsx` | ~100 | ~3 |
## Strings a Traduzir
| String EN | Chave i18n | String PT-BR |
|-----------|------------|--------------|
| "Audit Log" | `auditLog.title` | "Log de Auditoria" |
| "Search actions..." | `auditLog.searchPlaceholder` | "Buscar ações..." |
| "Action" | `auditLog.action` | "Ação" |
| "Actor" | `auditLog.actor` | "Autor" |
| "Target" | `auditLog.target` | "Alvo" |
| "Details" | `auditLog.details` | "Detalhes" |
| "IP Address" | `auditLog.ipAddress` | "Endereço IP" |
| "Timestamp" | `auditLog.timestamp` | "Data/Hora" |
| "No audit entries found" | `auditLog.noEntries` | "Nenhum registro de auditoria" |
| "Load More" | `auditLog.loadMore` | "Carregar Mais" |
## Checklist
- [ ] Adicionar chaves no `en.json`
- [ ] Adicionar traduções no `pt-BR.json`
- [ ] Substituir strings em `audit-log/page.tsx` e `AuditLogTab.tsx`
- [ ] Testar em EN e PT-BR
-37
View File
@@ -1,37 +0,0 @@
# Task 05 — CLI Tools Page
**Status:** `[ ]` Não iniciado
**Namespace JSON:** `cliTools`
## Arquivos
| Arquivo | Strings |
|---------|---------|
| `cli-tools/components/AntigravityToolCard.tsx` | ~3 |
| `cli-tools/components/ClaudeToolCard.tsx` | ~3 |
| `cli-tools/components/ClineToolCard.tsx` | ~4 |
| `cli-tools/components/CodexToolCard.tsx` | ~3 |
| `cli-tools/components/DefaultToolCard.tsx` | ~3 |
| `cli-tools/components/DroidToolCard.tsx` | ~2 |
| `cli-tools/components/KiloToolCard.tsx` | ~4 |
| `cli-tools/components/OpenClawToolCard.tsx` | ~2 |
## Strings comuns entre Tool Cards
| String EN | Chave i18n | String PT-BR |
|-----------|------------|--------------|
| "Status" | `cliTools.status` | "Status" |
| "Connected" | `cliTools.connected` | "Conectado" |
| "Not Connected" | `cliTools.notConnected` | "Não Conectado" |
| "Configure" | `cliTools.configure` | "Configurar" |
| "Test Connection" | `cliTools.testConnection` | "Testar Conexão" |
| "Models" | `cliTools.models` | "Modelos" |
| "Map Models" | `cliTools.mapModels` | "Mapear Modelos" |
| "Save" | `common.save` | ✅ já existe |
| "Cancel" | `common.cancel` | ✅ já existe |
## Checklist
- [ ] Levantar strings de cada ToolCard
- [ ] Adicionar chaves no `en.json`
- [ ] Adicionar traduções no `pt-BR.json`
- [ ] Substituir por `t()` em cada componente
- [ ] Testar em EN e PT-BR
-34
View File
@@ -1,34 +0,0 @@
# Task 06 — Combos Page
**Status:** `[ ]` Não iniciado
**Namespace JSON:** `combos`
## Arquivos
| Arquivo | Linhas | Strings |
|---------|--------|---------|
| `src/app/(dashboard)/dashboard/combos/page.tsx` | ~1000 | ~20 |
## Strings a Traduzir
| Linha | String EN | Chave i18n | String PT-BR |
|-------|-----------|------------|--------------|
| 207 | "Combos" | `combos.title` | "Combos" |
| 372 | "No models" | `combos.noModels` | "Sem modelos" |
| 747 | "Routing Strategy" | `combos.routingStrategy` | "Estratégia de Roteamento" |
| 791 | "Models" | `combos.models` | "Modelos" |
| 807 | "No models added yet" | `combos.noModelsYet` | "Nenhum modelo adicionado" |
| 922 | "Max Retries" | `combos.maxRetries` | "Máximo de Tentativas" |
| 959 | "Timeout (ms)" | `combos.timeout` | "Timeout (ms)" |
| 977 | "Healthcheck" | `combos.healthcheck` | "Verificação de Saúde" |
| — | "Create Combo" | `combos.create` | "Criar Combo" |
| — | "Edit Combo" | `combos.edit` | "Editar Combo" |
| — | "Delete Combo" | `combos.deleteCombo` | "Excluir Combo" |
| — | "Add Model" | `combos.addModel` | "Adicionar Modelo" |
| — | "Priority" | `combos.priority` | "Prioridade" |
| — | "Fallback" | `combos.fallback` | "Fallback" |
## Checklist
- [ ] Adicionar chaves no `en.json`
- [ ] Adicionar traduções no `pt-BR.json`
- [ ] Substituir strings por `t()` em `combos/page.tsx`
- [ ] Testar em EN e PT-BR
-23
View File
@@ -1,23 +0,0 @@
# Task 07 — Costs Page
**Status:** `[ ]` Não iniciado
**Namespace JSON:** `costs`
## Arquivos
| Arquivo | Linhas | Strings |
|---------|--------|---------|
| `src/app/(dashboard)/dashboard/costs/page.tsx` | ~200 | ~5 |
## Strings a Traduzir
| String EN | Chave i18n | String PT-BR |
|-----------|------------|--------------|
| "Costs" | `costs.title` | "Custos" |
| "Total Cost" | `costs.totalCost` | "Custo Total" |
| "Cost Breakdown" | `costs.breakdown` | "Detalhamento de Custos" |
| "No cost data" | `costs.noData` | "Sem dados de custo" |
## Checklist
- [ ] Levantar strings completas do código
- [ ] Adicionar chaves no `en.json` / `pt-BR.json`
- [ ] Substituir por `t()` e testar
-30
View File
@@ -1,30 +0,0 @@
# Task 08 — Endpoint Page
**Status:** `[ ]` Não iniciado
**Namespace JSON:** `endpoint`
## Arquivos
| Arquivo | Linhas | Strings |
|---------|--------|---------|
| `src/app/(dashboard)/dashboard/endpoint/EndpointPageClient.tsx` | ~750 | ~20 |
## Strings a Traduzir
| Linha | String EN | Chave i18n | String PT-BR |
|-------|-----------|------------|--------------|
| 320 | "API Endpoint" | `endpoint.title` | "Endpoint da API" |
| 403 | "Available Endpoints" | `endpoint.available` | "Endpoints Disponíveis" |
| 561 | "Cloud Proxy" | `endpoint.cloudProxy` | "Proxy na Nuvem" |
| 632 | "Note" | `endpoint.note` | "Nota" |
| 717 | "Warning" | `endpoint.warning` | "Aviso" |
| 740 | "Are you sure you want to disable cloud proxy?" | `endpoint.disableConfirm` | "Tem certeza que deseja desativar o proxy na nuvem?" |
| — | "Copy" | `common.copy` | ✅ já existe |
| — | "Base URL" | `endpoint.baseUrl` | "URL Base" |
| — | "Connected" | `endpoint.connected` | "Conectado" |
| — | "Enable" | `endpoint.enable` | "Ativar" |
| — | "Disable" | `endpoint.disable` | "Desativar" |
## Checklist
- [ ] Levantar strings restantes
- [ ] Adicionar chaves no `en.json` / `pt-BR.json`
- [ ] Substituir por `t()` e testar
-30
View File
@@ -1,30 +0,0 @@
# Task 09 — Health Page
**Status:** `[ ]` Não iniciado
**Namespace JSON:** `health`
## Arquivos
| Arquivo | Linhas | Strings |
|---------|--------|---------|
| `src/app/(dashboard)/dashboard/health/page.tsx` | ~350 | ~15 |
## Strings a Traduzir
| String EN | Chave i18n | String PT-BR |
|-----------|------------|--------------|
| "System Health" | `health.title` | "Saúde do Sistema" |
| "Healthy" | `health.healthy` | "Saudável" |
| "Degraded" | `health.degraded` | "Degradado" |
| "Down" | `health.down` | "Offline" |
| "Uptime" | `health.uptime` | "Tempo Ativo" |
| "Memory" | `health.memory` | "Memória" |
| "CPU" | `health.cpu` | "CPU" |
| "Database" | `health.database` | "Banco de Dados" |
| "Last Check" | `health.lastCheck` | "Última Verificação" |
| "Refresh" | `common.refresh` | ✅ já existe |
| ~5 strings adicionais | — | Levantar |
## Checklist
- [ ] Levantar strings restantes
- [ ] Adicionar chaves / traduções
- [ ] Substituir por `t()` e testar
-24
View File
@@ -1,24 +0,0 @@
# Task 10 — Limits Page
**Status:** `[ ]` Não iniciado
**Namespace JSON:** `limits`
## Arquivos
| Arquivo | Linhas | Strings |
|---------|--------|---------|
| `src/app/(dashboard)/dashboard/limits/page.tsx` | ~150 | ~5 |
## Strings a Traduzir
| String EN | Chave i18n | String PT-BR |
|-----------|------------|--------------|
| "Limits & Quotas" | `limits.title` | "Limites e Cotas" |
| "Rate Limit" | `limits.rateLimit` | "Limite de Taxa" |
| "Provider" | `limits.provider` | "Provedor" |
| "Remaining" | `limits.remaining` | "Restante" |
| "Reset" | `limits.reset` | "Reiniciar" |
## Checklist
- [ ] Levantar strings completas
- [ ] Adicionar chaves / traduções
- [ ] Substituir por `t()` e testar
-24
View File
@@ -1,24 +0,0 @@
# Task 11 — Logs Page
**Status:** `[ ]` Não iniciado
**Namespace JSON:** `logs`
## Arquivos
| Arquivo | Linhas | Strings |
|---------|--------|---------|
| `src/app/(dashboard)/dashboard/logs/` | ~200 | ~5 |
## Strings a Traduzir
| String EN | Chave i18n | String PT-BR |
|-----------|------------|--------------|
| "Logs" | `logs.title` | "Logs" |
| "Request Logs" | `logs.requestLogs` | "Logs de Requisições" |
| "Proxy Logs" | `logs.proxyLogs` | "Logs do Proxy" |
| "Audit Log" | `logs.auditLog` | "Log de Auditoria" |
| "Console" | `logs.console` | "Console" |
## Checklist
- [ ] Levantar strings completas
- [ ] Adicionar chaves / traduções
- [ ] Substituir por `t()` e testar
-26
View File
@@ -1,26 +0,0 @@
# Task 12 — Onboarding Page
**Status:** `[ ]` Não iniciado
**Namespace JSON:** `onboarding`
## Arquivos
| Arquivo | Linhas | Strings |
|---------|--------|---------|
| `src/app/(dashboard)/dashboard/onboarding/page.tsx` | ~300 | ~10 |
## Strings a Traduzir
| String EN | Chave i18n | String PT-BR |
|-----------|------------|--------------|
| "Welcome to OmniRoute" | `onboarding.welcome` | "Bem-vindo ao OmniRoute" |
| "Set Password" | `onboarding.setPassword` | "Definir Senha" |
| "Add Provider" | `onboarding.addProvider` | "Adicionar Provedor" |
| "Get Started" | `onboarding.getStarted` | "Começar" |
| "Skip" | `onboarding.skip` | "Pular" |
| "Next" | `common.next` | ✅ já existe |
| ~4 strings adicionais | — | Levantar |
## Checklist
- [ ] Levantar strings completas
- [ ] Adicionar chaves / traduções
- [ ] Substituir por `t()` e testar
-35
View File
@@ -1,35 +0,0 @@
# Task 13 — Providers Pages
**Status:** `[ ]` Não iniciado
**Namespace JSON:** `providers`
## Arquivos
| Arquivo | Strings |
|---------|---------|
| `providers/page.tsx` | ~5 |
| `providers/[id]/page.tsx` | ~12 |
| `providers/new/page.tsx` | ~3 |
| `providers/components/ModelAvailabilityPanel.tsx` | ~3 |
| `providers/components/ModelAvailabilityBadge.tsx` | ~1 |
## Strings a Traduzir
| String EN | Chave i18n | String PT-BR |
|-----------|------------|--------------|
| "Providers" | `providers.title` | "Provedores" |
| "Add Provider" | `providers.add` | "Adicionar Provedor" |
| "Edit Provider" | `providers.edit` | "Editar Provedor" |
| "Test Connection" | `providers.testConnection` | "Testar Conexão" |
| "Connected" | `providers.connected` | "Conectado" |
| "Disconnected" | `providers.disconnected` | "Desconectado" |
| "Models" | `providers.models` | "Modelos" |
| "Accounts" | `providers.accounts` | "Contas" |
| "Delete Provider" | `providers.deleteProvider` | "Excluir Provedor" |
| "No providers configured" | `providers.noProviders` | "Nenhum provedor configurado" |
| "Model Availability" | `providers.modelAvailability` | "Disponibilidade de Modelos" |
| ~9 strings adicionais | — | Levantar |
## Checklist
- [ ] Levantar strings completas de todos os arquivos
- [ ] Adicionar chaves / traduções
- [ ] Substituir por `t()` e testar
-51
View File
@@ -1,51 +0,0 @@
# Task 14 — Settings Page (MAIOR TAREFA)
**Status:** `[ ]` Não iniciado
**Namespace JSON:** `settings`
## Arquivos (20 componentes!)
| Arquivo | Strings |
|---------|---------|
| `settings/components/AppearanceTab.tsx` | ~4 |
| `settings/components/CacheStatsCard.tsx` | ~4 |
| `settings/components/ComboDefaultsTab.tsx` | ~8 |
| `settings/components/FallbackChainsEditor.tsx` | ~2 |
| `settings/components/IPFilterSection.tsx` | ~2 |
| `settings/components/PoliciesPanel.tsx` | ~5 |
| `settings/components/PricingTab.tsx` | ~8 |
| `settings/components/ProxyTab.tsx` | ~2 |
| `settings/components/ResilienceTab.tsx` | ~7 |
| `settings/components/RoutingTab.tsx` | ~4 |
| `settings/components/SecurityTab.tsx` | ~5 |
| `settings/components/SessionInfoCard.tsx` | ~5 |
| `settings/components/SystemPromptTab.tsx` | ~2 |
| `settings/components/SystemStorageTab.tsx` | ~8 |
| `settings/components/ThinkingBudgetTab.tsx` | ~5 |
| `settings/pricing/page.tsx` | ~17 |
## Strings a Traduzir (amostra)
| String EN | Chave i18n | String PT-BR |
|-----------|------------|--------------|
| "General" | `settings.general` | "Geral" |
| "Security" | `settings.security` | "Segurança" |
| "Appearance" | `settings.appearance` | "Aparência" |
| "Routing" | `settings.routing` | "Roteamento" |
| "Cache" | `settings.cache` | "Cache" |
| "Resilience" | `settings.resilience` | "Resiliência" |
| "System Prompt" | `settings.systemPrompt` | "Prompt do Sistema" |
| "Thinking Budget" | `settings.thinkingBudget` | "Orçamento de Raciocínio" |
| "Proxy" | `settings.proxy` | "Proxy" |
| "Pricing" | `settings.pricing` | "Preços" |
| "Storage" | `settings.storage` | "Armazenamento" |
| "Policies" | `settings.policies` | "Políticas" |
| "IP Filter" | `settings.ipFilter` | "Filtro de IP" |
| "Combo Defaults" | `settings.comboDefaults` | "Padrões de Combo" |
| "Fallback Chains" | `settings.fallbackChains` | "Cadeias de Fallback" |
| ~40 strings adicionais | — | Levantar em cada tab |
## Checklist
- [ ] Levantar strings de CADA componente (16 arquivos)
- [ ] Adicionar chaves / traduções
- [ ] Substituir por `t()` em todos os 16 arquivos
- [ ] Testar cada aba em EN e PT-BR
-41
View File
@@ -1,41 +0,0 @@
# Task 15 — Translator Page
**Status:** `[ ]` Não iniciado
**Namespace JSON:** `translator`
## Arquivos
| Arquivo | Strings |
|---------|---------|
| `translator/components/LiveMonitorMode.tsx` | ~11 |
| `translator/components/PlaygroundMode.tsx` | ~5 |
| `translator/components/TestBenchMode.tsx` | ~3 |
| `translator/components/ChatTesterMode.tsx` | ~4 |
## Strings a Traduzir
| String EN | Chave i18n | String PT-BR |
|-----------|------------|--------------|
| "Real-Time Translation Activity" | `translator.realtime` | "Atividade de Tradução em Tempo Real" |
| "Chat Tester" | `translator.chatTester` | "Testador de Chat" |
| "Test Bench" | `translator.testBench` | "Bancada de Testes" |
| "Recent Translations" | `translator.recentTranslations` | "Traduções Recentes" |
| "No translations yet" | `translator.noTranslations` | "Nenhuma tradução ainda" |
| "Time" | `translator.time` | "Tempo" |
| "Source" | `translator.source` | "Origem" |
| "Target" | `translator.target` | "Destino" |
| "Model" | `translator.model` | "Modelo" |
| "Status" | `translator.status` | "Status" |
| "Latency" | `translator.latency` | "Latência" |
| "Format Converter" | `translator.formatConverter` | "Conversor de Formato" |
| "Input" | `translator.input` | "Entrada" |
| "Output" | `translator.output` | "Saída" |
| "Example Templates" | `translator.exampleTemplates` | "Modelos de Exemplo" |
| "Compatibility Tester" | `translator.compatibilityTester` | "Testador de Compatibilidade" |
| "Compatibility Report" | `translator.compatibilityReport` | "Relatório de Compatibilidade" |
| "Pipeline Debugger" | `translator.pipelineDebugger` | "Depurador de Pipeline" |
| "Translation Pipeline" | `translator.translationPipeline` | "Pipeline de Tradução" |
## Checklist
- [ ] Adicionar chaves / traduções
- [ ] Substituir por `t()` em cada componente
- [ ] Testar em EN e PT-BR
-57
View File
@@ -1,57 +0,0 @@
# Task 16 — Usage Page
**Status:** `[ ]` Não iniciado
**Namespace JSON:** `usage`
## Arquivos
| Arquivo | Strings |
|---------|---------|
| `usage/components/BudgetTab.tsx` | ~4 |
| `usage/components/BudgetTelemetryCards.tsx` | ~9 |
| `usage/components/EvalsTab.tsx` | ~6 |
| `usage/components/RateLimitStatus.tsx` | ~2 |
| `usage/components/SessionsTab.tsx` | ~7 |
| `usage/components/ProviderLimits/index.tsx` | ~7 |
| `usage/components/ProviderLimits/ProviderLimitCard.tsx` | ~1 |
| `usage/components/ProviderLimits/QuotaTable.tsx` | ~1 |
## Strings a Traduzir
| String EN | Chave i18n | String PT-BR |
|-----------|------------|--------------|
| "Budget Management" | `usage.budgetManagement` | "Gerenciamento de Orçamento" |
| "API Key" | `usage.apiKey` | "Chave de API" |
| "This Month" | `usage.thisMonth` | "Este Mês" |
| "Set Limits" | `usage.setLimits` | "Definir Limites" |
| "Total requests" | `usage.totalRequests` | "Total de requisições" |
| "No data yet" | `usage.noData` | "Sem dados ainda" |
| "Entries" | `usage.entries` | "Entradas" |
| "Hit Rate" | `usage.hitRate` | "Taxa de Acerto" |
| "Circuit Breakers" | `usage.circuitBreakers` | "Disjuntores" |
| "Locked IPs" | `usage.lockedIPs` | "IPs Bloqueados" |
| "How It Works" | `usage.howItWorks` | "Como Funciona" |
| "Define" | `usage.define` | "Definir" |
| "Run" | `usage.run` | "Executar" |
| "Evaluate" | `usage.evaluate` | "Avaliar" |
| "Evaluation Suites" | `usage.evalSuites` | "Suítes de Avaliação" |
| "Model Evaluations" | `usage.modelEvals` | "Avaliações de Modelos" |
| "Model Lockouts" | `usage.modelLockouts` | "Bloqueios de Modelo" |
| "No models currently locked" | `usage.noLockouts` | "Nenhum modelo bloqueado" |
| "Active Sessions" | `usage.activeSessions` | "Sessões Ativas" |
| "No active sessions" | `usage.noSessions` | "Sem sessões ativas" |
| "Session" | `usage.session` | "Sessão" |
| "Age" | `usage.age` | "Idade" |
| "Requests" | `usage.requests` | "Requisições" |
| "Connection" | `usage.connection` | "Conexão" |
| "Provider Limits" | `usage.providerLimits` | "Limites do Provedor" |
| "No Providers Connected" | `usage.noProviders` | "Nenhum Provedor Conectado" |
| "Account" | `usage.account` | "Conta" |
| "Model Quotas" | `usage.modelQuotas` | "Cotas de Modelo" |
| "Last Used" | `usage.lastUsed` | "Último Uso" |
| "Actions" | `usage.actions` | "Ações" |
| "No quota data" | `usage.noQuota` | "Sem dados de cota" |
## Checklist
- [ ] Adicionar chaves / traduções
- [ ] Substituir por `t()` em cada componente
- [ ] Testar em EN e PT-BR
-44
View File
@@ -1,44 +0,0 @@
# Task 17 — Shared Modals
**Status:** `[ ]` Não iniciado
**Namespace JSON:** `modals`
## Arquivos
| Arquivo | Strings |
|---------|---------|
| `shared/components/OAuthModal.tsx` | ~6 |
| `shared/components/KiroAuthModal.tsx` | ~10 |
| `shared/components/KiroSocialOAuthModal.tsx` | ~3 |
| `shared/components/CursorAuthModal.tsx` | ~2 |
| `shared/components/PricingModal.tsx` | ~10 |
| `shared/components/ModelSelectModal.tsx` | ~2 |
| `shared/components/ProxyConfigModal.tsx` | ~1 |
## Strings a Traduzir
| String EN | String PT-BR |
|-----------|--------------|
| "Waiting for Authorization" | "Aguardando Autorização" |
| "Verification URL" | "URL de Verificação" |
| "Your Code" | "Seu Código" |
| "Remote access:" | "Acesso remoto:" |
| "Connected Successfully!" | "Conectado com Sucesso!" |
| "Connection Failed" | "Falha na Conexão" |
| "Choose your authentication method:" | "Escolha seu método de autenticação:" |
| "AWS Builder ID" | "AWS Builder ID" |
| "AWS IAM Identity Center" | "AWS IAM Identity Center" |
| "Google Account" | "Conta Google" |
| "GitHub Account" | "Conta GitHub" |
| "Import Token" | "Importar Token" |
| "Auto-detecting tokens..." | "Detectando tokens automaticamente..." |
| "Pricing Configuration" | "Configuração de Preços" |
| "Loading pricing data..." | "Carregando dados de preços..." |
| "Model" / "Input" / "Output" / "Cached" | "Modelo" / "Entrada" / "Saída" / "Em Cache" |
| "Combos" | "Combos" |
| "No models found" | "Nenhum modelo encontrado" |
| "Connected" | "Conectado" |
## Checklist
- [ ] Adicionar chaves / traduções
- [ ] Substituir por `t()` em cada modal
- [ ] Testar cada modal em EN e PT-BR
-37
View File
@@ -1,37 +0,0 @@
# Task 18 — Shared Loggers
**Status:** `[ ]` Não iniciado
**Namespace JSON:** `loggers`
## Arquivos
| Arquivo | Strings |
|---------|---------|
| `shared/components/RequestLoggerV2.tsx` | ~12 |
| `shared/components/RequestLoggerDetail.tsx` | ~4 |
| `shared/components/ProxyLogger.tsx` | ~7 |
| `shared/components/ProxyLogDetail.tsx` | ~6 |
| `shared/components/ConsoleLogViewer.tsx` | ~2 |
## Strings a Traduzir
| String EN | String PT-BR |
|-----------|--------------|
| "All Providers" | "Todos os Provedores" |
| "All Models" | "Todos os Modelos" |
| "All Accounts" | "Todas as Contas" |
| "All API Keys" | "Todas as Chaves de API" |
| "Newest" / "Oldest" | "Mais Recente" / "Mais Antigo" |
| "Model A-Z" / "Model Z-A" | "Modelo A-Z" / "Modelo Z-A" |
| "Columns" | "Colunas" |
| "Loading logs..." | "Carregando logs..." |
| "All Types" | "Todos os Tipos" |
| "All Levels" | "Todos os Níveis" |
| "Proxy Event" | "Evento do Proxy" |
| "Time" / "Model" / "Combo" | "Tempo" / "Modelo" / "Combo" |
| "No log entries found" | "Nenhuma entrada de log encontrada" |
| "No payload data available" | "Nenhum dado de payload disponível" |
## Checklist
- [ ] Adicionar chaves / traduções
- [ ] Substituir por `t()` em cada logger
- [ ] Testar em EN e PT-BR
-36
View File
@@ -1,36 +0,0 @@
# Task 19 — Shared Charts & Stats
**Status:** `[ ]` Não iniciado
**Namespace JSON:** `stats`
## Arquivos
| Arquivo | Strings |
|---------|---------|
| `shared/components/UsageStats.tsx` | ~6 |
| `shared/components/analytics/charts.tsx` | ~15 |
| `shared/components/TokenHealthBadge.tsx` | ~6 |
| `shared/components/SystemMonitor.tsx` | ~1 |
| `shared/components/Footer.tsx` | ~3 |
## Strings a Traduzir
| String EN | String PT-BR |
|-----------|--------------|
| "Usage Overview" | "Visão Geral de Uso" |
| "Output Tokens" | "Tokens de Saída" |
| "Total Cost" | "Custo Total" |
| "Usage by Model" | "Uso por Modelo" |
| "Usage by Account" | "Uso por Conta" |
| "Failed to load usage statistics." | "Falha ao carregar estatísticas." |
| "Token Health" | "Saúde dos Tokens" |
| "Total OAuth" | "Total OAuth" |
| "Healthy" / "Errored" / "Warning" | "Saudável" / "Com Erro" / "Aviso" |
| "Last check" | "Última verificação" |
| "No data" / "Share" | "Sem dados" / "Compartilhar" |
| "Unable to load system metrics" | "Não foi possível carregar métricas" |
| "Product" / "Resources" / "Company" (Footer) | "Produto" / "Recursos" / "Empresa" |
## Checklist
- [ ] Adicionar chaves / traduções
- [ ] Substituir por `t()` em cada componente
- [ ] Testar em EN e PT-BR
-36
View File
@@ -1,36 +0,0 @@
# Task 20 — Login & Auth Pages
**Status:** `[ ]` Não iniciado
**Namespace JSON:** `auth`
## Arquivos
| Arquivo | Strings |
|---------|---------|
| `src/app/login/page.tsx` | ~8 |
| `src/app/forgot-password/page.tsx` | ~3 |
| `src/app/callback/page.tsx` | ~5 |
| `src/app/forbidden/page.tsx` | ~1 |
## Strings a Traduzir
| String EN | String PT-BR |
|-----------|--------------|
| "Welcome" | "Bem-vindo" |
| "OmniRoute" | "OmniRoute" (não traduzir) |
| "Sign in" | "Entrar" |
| "Enter your password to continue" | "Digite sua senha para continuar" |
| "Password" | "Senha" |
| "Unified AI API Proxy" | "Proxy Unificado de API de IA" |
| "Loading..." | "Carregando..." |
| "Password protection is not enabled" | "Proteção por senha não está ativada" |
| "Reset Password" | "Redefinir Senha" |
| "Choose a method to recover access" | "Escolha um método para recuperar acesso" |
| "Processing..." | "Processando..." |
| "Authorization Successful!" | "Autorização bem-sucedida!" |
| "Copy This URL" | "Copiar esta URL" |
| "Access Denied" | "Acesso Negado" |
## Checklist
- [ ] Adicionar chaves / traduções
- [ ] Substituir por `t()` em cada página
- [ ] Testar em EN e PT-BR
-34
View File
@@ -1,34 +0,0 @@
# Task 21 — Landing Page
**Status:** `[ ]` Não iniciado
**Namespace JSON:** `landing`
## Arquivos
| Arquivo | Strings |
|---------|---------|
| `landing/components/HeroSection.tsx` | ~3 |
| `landing/components/Features.tsx` | ~10 |
| `landing/components/HowItWorks.tsx` | ~5 |
| `landing/components/GetStarted.tsx` | ~5 |
| `landing/components/Navigation.tsx` | ~2 |
| `landing/components/FlowAnimation.tsx` | ~2 |
| `landing/components/Footer.tsx` | ~5 |
## Strings a Traduzir (amostra)
| String EN | String PT-BR |
|-----------|--------------|
| "All AI Providers" | "Todos os Provedores de IA" |
| "One Endpoint" | "Um Endpoint" |
| "Powerful Features" | "Recursos Poderosos" |
| "How OmniRoute Works" | "Como o OmniRoute Funciona" |
| "Install OmniRoute" | "Instalar o OmniRoute" |
| "Open Dashboard" | "Abrir Painel" |
| "Route Requests" | "Rotear Requisições" |
| "Data Location:" | "Local dos Dados:" |
| "Product" / "Resources" / "Legal" | "Produto" / "Recursos" / "Legal" |
## Checklist
- [ ] Levantar strings completas de cada componente
- [ ] Adicionar chaves / traduções
- [ ] Substituir por `t()` e testar
-32
View File
@@ -1,32 +0,0 @@
# Task 22 — Docs Page
**Status:** `[ ]` Não iniciado
**Namespace JSON:** `docs`
## Arquivos
| Arquivo | Strings |
|---------|---------|
| `src/app/docs/page.tsx` | ~25 |
## Strings a Traduzir
| String EN | String PT-BR |
|-----------|--------------|
| "Quick Start" | "Início Rápido" |
| "Features" | "Recursos" |
| "Supported Providers" | "Provedores Suportados" |
| "Common Use Cases" | "Casos de Uso Comuns" |
| "Client Compatibility" | "Compatibilidade de Clientes" |
| "Cherry Studio" | "Cherry Studio" (não traduzir) |
| "Codex / GitHub Copilot Models" | "Modelos Codex / GitHub Copilot" |
| "Cursor IDE" | "Cursor IDE" (não traduzir) |
| "Claude Code / Antigravity" | "Claude Code / Antigravity" |
| "API Reference" | "Referência da API" |
| "Method" / "Path" / "Notes" | "Método" / "Caminho" / "Notas" |
| "Model Prefixes" | "Prefixos de Modelo" |
| "Prefix" / "Provider" / "Type" | "Prefixo" / "Provedor" / "Tipo" |
| "Troubleshooting" | "Solução de Problemas" |
## Checklist
- [ ] Adicionar chaves / traduções
- [ ] Substituir por `t()` e testar
-31
View File
@@ -1,31 +0,0 @@
# Task 23 — Legal Pages (Privacy & Terms)
**Status:** `[ ]` Não iniciado
**Namespace JSON:** `legal`
## Arquivos
| Arquivo | Strings |
|---------|---------|
| `src/app/privacy/page.tsx` | ~10 |
| `src/app/terms/page.tsx` | ~5 |
## Strings a Traduzir
| String EN | String PT-BR |
|-----------|--------------|
| "Privacy Policy" | "Política de Privacidade" |
| "Terms of Service" | "Termos de Serviço" |
| "Provider configurations" | "Configurações de provedores" |
| "API keys" | "Chaves de API" |
| "Usage logs" | "Logs de uso" |
| "Application settings" | "Configurações do aplicativo" |
| "View and export usage analytics" | "Visualizar e exportar análises de uso" |
| "Clear usage history at any time" | "Limpar histórico de uso a qualquer momento" |
| "Configure log retention policies" | "Configurar políticas de retenção de logs" |
| "Back up and restore your database" | "Fazer backup e restaurar seu banco de dados" |
## Checklist
- [ ] Adicionar chaves / traduções
- [ ] Substituir por `t()` e testar
> **Nota:** Textos legais podem requerer revisão jurídica para tradução formal.
-51
View File
@@ -1,51 +0,0 @@
# i18n Translation Tasks
Cada arquivo `.md` nesta pasta representa **uma tarefa de tradução** para uma página ou componente do OmniRoute.
## Status Legend
- `[ ]` — Não iniciado
- `[/]` — Em progresso
- `[x]` — Concluído
## Dashboard Pages (~260 strings)
| # | Tarefa | Arquivo | Strings | Status |
| --- | ---------------------------------- | ----------------------------------------------------- | ------- | ------ |
| 01 | [Home](./01-home.md) | `HomePageClient.tsx` | ~25 | `[ ]` |
| 02 | [Analytics](./02-analytics.md) | `analytics/page.tsx` | ~8 | `[ ]` |
| 03 | [API Manager](./03-api-manager.md) | `api-manager/` | ~20 | `[ ]` |
| 04 | [Audit Log](./04-audit-log.md) | `audit-log/page.tsx`, `logs/AuditLogTab.tsx` | ~15 | `[ ]` |
| 05 | [CLI Tools](./05-cli-tools.md) | `cli-tools/components/*.tsx` | ~20 | `[ ]` |
| 06 | [Combos](./06-combos.md) | `combos/page.tsx` | ~20 | `[ ]` |
| 07 | [Costs](./07-costs.md) | `costs/page.tsx` | ~5 | `[ ]` |
| 08 | [Endpoint](./08-endpoint.md) | `endpoint/EndpointPageClient.tsx` | ~20 | `[ ]` |
| 09 | [Health](./09-health.md) | `health/page.tsx` | ~15 | `[ ]` |
| 10 | [Limits](./10-limits.md) | `limits/page.tsx` | ~5 | `[ ]` |
| 11 | [Logs](./11-logs.md) | `logs/` | ~5 | `[ ]` |
| 12 | [Onboarding](./12-onboarding.md) | `onboarding/page.tsx` | ~10 | `[ ]` |
| 13 | [Providers](./13-providers.md) | `providers/page.tsx`, `[id]/page.tsx`, `new/page.tsx` | ~20 | `[ ]` |
| 14 | [Settings](./14-settings.md) | `settings/components/*.tsx` | ~55 | `[ ]` |
| 15 | [Translator](./15-translator.md) | `translator/components/*.tsx` | ~25 | `[ ]` |
| 16 | [Usage](./16-usage.md) | `usage/components/*.tsx` | ~35 | `[ ]` |
## Shared Components (~95 strings)
| # | Tarefa | Arquivo(s) | Strings | Status |
| --- | ---------------------------------------------- | ---------------------------------------------------- | ------- | ------ |
| 17 | [Shared Modals](./17-shared-modals.md) | `OAuthModal`, `KiroAuthModal`, `PricingModal`, etc. | ~40 | `[ ]` |
| 18 | [Shared Loggers](./18-shared-loggers.md) | `RequestLoggerV2`, `ProxyLogger`, `ProxyLogDetail` | ~30 | `[ ]` |
| 19 | [Shared Charts & Stats](./19-shared-charts.md) | `UsageStats`, `analytics/charts`, `TokenHealthBadge` | ~25 | `[ ]` |
## Non-Dashboard Pages (~75 strings)
| # | Tarefa | Arquivo(s) | Strings | Status |
| --- | ---------------------------------- | ------------------------------------------------------- | ------- | ------ |
| 20 | [Login & Auth](./20-login-auth.md) | `login/`, `forgot-password/`, `callback/`, `forbidden/` | ~20 | `[ ]` |
| 21 | [Landing Page](./21-landing.md) | `landing/components/*.tsx` | ~25 | `[ ]` |
| 22 | [Docs Page](./22-docs.md) | `docs/page.tsx` | ~25 | `[ ]` |
| 23 | [Legal Pages](./23-legal.md) | `privacy/`, `terms/` | ~15 | `[ ]` |
---
**Total estimado: ~460 strings em 23 tarefas**
+8 -7
View File
@@ -2,11 +2,12 @@
This directory contains machine-assisted translations based on the English docs.
- **API_REFERENCE.md**: 🇺🇸 [English](../API_REFERENCE.md) | 🇧🇷 [Português (Brasil)](./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) | 🇩🇰 [Dansk](./da/API_REFERENCE.md) | 🇫🇮 [Suomi](./fi/API_REFERENCE.md) | 🇮🇱 [עברית](./he/API_REFERENCE.md) | 🇭🇺 [Magyar](./hu/API_REFERENCE.md) | 🇮🇩 [Bahasa Indonesia](./id/API_REFERENCE.md) | 🇰🇷 [한국어](./ko/API_REFERENCE.md) | 🇲🇾 [Bahasa Melayu](./ms/API_REFERENCE.md) | 🇳🇱 [Nederlands](./nl/API_REFERENCE.md) | 🇳🇴 [Norsk](./no/API_REFERENCE.md) | 🇵🇹 [Português (Portugal)](./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) | 🇵🇭 [Filipino](./phi/API_REFERENCE.md)
- **ARCHITECTURE.md**: 🇺🇸 [English](../ARCHITECTURE.md) | 🇧🇷 [Português (Brasil)](./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) | 🇩🇰 [Dansk](./da/ARCHITECTURE.md) | 🇫🇮 [Suomi](./fi/ARCHITECTURE.md) | 🇮🇱 [עברית](./he/ARCHITECTURE.md) | 🇭🇺 [Magyar](./hu/ARCHITECTURE.md) | 🇮🇩 [Bahasa Indonesia](./id/ARCHITECTURE.md) | 🇰🇷 [한국어](./ko/ARCHITECTURE.md) | 🇲🇾 [Bahasa Melayu](./ms/ARCHITECTURE.md) | 🇳🇱 [Nederlands](./nl/ARCHITECTURE.md) | 🇳🇴 [Norsk](./no/ARCHITECTURE.md) | 🇵🇹 [Português (Portugal)](./pt/ARCHITECTURE.md) | 🇷🇴 [Română](./ro/ARCHITECTURE.md) | 🇵🇱 [Polski](./pl/ARCHITECTURE.md) | 🇸🇰 [Slovenčina](./sk/ARCHITECTURE.md) | 🇸🇪 [Svenska](./sv/ARCHITECTURE.md) | 🇵🇭 [Filipino](./phi/ARCHITECTURE.md)
- **CODEBASE_DOCUMENTATION.md**: 🇺🇸 [English](../CODEBASE_DOCUMENTATION.md) | 🇧🇷 [Português (Brasil)](./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) | 🇩🇰 [Dansk](./da/CODEBASE_DOCUMENTATION.md) | 🇫🇮 [Suomi](./fi/CODEBASE_DOCUMENTATION.md) | 🇮🇱 [עברית](./he/CODEBASE_DOCUMENTATION.md) | 🇭🇺 [Magyar](./hu/CODEBASE_DOCUMENTATION.md) | 🇮🇩 [Bahasa Indonesia](./id/CODEBASE_DOCUMENTATION.md) | 🇰🇷 [한국어](./ko/CODEBASE_DOCUMENTATION.md) | 🇲🇾 [Bahasa Melayu](./ms/CODEBASE_DOCUMENTATION.md) | 🇳🇱 [Nederlands](./nl/CODEBASE_DOCUMENTATION.md) | 🇳🇴 [Norsk](./no/CODEBASE_DOCUMENTATION.md) | 🇵🇹 [Português (Portugal)](./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) | 🇵🇭 [Filipino](./phi/CODEBASE_DOCUMENTATION.md)
- **FEATURES.md**: 🇺🇸 [English](../FEATURES.md) | 🇧🇷 [Português (Brasil)](./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) | 🇩🇰 [Dansk](./da/FEATURES.md) | 🇫🇮 [Suomi](./fi/FEATURES.md) | 🇮🇱 [עברית](./he/FEATURES.md) | 🇭🇺 [Magyar](./hu/FEATURES.md) | 🇮🇩 [Bahasa Indonesia](./id/FEATURES.md) | 🇰🇷 [한국어](./ko/FEATURES.md) | 🇲🇾 [Bahasa Melayu](./ms/FEATURES.md) | 🇳🇱 [Nederlands](./nl/FEATURES.md) | 🇳🇴 [Norsk](./no/FEATURES.md) | 🇵🇹 [Português (Portugal)](./pt/FEATURES.md) | 🇷🇴 [Română](./ro/FEATURES.md) | 🇵🇱 [Polski](./pl/FEATURES.md) | 🇸🇰 [Slovenčina](./sk/FEATURES.md) | 🇸🇪 [Svenska](./sv/FEATURES.md) | 🇵🇭 [Filipino](./phi/FEATURES.md)
- **TROUBLESHOOTING.md**: 🇺🇸 [English](../TROUBLESHOOTING.md) | 🇧🇷 [Português (Brasil)](./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) | 🇩🇰 [Dansk](./da/TROUBLESHOOTING.md) | 🇫🇮 [Suomi](./fi/TROUBLESHOOTING.md) | 🇮🇱 [עברית](./he/TROUBLESHOOTING.md) | 🇭🇺 [Magyar](./hu/TROUBLESHOOTING.md) | 🇮🇩 [Bahasa Indonesia](./id/TROUBLESHOOTING.md) | 🇰🇷 [한국어](./ko/TROUBLESHOOTING.md) | 🇲🇾 [Bahasa Melayu](./ms/TROUBLESHOOTING.md) | 🇳🇱 [Nederlands](./nl/TROUBLESHOOTING.md) | 🇳🇴 [Norsk](./no/TROUBLESHOOTING.md) | 🇵🇹 [Português (Portugal)](./pt/TROUBLESHOOTING.md) | 🇷🇴 [Română](./ro/TROUBLESHOOTING.md) | 🇵🇱 [Polski](./pl/TROUBLESHOOTING.md) | 🇸🇰 [Slovenčina](./sk/TROUBLESHOOTING.md) | 🇸🇪 [Svenska](./sv/TROUBLESHOOTING.md) | 🇵🇭 [Filipino](./phi/TROUBLESHOOTING.md)
- **USER_GUIDE.md**: 🇺🇸 [English](../USER_GUIDE.md) | 🇧🇷 [Português (Brasil)](./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) | 🇩🇰 [Dansk](./da/USER_GUIDE.md) | 🇫🇮 [Suomi](./fi/USER_GUIDE.md) | 🇮🇱 [עברית](./he/USER_GUIDE.md) | 🇭🇺 [Magyar](./hu/USER_GUIDE.md) | 🇮🇩 [Bahasa Indonesia](./id/USER_GUIDE.md) | 🇰🇷 [한국어](./ko/USER_GUIDE.md) | 🇲🇾 [Bahasa Melayu](./ms/USER_GUIDE.md) | 🇳🇱 [Nederlands](./nl/USER_GUIDE.md) | 🇳🇴 [Norsk](./no/USER_GUIDE.md) | 🇵🇹 [Português (Portugal)](./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) | 🇵🇭 [Filipino](./phi/USER_GUIDE.md)
- **API_REFERENCE.md**: 🇺🇸 [English](../API_REFERENCE.md) | 🇧🇷 [Português (Brasil)](./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) | 🇩🇰 [Dansk](./da/API_REFERENCE.md) | 🇫🇮 [Suomi](./fi/API_REFERENCE.md) | 🇮🇱 [עברית](./he/API_REFERENCE.md) | 🇭🇺 [Magyar](./hu/API_REFERENCE.md) | 🇮🇩 [Bahasa Indonesia](./id/API_REFERENCE.md) | 🇰🇷 [한국어](./ko/API_REFERENCE.md) | 🇲🇾 [Bahasa Melayu](./ms/API_REFERENCE.md) | 🇳🇱 [Nederlands](./nl/API_REFERENCE.md) | 🇳🇴 [Norsk](./no/API_REFERENCE.md) | 🇵🇹 [Português (Portugal)](./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) | 🇵🇭 [Filipino](./phi/API_REFERENCE.md) | 🇨🇿 [Čeština](./cs/API_REFERENCE.md)
- **ARCHITECTURE.md**: 🇺🇸 [English](../ARCHITECTURE.md) | 🇧🇷 [Português (Brasil)](./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) | 🇩🇰 [Dansk](./da/ARCHITECTURE.md) | 🇫🇮 [Suomi](./fi/ARCHITECTURE.md) | 🇮🇱 [עברית](./he/ARCHITECTURE.md) | 🇭🇺 [Magyar](./hu/ARCHITECTURE.md) | 🇮🇩 [Bahasa Indonesia](./id/ARCHITECTURE.md) | 🇰🇷 [한국어](./ko/ARCHITECTURE.md) | 🇲🇾 [Bahasa Melayu](./ms/ARCHITECTURE.md) | 🇳🇱 [Nederlands](./nl/ARCHITECTURE.md) | 🇳🇴 [Norsk](./no/ARCHITECTURE.md) | 🇵🇹 [Português (Portugal)](./pt/ARCHITECTURE.md) | 🇷🇴 [Română](./ro/ARCHITECTURE.md) | 🇵🇱 [Polski](./pl/ARCHITECTURE.md) | 🇸🇰 [Slovenčina](./sk/ARCHITECTURE.md) | 🇸🇪 [Svenska](./sv/ARCHITECTURE.md) | 🇵🇭 [Filipino](./phi/ARCHITECTURE.md) | 🇨🇿 [Čeština](./cs/ARCHITECTURE.md)
- **CODEBASE_DOCUMENTATION.md**: 🇺🇸 [English](../CODEBASE_DOCUMENTATION.md) | 🇧🇷 [Português (Brasil)](./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) | 🇩🇰 [Dansk](./da/CODEBASE_DOCUMENTATION.md) | 🇫🇮 [Suomi](./fi/CODEBASE_DOCUMENTATION.md) | 🇮🇱 [עברית](./he/CODEBASE_DOCUMENTATION.md) | 🇭🇺 [Magyar](./hu/CODEBASE_DOCUMENTATION.md) | 🇮🇩 [Bahasa Indonesia](./id/CODEBASE_DOCUMENTATION.md) | 🇰🇷 [한국어](./ko/CODEBASE_DOCUMENTATION.md) | 🇲🇾 [Bahasa Melayu](./ms/CODEBASE_DOCUMENTATION.md) | 🇳🇱 [Nederlands](./nl/CODEBASE_DOCUMENTATION.md) | 🇳🇴 [Norsk](./no/CODEBASE_DOCUMENTATION.md) | 🇵🇹 [Português (Portugal)](./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) | 🇵🇭 [Filipino](./phi/CODEBASE_DOCUMENTATION.md) | 🇨🇿 [Čeština](./cs/CODEBASE_DOCUMENTATION.md)
- **FEATURES.md**: 🇺🇸 [English](../FEATURES.md) | 🇧🇷 [Português (Brasil)](./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) | 🇩🇰 [Dansk](./da/FEATURES.md) | 🇫🇮 [Suomi](./fi/FEATURES.md) | 🇮🇱 [עברית](./he/FEATURES.md) | 🇭🇺 [Magyar](./hu/FEATURES.md) | 🇮🇩 [Bahasa Indonesia](./id/FEATURES.md) | 🇰🇷 [한국어](./ko/FEATURES.md) | 🇲🇾 [Bahasa Melayu](./ms/FEATURES.md) | 🇳🇱 [Nederlands](./nl/FEATURES.md) | 🇳🇴 [Norsk](./no/FEATURES.md) | 🇵🇹 [Português (Portugal)](./pt/FEATURES.md) | 🇷🇴 [Română](./ro/FEATURES.md) | 🇵🇱 [Polski](./pl/FEATURES.md) | 🇸🇰 [Slovenčina](./sk/FEATURES.md) | 🇸🇪 [Svenska](./sv/FEATURES.md) | 🇵🇭 [Filipino](./phi/FEATURES.md) | 🇨🇿 [Čeština](./cs/FEATURES.md)
- **TROUBLESHOOTING.md**: 🇺🇸 [English](../TROUBLESHOOTING.md) | 🇧🇷 [Português (Brasil)](./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) | 🇩🇰 [Dansk](./da/TROUBLESHOOTING.md) | 🇫🇮 [Suomi](./fi/TROUBLESHOOTING.md) | 🇮🇱 [עברית](./he/TROUBLESHOOTING.md) | 🇭🇺 [Magyar](./hu/TROUBLESHOOTING.md) | 🇮🇩 [Bahasa Indonesia](./id/TROUBLESHOOTING.md) | 🇰🇷 [한국어](./ko/TROUBLESHOOTING.md) | 🇲🇾 [Bahasa Melayu](./ms/TROUBLESHOOTING.md) | 🇳🇱 [Nederlands](./nl/TROUBLESHOOTING.md) | 🇳🇴 [Norsk](./no/TROUBLESHOOTING.md) | 🇵🇹 [Português (Portugal)](./pt/TROUBLESHOOTING.md) | 🇷🇴 [Română](./ro/TROUBLESHOOTING.md) | 🇵🇱 [Polski](./pl/TROUBLESHOOTING.md) | 🇸🇰 [Slovenčina](./sk/TROUBLESHOOTING.md) | 🇸🇪 [Svenska](./sv/TROUBLESHOOTING.md) | 🇵🇭 [Filipino](./phi/TROUBLESHOOTING.md) | 🇨🇿 [Čeština](./cs/TROUBLESHOOTING.md)
- **USER_GUIDE.md**: 🇺🇸 [English](../USER_GUIDE.md) | 🇧🇷 [Português (Brasil)](./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) | 🇩🇰 [Dansk](./da/USER_GUIDE.md) | 🇫🇮 [Suomi](./fi/USER_GUIDE.md) | 🇮🇱 [עברית](./he/USER_GUIDE.md) | 🇭🇺 [Magyar](./hu/USER_GUIDE.md) | 🇮🇩 [Bahasa Indonesia](./id/USER_GUIDE.md) | 🇰🇷 [한국어](./ko/USER_GUIDE.md) | 🇲🇾 [Bahasa Melayu](./ms/USER_GUIDE.md) | 🇳🇱 [Nederlands](./nl/USER_GUIDE.md) | 🇳🇴 [Norsk](./no/USER_GUIDE.md) | 🇵🇹 [Português (Portugal)](./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) | 🇵🇭 [Filipino](./phi/USER_GUIDE.md) | 🇨🇿 [Čeština](./cs/USER_GUIDE.md)
- **VM_DEPLOYMENT_GUIDE.md**: 🇺🇸 [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)
Generated on 2026-02-26.
Generated on 2026-03-19.
+200
View File
@@ -0,0 +1,200 @@
🌐 **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);
```
+191 -177
View File
@@ -1,12 +1,16 @@
# مرجع واجهة برمجة التطبيقات
🌐 **Languages:** 🇺🇸 [English](../../API_REFERENCE.md) | 🇧🇷 [Português (Brasil)](../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) | 🇩🇰 [Dansk](../da/API_REFERENCE.md) | 🇫🇮 [Suomi](../fi/API_REFERENCE.md) | 🇮🇱 [עברית](../he/API_REFERENCE.md) | 🇭🇺 [Magyar](../hu/API_REFERENCE.md) | 🇮🇩 [Bahasa Indonesia](../id/API_REFERENCE.md) | 🇰🇷 [한국어](../ko/API_REFERENCE.md) | 🇲🇾 [Bahasa Melayu](../ms/API_REFERENCE.md) | 🇳🇱 [Nederlands](../nl/API_REFERENCE.md) | 🇳🇴 [Norsk](../no/API_REFERENCE.md) | 🇵🇹 [Português (Portugal)](../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) | 🇵🇭 [Filipino](../phi/API_REFERENCE.md)
مرجع كامل لجميع نقاط نهاية OmniRoute API.
🌐 **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)
@@ -20,7 +24,7 @@
---
## إكمالات الدردشة
## Chat Completions
```bash
POST /v1/chat/completions
@@ -36,21 +40,21 @@ Content-Type: application/json
}
```
### رؤوس مخصصة
### Custom Headers
| رأس | الاتجاه | الوصف |
| ------------------------ | ------- | ------------------------------------------- |
| `X-OmniRoute-No-Cache` | طلب | اضبط على `true` لتجاوز ذاكرة التخزين المؤقت |
| `X-OmniRoute-Progress` | طلب | اضبط على `true` لأحداث التقدم |
| `Idempotency-Key` | طلب | مفتاح Dedup (نافذة 5 ثواني) |
| `X-Request-Id` | طلب | مفتاح إلغاء الحذف البديل |
| `X-OmniRoute-Cache` | الرد | `HIT` أو `MISS` (غير متدفق) |
| `X-OmniRoute-Idempotent` | الرد | `true` إذا تم إلغاء التكرار |
| `X-OmniRoute-Progress` | الرد | `enabled` إذا تم تتبع التقدم على |
| 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
@@ -63,7 +67,7 @@ Content-Type: application/json
}
```
مقدمو الخدمة المتاحون: Nebius، وOpenAI، وMistral، وTogether AI، وFireworks، وNVIDIA.
Available providers: Nebius, OpenAI, Mistral, Together AI, Fireworks, NVIDIA.
```bash
# List all embedding models
@@ -72,7 +76,7 @@ GET /v1/embeddings
---
## توليد الصور
## Image Generation
```bash
POST /v1/images/generations
@@ -86,7 +90,7 @@ Content-Type: application/json
}
```
الموفرون المتاحون: OpenAI (DALL-E)، xAI (Grok Image)، Together AI (FLUX)، Fireworks AI.
Available providers: OpenAI (DALL-E), xAI (Grok Image), Together AI (FLUX), Fireworks AI.
```bash
# List all image models
@@ -95,7 +99,7 @@ GET /v1/images/generations
---
## قائمة النماذج
## List Models
```bash
GET /v1/models
@@ -106,22 +110,22 @@ Authorization: Bearer your-api-key
---
## نقاط نهاية التوافق
## Compatibility Endpoints
| الطريقة | المسار | تنسيق |
| -------- | --------------------------- | --------------------- |
| مشاركة | `/v1/chat/completions` | أوبن آي |
| مشاركة | `/v1/messages` | انثروبي |
| مشاركة | `/v1/responses` | ردود OpenAI |
| مشاركة | `/v1/embeddings` | أوبن آي |
| مشاركة | `/v1/images/generations` | أوبن آي |
| احصل على | `/v1/models` | أوبن آي |
| مشاركة | `/v1/messages/count_tokens` | انثروبي |
| احصل على | `/v1beta/models` | الجوزاء |
| مشاركة | `/v1beta/models/{...path}` | الجوزاء توليد المحتوى |
| مشاركة | `/v1/api/chat` | أولاما |
| 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
@@ -129,11 +133,11 @@ POST /v1/providers/{provider}/embeddings
POST /v1/providers/{provider}/images/generations
```
تتم إضافة بادئة الموفر تلقائيًا في حالة فقدانها. تُرجع النماذج غير المتطابقة `400`.
The provider prefix is auto-added if missing. Mismatched models return `400`.
---
## ذاكرة التخزين المؤقت الدلالية
## Semantic Cache
```bash
# Get cache stats
@@ -143,7 +147,7 @@ GET /api/cache
DELETE /api/cache
```
مثال الاستجابة:
Response example:
```json
{
@@ -162,154 +166,164 @@ DELETE /api/cache
---
## لوحة القيادة والإدارة
## Dashboard & Management
### المصادقة
### Authentication
| نقطة النهاية | الطريقة | الوصف |
| ----------------------------- | -------------- | ------------------------ |
| `/api/auth/login` | مشاركة | تسجيل الدخول |
| `/api/auth/logout` | مشاركة | تسجيل الخروج |
| `/api/settings/require-login` | الحصول على/وضع | تبديل تسجيل الدخول مطلوب |
| Endpoint | Method | Description |
| ----------------------------- | ------- | --------------------- |
| `/api/auth/login` | POST | Login |
| `/api/auth/logout` | POST | Logout |
| `/api/settings/require-login` | GET/PUT | Toggle login required |
### إدارة مقدمي الخدمة
### Provider Management
| نقطة النهاية | الطريقة | الوصف |
| ---------------------------- | ------------------ | --------------------------- |
| `/api/providers` | الحصول على/النشر | قائمة / إنشاء مقدمي الخدمات |
| `/api/providers/[id]` | الحصول على/وضع/حذف | إدارة مزود |
| `/api/providers/[id]/test` | مشاركة | اختبار اتصال الموفر |
| `/api/providers/[id]/models` | احصل على | قائمة نماذج المزود |
| `/api/providers/validate` | مشاركة | التحقق من صحة تكوين الموفر |
| `/api/provider-nodes*` | متنوع | إدارة عقدة الموفر |
| `/api/provider-models` | الحصول على/نشر/حذف | نماذج مخصصة |
| 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
### OAuth Flows
| نقطة النهاية | الطريقة | الوصف |
| -------------------------------- | ------- | ------------------------ |
| `/api/oauth/[provider]/[action]` | متنوع | OAuth الخاص بموفر الخدمة |
| Endpoint | Method | Description |
| -------------------------------- | ------- | ----------------------- |
| `/api/oauth/[provider]/[action]` | Various | Provider-specific OAuth |
### التوجيه والتكوين
### Routing & Config
| نقطة النهاية | الطريقة | الوصف |
| --------------------- | ---------------- | --------------------------------- |
| `/api/models/alias` | الحصول على/النشر | الأسماء المستعارة للنموذج |
| `/api/models/catalog` | احصل على | جميع الموديلات حسب المزود + النوع |
| `/api/combos*` | متنوع | إدارة التحرير والسرد |
| `/api/keys*` | متنوع | إدارة مفاتيح API |
| `/api/pricing` | احصل على | التسعير النموذجي |
| 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
| نقطة النهاية | الطريقة | الوصف |
| --------------------------- | -------- | --------------------- |
| `/api/usage/history` | احصل على | تاريخ الاستخدام |
| `/api/usage/logs` | احصل على | سجلات الاستخدام |
| `/api/usage/request-logs` | احصل على | سجلات على مستوى الطلب |
| `/api/usage/[connectionId]` | احصل على | الاستخدام لكل اتصال |
| 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
| نقطة النهاية | الطريقة | الوصف |
| ------------------------------- | -------------- | ----------------------------------------------- |
| `/api/settings` | الحصول على/وضع | الإعدادات العامة |
| `/api/settings/proxy` | الحصول على/وضع | تكوين وكيل الشبكة |
| `/api/settings/proxy/test` | مشاركة | اختبار اتصال الوكيل |
| `/api/settings/ip-filter` | الحصول على/وضع | القائمة المسموح بها/القائمة المحظورة لعناوين IP |
| `/api/settings/thinking-budget` | الحصول على/وضع | الميزانية الرمزية المنطقية |
| `/api/settings/system-prompt` | الحصول على/وضع | موجه النظام العالمي |
| 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
| نقطة النهاية | الطريقة | الوصف |
| ------------------------ | -------------- | ----------------------------------- |
| `/api/sessions` | احصل على | تتبع الجلسة النشطة |
| `/api/rate-limits` | احصل على | حدود المعدل لكل حساب |
| `/api/monitoring/health` | احصل على | فحص الصحة |
| `/api/cache` | الحصول على/حذف | إحصائيات ذاكرة التخزين المؤقت / مسح |
| 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
| نقطة النهاية | الطريقة | الوصف |
| --------------------------- | -------- | -------------------------------------------------- |
| `/api/db-backups` | احصل على | قائمة النسخ الاحتياطية المتاحة |
| `/api/db-backups` | ضع | إنشاء نسخة احتياطية يدوية |
| `/api/db-backups` | مشاركة | استعادة من نسخة احتياطية محددة |
| `/api/db-backups/export` | احصل على | تنزيل قاعدة البيانات كملف .sqlite |
| `/api/db-backups/import` | مشاركة | قم بتحميل ملف .sqlite لاستبدال قاعدة البيانات |
| `/api/db-backups/exportAll` | احصل على | قم بتنزيل النسخة الاحتياطية الكاملة كأرشيف .tar.gz |
| 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
| نقطة النهاية | الطريقة | الوصف |
| ---------------------- | ------- | ------------------------ |
| `/api/sync/cloud` | متنوع | عمليات المزامنة السحابية |
| `/api/sync/initialize` | مشاركة | تهيئة المزامنة |
| `/api/cloud/*` | متنوع | إدارة السحابة |
| Endpoint | Method | Description |
| ---------------------- | ------- | --------------------- |
| `/api/sync/cloud` | Various | Cloud sync operations |
| `/api/sync/initialize` | POST | Initialize sync |
| `/api/cloud/*` | Various | Cloud management |
### أدوات سطر الأوامر
### CLI Tools
| نقطة النهاية | الطريقة | الوصف |
| ---------------------------------- | -------- | ------------------- |
| `/api/cli-tools/claude-settings` | احصل على | حالة كلود CLI |
| `/api/cli-tools/codex-settings` | احصل على | حالة Codex CLI |
| `/api/cli-tools/droid-settings` | احصل على | حالة Droid CLI |
| `/api/cli-tools/openclaw-settings` | احصل على | حالة OpenClaw CLI |
| `/api/cli-tools/runtime/[toolId]` | احصل على | وقت تشغيل CLI العام |
| 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 |
تتضمن استجابات واجهة سطر الأوامر: `installed`، `runnable`، `command`، `commandPath`، `runtimeMode`، `reason`.
CLI responses include: `installed`, `runnable`, `command`, `commandPath`, `runtimeMode`, `reason`.
### المرونة وحدود الأسعار
### ACP Agents
| نقطة النهاية | الطريقة | الوصف |
| ----------------------- | -------------- | ------------------------------------ |
| `/api/resilience` | الحصول على/وضع | الحصول على/تحديث ملفات تعريف المرونة |
| `/api/resilience/reset` | مشاركة | إعادة ضبط قواطع الدائرة |
| `/api/rate-limits` | احصل على | حالة حد المعدل لكل حساب |
| `/api/rate-limit` | احصل على | تكوين حد المعدل العالمي |
| 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).
| نقطة النهاية | الطريقة | الوصف |
| ------------ | ---------------- | ------------------------------------- |
| `/api/evals` | الحصول على/النشر | قائمة مجموعات التقييم / تشغيل التقييم |
### 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 |
| نقطة النهاية | الطريقة | الوصف |
| --------------- | ------------------ | -------------------- |
| `/api/policies` | الحصول على/نشر/حذف | إدارة سياسات التوجيه |
### Evals
###الامتثال
| Endpoint | Method | Description |
| ------------ | -------- | --------------------------------- |
| `/api/evals` | GET/POST | List eval suites / run evaluation |
| نقطة النهاية | الطريقة | الوصف |
| --------------------------- | -------- | ---------------------------- |
| `/api/compliance/audit-log` | احصل على | سجل تدقيق الامتثال (آخر رقم) |
### Policies
### v1beta (متوافق مع الجوزاء)
| Endpoint | Method | Description |
| --------------- | --------------- | ----------------------- |
| `/api/policies` | GET/POST/DELETE | Manage routing policies |
| نقطة النهاية | الطريقة | الوصف |
| -------------------------- | -------- | -------------------------------------- |
| `/v1beta/models` | احصل على | قائمة النماذج بصيغة الجوزاء |
| `/v1beta/models/{...path}` | مشاركة | الجوزاء `generateContent` نقطة النهاية |
### Compliance
تعكس نقاط النهاية هذه تنسيق Gemini API للعملاء الذين يتوقعون توافق Gemini SDK الأصلي.
| Endpoint | Method | Description |
| --------------------------- | ------ | ----------------------------- |
| `/api/compliance/audit-log` | GET | Compliance audit log (last N) |
### واجهات برمجة التطبيقات الداخلية / النظام
### v1beta (Gemini-Compatible)
| نقطة النهاية | الطريقة | الوصف |
| --------------- | -------- | -------------------------------------------------- |
| `/api/init` | احصل على | فحص تهيئة التطبيق (يستخدم عند التشغيل لأول مرة) |
| `/api/tags` | احصل على | علامات النماذج المتوافقة مع Ollama (لعملاء Ollama) |
| `/api/restart` | مشاركة | تشغيل إعادة تشغيل الخادم الرشيقة |
| `/api/shutdown` | مشاركة | تشغيل إيقاف تشغيل الخادم بشكل رشيق |
| Endpoint | Method | Description |
| -------------------------- | ------ | --------------------------------- |
| `/v1beta/models` | GET | List models in Gemini format |
| `/v1beta/models/{...path}` | POST | Gemini `generateContent` endpoint |
> **ملاحظة:** يتم استخدام نقاط النهاية هذه داخليًا بواسطة النظام أو للتوافق مع عميل Ollama. لا يتم استدعاؤها عادة من قبل المستخدمين النهائيين.
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
@@ -317,9 +331,9 @@ Authorization: Bearer your-api-key
Content-Type: multipart/form-data
```
قم بنسخ الملفات الصوتية باستخدام Deepgram أو AssemblyAI.
Transcribe audio files using Deepgram or AssemblyAI.
**الطلب:**
**Request:**
```bash
curl -X POST http://localhost:20128/v1/audio/transcriptions \
@@ -328,7 +342,7 @@ curl -X POST http://localhost:20128/v1/audio/transcriptions \
-F "model=deepgram/nova-3"
```
**الرد:**
**Response:**
```json
{
@@ -339,15 +353,15 @@ curl -X POST http://localhost:20128/v1/audio/transcriptions \
}
```
**الموفرون المدعمون:** `deepgram/nova-3`، `assemblyai/best`.
**Supported providers:** `deepgram/nova-3`, `assemblyai/best`.
**التنسيقات المدعومة:** `mp3`، `wav`، `m4a`، `flac`، `ogg`، `webm`.
**Supported formats:** `mp3`, `wav`, `m4a`, `flac`, `ogg`, `webm`.
---
## التوافق مع أولاما
## Ollama Compatibility
بالنسبة للعملاء الذين يستخدمون تنسيق واجهة برمجة تطبيقات Olma:
For clients that use Ollama's API format:
```bash
# Chat endpoint (Ollama format)
@@ -357,18 +371,18 @@ POST /v1/api/chat
GET /api/tags
```
تتم ترجمة الطلبات تلقائيًا بين تنسيقات Ollama والتنسيقات الداخلية.
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
{
@@ -381,7 +395,7 @@ GET /api/telemetry/summary
---
## الميزانية
## Budget
```bash
# Get budget status for all API keys
@@ -400,7 +414,7 @@ Content-Type: application/json
---
## توفر النموذج
## Model Availability
```bash
# Get real-time model availability across all providers
@@ -417,25 +431,25 @@ Content-Type: application/json
---
## معالجة الطلب
## Request Processing
1. يرسل العميل طلبًا إلى `/v1/*`
2. يستدعي معالج المسار `handleChat`، `handleEmbedding`، `handleAudioTranscription`، أو `handleImageGeneration`
3. تم حل النموذج (المزود/النموذج المباشر أو الاسم المستعار/السرد)
4. تم تحديد بيانات الاعتماد من قاعدة البيانات المحلية مع تصفية توفر الحساب
5. للدردشة: `handleChatCore`اكتشاف التنسيق، والترجمة، والتحقق من ذاكرة التخزين المؤقت، والتحقق من عدم الكفاءة
6. يقوم منفذ الموفر بإرسال طلب المنبع
7. تتم ترجمة الاستجابة مرة أخرى إلى تنسيق العميل (الدردشة) أو إعادتها كما هي (التضمينات/الصور/الصوت)
8. تم تسجيل الاستخدام/التسجيل
9. يتم تطبيق الإجراء الاحتياطي على الأخطاء وفقًا لقواعد التحرير والسرد
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
مرجع البنية الكاملة: [link](ARCHITECTURE.md)
Full architecture reference: [`ARCHITECTURE.md`](ARCHITECTURE.md)
---
## المصادقة
## Authentication
- تستخدم مسارات لوحة المعلومات (`/dashboard/*`) ملف تعريف الارتباط `auth_token`
- يستخدم تسجيل الدخول تجزئة كلمة المرور المحفوظة؛ الرجوع إلى `INITIAL_PASSWORD`
- `requireLogin` قابل للتبديل عبر `/api/settings/require-login`
- تتطلب مسارات `/v1/*` بشكل اختياري مفتاح Bearer API عندما `REQUIRE_API_KEY=true`
- 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`
+357 -351
View File
@@ -1,71 +1,75 @@
# العمارة OmniRoute
🌐 **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)
🌐 **Languages:** 🇺🇸 [English](../../ARCHITECTURE.md) | 🇧🇷 [Português (Brasil)](../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) | 🇩🇰 [Dansk](../da/ARCHITECTURE.md) | 🇫🇮 [Suomi](../fi/ARCHITECTURE.md) | 🇮🇱 [עברית](../he/ARCHITECTURE.md) | 🇭🇺 [Magyar](../hu/ARCHITECTURE.md) | 🇮🇩 [Bahasa Indonesia](../id/ARCHITECTURE.md) | 🇰🇷 [한국어](../ko/ARCHITECTURE.md) | 🇲🇾 [Bahasa Melayu](../ms/ARCHITECTURE.md) | 🇳🇱 [Nederlands](../nl/ARCHITECTURE.md) | 🇳🇴 [Norsk](../no/ARCHITECTURE.md) | 🇵🇹 [Português (Portugal)](../pt/ARCHITECTURE.md) | 🇷🇴 [Română](../ro/ARCHITECTURE.md) | 🇵🇱 [Polski](../pl/ARCHITECTURE.md) | 🇸🇰 [Slovenčina](../sk/ARCHITECTURE.md) | 🇸🇪 [Svenska](../sv/ARCHITECTURE.md) | 🇵🇭 [Filipino](../phi/ARCHITECTURE.md)
---
_آخر تحديث: 2026-02-18_
# 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)
OmniRoute عبارة عن بوابة توجيه محلية تعمل بالذكاء الاصطناعي ولوحة معلومات مبنية على Next.js.
فهو يوفر نقطة نهاية واحدة متوافقة مع OpenAI (`/v1/*`) ويوجه حركة المرور عبر العديد من موفري الخدمات الأولية مع الترجمة والاحتياط وتحديث الرمز المميز وتتبع الاستخدام.
_Last updated: 2026-03-04_
القدرات الأساسية:
## Executive Summary
- سطح API متوافق مع OpenAI لـ CLI/الأدوات (28 مزودًا)
- ترجمة الطلب/الاستجابة عبر تنسيقات الموفر
- نموذج احتياطي التحرير والسرد (تسلسل متعدد النماذج)
- احتياطي على مستوى الحساب (حسابات متعددة لكل مزود)
- إدارة اتصال موفر OAuth + API-key
- إنشاء التضمين عبر `/v1/embeddings` (6 موفري خدمات، 9 نماذج)
- إنشاء الصور عبر `/v1/images/generations` (4 مقدمي خدمات، 9 نماذج)
- فكر في تحليل العلامات (`<think>...</think>`) لنماذج الاستدلال
- تعقيم الاستجابة للتوافق الصارم مع OpenAI SDK
- تطبيع الدور (المطور → النظام، النظام → المستخدم) للتوافق بين الموفرين
- تحويل الإخراج المنظم (json_schema → Gemini ResponseSchema)
- الثبات المحلي لمقدمي الخدمات والمفاتيح والأسماء المستعارة والمجموعات والإعدادات والتسعير
- تتبع الاستخدام/التكلفة وتسجيل الطلب
- مزامنة سحابية اختيارية لمزامنة الأجهزة/الحالة المتعددة
- القائمة المسموح بها/القائمة المحظورة لـ IP للتحكم في الوصول إلى واجهة برمجة التطبيقات
- التفكير في إدارة الميزانية (العبور / التلقائي / المخصص / التكيفي)
- الحقن الفوري للنظام العالمي
- تتبع الجلسة وأخذ البصمات
- تحديد المعدل المحسن لكل حساب مع الملفات الشخصية الخاصة بالمزود
- نمط قاطع الدائرة لمرونة المزود
- حماية القطيع ضد الرعد مع قفل Mutex
- ذاكرة التخزين المؤقت لإلغاء البيانات المكررة للطلب المستندة إلى التوقيع
- طبقة المجال: توفر النموذج، وقواعد التكلفة، والسياسة الاحتياطية، وسياسة الإغلاق
- استمرارية حالة المجال (ذاكرة التخزين المؤقت للكتابة في SQLite للاحتياطيات والميزانيات وعمليات الإغلاق وقواطع الدائرة)
- محرك السياسة لتقييم الطلب المركزي (التأمين → الميزانية → الاحتياطي)
- طلب القياس عن بعد مع تجميع الكمون p50/p95/p99
- معرف الارتباط (X-Request-Id) للتتبع الشامل
- تسجيل تدقيق الامتثال مع إلغاء الاشتراك لكل مفتاح API
- إطار تقييمي لضمان جودة LLM
- لوحة تحكم واجهة المستخدم المرنة مع حالة قاطع الدائرة في الوقت الفعلي
- موفرو OAuth المعياريون (12 وحدة فردية ضمن `src/lib/oauth/providers/`)
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:
- تقوم مسارات تطبيق Next.js ضمن `src/app/api/*` بتنفيذ كل من واجهات برمجة تطبيقات لوحة المعلومات وواجهات برمجة تطبيقات التوافق
- نواة توجيه/SSE مشتركة في `src/sse/*` + `open-sse/*` تتعامل مع تنفيذ الموفر والترجمة والتدفق والرجوع والاستخدام
- 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 (`<think>...</think>`) 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
- وقت تشغيل البوابة المحلية
- واجهات برمجة التطبيقات لإدارة لوحة المعلومات
- مصادقة الموفر وتحديث الرمز المميز
- طلب الترجمة وتدفق SSE
- الحالة المحلية + استمرارية الاستخدام
- تنسيق مزامنة سحابية اختيارية
## Scope and Boundaries
### خارج النطاق
### In Scope
- تنفيذ الخدمة السحابية خلف `NEXT_PUBLIC_CLOUD_URL`
- مزود مستوى جيش تحرير السودان/مستوى التحكم خارج العملية المحلية
- ثنائيات CLI الخارجية نفسها (Claude CLI، Codex CLI، وما إلى ذلك)
- 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
@@ -81,8 +85,8 @@ flowchart LR
API[V1 Compatibility API\n/v1/*]
DASH[Dashboard + Management API\n/api/*]
CORE[SSE + Translation Core\nopen-sse + src/sse]
DB[(db.json)]
UDB[(usage.json + log.txt)]
DB[(storage.sqlite)]
UDB[(usage tables + log artifacts)]
end
subgraph Upstreams[Upstream Providers]
@@ -113,151 +117,152 @@ flowchart LR
DASH --> CLOUD
```
## مكونات وقت التشغيل الأساسية
## Core Runtime Components
## 1) واجهة برمجة التطبيقات وطبقة التوجيه (مسارات تطبيق Next.js)
## 1) API and Routing Layer (Next.js App Routes)
الدلائل الرئيسية:
Main directories:
- `src/app/api/v1/*` و`src/app/api/v1beta/*` لواجهات برمجة تطبيقات التوافق
- `src/app/api/*` لواجهات برمجة التطبيقات للإدارة/التكوين
- تتم إعادة الكتابة التالية في الخريطة `next.config.mjs` من `/v1/*` إلى `/api/v1/*`
- `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`يتضمن نماذج مخصصة مع `custom: true`
- `src/app/api/v1/embeddings/route.ts`إنشاء التضمين (6 موفري)
- `src/app/api/v1/images/generations/route.ts`إنشاء الصور (أكثر من 4 موفري خدمة، بما في ذلك Antigravity/Nebius)
- `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`دردشة مخصصة لكل مزود
- `src/app/api/v1/providers/[provider]/embeddings/route.ts`عمليات التضمين المخصصة لكل مزود
- `src/app/api/v1/providers/[provider]/images/generations/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:
- المصادقة/الإعدادات: `src/app/api/auth/*`، `src/app/api/settings/*`
- مقدمو الخدمة/الاتصالات: `src/app/api/providers*`
- عقد الموفر: `src/app/api/provider-nodes*`
- النماذج المخصصة: `src/app/api/provider-models` (GET/POST/DELETE)
- كتالوج النماذج: `src/app/api/models/catalog` (GET)
- تكوين الوكيل: `src/app/api/settings/proxy` (GET/PUT/DELETE) + `src/app/api/settings/proxy/test` (POST)
- 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/*`
- المفاتيح/الأسماء المستعارة/المجموعات/التسعير: `src/app/api/keys*`، `src/app/api/models/alias`، `src/app/api/combos*`، `src/app/api/pricing`
- الاستخدام: `src/app/api/usage/*`
- المزامنة/السحابة: `src/app/api/sync/*`، `src/app/api/cloud/*`
- مساعدي أدوات CLI: `src/app/api/cli-tools/*`
- مرشح IP: `src/app/api/settings/ip-filter` (GET/PUT)
- ميزانية التفكير: `src/app/api/settings/thinking-budget` (GET/PUT)
- موجه النظام: `src/app/api/settings/system-prompt` (GET/PUT)
- الجلسات: `src/app/api/sessions` (GET)
- حدود الأسعار: `src/app/api/rate-limits` (GET)
- المرونة: `src/app/api/resilience` (GET/PATCH) - ملفات تعريف الموفر، قاطع الدائرة، حالة حد المعدل
- إعادة ضبط المرونة: `src/app/api/resilience/reset` (POST) — إعادة ضبط الفواصل + فترات التهدئة
- إحصائيات ذاكرة التخزين المؤقت: `src/app/api/cache/stats` (الحصول على/الحذف)
- توفر النموذج: `src/app/api/models/availability` (GET/POST)
- القياس عن بعد: `src/app/api/telemetry/summary` (GET)
- الميزانية: `src/app/api/usage/budget` (GET/POST)
- السلاسل الاحتياطية: `src/app/api/fallback/chains` (GET/POST/DELETE)
- تدقيق الامتثال: `src/app/api/compliance/audit-log` (GET)
- التقييمات: `src/app/api/evals` (GET/POST)، `src/app/api/evals/[suiteId]` (GET)
- السياسات: `src/app/api/policies` (GET/POST)
- 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 + جوهر الترجمة
## 2) SSE + Translation Core
وحدات التدفق الرئيسية:
Main flow modules:
- الإدخال: `src/sse/handlers/chat.ts`
- التنسيق الأساسي: `open-sse/handlers/chatCore.ts`
- محولات تنفيذ الموفر: `open-sse/executors/*`
- اكتشاف التنسيق/تكوين الموفر: `open-sse/services/provider.ts`
- تحليل/حل النموذج: `src/sse/services/model.ts`، `open-sse/services/model.ts`
- المنطق الاحتياطي للحساب: `open-sse/services/accountFallback.ts`
- سجل الترجمة: `open-sse/translator/index.ts`
- تحويلات الدفق: `open-sse/utils/stream.ts`، `open-sse/utils/streamHandler.ts`
- استخراج/تسوية الاستخدام: `open-sse/utils/usageTracking.ts`
- محلل العلامات: `open-sse/utils/thinkTagParser.ts`
- معالج التضمين: `open-sse/handlers/embeddings.ts`
- تسجيل موفر التضمين: `open-sse/config/embeddingRegistry.ts`
- معالج إنشاء الصور: `open-sse/handlers/imageGeneration.ts`
- سجل موفر الصور: `open-sse/config/imageRegistry.ts`
- تعقيم الاستجابة: `open-sse/handlers/responseSanitizer.ts`
- تطبيع الدور: `open-sse/services/roleNormalizer.ts`
- 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):
- اختيار الحساب/تسجيل النقاط: `open-sse/services/accountSelector.ts`
- إدارة دورة حياة السياق: `open-sse/services/contextManager.ts`
- فرض عامل تصفية IP: `open-sse/services/ipFilter.ts`
- تتبع الجلسة: `open-sse/services/sessionManager.ts`
- طلب إلغاء البيانات المكررة: `open-sse/services/signatureCache.ts`
- الحقن الفوري للنظام: `open-sse/services/systemPrompt.ts`
- إدارة ميزانية التفكير: `open-sse/services/thinkingBudget.ts`
- توجيه نموذج حرف البدل: `open-sse/services/wildcardRouter.ts`
- إدارة حدود السعر: `open-sse/services/rateLimitManager.ts`
- قاطع الدائرة: `open-sse/services/circuitBreaker.ts`
- 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:
- توفر النموذج: `src/lib/domain/modelAvailability.ts`
- قواعد/ميزانيات التكلفة: `src/lib/domain/costRules.ts`
- السياسة الاحتياطية: `src/lib/domain/fallbackPolicy.ts`
- محلل التحرير والسرد: `src/lib/domain/comboResolver.ts`
- سياسة التأمين: `src/lib/domain/lockoutPolicy.ts`
- محرك السياسة: `src/domain/policyEngine.ts`الإغلاق المركزي ← الميزانية ← التقييم الاحتياطي
- كتالوج رموز الأخطاء: `src/lib/domain/errorCodes.ts`
- معرف الطلب: `src/lib/domain/requestId.ts`
- مهلة الجلب: `src/lib/domain/fetchTimeout.ts`
- طلب القياس عن بعد: `src/lib/domain/requestTelemetry.ts`
- الامتثال/التدقيق: `src/lib/domain/compliance/index.ts`
- عداء التقييم: `src/lib/domain/evalRunner.ts`
- استمرارية حالة المجال: `src/lib/db/domainState.ts` — SQLite CRUD للسلاسل الاحتياطية، والميزانيات، وتاريخ التكلفة، وحالة الإغلاق، وقواطع الدائرة
- 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 (12 ملفًا فرديًا ضمن `src/lib/oauth/providers/`):
OAuth provider modules (12 individual files under `src/lib/oauth/providers/`):
- فهرس التسجيل: `src/lib/oauth/providers/index.ts`
- مقدمو الخدمات الأفراد: `claude.ts`، `codex.ts`، `gemini.ts`، `antigravity.ts`، `iflow.ts`، `qwen.ts`، `kimi-coding.ts`، `github.ts`، `kiro.ts`، `cursor.ts`، `kilocode.ts`، `cline.ts`
- الغلاف الرقيق: `src/lib/oauth/providers.ts`إعادة التصدير من الوحدات الفردية
- Registry index: `src/lib/oauth/providers/index.ts`
- Individual providers: `claude.ts`, `codex.ts`, `gemini.ts`, `antigravity.ts`, `iflow.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) طبقة الثبات
## 3) Persistence Layer
قاعدة بيانات الحالة الأساسية:
Primary state DB (SQLite):
- `src/lib/localDb.ts`
- الملف: `${DATA_DIR}/db.json` (أو `$XDG_CONFIG_HOME/omniroute/db.json` عند التعيين، وإلا `~/.omniroute/db.json`)
- الكيانات:providerConnections، وproviderNodes، وmodelAliases، والمجموعات، وapiKeys، والإعدادات، والتسعير، **customModels**، **proxyConfig**، **ipFilter**، **thinkingBudget**، **systemPrompt**
- 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:
- `src/lib/usageDb.ts`
- الملفات: `${DATA_DIR}/usage.json`، `${DATA_DIR}/log.txt`، `${DATA_DIR}/call_logs/`
- يتبع نفس سياسة الدليل الأساسي مثل `localDb` (`DATA_DIR`، ثم `XDG_CONFIG_HOME/omniroute` عند التعيين)
- مقسمة إلى وحدات فرعية مركزة: `migrations.ts`، `usageHistory.ts`، `costCalculator.ts`، `usageStats.ts`، `callLogs.ts`
- 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/`, `<repo>/logs/...`)
- legacy JSON files are migrated to SQLite by startup migrations when present
قاعدة بيانات حالة المجال (SQLite):
Domain State DB (SQLite):
- `src/lib/db/domainState.ts`عمليات CRUD لحالة المجال
- الجداول (التي تم إنشاؤها في `src/lib/db/core.ts`): `domain_fallback_chains`، `domain_budgets`، `domain_cost_history`، `domain_lockout_state`، `domain_circuit_breakers`
- نمط ذاكرة التخزين المؤقت للكتابة: تعد الخرائط الموجودة في الذاكرة موثوقة في وقت التشغيل؛ تتم كتابة الطفرات بشكل متزامن إلى 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) المصادقة + الأسطح الأمنية
## 4) Auth + Security Surfaces
- مصادقة ملف تعريف الارتباط للوحة المعلومات: `src/proxy.ts`، `src/app/api/auth/login/route.ts`
- إنشاء/التحقق من مفتاح واجهة برمجة التطبيقات: `src/shared/utils/apiKey.ts`
- استمرت أسرار الموفر في إدخالات `providerConnections`
- دعم الوكيل الصادر عبر `open-sse/utils/proxyFetch.ts` (env vars) و`open-sse/utils/networkProxy.ts` (قابل للتكوين لكل موفر أو عالمي)
- 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) المزامنة السحابية
## 5) Cloud Sync
- الحرف الأول للمجدول: `src/lib/initCloudSync.ts`، `src/shared/services/initializeCloudSync.ts`
- المهمة الدورية: `src/shared/services/cloudSyncScheduler.ts`
- مسار التحكم: `src/app/api/sync/cloud/route.ts`
- 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`
## دورة حياة الطلب (`/v1/chat/completions`)
## Request Lifecycle (`/v1/chat/completions`)
```mermaid
sequenceDiagram
@@ -304,7 +309,7 @@ sequenceDiagram
Stream->>Usage: extract usage + persist history/log
```
## التحرير والسرد + التدفق الاحتياطي للحساب
## Combo + Account Fallback Flow
```mermaid
flowchart TD
@@ -334,9 +339,9 @@ flowchart TD
Q -- No --> R[Return all unavailable]
```
يتم اتخاذ القرارات الاحتياطية بواسطة `open-sse/services/accountFallback.ts` باستخدام رموز الحالة والاستدلال على رسائل الخطأ.
Fallback decisions are driven by `open-sse/services/accountFallback.ts` using status codes and error-message heuristics.
## دورة حياة OAuth Onboarding وتحديث الرمز المميز
## OAuth Onboarding and Token Refresh Lifecycle
```mermaid
sequenceDiagram
@@ -366,9 +371,9 @@ sequenceDiagram
Test-->>UI: validation result
```
يتم تنفيذ التحديث أثناء حركة المرور المباشرة داخل `open-sse/handlers/chatCore.ts` عبر المنفذ `refreshCredentials()`.
Refresh during live traffic is executed inside `open-sse/handlers/chatCore.ts` via executor `refreshCredentials()`.
## دورة حياة المزامنة السحابية (تمكين / مزامنة / تعطيل)
## Cloud Sync Lifecycle (Enable / Sync / Disable)
```mermaid
sequenceDiagram
@@ -400,9 +405,9 @@ sequenceDiagram
Sync-->>UI: disabled
```
يتم تشغيل المزامنة الدورية بواسطة `CloudSyncScheduler` عند تمكين السحابة.
Periodic sync is triggered by `CloudSyncScheduler` when cloud is enabled.
## نموذج البيانات وخريطة التخزين
## Data Model and Storage Map
```mermaid
erDiagram
@@ -503,14 +508,14 @@ erDiagram
}
```
ملفات التخزين المادية:
Physical storage files:
- الحالة الرئيسية: `${DATA_DIR}/db.json` (أو `$XDG_CONFIG_HOME/omniroute/db.json` عند التعيين، وإلا `~/.omniroute/db.json`)
- إحصائيات الاستخدام: `${DATA_DIR}/usage.json`
- خطوط سجل الطلب: `${DATA_DIR}/log.txt`
- جلسات تصحيح أخطاء المترجم/الطلب الاختيارية: `<repo>/logs/...`
- 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: `<repo>/logs/...`
## طبولوجيا النشر
## Deployment Topology
```mermaid
flowchart LR
@@ -522,8 +527,8 @@ flowchart LR
subgraph ContainerOrProcess[OmniRoute Runtime]
Next[Next.js Server\nPORT=20128]
Core[SSE Core + Executors]
MainDB[(db.json)]
UsageDB[(usage.json/log.txt)]
MainDB[(storage.sqlite)]
UsageDB[(usage tables + log artifacts)]
end
subgraph External[External Services]
@@ -541,241 +546,242 @@ flowchart LR
Next --> SyncCloud
```
## تعيين الوحدة (القرار الحاسم)
## Module Mapping (Decision-Critical)
### وحدات المسار وواجهة برمجة التطبيقات
### Route and API Modules
- `src/app/api/v1/*`، `src/app/api/v1beta/*`: واجهات برمجة تطبيقات التوافق
- `src/app/api/v1/providers/[provider]/*`: مسارات مخصصة لكل مزود (الدردشة والتضمين والصور)
- `src/app/api/providers*`: موفر CRUD والتحقق من الصحة والاختبار
- `src/app/api/provider-nodes*`: إدارة العقدة المتوافقة المخصصة
- `src/app/api/provider-models`: إدارة النماذج المخصصة (CRUD)
- `src/app/api/models/catalog`: واجهة برمجة تطبيقات كتالوج النموذج الكامل (جميع الأنواع مجمعة حسب الموفر)
- `src/app/api/oauth/*`: تدفقات OAuth/رمز الجهاز
- `src/app/api/keys*`: دورة حياة مفتاح واجهة برمجة التطبيقات المحلية
- `src/app/api/models/alias`: إدارة الاسم المستعار
- `src/app/api/combos*`: إدارة التحرير والسرد الاحتياطية
- `src/app/api/pricing`: تجاوزات التسعير لحساب التكلفة
- `src/app/api/settings/proxy`: تكوين الوكيل (GET/PUT/DELETE)
- `src/app/api/settings/proxy/test`: اختبار اتصال الوكيل الصادر (POST)
- `src/app/api/usage/*`: واجهات برمجة تطبيقات الاستخدام والسجلات
- `src/app/api/sync/*` + `src/app/api/cloud/*`: المزامنة السحابية والمساعدون الذين يواجهون السحابة
- `src/app/api/cli-tools/*`: كاتب/أداة فحص تكوين CLI المحلية
- `src/app/api/settings/ip-filter`: قائمة IP المسموح بها/القائمة المحظورة (GET/PUT)
- `src/app/api/settings/thinking-budget`: تكوين ميزانية الرمز المميز (GET/PUT)
- `src/app/api/settings/system-prompt`: موجه النظام العالمي (GET/PUT)
- `src/app/api/sessions`: قائمة الجلسة النشطة (GET)
- `src/app/api/rate-limits`: حالة حد السعر لكل حساب (GET)
- `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`: تحليل الطلب، ومعالجة التحرير والسرد، وحلقة اختيار الحساب
- `open-sse/handlers/chatCore.ts`: الترجمة، إرسال المنفذ، معالجة إعادة المحاولة/التحديث، إعداد الدفق
- `open-sse/executors/*`: سلوك الشبكة والتنسيق الخاص بالموفر
- `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`: تسجيل المترجم وتنسيقه
- طلب المترجمين: `open-sse/translator/request/*`
- مترجمو الرد: `open-sse/translator/response/*`
- ثوابت التنسيق: `open-sse/translator/formats.ts`
- `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/localDb.ts`: التكوين/الحالة المستمرة
- `src/lib/usageDb.ts`: سجل الاستخدام وسجلات الطلبات المتجددة
- `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)
كل مزود لديه منفذ متخصص يمتد `BaseExecutor` (في `open-sse/executors/base.ts`)، والذي يوفر بناء عنوان URL، وإنشاء الرأس، وإعادة المحاولة مع التراجع الأسي، وخطافات تحديث بيانات الاعتماد، وطريقة التنسيق `execute()`.
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.
| المنفذ | المزود (المقدمون) | التعامل الخاص |
| --------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------ | ---------------------------------------------------------------------- |
| `DefaultExecutor` | OpenAI، Claude، Gemini، Qwen، iFlow، OpenRouter، GLM، Kimi، MiniMax، DeepSeek، Groq، xAI، Mistral، Perplexity، Together، Fireworks، Cerebras، Cohere، NVIDIA | تكوين عنوان URL/الرأس الديناميكي لكل مزود |
| `AntigravityExecutor` | جوجل مكافحة الجاذبية | معرفات المشروع/الجلسة المخصصة، إعادة المحاولة بعد التحليل |
| `CodexExecutor` | OpenAI Codex | يحقن تعليمات النظام، ويفرض جهدًا منطقيًا |
| `CursorExecutor` | بيئة تطوير متكاملة للمؤشر | بروتوكول ConnectRPC، تشفير Protobuf، طلب التوقيع عبر المجموع الاختباري |
| `GithubExecutor` | جيثب مساعد الطيار | تحديث الرمز المميز لـ Copilot، ورؤوس محاكاة VSCode |
| `KiroExecutor` | AWS CodeWhisperer/كيرو | تنسيق AWS EventStream الثنائي → تحويل SSE |
| `GeminiCLIExecutor` | الجوزاء CLI | دورة تحديث رمز OAuth المميز لـ Google |
| Executor | Provider(s) | Special Handling |
| --------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------ | -------------------------------------------------------------------- |
| `DefaultExecutor` | OpenAI, Claude, Gemini, Qwen, iFlow, 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 |
يستخدم جميع الموفرين الآخرين (بما في ذلك العقد المتوافقة المخصصة) `DefaultExecutor`.
All other providers (including custom compatible nodes) use the `DefaultExecutor`.
## مصفوفة توافق الموفر
## Provider Compatibility Matrix
| مقدم | تنسيق | مصادقة | تيار | غير دفق | تحديث الرمز المميز | واجهة برمجة تطبيقات الاستخدام |
| ----------------------------------- | ---------------- | --------------------------- | --------------- | ------- | ------------------ | ----------------------------- |
| كلود | كلود | مفتاح API / OAuth | ✅ | ✅ | ✅ | ⚠️ المشرف فقط |
| الجوزاء | الجوزاء | مفتاح API / OAuth | ✅ | ✅ | ✅ | ⚠️ وحدة التحكم السحابية |
| الجوزاء CLI | الجوزاء-cli | أووث | ✅ | ✅ | ✅ | ⚠️ وحدة التحكم السحابية |
| مكافحة الجاذبية | ضد الجاذبية | أووث | ✅ | ✅ | ✅ | ✅ الحصة الكاملة API |
| أوبن آي | أوبيناي | مفتاح واجهة برمجة التطبيقات | ✅ | ✅ | ❌ | ❌ |
| الدستور الغذائي | openai-responses | أووث | ✅ مجبور | ❌ | ✅ | ✅ حدود المعدل |
| جيثب مساعد الطيار | أوبيناي | OAuth + رمز مساعد الطيار | ✅ | ✅ | ✅ | ✅ لقطات الحصص |
| المؤشر | المؤشر | المجموع الاختباري المخصص | ✅ | ✅ | ❌ | ❌ |
| كيرو | كيرو | AWS SSO OIDC | ✅(ايفنت ستريم) | ❌ | ✅ | ✅ حدود الاستخدام |
| كوين | أوبيناي | أووث | ✅ | ✅ | ✅ | ⚠️ حسب الطلب |
| اي فلو | أوبيناي | OAuth (أساسي) | ✅ | ✅ | ✅ | ⚠️ حسب الطلب |
| اوبن راوتر | أوبيناي | مفتاح واجهة برمجة التطبيقات | ✅ | ✅ | ❌ | ❌ |
| جي إل إم/كيمي/ميني ماكس | كلود | مفتاح واجهة برمجة التطبيقات | ✅ | ✅ | ❌ | ❌ |
| ديب سيك | أوبيناي | مفتاح واجهة برمجة التطبيقات | ✅ | ✅ | ❌ | ❌ |
| جروك | أوبيناي | مفتاح واجهة برمجة التطبيقات | ✅ | ✅ | ❌ | ❌ |
| xAI (جروك) | أوبيناي | مفتاح واجهة برمجة التطبيقات | ✅ | ✅ | ❌ | ❌ |
| ميسترال | أوبيناي | مفتاح واجهة برمجة التطبيقات | ✅ | ✅ | ❌ | ❌ |
| الحيرة | أوبيناي | مفتاح واجهة برمجة التطبيقات | ✅ | ✅ | ❌ | ❌ |
| معا منظمة العفو الدولية | أوبيناي | مفتاح واجهة برمجة التطبيقات | ✅ | ✅ | ❌ | ❌ |
| الألعاب النارية منظمة العفو الدولية | أوبيناي | مفتاح واجهة برمجة التطبيقات | ✅ | ✅ | ❌ | ❌ |
| المخيخ | أوبيناي | مفتاح واجهة برمجة التطبيقات | ✅ | ✅ | ❌ | ❌ |
| كوهير | أوبيناي | مفتاح واجهة برمجة التطبيقات | ✅ | ✅ | ❌ | ❌ |
| نفيديا نيم | أوبيناي | مفتاح واجهة برمجة التطبيقات | ✅ | ✅ | ❌ | ❌ |
| 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 |
| iFlow | 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
- كلود
- الجوزاء/الجوزاء-CLI/الظرف المضاد للجاذبية
- كيرو
- المؤشر
- OpenAI chat/Responses
- Claude
- Gemini/Gemini-CLI/Antigravity envelope
- Kiro
- Cursor
تستخدم الترجمات **OpenAI كتنسيق مركزي** — تمر جميع التحويلات عبر OpenAI كتنسيق وسيط:
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:
- **تطهير الاستجابة** — يزيل الحقول غير القياسية من استجابات تنسيق OpenAI (سواء المتدفقة أو غير المتدفقة) لضمان الامتثال الصارم لـ SDK
- **تطبيع الدور** — تحويل `developer``system` للأهداف غير التابعة لـ OpenAI؛ يدمج `system``user` للنماذج التي ترفض دور النظام (GLM، ERNIE)
- **فكر في استخراج العلامات** — يوزع كتل `<think>...</think>` من المحتوى إلى حقل `reasoning_content`
- **الإخراج المنظم** — يحول OpenAI `response_format.json_schema` إلى `responseMimeType` + `responseSchema` الخاص بـ Gemini
- **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 `<think>...</think>` blocks from content into `reasoning_content` field
- **Structured output** — Converts OpenAI `response_format.json_schema` to Gemini's `responseMimeType` + `responseSchema`
## نقاط نهاية واجهة برمجة التطبيقات المدعومة
## Supported API Endpoints
| نقطة النهاية | تنسيق | معالج |
| -------------------------------------------------- | ------------------ | ------------------------------------------------------------------------- |
| `POST /v1/chat/completions` | دردشة OpenAI | `src/sse/handlers/chat.ts` |
| `POST /v1/messages` | رسائل كلود | نفس المعالج (تم اكتشافه تلقائيًا) |
| `POST /v1/responses` | ردود OpenAI | `open-sse/handlers/responsesHandler.ts` |
| `POST /v1/embeddings` | تضمينات OpenAI | `open-sse/handlers/embeddings.ts` |
| `GET /v1/embeddings` | قائمة النماذج | طريق API |
| `POST /v1/images/generations` | صور OpenAI | `open-sse/handlers/imageGeneration.ts` |
| `GET /v1/images/generations` | قائمة النماذج | طريق API |
| `POST /v1/providers/{provider}/chat/completions` | دردشة OpenAI | مخصص لكل مزود مع التحقق من صحة النموذج |
| `POST /v1/providers/{provider}/embeddings` | تضمينات OpenAI | مخصص لكل مزود مع التحقق من صحة النموذج |
| `POST /v1/providers/{provider}/images/generations` | صور OpenAI | مخصص لكل مزود مع التحقق من صحة النموذج |
| `POST /v1/messages/count_tokens` | عدد كلود توكن | طريق API |
| `GET /v1/models` | قائمة نماذج OpenAI | مسار واجهة برمجة التطبيقات (الدردشة + التضمين + الصورة + النماذج المخصصة) |
| `GET /api/models/catalog` | كتالوج | جميع النماذج مجمعة حسب الموفر + النوع |
| `POST /v1beta/models/*:streamGenerateContent` | مولود برج الجوزاء | طريق API |
| `GET/PUT/DELETE /api/settings/proxy` | تكوين الوكيل | تكوين وكيل الشبكة |
| `POST /api/settings/proxy/test` | اتصال الوكيل | نقطة نهاية اختبار صحة الوكيل/الاتصال |
| `GET/POST/DELETE /api/provider-models` | نماذج مخصصة | إدارة النماذج المخصصة لكل مزود |
| 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
يعترض معالج التجاوز (`open-sse/utils/bypassHandler.ts`) طلبات "الرمي" المعروفة من Claude CLI - أصوات التمهيد، واستخراج العناوين، وعدد الرموز المميزة - ويعيد **استجابة زائفة** دون استهلاك الرموز المميزة للموفر الرئيسي. يتم تشغيل هذا فقط عندما يحتوي `User-Agent` على `claude-cli`.
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
يوفر مسجل الطلب (`open-sse/utils/requestLogger.ts`) مسارًا لتسجيل تصحيح الأخطاء مكون من 7 مراحل، معطل افتراضيًا، وممكن عبر `ENABLE_REQUEST_LOGS=true`:
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
```
تتم كتابة الملفات إلى `<repo>/logs/<session>/` لكل جلسة طلب.
Files are written to `<repo>/logs/<session>/` for each request session.
## أوضاع الفشل والمرونة
## Failure Modes and Resilience
## 1) توفر الحساب/المزود
## 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) انتهاء صلاحية الرمز المميز
## 2) Token Expiry
- الفحص المسبق والتحديث مع إعادة المحاولة لموفري الخدمة القابلين للتحديث
- 401/403 إعادة المحاولة بعد محاولة التحديث في المسار الأساسي
- pre-check and refresh with retry for refreshable providers
- 401/403 retry after refresh attempt in core path
## 3) سلامة الدفق
## 3) Stream Safety
- وحدة تحكم تيار قطع الاتصال
- دفق الترجمة مع تدفق نهاية الدفق ومعالجة `[DONE]`
- احتياطي تقدير الاستخدام عندما تكون البيانات الوصفية لاستخدام الموفر مفقودة
- disconnect-aware stream controller
- translation stream with end-of-stream flush and `[DONE]` handling
- usage estimation fallback when provider usage metadata is missing
## 4) تدهور المزامنة السحابية
## 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) سلامة البيانات
## 5) Data Integrity
- ترحيل/إصلاح شكل قاعدة البيانات للمفاتيح المفقودة
- ضمانات إعادة تعيين JSON الفاسدة لـ localDb وuseDb
- SQLite schema migrations and auto-upgrade hooks at startup
- legacy JSON → SQLite migration compatibility path
## إمكانية الملاحظة والإشارات التشغيلية
## Observability and Operational Signals
مصادر رؤية وقت التشغيل:
Runtime visibility sources:
- سجلات وحدة التحكم من `src/sse/utils/logger.ts`
- مجاميع الاستخدام لكل طلب في `usage.json`
- سجل حالة الطلب النصي في `log.txt`
- سجلات الطلب/الترجمة العميقة الاختيارية ضمن `logs/` عندما `ENABLE_REQUEST_LOGS=true`
- نقاط نهاية استخدام لوحة المعلومات (`/api/usage/*`) لاستهلاك واجهة المستخدم
- 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 (`JWT_SECRET`) يؤمن التحقق/التوقيع على ملف تعريف الارتباط لجلسة لوحة المعلومات
- يجب تجاوز الاحتياطي الأولي لكلمة المرور (`INITIAL_PASSWORD`، الافتراضي `123456`) في عمليات النشر الحقيقية
- سر HMAC لمفتاح API (`API_KEY_SECRET`) يؤمن تنسيق مفتاح API المحلي الذي تم إنشاؤه
- تظل أسرار الموفر (مفاتيح/رموز واجهة برمجة التطبيقات) موجودة في قاعدة البيانات المحلية ويجب حمايتها على مستوى نظام الملفات
- تعتمد نقاط نهاية المزامنة السحابية على مصادقة مفتاح API + دلالات معرف الجهاز
- 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:
- التطبيق/المصادقة: `JWT_SECRET`، `INITIAL_PASSWORD`
- التخزين: `DATA_DIR`
- سلوك العقدة المتوافقة: `ALLOW_MULTI_CONNECTIONS_PER_COMPAT_NODE`
- تجاوز قاعدة التخزين الاختيارية (Linux/macOS عند إلغاء تعيين `DATA_DIR`): `XDG_CONFIG_HOME`
- التجزئة الأمنية: `API_KEY_SECRET`، `MACHINE_ID_SALT`
- التسجيل: `ENABLE_REQUEST_LOGS`
- عنوان URL للمزامنة/السحابة: `NEXT_PUBLIC_BASE_URL`، `NEXT_PUBLIC_CLOUD_URL`
- الوكيل الصادر: `HTTP_PROXY`، `HTTPS_PROXY`، `ALL_PROXY`، `NO_PROXY` ومتغيرات الأحرف الصغيرة
- علامات ميزات SOCKS5: `ENABLE_SOCKS5_PROXY`، `NEXT_PUBLIC_ENABLE_SOCKS5_PROXY`
- مساعدو النظام الأساسي/وقت التشغيل (ليس التكوين الخاص بالتطبيق): `APPDATA`، `NODE_ENV`، `PORT`، `HOSTNAME`
- 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` و`localDb` الآن نفس سياسة الدليل الأساسي (`DATA_DIR` -> `XDG_CONFIG_HOME/omniroute` -> `~/.omniroute`) مع ترحيل الملفات القديمة.
2. يقوم `/api/v1/route.ts` بإرجاع قائمة نماذج ثابتة وهو ليس مصدر النماذج الرئيسي الذي يستخدمه `/v1/models`.
3. يقوم مسجل الطلب بكتابة الرؤوس/النص الكامل عند تمكينه؛ التعامل مع دليل السجل على أنه حساس.
4. يعتمد سلوك السحابة على `NEXT_PUBLIC_BASE_URL` الصحيح وإمكانية الوصول إلى نقطة نهاية السحابة.
5. تم نشر الدليل `open-sse/` باسم `@omniroute/open-sse` **حزمة مساحة عمل npm**. يقوم كود المصدر باستيراده عبر `@omniroute/open-sse/...` (تم حله بواسطة Next.js `transpilePackages`). لا تزال مسارات الملفات في هذا المستند تستخدم اسم الدليل `open-sse/` لتحقيق الاتساق.
6. تستخدم المخططات الموجودة في لوحة المعلومات **Recharts** (المستندة إلى SVG) لتصورات التحليلات التفاعلية التي يمكن الوصول إليها (المخططات الشريطية لاستخدام النموذج، والجداول التفصيلية للموفرين مع معدلات النجاح).
7. تستخدم اختبارات E2E **Playwright** (`tests/e2e/`)، ويتم تشغيلها عبر `npm run test:e2e`. تستخدم اختبارات الوحدة **مشغل اختبار Node.js** (`tests/unit/`)، ويتم تشغيله عبر `npm run test:plan3`. كود المصدر ضمن `src/` هو **TypeScript** (`.ts`/`.tsx`)؛ تظل مساحة العمل `open-sse/` JavaScript (`.js`).
8. تم تنظيم صفحة الإعدادات في 5 علامات تبويب: الأمان، التوجيه (6 إستراتيجيات عالمية: التعبئة أولاً، جولة روبن، p2c، عشوائي، الأقل استخدامًا، تحسين التكلفة)، المرونة (حدود المعدل القابلة للتحرير، قاطع الدائرة، السياسات)، الذكاء الاصطناعي (ميزانية التفكير، موجه النظام، ذاكرة التخزين المؤقت السريعة)، المتقدم (الوكيل).
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
- البناء من المصدر: `npm run build`
- إنشاء صورة Docker: `docker build -t omniroute .`
- ابدأ الخدمة وتحقق:
- Build from source: `npm run build`
- Build Docker image: `docker build -t omniroute .`
- Start service and verify:
- `GET /api/settings`
- `GET /api/v1/models`
- يجب أن يكون عنوان URL الأساسي لهدف واجهة سطر الأوامر هو `http://<host>:20128/v1` عندما يكون `PORT=20128`
- CLI target base URL should be `http://<host>:20128/v1` when `PORT=20128`
+67
View File
@@ -0,0 +1,67 @@
🌐 **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 |
+351
View File
@@ -0,0 +1,351 @@
🌐 **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 — OmniRoute
يشرح هذا الدليل كيفية تثبيت وتهيئة جميع أدوات CLI المدعومة لاستخدام **OmniRoute** كخلفية موحدة.
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 / Gemini CLI / OpenCode / Cline / KiloCode / Continue / Kiro CLI
▼ (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
| 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 |
---
## 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
# 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 <command>` |
| `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"
```
+170 -166
View File
@@ -1,22 +1,26 @@
# الطريق الشامل - وثائق قاعدة التعليمات البرمجية
🌐 **Languages:** 🇺🇸 [English](../../CODEBASE_DOCUMENTATION.md) | 🇧🇷 [Português (Brasil)](../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) | 🇩🇰 [Dansk](../da/CODEBASE_DOCUMENTATION.md) | 🇫🇮 [Suomi](../fi/CODEBASE_DOCUMENTATION.md) | 🇮🇱 [עברית](../he/CODEBASE_DOCUMENTATION.md) | 🇭🇺 [Magyar](../hu/CODEBASE_DOCUMENTATION.md) | 🇮🇩 [Bahasa Indonesia](../id/CODEBASE_DOCUMENTATION.md) | 🇰🇷 [한국어](../ko/CODEBASE_DOCUMENTATION.md) | 🇲🇾 [Bahasa Melayu](../ms/CODEBASE_DOCUMENTATION.md) | 🇳🇱 [Nederlands](../nl/CODEBASE_DOCUMENTATION.md) | 🇳🇴 [Norsk](../no/CODEBASE_DOCUMENTATION.md) | 🇵🇹 [Português (Portugal)](../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) | 🇵🇭 [Filipino](../phi/CODEBASE_DOCUMENTATION.md)
> دليل شامل ومناسب للمبتدئين إلى جهاز التوجيه الوكيل AI **omniroute** متعدد الموفرين.
🌐 **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)
---
## 1. ما هو الطريق الشامل؟
# omniroute — Codebase Documentation
omniroute هو **جهاز توجيه وكيل** يقع بين عملاء الذكاء الاصطناعي (Claude CLI، وCodex، وCursor IDE، وما إلى ذلك) وموفري الذكاء الاصطناعي (Anthropic، وGoogle، وOpenAI، وAWS، وGitHub، وما إلى ذلك). إنه يحل مشكلة واحدة كبيرة:
🌐 **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.
---
## 2. نظرة عامة على الهندسة المعمارية
## 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
@@ -61,20 +65,20 @@ graph LR
H -.-> G
```
### المبدأ الأساسي: الترجمة المحورية
### Core Principle: Hub-and-Spoke Translation
تمر جميع ترجمة التنسيقات عبر **تنسيق OpenAI كمركز**:
All format translation passes through **OpenAI format as the hub**:
```
Client Format → [OpenAI Hub] → Provider Format (request)
Provider Format → [OpenAI Hub] → Client Format (response)
```
هذا يعني أنك تحتاج فقط إلى مترجمين **N** (واحد لكل تنسيق) بدلاً من **N²** (كل زوج).
This means you only need **N translators** (one per format) instead of **N²** (every pair).
---
## 3. هيكل المشروع
## 3. Project Structure
```
omniroute/
@@ -104,22 +108,22 @@ omniroute/
---
## 4. تفصيل الوحدة تلو الأخرى
## 4. Module-by-Module Breakdown
### 4.1 التكوين (`open-sse/config/`)
### 4.1 Config (`open-sse/config/`)
**المصدر الوحيد للحقيقة** لجميع إعدادات الموفر.
The **single source of truth** for all provider configuration.
| ملف | الغرض |
| ----------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `constants.ts` | كائن `PROVIDERS` يحتوي على عناوين URL الأساسية وبيانات اعتماد OAuth (الافتراضية) والرؤوس ومطالبات النظام الافتراضية لكل موفر. يحدد أيضًا `HTTP_STATUS`، و`ERROR_TYPES`، و`COOLDOWN_MS`، و`BACKOFF_CONFIG`، و`SKIP_PATTERNS`. |
| `credentialLoader.ts` | يقوم بتحميل بيانات الاعتماد الخارجية من `data/provider-credentials.json` ويدمجها في الإعدادات الافتراضية المشفرة في `PROVIDERS`. يحافظ على الأسرار خارج نطاق التحكم بالمصدر مع الحفاظ على التوافق مع الإصدارات السابقة. |
| `providerModels.ts` | سجل النموذج المركزي: الأسماء المستعارة لموفر الخرائط → معرفات النموذج. وظائف مثل `getModels()`، `getProviderByAlias()`. |
| `codexInstructions.ts` | تعليمات النظام التي تم إدخالها في طلبات الدستور الغذائي (قيود التحرير، قواعد الاختبار، سياسات الموافقة). |
| `defaultThinkingSignature.ts` | توقيعات "التفكير" الافتراضية لنماذج كلود وجيميني. |
| `ollamaModels.ts` | تعريف المخطط لنماذج أولاما المحلية (الاسم، الحجم، العائلة، التكميم). |
| 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
@@ -142,9 +146,9 @@ flowchart TD
---
### 4.2 المنفذون (`open-sse/executors/`)
### 4.2 Executors (`open-sse/executors/`)
يقوم المنفذون بتغليف **المنطق الخاص بالمزود** باستخدام **نمط الإستراتيجية**. يتجاوز كل منفذ الأساليب الأساسية حسب الحاجة.
Executors encapsulate **provider-specific logic** using the **Strategy Pattern**. Each executor overrides base methods as needed.
```mermaid
classDiagram
@@ -194,32 +198,32 @@ classDiagram
BaseExecutor <|-- GithubExecutor
```
| المنفذ | مقدم | التخصصات الرئيسية |
| ---------------- | --------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------- |
| `base.ts` | — | قاعدة الملخصات: إنشاء عنوان URL، والرؤوس، ومنطق إعادة المحاولة، وتحديث بيانات الاعتماد |
| `default.ts` | كلود، جيميني، أوبن آي آي، جي إل إم، كيمي، ميني ماكس | تحديث رمز OAuth العام للموفرين القياسيين |
| `antigravity.ts` | جوجل كلاود كود | إنشاء معرف المشروع/الجلسة، وإرجاع عناوين URL المتعددة، وإعادة محاولة التحليل المخصصة من رسائل الخطأ ("إعادة التعيين بعد 2 ساعة و7 دقائق و23 ثانية") |
| `cursor.ts` | بيئة تطوير متكاملة للمؤشر | **الأكثر تعقيدًا**: مصادقة المجموع الاختباري SHA-256، وترميز طلب Protobuf، وEventStream الثنائي → تحليل استجابة SSE |
| `codex.ts` | OpenAI Codex | إدخال تعليمات النظام، وإدارة مستويات التفكير، وإزالة المعلمات غير المدعومة |
| `gemini-cli.ts` | جوجل الجوزاء CLI | بناء عنوان URL المخصص (`streamGenerateContent`)، تحديث رمز OAuth المميز لـ Google |
| `github.ts` | جيثب مساعد الطيار | نظام الرمز المزدوج (GitHub OAuth + Copilot token)، محاكاة رأس VSCode |
| `kiro.ts` | AWS CodeWhisperer | التحليل الثنائي لـ AWS EventStream، وإطارات أحداث AMZN، وتقدير الرمز المميز |
| `index.ts` | — | المصنع: اسم موفر الخرائط ← فئة المنفذ، مع خيار احتياطي افتراضي |
| 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 المعالجات (`open-sse/handlers/`)
### 4.3 Handlers (`open-sse/handlers/`)
**طبقة التنسيق** — تتولى تنسيق الترجمة والتنفيذ والتدفق ومعالجة الأخطاء.
The **orchestration layer**coordinates translation, execution, streaming, and error handling.
| ملف | الغرض |
| --------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `chatCore.ts` | ** المنسق المركزي ** (~ 600 سطر). يتعامل مع دورة حياة الطلب الكاملة: اكتشاف التنسيق ← الترجمة ← إرسال المنفذ ← استجابة التدفق/غير المتدفق ← تحديث الرمز المميز ← معالجة الأخطاء ← تسجيل الاستخدام. |
| `responsesHandler.ts` | محول واجهة برمجة تطبيقات استجابات OpenAI: يحول تنسيق الردود ← إكمالات الدردشة ← يرسل إلى `chatCore` ← يحول SSE مرة أخرى إلى تنسيق الردود. |
| `embeddings.ts` | معالج إنشاء التضمين: يحل نموذج التضمين → الموفر، ويرسل إلى واجهة برمجة تطبيقات الموفر، ويعيد استجابة التضمين المتوافقة مع OpenAI. يدعم 6+ مقدمي الخدمات. |
| `imageGeneration.ts` | معالج إنشاء الصور: يحل نموذج الصورة → الموفر، ويدعم الأوضاع المتوافقة مع OpenAI، وGemini-image (Antigravity)، والوضع الاحتياطي (Nebius). إرجاع صور base64 أو URL. |
| 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. |
#### دورة حياة الطلب (chatCore.ts)
#### Request Lifecycle (chatCore.ts)
```mermaid
sequenceDiagram
@@ -258,28 +262,28 @@ sequenceDiagram
---
### 4.4 الخدمات (`open-sse/services/`)
### 4.4 Services (`open-sse/services/`)
منطق الأعمال الذي يدعم المعالجات والمنفذين.
Business logic that supports the handlers and executors.
| ملف | الغرض |
| -------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `provider.ts` | **كشف التنسيق** (`detectFormat`): تحليلات بنية الجسم لتحديد تنسيقات Claude/OpenAI/Gemini/Antigravity/Responses (تتضمن `max_tokens` الاستدلال لكلود). أيضًا: بناء عنوان URL، وبناء الرأس، وتطبيع تكوين التفكير. يدعم موفري الخدمات الديناميكيين `openai-compatible-*` و`anthropic-compatible-*`. |
| `model.ts` | تحليل سلسلة النموذج (`claude/model-name``{provider: "claude", model: "model-name"}`)، ودقة الاسم المستعار مع اكتشاف التصادم، وتعقيم الإدخال (يرفض أحرف اجتياز المسار/التحكم)، ودقة معلومات النموذج مع دعم getter للاسم المستعار غير المتزامن. |
| `accountFallback.ts` | التعامل مع الحد الأقصى للمعدل: التراجع الأسي (1s → 2s → 4s → 2min كحد أقصى)، وإدارة فترة تهدئة الحساب، وتصنيف الأخطاء (أي الأخطاء تؤدي إلى التراجع مقابل عدم حدوثه). |
| `tokenRefresh.ts` | تحديث رمز OAuth المميز **لكل مزود**: Google (Gemini، Antigravity)، Claude، Codex، Qwen، iFlow، GitHub (OAuth + Copilot Dual-Token)، Kiro (AWS SSO OIDC + Social Auth). يتضمن ذاكرة تخزين مؤقت لإلغاء البيانات المكررة أثناء الرحلة وإعادة المحاولة مع التراجع المتسارع. |
| `combo.ts` | **نماذج مجمعة**: سلاسل من النماذج الاحتياطية. إذا فشل النموذج A مع وجود خطأ مؤهل للرجوع إليه، فجرّب النموذج B، ثم C، وما إلى ذلك. يقوم بإرجاع رموز الحالة الأولية الفعلية. |
| `usage.ts` | جلب بيانات الحصص/الاستخدام من واجهات برمجة تطبيقات الموفر (حصص GitHub Copilot، وحصص نماذج Antigravity، وحدود معدل Codex، وأعطال استخدام Kiro، وإعدادات Claude). |
| `accountSelector.ts` | اختيار الحساب الذكي باستخدام خوارزمية التسجيل: يأخذ في الاعتبار الأولوية والحالة الصحية والموضع الدائري وحالة التهدئة لاختيار الحساب الأمثل لكل طلب. |
| `contextManager.ts` | إدارة دورة حياة سياق الطلب: إنشاء وتتبع كائنات السياق لكل طلب باستخدام بيانات التعريف (معرف الطلب، والطوابع الزمنية، ومعلومات الموفر) لتصحيح الأخطاء والتسجيل. |
| `ipFilter.ts` | التحكم في الوصول المستند إلى IP: يدعم وضعي القائمة المسموح بها والقائمة المحظورة. التحقق من صحة عنوان IP للعميل مقابل القواعد التي تم تكوينها قبل معالجة طلبات واجهة برمجة التطبيقات. |
| `sessionManager.ts` | تتبع الجلسة باستخدام بصمة العميل: يتتبع الجلسات النشطة باستخدام معرفات العميل المجزأة، ويراقب عدد الطلبات، ويوفر مقاييس الجلسة. |
| `signatureCache.ts` | طلب ذاكرة التخزين المؤقت لإلغاء البيانات المكررة المستندة إلى التوقيع: يمنع الطلبات المكررة عن طريق تخزين توقيعات الطلب الأخيرة مؤقتًا وإرجاع الاستجابات المخزنة مؤقتًا للطلبات المتطابقة خلال نافذة زمنية. |
| `systemPrompt.ts` | الحقن الفوري للنظام العالمي: يُلحق أو يُلحق موجه نظام قابل للتكوين لجميع الطلبات، مع معالجة التوافق لكل مزود. |
| `thinkingBudget.ts` | إدارة ميزانية الرموز المميزة: تدعم أوضاع المرور، والتلقائي (تكوين التفكير الشريطي)، والمخصص (الميزانية الثابتة)، والتكيفية (مدرجة التعقيد) للتحكم في رموز التفكير/الاستدلال. |
| `wildcardRouter.ts` | توجيه نمط نموذج حرف البدل: يحل أنماط حرف البدل (على سبيل المثال، `*/claude-*`) لأزواج الموفر/النموذج الملموسة بناءً على التوفر والأولوية. |
| 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, iFlow, 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
@@ -300,7 +304,7 @@ sequenceDiagram
Cache->>Cache: Delete cache entry
```
#### آلة الحالة الاحتياطية للحساب
#### Account Fallback State Machine
```mermaid
stateDiagram-v2
@@ -325,7 +329,7 @@ stateDiagram-v2
}
```
#### سلسلة نماذج كومبو
#### Combo Model Chain
```mermaid
flowchart LR
@@ -344,11 +348,11 @@ flowchart LR
---
### مترجم 4.5 (`open-sse/translator/`)
### 4.5 Translator (`open-sse/translator/`)
**محرك ترجمة التنسيق** باستخدام نظام إضافي للتسجيل الذاتي.
The **format translation engine** using a self-registering plugin system.
####الهندسة المعمارية
#### Architecture
```mermaid
graph TD
@@ -374,15 +378,15 @@ graph TD
end
```
| الدليل | ملفات | الوصف |
| ------------ | --------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `request/` | 8 مترجمين | تحويل أجسام الطلب بين الصيغ. يتم تسجيل كل ملف ذاتيًا عبر `register(from, to, fn)` عند الاستيراد. |
| `response/` | 7 مترجمين | تحويل قطع الاستجابة المتدفقة بين الصيغ. يتعامل مع أنواع أحداث SSE وكتل التفكير واستدعاءات الأدوات. |
| `helpers/` | 6 مساعدين | الأدوات المساعدة المشتركة: `claudeHelper` (استخراج موجه النظام، تكوين التفكير)، `geminiHelper` (تعيين الأجزاء/المحتويات)، `openaiHelper` (تصفية التنسيق)، `toolCallHelper` (إنشاء المعرف، حقن الاستجابة المفقودة)، `maxTokensHelper`، `responsesApiHelper`. |
| `index.ts` | — | محرك الترجمة: `translateRequest()`، `translateResponse()`، إدارة الحالة، التسجيل. |
| `formats.ts` | — | ثوابت التنسيق: `OPENAI`، `CLAUDE`، `GEMINI`، `ANTIGRAVITY`، `KIRO`، `CURSOR`، `OPENAI_RESPONSES`. |
| 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:
@@ -395,19 +399,19 @@ import "./request/claude-to-openai.js"; // ← self-registers
---
### 4.6 الأدوات المساعدة (`open-sse/utils/`)
### 4.6 Utils (`open-sse/utils/`)
| ملف | الغرض |
| ------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `error.ts` | إنشاء استجابة للأخطاء (تنسيق متوافق مع OpenAI)، وتحليل الأخطاء الأولية، واستخراج وقت إعادة محاولة Antigravity من رسائل الخطأ، وتدفق أخطاء SSE. |
| `stream.ts` | **SSE Transform Stream**خط أنابيب البث الأساسي. وضعان: `TRANSLATE` (ترجمة التنسيق الكامل) و`PASSTHROUGH` (تطبيع + استخراج الاستخدام). يتعامل مع التخزين المؤقت للقطعة وتقدير الاستخدام وتتبع طول المحتوى. تتجنب مثيلات وحدة التشفير/وحدة فك التشفير لكل تيار الحالة المشتركة. |
| `streamHelpers.ts` | أدوات SSE ذات المستوى المنخفض: `parseSSELine` (تتحمل المسافات البيضاء)، `hasValuableContent` (تصفية الأجزاء الفارغة لـ OpenAI/Claude/Gemini)، `fixInvalidId`، `formatSSE` (تسلسل SSE مدرك للتنسيق مع تنظيف `perf_metrics`). |
| `usageTracking.ts` | استخراج استخدام الرمز المميز من أي تنسيق (Claude/OpenAI/Gemini/Responses)، والتقدير باستخدام نسب الأحرف لكل رمز مميز للأداة/الرسالة، وإضافة المخزن المؤقت (هامش أمان 2000 رمز مميز)، وتصفية الحقول الخاصة بالتنسيق، وتسجيل وحدة التحكم بألوان ANSI. |
| `requestLogger.ts` | تسجيل الطلب المستند إلى الملف (الاشتراك عبر `ENABLE_REQUEST_LOGS=true`). ينشئ مجلدات الجلسة بملفات مرقمة: `1_req_client.json``7_res_client.txt`. كل عمليات الإدخال/الإخراج غير متزامنة (أطلق النار وانسى). أقنعة الرؤوس الحساسة. |
| `bypassHandler.ts` | يعترض أنماطًا محددة من Claude CLI (استخراج العنوان، والتحمية، والعد) ويعيد استجابات مزيفة دون الاتصال بأي مزود. يدعم كلا من الدفق وغير الدفق. يقتصر عمدا على نطاق كلود CLI. |
| `networkProxy.ts` | يحل عنوان URL للوكيل الصادر لموفر معين مع الأسبقية: التكوين الخاص بالموفر → التكوين العام → متغيرات البيئة (`HTTPS_PROXY`/`HTTP_PROXY`/`ALL_PROXY`). يدعم استثناءات `NO_PROXY`. تكوين ذاكرة التخزين المؤقت لمدة 30 ثانية. |
| 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
#### SSE Streaming Pipeline
```mermaid
flowchart TD
@@ -429,7 +433,7 @@ flowchart TD
style M fill:#9f9,stroke:#333
```
#### بنية جلسة مسجل الطلب
#### Request Logger Session Structure
```
logs/
@@ -447,109 +451,109 @@ logs/
---
### 4.7 طبقة التطبيق (`src/`)
### 4.7 Application Layer (`src/`)
| الدليل | الغرض |
| ------------- | ------------------------------------------------------------------------------------------------------- |
| `src/app/` | واجهة مستخدم الويب، مسارات واجهة برمجة التطبيقات (API)، البرامج الوسيطة السريعة، معالجات رد اتصال OAuth |
| `src/lib/` | الوصول إلى قاعدة البيانات (`localDb.ts`، `usageDb.ts`)، المصادقة، مشتركة |
| `src/mitm/` | أدوات مساعدة للوكيل الوسيط لاعتراض حركة مرور الموفر |
| `src/models/` | تعريفات نماذج قواعد البيانات |
| `src/shared/` | أغلفة حول وظائف open-sse (المزود، الدفق، الخطأ، إلخ) |
| `src/sse/` | معالجات نقطة نهاية SSE التي تربط مكتبة open-sse بمسارات Express |
| `src/store/` | إدارة حالة التطبيق |
| 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 |
#### مسارات API البارزة
#### Notable API Routes
| الطريق | طرق | الغرض |
| --------------------------------------------- | ------------------ | ------------------------------------------------------------------------------ |
| `/api/provider-models` | الحصول على/نشر/حذف | CRUD للنماذج المخصصة لكل مزود |
| `/api/models/catalog` | احصل على | كتالوج مجمع لجميع النماذج (الدردشة، التضمين، الصورة، المخصصة) مجمعة حسب الموفر |
| `/api/settings/proxy` | الحصول على/وضع/حذف | تكوين الوكيل الصادر الهرمي (`global/providers/combos/keys`) |
| `/api/settings/proxy/test` | مشاركة | التحقق من صحة اتصال الوكيل وإرجاع IP/زمن الوصول العام |
| `/v1/providers/[provider]/chat/completions` | مشاركة | عمليات إكمال الدردشة المخصصة لكل مزود مع التحقق من صحة النموذج |
| `/v1/providers/[provider]/embeddings` | مشاركة | عمليات التضمين المخصصة لكل مزود مع التحقق من صحة النموذج |
| `/v1/providers/[provider]/images/generations` | مشاركة | إنشاء صور مخصصة لكل مزود مع التحقق من صحة النموذج |
| `/api/settings/ip-filter` | الحصول على/وضع | قائمة IP المسموح بها/إدارة القائمة المحظورة |
| `/api/settings/thinking-budget` | الحصول على/وضع | تكوين ميزانية الرمز المميز (العبور/التلقائي/المخصص/التكيفي) |
| `/api/settings/system-prompt` | الحصول على/وضع | الحقن الفوري للنظام العالمي لجميع الطلبات |
| `/api/sessions` | احصل على | تتبع الجلسة النشطة ومقاييسها |
| `/api/rate-limits` | احصل على | حالة حد المعدل لكل حساب |
| 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. أنماط التصميم الرئيسية
## 5. Key Design Patterns
### 5.1 الترجمة المحورية والمتحدثة
### 5.1 Hub-and-Spoke Translation
تتم ترجمة جميع التنسيقات من خلال **تنسيق OpenAI كمحور**. لا تتطلب إضافة موفر جديد سوى كتابة **زوج واحد** من المترجمين (من/إلى OpenAI)، وليس عدد N من المترجمين.
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 نمط استراتيجية المنفذ
### 5.2 Executor Strategy Pattern
كل مزود لديه فئة منفذة مخصصة ترث من `BaseExecutor`. يقوم المصنع في `executors/index.ts` باختيار المصنع المناسب في وقت التشغيل.
Each provider has a dedicated executor class inheriting from `BaseExecutor`. The factory in `executors/index.ts` selects the right one at runtime.
### 5.3 نظام البرنامج المساعد للتسجيل الذاتي
### 5.3 Self-Registering Plugin System
تسجل وحدات المترجم نفسها عند الاستيراد عبر `register()`. إن إضافة مترجم جديد يعني مجرد إنشاء ملف واستيراده.
Translator modules register themselves on import via `register()`. Adding a new translator is just creating a file and importing it.
### 5.4 التراجع في الحساب مع التراجع الأسي
### 5.4 Account Fallback with Exponential Backoff
عندما يقوم مقدم الخدمة بإرجاع 429/401/500، يمكن للنظام التبديل إلى الحساب التالي، مع تطبيق فترات التباطؤ الأسية (1ث → 2ث → 4ث2 دقيقة كحد أقصى).
When a provider returns 429/401/500, the system can switch to the next account, applying exponential cooldowns (1s → 2s → 4smax 2min).
### 5.5 سلاسل نماذج كومبو
### 5.5 Combo Model Chains
يقوم "التحرير والسرد" بتجميع سلاسل `provider/model` متعددة. إذا فشل الأول، يتم الرجوع إلى التالي تلقائيًا.
A "combo" groups multiple `provider/model` strings. If the first fails, fallback to the next automatically.
### 5.6 ترجمة متدفقة رائعة
### 5.6 Stateful Streaming Translation
تحافظ ترجمة الاستجابة على الحالة عبر أجزاء SSE (تتبع كتلة التفكير، وتراكم استدعاءات الأداة، وفهرسة كتلة المحتوى) عبر آلية `initState()`.
Response translation maintains state across SSE chunks (thinking block tracking, tool call accumulation, content block indexing) via the `initState()` mechanism.
### 5.7 المخزن المؤقت لسلامة الاستخدام
### 5.7 Usage Safety Buffer
تتم إضافة مخزن مؤقت مكون من 2000 رمز مميز إلى الاستخدام المبلغ عنه لمنع العملاء من الوصول إلى حدود نافذة السياق بسبب الحمل الزائد من مطالبات النظام وترجمة التنسيق.
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. التنسيقات المدعومة
## 6. Supported Formats
| تنسيق | الاتجاه | المعرف |
| ----------------------------------- | -------------- | ------------------ |
| استكمالات الدردشة OpenAI | المصدر + الهدف | `openai` |
| واجهة برمجة تطبيقات استجابات OpenAI | المصدر + الهدف | `openai-responses` |
| أنثروبي كلود | المصدر + الهدف | `claude` |
| جوجل الجوزاء | المصدر + الهدف | `gemini` |
| جوجل الجوزاء CLI | الهدف فقط | `gemini-cli` |
| مكافحة الجاذبية | المصدر + الهدف | `antigravity` |
| أوس كيرو | الهدف فقط | `kiro` |
| المؤشر | الهدف فقط | `cursor` |
| 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. مقدمو الخدمة المدعومين
## 7. Supported Providers
| مقدم | طريقة المصادقة | المنفذ | الملاحظات الرئيسية |
| ------------------------- | ------------------------ | --------------- | --------------------------------------------------------- |
| أنثروبي كلود | مفتاح API أو OAuth | الافتراضي | يستخدم رأس `x-api-key` |
| جوجل الجوزاء | مفتاح API أو OAuth | الافتراضي | يستخدم رأس `x-goog-api-key` |
| جوجل الجوزاء CLI | أووث | الجوزاء كلي | يستخدم `streamGenerateContent` نقطة النهاية |
| مكافحة الجاذبية | أووث | مكافحة الجاذبية | احتياطي عناوين URL المتعددة، إعادة محاولة التحليل المخصصة |
| أوبن آي | مفتاح API | الافتراضي | مصادقة حامل المعيار |
| الدستور الغذائي | أووث | الدستور الغذائي | يدخل تعليمات النظام ويدير التفكير |
| جيثب مساعد الطيار | OAuth + رمز مساعد الطيار | جيثب | رمز مزدوج، محاكاة رأس VSCode |
| كيرو (AWS) | AWS SSO OIDC أو Social | كيرو | تحليل دفق الأحداث الثنائية |
| بيئة تطوير متكاملة للمؤشر | مصادقة المجموع الاختباري | المؤشر | ترميز Protobuf، المجموع الاختباري SHA-256 |
| كوين | أووث | الافتراضي | المصادقة القياسية |
| اي فلو | OAuth (أساسي + حامل) | الافتراضي | رأس المصادقة المزدوجة |
| اوبن راوتر | مفتاح API | الافتراضي | مصادقة حامل المعيار |
| جي إل إم، كيمي، ميني ماكس | مفتاح API | الافتراضي | متوافق مع كلود، استخدم `x-api-key` |
| `openai-compatible-*` | مفتاح API | الافتراضي | ديناميكي: أي نقطة نهاية متوافقة مع OpenAI |
| `anthropic-compatible-*` | مفتاح API | الافتراضي | ديناميكي: أي نقطة نهاية متوافقة مع كلود |
| 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 |
| iFlow | 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. ملخص تدفق البيانات
## 8. Data Flow Summary
### طلب البث
### Streaming Request
```mermaid
flowchart LR
@@ -566,7 +570,7 @@ flowchart LR
K --> L["logUsage()\nsaveRequestUsage()"]
```
### طلب عدم البث
### Non-Streaming Request
```mermaid
flowchart LR
@@ -577,7 +581,7 @@ flowchart LR
E --> F["Return JSON\nresponse"]
```
### تجاوز التدفق (كلود CLI)
### Bypass Flow (Claude CLI)
```mermaid
flowchart LR
+91 -21
View File
@@ -1,77 +1,147 @@
# OmniRoute — معرض ميزات لوحة المعلومات
# OmniRoute — Dashboard Features Gallery (العربية)
🌐 **Languages:** 🇺🇸 [English](../../FEATURES.md) | 🇧🇷 [Português (Brasil)](../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) | 🇩🇰 [Dansk](../da/FEATURES.md) | 🇫🇮 [Suomi](../fi/FEATURES.md) | 🇮🇱 [עברית](../he/FEATURES.md) | 🇭🇺 [Magyar](../hu/FEATURES.md) | 🇮🇩 [Bahasa Indonesia](../id/FEATURES.md) | 🇰🇷 [한국어](../ko/FEATURES.md) | 🇲🇾 [Bahasa Melayu](../ms/FEATURES.md) | 🇳🇱 [Nederlands](../nl/FEATURES.md) | 🇳🇴 [Norsk](../no/FEATURES.md) | 🇵🇹 [Português (Portugal)](../pt/FEATURES.md) | 🇷🇴 [Română](../ro/FEATURES.md) | 🇵🇱 [Polski](../pl/FEATURES.md) | 🇸🇰 [Slovenčina](../sk/FEATURES.md) | 🇸🇪 [Svenska](../sv/FEATURES.md) | 🇵🇭 [Filipino](../phi/FEATURES.md)
🌐 **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)
دليل مرئي لكل قسم من لوحة معلومات OmniRoute.
> 🇺🇸 [English](../../../docs/FEATURES.md)
---
## 🔌 مقدمو الخدمة
Visual guide to every section of the OmniRoute dashboard.
إدارة اتصالات مزودي الذكاء الاصطناعي: موفري OAuth (Claude Code وCodex وGemini CLI) وموفري مفاتيح API (Groq وDeepSeek وOpenRouter) ومقدمي الخدمات المجانية (iFlow وQwen وKiro).
---
## 🔌 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.
![Providers Dashboard](screenshots/01-providers.png)
---
## 🎨 المجموعات
## 🎨 Combos
أنشئ مجموعات توجيه النماذج باستخدام 6 إستراتيجيات: التعبئة أولاً، والتدوير الدائري، وقوة الاختيارين، والعشوائية، والأقل استخدامًا، والمُحسَّنة من حيث التكلفة. تقوم كل مجموعة بتسلسل نماذج متعددة مع الرجوع التلقائي.
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.
![Combos Dashboard](screenshots/02-combos.png)
---
## 📊تحليلات
## 📊 Analytics
تحليلات استخدام شاملة مع استهلاك الرمز المميز، وتقديرات التكلفة، وخرائط النشاط، ومخططات التوزيع الأسبوعية، والتفاصيل لكل مزود.
Comprehensive usage analytics with token consumption, cost estimates, activity heatmaps, weekly distribution charts, and per-provider breakdowns.
![Analytics Dashboard](screenshots/03-analytics.png)
---
## 🏥 صحة النظام
## 🏥 System Health
المراقبة في الوقت الفعلي: وقت التشغيل، والذاكرة، والإصدار، والنسب المئوية لزمن الوصول (p50/p95/p99)، وإحصائيات ذاكرة التخزين المؤقت، وحالات قاطع دائرة الموفر.
Real-time monitoring: uptime, memory, version, latency percentiles (p50/p95/p99), cache statistics, and provider circuit breaker states.
![Health Dashboard](screenshots/04-health.png)
---
## 🔧 ملعب المترجم
## 🔧 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).
![Translator Playground](screenshots/05-translator.png)
---
## ⚙️ الإعدادات
## 🎮 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
- **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
![Settings Dashboard](screenshots/06-settings.png)
---
## 🔧 أدوات CLI
## 🔧 CLI Tools
تكوين بنقرة واحدة لأدوات ترميز الذكاء الاصطناعي: Claude Code، وCodex CLI، وGemini CLI، وOpenClaw، وKilo Code، وAntigravity.
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 Tools Dashboard](screenshots/07-cli-tools.png)
---
## 📝 سجلات الطلب
## 🤖 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.
![Usage Logs](screenshots/08-usage.png)
---
## 🌐 نقطة نهاية API
## 🌐 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.
![Endpoint Dashboard](screenshots/09-endpoint.png)
---
## 🔑 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.
+87
View File
@@ -0,0 +1,87 @@
🌐 **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 |
+43 -63
View File
@@ -8,51 +8,6 @@ _وكيل API العالمي الخاص بك - نقطة نهاية واحدة،
---
<div align="center">
[![إصدار npm](https://img.shields.io/npm/v/omniroute?color=cb3837&logo=npm)](https://www.npmjs.com/package/omniroute)
[![Docker Hub](https://img.shields.io/docker/v/diegosouzapw/omniroute?label=Docker%20Hub&logo=docker&color=2496ED)](https://hub.docker.com/r/diegosouzapw/omniroute)
[![الترخيص](https://img.shields.io/github/license/diegosouzapw/OmniRoute)](https://github.com/diegosouzapw/OmniRoute/blob/main/LICENSE)
[![موقع الويب](https://img.shields.io/badge/Website-omniroute.online-blue?logo=google-chrome&logoColor=white)](https://omniroute.online)
[![WhatsApp](https://img.shields.io/badge/WhatsApp-Community-25D366?logo=whatsapp&logoColor=white)](https://chat.whatsapp.com/JI7cDQ1GyaiDHhVBpLxf8b?mode=gi_t)
[🌐 الموقع الإلكتروني](https://omniroute.online) • [🚀 البداية السريعة](#-quick-start) • [💡 الميزات](#-key-features) • [📖 المستندات](#-documentation) • [💰 التسعير](#-pricing-at-a-glance) • [💬 واتساب](https://chat.whatsapp.com/JI7cDQ1GyaiDHhVBpLxf8b?mode=gi_t)
</div>
🌐 **متوفر باللغة:** 🇺🇸 [الإنجليزية](README.md) | 🇧🇷 [البرتغالية (البرازيل)](README.pt-BR.md) | 🇪🇸 [الإسبانية](README.es.md) | 🇫🇷 [Français](README.fr.md) | 🇮🇹 [الإيطالية](README.it.md) | 🇷🇺 [Русский](README.ru.md) | 🇨🇳 [中文 (简体)](README.zh-CN.md) | 🇩🇪 [الألمانية](README.de.md) | 🇮🇳 [هندي](README.in.md) | 🇹🇭 [ไทย](README.th.md) | 🇺🇦 [أوكرانيا](README.uk-UA.md) | 🇸🇦 [العربية](README.ar.md) | 🇯🇵 [日本語](README.ja.md) | 🇻🇳 [تيانج فيت](README.vi.md) | 🇧🇬 [بلغارسكي](README.bg.md) | 🇩🇰 [الدانسك](README.da.md) | 🇫🇮 [سومي](README.fi.md) | 🇮🇱 [العربية](README.he.md) | 🇭🇺 [المجرية](README.hu.md) | 🇮🇩 [البهاسا الإندونيسية](README.id.md) | 🇰🇷 [한국어](README.ko.md) | 🇲🇾 [البهاسا ملايو](README.ms.md) | 🇳🇱 [هولندا](README.nl.md) | 🇳🇴 [نورسك](README.no.md) | 🇵🇹 [البرتغالية (البرتغال)](README.pt.md) | 🇷🇴 [روماني](README.ro.md) | 🇵🇱 [بولسكي](README.pl.md) | 🇸🇰 [سلوفينسينا](README.sk.md) | 🇸🇪 [سفينسكا](README.sv.md) | 🇵🇭 [فلبينية](README.phi.md)
---
## 🖼️ لوحة التحكم الرئيسية
<div align="center">
<img src="./docs/screenshots/MainOmniRoute.png" alt="OmniRoute Dashboard" width="800"/>
</div>
---
## 📸 معاينة لوحة التحكم
<details>
<summary><b>انقر لرؤية لقطات شاشة لوحة القيادة</b></summary>
| صفحة | لقطة شاشة |
| --------------------- | -------------------------------------------------- |
| ** مقدمو الخدمة ** | ![مقدمو الخدمة](docs/screenshots/01-providers.png) |
| **المجموعات** | ![المجموعات](docs/screenshots/02-combos.png) |
| **تحليلات** | ![تحليلات](docs/screenshots/03-analytics.png) |
| **الصحة** | ![الصحة](docs/screenshots/04-health.png) |
| **مترجم** | ![مترجم](docs/screenshots/05-translator.png) |
| **الإعدادات** | ![الإعدادات](docs/screenshots/06-settings.png) |
| **أدوات سطر الأوامر** | ![أدوات CLI](docs/screenshots/07-cli-tools.png) |
| **سجلات الاستخدام** | ![الاستخدام](docs/screenshots/08-usage.png) |
| **نقطة النهاية** | ![نقطة النهاية](docs/screenshots/09-endpoint.png) |
</details>
---
### 🤖 موفر الذكاء الاصطناعي المجاني لوكلاء البرمجة المفضلين لديك
_قم بتوصيل أي أداة IDE أو CLI مدعومة بالذكاء الاصطناعي من خلال OmniRoute - بوابة واجهة برمجة التطبيقات المجانية للترميز غير المحدود._
@@ -137,6 +92,34 @@ _قم بتوصيل أي أداة IDE أو CLI مدعومة بالذكاء الا
---
### 🆕 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 `<omniModel>` 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 |
### 🆕 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 `<omniModel>` 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 |
---
## 🤔 لماذا OmniRoute؟
**توقف عن إهدار المال وضرب الحدود:**
@@ -253,6 +236,7 @@ Result: Never stop coding, minimal cost
**كيف يحل OmniRoute المشكلة:**
- **موفرو الطبقة المجانية المضمنون** — دعم أصلي لمقدمي الخدمات المجانيين بنسبة 100%: iFlow (8 نماذج غير محدودة)، Qwen (3 نماذج غير محدودة)، Kiro (Claude مجانًا)، Gemini CLI (180 ألف/شهر مجانًا)
- **Ollama Cloud** — Cloud-hosted Ollama models at `api.ollama.com` with free "Light usage" tier; use `ollamacloud/<model>` prefix
- **المجموعات المجانية فقط** — السلسلة `gc/gemini-3-flash → if/kimi-k2-thinking → qw/qwen3-coder-plus` = 0 USD/الشهر بدون أي توقف عن العمل
- **أرصدة NVIDIA NIM المجانية** — 1000 رصيد مجاني مدمج
- **استراتيجية التكلفة المحسنة** — استراتيجية التوجيه التي تختار تلقائيًا أرخص مزود متاح
@@ -909,8 +893,8 @@ npm run electron:build:linux # Linux (.AppImage)
| ميزة | ماذا يفعل || -------------------------- | ------------------------------------------------------------- |
| 🖼️ **إنشاء الصور** | `/v1/images/generations` مع الواجهات الخلفية السحابية والمحلية |
| 📐 **المضامين** | `/v1/embeddings` للبحث وخطوط أنابيب RAG |
| 🎤 **نسخ صوتي** | `/v1/audio/transcriptions` (مقدمو خدمات الهمس والإضافيون) |
| 🔊 **تحويل النص إلى كلام** | `/v1/audio/speech` (محركات/موفرو متعددون) |
| 🎤 **نسخ صوتي** | `/v1/audio/transcriptions` — 7 providers (Deepgram Nova 3, AssemblyAI, Groq Whisper, HuggingFace, ElevenLabs, OpenAI, Azure), auto-language detection, MP4/MP3/WAV support |
| 🔊 **تحويل النص إلى كلام** | `/v1/audio/speech` — 10 providers (ElevenLabs, OpenAI, Deepgram, Cartesia, PlayHT, HuggingFace, Nvidia NIM, Inworld, Coqui, Tortoise) |
| 🎬 **توليد الفيديو** | `/v1/videos/generations` (سير عمل ComfyUI + SD WebUI) |
| 🎵 **جيل الموسيقى** | `/v1/music/generations` (سير عمل ComfyUI) |
| 🛡️ **اعتدالات** | فحوصات السلامة `/v1/moderations` |
@@ -944,14 +928,16 @@ npm run electron:build:linux # Linux (.AppImage)
### ☁️ النشر والمنصة
| ميزة | ماذا يفعل |
| -------------------------------- | ------------------------------------------------ | --- | ------------------------ | ------------------------------- |
| 🌐 **النشر في أي مكان** | المضيف المحلي، VPS، Docker، البيئات السحابية | | 💾 **المزامنة السحابية** | مزامنة التكوين عبر عامل السحابة |
| 🔄 **النسخ الاحتياطي/الاستعادة** | تدفقات التصدير/الاستيراد والتعافي من الكوارث |
| 🧙 **معالج الإعداد** | الإعداد الموجه لأول مرة |
| 🔧 **لوحة تحكم أدوات CLI** | إعداد بنقرة واحدة لأدوات الترميز الشائعة |
| 🌐 **i18n (30 لغة)** | لوحة تحكم كاملة + دعم لغة المستندات مع تغطية RTL |
| 📂 **دليل البيانات المخصصة** | تجاوز `DATA_DIR` لموقع التخزين |
| ميزة | ماذا يفعل |
| -------------------------------- | --------------------------------------------------- | --- | ------------------------ | ------------------------------- |
| 🌐 **النشر في أي مكان** | المضيف المحلي، VPS، Docker، البيئات السحابية | | 💾 **المزامنة السحابية** | مزامنة التكوين عبر عامل السحابة |
| 🔄 **النسخ الاحتياطي/الاستعادة** | تدفقات التصدير/الاستيراد والتعافي من الكوارث |
| 🧙 **معالج الإعداد** | الإعداد الموجه لأول مرة |
| 🔧 **لوحة تحكم أدوات CLI** | إعداد بنقرة واحدة لأدوات الترميز الشائعة |
| 🌐 **i18n (30 لغة)** | لوحة تحكم كاملة + دعم لغة المستندات مع تغطية RTL |
| 🧹 **Clear All Models** | One-click model list clearing in provider details |
| 📋 **Issue Templates** | Standardized GitHub templates for bugs and features |
| 📂 **دليل البيانات المخصصة** | تجاوز `DATA_DIR` لموقع التخزين |
### ميزة الغوص العميق
@@ -1638,15 +1624,9 @@ gh release create v2.0.0 --title "v2.0.0" --generate-notes
## 📊 تاريخ النجوم
<a href="https://star-history.com/#diegosouzapw/OmniRoute&Date">
<picture>
<source media="(prefers-color-scheme: dark)" srcset="https://api.star-history.com/svg?repos=diegosouzapw/OmniRoute&type=Date&theme=dark" />
<source media="(prefers-color-scheme: light)" srcset="https://api.star-history.com/svg?repos=diegosouzapw/OmniRoute&type=Date" />
<img alt="Star History Chart" src="https://api.star-history.com/svg?repos=diegosouzapw/OmniRoute&type=Date" />
</picture>
</a>
## Stargazers over time
---
## [![Stargazers over time](https://starchart.cc/diegosouzapw/OmniRoute.svg?variant=adaptive)](https://starchart.cc/diegosouzapw/OmniRoute)
## 🙏 شكر وتقدير
+37
View File
@@ -0,0 +1,37 @@
🌐 **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).
+168 -129
View File
@@ -1,87 +1,91 @@
# استكشاف الأخطاء وإصلاحها
🌐 **Languages:** 🇺🇸 [English](../../TROUBLESHOOTING.md) | 🇧🇷 [Português (Brasil)](../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) | 🇩🇰 [Dansk](../da/TROUBLESHOOTING.md) | 🇫🇮 [Suomi](../fi/TROUBLESHOOTING.md) | 🇮🇱 [עברית](../he/TROUBLESHOOTING.md) | 🇭🇺 [Magyar](../hu/TROUBLESHOOTING.md) | 🇮🇩 [Bahasa Indonesia](../id/TROUBLESHOOTING.md) | 🇰🇷 [한국어](../ko/TROUBLESHOOTING.md) | 🇲🇾 [Bahasa Melayu](../ms/TROUBLESHOOTING.md) | 🇳🇱 [Nederlands](../nl/TROUBLESHOOTING.md) | 🇳🇴 [Norsk](../no/TROUBLESHOOTING.md) | 🇵🇹 [Português (Portugal)](../pt/TROUBLESHOOTING.md) | 🇷🇴 [Română](../ro/TROUBLESHOOTING.md) | 🇵🇱 [Polski](../pl/TROUBLESHOOTING.md) | 🇸🇰 [Slovenčina](../sk/TROUBLESHOOTING.md) | 🇸🇪 [Svenska](../sv/TROUBLESHOOTING.md) | 🇵🇭 [Filipino](../phi/TROUBLESHOOTING.md)
المشاكل والحلول الشائعة لـ OmniRoute.
🌐 **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
| مشكلة | الحل |
| --------------------------------- | ----------------------------------------------------------------- |
| تسجيل الدخول الأول لا يعمل | تحقق من `INITIAL_PASSWORD` في `.env` (الافتراضي: `123456`) |
| تفتح لوحة المعلومات على منفذ خاطئ | اضبط `PORT=20128` و`NEXT_PUBLIC_BASE_URL=http://localhost:20128` |
| لا توجد سجلات للطلب ضمن `logs/` | تعيين `ENABLE_REQUEST_LOGS=true` |
| EACCES: تم رفض الإذن | اضبط `DATA_DIR=/path/to/writable/dir` لتجاوز `~/.omniroute` |
| استراتيجية التوجيه لا تنقذ | التحديث إلى الإصدار 1.4.11+ (إصلاح مخطط Zod لاستمرارية الإعدادات) |
🌐 **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
### "نموذج اللغة لم يقدم رسائل"
**السبب:** استنفدت حصة الموفر.
**الإصلاح:**
1. تحقق من تعقب الحصص في لوحة القيادة
2. استخدم مجموعة من المستويات الاحتياطية
3. قم بالتبديل إلى الطبقة الأرخص/المجانية
### تحديد المعدل
**السبب:** استنفدت حصة الاشتراك.
**الإصلاح:**
- إضافة احتياطي: `cc/claude-opus-4-6 → glm/glm-4.7 → if/kimi-k2-thinking`
- استخدم GLM/MiniMax كنسخة احتياطية رخيصة الثمن
### انتهت صلاحية رمز OAuth
يقوم OmniRoute بتحديث الرموز المميزة تلقائيًا. إذا استمرت المشكلات:
1. لوحة المعلومات → الموفر → إعادة الاتصال
2. قم بحذف وإعادة إضافة اتصال الموفر
| 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"
1. تحقق من نقاط `BASE_URL` لمثيلك قيد التشغيل (على سبيل المثال، `http://localhost:20128`)
2. تحقق من نقاط `CLOUD_URL` إلى نقطة نهاية السحابة الخاصة بك (على سبيل المثال، `https://omniroute.dev`)
3. حافظ على محاذاة قيم `NEXT_PUBLIC_*` مع القيم من جانب الخادم
**Cause:** Provider quota exhausted.
### السحابة `stream=false` تُرجع 500
**Fix:**
**العَرَض:** `Unexpected token 'd'...` على نقطة نهاية السحابة للمكالمات غير المتدفقة.
1. Check dashboard quota tracker
2. Use a combo with fallback tiers
3. Switch to cheaper/free tier
**السبب:** يقوم المنبع بإرجاع حمولة SSE بينما يتوقع العميل JSON.
### Rate Limiting
**الحل البديل:** استخدم `stream=true` للمكالمات السحابية المباشرة. يتضمن وقت التشغيل المحلي SSE → JSON الاحتياطي.
**Cause:** Subscription quota exhausted.
### تقول السحابة إنها متصلة ولكن "مفتاح واجهة برمجة التطبيقات غير صالح"
**Fix:**
1. قم بإنشاء مفتاح جديد من لوحة المعلومات المحلية (`/api/keys`)
2. قم بتشغيل المزامنة السحابية: قم بتمكين السحابة → المزامنة الآن
3. لا يزال بإمكان المفاتيح القديمة/غير المتزامنة إرجاع `401` على السحابة
- 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
### تظهر أداة CLI غير مثبتة
### Cloud Sync Errors
1. تحقق من حقول وقت التشغيل: `curl http://localhost:20128/api/cli-tools/runtime/codex | jq`
2. بالنسبة للوضع المحمول: استخدم هدف الصورة `runner-cli` (CLIs المجمعة)
3. بالنسبة لوضع تثبيت المضيف: قم بتعيين `CLI_EXTRA_PATHS` وتثبيت دليل حاوية المضيف للقراءة فقط
4. إذا تم العثور على `installed=true` و`runnable=false`: ثنائي ولكن فشل التحقق من الصحة
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}'
@@ -91,24 +95,24 @@ curl -s http://localhost:20128/api/cli-tools/openclaw-settings | jq '{installed,
---
## قضايا التكلفة
## Cost Issues
### ارتفاع التكاليف
### High Costs
1. تحقق من إحصائيات الاستخدام في لوحة المعلومات → الاستخدام
2. قم بتبديل النموذج الأساسي إلى GLM/MiniMax
3. استخدم الطبقة المجانية (Gemini CLI، iFlow) للمهام غير الحرجة
4. قم بتعيين ميزانيات التكلفة لكل مفتاح واجهة برمجة التطبيقات: لوحة المعلومات ← مفاتيح واجهة برمجة التطبيقات ← الميزانية
1. Check usage stats in Dashboard → Usage
2. Switch primary model to GLM/MiniMax
3. Use free tier (Gemini CLI, iFlow) for non-critical tasks
4. Set cost budgets per API key: Dashboard → API Keys → Budget
---
## التصحيح
## Debugging
### تمكين سجلات الطلبات
### Enable Request Logs
قم بتعيين `ENABLE_REQUEST_LOGS=true` في ملف `.env` الخاص بك. تظهر السجلات ضمن الدليل `logs/`.
Set `ENABLE_REQUEST_LOGS=true` in your `.env` file. Logs appear under `logs/` directory.
### التحقق من صحة مقدم الخدمة
### Check Provider Health
```bash
# Health dashboard
@@ -118,102 +122,137 @@ http://localhost:20128/dashboard/health
curl http://localhost:20128/api/monitoring/health
```
### تخزين وقت التشغيل
### Runtime Storage
- الحالة الرئيسية: `${DATA_DIR}/db.json` (المزودون، المجموعات، الأسماء المستعارة، المفاتيح، الإعدادات)
- الاستخدام: `${DATA_DIR}/usage.json`، `${DATA_DIR}/log.txt`، `${DATA_DIR}/call_logs/`
- سجلات الطلب: `<repo>/logs/...` (عندما `ENABLE_REQUEST_LOGS=true`)
- 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: `<repo>/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. انتقل إلى **لوحة التحكم ← الإعدادات ← المرونة**
2. تحقق من بطاقة قاطع الدائرة الكهربائية الخاصة بالمزود المتأثر
3. انقر فوق **إعادة تعيين الكل** لمسح جميع القواطع، أو انتظر حتى تنتهي فترة التهدئة
4. تحقق من أن الموفر متاح فعليًا قبل إعادة التعيين
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. تحقق من **Dashboard → Health → Provider Health** لمعرفة نمط الفشل
2. انتقل إلى **الإعدادات → المرونة → ملفات تعريف الموفر** وقم بزيادة حد الفشل
3. تحقق مما إذا كان الموفر قد قام بتغيير حدود واجهة برمجة التطبيقات (API) أو طلب إعادة المصادقة
4. قم بمراجعة القياس عن بعد لزمن الاستجابة - قد يتسبب زمن الاستجابة العالي في حدوث أعطال بسبب انتهاء المهلة
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
- تأكد من أنك تستخدم البادئة الصحيحة: `deepgram/nova-3` أو `assemblyai/best`
- تحقق من أن الموفر متصل في **لوحة التحكم ← الموفرون**
- 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
- تحقق من تنسيقات الصوت المدعومة: `mp3`، `wav`، `m4a`، `flac`، `ogg`، `webm`
- التحقق من أن حجم الملف يقع ضمن حدود الموفر (عادةً أقل من 25 ميجابايت)
- التحقق من صلاحية مفتاح API الخاص بالموفر في بطاقة المزود
- 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
- **لا تظهر علامات التفكير** — تحقق مما إذا كان الموفر المستهدف يدعم التفكير وإعداد ميزانية التفكير
- **استدعاءات الأداة** — قد تؤدي بعض ترجمات التنسيق إلى إزالة الحقول غير المدعومة؛ تحقق في وضع الملعب
- **مطالبة النظام مفقودة** — يتعامل نظام Claude وGemini مع المطالبات بشكل مختلف؛ التحقق من إخراج الترجمة
- ** تقوم SDK بإرجاع سلسلة أولية بدلاً من الكائن ** - تم الإصلاح في الإصدار 1.1.0: تقوم أداة معالجة الاستجابة الآن بإزالة الحقول غير القياسية (`x_groq`، `usage_breakdown`، وما إلى ذلك) التي تتسبب في فشل التحقق من صحة OpenAI SDK Pydantic
- **GLM/ERNIE يرفض دور `system`**تم إصلاحه في الإصدار 1.1.0: يقوم مُطبيع الدور تلقائيًا بدمج رسائل النظام في رسائل المستخدم للنماذج غير المتوافقة
- **`developer` لم يتم التعرف على الدور** — تم إصلاحه في الإصدار 1.1.0: تم تحويله تلقائيًا إلى `system` لمقدمي الخدمات غير التابعين لـ OpenAI
- **`json_schema` لا يعمل مع Gemini** — تم إصلاحه في الإصدار 1.1.0: `response_format` تم تحويله الآن إلى `responseMimeType` + `responseSchema` الخاص بـ Gemini\_\_
- **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
- ينطبق حد المعدل التلقائي فقط على موفري مفاتيح واجهة برمجة التطبيقات (وليس OAuth/الاشتراك)
- تحقق من أن **الإعدادات → المرونة → ملفات تعريف الموفر** تم تمكين حد المعدل التلقائي
- تحقق مما إذا كان الموفر يعرض `429` رموز الحالة أو رؤوس `Retry-After`
- 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:
- **التأخير الأساسي** — وقت الانتظار الأولي بعد الفشل الأول (الافتراضي: 1 ثانية)
- **الحد الأقصى للتأخير** — الحد الأقصى لوقت الانتظار (الافتراضي: 30 ثانية)
- **المضاعف** — مقدار زيادة التأخير لكل فشل متتالي (الافتراضي: 2x)
- **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
عندما تصل العديد من الطلبات المتزامنة إلى موفر محدود السعر، يستخدم OmniRoute تحديد المعدل التلقائي + mutex لإجراء تسلسل للطلبات ومنع حالات الفشل المتتالية. وهذا تلقائي لموفري مفاتيح API.
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)
- **مشكلات GitHub**: [github.com/diegosouzapw/OmniRoute/issues](https://github.com/diegosouzapw/OmniRoute/issues)
- **الهندسة المعمارية**: راجع [link](ARCHITECTURE.md) للحصول على التفاصيل الداخلية
- **مرجع واجهة برمجة التطبيقات**: راجع [link](API_REFERENCE.md) لجميع نقاط النهاية
- **لوحة معلومات الصحة**: تحقق من **لوحة المعلومات ← الصحة** لمعرفة حالة النظام في الوقت الفعلي
- **المترجم**: استخدم **لوحة المعلومات ← المترجم** لتصحيح مشكلات التنسيق
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
+351 -236
View File
@@ -1,12 +1,16 @@
# دليل المستخدم
🌐 **Languages:** 🇺🇸 [English](../../USER_GUIDE.md) | 🇧🇷 [Português (Brasil)](../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) | 🇩🇰 [Dansk](../da/USER_GUIDE.md) | 🇫🇮 [Suomi](../fi/USER_GUIDE.md) | 🇮🇱 [עברית](../he/USER_GUIDE.md) | 🇭🇺 [Magyar](../hu/USER_GUIDE.md) | 🇮🇩 [Bahasa Indonesia](../id/USER_GUIDE.md) | 🇰🇷 [한국어](../ko/USER_GUIDE.md) | 🇲🇾 [Bahasa Melayu](../ms/USER_GUIDE.md) | 🇳🇱 [Nederlands](../nl/USER_GUIDE.md) | 🇳🇴 [Norsk](../no/USER_GUIDE.md) | 🇵🇹 [Português (Portugal)](../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) | 🇵🇭 [Filipino](../phi/USER_GUIDE.md)
الدليل الكامل لتكوين مقدمي الخدمات، وإنشاء المجموعات، ودمج أدوات CLI، ونشر OmniRoute.
🌐 **Languages:** 🇺🇸 [English](../../README.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)
---
## جدول المحتويات
# User Guide
🌐 **Languages:** 🇺🇸 [English](USER_GUIDE.md) | 🇧🇷 [Português (Brasil)](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) | 🇩🇰 [Dansk](i18n/da/USER_GUIDE.md) | 🇫🇮 [Suomi](i18n/fi/USER_GUIDE.md) | 🇮🇱 [עברית](i18n/he/USER_GUIDE.md) | 🇭🇺 [Magyar](i18n/hu/USER_GUIDE.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/USER_GUIDE.md) | 🇰🇷 [한국어](i18n/ko/USER_GUIDE.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/USER_GUIDE.md) | 🇳🇱 [Nederlands](i18n/nl/USER_GUIDE.md) | 🇳🇴 [Norsk](i18n/no/USER_GUIDE.md) | 🇵🇹 [Português (Portugal)](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) | 🇵🇭 [Filipino](i18n/phi/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)
@@ -18,40 +22,40 @@
---
## 💰 لمحة سريعة عن الأسعار
## 💰 Pricing at a Glance
| الطبقة | مقدم | التكلفة | إعادة ضبط الحصص | الأفضل لـ |
| ---------------------------------- | ----------------------------------- | ---------------------- | ----------------------- | -------------------------------------- |
| **💳الإشتراك** | كلود كود (برو) | 20 دولارًا شهريًا | 5 ساعات + أسبوعي | اشتركت بالفعل |
| | الدستور الغذائي (زائد / برو) | 20-200 دولار شهريًا | 5 ساعات + أسبوعي | مستخدمي OpenAI |
| | الجوزاء CLI | **مجاني** | 180 ألف/شهر + 1 ألف/يوم | الجميع! |
| | جيثب مساعد الطيار | 10-19 دولارًا شهريًا | شهري | مستخدمي جيثب |
| **🔑 مفتاح واجهة برمجة التطبيقات** | ديب سيك | الدفع لكل استخدام | لا شيء | الاستدلال الرخيص |
| | جروك | الدفع لكل استخدام | لا شيء | الاستدلال فائق السرعة |
| | xAI (جروك) | الدفع لكل استخدام | لا شيء | جروك 4 المنطق |
| | ميسترال | الدفع لكل استخدام | لا شيء | النماذج التي يستضيفها الاتحاد الأوروبي |
| | الحيرة | الدفع لكل استخدام | لا شيء | البحث المعزز |
| | معا منظمة العفو الدولية | الدفع لكل استخدام | لا شيء | نماذج مفتوحة المصدر |
| | الألعاب النارية منظمة العفو الدولية | الدفع لكل استخدام | لا شيء | صور التدفق السريع |
| | المخيخ | الدفع لكل استخدام | لا شيء | سرعة على نطاق الرقاقة |
| | كوهير | الدفع لكل استخدام | لا شيء | الأمر R+ RAG |
| | نفيديا نيم | الدفع لكل استخدام | لا شيء | نماذج المؤسسات |
| **💰 رخيص** | جي إل إم-4.7 | 0.6 دولار/1 مليون | يوميا 10 صباحا | نسخة احتياطية للميزانية |
| | ميني ماكس M2.1 | 0.2 دولار/1 مليون | المتداول لمدة 5 ساعات | الخيار الأرخص |
| | كيمي ك2 | 9 دولارات شهريًا مسطحة | 10 مليون رمز/شهر | التكلفة المتوقعة |
| **🆓مجانًا** | اي فلو | $0 | غير محدود | 8 نماذج مجانية |
| | كوين | $0 | غير محدود | 3 نماذج مجانية |
| | كيرو | $0 | غير محدود | كلود مجاني |
| 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** | iFlow | $0 | Unlimited | 8 models free |
| | Qwen | $0 | Unlimited | 3 models free |
| | Kiro | $0 | Unlimited | Claude free |
**💡 نصيحة احترافية:** ابدأ مع مجموعة Gemini CLI (180 ألفًا مجانًا شهريًا) + مجموعة iFlow (مجانية غير محدودة) = تكلفة 0 دولار!
**💡 Pro Tip:** Start with Gemini CLI (180K free/month) + iFlow (unlimited free) combo = $0 cost!
---
## 🎯 حالات الاستخدام
## 🎯 Use Cases
### الحالة 1: "لدي اشتراك Claude Pro"
### Case 1: "I have Claude Pro subscription"
**المشكلة:** تنتهي صلاحية الحصة غير المستخدمة، وحدود المعدل أثناء عملية الترميز المكثف
**Problem:** Quota expires unused, rate limits during heavy coding
```
Combo: "maximize-claude"
@@ -63,9 +67,9 @@ Monthly cost: $20 (subscription) + ~$5 (backup) = $25 total
vs. $20 + hitting limits = frustration
```
### الحالة 2: "أريد تكلفة صفرية"
### Case 2: "I want zero cost"
**المشكلة:** لا أستطيع تحمل تكلفة الاشتراكات، وتحتاج إلى ترميز يعتمد على الذكاء الاصطناعي
**Problem:** Can't afford subscriptions, need reliable AI coding
```
Combo: "free-forever"
@@ -77,9 +81,9 @@ Monthly cost: $0
Quality: Production-ready models
```
### الحالة 3: "أحتاج إلى تشفير على مدار 24 ساعة طوال أيام الأسبوع، دون انقطاع"
### Case 3: "I need 24/7 coding, no interruptions"
**المشكلة:** المواعيد النهائية، لا أستطيع تحمل فترات التوقف عن العمل
**Problem:** Deadlines, can't afford downtime
```
Combo: "always-on"
@@ -93,9 +97,9 @@ Result: 5 layers of fallback = zero downtime
Monthly cost: $20-200 (subscriptions) + $10-20 (backup)
```
### الحالة 4: "أريد ذكاءً اصطناعيًا مجانيًا في OpenClaw"
### Case 4: "I want FREE AI in OpenClaw"
**المشكلة:** تحتاج إلى مساعد الذكاء الاصطناعي في تطبيقات المراسلة، مجانًا تمامًا
**Problem:** Need AI assistant in messaging apps, completely free
```
Combo: "openclaw-free"
@@ -109,11 +113,11 @@ Access via: WhatsApp, Telegram, Slack, Discord, iMessage, Signal...
---
## 📖 إعداد الموفر
## 📖 Provider Setup
### 🔐 مقدمي الاشتراكات
### 🔐 Subscription Providers
#### كلود كود (برو/ماكس)
#### Claude Code (Pro/Max)
```bash
Dashboard → Providers → Connect Claude Code
@@ -126,7 +130,7 @@ Models:
cc/claude-haiku-4-5-20251001
```
**نصيحة احترافية:** استخدم Opus للمهام المعقدة، وSonnet للسرعة. OmniRoute يتتبع الحصة لكل نموذج!
**Pro Tip:** Use Opus for complex tasks, Sonnet for speed. OmniRoute tracks quota per model!
#### OpenAI Codex (Plus/Pro)
@@ -140,7 +144,7 @@ Models:
cx/gpt-5.1-codex-max
```
#### Gemini CLI (180 ألفًا شهريًا مجانًا!)
#### Gemini CLI (FREE 180K/month!)
```bash
Dashboard → Providers → Connect Gemini CLI
@@ -152,9 +156,9 @@ Models:
gc/gemini-2.5-pro
```
**أفضل قيمة:** طبقة مجانية ضخمة! استخدم هذا قبل المستويات المدفوعة.
**Best Value:** Huge free tier! Use this before paid tiers.
#### مساعد جيثب
#### GitHub Copilot
```bash
Dashboard → Providers → Connect GitHub
@@ -167,33 +171,33 @@ Models:
gh/gemini-3-pro
```
### 💰 مقدمو خدمات رخيصون
### 💰 Cheap Providers
#### GLM-4.7 (إعادة التعيين اليومي، 0.6 دولار/1 مليون)
#### GLM-4.7 (Daily reset, $0.6/1M)
1. قم بالتسجيل: [Zhipu AI](https://open.bigmodel.cn/)
2. احصل على مفتاح API من خطة الترميز
3. لوحة المعلومات → إضافة مفتاح واجهة برمجة التطبيقات: الموفر: `glm`، مفتاح واجهة برمجة التطبيقات: `your-key`
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`
**الاستخدام:** `glm/glm-4.7`**نصيحة احترافية:** توفر خطة البرمجة حصة 3× بتكلفة 1/7! إعادة الضبط يوميًا الساعة 10:00 صباحًا.
**Use:** `glm/glm-4.7`**Pro Tip:** Coding Plan offers 3× quota at 1/7 cost! Reset daily 10:00 AM.
#### MiniMax M2.1 (إعادة الضبط لمدة 5 ساعات، 0.20 دولار/1 مليون)
#### MiniMax M2.1 (5h reset, $0.20/1M)
1. قم بالتسجيل: [MiniMax](https://www.minimax.io/)
2. احصل على مفتاح API → لوحة المعلومات → إضافة مفتاح API
1. Sign up: [MiniMax](https://www.minimax.io/)
2. Get API key → Dashboard → Add API Key
**الاستخدام:** `minimax/MiniMax-M2.1`**نصيحة احترافية:** الخيار الأرخص للسياق الطويل (مليون رمز)!
**Use:** `minimax/MiniMax-M2.1`**Pro Tip:** Cheapest option for long context (1M tokens)!
#### كيمي K2 (شقة بقيمة 9 دولارات في الشهر)
#### Kimi K2 ($9/month flat)
1. الاشتراك: [Moonshot AI](https://platform.moonshot.ai/)
2. احصل على مفتاح API → لوحة المعلومات → إضافة مفتاح API
1. Subscribe: [Moonshot AI](https://platform.moonshot.ai/)
2. Get API key → Dashboard → Add API Key
**الاستخدام:** `kimi/kimi-latest`**نصيحة احترافية:** سعر ثابت قدره 9 دولارات شهريًا مقابل 10 ملايين رمز مميز = 0.90 دولارًا أمريكيًا/التكلفة الفعلية لمليون واحد!
**Use:** `kimi/kimi-latest`**Pro Tip:** Fixed $9/month for 10M tokens = $0.90/1M effective cost!
### 🆓 مقدمي الخدمة مجانًا
### 🆓 FREE Providers
#### iFlow (8 نماذج مجانية)
#### iFlow (8 FREE models)
```bash
Dashboard → Connect iFlow → OAuth login → Unlimited usage
@@ -201,7 +205,7 @@ Dashboard → Connect iFlow → OAuth login → Unlimited usage
Models: if/kimi-k2-thinking, if/qwen3-coder-plus, if/glm-4.7, if/minimax-m2, if/deepseek-r1
```
#### كوين (3 موديلات مجانية)
#### Qwen (3 FREE models)
```bash
Dashboard → Connect Qwen → Device code auth → Unlimited usage
@@ -209,7 +213,7 @@ 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
@@ -219,9 +223,9 @@ Models: kr/claude-sonnet-4.5, kr/claude-haiku-4.5
---
## 🎨 المجموعات
## 🎨 Combos
### مثال 1: زيادة الاشتراك إلى الحد الأقصى → النسخ الاحتياطي الرخيص
### Example 1: Maximize Subscription → Cheap Backup
```
Dashboard → Combos → Create New
@@ -235,7 +239,7 @@ Models:
Use in CLI: premium-coding
```
### المثال 2: مجاني فقط (بدون تكلفة)
### Example 2: Free-Only (Zero Cost)
```
Name: free-combo
@@ -249,9 +253,9 @@ Cost: $0 forever!
---
## 🔧 تكامل CLI
## 🔧 CLI Integration
### بيئة تطوير متكاملة للمؤشر
### Cursor IDE
```
Settings → Models → Advanced:
@@ -260,9 +264,9 @@ Settings → Models → Advanced:
Model: cc/claude-opus-4-6
```
### كلود كود
### Claude Code
تحرير `~/.claude/config.json`:
Edit `~/.claude/config.json`:
```json
{
@@ -271,7 +275,7 @@ Settings → Models → Advanced:
}
```
### كوديكس سطر الأوامر
### Codex CLI
```bash
export OPENAI_BASE_URL="http://localhost:20128"
@@ -281,7 +285,7 @@ codex "your prompt"
### OpenClaw
تحرير `~/.openclaw/openclaw.json`:
Edit `~/.openclaw/openclaw.json`:
```json
{
@@ -303,9 +307,9 @@ codex "your prompt"
}
```
**أو استخدم لوحة المعلومات:** أدوات CLI → OpenClaw → التكوين التلقائي
**Or use Dashboard:** CLI Tools → OpenClaw → Auto-config
### كلاين / متابعة / RooCode
### Cline / Continue / RooCode
```
Provider: OpenAI Compatible
@@ -316,9 +320,28 @@ Model: cc/claude-opus-4-6
---
## 🚀 النشر
## 🚀 Deployment
### نشر VPS
### 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
@@ -337,7 +360,44 @@ 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)
@@ -347,81 +407,84 @@ docker build -t omniroute:cli .
docker run -d --name omniroute -p 20128:20128 --env-file ./.env -v omniroute-data:/app/data omniroute:cli
```
بالنسبة للوضع المدمج مع المضيف مع ثنائيات CLI، راجع قسم Docker في المستندات الرئيسية.
For host-integrated mode with CLI binaries, see the Docker section in the main docs.
### متغيرات البيئة
### Environment Variables
| متغير | الافتراضي | الوصف |
| --------------------- | ------------------------------------ | ---------------------------------------------------------------- |
| `JWT_SECRET` | `omniroute-default-secret-change-me` | سر توقيع JWT (**تغيير في الإنتاج**) |
| `INITIAL_PASSWORD` | `123456` | كلمة المرور الأولى لتسجيل الدخول |
| `DATA_DIR` | `~/.omniroute` | دليل البيانات (ديسيبل، الاستخدام، السجلات) |
| `PORT` | الإطار الافتراضي | منفذ الخدمة (`20128` في الأمثلة) |
| `HOSTNAME` | الإطار الافتراضي | ربط المضيف (إعدادات Docker الافتراضية هي `0.0.0.0`) |
| `NODE_ENV` | وقت التشغيل الافتراضي | قم بتعيين `production` للنشر |
| `BASE_URL` | `http://localhost:20128` | عنوان URL الأساسي الداخلي من جانب الخادم |
| `CLOUD_URL` | `https://omniroute.dev` | عنوان URL الأساسي لنقطة نهاية المزامنة السحابية |
| `API_KEY_SECRET` | `endpoint-proxy-api-key-secret` | سر HMAC لمفاتيح API التي تم إنشاؤها |
| `REQUIRE_API_KEY` | `false` | فرض مفتاح Bearer API على `/v1/*` |
| `ENABLE_REQUEST_LOGS` | `false` | تمكين سجلات الطلب/الاستجابة |
| `AUTH_COOKIE_SECURE` | `false` | فرض ملف تعريف ارتباط المصادقة `Secure` (خلف الوكيل العكسي HTTPS) |
| 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 |
للحصول على مرجع متغير البيئة الكامل، راجع [README](../README.md).
For the full environment variable reference, see the [README](../README.md).
---
## 📊 الموديلات المتوفرة
## 📊 Available Models
<details>
<summary><b>عرض جميع الموديلات المتاحة</b></summary>
<summary><b>View all available models</b></summary>
**كود كلود (`cc/`)** — Pro/Max: `cc/claude-opus-4-6`, `cc/claude-sonnet-4-5-20250929`, `cc/claude-haiku-4-5-20251001`
**Claude Code (`cc/`)** — Pro/Max: `cc/claude-opus-4-6`, `cc/claude-sonnet-4-5-20250929`, `cc/claude-haiku-4-5-20251001`
**المخطوطة (`cx/`)** — Plus/Pro: `cx/gpt-5.2-codex`، `cx/gpt-5.1-codex-max`
**Codex (`cx/`)** — Plus/Pro: `cx/gpt-5.2-codex`, `cx/gpt-5.1-codex-max`
**Gemini CLI (`gc/`)** — مجانًا: `gc/gemini-3-flash-preview`، `gc/gemini-2.5-pro`
**Gemini CLI (`gc/`)** — FREE: `gc/gemini-3-flash-preview`, `gc/gemini-2.5-pro`
**مساعد GitHub (`gh/`)**: `gh/gpt-5`, `gh/claude-4.5-sonnet`
**GitHub Copilot (`gh/`)**: `gh/gpt-5`, `gh/claude-4.5-sonnet`
**GLM (`glm/`)** — 0.6 دولار/1 مليون: `glm/glm-4.7`
**GLM (`glm/`)** — $0.6/1M: `glm/glm-4.7`
**ميني ماكس (`minimax/`)** — 0.2 دولار/1 مليون: `minimax/MiniMax-M2.1`
**MiniMax (`minimax/`)** — $0.2/1M: `minimax/MiniMax-M2.1`
**iFlow (`if/`)** — مجانًا: `if/kimi-k2-thinking`، `if/qwen3-coder-plus`، `if/deepseek-r1`
**iFlow (`if/`)** — FREE: `if/kimi-k2-thinking`, `if/qwen3-coder-plus`, `if/deepseek-r1`
**كوين (`qw/`)** — مجانًا: `qw/qwen3-coder-plus`، `qw/qwen3-coder-flash`
**Qwen (`qw/`)** — FREE: `qw/qwen3-coder-plus`, `qw/qwen3-coder-flash`
**كيرو (`kr/`)** — مجانًا: `kr/claude-sonnet-4.5`، `kr/claude-haiku-4.5`
**Kiro (`kr/`)** — FREE: `kr/claude-sonnet-4.5`, `kr/claude-haiku-4.5`
**DeepSeek (`ds/`)**: `ds/deepseek-chat`، `ds/deepseek-reasoner`
**DeepSeek (`ds/`)**: `ds/deepseek-chat`, `ds/deepseek-reasoner`
** جروك (`groq/`)**: `groq/llama-3.3-70b-versatile`، `groq/llama-4-maverick-17b-128e-instruct`
**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`
**xAI (`xai/`)**: `xai/grok-4`, `xai/grok-4-0709-fast-reasoning`, `xai/grok-code-mini`
**ميسترال (`mistral/`)**: `mistral/mistral-large-2501`، `mistral/codestral-2501`
**Mistral (`mistral/`)**: `mistral/mistral-large-2501`, `mistral/codestral-2501`
**الحيرة (`pplx/`)**: `pplx/sonar-pro`, `pplx/sonar`
**Perplexity (`pplx/`)**: `pplx/sonar-pro`, `pplx/sonar`
** معًا الذكاء الاصطناعي (`together/`)**: `together/meta-llama/Llama-3.3-70B-Instruct-Turbo`
**Together AI (`together/`)**: `together/meta-llama/Llama-3.3-70B-Instruct-Turbo`
**الذكاء الاصطناعي للألعاب النارية (`fireworks/`)**: `fireworks/accounts/fireworks/models/deepseek-v3p1`
**Fireworks AI (`fireworks/`)**: `fireworks/accounts/fireworks/models/deepseek-v3p1`
** سيريبراس (`cerebras/`)**: `cerebras/llama-3.3-70b`
**Cerebras (`cerebras/`)**: `cerebras/llama-3.3-70b`
**الترابط (`cohere/`)**: `cohere/command-r-plus-08-2024`
**Cohere (`cohere/`)**: `cohere/command-r-plus-08-2024`
** نفيديا نيم (`nvidia/`)**: `nvidia/nvidia/llama-3.3-70b-instruct`
**NVIDIA NIM (`nvidia/`)**: `nvidia/nvidia/llama-3.3-70b-instruct`
</details>
---
## 🧩 ميزات متقدمة
## 🧩 Advanced Features
### نماذج مخصصة
### Custom Models
أضف أي معرف نموذج إلى أي مزود دون انتظار تحديث التطبيق:
Add any model ID to any provider without waiting for an app update:
```bash
# Via API
@@ -433,11 +496,11 @@ curl -X POST http://localhost:20128/api/provider-models \
# Remove: curl -X DELETE "http://localhost:20128/api/provider-models?provider=openai&model=gpt-4.5-preview"
```
أو استخدم لوحة المعلومات: **المزودون → [الموفر] → النماذج المخصصة**.
Or use Dashboard: **Providers → [Provider] → Custom Models**.
### مسارات موفر مخصصة
### Dedicated Provider Routes
توجيه الطلبات مباشرة إلى موفر محدد مع التحقق من صحة النموذج:
Route requests directly to a specific provider with model validation:
```bash
POST http://localhost:20128/v1/providers/openai/chat/completions
@@ -445,9 +508,9 @@ POST http://localhost:20128/v1/providers/openai/embeddings
POST http://localhost:20128/v1/providers/fireworks/images/generations
```
تتم إضافة بادئة الموفر تلقائيًا في حالة فقدانها. تُرجع النماذج غير المتطابقة `400`.
The provider prefix is auto-added if missing. Mismatched models return `400`.
### تكوين وكيل الشبكة
### Network Proxy Configuration
```bash
# Set global proxy
@@ -463,76 +526,76 @@ 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
```
إرجاع النماذج المجمعة حسب الموفر مع الأنواع (`chat`، `embedding`، `image`).
Returns models grouped by provider with types (`chat`, `embedding`, `image`).
### المزامنة السحابية
### Cloud Sync
- موفري المزامنة والمجموعات والإعدادات عبر الأجهزة
- مزامنة الخلفية التلقائية مع انتهاء المهلة + الفشل السريع
- تفضيل جانب الخادم `BASE_URL`/`CLOUD_URL` في الإنتاج
- Sync providers, combos, and settings across devices
- Automatic background sync with timeout + fail-fast
- Prefer server-side `BASE_URL`/`CLOUD_URL` in production
### LLM Gateway Intelligence (المرحلة 9)
### LLM Gateway Intelligence (Phase 9)
- **ذاكرة التخزين المؤقت الدلالية** — ذاكرة تخزين مؤقت تلقائية غير متدفقة، درجة الحرارة = 0 استجابات (تجاوز باستخدام `X-OmniRoute-No-Cache: true`)
- **صلاحية الطلب** — إلغاء تكرار الطلبات خلال 5 ثوانٍ عبر رأس `Idempotency-Key` أو `X-Request-Id`
- **تتبع التقدم** — الاشتراك في أحداث SSE `event: progress` عبر رأس `X-OmniRoute-Progress: true`
- **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
الوصول عبر **لوحة المعلومات → المترجم**. تصحيح الأخطاء وتصور كيفية قيام OmniRoute بترجمة طلبات واجهة برمجة التطبيقات (API) بين مقدمي الخدمة.
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:**
- تصحيح سبب فشل مجموعة محددة من العميل/الموفر
- التحقق من ترجمة علامات التفكير واستدعاءات الأدوات ومطالبات النظام بشكل صحيح
- مقارنة اختلافات التنسيق بين تنسيقات OpenAI وClaude وGemini وResponsions API
- 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**.
| استراتيجية | الوصف |
| ------------------------ | ---------------------------------------------------------------------------------------- |
| ** املأ أولا ** | يستخدم الحسابات بترتيب الأولوية — يعالج الحساب الأساسي جميع الطلبات حتى تصبح غير متاحة |
| ** راوند روبن ** | للتنقل عبر جميع الحسابات بحد ثابت قابل للتكوين (الافتراضي: 3 مكالمات لكل حساب) |
| **P2C (قوة الاختيارين)** | يختار حسابين عشوائيين ويوجهك إلى الحساب الأكثر صحة - الأرصدة محملة بالوعي الصحي |
| **عشوائي** | تحديد حساب عشوائيًا لكل طلب باستخدام خلط Fisher-Yates |
| **الأقل استخدامًا** | التوجيهات إلى الحساب ذو الطابع الزمني الأقدم `lastUsedAt`، مع توزيع حركة المرور بالتساوي |
| **التكلفة الأمثل** | التوجيهات إلى الحساب ذي أقل قيمة أولوية، مع تحسين موفري الخدمة الأقل تكلفة |
| 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 |
#### الأسماء المستعارة لنموذج البدل
#### 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
@@ -543,46 +606,46 @@ Chain: production-fallback
---
### المرونة وقواطع الدائرة
### Resilience & Circuit Breakers
قم بالتكوين عبر **لوحة المعلومات → الإعدادات → المرونة**.
Configure via **Dashboard → Settings → Resilience**.
تطبق OmniRoute المرونة على مستوى المزود من خلال أربعة مكونات:
OmniRoute implements provider-level resilience with four components:
1. **ملفات تعريف الموفر** — التكوين لكل موفر لـ:
- عتبة الفشل (كم عدد حالات الفشل قبل الفتح)
- مدة التهدئة
- حساسية الكشف عن حد المعدل
- معلمات التراجع الأسي
1. **Provider Profiles** — Per-provider configuration for:
- Failure threshold (how many failures before opening)
- Cooldown duration
- Rate limit detection sensitivity
- Exponential backoff parameters
2. **حدود المعدل القابلة للتحرير** — الإعدادات الافتراضية على مستوى النظام قابلة للتكوين في لوحة المعلومات:
- **الطلبات في الدقيقة (RPM)** — الحد الأقصى للطلبات في الدقيقة لكل حساب
- **الحد الأدنى للوقت بين الطلبات** — الحد الأدنى للفجوة بالمللي ثانية بين الطلبات
- **الحد الأقصى للطلبات المتزامنة** — الحد الأقصى للطلبات المتزامنة لكل حساب
- انقر **تحرير** للتعديل، ثم **حفظ** أو **إلغاء**. تستمر القيم عبر واجهة برمجة تطبيقات المرونة.
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. **قاطع الدائرة** — يتتبع حالات الفشل لكل مزود ويفتح الدائرة تلقائيًا عند الوصول إلى الحد الأدنى:
- **مغلق** (صحي) — تتدفق الطلبات بشكل طبيعي
- **مفتوح**تم حظر الموفر مؤقتًا بعد الفشل المتكرر
- **HALF_OPEN**اختبار ما إذا كان الموفر قد استعاد عافيته
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. **السياسات والمعرفات المقفلة** — تعرض حالة قاطع الدائرة والمعرفات المقفلة مع إمكانية إلغاء القفل بالقوة.
4. **Policies & Locked Identifiers** — Shows circuit breaker status and locked identifiers with force-unlock capability.
5. **الاكتشاف التلقائي لحدود المعدل** — يراقب الرؤوس `429` و`Retry-After` لتجنب الوصول إلى حدود معدل الموفر بشكل استباقي.
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**.
| العمل | الوصف |
| -------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------- |
| **تصدير قاعدة البيانات** | يقوم بتنزيل قاعدة بيانات SQLite الحالية كملف `.sqlite` |
| **تصدير الكل (.tar.gz)** | تنزيل أرشيف نسخ احتياطي كامل بما في ذلك: قاعدة البيانات، والإعدادات، والمجموعات، واتصالات الموفر (بدون بيانات اعتماد)، وبيانات تعريف مفتاح API |
| **استيراد قاعدة البيانات** | قم بتحميل ملف `.sqlite` لاستبدال قاعدة البيانات الحالية. يتم إنشاء نسخة احتياطية للاستيراد المسبق تلقائيًا |
| 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 |
```bash
# API: Export database
@@ -596,38 +659,38 @@ curl -X POST http://localhost:20128/api/db-backups/import \
-F "file=@backup.sqlite"
```
**التحقق من صحة الاستيراد:** يتم التحقق من صحة الملف المستورد للتأكد من سلامته (فحص براغما SQLite)، والجداول المطلوبة (`provider_connections`، `provider_nodes`، `combos`، `api_keys`)، والحجم (100 ميجابايت كحد أقصى).
**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:**
- ترحيل OmniRoute بين الأجهزة
- إنشاء نسخ احتياطية خارجية للتعافي من الكوارث
- مشاركة التكوينات بين أعضاء الفريق (تصدير الكل → مشاركة الأرشيف)
- Migrate OmniRoute between machines
- Create external backups for disaster recovery
- Share configurations between team members (export all → share archive)
---
### لوحة تحكم الإعدادات
### Settings Dashboard
يتم تنظيم صفحة الإعدادات في 5 علامات تبويب لسهولة التنقل:
The settings page is organized into 5 tabs for easy navigation:
| علامة التبويب | المحتويات |
| -------------------- | ---------------------------------------------------------------------------------------------------------------------------- |
| **الأمن** | إعدادات تسجيل الدخول/كلمة المرور، والتحكم في الوصول إلى IP، ومصادقة API لـ `/models`، وحظر الموفر |
| **التوجيه** | استراتيجية التوجيه العالمية (6 خيارات)، والأسماء المستعارة لنماذج أحرف البدل، والسلاسل الاحتياطية، وافتراضيات التحرير والسرد |
| **المرونة** | ملفات تعريف الموفر، وحدود الأسعار القابلة للتحرير، وحالة قاطع الدائرة، والسياسات والمعرفات المقفلة |
| **الذكاء الاصطناعي** | تكوين ميزانية التفكير، والحقن الفوري للنظام العالمي، وإحصائيات ذاكرة التخزين المؤقت السريعة |
| **متقدم** | تكوين الوكيل العالمي (HTTP/SOCKS5) |
| Tab | Contents |
| -------------- | ---------------------------------------------------------------------------------------------- |
| **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**.
| علامة التبويب | الغرض |
| ------------- | ------------------------------------------------------------------------------------------------ |
| **الميزانية** | قم بتعيين حدود الإنفاق لكل مفتاح API باستخدام ميزانيات يومية/أسبوعية/شهرية وتتبع في الوقت الفعلي |
| **التسعير** | عرض وتحرير إدخالات تسعير النموذج - التكلفة لكل ألف رمز إدخال/إخراج لكل مزود |
| 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
@@ -639,13 +702,13 @@ curl -X POST http://localhost:20128/api/usage/budget \
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 النسخ الصوتي عبر نقطة النهاية المتوافقة مع OpenAI:
OmniRoute supports audio transcription via the OpenAI-compatible endpoint:
```bash
POST /v1/audio/transcriptions
@@ -659,40 +722,92 @@ curl -X POST http://localhost:20128/v1/audio/transcriptions \
-F "model=deepgram/nova-3"
```
الموفرون المتاحون: **Deepgram** (`deepgram/`)، **AssemblyAI** (`assemblyai/`).
Available providers: **Deepgram** (`deepgram/`), **AssemblyAI** (`assemblyai/`).
تنسيقات الصوت المدعومة: `mp3`، `wav`، `m4a`، `flac`، `ogg`، `webm`.
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
الوصول عبر **لوحة التحكم → الصحة**. نظرة عامة على صحة النظام في الوقت الحقيقي مع 6 بطاقات:
Access via **Dashboard → Health**. Real-time system health overview with 6 cards:
| بطاقة | ما يظهر |
| ---------------------------------- | -------------------------------------------------------------- |
| **حالة النظام** | وقت التشغيل، الإصدار، استخدام الذاكرة، دليل البيانات |
| ** صحة المزود ** | حالة قاطع الدائرة الكهربائية لكل مزود (مغلق/مفتوح/نصف مفتوح) |
| ** حدود المعدل ** | فترات تهدئة حد المعدل النشط لكل حساب مع الوقت المتبقي |
| ** عمليات التأمين النشطة ** | تم حظر مقدمي الخدمة مؤقتًا بواسطة سياسة التأمين |
| ** ذاكرة التخزين المؤقت للتوقيع ** | إحصائيات إلغاء البيانات المكررة (المفاتيح النشطة، معدل الدخول) |
| ** قياس زمن الوصول ** | p50/p95/p99 تجميع زمن الوصول لكل مزود |
| 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 |
**نصيحة احترافية:** يتم تحديث صفحة الصحة تلقائيًا كل 10 ثوانٍ. استخدم بطاقة قاطع الدائرة لتحديد مقدمي الخدمة الذين يواجهون مشكلات.
**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.
### Installation
```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 (6416384 MB) |
📖 Full documentation: [`electron/README.md`](../electron/README.md)
+401
View File
@@ -0,0 +1,401 @@
# 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) |
+200
View File
@@ -0,0 +1,200 @@
🌐 **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);
```
+191 -177
View File
@@ -1,12 +1,16 @@
# Справка за API
🌐 **Languages:** 🇺🇸 [English](../../API_REFERENCE.md) | 🇧🇷 [Português (Brasil)](../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) | 🇩🇰 [Dansk](../da/API_REFERENCE.md) | 🇫🇮 [Suomi](../fi/API_REFERENCE.md) | 🇮🇱 [עברית](../he/API_REFERENCE.md) | 🇭🇺 [Magyar](../hu/API_REFERENCE.md) | 🇮🇩 [Bahasa Indonesia](../id/API_REFERENCE.md) | 🇰🇷 [한국어](../ko/API_REFERENCE.md) | 🇲🇾 [Bahasa Melayu](../ms/API_REFERENCE.md) | 🇳🇱 [Nederlands](../nl/API_REFERENCE.md) | 🇳🇴 [Norsk](../no/API_REFERENCE.md) | 🇵🇹 [Português (Portugal)](../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) | 🇵🇭 [Filipino](../phi/API_REFERENCE.md)
Пълна справка за всички крайни точки на OmniRoute API.
🌐 **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)
@@ -20,7 +24,7 @@
---
## Завършвания на чат
## Chat Completions
```bash
POST /v1/chat/completions
@@ -36,21 +40,21 @@ Content-Type: application/json
}
```
### Персонализирани заглавки
### Custom Headers
| Заглавка | Посока | Описание |
| ------------------------ | ------- | ------------------------------------------ |
| `X-OmniRoute-No-Cache` | Заявка | Задайте `true` за заобикаляне на кеша |
| `X-OmniRoute-Progress` | Заявка | Задайте `true` за събития за прогрес |
| `Idempotency-Key` | Заявка | Ключ за дедупиране (5s прозорец) |
| `X-Request-Id` | Заявка | Алтернативен дедуп ключ |
| `X-OmniRoute-Cache` | Отговор | `HIT` или `MISS` (без поточно предаване) |
| `X-OmniRoute-Idempotent` | Отговор | `true` ако е дедупликиран |
| `X-OmniRoute-Progress` | Отговор | `enabled` ако проследяване на напредъка на |
| 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
@@ -63,7 +67,7 @@ Content-Type: application/json
}
```
Налични доставчици: Nebius, OpenAI, Mistral, Together AI, Fireworks, NVIDIA.
Available providers: Nebius, OpenAI, Mistral, Together AI, Fireworks, NVIDIA.
```bash
# List all embedding models
@@ -72,7 +76,7 @@ GET /v1/embeddings
---
## Генериране на изображения
## Image Generation
```bash
POST /v1/images/generations
@@ -86,7 +90,7 @@ Content-Type: application/json
}
```
Налични доставчици: OpenAI (DALL-E), xAI (Grok Image), Together AI (FLUX), Fireworks AI.
Available providers: OpenAI (DALL-E), xAI (Grok Image), Together AI (FLUX), Fireworks AI.
```bash
# List all image models
@@ -95,7 +99,7 @@ GET /v1/images/generations
---
## Списък с модели
## List Models
```bash
GET /v1/models
@@ -106,22 +110,22 @@ Authorization: Bearer your-api-key
---
## Крайни точки за съвместимост
## Compatibility Endpoints
| Метод | Път | Формат |
| ---------- | --------------------------- | -------------------------- |
| ПУБЛИКАЦИЯ | `/v1/chat/completions` | OpenAI |
| ПУБЛИКАЦИЯ | `/v1/messages` | Антропен |
| ПУБЛИКАЦИЯ | `/v1/responses` | OpenAI отговори |
| ПУБЛИКАЦИЯ | `/v1/embeddings` | OpenAI |
| ПУБЛИКАЦИЯ | `/v1/images/generations` | OpenAI |
| ВЗЕМЕТЕ | `/v1/models` | OpenAI |
| ПУБЛИКАЦИЯ | `/v1/messages/count_tokens` | Антропен |
| ВЗЕМЕТЕ | `/v1beta/models` | Близнаци |
| ПУБЛИКАЦИЯ | `/v1beta/models/{...path}` | Gemini генерира съдържание |
| ПУБЛИКАЦИЯ | `/v1/api/chat` | Олама |
| 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
@@ -129,11 +133,11 @@ POST /v1/providers/{provider}/embeddings
POST /v1/providers/{provider}/images/generations
```
Префиксът на доставчика се добавя автоматично, ако липсва. Несъответстващите модели връщат `400`.
The provider prefix is auto-added if missing. Mismatched models return `400`.
---
## Семантичен кеш
## Semantic Cache
```bash
# Get cache stats
@@ -143,7 +147,7 @@ GET /api/cache
DELETE /api/cache
```
Пример за отговор:
Response example:
```json
{
@@ -162,154 +166,164 @@ DELETE /api/cache
---
## Табло за управление и управление
## Dashboard & Management
### Удостоверяване
### Authentication
| Крайна точка | Метод | Описание |
| ----------------------------- | ------------- | ---------------------------------- |
| `/api/auth/login` | ПУБЛИКАЦИЯ | Вход |
| `/api/auth/logout` | ПУБЛИКАЦИЯ | Изход |
| `/api/settings/require-login` | ВЗЕМИ/ПОСТАВИ | Изисква се превключване на влизане |
| Endpoint | Method | Description |
| ----------------------------- | ------- | --------------------- |
| `/api/auth/login` | POST | Login |
| `/api/auth/logout` | POST | Logout |
| `/api/settings/require-login` | GET/PUT | Toggle login required |
### Управление на доставчика
### Provider Management
| Крайна точка | Метод | Описание |
| ---------------------------- | -------------------------------- | ---------------------------------------- |
| `/api/providers` | ВЗЕМЕТЕ/ПУБЛИКУВАЙТЕ | Списък / създаване на доставчици |
| `/api/providers/[id]` | ПОЛУЧАВАНЕ/ПОСТАВЯНЕ/ИЗТРИВАНЕ | Управление на доставчик |
| `/api/providers/[id]/test` | ПУБЛИКАЦИЯ | Тествайте връзката с доставчик |
| `/api/providers/[id]/models` | ВЗЕМЕТЕ | Избройте модели на доставчици |
| `/api/providers/validate` | ПУБЛИКАЦИЯ | Проверка на конфигурацията на доставчика |
| `/api/provider-nodes*` | Различни | Управление на възел на доставчик |
| `/api/provider-models` | ПОЛУЧАВАНЕ/ПУБЛИКУВАНЕ/ИЗТРИВАНЕ | Персонализирани модели |
| 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 потоци
### OAuth Flows
| Крайна точка | Метод | Описание |
| -------------------------------- | -------- | ------------------------------ |
| `/api/oauth/[provider]/[action]` | Различни | Специфичен за доставчика OAuth |
| Endpoint | Method | Description |
| -------------------------------- | ------- | ----------------------- |
| `/api/oauth/[provider]/[action]` | Various | Provider-specific OAuth |
### Маршрутизиране и конфигурация
### Routing & Config
| Крайна точка | Метод | Описание |
| --------------------- | -------------------- | -------------------------------- |
| `/api/models/alias` | ВЗЕМЕТЕ/ПУБЛИКУВАЙТЕ | Псевдоними на модели |
| `/api/models/catalog` | ВЗЕМЕТЕ | Всички модели по доставчик + тип |
| `/api/combos*` | Различни | Комбо управление |
| `/api/keys*` | Различни | Управление на API ключове |
| `/api/pricing` | ВЗЕМЕТЕ | Моделна цена |
| 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
| Крайна точка | Метод | Описание |
| --------------------------- | ------- | ----------------------- |
| `/api/usage/history` | ВЗЕМЕТЕ | История на използването |
| `/api/usage/logs` | ВЗЕМЕТЕ | Дневници за използване |
| `/api/usage/request-logs` | ВЗЕМЕТЕ | Дневници на ниво заявка |
| `/api/usage/[connectionId]` | ВЗЕМЕТЕ | Използване на връзка |
| 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
| Крайна точка | Метод | Описание |
| ------------------------------- | ------------- | -------------------------------------- |
| `/api/settings` | ВЗЕМИ/ПОСТАВИ | Общи настройки |
| `/api/settings/proxy` | ВЗЕМИ/ПОСТАВИ | Конфигурация на мрежов прокси |
| `/api/settings/proxy/test` | ПУБЛИКАЦИЯ | Тествайте прокси връзката |
| `/api/settings/ip-filter` | ВЗЕМИ/ПОСТАВИ | Списък с разрешени/блокирани IP адреси |
| `/api/settings/thinking-budget` | ВЗЕМИ/ПОСТАВИ | Бюджет на жетон за разсъждение |
| `/api/settings/system-prompt` | ВЗЕМИ/ПОСТАВИ | Глобална системна подкана |
| 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
| Крайна точка | Метод | Описание |
| ------------------------ | -------------------- | ----------------------------- |
| `/api/sessions` | ВЗЕМЕТЕ | Проследяване на активна сесия |
| `/api/rate-limits` | ВЗЕМЕТЕ | Лимити за лихви по сметка |
| `/api/monitoring/health` | ВЗЕМЕТЕ | Здравна проверка |
| `/api/cache` | ПОЛУЧАВАНЕ/ИЗТРИВАНЕ | Кеш статистики / изчистване |
| 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
| Крайна точка | Метод | Описание |
| --------------------------- | ---------- | ------------------------------------------------ |
| `/api/db-backups` | ВЗЕМЕТЕ | Избройте наличните резервни копия |
| `/api/db-backups` | ПОСТАВЕТЕ | Създайте ръчно архивиране |
| `/api/db-backups` | ПУБЛИКАЦИЯ | Възстановяване от конкретен архив |
| `/api/db-backups/export` | ВЗЕМЕТЕ | Изтегляне на база данни като .sqlite файл |
| `/api/db-backups/import` | ПУБЛИКАЦИЯ | Качете .sqlite файл, за да замените базата данни |
| `/api/db-backups/exportAll` | ВЗЕМЕТЕ | Изтеглете пълното архивиране като .tar.gz архив |
| 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
| Крайна точка | Метод | Описание |
| ---------------------- | ---------- | ---------------------------------- |
| `/api/sync/cloud` | Различни | Операции за синхронизиране в облак |
| `/api/sync/initialize` | ПУБЛИКАЦИЯ | Инициализиране на синхронизиране |
| `/api/cloud/*` | Различни | Облачно управление |
| Endpoint | Method | Description |
| ---------------------- | ------- | --------------------- |
| `/api/sync/cloud` | Various | Cloud sync operations |
| `/api/sync/initialize` | POST | Initialize sync |
| `/api/cloud/*` | Various | Cloud management |
### CLI инструменти
### CLI Tools
| Крайна точка | Метод | Описание |
| ---------------------------------- | ------- | ---------------------- |
| `/api/cli-tools/claude-settings` | ВЗЕМЕТЕ | Клод CLI състояние |
| `/api/cli-tools/codex-settings` | ВЗЕМЕТЕ | Codex CLI състояние |
| `/api/cli-tools/droid-settings` | ВЗЕМЕТЕ | Droid CLI състояние |
| `/api/cli-tools/openclaw-settings` | ВЗЕМЕТЕ | OpenClaw CLI състояние |
| `/api/cli-tools/runtime/[toolId]` | ВЗЕМЕТЕ | Generic CLI runtime |
| 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 отговорите включват: `installed`, `runnable`, `command`, `commandPath`, `runtimeMode`, `reason`.
CLI responses include: `installed`, `runnable`, `command`, `commandPath`, `runtimeMode`, `reason`.
### Устойчивост и ограничения на скоростта
### ACP Agents
| Крайна точка | Метод | Описание |
| ----------------------- | ------------- | --------------------------------------------- |
| `/api/resilience` | ВЗЕМИ/ПОСТАВИ | Вземете/актуализирайте профили за устойчивост |
| `/api/resilience/reset` | ПУБЛИКАЦИЯ | Нулиране на прекъсвачи |
| `/api/rate-limits` | ВЗЕМЕТЕ | Състояние на ограничение на лимита по сметка |
| `/api/rate-limit` | ВЗЕМЕТЕ | Конфигурация на глобален лимит на скоростта |
| 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).
| Крайна точка | Метод | Описание |
| ------------ | -------------------- | --------------------------------------- |
| `/api/evals` | ВЗЕМЕТЕ/ПУБЛИКУВАЙТЕ | Избройте eval пакети / изпълнете оценка |
### 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 |
| Крайна точка | Метод | Описание |
| --------------- | -------------------------------- | ----------------------------------------- |
| `/api/policies` | ПОЛУЧАВАНЕ/ПУБЛИКУВАНЕ/ИЗТРИВАНЕ | Управление на правилата за маршрутизиране |
### Evals
### Съответствие
| Endpoint | Method | Description |
| ------------ | -------- | --------------------------------- |
| `/api/evals` | GET/POST | List eval suites / run evaluation |
| Крайна точка | Метод | Описание |
| --------------------------- | ------- | -------------------------------------------------- |
| `/api/compliance/audit-log` | ВЗЕМЕТЕ | Дневник за проверка на съответствието (последно N) |
### Policies
### v1beta (съвместим с Gemini)
| Endpoint | Method | Description |
| --------------- | --------------- | ----------------------- |
| `/api/policies` | GET/POST/DELETE | Manage routing policies |
| Крайна точка | Метод | Описание |
| -------------------------- | ---------- | ------------------------------------- |
| `/v1beta/models` | ВЗЕМЕТЕ | Избройте модели във формат Gemini |
| `/v1beta/models/{...path}` | ПУБЛИКАЦИЯ | Gemini `generateContent` крайна точка |
### Compliance
Тези крайни точки отразяват API формата на Gemini за клиенти, които очакват естествена съвместимост с Gemini SDK.
| Endpoint | Method | Description |
| --------------------------- | ------ | ----------------------------- |
| `/api/compliance/audit-log` | GET | Compliance audit log (last N) |
### Вътрешен/системен API
### v1beta (Gemini-Compatible)
| Крайна точка | Метод | Описание |
| --------------- | ---------- | ------------------------------------------------------------------------------ |
| `/api/init` | ВЗЕМЕТЕ | Проверка за инициализация на приложението (използва се при първото стартиране) |
| `/api/tags` | ВЗЕМЕТЕ | Тагове за модели, съвместими с Ollama (за клиенти на Ollama) |
| `/api/restart` | ПУБЛИКАЦИЯ | Задейства грациозно рестартиране на сървъра |
| `/api/shutdown` | ПУБЛИКАЦИЯ | Задействайте грациозно изключване на сървъра |
| Endpoint | Method | Description |
| -------------------------- | ------ | --------------------------------- |
| `/v1beta/models` | GET | List models in Gemini format |
| `/v1beta/models/{...path}` | POST | Gemini `generateContent` endpoint |
> **Забележка:** Тези крайни точки се използват вътрешно от системата или за съвместимост с клиента Ollama. Те обикновено не се извикват от крайните потребители.
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
@@ -317,9 +331,9 @@ Authorization: Bearer your-api-key
Content-Type: multipart/form-data
```
Транскрибирайте аудио файлове с помощта на Deepgram или AssemblyAI.
Transcribe audio files using Deepgram or AssemblyAI.
**Заявка:**
**Request:**
```bash
curl -X POST http://localhost:20128/v1/audio/transcriptions \
@@ -328,7 +342,7 @@ curl -X POST http://localhost:20128/v1/audio/transcriptions \
-F "model=deepgram/nova-3"
```
**Отговор:**
**Response:**
```json
{
@@ -339,15 +353,15 @@ curl -X POST http://localhost:20128/v1/audio/transcriptions \
}
```
**Поддържани доставчици:** `deepgram/nova-3`, `assemblyai/best`.
**Supported providers:** `deepgram/nova-3`, `assemblyai/best`.
**Поддържани формати:** `mp3`, `wav`, `m4a`, `flac`, `ogg`, `webm`.
**Supported formats:** `mp3`, `wav`, `m4a`, `flac`, `ogg`, `webm`.
---
## Съвместимост с Ollama
## Ollama Compatibility
За клиенти, които използват API формат на Ollama:
For clients that use Ollama's API format:
```bash
# Chat endpoint (Ollama format)
@@ -357,18 +371,18 @@ POST /v1/api/chat
GET /api/tags
```
Заявките се превеждат автоматично между Ollama и вътрешни формати.
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
{
@@ -381,7 +395,7 @@ GET /api/telemetry/summary
---
## Бюджет
## Budget
```bash
# Get budget status for all API keys
@@ -400,7 +414,7 @@ Content-Type: application/json
---
## Наличност на модела
## Model Availability
```bash
# Get real-time model availability across all providers
@@ -417,25 +431,25 @@ Content-Type: application/json
---
## Обработка на заявка
## Request Processing
1. Клиентът изпраща заявка до `/v1/*`
2. Обработчикът на маршрута извиква `handleChat`, `handleEmbedding`, `handleAudioTranscription` или `handleImageGeneration`
3. Моделът е разрешен (директен доставчик/модел или псевдоним/комбо)
4. Идентификационни данни, избрани от локална база данни с филтриране на наличността на акаунта
5. За чат: `handleChatCore`откриване на формат, превод, проверка на кеша, проверка на идемпотентност
6. Изпълнителят на доставчика изпраща заявка нагоре по веригата
7. Отговор, преведен обратно във формат на клиента (чат) или върнат такъв, какъвто е (вграждания/изображения/аудио)
8. Записано използване/регистриране
9. Резервният вариант се прилага при грешки според комбо правилата
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
Пълна справка за архитектурата: [link](ARCHITECTURE.md)
Full architecture reference: [`ARCHITECTURE.md`](ARCHITECTURE.md)
---
## Удостоверяване
## Authentication
- Маршрутите на таблото за управление (`/dashboard/*`) използват бисквитка `auth_token`
- Входът използва запазен хеш на паролата; връщане към `INITIAL_PASSWORD`
- `requireLogin` превключваем чрез `/api/settings/require-login`
- `/v1/*` маршрутите по избор изискват Bearer API ключ, когато `REQUIRE_API_KEY=true`
- 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`
+357 -351
View File
@@ -1,71 +1,75 @@
# Архитектура OmniRoute
🌐 **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)
🌐 **Languages:** 🇺🇸 [English](../../ARCHITECTURE.md) | 🇧🇷 [Português (Brasil)](../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) | 🇩🇰 [Dansk](../da/ARCHITECTURE.md) | 🇫🇮 [Suomi](../fi/ARCHITECTURE.md) | 🇮🇱 [עברית](../he/ARCHITECTURE.md) | 🇭🇺 [Magyar](../hu/ARCHITECTURE.md) | 🇮🇩 [Bahasa Indonesia](../id/ARCHITECTURE.md) | 🇰🇷 [한국어](../ko/ARCHITECTURE.md) | 🇲🇾 [Bahasa Melayu](../ms/ARCHITECTURE.md) | 🇳🇱 [Nederlands](../nl/ARCHITECTURE.md) | 🇳🇴 [Norsk](../no/ARCHITECTURE.md) | 🇵🇹 [Português (Portugal)](../pt/ARCHITECTURE.md) | 🇷🇴 [Română](../ro/ARCHITECTURE.md) | 🇵🇱 [Polski](../pl/ARCHITECTURE.md) | 🇸🇰 [Slovenčina](../sk/ARCHITECTURE.md) | 🇸🇪 [Svenska](../sv/ARCHITECTURE.md) | 🇵🇭 [Filipino](../phi/ARCHITECTURE.md)
---
_Последна актуализация: 2026-02-18_
# 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)
OmniRoute е локален AI маршрутизиращ шлюз и табло за управление, изградено на Next.js.
Той осигурява една крайна точка, съвместима с OpenAI (`/v1/*`) и маршрутизира трафика през множество доставчици нагоре по веригата с превод, резервен вариант, опресняване на токени и проследяване на използването.
_Last updated: 2026-03-04_
Основни възможности:
## Executive Summary
- OpenAI-съвместима API повърхност за CLI/инструменти (28 доставчици)
- Превод на заявка/отговор във форматите на доставчика
- Резервна комбинация от модели (последователност от няколко модела)
- Резервен вариант на ниво акаунт (мулти акаунт на доставчик)
- OAuth + API-ключ управление на връзката на доставчика
- Генериране на вграждане чрез `/v1/embeddings` (6 доставчика, 9 модела)
- Генериране на изображения чрез `/v1/images/generations` (4 доставчика, 9 модела)
- Мислен синтактичен анализ на етикет (`<think>...</think>`) за модели на разсъждение
- Дезинфекция на отговора за стриктна съвместимост с OpenAI SDK
- Нормализиране на ролята (разработчик→система, система→потребител) за съвместимост между доставчици
- Структурирано преобразуване на изход (json_schema → Gemini responseSchema)
- Локална устойчивост за доставчици, ключове, псевдоними, комбинации, настройки, ценообразуване
- Проследяване на използване/разходи и регистриране на заявки
- Допълнителна облачна синхронизация за синхронизиране на множество устройства/състояние
- Списък с разрешени/блокирани IP адреси за контрол на достъпа до API
- Мислещо управление на бюджета (преминаване/автоматично/персонализирано/адаптивно)
- Бързо инжектиране на глобалната система
- Проследяване на сесии и пръстови отпечатъци
- Подобрено ограничаване на скоростта за всеки акаунт със специфични за доставчика профили
- Модел на прекъсвача за устойчивост на доставчика
- Анти-гръмотевична стадна защита с mutex заключване
- Кеш за дедупликация на заявки, базиран на подпис
- Слой на домейна: наличност на модела, правила за разходите, резервна политика, политика за блокиране
- Устойчивост на състоянието на домейна (кеш за запис на SQLite за резервни варианти, бюджети, блокировки, прекъсвачи на верига)
- Механизъм за правила за централизирана оценка на заявката (заключване → бюджет → резервен)
- Заявка за телеметрия с p50/p95/p99 агрегиране на латентност
- ID на корелация (X-Request-Id) за проследяване от край до край
- Регистриране на одит за съответствие с отказ за всеки API ключ
- Eval framework за осигуряване на качеството на LLM
- Resilience UI табло със статус на прекъсвача в реално време
- Модулни OAuth доставчици (12 отделни модула под `src/lib/oauth/providers/`)
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:
- Маршрутите на приложението Next.js под `src/app/api/*` прилагат както API на таблото за управление, така и API за съвместимост
- Споделено SSE/маршрутизиращо ядро в `src/sse/*` + `open-sse/*` обработва изпълнението на доставчика, превода, стрийминг, резервен вариант и използване
- 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 (`<think>...</think>`) 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
- Време за изпълнение на локален шлюз
- API за управление на таблото
- Удостоверяване на доставчика и опресняване на токена
- Заявка за превод и SSE стрийминг
- Локално състояние + постоянство на използване
- Допълнителна синхронизация в облака
## Scope and Boundaries
### Извън обхвата
### In Scope
- Внедряване на облачна услуга зад `NEXT_PUBLIC_CLOUD_URL`
- SLA/контролна равнина на доставчика извън локалния процес
- Самите външни CLI двоични файлове (Claude CLI, Codex CLI и т.н.)
- 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
@@ -81,8 +85,8 @@ flowchart LR
API[V1 Compatibility API\n/v1/*]
DASH[Dashboard + Management API\n/api/*]
CORE[SSE + Translation Core\nopen-sse + src/sse]
DB[(db.json)]
UDB[(usage.json + log.txt)]
DB[(storage.sqlite)]
UDB[(usage tables + log artifacts)]
end
subgraph Upstreams[Upstream Providers]
@@ -113,151 +117,152 @@ flowchart LR
DASH --> CLOUD
```
## Основни компоненти по време на изпълнение
## Core Runtime Components
## 1) API и слой за маршрутизиране (Маршрути на приложението Next.js)
## 1) API and Routing Layer (Next.js App Routes)
Основни директории:
Main directories:
- `src/app/api/v1/*` и `src/app/api/v1beta/*` за API за съвместимост
- `src/app/api/*` за API за управление/конфигуриране
- Следващото пренаписване в `next.config.mjs` преобразува `/v1/*` в `/api/v1/*`
- `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`включва потребителски модели с `custom: true`
- `src/app/api/v1/embeddings/route.ts`генериране на вграждане (6 доставчика)
- `src/app/api/v1/images/generations/route.ts`генериране на изображения (4+ доставчици, вкл. Antigravity/Nebius)
- `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`специален чат за всеки доставчик
- `src/app/api/v1/providers/[provider]/embeddings/route.ts`специални вграждания за всеки доставчик
- `src/app/api/v1/providers/[provider]/images/generations/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:
- Удостоверяване/настройки: `src/app/api/auth/*`, `src/app/api/settings/*`
- Доставчици/връзки: `src/app/api/providers*`
- Възли на доставчик: `src/app/api/provider-nodes*`
- Персонализирани модели: `src/app/api/provider-models` (GET/POST/DELETE)
- Каталог с модели: `src/app/api/models/catalog` (GET)
- Прокси конфигурация: `src/app/api/settings/proxy` (GET/PUT/DELETE) + `src/app/api/settings/proxy/test` (POST)
- 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/*`
- Ключове/псевдоними/комбота/цени: `src/app/api/keys*`, `src/app/api/models/alias`, `src/app/api/combos*`, `src/app/api/pricing`
- Използване: `src/app/api/usage/*`
- Синхронизиране/облак: `src/app/api/sync/*`, `src/app/api/cloud/*`
- Помощни инструменти за CLI: `src/app/api/cli-tools/*`
- IP филтър: `src/app/api/settings/ip-filter` (GET/PUT)
- Бюджет за мислене: `src/app/api/settings/thinking-budget` (GET/PUT)
- Системна подкана: `src/app/api/settings/system-prompt` (GET/PUT)
- Сесии: `src/app/api/sessions` (GET)
- Ограничения на скоростта: `src/app/api/rate-limits` (GET)
- Устойчивост: `src/app/api/resilience` (GET/PATCH) — профили на доставчик, прекъсвач, състояние на ограничение на скоростта
- Нулиране на устойчивостта: `src/app/api/resilience/reset` (POST) — нулиране на прекъсвачи + охлаждане
- Кеш статистики: `src/app/api/cache/stats` (ПОЛУЧАВАНЕ/ИЗТРИВАНЕ)
- Наличност на модела: `src/app/api/models/availability` (GET/POST)
- Телеметрия: `src/app/api/telemetry/summary` (GET)
- Бюджет: `src/app/api/usage/budget` (GET/POST)
- Резервни вериги: `src/app/api/fallback/chains` (GET/POST/DELETE)
- Одит за съответствие: `src/app/api/compliance/audit-log` (GET)
- Стойности: `src/app/api/evals` (GET/POST), `src/app/api/evals/[suiteId]` (GET)
- Правила: `src/app/api/policies` (GET/POST)
- 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 + ядро за превод
## 2) SSE + Translation Core
Основни модули на потока:
Main flow modules:
- Запис: `src/sse/handlers/chat.ts`
- Основна оркестрация: `open-sse/handlers/chatCore.ts`
- Адаптери за изпълнение на доставчика: `open-sse/executors/*`
- Откриване на формат/конфигурация на доставчика: `open-sse/services/provider.ts`
- Разбор/разрешаване на модела: `src/sse/services/model.ts`, `open-sse/services/model.ts`
- Резервна логика на акаунта: `open-sse/services/accountFallback.ts`
- Регистър на преводите: `open-sse/translator/index.ts`
- Трансформации на потока: `open-sse/utils/stream.ts`, `open-sse/utils/streamHandler.ts`
- Извличане/нормализиране на използването: `open-sse/utils/usageTracking.ts`
- Мислен анализатор на етикети: `open-sse/utils/thinkTagParser.ts`
- Манипулатор за вграждане: `open-sse/handlers/embeddings.ts`
- Регистър на доставчика на вграждане: `open-sse/config/embeddingRegistry.ts`
- Манипулатор за генериране на изображения: `open-sse/handlers/imageGeneration.ts`
- Регистър на доставчика на изображения: `open-sse/config/imageRegistry.ts`
- Саниране на отговора: `open-sse/handlers/responseSanitizer.ts`
- Нормализация на ролята: `open-sse/services/roleNormalizer.ts`
- 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):
- Избор/точкуване на акаунт: `open-sse/services/accountSelector.ts`
- Управление на жизнения цикъл на контекста: `open-sse/services/contextManager.ts`
- Налагане на IP филтър: `open-sse/services/ipFilter.ts`
- Проследяване на сесии: `open-sse/services/sessionManager.ts`
- Искане за дедупликация: `open-sse/services/signatureCache.ts`
- Системно бързо инжектиране: `open-sse/services/systemPrompt.ts`
- Мислещо управление на бюджета: `open-sse/services/thinkingBudget.ts`
- Маршрутизиране на модела със заместващи знаци: `open-sse/services/wildcardRouter.ts`
- Управление на лимита на скоростта: `open-sse/services/rateLimitManager.ts`
- Прекъсвач: `open-sse/services/circuitBreaker.ts`
- 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:
- Наличност на модела: `src/lib/domain/modelAvailability.ts`
- Правила/бюджети за разходите: `src/lib/domain/costRules.ts`
- Резервна политика: `src/lib/domain/fallbackPolicy.ts`
- Комбо резолвер: `src/lib/domain/comboResolver.ts`
- Правила за блокиране: `src/lib/domain/lockoutPolicy.ts`
- Механизъм за правила: `src/domain/policyEngine.ts`централизирано блокиране → бюджет → резервна оценка
- Каталог с кодове за грешки: `src/lib/domain/errorCodes.ts`
- ID на заявката: `src/lib/domain/requestId.ts`
- Време за изчакване на извличане: `src/lib/domain/fetchTimeout.ts`
- Заявка за телеметрия: `src/lib/domain/requestTelemetry.ts`
- Съответствие/одит: `src/lib/domain/compliance/index.ts`
- Евал бегач: `src/lib/domain/evalRunner.ts`
- Устойчивост на състоянието на домейна: `src/lib/db/domainState.ts` — SQLite CRUD за резервни вериги, бюджети, история на разходите, състояние на блокиране, прекъсвачи
- 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 (12 отделни файла под `src/lib/oauth/providers/`):
OAuth provider modules (12 individual files under `src/lib/oauth/providers/`):
- Индекс на регистъра: `src/lib/oauth/providers/index.ts`
- Индивидуални доставчици: `claude.ts`, `codex.ts`, `gemini.ts`, `antigravity.ts`, `iflow.ts`, `qwen.ts`, `kimi-coding.ts`, `github.ts`, `kiro.ts`, `cursor.ts`, `kilocode.ts`, `cline.ts`
- Тънка обвивка: `src/lib/oauth/providers.ts`повторно експортиране от отделни модули
- Registry index: `src/lib/oauth/providers/index.ts`
- Individual providers: `claude.ts`, `codex.ts`, `gemini.ts`, `antigravity.ts`, `iflow.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) Слой за устойчивост
## 3) Persistence Layer
Основно състояние DB:
Primary state DB (SQLite):
- `src/lib/localDb.ts`
- файл: `${DATA_DIR}/db.json` (или `$XDG_CONFIG_HOME/omniroute/db.json`, когато е зададено, в противен случай `~/.omniroute/db.json`)
- обекти: providerConnections, providerNodes, modelAliases, комбинации, apiKeys, настройки, ценообразуване, **customModels**, **proxyConfig**, **ipFilter**, **thinkingBudget**, **systemPrompt**
- 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**
DB за използване:
Usage persistence:
- `src/lib/usageDb.ts`
- файлове: `${DATA_DIR}/usage.json`, `${DATA_DIR}/log.txt`, `${DATA_DIR}/call_logs/`
- следва същата основна политика за директория като `localDb` (`DATA_DIR`, след това `XDG_CONFIG_HOME/omniroute`, когато е зададено)
- разложен на фокусирани подмодули: `migrations.ts`, `usageHistory.ts`, `costCalculator.ts`, `usageStats.ts`, `callLogs.ts`
- 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/`, `<repo>/logs/...`)
- legacy JSON files are migrated to SQLite by startup migrations when present
DB на състоянието на домейна (SQLite):
Domain State DB (SQLite):
- `src/lib/db/domainState.ts` — CRUD операции за състояние на домейна
- Таблици (създадени в `src/lib/db/core.ts`): `domain_fallback_chains`, `domain_budgets`, `domain_cost_history`, `domain_lockout_state`, `domain_circuit_breakers`
- Модел на кеша за запис: Картите в паметта са авторитетни по време на изпълнение; мутациите се записват синхронно в SQLite; състоянието се възстановява от DB при студен старт
- `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) Удостоверяване + повърхности за сигурност
## 4) Auth + Security Surfaces
- Удостоверяване на бисквитките на таблото за управление: `src/proxy.ts`, `src/app/api/auth/login/route.ts`
- Генериране/проверка на API ключ: `src/shared/utils/apiKey.ts`
- Тайните на доставчика се запазват в `providerConnections` записи
- Поддръжка на изходящ прокси чрез `open-sse/utils/proxyFetch.ts` (env vars) и `open-sse/utils/networkProxy.ts` (конфигурируем за всеки доставчик или глобално)
- 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) Синхронизиране в облак
## 5) Cloud Sync
- Инициализация на планировчика: `src/lib/initCloudSync.ts`, `src/shared/services/initializeCloudSync.ts`
- Периодична задача: `src/shared/services/cloudSyncScheduler.ts`
- Контролен маршрут: `src/app/api/sync/cloud/route.ts`
- 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`
## Жизнен цикъл на заявка (`/v1/chat/completions`)
## Request Lifecycle (`/v1/chat/completions`)
```mermaid
sequenceDiagram
@@ -304,7 +309,7 @@ sequenceDiagram
Stream->>Usage: extract usage + persist history/log
```
## Комбо + Резервен поток на акаунт
## Combo + Account Fallback Flow
```mermaid
flowchart TD
@@ -334,9 +339,9 @@ flowchart TD
Q -- No --> R[Return all unavailable]
```
Резервните решения се управляват от `open-sse/services/accountFallback.ts` с помощта на кодове за състояние и евристика за съобщения за грешка.
Fallback decisions are driven by `open-sse/services/accountFallback.ts` using status codes and error-message heuristics.
## Жизнен цикъл на внедряване на OAuth и опресняване на токени
## OAuth Onboarding and Token Refresh Lifecycle
```mermaid
sequenceDiagram
@@ -366,9 +371,9 @@ sequenceDiagram
Test-->>UI: validation result
```
Опресняването по време на трафик на живо се изпълнява вътре в `open-sse/handlers/chatCore.ts` чрез изпълнител `refreshCredentials()`.
Refresh during live traffic is executed inside `open-sse/handlers/chatCore.ts` via executor `refreshCredentials()`.
## Жизнен цикъл на Cloud Sync (Активиране / Синхронизиране / Деактивиране)
## Cloud Sync Lifecycle (Enable / Sync / Disable)
```mermaid
sequenceDiagram
@@ -400,9 +405,9 @@ sequenceDiagram
Sync-->>UI: disabled
```
Периодичното синхронизиране се задейства от `CloudSyncScheduler`, когато облакът е активиран.
Periodic sync is triggered by `CloudSyncScheduler` when cloud is enabled.
## Модел на данни и карта за съхранение
## Data Model and Storage Map
```mermaid
erDiagram
@@ -503,14 +508,14 @@ erDiagram
}
```
Файлове за физическо съхранение:
Physical storage files:
- основно състояние: `${DATA_DIR}/db.json` (или `$XDG_CONFIG_HOME/omniroute/db.json`, когато е зададено, в противен случай `~/.omniroute/db.json`)
- статистика за използване: `${DATA_DIR}/usage.json`
- Редове на заявката: `${DATA_DIR}/log.txt`
- незадължителни сесии за преводач/заявка за отстраняване на грешки: `<repo>/logs/...`
- 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: `<repo>/logs/...`
## Топология на разполагане
## Deployment Topology
```mermaid
flowchart LR
@@ -522,8 +527,8 @@ flowchart LR
subgraph ContainerOrProcess[OmniRoute Runtime]
Next[Next.js Server\nPORT=20128]
Core[SSE Core + Executors]
MainDB[(db.json)]
UsageDB[(usage.json/log.txt)]
MainDB[(storage.sqlite)]
UsageDB[(usage tables + log artifacts)]
end
subgraph External[External Services]
@@ -541,241 +546,242 @@ flowchart LR
Next --> SyncCloud
```
## Съпоставяне на модул (критично за вземане на решения)
## Module Mapping (Decision-Critical)
### Модули за маршрут и API
### Route and API Modules
- `src/app/api/v1/*`, `src/app/api/v1beta/*`: API за съвместимост
- `src/app/api/v1/providers/[provider]/*`: специални маршрути за всеки доставчик (чат, вграждания, изображения)
- `src/app/api/providers*`: доставчик CRUD, валидиране, тестване
- `src/app/api/provider-nodes*`: персонализирано съвместимо управление на възли
- `src/app/api/provider-models`: персонализирано управление на модела (CRUD)
- `src/app/api/models/catalog`: пълен модел каталог API (всички типове групирани по доставчик)
- `src/app/api/oauth/*`: OAuth/код на устройство протича
- `src/app/api/keys*`: жизнен цикъл на локален API ключ
- `src/app/api/models/alias`: управление на псевдоними
- `src/app/api/combos*`: резервно комбо управление
- `src/app/api/pricing`: ценообразуване отменя за изчисляване на разходите
- `src/app/api/settings/proxy`: конфигурация на прокси (GET/PUT/DELETE)
- `src/app/api/settings/proxy/test`: тест за изходяща прокси връзка (POST)
- `src/app/api/usage/*`: API за използване и регистрационни файлове
- `src/app/api/sync/*` + `src/app/api/cloud/*`: облачно синхронизиране и помощници в облака
- `src/app/api/cli-tools/*`: локални писатели/контролери на CLI конфигурация
- `src/app/api/settings/ip-filter`: списък с разрешени/блокирани IP адреси (GET/PUT)
- `src/app/api/settings/thinking-budget`: конфигурация на бюджета на мислещ токен (GET/PUT)
- `src/app/api/settings/system-prompt`: глобална системна подкана (GET/PUT)
- `src/app/api/sessions`: списък с активни сесии (GET)
- `src/app/api/rate-limits`: състояние на ограничение на скоростта на сметка (GET)
- `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`: анализ на заявка, комбо обработка, цикъл за избор на акаунт
- `open-sse/handlers/chatCore.ts`: превод, изпращане на изпълнителя, обработка на повторен опит/опресняване, настройка на потока
- `open-sse/executors/*`: специфично за доставчика поведение на мрежата и формата
- `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`: регистър на преводача и оркестрация
- Заявка за преводачи: `open-sse/translator/request/*`
- Преводачи на отговори: `open-sse/translator/response/*`
- Константи на формата: `open-sse/translator/formats.ts`
- `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/localDb.ts`: постоянна конфигурация/състояние
- `src/lib/usageDb.ts`: хронология на използването и регистрационни файлове на текущи заявки
- `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)
Всеки доставчик има специализиран изпълнител, разширяващ `BaseExecutor` (в `open-sse/executors/base.ts`), който осигурява изграждане на URL адрес, изграждане на заглавка, повторен опит с експоненциално забавяне, кукички за опресняване на идентификационни данни и метода за оркестрация `execute()`.
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.
| Изпълнител | Доставчик(и) | Специална обработка |
| --------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------ | ----------------------------------------------------------------------------------- |
| `DefaultExecutor` | OpenAI, Claude, Gemini, Qwen, iFlow, OpenRouter, GLM, Kimi, MiniMax, DeepSeek, Groq, xAI, Mistral, Perplexity, Together, Fireworks, Cerebras, Cohere, NVIDIA | Конфигурация на динамичен URL/заглавие за доставчик |
| `AntigravityExecutor` | Google Антигравитация | Идентификационни номера на персонализирани проекти/сесии, повторен опит след анализ |
| `CodexExecutor` | OpenAI Codex | Вкарва системни инструкции, налага усилие за разсъждение |
| `CursorExecutor` | Курсор IDE | ConnectRPC протокол, Protobuf кодиране, подписване на заявка чрез контролна сума |
| `GithubExecutor` | Копилот на GitHub | Опресняване на Copilot token, заглавки, имитиращи VSCode |
| `KiroExecutor` | AWS CodeWhisperer/Киро | AWS EventStream двоичен формат → SSE конвертиране |
| `GeminiCLIExecutor` | Gemini CLI | Цикъл на опресняване на Google OAuth токен |
| Executor | Provider(s) | Special Handling |
| --------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------ | -------------------------------------------------------------------- |
| `DefaultExecutor` | OpenAI, Claude, Gemini, Qwen, iFlow, 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 |
Всички други доставчици (включително персонализирани съвместими възли) използват `DefaultExecutor`.
All other providers (including custom compatible nodes) use the `DefaultExecutor`.
## Матрица за съвместимост на доставчика
## Provider Compatibility Matrix
| Доставчик | Формат | Удостоверяване | Поток | Непоточно | Опресняване на токена | API за използване |
| ----------------- | --------------- | ------------------------------ | ---------------- | --------- | --------------------- | ---------------------------- |
| Клод | Клод | API ключ / OAuth | ✅ | ✅ | ✅ | ⚠️ Само администратор |
| Близнаци | близнаци | API ключ / OAuth | ✅ | ✅ | ✅ | ⚠️ Облачна конзола |
| Gemini CLI | gemini-cli | OAuth | ✅ | ✅ | ✅ | ⚠️ Облачна конзола |
| Антигравитация | антигравитация | OAuth | ✅ | ✅ | ✅ | ✅ API с пълна квота |
| OpenAI | openai | API ключ | ✅ | ✅ | ❌ | ❌ |
| Кодекс | openai-отговори | OAuth | ✅ принуден | ❌ | ✅ | ✅ Ограничения на скоростта |
| Копилот на GitHub | openai | OAuth + Copilot Token | ✅ | ✅ | ✅ | ✅ Моментни снимки на квоти |
| Курсор | курсор | Персонализирана контролна сума | ✅ | ✅ | ❌ | ❌ |
| Киро | киро | AWS SSO OIDC | ✅ (EventStream) | ❌ | ✅ | ✅ Ограничения за използване |
| Куен | openai | OAuth | ✅ | ✅ | ✅ | ⚠️ По заявка |
| iFlow | openai | OAuth (основен) | ✅ | ✅ | ✅ | ⚠️ По заявка |
| OpenRouter | openai | API ключ | ✅ | ✅ | ❌ | ❌ |
| GLM/Кими/МиниМакс | Клод | API ключ | ✅ | ✅ | ❌ | ❌ |
| DeepSeek | openai | API ключ | ✅ | ✅ | ❌ | ❌ |
| Groq | openai | API ключ | ✅ | ✅ | ❌ | ❌ |
| xAI (Grok) | openai | API ключ | ✅ | ✅ | ❌ | ❌ |
| Мистрал | openai | API ключ | ✅ | ✅ | ❌ | ❌ |
| Недоумение | openai | API ключ | ✅ | ✅ | ❌ | ❌ |
| Заедно AI | openai | API ключ | ✅ | ✅ | ❌ | ❌ |
| Фойерверки AI | openai | API ключ | ✅ | ✅ | ❌ | ❌ |
| Мозъци | openai | API ключ | ✅ | ✅ | ❌ | ❌ |
| Cohere | openai | API ключ | ✅ | ✅ | ❌ | ❌ |
| NVIDIA NIM | openai | API ключ | ✅ | ✅ | ❌ | ❌ |
| 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 |
| iFlow | 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 чат/Отговори
- Клод
- Gemini/Gemini-CLI/Антигравитационен плик
- Киро
- Курсор
- OpenAI chat/Responses
- Claude
- Gemini/Gemini-CLI/Antigravity envelope
- Kiro
- Cursor
Преводите използват **OpenAI като хъб формат** — всички реализации преминават през OpenAI като междинен:
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:
- **Дефектификация на отговора** — Премахва нестандартните полета от отговорите във формат OpenAI (както стрийминг, така и без стрийминг), за да се гарантира стриктно съответствие с SDK
- **Нормализиране на ролята** — Преобразува `developer``system` за цели, които не са OpenAI; обединява `system``user` за модели, които отхвърлят системната роля (GLM, ERNIE)
- **Извличане на мислен етикет** — Анализира `<think>...</think>` блокове от съдържание в поле `reasoning_content`
- **Структуриран изход** — Преобразува OpenAI `response_format.json_schema` в `responseMimeType` + `responseSchema` на Gemini
- **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 `<think>...</think>` blocks from content into `reasoning_content` field
- **Structured output** — Converts OpenAI `response_format.json_schema` to Gemini's `responseMimeType` + `responseSchema`
## Поддържани API крайни точки
## Supported API Endpoints
| Крайна точка | Формат | Манипулатор |
| -------------------------------------------------- | ------------------------- | ------------------------------------------------------------------ |
| `POST /v1/chat/completions` | OpenAI чат | `src/sse/handlers/chat.ts` |
| `POST /v1/messages` | Съобщения на Клод | Същият манипулатор (автоматично разпознат) |
| `POST /v1/responses` | OpenAI отговори | `open-sse/handlers/responsesHandler.ts` |
| `POST /v1/embeddings` | OpenAI вграждания | `open-sse/handlers/embeddings.ts` |
| `GET /v1/embeddings` | Списък на модели | API маршрут |
| `POST /v1/images/generations` | OpenAI изображения | `open-sse/handlers/imageGeneration.ts` |
| `GET /v1/images/generations` | Списък на модели | API маршрут |
| `POST /v1/providers/{provider}/chat/completions` | OpenAI чат | Специализиран за всеки доставчик с валидиране на модел |
| `POST /v1/providers/{provider}/embeddings` | OpenAI вграждания | Специализиран за всеки доставчик с валидиране на модел |
| `POST /v1/providers/{provider}/images/generations` | OpenAI изображения | Специализиран за всеки доставчик с валидиране на модел |
| `POST /v1/messages/count_tokens` | Клод Токен Брой | API маршрут |
| `GET /v1/models` | Списък с модели на OpenAI | API маршрут (чат + вграждане + изображение + потребителски модели) |
| `GET /api/models/catalog` | Каталог | Всички модели, групирани по доставчик + тип |
| `POST /v1beta/models/*:streamGenerateContent` | Родом от Близнаци | API маршрут |
| `GET/PUT/DELETE /api/settings/proxy` | Прокси конфигурация | Конфигурация на мрежов прокси |
| `POST /api/settings/proxy/test` | Прокси връзка | Крайна точка на прокси тест за изправност/свързаност |
| `GET/POST/DELETE /api/provider-models` | Персонализирани модели | Персонализирано управление на модели за всеки доставчик |
| 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
Обходният манипулатор (`open-sse/utils/bypassHandler.ts`) прихваща известни заявки за „изхвърляне“ от Claude CLI — пингове за загряване, извличане на заглавия и преброяване на токени — и връща **фалшив отговор**, без да консумира токени на доставчика нагоре по веригата. Това се задейства само когато `User-Agent` съдържа `claude-cli`.
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
Регистраторът на заявки (`open-sse/utils/requestLogger.ts`) осигурява 7-етапен конвейер за регистриране на грешки, деактивиран по подразбиране, активиран чрез `ENABLE_REQUEST_LOGS=true`:
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
```
Файловете се записват в `<repo>/logs/<session>/` за всяка сесия на заявка.
Files are written to `<repo>/logs/<session>/` for each request session.
## Режими на отказ и устойчивост
## Failure Modes and Resilience
## 1) Наличност на акаунт/доставчик
## 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) Изтичане на токена
## 2) Token Expiry
- предварителна проверка и опресняване с повторен опит за опресняващи доставчици
- 401/403 повторен опит след опит за опресняване в основния път
- pre-check and refresh with retry for refreshable providers
- 401/403 retry after refresh attempt in core path
## 3) Безопасност на потока
## 3) Stream Safety
- контролер на потоци, който се изключва
- поток за превод с промиване в края на потока и обработка на `[DONE]`
- резервна оценка на използването, когато липсват метаданни за използване на доставчика
- disconnect-aware stream controller
- translation stream with end-of-stream flush and `[DONE]` handling
- usage estimation fallback when provider usage metadata is missing
## 4) Влошаване на облачната синхронизация
## 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) Цялост на данните
## 5) Data Integrity
- Миграция/поправка на DB форма за липсващи ключове
- повредени предпазни мерки за нулиране на JSON за localDb и usageDb
- SQLite schema migrations and auto-upgrade hooks at startup
- legacy JSON → SQLite migration compatibility path
## Наблюдаемост и оперативни сигнали
## Observability and Operational Signals
Източници на видимост по време на изпълнение:
Runtime visibility sources:
- регистрационни файлове на конзолата от `src/sse/utils/logger.ts`
- агрегати за използване на заявка в `usage.json`
- влизане на състоянието на текстова заявка `log.txt`
- незадължителни дълбоки регистрационни файлове за заявка/превод под `logs/`, когато `ENABLE_REQUEST_LOGS=true`
- крайни точки за използване на таблото за управление (`/api/usage/*`) за потребление на UI
- 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 тайна (`JWT_SECRET`) защитава проверката/подписването на бисквитките на таблото за управление
- Първоначалната резервна парола (`INITIAL_PASSWORD`, по подразбиране `123456`) трябва да бъде заменена при реални внедрявания
- API ключ HMAC secret (`API_KEY_SECRET`) защитава генерирания локален формат на API ключ
- Тайните на доставчика (API ключове/токени) се съхраняват в локалната база данни и трябва да бъдат защитени на ниво файлова система
- Крайните точки за синхронизиране в облак разчитат на удостоверяване на API ключ + семантика на идентификатор на машина
- 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:
- Приложение/удостоверяване: `JWT_SECRET`, `INITIAL_PASSWORD`
- Съхранение: `DATA_DIR`
- Съвместимо поведение на възел: `ALLOW_MULTI_CONNECTIONS_PER_COMPAT_NODE`
- Допълнителна отмяна на базата за съхранение (Linux/macOS, когато `DATA_DIR` не е зададен): `XDG_CONFIG_HOME`
- Хеширане на сигурността: `API_KEY_SECRET`, `MACHINE_ID_SALT`
- Регистриране: `ENABLE_REQUEST_LOGS`
- Синхронизиране/облачно URL адресиране: `NEXT_PUBLIC_BASE_URL`, `NEXT_PUBLIC_CLOUD_URL`
- Изходящ прокси: `HTTP_PROXY`, `HTTPS_PROXY`, `ALL_PROXY`, `NO_PROXY` и варианти с малки букви
- Флагове за функция SOCKS5: `ENABLE_SOCKS5_PROXY`, `NEXT_PUBLIC_ENABLE_SOCKS5_PROXY`
- Помощници за платформа/време на изпълнение (не специфична за приложението конфигурация): `APPDATA`, `NODE_ENV`, `PORT`, `HOSTNAME`
- 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` и `localDb` сега споделят една и съща основна политика за директория (`DATA_DIR` -> `XDG_CONFIG_HOME/omniroute` -> `~/.omniroute`) с мигриране на наследени файлове.
2. `/api/v1/route.ts` връща списък със статичен модел и не е основният източник на модели, използван от `/v1/models`.
3. Request logger записва пълни заглавки/тяло, когато е разрешено; третира регистрационната директория като чувствителна.
4. Поведението в облака зависи от правилния `NEXT_PUBLIC_BASE_URL` и достижимостта на крайната точка на облака.
5. Директорията `open-sse/` е публикувана като `@omniroute/open-sse` **npm workspace package**. Изходният код го импортира чрез `@omniroute/open-sse/...` (разрешено от Next.js `transpilePackages`). Пътищата на файловете в този документ все още използват името на директорията `open-sse/` за последователност.
6. Диаграмите в таблото за управление използват **Recharts** (базирани на SVG) за достъпни, интерактивни аналитични визуализации (стълбовидни диаграми на използването на модела, таблици с разбивка на доставчиците с проценти на успех).
7. E2E тестовете използват **Playwright** (`tests/e2e/`), изпълняват се чрез `npm run test:e2e`. Модулните тестове използват **Node.js test runner** (`tests/unit/`), изпълняват се чрез `npm run test:plan3`. Изходният код под `src/` е **TypeScript** (`.ts`/`.tsx`); работното пространство `open-sse/` остава JavaScript (`.js`).
8. Страницата с настройки е организирана в 5 раздела: Сигурност, Маршрутизиране (6 глобални стратегии: първо попълване, кръгъл-робин, p2c, произволна, най-малко използвана, оптимизирана по отношение на разходите), Устойчивост (ограничения на скоростта за редактиране, прекъсвач, политики), AI (мислещ бюджет, системна подкана, кеш за подкана), Разширени (прокси).
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
- Създаване от източник: `npm run build`
- Изграждане на Docker изображение: `docker build -t omniroute .`
- Стартирайте услугата и проверете:
- 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 целеви базов URL трябва да бъде `http://<host>:20128/v1`, когато `PORT=20128`
- CLI target base URL should be `http://<host>:20128/v1` when `PORT=20128`
+67
View File
@@ -0,0 +1,67 @@
🌐 **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 |
+351
View File
@@ -0,0 +1,351 @@
🌐 **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 инструменти — OmniRoute
Това ръководство обяснява как да инсталирате и конфигурирате всички поддържани AI CLI инструменти за използване на **OmniRoute** като унифициран бекенд.
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 / Gemini CLI / OpenCode / Cline / KiloCode / Continue / Kiro CLI
▼ (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
| 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 |
---
## 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
# 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 <command>` |
| `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"
```
+169 -165
View File
@@ -1,22 +1,26 @@
# omniroute — Документация на кодовата база
🌐 **Languages:** 🇺🇸 [English](../../CODEBASE_DOCUMENTATION.md) | 🇧🇷 [Português (Brasil)](../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) | 🇩🇰 [Dansk](../da/CODEBASE_DOCUMENTATION.md) | 🇫🇮 [Suomi](../fi/CODEBASE_DOCUMENTATION.md) | 🇮🇱 [עברית](../he/CODEBASE_DOCUMENTATION.md) | 🇭🇺 [Magyar](../hu/CODEBASE_DOCUMENTATION.md) | 🇮🇩 [Bahasa Indonesia](../id/CODEBASE_DOCUMENTATION.md) | 🇰🇷 [한국어](../ko/CODEBASE_DOCUMENTATION.md) | 🇲🇾 [Bahasa Melayu](../ms/CODEBASE_DOCUMENTATION.md) | 🇳🇱 [Nederlands](../nl/CODEBASE_DOCUMENTATION.md) | 🇳🇴 [Norsk](../no/CODEBASE_DOCUMENTATION.md) | 🇵🇹 [Português (Portugal)](../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) | 🇵🇭 [Filipino](../phi/CODEBASE_DOCUMENTATION.md)
> Изчерпателно, удобно за начинаещи ръководство за **omniroute** прокси рутер с изкуствен интелект с множество доставчици.
🌐 **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)
---
## 1. Какво е omniroute?
# omniroute — Codebase Documentation
omniroute е **прокси рутер**, който се намира между AI клиенти (Claude CLI, Codex, Cursor IDE и др.) и AI доставчици (Anthropic, Google, OpenAI, AWS, GitHub и др.). Решава един голям проблем:
🌐 **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)
> **Различните AI клиенти говорят различни „езици“ (API формати) и различните доставчици на AI също очакват различни „езици“.** omniroute превежда автоматично между тях.
Мислете за това като за универсален преводач в Обединените нации - всеки делегат може да говори всеки език и преводачът го преобразува за всеки друг делегат.
> A comprehensive, beginner-friendly guide to the **omniroute** multi-provider AI proxy router.
---
## 2. Преглед на архитектурата
## 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
@@ -61,20 +65,20 @@ graph LR
H -.-> G
```
### Основен принцип: Превод на централно ниво
### Core Principle: Hub-and-Spoke Translation
Всички преводи на формати преминават през **OpenAI формат като център**:
All format translation passes through **OpenAI format as the hub**:
```
Client Format → [OpenAI Hub] → Provider Format (request)
Provider Format → [OpenAI Hub] → Client Format (response)
```
Това означава, че имате нужда само от **N преводачи** (по един на формат) вместо от **N²** (всяка двойка).
This means you only need **N translators** (one per format) instead of **N²** (every pair).
---
## 3. Структура на проекта
## 3. Project Structure
```
omniroute/
@@ -104,22 +108,22 @@ omniroute/
---
## 4. Разбивка модул по модул
## 4. Module-by-Module Breakdown
### 4.1 Конфигурация (`open-sse/config/`)
### 4.1 Config (`open-sse/config/`)
**Единственият източник на истина** за всички конфигурации на доставчика.
The **single source of truth** for all provider configuration.
| Файл | Цел |
| ----------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `constants.ts` | `PROVIDERS` обект с основни URL адреси, идентификационни данни за OAuth (по подразбиране), заглавки и системни подкани по подразбиране за всеки доставчик. Също така дефинира `HTTP_STATUS`, `ERROR_TYPES`, `COOLDOWN_MS`, `BACKOFF_CONFIG` и `SKIP_PATTERNS`. |
| `credentialLoader.ts` | Зарежда външни идентификационни данни от `data/provider-credentials.json` и ги обединява върху твърдо кодираните настройки по подразбиране в `PROVIDERS`. Пази тайните извън контрола на източника, като същевременно поддържа обратна съвместимост. |
| `providerModels.ts` | Централен регистър на моделите: псевдоними на доставчика на карти → ID на модела. Функции като `getModels()`, `getProviderByAlias()`. |
| `codexInstructions.ts` | Системни инструкции, инжектирани в заявките на Codex (ограничения за редактиране, правила на пясъчника, правила за одобрение). |
| `defaultThinkingSignature.ts` | „Мислещи“ подписи по подразбиране за модели Claude и Gemini. |
| `ollamaModels.ts` | Дефиниция на схема за локални модели Ollama (име, размер, семейство, квантуване). |
| 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
@@ -142,9 +146,9 @@ flowchart TD
---
### 4.2 Изпълнители (`open-sse/executors/`)
### 4.2 Executors (`open-sse/executors/`)
Изпълнителите капсулират **специфична за доставчика логика**, използвайки **стратегически модел**. Всеки изпълнител замества основните методи, ако е необходимо.
Executors encapsulate **provider-specific logic** using the **Strategy Pattern**. Each executor overrides base methods as needed.
```mermaid
classDiagram
@@ -194,32 +198,32 @@ classDiagram
BaseExecutor <|-- GithubExecutor
```
| Изпълнител | Доставчик | Ключови специализации |
| ---------------- | ------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `base.ts` | — | Абстрактна база: изграждане на URL, заглавки, логика за повторен опит, опресняване на идентификационни данни |
| `default.ts` | Claude, Gemini, OpenAI, GLM, Kimi, MiniMax | Генерично опресняване на OAuth токен за стандартни доставчици |
| `antigravity.ts` | Google Cloud Code | Генериране на идентификатор на проект/сесия, резервен URL адрес с множество URL адреси, персонализирано анализиране на повторен опит от съобщения за грешка („нулиране след 2h7m23s) |
| `cursor.ts` | Курсор IDE | **Най-сложни**: SHA-256 контролна сума auth, Protobuf кодиране на заявка, двоичен EventStream → SSE отговор анализ |
| `codex.ts` | OpenAI Codex | Вкарва системни инструкции, управлява нивата на мислене, премахва неподдържаните параметри |
| `gemini-cli.ts` | Google Gemini CLI | Изграждане на персонализиран URL (`streamGenerateContent`), опресняване на Google OAuth токен |
| `github.ts` | Копилот на GitHub | Система с двоен токен (GitHub OAuth + Copilot token), имитиране на заглавката на VSCode |
| `kiro.ts` | AWS CodeWhisperer | Двоичен анализ на AWS EventStream, рамки за събития AMZN, оценка на токена |
| `index.ts` | — | Фабрика: картографира името на доставчика → клас изпълнител, с резервен вариант по подразбиране |
| 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 Манипулатори (`open-sse/handlers/`)
### 4.3 Handlers (`open-sse/handlers/`)
**Слоят за оркестрация** — координира превода, изпълнението, поточното предаване и обработката на грешки.
The **orchestration layer**coordinates translation, execution, streaming, and error handling.
| Файл | Цел |
| --------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `chatCore.ts` | **Централен оркестратор** (~600 реда). Обработва пълния жизнен цикъл на заявката: откриване на формат → превод → изпращане на изпълнител → стрийминг/не-стрийминг отговор → опресняване на токена → обработка на грешки → регистриране на използването. |
| `responsesHandler.ts` | Адаптер за API за отговори на OpenAI: преобразува формата на отговорите → Завършвания на чат → изпраща до `chatCore` → конвертира SSE обратно във формат на отговорите. |
| `embeddings.ts` | Манипулатор за генериране на вграждане: разрешава модел на вграждане → доставчик, изпраща до API на доставчика, връща съвместим с OpenAI отговор за вграждане. Поддържа 6+ доставчици. |
| `imageGeneration.ts` | Манипулатор за генериране на изображения: разрешава модел на изображение → доставчик, поддържа режими, съвместими с OpenAI, Gemini-image (Антигравитация) и резервни (Nebius). Връща base64 или URL изображения. |
| 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. |
#### Жизнен цикъл на заявка (chatCore.ts)
#### Request Lifecycle (chatCore.ts)
```mermaid
sequenceDiagram
@@ -258,28 +262,28 @@ sequenceDiagram
---
### 4.4 Услуги (`open-sse/services/`)
### 4.4 Services (`open-sse/services/`)
Бизнес логика, която поддържа манипулаторите и изпълнителите.
Business logic that supports the handlers and executors.
| Файл | Цел |
| -------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `provider.ts` | **Откриване на формат** (`detectFormat`): анализира структурата на тялото на заявката, за да идентифицира форматите Claude/OpenAI/Gemini/Antigravity/Responses (включва `max_tokens` евристика за Claude). Също така: изграждане на URL адреси, изграждане на заглавки, нормализиране на конфигурацията на мислене. Поддържа `openai-compatible-*` и `anthropic-compatible-*` динамични доставчици. |
| `model.ts` | Разбор на низ на модел (`claude/model-name``{provider: "claude", model: "model-name"}`), разрешаване на псевдоними с откриване на сблъсък, дезинфекция на входа (отхвърля преминаване на пътя/контролни знаци) и разрешаване на информация за модела с поддръжка на асинхронно получаване на псевдоними. |
| `accountFallback.ts` | Обработка на ограничение на скоростта: експоненциално забавяне (1s → 2s → 4s → макс. 2min), управление на изчакване на акаунта, класификация на грешките (кои грешки задействат резервно или не). |
| `tokenRefresh.ts` | Опресняване на OAuth токена за **всеки доставчик**: Google (Gemini, Antigravity), Claude, Codex, Qwen, iFlow, GitHub (OAuth + Copilot dual-token), Kiro (AWS SSO OIDC + Social Auth). Включва кеш за дедупликация на обещание по време на полет и повторен опит с експоненциално забавяне. |
| `combo.ts` | **Комбинирани модели**: вериги от резервни модели. Ако модел A се провали с допустима грешка за резервен вариант, опитайте модел B, след това C и т.н. Връща действителните кодове за състояние нагоре по веригата. |
| `usage.ts` | Извлича данни за квоти/използване от API на доставчика (квоти на GitHub Copilot, квоти на модела на Antigravity, ограничения на скоростта на Codex, разбивки на използването на Kiro, настройки на Claude). |
| `accountSelector.ts` | Интелигентен избор на акаунт с алгоритъм за точкуване: взема предвид приоритет, здравословно състояние, кръгова позиция и състояние на изчакване, за да избере оптималния акаунт за всяка заявка. |
| `contextManager.ts` | Управление на жизнения цикъл на контекста на заявката: създава и проследява контекстни обекти на заявка с метаданни (идентификатор на заявка, времеви клейма, информация за доставчика) за отстраняване на грешки и регистриране. |
| `ipFilter.ts` | IP-базиран контрол на достъпа: поддържа разрешени и блокирани режими. Валидира клиентския IP адрес спрямо конфигурирани правила, преди да обработи API заявки. |
| `sessionManager.ts` | Проследяване на сесии с пръстов отпечатък на клиента: проследява активни сесии с помощта на хеширани клиентски идентификатори, следи броя на заявките и предоставя показатели за сесиите. |
| `signatureCache.ts` | Кеш за дедупликация, базиран на подписи на заявки: предотвратява дублиране на заявки чрез кеширане на подписи на скорошни заявки и връщане на кеширани отговори за идентични заявки в рамките на времеви прозорец. |
| `systemPrompt.ts` | Инжектиране на глобална системна подкана: добавя пред или добавя конфигурируема системна подкана към всички заявки, с обработка на съвместимостта за всеки доставчик. |
| `thinkingBudget.ts` | Управление на бюджета на токените за разсъждение: поддържа режими за преминаване, автоматичен (конфигурация на лентово мислене), персонализиран (фиксиран бюджет) и адаптивен (мащабиран според сложността) режими за контролиране на токени за мислене/разсъждение. |
| `wildcardRouter.ts` | Маршрутизиране на модела със заместващи знаци: разрешава шаблони със заместващи знаци (напр. `*/claude-*`) до конкретни двойки доставчик/модел въз основа на наличност и приоритет. |
| 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, iFlow, 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
@@ -300,7 +304,7 @@ sequenceDiagram
Cache->>Cache: Delete cache entry
```
#### Резервна държавна машина на акаунта
#### Account Fallback State Machine
```mermaid
stateDiagram-v2
@@ -325,7 +329,7 @@ stateDiagram-v2
}
```
#### Комбиниран модел верига
#### Combo Model Chain
```mermaid
flowchart LR
@@ -344,11 +348,11 @@ flowchart LR
---
### 4.5 Преводач (`open-sse/translator/`)
### 4.5 Translator (`open-sse/translator/`)
**Машината за превод на формати**, използваща саморегистрираща се плъгин система.
The **format translation engine** using a self-registering plugin system.
#### Архитектура
#### Architecture
```mermaid
graph TD
@@ -374,15 +378,15 @@ graph TD
end
```
| Указател | Файлове | Описание |
| ------------ | ----------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `request/` | 8 преводачи | Преобразувайте тела на заявки между формати. Всеки файл се саморегистрира чрез `register(from, to, fn)` при импортиране. |
| `response/` | 7 преводачи | Преобразувайте поточно предавани отговори между формати. Обработва SSE типове събития, мисловни блокове, извиквания на инструменти. |
| `helpers/` | 6 помощника | Споделени помощни програми: `claudeHelper` (извличане на системни подкани, мислеща конфигурация), `geminiHelper` (съпоставяне на части/съдържание), `openaiHelper` (филтриране на формат), `toolCallHelper` (генериране на ID, инжектиране на липсващ отговор), `maxTokensHelper`, `responsesApiHelper`. |
| `index.ts` | — | Механизъм за превод: `translateRequest()`, `translateResponse()`, управление на състоянието, регистър. |
| `formats.ts` | — | Константи на формата: `OPENAI`, `CLAUDE`, `GEMINI`, `ANTIGRAVITY`, `KIRO`, `CURSOR`, `OPENAI_RESPONSES`. |
| 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:
@@ -395,17 +399,17 @@ import "./request/claude-to-openai.js"; // ← self-registers
---
### 4.6 Помощни средства (`open-sse/utils/`)
### 4.6 Utils (`open-sse/utils/`)
| Файл | Цел |
| ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `error.ts` | Изграждане на отговор при грешка (съвместим с OpenAI формат), анализиране на грешка нагоре по веригата, извличане на времето за повторен опит на Antigravity от съобщения за грешка, поточно предаване на грешка на SSE. |
| `stream.ts` | **SSE Transform Stream**основният тръбопровод за стрийминг. Два режима: `TRANSLATE` (превод в пълен формат) и `PASSTHROUGH` (нормализиране + извличане на използването). Управлява буфериране на парчета, оценка на използването, проследяване на дължината на съдържанието. Екземплярите на енкодер/декодер на поток избягват споделено състояние. |
| `streamHelpers.ts` | Помощни програми за SSE на ниско ниво: `parseSSELine` (толерантни към бели интервали), `hasValuableContent` (филтрира празни парчета за OpenAI/Claude/Gemini), `fixInvalidId`, `formatSSE` (сериализация на SSE, съобразена с формата с `perf_metrics` почистване). |
| `usageTracking.ts` | Извличане на използване на токени от всеки формат (Claude/OpenAI/Gemini/Responses), оценка с отделни съотношения на инструмент/съобщение char-per-token, добавяне на буфер (марж за безопасност от 2000 токена), филтриране на специфично за формат поле, конзолно регистриране с ANSI цветове. |
| `requestLogger.ts` | Регистриране на искания на базата на файл (включване чрез `ENABLE_REQUEST_LOGS=true`). Създава сесийни папки с номерирани файлове: `1_req_client.json``7_res_client.txt`. Всички I/O са асинхронни (задействай и забрави). Маскира чувствителните заглавки. |
| `bypassHandler.ts` | Прихваща специфични модели от Claude CLI (извличане на заглавие, загряване, броене) и връща фалшиви отговори, без да се обажда на доставчик. Поддържа както стрийминг, така и не стрийминг. Умишлено ограничен до Claude CLI обхват. |
| `networkProxy.ts` | Разрешава URL адрес на изходящ прокси за даден доставчик с приоритет: специфична за доставчика конфигурация → глобална конфигурация → променливи на средата (`HTTPS_PROXY`/`HTTP_PROXY`/`ALL_PROXY`). Поддържа `NO_PROXY` изключения. Кешира конфигурацията за 30s. |
| 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
@@ -429,7 +433,7 @@ flowchart TD
style M fill:#9f9,stroke:#333
```
#### Структура на сесията на регистратора на заявка
#### Request Logger Session Structure
```
logs/
@@ -447,109 +451,109 @@ logs/
---
### 4.7 Приложен слой (`src/`)
### 4.7 Application Layer (`src/`)
| Указател | Цел |
| ------------- | ------------------------------------------------------------------------------------------------------------ |
| `src/app/` | Уеб потребителски интерфейс, API маршрути, Express междинен софтуер, манипулатори за обратно извикване OAuth |
| `src/lib/` | Достъп до база данни (`localDb.ts`, `usageDb.ts`), удостоверяване, споделено |
| `src/mitm/` | Прокси помощни програми Man-in-the-middle за прихващане на трафик на доставчик |
| `src/models/` | Дефиниции на модел на база данни |
| `src/shared/` | Обвивки около open-sse функции (доставчик, поток, грешка и др.) |
| `src/sse/` | SSE манипулатори на крайни точки, които свързват библиотеката open-sse към експресни маршрути |
| `src/store/` | Управление на състоянието на приложението |
| 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 |
#### Известни API маршрути
#### Notable API Routes
| Маршрут | Методи | Цел |
| --------------------------------------------- | -------------------------------- | ------------------------------------------------------------------------------------------------------- |
| `/api/provider-models` | ПОЛУЧАВАНЕ/ПУБЛИКУВАНЕ/ИЗТРИВАНЕ | CRUD за потребителски модели на доставчик |
| `/api/models/catalog` | ВЗЕМЕТЕ | Обобщен каталог на всички модели (чат, вграждане, изображение, персонализирани), групирани по доставчик |
| `/api/settings/proxy` | ПОЛУЧАВАНЕ/ПОСТАВЯНЕ/ИЗТРИВАНЕ | Конфигурация на йерархичен изходящ прокси (`global/providers/combos/keys`) |
| `/api/settings/proxy/test` | ПУБЛИКАЦИЯ | Потвърждава прокси свързаността и връща публичен IP/латентност |
| `/v1/providers/[provider]/chat/completions` | ПУБЛИКАЦИЯ | Специализирани завършвания на чат за всеки доставчик с валидиране на модел |
| `/v1/providers/[provider]/embeddings` | ПУБЛИКАЦИЯ | Специализирани вграждания за всеки доставчик с валидиране на модел |
| `/v1/providers/[provider]/images/generations` | ПУБЛИКАЦИЯ | Специално генериране на изображения за всеки доставчик с валидиране на модел |
| `/api/settings/ip-filter` | ВЗЕМИ/ПОСТАВИ | Управление на списък с разрешени/блокирани IP |
| `/api/settings/thinking-budget` | ВЗЕМИ/ПОСТАВИ | Конфигурация на бюджета на токена за разсъждение (пропускане/автоматично/персонализирано/адаптивно) |
| `/api/settings/system-prompt` | ВЗЕМИ/ПОСТАВИ | Бързо инжектиране на глобална система за всички заявки |
| `/api/sessions` | ВЗЕМЕТЕ | Проследяване на активна сесия и показатели |
| `/api/rate-limits` | ВЗЕМЕТЕ | Състояние на ограничение на лимита по сметка |
| 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. Ключови модели на дизайн
## 5. Key Design Patterns
### 5.1 Hub-and-Spoke превод
### 5.1 Hub-and-Spoke Translation
Всички формати се превеждат през **OpenAI формат като център**. Добавянето на нов доставчик изисква само писане на **една двойка** преводачи (към/от OpenAI), а не на N двойки.
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 Модел на стратегия за изпълнител
### 5.2 Executor Strategy Pattern
Всеки доставчик има специален клас изпълнител, наследен от `BaseExecutor`. Фабриката в `executors/index.ts` избира правилния по време на изпълнение.
Each provider has a dedicated executor class inheriting from `BaseExecutor`. The factory in `executors/index.ts` selects the right one at runtime.
### 5.3 Саморегистрираща се плъгин система
### 5.3 Self-Registering Plugin System
Модулите за преводач се регистрират при импортиране чрез `register()`. Добавянето на нов преводач е просто създаване на файл и импортирането му.
Translator modules register themselves on import via `register()`. Adding a new translator is just creating a file and importing it.
### 5.4 Резервен акаунт с експоненциално отстъпление
### 5.4 Account Fallback with Exponential Backoff
Когато доставчикът върне 429/401/500, системата може да превключи към следващия акаунт, прилагайки експоненциално охлаждане (1s → 2s → 4s → max 2min).
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
### 5.5 Combo Model Chains
„Комбо“ групира множество низове `provider/model`. Ако първият не успее, автоматично се върнете към следващия.
A "combo" groups multiple `provider/model` strings. If the first fails, fallback to the next automatically.
### 5.6 Поточен превод с пълно състояние
### 5.6 Stateful Streaming Translation
Преводът на отговор поддържа състоянието в SSE блокове (проследяване на мислещ блок, натрупване на извикване на инструмент, индексиране на блок съдържание) чрез механизма `initState()`.
Response translation maintains state across SSE chunks (thinking block tracking, tool call accumulation, content block indexing) via the `initState()` mechanism.
### 5.7 Буфер за безопасност при използване
### 5.7 Usage Safety Buffer
Добавя се буфер от 2000 токена към отчетеното използване, за да се предотврати достигането на ограниченията на контекстните прозорци на клиентите поради натоварване от системни подкани и превод на формати.
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. Поддържани формати
## 6. Supported Formats
| Формат | Посока | Идентификатор |
| ------------------------- | -------------- | ------------------ |
| Завършвания на OpenAI чат | източник + цел | `openai` |
| OpenAI Responses API | източник + цел | `openai-responses` |
| Антропичен Клод | източник + цел | `claude` |
| Google Gemini | източник + цел | `gemini` |
| Google Gemini CLI | само цел | `gemini-cli` |
| Антигравитация | източник + цел | `antigravity` |
| AWS Киро | само цел | `kiro` |
| Курсор | само цел | `cursor` |
| 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. Поддържани доставчици
## 7. Supported Providers
| Доставчик | Метод за удостоверяване | Изпълнител | Основни бележки |
| ------------------------ | -------------------------------- | --------------- | -------------------------------------------------- |
| Антропичен Клод | API ключ или OAuth | По подразбиране | Използва `x-api-key` заглавка |
| Google Gemini | API ключ или OAuth | По подразбиране | Използва `x-goog-api-key` заглавка |
| Google Gemini CLI | OAuth | GeminiCLI | Използва `streamGenerateContent` крайна точка |
| Антигравитация | OAuth | Антигравитация | Multi-URL резервен, персонализиран повторен анализ |
| OpenAI | API ключ | По подразбиране | Удостоверяване на стандартен носител |
| Кодекс | OAuth | Кодекс | Инжектира системни инструкции, управлява мисленето |
| Копилот на GitHub | OAuth + Copilot token | Github | Двоен токен, имитираща заглавка на VSCode |
| Киро (AWS) | AWS SSO OIDC или социални | Киро | Парсинг на двоичен EventStream |
| Курсор IDE | Контролна сума за удостоверяване | Курсор | Protobuf кодиране, SHA-256 контролни суми |
| Куен | OAuth | По подразбиране | Стандартно удостоверяване |
| iFlow | OAuth (основен + носител) | По подразбиране | Заглавка за двойно удостоверяване |
| OpenRouter | API ключ | По подразбиране | Удостоверяване на стандартен носител |
| GLM, Kimi, MiniMax | API ключ | По подразбиране | Съвместим с Claude, използвайте `x-api-key` |
| `openai-compatible-*` | API ключ | По подразбиране | Динамично: всяка крайна точка, съвместима с OpenAI |
| `anthropic-compatible-*` | API ключ | По подразбиране | Динамично: всяка крайна точка, съвместима с Claude |
| 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 |
| iFlow | 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. Резюме на потока от данни
## 8. Data Flow Summary
### Заявка за поточно предаване
### Streaming Request
```mermaid
flowchart LR
@@ -566,7 +570,7 @@ flowchart LR
K --> L["logUsage()\nsaveRequestUsage()"]
```
### Заявка без поточно предаване
### Non-Streaming Request
```mermaid
flowchart LR
@@ -577,7 +581,7 @@ flowchart LR
E --> F["Return JSON\nresponse"]
```
### Байпасен поток (Claude CLI)
### Bypass Flow (Claude CLI)
```mermaid
flowchart LR
+91 -21
View File
@@ -1,77 +1,147 @@
# OmniRoute — Галерия с функции на таблото
# OmniRoute — Dashboard Features Gallery (Български)
🌐 **Languages:** 🇺🇸 [English](../../FEATURES.md) | 🇧🇷 [Português (Brasil)](../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) | 🇩🇰 [Dansk](../da/FEATURES.md) | 🇫🇮 [Suomi](../fi/FEATURES.md) | 🇮🇱 [עברית](../he/FEATURES.md) | 🇭🇺 [Magyar](../hu/FEATURES.md) | 🇮🇩 [Bahasa Indonesia](../id/FEATURES.md) | 🇰🇷 [한국어](../ko/FEATURES.md) | 🇲🇾 [Bahasa Melayu](../ms/FEATURES.md) | 🇳🇱 [Nederlands](../nl/FEATURES.md) | 🇳🇴 [Norsk](../no/FEATURES.md) | 🇵🇹 [Português (Portugal)](../pt/FEATURES.md) | 🇷🇴 [Română](../ro/FEATURES.md) | 🇵🇱 [Polski](../pl/FEATURES.md) | 🇸🇰 [Slovenčina](../sk/FEATURES.md) | 🇸🇪 [Svenska](../sv/FEATURES.md) | 🇵🇭 [Filipino](../phi/FEATURES.md)
🌐 **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)
Визуално ръководство за всеки раздел на таблото за управление OmniRoute.
> 🇺🇸 [English](../../../docs/FEATURES.md)
---
## 🔌 Доставчици
Visual guide to every section of the OmniRoute dashboard.
Управлявайте връзките на доставчици на AI: OAuth доставчици (Claude Code, Codex, Gemini CLI), доставчици на API ключове (Groq, DeepSeek, OpenRouter) и безплатни доставчици (iFlow, Qwen, Kiro).
---
## 🔌 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.
![Providers Dashboard](screenshots/01-providers.png)
---
## 🎨 Комбота
## 🎨 Combos
Създавайте комбинации за маршрутизиране на модели с 6 стратегии: първо попълване, кръгъл робин, мощност от два избора, произволна, най-малко използвана и оптимизирана по отношение на разходите. Всяка комбинация свързва няколко модела с автоматичен резервен вариант.
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.
![Combos Dashboard](screenshots/02-combos.png)
---
## 📊 Анализ
## 📊 Analytics
Изчерпателни анализи на използването с потребление на токени, оценки на разходите, топлинни карти на активността, седмични диаграми на разпределение и разбивки по доставчик.
Comprehensive usage analytics with token consumption, cost estimates, activity heatmaps, weekly distribution charts, and per-provider breakdowns.
![Analytics Dashboard](screenshots/03-analytics.png)
---
## 🏥 Здраве на системата
## 🏥 System Health
Мониторинг в реално време: време на работа, памет, версия, процентили на латентност (p50/p95/p99), статистика на кеша и състояния на прекъсвача на доставчика.
Real-time monitoring: uptime, memory, version, latency percentiles (p50/p95/p99), cache statistics, and provider circuit breaker states.
![Health Dashboard](screenshots/04-health.png)
---
## 🔧 Площадка за преводачи
## 🔧 Translator Playground
Четири режима за отстраняване на грешки в API преводи: **Playground** (конвертор на формати), **Chat Tester** (заявки на живо), **Test Bench** (пакетни тестове) и **Live Monitor** (поток в реално време).
Four modes for debugging API translations: **Playground** (format converter), **Chat Tester** (live requests), **Test Bench** (batch tests), and **Live Monitor** (real-time stream).
![Translator Playground](screenshots/05-translator.png)
---
## ⚙️ Настройки
## 🎮 Model Playground _(v2.0.9+)_
Общи настройки, системно съхранение, управление на архивиране (база данни за експортиране/импортиране), външен вид (тъмен/светъл режим), сигурност (включва защита на крайна точка на API и блокиране на потребителски доставчик), маршрутизиране, устойчивост и разширена конфигурация.
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
- **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
![Settings Dashboard](screenshots/06-settings.png)
---
## 🔧 CLI инструменти
## 🔧 CLI Tools
Конфигурация с едно щракване за инструменти за кодиране на AI: Claude Code, Codex CLI, Gemini CLI, OpenClaw, Kilo Code и Antigravity.
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 Tools Dashboard](screenshots/07-cli-tools.png)
---
## 📝 Регистри за заявки
## 🤖 CLI Agents _(v2.0.11+)_
Регистриране на заявки в реално време с филтриране по доставчик, модел, акаунт и API ключ. Показва кодове за състояние, използване на токени, латентност и подробности за отговора.
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.
![Usage Logs](screenshots/08-usage.png)
---
## 🌐 Крайна точка на API
## 🌐 API Endpoint
Вашата унифицирана крайна точка на API с разбивка на възможностите: завършвания на чат, вграждания, генериране на изображения, прекласиране, аудио транскрипция и регистрирани ключове за API.
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.
![Endpoint Dashboard](screenshots/09-endpoint.png)
---
## 🔑 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.
+87
View File
@@ -0,0 +1,87 @@
🌐 **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 |
+48 -67
View File
@@ -8,51 +8,6 @@ _Вашият универсален API прокси — една крайна
---
<div align="center">
[![npm версия](https://img.shields.io/npm/v/omniroute?color=cb3837&logo=npm)](https://www.npmjs.com/package/omniroute)
[![Docker Hub](https://img.shields.io/docker/v/diegosouzapw/omniroute?label=Docker%20Hub&logo=docker&color=2496ED)](https://hub.docker.com/r/diegosouzapw/omniroute)
[![Лиценз](https://img.shields.io/github/license/diegosouzapw/OmniRoute)](https://github.com/diegosouzapw/OmniRoute/blob/main/LICENSE)
[![Уебсайт](https://img.shields.io/badge/Website-omniroute.online-blue?logo=google-chrome&logoColor=white)](https://omniroute.online)
[![WhatsApp](https://img.shields.io/badge/WhatsApp-Community-25D366?logo=whatsapp&logoColor=white)](https://chat.whatsapp.com/JI7cDQ1GyaiDHhVBpLxf8b?mode=gi_t)
[🌐 Уебсайт](https://omniroute.online) • [🚀 Бърз старт](#-quick-start) • [💡 Функции](#-key-features) • [📖 Документи](#-documentation) • [💰 Ценообразуване](#-pricing-at-a-glance) • [💬 WhatsApp](https://chat.whatsapp.com/JI7cDQ1GyaiDHhVBpLxf8b?mode=gi_t)
</div>
🌐 **Налично на:** 🇺🇸 [английски](README.md) | 🇧🇷 [Португалски (Бразилия)](README.pt-BR.md) | 🇪🇸 [Испански] (README.es.md) | 🇫🇷 [Français](README.fr.md) | 🇮🇹 [италиански] (README.it.md) | 🇷🇺 [Русский](README.ru.md) | 🇨🇳 [中文 (简体)](README.zh-CN.md) | 🇩🇪 [Deutsch](README.de.md) | 🇮🇳 [हिन्दी] (README.in.md) | 🇹🇭 [ไทย](README.th.md) | 🇺🇦 [Українська](README.uk-UA.md) | 🇸🇦 [العربية](README.ar.md) | 🇯🇵 [日本語](README.ja.md) | 🇻🇳 [Tiếng Việt](README.vi.md) | 🇧🇬 [Български](README.bg.md) | 🇩🇰 [Dansk](README.da.md) | 🇫🇮 [Suomi](README.fi.md) | 🇮🇱 [עברית](README.he.md) | 🇭🇺 [маджарски] (README.hu.md) | 🇮🇩 [бахаса Индонезия](README.id.md) | 🇰🇷 [한국어](README.ko.md) | 🇲🇾 [Bahasa Melayu](README.ms.md) | 🇳🇱 [Нидерландия](README.nl.md) | 🇳🇴 [Norsk](README.no.md) | 🇵🇹 [Português (Португалия)](README.pt.md) | 🇷🇴 [Română](README.ro.md) | 🇵🇱 [Полски](README.pl.md) | 🇸🇰 [Slovenčina](README.sk.md) | 🇸🇪 [Svenska](README.sv.md) | 🇵🇭 [филипински] (README.phi.md)
---
## 🖼️ Главно табло за управление
<div align="center">
<img src="./docs/screenshots/MainOmniRoute.png" alt="OmniRoute Dashboard" width="800"/>
</div>
---
## 📸 Визуализация на таблото за управление
<details>
<summary><b>Щракнете, за да видите екранни снимки на таблото </b></summary>
| Страница | Екранна снимка |
| -------------------------- | ----------------------------------------------------- |
| **Доставчици** | ![Доставчици](docs/screenshots/01-providers.png) |
| **Комбота** | ![Комбота](docs/screenshots/02-combos.png) |
| **Анализ** | ![Анализ](docs/screenshots/03-analytics.png) |
| **Здраве** | ![Здраве](docs/screenshots/04-health.png) |
| **Преводач** | ![Преводач](docs/screenshots/05-translator.png) |
| **Настройки** | ![Настройки](docs/screenshots/06-settings.png) |
| **CLI инструменти** | ![CLI инструменти](docs/screenshots/07-cli-tools.png) |
| **Регистри за използване** | ![Използване](docs/screenshots/08-usage.png) |
| **Крайна точка** | ![Крайна точка](docs/screenshots/09-endpoint.png) |
</details>
---
### 🤖 Безплатен доставчик на AI за вашите любими кодиращи агенти
_Свържете всеки базиран на AI IDE или CLI инструмент чрез OmniRoute — безплатен API шлюз за неограничено кодиране._
@@ -137,6 +92,34 @@ _Свържете всеки базиран на AI IDE или CLI инстру
---
### 🆕 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 `<omniModel>` 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 |
### 🆕 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 `<omniModel>` 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 |
---
## 🤔 Защо OmniRoute?
**Спрете да пилеете пари и да достигате лимити:**
@@ -253,6 +236,7 @@ OpenAI използва един формат, Claude (Anthropic) използв
**Как OmniRoute го решава:**
- **Вградени доставчици на безплатни нива** — Вградена поддръжка за 100% безплатни доставчици: iFlow (8 неограничени модела), Qwen (3 неограничени модела), Kiro (Claude безплатно), Gemini CLI (180K/месец безплатно)
- **Ollama Cloud** — Cloud-hosted Ollama models at `api.ollama.com` with free "Light usage" tier; use `ollamacloud/<model>` prefix
- **Безплатни само комбинации** — Верига `gc/gemini-3-flash → if/kimi-k2-thinking → qw/qwen3-coder-plus` = $0/месец с нулев престой
- **NVIDIA NIM безплатни кредити** — интегрирани 1000 безплатни кредита
- **Стратегия за оптимизиране на разходите** — Стратегия за маршрутизиране, която автоматично избира най-евтиния наличен доставчик
@@ -393,7 +377,7 @@ AI не е просто завършване на чат. Разработчиц
- **Текст към видео**`/v1/videos/generations` — ComfyUI (AnimateDiff, SVD) и SD WebUI
- **Текст към музика**`/v1/music/generations` — ComfyUI (Stable Audio Open, MusicGen)
- **Аудио транскрипция**`/v1/audio/transcriptions` — Whisper + Nvidia NIM, HuggingFace, Qwen3
- **Текст-към-говор**`/v1/audio/speech` — ElevenLabs, Nvidia NIM, HuggingFace, Coqui, Tortoise, Qwen3, + съществуващи доставчици
- **Текст-към-говор**`/v1/audio/speech` — ElevenLabs, Nvidia NIM, HuggingFace, Coqui, Tortoise, Qwen3, Inworld, Cartesia, PlayHT, + съществуващи доставчици
- **Модерации**`/v1/moderations` — Проверки за безопасност на съдържанието
- **Прекласиране**`/v1/rerank` — Прекласиране на уместността на документа
- **API за отговори** — Пълна `/v1/responses` поддръжка за Codex
@@ -910,8 +894,8 @@ OmniRoute v2.0 е създаден като операционна платфо
| Характеристика | Какво прави || -------------------------- | ------------------------------------------------------------ |
| 🖼️ **Генериране на изображения** | `/v1/images/generations` с облак и локален бекенд |
| 📐 **Вграждания** | `/v1/embeddings` за търсене и RAG тръбопроводи |
| 🎤 **Аудио транскрипция** | `/v1/audio/transcriptions` (Whisper и допълнителни доставчици) |
| 🔊 **Текст към говор** | `/v1/audio/speech` (множество машини/доставчици) |
| 🎤 **Аудио транскрипция** | `/v1/audio/transcriptions` — 7 providers (Deepgram Nova 3, AssemblyAI, Groq Whisper, HuggingFace, ElevenLabs, OpenAI, Azure), auto-language detection, MP4/MP3/WAV support |
| 🔊 **Текст към говор** | `/v1/audio/speech` — 10 providers (ElevenLabs, OpenAI, Deepgram, Cartesia, PlayHT, HuggingFace, Nvidia NIM, Inworld, Coqui, Tortoise) |
| 🎬 **Видео генериране** | `/v1/videos/generations` (работни процеси ComfyUI + SD WebUI) |
| 🎵 **Музикално поколение** | `/v1/music/generations` (работни процеси на ComfyUI) |
| 🛡️ **Модерации** | `/v1/moderations` проверки за безопасност |
@@ -919,17 +903,18 @@ OmniRoute v2.0 е създаден като операционна платфо
### 🛡️ Устойчивост, сигурност и управление
| Характеристика | Какво прави |
| -------------------------------------------- | ---------------------------------------------------------------------- |
| 🔌 **Прекъсвачи** | Пътуване/възстановяване на ниво доставчик с прагови контроли |
| 🛡️ **Anti-Thundering Herd** | Защита на Mutex + семафор при събития за повторен опит/скорост |
| 🧠 **Семантичен + кеш на подписа** | Намаляване на разходите/закъснението с два кеш слоя |
| ⚡ **Искане на идемпотентност** | Дублиран защитен прозорец |
| 🔒 **TLS Fingerprint Spoofing** | По-добра съвместимост с доставчици, филтрирани срещу бот |
| 🌐 **IP филтриране** | Списък с разрешени/списъци с блокирани контроли за открити внедрявания |
| 📊 **Редактируеми ограничения на скоростта** | Конфигурируеми глобални/на ниво доставчик ограничения с постоянство |
| 🔑 **API Key Management + Scoping** | Сигурно издаване/ротация на ключове и контроли на модел/доставчик |
| 🛡️ **Защитен `/models`** | Опционално удостоверяване и скриване на доставчик за каталог на модели |
| Характеристика | Какво прави |
| -------------------------------------------- | -------------------------------------------------------------------------------------- |
| 🔌 **Прекъсвачи** | Пътуване/възстановяване на ниво доставчик с прагови контроли |
| 🛡️ **Anti-Thundering Herd** | Защита на Mutex + семафор при събития за повторен опит/скорост |
| 🧠 **Семантичен + кеш на подписа** | Намаляване на разходите/закъснението с два кеш слоя |
| ⚡ **Искане на идемпотентност** | Дублиран защитен прозорец |
| 🔒 **TLS Fingerprint Spoofing** | По-добра съвместимост с доставчици, филтрирани срещу бот |
| 🔏 **CLI Fingerprint Matching** | Matches native CLI request signatures — **reduces ban risk while preserving proxy IP** |
| 🌐 **IP филтриране** | Списък с разрешени/списъци с блокирани контроли за открити внедрявания |
| 📊 **Редактируеми ограничения на скоростта** | Конфигурируеми глобални/на ниво доставчик ограничения с постоянство |
| 🔑 **API Key Management + Scoping** | Сигурно издаване/ротация на ключове и контроли на модел/доставчик |
| 🛡️ **Защитен `/models`** | Опционално удостоверяване и скриване на доставчик за каталог на модели |
### 📊 Наблюдаемост и анализ
@@ -952,6 +937,8 @@ OmniRoute v2.0 е създаден като операционна платфо
| 🧙 **Съветник за присъединяване** | Насочвана настройка при първо стартиране |
| 🔧 **CLI Tools Dashboard** | Настройка с едно щракване за популярни инструменти за кодиране |
| 🌐 **i18n (30 езика)** | Пълно табло за управление + езикова поддръжка на документи с RTL покритие |
| 🧹 **Clear All Models** | One-click model list clearing in provider details |
| 📋 **Issue Templates** | Standardized GitHub templates for bugs and features |
| 📂 **Директория с персонализирани данни** | `DATA_DIR` отмяна за място за съхранение |
### Функция Deep Dive
@@ -1645,15 +1632,9 @@ gh release create v2.0.0 --title "v2.0.0" --generate-notes
## 📊 Звездна история
<a href="https://star-history.com/#diegosouzapw/OmniRoute&Date">
<picture>
<source media="(prefers-color-scheme: dark)" srcset="https://api.star-history.com/svg?repos=diegosouzapw/OmniRoute&type=Date&theme=dark" />
<source media="(prefers-color-scheme: light)" srcset="https://api.star-history.com/svg?repos=diegosouzapw/OmniRoute&type=Date" />
<img alt="Star History Chart" src="https://api.star-history.com/svg?repos=diegosouzapw/OmniRoute&type=Date" />
</picture>
</a>
## Stargazers over time
---
## [![Stargazers over time](https://starchart.cc/diegosouzapw/OmniRoute.svg?variant=adaptive)](https://starchart.cc/diegosouzapw/OmniRoute)
## 🙏 Благодарности
+37
View File
@@ -0,0 +1,37 @@
🌐 **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).
+168 -129
View File
@@ -1,87 +1,91 @@
# Отстраняване на неизправности
🌐 **Languages:** 🇺🇸 [English](../../TROUBLESHOOTING.md) | 🇧🇷 [Português (Brasil)](../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) | 🇩🇰 [Dansk](../da/TROUBLESHOOTING.md) | 🇫🇮 [Suomi](../fi/TROUBLESHOOTING.md) | 🇮🇱 [עברית](../he/TROUBLESHOOTING.md) | 🇭🇺 [Magyar](../hu/TROUBLESHOOTING.md) | 🇮🇩 [Bahasa Indonesia](../id/TROUBLESHOOTING.md) | 🇰🇷 [한국어](../ko/TROUBLESHOOTING.md) | 🇲🇾 [Bahasa Melayu](../ms/TROUBLESHOOTING.md) | 🇳🇱 [Nederlands](../nl/TROUBLESHOOTING.md) | 🇳🇴 [Norsk](../no/TROUBLESHOOTING.md) | 🇵🇹 [Português (Portugal)](../pt/TROUBLESHOOTING.md) | 🇷🇴 [Română](../ro/TROUBLESHOOTING.md) | 🇵🇱 [Polski](../pl/TROUBLESHOOTING.md) | 🇸🇰 [Slovenčina](../sk/TROUBLESHOOTING.md) | 🇸🇪 [Svenska](../sv/TROUBLESHOOTING.md) | 🇵🇭 [Filipino](../phi/TROUBLESHOOTING.md)
Често срещани проблеми и решения за OmniRoute.
🌐 **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
| Проблем | Решение |
| ------------------------------------------------- | ------------------------------------------------------------------------------ |
| Първото влизане не работи | Проверете `INITIAL_PASSWORD` в `.env` (по подразбиране: `123456`) |
| Таблото се отваря на грешен порт | Задайте `PORT=20128` и `NEXT_PUBLIC_BASE_URL=http://localhost:20128` |
| Няма регистрационни файлове за заявки под `logs/` | Задайте `ENABLE_REQUEST_LOGS=true` |
| EACCES: разрешението е отказано | Задайте `DATA_DIR=/path/to/writable/dir` да замени `~/.omniroute` |
| Стратегията за маршрутизиране не се запазва | Актуализация до v1.4.11+ (корекция на Zod схема за постоянство на настройките) |
🌐 **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
### „Езиковият модел не предостави съобщения“
**Причина:** Квотата на доставчика е изчерпана.
**Коригиране:**
1. Проверете инструмента за проследяване на квоти на таблото за управление
2. Използвайте комбо с резервни нива
3. Преминете към по-евтино/безплатно ниво
### Ограничаване на скоростта
**Причина:** Абонаментната квота е изчерпана.
**Коригиране:**
- Добавете резервен вариант: `cc/claude-opus-4-6 → glm/glm-4.7 → if/kimi-k2-thinking`
- Използвайте GLM/MiniMax като евтино резервно копие
### OAuth Token е изтекъл
OmniRoute автоматично опреснява токените. Ако проблемите продължават:
1. Табло → Доставчик → Свързване отново
2. Изтрийте и добавете отново връзката с доставчика
| 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"
1. Проверете дали `BASE_URL` сочи към вашия работещ екземпляр (напр. `http://localhost:20128`)
2. Проверете `CLOUD_URL` точки към вашата крайна точка в облака (напр. `https://omniroute.dev`)
3. Поддържайте стойностите на `NEXT_PUBLIC_*` в съответствие със стойностите от страна на сървъра
**Cause:** Provider quota exhausted.
### Cloud `stream=false` Връща 500
**Fix:**
**Симптом:** `Unexpected token 'd'...` в крайна точка на облака за обаждания без поточно предаване.
1. Check dashboard quota tracker
2. Use a combo with fallback tiers
3. Switch to cheaper/free tier
**Причина:** Upstream връща SSE полезен товар, докато клиентът очаква JSON.
### Rate Limiting
**Заобиколно решение:** Използвайте `stream=true` за директни обаждания в облака. Локалното време на изпълнение включва резервен SSE→JSON.
**Cause:** Subscription quota exhausted.
### Облакът казва Свързан, но „Невалиден API ключ“
**Fix:**
1. Създайте нов ключ от локалното табло за управление (`/api/keys`)
2. Стартирайте облачна синхронизация: Активирайте Облак → Синхронизирай сега
3. Старите/несинхронизирани ключове все още могат да връщат `401` в облака
- 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
---
## Проблеми с Docker
## Cloud Issues
### CLI инструментът показва, че не е инсталиран
### Cloud Sync Errors
1. Проверете полетата по време на изпълнение: `curl http://localhost:20128/api/cli-tools/runtime/codex | jq`
2. За преносим режим: използвайте целево изображение `runner-cli` (пакетни CLI)
3. За режим на монтиране на хост: задайте `CLI_EXTRA_PATHS` и монтирайте директорията bin на хоста като само за четене
4. Ако `installed=true` и `runnable=false`: двоичен файл е намерен, но проверката на състоянието е неуспешна
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}'
@@ -91,24 +95,24 @@ curl -s http://localhost:20128/api/cli-tools/openclaw-settings | jq '{installed,
---
## Проблеми с разходите
## Cost Issues
### Високи разходи
### High Costs
1. Проверете статистическите данни за употреба в Табло → Използване
2. Превключете основния модел на GLM/MiniMax
3. Използвайте безплатно ниво (Gemini CLI, iFlow) за некритични задачи
4. Задайте бюджети за разходи за API ключ: Табло за управление → API ключове → Бюджет
1. Check usage stats in Dashboard → Usage
2. Switch primary model to GLM/MiniMax
3. Use free tier (Gemini CLI, iFlow) for non-critical tasks
4. Set cost budgets per API key: Dashboard → API Keys → Budget
---
## Отстраняване на грешки
## Debugging
### Активиране на регистрационните файлове на заявките
### Enable Request Logs
Задайте `ENABLE_REQUEST_LOGS=true` във вашия `.env` файл. Дневниците се появяват в директорията `logs/`.
Set `ENABLE_REQUEST_LOGS=true` in your `.env` file. Logs appear under `logs/` directory.
### Проверете здравето на доставчика
### Check Provider Health
```bash
# Health dashboard
@@ -118,102 +122,137 @@ http://localhost:20128/dashboard/health
curl http://localhost:20128/api/monitoring/health
```
### Съхранение по време на изпълнение
### Runtime Storage
- Основно състояние: `${DATA_DIR}/db.json` (доставчици, комбинации, псевдоними, ключове, настройки)
- Използване: `${DATA_DIR}/usage.json`, `${DATA_DIR}/log.txt`, `${DATA_DIR}/call_logs/`
- Регистрации за заявки: `<repo>/logs/...` (когато `ENABLE_REQUEST_LOGS=true`)
- 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: `<repo>/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. Отидете на **Табло → Настройки → Устойчивост**
2. Проверете картата на прекъсвача на засегнатия доставчик
3. Щракнете върху **Нулиране на всички**, за да изчистите всички прекъсвачи, или изчакайте времето за охлаждане да изтече
4. Уверете се, че доставчикът действително е наличен, преди да нулирате
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. Проверете **Табло → Здраве → Здраве на доставчика** за модела на повреда
2. Отидете на **Настройки → Устойчивост → Профили на доставчици** и увеличете прага на отказ
3. Проверете дали доставчикът е променил ограниченията на API или изисква повторно удостоверяване
4. Прегледайте телеметрията за латентност — високата латентност може да причини грешки, базирани на изчакване
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
- Уверете се, че използвате правилния префикс: `deepgram/nova-3` или `assemblyai/best`
- Проверете дали доставчикът е свързан в **Табло → Доставчици**
- 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
- Проверете поддържаните аудио формати: `mp3`, `wav`, `m4a`, `flac`, `ogg`, `webm`
- Уверете се, че размерът на файла е в границите на доставчика (обикновено < 25MB)
- Проверете валидността на API ключа на доставчика в картата на доставчика
- 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
- **Мислещите етикети не се появяват** — Проверете дали целевият доставчик поддържа мисленето и настройката на бюджета за мислене
- **Отпадане на извикванията на инструменти** — Някои преводи на формати може да премахнат неподдържаните полета; потвърдете в режим Playground
- **Липсва системна подкана** — Клод и Джемини обработват системните подкани по различен начин; проверка на резултата за превод
- **SDK връща необработен низ вместо обект** — Коригирано във v1.1.0: дезинфекциращото средство за отговор вече премахва нестандартните полета (`x_groq`, `usage_breakdown` и т.н.), които причиняват неуспешно валидиране на OpenAI SDK Pydantic
- **GLM/ERNIE отхвърля `system` роля**Коригирано във v1.1.0: нормализаторът на роли автоматично обединява системни съобщения в потребителски съобщения за несъвместими модели
- **`developer` ролята не е разпозната** — Коригирано във v1.1.0: автоматично преобразувано в `system` за доставчици, които не са OpenAI
- **`json_schema` не работи с Gemini** — Коригирано във v1.1.0: `response_format` сега се преобразува в `responseMimeType` + `responseSchema` на Gemini
- **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
- Автоматичното ограничение на скоростта се прилага само за доставчици на API ключове (не OAuth/абонамент)
- Уверете се, че **Настройки → Устойчивост → Профили на доставчици** има активиран автоматичен лимит на скоростта
- Проверете дали доставчикът връща `429` кодове за състояние или `Retry-After` заглавки
- 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:
- **Базово забавяне** — Първоначално време на изчакване след първата повреда (по подразбиране: 1s)
- **Максимално забавяне** — Максимално ограничение на времето за изчакване (по подразбиране: 30 секунди)
- **Множител** — Колко да се увеличи закъснението за последователен отказ (по подразбиране: 2x)
- **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
Когато много едновременни заявки попаднат на доставчик с ограничена скорост, OmniRoute използва mutex + автоматично ограничаване на скоростта, за да сериализира заявките и да предотврати каскадни грешки. Това е автоматично за доставчиците на API ключове.
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)
- **Проблеми с GitHub**: [github.com/diegosouzapw/OmniRoute/issues](https://github.com/diegosouzapw/OmniRoute/issues)
- **Архитектура**: Вижте [link](ARCHITECTURE.md) за вътрешни подробности
- **API Reference**: Вижте [link](API_REFERENCE.md) за всички крайни точки
- **Табло за управление на здравето**: Проверете **Табло за управление → Здраве** за състоянието на системата в реално време
- **Преводач**: Използвайте **Табло за управление → Преводач** за отстраняване на грешки при проблеми с формата
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
+340 -225
View File
@@ -1,12 +1,16 @@
# Ръководство за потребителя
🌐 **Languages:** 🇺🇸 [English](../../USER_GUIDE.md) | 🇧🇷 [Português (Brasil)](../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) | 🇩🇰 [Dansk](../da/USER_GUIDE.md) | 🇫🇮 [Suomi](../fi/USER_GUIDE.md) | 🇮🇱 [עברית](../he/USER_GUIDE.md) | 🇭🇺 [Magyar](../hu/USER_GUIDE.md) | 🇮🇩 [Bahasa Indonesia](../id/USER_GUIDE.md) | 🇰🇷 [한국어](../ko/USER_GUIDE.md) | 🇲🇾 [Bahasa Melayu](../ms/USER_GUIDE.md) | 🇳🇱 [Nederlands](../nl/USER_GUIDE.md) | 🇳🇴 [Norsk](../no/USER_GUIDE.md) | 🇵🇹 [Português (Portugal)](../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) | 🇵🇭 [Filipino](../phi/USER_GUIDE.md)
Пълно ръководство за конфигуриране на доставчици, създаване на комбинации, интегриране на CLI инструменти и внедряване на OmniRoute.
🌐 **Languages:** 🇺🇸 [English](../../README.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)
---
## Съдържание
# User Guide
🌐 **Languages:** 🇺🇸 [English](USER_GUIDE.md) | 🇧🇷 [Português (Brasil)](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) | 🇩🇰 [Dansk](i18n/da/USER_GUIDE.md) | 🇫🇮 [Suomi](i18n/fi/USER_GUIDE.md) | 🇮🇱 [עברית](i18n/he/USER_GUIDE.md) | 🇭🇺 [Magyar](i18n/hu/USER_GUIDE.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/USER_GUIDE.md) | 🇰🇷 [한국어](i18n/ko/USER_GUIDE.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/USER_GUIDE.md) | 🇳🇱 [Nederlands](i18n/nl/USER_GUIDE.md) | 🇳🇴 [Norsk](i18n/no/USER_GUIDE.md) | 🇵🇹 [Português (Portugal)](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) | 🇵🇭 [Filipino](i18n/phi/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)
@@ -18,40 +22,40 @@
---
## 💰 Ценообразуването с един поглед
## 💰 Pricing at a Glance
| Ниво | Доставчик | Цена | Нулиране на квота | Най-добро за |
| ------------------ | ----------------- | --------------------- | ----------------------- | ------------------------- |
| **💳 АБОНАМЕНТ** | Claude Code (Pro) | $20/месец | 5 часа + седмично | Вече сте абонирани |
| | Codex (Plus/Pro) | $20-200/месец | 5 часа + седмично | Потребители на OpenAI |
| | Gemini CLI | **БЕЗПЛАТНО** | 180K/месец + 1K/ден | всички! |
| | Копилот на GitHub | $10-19/месец | Месечно | Потребители на GitHub |
| **🔑 КЛЮЧ ЗА API** | DeepSeek | Плащане за използване | Няма | Евтини разсъждения |
| | Groq | Плащане за използване | Няма | Свръхбърз извод |
| | xAI (Grok) | Плащане за използване | Няма | Грок 4 разсъждения |
| | Мистрал | Плащане за използване | Няма | Хоствани в ЕС модели |
| | Недоумение | Плащане за използване | Няма | Разширено търсене |
| | Заедно AI | Плащане за използване | Няма | Модели с отворен код |
| | Фойерверки AI | Плащане за използване | Няма | Бързи FLUX изображения |
| | Мозъци | Плащане за използване | Няма | Скорост на вафла |
| | Cohere | Плащане за използване | Няма | Команда R+ RAG |
| | NVIDIA NIM | Плащане за използване | Няма | Корпоративни модели |
| **💰 ЕВТИНО** | GLM-4.7 | $0,6/1 милион | Ежедневно 10 сутринта | Резервно копие на бюджета |
| | MiniMax M2.1 | $0,2/1 милион | 5-часово търкаляне | Най-евтиният вариант |
| | Кими К2 | $9/месец апартамент | 10 милиона токена/месец | Предвидими разходи |
| **🆓 БЕЗПЛАТНО** | iFlow | $0 | Неограничен | 8 модела безплатно |
| | Куен | $0 | Неограничен | 3 модела безплатно |
| | Киро | $0 | Неограничен | Клод безплатно |
| 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** | iFlow | $0 | Unlimited | 8 models free |
| | Qwen | $0 | Unlimited | 3 models free |
| | Kiro | $0 | Unlimited | Claude free |
**💡 Професионален съвет:** Започнете с Gemini CLI (180K безплатно/месец) + iFlow (неограничено безплатно) комбинация = $0 цена!
**💡 Pro Tip:** Start with Gemini CLI (180K free/month) + iFlow (unlimited free) combo = $0 cost!
---
## 🎯 Случаи на употреба
## 🎯 Use Cases
### Случай 1: „Имам абонамент за Claude Pro“
### Case 1: "I have Claude Pro subscription"
**Проблем:** Квотата изтича неизползвана, ограничения на скоростта по време на тежко кодиране
**Problem:** Quota expires unused, rate limits during heavy coding
```
Combo: "maximize-claude"
@@ -63,9 +67,9 @@ Monthly cost: $20 (subscription) + ~$5 (backup) = $25 total
vs. $20 + hitting limits = frustration
```
### Случай 2: „Искам нулеви разходи“
### Case 2: "I want zero cost"
**Проблем:** Не мога да си позволя абонаменти, имам нужда от надеждно AI кодиране
**Problem:** Can't afford subscriptions, need reliable AI coding
```
Combo: "free-forever"
@@ -77,9 +81,9 @@ Monthly cost: $0
Quality: Production-ready models
```
### Случай 3: „Имам нужда от кодиране 24/7, без прекъсвания“
### Case 3: "I need 24/7 coding, no interruptions"
**Проблем:** Крайни срокове, не мога да си позволя престой
**Problem:** Deadlines, can't afford downtime
```
Combo: "always-on"
@@ -93,9 +97,9 @@ Result: 5 layers of fallback = zero downtime
Monthly cost: $20-200 (subscriptions) + $10-20 (backup)
```
### Случай 4: „Искам БЕЗПЛАТЕН AI в OpenClaw
### Case 4: "I want FREE AI in OpenClaw"
**Проблем:** Имате нужда от AI асистент в приложенията за съобщения, напълно безплатно
**Problem:** Need AI assistant in messaging apps, completely free
```
Combo: "openclaw-free"
@@ -109,9 +113,9 @@ Access via: WhatsApp, Telegram, Slack, Discord, iMessage, Signal...
---
## 📖 Настройка на доставчик
## 📖 Provider Setup
### 🔐 Доставчици на абонаменти
### 🔐 Subscription Providers
#### Claude Code (Pro/Max)
@@ -126,7 +130,7 @@ Models:
cc/claude-haiku-4-5-20251001
```
**Професионален съвет:** Използвайте Opus за сложни задачи, Sonnet за скорост. OmniRoute проследява квота за модел!
**Pro Tip:** Use Opus for complex tasks, Sonnet for speed. OmniRoute tracks quota per model!
#### OpenAI Codex (Plus/Pro)
@@ -140,7 +144,7 @@ Models:
cx/gpt-5.1-codex-max
```
#### Gemini CLI (БЕЗПЛАТНО 180K/месец!)
#### Gemini CLI (FREE 180K/month!)
```bash
Dashboard → Providers → Connect Gemini CLI
@@ -152,9 +156,9 @@ Models:
gc/gemini-2.5-pro
```
**Най-добра стойност:** Огромно безплатно ниво! Използвайте това преди платените нива.
**Best Value:** Huge free tier! Use this before paid tiers.
#### Копилот на GitHub
#### GitHub Copilot
```bash
Dashboard → Providers → Connect GitHub
@@ -167,33 +171,33 @@ Models:
gh/gemini-3-pro
```
### 💰 Евтини доставчици
### 💰 Cheap Providers
#### GLM-4.7 (Ежедневно нулиране, $0,6/1 млн.)
#### GLM-4.7 (Daily reset, $0.6/1M)
1. Регистрирайте се: [Zhipu AI](https://open.bigmodel.cn/)
2. Вземете API ключ от Coding Plan
3. Табло → Добавяне на API ключ: Доставчик: `glm`, API ключ: `your-key`
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`
**Използване:** `glm/glm-4.7`**Професионален съвет:** Планът за кодиране предлага 3× квота на цена 1/7! Нулирайте всеки ден в 10:00 ч.
**Use:** `glm/glm-4.7`**Pro Tip:** Coding Plan offers 3× quota at 1/7 cost! Reset daily 10:00 AM.
#### MiniMax M2.1 (5 часа нулиране, $0,20/1 млн.)
#### MiniMax M2.1 (5h reset, $0.20/1M)
1. Регистрирайте се: [MiniMax](https://www.minimax.io/)
2. Вземете API ключ → Табло → Добавете API ключ
1. Sign up: [MiniMax](https://www.minimax.io/)
2. Get API key → Dashboard → Add API Key
**Използване:** `minimax/MiniMax-M2.1`**Професионален съвет:** Най-евтината опция за дълъг контекст (1M токени)!
**Use:** `minimax/MiniMax-M2.1`**Pro Tip:** Cheapest option for long context (1M tokens)!
#### Kimi K2 ($9/месец фиксиран)
#### Kimi K2 ($9/month flat)
1. Абонирайте се: [Moonshot AI](https://platform.moonshot.ai/)
2. Вземете API ключ → Табло → Добавете API ключ
1. Subscribe: [Moonshot AI](https://platform.moonshot.ai/)
2. Get API key → Dashboard → Add API Key
**Използване:** `kimi/kimi-latest`**Професионален съвет:** Фиксирани $9/месец за 10 милиона токена = $0,90/1 милион ефективна цена!
**Use:** `kimi/kimi-latest`**Pro Tip:** Fixed $9/month for 10M tokens = $0.90/1M effective cost!
### 🆓 БЕЗПЛАТНИ доставчици
### 🆓 FREE Providers
#### iFlow (8 БЕЗПЛАТНИ модела)
#### iFlow (8 FREE models)
```bash
Dashboard → Connect iFlow → OAuth login → Unlimited usage
@@ -201,7 +205,7 @@ Dashboard → Connect iFlow → 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 БЕЗПЛАТНИ модела)
#### Qwen (3 FREE models)
```bash
Dashboard → Connect Qwen → Device code auth → Unlimited usage
@@ -209,7 +213,7 @@ 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
@@ -219,9 +223,9 @@ Models: kr/claude-sonnet-4.5, kr/claude-haiku-4.5
---
## 🎨 Комбота
## 🎨 Combos
### Пример 1: Увеличаване на абонамента → Евтино архивиране
### Example 1: Maximize Subscription → Cheap Backup
```
Dashboard → Combos → Create New
@@ -235,7 +239,7 @@ Models:
Use in CLI: premium-coding
```
### Пример 2: Само безплатно (нулева цена)
### Example 2: Free-Only (Zero Cost)
```
Name: free-combo
@@ -249,9 +253,9 @@ Cost: $0 forever!
---
## 🔧 CLI интеграция
## 🔧 CLI Integration
### Курсор IDE
### Cursor IDE
```
Settings → Models → Advanced:
@@ -260,9 +264,9 @@ Settings → Models → Advanced:
Model: cc/claude-opus-4-6
```
### Клод Код
### Claude Code
Редактиране на `~/.claude/config.json`:
Edit `~/.claude/config.json`:
```json
{
@@ -281,7 +285,7 @@ codex "your prompt"
### OpenClaw
Редактиране на `~/.openclaw/openclaw.json`:
Edit `~/.openclaw/openclaw.json`:
```json
{
@@ -303,9 +307,9 @@ codex "your prompt"
}
```
**Или използвайте таблото за управление:** CLI инструменти → OpenClaw → Автоматично конфигуриране
**Or use Dashboard:** CLI Tools → OpenClaw → Auto-config
### Cline / Продължи / RooCode
### Cline / Continue / RooCode
```
Provider: OpenAI Compatible
@@ -316,9 +320,28 @@ Model: cc/claude-opus-4-6
---
## 🚀 Внедряване
## 🚀 Deployment
### Внедряване на VPS
### 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
@@ -337,7 +360,44 @@ 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)
@@ -347,51 +407,54 @@ docker build -t omniroute:cli .
docker run -d --name omniroute -p 20128:20128 --env-file ./.env -v omniroute-data:/app/data omniroute:cli
```
За интегриран в хост режим с двоични файлове на CLI вижте раздела Docker в основните документи.
For host-integrated mode with CLI binaries, see the Docker section in the main docs.
### Променливи на средата
### Environment Variables
| Променлива | По подразбиране | Описание |
| --------------------- | -------------------------------------- | ---------------------------------------------------------------------------- |
| `JWT_SECRET` | `omniroute-default-secret-change-me` | Тайна за подписване на JWT (**промяна в производството**) |
| `INITIAL_PASSWORD` | `123456` | Първа парола за влизане |
| `DATA_DIR` | `~/.omniroute` | Директория с данни (db, използване, регистрационни файлове) |
| `PORT` | рамка по подразбиране | Сервизен порт (`20128` в примерите) |
| `HOSTNAME` | рамка по подразбиране | Свързване на хост (Docker по подразбиране е `0.0.0.0`) |
| `NODE_ENV` | по подразбиране по време на изпълнение | Задайте `production` за внедряване |
| `BASE_URL` | `http://localhost:20128` | Вътрешен основен URL адрес от страната на сървъра |
| `CLOUD_URL` | `https://omniroute.dev` | Основен URL адрес на крайна точка за синхронизиране в облак |
| `API_KEY_SECRET` | `endpoint-proxy-api-key-secret` | HMAC тайна за генерирани API ключове |
| `REQUIRE_API_KEY` | `false` | Прилагане на API ключ на носител на `/v1/*` |
| `ENABLE_REQUEST_LOGS` | `false` | Разрешава регистрационни файлове за заявки/отговори |
| `AUTH_COOKIE_SECURE` | `false` | Принудително `Secure` бисквитка за удостоверяване (зад HTTPS обратен прокси) |
| 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 |
За пълната справка за променливите на средата вижте [README](../README.md).
For the full environment variable reference, see the [README](../README.md).
---
## 📊 Налични модели
## 📊 Available Models
<details>
<summary><b>Вижте всички налични модели</b></summary>
<summary><b>View all available models</b></summary>
**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/`)** — БЕЗПЛАТНО: `gc/gemini-3-flash-preview`, `gc/gemini-2.5-pro`
**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/1 млн.: `glm/glm-4.7`
**GLM (`glm/`)** — $0.6/1M: `glm/glm-4.7`
**MiniMax (`minimax/`)** — $0,2/1 млн.: `minimax/MiniMax-M2.1`
**MiniMax (`minimax/`)** — $0.2/1M: `minimax/MiniMax-M2.1`
**iFlow (`if/`)** — БЕЗПЛАТНО: `if/kimi-k2-thinking`, `if/qwen3-coder-plus`, `if/deepseek-r1`
**iFlow (`if/`)** — FREE: `if/kimi-k2-thinking`, `if/qwen3-coder-plus`, `if/deepseek-r1`
**Qwen (`qw/`)** — БЕЗПЛАТНО: `qw/qwen3-coder-plus`, `qw/qwen3-coder-flash`
**Qwen (`qw/`)** — FREE: `qw/qwen3-coder-plus`, `qw/qwen3-coder-flash`
**Киро (`kr/`)** — БЕЗПЛАТНО: `kr/claude-sonnet-4.5`, `kr/claude-haiku-4.5`
**Kiro (`kr/`)** — FREE: `kr/claude-sonnet-4.5`, `kr/claude-haiku-4.5`
**DeepSeek (`ds/`)**: `ds/deepseek-chat`, `ds/deepseek-reasoner`
@@ -399,13 +462,13 @@ docker run -d --name omniroute -p 20128:20128 --env-file ./.env -v omniroute-dat
**xAI (`xai/`)**: `xai/grok-4`, `xai/grok-4-0709-fast-reasoning`, `xai/grok-code-mini`
**Мистрал (`mistral/`)**: `mistral/mistral-large-2501`, `mistral/codestral-2501`
**Mistral (`mistral/`)**: `mistral/mistral-large-2501`, `mistral/codestral-2501`
**Недоумение (`pplx/`)**: `pplx/sonar-pro`, `pplx/sonar`
**Perplexity (`pplx/`)**: `pplx/sonar-pro`, `pplx/sonar`
**Заедно AI (`together/`)**: `together/meta-llama/Llama-3.3-70B-Instruct-Turbo`
**Together AI (`together/`)**: `together/meta-llama/Llama-3.3-70B-Instruct-Turbo`
**Фойерверки AI (`fireworks/`)**: `fireworks/accounts/fireworks/models/deepseek-v3p1`
**Fireworks AI (`fireworks/`)**: `fireworks/accounts/fireworks/models/deepseek-v3p1`
**Cerebras (`cerebras/`)**: `cerebras/llama-3.3-70b`
@@ -417,11 +480,11 @@ docker run -d --name omniroute -p 20128:20128 --env-file ./.env -v omniroute-dat
---
## 🧩 Разширени функции
## 🧩 Advanced Features
### Персонализирани модели
### Custom Models
Добавете всеки ID на модел към всеки доставчик, без да чакате актуализация на приложението:
Add any model ID to any provider without waiting for an app update:
```bash
# Via API
@@ -433,11 +496,11 @@ curl -X POST http://localhost:20128/api/provider-models \
# Remove: curl -X DELETE "http://localhost:20128/api/provider-models?provider=openai&model=gpt-4.5-preview"
```
Или използвайте таблото за управление: **Доставчици → [Доставчик] → Персонализирани модели**.
Or use Dashboard: **Providers → [Provider] → Custom Models**.
### Специализирани маршрути на доставчик
### Dedicated Provider Routes
Насочвайте заявките директно към конкретен доставчик с валидиране на модела:
Route requests directly to a specific provider with model validation:
```bash
POST http://localhost:20128/v1/providers/openai/chat/completions
@@ -445,9 +508,9 @@ POST http://localhost:20128/v1/providers/openai/embeddings
POST http://localhost:20128/v1/providers/fireworks/images/generations
```
Префиксът на доставчика се добавя автоматично, ако липсва. Несъответстващите модели връщат `400`.
The provider prefix is auto-added if missing. Mismatched models return `400`.
### Конфигурация на мрежов прокси
### Network Proxy Configuration
```bash
# Set global proxy
@@ -463,76 +526,76 @@ 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.
### API за каталог на модели
### Model Catalog API
```bash
curl http://localhost:20128/api/models/catalog
```
Връща модели, групирани по доставчик с типове (`chat`, `embedding`, `image`).
Returns models grouped by provider with types (`chat`, `embedding`, `image`).
### Облачно синхронизиране
### Cloud Sync
- Синхронизиране на доставчици, комбинации и настройки на всички устройства
- Автоматична фонова синхронизация с изчакване + бързо отказване
- Предпочитане на сървъра `BASE_URL`/`CLOUD_URL` в производството
- Sync providers, combos, and settings across devices
- Automatic background sync with timeout + fail-fast
- Prefer server-side `BASE_URL`/`CLOUD_URL` in production
### LLM Gateway Intelligence (Фаза 9)
### LLM Gateway Intelligence (Phase 9)
- **Семантичен кеш** — Автоматично кешира нестрийминг, температура=0 отговори (заобикаляне с `X-OmniRoute-No-Cache: true`)
- **Request Idempotency**Дедупликира заявките в рамките на 5s чрез `Idempotency-Key` или `X-Request-Id` заглавка
- **Проследяване на напредъка** — Включване на SSE `event: progress` събития чрез `X-OmniRoute-Progress: true` заглавка
- **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
Достъп чрез **Табло → Преводач**. Отстранете грешки и визуализирайте как OmniRoute превежда API заявки между доставчици.
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:**
- Отстраняване на грешки защо конкретна комбинация клиент/доставчик е неуспешна
- Проверете дали мислещите тагове, извикванията на инструменти и системните подкани се превеждат правилно
- Сравнете разликите във форматите между форматите OpenAI, Claude, Gemini и Responses API
- 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**.
| Стратегия | Описание |
| ---------------------------- | -------------------------------------------------------------------------------------------------------------- |
| **Първо попълване** | Използва акаунти в приоритетен ред — основният акаунт обработва всички заявки, докато стане недостъпен |
| **Round Robin** | Преминава през всички акаунти с конфигурируем лепкав лимит (по подразбиране: 3 обаждания на акаунт) |
| **P2C (Сила на два избора)** | Избира 2 произволни акаунта и маршрути към по-здравословния — балансира натоварването с осъзнаване на здравето |
| **Произволно** | Произволно избира акаунт за всяка заявка чрез разбъркване на Fisher-Yates |
| **Най-малко използвани** | Насочва към акаунта с най-стария `lastUsedAt` времеви печат, разпределяйки трафика равномерно |
| **Оптимизирани разходи** | Маршрути към акаунта с най-ниска стойност на приоритет, оптимизиране за доставчици с най-ниска цена |
| 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 |
#### Псевдоними на модели със заместващи символи
#### 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
@@ -543,46 +606,46 @@ Chain: production-fallback
---
### Устойчивост и прекъсвачи
### Resilience & Circuit Breakers
Конфигурирайте чрез **Табло → Настройки → Устойчивост**.
Configure via **Dashboard → Settings → Resilience**.
OmniRoute прилага устойчивост на ниво доставчик с четири компонента:
OmniRoute implements provider-level resilience with four components:
1. **Профили на доставчици** — Конфигурация за всеки доставчик за:
- Праг на повреда (колко повреда преди отваряне)
- Продължителност на изчакване
- Чувствителност на откриване на ограничение на скоростта
- Параметри на експоненциално забавяне
1. **Provider Profiles** — Per-provider configuration for:
- Failure threshold (how many failures before opening)
- Cooldown duration
- Rate limit detection sensitivity
- Exponential backoff parameters
2. **Редактируеми ограничения на скоростта** — Настройки по подразбиране на системно ниво, които могат да се конфигурират в таблото за управление:
- **Заявки в минута (RPM)** — Максимален брой заявки в минута за акаунт
- **Минимално време между заявките** — Минимална разлика в милисекунди между заявките
- **Максимални едновременни заявки** — Максимални едновременни заявки за акаунт
- Щракнете върху **Редактиране**, за да промените, след това върху **Запазване** или **Отказ**. Стойностите се запазват чрез API за устойчивост.
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. **Прекъсвач на веригата** — Проследява повреди на доставчик и автоматично отваря веригата при достигане на праг:
- **ЗАТВОРЕНО** (здравословно) — Заявките протичат нормално
- **OPEN**Доставчикът е временно блокиран след повтарящи се повреди
- **HALF_OPEN**Тестване дали доставчикът се е възстановил
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. **Правила и заключени идентификатори** — Показва състоянието на прекъсвача и заключените идентификатори с възможност за принудително отключване.
4. **Policies & Locked Identifiers** — Shows circuit breaker status and locked identifiers with force-unlock capability.
5. **Автоматично откриване на ограничение на скоростта** — Наблюдава заглавките `429` и `Retry-After`, за да избегне проактивно достигане на ограниченията на скоростта на доставчика.
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**.
| Действие | Описание |
| ------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Експортиране на база данни** | Изтегля текущата база данни SQLite като `.sqlite` файл |
| **Експортиране на всички (.tar.gz)** | Изтегля пълен резервен архив, включително: база данни, настройки, комбинации, връзки с доставчик (без идентификационни данни), API ключ метаданни |
| **Импортиране на база данни** | Качете файл `.sqlite`, за да замените текущата база данни. Автоматично се създава резервно копие преди импортиране |
| 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 |
```bash
# API: Export database
@@ -596,38 +659,38 @@ curl -X POST http://localhost:20128/api/db-backups/import \
-F "file=@backup.sqlite"
```
**Проверка на импортиране:** Импортираният файл се валидира за цялост (проверка на SQLite pragma), необходими таблици (`provider_connections`, `provider_nodes`, `combos`, `api_keys`) и размер (макс. 100MB).
**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:**
- Мигрирайте OmniRoute между машини
- Създаване на външни резервни копия за възстановяване след бедствие
- Споделяне на конфигурации между членовете на екипа (експортиране на всички → споделяне на архив)
- Migrate OmniRoute between machines
- Create external backups for disaster recovery
- Share configurations between team members (export all → share archive)
---
### Табло за управление на настройките
### Settings Dashboard
Страницата с настройки е организирана в 5 раздела за лесна навигация:
The settings page is organized into 5 tabs for easy navigation:
| Раздел | Съдържание |
| ------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Сигурност** | Настройки за вход/парола, IP контрол на достъпа, API удостоверяване за `/models` и блокиране на доставчик |
| **Маршрутизиране** | Стратегия за глобално маршрутизиране (6 опции), псевдоними на модели със заместващи символи, резервни вериги, комбинирани настройки по подразбиране |
| **Устойчивост** | Профили на доставчици, редактируеми лимити на скоростта, състояние на прекъсвача, политики и заключени идентификатори |
| **AI** | Обмисляне на конфигурация на бюджета, инжектиране на глобална система, статистика на бързия кеш |
| **Разширено** | Глобална прокси конфигурация (HTTP/SOCKS5) |
| Tab | Contents |
| -------------- | ---------------------------------------------------------------------------------------------- |
| **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**.
| Раздел | Цел |
| ---------- | -------------------------------------------------------------------------------------------------------------- |
| **Бюджет** | Задайте лимити на разходите за API ключ с дневни/седмични/месечни бюджети и проследяване в реално време |
| **Цени** | Преглеждайте и редактирайте записи за ценообразуване на модела — цена за 1K входно/изходни токени на доставчик |
| 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
@@ -639,13 +702,13 @@ curl -X POST http://localhost:20128/api/usage/budget \
curl http://localhost:20128/api/usage/budget
```
**Проследяване на разходите:** Всяка заявка регистрира използването на токени и изчислява разходите с помощта на таблицата с цените. Вижте разбивки в **Табло за управление → Използване** по доставчик, модел и API ключ.
**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 поддържа аудио транскрипция чрез OpenAI-съвместима крайна точка:
OmniRoute supports audio transcription via the OpenAI-compatible endpoint:
```bash
POST /v1/audio/transcriptions
@@ -659,40 +722,92 @@ curl -X POST http://localhost:20128/v1/audio/transcriptions \
-F "model=deepgram/nova-3"
```
Налични доставчици: **Deepgram** (`deepgram/`), **AssemblyAI** (`assemblyai/`).
Available providers: **Deepgram** (`deepgram/`), **AssemblyAI** (`assemblyai/`).
Поддържани аудио формати: `mp3`, `wav`, `m4a`, `flac`, `ogg`, `webm`.
Supported audio formats: `mp3`, `wav`, `m4a`, `flac`, `ogg`, `webm`.
---
### Комбинирани стратегии за балансиране
### Combo Balancing Strategies
Конфигурирайте балансирането за комбо в **Табло за управление → Комбота → Създаване/Редактиране → Стратегия**.
Configure per-combo balancing in **Dashboard → Combos → Create/Edit → Strategy**.
| Стратегия | Описание |
| ---------------------------- | -------------------------------------------------------------------------------- |
| **Round-Robin** | Върти се през моделите последователно |
| **Приоритет** | Винаги пробва първия модел; връща се само при грешка |
| **Произволно** | Избира произволен модел от комбинацията за всяка заявка |
| **Претеглено** | Маршрути пропорционално въз основа на зададени тегла за модел |
| **Най-малко използвани** | Насочва към модела с най-малко скорошни заявки (използва комбинирани показатели) |
| **Оптимизиран за разходите** | Маршрути до най-евтиния наличен модел (използва ценова таблица) |
| 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
Достъп чрез **Табло → Здраве**. Преглед на здравето на системата в реално време с 6 карти:
Access via **Dashboard → Health**. Real-time system health overview with 6 cards:
| Карта | Какво показва |
| ---------------------------- | -------------------------------------------------------------------------- |
| **Състояние на системата** | Време на работа, версия, използване на паметта, директория с данни |
| **Здраве на доставчика** | Състояние на прекъсвача за всеки доставчик (затворен/отворен/полуотворен) |
| **Ограничения на скоростта** | Активен лимит на изчакване за акаунт с оставащо време |
| **Активни блокировки** | Доставчици, временно блокирани от политиката за блокиране |
| **Кеш на подписа** | Статистика на кеша за дедупликация (активни ключове, процент на попадения) |
| **Телеметрия за забавяне** | p50/p95/p99 агрегиране на латентност за доставчик |
| 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 |
**Професионален съвет:** Страницата Health се опреснява автоматично на всеки 10 секунди. Използвайте картата на прекъсвача, за да идентифицирате кои доставчици имат проблеми.
**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.
### Installation
```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 (6416384 MB) |
📖 Full documentation: [`electron/README.md`](../electron/README.md)
+401
View File
@@ -0,0 +1,401 @@
# 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) |
+196
View File
@@ -0,0 +1,196 @@
# 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);
```
+453
View File
@@ -0,0 +1,453 @@
# 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`
+782
View File
@@ -0,0 +1,782 @@
# 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ů ( `<think>...</think>` ).
- 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/iFlow/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` , `iflow.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/` , `<repo>/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í: `<repo>/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, iFlow, 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í |
| iFlow | 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 `<think>...</think>` 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 `<repo>/logs/<session>/` 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` -&gt; `XDG_CONFIG_HOME/omniroute` -&gt; `~/.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://<host>:20128/v1` , pokud `PORT=20128`
+63
View File
@@ -0,0 +1,63 @@
# 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 &lt; 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** : &gt;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

Some files were not shown because too many files have changed in this diff Show More