Compare commits

...

132 Commits

Author SHA1 Message Date
diegosouzapw
6a0760a2c5 chore: bump to v2.0.2 (v2.0.1 was claimed on npm) 2026-03-05 20:11:15 -03:00
diegosouzapw
b0819404c7 feat(release): v2.0.1 — endpoint-aware models, 3 bug fixes (#212, #213, #200), 3 features (#204, #205, #206) 2026-03-05 20:04:41 -03:00
diegosouzapw
228ebf436e feat: endpoint-aware model management + fix 3 bugs (#212, #213, #200)
Bug Fixes:
- #212: Auto-generate API_KEY_SECRET at startup (like JWT_SECRET)
- #213: Circuit breaker now scoped per-model instead of per-provider
- #200: Connectivity fallback for custom providers (Ollama, LM Studio)

Features:
- #204: API Format selector (Chat Completions / Responses API) for custom models
- #205: Combo endpoint field (chat / embeddings / images) in schema
- #206: Supported Endpoints checkboxes (chat, embeddings, images, audio)
- Custom models with endpoint tags appear in /v1/embeddings and /v1/images/generations
- Model catalog includes api_format, type, and supported_endpoints metadata
- Provider detail page shows badges for non-default endpoint configurations

Files changed: instrumentation.ts, combo.ts, validation.ts, models.ts,
schemas.ts, provider-models/route.ts, providers/[id]/page.tsx,
catalog.ts, embeddings/route.ts, images/generations/route.ts
2026-03-05 18:49:07 -03:00
diegosouzapw
d2b6624de4 Merge branch 'features-agente-mcp-a2a'
# Conflicts:
#	package-lock.json
2026-03-05 18:11:27 -03:00
diegosouzapw
0dd6d349b3 docs: consolidate v2.0.0 changelog — comprehensive release from v1.8.1
Merged all changes from the features-agente-mcp-a2a branch into a single
v2.0.0 release entry covering: MCP multi-transport (3 modes), 16 MCP tools,
A2A protocol, Auto-Combo engine, VS Code extension, consolidated Endpoints
dashboard with service toggles, 30-language i18n, full type safety overhaul,
and 1000+ tests.
2026-03-05 18:11:05 -03:00
diegosouzapw
ecb0774b7b feat(release): v2.0.1 — MCP multi-transport (stdio/SSE/Streamable HTTP), service toggles, endpoints consolidation
- MCP multi-transport: stdio, SSE (/api/mcp/sse), Streamable HTTP (/api/mcp/stream)
- Service enable/disable toggles with settings persistence (default: OFF)
- Consolidated Endpoints page with tabbed navigation
- Transport selector UI with connection URLs and Copy button
- Webpack barrel-file fix for settingsSchemas
2026-03-05 17:59:46 -03:00
diegosouzapw
6ab32b351f docs: update CHANGELOG and AGENTS.md with MCP multi-transport 2026-03-05 17:54:46 -03:00
diegosouzapw
e09d4a02a2 feat: add MCP multi-transport (stdio + SSE + Streamable HTTP)
- Created httpTransport.ts with singleton MCP server and WebStandard
  Streamable HTTP transport running inside Next.js process
- Added /api/mcp/sse route (GET+POST) for SSE transport
- Added /api/mcp/stream route (GET+POST+DELETE) for Streamable HTTP
- Added mcpTransport enum to settingsSchemas (stdio|sse|streamable-http)
- Updated /api/mcp/status to report HTTP transport state
- Added TransportSelector UI with mode buttons and connection URL display
- Routes guard against disabled MCP or wrong transport mode
2026-03-05 17:45:44 -03:00
diegosouzapw
3de8b4371a fix: extract updateSettingsSchema to bypass webpack barrel-file bug
- Created settingsSchemas.ts with updateSettingsSchema to avoid webpack
  tree-shaking the schema from the 908-line schemas.ts barrel file
- Updated settings/route.ts import to use new dedicated file
- Fixed focusRingColor lint error in ServiceToggle
2026-03-05 17:19:48 -03:00
diegosouzapw
396ab2bab5 feat: add MCP/A2A enable/disable toggle switches on Endpoints page
- Added mcpEnabled/a2aEnabled boolean fields to updateSettingsSchema
- Rewrote ServiceToggle as clickable on/off switch with status indicator
- Toggle persists state via PATCH /api/settings
- Both services default to disabled (OFF)
2026-03-05 16:56:04 -03:00
diegosouzapw
305fb56b62 docs: update AGENTS.md, README, CHANGELOG and all 30 i18n locales for Endpoints consolidation
- Rewrote AGENTS.md with v2.0.0 architecture (MCP, A2A, Auto-Combo, Endpoints tabs)
- Updated CHANGELOG unreleased section with Endpoints consolidation details
- Updated README references from Endpoint to Endpoints (screenshots, playbook, quickstart)
- Applied endpoints sidebar/header/namespace i18n to all 28 remaining language files
2026-03-05 16:51:11 -03:00
diegosouzapw
0f22f38f7e feat: consolidate Endpoint, MCP, A2A into tabbed Endpoints page
- Renamed sidebar 'Endpoint' to 'Endpoints', removed standalone MCP/A2A entries
- Created tabbed layout with SegmentedControl: Endpoint Proxy | MCP | A2A | API Endpoints
- Added inline ServiceToggle (online/offline status) for MCP and A2A tabs
- Created ApiEndpointsTab placeholder with Coming Soon badge
- Updated i18n in en.json and pt.json with new endpoints namespace
2026-03-05 16:36:58 -03:00
diegosouzapw
084b206ae6 fix: CORS headers on early-return error responses + auto-combo validation (#208, #209)
- Added CORS_HEADERS spread to 400/503 responses in chat/completions route
- Added createAutoComboSchema with Zod validation to /api/combos/auto
- Isolated JSON parsing errors with structured 400 response
- Prevented String(err) leakage on 500 errors
2026-03-05 15:56:17 -03:00
diegosouzapw
0d3728efa4 feat: Introduce combo readiness checks and strategy recommendations, updating i18n messages and e2e tests. 2026-03-05 14:38:03 -03:00
diegosouzapw
2b067c5d00 feat: Add i18n for new media and themes features, enhance combos with strategy guides and advanced settings, and introduce E2E tests for the combos flow. 2026-03-05 13:01:37 -03:00
diegosouzapw
21135407af feat: Introduce new A2A and MCP API routes, enhance dashboard UI, update READMEs, and add E2E tests. 2026-03-05 11:16:56 -03:00
diegosouzapw
c38a58fc98 chore: update lockfile to fix CI 2026-03-05 08:47:20 -03:00
Diego Rodrigues de Sa e Souza
20e4b1b011 Update open-sse/mcp-server/server.ts
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
2026-03-05 08:43:01 -03:00
Diego Rodrigues de Sa e Souza
9691469987 Update docs/openapi.yaml
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-03-05 08:42:21 -03:00
Diego Rodrigues de Sa e Souza
63114af08d Update src/app/api/auth/login/route.ts
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-03-05 08:42:04 -03:00
Diego Rodrigues de Sa e Souza
e78ede45b6 Potential fix for code scanning alert no. 54: Insecure randomness
Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
2026-03-05 08:41:44 -03:00
diegosouzapw
751ff77b7c fix: extract validation helpers to fix webpack barrel-file resolution bug
Extracted validateBody, isValidationFailure, and loginSchema from the
935-line schemas.ts barrel file into a dedicated helpers.ts module.
Updated 70 API route files to import directly from helpers.ts.

Root cause: webpack on certain environments fails to resolve exports
from the bottom of large barrel files (schemas.ts), causing
'(0, O.Jb) is not a function' errors in production builds.

Fix: Split validation helpers into a small dedicated module (helpers.ts)
so webpack can correctly resolve all exports regardless of file size.

- TypeScript compiles with 0 errors
- All API routes updated to import from helpers.ts
- schemas.ts re-exports from helpers.ts for backward compatibility
2026-03-05 08:05:58 -03:00
diegosouzapw
5a53c17e81 feat: configurable tool name prefix (#199) and custom rpm/tpm rate limits (#198)
- Issue #199: proxy_ prefix on tool names is now automatically disabled
  when routing to non-Claude backends (Gemini, Compatible, etc.).
  Prevents tool name mismatches in OpenCode, Cursor, and other clients.

- Issue #198: Added customRpm/customTpm support per provider connection.
  Users can configure custom rate limits via connection settings,
  overriding the default auto-learned limits from response headers.
2026-03-05 01:41:34 -03:00
Diego Rodrigues de Sa e Souza
9c32c30daf Merge pull request #203 from DavyMassoneto/fix/claude-oauth-usage-endpoint
Approving — all review issues resolved. Claude OAuth usage endpoint with proper fallback to legacy API key method. Thanks @DavyMassoneto! 🎉
2026-03-05 01:26:52 -03:00
diegosouzapw
baa0208fa9 feat: v2.0.0 - MCP server, A2A agent, proxy improvements and docs update 2026-03-05 01:16:56 -03:00
DavyMassoneto
2ec0cd13cd fix(claude): correct utilization inversion and propagate remainingPercentage
- Fix createQuotaObject: utilization is percentage USED, not remaining
- Add optional chaining to window access in createQuotaObject
- Use typeof object guards for five_hour/seven_day instead of !== undefined
- Use nullish coalescing for extra_usage
- Propagate remainingPercentage in parseQuotaData claude case
2026-03-04 22:17:00 -03:00
diegosouzapw
0d8f28a4a4 feat: Introduce A2A lifecycle management, add type safety to ComfyUI and stream handling, and update various handlers and translators. 2026-03-04 21:02:56 -03:00
diegosouzapw
33dfbf0177 refactor: harden open-sse services, eliminate any casts, add dashboard pages
- Replace all `as any` casts in MCP advancedTools with typed helpers (toRecord, toString, toNumber)
- Harden open-sse services: rateLimitManager, sessionManager, usage, roleNormalizer, signatureCache, comboMetrics
- Improve responseSanitizer and responseTranslator type safety
- Remove deprecated openai-responses request translator
- Add dashboard pages: /a2a, /mcp, /auto-combo with live data
- Improve error/loading/not-found pages with consistent design
- Add root loading.tsx and typecheck tsconfig variants
- Add check-t11-any-budget.mjs audit script
2026-03-04 19:38:34 -03:00
diegosouzapw
85c6b63c8f feat: add error pages, harden DB layer and compliance module
- Add HTTP error pages (400, 401, 403, 408, 429, 500, 502, 503)
- Add maintenance, offline, and system status pages
- Harden db/core.ts, db/apiKeys.ts, db/cliToolState.ts, db/backup.ts
- Strengthen compliance/index.ts audit logging
- Improve container.ts DI registrations
- Fix dataPaths.ts and tokenHealthCheck.ts
2026-03-04 19:35:38 -03:00
DavyMassoneto
d19f336286 refactor: address PR review feedback
- Use parseResetTime() for resetAt fields (consistency with other fetchers)
- Extract createQuotaObject() helper to reduce duplication
- Remove unnecessary Content-Type header from GET requests
- Use CLAUDE_CONFIG.usageUrl with template interpolation in legacy fallback
2026-03-04 19:27:40 -03:00
diegosouzapw
052eb8d330 refactor: replace any types with generics and add Zod validation schemas
Eliminate `any` usage across the codebase by introducing proper generics,
typed interfaces (StatementLike, DbLike, PromptRow, etc.), and helper
conversion functions (toNumber, toString, parseVariables). Add
comprehensive Zod validation schemas for API endpoint inputs to enforce
runtime type safety alongside compile-time checks.
2026-03-04 18:59:27 -03:00
diegosouzapw
3510d8c0bc feat: add A2A protocol support and refactor API validation layer
Implement Agent-to-Agent (A2A) JSON-RPC 2.0 endpoint with smart routing
and quota management skills, SSE streaming, and task lifecycle management.

- Add /a2a route with message/send, message/stream, tasks/get, tasks/cancel
- Add /.well-known/agent.json agent card endpoint
- Introduce Zod-based request validation schemas for all v1 API routes
- Extract shared getUnifiedModelsResponse to reduce duplication across
  /models, /v1/models, and /a2a model listing
- Refactor chat, embeddings, moderations, and models routes to use
  centralized validation and error handling
- Add A2A task manager, routing logger, and streaming utilities
2026-03-04 18:52:25 -03:00
diegosouzapw
20860877b8 feat: add TypeScript types and modularize translator registry
- Add type annotations to all providerModels helper functions
- Introduce LegacyProvider interface in providerRegistry
- Refactor translator system to use self-registering module pattern
  with bootstrapTranslatorRegistry() and per-file imports
- Simplify translator/index.ts by delegating to modular translators
- Remove hardcoded Gemini OAuth client secret for security
2026-03-04 18:46:49 -03:00
diegosouzapw
bddec84f4e feat: add MCP server, A2A protocol, auto-combo engine & VS Code extension
Introduce full AI orchestration ecosystem:
- MCP Server with 16 tools, scoped auth, and audit logging
- A2A v0.3 server with JSON-RPC 2.0, SSE streaming, and task manager
- Auto-Combo engine with 6-factor scoring and self-healing
- VS Code extension with smart dispatch and budget tracking
- Harden CI pipeline: add static checks, remove continue-on-error
- Add translator schema validation tests
- Update .gitignore and CHANGELOG for release checklist
2026-03-04 18:45:02 -03:00
DavyMassoneto
aba12ad5db chore: sync package-lock.json with package.json v1.8.1 2026-03-04 18:29:05 -03:00
DavyMassoneto
6ea8d094b2 fix: invert utilization values — API returns remaining, not used
The OAuth usage endpoint returns utilization as percentage remaining,
not percentage used. Claude.ai showing 10% used corresponded to
utilization=90 from the API.
2026-03-04 18:19:17 -03:00
DavyMassoneto
b5a3a3d019 fix: use OAuth usage endpoint for Claude Code provider limits
The Limits page showed "error" 0% for Claude Code (OAuth) providers
because getClaudeUsage() called /v1/settings which requires API key
with org admin access — unavailable to consumer OAuth tokens.

Now uses https://api.anthropic.com/api/oauth/usage with the
anthropic-beta: oauth-2025-04-20 header, which returns five_hour and
seven_day utilization data for OAuth accounts.

Falls back to legacy /v1/settings endpoint for API key users.
2026-03-04 17:57:09 -03:00
diegosouzapw
5ecef5c90c feat: normalize quota and combos API responses with shared contracts
Introduce `normalizeQuotaResponse` and `normalizeCombosResponse` helpers
to handle varying API response shapes (array vs wrapped object)
consistently across MCP server and advanced tools. Add optional `meta`
field to checkQuotaOutput schema and update sourceEndpoints to reflect
current API routes.
2026-03-04 08:18:09 -03:00
diegosouzapw
fe9d9a5a5c feat: migrate tests to TypeScript and add MCP advanced tools test suite
- Add unit tests for 8 MCP advanced tool handlers (Phase 3)
- Migrate test files from JavaScript to TypeScript (.ts/.tsx)
- Restructure file paths from app/ to src/app/ across all tests
- Refactor route assertions into reusable assertRouteMethods helper
- Add tests for new API routes (compliance, audit-log, evals/[suiteId])
- Update barrel export tests to use consolidated assertion pattern
2026-03-04 00:41:30 -03:00
diegosouzapw
e18cfe1d80 feat: add Phase 3 advanced MCP tools and A2A smart routing skill
Register 8 new advanced MCP tools (simulate_route, set_budget_guard,
set_resilience_profile, test_combo, get_provider_metrics,
best_combo_for_task, explain_route, get_session_snapshot) with their
handler implementations. Add A2A smart routing skill that routes
prompts through the OmniRoute pipeline with routing explanation,
cost envelope, and resilience trace metadata.
2026-03-03 18:53:11 -03:00
diegosouzapw
7eb45b2e19 feat: add MCP server mode with --mcp flag for IDE integration
Add stdio-based MCP server support to OmniRoute CLI, enabling AI agents
in VS Code, Cursor, Claude Desktop, and Copilot to interact with
OmniRoute tools (health, combos, quota, routing). Update help text,
gitignore vscode-extension subproject, and include MCP/A2A strategy report.
2026-03-03 17:42:24 -03:00
diegosouzapw
70465ada4d feat(release): v1.8.1 — usage API proxy support 2026-03-03 12:06:42 -03:00
Diego Rodrigues de Sa e Souza
8ddea153d3 Merge pull request #195 from diegosouzapw/fix/issue-194-usage-proxy
fix: route usage API quota fetches through configured proxy (#194)
2026-03-03 12:05:55 -03:00
diegosouzapw
8dca8fba6b fix: route usage API quota fetches through configured proxy (#194) 2026-03-03 12:04:59 -03:00
diegosouzapw
f21ba7df64 feat(release): v1.8.0 — empty tool_use.name validation, Windows electron fix 2026-03-03 11:21:31 -03:00
Diego Rodrigues de Sa e Souza
ef917e42d1 Merge pull request #190 from benzntech/fix/electron-windows-collect-installers
fix: Windows electron release — collect portable exe by pattern
2026-03-03 11:19:53 -03:00
Diego Rodrigues de Sa e Souza
865a1b9b2c Merge pull request #193 from diegosouzapw/fix/issue-191-empty-tool-use-name
fix: validate empty tool_use.name to prevent Claude 400 errors (#191)
2026-03-03 11:19:45 -03:00
diegosouzapw
de8a0836a8 fix: validate empty tool_use.name to prevent Claude 400 errors (#191) 2026-03-03 11:18:53 -03:00
benzntech
b8272c55d7 fix: address review — break after first portable exe, remove debug ls 2026-03-03 09:27:31 +05:30
benzntech
8d93c13f9a fix: collect portable exe by pattern instead of hardcoded filename
electron-builder produces 'OmniRoute 1.6.9.exe' (with version) as the
portable exe, not 'OmniRoute.exe'. The hardcoded check failed, returning
exit code 1 and breaking every Windows build in the release workflow.

Now finds the portable exe by excluding 'Setup' (NSIS installer) and
blockmap files, then copies it as OmniRoute.exe for the release assets.
2026-03-03 09:20:24 +05:30
diegosouzapw
8152b030bf chore: bump version to 1.7.14 and update CHANGELOG 2026-03-02 19:18:38 -03:00
diegosouzapw
9352ac767f Merge PR #188: fix passthrough stream for Responses SSE (#186) 2026-03-02 19:17:38 -03:00
diegosouzapw
5f20029ff7 fix: make passthrough stream format-aware for Responses SSE (#186)
Passthrough mode now detects Responses SSE payloads (parsed.type starts
with 'response.') and skips Chat Completions-specific sanitization:
- sanitizeStreamingChunk() only runs on Chat Completions payloads
- fixInvalidId() and hasValuableContent() checks skipped for Responses
- Usage extraction still runs for both formats
- Content length tracking adapted for Responses delta format

This prevents potential stream corruption when Responses SSE data
triggers idFixed or other Chat Completions-specific rewrite conditions.
2026-03-02 19:13:34 -03:00
diegosouzapw
dbd00117c8 chore: bump to 1.7.13 (npm republish) 2026-03-02 18:51:24 -03:00
diegosouzapw
2902a0fe26 chore: bump version to 1.7.12 2026-03-02 18:47:07 -03:00
diegosouzapw
7ba57634c1 feat: add blackbox.ai to dashboard frontend (#175)
- Added blackbox provider to APIKEY_PROVIDERS in providers.ts
- Added blackbox pricing entries in pricing.ts
- Added blackbox to ProviderId typedef in types.ts
- Added blackbox models endpoint config in models/route.ts
2026-03-02 18:46:48 -03:00
diegosouzapw
211dde25d0 chore: bump version to 1.7.11 and update CHANGELOG 2026-03-02 18:33:08 -03:00
diegosouzapw
57ff59aef2 Merge PR #183: fix projectId warnings + add blackbox.ai provider (#175, #176)
- Added warning logs when generateProjectId() is used as fallback
- Prefer translator-set body.project before generating a new fallback
- Added blackbox.ai as OpenAI-compatible provider with 6 models + logo
- Includes improvement from Copilot PRs #184 and #185
2026-03-02 18:32:08 -03:00
Diego Rodrigues de Sa e Souza
c39faba2b5 Update open-sse/executors/antigravity.ts
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-03-02 18:22:49 -03:00
diegosouzapw
212bca2e1e fix: add projectId warning logs and blackbox.ai provider (#175, #176)
- Added warning logs when generateProjectId() is used as fallback
  in antigravity.ts and openai-to-gemini.ts (3 locations), helping
  admins diagnose 404 errors from fake GCP project IDs (#176)
- Added blackbox.ai as new OpenAI-compatible provider with 6 models
  (GPT-4o, Gemini 2.5 Flash, Claude Sonnet 4, DeepSeek V3,
  Blackbox AI, Blackbox AI Pro) and provider logo (#175)
2026-03-02 17:58:43 -03:00
Diego Rodrigues de Sa e Souza
f807c56e31 Merge pull request #182 from diegosouzapw/dependabot/npm_and_yarn/development-51b319602c
deps: bump the development group with 2 updates
2026-03-02 17:47:43 -03:00
Diego Rodrigues de Sa e Souza
5510c25040 Merge pull request #181 from diegosouzapw/dependabot/npm_and_yarn/production-d7c3d31362
deps: bump wreq-js from 2.0.1 to 2.1.1 in the production group
2026-03-02 17:47:26 -03:00
dependabot[bot]
9d884d2d60 deps: bump the development group with 2 updates
Bumps the development group with 2 updates: [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) and [lint-staged](https://github.com/lint-staged/lint-staged).


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

Updates `lint-staged` from 16.2.7 to 16.3.1
- [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.2.7...v16.3.1)

---
updated-dependencies:
- dependency-name: "@types/node"
  dependency-version: 25.3.3
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: development
- dependency-name: lint-staged
  dependency-version: 16.3.1
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: development
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-03-02 20:22:45 +00:00
dependabot[bot]
f26fa67374 deps: bump wreq-js from 2.0.1 to 2.1.1 in the production group
Bumps the production group with 1 update: [wreq-js](https://github.com/sqdshguy/wreq-js).


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

---
updated-dependencies:
- dependency-name: wreq-js
  dependency-version: 2.1.1
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: production
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-03-02 20:22:16 +00:00
diegosouzapw
ccb314e065 feat: update agent workflows to use PR-based flow with user verification
Refactor resolve-issues and review-prs workflows to create branches
and PRs instead of committing directly. Add mandatory stop points
for user verification before merging, closing issues, or releasing.
Includes deploy step to local VPS after release.
2026-03-02 16:37:17 -03:00
diegosouzapw
0517dcf0b7 chore: bump version to 1.7.10 and update CHANGELOG 2026-03-02 15:31:38 -03:00
diegosouzapw
b7f0665ce9 fix: streaming tool calls missing id and wrong finish_reason in Responses→ChatCompletions translation (#180)
- Added tool_calls[].id and type:'function' to argument delta chunks
  so OpenAI-compatible clients can associate argument fragments with
  the correct tool call
- Changed finish_reason from hardcoded 'stop' to 'tool_calls' when
  tool calls were emitted (in flush, response.completed, and final chunk)
- Fixes state desync in agentic clients (OpenCode, Claude Code, etc.)
  where the assistant thinks tools already ran
2026-03-02 15:30:54 -03:00
diegosouzapw
144628755d chore: bump version to 1.7.9 and update CHANGELOG 2026-03-02 14:55:56 -03:00
diegosouzapw
7c5bb2c6b6 Merge PR #179: docs: update Cline URL to OpenClaw 2026-03-02 14:55:13 -03:00
diegosouzapw
afadb0fea1 Merge PR #178: fix: add JWT_SECRET env to electron release build step 2026-03-02 14:54:51 -03:00
MAINER4IK
b6c9c8a822 Change Cline to OpenClaw :)) 2026-03-02 22:28:01 +05:00
benzntech
11f43ca65c fix: add JWT_SECRET env to electron release build step
The Next.js build in electron-release.yml fails because the secrets
validator detects missing JWT_SECRET and exits with code 1. This adds
the env var to the build step, matching the pattern used in ci.yml.
2026-03-02 22:50:33 +05:30
diegosouzapw
8dce812a4d chore: bump version to 1.7.8 and update CHANGELOG 2026-03-02 12:14:58 -03:00
diegosouzapw
93047069b6 Merge PR #174: feat: add theme color settings and complete media/theme i18n 2026-03-02 12:13:53 -03:00
diegosouzapw
c4f1990aff fix: address agent review issues for theme color settings (#174)
Code Quality Improvements:
- Export COLOR_THEMES from themeStore.ts for reuse (DRY)
- Add coral preset to color list (fixes default inconsistency)
- Sync local customThemeColor state reactively via Zustand subscribe
- Add hex color validation with visual feedback (red border + disabled button)
- Remove dead /themes route from Header.tsx (page doesn't exist)
- Add CSS color-mix() fallback for older browsers
- Add themeCoral i18n key to all 30 locale files
2026-03-02 12:12:52 -03:00
mainer4ik
6e2816f08b feat: add theme color settings and complete media/theme i18n 2026-03-02 18:37:27 +05:00
diegosouzapw
227268024d chore: bump version to 1.7.7 and update CHANGELOG 2026-03-02 10:29:08 -03:00
diegosouzapw
8d5891a382 fix: sanitize tool schemas for Gemini provider (#173)
- Added cleanJSONSchemaForAntigravity() to openaiToGeminiBase() tool conversion
- Both OpenAI-format and Claude-format tool parameters are now sanitized
- Also sanitized response_format json_schema using the same function
- Removes unsupported JSON Schema keywords (additionalProperties, $schema, etc.)
- All Gemini paths (standard, CLI, Antigravity) now consistently sanitize schemas
2026-03-02 10:28:26 -03:00
diegosouzapw
7700fca501 chore: bump version to 1.7.6 and update CHANGELOG 2026-03-02 10:19:43 -03:00
diegosouzapw
527c542d6d fix: cloud proxy endpoint shows undefined/v1 when env var not set (#171)
- syncAndVerify now returns cloudUrl in API response for frontend to use
- EndpointPageClient uses dynamic cloudBaseUrl state instead of relying on env var
- Falls back gracefully when NEXT_PUBLIC_CLOUD_URL is not set (Docker deployments)
- Fixed setInterval in accountFallback.ts global scope for Cloudflare Workers compat
2026-03-02 10:18:21 -03:00
diegosouzapw
8fbae5e467 feat(release): v1.7.5 — OAuth re-auth duplicate fix (#170)
- Fixed OAuth re-auth creating duplicate connections instead of updating existing ones
- CHANGELOG.md updated with v1.7.5 section
- Version bumped to 1.7.5
2026-03-02 00:38:33 -03:00
diegosouzapw
4d2a5efd12 fix: OAuth re-auth now updates existing connection instead of creating duplicates (#170)
- Modified OAuth exchange route to use upsert logic at all 3 connection-save locations
- Before creating a new connection, checks for existing connections with same provider+email+authType
- If match found, calls updateProviderConnection() to refresh tokens instead of creating duplicate
- Falls back to createProviderConnection() for genuinely new connections
- Fixes: re-auth button creating new account entries instead of refreshing existing ones
2026-03-02 00:37:50 -03:00
diegosouzapw
5ffa14190a feat(release): v1.7.4 — OpenCode CLI integration, endpoint page restructure, i18n translations
- OpenCode CLI integration guide added to README (#169)
- Endpoint page restructured with 3 categories + Responses API & Models endpoints
- 21 new i18n keys (settings + endpoint) translated across 30 locales
- 30 translated READMEs synced with v1.7.3 features
- 3 new workflow files: update-docs, generate-release, issue-triage
2026-03-01 23:03:54 -03:00
diegosouzapw
7820145cbe docs: add OpenCode CLI integration guide (#169)
- Added OpenCode section to README.md CLI Integration with step-by-step instructions
- Uses @ai-sdk/openai-compatible adapter with custom opencode.json config
- Includes example models and baseURL configuration
- Closes #169
2026-03-01 22:59:10 -03:00
diegosouzapw
b7a6c563ac feat: add i18n translations for Model Aliases & Background Degradation + restructure Endpoint page
- Added 14 translated settings keys (modelAliasesTitle, backgroundDegradationTitle, enableDegradation, etc.) to all 30 locale files
- Added 7 translated endpoint keys (responsesDesc, listModelsDesc, categoryCore/Media/Utility) to all 30 locale files
- Restructured Endpoint page with 3 grouped categories: Core APIs, Media & Multi-Modal, Utility & Management
- Added Responses API (/v1/responses) and List Models (/v1/models) endpoint sections
- Fixed missing translation display issue where raw keys were shown instead of translated text
2026-03-01 22:50:07 -03:00
diegosouzapw
52221488d0 docs: sync all 30 language READMEs with v1.7.3 features + create workflow files
- Synced feature tables across all 28 translated READMEs (Model Aliases, Background Degradation, Rate Limit Persistence, Token Refresh Resilience)
- Updated 6 docs/i18n/*/FEATURES.md with new Settings description
- Created workflows: update-docs.md (with multi-language sync step), generate-release.md, issue-triage.md
2026-03-01 22:02:38 -03:00
diegosouzapw
4a1acb1446 feat(release): v1.7.3 — model deprecation, background degradation, rate limit persistence, thinking improvements, circuit breaker
Features:
- Model Deprecation Auto-Forward (10+ built-in aliases + custom via UI)
- Background Task Smart Degradation (19 patterns, degradation map)
- Rate Limit Persistence (SQLite, 60s debounce, 24h staleness)
- thinkingLevel string → budget conversion (high/medium/low/none)
- Claude -thinking model auto-injection
- Gemini 3.0/3.1 model registry distinction
- Token Refresh Circuit Breaker (5 failures → 30min cooldown)

Tests: 561 total (40+ new), 0 failures
2026-03-01 21:42:39 -03:00
diegosouzapw
dc90211222 feat: add /deploy-vps workflow for npm-based VPS deployment 2026-03-01 07:29:55 -03:00
diegosouzapw
378c9f321d docs: update CHANGELOG v1.7.2 and READMEs with new multi-modal features
- CHANGELOG: add new features section (multi-modal providers, media playground, unit tests, WFGY docs) and expand bug fixes
- README/README.pt-BR: add Video/Music to tagline, expand Pain Point #13 with all new modalities, update Multi-Modal APIs table with Video/Music Generation
2026-03-01 07:12:51 -03:00
diegosouzapw
e11bcc2848 feat: add unit tests for registryUtils, media playground page, TypeScript fixes
- 24 unit tests for parseModelFromRegistry, getAllModelsFromRegistry, buildAuthHeaders
- Integration tests for video/music registries
- Media Playground dashboard page (Image/Video/Music tabs with model selector)
- Sidebar navigation entry for Media page
- i18n translations (EN + PT-BR)
- Fix Record<string, any> → Record<string, unknown> in registryUtils.ts
- Update /resolve-issues workflow to wait for user validation before commit/release
2026-03-01 07:10:27 -03:00
Diego Rodrigues de Sa e Souza
3f10430150 Merge pull request #167 from ken2190/feat/new-providers-and-modalities
Approved — adds multi-modal support with new TTS/STT/Image/Video/Music providers. Follow-up commits will add frontend pages, unit tests, and configurable local provider URLs.
2026-03-01 07:03:14 -03:00
Diego Rodrigues de Sa e Souza
e8b72b54b3 Merge pull request #164 from onestardao/main
Approved — docs-only addition referencing the WFGY 16-problem RAG failure taxonomy in TROUBLESHOOTING.md.
2026-03-01 07:02:47 -03:00
Diego Rodrigues de Sa e Souza
d902dda4b1 Merge pull request #168 from benzntech/fix/electron-windows-shell
Approved — fixes Windows Electron release builds by adding `shell: bash` to the Collect installers step.
2026-03-01 07:02:39 -03:00
diegosouzapw
2538480b95 chore: release v1.7.2 — Gemini model import fix, Pino transport fallback 2026-03-01 06:49:27 -03:00
diegosouzapw
b9b8c93cb9 docs: enhance review-prs workflow with cross-layer analysis and thank-you step 2026-03-01 06:48:31 -03:00
diegosouzapw
68b7b35425 fix: log actual error and add sync pino.destination fallback (#165) 2026-03-01 06:48:02 -03:00
diegosouzapw
163c5feccc fix: strip models/ prefix from Gemini imported model IDs (#163) 2026-03-01 06:47:46 -03:00
Diego Rodrigues de Sa e Souza
0488f0536e Update docs/TROUBLESHOOTING.md
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
2026-03-01 06:33:22 -03:00
benzntech
09e90ec25b fix: use bash shell for Collect installers step on Windows runner 2026-03-01 14:25:22 +05:30
duongvdo
d97a11a54f fix: address code review issues (SSRF, saveCallLog, deduplication)
- Add path traversal validation for ElevenLabs voice_id and HuggingFace
  model_id URL concatenation (prevents SSRF via ../ sequences)
- Add saveCallLog usage tracking to video and music handlers for
  consistent analytics with imageGeneration.ts
- Extract shared upstreamErrorResponse() and audioStreamResponse()
  helpers to reduce error handling duplication in audioSpeech.ts
- Extract shared upstreamErrorResponse() and isValidPathSegment()
  helpers in audioTranscription.ts
- Add explicit format: "openai" to qwen TTS and STT provider entries
- Remove unused modelId parameter from handleCoquiSpeech and
  handleTortoiseSpeech
- Filter cloud video/music providers by active status in models route
  (local providers with authType: "none" always listed)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 14:34:10 +07:00
duongvdo
4a779dfe3c feat: add new providers & modalities (TTS, STT, Image, Video, Music)
Add 6 TTS providers (Nvidia NIM, ElevenLabs, HuggingFace, Coqui, Tortoise,
Qwen3), 3 STT providers (Nvidia NIM, HuggingFace, Qwen3), 2 local image
providers (SD WebUI, ComfyUI), and two new modalities — Text-to-Video
(/v1/videos/generations) and Text-to-Music (/v1/music/generations).

Key design decisions:
- Format-based unified providers: local providers grouped by API format
  (comfyui, sdwebui, coqui, tortoise, openai-compatible) with configurable
  base URLs and expandable model lists
- Cloud providers kept separate (unique auth and API shapes)
- Local providers use authType: "none" — credential checks bypassed at both
  route and handler level
- Shared ComfyUI client (comfyuiClient.ts) reused across image/video/music
- Shared registry utilities (registryUtils.ts) for model parsing and listing
- Qwen3 TTS/ASR use format: "openai" — no custom handler needed

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 13:31:29 +07:00
PSBigBig × MiniPS
61e09d545f docs: add optional RAG failure taxonomy to troubleshooting 2026-03-01 10:56:51 +08:00
diegosouzapw
3a68d7dabc fix: restore dashboard layout — Tailwind v4 @source for route groups
Tailwind CSS v4 auto-detection failed to scan Next.js route group
directories with parentheses (e.g. '(dashboard)'), causing responsive
grid utilities to be purged from production CSS. Added explicit @source
directives in globals.css to fix the content scanning.

CSS output: 10KB (broken) → 110KB (correct), 12 media queries restored.
2026-02-28 18:53:16 -03:00
diegosouzapw
22d318f201 chore(release): bump version to v1.7.0 2026-02-28 17:42:31 -03:00
diegosouzapw
afa2cea678 feat: 16 pain points docs, configurable User-Agent (#155), fix hardcoded $HOME (#156)
- Add collapsible '16 Real Pain Points' section to all 30 READMEs
- Fix 5 files bypassing dataPaths.ts with hardcoded os.homedir() (closes #156)
- Add per-provider User-Agent env var overrides in base executor (closes #155)
- Sync .env and .env.example with 9 provider UA defaults
- Update CHANGELOG.md for v1.7.0
2026-02-28 17:41:55 -03:00
diegosouzapw
6dce45505c chore(release): v1.6.9
- PR #160: CopilotToolCard URL fix + chat model filter (alpgul)
- PR #161: Proxy port preservation, credential encoding, cache invalidation (ken2190)
- CHANGELOG: v1.6.9 entry
- Version bump: 1.6.8 → 1.6.9
2026-02-28 16:29:25 -03:00
Diego Rodrigues de Sa e Souza
014732788c Merge pull request #161 from ken2190/fix/proxy-logic-and-docker-build
fix: preserve explicit proxy port and fix Docker build
2026-02-28 16:28:28 -03:00
Diego Rodrigues de Sa e Souza
0e75d838ab Merge pull request #160 from alpgul/fix/base-url-and-chat-filter
fix: improve API base URL handling and filter for chat models in CopilotToolCard
2026-02-28 16:28:26 -03:00
Alptekin Gülcan
8383da8a50 fix: improve API base URL handling and filter for chat models in CopilotToolCard 2026-02-28 19:10:17 +00:00
duongvdo
199d173816 fix: preserve explicit proxy port (80/443) instead of defaulting to 8080
The URL parser silently strips default ports (80 for HTTP, 443 for HTTPS)
when constructing URL objects. This caused proxy connections to use port
8080 instead of the user-specified port 80, resulting in connection
timeouts. Fix by extracting the port from the raw URL string before
parsing and building the normalized URL manually to avoid the serializer
stripping it.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 01:41:07 +07:00
diegosouzapw
f2829441f0 chore(release): v1.6.8
- Merged PR #159: Electron release workflow refactor (benzntech)
- Added app/ to .gitignore (Next.js App Router conflict fix)
- CHANGELOG: v1.6.8 entry
- Version bump: 1.6.7 → 1.6.8
2026-02-28 15:33:16 -03:00
diegosouzapw
21137bd84a fix: add app/ to .gitignore — prevents Next.js App Router conflict
The production standalone build directory (app/) created by scripts/prepublish.mjs
was conflicting with Next.js App Router detection. Next.js prioritizes root app/
over src/app/, causing all routes to return 404 in dev mode.

The package.json 'files' field still includes app/, so npm publish is unaffected.
2026-02-28 15:32:24 -03:00
Diego Rodrigues de Sa e Souza
a05e51a577 Merge pull request #159 from benzntech/fix/electron-release-filter
fix: filter Electron release assets to installers only
2026-02-28 15:30:59 -03:00
benzntech
09a094629c fix: include arm64 dmg in release assets
- Add explicit pattern for *-arm64.dmg files
- Fixes Kilo bot review: *.dmg doesn't match -arm64.dmg
2026-02-28 23:34:37 +05:30
benzntech
90de0fbf68 docs: add installation instructions with macOS Gatekeeper workaround 2026-02-28 23:21:39 +05:30
benzntech
c9cdd5109b feat: add Windows portable standalone exe
- NSIS installer: OmniRoute.Setup.X.Y.Z.exe (install to Program Files)
- Portable: OmniRoute.exe (run anywhere, no installation)
2026-02-28 23:19:20 +05:30
duongvdo
0e207dc5d2 fix: proxy logic bugs and Docker build failure
- URL-encode proxy credentials to handle special characters in passwords
- Decode URL-encoded credentials during legacy proxy migration
- Fix HTTPS proxy default port (443 instead of 8080) in frontend and migration
- Add dispatcher cache invalidation when proxy config changes
- Cast proxy port to number for SQLite INTEGER column in proxy logger
- Fix redundant .replace("//", "") in migration protocol parsing
- Copy postinstall script in Dockerfile before npm install

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 00:48:27 +07:00
benzntech
876a5a98f4 feat: add source code archives to releases
- Include .tar.gz and .zip of source code
- Uses git archive for clean export (excludes node_modules, build artifacts)
- Named: OmniRoute-vX.Y.Z.source.tar.gz / .zip
2026-02-28 23:16:43 +05:30
benzntech
8e82350d66 refactor: improve Electron release workflow
- Trigger on git tags (v*) instead of release.published
- Add manual workflow_dispatch for re-runs
- Add version validation step
- Use artifact upload/download pattern
- Single release job ensures all platforms complete first
- Prevents partial releases if one platform fails
2026-02-28 23:14:53 +05:30
benzntech
de75ed1551 fix: upload only installer files to releases
- Filter to *.dmg, *.exe, *.AppImage, *.blockmap only
- Prevents uploading unpacked app contents (DLLs, JS files, images)
2026-02-28 21:52:52 +05:30
benzntech
87266104a3 Merge origin/main - sync with v1.6.7 release 2026-02-28 21:52:38 +05:30
benzntech
fed8140404 chore: ignore electron build artifacts 2026-02-28 21:44:42 +05:30
diegosouzapw
e4d83e91bb chore(release): prepare release v1.6.7
- CHANGELOG: add v1.6.7 entry (Copilot Config Generator #142)
- FEATURES.md: add Copilot to CLI Tools section
- Version bump: 1.6.6 → 1.6.7 (package.json + electron/package.json)
2026-02-28 11:53:39 -03:00
diegosouzapw
a3153d893a feat: GitHub Copilot config generator for CLI Tools (#142)
Adds a Copilot configuration generator to the CLI Tools dashboard page.
Users can select models and generate the chatLanguageModels.json config
block for VS Code GitHub Copilot with the Azure vendor pattern.

Features:
- Bulk model selection from /v1/models (includes combos, custom, aliased)
- Search/filter for large model lists
- Configurable maxInputTokens, maxOutputTokens, toolCalling, vision
- One-click copy to clipboard
- Persistent model selection via localStorage
- Version compatibility warning (VS Code >= 1.109, Copilot >= v0.37)

Feedback from @alpgul applied:
- Use /v1/models instead of /api/models/alias (includes combo definitions)
- Use window.location.origin for URL (no port duplication in Docker)

Also: added electron/dist-electron/ to .gitignore (build artifact)
2026-02-28 11:31:55 -03:00
diegosouzapw
be219449f9 chore(release): bump version to v1.6.6 2026-02-28 11:17:26 -03:00
diegosouzapw
06d193f0d9 fix: prevent auth bypass after onboarding (#151)
The 'no password' auth bypass check was meant for fresh installs only,
but it also fired after onboarding was complete if the password row
was missing from the database (e.g. after DB migration in v1.6.3).

Fix: Added !settings.setupComplete guard so the bypass only applies
before onboarding is done. Once setupComplete=true, auth is always
required regardless of whether the password key exists in the DB.

Files changed:
- src/proxy.ts (dashboard middleware)
- src/shared/utils/apiAuth.ts (isAuthRequired)
2026-02-28 11:16:23 -03:00
diegosouzapw
4f413615d9 chore(release): prepare release v1.6.5
- Merge PR #154: official Electron icons and release workflow
- Fix electron-release.yml: npm ci → npm install (no package-lock.json)
- CHANGELOG: add v1.6.5 entry
- Version bump: 1.6.4 → 1.6.5
2026-02-28 10:27:58 -03:00
Benson
2a79b833fb feat(electron): add official icons and release workflow (#154)
* feat(electron): add app icons for Windows, macOS, and Linux releases

- icon.ico: Windows application icon (256x256 with multiple resolutions)
- icon.icns: macOS application icon bundle (16px to 1024px)
- icon.png: Linux/general purpose icon (512x512)
- tray-icon.png: System tray icon (32x32)

Icons generated from images/omniroute.png source logo.
Enables branded Electron desktop app builds for all platforms.

* chore: sync package-lock.json

* feat(electron): use official SVG logo and add release workflow

- Regenerated app icons from public/icon-192.svg (official OmniRoute logo)
- Added .github/workflows/electron-release.yml for automated builds
- Icons: icon.icns (macOS), icon.ico (Windows), icon.png (Linux), tray-icon.png
- Build workflow creates DMG (mac), EXE (win), AppImage (linux) on release

* ci: add npm cache to electron-release workflow
2026-02-28 10:26:46 -03:00
Diego Rodrigues de Sa e Souza
52e3d4b37b Merge pull request #153 from diegosouzapw/dependabot/npm_and_yarn/electron/npm_and_yarn-c9b74b4f42
chore(deps-dev): bump electron from 33.4.11 to 40.6.1 in /electron in the npm_and_yarn group across 1 directory
2026-02-28 10:21:25 -03:00
diegosouzapw
d9b393a308 docs: restructure all 30 READMEs — reorder sections, remove duplicates
Changes across README.md + 29 translations:
- Remove 🌐 English | Português (BR) language switcher from top
- Move Free AI Provider agents table below badges/links
- Move 📧 Support section right after agents table
- Move 💡 Key Features before 🎯 Use Cases
- Remove 📊 Available Models section
- Move 🔐 OAuth section inside Troubleshooting
- Remove entire 🇧🇷 Portuguese duplicate section at bottom
2026-02-28 09:56:32 -03:00
diegosouzapw
9a3d72c6a2 docs: update electron/README.md, USER_GUIDE.md, FEATURES.md with desktop app docs 2026-02-28 08:33:55 -03:00
dependabot[bot]
5b9b1cdd44 chore(deps-dev): bump electron
Bumps the npm_and_yarn group with 1 update in the /electron directory: [electron](https://github.com/electron/electron).


Updates `electron` from 33.4.11 to 40.6.1
- [Release notes](https://github.com/electron/electron/releases)
- [Commits](https://github.com/electron/electron/compare/v33.4.11...v40.6.1)

---
updated-dependencies:
- dependency-name: electron
  dependency-version: 40.6.1
  dependency-type: direct:development
  dependency-group: npm_and_yarn
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-02-28 11:16:30 +00:00
445 changed files with 61927 additions and 12965 deletions

View File

@@ -0,0 +1,55 @@
---
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`.

View File

@@ -0,0 +1,78 @@
---
description: Create a new release, bump version up to 1.x.10 threshold, update changelog, and manage Pull Requests
---
# Generate Release Workflow
Bump version, finalize CHANGELOG, commit, tag, push, publish to npm, and create GitHub release.
## Steps
### 1. Determine new version
Check current version in `package.json` and increment the patch number:
```bash
grep '"version"' package.json
```
Version format: `1.x.y` — increment `y` for patch, `x` for minor (threshold: y=10 triggers x+1).
### 2. Finalize CHANGELOG.md
Replace `[Unreleased]` header with the new version and date:
```markdown
## [1.x.y] — YYYY-MM-DD
```
### 3. Bump version in package.json
```bash
sed -i 's/"version": "OLD"/"version": "NEW"/' package.json
```
### 4. Stage, commit, and tag
// 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"
```
### 5. Push to GitHub
```bash
git push origin main
git push origin vX.Y.Z
```
### 6. Publish to npm
```bash
npm publish
```
Wait for completion (prepublishOnly runs `npm run build:cli` automatically).
### 7. Create GitHub release
```bash
gh release create vX.Y.Z --title "Release vX.Y.Z" --notes-file /tmp/release_notes.md
```
### 8. Deploy to VPS (if requested)
See `/deploy-vps` workflow for Akamai VPS or use npm for local VPS:
```bash
ssh root@<VPS_IP> "npm install -g omniroute@X.Y.Z && pm2 restart omniroute"
```
## 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`

View File

@@ -0,0 +1,50 @@
---
description: How to respond to GitHub issues with insufficient information
---
# Issue Triage Workflow
Respond to GitHub issues that need more information before they can be investigated.
## Steps
### 1. Identify issues needing triage
```bash
gh issue list --state open --limit 20
```
### 2. Evaluate each issue
Check if the issue has:
- Clear reproduction steps
- Environment details (OS, Node.js version, OmniRoute version)
- Error logs/screenshots
- Expected vs actual behavior
### 3. Respond with triage template
For issues missing information:
```markdown
Thank you for reporting this issue! To help us investigate, please provide:
1. **OmniRoute version**: (`omniroute --version`)
2. **Node.js version**: (`node --version`)
3. **Operating system**: (e.g., Ubuntu 24.04, macOS 15, Windows 11)
4. **Installation method**: (npm, Docker, source)
5. **Steps to reproduce**: (exact commands/actions that trigger the issue)
6. **Error logs**: (paste relevant logs from the console)
7. **Expected behavior**: (what should happen)
This will help us debug and resolve your issue faster. 🙏
```
### 4. Label the issue
Add appropriate labels: `needs-info`, `bug`, `enhancement`, `question`, etc.
```bash
gh issue edit <NUMBER> --add-label "needs-info"
```

View File

@@ -1,12 +1,12 @@
---
description: Fetch all open GitHub issues, analyze bugs, resolve what's possible, triage the rest, then commit and release
description: Fetch all open GitHub issues, analyze bugs, resolve what's possible, triage the rest, wait for user validation, then commit and release
---
# /resolve-issues — Automated Issue Resolution Workflow
## Overview
This workflow fetches all open issues from the project's GitHub repository, classifies them, analyzes bugs, resolves what can be fixed, triages issues with insufficient information, and generates a release with all fixes.
This workflow fetches all open issues from the project's GitHub repository, classifies them, analyzes bugs, resolves what can be fixed, and triages issues with insufficient information. **It does NOT merge or release automatically** — it creates a PR and waits for user validation before merging.
## Steps
@@ -60,41 +60,61 @@ Call the `/issue-triage` workflow (located at `~/.gemini/antigravity/global_work
Proceed with resolution:
1. **Research** — Search the codebase for files related to the issue
2. **Root Cause** — Identify the root cause by reading the relevant source files
3. **Implement Fix** — Apply the fix following existing code patterns and conventions
4. **Test** — Build the project and run tests to verify the fix
5. **Commit**Commit with message format: `fix: <description> (#<issue_number>)`
1. **Create a fix branch**`git checkout -b fix/issue-<NUMBER>-<short-description>`
2. **Research** — Search the codebase for files related to the issue
3. **Root Cause** — Identify the root cause by reading the relevant source files
4. **Implement Fix** — Apply the fix following existing code patterns and conventions
5. **Test**Build the project and run tests to verify the fix
6. **Commit** — Commit with message format: `fix: <description> (#<issue_number>)`
### 5. Commit All Fixes
### 5. Generate Report & Wait for Validation
After processing all issues:
Present a summary report to the user via `notify_user` with `BlockedOnUser: true`:
- Ensure all fixes are committed with proper issue references
- Each fix should be its own commit for clean git history
| Issue | Title | Status | Action |
| ----- | ----- | ------------- | ----------------------------- |
| #N | Title | ✅ Ready | Files changed (not committed) |
| #N | Title | ❓ Needs Info | Triage comment posted |
| #N | Title | ⏭️ Skipped | Feature request / not a bug |
### 6. Close Resolved Issues
> **⚠️ IMPORTANT**: Do NOT commit, close issues, or generate releases at this step.
> Wait for the user to review the changes and respond with **OK** before proceeding.
For each successfully fixed issue:
// turbo
- If the user says **OK** or approves → Proceed to step 6
- If the user requests changes → Apply the requested adjustments first, then present the report again
- If the user rejects → Revert the changes and stop
- Close with a comment: `gh issue close <NUMBER> --repo <owner>/<repo> --comment "Fixed in <commit_hash>. The fix will be included in the next release."`
### 6. Commit & Push Fix Branch (only after user approval)
### 7. Generate Report
After the user validates:
Present a summary report to the user via `notify_user`:
- Commit each fix individually with message format: `fix: <description> (#<issue_number>)`
- Push the fix branch: `git push origin fix/issue-<NUMBER>-<short-description>`
- Create a PR: `gh pr create --title "fix: <description> (#<issue_number>)" --body "<details>" --base main`
| Issue | Title | Status | Action |
| ----- | ----- | ------------- | --------------------------- |
| #N | Title | ✅ Fixed | Commit hash |
| #N | Title | ❓ Needs Info | Triage comment posted |
| #N | Title | ⏭️ Skipped | Feature request / not a bug |
### 7. 🛑 WAIT — Notify User & Await PR Verification
### 8. Update Docs & Release
**This is a mandatory stop point.** Use `notify_user` with `BlockedOnUser: true`:
If any fixes were committed:
- Inform the user that the PR was created and is **awaiting their verification**
- Include the PR number, URL, and a summary of what was changed
- **DO NOT merge, close issues, generate releases, or deploy until the user confirms**
1. Run the `/update-docs` workflow (at `~/.gemini/antigravity/global_workflows/update-docs.md`) to update CHANGELOG and README
2. Run the `/generate-release` workflow (at `.agents/workflows/generate-release.md`) to bump version, tag, and publish
Wait for the user to respond:
- **User confirms** → Proceed to step 8
- **User requests changes** → Apply changes, push to the same branch, notify again
- **User rejects** → Close the PR and stop
### 8. Merge, Close Issues & Release (only after user confirms PR)
After the user confirms the PR:
1. **Merge** the PR: `gh pr merge <NUMBER> --merge --repo <owner>/<repo>` or via local merge
2. **Close** resolved issues with a comment: `gh issue close <NUMBER> --repo <owner>/<repo> --comment "Fixed in <commit_hash>. The fix will be included in the next release."`
3. **Switch to main**: `git checkout main && git pull`
4. Run the `/update-docs` workflow (at `~/.gemini/antigravity/global_workflows/update-docs.md`) to update CHANGELOG and README
5. Run the `/generate-release` workflow (at `.agents/workflows/generate-release.md`) to bump version, tag, and publish
6. Deploy to local VPS: `ssh root@192.168.0.15 "npm install -g omniroute@<VERSION> && pm2 restart omniroute"`
If NO fixes were committed, skip this step and just present the report.

View File

@@ -6,7 +6,7 @@ description: Analyze open Pull Requests from the project's GitHub repository, ge
## Overview
This workflow fetches all open PRs from the project's GitHub repository, performs a critical analysis of each one, generates a detailed report, and waits for user approval before proceeding with implementation.
This workflow fetches all open PRs from the project's GitHub repository, performs a critical analysis of each one, generates a detailed report, and waits for user approval before proceeding with implementation. **All improvements are committed on top of the PR branch** and the user must verify before merge.
## Steps
@@ -60,6 +60,21 @@ This workflow fetches all open PRs from the project's GitHub repository, perform
- Are edge cases covered?
- Would existing tests break?
#### 3f. Cross-Layer (Global) Analysis
Perform a **global impact assessment** to verify whether the PR changes are complete across all layers of the application:
- **Backend → Frontend check**: If the PR adds or modifies backend-only resources (new endpoints, services, data models), evaluate whether corresponding frontend changes are missing:
- Does a new endpoint require a new screen/page in the dashboard?
- Should there be a new action button, menu item, or navigation link?
- Are there new data fields that should be displayed or editable in the UI?
- Does a new feature need a toggle, configuration panel, or status indicator?
- **Frontend → Backend check**: If the PR adds frontend elements, verify the backend support exists:
- Are the required API endpoints implemented?
- Is the data model sufficient for the new UI components?
- **Cross-cutting concerns**: Check shared layers (types, DTOs, validation schemas, routes, middleware) for completeness
- **Document gaps** — If missing layers are detected, list them as **IMPORTANT** issues in the report with concrete suggestions for what should be added
### 4. Generate Report — Create a markdown report for each PR including:
- **PR Summary** — What it does, files affected, commit count
@@ -79,18 +94,52 @@ This workflow fetches all open PRs from the project's GitHub repository, perform
### 6. Implementation (if approved)
- Checkout the PR branch or apply changes locally
- Checkout the PR branch: `gh pr checkout <NUMBER>`
- Implement any required fixes identified in the analysis
- If the Cross-Layer Analysis (3f) identified missing frontend/backend counterparts, implement them
- **Commit improvements on top of the PR branch** with descriptive commit messages
- Run the project's test suite to verify nothing breaks
// turbo
- Run: `npm test` or equivalent test command
- Build the project to verify compilation
// turbo
- Run: `npm run build` or equivalent build command
- If all checks pass, prepare the merge
- Push the updated branch: `git push origin <branch-name>`
### 7. Post-Merge (if applicable)
### 7. 🛑 WAIT — Notify User & Await PR Verification
- Update CHANGELOG.md with the new feature
- Consider version bump if warranted
- Follow the `/generate-release` workflow if a release is needed
**This is a mandatory stop point.** Use `notify_user` with `BlockedOnUser: true`:
- Inform the user that the PR has been **improved and pushed**, and is **awaiting their verification**
- Include:
- PR number and URL
- Summary of improvements/fixes applied
- Build/test status
- List of files changed
- **DO NOT merge, generate releases, or deploy until the user confirms**
Wait for the user to respond:
- **User confirms** → Proceed to step 8
- **User requests more changes** → Apply changes, push to the same branch, notify again
- **User rejects** → Leave a review comment and stop
### 8. Thank the Contributor
- Post a **thank-you comment** on the PR via the GitHub API
- The message should:
- Thank the author by name/username for their contribution
- Briefly mention what the PR accomplishes and any improvements applied
- Be friendly, professional, and encouraging
- Example: _"Thanks @author for this great contribution! 🎉 The [feature/fix] is now merged and will be part of the next release. We appreciate your effort!"_
### 9. Merge & Release (only after user confirms PR)
After the user confirms the PR:
1. **Merge** the PR into main (local merge with `--no-ff` or via `gh pr merge`)
2. **Push** to main: `git push origin main`
3. **Clean up** the feature branch: `git branch -d <branch-name>`
4. **Update CHANGELOG.md** with the new feature/fix
5. Run the `/generate-release` workflow (at `.agents/workflows/generate-release.md`) to bump version, tag, and publish
6. Deploy to local VPS: `ssh root@192.168.0.15 "npm install -g omniroute@<VERSION> && pm2 restart omniroute"`

View File

@@ -0,0 +1,105 @@
---
description: How to automatically summarize recent changes and update README and CHANGELOG
---
# Update Documentation Workflow
Update CHANGELOG.md, README.md, docs/ files, and all multi-language translations whenever features are added or changed.
## Steps
### 1. Summarize recent changes
Review git log and identify new features, fixes, or changes since the last release tag:
```bash
git log $(git describe --tags --abbrev=0)..HEAD --oneline
```
### 2. Update English CHANGELOG.md
Add an `[Unreleased]` section (or version header if releasing) with:
- `### ✨ New Features` — each feature as a bullet point
- `### 🐛 Bug Fixes` — if applicable
- `### 🧪 Tests` — test count changes
- `### 📁 New Files` — table of new files with purpose
### 3. Update English README.md
Update the feature tables in these sections:
- **🧠 Routing & Intelligence** — for routing/model features
- **🛡️ Resilience & Security** — for security/resilience features
- **📊 Observability & Analytics** — for monitoring features
- **☁️ Deploy & Sync** — for deployment features
### 4. Update docs/ files
- `docs/FEATURES.md` — update the Settings section description
- `docs/API_REFERENCE.md` — add new API routes if any
- `docs/ARCHITECTURE.md` — update architecture if structural changes
### 5. 🌐 Sync Multi-Language Documentation (CRITICAL)
// turbo-all
**This step MUST be run after every README or docs update.**
The project has **30 language versions** of documentation:
**README files (root directory):**
```
README.md (English - source of truth)
README.pt-BR.md README.pt.md README.es.md README.fr.md README.it.md
README.de.md README.nl.md README.sv.md README.no.md README.da.md README.fi.md
README.ru.md README.uk-UA.md README.bg.md README.sk.md README.pl.md README.ro.md README.hu.md
README.ar.md README.he.md README.th.md README.in.md README.id.md README.ms.md README.vi.md
README.ja.md README.ko.md README.zh-CN.md README.phi.md
```
**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}/
Each contains: API_REFERENCE.md, ARCHITECTURE.md, CODEBASE_DOCUMENTATION.md, FEATURES.md, TROUBLESHOOTING.md, USER_GUIDE.md
```
**Sync approach for feature table updates:**
a. Identify which feature table rows were added to English README.md
b. For each translated README, find the corresponding anchor lines:
- **Routing section:** Find the `💬` (System Prompt) table row — the line before it is always the last routing feature. Insert new routing features before System Prompt.
- **Resilience section:** Find the `📊` Rate Limits table row (the one in lines 590-600, NOT the quota tracking one in lines 560-570). Insert new resilience features after it.
c. The new feature entries can stay in English for technical features, matching the pattern used in the existing translations.
d. Use `sed` or similar tool to batch-insert across all 29 translated READMEs.
**Verification:**
```bash
# Verify all READMEs have the new features
grep -l "NEW_FEATURE_NAME" README.*.md | wc -l
# Should return 30 (all language versions)
```
**FEATURES.md sync:**
```bash
# Update Settings description in all docs/i18n/*/FEATURES.md
for dir in docs/i18n/*/; do
# Update the Settings section description to mention new features
# Check FEATURES.md in each directory
done
```
### 6. Verify documentation changes
```bash
# Check all modified files
git status --short
# Verify no broken markdown
# Optional: run markdownlint if available
```

View File

@@ -130,6 +130,22 @@ GEMINI_CLI_OAUTH_CLIENT_SECRET=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
# IFLOW_OAUTH_CLIENT_ID=
IFLOW_OAUTH_CLIENT_SECRET=4Z3YjXycVsQvyGF1etiNlIBB4RsqSDtW
# ─────────────────────────────────────────────────────────────────────────────
# Provider User-Agent Overrides (optional — customize per-provider UA headers)
# ─────────────────────────────────────────────────────────────────────────────
# Format: {PROVIDER_ID}_USER_AGENT=custom-value
# When set, overrides the default User-Agent header sent to that provider.
# Useful when providers update versions or block old user-agents.
CLAUDE_USER_AGENT=claude-cli/1.0.83 (external, cli)
CODEX_USER_AGENT=codex-cli/0.92.0 (Windows 10.0.26100; x64)
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
CURSOR_USER_AGENT=connect-es/1.6.1
GEMINI_CLI_USER_AGENT=google-api-nodejs-client/9.15.1
# API Key Providers (Phase 1 + Phase 4)
# Add via Dashboard → Providers → Add API Key, or set here
# DEEPSEEK_API_KEY=

View File

@@ -22,6 +22,12 @@ jobs:
cache: npm
- run: npm ci
- run: npm run lint
- run: npm run check:cycles
- run: npm run check:route-validation:t06
- run: npm run check:any-budget:t11
- run: npm run check:docs-sync
- run: npm run typecheck:core
- run: npm run typecheck:noimplicit:core
security:
name: Security Audit
@@ -127,7 +133,6 @@ jobs:
cache: npm
- run: npm ci
- run: npm run test:integration
continue-on-error: true
test-security:
name: Security Tests
@@ -144,4 +149,3 @@ jobs:
cache: npm
- run: npm ci
- run: npm run test:security
continue-on-error: true

177
.github/workflows/electron-release.yml vendored Normal file
View File

@@ -0,0 +1,177 @@
name: Build Electron Desktop App
on:
push:
tags:
- "v*"
workflow_dispatch:
inputs:
version:
description: "Release version (e.g., v1.6.8)"
required: true
type: string
permissions:
contents: write
jobs:
validate:
name: Validate version
runs-on: ubuntu-latest
outputs:
version: ${{ steps.validate.outputs.version }}
steps:
- name: Checkout code
uses: actions/checkout@v6
with:
fetch-depth: 0
- name: Validate version format
id: validate
run: |
if [[ "${{ github.event_name }}" == "push" ]]; then
VERSION="${GITHUB_REF#refs/tags/}"
else
VERSION="${{ inputs.version }}"
fi
if [[ ! "$VERSION" =~ ^v[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
echo "Error: Invalid version format. Expected: v1.6.8"
exit 1
fi
echo "version=$VERSION" >> $GITHUB_OUTPUT
echo "✓ Valid version: $VERSION"
build:
name: Build Electron (${{ matrix.platform }})
needs: validate
runs-on: ${{ matrix.runner }}
strategy:
fail-fast: false
matrix:
include:
- platform: windows
runner: windows-latest
target: win
ext: .exe
- platform: macos-intel
runner: macos-latest
target: mac
ext: .dmg
- platform: macos-arm64
runner: macos-latest
target: mac
ext: -arm64.dmg
- platform: linux
runner: ubuntu-latest
target: linux
ext: .AppImage
steps:
- name: Checkout
uses: actions/checkout@v6
- name: Setup Node.js
uses: actions/setup-node@v6
with:
node-version: 22
cache: npm
- name: Cache node_modules
uses: actions/cache@v4
with:
path: node_modules
key: ${{ runner.os }}-node-${{ hashFiles('package-lock.json') }}
restore-keys: |
${{ runner.os }}-node-
- name: Install dependencies
run: npm ci
- name: Build Next.js standalone
env:
JWT_SECRET: ci-build-secret-with-sufficient-length-for-validation
run: npm run build
- name: Install Electron dependencies
working-directory: electron
run: npm install --no-audit --no-fund
- name: Build Electron for ${{ matrix.platform }}
working-directory: electron
run: npm run build:${{ matrix.target }}
- name: Collect installers
shell: bash
run: |
mkdir -p release-assets
cd electron/dist-electron
# Copy only installer files for this platform
for file in *${{ matrix.ext }}; do
[ -f "$file" ] && cp "$file" ../../release-assets/
done
# Windows: also copy portable standalone exe as OmniRoute.exe
if [ "${{ matrix.platform }}" = "windows" ]; then
for file in *.exe; do
# Skip the NSIS installer (contains "Setup")
case "$file" in *Setup*) continue ;; esac
[ -f "$file" ] && cp "$file" "../../release-assets/OmniRoute.exe" && break
done
fi
- name: Upload artifacts
uses: actions/upload-artifact@v4
with:
name: electron-${{ matrix.platform }}
path: release-assets/
release:
name: Create Release
needs: [validate, build]
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v6
with:
fetch-depth: 0
- name: Download all artifacts
uses: actions/download-artifact@v4
with:
path: release-assets
merge-multiple: true
- name: Create source archives
run: |
# Create source code archives (excluding dev dependencies and build artifacts)
export TARBALL="OmniRoute-${{ needs.validate.outputs.version }}.source.tar.gz"
export ZIPBALL="OmniRoute-${{ needs.validate.outputs.version }}.source.zip"
# Use git archive for clean source export
git archive --format=tar.gz --prefix=OmniRoute-${{ needs.validate.outputs.version }}/ HEAD -o "release-assets/$TARBALL"
git archive --format=zip --prefix=OmniRoute-${{ needs.validate.outputs.version }}/ HEAD -o "release-assets/$ZIPBALL"
echo "✓ Created source archives:"
ls -lh "release-assets/$TARBALL" "release-assets/$ZIPBALL"
- name: List release files
run: ls -la release-assets/
- name: Create Release
uses: softprops/action-gh-release@v2
with:
tag_name: ${{ needs.validate.outputs.version }}
draft: false
prerelease: false
generate_release_notes: true
files: |
release-assets/*.dmg
release-assets/*-arm64.dmg
release-assets/*.exe
release-assets/*.AppImage
release-assets/*.blockmap
release-assets/*.source.tar.gz
release-assets/*.source.zip
release-assets/OmniRoute.exe
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

14
.gitignore vendored
View File

@@ -63,6 +63,7 @@ docs/*
!docs/TASK_NEBIUS_BACKEND_ENABLEMENT.md
!docs/frontend-backend-provider-gap-report.md
!docs/openapi.yaml
!docs/RELEASE_CHECKLIST.md
!docs/PLANO-IMPLANTACAO.md
!docs/TASKS.md
!docs/FASE-*.md
@@ -103,5 +104,16 @@ app.log
# Backup directories
app.__qa_backup/
# Electron (subproject dependency lock)
# Production standalone build (created by scripts/prepublish.mjs)
# Conflicts with Next.js App Router detection in dev (root app/ shadows src/app/)
# npm publish still includes it via package.json "files" field
/app/
# Electron (subproject dependency lock and build artifacts)
electron/package-lock.json
electron/dist-electron/
electron/node_modules/
icon.iconset/
# VS Code Extension (independent Git repo)
vscode-extension/

View File

@@ -4,6 +4,7 @@
Unified AI proxy/router — route any LLM through one endpoint. Multi-provider support
(OpenAI, Anthropic, Gemini, DeepSeek, Groq, xAI, Mistral, Fireworks, Cohere, etc.)
with **MCP Server** (16 tools for agent control) and **A2A v0.3 Protocol** (Agent-to-Agent orchestration).
## Stack
@@ -13,6 +14,7 @@ Unified AI proxy/router — route any LLM through one endpoint. Multi-provider s
- **Streaming**: SSE via `open-sse` internal package
- **Styling**: Tailwind CSS v4
- **Docker**: Multi-stage Dockerfile, 3 profiles (base / cli / host)
- **i18n**: next-intl with 30 languages (`src/i18n/messages/`)
## Architecture
@@ -47,6 +49,56 @@ but the real logic lives in `src/lib/db/`.
Translation between provider formats: `open-sse/translator/`
### 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` |
- Scoped authorization (9 scopes), audit logging, Zod schemas
- IDE configs for Claude Desktop, Cursor, VS Code Copilot
### A2A Server (`src/lib/a2a/`)
Agent-to-Agent v0.3 protocol:
- JSON-RPC 2.0: `message/send`, `message/stream`, `tasks/get`, `tasks/cancel`
- Agent Card at `/.well-known/agent.json`
- Skills: `smart-routing`, `quota-management`
- SSE streaming with 15s heartbeat
- Task Manager with state machine and TTL-based cleanup
### 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 |
### OAuth & Tokens (`src/lib/oauth/`)
18 modules handling OAuth flows, token refresh, and provider credentials.
@@ -76,7 +128,7 @@ overridable via env vars or `data/provider-credentials.json`.
- No hardcoded API keys or secrets in commits
- Auth middleware on all API routes
- Input validation on user-facing endpoints
- Input validation on user-facing endpoints (Zod schemas)
- SQLite encryption key must not be logged
### Architecture
@@ -85,6 +137,7 @@ overridable via env vars or `data/provider-credentials.json`.
- Provider requests flow through `open-sse/handlers/`
- Translations use `open-sse/translator/` modules
- `localDb.ts` is re-exports only — add new functions to the proper `db/*.ts` module
- MCP and A2A pages are embedded as tabs inside `/dashboard/endpoint`, not standalone routes
### Code Quality
@@ -92,6 +145,7 @@ overridable via env vars or `data/provider-credentials.json`.
- Proper HTTP status codes
- No memory leaks in SSE streams (abort signals, cleanup)
- Rate limit headers must be parsed correctly
- All API inputs validated with Zod schemas
### Docker

View File

@@ -7,6 +7,465 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
---
## [2.0.2] — 2026-03-05
> ### 🐛 Bug Fixes & ✨ Endpoint-Aware Model Management
### 🐛 Bug Fixes
- **#212 — API Key creation crash** — Auto-generate `API_KEY_SECRET` at startup (like `JWT_SECRET`) to prevent HMAC crashes
- **#213 — Circuit breaker scope** — Changed circuit breaker key from provider-level to model-level; a 429 on one account no longer blocks all accounts for the same provider
- **#200 — Custom provider connection check** — Added connectivity fallback for OpenAI-compatible providers (Ollama, LM Studio); if `/models` and `/chat/completions` fail, a simple HTTP ping to the base URL marks the provider as connected
### ✨ New Features
- **#204 — API Format selector** — Custom models can now specify `apiFormat`: `chat-completions` (default) or `responses` (for the Responses API)
- **#205 — Combo endpoint support** — Combos now accept an `endpoint` field in the schema (`chat` | `embeddings` | `images`), enabling fallback/rotation combos for non-chat endpoints
- **#206 — Supported Endpoints mapping** — When adding custom models, users can check which endpoints the model supports (💬 Chat, 📐 Embeddings, 🖼️ Images, 🔊 Audio). Models tagged for embeddings appear in `/v1/embeddings` and models tagged for images appear in `/v1/images/generations`
- **Visual badges** — Model rows now display colored badges for non-default API formats and endpoint types
- **Model catalog metadata** — `/v1/models` response includes `api_format`, `type`, and `supported_endpoints` for custom models
### 📁 Files Changed
| File | Change |
| ------------------------------------------------------- | ------------------------------------------------ |
| `src/instrumentation.ts` | Auto-generate `API_KEY_SECRET` |
| `open-sse/services/combo.ts` | Circuit breaker keyed per-model |
| `src/lib/providers/validation.ts` | Connectivity fallback ping |
| `src/lib/db/models.ts` | `apiFormat` + `supportedEndpoints` fields |
| `src/shared/schemas/validation.ts` | `endpoint` in `comboSchema` |
| `src/shared/validation/schemas.ts` | Extended `providerModelMutationSchema` |
| `src/app/api/provider-models/route.ts` | Pass new fields through API |
| `src/app/(dashboard)/dashboard/providers/[id]/page.tsx` | API format dropdown, endpoint checkboxes, badges |
| `src/app/api/v1/models/catalog.ts` | Custom model metadata enrichment |
| `src/app/api/v1/embeddings/route.ts` | Include custom embedding models |
| `src/app/api/v1/images/generations/route.ts` | Include custom image models |
---
## [2.0.0] — 2026-03-05
> ### 🚀 Major Release — MCP Multi-Transport, A2A Protocol, Auto-Combo Engine & Full Type Safety Overhaul
>
> **OmniRoute 2.0** transforms the AI gateway into a fully **agent-controllable platform**. AI agents can now discover, orchestrate, and optimize routing through 16 MCP tools (via 3 transports: stdio, SSE, Streamable HTTP) or the A2A v0.3 protocol. Accompanied by a self-healing Auto-Combo engine, VS Code extension, consolidated Endpoints dashboard with service toggles, and a comprehensive type safety overhaul across the entire codebase.
### 🔌 MCP Multi-Transport (3 Modes)
- **stdio** — Local transport for IDE integration (Claude Desktop, Cursor, VS Code Copilot). Launched via `omniroute --mcp`
- **SSE (Server-Sent Events)** — Remote HTTP transport at `/api/mcp/sse` (GET+POST). Runs in-process inside Next.js
- **Streamable HTTP** — Modern bidirectional HTTP transport at `/api/mcp/stream` (GET+POST+DELETE). Uses `WebStandardStreamableHTTPServerTransport` singleton
- **Transport Selector UI** — When MCP is enabled, a transport picker shows all 3 modes with connection URLs and a Copy button
- **Settings Persistence** — `mcpTransport` field in settings API (enum: `stdio` | `sse` | `streamable-http`)
### 🆕 MCP Server (16 Tools)
- **8 Essential Tools** — `get_health`, `list_combos`, `get_combo_metrics`, `switch_combo`, `check_quota`, `route_request`, `cost_report`, `list_models_catalog`
- **8 Advanced Tools** — `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 permission scopes (`read:health`, `read:combos`, `read:quota`, `read:usage`, `read:models`, `execute:completions`, `write:combos`, `write:budget`, `write:resilience`) with wildcard support
- **Audit Logging** — Every tool call logged to SQLite with SHA-256 input hashing, output summarization, and duration tracking
- **IDE Configs** — MCP configuration templates for Claude Desktop, Cursor, VS Code Copilot, and stdio transport
- **Type-Safe Schemas** — All 16 tools defined with Zod input/output schemas, descriptions, and scope declarations
- 📖 **Documentation** — [`open-sse/mcp-server/README.md`](open-sse/mcp-server/README.md) with architecture, tool reference, and client examples in Python, TypeScript, and Go
### 🤖 A2A Server (Agent-to-Agent v0.3)
- **JSON-RPC 2.0** — Full router with `message/send`, `message/stream`, `tasks/get`, `tasks/cancel`
- **Agent Card** — Dynamic `/.well-known/agent.json` with 2 skills and bearer auth
- **Skills** — `smart-routing` (routing explanation, cost envelope, resilience trace, policy verdict) and `quota-management` (natural language quota queries with ranking, free combo suggestions, and full summaries)
- **SSE Streaming** — Real-time task streaming with 15s heartbeat, chunk events, and completion metadata
- **Task Manager** — State machine (`submitted``working``completed`/`failed`/`cancelled`), TTL (5min default), auto-cleanup (2× TTL)
- **Routing Logger** — Decision audit trail with 7-day retention and routing statistics
- **Task Execution** — Generic executor with proper state transitions on success/failure
- 📖 **Documentation** — [`src/lib/a2a/README.md`](src/lib/a2a/README.md) with JSON-RPC methods, skill reference, client examples, and MCP vs A2A comparison
### ⚡ Auto-Combo Engine
- **6-Factor Scoring** — Quota, health, costInv, latencyInv, taskFit, stability (normalized 0-1)
- **Task Fitness Table** — 30+ models × 6 task types with wildcard boosts
- **4 Mode Packs** — Ship Fast, Cost Saver, Quality First, Offline Friendly
- **Self-Healing** — Progressive cooldown exclusion, probe-based re-admission, incident mode (>50% OPEN)
- **Bandit Exploration** — 5% exploratory routing for discovering better providers
- **Adaptation Persistence** — EMA scoring with disk persistence every 10 decisions
- **REST API** — `POST/GET /api/combos/auto` for CRUD operations
### 🎛️ Consolidated Endpoints Dashboard
- **Tabbed Navigation** — Merged standalone Endpoint, MCP, and A2A sidebar entries into a single **"Endpoints"** page using `SegmentedControl`. Four tabs: **Endpoint Proxy**, **MCP**, **A2A**, **API Endpoints**
- **Service Enable/Disable Toggles** — MCP and A2A tabs have clickable ON/OFF toggle switches with settings persistence (default: OFF)
- **Service Status Indicators** — Inline status badges (green "Online" / red "Offline") with 30s auto-refresh
- **API Endpoints Tab** — Placeholder page with "Coming Soon" badge, listing planned features: REST API catalog, webhooks, OpenAPI/Swagger spec, and per-endpoint auth management
- **Sidebar Cleanup** — Removed standalone MCP and A2A entries; renamed "Endpoint" to "Endpoints"
### 🧩 VS Code Extension — Advanced Features
- **MCP Client** — 16 tool wrappers with REST API fallback
- **A2A Client** — Agent discovery, message send/stream, task management
- **Smart Dispatch** — Task type detection, combo recommendation, risk scoring
- **Preflight Dialog** — Risk-based display (auto-skip low, info medium, modal high)
- **Budget Guard** — Session cost tracking with status bar indicator and threshold actions
- **Mode Pack Selector** — Quick-pick UI for switching optimization profiles
- **Health Monitor** — Circuit breaker state change notifications
- **Human Checkpoint** — Multi-factor confidence evaluation with handoff dialog
### 📊 Dashboard Pages
- **MCP Dashboard** — Tool listing, usage stats, audit log with 30s auto-refresh
- **A2A Dashboard** — Agent Card display, skill listing, task history with routing metadata
- **Auto-Combo Dashboard** — Provider score bars, factor breakdown, mode pack selector, incident indicator, exclusion list
- **Error Pages** — Custom error and not-found pages for the dashboard
### 🔗 Integrations
- **OpenClaw** — Dynamic `provider.order` endpoint at `/api/cli-tools/openclaw/auto-order`
- **Configurable Tool Name Prefix** — `TOOL_NAME_PREFIX` env var for custom MCP tool naming (#199)
- **Custom RPM/TPM Rate Limits** — Per-provider rate limit overrides (#198)
- **CORS Fix** — CORS headers on early-return error responses (#208)
- **Auto-Combo Validation** — Proper validation for auto-combo CRUD operations (#209)
### 🌐 i18n (30 Languages)
- **Endpoints Namespace** — Added `endpoints` i18n namespace with tab labels, toggle labels, and API Endpoints page translations across all 30 locales
- **Sidebar & Header Updates** — Updated sidebar key from `endpoint` to `endpoints` and header breadcrumb descriptions across all 30 locales
- **Media & Themes i18n** — Added media section and combo strategy guide translations across all 30 locales
### 🔧 Code Quality & Type Safety
- **Eliminated `any` types** — Replaced `any` casts across `open-sse/` services, translators, and handlers with proper generics and explicit types
- **Zod Validation Schemas** — Added Zod-based validation for all MCP tool inputs/outputs and API validation layer
- **Shared Contracts** — Normalized quota and combos API responses with shared contracts (`src/shared/contracts/quota.ts`) for consistent data shapes across MCP, A2A, and REST APIs
- **TypeScript Translator Types** — Added strict types and modularized the translator registry with proper interfaces
- **DB Layer Hardening** — Improved database layer with proper error handling and type safety in the compliance module
- **A2A Lifecycle Safety** — Enhanced A2A task lifecycle with type-safe state transitions, preventing invalid state changes on completed tasks
- **Stream Handling** — Improved ComfyUI and stream handling with proper type safety
- **Webpack Barrel-File Fix** — Extracted `updateSettingsSchema` into dedicated `settingsSchemas.ts` to bypass webpack tree-shaking bug
- **Security Fix** — Insecure randomness fix for code scanning alert #54
### 🧪 Tests
- **E2E Test Suite** — 6 scenarios covering MCP, A2A, Auto-Combo, OpenClaw, Stress (100+50 parallel), Security
- **Unit Tests** — Essential tools (139 tests), advanced tools (141 tests), Auto-Combo engine (162 tests), A2A lifecycle regression tests
- **Schema Hardening Tests** — `t06-schema-hardening.test.mjs` (132 tests) for input validation
- **Security Tests** — `t07-no-log-key-config.test.mjs` (138 tests), `t08-mcp-scope-enforcement.test.mjs` (72 tests)
- **Integration Tests** — `v1-contracts-behavior.test.mjs` (171 tests), `security-hardening.test.mjs` (103 tests)
- **Migrated Tests to TypeScript** — E2E ecosystem tests migrated from `.mjs` to `.ts` with proper typing
- **Combo E2E Tests** — Strategy guides, advanced settings, readiness checks
### 📝 Documentation
- **AGENTS.md** — Updated to v2.0.0 with MCP multi-transport, A2A Protocol, Auto-Combo Engine, consolidated Endpoints dashboard, and Zod validation references
- **README.md** — Updated Agent & Protocol feature table with 3 transport modes, consolidated endpoints, and service toggles
- **30 Translated READMEs** — Synced feature tables across all language versions
- **CHANGELOG.md** — Comprehensive release notes covering all v1.8.1 → v2.0.0 changes
### 📁 New Files (60+)
| Directory | Files |
| :------------------------------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `open-sse/mcp-server/` | `server.ts`, `index.ts`, `audit.ts`, `scopeEnforcement.ts`, `httpTransport.ts`, `tools/advancedTools.ts`, `README.md` |
| `open-sse/mcp-server/schemas/` | `tools.ts`, `a2a.ts`, `audit.ts`, `index.ts` |
| `src/lib/a2a/` | `taskManager.ts`, `taskExecution.ts`, `streaming.ts`, `routingLogger.ts`, `README.md` |
| `src/lib/a2a/skills/` | `smartRouting.ts`, `quotaManagement.ts` |
| `src/app/a2a/` | `route.ts` (JSON-RPC 2.0 dispatch handler) |
| `src/app/api/mcp/sse/` | `route.ts` (SSE transport endpoint) |
| `src/app/api/mcp/stream/` | `route.ts` (Streamable HTTP transport endpoint) |
| `open-sse/services/autoCombo/` | `scoring.ts`, `taskFitness.ts`, `engine.ts`, `selfHealing.ts`, `modePacks.ts`, `persistence.ts`, `index.ts` |
| `src/shared/contracts/` | `quota.ts` (shared API contracts) |
| `src/shared/constants/` | `mcpScopes.ts` |
| `src/shared/validation/` | `settingsSchemas.ts` (extracted settings Zod schema) |
| `src/lib/db/migrations/` | `002_mcp_a2a_tables.sql` |
| `src/app/(dashboard)/` | `dashboard/mcp/page.tsx`, `dashboard/a2a/page.tsx`, `dashboard/auto-combo/page.tsx`, `dashboard/endpoint/ApiEndpointsTab.tsx` |
| `vscode-extension/src/services/` | `mcpClient.ts`, `a2aClient.ts`, `policyEngine.ts`, `preflightDialog.ts`, `budgetGuard.ts`, `healthMonitor.ts`, `modePackSelector.ts`, `humanCheckpoint.ts` |
| `scripts/` | `check-cycles.mjs`, `check-docs-sync.mjs`, `check-route-validation.mjs`, `check-t11-any-budget.mjs`, `run-playwright-tests.mjs`, `runtime-env.mjs` |
| `tests/` | `t06-schema-hardening.test.mjs`, `t07-no-log-key-config.test.mjs`, `t08-mcp-scope-enforcement.test.mjs`, `ecosystem.test.ts` |
| `docs/` | `mcp-server.md`, `a2a-server.md`, `auto-combo.md`, `vscode-extension.md`, `integrations/ide-configs.md`, `RELEASE_CHECKLIST.md` |
### 📝 Commit History (`features-agente-mcp-a2a` branch)
| Commit | Date | Description |
| :-------- | :--------- | :--------------------------------------------------------------------------------------- |
| `e0ddb22` | 2026-03-03 | feat: add MCP server mode with `--mcp` flag for IDE integration |
| `09a1748` | 2026-03-03 | feat: add Phase 3 advanced MCP tools and A2A smart routing skill |
| `1e1a9c9` | 2026-03-04 | feat: migrate tests to TypeScript and add MCP advanced tools test suite |
| `ab77452` | 2026-03-04 | feat: normalize quota and combos API responses with shared contracts |
| `88ad4cc` | 2026-03-04 | feat: add MCP server, A2A protocol, auto-combo engine & VS Code extension |
| `cc429d4` | 2026-03-04 | feat: add TypeScript types and modularize translator registry |
| `adc8fdf` | 2026-03-04 | feat: add A2A protocol support and refactor API validation layer |
| `500cae3` | 2026-03-04 | refactor: replace `any` types with generics and add Zod validation schemas |
| `889e2ba` | 2026-03-04 | feat: add error pages, harden DB layer and compliance module |
| `cbd0b1c` | 2026-03-04 | refactor: harden open-sse services, eliminate any casts, add dashboard pages |
| `b33a853` | 2026-03-04 | feat: Introduce A2A lifecycle management, add type safety to ComfyUI and stream handling |
| `a1a2610` | 2026-03-04 | feat: v2.0.0 - MCP server, A2A agent, proxy improvements and docs update |
| `d615ca5` | 2026-03-05 | feat: configurable tool name prefix (#199) and custom rpm/tpm rate limits (#198) |
| `6d8868b` | 2026-03-05 | fix: extract validation helpers to fix webpack barrel-file resolution bug |
| `bc2e60c` | 2026-03-05 | feat: Introduce new A2A and MCP API routes, enhance dashboard UI, E2E tests |
| `79c23df` | 2026-03-05 | feat: Add i18n for media/themes, enhance combos with strategy guides, E2E tests |
| `2490ba5` | 2026-03-05 | feat: Introduce combo readiness checks and strategy recommendations |
| `48dda26` | 2026-03-05 | fix: CORS headers on early-return error responses + auto-combo validation (#208, #209) |
| `078a42b` | 2026-03-05 | feat: consolidate Endpoint, MCP, A2A into tabbed Endpoints page |
| `6f1e6a0` | 2026-03-05 | feat: add MCP/A2A enable/disable toggle switches on Endpoints page |
| `bb9d85b` | 2026-03-05 | fix: extract updateSettingsSchema to bypass webpack barrel-file bug |
| `cc7e1a0` | 2026-03-05 | feat: add MCP multi-transport (stdio + SSE + Streamable HTTP) |
---
## [1.8.1] — 2026-03-03
### 🐛 Bug Fixes
- **Usage API Proxy Support** — Quota/usage fetch calls (`/api/usage/[connectionId]`) now route through the dashboard-configured proxy (Global → Provider → Key level). Previously, usage fetchers used bare `fetch()` which bypassed the Global Proxy setting, causing "fetch failed" errors in Docker deployments behind a proxy. Fixes #194
## [1.8.0] — 2026-03-03
### 🐛 Bug Fixes
- **Empty `tool_use.name` Validation** — Fixed intermittent HTTP 400 errors when using Claude Code through OmniRoute. Assistant messages with empty `tool_use.name` fields (from interrupted tool calls or malformed history) are now validated and filtered at two layers: the `openai-to-claude` request translator and the `prepareClaudeRequest` sanitizer. Fixes #191
- **Windows Electron Release** — Fixed the "Collect installers" step failing in every Windows build since v1.7.5+. `electron-builder` produces versioned portable exe filenames (e.g., `OmniRoute 1.6.9.exe`), not the hardcoded `OmniRoute.exe` the workflow expected. Now finds the portable exe dynamically by pattern. PR #190 by @benzntech
## [1.7.14] — 2026-03-02
### 🐛 Bug Fixes
- **Responses SSE Passthrough** — Passthrough mode is now format-aware: Responses SSE payloads (`response.*` type) skip Chat Completions-specific sanitization (`sanitizeStreamingChunk`, `fixInvalidId`, `hasValuableContent`), preventing potential stream corruption for Responses-native clients. Usage extraction still works for both formats. Fixes #186
### ✨ Features
- **Blackbox AI Dashboard** — Added blackbox.ai provider to the dashboard frontend (providers page, pricing, models endpoint). Completes #175
## [1.7.11] — 2026-03-02
### ✨ Features
- **Blackbox AI Provider** — Added blackbox.ai as a new OpenAI-compatible provider with 6 default models (GPT-4o, Gemini 2.5 Flash, Claude Sonnet 4, DeepSeek V3, Blackbox AI, Blackbox AI Pro) and provider logo. Fixes #175
### 🐛 Bug Fixes
- **Antigravity 404 Error** — Added warning logs when `generateProjectId()` generates a fallback project ID because `credentials.projectId` is null. The executor now prefers the translator-set `body.project` before generating a new fallback, eliminating duplicate warnings and ID mismatch. Fixes #176. Includes improvements from PRs #184 and #185
## [1.7.10] — 2026-03-02
### 🐛 Bug Fixes
- **Streaming Tool Calls (Responses→ChatCompletions)** — Fixed two issues in the `openaiResponsesToOpenAIResponse` translator that broke tool call execution in agentic clients (OpenCode, Claude Code, Cursor, etc.): (1) Argument delta chunks now include `tool_calls[].id` and `type: "function"` so clients can associate argument fragments correctly. (2) `finish_reason` is now `"tool_calls"` instead of hardcoded `"stop"` when tool calls occurred. Fixes #180
## [1.7.9] — 2026-03-02
### 🐛 Bug Fixes
- **Electron CI Build** — Added `JWT_SECRET` environment variable to the Electron release workflow `Build Next.js standalone` step, fixing build failures in GitHub Actions. PR #178 by @benzntech
### 📝 Documentation
- **README** — Updated OpenClaw link from `cline/cline` to `openclaw/openclaw` to reflect the project rename. PR #179 by @MAINER4IK
## [1.7.8] — 2026-03-02
### ✨ New Features
- **Theme Color Customization** — Users can now select from 7 preset accent colors (Coral, Blue, Red, Green, Violet, Orange, Cyan) or define a custom color via color picker/hex input. The chosen color dynamically updates `--color-primary` and `--color-primary-hover` CSS variables across the entire UI. PR #174 by @mainer4ik
### 🌐 Multi-Language Sync
- **Theme & Media i18n** — Added `themeCoral`, `themeBlue`, `themeRed`, `themeGreen`, `themeViolet`, `themeOrange`, `themeCyan`, `themeAccent`, `themeAccentDesc`, `themeCustom`, `themeCreate`, and media section translations across all **30 language locales**
### 🔧 Code Quality (Review Improvements)
- Exported `COLOR_THEMES` constant from `themeStore.ts` for DRY reuse
- Added hex color validation with visual feedback (red border + disabled apply button)
- Synced local state via Zustand `subscribe` pattern for cross-tab consistency
- Removed dead `/themes` route from Header.tsx
- Added CSS `color-mix()` fallback for older browsers
## [1.7.7] — 2026-03-02
### 🐛 Bug Fixes
- **Gemini Tool Schema Sanitization** — The standard Gemini provider now sanitizes OpenAI tool schemas before forwarding to Gemini API, removing unsupported JSON Schema keywords (`additionalProperties`, `$schema`, `const`, `default`, `not`, etc.). Previously, sanitization only ran in the CLI executor path, causing Gemini to reject tool calls when schemas contained unsupported constraints. Also applied sanitization to `response_format.json_schema`. Fixes #173
## [1.7.6] — 2026-03-02
### 🐛 Bug Fixes
- **Cloud Proxy `undefined/v1` Fix** — When the `NEXT_PUBLIC_CLOUD_URL` environment variable is not set (common in Docker deployments), the endpoint page now correctly falls back instead of showing `undefined/v1`. The cloud sync API now returns `cloudUrl` in its response so the frontend can use it dynamically. Fixes #171
### ✨ New Features
- **Cloud Worker `/v1/models` Endpoint** — The Cloud Worker now supports the `/v1/models` endpoint for both URL formats (`/v1/models` and `/{machineId}/v1/models`), returning all available models synced from the local OmniRoute instance
### 🔧 Infrastructure
- **Cloudflare Workers Compatibility** — Fixed `setInterval` in global scope issue in `accountFallback.ts` that blocked Cloud Worker deployment. Lazy initialization pattern ensures compatibility with Cloudflare Workers runtime restrictions
## [1.7.5] — 2026-03-02
### 🐛 Bug Fixes
- **OAuth Re-Auth Duplicate Fix** — Re-authenticating an expired OAuth connection now updates the existing connection instead of creating a duplicate entry. When re-auth is triggered, the system matches by `provider` + `email` + `authType` and refreshes tokens in-place. Fixes #170
## [1.7.4] — 2026-03-01
### ✨ New Features
- **OpenCode CLI Integration** — Added full integration guide for [OpenCode](https://opencode.ai) AI CLI tool using `@ai-sdk/openai-compatible` adapter with custom `opencode.json` config. Resolves #169
- **Endpoint Page Restructured** — Reorganized the Endpoint dashboard page into 3 grouped categories (Core APIs, Media & Multi-Modal, Utility & Management) with visual dividers. Added 2 new endpoint sections: **Responses API** (`/v1/responses`) and **List Models** (`/v1/models`)
- **Model Aliases & Background Degradation i18n** — Added 14 translated settings keys and 7 translated endpoint keys across all **30 language locales**. Fixed missing translations showing raw keys like `settings.modelAliasesTitle` in the UI
### 🌐 Multi-Language Sync
- **30 README translations synced** — All 28 translated READMEs updated with v1.7.3 feature entries (Model Aliases, Background Degradation, Rate Limit Persistence, Token Refresh Resilience)
- **6 docs/i18n FEATURES.md updated** — Settings description expanded in da, it, nl, phi, pl, sv
### 📁 New Files
| File | Purpose |
| --------------------------------------- | ----------------------------------------------------------- |
| `.agents/workflows/update-docs.md` | Documentation update workflow with multi-language sync step |
| `.agents/workflows/generate-release.md` | Release generation workflow (version bump, npm, GitHub) |
| `.agents/workflows/issue-triage.md` | Issue triage workflow for issues with insufficient info |
## [1.7.3] — 2026-03-01
### ✨ New Features
- **Model Deprecation Auto-Forward** — New `modelDeprecation.ts` service with 10+ built-in aliases for legacy Gemini, Claude, and OpenAI models. Deprecated model IDs (e.g., `gemini-pro`, `claude-2`) are automatically forwarded to their current replacements. Custom aliases configurable via new Settings → Routing → Model Aliases UI tab with full CRUD API (`/api/settings/model-aliases`)
- **Background Task Smart Degradation** — New `backgroundTaskDetector.ts` service detects background/utility requests (title generation, summarization, etc.) via 19 system prompt patterns and `X-Request-Priority` header, and automatically reroutes them to cheaper models. Configurable degradation map and detection patterns via new Settings → Routing → Background Degradation UI tab. Disabled by default (opt-in)
- **Rate Limit Persistence** — Learned rate limits from API response headers are now persisted to SQLite with 60-second debouncing and restored on startup (24h staleness filter). Rate limits survive server restarts instead of being lost in memory
- **thinkingLevel String Conversion** — `applyThinkingBudget()` now handles string-based `thinkingLevel` inputs (`"high"`, `"medium"`, `"low"`, `"none"`) by converting them to numeric token budgets. Supports `thinkingLevel`, `thinking_level`, and Gemini's `generationConfig.thinkingConfig.thinkingLevel` fields
- **Claude -thinking Model Auto-Injection** — Models ending with `-thinking` suffix (e.g., `claude-opus-4-6-thinking`) automatically get thinking parameters injected to prevent API errors. `hasThinkingCapableModel()` updated to recognize these suffixes
- **Gemini 3.0/3.1 Model Registry** — Updated provider registry to explicitly distinguish Gemini 3.1 (Pro, Flash) from 3.0 Preview variants across `gemini`, `gemini-cli`, and `antigravity` providers with clear naming conventions
- **Token Refresh Circuit Breaker** — Per-provider circuit breaker in `refreshWithRetry()`: 5 consecutive failures trigger a 30-minute cooldown to prevent infinite retry loops. Added 30-second timeout wrapper per refresh attempt. Exported `isProviderBlocked()` and `getCircuitBreakerStatus()` for diagnostics
### 🧪 Tests
- **40+ new unit tests** across 3 files: `model-deprecation.test.mjs` (14 tests), `background-task-detector.test.mjs` (14 tests), extended `thinking-budget.test.mjs` (+13 tests). Total suite: **561 tests, 0 failures**
### 📁 New Files
| File | Purpose |
| ---------------------------------------------------------------------- | --------------------------------------------------------------------- |
| `open-sse/services/modelDeprecation.ts` | Model deprecation alias resolver with built-in + custom aliases |
| `open-sse/services/backgroundTaskDetector.ts` | Background task detection with pattern matching and model degradation |
| `src/app/api/settings/model-aliases/route.ts` | CRUD API for model alias management |
| `src/app/api/settings/background-degradation/route.ts` | API for background degradation config |
| `src/app/(dashboard)/settings/components/ModelAliasesTab.tsx` | Settings UI for model alias management |
| `src/app/(dashboard)/settings/components/BackgroundDegradationTab.tsx` | Settings UI for background degradation |
| `tests/unit/model-deprecation.test.mjs` | 14 unit tests for model deprecation |
| `tests/unit/background-task-detector.test.mjs` | 14 unit tests for background task detection |
---
## [1.7.2] — 2026-03-01
### ✨ New Features
- **Multi-Modal Provider Support** — Added 6 TTS providers (ElevenLabs, Nvidia NIM, HuggingFace, Coqui, Tortoise, Qwen3), 3 STT providers, 2 image providers (SD WebUI, ComfyUI), and two new modalities: `/v1/videos/generations` (Text-to-Video) and `/v1/music/generations` (Text-to-Music). Shared abstractions via `registryUtils.ts` and `comfyuiClient.ts` ([PR #167](https://github.com/diegosouzapw/OmniRoute/pull/167) by @ken2190)
- **Media Playground Page** — New dashboard page at `/dashboard/media` with tabbed interface (Image/Video/Music), model selector, prompt input, and JSON result viewer
- **Unit Tests for Registry Utils** — 24 tests covering `parseModelFromRegistry`, `getAllModelsFromRegistry`, `buildAuthHeaders`, and integration with video/music registries
- **WFGY 16-Problem RAG Failure Map** — Added troubleshooting reference for RAG/LLM failure taxonomy in `docs/TROUBLESHOOTING.md` ([PR #164](https://github.com/diegosouzapw/OmniRoute/pull/164) by @onestardao)
### 🐛 Fixed
- **Gemini Imported Models Return 404** — Strip `models/` prefix from Gemini model IDs during import to prevent doubled paths ([#163](https://github.com/diegosouzapw/OmniRoute/issues/163))
- **Pino File Transport Fails in Next.js Production** — Log actual error + add sync `pino.destination()` fallback ([#165](https://github.com/diegosouzapw/OmniRoute/issues/165))
- **Windows Electron CI Build** — Added `shell: bash` to Collect installers step for Windows runners ([PR #168](https://github.com/diegosouzapw/OmniRoute/pull/168) by @benzntech)
- **TypeScript Safety** — Replaced `Record<string, any>` with `Record<string, unknown>` in `registryUtils.ts`
---
## [1.7.1] — 2026-02-28
### 🐛 Fixed
- **Dashboard Layout Breakage** — Tailwind CSS v4 auto-detection failed to scan Next.js route group directories with parentheses (e.g. `(dashboard)`), causing all responsive grid utilities (`sm:grid-cols-*`, `md:grid-cols-*`, `lg:grid-cols-*`, `xl:grid-cols-*`) to be purged from production CSS. Cards displayed in a single column instead of multi-column grids. Fixed by adding explicit `@source` directives in `globals.css`
---
## [1.7.0] — 2026-02-28
### ✨ New Features
- **16 Pain Points Documentation** — New collapsible section "🎯 What OmniRoute Solves — 16 Real Pain Points" added to the main README and all 29 language-specific READMEs. Each pain point uses `<details>/<summary>` tags for clean, expandable content
- **Configurable User-Agent per Provider** — User-Agent strings for OAuth providers (Claude, Codex, GitHub, Antigravity, Kiro, iFlow, Qwen, Cursor, Gemini CLI) are now configurable via environment variables. Format: `{PROVIDER_ID}_USER_AGENT=custom-value` ([#155](https://github.com/diegosouzapw/OmniRoute/issues/155))
### 🐛 Fixed
- **Hardcoded `$HOME` Path in Standalone/Bun Builds** — 5 files (`backupService.ts`, `mitm/manager.ts`, `mitm/server.ts`, `mitm/cert/generate.ts`, `codex-profiles/route.ts`) were bypassing the centralized `dataPaths.ts` and using `os.homedir()` directly. This caused paths to bake the build machine's `$HOME` into standalone/bun builds, producing `EACCES: permission denied` errors on other machines. All files now use `resolveDataDir()` from `dataPaths.ts`, respecting `DATA_DIR` env var and XDG conventions ([#156](https://github.com/diegosouzapw/OmniRoute/issues/156))
### 📝 Documentation
- **`.env` and `.env.example` Synced** — Added 9 User-Agent env vars with latest known default values to both environment files
- **30 README Translations Updated** — All language READMEs now include the 16 Pain Points section
---
## [1.6.9] — 2026-02-28
### 🐛 Fixed
- **Proxy Port Preservation** — `new URL()` silently strips default ports (80/443); proxy connections now extract the port from the raw URL string before parsing, preventing connection timeouts ([PR #161](https://github.com/diegosouzapw/OmniRoute/pull/161))
- **Proxy Credential Encoding** — URL-encode special characters in proxy username/password; decode during legacy migration ([PR #161](https://github.com/diegosouzapw/OmniRoute/pull/161))
- **HTTPS Proxy Default Port** — Changed from 8080 to 443 in frontend and migration logic ([PR #161](https://github.com/diegosouzapw/OmniRoute/pull/161))
- **Proxy Dispatcher Cache** — Invalidate cached dispatchers when proxy config is updated or deleted ([PR #161](https://github.com/diegosouzapw/OmniRoute/pull/161))
- **Proxy Logger SQLite Type** — Cast `proxyPort` to `Number` for INTEGER column ([PR #161](https://github.com/diegosouzapw/OmniRoute/pull/161))
- **CopilotToolCard URL** — Use `baseUrl` prop directly instead of redundant `window.location.origin`; filter to chat models only (`!m.type && !m.parent`) ([PR #160](https://github.com/diegosouzapw/OmniRoute/pull/160))
---
## [1.6.8] — 2026-02-28
### 🔧 Improved
- **Electron Release Workflow** — Refactored CI to trigger on git tags (`v*`) + manual dispatch, with version validation, artifact upload/download pattern across 3 platforms, and a single release job. Only installer files (`.dmg`, `.exe`, `.AppImage`) are uploaded — no more 5K+ unpacked files ([PR #159](https://github.com/diegosouzapw/OmniRoute/pull/159))
- **Windows Portable Exe** — Added standalone portable `.exe` build alongside the NSIS installer ([PR #159](https://github.com/diegosouzapw/OmniRoute/pull/159))
- **Source Code Archives** — Releases now include `OmniRoute-vX.Y.Z.source.tar.gz` and `.zip` via `git archive` ([PR #159](https://github.com/diegosouzapw/OmniRoute/pull/159))
- **Installation Docs** — Added platform-specific installation instructions with macOS Gatekeeper workaround ([PR #159](https://github.com/diegosouzapw/OmniRoute/pull/159))
### 🐛 Fixed
- **Next.js App Router Conflict** — Added `app/` (production standalone build) to `.gitignore`. This directory was conflicting with Next.js App Router detection in dev mode, causing all routes to return 404
- **Git Tracking** — Added `electron/node_modules/` to `.gitignore`
---
## [1.6.7] — 2026-02-28
### ✨ New Feature
- **GitHub Copilot Configuration Generator** — New tool on the CLI Tools dashboard page. Select models and generate the `chatLanguageModels.json` config block for VS Code GitHub Copilot using the Azure vendor pattern. Features: bulk model selection from `/v1/models` (includes combos/custom), search/filter, configurable tokens/tool-calling/vision, one-click copy, persistent selection via localStorage. Version compatibility warning for VS Code ≥ 1.109 / Copilot Chat ≥ v0.37 ([#142](https://github.com/diegosouzapw/OmniRoute/issues/142))
### 🧹 Housekeeping
- Added `electron/dist-electron/` to `.gitignore` (build artifact)
---
## [1.6.6] — 2026-02-28
### 🔒 Security Fix
- **Auth bypass after onboarding** — Fixed regression where users could access the dashboard without authentication after upgrading from older versions. The "no password" safeguard (for fresh installs) was incorrectly firing after onboarding was complete, allowing unauthenticated access when `setupComplete=true` but the password DB row was missing ([#151](https://github.com/diegosouzapw/OmniRoute/issues/151))
---
## [1.6.5] — 2026-02-28
### 🖥️ Electron Desktop
- **Official app icons** — Added proper platform-specific icons derived from the OmniRoute SVG logo: `.icns` (macOS), `.ico` (Windows), `.png` (Linux), and `tray-icon.png` (32×32) — via PR [#154](https://github.com/diegosouzapw/OmniRoute/pull/154)
- **Automated release workflow** — New GitHub Actions workflow (`electron-release.yml`) builds Electron for Windows/macOS/Linux on every GitHub release publish
- **CI fix** — Changed `npm ci``npm install` in the Electron build step since `electron/package-lock.json` is `.gitignored`
### 📖 Documentation
- **Desktop App section** — Added to all 30 README files (9 fully translated: PT-BR, ES, FR, DE, ZH-CN, JA, RU, KO, AR)
- **Electron Fix Plan** — Published detailed code review and fix documentation at `docs/ELECTRON_FIX_PLAN.md`
### 🐛 Issue Triage
- **#151** — Auth bypass after v1.6.3 upgrade — triaged, requesting more info from reporter
- **#142** — Copilot Config Generator — previously triaged, 5 comments
---
## [1.6.4] — 2026-02-28
### 🖥️ Electron Desktop — Code Review Hardening (16 Fixes)

View File

@@ -2,6 +2,7 @@ FROM node:22-bookworm-slim AS builder
WORKDIR /app
COPY package*.json ./
COPY scripts/postinstall.mjs ./scripts/postinstall.mjs
RUN if [ -f package-lock.json ]; then npm ci --no-audit --no-fund; else npm install --no-audit --no-fund; fi
COPY . ./

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -110,6 +110,35 @@ _Conecta cualquier IDE o herramienta CLI con IA a través de OmniRoute — gatew
---
## 🖼️
<div align="center">
<img src="./docs/screenshots/MainOmniRoute.png" alt="OmniRoute" width="800"/>
</div>
---
## 📸
<details>
<summary><b>...</b></summary>
| # | # |
| ----- | ---------------------------------------- |
| **1** | ![1](docs/screenshots/01-providers.png) |
| **2** | ![2](docs/screenshots/02-combos.png) |
| **3** | ![3](docs/screenshots/03-analytics.png) |
| **4** | ![4](docs/screenshots/04-health.png) |
| **5** | ![5](docs/screenshots/05-translator.png) |
| **6** | ![6](docs/screenshots/06-settings.png) |
| **7** | ![7](docs/screenshots/07-cli-tools.png) |
| **8** | ![8](docs/screenshots/08-usage.png) |
| **9** | ![9](docs/screenshots/09-endpoint.png) |
</details>
---
## 🤔 ¿Por qué OmniRoute?
**Deja de desperdiciar dinero y chocar con límites:**
@@ -128,6 +157,18 @@ _Conecta cualquier IDE o herramienta CLI con IA a través de OmniRoute — gatew
---
## 📧 Soporte
> 💬 **¡Únete a la comunidad!** [Grupo WhatsApp](https://chat.whatsapp.com/JI7cDQ1GyaiDHhVBpLxf8b?mode=gi_t) — Obtén ayuda, comparte consejos y mantente al día.
- **Website**: [omniroute.online](https://omniroute.online)
- **GitHub**: [github.com/diegosouzapw/OmniRoute](https://github.com/diegosouzapw/OmniRoute)
- **Issues**: [github.com/diegosouzapw/OmniRoute/issues](https://github.com/diegosouzapw/OmniRoute/issues)
- **WhatsApp**: [Grupo de la Comunidad](https://chat.whatsapp.com/JI7cDQ1GyaiDHhVBpLxf8b?mode=gi_t)
- **Proyecto Original**: [9router por decolua](https://github.com/decolua/9router)
---
## 🔄 Cómo Funciona
```
@@ -157,6 +198,497 @@ Resultado: Nunca dejes de programar, costo mínimo
---
## 🎯 Lo que resuelve OmniRoute: 30 puntos débiles reales y casos de uso
> **Todos los desarrolladores que utilizan herramientas de IA se enfrentan a estos problemas a diario.** OmniRoute se creó para resolverlos todos: desde sobrecostos hasta bloqueos regionales, desde flujos rotos de OAuth hasta operaciones de protocolo y observabilidad empresarial.
<details>
<summary><b>💸 1. "Pago una suscripción costosa pero aún así me interrumpen los límites"</b></summary>
Los desarrolladores pagan entre 20 y 200 dólares al mes por Claude Pro, Codex Pro o GitHub Copilot. Incluso pagando, la cuota tiene un límite: 5 horas de uso, límites semanales o límites de tarifa por minuto. A mitad de la sesión de codificación, el proveedor deja de responder y el desarrollador pierde flujo y productividad.
**Cómo lo resuelve OmniRoute:**
- **Reserva inteligente de 4 niveles**: si se agota la cuota de suscripción, se redirige automáticamente a la clave API → Barato → Gratis sin intervención manual
- **Seguimiento de cuotas en tiempo real**: muestra el consumo de tokens en tiempo real con cuenta regresiva de reinicio (5 h, diario, semanal)
- **Soporte multicuenta**: varias cuentas por proveedor con rotación automática: cuando una se agota, cambia a la siguiente
- **Combinaciones personalizadas**: cadenas de respaldo personalizables con 6 estrategias de equilibrio (completar primero, por turnos, P2C, aleatoria, menos utilizada, de costo optimizado)
- **Cuotas comerciales de Codex**: monitoreo de cuotas del espacio de trabajo empresarial/de equipo directamente en el panel
</details>
<details>
<summary><b>🔌 2. "Necesito usar varios proveedores pero cada uno tiene una API diferente"</b></summary>
OpenAI usa un formato, Claude (Anthropic) usa otro, Gemini otro más. Si un desarrollador quiere probar modelos de diferentes proveedores o recurrir a ellos, debe reconfigurar los SDK, cambiar los puntos finales y lidiar con formatos incompatibles. Los proveedores personalizados (FriendLI, NIM) tienen puntos finales de modelo no estándar.
**Cómo lo resuelve OmniRoute:**
- **Punto final unificado**: un único `http://localhost:20128/v1` sirve como proxy para los más de 36 proveedores
- **Traducción de formato**: automática y transparente: OpenAI ↔ Claude ↔ Gemini ↔ API de respuestas
- **Desinfección de respuesta**: elimina los campos no estándar (`x_groq`, `usage_breakdown`, `service_tier`) que interrumpen OpenAI SDK v1.83+
- **Normalización de roles**: convierte `developer``system` para proveedores que no son OpenAI; `system``user` para GLM/ERNIE
- **Think Tag Extraction**: extrae bloques `<think>` de modelos como DeepSeek R1 en `reasoning_content` estandarizado.
- **Salida estructurada para Gemini** — `json_schema``responseMimeType`/`responseSchema` conversión automática
- **`stream` por defecto es `false`**: se alinea con las especificaciones de OpenAI, evitando SSE inesperado en los SDK de Python/Rust/Go
</details>
<details>
<summary><b>🌐 3. "Mi proveedor de IA bloquea mi región/país"</b></summary>
Proveedores como OpenAI/Codex bloquean el acceso desde ciertas regiones geográficas. Los usuarios obtienen errores como `unsupported_country_region_territory` durante las conexiones OAuth y API. Esto resulta especialmente frustrante para los desarrolladores de los países en desarrollo.
**Cómo lo resuelve OmniRoute:**
- **Configuración de proxy de 3 niveles**: Proxy configurable en 3 niveles: global (todo el tráfico), por proveedor (un solo proveedor) y por conexión/clave.
- **Insignias de proxy codificadas por colores** — Indicadores visuales: 🟢 proxy global, 🟡 proxy de proveedor, 🔵 proxy de conexión, que siempre muestra la IP
- **Intercambio de tokens de OAuth a través de proxy**: el flujo de OAuth también pasa a través del proxy, lo que resuelve `unsupported_country_region_territory`
- **Pruebas de conexión a través de proxy**: las pruebas de conexión utilizan el proxy configurado (no más derivación directa)
- **Soporte SOCKS5**: soporte completo de proxy SOCKS5 para enrutamiento saliente
- **Suplantación de huellas dactilares TLS**: huella digital TLS similar a la de un navegador a través de `wreq-js` para evitar la detección de bots.
</details>
<details>
<summary><b>🆓 4. "Quiero usar IA para codificar pero no tengo dinero"</b></summary>
No todo el mundo puede pagar entre 20 y 200 dólares al mes por suscripciones a IA. Los estudiantes, desarrolladores de países emergentes, aficionados y autónomos necesitan acceso a modelos de calidad sin costo alguno.
**Cómo lo resuelve OmniRoute:**
- **Proveedores de nivel gratuito integrados**: soporte nativo para proveedores 100% gratuitos: iFlow (8 modelos ilimitados), Qwen (3 modelos ilimitados), Kiro (Claude gratis), Gemini CLI (180K/mes gratis)
- **Combos solo gratuitos**: cadena `gc/gemini-3-flash → if/kimi-k2-thinking → qw/qwen3-coder-plus` = $0/mes sin tiempo de inactividad
- **Créditos gratuitos NVIDIA NIM**: 1000 créditos gratuitos integrados
- **Estrategia de optimización de costos**: estrategia de enrutamiento que elige automáticamente el proveedor más barato disponible
</details>
<details>
<summary><b>🔒 5. "Necesito proteger mi puerta de enlace AI del acceso no autorizado"</b></summary>
Al exponer una puerta de enlace de IA a la red (LAN, VPS, Docker), cualquiera con la dirección puede consumir los tokens/cuota del desarrollador. Sin protección, las API son vulnerables al mal uso, la inyección rápida y el abuso.
**Cómo lo resuelve OmniRoute:**
- **Administración de claves API**: generación, rotación y alcance por proveedor con una página `/dashboard/api-manager` dedicada
- **Permisos a nivel de modelo**: restrinja las claves API a modelos específicos (`openai/*`, patrones comodín), con la opción Permitir todo/Restringir
- **API Endpoint Protection**: requiere una clave para `/v1/models` y bloquea proveedores específicos del listado
- **Auth Guard + Protección CSRF**: todas las rutas del panel protegidas con middleware `withAuth` + tokens CSRF
- **Limitador de velocidad**: limitación de velocidad por IP con ventanas configurables
- **Filtrado de IP**: lista permitida/lista bloqueada para control de acceso
- **Prompt injection guard**: desinfección contra patrones de avisos maliciosos
- **Cifrado AES-256-GCM**: credenciales cifradas en reposo
</details>
<details>
<summary><b>🛑 6. "Mi proveedor dejó de funcionar y perdí mi flujo de codificación"</b></summary>
Los proveedores de IA pueden volverse inestables, devolver errores 5xx o alcanzar límites de velocidad temporales. Si un desarrollador depende de un solo proveedor, se le interrumpe. Sin disyuntores, los reintentos repetidos pueden bloquear la aplicación.
**Cómo lo resuelve OmniRoute:**
- **Disyuntor por proveedor**: apertura/cierre automático con umbrales configurables y enfriamiento (cerrado/abierto/medio abierto)
- **Retroceso exponencial**: retrasos progresivos en los reintentos
- **Anti-Thundering Herd** — Mutex + protección de semáforo contra tormentas de reintentos simultáneos
- **Cadenas alternativas combinadas**: si el proveedor principal falla, automáticamente pasa por la cadena sin intervención.
- **Disyuntor combinado**: desactiva automáticamente los proveedores defectuosos dentro de una cadena combinada
- **Panel de estado**: monitoreo del tiempo de actividad, estados de disyuntores, bloqueos, estadísticas de caché, latencia p50/p95/p99
</details>
<details>
<summary><b>🔧 7. "Configurar cada herramienta de IA es tedioso y repetitivo"</b></summary>
Los desarrolladores utilizan Cursor, Claude Code, Codex CLI, OpenClaw, Gemini CLI, Kilo Code... Cada herramienta necesita una configuración diferente (punto final API, clave, modelo). Reconfigurar al cambiar de proveedor o modelo es una pérdida de tiempo.
**Cómo lo resuelve OmniRoute:**
- **Panel de herramientas CLI**: página dedicada con configuración con un solo clic para Claude Code, Codex CLI, OpenClaw, Kilo Code, Antigravity, Cline
- **Generador de configuración de GitHub Copilot**: genera `chatLanguageModels.json` para código VS con selección de modelo masivo
- **Asistente de incorporación**: configuración guiada de 4 pasos para usuarios nuevos
- **Un punto final, todos los modelos**: configure `http://localhost:20128/v1` una vez, acceda a más de 36 proveedores
</details>
<details>
<summary><b>🔑 8. "Administrar tokens OAuth de múltiples proveedores es un infierno"</b></summary>
Claude Code, Codex, Gemini CLI, Copilot: todos usan OAuth 2.0 con tokens que caducan. Los desarrolladores necesitan volver a autenticarse constantemente, lidiar con `client_secret is missing`, `redirect_uri_mismatch` y fallas en servidores remotos. OAuth en LAN/VPS es particularmente problemático.
**Cómo lo resuelve OmniRoute:**
- **Actualización automática de tokens**: los tokens de OAuth se actualizan en segundo plano antes de que caduquen
- **OAuth 2.0 (PKCE) integrado**: flujo automático para Claude Code, Codex, Gemini CLI, Copilot, Kiro, Qwen, iFlow
- **OAuth multicuenta**: varias cuentas por proveedor mediante extracción de token JWT/ID
- **OAuth LAN/Remote Fix** — Detección de IP privada para `redirect_uri` + modo URL manual para servidores remotos
- **OAuth detrás de Nginx**: utiliza `window.location.origin` para compatibilidad con proxy inverso
- **Guía remota de OAuth**: guía paso a paso para las credenciales de Google Cloud en VPS/Docker
</details>
<details>
<summary><b>📊 9. "No sé cuánto estoy gastando ni dónde"</b></summary>
Los desarrolladores utilizan múltiples proveedores pagos pero no tienen una visión unificada del gasto. Cada proveedor tiene su propio panel de facturación, pero no hay una vista consolidada. Los costos inesperados pueden acumularse.
**Cómo lo resuelve OmniRoute:**
- **Panel de análisis de costos**: seguimiento de costos por token y gestión de presupuesto por proveedor
- **Límites de presupuesto por nivel**: límite de gasto por nivel que activa el respaldo automático
- **Configuración de precios por modelo**: precios configurables por modelo
- **Estadísticas de uso por clave API**: recuento de solicitudes y marca de tiempo utilizada por última vez por clave
- **Panel de análisis**: tarjetas de estadísticas, tabla de uso de modelos, tabla de proveedores con tasas de éxito y latencia.
</details>
<details>
<summary><b>🐛 10. "No puedo diagnosticar errores y problemas en llamadas AI"</b></summary>
Cuando falla una llamada, el desarrollador no sabe si se trata de un límite de velocidad, un token caducado, un formato incorrecto o un error del proveedor. Registros fragmentados en diferentes terminales. Sin observabilidad, la depuración es de prueba y error.
**Cómo lo resuelve OmniRoute:**
- **Panel de registros unificados**: 4 pestañas: registros de solicitudes, registros de proxy, registros de auditoría y consola
- **Visor de registros de consola**: visor estilo terminal en tiempo real con niveles codificados por colores, desplazamiento automático, búsqueda y filtro
- **Registros de proxy SQLite**: registros persistentes que sobreviven a los reinicios del servidor
- **Translator Playground**: 4 modos de depuración: Playground (traducción de formato), Chat Tester (ida y vuelta), Test Bench (por lotes), Live Monitor (en tiempo real)
- **Solicitud de telemetría**: latencia p50/p95/p99 + seguimiento de X-Request-Id
- **Registro basado en archivos con rotación**: el interceptor de consola captura todo en el registro JSON con rotación basada en el tamaño.
</details>
<details>
<summary><b>🏗️ 11. "Implementar y mantener la puerta de enlace es complejo"</b></summary>
Instalar, configurar y mantener un proxy de IA en diferentes entornos (local, VPS, Docker, nube) requiere mucha mano de obra. Problemas como rutas codificadas, `EACCES` en directorios, conflictos de puertos y compilaciones multiplataforma añaden fricción.
**Cómo lo resuelve OmniRoute:**
- **instalación global de npm** — `npm install -g omniroute && omniroute` — hecho
- **Docker multiplataforma**: AMD64 + ARM64 nativo (Apple Silicon, AWS Graviton, Raspberry Pi)
- **Perfiles de Docker Compose**: `base` (sin herramientas CLI) y `cli` (con Claude Code, Codex, OpenClaw)
- **Aplicación de escritorio Electron**: aplicación nativa para Windows/macOS/Linux con bandeja del sistema, inicio automático y modo sin conexión
- **Modo de puerto dividido**: API y panel en puertos separados para escenarios avanzados (proxy inverso, redes de contenedores)
- **Cloud Sync**: sincronización de configuración entre dispositivos a través de Cloudflare Workers
- **Copias de seguridad de base de datos**: copia de seguridad, restauración, exportación e importación automáticas de todas las configuraciones
</details>
<details>
<summary><b>🌍 12. "La interfaz es solo en inglés y mi equipo no habla inglés"</b></summary>
Los equipos en países que no hablan inglés, especialmente en América Latina, Asia y Europa, tienen dificultades con las interfaces solo en inglés. Las barreras del idioma reducen la adopción y aumentan los errores de configuración.
**Cómo lo resuelve OmniRoute:**
- **Panel i18n — 30 idiomas** — Las más de 500 teclas traducidas, incluidas árabe, búlgaro, danés, alemán, español, finlandés, francés, hebreo, hindi, húngaro, indonesio, italiano, japonés, coreano, malayo, holandés, noruego, polaco, portugués (PT/BR), rumano, ruso, eslovaco, sueco, tailandés, ucraniano, vietnamita, chino, filipino, inglés.
- **Soporte RTL**: soporte de derecha a izquierda para árabe y hebreo
- **README multilingüe**: 30 traducciones de documentación completa
- **Selector de idioma**: ícono de globo en el encabezado para cambiar en tiempo real
</details>
<details>
<summary><b>🔄 13. "Necesito más que chat: necesito incrustaciones, imágenes y audio"</b></summary>
La IA no es solo completar un chat. Los desarrolladores necesitan generar imágenes, transcribir audio, crear incrustaciones para RAG, reclasificar documentos y moderar contenido. Cada API tiene un punto final y un formato diferentes.
**Cómo lo resuelve OmniRoute:**
- **Integraciones** — `/v1/embeddings` con 6 proveedores y más de 9 modelos
- **Generación de imágenes** — `/v1/images/generations` con 10 proveedores y más de 20 modelos (OpenAI, xAI, Together, Fireworks, Nebius, Hyperbolic, NanoBanana, Antigravity, SD WebUI, ComfyUI)
- **Texto a vídeo** — `/v1/videos/generations` — ComfyUI (AnimateDiff, SVD) y SD WebUI
- **Texto a música** — `/v1/music/generations` — ComfyUI (audio estable abierto, MusicGen)
- **Transcripción de audio** — `/v1/audio/transcriptions` — Whisper + Nvidia NIM, HuggingFace, Qwen3
- **Texto a voz** — `/v1/audio/speech` — ElevenLabs, Nvidia NIM, HuggingFace, Coqui, Tortoise, Qwen3 y proveedores existentes
- **Moderaciones** — `/v1/moderations` — Comprobaciones de seguridad del contenido
- **Reclasificación** — `/v1/rerank` — Reclasificación de relevancia del documento
- **API de respuestas**: compatibilidad total con `/v1/responses` para Codex
</details>
<details>
<summary><b>🧪 14. "No tengo forma de probar y comparar la calidad entre modelos"</b></summary>
Los desarrolladores quieren saber qué modelo es mejor para su caso de uso (código, traducción, razonamiento), pero comparar manualmente es lento. No existen herramientas de evaluación integradas.
**Cómo lo resuelve OmniRoute:**
- **Evaluaciones LLM**: pruebas de conjunto dorado con 10 casos precargados que cubren saludos, matemáticas, geografía, generación de código, cumplimiento de JSON, traducción, rebajas y rechazo de seguridad.
- **4 estrategias de coincidencia**: `exact`, `contains`, `regex`, `custom` (función JS)
- **Translator Playground Test Bench**: pruebas por lotes con múltiples entradas y resultados esperados, comparación entre proveedores
- **Chat Tester**: recorrido completo de ida y vuelta con representación de respuesta visual
- **Live Monitor**: flujo en tiempo real de todas las solicitudes que fluyen a través del proxy
</details>
<details>
<summary><b>📈 15. "Necesito escalar sin perder rendimiento"</b></summary>
A medida que crece el volumen de solicitudes, sin almacenar en caché las mismas preguntas generan costos duplicados. Sin idempotencia, las solicitudes duplicadas desperdician el procesamiento. Se deben respetar los límites de tarifas por proveedor.
**Cómo lo resuelve OmniRoute:**
- **Caché semántica**: la caché de dos niveles (firma + semántica) reduce el costo y la latencia
- **Solicitud de idempotencia**: ventana de deduplicación de 5 segundos para solicitudes idénticas
- **Detección de límite de velocidad**: RPM por proveedor, intervalo mínimo y seguimiento simultáneo máximo
- **Límites de velocidad editables**: valores predeterminados configurables en Configuración → Resiliencia con persistencia
- **Caché de validación de clave API**: caché de 3 niveles para rendimiento de producción
- **Panel de estado con telemetría**: latencia p50/p95/p99, estadísticas de caché, tiempo de actividad
</details>
<details>
<summary><b>🤖 16. "Quiero controlar el comportamiento del modelo globalmente"</b></summary>
Desarrolladores que quieran todas las respuestas en un idioma específico, con un tono específico o quieran limitar los tokens de razonamiento. Configurar esto en cada herramienta/solicitud no es práctico.
**Cómo lo resuelve OmniRoute:**
- **Inyección de aviso del sistema**: aviso global aplicado a todas las solicitudes
- **Thinking Budget Validation**: control de asignación de tokens de razonamiento por solicitud (transferencia, automática, personalizada, adaptativa)
- **6 estrategias de enrutamiento**: estrategias globales que determinan cómo se distribuyen las solicitudes
- **Enrutador comodín**: los patrones `provider/*` se enrutan dinámicamente a cualquier proveedor
- **Activar/desactivar combinación de alternar**: alterna combinaciones directamente desde el panel
- **Alternar proveedor**: activa/desactiva todas las conexiones de un proveedor con un solo clic
- **Proveedores bloqueados**: excluye proveedores específicos del listado `/v1/models`
</details>
<details>
<summary><b>🧰 17. "Necesito herramientas MCP como capacidades de producto de primera clase"</b></summary>
Muchas puertas de enlace de IA exponen MCP solo como un detalle de implementación oculto. Los equipos necesitan una capa operativa visible y manejable.
**Cómo lo resuelve OmniRoute:**
- MCP aparece en la pestaña de navegación del panel y protocolo de punto final
- Página de gestión de MCP dedicada con procesos, herramientas, alcances y auditoría
- Inicio rápido integrado para `omniroute --mcp` e incorporación de clientes
</details>
<details>
<summary><b>🧠 18. "Necesito orquestación A2A con rutas de tareas de sincronización + transmisión"</b></summary>
Los flujos de trabajo de los agentes necesitan respuestas directas y una ejecución continua de larga duración con control del ciclo de vida.
**Cómo lo resuelve OmniRoute:**
- Punto final A2A JSON-RPC (`POST /a2a`) con `message/send` y `message/stream`
- Transmisión SSE con propagación del estado terminal
- API de ciclo de vida de tareas para `tasks/get` y `tasks/cancel`
</details>
<details>
<summary><b>🛰️ 19. "Necesito un estado real del proceso MCP, no un estado adivinado"</b></summary>
Los equipos operativos necesitan saber si MCP está realmente activo, no solo si se puede acceder a una API.
**Cómo lo resuelve OmniRoute:**
- Archivo de latidos en tiempo de ejecución con PID, marcas de tiempo, transporte, recuento de herramientas y modo de alcance
- API de estado de MCP que combina latidos + actividad reciente
- Tarjetas de estado de la interfaz de usuario para el proceso/tiempo de actividad/actualización de latidos
</details>
<details>
<summary><b>📋 20. "Necesito ejecución de herramienta MCP auditable"</b></summary>
Cuando las herramientas modifican la configuración o desencadenan acciones de operaciones, los equipos necesitan trazabilidad forense.
**Cómo lo resuelve OmniRoute:**
- Registro de auditoría respaldado por SQLite para llamadas a herramientas MCP
- Filtros por herramienta, éxito/fracaso, clave API y paginación
- Tabla de auditoría del panel + puntos finales de estadísticas para automatización
</details>
<details>
<summary><b>🔐 21. "Necesito permisos MCP con alcance por integración"</b></summary>
Los diferentes clientes deberían tener acceso con privilegios mínimos a las categorías de herramientas.
**Cómo lo resuelve OmniRoute:**
- 9 alcances MCP granulares para acceso controlado a herramientas
- Aplicación del alcance y visibilidad en la interfaz de usuario de gestión de MCP
- Postura predeterminada segura para herramientas operativas
</details>
<details>
<summary><b>⚙️ 22. "Necesito controles operativos sin redistribuir"</b></summary>
Los equipos necesitan cambios rápidos en el tiempo de ejecución durante incidentes o eventos de costos.
**Cómo lo resuelve OmniRoute:**
- Cambie la activación combinada directamente desde el panel de MCP
- Aplicar perfiles de resiliencia de paquetes de políticas predefinidos
- Restablecer el estado del disyuntor desde el mismo panel de operaciones.
</details>
<details>
<summary><b>🔄 23. "Necesito visibilidad y cancelación del ciclo de vida de la tarea A2A en vivo"</b></summary>
Sin visibilidad del ciclo de vida, los incidentes de tareas se vuelven difíciles de clasificar.
**Cómo lo resuelve OmniRoute:**
- Listado de tareas/filtrado por estado/habilidad con paginación
- Profundización en metadatos, eventos y artefactos de tareas
- Punto final de cancelación de tarea y acción de UI con confirmación
</details>
<details>
<summary><b>🌊 24. "Necesito métricas de transmisión activas para la carga A2A"</b></summary>
Los flujos de trabajo de streaming requieren información operativa sobre la simultaneidad y las conexiones en vivo.
**Cómo lo resuelve OmniRoute:**
- Contadores de flujo activos integrados en el estado A2A
- Marca de tiempo de la última tarea y recuentos por estado
- Tarjetas de tablero A2A para monitoreo de operaciones en tiempo real
</details>
<details>
<summary><b>🪪 25. "Necesito descubrimiento de agente estándar para clientes"</b></summary>
Los clientes y orquestadores externos necesitan metadatos legibles por máquina para la incorporación.
**Cómo lo resuelve OmniRoute:**
- Tarjeta de agente expuesta en `/.well-known/agent.json`
- Capacidades y habilidades mostradas en la interfaz de usuario de gestión.
- La API de estado A2A incluye metadatos de descubrimiento para la automatización
</details>
<details>
<summary><b>🧭 26. "Necesito capacidad de descubrimiento de protocolo en la UX del producto"</b></summary>
Si los usuarios no pueden descubrir las superficies de protocolo, la calidad de la adopción y el soporte disminuye.
**Cómo lo resuelve OmniRoute:**
- Entradas de la barra lateral para MCP y A2A
- Pestaña Protocolos de la página del endpoint con inicio rápido y estado
- Enlaces desde la descripción general a paneles de gestión dedicados
</details>
<details>
<summary><b>🧪 27. "Necesito validación de protocolo de extremo a extremo con clientes reales"</b></summary>
Las pruebas simuladas no son suficientes para validar la compatibilidad del protocolo antes del lanzamiento.
**Cómo lo resuelve OmniRoute:**
- Suite E2E que inicia la aplicación y utiliza transporte de cliente MCP SDK real
- Pruebas de cliente A2A para descubrimiento, envío, transmisión, obtención y cancelación de flujos
- Verificar las afirmaciones con las API de auditoría MCP y tareas A2A.
</details>
<details>
<summary><b>📡 28. "Necesito observabilidad unificada en todas las interfaces"</b></summary>
Dividir la observabilidad por protocolo crea puntos ciegos y MTTR más largos.
**Cómo lo resuelve OmniRoute:**
- Paneles/registros/análisis unificados en un solo producto
- Salud + auditoría + solicitud de telemetría en capas OpenAI, MCP y A2A
- API operativas para estado y automatización.
</details>
<details>
<summary><b>💼 29. "Necesito un tiempo de ejecución para proxy + herramientas + orquestación de agentes"</b></summary>
La ejecución de muchos servicios separados aumenta los costos operativos y los modos de falla.
**Cómo lo resuelve OmniRoute:**
- Proxy compatible con OpenAI, servidor MCP y servidor A2A en una sola pila
- Autenticación compartida, resiliencia, almacenamiento de datos y observabilidad.
- Modelo de política consistente en todas las superficies de interacción.
</details>
<details>
<summary><b>🚀 30. "Necesito enviar flujos de trabajo agentes sin expansión de código adhesivo"</b></summary>
Los equipos pierden velocidad al unir múltiples scripts y servicios ad hoc.
**Cómo lo resuelve OmniRoute:**
- Estrategia de endpoint unificada para clientes y agentes
- UI de gestión de protocolos integradas y rutas de validación de humo
- Fundamentos listos para producción (seguridad, registro, resiliencia, respaldo)
</details>
### Guías de ejemplo (casos de uso integrados)
**Libro de estrategias A: maximizar la suscripción paga + copia de seguridad económica**
```txt
Combo: "maximize-claude"
1. cc/claude-opus-4-6
2. glm/glm-4.7
3. if/kimi-k2-thinking
Monthly cost: $20 + small backup spend
Outcome: higher quality, near-zero interruption
```
**Libro de estrategias B: pila de codificación de costo cero**
```txt
Combo: "free-forever"
1. gc/gemini-3-flash
2. if/kimi-k2-thinking
3. qw/qwen3-coder-plus
Monthly cost: $0
Outcome: stable free coding workflow
```
**Libro de estrategias C: cadena alternativa siempre disponible las 24 horas del día, los 7 días de la semana**
```txt
Combo: "always-on"
1. cc/claude-opus-4-6
2. cx/gpt-5.2-codex
3. glm/glm-4.7
4. minimax/MiniMax-M2.1
5. if/kimi-k2-thinking
Outcome: deep fallback depth for deadline-critical workloads
```
**Libro de jugadas D: Operaciones del agente con MCP + A2A**
```txt
1) Start MCP transport (`omniroute --mcp`) for tool-driven operations
2) Run A2A tasks via `message/send` and `message/stream`
3) Observe via /dashboard/mcp and /dashboard/a2a
4) Control incidents with resilience profile + task cancellation
```
---
## ⚡ Inicio Rápido
**1. Instala globalmente:**
@@ -249,7 +781,7 @@ docker compose --profile cli up -d
---
## 🖥️ Aplicación de Escritorio — Sin Conexión y Siempre Activo
## 🖥️
> 🆕 **¡NUEVO!** OmniRoute ahora está disponible como **aplicación de escritorio nativa** para Windows, macOS y Linux.
@@ -300,67 +832,6 @@ npm run electron:build:linux # Linux (.AppImage)
---
## 🎯 Casos de Uso
### Caso 1: "Tengo suscripción Claude Pro"
**Problema:** La cuota expira sin usar, límites de tasa durante programación intensa
```
Combo: "maximize-claude"
1. cc/claude-opus-4-6 (usar suscripción al máximo)
2. glm/glm-4.7 (respaldo barato cuando la cuota se agota)
3. if/kimi-k2-thinking (fallback de emergencia gratuito)
Costo mensual: $20 (suscripción) + ~$5 (respaldo) = $25 total
vs. $20 + chocar con límites = frustración
```
### Caso 2: "Quiero costo cero"
**Problema:** No puede pagar suscripciones, necesita IA confiable para programar
```
Combo: "free-forever"
1. gc/gemini-3-flash (180K gratis/mes)
2. if/kimi-k2-thinking (ilimitado gratis)
3. qw/qwen3-coder-plus (ilimitado gratis)
Costo mensual: $0
Calidad: Modelos listos para producción
```
### Caso 3: "Necesito programar 24/7, sin interrupciones"
**Problema:** Plazos ajustados, no puede permitirse tiempo de inactividad
```
Combo: "always-on"
1. cc/claude-opus-4-6 (mejor calidad)
2. cx/gpt-5.2-codex (segunda suscripción)
3. glm/glm-4.7 (barato, reset diario)
4. minimax/MiniMax-M2.1 (más barato, reset 5h)
5. if/kimi-k2-thinking (gratuito ilimitado)
Resultado: 5 capas de fallback = cero tiempo de inactividad
```
### Caso 4: "Quiero IA GRATUITA en OpenClaw"
**Problema:** Necesita asistente de IA en apps de mensajería, completamente gratuito
```
Combo: "openclaw-free"
1. if/glm-4.7 (ilimitado gratis)
2. if/minimax-m2.1 (ilimitado gratis)
3. if/kimi-k2-thinking (ilimitado gratis)
Costo mensual: $0
Acceso vía: WhatsApp, Telegram, Slack, Discord, iMessage, Signal...
```
---
## 💡 Características Principales
### 🧠 Enrutamiento e Inteligencia
@@ -376,6 +847,8 @@ Acceso vía: WhatsApp, Telegram, Slack, Discord, iMessage, Signal...
| 🧩 **Modelos Personalizados** | Agrega cualquier ID de modelo a cualquier proveedor |
| 🌐 **Enrutador Wildcard** | Enruta patrones `provider/*` a cualquier proveedor dinámicamente |
| 🧠 **Presupuesto de Razonamiento** | Modos passthrough, auto, custom y adaptativo para modelos de razonamiento |
| 🔀 **Model Aliases** | Auto-forward deprecated model IDs to current replacements (built-in + custom) |
| ⚡ **Background Degradation** | Auto-route background tasks (titles, summaries) to cheaper models |
| 💬 **Inyección de System Prompt** | System prompt global aplicado en todas las solicitudes |
| 📄 **API Responses** | Soporte completo de la API Responses de OpenAI (`/v1/responses`) para Codex |
@@ -392,15 +865,18 @@ Acceso vía: WhatsApp, Telegram, Slack, Discord, iMessage, Signal...
### 🛡️ Resiliencia y Seguridad
| Característica | Qué Hace |
| ---------------------------------- | ---------------------------------------------------------------- |
| 🔌 **Circuit Breaker** | Auto-apertura/cierre por proveedor con umbrales configurables |
| 🛡️ **Anti-Thundering Herd** | Mutex + semáforo rate-limit para proveedores con API key |
| 🧠 **Caché Semántico** | Caché de dos niveles (firma + semántico) reduce costo y latencia |
| **Idempotencia de Solicitud** | Ventana de dedup de 5s para solicitudes duplicadas |
| 🔒 **Spoofing de Fingerprint TLS** | Bypass de detección de bot vía TLS con wreq-js |
| 🌐 **Filtrado de IP** | Allowlist/blocklist para control de acceso a la API |
| 📊 **Rate Limits Editables** | RPM, gap mínimo y concurrencia máxima configurables |
| Característica | Qué Hace |
| ---------------------------------- | ---------------------------------------------------------------------------- |
| 🔌 **Circuit Breaker** | Auto-apertura/cierre por proveedor con umbrales configurables |
| 🎯 **Endpoint-Aware Models** | Custom models declare supported endpoints + API format |
| 🛡️ **Anti-Thundering Herd** | Mutex + semáforo rate-limit para proveedores con API key |
| 🧠 **Caché Semántico** | Caché de dos niveles (firma + semántico) reduce costo y latencia |
| **Idempotencia de Solicitud** | Ventana de dedup de 5s para solicitudes duplicadas |
| 🔒 **Spoofing de Fingerprint TLS** | Bypass de detección de bot vía TLS con wreq-js |
| 🌐 **Filtrado de IP** | Allowlist/blocklist para control de acceso a la API |
| 📊 **Rate Limits Editables** | RPM, gap mínimo y concurrencia máxima configurables |
| 💾 **Rate Limit Persistence** | Learned limits survive restarts via SQLite with 60s debounce + 24h staleness |
| 🔄 **Token Refresh Resilience** | Per-provider circuit breaker (5 fails→30min) + 30s timeout per attempt |
### 📊 Observabilidad y Analytics
@@ -500,6 +976,27 @@ Traducción transparente entre formatos:
</details>
## 🧪 Evaluaciones (Evals)
OmniRoute incluye un framework de evaluación integrado para probar la calidad de respuestas de LLM contra un conjunto golden. Accede vía **Analytics → Evals** en el dashboard.
### Conjunto Golden Integrado
El "OmniRoute Golden Set" precargado contiene 10 casos de prueba que cubren:
- Saludos, matemáticas, geografía, generación de código
- Conformidad de formato JSON, traducción, markdown
- Rechazo de seguridad (contenido dañino), conteo, lógica booleana
### Estrategias de Evaluación
| Estrategia | Descripción | Ejemplo |
| ---------- | ---------------------------------------------------- | -------------------------------- |
| `exact` | La salida debe coincidir exactamente | `"4"` |
| `contains` | La salida debe contener subcadena (case-insensitive) | `"Paris"` |
| `regex` | La salida debe coincidir con el patrón regex | `"1.*2.*3"` |
| `custom` | Función JS personalizada retorna true/false | `(output) => output.length > 10` |
---
## 📖 Guía de Configuración
@@ -782,97 +1279,6 @@ Configuración → Configuración de API:
---
## 📊 Modelos Disponibles
<details>
<summary><b>Ver todos los modelos disponibles</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/`)** - GRATUITO:
- `gc/gemini-3-flash-preview`
- `gc/gemini-2.5-pro`
**GitHub Copilot (`gh/`)**:
- `gh/gpt-5`
- `gh/claude-4.5-sonnet`
**NVIDIA NIM (`nvidia/`)** - Créditos GRATUITOS:
- `nvidia/llama-3.3-70b-instruct`
- `nvidia/mistral-7b-instruct`
- 50+ más modelos en [build.nvidia.com](https://build.nvidia.com)
**GLM (`glm/`)** - $0.6/1M:
- `glm/glm-4.7`
**MiniMax (`minimax/`)** - $0.2/1M:
- `minimax/MiniMax-M2.1`
**iFlow (`if/`)** - GRATUITO:
- `if/kimi-k2-thinking`
- `if/qwen3-coder-plus`
- `if/deepseek-r1`
- `if/glm-4.7`
- `if/minimax-m2`
**Qwen (`qw/`)** - GRATUITO:
- `qw/qwen3-coder-plus`
- `qw/qwen3-coder-flash`
**Kiro (`kr/`)** - GRATUITO:
- `kr/claude-sonnet-4.5`
- `kr/claude-haiku-4.5`
**OpenRouter (`or/`)** - 100+ modelos:
- `or/anthropic/claude-4-sonnet`
- `or/google/gemini-2.5-pro`
- Cualquier modelo de [openrouter.ai/models](https://openrouter.ai/models)
</details>
---
## 🧪 Evaluaciones (Evals)
OmniRoute incluye un framework de evaluación integrado para probar la calidad de respuestas de LLM contra un conjunto golden. Accede vía **Analytics → Evals** en el dashboard.
### Conjunto Golden Integrado
El "OmniRoute Golden Set" precargado contiene 10 casos de prueba que cubren:
- Saludos, matemáticas, geografía, generación de código
- Conformidad de formato JSON, traducción, markdown
- Rechazo de seguridad (contenido dañino), conteo, lógica booleana
### Estrategias de Evaluación
| Estrategia | Descripción | Ejemplo |
| ---------- | ---------------------------------------------------- | -------------------------------- |
| `exact` | La salida debe coincidir exactamente | `"4"` |
| `contains` | La salida debe contener subcadena (case-insensitive) | `"Paris"` |
| `regex` | La salida debe coincidir con el patrón regex | `"1.*2.*3"` |
| `custom` | Función JS personalizada retorna true/false | `(output) => output.length > 10` |
---
## 🐛 Solución de Problemas
<details>
@@ -928,7 +1334,7 @@ El "OmniRoute Golden Set" precargado contiene 10 casos de prueba que cubren:
---
## 🛠️ Stack Tecnológico
## 🛠️
- **Runtime**: Node.js 20+
- **Lenguaje**: TypeScript 5.9 — **100% TypeScript** en `src/` y `open-sse/` (v1.0.6)
@@ -959,17 +1365,7 @@ El "OmniRoute Golden Set" precargado contiene 10 casos de prueba que cubren:
---
## 📧 Soporte
> 💬 **¡Únete a la comunidad!** [Grupo WhatsApp](https://chat.whatsapp.com/JI7cDQ1GyaiDHhVBpLxf8b?mode=gi_t) — Obtén ayuda, comparte consejos y mantente al día.
- **Website**: [omniroute.online](https://omniroute.online)
- **GitHub**: [github.com/diegosouzapw/OmniRoute](https://github.com/diegosouzapw/OmniRoute)
- **Issues**: [github.com/diegosouzapw/OmniRoute/issues](https://github.com/diegosouzapw/OmniRoute/issues)
- **WhatsApp**: [Grupo de la Comunidad](https://chat.whatsapp.com/JI7cDQ1GyaiDHhVBpLxf8b?mode=gi_t)
- **Proyecto Original**: [9router por decolua](https://github.com/decolua/9router)
---
## 🗺️
## 👥 Contribuidores

View File

@@ -3,8 +3,6 @@
# 🚀 OmniRoute — ilmainen tekoälyyhdyskäytävä
🌐 **[English](#-omniroute--the-free-ai-gateway)** | **[Português (BR)](#-omniroute--gateway-de-ia-gratuito)**
### Älä koskaan lopeta koodaamista. Älykäs reititys **ILMAisiin ja edullisiin tekoälymalleihin** automaattisella varalla.
_Universaali API-välityspalvelin yksi päätepiste, yli 36 palveluntarjoajaa, nolla seisokkia._
@@ -112,6 +110,35 @@ _Yhdistä mikä tahansa tekoälyllä toimiva IDE- tai CLI-työkalu OmniRouten ka
---
## 🖼️
<div align="center">
<img src="./docs/screenshots/MainOmniRoute.png" alt="OmniRoute" width="800"/>
</div>
---
## 📸
<details>
<summary><b>...</b></summary>
| # | # |
| ----- | ---------------------------------------- |
| **1** | ![1](docs/screenshots/01-providers.png) |
| **2** | ![2](docs/screenshots/02-combos.png) |
| **3** | ![3](docs/screenshots/03-analytics.png) |
| **4** | ![4](docs/screenshots/04-health.png) |
| **5** | ![5](docs/screenshots/05-translator.png) |
| **6** | ![6](docs/screenshots/06-settings.png) |
| **7** | ![7](docs/screenshots/07-cli-tools.png) |
| **8** | ![8](docs/screenshots/08-usage.png) |
| **9** | ![9](docs/screenshots/09-endpoint.png) |
</details>
---
## 🤔 Miksi OmniRoute?
**Lopeta rahan tuhlaaminen ja rajojen ylittäminen:**
@@ -130,6 +157,18 @@ _Yhdistä mikä tahansa tekoälyllä toimiva IDE- tai CLI-työkalu OmniRouten ka
---
## 📧 Tuki
> 💬 **Liity yhteisöömme!** [WhatsApp Group](https://chat.whatsapp.com/JI7cDQ1GyaiDHhVBpLxf8b?mode=gi_t) — Hanki apua, jaa vinkkejä ja pysy ajan tasalla.
- **Verkkosivusto**: [omniroute.online](https://omniroute.online)
- **GitHub**: [github.com/diegosouzapw/OmniRoute](https://github.com/diegosouzapw/OmniRoute)
- **Ongelmia**: [github.com/diegosouzapw/OmniRoute/issues](https://github.com/diegosouzapw/OmniRoute/issues)
- **WhatsApp**: [Community Group](https://chat.whatsapp.com/JI7cDQ1GyaiDHhVBpLxf8b?mode=gi_t)
- **Alkuperäinen projekti**: [9router by decolua](https://github.com/decolua/9router)
---
## 🔄 Näin se toimii
```
@@ -159,6 +198,498 @@ Result: Never stop coding, minimal cost
---
## 🎯 Mitä OmniRoute ratkaisee 30 todellista kipukohtaa ja käyttötapausta
> **Jokainen tekoälytyökaluja käyttävä kehittäjä kohtaa nämä ongelmat päivittäin.** OmniRoute luotiin ratkaisemaan ne kaikki kustannusten ylityksistä alueellisiin lohkoihin, rikkinäisistä OAuth-virroista protokollatoimintoihin ja yrityksen havainnointikykyyn.
<details>
<summary><b>💸 1. "Maksan kalliista tilauksesta, mutta silti rajoitukset häiritsevät minua"</b></summary>
Kehittäjät maksavat 20200 dollaria kuukaudessa Claude Prosta, Codex Prosta tai GitHub Copilotista. Maksamallakin kiintiöllä on katto 5 tuntia käyttöä, viikkorajat tai minuuttirajoitukset. Koodausistunnon puolivälissä palveluntarjoaja lakkaa vastaamasta ja kehittäjä menettää virtauksen ja tuottavuuden.
**Kuinka OmniRoute ratkaisee sen:**
- **Smart 4-Tier Fallback** — Jos tilauskiintiö loppuu, ohjataan automaattisesti kohtaan API-avain → Halpa → Ilmainen ilman manuaalista toimenpiteitä
- **Reaaliaikainen kiintiöseuranta** - Näyttää tunnuksen kulutuksen reaaliajassa ja nollaa lähtölaskenta (5 tuntia, päivittäin, viikoittain)
- **Useiden tilien tuki** — Useita tilejä palveluntarjoajaa kohden automaattisella kierrätyksellä — kun yksi loppuu, vaihtuu seuraavaan
- **Muokatut yhdistelmät** — Muokattavat varaketjut, joissa on 6 tasapainotusstrategiaa (täytä ensin, round-robin, P2C, satunnainen, vähiten käytetty, kustannusoptimoitu)
- **Codex Business Quotat** — Yritysten/Tiimien työtilan kiintiöiden valvonta suoraan kojelaudassa
</details>
<details>
<summary><b>🔌 2. "Minun täytyy käyttää useita palveluntarjoajia, mutta jokaisella on erilainen API"</b></summary>
OpenAI käyttää yhtä muotoa, Claude (Anthropic) käyttää toista, Gemini vielä toista. Jos kehittäjä haluaa testata eri palveluntarjoajien malleja tai vaihtoehtoja niiden välillä, hänen on määritettävä SDK:t uudelleen, muutettava päätepisteitä ja käsiteltävä yhteensopimattomia muotoja. Mukautetuilla palveluntarjoajilla (FriendLI, NIM) on mallista poikkeavat päätepisteet.
**Kuinka OmniRoute ratkaisee sen:**
- **Yhdistetty päätepiste** — Yksi `http://localhost:20128/v1` toimii välityspalvelimena kaikille yli 36 palveluntarjoajalle
- **Format Translation** - Automaattinen ja läpinäkyvä: OpenAI ↔ Claude ↔ Gemini ↔ Responses API
- **Response Sanitization** Poistaa standardista poikkeavat kentät (`x_groq`, `usage_breakdown`, `service_tier`), jotka rikkovat OpenAI SDK v1.83+:n
- **Roolin normalisointi** — Muuntaa `developer``system` muille kuin OpenAI-palveluntarjoajille; `system``user` GLM/ERNIE:lle
- **Think Tag Extraction** - Purkaa `<think>`-lohkot malleista, kuten DeepSeek R1, standardoituun `reasoning_content`:hen
- **Strukturoitu lähtö Geminille** — `json_schema``responseMimeType`/`responseSchema` automaattinen muunnos
- **`stream`:n oletusarvo on `false`** — yhdenmukaistuu OpenAI-spesifikaation kanssa välttäen odottamattoman SSE:n Python/Rust/Go SDK:issa
</details>
<details>
<summary><b>🌐 3. "Tekoälypalveluntarjoajani estää alueeni/maani"</b></summary>
Palveluntarjoajat, kuten OpenAI/Codex, estävät pääsyn tietyiltä maantieteellisiltä alueilta. Käyttäjät saavat virheitä, kuten `unsupported_country_region_territory`, OAuth- ja API-yhteyksien aikana. Tämä on erityisen turhauttavaa kehitysmaiden kehittäjille.
**Kuinka OmniRoute ratkaisee sen:**
- **3-tason välityspalvelimen määritys** Muokattava välityspalvelin kolmella tasolla: yleinen (kaikki liikenne), palveluntarjoajakohtainen (vain yksi palveluntarjoaja) ja yhteys/avain
- **Värikoodatut välityspalvelinmerkit** — Visuaaliset ilmaisimet: 🟢 maailmanlaajuinen välityspalvelin, 🟡 tarjoajan välityspalvelin, 🔵 yhteysvälityspalvelin, joka näyttää aina IP-osoitteen
- **OAuth-tunnusten vaihto välityspalvelimen kautta** — OAuth-kulku kulkee myös välityspalvelimen kautta, mikä ratkaisee `unsupported_country_region_territory`
- **Yhteystestit välityspalvelimen kautta** - Yhteystestit käyttävät määritettyä välityspalvelinta (ei enää suoraa ohitusta)
- **SOCKS5-tuki** — Täysi SOCKS5-välityspalvelintuki lähtevään reititykseen
- **TLS-sormenjälkien huijaus** — Selaimen kaltainen TLS-sormenjälki `wreq-js`:n kautta ohittaakseen bot-tunnistuksen
</details>
<details>
<summary><b>🆓 4. "Haluan käyttää tekoälyä koodaukseen, mutta minulla ei ole rahaa"</b></summary>
Kaikki eivät voi maksaa 20200 dollaria kuukaudessa tekoälytilauksista. Opiskelijat, kehittäjät nousevista maista, harrastajat ja freelancerit tarvitsevat pääsyn laadukkaisiin malleihin ilman kustannuksia.
**Kuinka OmniRoute ratkaisee sen:**
- **Free Tier Providers -sisäänrakennettu** - Natiivituki 100 % ilmaisille palveluntarjoajille: iFlow (8 rajatonta mallia), Qwen (3 rajoittamatonta mallia), Kiro (Claude ilmaiseksi), Gemini CLI (180 000/kk ilmaiseksi)
- **Vain ilmaiset yhdistelmät** — Ketju `gc/gemini-3-flash → if/kimi-k2-thinking → qw/qwen3-coder-plus` = 0 $/kk ilman seisonta-aikaa
- **NVIDIA NIM Free Credits** - 1000 ilmaista saldoa integroituna
- **Kustannusoptimoitu strategia** — Reititysstrategia, joka valitsee automaattisesti halvimman saatavilla olevan palveluntarjoajan
</details>
<details>
<summary><b>🔒 5. "Minun täytyy suojata tekoälyyhdyskäytävääni luvattomalta käytöltä"</b></summary>
Kun paljastat tekoälyyhdyskäytävän verkkoon (LAN, VPS, Docker), kuka tahansa osoitteen tietävä voi kuluttaa kehittäjän tunnukset/kiintiöt. Ilman suojaa API:t ovat alttiita väärinkäytölle, nopealle injektiolle ja väärinkäytöksille.
**Kuinka OmniRoute ratkaisee sen:**
- **API-avainten hallinta** — Luominen, kierto ja laajuus palveluntarjoajakohtaisesti erillisellä `/dashboard/api-manager`-sivulla
- **Mallitason käyttöoikeudet** - Rajoita API-avaimet tiettyihin malleihin (`openai/*`, jokerimerkkimallit) Salli kaikki/Rajoita-kytkimellä
- **API Endpoint Protection** — Vaadi avainta `/v1/models`:lle ja estä tietyt palveluntarjoajat luettelosta
- **Auth Guard + CSRF-suojaus** — Kaikki kojelaudan reitit on suojattu `withAuth`-väliohjelmistolla + CSRF-tunnuksilla
- **Rate Limiter** — IP-nopeuden rajoitus konfiguroitavilla ikkunoilla
- **IP-suodatus** — Pääsynhallinnan sallittu-/estolista
- **Prompt Injection Guard** — Desinfiointi haitallisia kehotusmalleja vastaan
- **AES-256-GCM Encryption** — Tunnistetiedot on salattu lepotilassa
</details>
<details>
<summary><b>🛑 6. "palveluntarjoajani kaatui ja menetin koodauskulkuni"</b></summary>
Tekoälypalveluntarjoajat voivat muuttua epävakaiksi, palauttaa 5xx-virheitä tai saavuttaa väliaikaiset nopeusrajoitukset. Jos kehittäjä on riippuvainen yhdestä palveluntarjoajasta, se keskeytyy. Ilman katkaisijoita toistuvat uudelleenyritykset voivat kaataa sovelluksen.
**Kuinka OmniRoute ratkaisee sen:**
- **Katkaisija palveluntarjoajakohtaisesti** - Automaattinen avautuminen/sulkeminen konfiguroitavilla kynnyksillä ja jäähdytys (suljettu/auki/puoliauki)
- **Eksponentiaalinen peruutus** — Progressiiviset uudelleenyritysviiveet
- **Anti-Thundering Herd** — Mutex + semaforisuoja samanaikaisia myrskyjä vastaan
- **Yhdistelmävaraketjut** Jos ensisijainen toimittaja epäonnistuu, putoaa automaattisesti ketjun läpi ilman väliintuloa
- **Combo Circuit Breaker** — Poistaa automaattisesti käytöstä vialliset palveluntarjoajat yhdistelmäketjussa
| 🎯 **Endpoint-Aware Models** | Custom models declare supported endpoints + API format |
- **Health Dashboard** — käytettävyyden valvonta, katkaisijoiden tilat, lukitukset, välimuistitilastot, p50/p95/p99-viive
</details>
<details>
<summary><b>🔧 7. "Jokaisen tekoälytyökalun määrittäminen on työlästä ja toistuvaa"</b></summary>
Kehittäjät käyttävät kursoria, Claude Codea, Codex CLI:tä, OpenClaw:ta, Gemini CLI:tä, Kilo Codea... Jokainen työkalu tarvitsee eri konfiguraation (API-päätepiste, avain, malli). Uudelleenmääritys toimittajaa tai mallia vaihdettaessa on ajanhukkaa.
**Kuinka OmniRoute ratkaisee sen:**
- **CLI Tools Dashboard** - Erillinen sivu yhdellä napsautuksella Claude Code, Codex CLI, OpenClaw, Kilo Code, Antigravity, Cline
- **GitHub Copilot Config Generator** — Luo `chatLanguageModels.json` VS-koodille joukkomallin valinnalla
- **Ohjattu käyttöönottotoiminto** — Ohjattu 4-vaiheinen asennus ensikertalaisille
- **Yksi päätepiste, kaikki mallit** — Määritä `http://localhost:20128/v1` kerran, käytä 36+ palveluntarjoajaa
</details>
<details>
<summary><b>🔑 8. "Useiden palveluntarjoajien OAuth-tunnusten hallinta on helvettiä"</b></summary>
Claude Code, Codex, Gemini CLI, Copilot kaikki käyttävät OAuth 2.0:aa vanhentuvilla tunnuksilla. Kehittäjien on todennettava jatkuvasti uudelleen, käsiteltävä `client_secret is missing`-, `redirect_uri_mismatch`- ja etäpalvelimien vikoja. OAuth LAN/VPS:ssä on erityisen ongelmallinen.
**Kuinka OmniRoute ratkaisee sen:**
- **Automaattinen tunnuksen päivitys** - OAuth-tunnukset päivittyvät taustalla ennen vanhenemista
- **Sisäänrakennettu OAuth 2.0 (PKCE)** - Automaattinen kulku Claude Codelle, Codexille, Gemini CLI:lle, Copilotille, Kirolle, Qwenille, iFlowille
- **Multi-Account OAuth** - Useita tilejä palveluntarjoajaa kohden JWT/ID-tunnuksen purkamisen kautta
- **OAuth LAN/Remote Fix** — Yksityinen IP-tunnistus `redirect_uri`:lle + manuaalinen URL-tila etäpalvelimille
- **OAuth Nginxin takana** - Käyttää `window.location.origin`-protokollaa käänteisen välityspalvelimen yhteensopivuuteen
- **OAuth-etäopas** — Vaiheittainen opas Google Cloud -kirjautumistiedoille VPS/Dockerissa
</details>
<details>
<summary><b>📊 9. "En tiedä kuinka paljon kulutan tai minne"</b></summary>
Kehittäjät käyttävät useita maksullisia palveluntarjoajia, mutta heillä ei ole yhtenäistä näkemystä kuluttamisesta. Jokaisella palveluntarjoajalla on oma laskutuksen hallintapaneeli, mutta yhdistettyä näkymää ei ole. Odottamattomat kustannukset voivat kasaantua.
**Kuinka OmniRoute ratkaisee sen:**
- **Cost Analytics Dashboard** Token-kohtainen kustannusseuranta ja budjetin hallinta palveluntarjoajakohtaisesti
- **Tasokohtaiset budjettirajat** Tasokohtainen kulutuskatto, joka laukaisee automaattisen varauksen
- **Malleittainen hinnoittelu** — Muokattavat hinnat mallikohtaisesti
- **Käyttötilastot API-avainta kohti** — Pyyntömäärä ja viimeksi käytetty aikaleima avainta kohti
- **Analytics Dashboard** - Tilastokortit, mallin käyttökaavio, toimittajataulukko onnistumisprosenteilla ja viiveellä
</details>
<details>
<summary><b>🐛 10. "En pysty diagnosoimaan tekoälypuhelujen virheitä ja ongelmia"</b></summary>
Kun puhelu epäonnistuu, kehittäjä ei tiedä, oliko kyseessä nopeusrajoitus, vanhentunut tunnus, väärä muoto vai palveluntarjoajan virhe. Sirpaloituneet lokit eri terminaaleissa. Ilman havaittavuutta virheenkorjaus on yrityksen ja erehdysten menetelmää.
**Kuinka OmniRoute ratkaisee sen:**
- **Yhdistettyjen lokien hallintapaneeli** - 4 välilehteä: pyyntölokit, välityspalvelimen lokit, tarkastuslokit, konsoli
- **Console Log Viewer** - Reaaliaikainen päätetyylinen katseluohjelma värikoodatuilla tasoilla, automaattinen vieritys, haku, suodatin
- **SQLite-välityspalvelimen lokit** — Pysyvät lokit, jotka kestävät palvelimen uudelleenkäynnistyksen
- **Kääntäjän leikkikenttä** — 4 virheenkorjaustilaa: Playground (muodon käännös), Chat Tester (meno-paluu), testipenkki (erä), Live Monitor (reaaliaikainen)
- **Pyyntötelemetria** — p50/p95/p99-latenssi + X-Request-Id-seuranta
- **Tiedostopohjainen kirjaaminen rotaatiolla** Konsolin sieppaaja tallentaa kaiken JSON-lokiin kokoperusteisella kierrolla
</details>
<details>
<summary><b>🏗️ 11. "Yhdyskäytävän käyttöönotto ja ylläpito on monimutkaista"</b></summary>
AI-välityspalvelimen asentaminen, määrittäminen ja ylläpito eri ympäristöissä (paikallinen, VPS, Docker, pilvi) on työvoimavaltaista. Ongelmat, kuten kovakoodatut polut, `EACCES` hakemistoissa, porttiristiriidat ja monikäyttöjärjestelmät lisäävät kitkaa.
**Kuinka OmniRoute ratkaisee sen:**
- **npm yleinen asennus** — `npm install -g omniroute && omniroute` — valmis
- **Docker Multi-Platform** - AMD64 + ARM64 natiivi (Apple Silicon, AWS Graviton, Raspberry Pi)
- **Docker Compose -profiilit** — `base` (ei CLI-työkaluja) ja `cli` (Claude Code, Codex, OpenClaw)
- **Electron Desktop App** - Natiivisovellus Windowsille/macOS:lle/Linuxille, jossa ilmaisinalue, automaattinen käynnistys, offline-tila
- **Split-Port Mode** — API ja Dashboard erillisissä porteissa edistyneille skenaarioille (käänteinen välityspalvelin, konttiverkko)
- **Cloud Sync** - Määritä synkronointi laitteiden välillä Cloudflare Workersin kautta
- **DB-varmuuskopiot** — Kaikkien asetusten automaattinen varmuuskopiointi, palautus, vienti ja tuonti
</details>
<details>
<summary><b>🌍 12. "Käyttöliittymä on vain englanninkielinen ja tiimini ei puhu englantia"</b></summary>
Ryhmät muissa kuin englanninkielisissä maissa, erityisesti Latinalaisessa Amerikassa, Aasiassa ja Euroopassa, kamppailevat vain englanninkielisten käyttöliittymien kanssa. Kielimuurit vähentävät käyttöönottoa ja lisäävät konfigurointivirheitä.
**Kuinka OmniRoute ratkaisee sen:**
- **Dashboard i18n — 30 kieltä** — Kaikki yli 500 näppäintä käännetty mukaan lukien arabia, bulgaria, tanska, saksa, espanja, suomi, ranska, heprea, hindi, unkari, indonesia, italia, japani, korea, malaiji, hollanti, norja, puola, portugali (PT/BR), romania, thai, venäjä, ukraina, slovakki, ruotsi, englanti
- **RTL-tuki** — Tuki oikealta vasemmalle arabian ja heprean kielelle
- **Multi-Language READMEs** - 30 täydellistä dokumentaation käännöstä
- **Kielen valitsin** — Maapallokuvake otsikossa reaaliaikaista vaihtoa varten
</details>
<details>
<summary><b>🔄 13. "Tarvitsen muutakin kuin chatin tarvitsen upotuksia, kuvia, ääntä"</b></summary>
Tekoäly ei ole vain chatin loppuun saattamista. Kehittäjien on luotava kuvia, litteroitava ääni, luotava upotuksia RAG:lle, järjestettävä asiakirjat uudelleen ja valvottava sisältöä. Jokaisella API:lla on eri päätepiste ja muoto.
**Kuinka OmniRoute ratkaisee sen:**
- **Upotukset** — `/v1/embeddings`, 6 toimittajaa ja 9+ mallia
- **Image Generation** — `/v1/images/generations` 10 palveluntarjoajan ja 20+ mallin kanssa (OpenAI, xAI, Together, Fireworks, Nebius, Hyperbolic, NanoBanana, Antigravity, SD WebUI, ComfyUI)
- **Tekstistä videoksi** — `/v1/videos/generations` — ComfyUI (AnimateDiff, SVD) ja SD WebUI
- **Tekstistä musiikiksi** — `/v1/music/generations` — ComfyUI (Stable Audio Open, MusicGen)
- **Äänitranskriptio** — `/v1/audio/transcriptions` — Whisper + Nvidia NIM, HuggingFace, Qwen3
- **Tekstistä puheeksi** — `/v1/audio/speech` — ElevenLabs, Nvidia NIM, HuggingFace, Coqui, Tortoise, Qwen3 ja olemassa olevat palveluntarjoajat
- **Moderaatiot** — `/v1/moderations` — Sisällön turvallisuustarkastukset
- **Uudelleensijoitus** — `/v1/rerank` — Asiakirjan relevanssin uudelleensijoitus
- **Responses API** — Täysi `/v1/responses`-tuki Codexille
</details>
<details>
<summary><b>🧪 14. "Minulla ei ole mahdollisuutta testata ja vertailla laatua eri mallien välillä"</b></summary>
Kehittäjät haluavat tietää, mikä malli sopii parhaiten heidän käyttötapaukseensa koodi, käännös, päättely mutta manuaalinen vertailu on hidasta. Integroituja arviointityökaluja ei ole olemassa.
**Kuinka OmniRoute ratkaisee sen:**
- **LLM-arvioinnit** — Golden set -testaus 10 esiladatulla kotelolla, jotka kattavat tervehdyksen, matematiikan, maantieteen, koodin luomisen, JSON-yhteensopivuuden, käännöksen, merkinnän, turvallisuuden kieltämisen
- **4 sovitusstrategiaa** — `exact`, `contains`, `regex`, `custom` (JS-toiminto)
- **Translator Playground Test Bench** - Erätestaus useilla tuloilla ja odotetulla lähdöllä, tarjoajien välinen vertailu
- **Chat Tester** - Täysi edestakainen matka visuaalisen vasteen renderöinnillä
- **Live Monitor** — Reaaliaikainen tietovirta kaikista välityspalvelimen kautta kulkevista pyynnöistä
</details>
<details>
<summary><b>📈 15. "Minun täytyy skaalata suorituskykyä menettämättä"</b></summary>
Pyynnön määrän kasvaessa samat kysymykset aiheuttavat päällekkäisiä kustannuksia välimuistiin tallentamatta. Ilman idempotenssia kaksoiskappaleet pyytävät jätteenkäsittelyä. Palveluntarjoajakohtaisia hintarajoja on noudatettava.
**Kuinka OmniRoute ratkaisee sen:**
- **Semanttinen välimuisti** Kaksitasoinen välimuisti (allekirjoitus + semanttinen) vähentää kustannuksia ja viivettä
- **Request Idempotency** — 5 sekunnin deduplikaatioikkuna identtisille pyynnöille
- **nopeusrajoituksen tunnistus** palveluntarjoajakohtainen RPM, pienin väli ja suurin samanaikainen seuranta
- **Muokattavat nopeusrajoitukset** - Määritettävissä olevat oletusasetukset kohdassa Asetukset → Resilience with persistence
- **API Key Validation Cache** 3-tasoinen välimuisti tuotannon suorituskykyä varten
- **Health Dashboard telemetrialla** - p50/p95/p99 latenssi, välimuistitilastot, käyttöaika
</details>
<details>
<summary><b>🤖 16. "Haluan hallita mallin käyttäytymistä maailmanlaajuisesti"</b></summary>
Kehittäjät, jotka haluavat kaikki vastaukset tietyllä kielellä, tietyllä sävyllä tai haluavat rajoittaa perusteluita. Tämän määrittäminen jokaiseen työkaluun/pyyntöön on epäkäytännöllistä.
**Kuinka OmniRoute ratkaisee sen:**
- **Järjestelmäkehotteen lisäys** — Yleinen kehote koskee kaikkia pyyntöjä
- **Thinking Budget Validation** perustelutunnisteen allokoinnin ohjaus pyyntöä kohti (läpivienti, automaattinen, mukautettu, mukautuva)
- **6 reititysstrategiaa** — Globaalit strategiat, jotka määrittävät pyyntöjen jakautumisen
- **Wildcard Router** — `provider/*`-mallit reitittävät dynaamisesti mille tahansa palveluntarjoajalle
- **Yhdistelmä käyttöön/pois käytöstä** - Vaihda yhdistelmät suoraan kojelaudalta
- **Provider Toggle** — Ota käyttöön tai poista käytöstä kaikki palveluntarjoajan yhteydet yhdellä napsautuksella
- **Estetyt palveluntarjoajat** - Sulje tietyt palveluntarjoajat pois `/v1/models`-luettelosta
</details>
<details>
<summary><b>🧰 17. "Tarvitsen MCP-työkaluja ensiluokkaisina tuoteominaisuuksina"</b></summary>
Monet tekoälyyhdyskäytävät paljastavat MCP:n vain piilotettuna toteutustietona. Tiimit tarvitsevat näkyvän, hallittavan toimintakerroksen.
**Kuinka OmniRoute ratkaisee sen:**
- MCP näkyy kojelaudan navigointi- ja päätepisteprotokolla-välilehdessä
- Erillinen MCP-hallintasivu, jossa on prosessit, työkalut, laajuudet ja tarkastus
- Sisäänrakennettu pikakäynnistys `omniroute --mcp`:lle ja asiakkaan käyttöönottoon
</details>
<details>
<summary><b>🧠 18. "Tarvitsen A2A-orkesterin synkronointia ja suoratoiston tehtäväpolkuja"</b></summary>
Agenttityönkulut tarvitsevat sekä suoria vastauksia että pitkäkestoista suoratoistoa elinkaariohjauksella.
**Kuinka OmniRoute ratkaisee sen:**
- A2A JSON-RPC -päätepiste (`POST /a2a`) `message/send`:n ja `message/stream`:n kanssa
- SSE-suoratoisto päätetilan etenemisellä
- Tehtävän elinkaaren sovellusliittymät `tasks/get`:lle ja `tasks/cancel`:lle
</details>
<details>
<summary><b>🛰️ 19. "Tarvitsen todellisen MCP-prosessin kunnon, en arvatun tilan"</b></summary>
Operatiivisten tiimien on tiedettävä, onko MCP todella elossa, ei vain sitä, onko API tavoitettavissa.
**Kuinka OmniRoute ratkaisee sen:**
- Ajonaikainen syketiedosto, jossa on PID, aikaleimat, kuljetus, työkalujen määrä ja laajuustila
- MCP-tilan API, joka yhdistää sykkeen + viimeaikaisen toiminnan
- Käyttöliittymän tilakortit prosessin / käytettävyyden / sydämenlyöntien tuoreudelle
</details>
<details>
<summary><b>📋 20. "Tarvitsen tarkastettavan MCP-työkalun suorituksen"</b></summary>
Kun työkalut muuttavat määrityksiä tai käynnistävät operaatioita, tiimit tarvitsevat rikosteknistä jäljitettävyyttä.
**Kuinka OmniRoute ratkaisee sen:**
- SQLite-tuettu tarkastusloki MCP-työkalukutsuille
- Suodattimet työkalun, onnistumisen/epäonnistumisen, API-avaimen ja sivutuksen mukaan
- Kojelaudan tarkastustaulukko + tilastopäätepisteet automatisointia varten
</details>
<details>
<summary><b>🔐 21. "Tarvitsen laajennettuja MCP-oikeuksia integraatiota kohti"</b></summary>
Eri asiakkailla tulisi olla vähiten käyttöoikeus työkaluluokkiin.
**Kuinka OmniRoute ratkaisee sen:**
- 9 rakeista MCP-skooppia ohjattua työkalujen käyttöä varten
- Laajuuden valvonta ja näkyvyys MCP-hallintaliittymässä
- Turvallinen oletusasento käyttötyökaluille
</details>
<details>
<summary><b>⚙️ 22. "Tarvitsen toiminnan ohjaimia ilman uudelleenjärjestelyä"</b></summary>
Tiimit tarvitsevat nopeita ajonaikaisia muutoksia tapausten tai kustannustapahtumien aikana.
**Kuinka OmniRoute ratkaisee sen:**
- Vaihda yhdistelmäaktivointia suoraan MCP-kojelaudalta
- Käytä joustavuusprofiileja ennalta määritetyistä käytäntöpaketeista
- Nollaa katkaisijan tila samasta käyttöpaneelista
</details>
<details>
<summary><b>🔄 23. "Tarvitsen live-A2A-tehtävän elinkaaren näkyvyyden ja peruutuksen"</b></summary>
Ilman elinkaaren näkyvyyttä tehtäväkohtauksista tulee vaikeasti luokiteltuja.
**Kuinka OmniRoute ratkaisee sen:**
- Tehtäväluettelo / suodatus tilan / taitojen mukaan ja sivutus
- Tehtävän metatietojen, tapahtumien ja artefaktien yksityiskohdat
- Tehtävän peruutuksen päätepiste ja käyttöliittymätoiminto vahvistuksen kanssa
</details>
<details>
<summary><b>🌊 24. "Tarvitsen aktiivisia suoratoistotietoja A2A-kuormalle"</b></summary>
Streaming-työnkulut edellyttävät toiminnallista tietoa samanaikaisuudesta ja reaaliaikaisista yhteyksistä.
**Kuinka OmniRoute ratkaisee sen:**
- Aktiiviset virtalaskurit integroitu A2A-tilaan
- Viimeisen tehtävän aikaleima ja tilakohtaiset määrät
- A2A kojelautakortit reaaliaikaiseen toimintojen seurantaan
</details>
<details>
<summary><b>🪪 25. "Tarvitsen asiakkaille vakioagentin haun"</b></summary>
Ulkoiset asiakkaat ja orkesterit tarvitsevat koneellisesti luettavaa metadataa käyttöönottoa varten.
**Kuinka OmniRoute ratkaisee sen:**
- Agenttikortti esillä osoitteessa `/.well-known/agent.json`
- Johdon käyttöliittymässä näkyvät valmiudet ja taidot
- A2A status API sisältää etsintämetatiedot automatisointia varten
</details>
<details>
<summary><b>🧭 26. "Tarvitsen protokollan löydettävyyden tuotteessa UX"</b></summary>
Jos käyttäjät eivät löydä protokollapintoja, käyttöönoton ja tuen laatu heikkenee.
**Kuinka OmniRoute ratkaisee sen:**
- Sivupalkkimerkinnät MCP:lle ja A2A:lle
- Päätepistesivu Protokollat-välilehti, jossa on pika-aloitus ja tila
- Linkit yleiskatsauksesta erityisiin hallintapaneeliin
</details>
<details>
<summary><b>🧪 27. "Tarvitsen päästä päähän -protokollan validoinnin oikeiden asiakkaiden kanssa"</b></summary>
Valetestit eivät riitä vahvistamaan protokollan yhteensopivuutta ennen julkaisua.
**Kuinka OmniRoute ratkaisee sen:**
- E2E-paketti, joka käynnistää sovelluksen ja käyttää todellista MCP SDK -asiakassiirtoa
- A2A-asiakas testaa virtojen löytämistä, lähettämistä, suoratoistoa, vastaanottamista ja peruuttamista
- Tarkista väitteet MCP-tarkastuksen ja A2A-tehtävien sovellusliittymien kanssa
</details>
<details>
<summary><b>📡 28. "Tarvitsen yhtenäisen havainnoinnin kaikissa liitännöissä"</b></summary>
Havainnon jakaminen protokollan mukaan luo kuolleita kulmia ja pidemmän MTTR:n.
**Kuinka OmniRoute ratkaisee sen:**
- Yhdistetyt kojelaudat/lokit/analytiikka yhdessä tuotteessa
- Terveys + auditointi + pyyntö telemetria OpenAI-, MCP- ja A2A-tasoilla
- Toiminnalliset sovellusliittymät tilaa ja automaatiota varten
</details>
<details>
<summary><b>💼 29. "Tarvitsen yhden suoritusajan välityspalvelimelle + työkaluille + agentin orkestraatiolle"</b></summary>
Useiden erillisten palvelujen suorittaminen lisää käyttökustannuksia ja vikatiloja.
**Kuinka OmniRoute ratkaisee sen:**
- OpenAI-yhteensopiva välityspalvelin, MCP-palvelin ja A2A-palvelin yhdessä pinossa
- Jaettu todennus, joustavuus, tietovarasto ja havaittavuus
- Yhdenmukainen toimintamalli kaikilla vuorovaikutuspinnoilla
</details>
<details>
<summary><b>🚀 30. "Minun on lähetettävä agenttityönkulkuja ilman liimakoodin leviämistä"</b></summary>
Tiimit menettävät nopeutta yhdistäessään useita ad-hoc-palveluita ja skriptejä.
**Kuinka OmniRoute ratkaisee sen:**
- Yhtenäinen päätepistestrategia asiakkaille ja edustajille
- Sisäänrakennetut protokollien hallinnan käyttöliittymät ja savun vahvistuspolut
- Tuotantovalmis perusta (turvallisuus, puunkorjuu, joustavuus, varmuuskopiointi)
</details>
### Esimerkkiohjekirjat (integroidut käyttötapaukset)
**Ohjekirja A: maksimoi maksullinen tilaus + halpa varmuuskopio**
```txt
Combo: "maximize-claude"
1. cc/claude-opus-4-6
2. glm/glm-4.7
3. if/kimi-k2-thinking
Monthly cost: $20 + small backup spend
Outcome: higher quality, near-zero interruption
```
**Ohjekirja B: Nollahintainen koodauspino**
```txt
Combo: "free-forever"
1. gc/gemini-3-flash
2. if/kimi-k2-thinking
3. qw/qwen3-coder-plus
Monthly cost: $0
Outcome: stable free coding workflow
```
**Playbook C: 24/7 aina päällä oleva varaketju**
```txt
Combo: "always-on"
1. cc/claude-opus-4-6
2. cx/gpt-5.2-codex
3. glm/glm-4.7
4. minimax/MiniMax-M2.1
5. if/kimi-k2-thinking
Outcome: deep fallback depth for deadline-critical workloads
```
**Pelikirja D: Agentti toimii MCP:llä + A2A**
```txt
1) Start MCP transport (`omniroute --mcp`) for tool-driven operations
2) Run A2A tasks via `message/send` and `message/stream`
3) Observe via /dashboard/mcp and /dashboard/a2a
4) Control incidents with resilience profile + task cancellation
```
---
## ⚡ Pika-aloitus
**1. Asenna maailmanlaajuisesti:**
@@ -251,7 +782,7 @@ docker compose --profile cli up -d
---
## 🖥️ Desktop App — Offline & Always-On
## 🖥️
> 🆕 **NEW!** OmniRoute is now available as a **native desktop application** for Windows, macOS, and Linux.
@@ -298,67 +829,6 @@ npm run electron:build:linux # Linux (.AppImage)
---
## 🎯 Käyttökotelot
### Tapaus 1: "Minulla on Claude Pro -tilaus"
**Ongelma:** Kiintiö vanhenee käyttämättä, nopeusrajoitukset raskaan koodauksen aikana
```
Combo: "maximize-claude"
1. cc/claude-opus-4-6 (use subscription fully)
2. glm/glm-4.7 (cheap backup when quota out)
3. if/kimi-k2-thinking (free emergency fallback)
Monthly cost: $20 (subscription) + ~$5 (backup) = $25 total
vs. $20 + hitting limits = frustration
```
### Tapaus 2: "Haluan ilman kustannuksia"
**Ongelma:** Ei ole varaa tilauksiin, tarvitaan luotettavaa tekoälykoodausta
```
Combo: "free-forever"
1. gc/gemini-3-flash (180K free/month)
2. if/kimi-k2-thinking (unlimited free)
3. qw/qwen3-coder-plus (unlimited free)
Monthly cost: $0
Quality: Production-ready models
```
### Tapaus 3: "Tarvitsen 24/7-koodausta, ei keskeytyksiä"
**Ongelma:** Määräajat, seisokkeihin ei ole varaa
```
Combo: "always-on"
1. cc/claude-opus-4-6 (best quality)
2. cx/gpt-5.2-codex (second subscription)
3. glm/glm-4.7 (cheap, resets daily)
4. minimax/MiniMax-M2.1 (cheapest, 5h reset)
5. if/kimi-k2-thinking (free unlimited)
Result: 5 layers of fallback = zero downtime
```
### Tapaus 4: "Haluan ILMAISTA tekoälyä OpenClawissa"
**Ongelma:** Tarvitset AI-avustajan viestisovelluksissa, täysin ilmainen
```
Combo: "openclaw-free"
1. if/glm-4.7 (unlimited free)
2. if/minimax-m2.1 (unlimited free)
3. if/kimi-k2-thinking (unlimited free)
Monthly cost: $0
Access via: WhatsApp, Telegram, Slack, Discord, iMessage, Signal...
```
---
## 💡 Tärkeimmät ominaisuudet
### 🧠 Ydinreititys ja älykkyys
@@ -374,6 +844,8 @@ Access via: WhatsApp, Telegram, Slack, Discord, iMessage, Signal...
| 🧩 **Räätälöidyt mallit** | Lisää mikä tahansa mallitunnus mille tahansa toimittajalle |
| 🌐 **Wildcard-reititin** | Reititä `provider/*` mallit mille tahansa palveluntarjoajalle dynaamisesti |
| 🧠 **Ajatteleva budjetti** | Läpivienti-, automaatti-, mukautetut ja mukautuvat tilat päättelymalleille |
| 🔀 **Model Aliases** | Auto-forward deprecated model IDs to current replacements (built-in + custom) |
| ⚡ **Background Degradation** | Auto-route background tasks (titles, summaries) to cheaper models |
| 💬 **Järjestelmän pikaruiskutus** | Maailmanlaajuinen järjestelmäkehote käytössä kaikissa pyynnöissä |
| 📄 **Responses API** | Täysi OpenAI Responses API (`/v1/responses`) tuki Codexille |
@@ -399,6 +871,8 @@ Access via: WhatsApp, Telegram, Slack, Discord, iMessage, Signal...
| 🔒 **TLS-sormenjälkien huijaus** | Ohita TLS-pohjainen bot-tunnistus wreq-js:n avulla |
| 🌐 **IP-suodatus** | API-käyttöoikeuksien hallinnan sallittu-/estoluettelo |
| 📊 **Muokattavat hintarajat** | Konfiguroitava kierrosluku, minimiväli ja suurin samanaikainen järjestelmätasolla |
| 💾 **Rate Limit Persistence** | Learned limits survive restarts via SQLite with 60s debounce + 24h staleness |
| 🔄 **Token Refresh Resilience** | Per-provider circuit breaker (5 fails→30min) + 30s timeout per attempt |
| 🛡 **API Endpoint Protection** | Todennusportin + tarjoajan esto `/models`-päätepisteelle |
| 🔒 **Välityspalvelimen näkyvyys** | Värikoodatut merkit: 🟢 maailmanlaajuinen, 🟡 tarjoaja, 🔵 yhteyskohtainen IP-näytöllä |
| 🌐 **3-tason välityspalvelimen määritys** | Määritä välityspalvelimet maailmanlaajuisesti, palveluntarjoajakohtaisesti tai yhteyskohtaisesti |
@@ -517,6 +991,27 @@ OmniRoute sisältää tehokkaan sisäänrakennetun Translator Playgroundin, joss
</details>
## 🧪 Arvioinnit (Evals)
OmniRoute sisältää sisäänrakennetun arviointikehyksen, jolla testataan LLM-vastauksen laatua kultaiseen joukkoon verrattuna. Käytä sitä kojelaudan **Analytics → Evals** kautta.
### Sisäänrakennettu kultainen setti
Esiladattu "OmniRoute Golden Set" sisältää 10 testitapausta, jotka kattavat:
- Tervehdys, matematiikka, maantiede, koodin luominen
- JSON-muodon noudattaminen, käännös, merkintä
- Turvallisuuskielto (haitallinen sisältö), laskenta, boolen logiikka
### Arviointistrategiat
| Strategia | Kuvaus | Esimerkki |
| ---------- | ------------------------------------------------------------------------ | -------------------------------- |
| `exact` | Tulosten on vastattava tarkasti | `"4"` |
| `contains` | Tulosteen tulee sisältää alimerkkijono (kirjainkoolla ei ole merkitystä) | `"Paris"` |
| `regex` | Tulostuksen on vastattava regex-mallia | `"1.*2.*3"` |
| `custom` | Mukautettu JS-funktio palauttaa true/false | `(output) => output.length > 10` |
---
## 📖 Asennusopas
@@ -799,104 +1294,64 @@ Settings → API Configuration:
---
## 📊 Saatavilla olevat mallit
## 🐛 Vianetsintä
<details>
<summary><b>Näytä kaikki saatavilla olevat mallit</b></summary>
<summary><b>Laajenna vianetsintäopas napsauttamalla</b></summary>
**Claude Code (`cc/`)** - Pro/Max:
**"Kielimalli ei antanut viestejä"**
- `cc/claude-opus-4-6`
- `cc/claude-sonnet-4-5-20250929`
- `cc/claude-haiku-4-5-20251001`
- Palveluntarjoajan kiintiö käytetty loppuun → Tarkista kojelaudan kiintiön seuranta
- Ratkaisu: Käytä yhdistelmävaraa tai vaihda halvempaan tasoon
**Koodi (`cx/`)** - Plus/Pro:
**hintarajoitus**
- `cx/gpt-5.2-codex`
- `cx/gpt-5.1-codex-max`
- Tilauskiintiö loppu → Varaa GLM/MiniMaxiin
- Lisää yhdistelmä: `cc/claude-opus-4-6 → glm/glm-4.7 → if/kimi-k2-thinking`
**Gemini CLI (`gc/`)** - ILMAINEN:
**OAuth-tunnus vanhentunut**
- `gc/gemini-3-flash-preview`
- `gc/gemini-2.5-pro`
- OmniRoute päivittää automaattisesti
- Jos ongelmat jatkuvat: Kojelauta → Palveluntarjoaja → Yhdistä uudelleen
**GitHub Copilot (`gh/`)**:
**Korkeat kustannukset**
- `gh/gpt-5`
- `gh/claude-4.5-sonnet`
- Tarkista käyttötilastot kohdassa Dashboard → Costs
- Vaihda ensisijaiseksi malliksi GLM/MiniMax
- Käytä ilmaista tasoa (Gemini CLI, iFlow) ei-kriittisiin tehtäviin
**NVIDIA NIM (`nvidia/`)** - ILMAISIA krediittejä:
**Kojelauta avautuu väärään porttiin**
- `nvidia/llama-3.3-70b-instruct`
- `nvidia/mistral-7b-instruct`
- Yli 50 mallia [build.nvidia.com](https://build.nvidia.com)
- Aseta `PORT=20128` ja `NEXT_PUBLIC_BASE_URL=http://localhost:20128`
**GLM (`glm/`)** - 0,6 $/1 milj.:
**Pilvisynkronointivirheet**
- `glm/glm-4.7`
- Vahvista `BASE_URL` pistettä käynnissä olevaan esiintymääsi
- Vahvista `CLOUD_URL` pistettä odotettuun pilvipäätepisteeseen
- Pidä `NEXT_PUBLIC_*`-arvot kohdakkain palvelinpuolen arvojen kanssa
**MiniMax (`minimax/`)** - 0,2 $/1 milj.
**Ensimmäinen kirjautuminen ei toimi**
- `minimax/MiniMax-M2.1`
- Tarkista `INITIAL_PASSWORD` kohteessa `.env`
- Jos ei ole asetettu, varasalasana on `123456`
**iFlow (`if/`)** - ILMAINEN:
**Ei pyyntölokeja**
- `if/kimi-k2-thinking`
- `if/qwen3-coder-plus`
- `if/deepseek-r1`
- `if/glm-4.7`
- `if/minimax-m2`
- Aseta `ENABLE_REQUEST_LOGS=true` kohteeseen `.env`
**Qwen (`qw/`)** - ILMAINEN:
**Yhteystesti näyttää "Virheellinen" OpenAI-yhteensopiville palveluntarjoajille**
- `qw/qwen3-coder-plus`
- `qw/qwen3-coder-flash`
- Monet palveluntarjoajat eivät paljasta `/models`-päätepistettä
- OmniRoute v1.0.6+ sisältää varatarkistuksen chatin loppuunsaattamisen kautta
- Varmista, että perus-URL sisältää `/v1`-liitteen
**Kiro (`kr/`)** - ILMAINEN:
- `kr/claude-sonnet-4.5`
- `kr/claude-haiku-4.5`
**OpenRouter (`or/`)** - 100+ mallia:
- `or/anthropic/claude-4-sonnet`
- `or/google/gemini-2.5-pro`
- Mikä tahansa malli alkaen [openrouter.ai/models](https://openrouter.ai/models)
</details>
---
## 🧪 Arvioinnit (Evals)
OmniRoute sisältää sisäänrakennetun arviointikehyksen, jolla testataan LLM-vastauksen laatua kultaiseen joukkoon verrattuna. Käytä sitä kojelaudan **Analytics → Evals** kautta.
### Sisäänrakennettu kultainen setti
Esiladattu "OmniRoute Golden Set" sisältää 10 testitapausta, jotka kattavat:
- Tervehdys, matematiikka, maantiede, koodin luominen
- JSON-muodon noudattaminen, käännös, merkintä
- Turvallisuuskielto (haitallinen sisältö), laskenta, boolen logiikka
### Arviointistrategiat
| Strategia | Kuvaus | Esimerkki |
| ---------- | ------------------------------------------------------------------------ | -------------------------------- |
| `exact` | Tulosten on vastattava tarkasti | `"4"` |
| `contains` | Tulosteen tulee sisältää alimerkkijono (kirjainkoolla ei ole merkitystä) | `"Paris"` |
| `regex` | Tulostuksen on vastattava regex-mallia | `"1.*2.*3"` |
| `custom` | Mukautettu JS-funktio palauttaa true/false | `(output) => output.length > 10` |
---
## 🔐 OAuth em Servidor Remoto (OAuth-etäasetus)
### 🔐 OAuth
<a name="oauth-em-servidor-remoto"></a>
> **⚠️ TÄRKEÄÄ käyttäjille com OmniRoute em VPS/Docker/servidor Remoto**
### Onko OAuth do Antigravity / Gemini CLI falha em servidores Remotos?
### OAuth
Os provedores **Antigravity** ja **Gemini CLI** usam **Google OAuth 2.0** para autenticação. O Google exige que a `redirect_uri` usada no fluxo OAuth seja **exatamente** uma das URIs pre-cadastradas no Google Cloud Console do aplicativo.
@@ -969,7 +1424,7 @@ Agora o Google redirecionará corretamente para `https://seu-servidor.com/callba
---
### Workaround temporário (sem configurar credenciais próprias)
#### Workaround temporário (sem configurar credenciais próprias)
Se não quiser criar credenciais próprias agora, ainda é possível usar o fluxo **manual de URL**:
@@ -981,64 +1436,11 @@ Se não quiser criar credenciais próprias agora, ainda é possível usar o flux
> Este workaround funciona porque o código de autorização na URL é válido independente do redirect ter carregado ou não.
---
## 🐛 Vianetsintä
<details>
<summary><b>Laajenna vianetsintäopas napsauttamalla</b></summary>
**"Kielimalli ei antanut viestejä"**
- Palveluntarjoajan kiintiö käytetty loppuun → Tarkista kojelaudan kiintiön seuranta
- Ratkaisu: Käytä yhdistelmävaraa tai vaihda halvempaan tasoon
**hintarajoitus**
- Tilauskiintiö loppu → Varaa GLM/MiniMaxiin
- Lisää yhdistelmä: `cc/claude-opus-4-6 → glm/glm-4.7 → if/kimi-k2-thinking`
**OAuth-tunnus vanhentunut**
- OmniRoute päivittää automaattisesti
- Jos ongelmat jatkuvat: Kojelauta → Palveluntarjoaja → Yhdistä uudelleen
**Korkeat kustannukset**
- Tarkista käyttötilastot kohdassa Dashboard → Costs
- Vaihda ensisijaiseksi malliksi GLM/MiniMax
- Käytä ilmaista tasoa (Gemini CLI, iFlow) ei-kriittisiin tehtäviin
**Kojelauta avautuu väärään porttiin**
- Aseta `PORT=20128` ja `NEXT_PUBLIC_BASE_URL=http://localhost:20128`
**Pilvisynkronointivirheet**
- Vahvista `BASE_URL` pistettä käynnissä olevaan esiintymääsi
- Vahvista `CLOUD_URL` pistettä odotettuun pilvipäätepisteeseen
- Pidä `NEXT_PUBLIC_*`-arvot kohdakkain palvelinpuolen arvojen kanssa
**Ensimmäinen kirjautuminen ei toimi**
- Tarkista `INITIAL_PASSWORD` kohteessa `.env`
- Jos ei ole asetettu, varasalasana on `123456`
**Ei pyyntölokeja**
- Aseta `ENABLE_REQUEST_LOGS=true` kohteeseen `.env`
**Yhteystesti näyttää "Virheellinen" OpenAI-yhteensopiville palveluntarjoajille**
- Monet palveluntarjoajat eivät paljasta `/models`-päätepistettä
- OmniRoute v1.0.6+ sisältää varatarkistuksen chatin loppuunsaattamisen kautta
- Varmista, että perus-URL sisältää `/v1`-liitteen
</details>
---
## 🛠️ Tech Stack
## 🛠️
- **Suoritusaika**: Node.js 1822 LTS (⚠️ Node.js 24+ -versiota **ei tueta**`better-sqlite3` alkuperäiset binaarit eivät ole yhteensopivia)
- **Kieli**: TypeScript 5.9 — **100 % TypeScript** `src/` ja `open-sse/` (v1.0.6) välillä
@@ -1090,7 +1492,7 @@ Se não quiser criar credenciais próprias agora, ainda é possível usar o flux
---
## 🗺️ Etenemissuunnitelma
## 🗺️
OmniRoutella on **210+ suunniteltua ominaisuutta** useissa kehitysvaiheissa. Tässä ovat tärkeimmät alueet:
@@ -1115,18 +1517,6 @@ OmniRoutella on **210+ suunniteltua ominaisuutta** useissa kehitysvaiheissa. Tä
---
## 📧 Tuki
> 💬 **Liity yhteisöömme!** [WhatsApp Group](https://chat.whatsapp.com/JI7cDQ1GyaiDHhVBpLxf8b?mode=gi_t) — Hanki apua, jaa vinkkejä ja pysy ajan tasalla.
- **Verkkosivusto**: [omniroute.online](https://omniroute.online)
- **GitHub**: [github.com/diegosouzapw/OmniRoute](https://github.com/diegosouzapw/OmniRoute)
- **Ongelmia**: [github.com/diegosouzapw/OmniRoute/issues](https://github.com/diegosouzapw/OmniRoute/issues)
- **WhatsApp**: [Community Group](https://chat.whatsapp.com/JI7cDQ1GyaiDHhVBpLxf8b?mode=gi_t)
- **Alkuperäinen projekti**: [9router by decolua](https://github.com/decolua/9router)
---
## 👥 Avustajat
[![Contributors](https://contrib.rocks/image?repo=diegosouzapw/OmniRoute&max=100&columns=20&anon=1)](https://github.com/diegosouzapw/OmniRoute/graphs/contributors)
@@ -1176,85 +1566,6 @@ MIT-lisenssi katso lisätietoja osoitteesta [LICENSE](LICENSE).
---
---
## 🇧🇷 OmniRoute — Gateway de IA Gratuito
<a name="-omniroute--gateway-de-ia-gratuito"></a>
### Nunca pare de codar. Roteamento inteligente para **mallit de IA GRATUITOS e de baixo custo** com backback automático.
_Seu välityspalvelin universaali de API — um päätepiste, 36+ valmistajaa, nolla seisokkeja._
### 🌐 Internacionalização (i18n)
OmniRoute-kojelauta tukee **múltiplos idiomas**. Atualmente disponível em:
| Idioma | Código | Tila |
| ----------------------- | ------- | -------------- |
| 🇺🇸 englanti | `en` | ✅ Täydellinen |
| 🇧🇷 Português (Brasilia) | `pt-BR` | ✅ Täydellinen |
**Para trocar o idioma:** Clique no seletor de idioma (🇺🇸 FI) no header do dashboard → selecione o idioma desejado.
**Para adicionar um novo idioma:**
1. Itke `src/i18n/messages/{codigo}.json` baseado em `en.json`
2. Adicione o código em `src/i18n/config.ts``LOCALES` ja `LANGUAGES`
3. Reinicie o servidor
### ⚡ Início Rápido
```bash
# Instalar via npm
npx omniroute@latest
# Ou rodar do código-fonte
cp .env.example .env
npm install
PORT=20128 NEXT_PUBLIC_BASE_URL=http://localhost:20128 npm run dev
```
### 🐳 Docker
```bash
docker run -d --name omniroute -p 20128:20128 diegosouzapw/omniroute:latest
```
### 🔑 Funcionalidades Principais
- **36+ IA:n tuottajaa** Claude, GPT, Gemini, Llama, Qwen, DeepSeek, e mais
- **Roteamento inteligente** — Varastoautomatico entre provedores
- **Tradução de formato** — OpenAI ↔ Claude ↔ Gemini automaticamente
- **Multi-conta** — Múltiplas contas por provedor com seleção inteligente
- **Cache semântico** - Reduz custos e latência
- **OAuth automático** — Tokens renovam automaticamente
- **Yhdistelmät personoidut** - 6 estratégias de roteamento
- **Dashboard Completo** - Monitoramento, lokit, analyysit, konfiguraatiot
- **CLI-työkalut** — Määritä Claude Code, Codex, Cursor, Cline com um clique
- **100 % TypeScript** - Código limpo e tipado
### 📖 Documentação
| Documento | Kuvaus |
| ----------------------------------------------- | ------------------------------------------- |
| [Guia do Usuário](docs/USER_GUIDE.md) | Provedorit, yhdistelmät, CLI, käyttöönotto |
| [Referência da API](docs/API_REFERENCE.md) | Todos os päätepisteet com exemplos |
| [Solução de Problemas](docs/TROUBLESHOOTING.md) | Problemas comuns e soluções |
| [Arquitetura](docs/ARCHITECTURE.md) | Arquitetura e internos do system |
| [Contribuição](CONTRIBUTING.md) | Desenvolvimento e -ohjeiden asennus |
| [Deploy em VM](docs/VM_DEPLOYMENT_GUIDE.md) | Täydellinen versio: VM + nginx + Cloudflare |
### 📧 Tuki
> 💬 **Entre para a comunidade!** [Grupo WhatsApp](https://chat.whatsapp.com/JI7cDQ1GyaiDHhVBpLxf8b?mode=gi_t) — Tire dúvidas, compartilhe dicas e fique atualizado.
- **Verkkosivusto**: [omniroute.online](https://omniroute.online)
- **GitHub**: [github.com/diegosouzapw/OmniRoute](https://github.com/diegosouzapw/OmniRoute)
- **Ongelmia**: [github.com/diegosouzapw/OmniRoute/issues](https://github.com/diegosouzapw/OmniRoute/issues)
---
<div align="center">
<sub>Rakennettu ❤️-kehittäjille, jotka koodaavat 24/7</sub>
<br/>

View File

@@ -110,6 +110,35 @@ _Connectez n'importe quel IDE ou outil CLI alimenté par l'IA via OmniRoute —
---
## 🖼️
<div align="center">
<img src="./docs/screenshots/MainOmniRoute.png" alt="OmniRoute" width="800"/>
</div>
---
## 📸
<details>
<summary><b>...</b></summary>
| # | # |
| ----- | ---------------------------------------- |
| **1** | ![1](docs/screenshots/01-providers.png) |
| **2** | ![2](docs/screenshots/02-combos.png) |
| **3** | ![3](docs/screenshots/03-analytics.png) |
| **4** | ![4](docs/screenshots/04-health.png) |
| **5** | ![5](docs/screenshots/05-translator.png) |
| **6** | ![6](docs/screenshots/06-settings.png) |
| **7** | ![7](docs/screenshots/07-cli-tools.png) |
| **8** | ![8](docs/screenshots/08-usage.png) |
| **9** | ![9](docs/screenshots/09-endpoint.png) |
</details>
---
## 🤔 Pourquoi OmniRoute ?
**Arrêtez de gaspiller de l'argent et de vous heurter aux limites :**
@@ -128,6 +157,18 @@ _Connectez n'importe quel IDE ou outil CLI alimenté par l'IA via OmniRoute —
---
## 📧 Support
> 💬 **Rejoignez notre communauté !** [Groupe WhatsApp](https://chat.whatsapp.com/JI7cDQ1GyaiDHhVBpLxf8b?mode=gi_t) — Obtenez de l'aide, partagez des astuces et restez informé.
- **Site web** : [omniroute.online](https://omniroute.online)
- **GitHub** : [github.com/diegosouzapw/OmniRoute](https://github.com/diegosouzapw/OmniRoute)
- **Issues** : [github.com/diegosouzapw/OmniRoute/issues](https://github.com/diegosouzapw/OmniRoute/issues)
- **WhatsApp** : [Groupe communautaire](https://chat.whatsapp.com/JI7cDQ1GyaiDHhVBpLxf8b?mode=gi_t)
- **Projet original** : [9router par decolua](https://github.com/decolua/9router)
---
## 🔄 Comment ça fonctionne
```
@@ -157,6 +198,497 @@ Résultat : Ne jamais arrêter de coder, coût minimal
---
## 🎯 Ce qu'OmniRoute résout : 30 problèmes réels et cas d'utilisation
> **Tous les développeurs utilisant des outils d'IA sont confrontés quotidiennement à ces problèmes.** OmniRoute a été conçu pour tous les résoudre : des dépassements de coûts aux blocages régionaux, des flux OAuth interrompus aux opérations de protocole et à l'observabilité de l'entreprise.
<details>
<summary><b>💸 1. "Je paie un abonnement coûteux mais je suis quand même interrompu par des limites" </b></summary>
Les développeurs paient entre 20 et 200 $/mois pour Claude Pro, Codex Pro ou GitHub Copilot. Même payant, le quota est plafonné : 5 heures d'utilisation, limites hebdomadaires ou limites de tarif à la minute. En cours de session de codage, le fournisseur ne répond plus et le développeur perd en fluidité et en productivité.
**Comment OmniRoute le résout :**
- **Smart 4-Tier Fallback** — Si le quota d'abonnement est épuisé, redirige automatiquement vers la clé API → Pas cher → Gratuit sans intervention manuelle
- **Suivi des quotas en temps réel** — Affiche la consommation de jetons en temps réel avec un compte à rebours réinitialisé (5 h, quotidiennement, hebdomadairement)
- **Support multi-comptes** — Plusieurs comptes par fournisseur avec tourniquet automatique — lorsqu'un compte est épuisé, passe au suivant
- **Combos personnalisés** — Chaînes de secours personnalisables avec 6 stratégies d'équilibrage (remplir en premier, round-robin, P2C, aléatoire, les moins utilisées, optimisées en termes de coûts)
- **Codex Business Quotas** — Surveillance des quotas d'espace de travail Business/Équipe directement dans le tableau de bord
</details>
<details>
<summary><b>🔌 2. "Je dois utiliser plusieurs fournisseurs mais chacun a une API différente" </b></summary>
OpenAI utilise un format, Claude (Anthropic) en utilise un autre, Gemini encore un autre. Si un développeur souhaite tester des modèles de différents fournisseurs ou utiliser un modèle de secours entre eux, il doit reconfigurer les SDK, modifier les points de terminaison et gérer les formats incompatibles. Les fournisseurs personnalisés (FriendLI, NIM) ont des points de terminaison de modèle non standard.
**Comment OmniRoute le résout :**
- **Point de terminaison unifié** : un seul `http://localhost:20128/v1` sert de proxy pour les plus de 36 fournisseurs.
- **Traduction de format** — Automatique et transparente : OpenAI ↔ Claude ↔ Gemini ↔ API Responses
- **Response Sanitization** — Supprime les champs non standard (`x_groq`, `usage_breakdown`, `service_tier`) qui cassent OpenAI SDK v1.83+
- **Role Normalization** — Convertit `developer``system` pour les fournisseurs non OpenAI ; `system``user` pour GLM/ERNIE
- **Think Tag Extraction** — Extrait les blocs `<think>` de modèles comme DeepSeek R1 dans un `reasoning_content` standardisé.
- **Sortie structurée pour Gemini** — Conversion automatique `json_schema``responseMimeType`/`responseSchema`
- **`stream` est par défaut `false`** — S'aligne sur les spécifications OpenAI, évitant ainsi le SSE inattendu dans les SDK Python/Rust/Go
</details>
<details>
<summary><b>🌐 3. "Mon fournisseur d'IA bloque ma région/pays" </b></summary>
Des fournisseurs comme OpenAI/Codex bloquent laccès depuis certaines régions géographiques. Les utilisateurs obtiennent des erreurs telles que `unsupported_country_region_territory` lors des connexions OAuth et API. Ceci est particulièrement frustrant pour les développeurs des pays en développement.
**Comment OmniRoute le résout :**
- **Configuration proxy à 3 niveaux** — Proxy configurable à 3 niveaux : global (tout le trafic), par fournisseur (un seul fournisseur) et par connexion/clé
- **Badges proxy à code couleur** — Indicateurs visuels : 🟢 proxy global, 🟡 proxy fournisseur, 🔵 proxy de connexion, affichant toujours l'adresse IP
- **Échange de jetons OAuth via proxy** — Le flux OAuth passe également par le proxy, résolvant `unsupported_country_region_territory`
- **Tests de connexion via proxy** — Les tests de connexion utilisent le proxy configuré (plus de contournement direct)
- **Support SOCKS5** — Prise en charge complète du proxy SOCKS5 pour le routage sortant
- **TLS Fingerprint Spoofing** — Empreinte digitale TLS de type navigateur via `wreq-js` pour contourner la détection des robots
</details>
<details>
<summary><b>🆓 4. "Je veux utiliser l'IA pour coder mais je n'ai pas d'argent"</b></summary>
Tout le monde ne peut pas payer entre 20 et 200 $/mois pour des abonnements à lIA. Les étudiants, les développeurs des pays émergents, les amateurs et les indépendants doivent avoir accès à des modèles de qualité à un coût nul.
**Comment OmniRoute le résout :**
- **Fournisseurs gratuits intégrés** — Prise en charge native des fournisseurs 100 % gratuits : iFlow (8 modèles illimités), Qwen (3 modèles illimités), Kiro (Claude gratuit), Gemini CLI (180 000 /mois gratuits)
- **Combos gratuits uniquement** — Chaîne `gc/gemini-3-flash → if/kimi-k2-thinking → qw/qwen3-coder-plus` = 0 $/mois sans temps d'arrêt
- **Crédits gratuits NVIDIA NIM** — 1 000 crédits gratuits intégrés
- **Stratégie d'optimisation des coûts** — Stratégie de routage qui choisit automatiquement le fournisseur disponible le moins cher
</details>
<details>
<summary><b>🔒 5. "Je dois protéger ma passerelle IA contre les accès non autorisés" </b></summary>
Lors de l'exposition d'une passerelle IA au réseau (LAN, VPS, Docker), toute personne possédant l'adresse peut consommer les jetons/quota du développeur. Sans protection, les API sont vulnérables aux utilisations abusives, aux injections rapides et aux abus.
**Comment OmniRoute le résout :**
- **Gestion des clés API** — Génération, rotation et portée par fournisseur avec une page `/dashboard/api-manager` dédiée
- **Autorisations au niveau du modèle** : restreindre les clés API à des modèles spécifiques (`openai/*`, modèles génériques), avec la bascule Autoriser tout/Restreindre
- **API Endpoint Protection**  exige une clé pour `/v1/models` et bloque des fournisseurs spécifiques de la liste
- **Auth Guard + Protection CSRF** — Toutes les routes du tableau de bord protégées avec le middleware `withAuth` + les jetons CSRF
- **Rate Limiter** — Limitation du débit par IP avec fenêtres configurables
- **Filtrage IP**  Liste autorisée/liste de blocage pour le contrôle d'accès
- **Prompt Injection Guard** — Nettoyage contre les modèles d'invite malveillants
- **Chiffrement AES-256-GCM** — Informations d'identification chiffrées au repos
</details>
<details>
<summary><b>🛑 6. "Mon fournisseur est tombé en panne et j'ai perdu mon flux de codage"</b></summary>
Les fournisseurs dIA peuvent devenir instables, renvoyer des erreurs 5xx ou atteindre des limites de débit temporaires. Si un développeur dépend d'un seul fournisseur, il est interrompu. Sans disjoncteurs, des tentatives répétées peuvent faire planter lapplication.
**Comment OmniRoute le résout :**
- **Disjoncteur par fournisseur** — Ouverture/fermeture automatique avec seuils et temps de recharge configurables (Fermé/Ouvert/Semi-ouvert)
- **Exponential Backoff** — Délais progressifs entre les tentatives
- **Anti-Thundering Herd** — Protection mutex + sémaphore contre les tempêtes de nouvelles tentatives simultanées
- **Chaînes de secours combinées** — Si le fournisseur principal échoue, passe automatiquement à travers la chaîne sans intervention
- **Combo Circuit Breaker**  Désactive automatiquement les fournisseurs défaillants au sein d'une chaîne combo
- **Tableau de bord de santé** — Surveillance de la disponibilité, états des disjoncteurs, verrouillages, statistiques du cache, latence p50/p95/p99
</details>
<details>
<summary><b>🔧 7. "La configuration de chaque outil d'IA est fastidieuse et répétitive"</b></summary>
Les développeurs utilisent Cursor, Claude Code, Codex CLI, OpenClaw, Gemini CLI, Kilo Code... Chaque outil nécessite une configuration différente (point de terminaison API, clé, modèle). La reconfiguration lors du changement de fournisseur ou de modèle est une perte de temps.
**Comment OmniRoute le résout :**
- **CLI Tools Dashboard** — Page dédiée avec configuration en un clic pour Claude Code, Codex CLI, OpenClaw, Kilo Code, Antigravity, Cline
- **GitHub Copilot Config Generator** — Génère `chatLanguageModels.json` pour VS Code avec sélection groupée de modèles
- **Assistant d'intégration** — Configuration guidée en 4 étapes pour les nouveaux utilisateurs
- **Un point de terminaison, tous les modèles**  Configurez `http://localhost:20128/v1` une fois, accédez à plus de 36 fournisseurs
</details>
<details>
<summary><b>🔑 8. "Gérer les jetons OAuth de plusieurs fournisseurs est un enfer"</b></summary>
Claude Code, Codex, Gemini CLI, Copilot — tous utilisent OAuth 2.0 avec des jetons expirant. Les développeurs doivent se réauthentifier constamment, gérer `client_secret is missing`, `redirect_uri_mismatch` et les pannes sur les serveurs distants. OAuth sur LAN/VPS est particulièrement problématique.
**Comment OmniRoute le résout :**
- **Actualisation automatique des jetons** : les jetons OAuth sont actualisés en arrière-plan avant leur expiration.
- **OAuth 2.0 (PKCE) intégré** — Flux automatique pour Claude Code, Codex, Gemini CLI, Copilot, Kiro, Qwen, iFlow
- **Multi-Account OAuth** — Plusieurs comptes par fournisseur via l'extraction de jetons JWT/ID
- **OAuth LAN/Remote Fix** — Détection IP privée pour `redirect_uri` + mode URL manuel pour les serveurs distants
- **OAuth derrière Nginx** — Utilise `window.location.origin` pour la compatibilité du proxy inverse
- **Guide OAuth à distance** — Guide étape par étape pour les informations d'identification Google Cloud sur VPS/Docker
</details>
<details>
<summary><b>📊 9. "Je ne sais pas combien je dépense ni où" </b></summary>
Les développeurs utilisent plusieurs fournisseurs payants mais n'ont pas de vue unifiée des dépenses. Chaque fournisseur dispose de son propre tableau de bord de facturation, mais il n'existe pas de vue consolidée. Les coûts inattendus peuvent saccumuler.
**Comment OmniRoute le résout :**
- **Cost Analytics Dashboard** — Suivi des coûts par jeton et gestion du budget par fournisseur
- **Limites budgétaires par niveau** — Plafond de dépenses par niveau qui déclenche un repli automatique
- **Configuration de tarification par modèle** — Prix configurables par modèle
- **Statistiques d'utilisation par clé API** — Nombre de demandes et horodatage de la dernière utilisation par clé
- **Tableau de bord Analytics** — Cartes statistiques, tableau d'utilisation du modèle, tableau des fournisseurs avec taux de réussite et latence
</details>
<details>
<summary><b>🐛 10. "Je ne peux pas diagnostiquer les erreurs et les problèmes dans les appels IA" </b></summary>
Lorsqu'un appel échoue, le développeur ne sait pas s'il s'agit d'une limite de débit, d'un jeton expiré, d'un format incorrect ou d'une erreur du fournisseur. Journaux fragmentés sur différents terminaux. Sans observabilité, le débogage est un essai et une erreur.
**Comment OmniRoute le résout :**
- **Tableau de bord des journaux unifiés** — 4 onglets : journaux de requêtes, journaux proxy, journaux d'audit, console
- **Console Log Viewer** — Visualiseur de style terminal en temps réel avec niveaux de code couleur, défilement automatique, recherche, filtre
- **Journaux du proxy SQLite** — Journaux persistants qui survivent aux redémarrages du serveur
- **Translator Playground** — 4 modes de débogage : Playground (traduction de format), Chat Tester (aller-retour), Test Bench (batch), Live Monitor (temps réel)
- **Demande de télémétrie** — latence p50/p95/p99 + traçage X-Request-Id
- **Journalisation basée sur des fichiers avec rotation** — L'intercepteur de console capture tout dans le journal JSON avec une rotation basée sur la taille
</details>
<details>
<summary><b>🏗️ 11. "Le déploiement et la maintenance de la passerelle sont complexes"</b></summary>
L'installation, la configuration et la maintenance d'un proxy IA dans différents environnements (local, VPS, Docker, cloud) demandent beaucoup de main-d'œuvre. Des problèmes tels que les chemins codés en dur, `EACCES` sur les répertoires, les conflits de ports et les versions multiplateformes ajoutent des frictions.
**Comment OmniRoute le résout :**
- **Installation globale npm** — `npm install -g omniroute && omniroute` — terminée
- **Docker Multi-Platform** — AMD64 + ARM64 natif (Apple Silicon, AWS Graviton, Raspberry Pi)
- **Profils Docker Compose** — `base` (pas d'outils CLI) et `cli` (avec Claude Code, Codex, OpenClaw)
- **Electron Desktop App** — Application native pour Windows/macOS/Linux avec barre d'état système, démarrage automatique et mode hors ligne
- **Mode Split-Port** — API et tableau de bord sur des ports séparés pour des scénarios avancés (proxy inverse, réseau de conteneurs)
- **Cloud Sync**  Configurez la synchronisation entre les appareils via Cloudflare Workers
- **Sauvegardes DB** — Sauvegarde, restauration, exportation et importation automatiques de tous les paramètres
</details>
<details>
<summary><b>🌍 12. "L'interface est uniquement en anglais et mon équipe ne parle pas anglais" </b></summary>
Les équipes des pays non anglophones, notamment en Amérique latine, en Asie et en Europe, ont du mal à utiliser des interfaces uniquement en anglais. Les barrières linguistiques réduisent ladoption et augmentent les erreurs de configuration.
**Comment OmniRoute le résout :**
- **Tableau de bord i18n — 30 langues** — Plus de 500 touches traduites, dont arabe, bulgare, danois, allemand, espagnol, finnois, français, hébreu, hindi, hongrois, indonésien, italien, japonais, coréen, malais, néerlandais, norvégien, polonais, portugais (PT/BR), roumain, russe, slovaque, suédois, thaï, ukrainien, vietnamien, chinois, philippin, anglais.
- **Support RTL** — Prise en charge de droite à gauche pour l'arabe et l'hébreu
- ** README multilingues ** — 30 traductions complètes de la documentation
- **Sélecteur de langue** — Icône de globe dans l'en-tête pour une commutation en temps réel
</details>
<details>
<summary><b>🔄 13. "J'ai besoin de plus que du chat : j'ai besoin d'intégrations, d'images, d'audio" </b></summary>
L'IA ne se limite pas à la réalisation de discussions. Les développeurs doivent générer des images, transcrire l'audio, créer des intégrations pour RAG, reclasser les documents et modérer le contenu. Chaque API a un point de terminaison et un format différents.
**Comment OmniRoute le résout :**
- **Embeddings** — `/v1/embeddings` avec 6 fournisseurs et plus de 9 modèles
- **Génération d'images** — `/v1/images/generations` avec 10 fournisseurs et plus de 20 modèles (OpenAI, xAI, Together, Fireworks, Nebius, Hyperbolic, NanoBanana, Antigravity, SD WebUI, ComfyUI)
- **Texte vers vidéo** — `/v1/videos/generations` — ComfyUI (AnimateDiff, SVD) et SD WebUI
- **Texte en musique** — `/v1/music/generations` — ComfyUI (Stable Audio Open, MusicGen)
- **Transcription audio** — `/v1/audio/transcriptions` — Whisper + Nvidia NIM, HuggingFace, Qwen3
- **Text-to-Speech** — `/v1/audio/speech` — ElevenLabs, Nvidia NIM, HuggingFace, Coqui, Tortoise, Qwen3, + fournisseurs existants
- **Modérations** — `/v1/moderations` — Contrôles de sécurité du contenu
- **Reclassement** — `/v1/rerank` — Reclassement de la pertinence du document
- **API Réponses** — Prise en charge complète de `/v1/responses` pour le Codex
</details>
<details>
<summary><b>🧪 14. "Je n'ai aucun moyen de tester et de comparer la qualité des modèles" </b></summary>
Les développeurs veulent savoir quel modèle convient le mieux à leur cas d'utilisation (code, traduction, raisonnement) mais la comparaison manuelle est lente. Il nexiste aucun outil dévaluation intégré.
**Comment OmniRoute le résout :**
- **Évaluations LLM** — Tests Golden Set avec 10 cas préchargés couvrant les salutations, les mathématiques, la géographie, la génération de code, la conformité JSON, la traduction, la démarque, le refus de sécurité
- **4 stratégies de correspondance** — `exact`, `contains`, `regex`, `custom` (fonction JS)
- **Banc de test Translator Playground** — Tests par lots avec plusieurs entrées et sorties attendues, comparaison entre fournisseurs
- **Chat Tester** — Aller-retour complet avec rendu de réponse visuelle
- **Live Monitor** — Flux en temps réel de toutes les requêtes transitant par le proxy
</details>
<details>
<summary><b>📈 15. "J'ai besoin d'évoluer sans perdre en performances"</b></summary>
À mesure que le volume de demandes augmente, sans mettre en cache les mêmes questions, cela génère des coûts en double. Sans idempotence, les demandes en double gaspillent le traitement. Les limites tarifaires par fournisseur doivent être respectées.
**Comment OmniRoute le résout :**
- **Cache sémantique** — Le cache à deux niveaux (signature + sémantique) réduit les coûts et la latence
- **Request Idempotency** — Fenêtre de déduplication de 5 s pour des requêtes identiques
- **Détection de limite de débit** — RPM par fournisseur, écart minimum et suivi simultané maximum
- **Limites de débit modifiables** — Valeurs par défaut configurables dans Paramètres → Résilience avec persistance
- **Cache de validation de clé API** — Cache à 3 niveaux pour les performances de production
- **Tableau de bord de santé avec télémétrie** — latence p50/p95/p99, statistiques de cache, disponibilité
</details>
<details>
<summary><b>🤖 16. "Je souhaite contrôler le comportement du modèle à l'échelle mondiale" </b></summary>
Les développeurs qui souhaitent que toutes les réponses soient dans une langue spécifique, avec un ton spécifique, ou qui souhaitent limiter les jetons de raisonnement. Configurer cela dans chaque outil/demande nest pas pratique.
**Comment OmniRoute le résout :**
- **Injection d'invite système** — Invite globale appliquée à toutes les requêtes
- **Thinking Budget Validation** — Contrôle d'allocation de jetons de raisonnement par requête (passthrough, automatique, personnalisé, adaptatif)
- **6 Stratégies de routage**  Stratégies globales qui déterminent la façon dont les demandes sont distribuées
- **Wildcard Router** — Les modèles `provider/*` sont acheminés dynamiquement vers n'importe quel fournisseur.
- **Combo Enable/Disable Toggle** — Basculez les combos directement depuis le tableau de bord
- **Provider Toggle** — Activer/désactiver toutes les connexions pour un fournisseur en un seul clic
- **Fournisseurs bloqués** — Exclure des fournisseurs spécifiques de la liste `/v1/models`
</details>
<details>
<summary><b>🧰 17. "J'ai besoin d'outils MCP en tant que fonctionnalités de produit de première classe" </b></summary>
De nombreuses passerelles IA exposent MCP uniquement en tant que détail d'implémentation caché. Les équipes ont besoin dune couche opérationnelle visible et gérable.
**Comment OmniRoute le résout :**
- MCP apparaît dans l'onglet de navigation du tableau de bord et de protocole de point de terminaison
- Page de gestion MCP dédiée avec processus, outils, portées et audit
- Démarrage rapide intégré pour `omniroute --mcp` et intégration du client
</details>
<details>
<summary><b>🧠 18. "J'ai besoin d'une orchestration A2A avec des chemins de tâches de synchronisation + flux" </b></summary>
Les flux de travail des agents nécessitent à la fois des réponses directes et une exécution en continu de longue durée avec contrôle du cycle de vie.
**Comment OmniRoute le résout :**
- Point de terminaison A2A JSON-RPC (`POST /a2a`) avec `message/send` et `message/stream`
- Streaming SSE avec propagation de l'état terminal
- API de cycle de vie des tâches pour `tasks/get` et `tasks/cancel`
</details>
<details>
<summary><b>🛰️ 19. "J'ai besoin d'un véritable état de santé du processus MCP, et non d'un état deviné" </b></summary>
Les équipes opérationnelles doivent savoir si MCP est réellement actif, et pas seulement si une API est accessible.
**Comment OmniRoute le résout :**
- Fichier de battement de cœur d'exécution avec PID, horodatages, transport, nombre d'outils et mode de portée
- API de statut MCP combinant battement de coeur + activité récente
- Cartes d'état de l'interface utilisateur pour la fraîcheur des processus/disponibilité/battement de cœur
</details>
<details>
<summary><b>📋 20. "J'ai besoin d'une exécution vérifiable de l'outil MCP" </b></summary>
Lorsque les outils modifient la configuration ou déclenchent des actions opérationnelles, les équipes ont besoin d'une traçabilité médico-légale.
**Comment OmniRoute le résout :**
- Journalisation d'audit basée sur SQLite pour les appels d'outils MCP
- Filtres par outil, succès/échec, clé API et pagination
- Tableau d'audit du tableau de bord + points de terminaison de statistiques pour l'automatisation
</details>
<details>
<summary><b>🔐 21. "J'ai besoin d'autorisations MCP limitées par intégration" </b></summary>
Différents clients doivent avoir le moindre privilège daccès aux catégories doutils.
**Comment OmniRoute le résout :**
- 9 étendues MCP granulaires pour un accès contrôlé aux outils
- Application de la portée et visibilité dans l'interface utilisateur de gestion MCP
- Posture par défaut sûre pour les outils opérationnels
</details>
<details>
<summary><b>⚙️ 22. "J'ai besoin de contrôles opérationnels sans redéploiement"</b></summary>
Les équipes ont besoin de changements d'exécution rapides lors d'incidents ou d'événements de coûts.
**Comment OmniRoute le résout :**
- Activer le combo de commutation directement depuis le tableau de bord MCP
- Appliquer des profils de résilience à partir de packs de politiques prédéfinis
- Réinitialiser l'état du disjoncteur à partir du même panneau de commande
</details>
<details>
<summary><b>🔄 23. "J'ai besoin d'une visibilité et d'une annulation en direct du cycle de vie des tâches A2A" </b></summary>
Sans visibilité sur le cycle de vie, les incidents de tâches deviennent difficiles à trier.
**Comment OmniRoute le résout :**
- Liste des tâches/filtrage par état/compétence avec pagination
- Analyse approfondie des métadonnées, des événements et des artefacts des tâches
- Point de terminaison d'annulation de tâche et action de l'interface utilisateur avec confirmation
</details>
<details>
<summary><b>🌊 24. "J'ai besoin de métriques de flux actif pour la charge A2A" </b></summary>
Les flux de travail de streaming nécessitent une vision opérationnelle de la concurrence et des connexions en direct.
**Comment OmniRoute le résout :**
- Compteurs de flux actifs intégrés au statut A2A
- Horodatage de la dernière tâche et nombre par état
- Cartes de tableau de bord A2A pour la surveillance des opérations en temps réel
</details>
<details>
<summary><b>🪪 25. "J'ai besoin d'une découverte d'agent standard pour les clients" </b></summary>
Les clients et orchestrateurs externes ont besoin de métadonnées lisibles par machine pour l'intégration.
**Comment OmniRoute le résout :**
- Carte d'agent exposée à `/.well-known/agent.json`
- Capacités et compétences affichées dans l'interface utilisateur de gestion
- L'API de statut A2A inclut des métadonnées de découverte pour l'automatisation
</details>
<details>
<summary><b>🧭 26. "J'ai besoin de la possibilité de découvrir le protocole dans le produit UX"</b></summary>
Si les utilisateurs ne peuvent pas découvrir les surfaces de protocole, ladoption et la qualité du support chutent.
**Comment OmniRoute le résout :**
- Entrées de la barre latérale pour MCP et A2A
- Onglet Protocoles de la page du point de terminaison avec démarrage rapide et état
- Liens depuis l'aperçu vers les tableaux de bord de gestion dédiés
</details>
<details>
<summary><b>🧪 27. "J'ai besoin d'une validation de protocole de bout en bout avec de vrais clients"</b></summary>
Les tests simulés ne suffisent pas pour valider la compatibilité des protocoles avant la publication.
**Comment OmniRoute le résout :**
- Suite E2E qui démarre l'application et utilise un véritable transport client MCP SDK
- Tests client A2A pour les flux de découverte, d'envoi, de streaming, d'obtention et d'annulation
- Vérifier les assertions par rapport aux API d'audit MCP et de tâches A2A
</details>
<details>
<summary><b>📡 28. "J'ai besoin d'une observabilité unifiée sur toutes les interfaces"</b></summary>
Le fractionnement de l'observabilité par protocole crée des angles morts et un MTTR plus long.
**Comment OmniRoute le résout :**
- Tableaux de bord/journaux/analyses unifiés dans un seul produit
- Santé + audit + télémétrie des demandes sur les couches OpenAI, MCP et A2A
- API opérationnelles pour le statut et l'automatisation
</details>
<details>
<summary><b>💼 29. "J'ai besoin d'un environnement d'exécution pour l'orchestration proxy + outils + agent" </b></summary>
Lexécution de nombreux services distincts augmente les coûts opérationnels et les modes de défaillance.
**Comment OmniRoute le résout :**
- Proxy compatible OpenAI, serveur MCP et serveur A2A dans une seule pile
- Authentification partagée, résilience, stockage de données et observabilité
- Modèle de politique cohérent sur toutes les surfaces d'interaction
</details>
<details>
<summary><b>🚀 30. "Je dois expédier des flux de travail agentiques sans prolifération de codes adhésifs" </b></summary>
Les équipes perdent de la vitesse lors de lassemblage de plusieurs services et scripts ad hoc.
**Comment OmniRoute le résout :**
- Stratégie de point de terminaison unifiée pour les clients et les agents
- Interfaces utilisateur de gestion de protocole intégrées et chemins de validation de fumée
- Bases prêtes pour la production (sécurité, journalisation, résilience, sauvegarde)
</details>
### Exemples de playbooks (cas d'utilisation intégrés)
**Playbook A : Maximisez l'abonnement payant + sauvegarde bon marché**
```txt
Combo: "maximize-claude"
1. cc/claude-opus-4-6
2. glm/glm-4.7
3. if/kimi-k2-thinking
Monthly cost: $20 + small backup spend
Outcome: higher quality, near-zero interruption
```
**Playbook B : pile de codage à coût nul**
```txt
Combo: "free-forever"
1. gc/gemini-3-flash
2. if/kimi-k2-thinking
3. qw/qwen3-coder-plus
Monthly cost: $0
Outcome: stable free coding workflow
```
**Playbook C : chaîne de secours toujours active 24h/24 et 7j/7**
```txt
Combo: "always-on"
1. cc/claude-opus-4-6
2. cx/gpt-5.2-codex
3. glm/glm-4.7
4. minimax/MiniMax-M2.1
5. if/kimi-k2-thinking
Outcome: deep fallback depth for deadline-critical workloads
```
**Playbook D : Opérations d'agent avec MCP + A2A**
```txt
1) Start MCP transport (`omniroute --mcp`) for tool-driven operations
2) Run A2A tasks via `message/send` and `message/stream`
3) Observe via /dashboard/mcp and /dashboard/a2a
4) Control incidents with resilience profile + task cancellation
```
---
## ⚡ Démarrage rapide
**1. Installer globalement :**
@@ -249,7 +781,7 @@ docker compose --profile cli up -d
---
## 🖥️ Application Bureau — Hors Ligne et Toujours Actif
## 🖥️
> 🆕 **NOUVEAU !** OmniRoute est maintenant disponible en tant qu'**application de bureau native** pour Windows, macOS et Linux.
@@ -298,67 +830,6 @@ npm run electron:build:linux # Linux (.AppImage)
---
## 🎯 Cas d'utilisation
### Cas 1 : « J'ai un abonnement Claude Pro »
**Problème :** Le quota expire inutilisé, limites de débit pendant le codage intensif
```
Combo : "maximize-claude"
1. cc/claude-opus-4-6 (utiliser l'abonnement au maximum)
2. glm/glm-4.7 (backup économique quand le quota est épuisé)
3. if/kimi-k2-thinking (fallback d'urgence gratuit)
Coût mensuel : 20 $ (abonnement) + ~5 $ (backup) = 25 $ au total
vs. 20 $ + atteindre les limites = frustration
```
### Cas 2 : « Je veux zéro coût »
**Problème :** Impossible de payer des abonnements, besoin d'IA fiable pour coder
```
Combo : "free-forever"
1. gc/gemini-3-flash (180K gratuits/mois)
2. if/kimi-k2-thinking (illimité gratuit)
3. qw/qwen3-coder-plus (illimité gratuit)
Coût mensuel : 0 $
Qualité : Modèles prêts pour la production
```
### Cas 3 : « Je dois coder 24/7, sans interruption »
**Problème :** Délais serrés, ne peut pas se permettre de temps d'arrêt
```
Combo : "always-on"
1. cc/claude-opus-4-6 (meilleure qualité)
2. cx/gpt-5.2-codex (deuxième abonnement)
3. glm/glm-4.7 (économique, reset quotidien)
4. minimax/MiniMax-M2.1 (le moins cher, reset 5h)
5. if/kimi-k2-thinking (gratuit illimité)
Résultat : 5 niveaux de fallback = zéro temps d'arrêt
```
### Cas 4 : « Je veux l'IA GRATUITE dans OpenClaw »
**Problème :** Besoin d'assistant IA dans les apps de messagerie, entièrement gratuit
```
Combo : "openclaw-free"
1. if/glm-4.7 (illimité gratuit)
2. if/minimax-m2.1 (illimité gratuit)
3. if/kimi-k2-thinking (illimité gratuit)
Coût mensuel : 0 $
Accès via : WhatsApp, Telegram, Slack, Discord, iMessage, Signal...
```
---
## 💡 Fonctionnalités principales
### 🧠 Routage & Intelligence
@@ -374,6 +845,8 @@ Accès via : WhatsApp, Telegram, Slack, Discord, iMessage, Signal...
| 🧩 **Modèles personnalisés** | Ajoutez n'importe quel ID de modèle à n'importe quel fournisseur |
| 🌐 **Routeur wildcard** | Routez les patterns `provider/*` vers n'importe quel fournisseur dynamiquement |
| 🧠 **Budget de raisonnement** | Modes passthrough, auto, custom et adaptive pour les modèles de raisonnement |
| 🔀 **Model Aliases** | Auto-forward deprecated model IDs to current replacements (built-in + custom) |
| ⚡ **Background Degradation** | Auto-route background tasks (titles, summaries) to cheaper models |
| 💬 **Injection System Prompt** | System prompt global appliqué à toutes les requêtes |
| 📄 **API Responses** | Support complet de l'API Responses d'OpenAI (`/v1/responses`) pour Codex |
@@ -390,15 +863,18 @@ Accès via : WhatsApp, Telegram, Slack, Discord, iMessage, Signal...
### 🛡️ Résilience & Sécurité
| Fonctionnalité | Ce qu'elle fait |
| ------------------------------- | -------------------------------------------------------------------- |
| 🔌 **Circuit Breaker** | Ouverture/fermeture auto par fournisseur avec seuils configurables |
| 🛡️ **Anti-Thundering Herd** | Mutex + sémaphore de rate-limit pour les fournisseurs avec clé API |
| 🧠 **Cache sémantique** | Cache à deux niveaux (signature + sémantique) réduit coût et latence |
| **Idempotence des requêtes** | Fenêtre de dédup 5s pour les requêtes dupliquées |
| 🔒 **Spoofing TLS Fingerprint** | Contournement de détection de bot via wreq-js |
| 🌐 **Filtrage IP** | Allowlist/blocklist pour le contrôle d'accès API |
| 📊 **Rate limits éditables** | RPM configurable, intervalle minimum, concurrence max |
| Fonctionnalité | Ce qu'elle fait |
| ------------------------------- | ---------------------------------------------------------------------------- |
| 🔌 **Circuit Breaker** | Ouverture/fermeture auto par fournisseur avec seuils configurables |
| 🎯 **Endpoint-Aware Models** | Custom models declare supported endpoints + API format |
| 🛡️ **Anti-Thundering Herd** | Mutex + sémaphore de rate-limit pour les fournisseurs avec clé API |
| 🧠 **Cache sémantique** | Cache à deux niveaux (signature + sémantique) réduit coût et latence |
| **Idempotence des requêtes** | Fenêtre de dédup 5s pour les requêtes dupliquées |
| 🔒 **Spoofing TLS Fingerprint** | Contournement de détection de bot via wreq-js |
| 🌐 **Filtrage IP** | Allowlist/blocklist pour le contrôle d'accès API |
| 📊 **Rate limits éditables** | RPM configurable, intervalle minimum, concurrence max |
| 💾 **Rate Limit Persistence** | Learned limits survive restarts via SQLite with 60s debounce + 24h staleness |
| 🔄 **Token Refresh Resilience** | Per-provider circuit breaker (5 fails→30min) + 30s timeout per attempt |
### 📊 Observabilité & Analytique
@@ -498,6 +974,27 @@ Traduction transparente entre les formats :
</details>
## 🧪 Évaluations (Evals)
OmniRoute inclut un framework d'évaluation intégré pour tester la qualité des réponses LLM contre un golden set. Accès via **Analytics → Evals** dans le tableau de bord.
### Set intégré
Le « OmniRoute Golden Set » préchargé contient 10 cas de test :
- Salutations, mathématiques, géographie, génération de code
- Conformité format JSON, traduction, markdown
- Rejet de sécurité (contenu nocif), comptage, logique booléenne
### Stratégies d'évaluation
| Stratégie | Description | Exemple |
| ---------- | -------------------------------------------------------------- | -------------------------------- |
| `exact` | La sortie doit correspondre exactement | `"4"` |
| `contains` | La sortie doit contenir la sous-chaîne (insensible à la casse) | `"Paris"` |
| `regex` | La sortie doit correspondre au motif regex | `"1.*2.*3"` |
| `custom` | Fonction JS personnalisée retourne true/false | `(output) => output.length > 10` |
---
## 📖 Guide de configuration
@@ -780,97 +1277,6 @@ Paramètres → Configuration API :
---
## 📊 Modèles disponibles
<details>
<summary><b>Voir tous les modèles disponibles</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/`)** - GRATUIT :
- `gc/gemini-3-flash-preview`
- `gc/gemini-2.5-pro`
**GitHub Copilot (`gh/`)** :
- `gh/gpt-5`
- `gh/claude-4.5-sonnet`
**NVIDIA NIM (`nvidia/`)** - Crédits GRATUITS :
- `nvidia/llama-3.3-70b-instruct`
- `nvidia/mistral-7b-instruct`
- 50+ modèles sur [build.nvidia.com](https://build.nvidia.com)
**GLM (`glm/`)** - $0.6/1M :
- `glm/glm-4.7`
**MiniMax (`minimax/`)** - $0.2/1M :
- `minimax/MiniMax-M2.1`
**iFlow (`if/`)** - GRATUIT :
- `if/kimi-k2-thinking`
- `if/qwen3-coder-plus`
- `if/deepseek-r1`
- `if/glm-4.7`
- `if/minimax-m2`
**Qwen (`qw/`)** - GRATUIT :
- `qw/qwen3-coder-plus`
- `qw/qwen3-coder-flash`
**Kiro (`kr/`)** - GRATUIT :
- `kr/claude-sonnet-4.5`
- `kr/claude-haiku-4.5`
**OpenRouter (`or/`)** - 100+ modèles :
- `or/anthropic/claude-4-sonnet`
- `or/google/gemini-2.5-pro`
- Tout modèle de [openrouter.ai/models](https://openrouter.ai/models)
</details>
---
## 🧪 Évaluations (Evals)
OmniRoute inclut un framework d'évaluation intégré pour tester la qualité des réponses LLM contre un golden set. Accès via **Analytics → Evals** dans le tableau de bord.
### Golden Set intégré
Le « OmniRoute Golden Set » préchargé contient 10 cas de test :
- Salutations, mathématiques, géographie, génération de code
- Conformité format JSON, traduction, markdown
- Rejet de sécurité (contenu nocif), comptage, logique booléenne
### Stratégies d'évaluation
| Stratégie | Description | Exemple |
| ---------- | -------------------------------------------------------------- | -------------------------------- |
| `exact` | La sortie doit correspondre exactement | `"4"` |
| `contains` | La sortie doit contenir la sous-chaîne (insensible à la casse) | `"Paris"` |
| `regex` | La sortie doit correspondre au motif regex | `"1.*2.*3"` |
| `custom` | Fonction JS personnalisée retourne true/false | `(output) => output.length > 10` |
---
## 🐛 Dépannage
<details>
@@ -926,7 +1332,7 @@ Le « OmniRoute Golden Set » préchargé contient 10 cas de test :
---
## 🛠️ Stack technologique
## 🛠️
- **Runtime** : Node.js 20+
- **Langage** : TypeScript 5.9 — **100% TypeScript** dans `src/` et `open-sse/` (v1.0.6)
@@ -957,17 +1363,7 @@ Le « OmniRoute Golden Set » préchargé contient 10 cas de test :
---
## 📧 Support
> 💬 **Rejoignez notre communauté !** [Groupe WhatsApp](https://chat.whatsapp.com/JI7cDQ1GyaiDHhVBpLxf8b?mode=gi_t) — Obtenez de l'aide, partagez des astuces et restez informé.
- **Site web** : [omniroute.online](https://omniroute.online)
- **GitHub** : [github.com/diegosouzapw/OmniRoute](https://github.com/diegosouzapw/OmniRoute)
- **Issues** : [github.com/diegosouzapw/OmniRoute/issues](https://github.com/diegosouzapw/OmniRoute/issues)
- **WhatsApp** : [Groupe communautaire](https://chat.whatsapp.com/JI7cDQ1GyaiDHhVBpLxf8b?mode=gi_t)
- **Projet original** : [9router par decolua](https://github.com/decolua/9router)
---
## 🗺️
## 👥 Contributeurs

File diff suppressed because it is too large Load Diff

View File

@@ -3,8 +3,6 @@
# 🚀 OmniRoute Az ingyenes mesterséges intelligencia átjáró
🌐 **[English](#-omniroute--the-free-ai-gateway)** | **[Português (BR)](#-omniroute--gateway-de-ia-gratuito)**
### Soha ne hagyd abba a kódolást. Intelligens útválasztás **INGYENES és alacsony költségű mesterséges intelligencia modellekhez** automatikus visszaállítással.
_Az univerzális API-proxy egy végpont, 36+ szolgáltató, nulla állásidő._
@@ -112,6 +110,35 @@ _Csatlakoztasson bármilyen mesterséges intelligencia-alapú IDE-t vagy CLI-esz
---
## 🖼️
<div align="center">
<img src="./docs/screenshots/MainOmniRoute.png" alt="OmniRoute" width="800"/>
</div>
---
## 📸
<details>
<summary><b>...</b></summary>
| # | # |
| ----- | ---------------------------------------- |
| **1** | ![1](docs/screenshots/01-providers.png) |
| **2** | ![2](docs/screenshots/02-combos.png) |
| **3** | ![3](docs/screenshots/03-analytics.png) |
| **4** | ![4](docs/screenshots/04-health.png) |
| **5** | ![5](docs/screenshots/05-translator.png) |
| **6** | ![6](docs/screenshots/06-settings.png) |
| **7** | ![7](docs/screenshots/07-cli-tools.png) |
| **8** | ![8](docs/screenshots/08-usage.png) |
| **9** | ![9](docs/screenshots/09-endpoint.png) |
</details>
---
## 🤔 Miért az OmniRoute?
**Ne pazarolja a pénzt, és ne lépje túl a limiteket:**
@@ -130,6 +157,18 @@ _Csatlakoztasson bármilyen mesterséges intelligencia-alapú IDE-t vagy CLI-esz
---
## 📧 Támogatás
> 💬 **Csatlakozzon közösségünkhöz!** [WhatsApp Group](https://chat.whatsapp.com/JI7cDQ1GyaiDHhVBpLxf8b?mode=gi_t) — Kérjen segítséget, ossza meg tippjeit, és naprakész legyen.
- **Webhely**: [omniroute.online](https://omniroute.online)
- **GitHub**: [github.com/diegosouzapw/OmniRoute](https://github.com/diegosouzapw/OmniRoute)
- **Problémák**: [github.com/diegosouzapw/OmniRoute/issues](https://github.com/diegosouzapw/OmniRoute/issues)
- **WhatsApp**: [Community Group](https://chat.whatsapp.com/JI7cDQ1GyaiDHhVBpLxf8b?mode=gi_t)
- **Eredeti projekt**: [9router by decolua](https://github.com/decolua/9router)
---
## 🔄 Hogyan működik
```
@@ -159,6 +198,498 @@ Result: Never stop coding, minimal cost
---
## 🎯 Mit old meg az OmniRoute 30 valódi fájdalompont és használati eset
> **Minden mesterséges intelligencia-eszközöket használó fejlesztő naponta szembesül ezekkel a problémákkal.** Az OmniRoute úgy készült, hogy ezeket mind megoldja a költségtúllépésektől a regionális blokkokig, a megszakadt OAuth-folyamatoktól a protokollműveletekig és a vállalati megfigyelhetőségig.
<details>
<summary><b>💸 1. "Drága előfizetésért fizetek, de még mindig megszakítanak a korlátozások" </b></summary>
A fejlesztők havi 20200 dollárt fizetnek a Claude Pro, Codex Pro vagy GitHub Copilotért. A kvótának még fizetés esetén is van felső határa 5 óra használat, heti limitek vagy percdíjkorlátok. A kódolási munkamenet közepén a szolgáltató leáll, és a fejlesztő elveszíti a folyamatot és a termelékenységet.
**Hogyan oldja meg az OmniRoute:**
- **Smart 4-Tier Fallback** Ha az előfizetési kvóta kimerül, automatikusan átirányítja az API-kulcs → Olcsó → Ingyenes, manuális beavatkozás nélkül
- **Valós idejű kvótakövetés** Valós időben mutatja a token felhasználást, visszaszámlálással (5 óra, napi, heti)
- **Több fiók támogatása** - Több fiók szolgáltatónként automatikus körváltással - ha az egyik elfogy, átvált a következőre
- **Egyéni kombók** — Testreszabható tartalék láncok 6 kiegyensúlyozási stratégiával (fill-first, round-robin, P2C, véletlenszerű, legkevésbé használt, költségoptimalizált)
- **Codex üzleti kvóták** — Üzleti/csapat munkaterület-kvóta figyelése közvetlenül az irányítópulton
</details>
<details>
<summary><b>🔌 2. "Több szolgáltatót kell használnom, de mindegyiknek más API" </b></summary>
Az OpenAI egy formátumot használ, a Claude (Anthropic) egy másikat, a Gemini pedig egy másikat. Ha egy fejlesztő különböző szolgáltatók modelljeit szeretné tesztelni, vagy tartalékot szeretne közöttük, akkor újra kell konfigurálnia az SDK-kat, módosítania kell a végpontokat, és kezelnie kell az inkompatibilis formátumokat. Az egyéni szolgáltatók (FriendLI, NIM) nem szabványos modellvégpontokkal rendelkeznek.
**Hogyan oldja meg az OmniRoute:**
- **Egységes végpont** - Egy `http://localhost:20128/v1` proxyként szolgál mind a 36+ szolgáltató számára
- **Formátumfordítás** - Automatikus és átlátható: OpenAI ↔ Claude ↔ Gemini ↔ Responses API
- **Response Sanitization** Eltávolítja azokat a nem szabványos mezőket (`x_groq`, `usage_breakdown`, `service_tier`), amelyek megszakítják az OpenAI SDK v1.83+ verzióját
- **Szerepek normalizálása** — `developer``system` konvertálása nem OpenAI szolgáltatók számára; `system``user` a GLM/ERNIE számára
- **Think Tag Extraction** `<think>` blokkokat bont ki olyan modellekből, mint a DeepSeek R1 szabványos `reasoning_content`-be
- **Strukturált kimenet a Gemini számára** — `json_schema``responseMimeType`/`responseSchema` automatikus átalakítás
- **`stream` az alapértelmezett `false`** - Az OpenAI specifikációhoz igazodik, elkerülve a váratlan SSE-t a Python/Rust/Go SDK-kban
</details>
<details>
<summary><b>🌐 3. „Az AI-szolgáltatóm blokkolja a régiómat/országomat”</b></summary>
Az olyan szolgáltatók, mint az OpenAI/Codex, blokkolják a hozzáférést bizonyos földrajzi régiókból. A felhasználók OAuth- és API-kapcsolatok során olyan hibákat kapnak, mint az `unsupported_country_region_territory`. Ez különösen frusztráló a fejlődő országok fejlesztői számára.
**Hogyan oldja meg az OmniRoute:**
- **3-szintű proxykonfiguráció** 3 szinten konfigurálható proxy: globális (teljes forgalom), szolgáltatónként (csak egy szolgáltató) és kapcsolatonként/kulcsonként
- **Színes proxy jelvények** - Vizuális jelzők: 🟢 globális proxy, 🟡 szolgáltató proxy, 🔵 kapcsolat proxy, mindig az IP-t mutatja
- **OAuth-tokencsere proxyn keresztül** — Az OAuth-folyamat a proxyn keresztül is megy, megoldva az `unsupported_country_region_territory` problémát
- **Kapcsolódási tesztek proxyn keresztül** - A csatlakozási tesztek a konfigurált proxyt használják (nincs többé közvetlen kiiktatás)
- **SOCKS5 támogatás** — Teljes SOCKS5 proxy támogatás a kimenő útválasztáshoz
- **TLS-ujjlenyomat-hamisítás** — Böngészőszerű TLS-ujjlenyomat az `wreq-js`-n keresztül a botészlelés megkerüléséhez
</details>
<details>
<summary><b>🆓 4. "MI-t akarok használni kódoláshoz, de nincs pénzem" </b></summary>
Nem mindenki fizethet havi 20200 dollárt az AI-előfizetésekért. A feltörekvő országok diákjainak, fejlesztőinek, amatőröknek és szabadúszóknak nulla költséggel kell hozzáférniük a minőségi modellekhez.
**Hogyan oldja meg az OmniRoute:**
- **Beépített ingyenes szolgáltatók** - Natív támogatás 100%-ban ingyenes szolgáltatókhoz: iFlow (8 korlátlan modell), Qwen (3 korlátlan modell), Kiro (Claude ingyenes), Gemini CLI (180 000/hónap ingyenes)
- **Csak ingyenes kombók** — `gc/gemini-3-flash → if/kimi-k2-thinking → qw/qwen3-coder-plus` lánc = 0 USD/hó nulla állásidővel
- **NVIDIA NIM ingyenes kreditek** 1000 ingyenes kredit integrálva
- **Költségoptimalizált stratégia** — Útválasztási stratégia, amely automatikusan a legolcsóbb elérhető szolgáltatót választja
</details>
<details>
<summary><b>🔒 5. "Meg kell védenem a mesterséges intelligencia átjárómat a jogosulatlan hozzáféréstől"</b></summary>
Ha AI átjárót teszünk ki a hálózatnak (LAN, VPS, Docker), a cím birtokában bárki felhasználhatja a fejlesztő tokenjeit/kvótáját. Védelem nélkül az API-k sebezhetőek a visszaélésekkel, azonnali befecskendezéssel és visszaélésekkel szemben.
**Hogyan oldja meg az OmniRoute:**
- **API-kulcskezelés** — Generálás, rotáció és hatókör szolgáltatónként egy dedikált `/dashboard/api-manager`-oldallal
- **Modellszintű engedélyek** - API-kulcsok korlátozása adott modellekre (`openai/*`, helyettesítő karakteres minták), az Összes engedélyezése/Korlátozása kapcsolóval
- **API Endpoint Protection** — Kulcs szükséges az `/v1/models` számára, és bizonyos szolgáltatók letiltása a listáról
- **Auth Guard + CSRF védelem** - Minden irányítópult-útvonal `withAuth` köztes szoftverrel + CSRF tokenekkel védett
- **Rate Limiter** — IP-nkénti sebességkorlátozás konfigurálható ablakokkal
- **IP-szűrés** — Engedélyezési lista/blokkolólista a hozzáférés-vezérléshez
- **Prompt Injection Guard** fertőtlenítés a rosszindulatú felszólítási minták ellen
- **AES-256-GCM titkosítás** - A hitelesítő adatok nyugalmi állapotban titkosítva
</details>
<details>
<summary><b>🛑 6. "A szolgáltatóm leállt, és elvesztettem a kódolási folyamatomat"</b></summary>
Az AI-szolgáltatók instabillá válhatnak, 5xx-es hibákat adnak vissza, vagy elérhetik az ideiglenes sebességkorlátokat. Ha egy fejlesztő egyetlen szolgáltatótól függ, akkor megszakad. Megszakítók nélkül az ismételt újrapróbálkozások összeomolhatják az alkalmazást.
**Hogyan oldja meg az OmniRoute:**
- **Megszakító szolgáltatónként** - Automatikus nyitás/zárás konfigurálható küszöbértékekkel és lehűtéssel (zárt/nyitott/félig nyitott)
- **Exponenciális visszalépés** — Progresszív újrapróbálkozási késések
- **Mennydörgés elleni csorda** - Mutex + szemafor védelem az egyidejű újrapróbálkozási viharok ellen
- **Kombinált tartalék láncok** Ha az elsődleges szolgáltató meghibásodik, automatikusan, beavatkozás nélkül átesik a láncon
- **Combo Circuit Breaker** Automatikusan letiltja a hibás szolgáltatókat a kombinált láncon belül
| 🎯 **Endpoint-Aware Models** | Custom models declare supported endpoints + API format |
- **Egészségügyi irányítópult** — Üzemidő-figyelés, áramkör-megszakító állapotok, zárolások, gyorsítótár-statisztika, p50/p95/p99 késleltetés
</details>
<details>
<summary><b>🔧 7. "Az egyes AI-eszközök konfigurálása fárasztó és ismétlődő"</b></summary>
A fejlesztők Cursort, Claude Code-ot, Codex CLI-t, OpenClaw-ot, Gemini CLI-t, Kilo Code-ot használnak... Minden eszköznek más konfigurációra van szüksége (API végpont, kulcs, modell). Az újrakonfigurálás szolgáltató- vagy modellváltáskor időpocsékolás.
**Hogyan oldja meg az OmniRoute:**
- **CLI Tools Dashboard** - Dedikált oldal egykattintásos beállítással a Claude Code, Codex CLI, OpenClaw, Kilo Code, Antigravity, Cline számára
- **GitHub másodpilóta konfigurációs generátor** — `chatLanguageModels.json` kódot generál VS kódhoz tömeges modellválasztással
- **Bevezető varázsló** Irányított 4 lépéses beállítás első felhasználók számára
- **Egy végpont, minden modell** — Az `http://localhost:20128/v1` egyszeri konfigurálása, 36+ szolgáltató elérése
</details>
<details>
<summary><b>🔑 8. "A több szolgáltatótól származó OAuth-tokenek kezelése pokol"</b></summary>
Claude Code, Codex, Gemini CLI, Copilot mindegyik az OAuth 2.0-t használja lejáró tokenekkel. A fejlesztőknek folyamatosan újra kell hitelesíteniük, kezelniük kell az `client_secret is missing`, `redirect_uri_mismatch` és a távoli szerverek hibáit. Az OAuth a LAN/VPS-en különösen problémás.
**Hogyan oldja meg az OmniRoute:**
- **Automatikus tokenfrissítés** - Az OAuth-tokenek a háttérben frissülnek a lejárat előtt
- **OAuth 2.0 (PKCE) beépített** - Automatikus áramlás Claude Code, Codex, Gemini CLI, Copilot, Kiro, Qwen, iFlow számára
- **Multi-Account OAuth** - Több fiók szolgáltatónként a JWT/ID token kivonattal
- **OAuth LAN/Távoli javítás** - Privát IP-észlelés `redirect_uri`-hez + kézi URL mód távoli szerverekhez
- **OAuth az Nginx mögött** - `window.location.origin`-t használ a fordított proxy kompatibilitás érdekében
- **Távoli OAuth útmutató** Lépésről lépésre útmutató a Google Cloud hitelesítő adataihoz VPS/Docker rendszeren
</details>
<details>
<summary><b>📊 9. "Nem tudom, mennyit költök vagy hova"</b></summary>
A fejlesztők több fizetős szolgáltatót használnak, de nincs egységes nézetük a kiadásokról. Minden szolgáltató saját számlázási irányítópulttal rendelkezik, de nincs összevont nézet. A váratlan költségek felhalmozódhatnak.
**Hogyan oldja meg az OmniRoute:**
- **Költségelemzési irányítópult** Tokenenkénti költségkövetés és költségkeret-kezelés szolgáltatónként
- **Költségkeret-korlátok rétegenként** - Költési felső határ szintenként, amely automatikus visszalépést vált ki
- **Modellenkénti árképzés** - Konfigurálható árak modellenként
- **Használati statisztika API-kulcsonként** — A kérések száma és az utoljára használt időbélyeg kulcsonként
- **Analytics Dashboard** — Statisztikai kártyák, modellhasználati diagram, szolgáltatói táblázat sikerarányokkal és késleltetéssel
</details>
<details>
<summary><b>🐛 10. "Nem tudom diagnosztizálni a hibákat és problémákat az AI-hívásoknál"</b></summary>
Ha egy hívás meghiúsul, a fejlesztő nem tudja, hogy sebességkorlátozás, lejárt token, rossz formátum vagy szolgáltatói hiba volt-e. Töredezett naplók különböző terminálokon. Megfigyelhetőség nélkül a hibakeresés próba és hiba.
**Hogyan oldja meg az OmniRoute:**
- **Egységes naplók irányítópultja** - 4 lap: Kérelemnaplók, Proxynaplók, Auditnaplók, Konzol
- **Konzolnapló-nézegető** — Valós idejű terminál stílusú megjelenítő színkódolt szintekkel, automatikus görgetés, keresés, szűrés
- **SQLite proxynaplók** Állandó naplók, amelyek túlélik a szerver újraindítását
- **Translator Playground** 4 hibakeresési mód: Playground (formátum fordítás), Chat Tester (oda-vissza út), Tesztpad (kötegelt), Élő monitor (valós idejű)
- **Request Telemetria** p50/p95/p99 késleltetés + X-Request-Id nyomkövetés
- **Fájlalapú naplózás elforgatással** - A konzolelfogó mindent JSON-naplóba rögzít méretalapú elforgatással
</details>
<details>
<summary><b>🏗️ 11. "Az átjáró telepítése és karbantartása összetett" </b></summary>
Az AI-proxy telepítése, konfigurálása és karbantartása különböző környezetekben (helyi, VPS, Docker, felhő) munkaigényes. Az olyan problémák, mint a keménykódolt elérési utak, az `EACCES` a könyvtárakon, a portütközések és a többplatformos buildek súrlódást okoznak.
**Hogyan oldja meg az OmniRoute:**
- **npm globális telepítés** — `npm install -g omniroute && omniroute` — kész
- **Docker Multi-Platform** AMD64 + ARM64 natív (Apple Silicon, AWS Graviton, Raspberry Pi)
- **Docker Compose Profiles** — `base` (nincs CLI-eszközök) és `cli` (Claude Code-al, Codex-szel, OpenClaw-val)
- **Electron Desktop App** Natív alkalmazás Windows/macOS/Linux rendszerhez rendszertálcával, automatikus indítással, offline móddal
- **Split-Port Mode** API és irányítópult külön portokon haladó forgatókönyvekhez (fordított proxy, konténerhálózat)
- **Cloud Sync** Szinkronizálás konfigurálása az eszközök között a Cloudflare Workers segítségével
- **DB biztonsági mentések** — Az összes beállítás automatikus biztonsági mentése, visszaállítása, exportálása és importálása
</details>
<details>
<summary><b>🌍 12. "A felület csak angol nyelvű, és a csapatom nem beszél angolul"</b></summary>
A nem angol nyelvű országokban, különösen Latin-Amerikában, Ázsiában és Európában működő csapatok csak angol nyelvű felületekkel küszködnek. A nyelvi akadályok csökkentik az átvételt és növelik a konfigurációs hibákat.
**Hogyan oldja meg az OmniRoute:**
- ** Irányítópult i18n 30 nyelv** Mind az 500+ billentyű lefordítva, beleértve arab, bolgár, dán, német, spanyol, finn, francia, héber, hindi, magyar, indonéz, olasz, japán, koreai, maláj, holland, norvég, lengyel, portugál (PT/BR), román, thai, orosz, szlovák, svéd, filippínó, angol, thai, orosz, kínai, filippínó
- **RTL támogatás** Jobbról balra haladó arab és héber nyelv támogatása
- **Többnyelvű README-k** — 30 teljes dokumentáció fordítás
- **Nyelvválasztó** — Globe ikon a fejlécben a valós idejű váltáshoz
</details>
<details>
<summary><b>🔄 13. "Többre van szükségem, mint csevegésre beágyazásra, képekre, hangra van szükségem"</b></summary>
Az AI nem csak a csevegés befejezése. A fejlesztőknek képeket kell generálniuk, hangot kell átírniuk, beágyazást kell létrehozniuk a RAG számára, át kell sorolniuk a dokumentumokat, és moderálniuk kell a tartalmat. Minden API más végponttal és formátummal rendelkezik.
**Hogyan oldja meg az OmniRoute:**
- **Beágyazások** — `/v1/embeddings` 6 szolgáltatóval és 9+ modellel
- **Képgenerálás** — `/v1/images/generations` 10 szolgáltatóval és 20+ modellel (OpenAI, xAI, Together, Fireworks, Nebius, Hyperbolic, NanoBanana, Antigravity, SD WebUI, ComfyUI)
- **Text-to-Video** — `/v1/videos/generations` — ComfyUI (AnimateDiff, SVD) és SD WebUI
- **Text-to-Music** — `/v1/music/generations` — ComfyUI (Stable Audio Open, MusicGen)
- **Audio átírás** - `/v1/audio/transcriptions` - Whisper + Nvidia NIM, HuggingFace, Qwen3
- **Szövegfelolvasó** — `/v1/audio/speech` — ElevenLabs, Nvidia NIM, HuggingFace, Coqui, Tortoise, Qwen3, + meglévő szolgáltatók
- **Moderálás** — `/v1/moderations` — Tartalombiztonsági ellenőrzések
- **Átsorolás** — `/v1/rerank` — Dokumentumreleváns átsorolás
- **Responses API** - Teljes `/v1/responses` támogatás a Codexhez
</details>
<details>
<summary><b>🧪 14. "Nincs módom tesztelni és összehasonlítani a minőséget a különböző modellek között"</b></summary>
A fejlesztők szeretnék tudni, hogy melyik modell a legjobb az ő használati esetükben kód, fordítás, érvelés , de a manuális összehasonlítás lassú. Nincsenek integrált eval eszközök.
**Hogyan oldja meg az OmniRoute:**
- **LLM-értékelések** — Arany készlet tesztelése 10 előre betöltött esettel, beleértve az üdvözlést, a matematikát, a földrajzot, a kódgenerálást, a JSON-megfelelőséget, a fordítást, a leértékelést, a biztonsági megtagadást
- **4 egyezési stratégia** — `exact`, `contains`, `regex`, `custom` (JS funkció)
- **Translator Playground Test Bench** - Kötegelt tesztelés több bemenettel és várható kimenettel, szolgáltatók közötti összehasonlítás
- **Csevegés tesztelő** - Teljes körút vizuális válaszmegjelenítéssel
- **Élő monitor** Valós idejű adatfolyam a proxyn keresztül folyó összes kérésről
</details>
<details>
<summary><b>📈 15. "A teljesítmény elvesztése nélkül kell méreteznem" </b></summary>
A kérelmek mennyiségének növekedésével ugyanazok a kérdések a gyorsítótárazás nélkül duplikált költségeket generálnak. Idempotencia nélkül a duplikált hulladékfeldolgozási kérelmek. A szolgáltatónkénti díjkorlátokat be kell tartani.
**Hogyan oldja meg az OmniRoute:**
- **Szemantikus gyorsítótár** A kétszintű gyorsítótár (aláírás + szemantikai) csökkenti a költségeket és a késleltetést
- **Idempotency kérése** 5 másodperces deduplikációs ablak azonos kérések esetén
- **Drátakorlát észlelése** Szolgáltatónkénti RPM, minimális rés és maximális egyidejű követés
- **Szerkeszthető sebességkorlátok** - Konfigurálható alapértékek a Beállítások → Kitartással ellenálló képesség menüpontban
- **API Key Validation Cache** 3-szintű gyorsítótár az éles teljesítményhez
- **Egészségügyi irányítópult telemetriával** — p50/p95/p99 késleltetés, gyorsítótár statisztika, üzemidő
</details>
<details>
<summary><b>🤖 16. "Globálisan szeretném szabályozni a modell viselkedését" </b></summary>
Azok a fejlesztők, akik minden választ egy adott nyelven, egy adott hangnemben szeretnének, vagy korlátozni szeretnék az érvelési tokeneket. Ennek konfigurálása minden eszközben/kérelemben nem praktikus.
**Hogyan oldja meg az OmniRoute:**
- **Rendszerprompt Injection** — Globális prompt minden kérelemre vonatkozik
- **A költségkeret átgondolásának ellenőrzése** Indoklási token-kiosztás ellenőrzése kérésenként (áthaladó, automatikus, egyéni, adaptív)
- **6 Útválasztási stratégia** Globális stratégiák, amelyek meghatározzák a kérések elosztását
- **Wildcard Router** — `provider/*` minták dinamikusan továbbítanak bármely szolgáltatóhoz
- **Kombinációs engedélyezés/letiltás váltás** - A kombók váltása közvetlenül az irányítópultról
- **Provider Toggle** — Egy szolgáltató összes kapcsolatának engedélyezése/letiltása egyetlen kattintással
- **Letiltott szolgáltatók** - Adott szolgáltatók kizárása az `/v1/models` listáról
</details>
<details>
<summary><b>🧰 17. "MCP eszközökre van szükségem, mint első osztályú termékképességekre" </b></summary>
Sok mesterséges intelligencia-átjáró csak rejtett megvalósítási részletként teszi közzé az MCP-t. A csapatoknak látható, kezelhető műveleti rétegre van szükségük.
**Hogyan oldja meg az OmniRoute:**
- Az MCP megjelenik az irányítópult navigációs és végponti protokoll lapján
- Dedikált MCP-kezelési oldal folyamatokkal, eszközökkel, hatókörökkel és audittal
- Beépített gyorsindítás az `omniroute --mcp` és a kliens beépítéséhez
</details>
<details>
<summary><b>🧠 18. "A2A hangszerelésre van szükségem szinkronizálással + adatfolyam feladatútvonalak" </b></summary>
Az ügynöki munkafolyamatokhoz közvetlen válaszokra és hosszú távú, streamelt végrehajtásra van szükség életciklus-vezérléssel.
**Hogyan oldja meg az OmniRoute:**
- A2A JSON-RPC végpont (`POST /a2a`) `message/send` és `message/stream`
- SSE streaming terminál állapot terjesztéssel
- Feladat életciklus API-k `tasks/get` és `tasks/cancel`
</details>
<details>
<summary><b>🛰️ 19. "Valódi MCP folyamatállapotra van szükségem, nem kitalált állapotra" </b></summary>
Az operatív csapatoknak tudniuk kell, hogy az MCP valóban életben van-e, nem csak azt, hogy egy API elérhető-e.
**Hogyan oldja meg az OmniRoute:**
- Futásidejű szívverés fájl PID-vel, időbélyegekkel, szállítással, szerszámszámmal és hatókör móddal
- MCP állapot API, amely kombinálja a szívverést + a legutóbbi tevékenységet
- UI állapotkártyák a folyamat/üzemidő/szívverés frissességéhez
</details>
<details>
<summary><b>📋 20. "Kivizsgálható MCP-eszköz végrehajtásra van szükségem" </b></summary>
Amikor az eszközök módosítják a konfigurációt vagy működési műveleteket indítanak el, a csapatoknak kriminalisztikai nyomon követhetőségre van szükségük.
**Hogyan oldja meg az OmniRoute:**
- SQLite-alapú audit naplózás MCP-eszközhívásokhoz
- Szűrések eszköz, siker/kudarc, API-kulcs és oldalszámozás szerint
- Irányítópult audit táblázat + statisztikai végpontok az automatizáláshoz
</details>
<details>
<summary><b>🔐 21. "Hatókörű MCP-engedélyekre van szükségem integrációnként"</b></summary>
A különböző ügyfeleknek a legkevesebb jogosultsággal kell rendelkezniük az eszközkategóriákhoz.
**Hogyan oldja meg az OmniRoute:**
- 9 szemcsés MCP hatókör az ellenőrzött szerszámhozzáféréshez
- Hatályérvényesítés és láthatóság az MCP-kezelő felületen
- Biztonságos alaphelyzet az üzemi szerszámokhoz
</details>
<details>
<summary><b>⚙️ 22. "Üzemeltetési vezérlőkre van szükségem átcsoportosítás nélkül" </b></summary>
A csapatoknak gyors futásidejű változtatásokra van szükségük incidensek vagy költségesemények során.
**Hogyan oldja meg az OmniRoute:**
- A kombinált aktiválás váltása közvetlenül az MCP műszerfaláról
- Rugalmassági profilok alkalmazása előre meghatározott házirend-csomagokból
- Állítsa vissza a megszakító állapotát ugyanarról a kezelőpanelről
</details>
<details>
<summary><b>🔄 23. "Szükségem van élő A2A feladatok életciklusának láthatóságára és törlésére"</b></summary>
Az életciklus láthatósága nélkül a feladat-incidensek nehezen osztályozhatók.
**Hogyan oldja meg az OmniRoute:**
- Feladatok listázása/szűrés állapot/készség szerint oldalszámozással
- A feladatok metaadatainak, eseményeinek és műtermékeinek részletezése
- Feladat törlési végpont és felhasználói felület művelet megerősítéssel
</details>
<details>
<summary><b>🌊 24. "Aktív adatfolyam-metrikákra van szükségem A2A terheléshez"</b></summary>
A streamelési munkafolyamatok működési betekintést igényelnek a párhuzamosság és az élő kapcsolatok terén.
**Hogyan oldja meg az OmniRoute:**
- Az A2A állapotba integrált aktív folyamszámlálók
- Utolsó feladat időbélyegzője és állapotonkénti száma
- A2A műszerfalkártyák a valós idejű műveletek figyeléséhez
</details>
<details>
<summary><b>🪪 25. "Szabványos ügynökfelderítésre van szükségem az ügyfelek számára" </b></summary>
A külső klienseknek és hangszerelőknek géppel olvasható metaadatokra van szükségük a bevezetéshez.
**Hogyan oldja meg az OmniRoute:**
- Az ügynökkártya az `/.well-known/agent.json` címen látható
- A menedzsment felületen látható képességek és készségek
- Az A2A állapot API felfedezési metaadatokat tartalmaz az automatizáláshoz
</details>
<details>
<summary><b>🧭 26. "Protokoll felfedezhetőségre van szükségem az UX termékben"</b></summary>
Ha a felhasználók nem fedezik fel a protokollfelületeket, az elfogadás és a támogatás minősége csökken.
**Hogyan oldja meg az OmniRoute:**
- Oldalsáv bejegyzések MCP és A2A számára
- Végpont oldal Protokollok lap gyorsindítással és állapottal
- Linkek az áttekintésből a dedikált felügyeleti irányítópultokhoz
</details>
<details>
<summary><b>🧪 27. "Végponttól végpontig terjedő protokoll-érvényesítésre van szükségem valós kliensekkel"</b></summary>
A próbatesztek nem elegendőek a protokoll-kompatibilitás ellenőrzéséhez a kiadás előtt.
**Hogyan oldja meg az OmniRoute:**
- E2E csomag, amely elindítja az alkalmazást, és valódi MCP SDK kliens szállítást használ
- Az A2A kliens teszteli az áramlások felfedezését, küldését, streamingjét, lekérését és megszakítását
- Az állítások keresztellenőrzése az MCP audit és az A2A feladatok API-jával szemben
</details>
<details>
<summary><b>📡 28. "Egységes megfigyelhetőségre van szükségem minden interfészen"</b></summary>
A megfigyelhetőség protokoll szerinti felosztása vakfoltokat és hosszabb MTTR-t hoz létre.
**Hogyan oldja meg az OmniRoute:**
- Egységes irányítópultok/naplók/analytics egy termékben
- Egészség + audit + kérés telemetria OpenAI, MCP és A2A rétegeken keresztül
- Működési API-k az állapothoz és az automatizáláshoz
</details>
<details>
<summary><b>💼 29. "Egy futási időre van szükségem a proxyhoz + eszközökhöz + ügynök hangszereléshez" </b></summary>
Számos külön szolgáltatás futtatása növeli a működési költségeket és a hibamódokat.
**Hogyan oldja meg az OmniRoute:**
- OpenAI-kompatibilis proxy, MCP szerver és A2A szerver egy veremben
- Megosztott hitelesítés, rugalmasság, adattárolás és megfigyelhetőség
- Konzisztens politikai modell az összes interakciós felületen
</details>
<details>
<summary><b>🚀 30. "Az ügynöki munkafolyamatokat ragasztókód szétszórása nélkül kell szállítanom" </b></summary>
A csapatok veszítenek sebességükből, amikor több ad-hoc szolgáltatást és szkriptet illesztenek össze.
**Hogyan oldja meg az OmniRoute:**
- Egységes végpont stratégia az ügyfelek és ügynökök számára
- Beépített protokollkezelő felhasználói felületek és füstellenőrzési útvonalak
- Gyártásra kész alapok (biztonság, naplózás, rugalmasság, biztonsági mentés)
</details>
### Példa forgatókönyvekre (integrált használati esetek)
**A játékkönyv: Maximalizálja a fizetett előfizetést + olcsó biztonsági mentés**
```txt
Combo: "maximize-claude"
1. cc/claude-opus-4-6
2. glm/glm-4.7
3. if/kimi-k2-thinking
Monthly cost: $20 + small backup spend
Outcome: higher quality, near-zero interruption
```
**Playbook B: Zéró költségű kódolási verem**
```txt
Combo: "free-forever"
1. gc/gemini-3-flash
2. if/kimi-k2-thinking
3. qw/qwen3-coder-plus
Monthly cost: $0
Outcome: stable free coding workflow
```
**Playbook C: 24/7 mindig bekapcsolt tartalék lánc**
```txt
Combo: "always-on"
1. cc/claude-opus-4-6
2. cx/gpt-5.2-codex
3. glm/glm-4.7
4. minimax/MiniMax-M2.1
5. if/kimi-k2-thinking
Outcome: deep fallback depth for deadline-critical workloads
```
**D játékkönyv: Az ügynök MCP + A2A-val működik**
```txt
1) Start MCP transport (`omniroute --mcp`) for tool-driven operations
2) Run A2A tasks via `message/send` and `message/stream`
3) Observe via /dashboard/mcp and /dashboard/a2a
4) Control incidents with resilience profile + task cancellation
```
---
## ⚡ Gyors kezdés
**1. Globális telepítés:**
@@ -251,7 +782,7 @@ docker compose --profile cli up -d
---
## 🖥️ Desktop App — Offline & Always-On
## 🖥️
> 🆕 **NEW!** OmniRoute is now available as a **native desktop application** for Windows, macOS, and Linux.
@@ -298,67 +829,6 @@ npm run electron:build:linux # Linux (.AppImage)
---
## 🎯 Használati esetek
### 1. eset: "Claude Pro előfizetésem van"
**Probléma:** A kvóta lejár, kihasználatlanul, sebességkorlátozások erős kódolás közben
```
Combo: "maximize-claude"
1. cc/claude-opus-4-6 (use subscription fully)
2. glm/glm-4.7 (cheap backup when quota out)
3. if/kimi-k2-thinking (free emergency fallback)
Monthly cost: $20 (subscription) + ~$5 (backup) = $25 total
vs. $20 + hitting limits = frustration
```
### 2. eset: "Nulla költséget akarok"
**Probléma:** Nem engedheti meg magának az előfizetést, megbízható mesterséges intelligencia kódolásra van szüksége
```
Combo: "free-forever"
1. gc/gemini-3-flash (180K free/month)
2. if/kimi-k2-thinking (unlimited free)
3. qw/qwen3-coder-plus (unlimited free)
Monthly cost: $0
Quality: Production-ready models
```
### 3. eset: "24 órás kódolásra van szükségem, megszakítás nélkül"
**Probléma:** Határidők, nem engedheti meg magának az állásidőt
```
Combo: "always-on"
1. cc/claude-opus-4-6 (best quality)
2. cx/gpt-5.2-codex (second subscription)
3. glm/glm-4.7 (cheap, resets daily)
4. minimax/MiniMax-M2.1 (cheapest, 5h reset)
5. if/kimi-k2-thinking (free unlimited)
Result: 5 layers of fallback = zero downtime
```
### 4. eset: "INGYENES AI-t akarok az OpenClawban"
**Probléma:** AI-asszisztens szükséges az üzenetküldő alkalmazásokhoz, teljesen ingyenes
```
Combo: "openclaw-free"
1. if/glm-4.7 (unlimited free)
2. if/minimax-m2.1 (unlimited free)
3. if/kimi-k2-thinking (unlimited free)
Monthly cost: $0
Access via: WhatsApp, Telegram, Slack, Discord, iMessage, Signal...
```
---
## 💡 Főbb jellemzők
### 🧠 Core Routing & Intelligence
@@ -374,6 +844,8 @@ Access via: WhatsApp, Telegram, Slack, Discord, iMessage, Signal...
| 🧩 **Egyedi modellek** | Adjon hozzá bármilyen modellazonosítót bármely szolgáltatóhoz |
| 🌐 **Wildcard Router** | `provider/*` minták továbbítása bármely szolgáltatóhoz dinamikusan |
| 🧠 **Átgondolt költségvetés** | Átjárási, automatikus, egyéni és adaptív módok érvelési modellekhez |
| 🔀 **Model Aliases** | Auto-forward deprecated model IDs to current replacements (built-in + custom) |
| ⚡ **Background Degradation** | Auto-route background tasks (titles, summaries) to cheaper models |
| 💬 **Rendszer azonnali befecskendezés** | Globális rendszerkérdés minden kérelemre érvényes |
| 📄 **Responses API** | Teljes OpenAI Responses API (`/v1/responses`) támogatás a Codexhez |
@@ -399,6 +871,8 @@ Access via: WhatsApp, Telegram, Slack, Discord, iMessage, Signal...
| 🔒 **TLS ujjlenyomat-hamisítás** | A TLS-alapú botészlelés megkerülése a wreq-js segítségével |
| 🌐 **IP-szűrés** | Allowlist/blokkolista API hozzáférés-vezérléshez |
| 📊 **Szerkeszthető díjkorlátok** | Konfigurálható fordulatszám, minimális rés és maximális egyidejű rendszerszinten |
| 💾 **Rate Limit Persistence** | Learned limits survive restarts via SQLite with 60s debounce + 24h staleness |
| 🔄 **Token Refresh Resilience** | Per-provider circuit breaker (5 fails→30min) + 30s timeout per attempt |
| 🛡 **API Endpoint Protection** | Auth kapuzás + szolgáltató blokkolása a `/models` végponthoz |
| 🔒 **Proxy láthatósága** | Színkódolt jelvények: 🟢 globális, 🟡 szolgáltató, 🔵 kapcsolatonként IP kijelzővel |
| 🌐 **3-szintű proxykonfiguráció** | Proxyk konfigurálása globális, szolgáltatónkénti vagy kapcsolatonkénti szinten |
@@ -517,6 +991,27 @@ Az OmniRoute egy erőteljes beépített fordítói játszóteret tartalmaz **4 m
</details>
## 🧪 Értékelések (Evals)
Az OmniRoute egy beépített értékelési keretrendszert tartalmaz az LLM-válasz minőségének tesztelésére egy aranykészlettel összehasonlítva. Az irányítópult **Analytics → Evals** menüpontjában érheti el.
### Beépített arany készlet
Az előre feltöltött "OmniRoute Golden Set" 10 tesztesetet tartalmaz, amelyek lefedik:
- Üdvözlet, matematika, földrajz, kódgenerálás
- JSON formátum megfelelés, fordítás, leértékelés
- Biztonsági elutasítás (káros tartalom), számlálás, logikai logika
### Értékelési stratégiák
| Stratégia | Leírás | Példa |
| ---------- | ------------------------------------------------------------------------------------------------- | -------------------------------- |
| `exact` | A kimenetnek pontosan meg kell egyeznie | `"4"` |
| `contains` | A kimenetnek tartalmaznia kell részkarakterláncot (a kis- és nagybetűk nem különböznek egymástól) | `"Paris"` |
| `regex` | A kimenetnek meg kell egyeznie a regex mintával | `"1.*2.*3"` |
| `custom` | Az egyéni JS függvény igaz/hamis | `(output) => output.length > 10` |
---
## 📖 Beállítási útmutató
@@ -799,104 +1294,64 @@ Settings → API Configuration:
---
## 📊 Elérhető modellek
## 🐛 Hibaelhárítás
<details>
<summary><b>Az összes elérhető modell megtekintése</b></summary>
<summary><b>Kattintson a hibaelhárítási útmutató kibontásához</b></summary>
**Claude Code (`cc/`)** - Pro/Max:
**"A nyelvi modell nem adott üzenetet"**
- `cc/claude-opus-4-6`
- `cc/claude-sonnet-4-5-20250929`
- `cc/claude-haiku-4-5-20251001`
- A szolgáltatói kvóta kimerült → Ellenőrizze az irányítópult kvótakövetőjét
- Megoldás: Használjon kombinált tartalékot, vagy váltson olcsóbb szintre
**Kód (`cx/`)** - Plusz/Pro:
**Drátakorlát**
- `cx/gpt-5.2-codex`
- `cx/gpt-5.1-codex-max`
- Előfizetési kvóta lejárt → Tartalék a GLM/MiniMax-hoz
- Kombinó hozzáadása: `cc/claude-opus-4-6 → glm/glm-4.7 → if/kimi-k2-thinking`
**Gemini CLI (`gc/`)** INGYENES:
**OAuth token lejárt**
- `gc/gemini-3-flash-preview`
- `gc/gemini-2.5-pro`
- Az OmniRoute automatikusan frissíti
- Ha a problémák továbbra is fennállnak: Irányítópult → Szolgáltató → Újracsatlakozás
**GitHub másodpilóta (`gh/`)**:
**Magas költségek**
- `gh/gpt-5`
- `gh/claude-4.5-sonnet`
- Ellenőrizze a használati statisztikákat az Irányítópult → Költségek menüpontban
- Állítsa át az elsődleges modellt GLM/MiniMax-ra
- Használjon ingyenes réteget (Gemini CLI, iFlow) a nem kritikus feladatokhoz
**NVIDIA NIM (`nvidia/`)** - INGYENES kreditek:
**A műszerfal rossz porton nyílik meg**
- `nvidia/llama-3.3-70b-instruct`
- `nvidia/mistral-7b-instruct`
- 50+ további modell itt: [build.nvidia.com](https://build.nvidia.com)
- `PORT=20128` és `NEXT_PUBLIC_BASE_URL=http://localhost:20128` beállítása
**GLM (`glm/`)** - 0,6 USD/1 millió:
**Felhő szinkronizálási hibák**
- `glm/glm-4.7`
- Ellenőrizze, hogy `BASE_URL` mutat a futó példányra
- Ellenőrizzen `CLOUD_URL` pontot a várható felhő-végponthoz
- Tartsa az `NEXT_PUBLIC_*` értékeket a szerveroldali értékekkel összhangban
**MiniMax (`minimax/`)** - 0,2 USD/1 millió:
**Az első bejelentkezés nem működik**
- `minimax/MiniMax-M2.1`
- Ellenőrizze a `INITIAL_PASSWORD`-t itt: `.env`
- Ha nincs beállítva, a tartalék jelszó: `123456`
**iFlow (`if/`)** INGYENES:
**Nincs kérésnapló**
- `if/kimi-k2-thinking`
- `if/qwen3-coder-plus`
- `if/deepseek-r1`
- `if/glm-4.7`
- `if/minimax-m2`
- Állítsa be `ENABLE_REQUEST_LOGS=true` a `.env`-ban
**Qwen (`qw/`)** - INGYENES:
**A csatlakozási teszt „Érvénytelen” üzenetet mutat az OpenAI-kompatibilis szolgáltatók esetében**
- `qw/qwen3-coder-plus`
- `qw/qwen3-coder-flash`
- Sok szolgáltató nem tesz közzé `/models` végpontot
- Az OmniRoute v1.0.6+ tartalmazza a tartalék érvényesítést a csevegés befejezésén keresztül
- Győződjön meg arról, hogy az alap URL tartalmazza a `/v1` utótagot
**Kiro (`kr/`)** INGYENES:
- `kr/claude-sonnet-4.5`
- `kr/claude-haiku-4.5`
**OpenRouter (`or/`)** - 100+ modell:
- `or/anthropic/claude-4-sonnet`
- `or/google/gemini-2.5-pro`
- Bármelyik modell a [openrouter.ai/models](https://openrouter.ai/models) terméktől
</details>
---
## 🧪 Értékelések (Evals)
Az OmniRoute egy beépített értékelési keretrendszert tartalmaz az LLM-válasz minőségének tesztelésére egy aranykészlettel összehasonlítva. Az irányítópult **Analytics → Evals** menüpontjában érheti el.
### Beépített arany készlet
Az előre feltöltött "OmniRoute Golden Set" 10 tesztesetet tartalmaz, amelyek lefedik:
- Üdvözlet, matematika, földrajz, kódgenerálás
- JSON formátum megfelelés, fordítás, leértékelés
- Biztonsági elutasítás (káros tartalom), számlálás, logikai logika
### Értékelési stratégiák
| Stratégia | Leírás | Példa |
| ---------- | ------------------------------------------------------------------------------------------------- | -------------------------------- |
| `exact` | A kimenetnek pontosan meg kell egyeznie | `"4"` |
| `contains` | A kimenetnek tartalmaznia kell részkarakterláncot (a kis- és nagybetűk nem különböznek egymástól) | `"Paris"` |
| `regex` | A kimenetnek meg kell egyeznie a regex mintával | `"1.*2.*3"` |
| `custom` | Az egyéni JS függvény igaz/hamis | `(output) => output.length > 10` |
---
## 🔐 OAuth em Servidor Remoto (távoli OAuth beállítás)
### 🔐 OAuth
<a name="oauth-em-servidor-remoto"></a>
> **⚠️ FONTOS az OmniRoute em VPS/Docker/servidor Remoto használatához**
### Az OAuth do Antigravity / Gemini CLI falha em servidores remotos?
### OAuth
Az **Antigravitáció** és a **Gemini CLI** usam **Google OAuth 2.0** hitelesítése. A Google exige que a `redirect_uri` nincs fluxo OAuth seja **exatamente** uma das URI-k pre-cadastradas no Google Cloud Console do aplicativo.
@@ -981,64 +1436,11 @@ Se não quiser criar credenciais próprias agora, ainda é possível usar o flux
> Este workaround funciona porque o código de autorização na URL é válido independente do redirect ter carregado ou não.
---
## 🐛 Hibaelhárítás
<details>
<summary><b>Kattintson a hibaelhárítási útmutató kibontásához</b></summary>
**"A nyelvi modell nem adott üzenetet"**
- A szolgáltatói kvóta kimerült → Ellenőrizze az irányítópult kvótakövetőjét
- Megoldás: Használjon kombinált tartalékot, vagy váltson olcsóbb szintre
**Drátakorlát**
- Előfizetési kvóta lejárt → Tartalék a GLM/MiniMax-hoz
- Kombinó hozzáadása: `cc/claude-opus-4-6 → glm/glm-4.7 → if/kimi-k2-thinking`
**OAuth token lejárt**
- Az OmniRoute automatikusan frissíti
- Ha a problémák továbbra is fennállnak: Irányítópult → Szolgáltató → Újracsatlakozás
**Magas költségek**
- Ellenőrizze a használati statisztikákat az Irányítópult → Költségek menüpontban
- Állítsa át az elsődleges modellt GLM/MiniMax-ra
- Használjon ingyenes réteget (Gemini CLI, iFlow) a nem kritikus feladatokhoz
**A műszerfal rossz porton nyílik meg**
- `PORT=20128` és `NEXT_PUBLIC_BASE_URL=http://localhost:20128` beállítása
**Felhő szinkronizálási hibák**
- Ellenőrizze, hogy `BASE_URL` mutat a futó példányra
- Ellenőrizzen `CLOUD_URL` pontot a várható felhő-végponthoz
- Tartsa az `NEXT_PUBLIC_*` értékeket a szerveroldali értékekkel összhangban
**Az első bejelentkezés nem működik**
- Ellenőrizze a `INITIAL_PASSWORD`-t itt: `.env`
- Ha nincs beállítva, a tartalék jelszó: `123456`
**Nincs kérésnapló**
- Állítsa be `ENABLE_REQUEST_LOGS=true` a `.env`-ban
**A csatlakozási teszt „Érvénytelen” üzenetet mutat az OpenAI-kompatibilis szolgáltatók esetében**
- Sok szolgáltató nem tesz közzé `/models` végpontot
- Az OmniRoute v1.0.6+ tartalmazza a tartalék érvényesítést a csevegés befejezésén keresztül
- Győződjön meg arról, hogy az alap URL tartalmazza a `/v1` utótagot
</details>
---
## 🛠️ Tech Stack
## 🛠️
- **Futtatási idejű**: Node.js 1822 LTS (⚠️ A Node.js 24+ **nem támogatott** - A `better-sqlite3` natív binárisok nem kompatibilisek)
- **Nyelv**: TypeScript 5.9 **100% TypeScript** `src/` és `open-sse/` (v1.0.6) között
@@ -1090,7 +1492,7 @@ Se não quiser criar credenciais próprias agora, ainda é possível usar o flux
---
## 🗺️ Útiterv
## 🗺️
Az OmniRoute **210+ funkciót tervez** több fejlesztési fázisban. Íme a legfontosabb területek:
@@ -1115,18 +1517,6 @@ Az OmniRoute **210+ funkciót tervez** több fejlesztési fázisban. Íme a legf
---
## 📧 Támogatás
> 💬 **Csatlakozzon közösségünkhöz!** [WhatsApp Group](https://chat.whatsapp.com/JI7cDQ1GyaiDHhVBpLxf8b?mode=gi_t) — Kérjen segítséget, ossza meg tippjeit, és naprakész legyen.
- **Webhely**: [omniroute.online](https://omniroute.online)
- **GitHub**: [github.com/diegosouzapw/OmniRoute](https://github.com/diegosouzapw/OmniRoute)
- **Problémák**: [github.com/diegosouzapw/OmniRoute/issues](https://github.com/diegosouzapw/OmniRoute/issues)
- **WhatsApp**: [Community Group](https://chat.whatsapp.com/JI7cDQ1GyaiDHhVBpLxf8b?mode=gi_t)
- **Eredeti projekt**: [9router by decolua](https://github.com/decolua/9router)
---
## 👥 Közreműködők
[![Contributors](https://contrib.rocks/image?repo=diegosouzapw/OmniRoute&max=100&columns=20&anon=1)](https://github.com/diegosouzapw/OmniRoute/graphs/contributors)
@@ -1176,85 +1566,6 @@ MIT-licenc a részletekért lásd: [LICENSE](LICENSE).
---
---
## 🇧🇷 OmniRoute — IA ingyenes átjáró
<a name="-omniroute--gateway-de-ia-gratuito"></a>
### Nunca pare de codar. Roteamento inteligente para **modelos de IA GRATUITOS e de baixo custo** com backback automatico.
_Seu proxy univerzális API um végpont, 36+ gyártó, nulla leállás._
### 🌐 Internacionalização (i18n)
O dashboard do OmniRoute támogatja a **múltiplos idiomas**. Atualmente disponível em:
| Idioma | Código | Állapot |
| --------------------- | ------- | ----------- |
| 🇺🇸 angol | `en` | ✅ Completo |
| 🇧🇷 Português (Brasil) | `pt-BR` | ✅ Completo |
**Para trocar o idioma:** Clique no seletor de idioma (🇺🇸 EN) no header do dashboard → Selectione o idioma desejado.
**Para adicionar um novo idioma:**
1. Sírj `src/i18n/messages/{codigo}.json` baseado em `en.json`
2. Adicione o código em `src/i18n/config.ts``LOCALES` e `LANGUAGES`
3. Reinicie o servidor
### ⚡ Início Rápido
```bash
# Instalar via npm
npx omniroute@latest
# Ou rodar do código-fonte
cp .env.example .env
npm install
PORT=20128 NEXT_PUBLIC_BASE_URL=http://localhost:20128 npm run dev
```
### 🐳 Docker
```bash
docker run -d --name omniroute -p 20128:20128 diegosouzapw/omniroute:latest
```
### 🔑 Funcionalidades Principais
- **36+ IA produkátor** Claude, GPT, Gemini, Llama, Qwen, DeepSeek, e mais
- **Roteamento inteligente** — Fallback automatico entre provedores
- **Tradução de formato** — OpenAI ↔ Claude ↔ Gemini automatamente
- **Multi-conta** — Múltiplas contas por provedor com seleção inteligente
- **Cache szemântico** Reduz custos e latência
- **OAuth automatico** — Tokens renovam automaticamente
- **Combos personalizados** - 6 estratégias de roteamento
- **Befejezett irányítópult** - Monitoring, naplók, elemzések, konfigurációk
- **CLI eszközök** — Claude Code, Codex, Cursor, Cline com um clique konfigurálása
- **100% TypeScript** Código limpo e tipado
### 📖 Documentação
| Documento | Leírás |
| ----------------------------------------------- | -------------------------------------- |
| [Guia do Usuário](docs/USER_GUIDE.md) | Provedores, kombók, CLI, telepítés |
| [Referência da API](docs/API_REFERENCE.md) | Todos os végpontok com exemplos |
| [Solução de Problemas](docs/TROUBLESHOOTING.md) | Problemas comuns e soluções |
| [Arquitetura](docs/ARCHITECTURE.md) | Arquitetura e internos do sistema |
| [Contribuição](CONTRIBUTING.md) | Setup de desenvolvimento e Guidelines |
| [Deploy em VM](docs/VM_DEPLOYMENT_GUIDE.md) | Teljes verzió: VM + nginx + Cloudflare |
### 📧 Támogatás
> 💬 **Entre para a comunidade!** [Grupo WhatsApp](https://chat.whatsapp.com/JI7cDQ1GyaiDHhVBpLxf8b?mode=gi_t) — Tire dúvidas, compartilhe dicas e fique atualizado.
- **Webhely**: [omniroute.online](https://omniroute.online)
- **GitHub**: [github.com/diegosouzapw/OmniRoute](https://github.com/diegosouzapw/OmniRoute)
- **Problémák**: [github.com/diegosouzapw/OmniRoute/issues](https://github.com/diegosouzapw/OmniRoute/issues)
---
<div align="center">
<sub>A ❤️ segítségével készült a 24/7 kódoló fejlesztőknek</sub>
<br/>

View File

@@ -3,8 +3,6 @@
# 🚀 OmniRoute — Gerbang AI Gratis
🌐 **[English](#-omniroute--the-free-ai-gateway)** | **[Português (BR)](#-omniroute--gateway-de-ia-gratuito)**
### Jangan pernah berhenti membuat kode. Perutean cerdas ke **model AI GRATIS & berbiaya rendah** dengan fallback otomatis.
_Proksi API universal Anda — satu titik akhir, 36+ penyedia, tanpa waktu henti._
@@ -112,6 +110,35 @@ _Hubungkan alat IDE atau CLI apa pun yang didukung AI melalui OmniRoute — gerb
---
## 🖼️
<div align="center">
<img src="./docs/screenshots/MainOmniRoute.png" alt="OmniRoute" width="800"/>
</div>
---
## 📸
<details>
<summary><b>...</b></summary>
| # | # |
| ----- | ---------------------------------------- |
| **1** | ![1](docs/screenshots/01-providers.png) |
| **2** | ![2](docs/screenshots/02-combos.png) |
| **3** | ![3](docs/screenshots/03-analytics.png) |
| **4** | ![4](docs/screenshots/04-health.png) |
| **5** | ![5](docs/screenshots/05-translator.png) |
| **6** | ![6](docs/screenshots/06-settings.png) |
| **7** | ![7](docs/screenshots/07-cli-tools.png) |
| **8** | ![8](docs/screenshots/08-usage.png) |
| **9** | ![9](docs/screenshots/09-endpoint.png) |
</details>
---
## 🤔 Mengapa OmniRoute?
**Berhenti membuang-buang uang dan mencapai batas:**
@@ -130,6 +157,18 @@ _Hubungkan alat IDE atau CLI apa pun yang didukung AI melalui OmniRoute — gerb
---
## 📧 Dukungan
> 💬 **Bergabunglah dengan komunitas kami!** [WhatsApp Group](https://chat.whatsapp.com/JI7cDQ1GyaiDHhVBpLxf8b?mode=gi_t) — Dapatkan bantuan, berbagi kiat, dan dapatkan informasi terbaru.
- **Situs Web**: [omniroute.online](https://omniroute.online)
- **GitHub**: [github.com/diegosouzapw/OmniRoute](https://github.com/diegosouzapw/OmniRoute)
- **Masalah**: [github.com/diegosouzapw/OmniRoute/issues](https://github.com/diegosouzapw/OmniRoute/issues)
- **WhatsApp**: [Community Group](https://chat.whatsapp.com/JI7cDQ1GyaiDHhVBpLxf8b?mode=gi_t)
- **Proyek Asli**: [9router by decolua](https://github.com/decolua/9router)
---
## 🔄 Cara Kerjanya
```
@@ -159,6 +198,498 @@ Result: Never stop coding, minimal cost
---
## 🎯 Apa yang Dipecahkan OmniRoute — 30 Masalah Nyata & Kasus Penggunaan
> **Setiap pengembang yang menggunakan alat AI menghadapi masalah ini setiap hari.** OmniRoute dibuat untuk menyelesaikan semuanya — mulai dari pembengkakan biaya hingga pemblokiran regional, mulai dari aliran OAuth yang rusak hingga operasi protokol dan kemampuan observasi perusahaan.
<details>
<summary><b>💸 1. "Saya membayar langganan yang mahal tetapi masih terganggu oleh batasan"</b></summary>
Pengembang membayar $20200/bulan untuk Claude Pro, Codex Pro, atau GitHub Copilot. Bahkan saat membayar, kuota memiliki batas tertinggi — penggunaan 5 jam, batas mingguan, atau batas tarif per menit. Di tengah sesi pengkodean, penyedia berhenti merespons dan pengembang kehilangan aliran dan produktivitas.
**Bagaimana OmniRoute menyelesaikannya:**
- **Smart 4-Tier Fallback** — Jika kuota berlangganan habis, otomatis dialihkan ke Kunci API → Murah → Gratis tanpa intervensi manual
- **Pelacakan Kuota Real-Time** — Menampilkan konsumsi token secara real-time dengan hitungan mundur reset (5 jam, harian, mingguan)
- **Dukungan Multi-Akun** — Beberapa akun per penyedia dengan sistem round-robin otomatis — jika satu akun habis, beralih ke akun berikutnya
- **Kombo Khusus** — Rantai cadangan yang dapat disesuaikan dengan 6 strategi penyeimbangan (isi terlebih dahulu, round-robin, P2C, acak, paling jarang digunakan, hemat biaya)
- **Codex Business Quotas** — Pemantauan kuota ruang kerja Bisnis/Tim langsung di dasbor
</details>
<details>
<summary><b>🔌 2. "Saya perlu menggunakan beberapa penyedia tetapi masing-masing memiliki API yang berbeda"</b></summary>
OpenAI menggunakan satu format, Claude (Anthropic) menggunakan format lain, Gemini menggunakan format lain. Jika pengembang ingin menguji model dari penyedia yang berbeda atau melakukan fallback di antara penyedia tersebut, mereka perlu mengonfigurasi ulang SDK, mengubah titik akhir, menangani format yang tidak kompatibel. Penyedia khusus (FriendLI, NIM) memiliki titik akhir model non-standar.
**Bagaimana OmniRoute menyelesaikannya:**
- **Titik Akhir Terpadu** — Satu `http://localhost:20128/v1` berfungsi sebagai proxy untuk 36+ penyedia
- **Terjemahan Format** — Otomatis dan transparan: OpenAI ↔ Claude ↔ Gemini ↔ Responses API
- **Sanitasi Respons** — Menghapus kolom non-standar (`x_groq`, `usage_breakdown`, `service_tier`) yang merusak OpenAI SDK v1.83+
- **Normalisasi Peran** — Mengonversi `developer``system` untuk penyedia non-OpenAI; `system``user` untuk GLM/ERNIE
- **Think Tag Extraction** — Mengekstrak blok `<think>` dari model seperti DeepSeek R1 ke dalam `reasoning_content` standar
- **Output Terstruktur untuk Gemini** — `json_schema``responseMimeType`/`responseSchema` konversi otomatis
- **`stream` defaultnya adalah `false`** — Sesuai dengan spesifikasi OpenAI, menghindari SSE yang tidak terduga di SDK Python/Rust/Go
</details>
<details>
<summary><b>🌐 3. "Penyedia AI saya memblokir wilayah/negara saya"</b></summary>
Penyedia seperti OpenAI/Codex memblokir akses dari wilayah geografis tertentu. Pengguna mendapatkan kesalahan seperti `unsupported_country_region_territory` selama koneksi OAuth dan API. Hal ini sangat membuat frustasi bagi pengembang dari negara-negara berkembang.
**Bagaimana OmniRoute menyelesaikannya:**
- **Konfigurasi Proksi 3 Tingkat** — Proksi yang dapat dikonfigurasi pada 3 tingkat: global (semua lalu lintas), per penyedia (hanya satu penyedia), dan per koneksi/kunci
- **Lencana Proksi Berkode Warna** — Indikator visual: 🟢 proksi global, 🟡 proksi penyedia, 🔵 proksi koneksi, selalu menampilkan IP
- **OAuth Token Exchange Through Proxy** — Aliran OAuth juga melewati proxy, menyelesaikan `unsupported_country_region_territory`
- **Tes Koneksi melalui Proxy** — Tes koneksi menggunakan proxy yang dikonfigurasi (tidak ada lagi bypass langsung)
- **Dukungan SOCKS5** — Dukungan proksi SOCKS5 penuh untuk perutean keluar
- **TLS Fingerprint Spoofing** — Sidik jari TLS mirip browser melalui `wreq-js` untuk melewati deteksi bot
</details>
<details>
<summary><b>🆓 4. "Saya ingin menggunakan AI untuk coding tetapi saya tidak punya uang" </b></summary>
Tidak semua orang mampu membayar $20200/bulan untuk berlangganan AI. Pelajar, pengembang dari negara-negara berkembang, penghobi, dan pekerja lepas memerlukan akses ke model berkualitas tanpa biaya.
**Bagaimana OmniRoute menyelesaikannya:**
- **Terintegrasi Penyedia Tingkat Gratis** — Dukungan asli untuk 100% penyedia gratis: iFlow (8 model tak terbatas), Qwen (3 model tak terbatas), Kiro (Claude gratis), Gemini CLI (gratis 180K/bulan)
- **Kombo Khusus Gratis** — Rantai `gc/gemini-3-flash → if/kimi-k2-thinking → qw/qwen3-coder-plus` = $0/bulan tanpa downtime
- **Kredit Gratis NVIDIA NIM** — 1000 kredit gratis terintegrasi
- **Strategi Pengoptimalan Biaya** — Strategi perutean yang secara otomatis memilih penyedia termurah yang tersedia
</details>
<details>
<summary><b>🔒 5. "Saya perlu melindungi gateway AI saya dari akses tidak sah" </b></summary>
Saat mengekspos gateway AI ke jaringan (LAN, VPS, Docker), siapa pun yang memiliki alamat tersebut dapat menggunakan token/kuota pengembang. Tanpa perlindungan, API rentan terhadap penyalahgunaan, injeksi cepat, dan penyalahgunaan.
**Bagaimana OmniRoute menyelesaikannya:**
- **Manajemen Kunci API** — Pembuatan, rotasi, dan pelingkupan per penyedia dengan halaman `/dashboard/api-manager` khusus
- **Izin Tingkat Model** — Membatasi kunci API untuk model tertentu (`openai/*`, pola karakter pengganti), dengan tombol Izinkan Semua/Batasi
- **API Endpoint Protection** — Memerlukan kunci untuk `/v1/models` dan memblokir penyedia tertentu dari daftar
- **Auth Guard + Perlindungan CSRF** — Semua rute dasbor dilindungi dengan middleware `withAuth` + token CSRF
- **Pembatas Kecepatan** — Pembatasan kecepatan per-IP dengan jendela yang dapat dikonfigurasi
- **Pemfilteran IP** — Daftar yang diizinkan/daftar blokir untuk kontrol akses
- **Prompt Injection Guard** — Sanitasi terhadap pola prompt berbahaya
- **Enkripsi AES-256-GCM** — Kredensial dienkripsi saat disimpan
</details>
<details>
<summary><b>🛑 6. "Penyedia saya down dan saya kehilangan alur pengkodean"</b></summary>
Penyedia AI bisa menjadi tidak stabil, menampilkan kesalahan 5xx, atau mencapai batas kecepatan sementara. Jika pengembang bergantung pada satu penyedia, mereka akan terganggu. Tanpa pemutus sirkuit, percobaan ulang yang berulang-ulang dapat membuat aplikasi crash.
**Bagaimana OmniRoute menyelesaikannya:**
- **Pemutus Sirkuit per penyedia** — Buka/tutup otomatis dengan ambang batas dan cooldown yang dapat dikonfigurasi (Tertutup/Terbuka/Setengah Terbuka)
- **Kemunduran Eksponensial** — Penundaan percobaan ulang yang progresif
- **Kawanan Anti-Guntur** — Perlindungan mutex + semaphore terhadap badai percobaan ulang secara bersamaan
- **Combo Fallback Chains** — Jika penyedia utama gagal, otomatis gagal dalam rantai tanpa intervensi
- **Combo Circuit Breaker** — Menonaktifkan secara otomatis penyedia yang gagal dalam rantai kombo
| 🎯 **Endpoint-Aware Models** | Custom models declare supported endpoints + API format |
- **Dasbor Kesehatan** — Pemantauan waktu aktif, status pemutus sirkuit, penguncian, statistik cache, latensi p50/p95/p99
</details>
<details>
<summary><b>🔧 7. "Mengonfigurasi setiap alat AI membosankan dan berulang-ulang"</b></summary>
Pengembang menggunakan Cursor, Claude Code, Codex CLI, OpenClaw, Gemini CLI, Kilo Code... Setiap alat memerlukan konfigurasi yang berbeda (titik akhir API, kunci, model). Mengonfigurasi ulang saat berpindah penyedia atau model hanya membuang-buang waktu.
**Bagaimana OmniRoute menyelesaikannya:**
- **Dasbor Alat CLI** — Halaman khusus dengan pengaturan sekali klik untuk Claude Code, Codex CLI, OpenClaw, Kilo Code, Antigravity, Cline
- **GitHub Copilot Config Generator** — Menghasilkan `chatLanguageModels.json` untuk VS Code dengan pemilihan model massal
- **Onboarding Wizard** — Panduan penyiapan 4 langkah untuk pengguna pertama kali
- **Satu titik akhir, semua model** — Konfigurasikan `http://localhost:20128/v1` satu kali, akses 36+ penyedia
</details>
<details>
<summary><b>🔑 8. "Mengelola token OAuth dari banyak penyedia adalah neraka"</b></summary>
Claude Code, Codex, Gemini CLI, Copilot — semuanya menggunakan OAuth 2.0 dengan token yang kedaluwarsa. Pengembang perlu melakukan autentikasi ulang terus-menerus, menangani `client_secret is missing`, `redirect_uri_mismatch`, dan kegagalan pada server jarak jauh. OAuth pada LAN/VPS sangat bermasalah.
**Bagaimana OmniRoute menyelesaikannya:**
- **Penyegaran Token Otomatis** — Penyegaran token OAuth di latar belakang sebelum masa berlakunya habis
- **OAuth 2.0 (PKCE) Bawaan** — Aliran otomatis untuk Claude Code, Codex, Gemini CLI, Copilot, Kiro, Qwen, iFlow
- **OAuth Multi-Akun** — Beberapa akun per penyedia melalui ekstraksi token JWT/ID
- **OAuth LAN/Remote Fix** — Deteksi IP pribadi untuk `redirect_uri` + mode URL manual untuk server jarak jauh
- **OAuth Dibalik Nginx** — Menggunakan `window.location.origin` untuk kompatibilitas proxy terbalik
- **Panduan OAuth Jarak Jauh** — Panduan langkah demi langkah untuk kredensial Google Cloud di VPS/Docker
</details>
<details>
<summary><b>📊 9. "Saya tidak tahu berapa banyak yang saya belanjakan atau di mana" </b></summary>
Pengembang menggunakan beberapa penyedia berbayar tetapi tidak memiliki pandangan terpadu mengenai pembelanjaan. Setiap penyedia memiliki dasbor penagihannya sendiri, namun tidak ada tampilan gabungan. Biaya tak terduga bisa menumpuk.
**Bagaimana OmniRoute menyelesaikannya:**
- **Dasbor Analisis Biaya** — Pelacakan biaya per token dan pengelolaan anggaran per penyedia
- **Batas Anggaran per Tingkat** — Batas pembelanjaan per tingkat yang memicu penggantian otomatis
- **Konfigurasi Harga Per Model** — Harga per model yang dapat dikonfigurasi
- **Statistik Penggunaan Per Kunci API** — Jumlah permintaan dan stempel waktu terakhir digunakan per kunci
- **Dasbor Analytics** — Kartu statistik, diagram penggunaan model, tabel penyedia dengan tingkat keberhasilan dan latensi
</details>
<details>
<summary><b>🐛 10. "Saya tidak dapat mendiagnosis kesalahan dan masalah dalam panggilan AI"</b></summary>
Saat panggilan gagal, pengembang tidak mengetahui apakah itu batas kecepatan, token kedaluwarsa, format salah, atau kesalahan penyedia. Log terfragmentasi di terminal yang berbeda. Tanpa observabilitas, debugging adalah trial-and-error.
**Bagaimana OmniRoute menyelesaikannya:**
- **Dasbor Log Terpadu** — 4 tab: Log Permintaan, Log Proksi, Log Audit, Konsol
- **Penampil Log Konsol** — Penampil gaya terminal real-time dengan level kode warna, gulir otomatis, pencarian, filter
- **Log Proxy SQLite** — Log persisten yang bertahan saat server dimulai ulang
- **Translator Playground** — 4 mode debugging: Playground (terjemahan format), Chat Tester (pulang pergi), Test Bench (batch), Live Monitor (real-time)
- **Telemetri Permintaan** — latensi p50/p95/p99 + penelusuran X-Request-Id
- **Logging Berbasis File dengan Rotasi** — Pencegat konsol menangkap semuanya ke log JSON dengan rotasi berbasis ukuran
</details>
<details>
<summary><b>🏗️ 11. "Menyebarkan dan memelihara gateway itu rumit"</b></summary>
Menginstal, mengonfigurasi, dan memelihara proksi AI di berbagai lingkungan (lokal, VPS, Docker, cloud) membutuhkan banyak tenaga. Masalah seperti jalur hardcode, `EACCES` pada direktori, konflik port, dan pembangunan lintas platform menambah gesekan.
**Bagaimana OmniRoute menyelesaikannya:**
- **instal global npm** — `npm install -g omniroute && omniroute` — selesai
- **Docker Multi-Platform** — asli AMD64 + ARM64 (Apple Silicon, AWS Graviton, Raspberry Pi)
- **Docker Compose Profiles** — `base` (tanpa alat CLI) dan `cli` (dengan Claude Code, Codex, OpenClaw)
- **Aplikasi Desktop Electron** — Aplikasi asli untuk Windows/macOS/Linux dengan baki sistem, mulai otomatis, mode offline
- **Mode Port Terpisah** — API dan Dasbor pada port terpisah untuk skenario tingkat lanjut (proksi terbalik, jaringan kontainer)
- **Cloud Sync** — Konfigurasi sinkronisasi antar perangkat melalui Cloudflare Workers
- **DB Backups** — Pencadangan otomatis, pemulihan, ekspor dan impor semua pengaturan
</details>
<details>
<summary><b>🌍 12. "Antarmuka hanya berbahasa Inggris dan tim saya tidak bisa berbahasa Inggris"</b></summary>
Tim di negara-negara yang tidak berbahasa Inggris, khususnya di Amerika Latin, Asia, dan Eropa, kesulitan dengan antarmuka yang hanya berbahasa Inggris. Hambatan bahasa mengurangi adopsi dan meningkatkan kesalahan konfigurasi.
**Bagaimana OmniRoute menyelesaikannya:**
- **Dasbor i18n — 30 Bahasa** — 500+ tombol diterjemahkan termasuk Arab, Bulgaria, Denmark, Jerman, Spanyol, Finlandia, Prancis, Ibrani, Hindi, Hungaria, Indonesia, Italia, Jepang, Korea, Melayu, Belanda, Norwegia, Polandia, Portugis (PT/BR), Rumania, Rusia, Slovakia, Swedia, Thailand, Ukraina, Vietnam, China, Filipina, Inggris
- **Dukungan RTL** — Dukungan kanan ke kiri untuk bahasa Arab dan Ibrani
- **README Multi-Bahasa** — 30 terjemahan dokumentasi lengkap
- **Pemilih Bahasa** — Ikon bola dunia di header untuk peralihan waktu nyata
</details>
<details>
<summary><b>🔄 13. "Saya memerlukan lebih dari sekadar obrolan — saya memerlukan penyematan, gambar, audio"</b></summary>
AI bukan hanya penyelesaian obrolan. Pengembang perlu membuat gambar, mentranskripsikan audio, membuat penyematan untuk RAG, mengubah peringkat dokumen, dan memoderasi konten. Setiap API memiliki titik akhir dan format yang berbeda.
**Bagaimana OmniRoute menyelesaikannya:**
- **Sematan** — `/v1/embeddings` dengan 6 penyedia dan 9+ model
- **Image Generation** — `/v1/images/generations` dengan 10 penyedia dan 20+ model (OpenAI, xAI, Together, Fireworks, Nebius, Hyperbolic, NanoBanana, Antigravity, SD WebUI, ComfyUI)
- **Teks-ke-Video** — `/v1/videos/generations` — ComfyUI (AnimateDiff, SVD) dan SD WebUI
- **Teks-ke-Musik** — `/v1/music/generations` — ComfyUI (Audio Terbuka Stabil, MusicGen)
- **Transkripsi Audio** — `/v1/audio/transcriptions` — Whisper + Nvidia NIM, HuggingFace, Qwen3
- **Text-to-Speech** — `/v1/audio/speech` — ElevenLabs, Nvidia NIM, HuggingFace, Coqui, Tortoise, Qwen3, + penyedia yang ada
- **Moderasi** — `/v1/moderations` — Pemeriksaan keamanan konten
- **Pemeringkatan ulang** — `/v1/rerank` — Pemeringkatan ulang relevansi dokumen
- **Respon API** — Dukungan penuh `/v1/responses` untuk Codex
</details>
<details>
<summary><b>🧪 14. "Saya tidak punya cara untuk menguji dan membandingkan kualitas antar model"</b></summary>
Pengembang ingin mengetahui model mana yang terbaik untuk kasus penggunaan mereka — kode, terjemahan, penalaran — tetapi membandingkan secara manual itu lambat. Tidak ada alat evaluasi terintegrasi.
**Bagaimana OmniRoute menyelesaikannya:**
- **Evaluasi LLM** — Pengujian set emas dengan 10 kasus yang dimuat sebelumnya yang mencakup salam, matematika, geografi, pembuatan kode, kepatuhan JSON, terjemahan, penurunan harga, penolakan keamanan
- **4 Strategi Pertandingan** — `exact`, `contains`, `regex`, `custom` (fungsi JS)
- **Bangku Tes Taman Bermain Penerjemah** — Pengujian batch dengan banyak masukan dan keluaran yang diharapkan, perbandingan lintas penyedia
- **Penguji Obrolan** — Perjalanan bolak-balik penuh dengan rendering respons visual
- **Monitor Langsung** — Aliran real-time dari semua permintaan yang mengalir melalui proxy
</details>
<details>
<summary><b>📈 15. "Saya perlu melakukan penskalaan tanpa kehilangan performa"</b></summary>
Seiring bertambahnya volume permintaan, tanpa menyimpan pertanyaan yang sama akan menghasilkan biaya duplikat. Tanpa idempotensi, permintaan duplikat akan membuang-buang pemrosesan. Batasan tarif per penyedia harus dipatuhi.
**Bagaimana OmniRoute menyelesaikannya:**
- **Cache Semantik** — Cache dua tingkat (tanda tangan + semantik) mengurangi biaya dan latensi
- **Request Idempoency** — Jendela deduplikasi 5 detik untuk permintaan yang identik
- **Deteksi Batas Tarif** — RPM per penyedia, selisih minimum, dan pelacakan serentak maks
- **Batas Nilai yang Dapat Diedit** — Default yang dapat dikonfigurasi di Pengaturan → Ketahanan dengan persistensi
- **Cache Validasi Kunci API** — cache 3 tingkat untuk kinerja produksi
- **Dasbor Kesehatan dengan Telemetri** — latensi p50/p95/p99, statistik cache, waktu aktif
</details>
<details>
<summary><b>🤖 16. "Saya ingin mengontrol perilaku model secara global"</b></summary>
Pengembang yang menginginkan semua respons dalam bahasa tertentu, dengan nada tertentu, atau ingin membatasi token penalaran. Mengonfigurasi ini di setiap alat/permintaan tidak praktis.
**Bagaimana OmniRoute menyelesaikannya:**
- **Injeksi Perintah Sistem** — Perintah global diterapkan ke semua permintaan
- **Validasi Anggaran Berpikir** — Kontrol alokasi token penalaran per permintaan (passthrough, otomatis, kustom, adaptif)
- **6 Strategi Perutean** — Strategi global yang menentukan cara permintaan didistribusikan
- **Wildcard Router** — Pola `provider/*` dirutekan secara dinamis ke penyedia mana pun
- **Combo Aktifkan/Nonaktifkan Toggle** — Beralih kombo langsung dari dasbor
- **Toggle Penyedia** — Mengaktifkan/menonaktifkan semua koneksi untuk penyedia dengan satu klik
- **Penyedia yang Diblokir** — Kecualikan penyedia tertentu dari daftar `/v1/models`
</details>
<details>
<summary><b>🧰 17. "Saya membutuhkan alat MCP sebagai kemampuan produk kelas satu" </b></summary>
Banyak gateway AI yang mengekspos MCP hanya sebagai detail implementasi yang tersembunyi. Tim memerlukan lapisan operasi yang terlihat dan dapat dikelola.
**Bagaimana OmniRoute menyelesaikannya:**
- MCP muncul di navigasi dasbor dan tab protokol titik akhir
- Halaman manajemen MCP khusus dengan proses, alat, cakupan, dan audit
- Mulai cepat bawaan untuk `omniroute --mcp` dan orientasi klien
</details>
<details>
<summary><b>🧠 18. "Saya memerlukan orkestrasi A2A dengan jalur tugas sinkronisasi + streaming"</b></summary>
Alur kerja agen memerlukan balasan langsung dan eksekusi streaming jangka panjang dengan kontrol siklus hidup.
**Bagaimana OmniRoute menyelesaikannya:**
- Titik akhir A2A JSON-RPC (`POST /a2a`) dengan `message/send` dan `message/stream`
- Streaming SSE dengan propagasi status terminal
- API siklus hidup tugas untuk `tasks/get` dan `tasks/cancel`
</details>
<details>
<summary><b>🛰️ 19. "Saya membutuhkan kesehatan proses MCP yang nyata, bukan status yang dapat ditebak" </b></summary>
Tim operasional perlu mengetahui apakah MCP benar-benar aktif, bukan hanya apakah API dapat dijangkau.
**Bagaimana OmniRoute menyelesaikannya:**
- File detak jantung runtime dengan PID, stempel waktu, transportasi, jumlah alat, dan mode cakupan
- API status MCP menggabungkan detak jantung + aktivitas terkini
- Kartu status UI untuk kesegaran proses/waktu aktif/detak jantung
</details>
<details>
<summary><b>📋 20. "Saya memerlukan eksekusi alat MCP yang dapat diaudit"</b></summary>
Saat alat mengubah konfigurasi atau memicu tindakan operasi, tim memerlukan kemampuan penelusuran forensik.
**Bagaimana OmniRoute menyelesaikannya:**
- Pencatatan audit yang didukung SQLite untuk panggilan alat MCP
- Filter berdasarkan alat, keberhasilan/kegagalan, kunci API, dan penomoran halaman
- Tabel audit dasbor + titik akhir statistik untuk otomatisasi
</details>
<details>
<summary><b>🔐 21. "Saya memerlukan izin MCP terbatas per integrasi"</b></summary>
Klien yang berbeda harus memiliki akses dengan hak istimewa paling rendah ke kategori alat.
**Bagaimana OmniRoute menyelesaikannya:**
- 9 cakupan MCP granular untuk akses alat terkontrol
- Penegakan cakupan dan visibilitas di UI manajemen MCP
- Postur default yang aman untuk perkakas operasional
</details>
<details>
<summary><b>⚙️ 22. "Saya memerlukan kontrol operasional tanpa memindahkan" </b></summary>
Tim memerlukan perubahan runtime yang cepat selama insiden atau peristiwa biaya.
**Bagaimana OmniRoute menyelesaikannya:**
- Beralih aktivasi kombo langsung dari dasbor MCP
- Menerapkan profil ketahanan dari paket kebijakan yang telah ditentukan sebelumnya
- Reset status pemutus sirkuit dari panel operasi yang sama
</details>
<details>
<summary><b>🔄 23. "Saya memerlukan visibilitas dan pembatalan siklus hidup tugas A2A langsung" </b></summary>
Tanpa visibilitas siklus hidup, insiden tugas menjadi sulit untuk diprioritaskan.
**Bagaimana OmniRoute menyelesaikannya:**
- Daftar tugas/pemfilteran berdasarkan status/keterampilan dengan penomoran halaman
- Telusuri metadata tugas, peristiwa, dan artefak
- Titik akhir pembatalan tugas dan tindakan UI dengan konfirmasi
</details>
<details>
<summary><b>🌊 24. "Saya memerlukan metrik streaming aktif untuk memuat A2A"</b></summary>
Alur kerja streaming memerlukan wawasan operasional tentang konkurensi dan koneksi langsung.
**Bagaimana OmniRoute menyelesaikannya:**
- Penghitung aliran aktif terintegrasi ke dalam status A2A
- Stempel waktu tugas terakhir dan jumlah per negara bagian
- Kartu dasbor A2A untuk pemantauan operasi waktu nyata
</details>
<details>
<summary><b>🪪 25. "Saya memerlukan penemuan agen standar untuk klien"</b></summary>
Klien dan orkestra eksternal memerlukan metadata yang dapat dibaca mesin untuk orientasi.
**Bagaimana OmniRoute menyelesaikannya:**
- Kartu Agen terekspos di `/.well-known/agent.json`
- Kemampuan dan keterampilan yang ditunjukkan dalam manajemen UI
- API status A2A mencakup metadata penemuan untuk otomatisasi
</details>
<details>
<summary><b>🧭 26. "Saya memerlukan kemampuan protokol untuk ditemukan di UX produk" </b></summary>
Jika pengguna tidak dapat menemukan permukaan protokol, kualitas adopsi dan dukungan akan menurun.
**Bagaimana OmniRoute menyelesaikannya:**
- Entri sidebar untuk MCP dan A2A
- Tab Protokol halaman titik akhir dengan mulai cepat dan status
- Tautan dari ikhtisar ke dasbor manajemen khusus
</details>
<details>
<summary><b>🧪 27. "Saya memerlukan validasi protokol end-to-end dengan klien nyata"</b></summary>
Tes tiruan tidak cukup untuk memvalidasi kompatibilitas protokol sebelum rilis.
**Bagaimana OmniRoute menyelesaikannya:**
- Suite E2E yang mem-boot aplikasi dan menggunakan transportasi klien MCP SDK yang sebenarnya
- Klien A2A menguji penemuan, pengiriman, streaming, dapatkan, dan pembatalan aliran
- Periksa silang pernyataan terhadap audit MCP dan API tugas A2A
</details>
<details>
<summary><b>📡 28. "Saya memerlukan kemampuan pengamatan terpadu di semua antarmuka"</b></summary>
Memisahkan observabilitas berdasarkan protokol menciptakan titik buta dan MTTR yang lebih panjang.
**Bagaimana OmniRoute menyelesaikannya:**
- Dasbor/log/analitik terpadu dalam satu produk
- Kesehatan + audit + permintaan telemetri di seluruh lapisan OpenAI, MCP, dan A2A
- API Operasional untuk status dan otomatisasi
</details>
<details>
<summary><b>💼 29. "Saya memerlukan satu runtime untuk proxy + alat + orkestrasi agen" </b></summary>
Menjalankan banyak layanan terpisah akan meningkatkan biaya operasional dan mode kegagalan.
**Bagaimana OmniRoute menyelesaikannya:**
- Proksi yang kompatibel dengan OpenAI, server MCP, dan server A2A dalam satu tumpukan
- Otentikasi bersama, ketahanan, penyimpanan data, dan kemampuan observasi
- Model kebijakan yang konsisten di seluruh platform interaksi
</details>
<details>
<summary><b>🚀 30. "Saya perlu mengirimkan alur kerja agen tanpa gepeng kode lem"</b></summary>
Tim kehilangan kecepatan saat menggabungkan beberapa layanan dan skrip ad-hoc.
**Bagaimana OmniRoute menyelesaikannya:**
- Strategi titik akhir terpadu untuk klien dan agen
- UI manajemen protokol bawaan dan jalur validasi asap
- Fondasi siap produksi (keamanan, logging, ketahanan, cadangan)
</details>
### Contoh Playbook (Kasus Penggunaan Terintegrasi)
**Playbook A: Maksimalkan langganan berbayar + cadangan murah**
```txt
Combo: "maximize-claude"
1. cc/claude-opus-4-6
2. glm/glm-4.7
3. if/kimi-k2-thinking
Monthly cost: $20 + small backup spend
Outcome: higher quality, near-zero interruption
```
**Playbook B: Tumpukan coding tanpa biaya**
```txt
Combo: "free-forever"
1. gc/gemini-3-flash
2. if/kimi-k2-thinking
3. qw/qwen3-coder-plus
Monthly cost: $0
Outcome: stable free coding workflow
```
**Playbook C: Rantai fallback yang selalu aktif 24/7**
```txt
Combo: "always-on"
1. cc/claude-opus-4-6
2. cx/gpt-5.2-codex
3. glm/glm-4.7
4. minimax/MiniMax-M2.1
5. if/kimi-k2-thinking
Outcome: deep fallback depth for deadline-critical workloads
```
**Playbook D: Operasi agen dengan MCP + A2A**
```txt
1) Start MCP transport (`omniroute --mcp`) for tool-driven operations
2) Run A2A tasks via `message/send` and `message/stream`
3) Observe via /dashboard/mcp and /dashboard/a2a
4) Control incidents with resilience profile + task cancellation
```
---
## ⚡ Mulai Cepat
**1. Instal secara global:**
@@ -251,7 +782,7 @@ docker compose --profile cli up -d
---
## 🖥️ Desktop App — Offline & Always-On
## 🖥️
> 🆕 **NEW!** OmniRoute is now available as a **native desktop application** for Windows, macOS, and Linux.
@@ -298,67 +829,6 @@ npm run electron:build:linux # Linux (.AppImage)
---
## 🎯 Kasus Penggunaan
### Kasus 1: "Saya berlangganan Claude Pro"
**Masalah:** Kuota habis tanpa terpakai, batas kecepatan selama coding berat
```
Combo: "maximize-claude"
1. cc/claude-opus-4-6 (use subscription fully)
2. glm/glm-4.7 (cheap backup when quota out)
3. if/kimi-k2-thinking (free emergency fallback)
Monthly cost: $20 (subscription) + ~$5 (backup) = $25 total
vs. $20 + hitting limits = frustration
```
### Kasus 2: "Saya ingin tanpa biaya"
**Masalah:** Tidak mampu berlangganan, memerlukan pengkodean AI yang andal
```
Combo: "free-forever"
1. gc/gemini-3-flash (180K free/month)
2. if/kimi-k2-thinking (unlimited free)
3. qw/qwen3-coder-plus (unlimited free)
Monthly cost: $0
Quality: Production-ready models
```
### Kasus 3: "Saya memerlukan pengkodean 24/7, tanpa gangguan"
**Masalah:** Tenggat waktu, tidak mampu membayar downtime
```
Combo: "always-on"
1. cc/claude-opus-4-6 (best quality)
2. cx/gpt-5.2-codex (second subscription)
3. glm/glm-4.7 (cheap, resets daily)
4. minimax/MiniMax-M2.1 (cheapest, 5h reset)
5. if/kimi-k2-thinking (free unlimited)
Result: 5 layers of fallback = zero downtime
```
### Kasus 4: "Saya ingin AI GRATIS di OpenClaw"
**Masalah:** Membutuhkan asisten AI dalam aplikasi perpesanan, sepenuhnya gratis
```
Combo: "openclaw-free"
1. if/glm-4.7 (unlimited free)
2. if/minimax-m2.1 (unlimited free)
3. if/kimi-k2-thinking (unlimited free)
Monthly cost: $0
Access via: WhatsApp, Telegram, Slack, Discord, iMessage, Signal...
```
---
## 💡 Fitur Utama
### 🧠 Perutean & Kecerdasan Inti
@@ -374,6 +844,8 @@ Access via: WhatsApp, Telegram, Slack, Discord, iMessage, Signal...
| 🧩 **Model Khusus** | Tambahkan ID model apa pun ke penyedia mana pun |
| 🌐 **Router Wildcard** | Rutekan pola `provider/*` ke penyedia mana pun secara dinamis |
| 🧠 **Memikirkan Anggaran** | Mode passthrough, otomatis, kustom, dan adaptif untuk model penalaran |
| 🔀 **Model Aliases** | Auto-forward deprecated model IDs to current replacements (built-in + custom) |
| ⚡ **Background Degradation** | Auto-route background tasks (titles, summaries) to cheaper models |
| 💬 **Injeksi Perintah Sistem** | Perintah sistem global diterapkan di semua permintaan |
| 📄 **API Respons** | Dukungan penuh OpenAI Responses API (`/v1/responses`) untuk Codex |
@@ -399,6 +871,8 @@ Access via: WhatsApp, Telegram, Slack, Discord, iMessage, Signal...
| 🔒 **Spoofing Sidik Jari TLS** | Lewati deteksi bot berbasis TLS melalui wreq-js |
| 🌐 **Pemfilteran IP** | Daftar yang diizinkan/daftar blokir untuk kontrol akses API |
| 📊 **Batas Tarif yang Dapat Diedit** | RPM yang dapat dikonfigurasi, celah minimum, dan maks secara bersamaan pada tingkat sistem |
| 💾 **Rate Limit Persistence** | Learned limits survive restarts via SQLite with 60s debounce + 24h staleness |
| 🔄 **Token Refresh Resilience** | Per-provider circuit breaker (5 fails→30min) + 30s timeout per attempt |
| 🛡 **Perlindungan Titik Akhir API** | Gerbang autentikasi + pemblokiran penyedia untuk titik akhir `/models` |
| 🔒 **Visibilitas Proksi** | Lencana berkode warna: 🟢 global, 🟡 penyedia, 🔵 per koneksi dengan tampilan IP |
| 🌐 **Konfigurasi Proksi 3 Tingkat** | Konfigurasikan proxy di tingkat global, per penyedia, atau per koneksi |
@@ -517,6 +991,27 @@ OmniRoute menyertakan Taman Bermain Penerjemah bawaan yang canggih dengan **4 mo
</details>
## 🧪 Evaluasi (Eval)
OmniRoute menyertakan kerangka evaluasi bawaan untuk menguji kualitas respons LLM terhadap rangkaian emas. Akses melalui **Analytics → Evals** di dasbor.
### Set Emas Bawaan
"OmniRoute Golden Set" yang dimuat sebelumnya berisi 10 kasus uji yang meliputi:
- Salam, matematika, geografi, pembuatan kode
- Kepatuhan format JSON, terjemahan, penurunan harga
- Penolakan keamanan (konten berbahaya), penghitungan, logika boolean
### Strategi Evaluasi
| Strategi | Deskripsi | Contoh |
| ---------- | ------------------------------------------------------------ | -------------------------------- |
| `exact` | Output harus sama persis | `"4"` |
| `contains` | Output harus berisi substring (tidak peka huruf besar-kecil) | `"Paris"` |
| `regex` | Output harus sesuai dengan pola regex | `"1.*2.*3"` |
| `custom` | Fungsi JS khusus mengembalikan benar/salah | `(output) => output.length > 10` |
---
## 📖 Panduan Pengaturan
@@ -799,104 +1294,64 @@ Settings → API Configuration:
---
## 📊 Model yang Tersedia
## 🐛 Pemecahan masalah
<details>
<summary><b>Lihat semua model yang tersedia</b></summary>
<summary><b>Klik untuk memperluas panduan pemecahan masalah</b></summary>
**Kode Claude (`cc/`)** - Pro/Maks:
**"Model bahasa tidak memberikan pesan"**
- `cc/claude-opus-4-6`
- `cc/claude-sonnet-4-5-20250929`
- `cc/claude-haiku-4-5-20251001`
- Kuota penyedia habis → Periksa dashboard pelacak kuota
- Solusi: Gunakan combo fallback atau beralih ke tier yang lebih murah
**Kodeks (`cx/`)** - Plus/Pro:
**Pembatasan tarif**
- `cx/gpt-5.2-codex`
- `cx/gpt-5.1-codex-max`
- Kuota berlangganan habis → Penggantian ke GLM/MiniMax
- Tambahkan kombo: `cc/claude-opus-4-6 → glm/glm-4.7 → if/kimi-k2-thinking`
**Gemini CLI (`gc/`)** - GRATIS:
**Token OAuth kedaluwarsa**
- `gc/gemini-3-flash-preview`
- `gc/gemini-2.5-pro`
- Disegarkan secara otomatis oleh OmniRoute
- Jika masalah terus berlanjut: Dasbor → Penyedia → Sambungkan kembali
**Copilot GitHub (`gh/`)**:
**Biaya tinggi**
- `gh/gpt-5`
- `gh/claude-4.5-sonnet`
- Periksa statistik penggunaan di Dashboard → Biaya
- Ganti model utama ke GLM/MiniMax
- Gunakan tingkat gratis (Gemini CLI, iFlow) untuk tugas-tugas yang tidak penting
**NVIDIA NIM (`nvidia/`)** - Kredit GRATIS:
**Dasbor terbuka pada port yang salah**
- `nvidia/llama-3.3-70b-instruct`
- `nvidia/mistral-7b-instruct`
- 50+ model lainnya di [build.nvidia.com](https://build.nvidia.com)
- Tetapkan `PORT=20128` dan `NEXT_PUBLIC_BASE_URL=http://localhost:20128`
**GLM (`glm/`)** - $0,6/1 juta:
**Kesalahan sinkronisasi cloud**
- `glm/glm-4.7`
- Verifikasi `BASE_URL` poin ke instance Anda yang sedang berjalan
- Verifikasi `CLOUD_URL` poin ke titik akhir cloud yang Anda harapkan
- Jaga agar nilai `NEXT_PUBLIC_*` selaras dengan nilai sisi server
**MiniMax (`minimax/`)** - $0,2/1 juta:
**Login pertama tidak berfungsi**
- `minimax/MiniMax-M2.1`
- Periksa `INITIAL_PASSWORD` di `.env`
- Jika tidak disetel, kata sandi cadangan adalah `123456`
**iFlow (`if/`)** - GRATIS:
**Tidak ada log permintaan**
- `if/kimi-k2-thinking`
- `if/qwen3-coder-plus`
- `if/deepseek-r1`
- `if/glm-4.7`
- `if/minimax-m2`
- Tetapkan `ENABLE_REQUEST_LOGS=true` di `.env`
**Qwen (`qw/`)** - GRATIS:
**Tes koneksi menunjukkan "Tidak Valid" untuk penyedia yang kompatibel dengan OpenAI**
- `qw/qwen3-coder-plus`
- `qw/qwen3-coder-flash`
- Banyak penyedia tidak mengekspos titik akhir `/models`
- OmniRoute v1.0.6+ menyertakan validasi fallback melalui penyelesaian obrolan
- Pastikan URL dasar menyertakan akhiran `/v1`
**Kiro (`kr/`)** - GRATIS:
- `kr/claude-sonnet-4.5`
- `kr/claude-haiku-4.5`
**OpenRouter (`or/`)** - 100+ model:
- `or/anthropic/claude-4-sonnet`
- `or/google/gemini-2.5-pro`
- Model apa pun dari [openrouter.ai/models](https://openrouter.ai/models)
</details>
---
## 🧪 Evaluasi (Eval)
OmniRoute menyertakan kerangka evaluasi bawaan untuk menguji kualitas respons LLM terhadap rangkaian emas. Akses melalui **Analytics → Evals** di dasbor.
### Set Emas Bawaan
"OmniRoute Golden Set" yang dimuat sebelumnya berisi 10 kasus uji yang meliputi:
- Salam, matematika, geografi, pembuatan kode
- Kepatuhan format JSON, terjemahan, penurunan harga
- Penolakan keamanan (konten berbahaya), penghitungan, logika boolean
### Strategi Evaluasi
| Strategi | Deskripsi | Contoh |
| ---------- | ------------------------------------------------------------ | -------------------------------- |
| `exact` | Output harus sama persis | `"4"` |
| `contains` | Output harus berisi substring (tidak peka huruf besar-kecil) | `"Paris"` |
| `regex` | Output harus sesuai dengan pola regex | `"1.*2.*3"` |
| `custom` | Fungsi JS khusus mengembalikan benar/salah | `(output) => output.length > 10` |
---
## 🔐 OAuth em Servidor Remoto (Pengaturan OAuth Jarak Jauh)
### 🔐 OAuth
<a name="oauth-em-servidor-remoto"></a>
> **⚠️ PENTING bagi pengguna dengan OmniRoute pada VPS/Docker/server jarak jauh**
### Mengapa OAuth melakukan Antigravity / Gemini CLI gagal dalam layanan jarak jauh?
### OAuth
Pembuktiannya **Antigravitasi** dan **Gemini CLI** digunakan **Google OAuth 2.0** untuk autentikasi. Google meminta agar `redirect_uri` menggunakan OAuth yang terus berubah, jadi **exatamente** adalah URI yang sudah ada sebelumnya di Google Cloud Console yang dapat diterapkan.
@@ -981,64 +1436,11 @@ Jika Anda tidak ingin membuat kredensial pribadi sekarang, Anda mungkin dapat me
> Solusi ini berfungsi karena kode otorisasi pada URL valid secara independen untuk mengarahkan ulang ke akun atau tidak.
---
## 🐛 Pemecahan masalah
<details>
<summary><b>Klik untuk memperluas panduan pemecahan masalah</b></summary>
**"Model bahasa tidak memberikan pesan"**
- Kuota penyedia habis → Periksa dashboard pelacak kuota
- Solusi: Gunakan combo fallback atau beralih ke tier yang lebih murah
**Pembatasan tarif**
- Kuota berlangganan habis → Penggantian ke GLM/MiniMax
- Tambahkan kombo: `cc/claude-opus-4-6 → glm/glm-4.7 → if/kimi-k2-thinking`
**Token OAuth kedaluwarsa**
- Disegarkan secara otomatis oleh OmniRoute
- Jika masalah terus berlanjut: Dasbor → Penyedia → Sambungkan kembali
**Biaya tinggi**
- Periksa statistik penggunaan di Dashboard → Biaya
- Ganti model utama ke GLM/MiniMax
- Gunakan tingkat gratis (Gemini CLI, iFlow) untuk tugas-tugas yang tidak penting
**Dasbor terbuka pada port yang salah**
- Tetapkan `PORT=20128` dan `NEXT_PUBLIC_BASE_URL=http://localhost:20128`
**Kesalahan sinkronisasi cloud**
- Verifikasi `BASE_URL` poin ke instance Anda yang sedang berjalan
- Verifikasi `CLOUD_URL` poin ke titik akhir cloud yang Anda harapkan
- Jaga agar nilai `NEXT_PUBLIC_*` selaras dengan nilai sisi server
**Login pertama tidak berfungsi**
- Periksa `INITIAL_PASSWORD` di `.env`
- Jika tidak disetel, kata sandi cadangan adalah `123456`
**Tidak ada log permintaan**
- Tetapkan `ENABLE_REQUEST_LOGS=true` di `.env`
**Tes koneksi menunjukkan "Tidak Valid" untuk penyedia yang kompatibel dengan OpenAI**
- Banyak penyedia tidak mengekspos titik akhir `/models`
- OmniRoute v1.0.6+ menyertakan validasi fallback melalui penyelesaian obrolan
- Pastikan URL dasar menyertakan akhiran `/v1`
</details>
---
## 🛠️ Tumpukan Teknologi
## 🛠️
- **Runtime**: Node.js 1822 LTS (⚠️ Node.js 24+ **tidak didukung**`better-sqlite3` biner asli tidak kompatibel)
- **Bahasa**: TypeScript 5.9 — **100% TypeScript** di `src/` dan `open-sse/` (v1.0.6)
@@ -1090,7 +1492,7 @@ Jika Anda tidak ingin membuat kredensial pribadi sekarang, Anda mungkin dapat me
---
## 🗺️ Peta Jalan
## 🗺️
OmniRoute memiliki **210+ fitur yang direncanakan** di berbagai fase pengembangan. Berikut adalah bidang-bidang utamanya:
@@ -1115,18 +1517,6 @@ OmniRoute memiliki **210+ fitur yang direncanakan** di berbagai fase pengembanga
---
## 📧 Dukungan
> 💬 **Bergabunglah dengan komunitas kami!** [WhatsApp Group](https://chat.whatsapp.com/JI7cDQ1GyaiDHhVBpLxf8b?mode=gi_t) — Dapatkan bantuan, berbagi kiat, dan dapatkan informasi terbaru.
- **Situs Web**: [omniroute.online](https://omniroute.online)
- **GitHub**: [github.com/diegosouzapw/OmniRoute](https://github.com/diegosouzapw/OmniRoute)
- **Masalah**: [github.com/diegosouzapw/OmniRoute/issues](https://github.com/diegosouzapw/OmniRoute/issues)
- **WhatsApp**: [Community Group](https://chat.whatsapp.com/JI7cDQ1GyaiDHhVBpLxf8b?mode=gi_t)
- **Proyek Asli**: [9router by decolua](https://github.com/decolua/9router)
---
## 👥 Kontributor
[![Contributors](https://contrib.rocks/image?repo=diegosouzapw/OmniRoute&max=100&columns=20&anon=1)](https://github.com/diegosouzapw/OmniRoute/graphs/contributors)
@@ -1176,85 +1566,6 @@ Lisensi MIT - lihat [LICENSE](LICENSE) untuk detailnya.
---
---
## 🇧🇷 OmniRoute — Gerbang IA Gratis
<a name="-omniroute--gateway-de-ia-gratuito"></a>
### Tidak ada kode apa pun. Roteamento cerdas untuk **model IA GRATIS dan hak istimewa** dengan fallback otomatis.
_Proksi universal API — um titik akhir, 36+ bukti, tanpa waktu henti._
### 🌐 Internasionalisasi (i18n)
Pada dasbor, lakukan OmniRoute mendukung **beberapa idiom**. Saat ini kami telah membagikannya:
| Idiom | Kode | Status |
| --------------------- | ------- | ---------- |
| 🇮🇩 Bahasa Inggris | `en` | ✅ Lengkap |
| 🇧🇷 Português (Brasil) | `pt-BR` | ✅ Lengkap |
**Untuk trocar o idioma:** Klik no selector de idioma (🇮🇩 EN) no header do dashboard → pilih idioma yang diinginkan.
**Untuk menambahkan idiom baru:**
1. Teriak `src/i18n/messages/{codigo}.json` berdasarkan `en.json`
2. Tambahan kode pada `src/i18n/config.ts``LOCALES` dan `LANGUAGES`
3. Memulai kembali server
### ⚡ Mulai Cepat
```bash
# Instalar via npm
npx omniroute@latest
# Ou rodar do código-fonte
cp .env.example .env
npm install
PORT=20128 NEXT_PUBLIC_BASE_URL=http://localhost:20128 npm run dev
```
### 🐳 buruh pelabuhan
```bash
docker run -d --name omniroute -p 20128:20128 diegosouzapw/omniroute:latest
```
### 🔑 Prinsip Fungsionalidades
- **36+ bukti IA** — Claude, GPT, Gemini, Llama, Qwen, DeepSeek, dan lainnya
- **Roteamento inteligente** — Penggantian otomatis ke seluruh bukti
- **Penulisan format** — OpenAI ↔ Claude ↔ Gemini secara otomatis
- **Multi-konta** — Multi-konta berdasarkan pilihan yang cerdas
- **Cache semântico** — Memulihkan biaya dan latensi
- **OAuth otomatis** — Token diperbarui secara otomatis
- **Kombo yang dipersonalisasi** — 6 strategi roteamento
- **Dasbor lengkap** — Monitor, log, analisis, konfigurasi
- **Alat CLI** — Konfigurasikan Kode Claude, Codex, Kursor, Cline com um klik
- **100% TypeScript** — Kode limpo dan tipado
### 📖 Dokumentasi
| Dokumen | Deskripsi |
| ----------------------------------------------- | ---------------------------------------- |
| [Guia do Usuário](docs/USER_GUIDE.md) | Provedores, kombo, CLI, terapkan |
| [Referência da API](docs/API_REFERENCE.md) | Semua titik akhir dengan contoh |
| [Solução de Problemas](docs/TROUBLESHOOTING.md) | Masalah Umum dan Solusi |
| [Arquitetura](docs/ARCHITECTURE.md) | Arquitetura dan internal dalam sistem |
| [Contribuição](CONTRIBUTING.md) | Menyiapkan pedoman desenvolvimento |
| [Deploy em VM](docs/VM_DEPLOYMENT_GUIDE.md) | Panduan lengkap: VM + nginx + Cloudflare |
### 📧 Dukungan
> 💬 **Entre to a comunidade!** [Grupo WhatsApp](https://chat.whatsapp.com/JI7cDQ1GyaiDHhVBpLxf8b?mode=gi_t) — Ban dúvidas, compartilhe dicas dan fique aktualizado.
- **Situs Web**: [omniroute.online](https://omniroute.online)
- **GitHub**: [github.com/diegosouzapw/OmniRoute](https://github.com/diegosouzapw/OmniRoute)
- **Masalah**: [github.com/diegosouzapw/OmniRoute/issues](https://github.com/diegosouzapw/OmniRoute/issues)
---
<div align="center">
<sub>Dibangun dengan ❤️ untuk pengembang yang membuat kode 24/7</sub>
<br/>

View File

@@ -33,6 +33,35 @@ _OmniRoute के माध्यम से किसी भी AI-संचा
---
## 🖼️
<div align="center">
<img src="./docs/screenshots/MainOmniRoute.png" alt="OmniRoute" width="800"/>
</div>
---
## 📸
<details>
<summary><b>...</b></summary>
| # | # |
| ----- | ---------------------------------------- |
| **1** | ![1](docs/screenshots/01-providers.png) |
| **2** | ![2](docs/screenshots/02-combos.png) |
| **3** | ![3](docs/screenshots/03-analytics.png) |
| **4** | ![4](docs/screenshots/04-health.png) |
| **5** | ![5](docs/screenshots/05-translator.png) |
| **6** | ![6](docs/screenshots/06-settings.png) |
| **7** | ![7](docs/screenshots/07-cli-tools.png) |
| **8** | ![8](docs/screenshots/08-usage.png) |
| **9** | ![9](docs/screenshots/09-endpoint.png) |
</details>
---
## 🤔ओम्नीरूट क्यों?
**पैसा बर्बाद करना और सीमा पार करना बंद करें:**
@@ -51,6 +80,18 @@ _OmniRoute के माध्यम से किसी भी AI-संचा
---
## 📧समर्थन
> 💬 **हमारे समुदाय में शामिल हों!** [WhatsApp Group](https://chat.whatsapp.com/JI7cDQ1GyaiDHhVBpLxf8b?mode=gi_t) - सहायता प्राप्त करें, सुझाव साझा करें और अपडेट रहें।
- **वेबसाइट**: [omniroute.online](https://omniroute.online)
- **गिटहब**: [github.com/diegosouzapw/OmniRoute](https://github.com/diegosouzapw/OmniRoute)
- **मुद्दे**: [github.com/diegosouzapw/OmniRoute/issues](https://github.com/diegosouzapw/OmniRoute/issues)
- **व्हाट्सएप**: [Community Group](https://chat.whatsapp.com/JI7cDQ1GyaiDHhVBpLxf8b?mode=gi_t)
- **मूल परियोजना**: [9router by decolua](https://github.com/decolua/9router)
---
## 🔄 यह कैसे काम करता है
```
@@ -80,6 +121,497 @@ Result: Never stop coding, minimal cost
---
## 🎯 ओमनीरूट क्या समाधान करता है - 30 वास्तविक समस्या बिंदु और उपयोग के मामले
> **एआई टूल का उपयोग करने वाला प्रत्येक डेवलपर प्रतिदिन इन समस्याओं का सामना करता है।** ओम्नीरूट को उन सभी को हल करने के लिए बनाया गया था - लागत वृद्धि से लेकर क्षेत्रीय ब्लॉक तक, टूटे हुए ओएथ प्रवाह से लेकर प्रोटोकॉल संचालन और एंटरप्राइज़ अवलोकन तक।
<details>
<summary><b>💸 1. "मैं एक महंगी सदस्यता के लिए भुगतान करता हूं लेकिन फिर भी सीमा से बाधित होता हूं"</b></summary>
डेवलपर्स क्लाउड प्रो, कोडेक्स प्रो, या गिटहब कोपायलट के लिए $20-200/माह का भुगतान करते हैं। यहां तक ​​कि भुगतान करने पर भी, कोटा की एक सीमा होती है - 5 घंटे का उपयोग, साप्ताहिक सीमा, या प्रति मिनट की दर सीमा। मध्य-कोडिंग सत्र में, प्रदाता प्रत्युत्तर देना बंद कर देता है और डेवलपर प्रवाह और उत्पादकता खो देता है।
**ओम्नीरूट इसे कैसे हल करता है:**
- **स्मार्ट 4-टियर फ़ॉलबैक** - यदि सदस्यता कोटा समाप्त हो जाता है, तो स्वचालित रूप से एपीआई कुंजी पर रीडायरेक्ट हो जाता है → सस्ता → शून्य मैन्युअल हस्तक्षेप के साथ मुफ़्त
- **वास्तविक समय कोटा ट्रैकिंग** - रीसेट उलटी गिनती के साथ वास्तविक समय में टोकन खपत दिखाता है (5 घंटे, दैनिक, साप्ताहिक)
- **मल्टी-अकाउंट सपोर्ट** - ऑटो राउंड-रॉबिन के साथ प्रति प्रदाता एकाधिक खाते - जब एक खत्म हो जाता है, तो अगले पर स्विच हो जाता है
- **कस्टम कॉम्बो** - 6 संतुलन रणनीतियों (भरण-प्रथम, राउंड-रॉबिन, पी2सी, यादृच्छिक, कम से कम उपयोग, लागत-अनुकूलित) के साथ अनुकूलन योग्य फ़ॉलबैक चेन
- **कोडेक्स बिजनेस कोटा** - बिजनेस/टीम कार्यक्षेत्र कोटा की निगरानी सीधे डैशबोर्ड में
</details>
<details>
<summary><b>🔌 2. "मुझे कई प्रदाताओं का उपयोग करने की आवश्यकता है लेकिन प्रत्येक के पास एक अलग एपीआई है" </b></summary>
ओपनएआई एक प्रारूप का उपयोग करता है, क्लाउड (एंथ्रोपिक) दूसरे का उपयोग करता है, जेमिनी एक और का उपयोग करता है। यदि कोई डेवलपर विभिन्न प्रदाताओं के मॉडल का परीक्षण करना चाहता है या उनके बीच फ़ॉलबैक करना चाहता है, तो उन्हें एसडीके को फिर से कॉन्फ़िगर करना होगा, एंडपॉइंट बदलना होगा, असंगत प्रारूपों से निपटना होगा। कस्टम प्रदाताओं (फ्रेंडएलआई, एनआईएम) के पास गैर-मानक मॉडल एंडपॉइंट हैं।
**ओम्नीरूट इसे कैसे हल करता है:**
- **एकीकृत समापन बिंदु** - एक एकल `http://localhost:20128/v1` सभी 36+ प्रदाताओं के लिए प्रॉक्सी के रूप में कार्य करता है
- **प्रारूप अनुवाद** - स्वचालित और पारदर्शी: ओपनएआई ↔ क्लाउड ↔ जेमिनी ↔ प्रतिक्रिया एपीआई
- **प्रतिक्रिया स्वच्छता** - गैर-मानक फ़ील्ड (`x_groq`, `usage_breakdown`, `service_tier`) को स्ट्रिप्स करता है जो OpenAI SDK v1.83+ को तोड़ता है
- **भूमिका सामान्यीकरण** - गैर-ओपनएआई प्रदाताओं के लिए `developer``system` परिवर्तित करता है; `system` → GLM/ERNIE के लिए `user`
- **टैग एक्सट्रैक्शन के बारे में सोचें** - डीपसीक R1 जैसे मॉडलों से `<think>` ब्लॉक को मानकीकृत `reasoning_content` में निकालता है
- **मिथुन राशि वालों के लिए संरचित आउटपुट** — `json_schema``responseMimeType`/`responseSchema` स्वचालित रूपांतरण
- **`stream` डिफ़ॉल्ट रूप से `false`** पर आता है - OpenAI स्पेक के साथ संरेखित होता है, Python/Rust/Go SDKs में अप्रत्याशित SSE से बचता है
</details>
<details>
<summary><b>🌐 3. "मेरा AI प्रदाता मेरे क्षेत्र/देश को ब्लॉक कर देता है"</b></summary>
OpenAI/Codex जैसे प्रदाता कुछ भौगोलिक क्षेत्रों से पहुंच को रोकते हैं। OAuth और API कनेक्शन के दौरान उपयोगकर्ताओं को `unsupported_country_region_territory` जैसी त्रुटियां मिलती हैं। यह विकासशील देशों के डेवलपर्स के लिए विशेष रूप से निराशाजनक है।
**ओम्नीरूट इसे कैसे हल करता है:**
- **3-स्तरीय प्रॉक्सी कॉन्फ़िगरेशन** - 3 स्तरों पर कॉन्फ़िगर करने योग्य प्रॉक्सी: वैश्विक (सभी ट्रैफ़िक), प्रति-प्रदाता (केवल एक प्रदाता), और प्रति-कनेक्शन/कुंजी
- **रंग-कोडित प्रॉक्सी बैज** - दृश्य संकेतक: 🟢 वैश्विक प्रॉक्सी, 🟡 प्रदाता प्रॉक्सी, 🔵 कनेक्शन प्रॉक्सी, हमेशा आईपी दिखाता है
- **प्रॉक्सी के माध्यम से OAuth टोकन एक्सचेंज** - OAuth प्रवाह भी प्रॉक्सी के माध्यम से चलता है, `unsupported_country_region_territory` को हल करता है
- **प्रॉक्सी के माध्यम से कनेक्शन परीक्षण** - कनेक्शन परीक्षण कॉन्फ़िगर प्रॉक्सी का उपयोग करते हैं (अब कोई प्रत्यक्ष बाईपास नहीं)
- **SOCKS5 समर्थन** - आउटबाउंड रूटिंग के लिए पूर्ण SOCKS5 प्रॉक्सी समर्थन
- **टीएलएस फिंगरप्रिंट स्पूफिंग** - बॉट डिटेक्शन को बायपास करने के लिए `wreq-js` के माध्यम से ब्राउज़र जैसा टीएलएस फिंगरप्रिंट
</details>
<details>
<summary><b>🆓 4. "मैं कोडिंग के लिए AI का उपयोग करना चाहता हूं लेकिन मेरे पास पैसे नहीं हैं"</b></summary>
हर कोई AI सदस्यता के लिए $20-200/माह का भुगतान नहीं कर सकता। छात्रों, उभरते देशों के डेवलपर्स, शौकीनों और फ्रीलांसरों को शून्य लागत पर गुणवत्ता वाले मॉडल तक पहुंच की आवश्यकता है।
**ओम्नीरूट इसे कैसे हल करता है:**
- **फ्री टियर प्रोवाइडर बिल्ट-इन** - 100% फ्री प्रदाताओं के लिए मूल समर्थन: आईफ्लो (8 असीमित मॉडल), क्वेन (3 असीमित मॉडल), किरो (क्लाउड मुफ्त में), जेमिनी सीएलआई (180K/माह मुफ्त)
- **केवल-निःशुल्क कॉम्बो** - चेन `gc/gemini-3-flash → if/kimi-k2-thinking → qw/qwen3-coder-plus` = शून्य डाउनटाइम के साथ $0/माह
- **एनवीडिया एनआईएम फ्री क्रेडिट** - 1000 मुफ्त क्रेडिट एकीकृत
- **लागत अनुकूलित रणनीति** - रूटिंग रणनीति जो स्वचालित रूप से सबसे सस्ते उपलब्ध प्रदाता को चुनती है
</details>
<details>
<summary><b>🔒 5. "मुझे अपने AI गेटवे को अनधिकृत पहुंच से सुरक्षित रखने की आवश्यकता है"</b></summary>
नेटवर्क (LAN, VPS, Docker) में AI गेटवे को उजागर करते समय, पते वाला कोई भी व्यक्ति डेवलपर के टोकन/कोटा का उपभोग कर सकता है। सुरक्षा के बिना, एपीआई दुरुपयोग, त्वरित इंजेक्शन और दुरुपयोग के प्रति संवेदनशील हैं।
**ओम्नीरूट इसे कैसे हल करता है:**
- **एपीआई कुंजी प्रबंधन** - एक समर्पित `/dashboard/api-manager` पेज के साथ प्रति प्रदाता जेनरेशन, रोटेशन और स्कोपिंग
- **मॉडल-स्तरीय अनुमतियाँ** - एपीआई कुंजियों को विशिष्ट मॉडलों (`openai/*`, वाइल्डकार्ड पैटर्न) तक सीमित करें, सभी को अनुमति दें/प्रतिबंधित टॉगल के साथ
- **एपीआई एंडपॉइंट सुरक्षा** - `/v1/models` के लिए एक कुंजी की आवश्यकता है और लिस्टिंग से विशिष्ट प्रदाताओं को ब्लॉक करें
- **ऑथ गार्ड + सीएसआरएफ सुरक्षा** - सभी डैशबोर्ड रूट `withAuth` मिडलवेयर + सीएसआरएफ टोकन से सुरक्षित हैं
- **रेट लिमिटर** - कॉन्फ़िगर करने योग्य विंडो के साथ प्रति-आईपी दर सीमित करना
- **आईपी फ़िल्टरिंग** - अभिगम नियंत्रण के लिए अनुमति सूची/अवरुद्ध सूची
- **प्रॉम्प्ट इंजेक्शन गार्ड** - दुर्भावनापूर्ण प्रॉम्प्ट पैटर्न के विरुद्ध स्वच्छता
- **एईएस-256-जीसीएम एन्क्रिप्शन** - क्रेडेंशियल आराम से एन्क्रिप्ट किए गए
</details>
<details>
<summary><b>🛑 6. "मेरा प्रदाता बंद हो गया और मैंने अपना कोडिंग प्रवाह खो दिया"</b></summary>
एआई प्रदाता अस्थिर हो सकते हैं, 5xx त्रुटियाँ लौटा सकते हैं, या अस्थायी दर सीमा तक पहुँच सकते हैं। यदि कोई डेवलपर किसी एकल प्रदाता पर निर्भर करता है, तो वे बाधित हो जाते हैं। सर्किट ब्रेकर के बिना, बार-बार पुनः प्रयास करने से एप्लिकेशन क्रैश हो सकता है।
**ओम्नीरूट इसे कैसे हल करता है:**
- **सर्किट ब्रेकर प्रति-प्रदाता** - कॉन्फ़िगर करने योग्य थ्रेसहोल्ड और कूलडाउन के साथ ऑटो-खुला/बंद (बंद/खुला/आधा-खुला)
- **एक्सपोनेंशियल बैकऑफ़** - प्रगतिशील पुनः प्रयास में देरी
- **एंटी-थंडरिंग हर्ड** - म्यूटेक्स + समवर्ती रिट्री तूफानों के खिलाफ सेमाफोर सुरक्षा
- **कॉम्बो फ़ॉलबैक चेन** - यदि प्राथमिक प्रदाता विफल हो जाता है, तो बिना किसी हस्तक्षेप के स्वचालित रूप से चेन से गिर जाता है
- **कॉम्बो सर्किट ब्रेकर** - कॉम्बो श्रृंखला के भीतर विफल प्रदाताओं को स्वचालित रूप से अक्षम करता है
- **स्वास्थ्य डैशबोर्ड** - अपटाइम मॉनिटरिंग, सर्किट ब्रेकर स्थिति, लॉकआउट, कैश आँकड़े, p50/p95/p99 विलंबता
</details>
<details>
<summary><b>🔧 7. "प्रत्येक AI उपकरण को कॉन्फ़िगर करना कठिन और दोहराव वाला है"</b></summary>
डेवलपर्स कर्सर, क्लाउड कोड, कोडेक्स सीएलआई, ओपनक्लाव, जेमिनी सीएलआई, किलो कोड का उपयोग करते हैं... प्रत्येक टूल को एक अलग कॉन्फ़िगरेशन (एपीआई एंडपॉइंट, कुंजी, मॉडल) की आवश्यकता होती है। प्रदाताओं या मॉडलों को स्विच करते समय पुन: कॉन्फ़िगर करना समय की बर्बादी है।
**ओम्नीरूट इसे कैसे हल करता है:**
- **सीएलआई टूल्स डैशबोर्ड** - क्लाउड कोड, कोडेक्स सीएलआई, ओपनक्लाव, किलो कोड, एंटीग्रेविटी, क्लाइन के लिए एक-क्लिक सेटअप वाला समर्पित पृष्ठ
- **GitHub Copilot कॉन्फिग जेनरेटर** - बल्क मॉडल चयन के साथ VS कोड के लिए `chatLanguageModels.json` जेनरेट करता है
- **ऑनबोर्डिंग विज़ार्ड** - पहली बार उपयोगकर्ताओं के लिए निर्देशित 4-चरणीय सेटअप
- **एक समापन बिंदु, सभी मॉडल** - `http://localhost:20128/v1` को एक बार कॉन्फ़िगर करें, 36+ प्रदाताओं तक पहुंचें
</details>
<details>
<summary><b>🔑 8. "एकाधिक प्रदाताओं से OAuth टोकन प्रबंधित करना नरक है"</b></summary>
क्लाउड कोड, कोडेक्स, जेमिनी सीएलआई, कोपायलट - सभी समाप्त होने वाले टोकन के साथ OAuth 2.0 का उपयोग करते हैं। डेवलपर्स को लगातार पुन: प्रमाणित करने, `client_secret is missing`, `redirect_uri_mismatch` और दूरस्थ सर्वर पर विफलताओं से निपटने की आवश्यकता है। LAN/VPS पर OAuth विशेष रूप से समस्याग्रस्त है।
**ओम्नीरूट इसे कैसे हल करता है:**
- **ऑटो टोकन रिफ्रेश** - OAuth टोकन समाप्ति से पहले पृष्ठभूमि में रिफ्रेश होते हैं
- **OAuth 2.0 (PKCE) बिल्ट-इन** - क्लाउड कोड, कोडेक्स, जेमिनी सीएलआई, कोपायलट, किरो, क्वेन, आईफ्लो के लिए स्वचालित प्रवाह
- **मल्टी-अकाउंट OAuth** - JWT/ID टोकन निष्कर्षण के माध्यम से प्रति प्रदाता एकाधिक खाते
- **OAuth LAN/रिमोट फिक्स** - `redirect_uri` के लिए निजी आईपी डिटेक्शन + रिमोट सर्वर के लिए मैनुअल यूआरएल मोड
- **Nginx के पीछे OAuth** - रिवर्स प्रॉक्सी संगतता के लिए `window.location.origin` का उपयोग करता है
- **दूरस्थ OAuth मार्गदर्शिका** — VPS/Docker पर Google क्लाउड क्रेडेंशियल के लिए चरण-दर-चरण मार्गदर्शिका
</details>
<details>
<summary><b>📊 9. "मुझे नहीं पता कि मैं कितना और कहां खर्च कर रहा हूं"</b></summary>
डेवलपर्स कई भुगतान प्रदाताओं का उपयोग करते हैं लेकिन खर्च के बारे में कोई एकीकृत दृष्टिकोण नहीं रखते हैं। प्रत्येक प्रदाता का अपना बिलिंग डैशबोर्ड होता है, लेकिन कोई समेकित दृश्य नहीं होता है। अप्रत्याशित लागतें बढ़ सकती हैं।
**ओम्नीरूट इसे कैसे हल करता है:**
- **लागत विश्लेषण डैशबोर्ड** — प्रति प्रदाता प्रति टोकन लागत ट्रैकिंग और बजट प्रबंधन
- **प्रति स्तर बजट सीमा** - प्रति स्तर खर्च की अधिकतम सीमा जो स्वचालित फ़ॉलबैक को ट्रिगर करती है
- **प्रति-मॉडल मूल्य निर्धारण कॉन्फ़िगरेशन** - प्रति मॉडल कॉन्फ़िगर करने योग्य कीमतें
- **प्रति एपीआई कुंजी उपयोग सांख्यिकी** - अनुरोध गणना और प्रति कुंजी अंतिम बार उपयोग किया गया टाइमस्टैम्प
- **एनालिटिक्स डैशबोर्ड** - स्टेट कार्ड, मॉडल उपयोग चार्ट, सफलता दर और विलंबता के साथ प्रदाता तालिका
</details>
<details>
<summary><b>🐛 10. "मैं AI कॉल में त्रुटियों और समस्याओं का निदान नहीं कर सकता"</b></summary>
जब कोई कॉल विफल हो जाती है, तो देव को पता नहीं चलता कि यह दर सीमा, समाप्त टोकन, गलत प्रारूप या प्रदाता त्रुटि थी। विभिन्न टर्मिनलों पर खंडित लॉग। अवलोकन के बिना, डिबगिंग परीक्षण-और-त्रुटि है।
**ओम्नीरूट इसे कैसे हल करता है:**
- **एकीकृत लॉग डैशबोर्ड** - 4 टैब: अनुरोध लॉग, प्रॉक्सी लॉग, ऑडिट लॉग, कंसोल
- **कंसोल लॉग व्यूअर** - रंग-कोडित स्तरों, ऑटो-स्क्रॉल, खोज, फ़िल्टर के साथ वास्तविक समय टर्मिनल-शैली व्यूअर
- **SQLite प्रॉक्सी लॉग** - लगातार लॉग जो सर्वर पुनरारंभ होने से बचे रहते हैं
- **अनुवादक खेल का मैदान** - 4 डिबगिंग मोड: खेल का मैदान (प्रारूप अनुवाद), चैट टेस्टर (राउंड-ट्रिप), टेस्ट बेंच (बैच), लाइव मॉनिटर (वास्तविक समय)
- **अनुरोध टेलीमेट्री** - p50/p95/p99 विलंबता + X-अनुरोध-आईडी ट्रेसिंग
- **रोटेशन के साथ फ़ाइल-आधारित लॉगिंग** - कंसोल इंटरसेप्टर आकार-आधारित रोटेशन के साथ JSON लॉग में सब कुछ कैप्चर करता है
</details>
<details>
<summary><b>🏗️ 11. "गेटवे की तैनाती और रखरखाव जटिल है"</b></summary>
विभिन्न वातावरणों (स्थानीय, वीपीएस, डॉकर, क्लाउड) में एआई प्रॉक्सी को स्थापित करना, कॉन्फ़िगर करना और बनाए रखना श्रम-गहन है। हार्डकोडेड पथ, निर्देशिकाओं पर `EACCES`, पोर्ट विरोध और क्रॉस-प्लेटफ़ॉर्म बिल्ड जैसी समस्याएं घर्षण बढ़ाती हैं।
**ओम्नीरूट इसे कैसे हल करता है:**
- **npm ग्लोबल इंस्टाल** — `npm install -g omniroute && omniroute` — हो गया
- **डॉकर मल्टी-प्लेटफ़ॉर्म** - AMD64 + ARM64 नेटिव (Apple सिलिकॉन, AWS ग्रेविटॉन, रास्पबेरी पाई)
- **डॉकर कंपोज प्रोफाइल** - `base` (कोई CLI उपकरण नहीं) और `cli` (क्लाउड कोड, कोडेक्स, ओपनक्लाव के साथ)
- **इलेक्ट्रॉन डेस्कटॉप ऐप** - सिस्टम ट्रे, ऑटो-स्टार्ट, ऑफ़लाइन मोड के साथ विंडोज/मैकओएस/लिनक्स के लिए मूल ऐप
- **स्प्लिट-पोर्ट मोड** - उन्नत परिदृश्यों के लिए अलग-अलग पोर्ट पर एपीआई और डैशबोर्ड (रिवर्स प्रॉक्सी, कंटेनर नेटवर्किंग)
- **क्लाउड सिंक** - क्लाउडफ्लेयर वर्कर्स के माध्यम से सभी डिवाइसों में कॉन्फिग सिंक्रोनाइजेशन
- **डीबी बैकअप** - सभी सेटिंग्स का स्वचालित बैकअप, पुनर्स्थापना, निर्यात और आयात
</details>
<details>
<summary><b>🌍 12. "इंटरफ़ेस केवल अंग्रेजी है और मेरी टीम अंग्रेजी नहीं बोलती है"</b></summary>
गैर-अंग्रेजी भाषी देशों, विशेष रूप से लैटिन अमेरिका, एशिया और यूरोप में टीमें, केवल अंग्रेजी इंटरफेस के साथ संघर्ष करती हैं। भाषा बाधाएँ अपनाने को कम करती हैं और कॉन्फ़िगरेशन त्रुटियों को बढ़ाती हैं।
**ओम्नीरूट इसे कैसे हल करता है:**
- **डैशबोर्ड i18n - 30 भाषाएँ** - अरबी, बल्गेरियाई, डेनिश, जर्मन, स्पेनिश, फिनिश, फ्रेंच, हिब्रू, हिंदी, हंगेरियन, इंडोनेशियाई, इतालवी, जापानी, कोरियाई, मलय, डच, नॉर्वेजियन, पोलिश, पुर्तगाली (पीटी/बीआर), रोमानियाई, रूसी, स्लोवाक, स्वीडिश, थाई, यूक्रेनी, वियतनामी, चीनी, फिलिपिनो, अंग्रेजी सहित सभी 500+ कुंजियाँ अनुवादित
- **आरटीएल समर्थन** - अरबी और हिब्रू के लिए दाएं से बाएं समर्थन
- **बहु-भाषा रीडमी** - 30 पूर्ण दस्तावेज़ीकरण अनुवाद
- **भाषा चयनकर्ता** - वास्तविक समय स्विचिंग के लिए हेडर में ग्लोब आइकन
</details>
<details>
<summary><b>🔄 13. "मुझे चैट से अधिक की आवश्यकता है - मुझे एम्बेडिंग, चित्र, ऑडियो की आवश्यकता है"</b></summary>
एआई का मतलब सिर्फ चैट पूरा करना नहीं है। डेवलपर्स को छवियां उत्पन्न करने, ऑडियो ट्रांसक्राइब करने, आरएजी के लिए एम्बेडिंग बनाने, दस्तावेज़ों को फिर से रैंक करने और सामग्री को मॉडरेट करने की आवश्यकता होती है। प्रत्येक एपीआई का एक अलग समापन बिंदु और प्रारूप होता है।
**ओम्नीरूट इसे कैसे हल करता है:**
- **एम्बेडिंग्स** - 6 प्रदाताओं और 9+ मॉडलों के साथ `/v1/embeddings`
- **इमेज जेनरेशन** - `/v1/images/generations` 10 प्रदाताओं और 20+ मॉडलों के साथ (ओपनएआई, एक्सएआई, टुगेदर, फायरवर्क्स, नेबियस, हाइपरबोलिक, नैनोबनाना, एंटीग्रेविटी, एसडी वेबयूआई, कॉम्फीयूआई)
- **टेक्स्ट-टू-वीडियो** — `/v1/videos/generations` — कॉम्फीयूआई (एनिमेटडिफ, एसवीडी) और एसडी वेबयूआई
- **टेक्स्ट-टू-म्यूजिक** — `/v1/music/generations` — कॉम्फीयूआई (स्थिर ऑडियो ओपन, म्यूजिकजेन)
- **ऑडियो ट्रांसक्रिप्शन** - `/v1/audio/transcriptions` - व्हिस्पर + एनवीडिया एनआईएम, हगिंगफेस, क्वेन3
- **टेक्स्ट-टू-स्पीच** - `/v1/audio/speech` - इलेवनलैब्स, एनवीडिया एनआईएम, हगिंगफेस, कोक्वी, टोरटोइज़, क्वेन3, + मौजूदा प्रदाता
- **संयम** — `/v1/moderations` — सामग्री सुरक्षा जांच
- **पुनर्रैंकिंग** — `/v1/rerank` — दस्तावेज़ प्रासंगिकता पुनर्रैंकिंग
- **प्रतिक्रिया एपीआई** - कोडेक्स के लिए पूर्ण `/v1/responses` समर्थन
</details>
<details>
<summary><b>🧪 14. "मेरे पास सभी मॉडलों की गुणवत्ता का परीक्षण और तुलना करने का कोई तरीका नहीं है"</b></summary>
डेवलपर्स जानना चाहते हैं कि उनके उपयोग के मामले में कौन सा मॉडल सबसे अच्छा है - कोड, अनुवाद, तर्क - लेकिन मैन्युअल रूप से तुलना करना धीमा है। कोई एकीकृत eval उपकरण मौजूद नहीं है।
**ओम्नीरूट इसे कैसे हल करता है:**
- **एलएलएम मूल्यांकन** - अभिवादन, गणित, भूगोल, कोड जनरेशन, JSON अनुपालन, अनुवाद, मार्कडाउन, सुरक्षा इनकार को कवर करने वाले 10 प्री-लोडेड मामलों के साथ गोल्डन सेट परीक्षण
- **4 मैच रणनीतियाँ** - `exact`, `contains`, `regex`, `custom` (JS फ़ंक्शन)
- **अनुवादक खेल का मैदान परीक्षण बेंच** - एकाधिक इनपुट और अपेक्षित आउटपुट, क्रॉस-प्रदाता तुलना के साथ बैच परीक्षण
- **चैट परीक्षक** - दृश्य प्रतिक्रिया प्रतिपादन के साथ पूर्ण राउंड-ट्रिप
- **लाइव मॉनिटर** - प्रॉक्सी के माध्यम से बहने वाले सभी अनुरोधों की वास्तविक समय स्ट्रीम
</details>
<details>
<summary><b>📈 15. "मुझे प्रदर्शन खोए बिना स्केल करने की आवश्यकता है"</b></summary>
जैसे-जैसे अनुरोध की मात्रा बढ़ती है, कैशिंग के बिना वही प्रश्न डुप्लिकेट लागत उत्पन्न करते हैं। निष्क्रियता के बिना, डुप्लिकेट अपशिष्ट प्रसंस्करण का अनुरोध करता है। प्रति-प्रदाता दर सीमा का सम्मान किया जाना चाहिए।
**ओम्नीरूट इसे कैसे हल करता है:**
- **सिमेंटिक कैश** - दो-स्तरीय कैश (हस्ताक्षर + सिमेंटिक) लागत और विलंबता को कम करता है
- **अनुरोध Idempotency** - समान अनुरोधों के लिए 5s डिडुप्लीकेशन विंडो
- **दर सीमा का पता लगाना** - प्रति-प्रदाता आरपीएम, न्यूनतम अंतर, और अधिकतम समवर्ती ट्रैकिंग
- **संपादन योग्य दर सीमाएँ** — सेटिंग्स में कॉन्फ़िगर करने योग्य डिफ़ॉल्ट → दृढ़ता के साथ लचीलापन
- **एपीआई कुंजी सत्यापन कैश** - उत्पादन प्रदर्शन के लिए 3-स्तरीय कैश
- **टेलीमेट्री के साथ स्वास्थ्य डैशबोर्ड** — p50/p95/p99 विलंबता, कैश आँकड़े, अपटाइम
</details>
<details>
<summary><b>🤖 16. "मैं विश्व स्तर पर मॉडल व्यवहार को नियंत्रित करना चाहता हूं"</b></summary>
ऐसे डेवलपर जो सभी प्रतिक्रियाएं एक विशिष्ट भाषा में, एक विशिष्ट लहजे में चाहते हैं, या तर्क टोकन को सीमित करना चाहते हैं। प्रत्येक टूल/अनुरोध में इसे कॉन्फ़िगर करना अव्यावहारिक है।
**ओम्नीरूट इसे कैसे हल करता है:**
- **सिस्टम प्रॉम्प्ट इंजेक्शन** — ग्लोबल प्रॉम्प्ट सभी अनुरोधों पर लागू होता है
- **सोच बजट सत्यापन** - प्रति अनुरोध तर्क टोकन आवंटन नियंत्रण (पासथ्रू, ऑटो, कस्टम, अनुकूली)
- **6 रूटिंग रणनीतियाँ** - वैश्विक रणनीतियाँ जो यह निर्धारित करती हैं कि अनुरोध कैसे वितरित किए जाते हैं
- **वाइल्डकार्ड राउटर** - `provider/*` पैटर्न किसी भी प्रदाता को गतिशील रूप से रूट करता है
- **कॉम्बो सक्षम/अक्षम टॉगल** — कॉम्बो को सीधे डैशबोर्ड से टॉगल करें
- **प्रदाता टॉगल** — एक क्लिक से प्रदाता के लिए सभी कनेक्शन सक्षम/अक्षम करें
- **अवरुद्ध प्रदाता** - `/v1/models` सूची से विशिष्ट प्रदाताओं को बाहर करें
</details>
<details>
<summary><b>🧰 17. "मुझे प्रथम श्रेणी उत्पाद क्षमताओं के रूप में MCP टूल की आवश्यकता है"</b></summary>
कई एआई गेटवे एमसीपी को केवल एक छिपे हुए कार्यान्वयन विवरण के रूप में उजागर करते हैं। टीमों को एक दृश्यमान, प्रबंधनीय संचालन परत की आवश्यकता होती है।
**ओम्नीरूट इसे कैसे हल करता है:**
- एमसीपी डैशबोर्ड नेविगेशन और एंडपॉइंट प्रोटोकॉल टैब में दिखाई देता है
- प्रक्रिया, उपकरण, कार्यक्षेत्र और ऑडिट के साथ समर्पित एमसीपी प्रबंधन पृष्ठ
- `omniroute --mcp` और क्लाइंट ऑनबोर्डिंग के लिए बिल्ट-इन क्विक-स्टार्ट
</details>
<details>
<summary><b>🧠 18. "मुझे सिंक + स्ट्रीम कार्य पथों के साथ A2A ऑर्केस्ट्रेशन की आवश्यकता है"</b></summary>
एजेंट वर्कफ़्लो को जीवनचक्र नियंत्रण के साथ सीधे उत्तर और लंबे समय तक चलने वाले स्ट्रीम निष्पादन दोनों की आवश्यकता होती है।
**ओम्नीरूट इसे कैसे हल करता है:**
- A2A JSON-RPC एंडपॉइंट (`POST /a2a`) `message/send` और `message/stream` के साथ
- टर्मिनल राज्य प्रसार के साथ एसएसई स्ट्रीमिंग
- `tasks/get` और `tasks/cancel` के लिए कार्य जीवनचक्र एपीआई
</details>
<details>
<summary><b>🛰️ 19. "मुझे वास्तविक MCP प्रक्रिया स्वास्थ्य की आवश्यकता है, अनुमानित स्थिति की नहीं"</b></summary>
परिचालन टीमों को यह जानने की जरूरत है कि क्या एमसीपी वास्तव में जीवित है, न कि केवल एपीआई पहुंच योग्य है या नहीं।
**ओम्नीरूट इसे कैसे हल करता है:**
- पीआईडी, टाइमस्टैम्प, ट्रांसपोर्ट, टूल काउंट और स्कोप मोड के साथ रनटाइम हार्टबीट फ़ाइल
- एमसीपी स्थिति एपीआई दिल की धड़कन + हाल की गतिविधि का संयोजन
- प्रक्रिया/अपटाइम/दिल की धड़कन ताजगी के लिए यूआई स्टेटस कार्ड
</details>
<details>
<summary><b>📋 20. "मुझे ऑडिटेबल MCP टूल निष्पादन की आवश्यकता है"</b></summary>
जब उपकरण कॉन्फ़िगरेशन को बदलते हैं या ऑप्स क्रियाओं को ट्रिगर करते हैं, तो टीमों को फोरेंसिक ट्रैसेबिलिटी की आवश्यकता होती है।
**ओम्नीरूट इसे कैसे हल करता है:**
- MCP टूल कॉल के लिए SQLite समर्थित ऑडिट लॉगिंग
- टूल, सफलता/असफलता, एपीआई कुंजी और पेजिनेशन द्वारा फ़िल्टर
- डैशबोर्ड ऑडिट टेबल + स्वचालन के लिए आँकड़े समापन बिंदु
</details>
<details>
<summary><b>🔐 21. "मुझे प्रति एकीकरण के लिए स्कोप्ड MCP अनुमतियों की आवश्यकता है"</b></summary>
विभिन्न ग्राहकों को टूल श्रेणियों तक कम से कम विशेषाधिकार प्राप्त होना चाहिए।
**ओम्नीरूट इसे कैसे हल करता है:**
- नियंत्रित टूल एक्सेस के लिए 9 दानेदार एमसीपी स्कोप
- एमसीपी प्रबंधन यूआई में दायरा प्रवर्तन और दृश्यता
- परिचालन टूलींग के लिए सुरक्षित डिफ़ॉल्ट मुद्रा
</details>
<details>
<summary><b>⚙️ 22. "मुझे पुनः तैनाती के बिना परिचालन नियंत्रण की आवश्यकता है"</b></summary>
घटनाओं या लागत आयोजनों के दौरान टीमों को त्वरित रनटाइम परिवर्तन की आवश्यकता होती है।
**ओम्नीरूट इसे कैसे हल करता है:**
- कॉम्बो सक्रियण को सीधे एमसीपी डैशबोर्ड से स्विच करें
- पूर्व-निर्धारित पॉलिसी पैक से लचीलापन प्रोफ़ाइल लागू करें
- उसी ऑपरेशन पैनल से सर्किट ब्रेकर स्थिति को रीसेट करें
</details>
<details>
<summary><b>🔄 23. "मुझे लाइव A2A कार्य जीवनचक्र दृश्यता और रद्दीकरण की आवश्यकता है"</b></summary>
जीवनचक्र दृश्यता के बिना, कार्य घटनाओं का परीक्षण करना कठिन हो जाता है।
**ओम्नीरूट इसे कैसे हल करता है:**
- पेजिनेशन के साथ राज्य/कौशल द्वारा कार्य सूचीकरण/फ़िल्टरिंग
- कार्य मेटाडेटा, घटनाओं और कलाकृतियों पर ड्रिल-डाउन
- पुष्टि के साथ कार्य रद्दीकरण समापन बिंदु और यूआई कार्रवाई
</details>
<details>
<summary><b>🌊 24. "मुझे A2A लोड के लिए सक्रिय स्ट्रीम मेट्रिक्स की आवश्यकता है"</b></summary>
स्ट्रीमिंग वर्कफ़्लो के लिए समवर्ती और लाइव कनेक्शन में परिचालन अंतर्दृष्टि की आवश्यकता होती है।
**ओम्नीरूट इसे कैसे हल करता है:**
- सक्रिय स्ट्रीम काउंटर A2A स्थिति में एकीकृत
- अंतिम कार्य टाइमस्टैम्प और प्रति-राज्य गणना
- वास्तविक समय ऑप्स निगरानी के लिए A2A डैशबोर्ड कार्ड
</details>
<details>
<summary><b>🪪 25. "मुझे ग्राहकों के लिए मानक एजेंट खोज की आवश्यकता है"</b></summary>
बाहरी ग्राहकों और ऑर्केस्ट्रेटर्स को ऑनबोर्डिंग के लिए मशीन-पठनीय मेटाडेटा की आवश्यकता होती है।
**ओम्नीरूट इसे कैसे हल करता है:**
- एजेंट कार्ड `/.well-known/agent.json` पर प्रदर्शित हुआ
- प्रबंधन यूआई में दिखाई गई क्षमताएं और कौशल
- A2A स्थिति API में स्वचालन के लिए खोज मेटाडेटा शामिल है
</details>
<details>
<summary><b>🧭 26. "मुझे उत्पाद UX में प्रोटोकॉल खोज योग्यता की आवश्यकता है"</b></summary>
यदि उपयोगकर्ता प्रोटोकॉल सतहों की खोज नहीं कर पाते हैं, तो अपनाने और समर्थन की गुणवत्ता में गिरावट आती है।
**ओम्नीरूट इसे कैसे हल करता है:**
- MCP और A2A के लिए साइडबार प्रविष्टियाँ
- समापन बिंदु पृष्ठ प्रोटोकॉल टैब त्वरित-प्रारंभ और स्थिति के साथ
- सिंहावलोकन से लेकर समर्पित प्रबंधन डैशबोर्ड तक के लिंक
</details>
<details>
<summary><b>🧪 27. "मुझे वास्तविक ग्राहकों के साथ एंड-टू-एंड प्रोटोकॉल सत्यापन की आवश्यकता है"</b></summary>
रिलीज़ से पहले प्रोटोकॉल संगतता को सत्यापित करने के लिए मॉक परीक्षण पर्याप्त नहीं हैं।
**ओम्नीरूट इसे कैसे हल करता है:**
- E2E सुइट जो ऐप को बूट करता है और वास्तविक MCP SDK क्लाइंट ट्रांसपोर्ट का उपयोग करता है
- A2A क्लाइंट खोज, भेजने, स्ट्रीम करने, प्राप्त करने और प्रवाह को रद्द करने के लिए परीक्षण करता है
- एमसीपी ऑडिट और ए2ए कार्य एपीआई के खिलाफ दावों की क्रॉस-चेक करें
</details>
<details>
<summary><b>📡 28. "मुझे सभी इंटरफेस में एकीकृत अवलोकन की आवश्यकता है"</b></summary>
प्रोटोकॉल द्वारा अवलोकनशीलता को विभाजित करने से ब्लाइंड स्पॉट और लंबा एमटीटीआर बनता है।
**ओम्नीरूट इसे कैसे हल करता है:**
- एक उत्पाद में एकीकृत डैशबोर्ड/लॉग/एनालिटिक्स
- स्वास्थ्य + ऑडिट + ओपनएआई, एमसीपी और ए2ए परतों में टेलीमेट्री अनुरोध
- स्थिति और स्वचालन के लिए परिचालन एपीआई
</details>
<details>
<summary><b>💼 29. "मुझे प्रॉक्सी + टूल + एजेंट ऑर्केस्ट्रेशन के लिए एक रनटाइम की आवश्यकता है" </b></summary>
कई अलग-अलग सेवाएँ चलाने से परिचालन लागत और विफलता मोड बढ़ जाते हैं।
**ओम्नीरूट इसे कैसे हल करता है:**
- OpenAI-संगत प्रॉक्सी, MCP सर्वर और A2A सर्वर एक स्टैक में
- साझा प्रमाणीकरण, लचीलापन, डेटा भंडारण और अवलोकन क्षमता
- सभी संपर्क सतहों पर सुसंगत नीति मॉडल
</details>
<details>
<summary><b>🚀 30. "मुझे ग्लू-कोड फैलाव के बिना एजेंटिक वर्कफ़्लो भेजने की आवश्यकता है"</b></summary>
कई तदर्थ सेवाओं और स्क्रिप्ट्स को सिलाई करते समय टीमों की गति कम हो जाती है।
**ओम्नीरूट इसे कैसे हल करता है:**
- ग्राहकों और एजेंटों के लिए एकीकृत समापन बिंदु रणनीति
- अंतर्निहित प्रोटोकॉल प्रबंधन यूआई और धूम्रपान सत्यापन पथ
- उत्पादन के लिए तैयार नींव (सुरक्षा, लॉगिंग, लचीलापन, बैकअप)
</details>
### उदाहरण प्लेबुक (एकीकृत उपयोग के मामले)
**प्लेबुक ए: सशुल्क सदस्यता + सस्ता बैकअप अधिकतम करें**
```txt
Combo: "maximize-claude"
1. cc/claude-opus-4-6
2. glm/glm-4.7
3. if/kimi-k2-thinking
Monthly cost: $20 + small backup spend
Outcome: higher quality, near-zero interruption
```
**प्लेबुक बी: शून्य-लागत कोडिंग स्टैक**
```txt
Combo: "free-forever"
1. gc/gemini-3-flash
2. if/kimi-k2-thinking
3. qw/qwen3-coder-plus
Monthly cost: $0
Outcome: stable free coding workflow
```
**प्लेबुक सी: 24/7 हमेशा चालू फ़ॉलबैक श्रृंखला**
```txt
Combo: "always-on"
1. cc/claude-opus-4-6
2. cx/gpt-5.2-codex
3. glm/glm-4.7
4. minimax/MiniMax-M2.1
5. if/kimi-k2-thinking
Outcome: deep fallback depth for deadline-critical workloads
```
**प्लेबुक डी: एजेंट एमसीपी + ए2ए के साथ काम करता है**
```txt
1) Start MCP transport (`omniroute --mcp`) for tool-driven operations
2) Run A2A tasks via `message/send` and `message/stream`
3) Observe via /dashboard/mcp and /dashboard/a2a
4) Control incidents with resilience profile + task cancellation
```
---
## ⚡ त्वरित शुरुआत
**1. विश्व स्तर पर स्थापित करें:**
@@ -146,7 +678,7 @@ docker run -d \
---
## 🖥️ Desktop App — Offline & Always-On
## 🖥️
> 🆕 **NEW!** OmniRoute is now available as a **native desktop application** for Windows, macOS, and Linux.
@@ -193,57 +725,6 @@ npm run electron:build:linux # Linux (.AppImage)
---
## 🎯 उपयोग के मामले
### केस 1: "मेरे पास क्लाउड प्रो सदस्यता है"
**समस्या:** भारी कोडिंग के दौरान कोटा अप्रयुक्त, दर सीमा समाप्त हो जाता है
```
Combo: "maximize-claude"
1. cc/claude-opus-4-6 (use subscription fully)
2. glm/glm-4.7 (cheap backup when quota out)
3. if/kimi-k2-thinking (free emergency fallback)
Monthly cost: $20 (subscription) + ~$5 (backup) = $25 total
vs. $20 + hitting limits = frustration
```
### केस 2: "मुझे शून्य लागत चाहिए"
**समस्या:** सदस्यताएं वहन नहीं कर सकते, विश्वसनीय एआई कोडिंग की आवश्यकता है
### केस 3: "मुझे 24/7 कोडिंग चाहिए, कोई रुकावट नहीं"
**समस्या:** समय सीमा, डाउनटाइम बर्दाश्त नहीं कर सकते
```
Combo: "always-on"
1. cc/claude-opus-4-6 (best quality)
2. cx/gpt-5.2-codex (second subscription)
3. glm/glm-4.7 (cheap, resets daily)
4. minimax/MiniMax-M2.1 (cheapest, 5h reset)
5. if/kimi-k2-thinking (free unlimited)
Result: 5 layers of fallback = zero downtime
```
### केस 4: "मुझे ओपनक्लॉ में मुफ़्त एआई चाहिए"
**समस्या:** मैसेजिंग ऐप्स में AI सहायक की आवश्यकता है, पूरी तरह से निःशुल्क
```
Combo: "openclaw-free"
1. if/glm-4.7 (unlimited free)
2. if/minimax-m2.1 (unlimited free)
3. if/kimi-k2-thinking (unlimited free)
Monthly cost: $0
Access via: WhatsApp, Telegram, Slack, Discord, iMessage, Signal...
```
---
## 💡 मुख्य विशेषताएं
### 🧠 कोर रूटिंग और इंटेलिजेंस
@@ -259,6 +740,8 @@ Access via: WhatsApp, Telegram, Slack, Discord, iMessage, Signal...
| 🧩 **कस्टम मॉडल** | किसी भी प्रदाता से कोई भी मॉडल आईडी जोड़ें |
| 🌐 **वाइल्डकार्ड राउटर** | `provider/*` पैटर्न को गतिशील रूप से किसी भी प्रदाता तक रूट करें |
| 🧠 **सोच बजट** | तर्क मॉडल के लिए पासथ्रू, ऑटो, कस्टम और अनुकूली मोड |
| 🔀 **Model Aliases** | Auto-forward deprecated model IDs to current replacements (built-in + custom) |
| ⚡ **Background Degradation** | Auto-route background tasks (titles, summaries) to cheaper models |
| 💬 **सिस्टम प्रॉम्प्ट इंजेक्शन** | ग्लोबल सिस्टम प्रॉम्प्ट सभी अनुरोधों पर लागू किया गया |
| 📄 **प्रतिक्रियाएं एपीआई** | कोडेक्स के लिए पूर्ण ओपनएआई रिस्पॉन्स एपीआई (`/v1/responses`) समर्थन |
@@ -284,6 +767,8 @@ Access via: WhatsApp, Telegram, Slack, Discord, iMessage, Signal...
| 🔒 **टीएलएस फ़िंगरप्रिंट स्पूफ़िंग** | Wreq-js के माध्यम से टीएलएस-आधारित बॉट डिटेक्शन को बायपास करें |
| 🌐 **आईपी फ़िल्टरिंग** | एपीआई अभिगम नियंत्रण के लिए अनुमति सूची/अवरुद्ध सूची |
| 📊 **संपादन योग्य दर सीमाएँ** | सिस्टम स्तर पर कॉन्फ़िगर करने योग्य आरपीएम, न्यूनतम अंतर और अधिकतम समवर्ती |
| 💾 **Rate Limit Persistence** | Learned limits survive restarts via SQLite with 60s debounce + 24h staleness |
| 🔄 **Token Refresh Resilience** | Per-provider circuit breaker (5 fails→30min) + 30s timeout per attempt |
| 🛡 **एपीआई एंडपॉइंट सुरक्षा** | `/models` समापन बिंदु के लिए ऑथेंटिक गेटिंग + प्रदाता अवरोधन |
| 🔒 **प्रॉक्सी दृश्यता** | रंग-कोडित बैज: 🟢 वैश्विक, 🟡 प्रदाता, 🔵 आईपी डिस्प्ले के साथ प्रति-कनेक्शन |
| 🌐 **3-स्तरीय प्रॉक्सी कॉन्फ़िगरेशन** | वैश्विक, प्रति-प्रदाता, या प्रति-कनेक्शन स्तर पर प्रॉक्सी कॉन्फ़िगर करें |
@@ -389,6 +874,27 @@ Access via: WhatsApp, Telegram, Slack, Discord, iMessage, Signal...
- स्वचालित पृष्ठभूमि सिंक
- सुरक्षित एन्क्रिप्टेड भंडारण
## 🧪 मूल्यांकन
ओमनीरूट में गोल्डन सेट के मुकाबले एलएलएम प्रतिक्रिया गुणवत्ता का परीक्षण करने के लिए एक अंतर्निहित मूल्यांकन ढांचा शामिल है। डैशबोर्ड में **एनालिटिक्स → इवेल्स** के माध्यम से इसे एक्सेस करें।
### बिल्ट-इन गोल्डन सेट
प्री-लोडेड "ओम्नीरूट गोल्डन सेट" में 10 परीक्षण मामले शामिल हैं:
- नमस्ते, गणित, भूगोल, कोड जनरेशन
- JSON प्रारूप अनुपालन, अनुवाद, मार्कडाउन
- सुरक्षा इनकार (हानिकारक सामग्री), गिनती, बूलियन तर्क
### मूल्यांकन रणनीतियाँ
| रणनीति | विवरण | उदाहरण |
| ---------- | ------------------------------------------------- | -------------------------------- |
| `exact` | आउटपुट बिल्कुल मेल खाना चाहिए | `"4"` |
| `contains` | आउटपुट में सबस्ट्रिंग (केस-असंवेदनशील) होना चाहिए | `"Paris"` |
| `regex` | आउटपुट रेगेक्स पैटर्न से मेल खाना चाहिए | `"1.*2.*3"` |
| `custom` | कस्टम जेएस फ़ंक्शन सही/गलत लौटाता है | `(output) => output.length > 10` |
---
## 📖 सेटअप गाइड
@@ -527,184 +1033,6 @@ Cost: $0 forever!
---
## 📊 उपलब्ध मॉडल
<details>
<summary><b>सभी उपलब्ध मॉडल देखें</b></summary>
**क्लाउड कोड (`cc/`)** - प्रो/मैक्स:
- `cc/claude-opus-4-6`
- `cc/claude-sonnet-4-5-20250929`
- `cc/claude-haiku-4-5-20251001`
**कोडेक्स (`cx/`)** - प्लस/प्रो:
-
- `cx/gpt-5.1-codex-max`
**मिथुन सीएलआई (`gc/`)** - मुफ़्त:
- `gc/gemini-3-flash-preview`
- `gc/gemini-2.5-pro`
**गिटहब कोपायलट (`gh/`)**:
- `gh/gpt-5`
- `gh/claude-4.5-sonnet`
**एनवीडिया एनआईएम (`nvidia/`)** - मुफ़्त क्रेडिट:
- `nvidia/llama-3.3-70b-instruct`
- `nvidia/mistral-7b-instruct`
- [build.nvidia.com](https://build.nvidia.com) पर 50+ अधिक मॉडल
**जीएलएम (`glm/`)** - $0.6/1M:
- `glm/glm-4.7`
**मिनीमैक्स (`minimax/`)** - $0.2/1M:
- `minimax/MiniMax-M2.1`
**iFlow (`if/`)** - मुफ़्त:
- `if/kimi-k2-thinking`
- `if/qwen3-coder-plus`
- `if/deepseek-r1`
- `if/glm-4.7`
- `if/minimax-m2`
**क्वेन (`qw/`)** - मुफ़्त:
- `qw/qwen3-coder-plus`
- `qw/qwen3-coder-flash`
**किरो (`kr/`)** - मुफ़्त:
- `kr/claude-sonnet-4.5`
- `kr/claude-haiku-4.5`
**ओपनराउटर (`or/`)** - 100+ मॉडल:
- `or/anthropic/claude-4-sonnet`
- `or/google/gemini-2.5-pro`
- [openrouter.ai/models](https://openrouter.ai/models) से कोई भी मॉडल
---
## 🧪 मूल्यांकन (Evaluations)
ओमनीरूट में गोल्डन सेट के मुकाबले एलएलएम प्रतिक्रिया गुणवत्ता का परीक्षण करने के लिए एक अंतर्निहित मूल्यांकन ढांचा शामिल है। डैशबोर्ड में **एनालिटिक्स → इवेल्स** के माध्यम से इसे एक्सेस करें।
### बिल्ट-इन गोल्डन सेट
प्री-लोडेड "ओम्नीरूट गोल्डन सेट" में 10 परीक्षण मामले शामिल हैं:
- नमस्ते, गणित, भूगोल, कोड जनरेशन
- JSON प्रारूप अनुपालन, अनुवाद, मार्कडाउन
- सुरक्षा इनकार (हानिकारक सामग्री), गिनती, बूलियन तर्क
### मूल्यांकन रणनीतियाँ
| रणनीति | विवरण | उदाहरण |
| ---------- | ------------------------------------------------- | -------------------------------- |
| `exact` | आउटपुट बिल्कुल मेल खाना चाहिए | `"4"` |
| `contains` | आउटपुट में सबस्ट्रिंग (केस-असंवेदनशील) होना चाहिए | `"Paris"` |
| `regex` | आउटपुट रेगेक्स पैटर्न से मेल खाना चाहिए | `"1.*2.*3"` |
| `custom` | कस्टम जेएस फ़ंक्शन सही/गलत लौटाता है | `(output) => output.length > 10` |
---
## 🔐 OAuth em सर्विडोर रेमोटो (रिमोट OAuth सेटअप)
<a name="oauth-em-servidor-remoto"></a>
> **⚠️ वीपीएस/डॉकर/सर्विडोर रिमोट पर ओमनीरूट का उपयोग करने के लिए महत्वपूर्ण**
### क्या आप एंटीग्रेविटी/जेमिनी सीएलआई के लिए OAuth का उपयोग कर रहे हैं?
प्रमाणित करने के लिए **एंटीग्रेविटी** और **मिथुन सीएलआई** का उपयोग करें **Google OAuth 2.0** का उपयोग करें। Google के लिए यह आवश्यक है कि `redirect_uri` का उपयोग बिना किसी प्रवाह के OAuth सेजा **exatamente** के माध्यम से किया जाए ताकि URIs को Google क्लाउड कंसोल के लिए पूर्व-आवेदन किया जा सके।
जैसा कि OAuth का प्रमाण है, कोई ओम्निरूट कैडस्ट्राड नहीं है ** `localhost`** के लिए एपेनास। एक सर्विडोर रिमोट (उदा: `https://omniroute.meuservidor.com`) पर ओमनीरूट का उपयोग कैसे करें, या Google एक प्रमाणीकरण कॉम को पुनः प्राप्त करता है:
### समाधान: OAuth को कॉन्फ़िगर करें
आपका सटीक विवरण **OAuth 2.0 क्लाइंट आईडी** आपके सर्वर पर यूआरआई के साथ Google क्लाउड कंसोल नहीं है।
#### पासो ए पासो
**1. Google क्लाउड कंसोल तक पहुंच**
अब्राहम: [https://console.cloud.google.com/apis/credentials](https://console.cloud.google.com/apis/credentials)
**2. नया OAuth 2.0 क्लाइंट आईडी देखें**
- उन्हें क्लिक करें **"+ क्रेडेंशियल बनाएं"** → **"OAuth क्लाइंट आईडी"**
- आवेदन टिप: **"वेब एप्लिकेशन"**
- नोम: एस्कोल्हा क्वाल्कर नोम (उदा: `OmniRoute Remote`)
**3. अधिकृत रीडायरेक्ट यूआरआई के रूप में एडिकियोन**
कोई शिकायत नहीं **"अधिकृत रीडायरेक्ट यूआरआई"**, आदि:
```
https://seu-servidor.com/callback
```
> स्थानापन्न `seu-servidor.com` अपने आईपी को अपने सर्वर पर रखें (इसमें एक आवश्यक पोर्ट भी शामिल है, उदाहरण के लिए: `http://45.33.32.156:20128/callback`)।
**4. साख के रूप में सहेजें और कॉपी करें**
एपोस क्रियर, Google द्वारा **क्लाइंट आईडी** और **क्लाइंट सीक्रेट**
**5. परिवेश परिवर्तन** के रूप में कॉन्फ़िगर करें
कोई `.env` नहीं (आप डॉकर के परिवेश को कैसे बदल सकते हैं):
```bash
# Para Antigravity:
ANTIGRAVITY_OAUTH_CLIENT_ID=seu-client-id.apps.googleusercontent.com
ANTIGRAVITY_OAUTH_CLIENT_SECRET=GOCSPX-seu-secret
# Para Gemini CLI:
GEMINI_OAUTH_CLIENT_ID=seu-client-id.apps.googleusercontent.com
GEMINI_OAUTH_CLIENT_SECRET=GOCSPX-seu-secret
GEMINI_CLI_OAUTH_CLIENT_SECRET=GOCSPX-seu-secret
```
**6. ओम्निरूट का नवीनीकरण**
```bash
# Se usando npm:
npm run dev
# Se usando Docker:
docker restart omniroute
```
**7. नए सिरे से संपर्क करें**
डैशबोर्ड → प्रदाता → एंटीग्रेविटी (या जेमिनी सीएलआई) → OAuth
`https://seu-servidor.com/callback` और एक प्रमाणीकरण कार्य के लिए Google पुनर्निर्देशन।
---
### वर्कअराउंड टेम्पोरैरियो (सेम कॉन्फिगरेशन क्रेडेंशियल प्रोप्रियास)
यदि आप पहले से ही उचित क्रेडेंशियल प्राप्त नहीं करना चाहते हैं, तो आपके लिए फ्लक्सो का उपयोग करना संभव है **यूआरएल का मैनुअल**:
1. Google पर स्वचालित URL का उपयोग करके ओम्निरूट का उपयोग करें
2. ऑटोरिज़ार का लाभ, `localhost` के लिए Google पुनर्निर्देशन (यदि कोई सर्वर रिमोट नहीं है)
3. **एक यूआरएल को पूरा कॉपी करें** अपने ब्राउजर से दोबारा डाउनलोड करें (मुझे लगता है कि एक पेज अभी भी उपलब्ध है)
4. ओम्निरूट से जुड़ने के लिए कोई भी यूआरएल नहीं है
5. उन्हें क्लिक करें **"कनेक्ट"**
> यह समाधान यूआरएल को स्वचालित रूप से डाउनलोड करने के लिए काम कर रहा है और आपके द्वारा किए गए रीडायरेक्ट को स्वतंत्र रूप से वैध बनाता है।
---
## 🐛 समस्या निवारण
<summary><b>समस्या निवारण मार्गदर्शिका का विस्तार करने के लिए क्लिक करें</b></summary>
@@ -757,7 +1085,7 @@ docker restart omniroute
---
## 🛠️ टेक स्टैक
## 🛠️
- **रनटाइम**: Node.js 1822 LTS (⚠️ Node.js 24+ **समर्थित नहीं** है - `better-sqlite3` मूल बायनेरिज़ असंगत हैं)
- **भाषा**: टाइपस्क्रिप्ट 5.9 - **100% टाइपस्क्रिप्ट** `src/` और `open-sse/` (v1.0.6) में
@@ -806,18 +1134,19 @@ docker restart omniroute
---
## 🗺️ रोडमैप
## 🗺️
ओम्निरूट ने कई विकास चरणों में **210+ सुविधाओं की योजना बनाई है**। यहां प्रमुख क्षेत्र हैं:
| श्रेणी | नियोजित विशेषताएं | हाइलाइट्स |
| --------------------------- | ----------------- | ------------------------------------------------------------------------------------------- |
| 🧠 **रूटिंग और इंटेलिजेंस** | 25+ | न्यूनतम-विलंबता रूटिंग, टैग-आधारित रूटिंग, कोटा प्रीफ़्लाइट, पी2सी खाता चयन |
| 🔒 **सुरक्षा एवं अनुपालन** | 20+ | एसएसआरएफ हार्डनिंग, क्रेडेंशियल क्लोकिंग, प्रति समापन बिंदु दर-सीमा, प्रबंधन कुंजी स्कोपिंग |
| 📊 **अवलोकनशीलता** | 15+ | ओपन टेलीमेट्री एकीकरण, वास्तविक समय कोटा निगरानी, ​​प्रति मॉडल लागत ट्रैकिंग |
| 🔄 **प्रदाता एकीकरण** | 20+ | डायनेमिक मॉडल रजिस्ट्री, प्रदाता कूलडाउन, मल्टी-अकाउंट कोडेक्स, कोपायलट कोटा पार्सिंग |
| **प्रदर्शन** | 15+ | दोहरी कैश परत, शीघ्र कैश, प्रतिक्रिया कैश, स्ट्रीमिंग कीपलाइव, बैच एपीआई |
| 🌐 **पारिस्थितिकी तंत्र** | 10+ | वेबसॉकेट एपीआई, कॉन्फिग हॉट-रीलोड, वितरित कॉन्फिग स्टोर, वाणिज्यिक मोड |
| श्रेणी | नियोजित विशेषताएं | हाइलाइट्स |
| ---------------------------- | ------------------------------------------------------ | ------------------------------------------------------------------------------------------- |
| 🎯 **Endpoint-Aware Models** | Custom models declare supported endpoints + API format |
| 🧠 **रूटिंग और इंटेलिजेंस** | 25+ | न्यूनतम-विलंबता रूटिंग, टैग-आधारित रूटिंग, कोटा प्रीफ़्लाइट, पी2सी खाता चयन |
| 🔒 **सुरक्षा एवं अनुपालन** | 20+ | एसएसआरएफ हार्डनिंग, क्रेडेंशियल क्लोकिंग, प्रति समापन बिंदु दर-सीमा, प्रबंधन कुंजी स्कोपिंग |
| 📊 **अवलोकनशीलता** | 15+ | ओपन टेलीमेट्री एकीकरण, वास्तविक समय कोटा निगरानी, ​​प्रति मॉडल लागत ट्रैकिंग |
| 🔄 **प्रदाता एकीकरण** | 20+ | डायनेमिक मॉडल रजिस्ट्री, प्रदाता कूलडाउन, मल्टी-अकाउंट कोडेक्स, कोपायलट कोटा पार्सिंग |
| **प्रदर्शन** | 15+ | दोहरी कैश परत, शीघ्र कैश, प्रतिक्रिया कैश, स्ट्रीमिंग कीपलाइव, बैच एपीआई |
| 🌐 **पारिस्थितिकी तंत्र** | 10+ | वेबसॉकेट एपीआई, कॉन्फिग हॉट-रीलोड, वितरित कॉन्फिग स्टोर, वाणिज्यिक मोड |
### 🔜 जल्द आ रहा है
@@ -831,18 +1160,6 @@ docker restart omniroute
---
## 📧समर्थन
> 💬 **हमारे समुदाय में शामिल हों!** [WhatsApp Group](https://chat.whatsapp.com/JI7cDQ1GyaiDHhVBpLxf8b?mode=gi_t) - सहायता प्राप्त करें, सुझाव साझा करें और अपडेट रहें।
- **वेबसाइट**: [omniroute.online](https://omniroute.online)
- **गिटहब**: [github.com/diegosouzapw/OmniRoute](https://github.com/diegosouzapw/OmniRoute)
- **मुद्दे**: [github.com/diegosouzapw/OmniRoute/issues](https://github.com/diegosouzapw/OmniRoute/issues)
- **व्हाट्सएप**: [Community Group](https://chat.whatsapp.com/JI7cDQ1GyaiDHhVBpLxf8b?mode=gi_t)
- **मूल परियोजना**: [9router by decolua](https://github.com/decolua/9router)
---
## 👥 योगदानकर्ता
[![Contributors](https://contrib.rocks/image?repo=diegosouzapw/OmniRoute&max=100&columns=20&anon=1)](https://github.com/diegosouzapw/OmniRoute/graphs/contributors)
@@ -893,84 +1210,3 @@ gh release create v1.0.6 --title "v1.0.6" --generate-notes
---
---
## 🇧🇷 ओमनीरूट - गेटवे डी आईए ग्रैटुइटो
<a name="-omniroute--gateway-de-ia-gratuito"></a>
### नूनका पारे डे कोडर। रोटेमेंटो इंटेलिजेंट पैरा **मॉडलोस डी आईए ग्रैटुइटोस और डे बैक्सो कस्टम** कॉम फ़ॉलबैक ऑटोमेटिको।
_एसईयू प्रॉक्सी यूनिवर्सल डी एपीआई - उम एंडपॉइंट, 36+ प्रोडोर्स, शून्य डाउनटाइम।_
### 🌐 इंटरनेशनलिज़ाकाओ (i18n)
ओम्नीरूट का डैशबोर्ड **मल्टीप्लोस इडियोमास** का समर्थन करता है। उन्हें वास्तविक वितरण:
| मुहावरा | कोडिगो | स्थिति |
| ----------------------- | ------- | ----------- |
| 🇺🇸 अंग्रेजी | `en` | ✅ कंप्लीटो |
| 🇧🇷 पोर्टुगुएस (ब्राजील) | `pt-BR` | ✅ कंप्लीटो |
**मुहावरे के बारे में जानकारी:** मुहावरे के चयन पर क्लिक करें (🇺🇸 EN) डैशबोर्ड पर कोई हेडर नहीं → वाक्यांश के चयन के बारे में क्लिक करें।
**एक नया मुहावरा जोड़ने के लिए:**
1. `src/i18n/messages/{codigo}.json` को `en.json` पर आधारित करें
2. `src/i18n/config.ts``LOCALES` और `LANGUAGES` कोड का उपयोग
3. सेवा प्रदाता की सेवा
### ⚡ इनिसियो रैपिडो
```bash
# Instalar via npm
npx omniroute@latest
# Ou rodar do código-fonte
cp .env.example .env
npm install
PORT=20128 NEXT_PUBLIC_BASE_URL=http://localhost:20128 npm run dev
```
### 🐳 डॉकर
```bash
docker run -d --name omniroute -p 20128:20128 diegosouzapw/omniroute:latest
```
### 🔑 फंक्सोनियलिडेड्स प्रिंसिपैस
- **36+ आईए** - क्लाउड, जीपीटी, जेमिनी, लामा, क्वेन, डीपसीक, और अन्य
- **रोटीमेंटो इंटेलिजेंट** — फ़ॉलबैक ऑटोमेटिको एंटर प्रोवोर्स
- **प्रारूप अनुवाद** — OpenAI ↔ क्लाउड ↔ जेमिनी ऑटोमैटिक
- **मल्टी-कॉन्टा** - चयनित इंटेलिजेंट के लिए मल्टीप्लास कॉन्टास
- **कैश सिमेंटिको** - कस्टम और लेटेंसी रेडुज़
- **OAuth automático** — टोकन स्वचालित रूप से नवीनीकृत होते हैं
- **व्यक्तिगत संयोजन** — 6 रोटेमेंटो एस्ट्रैटेजीस
- **डैशबोर्ड संपूर्ण** - मॉनिटर, लॉग, विश्लेषण, कॉन्फ़िगरेशन
- **सीएलआई उपकरण** - क्लाउड कोड, कोडेक्स, कर्सर, क्लाइन को एक क्लिक पर कॉन्फ़िगर करें
- **100% टाइपस्क्रिप्ट** — कोडिगो लिम्पो और टिपडो
### 📖 दस्तावेज़ीकरण
| डॉक्यूमेंटो | विवरण |
| ----------------------------------------------- | --------------------------------------------- |
| [Guia do Usuário](docs/USER_GUIDE.md) | प्रोवेडोर्स, कॉम्बो, सीएलआई, तैनाती |
| [Referência da API](docs/API_REFERENCE.md) | सभी ओएस एंडपॉइंट उदाहरण उदाहरण |
| [Solução de Problemas](docs/TROUBLESHOOTING.md) | समस्याएं और समाधान |
| [Arquitetura](docs/ARCHITECTURE.md) | आर्किटेक्चर और इंटर्नोस डो सिस्तेमा |
| [Contribuição](CONTRIBUTING.md) | सेटअप डे डेसेनवोल्विमेंटो ई दिशानिर्देश |
| [Deploy em VM](docs/VM_DEPLOYMENT_GUIDE.md) | संपूर्ण मार्गदर्शिका: VM + nginx + Cloudflare |
### 📧 सपोर्ट
> 💬 **एक अधिसूचना के लिए प्रवेश!** [Grupo WhatsApp](https://chat.whatsapp.com/JI7cDQ1GyaiDHhVBpLxf8b?mode=gi_t) — दो सप्ताह, पूर्ण विवरण और पूर्ण विवरण।
- **वेबसाइट**: [omniroute.online](https://omniroute.online)
- **गिटहब**: [github.com/diegosouzapw/OmniRoute](https://github.com/diegosouzapw/OmniRoute)
- **मुद्दे**: [github.com/diegosouzapw/OmniRoute/issues](https://github.com/diegosouzapw/OmniRoute/issues)
---
<sub>24/7 कोड करने वाले डेवलपर्स के लिए ❤️ के साथ निर्मित</sub>
<sub><a href="https://omniroute.online">omniroute.online</a></sub>

View File

@@ -110,6 +110,35 @@ _Connetti qualsiasi IDE o strumento CLI con IA tramite OmniRoute — gateway API
---
## 🖼️
<div align="center">
<img src="./docs/screenshots/MainOmniRoute.png" alt="OmniRoute" width="800"/>
</div>
---
## 📸
<details>
<summary><b>...</b></summary>
| # | # |
| ----- | ---------------------------------------- |
| **1** | ![1](docs/screenshots/01-providers.png) |
| **2** | ![2](docs/screenshots/02-combos.png) |
| **3** | ![3](docs/screenshots/03-analytics.png) |
| **4** | ![4](docs/screenshots/04-health.png) |
| **5** | ![5](docs/screenshots/05-translator.png) |
| **6** | ![6](docs/screenshots/06-settings.png) |
| **7** | ![7](docs/screenshots/07-cli-tools.png) |
| **8** | ![8](docs/screenshots/08-usage.png) |
| **9** | ![9](docs/screenshots/09-endpoint.png) |
</details>
---
## 🤔 Perché OmniRoute?
**Smetti di sprecare soldi e di sbattere contro i limiti:**
@@ -128,6 +157,19 @@ _Connetti qualsiasi IDE o strumento CLI con IA tramite OmniRoute — gateway API
---
## 📧 Supporto
> 💬 **Unisciti alla nostra community!** [Gruppo WhatsApp](https://chat.whatsapp.com/JI7cDQ1GyaiDHhVBpLxf8b?mode=gi_t) — Ottieni aiuto, condividi consigli e rimani aggiornato.
- **Sito Web**: [omniroute.online](https://omniroute.online)
- **GitHub**: [github.com/diegosouzapw/OmniRoute](https://github.com/diegosouzapw/OmniRoute)
- **Issues**: [github.com/diegosouzapw/OmniRoute/issues](https://github.com/diegosouzapw/OmniRoute/issues)
- **WhatsApp**: [Gruppo della comunità](https://chat.whatsapp.com/JI7cDQ1GyaiDHhVBpLxf8b?mode=gi_t)
- **WhatsApp**: [Gruppo della comunità](https://chat.whatsapp.com/JI7cDQ1GyaiDHhVBpLxf8b?mode=gi_t)
- **Progetto Originale**: [9router di decolua](https://github.com/decolua/9router)
---
## 🔄 Come Funziona
```
@@ -157,6 +199,497 @@ Risultato: Non smettere mai di programmare, costo minimo
---
## 🎯 Cosa risolve OmniRoute: 30 punti critici reali e casi d'uso
> **Ogni sviluppatore che utilizza strumenti di intelligenza artificiale affronta questi problemi quotidianamente.** OmniRoute è stato creato per risolverli tutti: dai superamenti dei costi ai blocchi regionali, dai flussi OAuth interrotti alle operazioni di protocollo e all'osservabilità aziendale.
<details>
<summary><b>💸 1. "Pago un abbonamento costoso ma vengo comunque interrotto dai limiti"</b></summary>
Gli sviluppatori pagano $ 20-200 al mese per Claude Pro, Codex Pro o GitHub Copilot. Anche pagando, la quota ha un tetto: 5 ore di utilizzo, limiti settimanali o limiti di tariffa al minuto. A metà sessione di codifica, il provider smette di rispondere e lo sviluppatore perde flusso e produttività.
**Come OmniRoute risolve il problema:**
- **Fallback intelligente a 4 livelli**: se la quota dell'abbonamento si esaurisce, reindirizza automaticamente alla chiave API → Economico → Gratuito senza alcun intervento manuale
- **Monitoraggio delle quote in tempo reale**: mostra il consumo di token in tempo reale con il conto alla rovescia ripristinato (5 ore, giornaliero, settimanale)
- **Supporto multi-account**: più account per fornitore con round robin automatico: quando uno si esaurisce, passa a quello successivo
- **Combo personalizzate** — Catene di fallback personalizzabili con 6 strategie di bilanciamento (fill-first, round-robin, P2C, casuale, meno utilizzato, ottimizzato in termini di costi)
- **Quote aziendali Codex**: monitoraggio delle quote dello spazio di lavoro aziendale/team direttamente nella dashboard
</details>
<details>
<summary><b>🔌 2. "Devo utilizzare più provider ma ognuno ha un'API diversa"</b></summary>
OpenAI utilizza un formato, Claude (Anthropic) ne utilizza un altro, Gemini ancora un altro. Se uno sviluppatore desidera testare modelli di fornitori diversi o eseguire il fallback tra di loro, deve riconfigurare gli SDK, modificare gli endpoint e gestire formati incompatibili. I provider personalizzati (FriendLI, NIM) hanno endpoint del modello non standard.
**Come OmniRoute risolve il problema:**
- **Endpoint unificato**: un singolo `http://localhost:20128/v1` funge da proxy per tutti gli oltre 36 provider
- **Traduzione del formato** — Automatica e trasparente: OpenAI ↔ Claude ↔ Gemini ↔ API di risposta
- **Sanitizzazione della risposta**: rimuove i campi non standard (`x_groq`, `usage_breakdown`, `service_tier`) che interrompono OpenAI SDK v1.83+
- **Normalizzazione del ruolo**: converte `developer``system` per provider non OpenAI; `system``user` per GLM/ERNIE
- **Think Tag Extraction** — Estrae i blocchi `<think>` da modelli come DeepSeek R1 in `reasoning_content` standardizzati
- **Uscita strutturata per Gemini** — `json_schema``responseMimeType`/`responseSchema` conversione automatica
- **`stream` per impostazione predefinita è `false`** — Si allinea con le specifiche OpenAI, evitando SSE imprevisti negli SDK Python/Rust/Go
</details>
<details>
<summary><b>🌐 3. "Il mio fornitore di intelligenza artificiale blocca la mia regione/paese"</b></summary>
Provider come OpenAI/Codex bloccano l'accesso da determinate regioni geografiche. Gli utenti ricevono errori come `unsupported_country_region_territory` durante le connessioni OAuth e API. Ciò è particolarmente frustrante per gli sviluppatori dei paesi in via di sviluppo.
**Come OmniRoute risolve il problema:**
- **Configurazione proxy a 3 livelli**: proxy configurabile a 3 livelli: globale (tutto il traffico), per provider (un solo provider) e per connessione/chiave
- **Badge proxy con codice colore** — Indicatori visivi: 🟢 proxy globale, 🟡 proxy provider, 🔵 proxy di connessione, che mostra sempre l'IP
- **Scambio di token OAuth tramite proxy**: anche il flusso OAuth passa attraverso il proxy, risolvendo `unsupported_country_region_territory`
- **Test di connessione tramite proxy**: i test di connessione utilizzano il proxy configurato (non più bypass diretto)
- **Supporto SOCKS5**: supporto completo del proxy SOCKS5 per il routing in uscita
- **Spoofing dell'impronta digitale TLS**: impronta digitale TLS simile a un browser tramite `wreq-js` per bypassare il rilevamento dei bot
</details>
<details>
<summary><b>🆓 4. "Voglio usare l'intelligenza artificiale per programmare ma non ho soldi"</b></summary>
Non tutti possono pagare $ 20-200 al mese per gli abbonamenti AI. Studenti, sviluppatori provenienti da paesi emergenti, hobbisti e liberi professionisti hanno bisogno di accedere a modelli di qualità a costo zero.
**Come OmniRoute risolve il problema:**
- **Fornitori del livello gratuito integrati**: supporto nativo per fornitori gratuiti al 100%: iFlow (8 modelli illimitati), Qwen (3 modelli illimitati), Kiro (Claude gratis), Gemini CLI (180.000/mese gratuiti)
- **Combo solo gratuiti** — Catena `gc/gemini-3-flash → if/kimi-k2-thinking → qw/qwen3-coder-plus` = $ 0/mese senza tempi di inattività
- **Crediti gratuiti NVIDIA NIM**: 1000 crediti gratuiti integrati
- **Strategia di ottimizzazione dei costi**: strategia di routing che sceglie automaticamente il fornitore più economico disponibile
</details>
<details>
<summary><b>🔒 5. "Devo proteggere il mio gateway AI da accessi non autorizzati"</b></summary>
Quando si espone un gateway AI alla rete (LAN, VPS, Docker), chiunque abbia l'indirizzo può consumare i token/la quota dello sviluppatore. Senza protezione, le API sono vulnerabili ad usi impropri, tempestive iniezioni e abusi.
**Come OmniRoute risolve il problema:**
- **Gestione delle chiavi API**: generazione, rotazione e ambito per provider con una pagina `/dashboard/api-manager` dedicata
- **Autorizzazioni a livello di modello**: limita le chiavi API a modelli specifici (`openai/*`, modelli con caratteri jolly), con l'interruttore Consenti tutto/Limita
- **API Endpoint Protection**: richiede una chiave per `/v1/models` e blocca provider specifici dall'elenco
- **Auth Guard + Protezione CSRF**: tutti i percorsi del dashboard protetti con middleware `withAuth` + token CSRF
- **Rate Limiter**: limitazione della velocità per IP con finestre configurabili
- **Filtro IP**: lista consentita/lista bloccata per il controllo degli accessi
- **Prompt Injection Guard**: sanificazione contro modelli di prompt dannosi
- **Crittografia AES-256-GCM**: credenziali crittografate a riposo
</details>
<details>
<summary><b>🛑 6. "Il mio provider è andato in tilt e ho perso il flusso di codifica"</b></summary>
I fornitori di intelligenza artificiale possono diventare instabili, restituire errori 5xx o raggiungere limiti di velocità temporanei. Se uno sviluppatore dipende da un singolo fornitore, viene interrotto. Senza interruttori automatici, tentativi ripetuti possono bloccare l'applicazione.
**Come OmniRoute risolve il problema:**
- **Interruttore automatico per provider**: apertura/chiusura automatica con soglie e raffreddamento configurabili (chiuso/aperto/semiaperto)
- **Backoff esponenziale**: ritardi progressivi tra i tentativi
- **Anti-Thundering Herd** — Mutex + protezione semaforo contro tempeste di tentativi simultanei
- **Catene di fallback combinate**: se il fornitore primario fallisce, cade automaticamente nella catena senza alcun intervento
- **Combo Circuit Breaker**: disabilita automaticamente i provider in errore all'interno di una catena combinata
- **Dashboard integrità**: monitoraggio del tempo di attività, stati degli interruttori automatici, blocchi, statistiche della cache, latenza p50/p95/p99
</details>
<details>
<summary><b>🔧 7. "Configurare ogni strumento AI è noioso e ripetitivo"</b></summary>
Gli sviluppatori utilizzano Cursor, Claude Code, Codex CLI, OpenClaw, Gemini CLI, Kilo Code... Ogni strumento necessita di una configurazione diversa (endpoint API, chiave, modello). La riconfigurazione quando si cambia fornitore o modello è una perdita di tempo.
**Come OmniRoute risolve il problema:**
- **Dashboard degli strumenti CLI**: pagina dedicata con configurazione con un clic per Claude Code, Codex CLI, OpenClaw, Kilo Code, Antigravity, Cline
- **GitHub Copilot Config Generator**: genera `chatLanguageModels.json` per VS Code con selezione di modelli in blocco
- **Procedura guidata di onboarding**: configurazione guidata in 4 passaggi per gli utenti alle prime armi
- **Un endpoint, tutti i modelli**: configura `http://localhost:20128/v1` una volta, accedi a oltre 36 provider
</details>
<details>
<summary><b>🔑 8. "Gestire token OAuth da più provider è un inferno"</b></summary>
Claude Code, Codex, Gemini CLI, Copilot: utilizzano tutti OAuth 2.0 con token in scadenza. Gli sviluppatori devono autenticarsi nuovamente costantemente, gestire `client_secret is missing`, `redirect_uri_mismatch` e errori sui server remoti. OAuth su LAN/VPS è particolarmente problematico.
**Come OmniRoute risolve il problema:**
- **Aggiornamento automatico dei token**: i token OAuth si aggiornano in background prima della scadenza
- **OAuth 2.0 (PKCE) integrato**: flusso automatico per Claude Code, Codex, Gemini CLI, Copilot, Kiro, Qwen, iFlow
- **OAuth multi-account**: account multipli per provider tramite estrazione di token JWT/ID
- **OAuth LAN/Correzione remota**: rilevamento IP privato per `redirect_uri` + modalità URL manuale per server remoti
- **OAuth Behind Nginx**: utilizza `window.location.origin` per la compatibilità con proxy inverso
- **Guida OAuth remota**: guida passo passo per le credenziali Google Cloud su VPS/Docker
</details>
<details>
<summary><b>📊 9. "Non so quanto sto spendendo né dove"</b></summary>
Gli sviluppatori utilizzano più fornitori a pagamento ma non hanno una visione unificata della spesa. Ogni fornitore ha il proprio dashboard di fatturazione, ma non esiste una visualizzazione consolidata. I costi imprevisti possono accumularsi.
**Come OmniRoute risolve il problema:**
- **Dashboard di analisi dei costi**: monitoraggio dei costi per token e gestione del budget per fornitore
- **Limiti di budget per livello**: massimale di spesa per livello che attiva il fallback automatico
- **Configurazione dei prezzi per modello**: prezzi configurabili per modello
- **Statistiche di utilizzo per chiave API**: conteggio delle richieste e timestamp dell'ultimo utilizzo per chiave
- **Dashboard di analisi**: schede statistiche, grafico di utilizzo del modello, tabella dei fornitori con percentuali di successo e latenza
</details>
<details>
<summary><b>🐛 10. "Non riesco a diagnosticare errori e problemi nelle chiamate AI"</b></summary>
Quando una chiamata fallisce, lo sviluppatore non sa se si trattava di un limite di velocità, di un token scaduto, di un formato errato o di un errore del provider. Registri frammentati su diversi terminali. Senza osservabilità, il debug è un processo per tentativi ed errori.
**Come OmniRoute risolve il problema:**
- **Dashboard dei registri unificati**: 4 schede: registri delle richieste, registri del proxy, registri di controllo, console
- **Visualizzatore log della console**: visualizzatore in stile terminale in tempo reale con livelli codificati a colori, scorrimento automatico, ricerca, filtro
- **Registri proxy SQLite**: registri persistenti che sopravvivono ai riavvii del server
- **Translator Playground** — 4 modalità di debug: Playground (traduzione del formato), Chat Tester (andata e ritorno), Test Bench (batch), Live Monitor (in tempo reale)
- **Telemetria richiesta**: latenza p50/p95/p99 + traccia X-Request-Id
- **Registrazione basata su file con rotazione**: l'interceptor della console acquisisce tutto nel registro JSON con rotazione basata sulle dimensioni
</details>
<details>
<summary><b>🏗️ 11. "L'implementazione e la manutenzione del gateway sono complesse"</b></summary>
L'installazione, la configurazione e la manutenzione di un proxy AI in diversi ambienti (locale, VPS, Docker, cloud) richiedono molto lavoro. Problemi come percorsi codificati, `EACCES` nelle directory, conflitti di porte e build multipiattaforma aggiungono attrito.
**Come OmniRoute risolve il problema:**
- **Installazione globale npm** — `npm install -g omniroute && omniroute` — completata
- **Docker multipiattaforma** — AMD64 + ARM64 nativo (Apple Silicon, AWS Graviton, Raspberry Pi)
- **Docker Compose Profiles** — `base` (senza strumenti CLI) e `cli` (con Claude Code, Codex, OpenClaw)
- **App desktop Electron**: app nativa per Windows/macOS/Linux con barra delle applicazioni, avvio automatico, modalità offline
- **Modalità porta divisa**: API e dashboard su porte separate per scenari avanzati (proxy inverso, rete di contenitori)
- **Cloud Sync**: configura la sincronizzazione tra dispositivi tramite Cloudflare Workers
- **Backup DB**: backup, ripristino, esportazione e importazione automatici di tutte le impostazioni
</details>
<details>
<summary><b>🌍 12. "L'interfaccia è solo inglese e il mio team non parla inglese"</b></summary>
I team nei paesi non anglofoni, soprattutto in America Latina, Asia ed Europa, hanno difficoltà con le interfacce solo in inglese. Le barriere linguistiche riducono l'adozione e aumentano gli errori di configurazione.
**Come OmniRoute risolve il problema:**
- **Dashboard i18n — 30 lingue** — Tutti gli oltre 500 tasti tradotti tra cui arabo, bulgaro, danese, tedesco, spagnolo, finlandese, francese, ebraico, hindi, ungherese, indonesiano, italiano, giapponese, coreano, malese, olandese, norvegese, polacco, portoghese (PT/BR), rumeno, russo, slovacco, svedese, tailandese, ucraino, vietnamita, cinese, filippino, inglese
- **Supporto RTL**: supporto da destra a sinistra per arabo ed ebraico
- **README multilingue**: 30 traduzioni complete di documentazione
- **Selettore lingua**: icona del globo nell'intestazione per la commutazione in tempo reale
</details>
<details>
<summary><b>🔄 13. "Ho bisogno di qualcosa di più della semplice chat: ho bisogno di incorporamenti, immagini, audio"</b></summary>
L'intelligenza artificiale non è solo il completamento della chat. Gli sviluppatori devono generare immagini, trascrivere audio, creare incorporamenti per RAG, riclassificare i documenti e moderare i contenuti. Ogni API ha un endpoint e un formato diversi.
**Come OmniRoute risolve il problema:**
- **Incorporamenti** — `/v1/embeddings` con 6 fornitori e oltre 9 modelli
- **Generazione di immagini** — `/v1/images/generations` con 10 provider e oltre 20 modelli (OpenAI, xAI, Together, Fireworks, Nebius, Hyperbolic, NanoBanana, Antigravity, SD WebUI, ComfyUI)
- **Da testo a video** — `/v1/videos/generations` — ComfyUI (AnimateDiff, SVD) e SD WebUI
- **Trasformazione testo in musica** — `/v1/music/generations` — ComfyUI (Stable Audio Open, MusicGen)
- **Trascrizione audio** — `/v1/audio/transcriptions` — Whisper + Nvidia NIM, HuggingFace, Qwen3
- **Sintesi vocale** — `/v1/audio/speech` — ElevenLabs, Nvidia NIM, HuggingFace, Coqui, Tortoise, Qwen3, + fornitori esistenti
- **Moderazioni** — `/v1/moderations` — Controlli di sicurezza dei contenuti
- **Riclassificazione** — `/v1/rerank`: riclassificazione della pertinenza del documento
- **API di risposta**: supporto `/v1/responses` completo per Codex
</details>
<details>
<summary><b>🧪 14. "Non ho modo di testare e confrontare la qualità tra i modelli"</b></summary>
Gli sviluppatori vogliono sapere quale modello è il migliore per il loro caso d'uso (codice, traduzione, ragionamento), ma il confronto manuale è lento. Non esistono strumenti di valutazione integrati.
**Come OmniRoute risolve il problema:**
- **Valutazioni LLM**: test Golden Set con 10 casi precaricati che coprono saluti, matematica, geografia, generazione di codice, conformità JSON, traduzione, ribasso, rifiuto di sicurezza
- **4 strategie di corrispondenza** — `exact`, `contains`, `regex`, `custom` (funzione JS)
- **Translator Playground Test Bench**: test in batch con input multipli e output previsti, confronto tra provider
- **Chat Tester**: andata e ritorno completo con rendering della risposta visiva
- **Live Monitor**: flusso in tempo reale di tutte le richieste che passano attraverso il proxy
</details>
<details>
<summary><b>📈 15. "Ho bisogno di scalare senza perdere prestazioni"</b></summary>
Man mano che il volume delle richieste cresce, senza la memorizzazione nella cache le stesse domande generano costi duplicati. Senza idempotenza, le richieste duplicate sprecano elaborazione. I limiti tariffari per fornitore devono essere rispettati.
**Come OmniRoute risolve il problema:**
- **Cache semantica**: la cache a due livelli (firma + semantica) riduce costi e latenza
- **Idempotenza richiesta**: finestra di deduplicazione di 5 secondi per richieste identiche
- **Rilevamento del limite di velocità**: RPM per provider, gap minimo e monitoraggio simultaneo massimo
- **Limiti di velocità modificabili**: impostazioni predefinite configurabili in Impostazioni → Resilienza con persistenza
- **Cache di convalida della chiave API**: cache a 3 livelli per prestazioni di produzione
- **Dashboard integrità con telemetria**: latenza p50/p95/p99, statistiche cache, tempo di attività
</details>
<details>
<summary><b>🤖 16. "Voglio controllare il comportamento del modello a livello globale"</b></summary>
Sviluppatori che desiderano tutte le risposte in una lingua specifica, con un tono specifico o che desiderano limitare i token di ragionamento. Configurarlo in ogni strumento/richiesta non è pratico.
**Come OmniRoute risolve il problema:**
- **Inserimento prompt di sistema**: prompt globale applicato a tutte le richieste
- **Thinking Budget Validation**: controllo dell'allocazione dei token tramite ragionamento per richiesta (passthrough, automatico, personalizzato, adattivo)
- **6 Strategie di routing**: strategie globali che determinano la modalità di distribuzione delle richieste
- **Wildcard Router**: i modelli `provider/*` instradano dinamicamente a qualsiasi provider
- **Abilita/Disabilita combo**: attiva/disattiva le combo direttamente dalla dashboard
- **Attiva/disattiva provider**: attiva/disattiva tutte le connessioni per un provider con un clic
- **Fornitori bloccati**: esclude fornitori specifici dall'elenco `/v1/models`
</details>
<details>
<summary><b>🧰 17. "Ho bisogno degli strumenti MCP come funzionalità di prodotto di prima classe"</b></summary>
Molti gateway AI espongono MCP solo come dettaglio di implementazione nascosto. I team hanno bisogno di un livello operativo visibile e gestibile.
**Come OmniRoute risolve il problema:**
- MCP viene visualizzato nella navigazione del dashboard e nella scheda del protocollo dell'endpoint
- Pagina di gestione MCP dedicata con processo, strumenti, ambiti e audit
- Avvio rapido integrato per `omniroute --mcp` e onboarding del client
</details>
<details>
<summary><b>🧠 18. "Ho bisogno dell'orchestrazione A2A con percorsi di attività di sincronizzazione + streaming"</b></summary>
I flussi di lavoro degli agenti necessitano sia di risposte dirette che di esecuzione in streaming di lunga durata con controllo del ciclo di vita.
**Come OmniRoute risolve il problema:**
- Endpoint A2A JSON-RPC (`POST /a2a`) con `message/send` e `message/stream`
- Streaming SSE con propagazione dello stato terminale
- API del ciclo di vita delle attività per `tasks/get` e `tasks/cancel`
</details>
<details>
<summary><b>🛰️ 19. "Ho bisogno dello stato reale del processo MCP, non di uno stato indovinato"</b></summary>
I team operativi devono sapere se MCP è effettivamente attivo, non solo se un'API è raggiungibile.
**Come OmniRoute risolve il problema:**
- File heartbeat di runtime con PID, timestamp, trasporto, conteggio strumenti e modalità ambito
- API di stato MCP che combina battito cardiaco + attività recente
- Schede di stato dell'interfaccia utente per l'aggiornamento di processo/tempo di attività/battito cardiaco
</details>
<details>
<summary><b>📋 20. "Ho bisogno dell'esecuzione verificabile dello strumento MCP"</b></summary>
Quando gli strumenti modificano la configurazione o attivano azioni operative, i team necessitano di tracciabilità forense.
**Come OmniRoute risolve il problema:**
- Registrazione di controllo supportata da SQLite per le chiamate allo strumento MCP
- Filtri per strumento, successo/fallimento, chiave API e impaginazione
- Tabella di controllo della dashboard + endpoint statistici per l'automazione
</details>
<details>
<summary><b>🔐 21. "Ho bisogno di autorizzazioni MCP con ambito per integrazione"</b></summary>
Client diversi dovrebbero avere accesso con privilegi minimi alle categorie di strumenti.
**Come OmniRoute risolve il problema:**
- 9 ambiti MCP granulari per l'accesso controllato agli strumenti
- Applicazione dell'ambito e visibilità nell'interfaccia utente di gestione MCP
- Postura predefinita sicura per gli strumenti operativi
</details>
<details>
<summary><b>⚙️ 22. "Ho bisogno di controlli operativi senza ridistribuirmi"</b></summary>
I team necessitano di rapidi cambiamenti di runtime durante incidenti o eventi di costo.
**Come OmniRoute risolve il problema:**
- Cambia l'attivazione combinata direttamente dalla dashboard MCP
- Applicare profili di resilienza da pacchetti di policy predefiniti
- Ripristinare lo stato dell'interruttore dallo stesso pannello operativo
</details>
<details>
<summary><b>🔄 23. "Ho bisogno di visibilità e cancellazione del ciclo di vita delle attività A2A in tempo reale"</b></summary>
Senza visibilità del ciclo di vita, gli incidenti relativi alle attività diventano difficili da valutare.
**Come OmniRoute risolve il problema:**
- Elenco/filtro delle attività per stato/competenza con impaginazione
- Esamina i metadati, gli eventi e gli artefatti delle attività
- Endpoint di annullamento dell'attività e azione dell'interfaccia utente con conferma
</details>
<details>
<summary><b>🌊 24. "Ho bisogno di metriche di flusso attive per il carico A2A"</b></summary>
I flussi di lavoro in streaming richiedono informazioni operative sulla concorrenza e sulle connessioni live.
**Come OmniRoute risolve il problema:**
- Contatori di flussi attivi integrati nello stato A2A
- Timestamp dell'ultima attività e conteggi per stato
- Schede dashboard A2A per il monitoraggio delle operazioni in tempo reale
</details>
<details>
<summary><b>🪪 25. "Ho bisogno del rilevamento degli agenti standard per i clienti"</b></summary>
I client e gli agenti di orchestrazione esterni necessitano di metadati leggibili dal computer per l'onboarding.
**Come OmniRoute risolve il problema:**
- Carta Agente esposta a `/.well-known/agent.json`
- Capacità e competenze mostrate nell'interfaccia utente di gestione
- L'API di stato A2A include metadati di rilevamento per l'automazione
</details>
<details>
<summary><b>🧭 26. "Ho bisogno della rilevabilità del protocollo nella UX del prodotto"</b></summary>
Se gli utenti non riescono a scoprire le superfici del protocollo, l'adozione e la qualità del supporto diminuiscono.
**Come OmniRoute risolve il problema:**
- Voci della barra laterale per MCP e A2A
- Scheda Protocolli della pagina Endpoint con avvio rapido e stato
- Collegamenti dalla panoramica alle dashboard di gestione dedicate
</details>
<details>
<summary><b>🧪 27. "Ho bisogno della convalida del protocollo end-to-end con clienti reali"</b></summary>
I test simulati non sono sufficienti per verificare la compatibilità del protocollo prima del rilascio.
**Come OmniRoute risolve il problema:**
- Suite E2E che avvia l'app e utilizza il trasporto client SDK MCP reale
- Test client A2A per i flussi di rilevamento, invio, streaming, acquisizione e annullamento
- Effettuare un controllo incrociato delle asserzioni con l'audit MCP e le API delle attività A2A
</details>
<details>
<summary><b>📡 28. "Ho bisogno di osservabilità unificata su tutte le interfacce"</b></summary>
Suddividere l'osservabilità per protocollo crea punti ciechi e un MTTR più lungo.
**Come OmniRoute risolve il problema:**
- Dashboard/registri/analisi unificati in un unico prodotto
- Salute + audit + richiesta di telemetria su livelli OpenAI, MCP e A2A
- API operative per stato e automazione
</details>
<details>
<summary><b>💼 29. "Ho bisogno di un runtime per proxy + strumenti + orchestrazione agente"</b></summary>
L'esecuzione di numerosi servizi separati aumenta i costi operativi e le modalità di guasto.
**Come OmniRoute risolve il problema:**
- Proxy compatibile con OpenAI, server MCP e server A2A in uno stack
- Autenticazione condivisa, resilienza, archivio dati e osservabilità
- Modello politico coerente su tutte le superfici di interazione
</details>
<details>
<summary><b>🚀 30. "Ho bisogno di spedire flussi di lavoro di agenti senza la proliferazione del codice adesivo"</b></summary>
I team perdono velocità quando uniscono più servizi e script ad hoc.
**Come OmniRoute risolve il problema:**
- Strategia endpoint unificata per clienti e agenti
- Interfacce utente di gestione del protocollo integrate e percorsi di convalida del fumo
- Fondamenti pronti per la produzione (sicurezza, registrazione, resilienza, backup)
</details>
### Playbook di esempio (casi d'uso integrati)
**Playbook A: massimizza l'abbonamento a pagamento + backup economico**
```txt
Combo: "maximize-claude"
1. cc/claude-opus-4-6
2. glm/glm-4.7
3. if/kimi-k2-thinking
Monthly cost: $20 + small backup spend
Outcome: higher quality, near-zero interruption
```
**Playbook B: stack di codifica a costo zero**
```txt
Combo: "free-forever"
1. gc/gemini-3-flash
2. if/kimi-k2-thinking
3. qw/qwen3-coder-plus
Monthly cost: $0
Outcome: stable free coding workflow
```
**Playbook C: catena di fallback sempre attiva 24 ore su 24, 7 giorni su 7**
```txt
Combo: "always-on"
1. cc/claude-opus-4-6
2. cx/gpt-5.2-codex
3. glm/glm-4.7
4. minimax/MiniMax-M2.1
5. if/kimi-k2-thinking
Outcome: deep fallback depth for deadline-critical workloads
```
**Playbook D: operazioni dell'agente con MCP + A2A**
```txt
1) Start MCP transport (`omniroute --mcp`) for tool-driven operations
2) Run A2A tasks via `message/send` and `message/stream`
3) Observe via /dashboard/mcp and /dashboard/a2a
4) Control incidents with resilience profile + task cancellation
```
---
## ⚡ Avvio Rapido
**1. Installa globalmente:**
@@ -249,7 +782,7 @@ docker compose --profile cli up -d
---
## 🖥️ Desktop App — Offline & Always-On
## 🖥️
> 🆕 **NEW!** OmniRoute is now available as a **native desktop application** for Windows, macOS, and Linux.
@@ -296,67 +829,6 @@ npm run electron:build:linux # Linux (.AppImage)
---
## 🎯 Casi d'Uso
### Caso 1: "Ho un abbonamento Claude Pro"
**Problema:** La quota scade inutilizzata, limiti di rate durante la programmazione intensa
```
Combo: "maximize-claude"
1. cc/claude-opus-4-6 (usa l'abbonamento al massimo)
2. glm/glm-4.7 (backup economico quando la quota è esaurita)
3. if/kimi-k2-thinking (fallback d'emergenza gratuito)
Costo mensile: $20 (abbonamento) + ~$5 (backup) = $25 totale
vs. $20 + sbattere contro i limiti = frustrazione
```
### Caso 2: "Voglio costo zero"
**Problema:** Non può permettersi abbonamenti, ha bisogno di IA affidabile per programmare
```
Combo: "free-forever"
1. gc/gemini-3-flash (180K gratis/mese)
2. if/kimi-k2-thinking (illimitato gratis)
3. qw/qwen3-coder-plus (illimitato gratis)
Costo mensile: $0
Qualità: Modelli pronti per la produzione
```
### Caso 3: "Devo programmare 24/7, senza interruzioni"
**Problema:** Scadenze strette, non può permettersi downtime
```
Combo: "always-on"
1. cc/claude-opus-4-6 (migliore qualità)
2. cx/gpt-5.2-codex (secondo abbonamento)
3. glm/glm-4.7 (economico, reset giornaliero)
4. minimax/MiniMax-M2.1 (più economico, reset 5h)
5. if/kimi-k2-thinking (gratuito illimitato)
Risultato: 5 livelli di fallback = zero downtime
```
### Caso 4: "Voglio IA GRATUITA in OpenClaw"
**Problema:** Ha bisogno di assistente IA nelle app di messaggistica, completamente gratuito
```
Combo: "openclaw-free"
1. if/glm-4.7 (illimitato gratis)
2. if/minimax-m2.1 (illimitato gratis)
3. if/kimi-k2-thinking (illimitato gratis)
Costo mensile: $0
Accesso via: WhatsApp, Telegram, Slack, Discord, iMessage, Signal...
```
---
## 💡 Funzionalità Principali
### 🧠 Routing & Intelligenza
@@ -372,6 +844,8 @@ Accesso via: WhatsApp, Telegram, Slack, Discord, iMessage, Signal...
| 🧩 **Modelli personalizzati** | Aggiungi qualsiasi ID modello a qualsiasi provider |
| 🌐 **Router wildcard** | Instrada pattern `provider/*` verso qualsiasi provider dinamicamente |
| 🧠 **Budget di ragionamento** | Modalità passthrough, auto, custom e adaptive per modelli di ragionamento |
| 🔀 **Model Aliases** | Auto-forward deprecated model IDs to current replacements (built-in + custom) |
| ⚡ **Background Degradation** | Auto-route background tasks (titles, summaries) to cheaper models |
| 💬 **Iniezione System Prompt** | System prompt globale applicato a tutte le richieste |
| 📄 **API Responses** | Supporto completo per OpenAI Responses API (`/v1/responses`) per Codex |
@@ -388,15 +862,18 @@ Accesso via: WhatsApp, Telegram, Slack, Discord, iMessage, Signal...
### 🛡️ Resilienza & Sicurezza
| Funzionalità | Cosa Fa |
| ------------------------------- | -------------------------------------------------------------- |
| 🔌 **Circuit Breaker** | Apertura/chiusura auto per provider con soglie configurabili |
| 🛡️ **Anti-Thundering Herd** | Mutex + semaforo rate-limit per provider con API key |
| 🧠 **Cache semantica** | Cache a due livelli (firma + semantica) riduce costi e latenza |
| **Idempotenza richieste** | Finestra dedup 5s per richieste duplicate |
| 🔒 **Spoofing TLS Fingerprint** | Bypass rilevamento bot tramite wreq-js |
| 🌐 **Filtro IP** | Allowlist/blocklist per controllo accesso API |
| 📊 **Rate limit modificabili** | RPM, gap minimo e concorrenza massima configurabili |
| Funzionalità | Cosa Fa |
| ------------------------------- | ---------------------------------------------------------------------------- |
| 🔌 **Circuit Breaker** | Apertura/chiusura auto per provider con soglie configurabili |
| 🎯 **Endpoint-Aware Models** | Custom models declare supported endpoints + API format |
| 🛡️ **Anti-Thundering Herd** | Mutex + semaforo rate-limit per provider con API key |
| 🧠 **Cache semantica** | Cache a due livelli (firma + semantica) riduce costi e latenza |
| **Idempotenza richieste** | Finestra dedup 5s per richieste duplicate |
| 🔒 **Spoofing TLS Fingerprint** | Bypass rilevamento bot tramite wreq-js |
| 🌐 **Filtro IP** | Allowlist/blocklist per controllo accesso API |
| 📊 **Rate limit modificabili** | RPM, gap minimo e concorrenza massima configurabili |
| 💾 **Rate Limit Persistence** | Learned limits survive restarts via SQLite with 60s debounce + 24h staleness |
| 🔄 **Token Refresh Resilience** | Per-provider circuit breaker (5 fails→30min) + 30s timeout per attempt |
### 📊 Osservabilità & Analytics
@@ -496,6 +973,27 @@ Traduzione trasparente tra formati:
</details>
## 🧪 Valutazioni (Evals)
OmniRoute include un framework di valutazione integrato per testare la qualità delle risposte LLM contro un golden set. Accesso via **Analytics → Evals** nella dashboard.
### Set integrato
Il "OmniRoute Golden Set" precaricato contiene 10 casi di test:
- Saluti, matematica, geografia, generazione codice
- Conformità formato JSON, traduzione, markdown
- Rifiuto sicurezza (contenuto nocivo), conteggio, logica booleana
### Strategie di valutazione
| Strategia | Descrizione | Esempio |
| ---------- | ---------------------------------------------------------- | -------------------------------- |
| `exact` | L'output deve corrispondere esattamente | `"4"` |
| `contains` | L'output deve contenere la sottostringa (case-insensitive) | `"Paris"` |
| `regex` | L'output deve corrispondere al pattern regex | `"1.*2.*3"` |
| `custom` | Funzione JS personalizzata restituisce true/false | `(output) => output.length > 10` |
---
## 📖 Guida alla Configurazione
@@ -778,97 +1276,6 @@ Impostazioni → Configurazione API:
---
## 📊 Modelli Disponibili
<details>
<summary><b>Vedi tutti i modelli disponibili</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/`)** - GRATUITO:
- `gc/gemini-3-flash-preview`
- `gc/gemini-2.5-pro`
**GitHub Copilot (`gh/`)**:
- `gh/gpt-5`
- `gh/claude-4.5-sonnet`
**NVIDIA NIM (`nvidia/`)** - Crediti GRATUITI:
- `nvidia/llama-3.3-70b-instruct`
- `nvidia/mistral-7b-instruct`
- 50+ modelli su [build.nvidia.com](https://build.nvidia.com)
**GLM (`glm/`)** - $0.6/1M:
- `glm/glm-4.7`
**MiniMax (`minimax/`)** - $0.2/1M:
- `minimax/MiniMax-M2.1`
**iFlow (`if/`)** - GRATUITO:
- `if/kimi-k2-thinking`
- `if/qwen3-coder-plus`
- `if/deepseek-r1`
- `if/glm-4.7`
- `if/minimax-m2`
**Qwen (`qw/`)** - GRATUITO:
- `qw/qwen3-coder-plus`
- `qw/qwen3-coder-flash`
**Kiro (`kr/`)** - GRATUITO:
- `kr/claude-sonnet-4.5`
- `kr/claude-haiku-4.5`
**OpenRouter (`or/`)** - 100+ modelli:
- `or/anthropic/claude-4-sonnet`
- `or/google/gemini-2.5-pro`
- Qualsiasi modello da [openrouter.ai/models](https://openrouter.ai/models)
</details>
---
## 🧪 Valutazioni (Evals)
OmniRoute include un framework di valutazione integrato per testare la qualità delle risposte LLM contro un golden set. Accesso via **Analytics → Evals** nella dashboard.
### Golden Set integrato
Il "OmniRoute Golden Set" precaricato contiene 10 casi di test:
- Saluti, matematica, geografia, generazione codice
- Conformità formato JSON, traduzione, markdown
- Rifiuto sicurezza (contenuto nocivo), conteggio, logica booleana
### Strategie di valutazione
| Strategia | Descrizione | Esempio |
| ---------- | ---------------------------------------------------------- | -------------------------------- |
| `exact` | L'output deve corrispondere esattamente | `"4"` |
| `contains` | L'output deve contenere la sottostringa (case-insensitive) | `"Paris"` |
| `regex` | L'output deve corrispondere al pattern regex | `"1.*2.*3"` |
| `custom` | Funzione JS personalizzata restituisce true/false | `(output) => output.length > 10` |
---
## 🐛 Risoluzione Problemi
<details>
@@ -924,7 +1331,7 @@ Il "OmniRoute Golden Set" precaricato contiene 10 casi di test:
---
## 🛠️ Stack Tecnologico
## 🛠️
- **Runtime**: Node.js 20+
- **Linguaggio**: TypeScript 5.9 — **100% TypeScript** in `src/` e `open-sse/` (v1.0.6)
@@ -955,18 +1362,7 @@ Il "OmniRoute Golden Set" precaricato contiene 10 casi di test:
---
## 📧 Supporto
> 💬 **Unisciti alla nostra community!** [Gruppo WhatsApp](https://chat.whatsapp.com/JI7cDQ1GyaiDHhVBpLxf8b?mode=gi_t) — Ottieni aiuto, condividi consigli e rimani aggiornato.
- **Sito Web**: [omniroute.online](https://omniroute.online)
- **GitHub**: [github.com/diegosouzapw/OmniRoute](https://github.com/diegosouzapw/OmniRoute)
- **Issues**: [github.com/diegosouzapw/OmniRoute/issues](https://github.com/diegosouzapw/OmniRoute/issues)
- **WhatsApp**: [Gruppo della comunità](https://chat.whatsapp.com/JI7cDQ1GyaiDHhVBpLxf8b?mode=gi_t)
- **WhatsApp**: [Gruppo della comunità](https://chat.whatsapp.com/JI7cDQ1GyaiDHhVBpLxf8b?mode=gi_t)
- **Progetto Originale**: [9router di decolua](https://github.com/decolua/9router)
---
## 🗺️
## 👥 Contributori

View File

@@ -110,6 +110,35 @@ _AI を活用した IDE または CLI ツールを、無制限のコーディン
---
## 🖼️
<div align="center">
<img src="./docs/screenshots/MainOmniRoute.png" alt="OmniRoute" width="800"/>
</div>
---
## 📸
<details>
<summary><b>...</b></summary>
| # | # |
| ----- | ---------------------------------------- |
| **1** | ![1](docs/screenshots/01-providers.png) |
| **2** | ![2](docs/screenshots/02-combos.png) |
| **3** | ![3](docs/screenshots/03-analytics.png) |
| **4** | ![4](docs/screenshots/04-health.png) |
| **5** | ![5](docs/screenshots/05-translator.png) |
| **6** | ![6](docs/screenshots/06-settings.png) |
| **7** | ![7](docs/screenshots/07-cli-tools.png) |
| **8** | ![8](docs/screenshots/08-usage.png) |
| **9** | ![9](docs/screenshots/09-endpoint.png) |
</details>
---
## 🤔 なぜオムニルートなのか?
**お金の無駄遣いや限界に達するのはやめましょう:**
@@ -128,6 +157,18 @@ _AI を活用した IDE または CLI ツールを、無制限のコーディン
---
## 📧 サポート
> 💬 **コミュニティに参加してください!** [WhatsApp Group](https://chat.whatsapp.com/JI7cDQ1GyaiDHhVBpLxf8b?mode=gi_t) — ヘルプを取得し、ヒントを共有し、最新情報を入手してください。
- **ウェブサイト**: [omniroute.online](https://omniroute.online)
- **GitHub**: [github.com/diegosouzapw/OmniRoute](https://github.com/diegosouzapw/OmniRoute)
- **問題**: [github.com/diegosouzapw/OmniRoute/issues](https://github.com/diegosouzapw/OmniRoute/issues)
- **WhatsApp**: [Community Group](https://chat.whatsapp.com/JI7cDQ1GyaiDHhVBpLxf8b?mode=gi_t)
- **オリジナル プロジェクト**: [9router by decolua](https://github.com/decolua/9router)
---
## 🔄 仕組み
```
@@ -157,6 +198,498 @@ Result: Never stop coding, minimal cost
---
## 🎯 OmniRoute が解決するもの — 30 の実際の問題点とユースケース
> **AI ツールを使用するすべての開発者は、これらの問題に日々直面しています。** OmniRoute は、コスト超過から地域ブロック、壊れた OAuth フローからプロトコル操作、企業の可観測性まで、それらすべてを解決するために構築されました。
<details>
<summary><b>💸 1. 「高価なサブスクリプションの料金を支払っているのに、制限によって中断されます」</b></summary>
開発者は、Claude Pro、Codex Pro、または GitHub Copilot に月額 20 200 ドルを支払います。有料であっても、割り当てには上限があり、5 時間の使用量、週ごとの制限、または分ごとのレート制限があります。コーディング セッションの途中でプロバイダーが応答を停止し、開発者はフローと生産性を失います。
**OmniRoute がそれを解決する方法:**
- **スマート 4 層フォールバック** — サブスクリプション クォータが不足すると、手動介入なしで自動的に API キー→格安→無料にリダイレクトされます。
- **リアルタイム クォータ トラッキング** — リセット カウントダウン (5 時間、毎日、毎週) でトークンの消費量をリアルタイムで表示します。
- **マルチアカウントのサポート** — 自動ラウンドロビンによるプロバイダーごとの複数のアカウント — 1 つのアカウントがなくなると、次のアカウントに切り替わります
- **カスタム コンボ** — 6 つのバランシング戦略 (フィルファースト、ラウンドロビン、P2C、ランダム、最小使用、コスト最適化) を備えたカスタマイズ可能なフォールバック チェーン
- **Codex Business クォータ** — ビジネス/チームのワークスペース クォータをダッシュボードで直接監視
</details>
<details>
<summary><b>🔌 2. 「複数のプロバイダーを使用する必要がありますが、それぞれに異なる API があります」</b></summary>
OpenAI は 1 つの形式を使用し、Claude (Anthropic) は別の形式を使用し、Gemini はさらに別の形式を使用します。開発者が異なるプロバイダーのモデルをテストしたり、プロバイダー間でフォールバックしたりする場合は、SDK を再構成し、エンドポイントを変更し、互換性のない形式に対処する必要があります。カスタム プロバイダー (FriendLI、NIM) には、非標準モデルのエンドポイントがあります。
**OmniRoute がそれを解決する方法:**
- **統合エンドポイント** - 単一の `http://localhost:20128/v1` が 36 を超えるすべてのプロバイダーのプロキシとして機能します
- **フォーマット変換** — 自動かつ透過的: OpenAI ↔ Claude ↔ Gemini ↔ Responses API
- **レスポンスのサニタイズ** — OpenAI SDK v1.83 以降を破壊する非標準フィールド (`x_groq``usage_breakdown``service_tier`) を除去します。
- **ロールの正規化** — 非 OpenAI プロバイダーに対して `developer``system` を変換します。 GLM/ERNIE 用 `system``user`
- **Think Tag Extraction** — DeepSeek R1 などのモデルから `<think>` ブロックを標準化された `reasoning_content` に抽出します。
- **Gemini の構造化出力** — `json_schema``responseMimeType`/`responseSchema` 自動変換
- **`stream` のデフォルトは `false`** — OpenAI 仕様に準拠し、Python/Rust/Go SDK での予期しない SSE を回避します
</details>
<details>
<summary><b>🌐 3. 「AI プロバイダーが私の地域/国をブロックしています」</b></summary>
OpenAI/Codex などのプロバイダーは、特定の地理的地域からのアクセスをブロックします。 OAuth および API 接続中に、ユーザーは `unsupported_country_region_territory` のようなエラーを受け取ります。これは、発展途上国の開発者にとって特にイライラさせられます。
**OmniRoute がそれを解決する方法:**
- **3 レベルのプロキシ構成** — 3 つのレベルで構成可能なプロキシ: グローバル (すべてのトラフィック)、プロバイダーごと (1 つのプロバイダーのみ)、および接続/キーごと
- **色分けされたプロキシ バッジ** — 視覚的なインジケーター: 🟢 グローバル プロキシ、🟡 プロバイダー プロキシ、🔵 接続プロキシ、常に IP を表示
- **プロキシを介した OAuth トークン交換** — OAuth フローもプロキシを通過し、`unsupported_country_region_territory` を解決します
- **プロキシ経由の接続テスト** — 接続テストは構成されたプロキシを使用します (直接バイパスはありません)。
- **SOCKS5 サポート** — アウトバウンド ルーティングに対する SOCKS5 プロキシの完全なサポート
- **TLS フィンガープリント スプーフィング** — `wreq-js` を介したブラウザーのような TLS フィンガープリントによりボット検出をバイパスします
</details>
<details>
<summary><b>🆓 4. 「AIを使ってコーディングしたいけどお金がない」</b></summary>
誰もが AI サブスクリプションに月額 20 200 ドルを支払えるわけではありません。学生、新興国の開発者、愛好家、フリーランサーは、高品質のモデルに無料でアクセスできる必要があります。
**OmniRoute がそれを解決する方法:**
- **無料利用枠プロバイダーの組み込み** — 100% 無料プロバイダーのネイティブ サポート: iFlow (8 つの無制限のモデル)、Qwen (3 つの無制限のモデル)、Kiro (無料の Claude)、Gemini CLI (180K/月無料)
- **無料のみのコンボ** — チェーン `gc/gemini-3-flash → if/kimi-k2-thinking → qw/qwen3-coder-plus` = 月額 0 ドル、ダウンタイムなし
- **NVIDIA NIM 無料クレジット** — 1000 の無料クレジットが統合されています
- **コスト最適化戦略** — 利用可能な最も安価なプロバイダーを自動的に選択するルーティング戦略
</details>
<details>
<summary><b>🔒 5. 「AI ゲートウェイを不正アクセスから保護する必要があります」</b></summary>
AI ゲートウェイをネットワーク (LAN、VPS、Docker) に公開すると、アドレスを持っている人は誰でも開発者のトークン/クォータを消費できます。保護がなければ、API は誤用、即時挿入、悪用に対して脆弱になります。
**OmniRoute がそれを解決する方法:**
- **API キー管理** — 専用の `/dashboard/api-manager` ページを使用したプロバイダーごとの生成、ローテーション、およびスコープ設定
- **モデルレベルの権限** — すべて許可/制限の切り替えにより、API キーを特定のモデル (`openai/*`、ワイルドカード パターン) に制限します
- **API エンドポイント保護** - `/v1/models` のキーを要求し、リストから特定のプロバイダーをブロックします
- **認証ガード + CSRF 保護** — すべてのダッシュボード ルートは `withAuth` ミドルウェア + CSRF トークンで保護されています
- **レート リミッター** — 構成可能なウィンドウによる IP ごとのレート制限
- **IP フィルタリング** — アクセス制御の許可リスト/ブロックリスト
- **プロンプト インジェクション ガード** — 悪意のあるプロンプト パターンに対するサニタイズ
- **AES-256-GCM 暗号化** — 認証情報は保存時に暗号化されます
</details>
<details>
<summary><b>🛑 6. 「プロバイダーがダウンしてコーディング フローが失われました」</b></summary>
AI プロバイダーが不安定になったり、5xx エラーを返したり、一時的なレート制限に達したりする可能性があります。開発者が単一のプロバイダーに依存している場合、それらは中断されます。サーキット ブレーカーがないと、再試行を繰り返すとアプリケーションがクラッシュする可能性があります。
**OmniRoute がそれを解決する方法:**
- **プロバイダーごとのサーキット ブレーカー** — 設定可能なしきい値とクールダウンによる自動開閉 (クローズ/オープン/ハーフオープン)
- **指数バックオフ** — 漸進的な再試行遅延
- **Anti-Thundering Herd** — 同時再試行の嵐に対するミューテックス + セマフォ保護
- **コンボ フォールバック チェーン** - プライマリ プロバイダーに障害が発生した場合、介入なしで自動的にチェーンを通過します。
- **コンボ サーキット ブレーカー** — コンボ チェーン内の障害が発生したプロバイダーを自動的に無効にします
- **ヘルス ダッシュボード** — 稼働時間モニタリング、サーキット ブレーカーの状態、ロックアウト、キャッシュ統計、p50/p95/p99 レイテンシ
</details>
<details>
<summary><b>🔧 7. 「各 AI ツールの設定は面倒で繰り返しが多い」</b></summary>
開発者は、Cursor、Claude Code、Codex CLI、OpenClaw、Gemini CLI、Kilo Code を使用します。各ツールには異なる構成 (API エンドポイント、キー、モデル) が必要です。プロバイダーや機種変更時に再設定するのは時間の無駄です。
**OmniRoute がそれを解決する方法:**
- **CLI ツール ダッシュボード** — Claude Code、Codex CLI、OpenClaw、Kilo Code、Antigravity、Cline をワンクリックでセットアップできる専用ページ
- **GitHub Copilot Config Generator** — モデルを一括選択して VS Code の `chatLanguageModels.json` を生成します
- **オンボーディング ウィザード** - 初めてユーザー向けのガイド付き 4 ステップ セットアップ
- **1 つのエンドポイント、すべてのモデル** — `http://localhost:20128/v1` を 1 回構成すると、36 を超えるプロバイダーにアクセスできます
</details>
<details>
<summary><b>🔑 8. 「複数のプロバイダーからの OAuth トークンを管理するのは地獄です」</b></summary>
Claude Code、Codex、Gemini CLI、Copilot — すべては有効期限切れのトークンを持つ OAuth 2.0 を使用します。開発者は定期的に再認証し、`client_secret is missing``redirect_uri_mismatch`、およびリモート サーバーの障害に対処する必要があります。 LAN/VPS 上の OAuth は特に問題があります。
**OmniRoute がそれを解決する方法:**
- **自動トークン更新** — OAuth トークンは有効期限が切れる前にバックグラウンドで更新されます。
- **OAuth 2.0 (PKCE) ビルトイン** — Claude Code、Codex、Gemini CLI、Copilot、Kiro、Qwen、iFlow の自動フロー
- **マルチアカウント OAuth** — JWT/ID トークン抽出によるプロバイダーごとの複数のアカウント
- **OAuth LAN/リモート修正** — `redirect_uri` のプライベート IP 検出 + リモート サーバーの手動 URL モード
- **Nginx の背後にある OAuth** — リバース プロキシの互換性のために `window.location.origin` を使用します
- **リモート OAuth ガイド** — VPS/Docker での Google Cloud 認証情報のステップバイステップ ガイド
</details>
<details>
<summary><b>📊 9. 「どこにいくら使っているのか分かりません」</b></summary>
開発者は複数の有料プロバイダーを使用していますが、支出について統一した見解がありません。各プロバイダーには独自の請求ダッシュボードがありますが、統合されたビューはありません。予期せぬ出費がかさむ可能性があります。
**OmniRoute がそれを解決する方法:**
- **コスト分析ダッシュボード** — トークンごとのコスト追跡とプロバイダーごとの予算管理
- **階層ごとの予算制限** — 自動フォールバックをトリガーする階層ごとの支出上限
- **モデルごとの価格構成** — モデルごとに構成可能な価格
- **API キーごとの使用統計** — キーごとのリクエスト数と最後に使用されたタイムスタンプ
- **分析ダッシュボード** — 統計カード、モデル使用状況グラフ、成功率と遅延を含むプロバイダー表
</details>
<details>
<summary><b>🐛 10. 「AI 呼び出しのエラーや問題を診断できません」</b></summary>
呼び出しが失敗すると、開発者はそれがレート制限なのか、トークンの期限切れなのか、間違った形式なのか、プロバイダーのエラーなのかわかりません。さまざまな端末にわたる断片化されたログ。可観測性がなければ、デバッグは試行錯誤になります。
**OmniRoute がそれを解決する方法:**
- **統合ログ ダッシュボード** — 4 つのタブ: リクエスト ログ、プロキシ ログ、監査ログ、コンソール
- **コンソール ログ ビューア** — 色分けされたレベル、自動スクロール、検索、フィルターを備えたリアルタイムのターミナル スタイルのビューア
- **SQLite プロキシ ログ** — サーバーの再起動後も存続する永続的なログ
- **Translator Playground** — 4 つのデバッグ モード: プレイグラウンド (形式変換)、チャット テスター (往復)、テストベンチ (バッチ)、ライブ モニター (リアルタイム)
- **リクエスト テレメトリ** — p50/p95/p99 レイテンシ + X-Request-Id トレース
- **ローテーションを使用したファイルベースのログ** — コンソール インターセプターは、サイズベースのローテーションを使用してすべてを JSON ログにキャプチャします。
</details>
<details>
<summary><b>🏗️ 11. 「ゲートウェイの導入と保守は複雑です」</b></summary>
さまざまな環境 (ローカル、VPS、Docker、クラウド) 間で AI プロキシをインストール、構成、維持するには、多大な労力がかかります。ハードコーディングされたパス、ディレクトリ上の `EACCES`、ポートの競合、クロスプラットフォーム ビルドなどの問題により、摩擦が増大します。
**OmniRoute がそれを解決する方法:**
- **npm グローバル インストール** — `npm install -g omniroute && omniroute` — 完了
- **Docker マルチプラットフォーム** — AMD64 + ARM64 ネイティブ (Apple Silicon、AWS Graviton、Raspberry Pi)
- **Docker Compose プロファイル** — `base` (CLI ツールなし) および `cli` (Claude Code、Codex、OpenClaw あり)
- **Electron デスクトップ アプリ** — システム トレイ、自動起動、オフライン モードを備えた Windows/macOS/Linux 用ネイティブ アプリ
- **分割ポート モード** - 高度なシナリオ (リバース プロキシ、コンテナ ネットワーキング) 向けに個別のポート上の API とダッシュボード
- **Cloud Sync** — Cloudflare Workers を介したデバイス間での設定の同期
- **DB バックアップ** — すべての設定の自動バックアップ、復元、エクスポート、インポート
</details>
<details>
<summary><b>🌍 12. 「インターフェースは英語のみで、私のチームは英語を話せません」</b></summary>
非英語圏の国、特にラテンアメリカ、アジア、ヨーロッパのチームは、英語のみのインターフェースに苦労しています。言語の壁があると採用が減り、構成エラーが増加します。
**OmniRoute がそれを解決する方法:**
- **ダッシュボード i18n — 30 言語** — アラビア語、ブルガリア語、デンマーク語、ドイツ語、スペイン語、フィンランド語、フランス語、ヘブライ語、ヒンディー語、ハンガリー語、インドネシア語、イタリア語、日本語、韓国語、マレー語、オランダ語、ノルウェー語、ポーランド語、ポルトガル語 (PT/BR)、ルーマニア語、ロシア語、スロバキア語、スウェーデン語、タイ語、ウクライナ語、ベトナム語、中国語、フィリピン語、英語
- **RTL サポート** — アラビア語とヘブライ語の右から左へのサポート
- **多言語 README** — 30 件の完全なドキュメント翻訳
- **言語セレクター** — リアルタイム切り替えのためのヘッダーの地球儀アイコン
</details>
<details>
<summary><b>🔄 13. 「チャット以上のものが必要です — 埋め込み、画像、音声が必要です」</b></summary>
AIは単なるチャット補完ではありません。開発者は、画像の生成、音声の文字起こし、RAG の埋め込みの作成、ドキュメントの再ランク付け、およびコンテンツの管理を行う必要があります。各 API には異なるエンドポイントと形式があります。
**OmniRoute がそれを解決する方法:**
- **エンベディング** — 6 つのプロバイダーと 9 つ以上のモデルを備えた `/v1/embeddings`
- **画像生成** — 10 プロバイダーと 20 以上のモデルを備えた `/v1/images/generations` (OpenAI、xAI、Togetter、Fireworks、Nebius、Hyperbolic、NanoBanana、Antigravity、SD WebUI、ComfyUI)
- **Text-to-Video** — `/v1/videos/generations` — ComfyUI (AnimateDiff、SVD) および SD WebUI
- **テキストから音楽へ** — `/v1/music/generations` — ComfyUI (安定したオーディオ オープン、MusicGen)
- **音声転写** — `/v1/audio/transcriptions` — Whisper + Nvidia NIM、HuggingFace、Qwen3
- **テキスト読み上げ** — `/v1/audio/speech` — イレブンラボ、Nvidia NIM、HuggingFace、Coqui、Tortoise、Qwen3、+ 既存のプロバイダー
- **モデレーション** — `/v1/moderations` — コンテンツの安全性チェック
- **再ランキング** — `/v1/rerank` — ドキュメントの関連性の再ランキング
- **応答 API** — Codex の `/v1/responses` の完全サポート
</details>
<details>
<summary><b>🧪 14. 「モデル間で品質をテストして比較する方法がありません」</b></summary>
開発者は、コード、翻訳、推論などのユースケースにどのモデルが最適であるかを知りたいと考えていますが、手動で比較するのは時間がかかります。統合された評価ツールは存在しません。
**OmniRoute がそれを解決する方法:**
- **LLM 評価** — 挨拶、数学、地理、コード生成、JSON 準拠、翻訳、マークダウン、安全性の拒否をカバーする 10 個の事前ロードされたケースによるゴールデン セット テスト
- **4 つのマッチ戦略** — `exact``contains``regex``custom` (JS 関数)
- **Translator Playground Test Bench** — 複数の入力と予想される出力を使用したバッチ テスト、クロスプロバイダー比較
- **チャット テスター** — 視覚的な応答レンダリングによる完全な往復
- **ライブ モニター** — プロキシを通過するすべてのリクエストのリアルタイム ストリーム
</details>
<details>
<summary><b>📈 15. 「パフォーマンスを落とさずにスケールする必要がある」</b></summary>
リクエストの量が増えると、同じ質問をキャッシュしないと重複したコストが発生します。冪等性がないと、重複したリクエストにより処理が無駄になります。プロバイダーごとのレート制限を遵守する必要があります。
**OmniRoute がそれを解決する方法:**
- **セマンティック キャッシュ** — 2 層キャッシュ (署名 + セマンティック) によりコストと遅延が削減されます。
- **リクエストの冪等性** — 同一のリクエストに対する重複排除ウィンドウは 5 秒です
- **レート制限検出** — プロバイダーごとの RPM、最小ギャップ、最大同時トラッキング
- **編集可能なレート制限** — [設定] → [永続性を伴う回復力] で構成可能なデフォルト
- **API キー検証キャッシュ** — 運用パフォーマンスのための 3 層キャッシュ
- **テレメトリ付きヘルス ダッシュボード** — p50/p95/p99 レイテンシ、キャッシュ統計、稼働時間
</details>
<details>
<summary><b>🤖 16. 「モデルの動作をグローバルに制御したい」</b></summary>
すべての応答を特定の言語、特定の口調で行いたい、または推論トークンを制限したい開発者。すべてのツール/リクエストでこれを設定するのは現実的ではありません。
**OmniRoute がそれを解決する方法:**
- **システム プロンプト インジェクション** — すべてのリクエストに適用されるグローバル プロンプト
- **思考予算検証** — リクエストごとの推論トークン割り当て制御 (パススルー、自動、カスタム、適応)
- **6 ルーティング戦略** — リクエストの分散方法を決定するグローバル戦略
- **ワイルドカード ルーター** - `provider/*` パターンは任意のプロバイダーに動的にルーティングします
- **コンボ有効/無効切り替え** — ダッシュボードから直接コンボを切り替えます
- **プロバイダー切り替え** — ワンクリックでプロバイダーのすべての接続を有効/無効にします。
- **ブロックされたプロバイダー** — `/v1/models` リストから特定のプロバイダーを除外します
</details>
<details>
<summary><b>🧰 17. 「一流の製品機能として MCP ツールが必要です」</b></summary>
多くの AI ゲートウェイは、MCP を非表示の実装詳細としてのみ公開します。チームには、目に見えて管理しやすいオペレーション レイヤーが必要です。
**OmniRoute がそれを解決する方法:**
- MCP はダッシュボードのナビゲーションとエンドポイント プロトコル タブに表示されます
- プロセス、ツール、スコープ、監査を備えた専用の MCP 管理ページ
- `omniroute --mcp` およびクライアントのオンボーディング用の組み込みクイックスタート
</details>
<details>
<summary><b>🧠 18. 「同期 + ストリーム タスク パスを備えた A2A オーケストレーションが必要です」</b></summary>
エージェント ワークフローには、直接応答と、ライフサイクル制御による長時間実行のストリーミング実行の両方が必要です。
**OmniRoute がそれを解決する方法:**
- A2A JSON-RPC エンドポイント (`POST /a2a`) (`message/send` および `message/stream`)
- 端末状態の伝播を伴う SSE ストリーミング
- `tasks/get` および `tasks/cancel` のタスク ライフサイクル API
</details>
<details>
<summary><b>🛰️ 19. 「推測されたステータスではなく、実際の MCP プロセスの健全性が必要です」</b></summary>
運用チームは、API が到達可能かどうかだけでなく、MCP が実際に生きているかどうかを知る必要があります。
**OmniRoute がそれを解決する方法:**
- PID、タイムスタンプ、トランスポート、ツール数、およびスコープモードを含むランタイムハートビートファイル
- ハートビートと最近のアクティビティを組み合わせた MCP ステータス API
- プロセス/稼働時間/ハートビートの鮮度を示す UI ステータス カード
</details>
<details>
<summary><b>📋 20. 「監査可能な MCP ツールの実行が必要です」</b></summary>
ツールが構成を変更したり、運用アクションをトリガーしたりする場合、チームはフォレンジックなトレーサビリティを必要とします。
**OmniRoute がそれを解決する方法:**
- MCP ツール呼び出しの SQLite ベースの監査ログ
- ツール、成功/失敗、API キー、ページネーションによるフィルター
- ダッシュボード監査テーブル + 自動化のための統計エンドポイント
</details>
<details>
<summary><b>🔐 21. 「統合ごとにスコープ指定された MCP 権限が必要です」</b></summary>
異なるクライアントには、ツール カテゴリへの最小限の特権アクセスが必要です。
**OmniRoute がそれを解決する方法:**
- 制御されたツールアクセスのための 9 つの詳細な MCP スコープ
- MCP 管理 UI でのスコープの適用と可視性
- 運用ツールの安全なデフォルト姿勢
</details>
<details>
<summary><b>⚙️ 22. 「再デプロイせずに運用制御が必要です」</b></summary>
チームは、インシデントやコスト イベントが発生した際に、実行時の変更を迅速に行う必要があります。
**OmniRoute がそれを解決する方法:**
- MCP ダッシュボードからコンボのアクティブ化を直接切り替えます
- 事前定義されたポリシーパックから復元プロファイルを適用
- 同じ操作パネルからサーキットブレーカーの状態をリセット
| 🎯 **Endpoint-Aware Models** | Custom models declare supported endpoints + API format |
</details>
<details>
<summary><b>🔄 23. 「ライブ A2A タスクのライフサイクルの可視化とキャンセルが必要です」</b></summary>
ライフサイクルの可視性がなければ、タスク インシデントの優先順位付けが困難になります。
**OmniRoute がそれを解決する方法:**
- ページネーションを使用した状態/スキルによるタスクのリスト/フィルタリング
- タスクのメタデータ、イベント、アーティファクトのドリルダウン
- タスクキャンセルエンドポイントと確認付きの UI アクション
</details>
<details>
<summary><b>🌊 24. 「A2A ロード用のアクティブ ストリーム メトリクスが必要です」</b></summary>
ストリーミング ワークフローには、同時実行性とライブ接続に関する運用上の洞察が必要です。
**OmniRoute がそれを解決する方法:**
- アクティブ ストリーム カウンターが A2A ステータスに統合されました
- 最後のタスクのタイムスタンプと状態ごとのカウント
- リアルタイム運用監視用の A2A ダッシュボード カード
</details>
<details>
<summary><b>🪪 25. 「クライアントの標準エージェント検出が必要です」</b></summary>
外部クライアントとオーケストレーターには、オンボーディング用の機械可読メタデータが必要です。
**OmniRoute がそれを解決する方法:**
- エージェント カードが `/.well-known/agent.json` で公開される
- 管理UIに表示される能力とスキル
- A2A ステータス API には自動化のための検出メタデータが含まれています
</details>
<details>
<summary><b>🧭 26. 「製品 UX にプロトコルの検出機能が必要です」</b></summary>
ユーザーがプロトコルの表面を発見できない場合、導入とサポートの品質が低下します。
**OmniRoute がそれを解決する方法:**
- MCP および A2A のサイドバー エントリ
- クイックスタートとステータスを含むエンドポイント ページの [プロトコル] タブ
- 概要から専用の管理ダッシュボードへのリンク
</details>
<details>
<summary><b>🧪 27. 「実際のクライアントを使用したエンドツーエンドのプロトコル検証が必要です」</b></summary>
模擬テストは、リリース前にプロトコルの互換性を検証するには十分ではありません。
**OmniRoute がそれを解決する方法:**
- アプリを起動し、実際の MCP SDK クライアント トランスポートを使用する E2E スイート
- A2A クライアントは、フローの検出、送信、ストリーミング、取得、キャンセルをテストします。
- MCP 監査および A2A タスク API に対するアサーションのクロスチェック
</details>
<details>
<summary><b>📡 28. 「すべてのインターフェースにわたって統合された可観測性が必要です」</b></summary>
プロトコルごとに可観測性を分割すると、盲点が生じ、MTTR が長くなります。
**OmniRoute がそれを解決する方法:**
- ダッシュボード/ログ/分析を 1 つの製品に統合
- OpenAI、MCP、A2A レイヤーにわたるヘルス + 監査 + リクエスト テレメトリ
- ステータスと自動化のための運用 API
</details>
<details>
<summary><b>💼 29. 「プロキシ + ツール + エージェント オーケストレーション用のランタイムが 1 つ必要です」</b></summary>
多くの個別のサービスを実行すると、運用コストが増加し、障害モードが増加します。
**OmniRoute がそれを解決する方法:**
- OpenAI互換プロキシ、MCPサーバー、A2Aサーバーを1つのスタックに搭載
- 共有認証、復元力、データストア、可観測性
- すべての対話面にわたる一貫したポリシー モデル
</details>
<details>
<summary><b>🚀 30. 「グルーコードのスプロールなしでエージェント ワークフローを出荷する必要がある」</b></summary>
複数のアドホック サービスとスクリプトをつなぎ合わせると、チームの速度が低下します。
**OmniRoute がそれを解決する方法:**
- クライアントとエージェント向けの統合エンドポイント戦略
- 組み込みのプロトコル管理 UI とスモーク検証パス
- 本番環境に対応した基盤 (セキュリティ、ロギング、復元力、バックアップ)
</details>
### プレイブックの例 (統合されたユースケース)
**戦略 A: 有料サブスクリプション + 安価なバックアップを最大限に活用する**
```txt
Combo: "maximize-claude"
1. cc/claude-opus-4-6
2. glm/glm-4.7
3. if/kimi-k2-thinking
Monthly cost: $20 + small backup spend
Outcome: higher quality, near-zero interruption
```
**プレイブック B: ゼロコストのコーディング スタック**
```txt
Combo: "free-forever"
1. gc/gemini-3-flash
2. if/kimi-k2-thinking
3. qw/qwen3-coder-plus
Monthly cost: $0
Outcome: stable free coding workflow
```
**プレイブック C: 24 時間年中無休の常時オンのフォールバック チェーン**
```txt
Combo: "always-on"
1. cc/claude-opus-4-6
2. cx/gpt-5.2-codex
3. glm/glm-4.7
4. minimax/MiniMax-M2.1
5. if/kimi-k2-thinking
Outcome: deep fallback depth for deadline-critical workloads
```
**プレイブック D: MCP + A2A を使用したエージェントの運用**
```txt
1) Start MCP transport (`omniroute --mcp`) for tool-driven operations
2) Run A2A tasks via `message/send` and `message/stream`
3) Observe via /dashboard/mcp and /dashboard/a2a
4) Control incidents with resilience profile + task cancellation
```
---
## ⚡ クイックスタート
**1.グローバルにインストール:**
@@ -249,7 +782,7 @@ docker compose --profile cli up -d
---
## 🖥️ デスクトップアプリ — オフライン&常時稼働
## 🖥️
> 🆕 **新機能!** OmniRouteが**ネイティブデスクトップアプリケーション**としてWindows、macOS、Linuxで利用可能になりました。
@@ -296,67 +829,6 @@ npm run electron:build:linux # Linux (.AppImage)
---
## 🎯 使用例
### ケース 1: 「Claude Pro サブスクリプションを持っています」
**問題:** 大量のコーディング中にクォータが使用されずに期限切れになり、レート制限が発生する
```
Combo: "maximize-claude"
1. cc/claude-opus-4-6 (use subscription fully)
2. glm/glm-4.7 (cheap backup when quota out)
3. if/kimi-k2-thinking (free emergency fallback)
Monthly cost: $20 (subscription) + ~$5 (backup) = $25 total
vs. $20 + hitting limits = frustration
```
### ケース 2: 「コストをゼロにしたい」
**問題:** サブスクリプションを購入する余裕がないため、信頼性の高い AI コーディングが必要です
```
Combo: "free-forever"
1. gc/gemini-3-flash (180K free/month)
2. if/kimi-k2-thinking (unlimited free)
3. qw/qwen3-coder-plus (unlimited free)
Monthly cost: $0
Quality: Production-ready models
```
### ケース 3: 「24 時間年中無休でコーディングが必要で、中断はありません」
**問題:** 締め切りが迫っており、ダウンタイムを許すことができません
```
Combo: "always-on"
1. cc/claude-opus-4-6 (best quality)
2. cx/gpt-5.2-codex (second subscription)
3. glm/glm-4.7 (cheap, resets daily)
4. minimax/MiniMax-M2.1 (cheapest, 5h reset)
5. if/kimi-k2-thinking (free unlimited)
Result: 5 layers of fallback = zero downtime
```
### ケース 4: 「OpenClaw に無料の AI が欲しい」
**問題:** メッセージング アプリには AI アシスタントが必要ですが、完全に無料です
```
Combo: "openclaw-free"
1. if/glm-4.7 (unlimited free)
2. if/minimax-m2.1 (unlimited free)
3. if/kimi-k2-thinking (unlimited free)
Monthly cost: $0
Access via: WhatsApp, Telegram, Slack, Discord, iMessage, Signal...
```
---
## 💡 主な機能
### 🧠 コアルーティングとインテリジェンス
@@ -372,6 +844,8 @@ Access via: WhatsApp, Telegram, Slack, Discord, iMessage, Signal...
| 🧩 **カスタムモデル** | 任意のモデル ID を任意のプロバイダーに追加する |
| 🌐 **ワイルドカードルーター** | `provider/*` パターンを任意のプロバイダーに動的にルーティングする |
| 🧠 **予算を考える** | 推論モデルのパススルー、自動、カスタム、および適応モード |
| 🔀 **Model Aliases** | Auto-forward deprecated model IDs to current replacements (built-in + custom) |
| ⚡ **Background Degradation** | Auto-route background tasks (titles, summaries) to cheaper models |
| 💬 **システム プロンプト インジェクション** | すべてのリクエストに適用されるグローバル システム プロンプト |
| 📄 **レスポンス API** | Codex の OpenAI Response API (`/v1/responses`) の完全なサポート |
@@ -391,12 +865,15 @@ Access via: WhatsApp, Telegram, Slack, Discord, iMessage, Signal...
| 特集 | 何をするのか |
| -------------------------------- | ---------------------------------------------------------------------------- |
| 🔌 **サーキットブレーカー** | 設定可能なしきい値によるプロバイダーごとの自動開閉 |
| 🎯 **Endpoint-Aware Models** | Custom models declare supported endpoints + API format |
| 🛡️ **対雷鳴の群れ** | API キープロバイダーのミューテックス + セマフォのレート制限 |
| 🧠 **セマンティック キャッシュ** | 2 層キャッシュ (シグネチャ + セマンティック) によりコストと遅延が削減 |
| ⚡ **冪等性のリクエスト** | 重複リクエストに対する 5 秒の重複除去ウィンドウ |
| 🔒 **TLS 指紋スプーフィング** | wreq-js 経由で TLS ベースのボット検出をバイパスする |
| 🌐 **IP フィルタリング** | API アクセス制御の許可リスト/ブロックリスト |
| 📊 **編集可能なレート制限** | システム レベルで構成可能な RPM、最小ギャップ、最大同時実行 |
| 💾 **Rate Limit Persistence** | Learned limits survive restarts via SQLite with 60s debounce + 24h staleness |
| 🔄 **Token Refresh Resilience** | Per-provider circuit breaker (5 fails→30min) + 30s timeout per attempt |
| 🛡 **API エンドポイント保護** | `/models` エンドポイントの認証ゲート + プロバイダー ブロック |
| 🔒 **プロキシの可視性** | 色分けされたバッジ: 🟢 グローバル、🟡 プロバイダー、🔵 IP 表示による接続ごと |
| 🌐 **3 レベルのプロキシ構成** | グローバル、プロバイダーごと、または接続ごとのレベルでプロキシを構成する |
@@ -489,6 +966,7 @@ Combo: "my-coding-stack"
- システムステータス (稼働時間、バージョン、メモリ使用量)
- プロバイダーごとのサーキットブレーカーの状態 (クローズ/オープン/ハーフオープン)
| 🎯 **Endpoint-Aware Models** | Custom models declare supported endpoints + API format |
- レート制限ステータスとアクティブなロックアウト
- 署名キャッシュ統計
- レイテンシ テレメトリ (p50/p95/p99) + プロンプト キャッシュ
@@ -515,6 +993,27 @@ OmniRoute には、API 翻訳のデバッグ、テスト、監視のための **
</details>
## 🧪 評価 (Evals)
OmniRoute には、ゴールデン セットに対して LLM 応答品質をテストするための評価フレームワークが組み込まれています。ダッシュボードの **Analytics → Evals** からアクセスします。
### 内蔵ゴールデンセット
プリロードされた「OmniRoute Golden Set」には、以下をカバーする 10 のテスト ケースが含まれています。
- 挨拶、数学、地理、コード生成
- JSON形式への準拠、翻訳、マークダウン
- 安全拒否(有害なコンテンツ)、カウント、ブール論理
### 評価戦略
| 戦略 | 説明 | 例 |
| ---------- | ------------------------------------------------------------------------------------------- | ----------- |
| `exact` | 出力は正確に一致する必要があります | `"4"` |
| `contains` | 出力には部分文字列が含まれている必要があります (大文字と小文字は区別されません)。 `"Paris"` |
| `regex` | 出力は正規表現パターンと一致する必要があります | `"1.*2.*3"` |
| `custom` | カスタム JS 関数は true/false を返します。 `(output) => output.length > 10` |
---
## 📖 セットアップガイド
@@ -796,104 +1295,64 @@ Settings → API Configuration:
---
## 📊 利用可能なモデル
## 🐛 トラブルシューティング
<details>
<summary><b>利用可能なモデルをすべて表示</b></summary>
<summary><b>クリックしてトラブルシューティング ガイドを展開</b></summary>
**クロード コード (`cc/`)** - Pro/Max:
**「言語モデルがメッセージを提供しませんでした」**
- `cc/claude-opus-4-6`
- `cc/claude-sonnet-4-5-20250929`
- `cc/claude-haiku-4-5-20251001`
- プロバイダー クォータが枯渇した → ダッシュボード クォータ トラッカーを確認してください
- 解決策: コンボフォールバックを使用するか、より安価なレベルに切り替える
**コーデックス (`cx/`)** - プラス/プロ:
**レート制限**
- `cx/gpt-5.2-codex`
- `cx/gpt-5.1-codex-max`
- サブスクリプション クォータ アウト → GLM/MiniMax へのフォールバック
- コンボを追加: `cc/claude-opus-4-6 → glm/glm-4.7 → if/kimi-k2-thinking`
**Gemini CLI (`gc/`)** - 無料:
**OAuth トークンの有効期限が切れました**
- `gc/gemini-3-flash-preview`
- `gc/gemini-2.5-pro`
- OmniRouteによる自動更新
- 問題が解決しない場合: ダッシュボード → プロバイダー → 再接続
**GitHub コパイロット (`gh/`)**:
**高コスト**
- `gh/gpt-5`
- `gh/claude-4.5-sonnet`
- [ダッシュボード] → [コスト] で使用状況の統計を確認します。
- プライマリ モデルを GLM/MiniMax に切り替えます
- 重要ではないタスクには無料枠 (Gemini CLI、iFlow) を使用する
**NVIDIA NIM (`nvidia/`)** - 無料クレジット:
**ダッシュボードが間違ったポートで開きます**
- `nvidia/llama-3.3-70b-instruct`
- `nvidia/mistral-7b-instruct`
- [build.nvidia.com](https://build.nvidia.com) には 50 以上のモデル
- `PORT=20128` および `NEXT_PUBLIC_BASE_URL=http://localhost:20128` を設定します
**GLM (`glm/`)** - 0.6 ドル/100 万:
**クラウド同期エラー**
- `glm/glm-4.7`
- `BASE_URL` が実行中のインスタンスを指していることを確認します
- `CLOUD_URL` が予想されるクラウド エンドポイントを指していることを確認します
- `NEXT_PUBLIC_*` 値をサーバー側の値と一致させます。
**MiniMax (`minimax/`)** - $0.2/100 万:
**最初のログインが機能しない**
- `minimax/MiniMax-M2.1`
- `.env``INITIAL_PASSWORD` を確認してください
- 設定されていない場合、フォールバック パスワードは `123456` です
**iFlow (`if/`)** - 無料:
**リクエストログなし**
- `if/kimi-k2-thinking`
- `if/qwen3-coder-plus`
- `if/deepseek-r1`
- `if/glm-4.7`
- `if/minimax-m2`
- `.env``ENABLE_REQUEST_LOGS=true` を設定します
**クウェン (`qw/`)** - 無料:
**OpenAI 互換プロバイダーの接続テストで「無効」と表示される**
- `qw/qwen3-coder-plus`
- `qw/qwen3-coder-flash`
- 多くのプロバイダーは `/models` エンドポイントを公開していません
- OmniRoute v1.0.6+ には、チャット完了によるフォールバック検証が含まれています
- ベース URL に `/v1` サフィックスが含まれていることを確認してください
**キロ (`kr/`)** - 無料:
- `kr/claude-sonnet-4.5`
- `kr/claude-haiku-4.5`
**OpenRouter (`or/`)** - 100 以上のモデル:
- `or/anthropic/claude-4-sonnet`
- `or/google/gemini-2.5-pro`
- [openrouter.ai/models](https://openrouter.ai/models) の任意のモデル
</details>
---
## 🧪 評価 (Evals)
OmniRoute には、ゴールデン セットに対して LLM 応答品質をテストするための評価フレームワークが組み込まれています。ダッシュボードの **Analytics → Evals** からアクセスします。
### 内蔵ゴールデンセット
プリロードされた「OmniRoute Golden Set」には、以下をカバーする 10 のテスト ケースが含まれています。
- 挨拶、数学、地理、コード生成
- JSON形式への準拠、翻訳、マークダウン
- 安全拒否(有害なコンテンツ)、カウント、ブール論理
### 評価戦略
| 戦略 | 説明 | 例 |
| ---------- | ------------------------------------------------------------------------------------------- | ----------- |
| `exact` | 出力は正確に一致する必要があります | `"4"` |
| `contains` | 出力には部分文字列が含まれている必要があります (大文字と小文字は区別されません)。 `"Paris"` |
| `regex` | 出力は正規表現パターンと一致する必要があります | `"1.*2.*3"` |
| `custom` | カスタム JS 関数は true/false を返します。 `(output) => output.length > 10` |
---
## 🔐 サーバーリモートの OAuth (リモート OAuth セットアップ)
### 🔐 サーバーリモートの OAuth (リモート OAuth セットアップ)
<a name="oauth-em-servidor-remoto"></a>
> **⚠️ VPS/Docker/サーバーリモートの OmniRoute に関する重要事項**
### Antigravity / Gemini CLI で OAuth を実行すると、リモートのサービスが提供されますか?
### OAuth
**反重力****Gemini CLI** を使用して **Google OAuth 2.0** を認証します。 O Google exige que a `redirect_uri` usada no fluxo OAuth seja **exatamente** uma das URIs pré-cadastradas Google Cloud Console でアプリケーションを実行できません。
@@ -978,64 +1437,11 @@ docker restart omniroute
> 自動回避策の機能は URL から独立してリダイレクトされます。
---
## 🐛 トラブルシューティング
<details>
<summary><b>クリックしてトラブルシューティング ガイドを展開</b></summary>
**「言語モデルがメッセージを提供しませんでした」**
- プロバイダー クォータが枯渇した → ダッシュボード クォータ トラッカーを確認してください
- 解決策: コンボフォールバックを使用するか、より安価なレベルに切り替える
**レート制限**
- サブスクリプション クォータ アウト → GLM/MiniMax へのフォールバック
- コンボを追加: `cc/claude-opus-4-6 → glm/glm-4.7 → if/kimi-k2-thinking`
**OAuth トークンの有効期限が切れました**
- OmniRouteによる自動更新
- 問題が解決しない場合: ダッシュボード → プロバイダー → 再接続
**高コスト**
- [ダッシュボード] → [コスト] で使用状況の統計を確認します。
- プライマリ モデルを GLM/MiniMax に切り替えます
- 重要ではないタスクには無料枠 (Gemini CLI、iFlow) を使用する
**ダッシュボードが間違ったポートで開きます**
- `PORT=20128` および `NEXT_PUBLIC_BASE_URL=http://localhost:20128` を設定します
**クラウド同期エラー**
- `BASE_URL` が実行中のインスタンスを指していることを確認します
- `CLOUD_URL` が予想されるクラウド エンドポイントを指していることを確認します
- `NEXT_PUBLIC_*` 値をサーバー側の値と一致させます。
**最初のログインが機能しない**
- `.env``INITIAL_PASSWORD` を確認してください
- 設定されていない場合、フォールバック パスワードは `123456` です
**リクエストログなし**
- `.env``ENABLE_REQUEST_LOGS=true` を設定します
**OpenAI 互換プロバイダーの接続テストで「無効」と表示される**
- 多くのプロバイダーは `/models` エンドポイントを公開していません
- OmniRoute v1.0.6+ には、チャット完了によるフォールバック検証が含まれています
- ベース URL に `/v1` サフィックスが含まれていることを確認してください
</details>
---
## 🛠️ 技術スタック
## 🛠️
- **ランタイム**: Node.js 1822 LTS (⚠️ Node.js 24+ は **サポートされていません**`better-sqlite3` ネイティブ バイナリは互換性がありません)
- **言語**: TypeScript 5.9 — `src/` および `open-sse/`**100% TypeScript** (v1.0.6)
@@ -1087,7 +1493,7 @@ docker restart omniroute
---
## 🗺️ ロードマップ
## 🗺️
OmniRoute には、複数の開発フェーズにわたって **210 以上の機能が計画されています**。主要な領域は次のとおりです。
@@ -1112,18 +1518,6 @@ OmniRoute には、複数の開発フェーズにわたって **210 以上の機
---
## 📧 サポート
> 💬 **コミュニティに参加してください!** [WhatsApp Group](https://chat.whatsapp.com/JI7cDQ1GyaiDHhVBpLxf8b?mode=gi_t) — ヘルプを取得し、ヒントを共有し、最新情報を入手してください。
- **ウェブサイト**: [omniroute.online](https://omniroute.online)
- **GitHub**: [github.com/diegosouzapw/OmniRoute](https://github.com/diegosouzapw/OmniRoute)
- **問題**: [github.com/diegosouzapw/OmniRoute/issues](https://github.com/diegosouzapw/OmniRoute/issues)
- **WhatsApp**: [Community Group](https://chat.whatsapp.com/JI7cDQ1GyaiDHhVBpLxf8b?mode=gi_t)
- **オリジナル プロジェクト**: [9router by decolua](https://github.com/decolua/9router)
---
## 👥 貢献者
[![Contributors](https://contrib.rocks/image?repo=diegosouzapw/OmniRoute&max=100&columns=20&anon=1)](https://github.com/diegosouzapw/OmniRoute/graphs/contributors)

File diff suppressed because it is too large Load Diff

1370
README.md

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -3,8 +3,6 @@
# 🚀 OmniRoute — Den gratis AI-gatewayen
🌐 **[English](#-omniroute--the-free-ai-gateway)** | **[Português (BR)](#-omniroute--gateway-de-ia-gratuito)**
### Slutt aldri å kode. Smart ruting til **GRATIS og rimelige AI-modeller** med automatisk fallback.
_Din universelle API-proxy ett endepunkt, 36+ leverandører, null nedetid._
@@ -112,6 +110,35 @@ _Koble til ethvert AI-drevet IDE- eller CLI-verktøy gjennom OmniRoute grati
---
## 🖼️
<div align="center">
<img src="./docs/screenshots/MainOmniRoute.png" alt="OmniRoute" width="800"/>
</div>
---
## 📸
<details>
<summary><b>...</b></summary>
| # | # |
| ----- | ---------------------------------------- |
| **1** | ![1](docs/screenshots/01-providers.png) |
| **2** | ![2](docs/screenshots/02-combos.png) |
| **3** | ![3](docs/screenshots/03-analytics.png) |
| **4** | ![4](docs/screenshots/04-health.png) |
| **5** | ![5](docs/screenshots/05-translator.png) |
| **6** | ![6](docs/screenshots/06-settings.png) |
| **7** | ![7](docs/screenshots/07-cli-tools.png) |
| **8** | ![8](docs/screenshots/08-usage.png) |
| **9** | ![9](docs/screenshots/09-endpoint.png) |
</details>
---
## 🤔 Hvorfor OmniRoute?
**Slutt å kaste bort penger og nå grensene:**
@@ -130,6 +157,18 @@ _Koble til ethvert AI-drevet IDE- eller CLI-verktøy gjennom OmniRoute grati
---
## 📧 Støtte
> 💬 **Bli med i fellesskapet vårt!** [WhatsApp Group](https://chat.whatsapp.com/JI7cDQ1GyaiDHhVBpLxf8b?mode=gi_t) — Få hjelp, del tips og hold deg oppdatert.
- **Nettsted**: [omniroute.online](https://omniroute.online)
- **GitHub**: [github.com/diegosouzapw/OmniRoute](https://github.com/diegosouzapw/OmniRoute)
- **Problemer**: [github.com/diegosouzapw/OmniRoute/issues](https://github.com/diegosouzapw/OmniRoute/issues)
- **WhatsApp**: [Community Group](https://chat.whatsapp.com/JI7cDQ1GyaiDHhVBpLxf8b?mode=gi_t)
- **Originalt prosjekt**: [9router by decolua](https://github.com/decolua/9router)
---
## 🔄 Hvordan det fungerer
```
@@ -159,6 +198,497 @@ Result: Never stop coding, minimal cost
---
## 🎯 Hva OmniRoute løser — 30 ekte smertepoeng og brukstilfeller
> **Hver utviklere som bruker AI-verktøy møter disse problemene daglig.** OmniRoute ble bygget for å løse dem alle fra kostnadsoverskridelser til regionale blokker, fra ødelagte OAuth-flyter til protokolloperasjoner og observerbarhet i bedrifter.
<details>
<summary><b>💸 1. "Jeg betaler for et dyrt abonnement, men blir fortsatt avbrutt av grenser" </b></summary>
Utviklere betaler $20200/måned for Claude Pro, Codex Pro eller GitHub Copilot. Selv om du betaler, har kvoten et tak 5 timers bruk, ukentlige grenser eller rategrenser per minutt. Midtkodingsøkt, leverandøren slutter å svare og utvikleren mister flyt og produktivitet.
**Hvordan OmniRoute løser det:**
- **Smart 4-lags fallback** — Hvis abonnementskvoten går tom, omdirigeres automatisk til API-nøkkel → Billig → Gratis med null manuell intervensjon
- **Sanntidskvotesporing** — Viser tokenforbruk i sanntid med tilbakestilt nedtelling (5 timer, daglig, ukentlig)
- **Støtte for flere kontoer** - Flere kontoer per leverandør med automatisk round-robin - når en går tom, bytter du til den neste
- **Egendefinerte kombinasjoner** — Tilpassbare reservekjeder med 6 balansestrategier (fyll først, round-robin, P2C, tilfeldig, minst brukt, kostnadsoptimalisert)
- **Codex Business Quotas** — Overvåking av bedrifts-/teamarbeidsområdekvoter direkte i dashbordet
</details>
<details>
<summary><b>🔌 2. "Jeg trenger å bruke flere leverandører, men hver av dem har en annen API" </b></summary>
OpenAI bruker ett format, Claude (Anthropic) bruker et annet, Gemini enda et annet. Hvis en utvikler ønsker å teste modeller fra forskjellige leverandører eller fallback mellom dem, må de rekonfigurere SDK-er, endre endepunkter, håndtere inkompatible formater. Tilpassede leverandører (FriendLI, NIM) har ikke-standardmodellende endepunkter.
**Hvordan OmniRoute løser det:**
- **Unified Endpoint** - En enkelt `http://localhost:20128/v1` fungerer som proxy for alle 36+ leverandører
- **Formatoversettelse** — Automatisk og gjennomsiktig: OpenAI ↔ Claude ↔ Gemini ↔ Responses API
- **Responsrensing** — Fjerner ikke-standardfelter (`x_groq`, `usage_breakdown`, `service_tier`) som bryter OpenAI SDK v1.83+
- **Rollenormalisering** — Konverterer `developer``system` for ikke-OpenAI-leverandører; `system``user` for GLM/ERNIE
- **Think Tag Extraction** — Trekker ut `<think>`-blokker fra modeller som DeepSeek R1 til standardiserte `reasoning_content`
- **Structured Output for Gemini** — `json_schema``responseMimeType`/`responseSchema` automatisk konvertering
- **`stream` er standard til `false`** — Justerer med OpenAI-spesifikasjoner, og unngår uventet SSE i Python/Rust/Go SDK-er
</details>
<details>
<summary><b>🌐 3. "Min AI-leverandør blokkerer min region/land" </b></summary>
Leverandører som OpenAI/Codex blokkerer tilgang fra visse geografiske områder. Brukere får feil som `unsupported_country_region_territory` under OAuth- og API-tilkoblinger. Dette er spesielt frustrerende for utviklere fra utviklingsland.
**Hvordan OmniRoute løser det:**
- **3-Level Proxy Config** — Konfigurerbar proxy på 3 nivåer: global (all trafikk), per leverandør (kun én leverandør) og per tilkobling/nøkkel
- **Fargekodede proxy-merker** — Visuelle indikatorer: 🟢 global proxy, 🟡 leverandørproxy, 🔵 tilkoblings proxy, viser alltid IP
- **OAuth-tokenutveksling gjennom proxy** - OAuth-flyt går også gjennom proxyen, og løser `unsupported_country_region_territory`
- **Test av tilkobling via proxy** — Tilkoblingstester bruker den konfigurerte proxyen (ikke mer direkte forbikobling)
- **SOCKS5-støtte** — Full SOCKS5-proxystøtte for utgående ruting
- **TLS-fingeravtrykkspoofing** — Nettleserlignende TLS-fingeravtrykk via `wreq-js` for å omgå botdeteksjon
</details>
<details>
<summary><b>🆓 4. "Jeg vil bruke AI for koding, men jeg har ingen penger" </b></summary>
Ikke alle kan betale $20200 per måned for AI-abonnementer. Studenter, utviklere fra fremvoksende land, hobbyfolk og frilansere trenger tilgang til kvalitetsmodeller uten kostnad.
**Hvordan OmniRoute løser det:**
- **Gratis-tilbydere innebygd** — Innebygd støtte for 100 % gratisleverandører: iFlow (8 ubegrensede modeller), Qwen (3 ubegrensede modeller), Kiro (Claude gratis), Gemini CLI (180K/mnd gratis)
- **Kun gratis kombinasjoner** — Kjede `gc/gemini-3-flash → if/kimi-k2-thinking → qw/qwen3-coder-plus` = $0/måned med null nedetid
- **NVIDIA NIM gratis kreditter** — 1000 gratis kreditter integrert
- **Kostnadsoptimalisert strategi** — Rutingstrategi som automatisk velger den billigste tilgjengelige leverandøren
</details>
<details>
<summary><b>🔒 5. "Jeg trenger å beskytte AI-gatewayen min mot uautorisert tilgang" </b></summary>
Når du eksponerer en AI-gateway til nettverket (LAN, VPS, Docker), kan alle med adressen konsumere utviklerens tokens/kvote. Uten beskyttelse er API-er sårbare for misbruk, umiddelbar injeksjon og misbruk.
**Hvordan OmniRoute løser det:**
- **API Key Management** — Generering, rotasjon og scoping per leverandør med en dedikert `/dashboard/api-manager`-side
- **Tillatelser på modellnivå** — Begrens API-nøkler til spesifikke modeller (`openai/*`, jokertegnmønstre), med Tillat alt/begrens
- **API Endpoint Protection** — Krev en nøkkel for `/v1/models` og blokker spesifikke leverandører fra oppføringen
- **Auth Guard + CSRF Protection** — Alle dashbordruter beskyttet med `withAuth` mellomvare + CSRF-tokens
- **Rate Limiter** — Per-IP ratebegrensning med konfigurerbare vinduer
- **IP-filtrering** — Tillatelsesliste/blokkeringsliste for tilgangskontroll
- **Prompt Injection Guard** — Sanitisering mot ondsinnede spørsmålsmønstre
- **AES-256-GCM-kryptering** — Legitimasjon kryptert i hvile
</details>
<details>
<summary><b>🛑 6. «Tilbyderen min gikk ned og jeg mistet kodeflyten min» </b></summary>
AI-leverandører kan bli ustabile, returnere 5xx-feil eller nå midlertidige hastighetsgrenser. Hvis en utvikler er avhengig av en enkelt leverandør, blir de avbrutt. Uten strømbrytere kan gjentatte forsøk krasje applikasjonen.
**Hvordan OmniRoute løser det:**
- **Circuit Breaker per leverandør** — Automatisk åpning/lukking med konfigurerbare terskler og nedkjøling (Lukket/Åpen/HalvÅpen)
- **Eksponentiell backoff** — Progressive forsinkelser på nytt forsøk
- **Anti-tordenflokk** — Mutex + semaforbeskyttelse mot samtidige stormer på nytt forsøk
- **Combo Fallback Chains** — Hvis primærleverandøren mislykkes, faller den automatisk gjennom kjeden uten inngrep
- **Combo Circuit Breaker** - Deaktiverer sviktende leverandører automatisk i en kombinasjonskjede
- **Helsedashbord** — Oppetidsovervåking, strømbrytertilstander, sperringer, cachestatistikk, p50/p95/p99 latency
</details>
<details>
<summary><b>🔧 7. "Å konfigurere hvert AI-verktøy er kjedelig og repeterende" </b></summary>
Utviklere bruker Cursor, Claude Code, Codex CLI, OpenClaw, Gemini CLI, Kilo Code... Hvert verktøy trenger en annen konfigurasjon (API-endepunkt, nøkkel, modell). Å konfigurere på nytt når du bytter leverandør eller modell er bortkastet tid.
**Hvordan OmniRoute løser det:**
- **CLI Tools Dashboard** — Dedikert side med ett-klikksoppsett for Claude Code, Codex CLI, OpenClaw, Kilo Code, Antigravity, Cline
- **GitHub Copilot Config Generator** — Genererer `chatLanguageModels.json` for VS-kode med bulkmodellvalg
- **Onboarding Wizard** — Veiledet 4-trinns oppsett for førstegangsbrukere
- **Ett endepunkt, alle modeller** — Konfigurer `http://localhost:20128/v1` én gang, få tilgang til 36+ leverandører
</details>
<details>
<summary><b>🔑 8. "Å administrere OAuth-tokens fra flere leverandører er et helvete" </b></summary>
Claude Code, Codex, Gemini CLI, Copilot alle bruker OAuth 2.0 med tokens som utløper. Utviklere må re-autentisere hele tiden, håndtere `client_secret is missing`, `redirect_uri_mismatch` og feil på eksterne servere. OAuth på LAN/VPS er spesielt problematisk.
**Hvordan OmniRoute løser det:**
- **Automatisk oppdatering av token** — OAuth-tokener oppdateres i bakgrunnen før utløp
- **OAuth 2.0 (PKCE) innebygd** — Automatisk flyt for Claude Code, Codex, Gemini CLI, Copilot, Kiro, Qwen, iFlow
- **Multi-Account OAuth** - Flere kontoer per leverandør via JWT/ID-tokenutvinning
- **OAuth LAN/Remote Fix** — Privat IP-deteksjon for `redirect_uri` + manuell URL-modus for eksterne servere
- **OAuth Behind Nginx** — Bruker `window.location.origin` for omvendt proxy-kompatibilitet
- **Remote OAuth Guide** — Trinn-for-trinn-veiledning for Google Cloud-legitimasjon på VPS/Docker
</details>
<details>
<summary><b>📊 9. "Jeg vet ikke hvor mye jeg bruker eller hvor" </b></summary>
Utviklere bruker flere betalte leverandører, men har ikke noe enhetlig syn på utgifter. Hver leverandør har sitt eget faktureringsdashbord, men det er ingen konsolidert visning. Uventede kostnader kan hope seg opp.
**Hvordan OmniRoute løser det:**
- **Dashboard for kostnadsanalyse** — Kostnadssporing per token og budsjettadministrasjon per leverandør
**Budsjettgrenser per nivå** Utgiftstak per nivå som utløser automatisk fallback
- **Priskonfigurasjon per modell** — Konfigurerbare priser per modell
- **Bruksstatistikk per API-nøkkel** — Antall forespørsler og sist brukte tidsstempel per nøkkel
- **Analytics Dashboard** — Statistiske kort, modellbruksdiagram, leverandørtabell med suksessrater og latens
</details>
<details>
<summary><b>🐛 10. "Jeg kan ikke diagnostisere feil og problemer i AI-anrop" </b></summary>
Når et anrop mislykkes, vet ikke utvikleren om det var en takstgrense, utløpt token, feil format eller leverandørfeil. Fragmenterte logger på tvers av forskjellige terminaler. Uten observerbarhet er feilsøking prøving og feiling.
**Hvordan OmniRoute løser det:**
- **Unified Logs Dashboard** — 4 faner: Forespørselslogger, proxy-logger, revisjonslogger, konsoll
- **Console Log Viewer** — Viser i sanntid i terminalstil med fargekodede nivåer, automatisk rulling, søk, filter
- **SQLite Proxy Logger** — Vedvarende logger som overlever serverstarter
- **Translator Playground** — 4 feilsøkingsmoduser: Playground (formatoversettelse), Chat Tester (tur-retur), Test Bench (batch), Live Monitor (sanntid)
- **Request Telemetri** — p50/p95/p99 latens + X-Request-Id-sporing
- **Filbasert logging med rotasjon** — Konsollinterceptor fanger opp alt til JSON-logg med størrelsesbasert rotasjon
</details>
<details>
<summary><b>🏗️ 11. "Deployering og vedlikehold av gatewayen er kompleks" </b></summary>
Installering, konfigurering og vedlikehold av en AI-proxy på tvers av forskjellige miljøer (lokalt, VPS, Docker, sky) er arbeidskrevende. Problemer som hardkodede baner, `EACCES` på kataloger, portkonflikter og kryssplattformbygg gir friksjon.
**Hvordan OmniRoute løser det:**
- **npm global installasjon** — `npm install -g omniroute && omniroute` — ferdig
- **Docker Multi-Platform** — AMD64 + ARM64 native (Apple Silicon, AWS Graviton, Raspberry Pi)
- **Docker Compose-profiler** — `base` (ingen CLI-verktøy) og `cli` (med Claude Code, Codex, OpenClaw)
- **Electron Desktop App** — Innebygd app for Windows/macOS/Linux med systemstatusfelt, automatisk start, offline-modus
- **Split-Port Mode** — API og Dashboard på separate porter for avanserte scenarier (omvendt proxy, containernettverk)
- **Cloud Sync** — Konfigurer synkronisering på tvers av enheter via Cloudflare Workers
- **DB-sikkerhetskopier** — Automatisk sikkerhetskopiering, gjenoppretting, eksport og import av alle innstillinger
</details>
<details>
<summary><b>🌍 12. "Grensesnittet er kun engelsk, og teamet mitt snakker ikke engelsk" </b></summary>
Lag i ikke-engelsktalende land, spesielt i Latin-Amerika, Asia og Europa, sliter med grensesnitt som kun er på engelsk. Språkbarrierer reduserer bruken og øker konfigurasjonsfeil.
**Hvordan OmniRoute løser det:**
- **Dashboard i18n — 30 språk** — Alle 500+ nøkler oversatt, inkludert arabisk, bulgarsk, dansk, tysk, spansk, finsk, fransk, hebraisk, hindi, ungarsk, indonesisk, italiensk, japansk, koreansk, malaysisk, nederlandsk, norsk, polsk, portugisisk (PT/BR), rumensk, russisk, ukrainsk, ukrainsk, kinesisk, engelsk, kinesisk, ukrainsk, kinesisk, ukrainsk, kinesisk, ukrainsk, kinesisk, ukrainsk, kinesisk
- **RTL-støtte** — Høyre-til-venstre-støtte for arabisk og hebraisk
- **Multi-Language READMEs** - 30 komplette dokumentasjonsoversettelser
- **Språkvelger** — Globusikon i overskriften for sanntidsbytte
</details>
<details>
<summary><b>🔄 13. "Jeg trenger mer enn chat — jeg trenger innebygginger, bilder, lyd" </b></summary>
AI er ikke bare fullføring av chat. Utviklere må generere bilder, transkribere lyd, lage innbygginger for RAG, omrangere dokumenter og moderere innhold. Hver API har et annet endepunkt og format.
**Hvordan OmniRoute løser det:**
- **Innbygging** — `/v1/embeddings` med 6 leverandører og 9+ modeller
- **Bildegenerering** — `/v1/images/generations` med 10 leverandører og 20+ modeller (OpenAI, xAI, Together, Fireworks, Nebius, Hyperbolic, NanoBanana, Antigravity, SD WebUI, ComfyUI)
- **Tekst-til-video** — `/v1/videos/generations` — ComfyUI (AnimateDiff, SVD) og SD WebUI
- **Tekst-til-musikk** — `/v1/music/generations` — ComfyUI (Stable Audio Open, MusicGen)
- **Lydtranskripsjon** — `/v1/audio/transcriptions` — Whisper + Nvidia NIM, HuggingFace, Qwen3
- **Tekst-til-tale** — `/v1/audio/speech` — ElevenLabs, Nvidia NIM, HuggingFace, Coqui, Tortoise, Qwen3, + eksisterende leverandører
- **Moderasjoner** — `/v1/moderations` — Innholdssikkerhetssjekker
- **Rerangering** — `/v1/rerank` — Rerangering av dokumentrelevans
- **Responses API** — Full `/v1/responses`-støtte for Codex
</details>
<details>
<summary><b>🧪 14. "Jeg har ingen måte å teste og sammenligne kvalitet på tvers av modeller" </b></summary>
Utviklere ønsker å vite hvilken modell som er best for deres brukssituasjon kode, oversettelse, resonnement men det går tregt å sammenligne manuelt. Det finnes ingen integrerte evalueringsverktøy.
**Hvordan OmniRoute løser det:**
- **LLM-evalueringer** — Gyldent sett-testing med 10 forhåndslastede tilfeller som dekker hilsener, matematikk, geografi, kodegenerering, JSON-overholdelse, oversettelse, nedskrivning, sikkerhetsavslag
- **4 matchstrategier** — `exact`, `contains`, `regex`, `custom` (JS-funksjon)
- **Translator Playground Test Bench** — Batchtesting med flere innganger og forventede utganger, sammenligning på tvers av leverandører
- **Chattetester** — Full rundtur med visuell responsgjengivelse
- **Live Monitor** — Sanntidsstrøm av alle forespørsler som strømmer gjennom proxyen
</details>
<details>
<summary><b>📈 15. "Jeg trenger å skalere uten å miste ytelse" </b></summary>
Når forespørselsvolumet vokser, genererer de samme spørsmålene dupliserte kostnader uten å bufre. Uten idempotens, dupliserte forespørsler om avfallsbehandling. Satsgrenser per leverandør må respekteres.
**Hvordan OmniRoute løser det:**
- **Semantisk hurtigbuffer** — To-lags cache (signatur + semantisk) reduserer kostnader og ventetid
- **Request Idempotency** — 5s dedupliseringsvindu for identiske forespørsler
- **Deteksjon av hastighetsgrense** - RPM per leverandør, minimum gap og maksimal samtidig sporing
- **Redigerbare frekvensgrenser** — Konfigurerbare standardinnstillinger i Innstillinger → Motstandsdyktighet med utholdenhet
- **API Key Validation Cache** — 3-lags cache for produksjonsytelse
- **Helsedashbord med telemetri** — p50/p95/p99-forsinkelse, hurtigbufferstatistikk, oppetid
</details>
<details>
<summary><b>🤖 16. "Jeg vil kontrollere modellatferd globalt" </b></summary>
Utviklere som vil ha alle svar på et spesifikt språk, med en bestemt tone, eller som ønsker å begrense resonnement-tokens. Å konfigurere dette i hvert verktøy/hver forespørsel er upraktisk.
**Hvordan OmniRoute løser det:**
- **System Prompt Injection** — Global forespørsel brukt på alle forespørsler
- **Thinking Budget Validation** — Reasoning token allocation control per request (passthrough, auto, custom, adaptive)
- **6 rutingstrategier** — Globale strategier som bestemmer hvordan forespørsler distribueres
- **Wildcard-ruter** — `provider/*`-mønstre ruter dynamisk til enhver leverandør
- **Kombo aktiver/deaktiver veksle** — Veksle kombinasjoner direkte fra dashbordet
- **Tilkobling av leverandør** — Aktiver/deaktiver alle tilkoblinger for en leverandør med ett klikk
- **Blokkerte leverandører** — Ekskluder spesifikke leverandører fra `/v1/models`-oppføringen
</details>
<details>
<summary><b>🧰 17. "Jeg trenger MCP-verktøy som førsteklasses produktegenskaper" </b></summary>
Mange AI-gatewayer avslører MCP bare som en skjult implementeringsdetalj. Team trenger et synlig, håndterbart driftslag.
**Hvordan OmniRoute løser det:**
- MCP vises i dashbordnavigasjons- og endepunktprotokollfanen
- Dedikert MCP-administrasjonsside med prosess, verktøy, omfang og revisjon
- Innebygd hurtigstart for `omniroute --mcp` og klient onboarding
</details>
<details>
<summary><b>🧠 18. "Jeg trenger A2A-orkestrering med synkronisering + strømoppgavestier" </b></summary>
Agentarbeidsflyter trenger både direkte svar og langvarig strømmet utførelse med livssykluskontroll.
**Hvordan OmniRoute løser det:**
- A2A JSON-RPC-endepunkt (`POST /a2a`) med `message/send` og `message/stream`
- SSE-streaming med forplantning av terminaltilstand
- Oppgavelivssyklus-APIer for `tasks/get` og `tasks/cancel`
</details>
<details>
<summary><b>🛰️ 19. "Jeg trenger ekte MCP-prosesshelse, ikke gjettet status" </b></summary>
Operasjonelle team må vite om MCP faktisk er i live, ikke bare om en API er tilgjengelig.
**Hvordan OmniRoute løser det:**
- Runtime hjerteslag-fil med PID, tidsstempler, transport, verktøytelling og omfangsmodus
- MCP status API som kombinerer hjerteslag + nylig aktivitet
- UI-statuskort for prosess/oppetid/hjerteslag
</details>
<details>
<summary><b>📋 20. "Jeg trenger reviderbar MCP-verktøykjøring" </b></summary>
Når verktøy muterer konfigurasjon eller utløser operasjonshandlinger, trenger teamene rettsmedisinsk sporbarhet.
**Hvordan OmniRoute løser det:**
- SQLite-støttet revisjonslogging for MCP-verktøykall
- Filtrerer etter verktøy, suksess/fiasko, API-nøkkel og paginering
- Dashboard revisjonstabell + statistikkendepunkter for automatisering
</details>
<details>
<summary><b>🔐 21. "Jeg trenger scoped MCP-tillatelser per integrasjon" </b></summary>
Ulike klienter bør ha minst privilegert tilgang til verktøykategorier.
**Hvordan OmniRoute løser det:**
- 9 granulære MCP-skoper for kontrollert verktøytilgang
- Håndhevelse av omfang og synlighet i MCP-administrasjonsgrensesnittet
- Sikker standardstilling for operativt verktøy
</details>
<details>
<summary><b>⚙️ 22. "Jeg trenger operasjonelle kontroller uten å omdistribuere" </b></summary>
Lag trenger raske endringer i kjøretiden under hendelser eller kostnadshendelser.
**Hvordan OmniRoute løser det:**
- Bytt kombinasjonsaktivering direkte fra MCP-dashbordet
- Bruk robusthetsprofiler fra forhåndsdefinerte policypakker
- Tilbakestill strømbryterens tilstand fra samme driftspanel
</details>
<details>
<summary><b>🔄 23. «I need live A2A task lifecycle synibility and cancellation»</b></summary>
Uten livssyklussynlighet blir oppgavehendelser vanskelig å triage.
**Hvordan OmniRoute løser det:**
- Oppgaveliste/filtrering etter tilstand/ferdighet med paginering
- Drill-down på oppgavemetadata, hendelser og artefakter
- Sluttpunkt for kansellering av oppgave og UI-handling med bekreftelse
</details>
<details>
<summary><b>🌊 24. «Jeg trenger aktive strømmålinger for A2A-last» </b></summary>
Strømmearbeidsflyter krever operasjonell innsikt i samtidighet og direkteforbindelser.
**Hvordan OmniRoute løser det:**
- Aktive strømtellere integrert i A2A-status
- Tidsstempel for siste oppgave og antall per stat
- A2A dashbordkort for operasjonsovervåking i sanntid
</details>
<details>
<summary><b>🪪 25. "Jeg trenger standard agentoppdagelse for klienter" </b></summary>
Eksterne klienter og orkestratorer trenger maskinlesbare metadata for onboarding.
**Hvordan OmniRoute løser det:**
- Agentkort eksponert på `/.well-known/agent.json`
- Evner og ferdigheter vist i ledelsens brukergrensesnitt
- A2A status API inkluderer oppdagelsesmetadata for automatisering
</details>
<details>
<summary><b>🧭 26. "Jeg trenger protokolloppdagbarhet i produktets UX" </b></summary>
Hvis brukere ikke kan oppdage protokolloverflater, faller kvaliteten på adopsjon og støtte.
**Hvordan OmniRoute løser det:**
- Sidefeltoppføringer for MCP og A2A
- Endpoint-side Protokoller-fane med hurtigstart og status
- Lenker fra oversikt til dedikerte styringsdashboards
</details>
<details>
<summary><b>🧪 27. "Jeg trenger ende-til-ende protokollvalidering med ekte klienter" </b></summary>
Mock-tester er ikke nok til å validere protokollkompatibilitet før utgivelse.
**Hvordan OmniRoute løser det:**
- E2E-suite som starter opp app og bruker ekte MCP SDK-klienttransport
- A2A-klient tester for å oppdage, sende, streame, hente og kansellere flyter
- Krysssjekk påstander mot MCP-revisjon og A2A-oppgave-APIer
</details>
<details>
<summary><b>📡 28. «Jeg trenger enhetlig observerbarhet på tvers av alle grensesnitt» </b></summary>
Å dele observerbarhet etter protokoll skaper blinde flekker og lengre MTTR.
**Hvordan OmniRoute løser det:**
- Samlede dashboards/logger/analyse i ett produkt
- Helse + revisjon + forespørsel om telemetri på tvers av OpenAI-, MCP- og A2A-lag
- Operasjonelle APIer for status og automatisering
</details>
<details>
<summary><b>💼 29. "Jeg trenger én kjøretid for proxy + verktøy + agentorkestrering" </b></summary>
Å kjøre mange separate tjenester øker driftskostnadene og feilmodusene.
**Hvordan OmniRoute løser det:**
- OpenAI-kompatibel proxy, MCP-server og A2A-server i én stabel
- Delt autentisering, robusthet, datalagring og observerbarhet
- Konsekvent policymodell på tvers av alle interaksjonsflater
</details>
<details>
<summary><b>🚀 30. "Jeg trenger å sende agentiske arbeidsflyter uten limkodespredning" </b></summary>
Lag mister hastighet når de setter sammen flere ad-hoc-tjenester og skript.
**Hvordan OmniRoute løser det:**
- Enhetlig endepunktstrategi for kunder og agenter
- Innebygde brukergrensesnitt for protokolladministrasjon og røykvalideringsveier
- Produksjonsklare fundamenter (sikkerhet, logging, robusthet, backup)
</details>
### Eksempel på Playbooks (integrerte brukstilfeller)
**Playbook A: Maksimer betalt abonnement + billig backup**
```txt
Combo: "maximize-claude"
1. cc/claude-opus-4-6
2. glm/glm-4.7
3. if/kimi-k2-thinking
Monthly cost: $20 + small backup spend
Outcome: higher quality, near-zero interruption
```
**Playbook B: Nullkostnadskodestabel**
```txt
Combo: "free-forever"
1. gc/gemini-3-flash
2. if/kimi-k2-thinking
3. qw/qwen3-coder-plus
Monthly cost: $0
Outcome: stable free coding workflow
```
**Playbook C: 24/7 alltid aktiv reservekjede**
```txt
Combo: "always-on"
1. cc/claude-opus-4-6
2. cx/gpt-5.2-codex
3. glm/glm-4.7
4. minimax/MiniMax-M2.1
5. if/kimi-k2-thinking
Outcome: deep fallback depth for deadline-critical workloads
```
**Playbook D: Agentoperasjoner med MCP + A2A**
```txt
1) Start MCP transport (`omniroute --mcp`) for tool-driven operations
2) Run A2A tasks via `message/send` and `message/stream`
3) Observe via /dashboard/mcp and /dashboard/a2a
4) Control incidents with resilience profile + task cancellation
```
---
## ⚡ Hurtigstart
**1. Installer globalt:**
@@ -251,7 +781,7 @@ docker compose --profile cli up -d
---
## 🖥️ Desktop App — Offline & Always-On
## 🖥️
> 🆕 **NEW!** OmniRoute is now available as a **native desktop application** for Windows, macOS, and Linux.
@@ -298,67 +828,6 @@ npm run electron:build:linux # Linux (.AppImage)
---
## 🎯 Brukssaker
### Sak 1: "Jeg har Claude Pro-abonnement"
**Problem:** Kvoten utløper ubrukt, satsgrenser under tung koding
```
Combo: "maximize-claude"
1. cc/claude-opus-4-6 (use subscription fully)
2. glm/glm-4.7 (cheap backup when quota out)
3. if/kimi-k2-thinking (free emergency fallback)
Monthly cost: $20 (subscription) + ~$5 (backup) = $25 total
vs. $20 + hitting limits = frustration
```
### Tilfelle 2: "Jeg vil ha null kostnad"
**Problem:** Har ikke råd til abonnementer, trenger pålitelig AI-koding
```
Combo: "free-forever"
1. gc/gemini-3-flash (180K free/month)
2. if/kimi-k2-thinking (unlimited free)
3. qw/qwen3-coder-plus (unlimited free)
Monthly cost: $0
Quality: Production-ready models
```
### Tilfelle 3: "Jeg trenger 24/7 koding, ingen avbrudd"
**Problem:** Tidsfrister, har ikke råd til nedetid
```
Combo: "always-on"
1. cc/claude-opus-4-6 (best quality)
2. cx/gpt-5.2-codex (second subscription)
3. glm/glm-4.7 (cheap, resets daily)
4. minimax/MiniMax-M2.1 (cheapest, 5h reset)
5. if/kimi-k2-thinking (free unlimited)
Result: 5 layers of fallback = zero downtime
```
### Tilfelle 4: "Jeg vil ha GRATIS AI i OpenClaw"
**Problem:** Trenger AI-assistent i meldingsapper, helt gratis
```
Combo: "openclaw-free"
1. if/glm-4.7 (unlimited free)
2. if/minimax-m2.1 (unlimited free)
3. if/kimi-k2-thinking (unlimited free)
Monthly cost: $0
Access via: WhatsApp, Telegram, Slack, Discord, iMessage, Signal...
```
---
## 💡 Nøkkelfunksjoner
### 🧠 Kjerneruting og intelligens
@@ -374,6 +843,8 @@ Access via: WhatsApp, Telegram, Slack, Discord, iMessage, Signal...
| 🧩 **Egendefinerte modeller** | Legg til hvilken som helst modell-ID til en hvilken som helst leverandør |
| 🌐 **Wildcard-ruter** | Ruter `provider/*`-mønstre til enhver leverandør dynamisk |
| 🧠 **Tenkebudsjett** | Passthrough, auto, egendefinerte og adaptive moduser for resonnerende modeller |
| 🔀 **Model Aliases** | Auto-forward deprecated model IDs to current replacements (built-in + custom) |
| ⚡ **Background Degradation** | Auto-route background tasks (titles, summaries) to cheaper models |
| 💬 **Systemprompt-injeksjon** | Global systemforespørsel brukt på alle forespørsler |
| 📄 **Responses API** | Full støtte for OpenAI Responses API (`/v1/responses`) for Codex |
@@ -393,12 +864,15 @@ Access via: WhatsApp, Telegram, Slack, Discord, iMessage, Signal...
| Funksjon | Hva det gjør |
| --------------------------------- | ----------------------------------------------------------------------------- |
| 🔌 **Circuit Breaker** | Automatisk åpning/lukking per leverandør med konfigurerbare terskler |
| 🎯 **Endpoint-Aware Models** | Custom models declare supported endpoints + API format |
| 🛡️ **Anti-tordenflokk** | Mutex + semaforhastighetsgrense for API-nøkkelleverandører |
| 🧠 **Semantisk cache** | To-lags cache (signatur + semantisk) reduserer kostnader og ventetid |
| ⚡ **Be om idempotens** | 5s dedup-vindu for dupliserte forespørsler |
| 🔒 **TLS-fingeravtrykkspoofing** | Omgå TLS-basert botdeteksjon via wreq-js |
| 🌐 **IP-filtrering** | Tillatelsesliste/blokkeringsliste for API-tilgangskontroll |
| 📊 **Redigerbare satsgrenser** | Konfigurerbar RPM, min gap og maks samtidig på systemnivå |
| 💾 **Rate Limit Persistence** | Learned limits survive restarts via SQLite with 60s debounce + 24h staleness |
| 🔄 **Token Refresh Resilience** | Per-provider circuit breaker (5 fails→30min) + 30s timeout per attempt |
| 🛡 **API-endepunktbeskyttelse** | Auth-gate + leverandørblokkering for `/models`-endepunktet |
| 🔒 **Proxy-synlighet** | Fargekodede merker: 🟢 global, 🟡 leverandør, 🔵 per tilkobling med IP-skjerm |
| 🌐 **3-nivå proxy-konfigurasjon** | Konfigurer proxyer på globalt nivå, per leverandør eller per tilkoblingsnivå |
@@ -517,6 +991,27 @@ OmniRoute inkluderer en kraftig innebygd oversetterlekeplass med **4 moduser** f
</details>
## 🧪 Evalueringer (evalueringer)
OmniRoute inkluderer et innebygd evalueringsrammeverk for å teste LLM-responskvaliteten mot et gyldent sett. Få tilgang til den via **Analytics → Evals** i dashbordet.
### Innebygd gyldent sett
Det forhåndsinstallerte "OmniRoute Golden Set" inneholder 10 testcases som dekker:
- Hilsen, matematikk, geografi, kodegenerering
- JSON-formatoverholdelse, oversettelse, markdown
- Sikkerhetsavslag (skadelig innhold), telling, boolsk logikk
### Evalueringsstrategier
| Strategi | Beskrivelse | Eksempel |
| ---------- | --------------------------------------------------------------------- | -------------------------------- |
| `exact` | Utdata må samsvare nøyaktig med | `"4"` |
| `contains` | Utdata må inneholde understreng (uavhengig av store og små bokstaver) | `"Paris"` |
| `regex` | Utdata må samsvare med regulært uttrykksmønster | `"1.*2.*3"` |
| `custom` | Egendefinert JS-funksjon returnerer true/false | `(output) => output.length > 10` |
---
## 📖 Oppsettveiledning
@@ -799,104 +1294,64 @@ Settings → API Configuration:
---
## 📊 Tilgjengelige modeller
## 🐛 Feilsøking
<details>
<summary><b>Se alle tilgjengelige modeller</b></summary>
<summary><b>Klikk for å utvide feilsøkingsveiledningen</b></summary>
**Claude-kode (`cc/`)** - Pro/Max:
**«Språkmodellen ga ikke meldinger»**
- `cc/claude-opus-4-6`
- `cc/claude-sonnet-4-5-20250929`
- `cc/claude-haiku-4-5-20251001`
- Leverandørkvoten er oppbrukt → Sjekk dashboardkvotesporing
- Løsning: Bruk kombinasjonsalternativ eller bytt til et billigere nivå
**Kodex (`cx/`)** - Pluss/Proff:
**Satsbegrensning**
- `cx/gpt-5.2-codex`
- `cx/gpt-5.1-codex-max`
- Abonnementskvote ut → Fallback til GLM/MiniMax
- Legg til kombinasjon: `cc/claude-opus-4-6 → glm/glm-4.7 → if/kimi-k2-thinking`
**Gemini CLI (`gc/`)** - GRATIS:
**OAuth-token er utløpt**
- `gc/gemini-3-flash-preview`
- `gc/gemini-2.5-pro`
- Automatisk oppdatering av OmniRoute
- Hvis problemene vedvarer: Dashboard → Leverandør → Koble til på nytt
**GitHub Copilot (`gh/`)**:
**Høye kostnader**
- `gh/gpt-5`
- `gh/claude-4.5-sonnet`
- Sjekk bruksstatistikk i Dashboard → Kostnader
- Bytt primærmodell til GLM/MiniMax
- Bruk gratis nivå (Gemini CLI, iFlow) for ikke-kritiske oppgaver
**NVIDIA NIM (`nvidia/`)** - GRATIS kreditter:
**Dashboard åpnes på feil port**
- `nvidia/llama-3.3-70b-instruct`
- `nvidia/mistral-7b-instruct`
- 50+ flere modeller på [build.nvidia.com](https://build.nvidia.com)
- Sett `PORT=20128` og `NEXT_PUBLIC_BASE_URL=http://localhost:20128`
**GLM (`glm/`)** - $0,6/1M:
**Skysynkroniseringsfeil**
- `glm/glm-4.7`
- Bekreft at `BASE_URL` peker på løpeforekomsten din
- Bekreft `CLOUD_URL` poeng til det forventede skyendepunktet
- Hold `NEXT_PUBLIC_*` verdier på linje med verdiene på tjenersiden
**MiniMax (`minimax/`)** - $0,2/1M:
**Første pålogging fungerer ikke**
- `minimax/MiniMax-M2.1`
- Sjekk `INITIAL_PASSWORD` i `.env`
- Hvis det ikke er angitt, er reservepassordet `123456`
**iFlow (`if/`)** - GRATIS:
**Ingen forespørselslogger**
- `if/kimi-k2-thinking`
- `if/qwen3-coder-plus`
- `if/deepseek-r1`
- `if/glm-4.7`
- `if/minimax-m2`
- Sett `ENABLE_REQUEST_LOGS=true` i `.env`
**Qwen (`qw/`)** - GRATIS:
**Test viser «Ugyldig» for OpenAI-kompatible leverandører**
- `qw/qwen3-coder-plus`
- `qw/qwen3-coder-flash`
- Mange leverandører avslører ikke et `/models`-endepunkt
- OmniRoute v1.0.6+ inkluderer reservevalidering via chatfullføringer
- Sørg for at basis-URL inkluderer suffikset `/v1`
**Kiro (`kr/`)** - GRATIS:
- `kr/claude-sonnet-4.5`
- `kr/claude-haiku-4.5`
**OpenRouter (`or/`)** - 100+ modeller:
- `or/anthropic/claude-4-sonnet`
- `or/google/gemini-2.5-pro`
- Alle modeller fra [openrouter.ai/models](https://openrouter.ai/models)
</details>
---
## 🧪 Evalueringer (evalueringer)
OmniRoute inkluderer et innebygd evalueringsrammeverk for å teste LLM-responskvaliteten mot et gyldent sett. Få tilgang til den via **Analytics → Evals** i dashbordet.
### Innebygd gyldent sett
Det forhåndsinstallerte "OmniRoute Golden Set" inneholder 10 testcases som dekker:
- Hilsen, matematikk, geografi, kodegenerering
- JSON-formatoverholdelse, oversettelse, markdown
- Sikkerhetsavslag (skadelig innhold), telling, boolsk logikk
### Evalueringsstrategier
| Strategi | Beskrivelse | Eksempel |
| ---------- | --------------------------------------------------------------------- | -------------------------------- |
| `exact` | Utdata må samsvare nøyaktig med | `"4"` |
| `contains` | Utdata må inneholde understreng (uavhengig av store og små bokstaver) | `"Paris"` |
| `regex` | Utdata må samsvare med regulært uttrykksmønster | `"1.*2.*3"` |
| `custom` | Egendefinert JS-funksjon returnerer true/false | `(output) => output.length > 10` |
---
## 🔐 OAuth em Servidor Remoto (Ekstern OAuth-oppsett)
### 🔐 OAuth
<a name="oauth-em-servidor-remoto"></a>
> **⚠️ VIKTIG for bruk av OmniRoute med VPS/Docker/server-fjernkontroll**
### Hva med OAuth gjør Antigravity / Gemini CLI falha em servidores remotos?
### OAuth
Os testedores **Antigravity** og **Gemini CLI** usam **Google OAuth 2.0** for autenticação. O Google exige que a `redirect_uri` usada no fluxo OAuth seja **exatamente** uma das URIs pre-cadastradas no Google Cloud Console do aplicativo.
@@ -981,64 +1436,11 @@ Se não quiser criar credenciais próprias agora, ainda é possível usar o flux
> Este workaround funciona porque or código de autorização na URL é válido independente do redirect ter carregado or não.
---
## 🐛 Feilsøking
<details>
<summary><b>Klikk for å utvide feilsøkingsveiledningen</b></summary>
**«Språkmodellen ga ikke meldinger»**
- Leverandørkvoten er oppbrukt → Sjekk dashboardkvotesporing
- Løsning: Bruk kombinasjonsalternativ eller bytt til et billigere nivå
**Satsbegrensning**
- Abonnementskvote ut → Fallback til GLM/MiniMax
- Legg til kombinasjon: `cc/claude-opus-4-6 → glm/glm-4.7 → if/kimi-k2-thinking`
**OAuth-token er utløpt**
- Automatisk oppdatering av OmniRoute
- Hvis problemene vedvarer: Dashboard → Leverandør → Koble til på nytt
**Høye kostnader**
- Sjekk bruksstatistikk i Dashboard → Kostnader
- Bytt primærmodell til GLM/MiniMax
- Bruk gratis nivå (Gemini CLI, iFlow) for ikke-kritiske oppgaver
**Dashboard åpnes på feil port**
- Sett `PORT=20128` og `NEXT_PUBLIC_BASE_URL=http://localhost:20128`
**Skysynkroniseringsfeil**
- Bekreft at `BASE_URL` peker på løpeforekomsten din
- Bekreft `CLOUD_URL` poeng til det forventede skyendepunktet
- Hold `NEXT_PUBLIC_*` verdier på linje med verdiene på tjenersiden
**Første pålogging fungerer ikke**
- Sjekk `INITIAL_PASSWORD` i `.env`
- Hvis det ikke er angitt, er reservepassordet `123456`
**Ingen forespørselslogger**
- Sett `ENABLE_REQUEST_LOGS=true` i `.env`
**Test viser «Ugyldig» for OpenAI-kompatible leverandører**
- Mange leverandører avslører ikke et `/models`-endepunkt
- OmniRoute v1.0.6+ inkluderer reservevalidering via chatfullføringer
- Sørg for at basis-URL inkluderer suffikset `/v1`
</details>
---
## 🛠️ Tech Stack
## 🛠️
- **Kjøretid**: Node.js 1822 LTS (⚠️ Node.js 24+ støttes **ikke**`better-sqlite3` native binærfiler er inkompatible)
- **Språk**: TypeScript 5.9 — **100 % TypeScript** på tvers av `src/` og `open-sse/` (v1.0.6)
@@ -1090,7 +1492,7 @@ Se não quiser criar credenciais próprias agora, ainda é possível usar o flux
---
## 🗺️ Veikart
## 🗺️
OmniRoute har **210+ funksjoner planlagt** på tvers av flere utviklingsfaser. Her er nøkkelområdene:
@@ -1115,18 +1517,6 @@ OmniRoute har **210+ funksjoner planlagt** på tvers av flere utviklingsfaser. H
---
## 📧 Støtte
> 💬 **Bli med i fellesskapet vårt!** [WhatsApp Group](https://chat.whatsapp.com/JI7cDQ1GyaiDHhVBpLxf8b?mode=gi_t) — Få hjelp, del tips og hold deg oppdatert.
- **Nettsted**: [omniroute.online](https://omniroute.online)
- **GitHub**: [github.com/diegosouzapw/OmniRoute](https://github.com/diegosouzapw/OmniRoute)
- **Problemer**: [github.com/diegosouzapw/OmniRoute/issues](https://github.com/diegosouzapw/OmniRoute/issues)
- **WhatsApp**: [Community Group](https://chat.whatsapp.com/JI7cDQ1GyaiDHhVBpLxf8b?mode=gi_t)
- **Originalt prosjekt**: [9router by decolua](https://github.com/decolua/9router)
---
## 👥 Bidragsytere
[![Contributors](https://contrib.rocks/image?repo=diegosouzapw/OmniRoute&max=100&columns=20&anon=1)](https://github.com/diegosouzapw/OmniRoute/graphs/contributors)
@@ -1176,85 +1566,6 @@ MIT-lisens - se [LICENSE](LICENSE) for detaljer.
---
---
## 🇧🇷 OmniRoute — Gateway de IA Gratuito
<a name="-omniroute--gateway-de-ia-gratuito"></a>
### Nunca pare de codar. Roteamento inteligente for **modeller av IA GRATUITOS og de baixo custo** com reserve automático.
_Seu proxy universal de API — et endepunkt, 36+ tester, null nedetid._
### 🌐 Internacionalização (i18n)
O dashbordet for OmniRoute støtter **multiplos idiomas**. Atualmente disponível em:
| Idioma | Kode | Status |
| --------------------- | ------- | ----------- |
| 🇺🇸 Engelsk | `en` | ✅ Komplett |
| 🇧🇷 Português (Brasil) | `pt-BR` | ✅ Komplett |
**Para trocar o idioma:** Clique no selector de idioma (🇺🇸 EN) no header do dashboard → selection o idioma desejado.
**Tillegg et nytt uttrykk:**
1. Crie `src/i18n/messages/{codigo}.json` baseado em `en.json`
2. Adicione o código em `src/i18n/config.ts``LOCALES` og `LANGUAGES`
3. Reinicie o servidor
### ⚡ Início Rápido
```bash
# Instalar via npm
npx omniroute@latest
# Ou rodar do código-fonte
cp .env.example .env
npm install
PORT=20128 NEXT_PUBLIC_BASE_URL=http://localhost:20128 npm run dev
```
### 🐳 Docker
```bash
docker run -d --name omniroute -p 20128:20128 diegosouzapw/omniroute:latest
```
### 🔑 Funcionalidades Principais
- **36+ provedores de IA** - Claude, GPT, Gemini, Llama, Qwen, DeepSeek, e mais
- **Roteamento inteligente** — Fallback automático entre provedores
- **Tradução de formato** — OpenAI ↔ Claude ↔ Gemini automaticamente
- **Multi-conta** — Multiplas-innhold for testing com seleção inteligente
- **Cache semântico** — Reduz custos e latência
- **OAuth automático** — Tokens renovam automaticamente
- **Personlig kombinasjoner** — 6 estratégias de roteamento
- **Dashboard komplett** — Monitoramento, logger, analyser, konfigurasjoner
- **CLI Tools** — Konfigurer Claude Code, Codex, Cursor, Cline com um clique
- **100 % TypeScript** — Código limpo e tipado
### 📖 Dokumentasjon
| Documento | Beskrivelse |
| ----------------------------------------------- | -------------------------------------------- |
| [Guia do Usuário](docs/USER_GUIDE.md) | Provedores, combos, CLI, distribuere |
| [Referência da API](docs/API_REFERENCE.md) | Todos os endepunkter med eksempler |
| [Solução de Problemas](docs/TROUBLESHOOTING.md) | Problemas comuns e soluções |
| [Arquitetura](docs/ARCHITECTURE.md) | Arquitetura e internos do sistema |
| [Contribuição](CONTRIBUTING.md) | Oppsett av desenvolvimento og retningslinjer |
| [Deploy em VM](docs/VM_DEPLOYMENT_GUIDE.md) | Fullfør: VM + nginx + Cloudflare |
### 📧 Støtte
> 💬 **Entre para a comunidade!** [Grupo WhatsApp](https://chat.whatsapp.com/JI7cDQ1GyaiDHhVBpLxf8b?mode=gi_t) — Tire dúvidas, compartilhe dicas e fique atualizado.
- **Nettsted**: [omniroute.online](https://omniroute.online)
- **GitHub**: [github.com/diegosouzapw/OmniRoute](https://github.com/diegosouzapw/OmniRoute)
- **Problemer**: [github.com/diegosouzapw/OmniRoute/issues](https://github.com/diegosouzapw/OmniRoute/issues)
---
<div align="center">
<sub>Bygget med ❤️ for utviklere som koder 24/7</sub>
<br/>

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -7,7 +7,7 @@
_Seu proxy de API universal — um endpoint, 36+ provedores, zero tempo de inatividade._
**Chat Completions • Embeddings • Geração de Imagem • Áudio • Reranking • 100% TypeScript**
**Chat Completions • Embeddings • Geração de Imagem • Vídeo • Música • Áudio • Reranking • 100% TypeScript**
---
@@ -110,6 +110,35 @@ _Conecte qualquer IDE ou ferramenta CLI com IA através do OmniRoute — gateway
---
## 🖼️
<div align="center">
<img src="./docs/screenshots/MainOmniRoute.png" alt="OmniRoute" width="800"/>
</div>
---
## 📸
<details>
<summary><b>...</b></summary>
| # | # |
| ----- | ---------------------------------------- |
| **1** | ![1](docs/screenshots/01-providers.png) |
| **2** | ![2](docs/screenshots/02-combos.png) |
| **3** | ![3](docs/screenshots/03-analytics.png) |
| **4** | ![4](docs/screenshots/04-health.png) |
| **5** | ![5](docs/screenshots/05-translator.png) |
| **6** | ![6](docs/screenshots/06-settings.png) |
| **7** | ![7](docs/screenshots/07-cli-tools.png) |
| **8** | ![8](docs/screenshots/08-usage.png) |
| **9** | ![9](docs/screenshots/09-endpoint.png) |
</details>
---
## 🤔 Por que OmniRoute?
**Pare de desperdiçar dinheiro e bater em limites:**
@@ -128,6 +157,18 @@ _Conecte qualquer IDE ou ferramenta CLI com IA através do OmniRoute — gateway
---
## 📧 Suporte
> 💬 **Participe da comunidade!** [Grupo WhatsApp](https://chat.whatsapp.com/JI7cDQ1GyaiDHhVBpLxf8b?mode=gi_t) — Tire dúvidas, compartilhe dicas e fique atualizado.
- **Website**: [omniroute.online](https://omniroute.online)
- **GitHub**: [github.com/diegosouzapw/OmniRoute](https://github.com/diegosouzapw/OmniRoute)
- **Issues**: [github.com/diegosouzapw/OmniRoute/issues](https://github.com/diegosouzapw/OmniRoute/issues)
- **WhatsApp**: [Grupo da Comunidade](https://chat.whatsapp.com/JI7cDQ1GyaiDHhVBpLxf8b?mode=gi_t)
- **Projeto Original**: [9router por decolua](https://github.com/decolua/9router)
---
## 🔄 Como Funciona
```
@@ -157,6 +198,473 @@ Resultado: Nunca pare de programar, custo mínimo
---
## 🎯 O que o OmniRoute resolve — 30 dores reais e casos de uso
> **Todo desenvolvedor que usa ferramentas de IA enfrenta esses problemas diariamente.** O OmniRoute foi criado para resolver todos eles, desde estouro de custos e bloqueios regionais até operações de protocolo e observabilidade de nível produção.
<details>
<summary><b>💸 1. "Pago uma assinatura cara e ainda sou interrompido por limites"</b></summary>
Desenvolvedores pagam de $20 a $200/mês por Claude Pro, Codex Pro ou GitHub Copilot. Mesmo pagando, há teto de cota, limite de 5h, limites semanais ou por minuto. No meio da sessão de coding, o provedor para de responder e o desenvolvedor perde fluxo e produtividade.
**Como o OmniRoute resolve isso:**
- **Fallback Inteligente em 4 Tiers** — Se a cota de assinatura acabar, redireciona automaticamente para API Key → Barato → Gratuito sem intervenção manual
- **Rastreamento de Cota em Tempo Real** — Exibe consumo de tokens ao vivo com contagem regressiva de reset (5h, diário, semanal)
- **Suporte Multi-Conta** — Várias contas por provedor com round-robin automático; quando uma esgota, passa para a próxima
- **Combos Personalizados** — Cadeias de fallback customizáveis com 6 estratégias (fill-first, round-robin, P2C, aleatório, least-used, cost-optimized)
- **Cotas Business do Codex** — Monitoramento de cota de workspace Business/Team direto no dashboard
</details>
<details>
<summary><b>🔌 2. "Preciso usar múltiplos provedores, mas cada um tem uma API diferente"</b></summary>
OpenAI usa um formato, Claude (Anthropic) usa outro, Gemini usa outro. Se o dev quer testar modelos de provedores diferentes ou fazer fallback entre eles, precisa reconfigurar SDKs, trocar endpoints e lidar com formatos incompatíveis. Provedores customizados (FriendLI, NIM) também têm endpoints não padronizados.
**Como o OmniRoute resolve isso:**
- **Endpoint Unificado** — Um único `http://localhost:20128/v1` serve como proxy para 36+ provedores
- **Tradução de Formato** — Conversão automática e transparente: OpenAI ↔ Claude ↔ Gemini ↔ Responses API
- **Sanitização de Resposta** — Remove campos fora do padrão (`x_groq`, `usage_breakdown`, `service_tier`) que quebram OpenAI SDK v1.83+
- **Normalização de Roles** — Converte `developer``system` para provedores não-OpenAI; `system``user` para GLM/ERNIE
- **Extração de Tags Think** — Extrai blocos `<think>` de modelos como DeepSeek R1 para `reasoning_content` padronizado
- **Saída Estruturada no Gemini** — Conversão automática de `json_schema``responseMimeType`/`responseSchema`
- **`stream` padrão `false`** — Alinha com a especificação OpenAI e evita SSE inesperado em SDKs Python/Rust/Go
</details>
<details>
<summary><b>🌐 3. "Meu provedor de IA bloqueia minha região/país"</b></summary>
Provedores como OpenAI/Codex bloqueiam acesso em determinadas regiões. Usuários recebem erros como `unsupported_country_region_territory` durante OAuth e conexões de API. Isso é especialmente frustrante para desenvolvedores de países emergentes.
**Como o OmniRoute resolve isso:**
- **Config de Proxy em 3 Níveis** — Proxy configurável em nível global (todo tráfego), por provedor e por conexão/chave
- **Badges de Proxy por Cor** — Indicadores visuais: 🟢 proxy global, 🟡 proxy do provedor, 🔵 proxy da conexão, sempre mostrando o IP
- **Troca de Token OAuth via Proxy** — O fluxo OAuth também passa pelo proxy, resolvendo `unsupported_country_region_territory`
- **Teste de Conexão via Proxy** — Testes usam o proxy configurado (sem bypass direto)
- **Suporte SOCKS5** — Suporte completo a proxy SOCKS5 para roteamento de saída
- **Spoofing de Impressão TLS** — Fingerprint TLS estilo navegador via `wreq-js` para contornar detecção de bot
</details>
<details>
<summary><b>🆓 4. "Quero usar IA para programar, mas não tenho dinheiro"</b></summary>
Nem todo mundo pode pagar $20200/mês em assinaturas de IA. Estudantes, devs de países emergentes, hobistas e freelancers precisam de acesso a modelos de qualidade com custo zero.
**Como o OmniRoute resolve isso:**
- **Provedores Gratuitos nativos** — Suporte nativo a provedores 100% free: iFlow (8 modelos ilimitados), Qwen (3 ilimitados), Kiro (Claude grátis), Gemini CLI (180K/mês grátis)
- **Combos Apenas Gratuitos** — Cadeia `gc/gemini-3-flash → if/kimi-k2-thinking → qw/qwen3-coder-plus` = $0/mês com zero downtime
- **Créditos Gratuitos NVIDIA NIM** — 1000 créditos free integrados
- **Estratégia Cost Optimized** — Estratégia que escolhe automaticamente o provedor mais barato disponível
</details>
<details>
<summary><b>🔒 5. "Preciso proteger meu gateway de IA contra acesso não autorizado"</b></summary>
Ao expor um gateway de IA na rede (LAN, VPS, Docker), qualquer pessoa com o endereço pode consumir tokens/cota do desenvolvedor. Sem proteção, as APIs ficam vulneráveis a uso indevido, prompt injection e abuso.
**Como o OmniRoute resolve isso:**
- **Gestão de API Keys** — Geração, rotação e escopo por provedor com página dedicada em `/dashboard/api-manager`
- **Permissões por Modelo** — Restringe chaves a modelos específicos (`openai/*`, padrões wildcard), com toggle Allow All/Restrict
- **Proteção de Endpoint de API** — Exige chave para `/v1/models` e bloqueia provedores específicos da listagem
- **Auth Guard + CSRF Protection** — Todas as rotas do dashboard protegidas com middleware `withAuth` + tokens CSRF
- **Rate Limiter** — Limite por IP com janelas configuráveis
- **Filtragem por IP** — Allowlist/blocklist para controle de acesso
- **Proteção contra Prompt Injection** — Sanitização contra padrões maliciosos
- **Criptografia AES-256-GCM** — Credenciais criptografadas em repouso
</details>
<details>
<summary><b>🛑 6. "Meu provedor caiu e eu perdi meu fluxo de programação"</b></summary>
Provedores de IA podem ficar instáveis, retornar erro 5xx ou atingir limites temporários de taxa. Se o dev depende de um único provedor, ele é interrompido. Sem circuit breaker, retries repetidos podem derrubar a aplicação.
**Como o OmniRoute resolve isso:**
- **Circuit Breaker por modelo** — Abre/fecha automaticamente com limiares e cooldown configuráveis (Closed/Open/Half-Open)
- **Exponential Backoff** — Atrasos progressivos de retry
- **Anti-Thundering Herd** — Proteção com mutex + semáforo contra tempestade de retries concorrentes
- **Cadeias de Fallback em Combo** — Se o primário falhar, avança automaticamente na cadeia sem intervenção
- **Circuit Breaker de Combo** — Desativa automaticamente provedores com falha dentro da cadeia
- **Health Dashboard** — Monitoramento de uptime, estados de breaker, lockouts, estatísticas de cache e latência p50/p95/p99
</details>
<details>
<summary><b>🔧 7. "Configurar cada ferramenta de IA é tedioso e repetitivo"</b></summary>
Desenvolvedores usam Cursor, Claude Code, Codex CLI, OpenClaw, Gemini CLI, Kilo Code... Cada ferramenta pede configuração diferente (endpoint, chave, modelo). Reconfigurar ao trocar de provedor ou modelo é perda de tempo.
**Como o OmniRoute resolve isso:**
- **Dashboard de Ferramentas CLI** — Página dedicada com setup em 1 clique para Claude Code, Codex CLI, OpenClaw, Kilo Code, Antigravity e Cline
- **Gerador de Config do GitHub Copilot** — Gera `chatLanguageModels.json` para VS Code com seleção em lote de modelos
- **Onboarding Wizard** — Fluxo guiado de 4 etapas para novos usuários
- **Um endpoint para todos os modelos** — Configure `http://localhost:20128/v1` uma vez e acesse 36+ provedores
</details>
<details>
<summary><b>🔑 8. "Gerenciar tokens OAuth de múltiplos provedores é um caos"</b></summary>
Claude Code, Codex, Gemini CLI e Copilot usam OAuth 2.0 com tokens que expiram. Devs precisam reautenticar o tempo todo e lidar com erros como `client_secret is missing`, `redirect_uri_mismatch` e falhas em servidores remotos. OAuth em LAN/VPS é especialmente problemático.
**Como o OmniRoute resolve isso:**
- **Auto Token Refresh** — Tokens OAuth renovados em background antes da expiração
- **OAuth 2.0 (PKCE) nativo** — Fluxo automático para Claude Code, Codex, Gemini CLI, Copilot, Kiro, Qwen e iFlow
- **OAuth Multi-Conta** — Múltiplas contas por provedor via extração de JWT/ID token
- **Correções OAuth LAN/Remoto** — Detecção de IP privado para `redirect_uri` + modo manual de URL para servidores remotos
- **OAuth atrás de Nginx** — Usa `window.location.origin` para compatibilidade com reverse proxy
- **Guia de OAuth Remoto** — Passo a passo para credenciais Google Cloud em VPS/Docker
</details>
<details>
<summary><b>📊 9. "Não sei quanto estou gastando nem onde"</b></summary>
Desenvolvedores usam vários provedores pagos, mas não têm visão unificada de gastos. Cada provedor tem seu dashboard de billing, sem consolidação. Custos inesperados podem se acumular.
**Como o OmniRoute resolve isso:**
- **Dashboard de Analytics de Custo** — Rastreamento de custo por token e gestão de orçamento por provedor
- **Limites de Orçamento por Tier** — Teto de gasto por tier que aciona fallback automático
- **Configuração de Preço por Modelo** — Preços configuráveis por modelo
- **Estatísticas de Uso por API Key** — Contagem de requests e timestamp de último uso por chave
- **Analytics Dashboard** — Cards, gráfico de uso por modelo e tabela de provedores com taxa de sucesso e latência
</details>
<details>
<summary><b>🐛 10. "Não consigo diagnosticar erros e problemas nas chamadas de IA"</b></summary>
Quando uma chamada falha, o dev não sabe se foi rate limit, token expirado, formato incorreto ou erro do provedor. Logs ficam fragmentados em terminais diferentes. Sem observabilidade, debug vira tentativa e erro.
**Como o OmniRoute resolve isso:**
- **Dashboard de Logs Unificado** — 4 abas: Request Logs, Proxy Logs, Audit Logs e Console
- **Visualizador de Console** — Viewer em tempo real estilo terminal com níveis por cor, auto-scroll, busca e filtros
- **Proxy Logs em SQLite** — Logs persistentes que sobrevivem a reinícios do servidor
- **Playground do Tradutor** — 4 modos de debug: Playground (tradução), Chat Tester (round-trip), Test Bench (lote), Live Monitor (tempo real)
- **Telemetria de Request** — Latência p50/p95/p99 + rastreamento por X-Request-Id
- **Logging em Arquivo com Rotação** — Interceptador de console grava tudo em JSON com rotação por tamanho
</details>
<details>
<summary><b>🏗️ 11. "Implantar e manter o gateway é complexo"</b></summary>
Instalar, configurar e manter um proxy de IA em ambientes diferentes (local, VPS, Docker, cloud) exige muito trabalho. Problemas como caminhos hardcoded, `EACCES` em diretórios, conflito de portas e build cross-platform aumentam a fricção.
**Como o OmniRoute resolve isso:**
- **Instalação global via npm** — `npm install -g omniroute && omniroute` e pronto
- **Docker Multi-Platform** — AMD64 + ARM64 nativo (Apple Silicon, AWS Graviton, Raspberry Pi)
- **Perfis Docker Compose** — `base` (sem ferramentas CLI) e `cli` (com Claude Code, Codex, OpenClaw)
- **App Desktop Electron** — App nativo para Windows/macOS/Linux com bandeja, auto-start e modo offline
- **Modo de Porta Separada** — API e Dashboard em portas distintas para cenários avançados (reverse proxy, rede de containers)
- **Cloud Sync** — Sincronização de configuração entre dispositivos via Cloudflare Workers
- **Backups de DB** — Backup automático, restauração, export e import de todas as configurações
</details>
<details>
<summary><b>🌍 12. "A interface é só em inglês e meu time não fala inglês"</b></summary>
Times em países não anglófonos, especialmente na América Latina, Ásia e Europa, sofrem com interfaces só em inglês. A barreira de idioma reduz adoção e aumenta erros de configuração.
**Como o OmniRoute resolve isso:**
- **i18n do Dashboard — 30 idiomas** — Mais de 500 chaves traduzidas, incluindo árabe, búlgaro, dinamarquês, alemão, espanhol, finlandês, francês, hebraico, hindi, húngaro, indonésio, italiano, japonês, coreano, malaio, holandês, norueguês, polonês, português (PT/BR), romeno, russo, eslovaco, sueco, tailandês, ucraniano, vietnamita, chinês, filipino e inglês
- **Suporte RTL** — Suporte right-to-left para árabe e hebraico
- **READMEs multilíngues** — 30 traduções completas de documentação
- **Seletor de Idioma** — Ícone de globo no header para troca em tempo real
</details>
<details>
<summary><b>🔄 13. "Preciso de mais do que chat: embeddings, imagens, áudio"</b></summary>
IA não é só chat completion. Devs precisam gerar imagens, transcrever áudio, criar embeddings para RAG, reranquear documentos e moderar conteúdo. Cada API tem endpoint e formato diferentes.
**Como o OmniRoute resolve isso:**
- **Embeddings** — `/v1/embeddings` com 6 provedores e 9+ modelos
- **Geração de Imagem** — `/v1/images/generations` com 10 provedores e 20+ modelos (OpenAI, xAI, Together, Fireworks, Nebius, Hyperbolic, NanoBanana, Antigravity, SD WebUI, ComfyUI)
- **Texto para Vídeo** — `/v1/videos/generations` com ComfyUI (AnimateDiff, SVD) e SD WebUI
- **Texto para Música** — `/v1/music/generations` com ComfyUI (Stable Audio Open, MusicGen)
- **Transcrição de Áudio** — `/v1/audio/transcriptions` com Whisper + Nvidia NIM, HuggingFace e Qwen3
- **Texto para Fala (TTS)** — `/v1/audio/speech` com ElevenLabs, Nvidia NIM, HuggingFace, Coqui, Tortoise e Qwen3
- **Moderações** — `/v1/moderations` para checagens de segurança de conteúdo
- **Reranking** — `/v1/rerank` para relevância de documentos
- **Responses API** — Suporte completo a `/v1/responses` para Codex
</details>
<details>
<summary><b>🧪 14. "Não tenho como testar e comparar qualidade entre modelos"</b></summary>
Desenvolvedores querem saber qual modelo é melhor para cada caso de uso (código, tradução, raciocínio), mas comparar manualmente é lento. Não existem ferramentas integradas de avaliação na maioria das stacks.
**Como o OmniRoute resolve isso:**
- **Avaliações de LLM** — Golden set com 10 casos pré-carregados cobrindo saudação, matemática, geografia, geração de código, conformidade JSON, tradução, markdown e recusa de conteúdo inseguro
- **4 Estratégias de Match** — `exact`, `contains`, `regex`, `custom` (função JS)
- **Test Bench do Playground do Tradutor** — Testes em lote com múltiplas entradas/saídas esperadas e comparação entre provedores
- **Chat Tester** — Round-trip completo com renderização visual da resposta
- **Live Monitor** — Stream em tempo real de todas as requisições que passam pelo proxy
</details>
<details>
<summary><b>📈 15. "Preciso escalar sem perder performance"</b></summary>
À medida que o volume cresce, sem cache as mesmas perguntas geram custos duplicados. Sem idempotência, requisições duplicadas desperdiçam processamento. Também é necessário respeitar rate limits por provedor.
**Como o OmniRoute resolve isso:**
- **Cache Semântico** — Cache em duas camadas (assinatura + semântico) para reduzir custo e latência
- **Idempotência de Request** — Janela de deduplicação de 5s para requisições idênticas
- **Detecção de Rate Limit** — Rastreamento por provedor de RPM, intervalo mínimo e concorrência máxima
- **Rate Limits Editáveis** — Padrões configuráveis em Settings → Resilience com persistência
- **Cache de Validação de API Key** — Cache em 3 camadas para performance em produção
- **Health Dashboard com Telemetria** — Latência p50/p95/p99, estatísticas de cache e uptime
</details>
<details>
<summary><b>🤖 16. "Quero controlar o comportamento dos modelos globalmente"</b></summary>
Desenvolvedores podem querer todas as respostas em um idioma específico, com tom específico ou com limite de tokens de raciocínio. Configurar isso em cada ferramenta/requisição é impraticável.
**Como o OmniRoute resolve isso:**
- **Injeção de System Prompt** — Prompt global aplicado a todas as requisições
- **Validação de Thinking Budget** — Controle de alocação de tokens de raciocínio por requisição (passthrough, auto, custom, adaptive)
- **6 Estratégias de Roteamento** — Estratégias globais que definem como as requisições são distribuídas
- **Wildcard Router** — Padrões `provider/*` roteiam dinamicamente para qualquer provedor
- **Toggle de Combo** — Ativa/desativa combos diretamente no dashboard
- **Toggle de Provedor** — Ativa/desativa todas as conexões de um provedor com um clique
- **Provedores Bloqueados** — Exclui provedores específicos da listagem de `/v1/models`
</details>
<details>
<summary><b>🧰 17. "Preciso de ferramentas MCP como capacidades de primeira classe do produto"</b></summary>
Muitos gateways de IA expõem MCP apenas como detalhe de implementação oculto. Times precisam de uma camada operacional visível e gerenciável.
**Como o OmniRoute resolve isso:**
- MCP aparece no menu do dashboard e na aba de protocolos em Endpoint
- Página dedicada de gestão MCP com processo, ferramentas, escopos e auditoria
- Quick-start embutido para `omniroute --mcp` e onboarding de clientes
</details>
<details>
<summary><b>🧠 18. "Preciso de orquestração A2A com caminhos síncronos + streaming"</b></summary>
Fluxos de agentes precisam de respostas diretas e também de execuções longas com streaming e controle de ciclo de vida.
**Como o OmniRoute resolve isso:**
- Endpoint A2A JSON-RPC (`POST /a2a`) com `message/send` e `message/stream`
- Streaming SSE com propagação de estado terminal
- APIs de ciclo de vida de tarefas para `tasks/get` e `tasks/cancel`
</details>
<details>
<summary><b>🛰️ 19. "Preciso de saúde real do processo MCP, não status estimado"</b></summary>
Times operacionais precisam saber se o MCP está realmente ativo, não apenas se uma API está respondendo.
**Como o OmniRoute resolve isso:**
- Arquivo de heartbeat em runtime com PID, timestamps, transporte, quantidade de ferramentas e modo de escopo
- API de status MCP combinando heartbeat + atividade recente
- Cards de status na UI para processo/uptime/frescor do heartbeat
</details>
<details>
<summary><b>📋 20. "Preciso de execução auditável das ferramentas MCP"</b></summary>
Quando ferramentas alteram configuração ou disparam ações operacionais, os times precisam de rastreabilidade forense.
**Como o OmniRoute resolve isso:**
- Auditoria de chamadas MCP baseada em SQLite
- Filtros por ferramenta, sucesso/falha, chave de API e paginação
- Tabela de auditoria no dashboard + endpoints de métricas para automação
</details>
<details>
<summary><b>🔐 21. "Preciso de permissões MCP por escopo para cada integração"</b></summary>
Clientes diferentes devem operar com privilégio mínimo por categoria de ferramenta.
**Como o OmniRoute resolve isso:**
- 9 escopos MCP granulares para controle de acesso às ferramentas
- Aplicação de escopo e visibilidade na UI de gestão MCP
- Postura segura por padrão para operações sensíveis
</details>
<details>
<summary><b>⚙️ 22. "Preciso de controles operacionais sem redeploy"</b></summary>
Times precisam de mudanças rápidas em runtime durante incidentes e picos de custo.
**Como o OmniRoute resolve isso:**
- Troca de ativação de combo direto no dashboard de MCP
- Aplicação de perfis de resiliência via pacotes de política prontos
- Reset de circuit breaker no mesmo painel operacional
</details>
<details>
<summary><b>🔄 23. "Preciso de visibilidade ao vivo do ciclo de vida A2A e cancelamento"</b></summary>
Sem visibilidade de lifecycle, incidentes de tarefas ficam difíceis de investigar e corrigir.
**Como o OmniRoute resolve isso:**
- Listagem/filtragem de tarefas por estado/skill com paginação
- Drill-down de metadados, eventos e artefatos da tarefa
- Endpoint de cancelamento + ação de UI com confirmação
</details>
<details>
<summary><b>🌊 24. "Preciso de métricas de streams ativos para carga A2A"</b></summary>
Fluxos em streaming exigem visão operacional de concorrência e conexões ativas.
**Como o OmniRoute resolve isso:**
- Contadores de streams ativos integrados ao status A2A
- Timestamp da última tarefa e contagens por estado
- Cards no dashboard A2A para monitoramento operacional em tempo real
</details>
<details>
<summary><b>🪪 25. "Preciso de descoberta padrão de agente para clientes"</b></summary>
Clientes externos e orquestradores precisam de metadados legíveis por máquina para onboarding automático.
**Como o OmniRoute resolve isso:**
- Agent Card exposto em `/.well-known/agent.json`
- Capacidades e skills exibidas na UI de gestão
- API de status A2A inclui metadados de descoberta para automação
</details>
<details>
<summary><b>🧭 26. "Preciso de descobribilidade de protocolos na experiência do produto"</b></summary>
Se os usuários não encontram superfícies de protocolo, adoção e qualidade de suporte caem.
**Como o OmniRoute resolve isso:**
- Entradas MCP e A2A na sidebar
- Aba Protocolos em Endpoint com quick-start e status
- Links do overview para dashboards dedicados de gestão
</details>
<details>
<summary><b>🧪 27. "Preciso de validação end-to-end de protocolo com clientes reais"</b></summary>
Testes mockados não bastam para validar compatibilidade de protocolo antes do release.
**Como o OmniRoute resolve isso:**
- Suíte E2E que sobe a aplicação e usa transporte real do SDK MCP
- Testes de cliente A2A para discovery, send, stream, get e cancel
- Cross-check das validações com APIs de auditoria MCP e tarefas A2A
</details>
<details>
<summary><b>📡 28. "Preciso de observabilidade unificada em todas as interfaces"</b></summary>
Separar observabilidade por protocolo cria pontos cegos e aumenta o MTTR.
**Como o OmniRoute resolve isso:**
- Dashboards/logs/analytics unificados no mesmo produto
- Saúde + auditoria + telemetria de requisição em OpenAI, MCP e A2A
- APIs operacionais de status para automação
</details>
<details>
<summary><b>💼 29. "Preciso de um runtime único para proxy + tools + orquestração de agentes"</b></summary>
Manter vários serviços separados aumenta custo operacional e modos de falha.
**Como o OmniRoute resolve isso:**
- Proxy OpenAI-compatible, servidor MCP e servidor A2A na mesma stack
- Autenticação, resiliência, armazenamento e observabilidade compartilhados
- Modelo de políticas consistente em todas as superfícies de interação
</details>
<details>
<summary><b>🚀 30. "Preciso entregar workflows agênticos sem sprawl de glue code"</b></summary>
Times perdem velocidade quando precisam costurar múltiplos serviços e scripts ad hoc.
**Como o OmniRoute resolve isso:**
- Estratégia de endpoint unificada para clientes e agentes
- UIs de gestão de protocolo e fluxos de validação/smoke embutidos
- Base pronta para produção (segurança, logging, resiliência e backup)
</details>
### Exemplos de Playbooks (Casos de Uso Integrados)
**Playbook A: Maximizar assinatura paga + backup barato**
```txt
Combo: "maximize-claude"
1. cc/claude-opus-4-6
2. glm/glm-4.7
3. if/kimi-k2-thinking
Custo mensal: $20 + pequeno gasto de backup
Resultado: qualidade maior, interrupção quase zero
```
**Playbook B: Stack de programação com custo zero**
```txt
Combo: "free-forever"
1. gc/gemini-3-flash
2. if/kimi-k2-thinking
3. qw/qwen3-coder-plus
Custo mensal: $0
Resultado: fluxo de coding gratuito e estável
```
## ⚡ Início Rápido
**1. Instale globalmente:**
@@ -249,7 +757,7 @@ docker compose --profile cli up -d
---
## 🖥️ Aplicativo Desktop — Offline e Sempre Ativo
## 🖥️
> 🆕 **NOVO!** O OmniRoute agora está disponível como **aplicativo desktop nativo** para Windows, macOS e Linux.
@@ -311,110 +819,71 @@ Quando minimizado, o OmniRoute fica na bandeja do sistema com ações rápidas:
---
## 🎯 Casos de Uso
### Caso 1: "Tenho assinatura Claude Pro"
**Problema:** Cota expira sem uso, limites de taxa durante programação intensa
```
Combo: "maximize-claude"
1. cc/claude-opus-4-6 (usar assinatura ao máximo)
2. glm/glm-4.7 (backup barato quando a cota acabar)
3. if/kimi-k2-thinking (fallback de emergência gratuito)
Custo mensal: $20 (assinatura) + ~$5 (backup) = $25 total
vs. $20 + bater em limites = frustração
```
### Caso 2: "Quero custo zero"
**Problema:** Não pode pagar assinaturas, precisa de IA confiável para programar
```
Combo: "free-forever"
1. gc/gemini-3-flash (180K grátis/mês)
2. if/kimi-k2-thinking (ilimitado grátis)
3. qw/qwen3-coder-plus (ilimitado grátis)
Custo mensal: $0
Qualidade: Modelos prontos para produção
```
### Caso 3: "Preciso programar 24/7, sem interrupções"
**Problema:** Prazos apertados, não pode ter tempo de inatividade
```
Combo: "always-on"
1. cc/claude-opus-4-6 (melhor qualidade)
2. cx/gpt-5.2-codex (segunda assinatura)
3. glm/glm-4.7 (barato, reset diário)
4. minimax/MiniMax-M2.1 (mais barato, reset 5h)
5. if/kimi-k2-thinking (gratuito ilimitado)
Resultado: 5 camadas de fallback = zero tempo de inatividade
```
### Caso 4: "Quero IA GRATUITA no OpenClaw"
**Problema:** Precisa de assistente de IA em aplicativos de mensagens, completamente gratuito
```
Combo: "openclaw-free"
1. if/glm-4.7 (ilimitado grátis)
2. if/minimax-m2.1 (ilimitado grátis)
3. if/kimi-k2-thinking (ilimitado grátis)
Custo mensal: $0
Acesso via: WhatsApp, Telegram, Slack, Discord, iMessage, Signal...
```
---
## 💡 Funcionalidades Principais
### 🧭 Gestão MCP + A2A (Camada Operacional)
A maioria dos gateways de IA expõe MCP/A2A apenas como endpoints “escondidos”. O OmniRoute traz operação de primeira classe para os dois protocolos:
- **Descoberta na interface** — Entradas `MCP` e `A2A` na sidebar e aba `Protocolos` na página de Endpoint com quick-start e cartões de status.
- **Painel operacional MCP** (`/dashboard/mcp`) — Status real do processo por heartbeat, inventário de ferramentas/scopes, auditoria com filtros e controles operacionais (trocar combo, aplicar perfil de resiliência, resetar breakers).
- **Painel operacional A2A** (`/dashboard/a2a`) — Visão do agent card, ciclo de vida de tarefas por estado, contagem de streams ativos, drill-down/cancelamento de tasks e smoke tests de `message/send` e `message/stream`.
- **APIs de monitoramento** — Endpoints `/api/mcp/*` e `/api/a2a/*` para status, tasks, auditoria e automações externas.
Por que isso é relevante:
- **Um runtime, três papéis**: router/proxy OpenAI-compatible + servidor de ferramentas MCP + servidor agente A2A.
- **Governança unificada**: autenticação, auditoria e controles de resiliência compartilhados.
- **Operação confiável**: times conseguem validar, monitorar e depurar comportamento dos protocolos sem sair do produto.
### 🧠 Roteamento e Inteligência
| Funcionalidade | O que Faz |
| ----------------------------------------- | ------------------------------------------------------------------------------- |
| 🎯 **Fallback Inteligente 4 Tiers** | Auto-roteamento: Assinatura → API Key → Barato → Gratuito |
| 📊 **Rastreamento de Cota em Tempo Real** | Contagem de tokens ao vivo + countdown de reset por provedor |
| 🔄 **Tradução de Formato** | OpenAI ↔ Claude ↔ Gemini ↔ Cursor ↔ Kiro transparente |
| 👥 **Suporte Multi-Conta** | Múltiplas contas por provedor com seleção inteligente |
| 🔄 **Renovação Automática de Token** | Tokens OAuth renovam automaticamente com retry |
| 🎨 **Combos Personalizados** | 6 estratégias: fill-first, round-robin, p2c, random, least-used, cost-optimized |
| 🧩 **Modelos Personalizados** | Adicione qualquer ID de modelo a qualquer provedor |
| 🌐 **Roteador Wildcard** | Roteie padrões `provider/*` para qualquer provedor dinamicamente |
| 🧠 **Budget de Raciocínio** | Modos passthrough, auto, custom e adaptativo para modelos de raciocínio |
| 💬 **Injeção de System Prompt** | System prompt global aplicado em todas as requisições |
| 📄 **API Responses** | Suporte completo à API Responses da OpenAI (`/v1/responses`) para Codex |
| Funcionalidade | O que Faz |
| ----------------------------------------- | ---------------------------------------------------------------------------------- |
| 🎯 **Fallback Inteligente 4 Tiers** | Auto-roteamento: Assinatura → API Key → Barato → Gratuito |
| 📊 **Rastreamento de Cota em Tempo Real** | Contagem de tokens ao vivo + countdown de reset por provedor |
| 🔄 **Tradução de Formato** | OpenAI ↔ Claude ↔ Gemini ↔ Cursor ↔ Kiro transparente |
| 👥 **Suporte Multi-Conta** | Múltiplas contas por provedor com seleção inteligente |
| 🔄 **Renovação Automática de Token** | Tokens OAuth renovam automaticamente com retry |
| 🎨 **Combos Personalizados** | 6 estratégias: fill-first, round-robin, p2c, random, least-used, cost-optimized |
| 🧩 **Modelos Personalizados** | Adicione qualquer ID de modelo a qualquer provedor |
| 🌐 **Roteador Wildcard** | Roteie padrões `provider/*` para qualquer provedor dinamicamente |
| 🧠 **Budget de Raciocínio** | Modos passthrough, auto, custom e adaptativo para modelos de raciocínio |
| <EFBFBD> **Aliases de Modelo** | Redireciona IDs de modelos depreciados para substitutos atuais (built-in + custom) |
| **Degradação em Background** | Redireciona tarefas em background (títulos, resumos) para modelos mais baratos |
| <20>💬 **Injeção de System Prompt** | System prompt global aplicado em todas as requisições |
| 📄 **API Responses** | Suporte completo à API Responses da OpenAI (`/v1/responses`) para Codex |
### 🎵 APIs Multi-Modal
| Funcionalidade | O que Faz |
| --------------------------- | ---------------------------------------------------- |
| 🖼️ **Geração de Imagem** | `/v1/images/generations`4 provedores, 9+ modelos |
| 📐 **Embeddings** | `/v1/embeddings` — 6 provedores, 9+ modelos |
| 🎤 **Transcrição de Áudio** | `/v1/audio/transcriptions`Compatível com Whisper |
| 🔊 **Texto para Fala** | `/v1/audio/speech`Síntese de áudio multi-provedor |
| 🛡️ **Moderações** | `/v1/moderations`Verificações de segurança |
| 🔀 **Reranking** | `/v1/rerank` — Reranking de relevância de documentos |
| Funcionalidade | O que Faz |
| --------------------------- | -------------------------------------------------------------------------------- |
| 🖼️ **Geração de Imagem** | `/v1/images/generations`10 provedores, 20+ modelos (cloud + local) |
| 📐 **Embeddings** | `/v1/embeddings` — 6 provedores, 9+ modelos |
| 🎤 **Transcrição de Áudio** | `/v1/audio/transcriptions`Whisper + Nvidia NIM, HuggingFace, Qwen3 |
| 🔊 **Texto para Fala** | `/v1/audio/speech`ElevenLabs, Nvidia NIM, HuggingFace, Coqui, Tortoise, Qwen3 |
| 🎬 **Geração de Vídeo** | `/v1/videos/generations`ComfyUI (AnimateDiff, SVD), SD WebUI |
| 🎵 **Geração de Música** | `/v1/music/generations` — ComfyUI (Stable Audio Open, MusicGen) |
| 🛡️ **Moderações** | `/v1/moderations` — Verificações de segurança |
| 🔀 **Reranking** | `/v1/rerank` — Reranking de relevância de documentos |
### 🛡️ Resiliência e Segurança
| Funcionalidade | O que Faz |
| ---------------------------------- | --------------------------------------------------------------------------- |
| 🔌 **Circuit Breaker** | Auto-abertura/fechamento por provedor com limites configuráveis |
| 🛡️ **Anti-Thundering Herd** | Mutex + semáforo rate-limit para provedores com API key |
| 🧠 **Cache Semântico** | Cache de duas camadas (assinatura + semântico) reduz custo e latência |
| **Idempotência de Requisição** | Janela de dedup de 5s para requisições duplicadas |
| 🔒 **Spoofing de Fingerprint TLS** | Bypass de detecção de bot via TLS com wreq-js |
| 🌐 **Filtragem de IP** | Allowlist/blocklist para controle de acesso à API |
| 📊 **Rate Limits Editáveis** | RPM, gap mínimo e concorrência máxima configuráveis |
| 🛡 **Proteção de Endpoint API** | Gateway de Auth + bloqueio de provedores para o endpoint `/models` |
| 🔒 **Visibilidade de Proxy** | Badges coloridos: 🟢 global, 🟡 provedor, 🔵 por-conexão com exibição de IP |
| 🌐 **Proxy em 3 Níveis** | Configure proxies em nível global, por provedor ou por conexão |
| Funcionalidade | O que Faz |
| ----------------------------------- | ----------------------------------------------------------------------------- |
| 🔌 **Circuit Breaker** | Trip/recover por modelo com limites configuráveis |
| 🎯 **Endpoint-Aware Models** | Custom models declare supported endpoints + API format |
| 🛡️ **Anti-Thundering Herd** | Mutex + semáforo rate-limit para provedores com API key |
| 🧠 **Cache Semântico** | Cache de duas camadas (assinatura + semântico) reduz custo e latência |
| **Idempotência de Requisição** | Janela de dedup de 5s para requisições duplicadas |
| 🔒 **Spoofing de Fingerprint TLS** | Bypass de detecção de bot via TLS com wreq-js |
| 🌐 **Filtragem de IP** | Allowlist/blocklist para controle de acesso à API |
| 📊 **Rate Limits Editáveis** | RPM, gap mínimo e concorrência máxima configuráveis |
| 💾 **Persistência de Rate Limits** | Limites aprendidos persistem via SQLite com debounce de 60s + 24h de validade |
| 🔄 **Resiliência de Token Refresh** | Circuit breaker por provedor (5 falhas→30min) + timeout de 30s por tentativa |
| 🛡 **Proteção de Endpoint API** | Gateway de Auth + bloqueio de provedores para o endpoint `/models` |
| 🔒 **Visibilidade de Proxy** | Badges coloridos: 🟢 global, 🟡 provedor, 🔵 por-conexão com exibição de IP |
| 🌐 **Proxy em 3 Níveis** | Configure proxies em nível global, por provedor ou por conexão |
### 📊 Observabilidade e Analytics
@@ -526,6 +995,29 @@ O OmniRoute inclui um poderoso Playground de Tradução integrado com **4 modos*
---
## 🧪 Avaliações (Evals)
OmniRoute inclui um framework de avaliação integrado para testar a qualidade de respostas de LLM contra um conjunto golden. Acesse via **Analytics → Evals** no dashboard.
### Conjunto Golden Integrado
O "OmniRoute Golden Set" pré-carregado contém 10 casos de teste cobrindo:
- Saudações, matemática, geografia, geração de código
- Conformidade de formato JSON, tradução, markdown
- Recusa de segurança (conteúdo prejudicial), contagem, lógica booleana
### Estratégias de Avaliação
| Estratégia | Descrição | Exemplo |
| ---------- | ---------------------------------------------- | -------------------------------- |
| `exact` | Saída deve corresponder exatamente | `"4"` |
| `contains` | Saída deve conter substring (case-insensitive) | `"Paris"` |
| `regex` | Saída deve corresponder ao padrão regex | `"1.*2.*3"` |
| `custom` | Função JS customizada retorna true/false | `(output) => output.length > 10` |
---
## 📖 Guia de Configuração
<details>
@@ -806,97 +1298,6 @@ Configurações → Configuração de API:
---
## 📊 Modelos Disponíveis
<details>
<summary><b>Ver todos os modelos disponíveis</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/`)** - GRATUITO:
- `gc/gemini-3-flash-preview`
- `gc/gemini-2.5-pro`
**GitHub Copilot (`gh/`)**:
- `gh/gpt-5`
- `gh/claude-4.5-sonnet`
**NVIDIA NIM (`nvidia/`)** - Créditos GRATUITOS:
- `nvidia/llama-3.3-70b-instruct`
- `nvidia/mistral-7b-instruct`
- 50+ mais modelos em [build.nvidia.com](https://build.nvidia.com)
**GLM (`glm/`)** - $0.6/1M:
- `glm/glm-4.7`
**MiniMax (`minimax/`)** - $0.2/1M:
- `minimax/MiniMax-M2.1`
**iFlow (`if/`)** - GRATUITO:
- `if/kimi-k2-thinking`
- `if/qwen3-coder-plus`
- `if/deepseek-r1`
- `if/glm-4.7`
- `if/minimax-m2`
**Qwen (`qw/`)** - GRATUITO:
- `qw/qwen3-coder-plus`
- `qw/qwen3-coder-flash`
**Kiro (`kr/`)** - GRATUITO:
- `kr/claude-sonnet-4.5`
- `kr/claude-haiku-4.5`
**OpenRouter (`or/`)** - 100+ modelos:
- `or/anthropic/claude-4-sonnet`
- `or/google/gemini-2.5-pro`
- Qualquer modelo de [openrouter.ai/models](https://openrouter.ai/models)
</details>
---
## 🧪 Avaliações (Evals)
OmniRoute inclui um framework de avaliação integrado para testar a qualidade de respostas de LLM contra um conjunto golden. Acesse via **Analytics → Evals** no dashboard.
### Conjunto Golden Integrado
O "OmniRoute Golden Set" pré-carregado contém 10 casos de teste cobrindo:
- Saudações, matemática, geografia, geração de código
- Conformidade de formato JSON, tradução, markdown
- Recusa de segurança (conteúdo prejudicial), contagem, lógica booleana
### Estratégias de Avaliação
| Estratégia | Descrição | Exemplo |
| ---------- | ---------------------------------------------- | -------------------------------- |
| `exact` | Saída deve corresponder exatamente | `"4"` |
| `contains` | Saída deve conter substring (case-insensitive) | `"Paris"` |
| `regex` | Saída deve corresponder ao padrão regex | `"1.*2.*3"` |
| `custom` | Função JS customizada retorna true/false | `(output) => output.length > 10` |
---
## 🐛 Solução de Problemas
<details>
@@ -952,7 +1353,7 @@ O "OmniRoute Golden Set" pré-carregado contém 10 casos de teste cobrindo:
---
## 🛠️ Stack Tecnológico
## 🛠️
- **Runtime**: Node.js 20+
- **Linguagem**: TypeScript 5.9 — **100% TypeScript** em `src/` e `open-sse/` (v1.0.6)
@@ -1004,7 +1405,7 @@ O "OmniRoute Golden Set" pré-carregado contém 10 casos de teste cobrindo:
---
## 🗺️ Roadmap
## 🗺️
O OmniRoute tem **210+ funcionalidades planejadas** em múltiplas fases de desenvolvimento. Áreas principais:
@@ -1029,18 +1430,6 @@ O OmniRoute tem **210+ funcionalidades planejadas** em múltiplas fases de desen
---
## 📧 Suporte
> 💬 **Participe da comunidade!** [Grupo WhatsApp](https://chat.whatsapp.com/JI7cDQ1GyaiDHhVBpLxf8b?mode=gi_t) — Tire dúvidas, compartilhe dicas e fique atualizado.
- **Website**: [omniroute.online](https://omniroute.online)
- **GitHub**: [github.com/diegosouzapw/OmniRoute](https://github.com/diegosouzapw/OmniRoute)
- **Issues**: [github.com/diegosouzapw/OmniRoute/issues](https://github.com/diegosouzapw/OmniRoute/issues)
- **WhatsApp**: [Grupo da Comunidade](https://chat.whatsapp.com/JI7cDQ1GyaiDHhVBpLxf8b?mode=gi_t)
- **Projeto Original**: [9router por decolua](https://github.com/decolua/9router)
---
## 👥 Contribuidores
[![Contributors](https://contrib.rocks/image?repo=diegosouzapw/OmniRoute&max=100&columns=20&anon=1)](https://github.com/diegosouzapw/OmniRoute/graphs/contributors)

File diff suppressed because it is too large Load Diff

View File

@@ -3,8 +3,6 @@
# 🚀 OmniRoute — Gateway-ul gratuit AI
🌐 **[English](#-omniroute--the-free-ai-gateway)** | **[Português (BR)](#-omniroute--gateway-de-ia-gratuito)**
### Nu opriți niciodată codificarea. Dirijare inteligentă către **modele AI GRATUITE și cu costuri reduse** cu rezervă automată.
_Proxy-ul dvs. universal API - un punct final, peste 36 de furnizori, zero timpi de nefuncționare._
@@ -112,6 +110,35 @@ _Conectați orice instrument IDE sau CLI alimentat de AI prin OmniRoute — gate
---
## 🖼️
<div align="center">
<img src="./docs/screenshots/MainOmniRoute.png" alt="OmniRoute" width="800"/>
</div>
---
## 📸
<details>
<summary><b>...</b></summary>
| # | # |
| ----- | ---------------------------------------- |
| **1** | ![1](docs/screenshots/01-providers.png) |
| **2** | ![2](docs/screenshots/02-combos.png) |
| **3** | ![3](docs/screenshots/03-analytics.png) |
| **4** | ![4](docs/screenshots/04-health.png) |
| **5** | ![5](docs/screenshots/05-translator.png) |
| **6** | ![6](docs/screenshots/06-settings.png) |
| **7** | ![7](docs/screenshots/07-cli-tools.png) |
| **8** | ![8](docs/screenshots/08-usage.png) |
| **9** | ![9](docs/screenshots/09-endpoint.png) |
</details>
---
## 🤔 De ce OmniRoute?
**Nu mai risipi banii și nu mai atingeți limitele:**
@@ -130,6 +157,18 @@ _Conectați orice instrument IDE sau CLI alimentat de AI prin OmniRoute — gate
---
## 📧 Suport
> 💬 **Alăturați-vă comunității noastre!** [WhatsApp Group](https://chat.whatsapp.com/JI7cDQ1GyaiDHhVBpLxf8b?mode=gi_t) — Obțineți ajutor, împărtășiți sfaturi și fiți la curent.
- **Site web**: [omniroute.online](https://omniroute.online)
- **GitHub**: [github.com/diegosouzapw/OmniRoute](https://github.com/diegosouzapw/OmniRoute)
- **Probleme**: [github.com/diegosouzapw/OmniRoute/issues](https://github.com/diegosouzapw/OmniRoute/issues)
- **WhatsApp**: [Community Group](https://chat.whatsapp.com/JI7cDQ1GyaiDHhVBpLxf8b?mode=gi_t)
- **Proiect original**: [9router by decolua](https://github.com/decolua/9router)
---
## 🔄 Cum funcționează
```
@@ -159,6 +198,499 @@ Result: Never stop coding, minimal cost
---
## 🎯 Ce rezolvă OmniRoute — 30 de puncte reale de durere și cazuri de utilizare
> **Fiecare dezvoltator care folosește instrumente AI se confruntă zilnic cu aceste probleme.** OmniRoute a fost creat pentru a le rezolva pe toate - de la depășiri de costuri la blocaje regionale, de la fluxuri OAuth întrerupte la operațiuni de protocol și observabilitate a întreprinderii.
<details>
<summary><b>💸 1. „Plătesc pentru un abonament scump, dar tot sunt întrerupt de limite”</b></summary>
Dezvoltatorii plătesc 20200 USD/lună pentru Claude Pro, Codex Pro sau GitHub Copilot. Chiar și plătind, cota are un plafon - 5 ore de utilizare, limite săptămânale sau limite de tarif pe minut. La mijlocul sesiunii de codare, furnizorul nu mai răspunde și dezvoltatorul își pierde fluxul și productivitatea.
**Cum o rezolvă OmniRoute:**
- **Smart 4-Tier Fallback** — Dacă cota de abonament se epuizează, redirecționează automat la cheia API → Ieftin → Gratuit fără intervenție manuală
- **Urmărirea cotelor în timp real** — Afișează consumul de simboluri în timp real cu numărătoarea inversă de resetare (5 ore, zilnic, săptămânal)
- **Asistență pentru mai multe conturi** — Conturi multiple per furnizor cu turneu automat automat — când unul se epuizează, trece la următorul
- **Combinații personalizate** — Lanțuri de rezervă personalizabile cu 6 strategii de echilibrare (fill-first, round-robin, P2C, aleatoriu, cel mai puțin utilizat, optimizat din punct de vedere al costurilor)
- **Cote de afaceri Codex** — Monitorizarea cotelor de spațiu de lucru pentru afaceri/echipe direct în tabloul de bord
</details>
<details>
<summary><b>🔌 2. „Trebuie să folosesc mai mulți furnizori, dar fiecare are un API diferit”</b></summary>
OpenAI folosește un format, Claude (Anthropic) folosește altul, Gemini încă altul. Dacă un dezvoltator dorește să testeze modele de la diferiți furnizori sau să se retragă între aceștia, trebuie să reconfigureze SDK-urile, să schimbe punctele finale, să se ocupe de formate incompatibile. Furnizorii personalizați (FriendLI, NIM) au puncte finale de model non-standard.
**Cum o rezolvă OmniRoute:**
- **Unified Endpoint** — Un singur `http://localhost:20128/v1` servește drept proxy pentru toți cei 36 de furnizori și mai sus
- **Traducerea formatului** — Automată și transparentă: OpenAI ↔ Claude ↔ Gemeni ↔ Responses API
- **Response Sanitization** — Elimina câmpurile nestandard (`x_groq`, `usage_breakdown`, `service_tier`) care încalcă OpenAI SDK v1.83+
- **Normalizarea rolurilor** — Convertește `developer``system` pentru furnizorii non-OpenAI; `system``user` pentru GLM/ERNIE
- **Think Tag Extraction** — Extrage blocurile `<think>` de la modele precum DeepSeek R1 în `reasoning_content` standardizat
- **Ieșire structurată pentru Gemeni** — `json_schema``responseMimeType`/`responseSchema` conversie automată
- **`stream` este implicit `false`** — Se aliniază cu specificațiile OpenAI, evitând SSE neașteptat în SDK-urile Python/Rust/Go
</details>
<details>
<summary><b>🌐 3. „Furnizorul meu AI îmi blochează regiunea/țara”</b></summary>
Furnizori precum OpenAI/Codex blochează accesul din anumite regiuni geografice. Utilizatorii primesc erori precum `unsupported_country_region_territory` în timpul conexiunilor OAuth și API. Acest lucru este frustrant în special pentru dezvoltatorii din țările în curs de dezvoltare.
**Cum o rezolvă OmniRoute:**
- **3-Level Proxy Config** — Proxy configurabil la 3 niveluri: global (tot traficul), per furnizor (doar un singur furnizor) și per conexiune/cheie
- **Insigne de proxy cu coduri de culoare** — Indicatori vizuali: 🟢 proxy global, 🟡 proxy furnizor, 🔵 proxy de conexiune, indicând întotdeauna IP-ul
- **Schimb de jetoane OAuth prin proxy** — fluxul OAuth trece și prin proxy, rezolvând `unsupported_country_region_territory`
- **Teste de conexiune prin proxy** — Testele de conexiune folosesc proxy-ul configurat (nu mai este ocolire directă)
- **Support SOCKS5** — Suport complet SOCKS5 proxy pentru rutarea de ieșire
- **TLS Fingerprint Spoofing** — Amprenta TLS asemănătoare unui browser prin `wreq-js` pentru a ocoli detectarea botului
</details>
<details>
<summary><b>🆓 4. „Vreau să folosesc AI pentru codare, dar nu am bani”</b></summary>
Nu toată lumea poate plăti 20200 USD/lună pentru abonamentele AI. Studenții, dezvoltatorii din țările emergente, pasionații și freelancerii au nevoie de acces la modele de calitate la cost zero.
**Cum o rezolvă OmniRoute:**
- **Free Tier Providers Built-in** — Suport nativ pentru furnizori 100% gratuiti: iFlow (8 modele nelimitate), Qwen (3 modele nelimitate), Kiro (Claude gratuit), Gemini CLI (180K/lună gratuit)
- **Combinații numai gratuite** — Lanțul `gc/gemini-3-flash → if/kimi-k2-thinking → qw/qwen3-coder-plus` = 0 USD/lună fără timp de nefuncționare
- **Credite gratuite NVIDIA NIM** — 1000 de credite gratuite integrate
- **Cost Optimized Strategy** — Strategie de rutare care alege automat cel mai ieftin furnizor disponibil
</details>
<details>
<summary><b>🔒 5. „Trebuie să-mi protejez poarta AI de accesul neautorizat”</b></summary>
Când expuneți un gateway AI în rețea (LAN, VPS, Docker), oricine are adresa poate consuma jetoanele/cota dezvoltatorului. Fără protecție, API-urile sunt vulnerabile la utilizare greșită, injectare promptă și abuz.
**Cum o rezolvă OmniRoute:**
- **Gestionarea cheilor API** — Generare, rotație și definire pentru fiecare furnizor cu o pagină dedicată `/dashboard/api-manager`
- **Permisiuni la nivel de model** — Restricționați cheile API la anumite modele (`openai/*`, modele cu caractere metalice), cu comutatorul Permite toate/Restricționați
- **API Endpoint Protection** — Solicitați o cheie pentru `/v1/models` și blocați anumiți furnizori din listă
- **Auth Guard + CSRF Protection** — Toate rutele tabloului de bord sunt protejate cu middleware `withAuth` + jetoane CSRF
- **Rate Limiter** — Limitarea ratei per-IP cu ferestre configurabile
- **Filtrare IP** — Lista permisă/lista blocată pentru controlul accesului
- **Prompt Injection Guard** — Igienizare împotriva tiparelor de prompte rău intenționate
- **Criptare AES-256-GCM** — Acreditări criptate în repaus
</details>
<details>
<summary><b>🛑 6. „Furnizorul meu a căzut și mi-am pierdut fluxul de codare”</b></summary>
Furnizorii de AI pot deveni instabili, pot returna erori 5xx sau pot atinge limitele temporare ale ratei. Dacă un dezvoltator depinde de un singur furnizor, acesta este întrerupt. Fără întreruptoare, reîncercări repetate pot bloca aplicația.
**Cum o rezolvă OmniRoute:**
- **Circuit Breaker per furnizor** - Deschidere/închidere automată cu praguri configurabile și răcire (Închis/Deschis/Pe jumătate deschis)
| 🎯 **Endpoint-Aware Models** | Custom models declare supported endpoints + API format |
- **Backoff exponențial** — Întârzieri progresive ale reîncercării
- **Anti-Thundering Herd** — Mutex + protecție semafor împotriva furtunilor concurente de reîncercare
- **Combo Fallback Chains** — Dacă furnizorul principal eșuează, trece automat prin lanț fără nicio intervenție
- **Combo Circuit Breaker** — Dezactivează automat furnizorii care eșuează dintr-un lanț combinat
| 🎯 **Endpoint-Aware Models** | Custom models declare supported endpoints + API format |
- **Tabloul de bord pentru sănătate** — Monitorizare timp de funcționare, stări întrerupătoare de circuit, blocări, statistici cache, latență p50/p95/p99
</details>
<details>
<summary><b>🔧 7. „Configurarea fiecărui instrument AI este plictisitoare și repetitivă”</b></summary>
Dezvoltatorii folosesc Cursor, Claude Code, Codex CLI, OpenClaw, Gemini CLI, Kilo Code... Fiecare instrument are nevoie de o configurație diferită (punct final API, cheie, model). Reconfigurarea la schimbarea de furnizor sau de model este o pierdere de timp.
**Cum o rezolvă OmniRoute:**
- **CLI Tools Dashboard** — pagină dedicată cu setare cu un singur clic pentru Claude Code, Codex CLI, OpenClaw, Kilo Code, Antigravity, Cline
- **GitHub Copilot Config Generator** — generează `chatLanguageModels.json` pentru VS Code cu selecția în bloc a modelului
- **Onboarding Wizard** — Configurare ghidată în 4 pași pentru utilizatorii debutanți
- **Un punct final, toate modelele** — Configurați `http://localhost:20128/v1` o dată, accesați peste 36 de furnizori
</details>
<details>
<summary><b>🔑 8. „Gestionarea jetoanelor OAuth de la mai mulți furnizori este un iad” </b></summary>
Claude Code, Codex, Gemini CLI, Copilot - toate folosesc OAuth 2.0 cu token-uri care expiră. Dezvoltatorii trebuie să se reautentifice în mod constant, să se ocupe de `client_secret is missing`, `redirect_uri_mismatch` și defecțiunile de pe serverele de la distanță. OAuth pe LAN/VPS este deosebit de problematică.
**Cum o rezolvă OmniRoute:**
- **Reîmprospătare automată a simbolurilor** — jetoanele OAuth se reîmprospătează în fundal înainte de expirare
- **OAuth 2.0 (PKCE) încorporat** — Flux automat pentru Claude Code, Codex, Gemini CLI, Copilot, Kiro, Qwen, iFlow
- **OAuth cu mai multe conturi** — Conturi multiple per furnizor prin extragerea jetonului JWT/ID
- **OAuth LAN/Remediere la distanță** — Detectare IP privată pentru `redirect_uri` + modul URL manual pentru servere la distanță
- **OAuth în spatele Nginx** — Utilizează `window.location.origin` pentru compatibilitatea cu proxy invers
- **Ghid OAuth la distanță** — Ghid pas cu pas pentru acreditările Google Cloud pe VPS/Docker
</details>
<details>
<summary><b>📊 9. „Nu știu cât cheltuiesc sau unde”</b></summary>
Dezvoltatorii folosesc mai mulți furnizori plătiți, dar nu au o viziune unificată asupra cheltuielilor. Fiecare furnizor are propriul tablou de bord de facturare, dar nu există o vizualizare consolidată. Costurile neașteptate se pot acumula.
**Cum o rezolvă OmniRoute:**
- **Tabloul de bord pentru analiza costurilor** — Urmărirea costurilor pe token și gestionarea bugetului per furnizor
- **Limite bugetare pe nivel** — Plafonul de cheltuieli pe nivel care declanșează o rezervă automată
- **Configurație de preț pe model** — Prețuri configurabile pe model
- **Statistici de utilizare per cheie API** — Numărul de solicitări și marcajul temporal al ultimei utilizări per cheie
- **Tabloul de bord de analiză** — Carduri cu statistici, diagramă de utilizare a modelului, tabel cu furnizori cu rate de succes și latență
</details>
<details>
<summary><b>🐛 10. „Nu pot diagnostica erorile și problemele în apelurile AI”</b></summary>
Când un apel eșuează, dezvoltatorul nu știe dacă a fost o limită de rată, un simbol expirat, un format greșit sau o eroare a furnizorului. Jurnalele fragmentate pe diferite terminale. Fără observabilitate, depanarea este o încercare și eroare.
**Cum o rezolvă OmniRoute:**
- **Tabloul de bord pentru jurnalele unificate** — 4 file: jurnalele de solicitare, jurnalele proxy, jurnalele de audit, consolă
- **Console Log Viewer** — Vizualizator în timp real în stil terminal cu niveluri codificate în culori, defilare automată, căutare, filtru
- **SQLite Proxy Logs** — Jurnale persistente care supraviețuiesc repornirilor serverului
- **Translator Playground** — 4 moduri de depanare: Playground (traducere format), Chat Tester (dus-întors), Test Bench (lot), Live Monitor (în timp real)
- **Solicitare telemetrie** — latență p50/p95/p99 + urmărire X-Request-Id
- **Înregistrare bazată pe fișiere cu rotație** — Interceptor de consolă captează totul în jurnalul JSON cu rotație bazată pe dimensiune
</details>
<details>
<summary><b>🏗️ 11. „Implementarea și întreținerea gateway-ului este complexă”</b></summary>
Instalarea, configurarea și menținerea unui proxy AI în diferite medii (local, VPS, Docker, cloud) necesită multă muncă. Probleme precum căile codificate hard, `EACCES` pe directoare, conflictele de porturi și versiunile pe mai multe platforme adaugă fricțiuni.
**Cum o rezolvă OmniRoute:**
- **npm global install** — `npm install -g omniroute && omniroute` — finalizat
- **Docker Multi-Platform** - AMD64 + ARM64 nativ (Apple Silicon, AWS Graviton, Raspberry Pi)
- **Docker Compose Profiles** — `base` (fără instrumente CLI) și `cli` (cu Claude Code, Codex, OpenClaw)
- **Electron Desktop App** — aplicație nativă pentru Windows/macOS/Linux cu bară de sistem, pornire automată, mod offline
- **Split-Port Mode** — API și tablou de bord pe porturi separate pentru scenarii avansate (reverse proxy, rețea container)
- **Cloud Sync** — Configurați sincronizarea între dispozitive prin Cloudflare Workers
- **Backups DB** — Backup automat, restaurare, export și import al tuturor setărilor
</details>
<details>
<summary><b>🌍 12. „Interfața este doar în limba engleză și echipa mea nu vorbește engleză” </b></summary>
Echipele din țările care nu vorbesc engleza, în special din America Latină, Asia și Europa, se luptă cu interfețele doar în limba engleză. Barierele lingvistice reduc adoptarea și cresc erorile de configurare.
**Cum o rezolvă OmniRoute:**
- **Tabloul de bord i18n — 30 de limbi** — Toate cele peste 500 de taste traduse, inclusiv arabă, bulgară, daneză, germană, spaniolă, finlandeză, franceză, ebraică, hindi, maghiară, indoneziană, italiană, japoneză, coreeană, malay, olandeză, norvegiană, poloneză, portugheză (PT/BR), română, rusă, slovacă, suedeză, thailandeză, ucraineană, filipineză, engleză, chineză, vietnameză,
- ** Suport RTL** — Suport de la dreapta la stânga pentru arabă și ebraică
- **ReadME-uri în mai multe limbi** — 30 de traduceri complete de documentație
- **Selector de limbă** — Pictograma glob în antet pentru comutare în timp real
</details>
<details>
<summary><b>🔄 13. „Am nevoie de mai mult decât de chat — am nevoie de încorporare, imagini, audio” </b></summary>
AI nu este doar finalizarea chatului. Dezvoltatorii trebuie să genereze imagini, să transcrie sunetul, să creeze înglobări pentru RAG, să reclasifice documentele și să modereze conținutul. Fiecare API are un punct final și un format diferit.
**Cum o rezolvă OmniRoute:**
- **Embeddings** — `/v1/embeddings` cu 6 furnizori și peste 9 modele
- **Generarea imaginii** — `/v1/images/generations` cu 10 furnizori și peste 20 de modele (OpenAI, xAI, Together, Fireworks, Nebius, Hyperbolic, NanoBanana, Antigravity, SD WebUI, ComfyUI)
- **Text-to-Video** — `/v1/videos/generations` — ComfyUI (AnimateDiff, SVD) și SD WebUI
- **Text-to-Music** — `/v1/music/generations` — ComfyUI (Stable Audio Open, MusicGen)
- **Transcriere audio** — `/v1/audio/transcriptions` — Whisper + Nvidia NIM, HuggingFace, Qwen3
- **Text-to-Speech** — `/v1/audio/speech` — ElevenLabs, Nvidia NIM, HuggingFace, Coqui, Tortoise, Qwen3, + furnizori existenți
- **Moderări** — `/v1/moderations` — Verificări de siguranță a conținutului
- **Reclasificare** — `/v1/rerank` — Reclasificarea relevanței documentului
- **Responses API** — Suport complet `/v1/responses` pentru Codex
</details>
<details>
<summary><b>🧪 14. „Nu am cum să testez și să compar calitatea între modele” </b></summary>
Dezvoltatorii vor să știe care model este cel mai bun pentru cazul lor de utilizare - cod, traducere, raționament - dar compararea manuală este lentă. Nu există instrumente de evaluare integrate.
**Cum o rezolvă OmniRoute:**
- **Evaluări LLM** — Testarea setului de aur cu 10 cazuri preîncărcate care acoperă salutări, matematică, geografie, generare de cod, conformitate cu JSON, traducere, reducere, refuz de siguranță
- **4 strategii de potrivire** — `exact`, `contains`, `regex`, `custom` (funcția JS)
- **Translator Playground Test Bench** — Testare în loturi cu mai multe intrări și rezultate așteptate, comparație între furnizori
- **Tester de chat** — Tur complet dus-întors cu randare vizuală a răspunsului
- **Live Monitor** — Flux în timp real al tuturor solicitărilor care circulă prin proxy
</details>
<details>
<summary><b>📈 15. „Trebuie să mă scalez fără a pierde performanța”</b></summary>
Pe măsură ce volumul cererilor crește, fără memorarea în cache aceleași întrebări generează costuri duplicate. Fara idempotenta, cererile duplicate procesarea deseurilor. Limitele de tarife pentru fiecare furnizor trebuie respectate.
**Cum o rezolvă OmniRoute:**
- **Cache semantic** — Cache-ul pe două niveluri (semnătură + semantică) reduce costurile și latența
- **Request Idempotency** — fereastră de deduplicare 5s pentru cereri identice
- **Rate Limit Detection** — RPM per furnizor, interval minim și urmărire simultană maximă
- **Limite de rată editabile** — Valori implicite configurabile în Setări → Reziliență cu persistență
- **API Key Validation Cache** — cache pe 3 niveluri pentru performanța producției
- **Tabloul de bord pentru sănătate cu telemetrie** — latență p50/p95/p99, statistici cache, timp de funcționare
</details>
<details>
<summary><b>🤖 16. „Vreau să controlez comportamentul modelului la nivel global”</b></summary>
Dezvoltatori care doresc toate răspunsurile într-o anumită limbă, cu un anumit ton sau care doresc să limiteze simbolurile de raționament. Configurarea acestui lucru în fiecare instrument/cerere nu este practică.
**Cum o rezolvă OmniRoute:**
- **System Prompt Injection** — Prompt global aplicat tuturor solicitărilor
- **Thinking Budget Validation** — Controlul raționării alocării token-ului per cerere (transmis, automat, personalizat, adaptiv)
- **6 Strategii de rutare** — Strategii globale care determină modul în care sunt distribuite cererile
- **Wildcard Router** — modelele `provider/*` sunt direcționate dinamic către orice furnizor
- **Combo Activare/Dezactivare Comutare** — Comută combo direct din tabloul de bord
- **Comutare furnizor** — Activați/dezactivați toate conexiunile pentru un furnizor cu un singur clic
- **Furnizori blocați** — Excludeți anumiți furnizori din lista `/v1/models`
</details>
<details>
<summary><b>🧰 17. „Am nevoie de instrumente MCP ca capabilități de produs de primă clasă”</b></summary>
Multe gateway-uri AI expun MCP doar ca un detaliu ascuns de implementare. Echipele au nevoie de un nivel de operare vizibil și ușor de gestionat.
**Cum o rezolvă OmniRoute:**
- MCP apare în panoul de bord de navigare și fila de protocol final
- Pagina de management MCP dedicată cu proces, instrumente, domenii și audit
- Pornire rapidă încorporată pentru `omniroute --mcp` și integrarea clientului
</details>
<details>
<summary><b>🧠 18. „Am nevoie de orchestrare A2A cu sincronizare + căi de activități de flux” </b></summary>
Fluxurile de lucru ale agenților necesită atât răspunsuri directe, cât și execuție în flux de lungă durată, cu control ciclului de viață.
**Cum o rezolvă OmniRoute:**
- Punct final A2A JSON-RPC (`POST /a2a`) cu `message/send` și `message/stream`
- Streaming SSE cu propagare a stării terminale
- API-uri pentru ciclul de viață al sarcinilor pentru `tasks/get` și `tasks/cancel`
</details>
<details>
<summary><b>🛰️ 19. „Am nevoie de sănătate reală a procesului MCP, nu de stare ghicită” </b></summary>
Echipele operaționale trebuie să știe dacă MCP este de fapt în viață, nu doar dacă un API este accesibil.
**Cum o rezolvă OmniRoute:**
- Fișier runtime heartbeat cu PID, marcaje de timp, transport, număr de instrumente și modul de aplicare
- API de stare MCP care combină bătăile inimii + activitatea recentă
- Carduri de stare a interfeței de utilizare pentru prospețimea procesului/uptime/inima
</details>
<details>
<summary><b>📋 20. „Am nevoie de o execuție auditabilă a instrumentului MCP” </b></summary>
Când instrumentele modifică configurația sau declanșează acțiuni operaționale, echipele au nevoie de trasabilitate criminalistică.
**Cum o rezolvă OmniRoute:**
- Înregistrare de audit susținută de SQLite pentru apelurile instrumentelor MCP
- Filtrează după instrument, succes/eșec, cheie API și paginare
- Tabelul de audit al tabloului de bord + punctele finale de statistici pentru automatizare
</details>
<details>
<summary><b>🔐 21. „Am nevoie de permisiuni MCP pentru fiecare integrare” </b></summary>
Clienții diferiți ar trebui să aibă cel mai mic privilegiu de acces la categoriile de instrumente.
**Cum o rezolvă OmniRoute:**
- 9 lunete MCP granulare pentru acces controlat la instrumente
- Aplicarea domeniului de aplicare și vizibilitatea în interfața de utilizare a managementului MCP
- Poziție implicită sigură pentru instrumentele operaționale
</details>
<details>
<summary><b>⚙️ 22. „Am nevoie de controale operaționale fără redistribuire”</b></summary>
Echipele au nevoie de modificări rapide ale timpului de rulare în timpul incidentelor sau evenimentelor de cost.
**Cum o rezolvă OmniRoute:**
- Comutați activarea comboi direct din tabloul de bord MCP
- Aplicați profiluri de rezistență din pachetele de politici predefinite
- Resetați starea întreruptorului de la același panou de operare
</details>
<details>
<summary><b>🔄 23. „Am nevoie de vizibilitate și anulare a ciclului de viață a sarcinii A2A live”</b></summary>
Fără vizibilitatea ciclului de viață, incidentele sarcinilor devin greu de triat.
**Cum o rezolvă OmniRoute:**
- Listarea sarcinilor/filtrarea după stare/abilitate cu paginare
- Detaliați metadatele sarcinii, evenimentele și artefactele
- Punct final de anulare a sarcinii și acțiune UI cu confirmare
</details>
<details>
<summary><b>🌊 24. „Am nevoie de valori de flux active pentru încărcarea A2A”</b></summary>
Fluxurile de lucru în flux necesită o perspectivă operațională privind concurența și conexiunile live.
**Cum o rezolvă OmniRoute:**
- Contoare active de flux integrate în starea A2A
- Marcaj de timp pentru ultima sarcină și numărătoare pentru fiecare stat
- Carduri de bord A2A pentru monitorizarea operațiunilor în timp real
</details>
<details>
<summary><b>🪪 25. „Am nevoie de descoperire de agenți standard pentru clienți”</b></summary>
Clienții externi și orchestratorii au nevoie de metadate care pot fi citite de mașină pentru integrare.
**Cum o rezolvă OmniRoute:**
- Card de agent expus la `/.well-known/agent.json`
- Capacități și abilități afișate în UI de management
- API-ul de stare A2A include metadate de descoperire pentru automatizare
</details>
<details>
<summary><b>🧭 26. „Am nevoie de descoperirea protocolului în produsul UX”</b></summary>
Dacă utilizatorii nu pot descoperi suprafețele de protocol, calitatea adoptării și a suportului scade.
**Cum o rezolvă OmniRoute:**
- Intrări din bara laterală pentru MCP și A2A
- Pagina Endpoint Fila Protocoale cu pornire rapidă și stare
- Link-uri de la prezentare generală la tablouri de bord dedicate de management
</details>
<details>
<summary><b>🧪 27. „Am nevoie de validarea protocolului end-to-end cu clienți reali”</b></summary>
Testele simulate nu sunt suficiente pentru a valida compatibilitatea protocolului înainte de lansare.
**Cum o rezolvă OmniRoute:**
- Suita E2E care pornește aplicația și utilizează transportul clientului MCP SDK real
- Testele client A2A pentru descoperirea, trimiterea, transmiterea în flux, obținerea și anularea fluxurilor
- Verificați încrucișați afirmațiile cu auditul MCP și API-urile pentru sarcini A2A
</details>
<details>
<summary><b>📡 28. „Am nevoie de observabilitate unificată pe toate interfețele”</b></summary>
Împărțirea observabilității în funcție de protocol creează puncte oarbe și MTTR mai lung.
**Cum o rezolvă OmniRoute:**
- Tablouri de bord/jurnale/analitice unificate într-un singur produs
- Sănătate + audit + solicitare de telemetrie în straturi OpenAI, MCP și A2A
- API-uri operaționale pentru stare și automatizare
</details>
<details>
<summary><b>💼 29. „Am nevoie de un timp de rulare pentru proxy + instrumente + orchestrare agent”</b></summary>
Rularea multor servicii separate crește costurile operaționale și modurile de eșec.
**Cum o rezolvă OmniRoute:**
- Proxy compatibil OpenAI, server MCP și server A2A într-o singură stivă
- Autentificare partajată, rezistență, stocare de date și observabilitate
- Model de politică consistent pe toate suprafețele de interacțiune
</details>
<details>
<summary><b>🚀 30. „Trebuie să trimit fluxuri de lucru agentice fără extinderea codului lipici”</b></summary>
Echipele își pierd din viteza atunci când realizează mai multe servicii și scripturi ad-hoc.
**Cum o rezolvă OmniRoute:**
- Strategie unificată pentru clienți și agenți
- Interfețe de utilizare a protocolului încorporate și căi de validare a fumului
- Baze pregătite pentru producție (securitate, logare, rezistență, backup)
</details>
### Exemple de manuale (cazuri de utilizare integrate)
**Playbook A: Maximizați abonamentul plătit + backup ieftin**
```txt
Combo: "maximize-claude"
1. cc/claude-opus-4-6
2. glm/glm-4.7
3. if/kimi-k2-thinking
Monthly cost: $20 + small backup spend
Outcome: higher quality, near-zero interruption
```
**Playbook B: teanc de codare cu costuri zero**
```txt
Combo: "free-forever"
1. gc/gemini-3-flash
2. if/kimi-k2-thinking
3. qw/qwen3-coder-plus
Monthly cost: $0
Outcome: stable free coding workflow
```
**Playbook C: lanț alternativ permanent activ 24/7**
```txt
Combo: "always-on"
1. cc/claude-opus-4-6
2. cx/gpt-5.2-codex
3. glm/glm-4.7
4. minimax/MiniMax-M2.1
5. if/kimi-k2-thinking
Outcome: deep fallback depth for deadline-critical workloads
```
**Playbook D: Agentul operează cu MCP + A2A**
```txt
1) Start MCP transport (`omniroute --mcp`) for tool-driven operations
2) Run A2A tasks via `message/send` and `message/stream`
3) Observe via /dashboard/mcp and /dashboard/a2a
4) Control incidents with resilience profile + task cancellation
```
---
## ⚡ Pornire rapidă
**1. Instalați la nivel global:**
@@ -251,7 +783,7 @@ docker compose --profile cli up -d
---
## 🖥️ Desktop App — Offline & Always-On
## 🖥️
> 🆕 **NEW!** OmniRoute is now available as a **native desktop application** for Windows, macOS, and Linux.
@@ -298,67 +830,6 @@ npm run electron:build:linux # Linux (.AppImage)
---
## 🎯 Cazuri de utilizare
### Cazul 1: „Am abonament Claude Pro”
**Problemă:** Cota expiră neutilizată, limitele ratei în timpul codării grele
```
Combo: "maximize-claude"
1. cc/claude-opus-4-6 (use subscription fully)
2. glm/glm-4.7 (cheap backup when quota out)
3. if/kimi-k2-thinking (free emergency fallback)
Monthly cost: $20 (subscription) + ~$5 (backup) = $25 total
vs. $20 + hitting limits = frustration
```
### Cazul 2: „Vreau cost zero”
**Problemă:** Nu-mi permit abonamente, au nevoie de codare AI de încredere
```
Combo: "free-forever"
1. gc/gemini-3-flash (180K free/month)
2. if/kimi-k2-thinking (unlimited free)
3. qw/qwen3-coder-plus (unlimited free)
Monthly cost: $0
Quality: Production-ready models
```
### Cazul 3: „Am nevoie de codare 24/7, fără întreruperi”
**Problemă:** Termenele limită, nu-mi permit timpi de nefuncționare
```
Combo: "always-on"
1. cc/claude-opus-4-6 (best quality)
2. cx/gpt-5.2-codex (second subscription)
3. glm/glm-4.7 (cheap, resets daily)
4. minimax/MiniMax-M2.1 (cheapest, 5h reset)
5. if/kimi-k2-thinking (free unlimited)
Result: 5 layers of fallback = zero downtime
```
### Cazul 4: „Vreau AI GRATUIT în OpenClaw”
**Problemă:** Aveți nevoie de asistent AI în aplicațiile de mesagerie, complet gratuit
```
Combo: "openclaw-free"
1. if/glm-4.7 (unlimited free)
2. if/minimax-m2.1 (unlimited free)
3. if/kimi-k2-thinking (unlimited free)
Monthly cost: $0
Access via: WhatsApp, Telegram, Slack, Discord, iMessage, Signal...
```
---
## 💡 Caracteristici cheie
### 🧠 Core Routing & Intelligence
@@ -374,6 +845,8 @@ Access via: WhatsApp, Telegram, Slack, Discord, iMessage, Signal...
| 🧩 **Modele personalizate** | Adăugați orice ID de model oricărui furnizor |
| 🌐 **Wildcard Router** | Dirijați dinamic modelele `provider/*` către orice furnizor |
| 🧠 **Buget de gândire** | Moduri de trecere, automat, personalizat și adaptiv pentru modelele de raționament |
| 🔀 **Model Aliases** | Auto-forward deprecated model IDs to current replacements (built-in + custom) |
| ⚡ **Background Degradation** | Auto-route background tasks (titles, summaries) to cheaper models |
| 💬 **System Prompt Injection** | Prompt de sistem global aplicat pentru toate solicitările |
| 📄 **Responses API** | Compatibilitate completă cu OpenAI Responses API (`/v1/responses`) pentru Codex |
@@ -399,6 +872,8 @@ Access via: WhatsApp, Telegram, Slack, Discord, iMessage, Signal...
| 🔒 **TLS Fingerprint Spoofing** | Ocoliți detectarea botului bazată pe TLS prin wreq-js |
| 🌐 **Filtrare IP** | Lista permisă/lista blocată pentru controlul accesului API |
| 📊 **Limite de rată editabile** | RPM configurabil, interval minim și concurență maximă la nivel de sistem |
| 💾 **Rate Limit Persistence** | Learned limits survive restarts via SQLite with 60s debounce + 24h staleness |
| 🔄 **Token Refresh Resilience** | Per-provider circuit breaker (5 fails→30min) + 30s timeout per attempt |
| 🛡 **Protecție API Endpoint** | Autentificare + blocare furnizor pentru punctul final `/models` |
| 🔒 **Vizibilitatea proxy** | Ecusoane cu coduri de culoare: 🟢 global, 🟡 furnizor, 🔵 per conexiune cu afișaj IP |
| 🌐 **Configurare proxy pe 3 niveluri** | Configurați proxy-uri la nivel global, per furnizor sau per conexiune |
@@ -517,6 +992,27 @@ OmniRoute include un puternic Translator Playground încorporat cu **4 moduri**
</details>
## 🧪 Evaluări (Evaluări)
OmniRoute include un cadru de evaluare încorporat pentru a testa calitatea răspunsului LLM față de un set de aur. Accesați-l prin **Analitice → Evaluări** în tabloul de bord.
### Set de aur încorporat
„Setul de Aur OmniRoute” preîncărcat conține 10 cazuri de testare care acoperă:
- Salutări, matematică, geografie, generare de cod
- Conformitatea formatului JSON, traducere, reducere
- Refuz de siguranță (conținut dăunător), numărare, logică booleană
### Strategii de evaluare
| Strategie | Descriere | Exemplu |
| ---------- | ------------------------------------------------------------------------- | -------------------------------- |
| `exact` | Ieșirea trebuie să se potrivească exact cu | `"4"` |
| `contains` | Ieșirea trebuie să conțină subșir (indiferență de majuscule și minuscule) | `"Paris"` |
| `regex` | Ieșirea trebuie să se potrivească cu modelul regex | `"1.*2.*3"` |
| `custom` | Funcția JS personalizată returnează adevărat/fals | `(output) => output.length > 10` |
---
## 📖 Ghid de configurare
@@ -799,104 +1295,64 @@ Settings → API Configuration:
---
## 📊 Modele disponibile
## 🐛 Depanare
<details>
<summary><b>Vedeți toate modelele disponibile</b></summary>
<summary><b>Faceți clic pentru a extinde ghidul de depanare</b></summary>
**Cod Claude (`cc/`)** - Pro/Max:
**„Modelul de limbă nu a furnizat mesaje”**
- `cc/claude-opus-4-6`
- `cc/claude-sonnet-4-5-20250929`
- `cc/claude-haiku-4-5-20251001`
- Cota de furnizor epuizată → Verificați instrumentul de urmărire a cotei din tabloul de bord
- Soluție: utilizați alternativă combinată sau treceți la un nivel mai ieftin
**Codex (`cx/`)** - Plus/Pro:
**Limitarea ratei**
- `cx/gpt-5.2-codex`
- `cx/gpt-5.1-codex-max`
- Scăderea cotei de abonament → Fallback la GLM/MiniMax
- Adăugați combo: `cc/claude-opus-4-6 → glm/glm-4.7 → if/kimi-k2-thinking`
**CLI Gemini (`gc/`)** - GRATUIT:
**Tokenul OAuth a expirat**
- `gc/gemini-3-flash-preview`
- `gc/gemini-2.5-pro`
- Reîmprospătat automat de OmniRoute
- Dacă problemele persistă: Dashboard → Provider → Reconnect
**Copilot GitHub (`gh/`)**:
**Costuri mari**
- `gh/gpt-5`
- `gh/claude-4.5-sonnet`
- Verificați statisticile de utilizare în Tabloul de bord → Costuri
- Comutați modelul principal la GLM/MiniMax
- Utilizați nivelul gratuit (Gemini CLI, iFlow) pentru sarcini necritice
**NVIDIA NIM (`nvidia/`)** - credite GRATUITE:
**Tabloul de bord se deschide pe portul greșit**
- `nvidia/llama-3.3-70b-instruct`
- `nvidia/mistral-7b-instruct`
- Mai mult de 50 de modele pe [build.nvidia.com](https://build.nvidia.com)
- Setați `PORT=20128` și `NEXT_PUBLIC_BASE_URL=http://localhost:20128`
**GLM (`glm/`)** - 0,6 USD/1 milion:
**Erori de sincronizare în cloud**
- `glm/glm-4.7`
- Verificați `BASE_URL` puncte către instanța dvs. care rulează
- Verificați `CLOUD_URL` puncte către punctul final din cloud așteptat
- Păstrați valorile `NEXT_PUBLIC_*` aliniate cu valorile de pe partea serverului
**MiniMax (`minimax/`)** - 0,2 USD/1 milion:
**Prima conectare nu funcționează**
- `minimax/MiniMax-M2.1`
- Verificați `INITIAL_PASSWORD` în `.env`
- Dacă nu este setată, parola de rezervă este `123456`
**iFlow (`if/`)** - GRATUIT:
**Fără jurnal de solicitare**
- `if/kimi-k2-thinking`
- `if/qwen3-coder-plus`
- `if/deepseek-r1`
- `if/glm-4.7`
- `if/minimax-m2`
- Setați `ENABLE_REQUEST_LOGS=true` în `.env`
**Qwen (`qw/`)** - GRATUIT:
**Testul de conectare arată „Invalid” pentru furnizorii compatibili cu OpenAI**
- `qw/qwen3-coder-plus`
- `qw/qwen3-coder-flash`
- Mulți furnizori nu expun un punct final `/models`
- OmniRoute v1.0.6+ include validarea de rezervă prin finalizarea chatului
- Asigurați-vă că adresa URL de bază include sufixul `/v1`
**Kiro (`kr/`)** - GRATUIT:
- `kr/claude-sonnet-4.5`
- `kr/claude-haiku-4.5`
**OpenRouter (`or/`)** - peste 100 de modele:
- `or/anthropic/claude-4-sonnet`
- `or/google/gemini-2.5-pro`
- Orice model de la [openrouter.ai/models](https://openrouter.ai/models)
</details>
---
## 🧪 Evaluări (Evaluări)
OmniRoute include un cadru de evaluare încorporat pentru a testa calitatea răspunsului LLM față de un set de aur. Accesați-l prin **Analitice → Evaluări** în tabloul de bord.
### Set de aur încorporat
„Setul de Aur OmniRoute” preîncărcat conține 10 cazuri de testare care acoperă:
- Salutări, matematică, geografie, generare de cod
- Conformitatea formatului JSON, traducere, reducere
- Refuz de siguranță (conținut dăunător), numărare, logică booleană
### Strategii de evaluare
| Strategie | Descriere | Exemplu |
| ---------- | ------------------------------------------------------------------------- | -------------------------------- |
| `exact` | Ieșirea trebuie să se potrivească exact cu | `"4"` |
| `contains` | Ieșirea trebuie să conțină subșir (indiferență de majuscule și minuscule) | `"Paris"` |
| `regex` | Ieșirea trebuie să se potrivească cu modelul regex | `"1.*2.*3"` |
| `custom` | Funcția JS personalizată returnează adevărat/fals | `(output) => output.length > 10` |
---
## 🔐 OAuth em Servidor Remoto (Configurare OAuth la distanță)
### 🔐 OAuth
<a name="oauth-em-servidor-remoto"></a>
> **⚠️ IMPORTANT pentru utilizatorii cu OmniRoute în VPS/Docker/servidor remoto**
### Por que o OAuth do Antigravity / Gemini CLI falha em serveres remotes?
#### OAuth
Pentru autentificare, **Antigravity** și **Gemini CLI** folosesc **Google OAuth 2.0**. O Google exige que a `redirect_uri` utilizat nu fluxo OAuth seja **exatamente** uma das URIs pre-cadastradas no Google Cloud Console do aplicative.
@@ -981,64 +1437,11 @@ Nu vă rugăm să vă convingeți acum, dar este posibil să utilizați sau să
> Această soluție de soluționare funcționează deoarece codul de autorizare a URL-ului este valabil independent de redirecționare pentru a încărca sau nu.
---
## 🐛 Depanare
<details>
<summary><b>Faceți clic pentru a extinde ghidul de depanare</b></summary>
**„Modelul de limbă nu a furnizat mesaje”**
- Cota de furnizor epuizată → Verificați instrumentul de urmărire a cotei din tabloul de bord
- Soluție: utilizați alternativă combinată sau treceți la un nivel mai ieftin
**Limitarea ratei**
- Scăderea cotei de abonament → Fallback la GLM/MiniMax
- Adăugați combo: `cc/claude-opus-4-6 → glm/glm-4.7 → if/kimi-k2-thinking`
**Tokenul OAuth a expirat**
- Reîmprospătat automat de OmniRoute
- Dacă problemele persistă: Dashboard → Provider → Reconnect
**Costuri mari**
- Verificați statisticile de utilizare în Tabloul de bord → Costuri
- Comutați modelul principal la GLM/MiniMax
- Utilizați nivelul gratuit (Gemini CLI, iFlow) pentru sarcini necritice
**Tabloul de bord se deschide pe portul greșit**
- Setați `PORT=20128` și `NEXT_PUBLIC_BASE_URL=http://localhost:20128`
**Erori de sincronizare în cloud**
- Verificați `BASE_URL` puncte către instanța dvs. care rulează
- Verificați `CLOUD_URL` puncte către punctul final din cloud așteptat
- Păstrați valorile `NEXT_PUBLIC_*` aliniate cu valorile de pe partea serverului
**Prima conectare nu funcționează**
- Verificați `INITIAL_PASSWORD` în `.env`
- Dacă nu este setată, parola de rezervă este `123456`
**Fără jurnal de solicitare**
- Setați `ENABLE_REQUEST_LOGS=true` în `.env`
**Testul de conectare arată „Invalid” pentru furnizorii compatibili cu OpenAI**
- Mulți furnizori nu expun un punct final `/models`
- OmniRoute v1.0.6+ include validarea de rezervă prin finalizarea chatului
- Asigurați-vă că adresa URL de bază include sufixul `/v1`
</details>
---
## 🛠️ Tech Stack
## 🛠️
- **Runtime**: Node.js 1822 LTS (⚠️ Node.js 24+ este **nu este acceptat** - `better-sqlite3` binarele native sunt incompatibile)
- **Limba**: TypeScript 5.9 — **100% TypeScript** în `src/` și `open-sse/` (v1.0.6)
@@ -1090,7 +1493,7 @@ Nu vă rugăm să vă convingeți acum, dar este posibil să utilizați sau să
---
## 🗺️ Foaia de parcurs
## 🗺️
OmniRoute are **210+ funcții planificate** în mai multe faze de dezvoltare. Iată domeniile cheie:
@@ -1115,18 +1518,6 @@ OmniRoute are **210+ funcții planificate** în mai multe faze de dezvoltare. Ia
---
## 📧 Suport
> 💬 **Alăturați-vă comunității noastre!** [WhatsApp Group](https://chat.whatsapp.com/JI7cDQ1GyaiDHhVBpLxf8b?mode=gi_t) — Obțineți ajutor, împărtășiți sfaturi și fiți la curent.
- **Site web**: [omniroute.online](https://omniroute.online)
- **GitHub**: [github.com/diegosouzapw/OmniRoute](https://github.com/diegosouzapw/OmniRoute)
- **Probleme**: [github.com/diegosouzapw/OmniRoute/issues](https://github.com/diegosouzapw/OmniRoute/issues)
- **WhatsApp**: [Community Group](https://chat.whatsapp.com/JI7cDQ1GyaiDHhVBpLxf8b?mode=gi_t)
- **Proiect original**: [9router by decolua](https://github.com/decolua/9router)
---
## 👥 Colaboratori
[![Contributors](https://contrib.rocks/image?repo=diegosouzapw/OmniRoute&max=100&columns=20&anon=1)](https://github.com/diegosouzapw/OmniRoute/graphs/contributors)
@@ -1176,85 +1567,6 @@ Licență MIT - consultați [LICENSE](LICENSE) pentru detalii.
---
---
## 🇧🇷 OmniRoute — Gateway de IA Gratuito
<a name="-omniroute--gateway-de-ia-gratuito"></a>
### Nunca pare de codar. Roteamento inteligente pentru **modele de IA GRATUITE și de baixo custo** com fallback automático.
_Seu proxy universal de API — um endpoint, peste 36 de probe, zero downtime._
### 🌐 Internaționalizare (i18n)
O tablou de bord pentru OmniRoute suportă **multiplos idiomas**. De fapt, sunt disponibile:
| Idioma | Cod | Stare |
| ----------------------- | ------- | ---------- |
| 🇺🇸 engleză | `en` | ✅ Complet |
| 🇧🇷 Português (Brazilia) | `pt-BR` | ✅ Complet |
**Para trocar o idioma:** Clique no selector de idioma (🇺🇸 EN) no header do dashboard → selecione o idioma desejado.
**Para adicionar um nou idioma:**
1. Plânge `src/i18n/messages/{codigo}.json` bazat pe `en.json`
2. Adăugați codul în `src/i18n/config.ts``LOCALES` și `LANGUAGES`
3. Reinicie o servidor
### ⚡ Início Rápido
```bash
# Instalar via npm
npx omniroute@latest
# Ou rodar do código-fonte
cp .env.example .env
npm install
PORT=20128 NEXT_PUBLIC_BASE_URL=http://localhost:20128 npm run dev
```
### 🐳 Docker
```bash
docker run -d --name omniroute -p 20128:20128 diegosouzapw/omniroute:latest
```
### 🔑 Funcționalități principale
- **36+ provedores de IA** — Claude, GPT, Gemini, Llama, Qwen, DeepSeek, și mai mult
- **Roteamento inteligente** — Fallback automat entre provedores
- **Tradução de format** — OpenAI ↔ Claude ↔ Gemeni automaticamente
- **Multi-conta** — Múltiplas contas por provedor com seleção inteligente
- **Cache semântico** — Reduz custos e latência
- **OAuth automat** — Jetoane renovate automat
- **Combos personalizados** — 6 estratégias de roteamento
- **Dashboard complet** — Monitorizare, jurnale, analize, configurații
- **CLI Tools** — Configurați Claude Code, Codex, Cursor, Cline com um clique
- **100% TypeScript** — Código limpo e tipado
### 📖 Documentação
| Documento | Descriere |
| ----------------------------------------------- | ---------------------------------------- |
| [Guia do Usuário](docs/USER_GUIDE.md) | Provedores, combo-uri, CLI, implementare |
| [Referência da API](docs/API_REFERENCE.md) | Toate punctele finale, cum ar fi exemple |
| [Solução de Problemas](docs/TROUBLESHOOTING.md) | Problemas comuns e soluções |
| [Arquitetura](docs/ARCHITECTURE.md) | Arquitetura e internos do sistema |
| [Contribuição](CONTRIBUTING.md) | Configurare de dezvoltare și ghiduri |
| [Deploy em VM](docs/VM_DEPLOYMENT_GUIDE.md) | Ghid complet: VM + nginx + Cloudflare |
### 📧 Suport
> 💬 **Entre para a comunidade!** [Grupo WhatsApp](https://chat.whatsapp.com/JI7cDQ1GyaiDHhVBpLxf8b?mode=gi_t) — Tire dúvidas, compartilhe dicas e fique atualizado.
- **Site web**: [omniroute.online](https://omniroute.online)
- **GitHub**: [github.com/diegosouzapw/OmniRoute](https://github.com/diegosouzapw/OmniRoute)
- **Probleme**: [github.com/diegosouzapw/OmniRoute/issues](https://github.com/diegosouzapw/OmniRoute/issues)
---
<div align="center">
<sub>Construit cu ❤️ pentru dezvoltatorii care codifică 24/7</sub>
<br/>

View File

@@ -110,6 +110,35 @@ _Подключайте любую IDE или CLI-инструмент с AI ч
---
## 🖼️
<div align="center">
<img src="./docs/screenshots/MainOmniRoute.png" alt="OmniRoute" width="800"/>
</div>
---
## 📸
<details>
<summary><b>...</b></summary>
| # | # |
| ----- | ---------------------------------------- |
| **1** | ![1](docs/screenshots/01-providers.png) |
| **2** | ![2](docs/screenshots/02-combos.png) |
| **3** | ![3](docs/screenshots/03-analytics.png) |
| **4** | ![4](docs/screenshots/04-health.png) |
| **5** | ![5](docs/screenshots/05-translator.png) |
| **6** | ![6](docs/screenshots/06-settings.png) |
| **7** | ![7](docs/screenshots/07-cli-tools.png) |
| **8** | ![8](docs/screenshots/08-usage.png) |
| **9** | ![9](docs/screenshots/09-endpoint.png) |
</details>
---
## 🤔 Почему OmniRoute?
**Перестаньте тратить деньги и упираться в лимиты:**
@@ -128,6 +157,18 @@ _Подключайте любую IDE или CLI-инструмент с AI ч
---
## 📧 Поддержка
> 💬 **Присоединяйтесь к сообществу!** [Группа WhatsApp](https://chat.whatsapp.com/JI7cDQ1GyaiDHhVBpLxf8b?mode=gi_t) — Получайте помощь, делитесь советами и оставайтесь в курсе.
- **Сайт**: [omniroute.online](https://omniroute.online)
- **GitHub**: [github.com/diegosouzapw/OmniRoute](https://github.com/diegosouzapw/OmniRoute)
- **Issues**: [github.com/diegosouzapw/OmniRoute/issues](https://github.com/diegosouzapw/OmniRoute/issues)
- **WhatsApp**: [Группа сообщества](https://chat.whatsapp.com/JI7cDQ1GyaiDHhVBpLxf8b?mode=gi_t)
- **Оригинальный проект**: [9router от decolua](https://github.com/decolua/9router)
---
## 🔄 Как это работает
```
@@ -157,6 +198,497 @@ _Подключайте любую IDE или CLI-инструмент с AI ч
---
## 🎯 Что решает OmniRoute — 30 реальных проблем и вариантов использования
> **Каждый разработчик, использующий инструменты искусственного интеллекта, ежедневно сталкивается с этими проблемами.** OmniRoute был создан для решения всех этих проблем — от перерасхода средств до региональных блоков, от нарушенных потоков OAuth до операций протокола и наблюдения за предприятием.
<details>
<summary><b>💸 1. «Я плачу за дорогую подписку, но меня все равно прерывают лимиты» </b></summary>
Разработчики платят 20200 долларов в месяц за Claude Pro, Codex Pro или GitHub Copilot. Даже при оплате квота имеет потолок — 5 часов использования, еженедельные лимиты или поминутные ограничения. В середине сеанса кодирования провайдер перестает отвечать, и разработчик теряет поток и производительность.
**Как OmniRoute решает эту проблему:**
- **Умный 4-уровневый резерв** — если квота подписки исчерпана, происходит автоматическое перенаправление на API-ключ → Дешево → Бесплатно без вмешательства вручную.
- **Отслеживание квот в реальном времени** — показывает потребление токенов в режиме реального времени с обратным отсчетом сброса (5 часов, ежедневно, еженедельно).
- **Поддержка нескольких учетных записей** — Несколько учетных записей у каждого провайдера с автоматическим циклическим перебором — когда один из них заканчивается, переключается на следующий
- **Пользовательские комбинации** — Настраиваемые резервные цепочки с 6 стратегиями балансировки (сначала заполняемые, циклический, P2C, случайные, наименее используемые, с оптимизацией затрат)
- **Бизнес-квоты Кодекса** — мониторинг квот рабочего пространства для бизнеса/команды непосредственно на панели управления.
</details>
<details>
<summary><b>🔌 2. «Мне нужно использовать несколько поставщиков, но у каждого свой API» </b></summary>
OpenAI использует один формат, Claude (Anthropic) — другой, Gemini — третий. Если разработчик хочет протестировать модели от разных поставщиков или использовать резервный вариант между ними, ему необходимо перенастроить SDK, изменить конечные точки, разобраться с несовместимыми форматами. Пользовательские поставщики (FriendLI, NIM) имеют нестандартные конечные точки модели.
**Как OmniRoute решает эту проблему:**
- **Единая конечная точка** — один `http://localhost:20128/v1` служит прокси для всех 36+ провайдеров.
- **Перевод формата** — Автоматический и прозрачный: OpenAI ↔ Claude ↔ Gemini ↔ API ответов
- **Очистка ответов** — удаляются нестандартные поля (`x_groq`, `usage_breakdown`, `service_tier`), которые нарушают OpenAI SDK v1.83+.
- **Нормализация ролей** — преобразует `developer` в `system` для поставщиков, не поддерживающих OpenAI; `system``user` для GLM/ERNIE
- **Think Tag Extraction** — извлекает блоки `<think>` из таких моделей, как DeepSeek R1, в стандартизированный `reasoning_content`.
- **Структурированный вывод для Gemini** — автоматическое преобразование `json_schema``responseMimeType`/`responseSchema`.
- **`stream` по умолчанию — `false`** — соответствует спецификации OpenAI, что позволяет избежать неожиданного SSE в SDK Python/Rust/Go.
</details>
<details>
<summary><b>🌐 3. «Мой провайдер ИИ блокирует мой регион/страну» </b></summary>
Такие провайдеры, как OpenAI/Codex, блокируют доступ из определенных географических регионов. Пользователи получают ошибки типа `unsupported_country_region_territory` во время подключений OAuth и API. Особенно это расстраивает разработчиков из развивающихся стран.
**Как OmniRoute решает эту проблему:**
- **3-уровневая конфигурация прокси** — настраиваемый прокси-сервер на трех уровнях: глобальный (весь трафик), для каждого провайдера (только один провайдер) и для каждого соединения/ключа.
- **Значки прокси с цветной кодировкой** — Визуальные индикаторы: 🟢 глобальный прокси, 🟡 прокси-сервер провайдера, 🔵 прокси-сервер подключения, всегда показывающий IP-адрес.
- **Обмен токенов OAuth через прокси** — поток OAuth также проходит через прокси, решая проблему `unsupported_country_region_territory`.
- **Тесты подключения через прокси** — тесты подключения используют настроенный прокси-сервер (прямого обхода больше нет)
- **Поддержка SOCKS5** — Полная поддержка прокси-сервера SOCKS5 для исходящей маршрутизации.
- **Подмена отпечатка пальца TLS** — отпечаток TLS, подобный браузеру, через `wreq-js` для обхода обнаружения ботов.
</details>
<details>
<summary><b>🆓 4. «Я хочу использовать ИИ для кодирования, но у меня нет денег» </b></summary>
Не каждый может платить 20200 долларов в месяц за подписку на ИИ. Студентам, разработчикам из развивающихся стран, любителям и фрилансерам нужен доступ к качественным моделям по нулевой цене.
**Как OmniRoute решает эту проблему:**
- **Встроенные провайдеры уровня бесплатного пользования** — Встроенная поддержка 100% бесплатных провайдеров: iFlow (8 моделей с неограниченным количеством пользователей), Qwen (3 модели с неограниченным количеством пользователей), Kiro (Claude бесплатно), Gemini CLI (180 тысяч в месяц бесплатно).
- **Комбинации только бесплатно** — цепочка `gc/gemini-3-flash → if/kimi-k2-thinking → qw/qwen3-coder-plus` = 0 долларов США в месяц без простоев.
- **Бесплатные кредиты NVIDIA NIM** — интегрировано 1000 бесплатных кредитов.
- **Стратегия оптимизации затрат** — стратегия маршрутизации, которая автоматически выбирает самого дешевого доступного провайдера.
</details>
<details>
<summary><b>🔒 5. «Мне нужно защитить мой AI-шлюз от несанкционированного доступа» </b></summary>
При предоставлении доступа к сети AI-шлюза (LAN, VPS, Docker) любой, у кого есть адрес, может использовать токены/квоту разработчика. Без защиты API уязвимы для неправильного использования, быстрого внедрения и злоупотреблений.
**Как OmniRoute решает эту проблему:**
- **Управление ключами API** — генерация, ротация и определение области действия для каждого поставщика с помощью специальной страницы `/dashboard/api-manager`.
- **Разрешения на уровне модели** — Ограничьте использование ключей API определенными моделями (`openai/*`, шаблоны подстановочных знаков) с помощью переключателя Разрешить все/Ограничить.
- **API Endpoint Protection** — требует ключ для `/v1/models` и блокирует определенных поставщиков из списка.
- **Auth Guard + защита CSRF** — все маршруты информационной панели защищены промежуточным программным обеспечением `withAuth` + токенами CSRF.
- **Ограничитель скорости** — ограничение скорости для каждого IP с помощью настраиваемых окон.
- **IP-фильтрация** — список разрешенных/блокированных для контроля доступа.
- **Prompt Injection Guard** — очистка от вредоносных шаблонов подсказок.
- **Шифрование AES-256-GCM** — неактивные учетные данные зашифрованы.
</details>
<details>
<summary><b>🛑 6. «Мой провайдер вышел из строя, и я потерял процесс кодирования» </b></summary>
Поставщики ИИ могут работать нестабильно, возвращать ошибки 5xx или достигать временных ограничений скорости. Если разработчик зависит от одного провайдера, его работу прерывают. Без автоматических выключателей повторные попытки могут привести к сбою приложения.
**Как OmniRoute решает эту проблему:**
- **Выключатель для каждого поставщика** — автоматическое открытие/закрытие с настраиваемыми пороговыми значениями и временем восстановления (закрыто/открыто/полуоткрыто).
- **Экспоненциальная задержка**  прогрессивная задержка повторных попыток.
- **Anti-Thundering Herd** — Мьютекс + защита семафора от одновременных штормов повторных попыток.
- **Комбо-резервные цепочки** — в случае сбоя основного поставщика автоматически проходит через цепочку без вмешательства.
- **Комбо-выключатель** — автоматически отключает неисправных поставщиков в комбинированной цепочке.
- **Панель работоспособности** — мониторинг работоспособности, состояния автоматических выключателей, блокировки, статистика кэша, задержка p50/p95/p99.
</details>
<details>
<summary><b>🔧 7. «Настройка каждого инструмента искусственного интеллекта утомительна и повторяется» </b></summary>
Разработчики используют Cursor, Claude Code, Codex CLI, OpenClaw, Gemini CLI, Kilo Code... Для каждого инструмента требуется своя конфигурация (конечная точка API, ключ, модель). Перенастройка при смене провайдера или модели — пустая трата времени.
**Как OmniRoute решает эту проблему:**
- **Панель инструментов CLI** — выделенная страница с настройкой в один клик Claude Code, Codex CLI, OpenClaw, Kilo Code, Antigravity, Cline.
- **Генератор конфигураций GitHub Copilot** — генерирует `chatLanguageModels.json` для кода VS с массовым выбором модели.
- **Мастер адаптации** — пошаговая пошаговая настройка для начинающих пользователей.
- **Одна конечная точка, все модели** — настройте `http://localhost:20128/v1` один раз и получите доступ к более чем 36 поставщикам услуг.
</details>
<details>
<summary><b>🔑 8. «Управление токенами OAuth от нескольких провайдеров — это ад» </b></summary>
Claude Code, Codex, Gemini CLI, Copilot — все используют OAuth 2.0 с токенами с истекающим сроком действия. Разработчикам необходимо постоянно проходить повторную аутентификацию, иметь дело с `client_secret is missing`, `redirect_uri_mismatch` и сбоями на удаленных серверах. OAuth в LAN/VPS особенно проблематичен.
**Как OmniRoute решает эту проблему:**
- **Автоматическое обновление токенов** — токены OAuth обновляются в фоновом режиме до истечения срока их действия.
- **Встроенный OAuth 2.0 (PKCE)** — автоматический поток для Claude Code, Codex, Gemini CLI, Copilot, Kiro, Qwen, iFlow.
- **OAuth с несколькими учетными записями**  несколько учетных записей для каждого провайдера посредством извлечения токена JWT/ID.
- **OAuth LAN/Remote Fix** — обнаружение частного IP-адреса для `redirect_uri` + ручной режим URL-адреса для удаленных серверов.
- **OAuth за Nginx** — использует `window.location.origin` для совместимости с обратным прокси-сервером.
- **Руководство по удаленному OAuth** — пошаговое руководство по учетным данным Google Cloud на VPS/Docker.
</details>
<details>
<summary><b>📊 9. «Я не знаю, сколько и куда я трачу» </b></summary>
Разработчики используют нескольких платных поставщиков, но не имеют единого представления о расходах. У каждого провайдера есть своя панель выставления счетов, но единого представления нет. Неожиданные расходы могут накопиться.
**Как OmniRoute решает эту проблему:**
- **Панель анализа затрат** — отслеживание затрат на каждый токен и управление бюджетом для каждого поставщика.
- **Ограничения бюджета на уровень** — потолок расходов на уровень, который запускает автоматический возврат к резервному варианту.
- **Конфигурация цен на модель** — настраиваемые цены на модель.
- **Статистика использования каждого ключа API** — количество запросов и временная метка последнего использования для каждого ключа.
- **Панель аналитики** — карточки статистики, диаграмма использования модели, таблица поставщиков с показателями успеха и задержкой.
</details>
<details>
<summary><b>🐛 10. «Я не могу диагностировать ошибки и проблемы в вызовах ИИ» </b></summary>
Когда вызов завершается неудачей, разработчик не знает, было ли это ограничением скорости, сроком действия токена, неправильным форматом или ошибкой провайдера. Фрагментированные журналы на разных терминалах. Без наблюдаемости отладка осуществляется методом проб и ошибок.
**Как OmniRoute решает эту проблему:**
- **Панель управления унифицированными журналами** — 4 вкладки: журналы запросов, журналы прокси, журналы аудита, консоль.
- **Консольный просмотр журнала** — просмотрщик в режиме терминала в режиме реального времени с уровнями с цветовой кодировкой, автоматической прокруткой, поиском и фильтрацией.
- **Журналы прокси-сервера SQLite** — постоянные журналы, сохраняющиеся после перезапуска сервера.
- **Площадка переводчика** — 4 режима отладки: Площадка (перевод формата), Тестер чата (туда и обратно), Тестовый стенд (пакетный), Мониторинг в реальном времени (в режиме реального времени).
- **Запрос телеметрии** — задержка p50/p95/p99 + отслеживание X-Request-Id
- **Журналирование на основе файлов с ротацией** — перехватчик консоли записывает все в журнал JSON с ротацией на основе размера.
</details>
<details>
<summary><b>🏗️ 11. «Развертывание и обслуживание шлюза сложны» </b></summary>
Установка, настройка и обслуживание прокси-сервера AI в различных средах (локальных, VPS, Docker, облаке) — трудоемкий процесс. Такие проблемы, как жестко запрограммированные пути, `EACCES` в каталогах, конфликты портов и кроссплатформенные сборки, добавляют проблем.
**Как OmniRoute решает эту проблему:**
- **глобальная установка npm** — `npm install -g omniroute && omniroute` — выполнено
- **Мультиплатформенность Docker** — встроенная версия AMD64 + ARM64 (Apple Silicon, AWS Graviton, Raspberry Pi)
- **Профили Docker Compose** — `base` (без инструментов CLI) и `cli` (с Claude Code, Codex, OpenClaw)
- **Electron Desktop App** — собственное приложение для Windows/macOS/Linux с панелью задач, автозапуском и автономным режимом.
- **Режим разделения портов** — API и панель мониторинга на отдельных портах для расширенных сценариев (обратный прокси-сервер, сеть контейнеров).
- **Cloud Sync** — синхронизация конфигурации между устройствами через Cloudflare Workers.
- **Резервные копии БД** — автоматическое резервное копирование, восстановление, экспорт и импорт всех настроек.
</details>
<details>
<summary><b>🌍 12. «Интерфейс только на английском языке, и моя команда не говорит по-английски» </b></summary>
Команды в неанглоязычных странах, особенно в Латинской Америке, Азии и Европе, испытывают трудности с интерфейсами только на английском языке. Языковые барьеры сокращают внедрение и увеличивают количество ошибок в конфигурации.
**Как OmniRoute решает эту проблему:**
- **Панель управления i18n — 30 языков** — Все более 500 клавиш переведены, включая арабский, болгарский, датский, немецкий, испанский, финский, французский, иврит, хинди, венгерский, индонезийский, итальянский, японский, корейский, малайский, голландский, норвежский, польский, португальский (PT/BR), румынский, русский, словацкий, шведский, тайский, украинский, вьетнамский, китайский, филиппинский, английский
- **Поддержка RTL** — поддержка написания справа налево для арабского языка и иврита.
- **Многоязычные файлы README** — 30 полных переводов документации.
- **Выбор языка** — значок глобуса в заголовке для переключения в реальном времени.
</details>
<details>
<summary><b>🔄 13. «Мне нужно больше, чем просто чат — мне нужны вложения, изображения, аудио»</b></summary>
ИИ — это не просто завершение чата. Разработчикам необходимо генерировать изображения, расшифровывать аудио, создавать вложения для RAG, изменять ранжирование документов и модерировать контент. Каждый API имеет свою конечную точку и формат.
**Как OmniRoute решает эту проблему:**
- **Встраивания** — `/v1/embeddings` с 6 поставщиками и более чем 9 моделями.
- **Генерация изображений** — `/v1/images/generations` с 10 поставщиками и более чем 20 моделями (OpenAI, xAI, Together, Fireworks, Nebius, Hyperbolic, NanoBanana, Antigradity, SD WebUI, ComfyUI)
- **Преобразование текста в видео** — `/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/moderations` — Проверка безопасности контента.
- **Реранжирование** — `/v1/rerank` — Изменение ранжирования релевантности документа.
- **API ответов** — полная поддержка `/v1/responses` для Кодекса.
</details>
<details>
<summary><b>🧪 14. «У меня нет возможности тестировать и сравнивать качество разных моделей» </b></summary>
Разработчики хотят знать, какая модель лучше всего подходит для их варианта использования (код, перевод, рассуждения), но сравнивать вручную — это медленно. Интегрированных инструментов оценки не существует.
**Как OmniRoute решает эту проблему:**
- **Оценки LLM** — тестирование золотого набора с 10 предварительно загруженными вариантами, охватывающими приветствия, математику, географию, генерацию кода, соответствие JSON, перевод, уценку, отказ от безопасности.
- **4 стратегии сопоставления** — `exact`, `contains`, `regex`, `custom` (функция JS)
- **Тестовый стенд Translator Playground** — пакетное тестирование с несколькими входными данными и ожидаемыми результатами, сравнение между поставщиками.
- **Тестер чата** — полный цикл с визуальным отображением ответов.
- **Живой монитор** — поток всех запросов, проходящих через прокси, в реальном времени.
</details>
<details>
<summary><b>📈 15. «Мне нужно масштабироваться без потери производительности» </b></summary>
По мере роста объема запросов без кэширования одних и тех же вопросов возникают дублирующие затраты. Без идемпотентности дублирование запросов приводит к отходам обработки. Необходимо соблюдать ограничения по тарифам для каждого поставщика.
**Как OmniRoute решает эту проблему:**
- **Семантический кеш** — двухуровневый кеш (сигнатура + семантика) снижает стоимость и задержку.
- **Request Idempotency** — окно дедупликации 5 с для идентичных запросов.
- **Обнаружение ограничения скорости** — число оборотов в минуту для каждого провайдера, минимальный разрыв и максимальное одновременное отслеживание.
- **Редактируемые ограничения скорости** — настраиваемые значения по умолчанию в меню «Настройки» → «Устойчивость с постоянством».
- **Кэш проверки ключей API** — трехуровневый кеш для повышения производительности.
- **Панель состояния с телеметрией** — задержка p50/p95/p99, статистика кэша, время безотказной работы.
</details>
<details>
<summary><b>🤖 16. «Я хочу глобально контролировать поведение модели» </b></summary>
Разработчики, которым нужны все ответы на определенном языке, с определенным тоном или которые хотят ограничить количество токенов рассуждения. Настраивать это в каждом инструменте/запросе непрактично.
**Как OmniRoute решает эту проблему:**
- **Внедрение системных подсказок** — глобальное приглашение применяется ко всем запросам.
- **Продуманная проверка бюджета** — контроль распределения токенов для каждого запроса (сквозной, автоматический, пользовательский, адаптивный)
- **6 стратегий маршрутизации** — глобальные стратегии, определяющие распределение запросов.
- **Маршрутизатор с подстановочными знаками** — шаблоны `provider/*` динамически маршрутизируются к любому поставщику.
- **Переключение/включение комбо** — переключение комбо непосредственно с панели управления.
- **Переключение поставщика** — включение/отключение всех подключений к провайдеру одним щелчком мыши.
- **Заблокированные поставщики** — исключить определенных поставщиков из списка `/v1/models`.
</details>
<details>
<summary><b>🧰 17. «Мне нужны инструменты MCP как первоклассные возможности продукта» </b></summary>
Многие шлюзы AI предоставляют MCP только как скрытую деталь реализации. Командам нужен видимый и управляемый операционный уровень.
**Как OmniRoute решает эту проблему:**
- MCP отображается на панели навигации панели управления и на вкладке протокола конечной точки.
- Отдельная страница управления MCP с процессами, инструментами, объемами работ и аудитом.
- Встроенное краткое руководство по `omniroute --mcp` и адаптации клиентов.
</details>
<details>
<summary><b>🧠 18. «Мне нужна оркестровка A2A с путями задач синхронизации и потоковой передачи» </b></summary>
Рабочие процессы агента требуют как прямых ответов, так и длительного потокового выполнения с контролем жизненного цикла.
**Как OmniRoute решает эту проблему:**
- Конечная точка A2A JSON-RPC (`POST /a2a`) с `message/send` и `message/stream`.
- Потоковая передача SSE с распространением состояния терминала
- API жизненного цикла задач для `tasks/get` и `tasks/cancel`.
</details>
<details>
<summary><b>🛰️ 19. «Мне нужно реальное состояние процесса MCP, а не угаданный статус» </b></summary>
Оперативным группам необходимо знать, действительно ли MCP работает, а не только доступен ли API.
**Как OmniRoute решает эту проблему:**
- Файл контрольного сигнала времени выполнения с PID, временными метками, транспортом, количеством инструментов и режимом области действия.
- API статуса MCP, объединяющий пульс + недавнюю активность
- Карты состояния пользовательского интерфейса для актуальности процессов, времени безотказной работы и пульса.
</details>
<details>
<summary><b>📋 20. «Мне нужно проверяемое выполнение инструмента MCP» </b></summary>
Когда инструменты изменяют конфигурацию или запускают действия операционной системы, командам необходима судебно-медицинская отслеживаемость.
**Как OmniRoute решает эту проблему:**
- Ведение журнала аудита на основе SQLite для вызовов инструментов MCP.
- Фильтры по инструменту, успеху/неуспеху, ключу API и нумерации страниц.
- Таблица аудита панели мониторинга + конечные точки статистики для автоматизации
</details>
<details>
<summary><b>🔐 21. «Мне нужны ограниченные разрешения MCP для каждой интеграции» </b></summary>
Разные клиенты должны иметь минимальный доступ к категориям инструментов.
**Как OmniRoute решает эту проблему:**
- 9 детальных областей MCP для контролируемого доступа к инструментам
- Обеспечение соблюдения границ и видимость в пользовательском интерфейсе управления MCP.
- Безопасное положение по умолчанию для рабочих инструментов.
</details>
<details>
<summary><b>⚙️ 22. «Мне нужен оперативный контроль без передислокации» </b></summary>
Командам необходимы быстрые изменения во время выполнения во время инцидентов или событий, связанных с затратами.
**Как OmniRoute решает эту проблему:**
- Переключение комбо-активации прямо с панели управления MCP.
- Применение профилей устойчивости из предварительно определенных пакетов политик.
- Сброс состояния автоматического выключателя с той же панели управления.
</details>
<details>
<summary><b>🔄 23. «Мне нужна оперативная видимость и отмена жизненного цикла задачи A2A» </b></summary>
Без прозрачности жизненного цикла инциденты с задачами становится трудно сортировать.
**Как OmniRoute решает эту проблему:**
- Список задач/фильтрация по состоянию/навыку с нумерацией страниц
- Детализация метаданных задачи, событий и артефактов.
- Конечная точка отмены задачи и действие пользовательского интерфейса с подтверждением.
</details>
<details>
<summary><b>🌊 24. «Мне нужны метрики активного потока для загрузки A2A» </b></summary>
Рабочие процессы потоковой передачи требуют оперативного понимания параллелизма и живых соединений.
**Как OmniRoute решает эту проблему:**
- Счетчики активных потоков интегрированы в статус A2A
- Временная метка последней задачи и количество состояний
- Карты информационной панели A2A для мониторинга операций в реальном времени.
</details>
<details>
<summary><b>🪪 25. «Мне нужно стандартное обнаружение агента для клиентов» </b></summary>
Внешним клиентам и оркестраторам для адаптации необходимы машиночитаемые метаданные.
**Как OmniRoute решает эту проблему:**
- Карта агента открыта по адресу `/.well-known/agent.json`.
- Возможности и навыки, отображаемые в пользовательском интерфейсе управления.
- API статуса A2A включает метаданные обнаружения для автоматизации.
</details>
<details>
<summary><b>🧭 26. «Мне нужна возможность обнаружения протокола в UX продукта» </b></summary>
Если пользователи не могут обнаружить поверхности протокола, качество внедрения и поддержки снижается.
**Как OmniRoute решает эту проблему:**
- Записи на боковой панели для MCP и A2A.
- Вкладка «Протоколы» на странице конечной точки с быстрым запуском и статусом.
- Ссылки из обзора на специальные панели управления.
</details>
<details>
<summary><b>🧪 27. «Мне нужна сквозная проверка протокола с реальными клиентами» </b></summary>
Пробных тестов недостаточно для проверки совместимости протокола перед выпуском.
**Как OmniRoute решает эту проблему:**
- Пакет E2E, который загружает приложение и использует настоящий клиентский транспорт MCP SDK.
- Клиент A2A тестирует потоки обнаружения, отправки, потоковой передачи, получения и отмены.
- Перекрестная проверка утверждений с помощью API-интерфейсов аудита MCP и задач A2A.
</details>
<details>
<summary><b>📡 28. «Мне нужна унифицированная наблюдаемость на всех интерфейсах» </b></summary>
Разделение наблюдаемости по протоколам создает «слепые зоны» и увеличивает MTTR.
**Как OmniRoute решает эту проблему:**
- Унифицированные дашборды/логи/аналитика в одном продукте
- Здоровье + аудит + телеметрия запросов на уровнях OpenAI, MCP и A2A.
- Операционные API для статуса и автоматизации
</details>
<details>
<summary><b>💼 29. «Мне нужна одна среда выполнения для прокси + инструментов + оркестровки агентов» </b></summary>
Запуск множества отдельных служб увеличивает эксплуатационные расходы и количество видов сбоев.
**Как OmniRoute решает эту проблему:**
- OpenAI-совместимый прокси, сервер MCP и сервер A2A в одном стеке
- Общая аутентификация, устойчивость, хранилище данных и наблюдаемость.
- Согласованная модель политики на всех поверхностях взаимодействия.
</details>
<details>
<summary><b>🚀 30. «Мне нужно реализовать агентские рабочие процессы без разрастания связующего кода» </b></summary>
Команды теряют скорость при объединении нескольких специальных сервисов и сценариев.
**Как OmniRoute решает эту проблему:**
- Единая стратегия конечных точек для клиентов и агентов
- Встроенные пользовательские интерфейсы управления протоколами и пути проверки дыма.
- Готовые к работе основы (безопасность, ведение журналов, отказоустойчивость, резервное копирование)
</details>
### Примеры сборников сценариев (интегрированные варианты использования)
**Пособие А: максимальное использование платной подписки + дешевое резервное копирование**
```txt
Combo: "maximize-claude"
1. cc/claude-opus-4-6
2. glm/glm-4.7
3. if/kimi-k2-thinking
Monthly cost: $20 + small backup spend
Outcome: higher quality, near-zero interruption
```
**Пособие Б: стек кодирования с нулевой стоимостью**
```txt
Combo: "free-forever"
1. gc/gemini-3-flash
2. if/kimi-k2-thinking
3. qw/qwen3-coder-plus
Monthly cost: $0
Outcome: stable free coding workflow
```
**Пособие C: Всегда работающая резервная цепочка 24 часа в сутки, 7 дней в неделю**
```txt
Combo: "always-on"
1. cc/claude-opus-4-6
2. cx/gpt-5.2-codex
3. glm/glm-4.7
4. minimax/MiniMax-M2.1
5. if/kimi-k2-thinking
Outcome: deep fallback depth for deadline-critical workloads
```
**Сборник D: Операции агента с помощью MCP + A2A**
```txt
1) Start MCP transport (`omniroute --mcp`) for tool-driven operations
2) Run A2A tasks via `message/send` and `message/stream`
3) Observe via /dashboard/mcp and /dashboard/a2a
4) Control incidents with resilience profile + task cancellation
```
---
## ⚡ Быстрый старт
**1. Установите глобально:**
@@ -249,7 +781,7 @@ docker compose --profile cli up -d
---
## 🖥️ Настольное Приложение — Оффлайн и Всегда Активно
## 🖥️
> 🆕 **НОВИНКА!** OmniRoute теперь доступен как **нативное настольное приложение** для Windows, macOS и Linux.
@@ -296,67 +828,6 @@ npm run electron:build:linux # Linux (.AppImage)
---
## 🎯 Сценарии использования
### Сценарий 1: «У меня подписка Claude Pro»
**Проблема:** Квота истекает неиспользованной, лимиты скорости во время интенсивного программирования
```
Combo: "maximize-claude"
1. cc/claude-opus-4-6 (используйте подписку полностью)
2. glm/glm-4.7 (дешёвый бэкап при исчерпании квоты)
3. if/kimi-k2-thinking (бесплатный аварийный fallback)
Месячная стоимость: $20 (подписка) + ~$5 (бэкап) = $25 итого
vs. $20 + упирание в лимиты = разочарование
```
### Сценарий 2: «Хочу нулевую стоимость»
**Проблема:** Не может позволить подписки, нужен надёжный AI для программирования
```
Combo: "free-forever"
1. gc/gemini-3-flash (180K бесплатно/мес)
2. if/kimi-k2-thinking (неограниченно бесплатно)
3. qw/qwen3-coder-plus (неограниченно бесплатно)
Месячная стоимость: $0
Качество: Модели готовые к продакшену
```
### Сценарий 3: «Мне нужно программировать 24/7, без перерывов»
**Проблема:** Дедлайны, не может позволить простой
```
Combo: "always-on"
1. cc/claude-opus-4-6 (лучшее качество)
2. cx/gpt-5.2-codex (вторая подписка)
3. glm/glm-4.7 (дешёвый, ежедневный сброс)
4. minimax/MiniMax-M2.1 (самый дешёвый, сброс 5ч)
5. if/kimi-k2-thinking (бесплатно неограниченно)
Результат: 5 уровней fallback = нулевой простой
```
### Сценарий 4: «Хочу БЕСПЛАТНЫЙ AI в OpenClaw»
**Проблема:** Нужен AI-ассистент в мессенджерах, полностью бесплатно
```
Combo: "openclaw-free"
1. if/glm-4.7 (неограниченно бесплатно)
2. if/minimax-m2.1 (неограниченно бесплатно)
3. if/kimi-k2-thinking (неограниченно бесплатно)
Месячная стоимость: $0
Доступ через: WhatsApp, Telegram, Slack, Discord, iMessage, Signal...
```
---
## 💡 Основные функции
### 🧠 Маршрутизация и интеллект
@@ -372,6 +843,8 @@ Combo: "openclaw-free"
| 🧩 **Пользовательские модели** | Добавьте любой ID модели к любому провайдеру |
| 🌐 **Wildcard-маршрутизатор** | Маршрутизируйте паттерны `provider/*` к любому провайдеру динамически |
| 🧠 **Бюджет рассуждений** | Режимы passthrough, auto, custom и adaptive для моделей рассуждений |
| 🔀 **Model Aliases** | Auto-forward deprecated model IDs to current replacements (built-in + custom) |
| ⚡ **Background Degradation** | Auto-route background tasks (titles, summaries) to cheaper models |
| 💬 **Инъекция System Prompt** | Глобальный system prompt для всех запросов |
| 📄 **API Responses** | Полная поддержка OpenAI Responses API (`/v1/responses`) для Codex |
@@ -388,15 +861,18 @@ Combo: "openclaw-free"
### 🛡️ Устойчивость и безопасность
| Функция | Что делает |
| -------------------------------- | -------------------------------------------------------------- |
| 🔌 **Circuit Breaker** | Авто-открытие/закрытие по провайдеру с настраиваемыми порогами |
| 🛡️ **Anti-Thundering Herd** | Mutex + семафор для API key провайдеров |
| 🧠 **Семантический кеш** | Двухуровневый кеш (сигнатура + семантика) снижает стоимость |
| **Идемпотентность запросов** | 5с окно дедупликации для дублирующихся запросов |
| 🔒 **Спуфинг TLS Fingerprint** | Обход обнаружения ботов через wreq-js |
| 🌐 **Фильтрация IP** | Allowlist/blocklist для контроля доступа к API |
| 📊 **Настраиваемые Rate Limits** | Настраиваемые RPM, минимальный интервал, макс. конкуррентность |
| Функция | Что делает |
| -------------------------------- | ---------------------------------------------------------------------------- |
| 🔌 **Circuit Breaker** | Авто-открытие/закрытие по провайдеру с настраиваемыми порогами |
| 🎯 **Endpoint-Aware Models** | Custom models declare supported endpoints + API format |
| 🛡️ **Anti-Thundering Herd** | Mutex + семафор для API key провайдеров |
| 🧠 **Семантический кеш** | Двухуровневый кеш (сигнатура + семантика) снижает стоимость |
| **Идемпотентность запросов** | 5с окно дедупликации для дублирующихся запросов |
| 🔒 **Спуфинг TLS Fingerprint** | Обход обнаружения ботов через wreq-js |
| 🌐 **Фильтрация IP** | Allowlist/blocklist для контроля доступа к API |
| 📊 **Настраиваемые Rate Limits** | Настраиваемые RPM, минимальный интервал, макс. конкуррентность |
| 💾 **Rate Limit Persistence** | Learned limits survive restarts via SQLite with 60s debounce + 24h staleness |
| 🔄 **Token Refresh Resilience** | Per-provider circuit breaker (5 fails→30min) + 30s timeout per attempt |
### 📊 Наблюдаемость и аналитика
@@ -496,6 +972,27 @@ Combo: "my-coding-stack"
</details>
## 🧪 Оценки (Evals)
OmniRoute включает встроенный фреймворк оценки для тестирования качества ответов LLM по golden set. Доступ через **Analytics → Evals** в dashboard.
### Встроенный Set
Предзагруженный «OmniRoute Golden Set» содержит 10 тестов:
- Приветствия, математика, география, генерация кода
- Соответствие формату JSON, перевод, markdown
- Отказ от небезопасного контента, подсчёт, булева логика
### Стратегии оценки
| Стратегия | Описание | Пример |
| ---------- | ----------------------------------------------------- | -------------------------------- |
| `exact` | Вывод должен совпадать точно | `"4"` |
| `contains` | Вывод должен содержать подстроку (без учёта регистра) | `"Paris"` |
| `regex` | Вывод должен соответствовать regex-паттерну | `"1.*2.*3"` |
| `custom` | Пользовательская JS-функция возвращает true/false | `(output) => output.length > 10` |
---
## 📖 Руководство по настройке
@@ -778,97 +1275,6 @@ Dashboard → CLI Tools → OpenClaw → Выбрать модель → При
---
## 📊 Доступные модели
<details>
<summary><b>Посмотреть все доступные модели</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`
**GitHub Copilot (`gh/`)**:
- `gh/gpt-5`
- `gh/claude-4.5-sonnet`
**NVIDIA NIM (`nvidia/`)** - БЕСПЛАТНЫЕ кредиты:
- `nvidia/llama-3.3-70b-instruct`
- `nvidia/mistral-7b-instruct`
- 50+ моделей на [build.nvidia.com](https://build.nvidia.com)
**GLM (`glm/`)** - $0.6/1M:
- `glm/glm-4.7`
**MiniMax (`minimax/`)** - $0.2/1M:
- `minimax/MiniMax-M2.1`
**iFlow (`if/`)** - БЕСПЛАТНО:
- `if/kimi-k2-thinking`
- `if/qwen3-coder-plus`
- `if/deepseek-r1`
- `if/glm-4.7`
- `if/minimax-m2`
**Qwen (`qw/`)** - БЕСПЛАТНО:
- `qw/qwen3-coder-plus`
- `qw/qwen3-coder-flash`
**Kiro (`kr/`)** - БЕСПЛАТНО:
- `kr/claude-sonnet-4.5`
- `kr/claude-haiku-4.5`
**OpenRouter (`or/`)** - 100+ моделей:
- `or/anthropic/claude-4-sonnet`
- `or/google/gemini-2.5-pro`
- Любая модель с [openrouter.ai/models](https://openrouter.ai/models)
</details>
---
## 🧪 Оценки (Evals)
OmniRoute включает встроенный фреймворк оценки для тестирования качества ответов LLM по golden set. Доступ через **Analytics → Evals** в dashboard.
### Встроенный Golden Set
Предзагруженный «OmniRoute Golden Set» содержит 10 тестов:
- Приветствия, математика, география, генерация кода
- Соответствие формату JSON, перевод, markdown
- Отказ от небезопасного контента, подсчёт, булева логика
### Стратегии оценки
| Стратегия | Описание | Пример |
| ---------- | ----------------------------------------------------- | -------------------------------- |
| `exact` | Вывод должен совпадать точно | `"4"` |
| `contains` | Вывод должен содержать подстроку (без учёта регистра) | `"Paris"` |
| `regex` | Вывод должен соответствовать regex-паттерну | `"1.*2.*3"` |
| `custom` | Пользовательская JS-функция возвращает true/false | `(output) => output.length > 10` |
---
## 🐛 Устранение неполадок
<details>
@@ -924,7 +1330,7 @@ OmniRoute включает встроенный фреймворк оценки
---
## 🛠️ Технологический стек
## 🛠️
- **Runtime**: Node.js 20+
- **Язык**: TypeScript 5.9 — **100% TypeScript** в `src/` и `open-sse/` (v1.0.6)
@@ -955,17 +1361,7 @@ OmniRoute включает встроенный фреймворк оценки
---
## 📧 Поддержка
> 💬 **Присоединяйтесь к сообществу!** [Группа WhatsApp](https://chat.whatsapp.com/JI7cDQ1GyaiDHhVBpLxf8b?mode=gi_t) — Получайте помощь, делитесь советами и оставайтесь в курсе.
- **Сайт**: [omniroute.online](https://omniroute.online)
- **GitHub**: [github.com/diegosouzapw/OmniRoute](https://github.com/diegosouzapw/OmniRoute)
- **Issues**: [github.com/diegosouzapw/OmniRoute/issues](https://github.com/diegosouzapw/OmniRoute/issues)
- **WhatsApp**: [Группа сообщества](https://chat.whatsapp.com/JI7cDQ1GyaiDHhVBpLxf8b?mode=gi_t)
- **Оригинальный проект**: [9router от decolua](https://github.com/decolua/9router)
---
## 🗺️
## 👥 Участники

View File

@@ -3,8 +3,6 @@
# 🚀 OmniRoute — bezplatná brána AI
🌐 **[English](#-omniroute--the-free-ai-gateway)** | **[Português (BR)](#-omniroute--gateway-de-ia-gratuito)**
### Nikdy neprestávajte kódovať. Inteligentné smerovanie na **BEZPLATNÉ a nízkonákladové modely AI** s automatickým vrátením.
_Váš univerzálny proxy server API jeden koncový bod, 36+ poskytovateľov, nulové prestoje._
@@ -112,6 +110,35 @@ _Pripojte akýkoľvek nástroj IDE alebo CLI poháňaný AI cez OmniRoute be
---
## 🖼️
<div align="center">
<img src="./docs/screenshots/MainOmniRoute.png" alt="OmniRoute" width="800"/>
</div>
---
## 📸
<details>
<summary><b>...</b></summary>
| # | # |
| ----- | ---------------------------------------- |
| **1** | ![1](docs/screenshots/01-providers.png) |
| **2** | ![2](docs/screenshots/02-combos.png) |
| **3** | ![3](docs/screenshots/03-analytics.png) |
| **4** | ![4](docs/screenshots/04-health.png) |
| **5** | ![5](docs/screenshots/05-translator.png) |
| **6** | ![6](docs/screenshots/06-settings.png) |
| **7** | ![7](docs/screenshots/07-cli-tools.png) |
| **8** | ![8](docs/screenshots/08-usage.png) |
| **9** | ![9](docs/screenshots/09-endpoint.png) |
</details>
---
## 🤔 Prečo OmniRoute?
**Prestaňte plytvať peniazmi a dosahovať limity:**
@@ -130,6 +157,18 @@ _Pripojte akýkoľvek nástroj IDE alebo CLI poháňaný AI cez OmniRoute be
---
## 📧 Podpora
> 💬 **Pripojte sa k našej komunite!** [WhatsApp Group](https://chat.whatsapp.com/JI7cDQ1GyaiDHhVBpLxf8b?mode=gi_t) — Získajte pomoc, zdieľajte tipy a buďte informovaní.
- **Web**: [omniroute.online](https://omniroute.online)
- **GitHub**: [github.com/diegosouzapw/OmniRoute](https://github.com/diegosouzapw/OmniRoute)
- **Problémy**: [github.com/diegosouzapw/OmniRoute/issues](https://github.com/diegosouzapw/OmniRoute/issues)
- **WhatsApp**: [Community Group](https://chat.whatsapp.com/JI7cDQ1GyaiDHhVBpLxf8b?mode=gi_t)
- **Pôvodný projekt**: [9router by decolua](https://github.com/decolua/9router)
---
## 🔄 Ako to funguje
```
@@ -159,6 +198,501 @@ Result: Never stop coding, minimal cost
---
## 🎯 Čo OmniRoute rieši — 30 bodov skutočnej bolesti a prípadov použitia
> **Každý vývojár, ktorý používa nástroje AI, čelí týmto problémom denne.** OmniRoute bol vytvorený tak, aby ich všetky vyriešil od prekročenia nákladov po regionálne bloky, od prerušených tokov OAuth po operácie protokolov a pozorovateľnosť podniku.
<details>
<summary><b>💸 1. „Platím za drahé predplatné, ale stále ma prerušujú limity“ </b></summary>
Vývojári platia za Claude Pro, Codex Pro alebo GitHub Copilot 20 200 dolárov mesačne. Aj pri platení má kvóta strop 5 hodín používania, týždenné limity alebo limity za minútu. Počas relácie kódovania poskytovateľ prestane reagovať a vývojár stráca tok a produktivitu.
**Ako to rieši OmniRoute:**
- **Inteligentný 4-úrovňový záložný systém** Ak sa vyčerpá kvóta predplatného, automaticky sa presmeruje na kľúč API → Lacné → Zadarmo s nulovým manuálnym zásahom
- **Sledovanie kvóty v reálnom čase** Zobrazuje spotrebu tokenov v reálnom čase s resetovaným odpočítavaním (5 hodín, denne, týždenne)
**Podpora viacerých účtov** Viacero účtov na poskytovateľa s automatickým opakovaním keď sa jeden minie, prepne sa na ďalší
**Vlastné kombá** Prispôsobiteľné záložné reťazce so 6 stratégiami vyvažovania (najskôr vyplniť, opakovane, P2C, náhodné, najmenej používané, nákladovo optimalizované)
- **Codex Business Quotas** — Monitorovanie kvót pracovného priestoru pre firmy/tím priamo na paneli
</details>
<details>
<summary><b>🔌 2. „Potrebujem použiť viacerých poskytovateľov, ale každý má iné API“ </b></summary>
OpenAI používa jeden formát, Claude (Anthropic) iný a Gemini ďalší. Ak chce vývojár testovať modely od rôznych poskytovateľov alebo medzi nimi záložné riešenie, musí prekonfigurovať súpravy SDK, zmeniť koncové body, vysporiadať sa s nekompatibilnými formátmi. Vlastní poskytovatelia (FriendLI, NIM) majú neštandardné modelové koncové body.
**Ako to rieši OmniRoute:**
- **Unified Endpoint** Jediný `http://localhost:20128/v1` slúži ako proxy pre všetkých 36+ poskytovateľov
- **Formátový preklad** — Automatický a transparentný: OpenAI ↔ Claude ↔ Gemini ↔ Responses API
**Dezinfekcia odozvy** Odstráni neštandardné polia (`x_groq`, `usage_breakdown`, `service_tier`), ktoré porušujú OpenAI SDK v1.83+
- **Normalizácia rolí** Konvertuje `developer``system` pre poskytovateľov, ktorí nie sú OpenAI; `system``user` pre GLM/ERNIE
**Think Tag Extraction** Extrahuje bloky `<think>` z modelov ako DeepSeek R1 do štandardizovaných `reasoning_content`
- **Štruktúrovaný výstup pre Gemini** — `json_schema` → automatická konverzia `responseMimeType`/`responseSchema`
- **`stream` predvolene je `false`** — Zosúladí sa so špecifikáciou OpenAI, čím sa zabráni neočakávanému SSE v súpravách Python/Rust/Go SDK
</details>
<details>
<summary><b>🌐 3. „Môj poskytovateľ AI blokuje môj región/krajinu“</b></summary>
Poskytovatelia ako OpenAI/Codex blokujú prístup z určitých geografických oblastí. Používatelia dostanú chyby ako `unsupported_country_region_territory` počas pripojení OAuth a API. To je frustrujúce najmä pre vývojárov z rozvojových krajín.
**Ako to rieši OmniRoute:**
- **Konfigurácia proxy servera na troch úrovniach** Konfigurovateľný server proxy na 3 úrovniach: globálny (celá prevádzka), podľa jednotlivých poskytovateľov (iba jeden poskytovateľ) a podľa pripojenia/kľúča
- **Farebné odznaky proxy** — Vizuálne indikátory: 🢢 globálny proxy, 🟡 proxy poskytovateľa, 🔵 proxy pripojenia, vždy zobrazuje IP
**Výmena tokenov OAuth cez proxy** tok OAuth prechádza aj cez proxy, čím sa rieši `unsupported_country_region_territory`
- **Testy pripojenia cez proxy** Testy pripojenia používajú nakonfigurovaný proxy (už žiadne priame obchádzanie)
- **Podpora SOCKS5** — Úplná podpora proxy SOCKS5 pre odchádzajúce smerovanie
- **TLS Fingerprint Spoofing** Odtlačok prsta TLS podobný prehliadaču cez `wreq-js` na obídenie detekcie robotov
</details>
<details>
<summary><b>🆓 4. „Chcem použiť AI na kódovanie, ale nemám peniaze“</b></summary>
Nie každý môže platiť 20 200 $ mesačne za predplatné AI. Študenti, vývojári z rozvíjajúcich sa krajín, fanúšikovia a nezávislí pracovníci potrebujú prístup ku kvalitným modelom za nulové náklady.
**Ako to rieši OmniRoute:**
- **Zabudovaní poskytovatelia bezplatnej úrovne** — Natívna podpora pre 100 % bezplatných poskytovateľov: iFlow (8 neobmedzených modelov), Qwen (3 neobmedzené modely), Kiro (Claude zdarma), Gemini CLI (180 000/mesiac zdarma)
- **Len bezplatné kombá** — Reťaz `gc/gemini-3-flash → if/kimi-k2-thinking → qw/qwen3-coder-plus` = 0 USD/mesiac s nulovými prestojmi
- **Bezplatné kredity NVIDIA NIM** integrovaných 1 000 bezplatných kreditov
- **Cost Optimized Strategy** Stratégia smerovania, ktorá automaticky vyberie najlacnejšieho dostupného poskytovateľa
</details>
<details>
<summary><b>🔒 5. „Potrebujem chrániť svoju bránu AI pred neoprávneným prístupom“</b></summary>
Pri vystavení brány AI do siete (LAN, VPS, Docker) môže ktokoľvek s adresou spotrebovať tokeny/kvótu vývojára. Bez ochrany sú rozhrania API náchylné na nesprávne použitie, rýchle vloženie a zneužitie.
**Ako to rieši OmniRoute:**
**Správa kľúčov API** Generovanie, rotácia a rozsah podľa poskytovateľa s vyhradenou stránkou `/dashboard/api-manager`
**Povolenia na úrovni modelu** Obmedzenie kľúčov API na konkrétne modely (`openai/*`, vzory zástupných znakov) s prepínačom Povoliť všetko/Obmedziť
**API Endpoint Protection** Vyžadovať kľúč pre `/v1/models` a blokovať konkrétnych poskytovateľov zo zoznamu
- **Auth Guard + ochrana CSRF** - Všetky trasy na dashboarde sú chránené middlevérom `withAuth` + tokenmi CSRF
- **Rate Limiter** — Obmedzenie rýchlosti na IP pomocou konfigurovateľných okien
- **IP Filtering** — Zoznam povolených/blokovaných pre riadenie prístupu
- **Prompt Injection Guard** Dezinfekcia proti škodlivým vzorom výzvy
- **Šifrovanie AES-256-GCM** — Prihlasovacie údaje sú v pokoji zašifrované
</details>
<details>
<summary><b>🛑 6. „Môj poskytovateľ zlyhal a stratil som tok kódovania“</b></summary>
Poskytovatelia AI sa môžu stať nestabilnými, vrátiť chyby 5xx alebo dosiahnuť dočasné limity sadzieb. Ak vývojár závisí od jedného poskytovateľa, bude prerušený. Bez ističov môžu opakované pokusy zlyhať aplikáciu.
**Ako to rieši OmniRoute:**
- **Istič pre každého poskytovateľa** — Automatické otváranie/zatváranie s konfigurovateľnými prahmi a chladením (zatvorené/otvorené/polootvorené)
- **Exponenciálne stiahnutie** — Postupné oneskorenie opakovania
- **Anti-Thundering Herd** - ochrana Mutex + semafor proti súbežným opakovaným búrkam
- **Combo Fallback Chains** Ak primárny poskytovateľ zlyhá, automaticky prepadne reťazcom bez akéhokoľvek zásahu
- **Combo Circuit Breaker** Automaticky deaktivuje zlyhávajúcich poskytovateľov v rámci kombinovaného reťazca
| 🎯 **Endpoint-Aware Models** | Custom models declare supported endpoints + API format |
**Health Dashboard** Monitorovanie dostupnosti, stavy ističov, blokovania, štatistiky vyrovnávacej pamäte, latencia p50/p95/p99
</details>
<details>
<summary><b>🔧 7. „Konfigurácia každého nástroja AI je únavná a opakovaná“ </b></summary>
Vývojári používajú Cursor, Claude Code, Codex CLI, OpenClaw, Gemini CLI, Kilo Code... Každý nástroj potrebuje inú konfiguráciu (API endpoint, kľúč, model). Prekonfigurovanie pri zmene poskytovateľa alebo modelu je strata času.
**Ako to rieši OmniRoute:**
- **CLI Tools Dashboard** Vyhradená stránka s nastavením jedným kliknutím pre Claude Code, Codex CLI, OpenClaw, Kilo Code, Antigravity, Cline
**GitHub Copilot Config Generator** Generuje `chatLanguageModels.json` pre kód VS s hromadným výberom modelu
- **Sprievodca registráciou** Sprievodca nastavením v 4 krokoch pre začínajúcich používateľov
**Jeden koncový bod, všetky modely** Nakonfigurujte `http://localhost:20128/v1` raz a získajte prístup k viac ako 36 poskytovateľom
</details>
<details>
<summary><b>🔑 8. „Správa tokenov OAuth od viacerých poskytovateľov je peklo“ </b></summary>
Claude Code, Codex, Gemini CLI, Copilot všetky používajú OAuth 2.0 s tokenmi, ktorých platnosť sa končí. Vývojári sa musia neustále znovu overovať, riešiť `client_secret is missing`, `redirect_uri_mismatch` a zlyhania na vzdialených serveroch. Obzvlášť problematické je OAuth na LAN/VPS.
**Ako to rieši OmniRoute:**
- **Automatická obnova tokenov** Tokeny OAuth sa pred vypršaním platnosti obnovujú na pozadí
- **Vstavaný OAuth 2.0 (PKCE)** Automatický tok pre Claude Code, Codex, Gemini CLI, Copilot, Kiro, Qwen, iFlow
**Multi-Auth OAuth** Viaceré účty na poskytovateľa prostredníctvom extrakcie tokenov JWT/ID
- **Oprava OAuth LAN/Remote** — Detekcia súkromnej adresy IP pre `redirect_uri` + manuálny režim adresy URL pre vzdialené servery
- **OAuth Behind Nginx** - Používa `window.location.origin` na reverznú kompatibilitu proxy
**Príručka vzdialeného OAuth** Podrobný sprievodca povereniami Google Cloud na VPS/Docker
</details>
<details>
<summary><b>📊 9. "Neviem, koľko míňam alebo kde" </b></summary>
Vývojári využívajú viacerých platených poskytovateľov, ale nemajú jednotný pohľad na výdavky. Každý poskytovateľ má svoj vlastný informačný panel fakturácie, ale neexistuje žiadne konsolidované zobrazenie. Neočakávané náklady sa môžu nahromadiť.
**Ako to rieši OmniRoute:**
**Informačný panel analýzy nákladov** sledovanie nákladov na token a správa rozpočtu podľa poskytovateľa
- **Obmedzenia rozpočtu na úroveň** Strop výdavkov na úroveň, ktorý spúšťa automatické záložné právo
- **Konfigurácia cien za model** Konfigurovateľné ceny za model
- **Štatistiky používania na kľúč API** Počet žiadostí a časová pečiatka posledného použitia na kľúč
**Panel Analytics** štatistické karty, graf používania modelu, tabuľka poskytovateľov s mierami úspešnosti a latenciou
</details>
<details>
<summary><b>🐛 10. „Nedokážem diagnostikovať chyby a problémy vo volaniach AI“ </b></summary>
Keď hovor zlyhá, vývojár nevie, či to bol limit sadzby, vypršaný token, nesprávny formát alebo chyba poskytovateľa. Fragmentované protokoly cez rôzne terminály. Bez pozorovateľnosti je ladenie metódou pokus-omyl.
**Ako to rieši OmniRoute:**
**Panel jednotných protokolov** 4 karty: Protokoly žiadostí, Protokoly proxy, Protokoly auditu, Konzola
- **Console Log Viewer** — Prehliadač v štýle terminálu v reálnom čase s farebne odlíšenými úrovňami, automatickým posúvaním, vyhľadávaním a filtrovaním
- **Proxy protokoly SQLite** — Trvalé protokoly, ktoré prežijú reštart servera
- **Translator Playground** 4 režimy ladenia: Playground (preklad formátu), Chat Tester (spiatočný), Test Bench (dávka), Live Monitor (v reálnom čase)
**Požiadať o telemetriu** latencia p50/p95/p99 + sledovanie X-request-Id
**Protokolovanie založené na súboroch s rotáciou** Konzolový zachytávač zachytáva všetko do protokolu JSON s rotáciou na základe veľkosti
</details>
<details>
<summary><b>🏗️ 11. „Nasadenie a údržba brány je zložitá“ </b></summary>
Inštalácia, konfigurácia a údržba AI proxy v rôznych prostrediach (lokálne, VPS, Docker, cloud) je náročná na prácu. Problémy ako pevne zakódované cesty, `EACCES` v adresároch, konflikty portov a zostavy naprieč platformami zvyšujú trenie.
**Ako to rieši OmniRoute:**
- **Globálna inštalácia npm** — `npm install -g omniroute && omniroute` — hotovo
- **Docker Multi-Platform** natívne AMD64 + ARM64 (Apple Silicon, AWS Graviton, Raspberry Pi)
- **Profily Docker Compose** — `base` (bez nástrojov CLI) a `cli` (s Claude Code, Codex, OpenClaw)
- **Electron Desktop App** natívna aplikácia pre Windows/macOS/Linux so systémovou lištou, automatickým spustením, offline režimom
- **Split-Port Mode** API a Dashboard na samostatných portoch pre pokročilé scenáre (reverzný proxy, kontajnerová sieť)
- **Cloud Sync** — Synchronizácia konfigurácie medzi zariadeniami cez Cloudflare Workers
- **DB Backups** — Automatické zálohovanie, obnovenie, export a import všetkých nastavení
</details>
<details>
<summary><b>🌍 12. „Rozhranie je len v angličtine a môj tím nehovorí po anglicky“ </b></summary>
Tímy v neanglicky hovoriacich krajinách, najmä v Latinskej Amerike, Ázii a Európe, zápasia s rozhraním iba v angličtine. Jazykové bariéry znižujú prijatie a zvyšujú chyby v konfigurácii.
**Ako to rieši OmniRoute:**
- **Dashboard i18n — 30 jazykov** — Všetkých 500+ kláves preložených vrátane arabčiny, bulharčiny, dánčiny, nemčiny, španielčiny, fínčiny, francúzštiny, hebrejčiny, hindčiny, maďarčiny, indonézštiny, taliančiny, japončiny, kórejčiny, malajčiny, holandčiny, nórčiny, poľštiny, portugalčiny (PT/BR), rumunčiny, ruštiny, slovenčiny, švédčiny, thajčiny, ukrajinčiny, vietnamčiny, angličtiny
- **Podpora RTL** — Podpora sprava doľava pre arabčinu a hebrejčinu
- **Viacjazyčné README** — 30 kompletných prekladov dokumentácie
- **Language Selector** ikona zemegule v hlavičke pre prepínanie v reálnom čase
</details>
<details>
<summary><b>🔄 13. „Potrebujem viac ako chat potrebujem vloženie, obrázky, zvuk“</b></summary>
AI nie je len dokončenie chatu. Vývojári potrebujú generovať obrázky, prepisovať zvuk, vytvárať vloženia pre RAG, meniť hodnotenie dokumentov a moderovať obsah. Každé API má iný koncový bod a formát.
**Ako to rieši OmniRoute:**
- **Vloženie** — `/v1/embeddings` so 6 poskytovateľmi a 9+ modelmi
- **Generácia obrazu** — `/v1/images/generations` s 10 poskytovateľmi a 20+ modelmi (OpenAI, xAI, Together, Fireworks, Nebius, Hyperbolic, NanoBanana, Antigravity, SD WebUI, ComfyUI)
- **Text-to-Video** — `/v1/videos/generations` — ComfyUI (AnimateDiff, SVD) a SD WebUI
- **Text-to-Music** — `/v1/music/generations` — ComfyUI (Stable Audio Open, MusicGen)
- **Prepis zvuku** — `/v1/audio/transcriptions` — Whisper + Nvidia NIM, HuggingFace, Qwen3
- **Text-to-Speech** — `/v1/audio/speech` — ElevenLabs, Nvidia NIM, HuggingFace, Coqui, Tortoise, Qwen3 a + existujúci poskytovatelia
- **Moderácie** — `/v1/moderations` — Kontroly bezpečnosti obsahu
- **Zmena poradia** — `/v1/rerank` — Zmena poradia relevantnosti dokumentu
- **Responses API** plná podpora `/v1/responses` pre kódex
</details>
<details>
<summary><b>🧪 14. „Nemám možnosť testovať a porovnávať kvalitu medzi modelmi“ </b></summary>
Vývojári chcú vedieť, ktorý model je pre ich prípad použitia najlepší kód, preklad, zdôvodnenie ale manuálne porovnávanie je pomalé. Neexistujú žiadne integrované nástroje hodnotenia.
**Ako to rieši OmniRoute:**
- **Hodnotenia LLM** testovanie zlatej sady s 10 predinštalovanými prípadmi zahŕňajúcimi pozdravy, matematiku, geografiu, generovanie kódu, súlad s JSON, preklad, označenie, odmietnutie bezpečnosti
- **4 stratégie zhody** — `exact`, `contains`, `regex`, `custom` (funkcia JS)
- **Testovacia lavica pre prekladateľské ihrisko** dávkové testovanie s viacerými vstupmi a očakávanými výstupmi, porovnanie medzi poskytovateľmi
- **Chat Tester** celý spiatočný výlet s vykresľovaním vizuálnej odozvy
- **Live Monitor** tok všetkých požiadaviek prechádzajúcich cez server proxy v reálnom čase
</details>
<details>
<summary><b>📈 15. „Potrebujem škálovať bez straty výkonu“</b></summary>
Keďže objem žiadostí rastie, bez ukladania rovnakých otázok do vyrovnávacej pamäte vznikajú duplicitné náklady. Bez idempotencie duplikát požaduje spracovanie odpadu. Musia sa dodržiavať limity sadzieb na poskytovateľa.
**Ako to rieši OmniRoute:**
- **Sémantická vyrovnávacia pamäť** Dvojvrstvová vyrovnávacia pamäť (podpis + sémantická) znižuje náklady a latenciu
- **Idempotencia požiadavky** 5-sekundové deduplikačné okno pre identické požiadavky
**Detekcia limitu rýchlosti** RPM, minimálna medzera a maximálne súbežné sledovanie jednotlivých poskytovateľov
- **Upraviteľné limity frekvencie** Konfigurovateľné predvolené hodnoty v Nastaveniach → Odolnosť s perzistenciou
- **Cache na overenie kľúča API** — 3-vrstvová vyrovnávacia pamäť pre produkčný výkon
**Panel zdravia s telemetriou** latencia p50/p95/p99, štatistiky vyrovnávacej pamäte, doba prevádzky
</details>
<details>
<summary><b>🤖 16. „Chcem globálne ovládať správanie modelu“</b></summary>
Vývojári, ktorí chcú všetky odpovede v konkrétnom jazyku, so špecifickým tónom alebo chcú obmedziť tokeny uvažovania. Konfigurovať to v každom nástroji/požiadavke je nepraktické.
**Ako to rieši OmniRoute:**
- **System Prompt Injection** Globálna výzva aplikovaná na všetky požiadavky
**Thinking Budget Validation** Zdôvodnenie riadenia prideľovania tokenov na žiadosť (priechodné, automatické, vlastné, adaptívne)
- **6 stratégií smerovania** — Globálne stratégie, ktoré určujú spôsob distribúcie požiadaviek
- **Wildcard Router** — Vzory `provider/*` smerujú dynamicky k akémukoľvek poskytovateľovi
- **Prepínač povoliť/zakázať kombo** — Prepínajte kombinácie priamo z ovládacieho panela
- **Provider Toggle** — Povolenie/zakázanie všetkých pripojení pre poskytovateľa jedným kliknutím
**Blokovaní poskytovatelia** vylúčte konkrétnych poskytovateľov zo zoznamu `/v1/models`
</details>
<details>
<summary><b>🧰 17. "Potrebujem nástroje MCP ako prvotriedne možnosti produktu"</b></summary>
Mnohé brány AI odhaľujú MCP iba ako skrytý detail implementácie. Tímy potrebujú viditeľnú a spravovateľnú operačnú vrstvu.
**Ako to rieši OmniRoute:**
- MCP sa zobrazí na navigačnom paneli a na karte protokolu koncového bodu
- Vyhradená stránka správy MCP s procesmi, nástrojmi, rozsahmi a auditom
- Vstavaný rýchly štart pre `omniroute --mcp` a registráciu klienta
</details>
<details>
<summary><b>🧠 18. "Potrebujem orchestráciu A2A s cestami synchronizácie + streamovania"</b></summary>
Pracovné postupy agentov vyžadujú priame odpovede a dlhotrvajúce streamované vykonávanie s kontrolou životného cyklu.
**Ako to rieši OmniRoute:**
- Koncový bod A2A JSON-RPC (`POST /a2a`) s `message/send` a `message/stream`
- SSE streaming so šírením koncového stavu
- Rozhrania API životného cyklu úloh pre `tasks/get` a `tasks/cancel`
</details>
<details>
<summary><b>🛰️ 19. „Potrebujem skutočné zdravie procesu MCP, nie uhádnutý stav“</b></summary>
Operačné tímy potrebujú vedieť, či je MCP skutočne nažive, nielen to, či je dostupné API.
**Ako to rieši OmniRoute:**
- Súbor srdcového tepu za behu s PID, časovými pečiatkami, transportom, počtom nástrojov a režimom rozsahu
- Stavové rozhranie MCP API, ktoré kombinuje srdcový tep + nedávnu aktivitu
- Stavové karty používateľského rozhrania pre sviežosť procesu / dostupnosti / tepu
</details>
<details>
<summary><b>📋 20. "Potrebujem auditovateľné spustenie nástroja MCP" </b></summary>
Keď nástroje mutujú konfiguráciu alebo spúšťajú akcie operácií, tímy potrebujú forenznú sledovateľnosť.
**Ako to rieši OmniRoute:**
- Záznamy auditu podporované SQLite pre volania nástrojov MCP
- Filtre podľa nástroja, úspechu/neúspechu, kľúča API a stránkovania
- Tabuľka auditu palubnej dosky + štatistické koncové body pre automatizáciu
</details>
<details>
<summary><b>🔐 21. "Potrebujem povolenia MCP v rozsahu na jednu integráciu"</b></summary>
Rôzni klienti by mali mať najmenej privilegovaný prístup ku kategóriám nástrojov.
**Ako to rieši OmniRoute:**
- 9 zrnitých rozsahov MCP pre kontrolovaný prístup k nástrojom
- Presadzovanie rozsahu a viditeľnosť v používateľskom rozhraní správy MCP
- Bezpečná východisková poloha pre prevádzkové nástroje
</details>
<details>
<summary><b>⚙️ 22. „Potrebujem prevádzkové ovládacie prvky bez premiestňovania“ </b></summary>
Tímy potrebujú rýchle zmeny runtime počas incidentov alebo nákladových udalostí.
**Ako to rieši OmniRoute:**
- Aktivácia komba prepínača priamo z ovládacieho panela MCP
- Použite profily odolnosti z preddefinovaných balíkov politík
- Resetujte stav ističa z rovnakého ovládacieho panela
</details>
<details>
<summary><b>🔄 23. „Potrebujem viditeľnosť a zrušenie životného cyklu úlohy A2A“ </b></summary>
Bez viditeľnosti životného cyklu sa incidenty úloh ťažko triedia.
**Ako to rieši OmniRoute:**
- Zoznam úloh / filtrovanie podľa stavu / zručnosti so stránkovaním
- Rozbalenie metadát úloh, udalostí a artefaktov
- Koncový bod zrušenia úlohy a akcia používateľského rozhrania s potvrdením
</details>
<details>
<summary><b>🌊 24. „Potrebujem aktívne metriky streamu pre načítanie A2A“</b></summary>
Streamovanie pracovných tokov vyžaduje operačný prehľad o súbežnosti a živých pripojeniach.
**Ako to rieši OmniRoute:**
- Aktívne počítadlá toku integrované do stavu A2A
- Časová pečiatka poslednej úlohy a počet jednotlivých štátov
- Karty palubnej dosky A2A na monitorovanie operácií v reálnom čase
</details>
<details>
<summary><b>🪪 25. "Potrebujem štandardné vyhľadávanie agentov pre klientov"</b></summary>
Externí klienti a orchestrátori potrebujú strojovo čitateľné metadáta na integráciu.
**Ako to rieši OmniRoute:**
- Karta agenta vystavená na `/.well-known/agent.json`
- Schopnosti a zručnosti zobrazené v používateľskom rozhraní správy
- API stavu A2A obsahuje metaúdaje zisťovania pre automatizáciu
</details>
<details>
<summary><b>🧭 26. "Potrebujem zistiteľnosť protokolu v UX produktu"</b></summary>
Ak používatelia nemôžu objaviť povrchy protokolov, kvalita prijatia a podpory klesá.
**Ako to rieši OmniRoute:**
- Položky na bočnom paneli pre MCP a A2A
- Koncový bod Karta Protokoly s rýchlym spustením a stavom
- Odkazy z prehľadu na špecializované riadiace panely
</details>
<details>
<summary><b>🧪 27. "Potrebujem komplexné overenie protokolu so skutočnými klientmi" </b></summary>
Falošné testy nestačia na overenie kompatibility protokolu pred vydaním.
**Ako to rieši OmniRoute:**
- E2E balík, ktorý spúšťa aplikáciu a využíva skutočný prenos klienta MCP SDK
- Klient A2A testuje toky zisťovania, odosielania, streamovania, získavania a rušenia
- Krížová kontrola tvrdení proti auditu MCP a API úloh A2A
</details>
<details>
<summary><b>📡 28. „Potrebujem jednotnú pozorovateľnosť naprieč všetkými rozhraniami“ </b></summary>
Rozdelenie pozorovateľnosti podľa protokolu vytvára slepé miesta a dlhšie MTTR.
**Ako to rieši OmniRoute:**
- Zjednotené informačné panely / protokoly / analýzy v jednom produkte
- Zdravie + audit + telemetria požiadaviek cez vrstvy OpenAI, MCP a A2A
- Operačné API pre stav a automatizáciu
</details>
<details>
<summary><b>💼 29. "Potrebujem jeden runtime pre proxy + nástroje + orchestráciu agentov" </b></summary>
Prevádzka mnohých samostatných služieb zvyšuje prevádzkové náklady a spôsoby zlyhania.
**Ako to rieši OmniRoute:**
- Proxy, server MCP a server A2A kompatibilný s OpenAI v jednom zásobníku
- Zdieľaná autentifikácia, odolnosť, ukladanie údajov a pozorovateľnosť
- Konzistentný model politiky na všetkých interakčných plochách
</details>
<details>
<summary><b>🚀 30. „Potrebujem odoslať agentské pracovné postupy bez roztiahnutia kódu lepidla“ </b></summary>
Tímy strácajú rýchlosť pri spájaní viacerých ad-hoc služieb a skriptov.
**Ako to rieši OmniRoute:**
- Jednotná stratégia koncových bodov pre klientov a agentov
- Vstavané používateľské rozhrania na správu protokolov a cesty overovania dymu
- Základy pripravené na výrobu (zabezpečenie, protokolovanie, odolnosť, zálohovanie)
</details>
### Príklady príručiek (integrované prípady použitia)
**Príručka A: Maximalizujte platené predplatné + lacné zálohovanie**
```txt
Combo: "maximize-claude"
1. cc/claude-opus-4-6
2. glm/glm-4.7
3. if/kimi-k2-thinking
Monthly cost: $20 + small backup spend
Outcome: higher quality, near-zero interruption
```
**Príručka B: Balík kódovania s nulovými nákladmi**
```txt
Combo: "free-forever"
1. gc/gemini-3-flash
2. if/kimi-k2-thinking
3. qw/qwen3-coder-plus
Monthly cost: $0
Outcome: stable free coding workflow
```
**Príručka C: 24/7 vždy zapnutý záložný reťazec**
```txt
Combo: "always-on"
1. cc/claude-opus-4-6
2. cx/gpt-5.2-codex
3. glm/glm-4.7
4. minimax/MiniMax-M2.1
5. if/kimi-k2-thinking
Outcome: deep fallback depth for deadline-critical workloads
```
**Príručka D: Operačný program agenta s MCP + A2A**
```txt
1) Start MCP transport (`omniroute --mcp`) for tool-driven operations
2) Run A2A tasks via `message/send` and `message/stream`
3) Observe via /dashboard/mcp and /dashboard/a2a
4) Control incidents with resilience profile + task cancellation
```
---
## ⚡ Rýchly štart
**1. Inštalovať globálne:**
@@ -251,7 +785,7 @@ docker compose --profile cli up -d
---
## 🖥️ Desktop App — Offline & Always-On
## 🖥️
> 🆕 **NEW!** OmniRoute is now available as a **native desktop application** for Windows, macOS, and Linux.
@@ -298,67 +832,6 @@ npm run electron:build:linux # Linux (.AppImage)
---
## 🎯 Prípady použitia
### Prípad 1: „Mám predplatné Claude Pro“
**Problém:** Platnosť kvóty vyprší nevyužitá, obmedzenia sadzieb počas náročného kódovania
```
Combo: "maximize-claude"
1. cc/claude-opus-4-6 (use subscription fully)
2. glm/glm-4.7 (cheap backup when quota out)
3. if/kimi-k2-thinking (free emergency fallback)
Monthly cost: $20 (subscription) + ~$5 (backup) = $25 total
vs. $20 + hitting limits = frustration
```
### Prípad 2: „Chcem nulové náklady“
**Problém:** Nemôžem si dovoliť predplatné, potrebujem spoľahlivé kódovanie AI
```
Combo: "free-forever"
1. gc/gemini-3-flash (180K free/month)
2. if/kimi-k2-thinking (unlimited free)
3. qw/qwen3-coder-plus (unlimited free)
Monthly cost: $0
Quality: Production-ready models
```
### Prípad 3: „Potrebujem kódovanie 24/7, žiadne prerušenia“
**Problém:** Termíny, nemôžem si dovoliť prestoje
```
Combo: "always-on"
1. cc/claude-opus-4-6 (best quality)
2. cx/gpt-5.2-codex (second subscription)
3. glm/glm-4.7 (cheap, resets daily)
4. minimax/MiniMax-M2.1 (cheapest, 5h reset)
5. if/kimi-k2-thinking (free unlimited)
Result: 5 layers of fallback = zero downtime
```
### Prípad 4: „Chcem AI ZDARMA v OpenClaw“
**Problém:** Potrebujete asistenta AI v aplikáciách na odosielanie správ, úplne zadarmo
```
Combo: "openclaw-free"
1. if/glm-4.7 (unlimited free)
2. if/minimax-m2.1 (unlimited free)
3. if/kimi-k2-thinking (unlimited free)
Monthly cost: $0
Access via: WhatsApp, Telegram, Slack, Discord, iMessage, Signal...
```
---
## 💡 Kľúčové vlastnosti
### 🧠 Základné smerovanie a inteligencia
@@ -374,6 +847,8 @@ Access via: WhatsApp, Telegram, Slack, Discord, iMessage, Signal...
| 🧩 **Vlastné modely** | Pridajte akékoľvek ID modelu k akémukoľvek poskytovateľovi |
| 🌐 **Wildcard Router** | Dynamicky smerujte vzory `provider/*` k akémukoľvek poskytovateľovi |
| 🧠 **Premýšľajúci rozpočet** | Priechodný, automatický, vlastný a adaptívny režim pre modely uvažovania |
| 🔀 **Model Aliases** | Auto-forward deprecated model IDs to current replacements (built-in + custom) |
| ⚡ **Background Degradation** | Auto-route background tasks (titles, summaries) to cheaper models |
| 💬 **Promptné vstrekovanie systému** | Globálna systémová výzva aplikovaná na všetky požiadavky |
| 📄 **Responses API** | Plná podpora OpenAI Responses API (`/v1/responses`) pre Codex |
@@ -399,6 +874,8 @@ Access via: WhatsApp, Telegram, Slack, Discord, iMessage, Signal...
| 🔒 ** Spoofing odtlačkov prstov TLS** | Obíďte detekciu botov na báze TLS cez wreq-js |
| 🌐 **Filtrovanie IP** | Zoznam povolených/blokovaných pre riadenie prístupu API |
| 📊 **Upraviteľné limity sadzieb** | Konfigurovateľné otáčky za minútu, minimálna medzera a maximálna súbežná rýchlosť na systémovej úrovni |
| 💾 **Rate Limit Persistence** | Learned limits survive restarts via SQLite with 60s debounce + 24h staleness |
| 🔄 **Token Refresh Resilience** | Per-provider circuit breaker (5 fails→30min) + 30s timeout per attempt |
| 🛡 **API Endpoint Protection** | Auth gating + blokovanie poskytovateľa pre koncový bod `/models` |
| 🔒 **Viditeľnosť proxy** | Farebne rozlíšené odznaky: 🟢 globálne, 🟡 poskytovateľ, 🔵 na pripojenie s IP displejom |
| 🌐 **3-úrovňová konfigurácia proxy** | Nakonfigurujte proxy na globálnej úrovni, na úrovni jednotlivých poskytovateľov alebo na úrovni pripojenia |
@@ -518,6 +995,27 @@ OmniRoute obsahuje výkonné vstavané ihrisko pre prekladateľov so **4 režima
</details>
## 🧪 Hodnotenia (Evals)
OmniRoute obsahuje vstavaný hodnotiaci rámec na testovanie kvality odozvy LLM oproti zlatému súboru. Prístup k nej získate cez **Analytics → Evals** na hlavnom paneli.
### Vstavaná zlatá súprava
Predinštalovaná sada „OmniRoute Golden Set“ obsahuje 10 testovacích prípadov, ktoré zahŕňajú:
- Pozdravy, matematika, geografia, generovanie kódu
- Súlad s formátom JSON, preklad, zníženie
- Bezpečnostné odmietnutie (škodlivý obsah), počítanie, booleovská logika
### Stratégie hodnotenia
| Stratégia | Popis | Príklad |
| ---------- | ---------------------------------------------------------------------- | -------------------------------- |
| `exact` | Výstup sa musí presne zhodovať | `"4"` |
| `contains` | Výstup musí obsahovať podreťazec (nerozlišujú sa malé a veľké písmená) | `"Paris"` |
| `regex` | Výstup musí zodpovedať vzoru regulárneho výrazu | `"1.*2.*3"` |
| `custom` | Vlastná funkcia JS vracia true/false | `(output) => output.length > 10` |
---
## 📖 Sprievodca nastavením
@@ -800,104 +1298,64 @@ Settings → API Configuration:
---
## 📊 Dostupné modely
## 🐛 Riešenie problémov
<details>
<summary><b>Zobraziť všetky dostupné modely</b></summary>
<summary><b>Kliknutím rozbalíte sprievodcu riešením problémov</b></summary>
**Claude Code (`cc/`)** Pro/Max:
**„Jazykový model neposkytol správy“**
- `cc/claude-opus-4-6`
- `cc/claude-sonnet-4-5-20250929`
- `cc/claude-haiku-4-5-20251001`
- Kvóta poskytovateľa je vyčerpaná → Skontrolujte sledovanie kvót na paneli
- Riešenie: Použite záložnú kombináciu alebo prejdite na lacnejšiu úroveň
**Codex (`cx/`)** - Plus/Pro:
**Obmedzenie sadzby**
- `cx/gpt-5.2-codex`
- `cx/gpt-5.1-codex-max`
- Vyčerpaná kvóta predplatného → Návrat na GLM/MiniMax
- Pridať kombináciu: `cc/claude-opus-4-6 → glm/glm-4.7 → if/kimi-k2-thinking`
**Gemini CLI (`gc/`)** ZDARMA:
**Platnosť tokenu OAuth vypršala**
- `gc/gemini-3-flash-preview`
- `gc/gemini-2.5-pro`
- Automaticky obnovuje OmniRoute
- Ak problémy pretrvávajú: Dashboard → Provider → Reconnect
**GitHub Copilot (`gh/`)**:
**Vysoké náklady**
- `gh/gpt-5`
- `gh/claude-4.5-sonnet`
- Skontrolujte štatistiky používania v hlavnom paneli → Náklady
- Prepnite primárny model na GLM/MiniMax
- Používajte bezplatnú vrstvu (Gemini CLI, iFlow) pre nekritické úlohy
**NVIDIA NIM (`nvidia/`)** BEZPLATNÉ kredity:
**Palubná doska sa otvára na nesprávnom porte**
- `nvidia/llama-3.3-70b-instruct`
- `nvidia/mistral-7b-instruct`
- 50+ ďalších modelov na [build.nvidia.com](https://build.nvidia.com)
- Nastavte `PORT=20128` a `NEXT_PUBLIC_BASE_URL=http://localhost:20128`
**GLM (`glm/`)** 0,6 USD/1 milión:
**Chyby synchronizácie v cloude**
- `glm/glm-4.7`
- Overte `BASE_URL` body na vašu spustenú inštanciu
Overte `CLOUD_URL` bodov k očakávanému koncovému bodu cloudu
- Ponechajte hodnoty `NEXT_PUBLIC_*` zarovnané s hodnotami na strane servera
**MiniMax (`minimax/`)** 0,2 USD/1 milión:
**Prvé prihlásenie nefunguje**
- `minimax/MiniMax-M2.1`
- Skontrolujte `INITIAL_PASSWORD` v `.env`
Ak nie je nastavené, záložné heslo je `123456`
**iFlow (`if/`)** ZDARMA:
**Žiadne záznamy žiadostí**
- `if/kimi-k2-thinking`
- `if/qwen3-coder-plus`
- `if/deepseek-r1`
- `if/glm-4.7`
- `if/minimax-m2`
- Nastaviť `ENABLE_REQUEST_LOGS=true` v `.env`
**Qwen (`qw/`)** ZDARMA:
**Test pripojenia ukazuje „Neplatné“ pre poskytovateľov kompatibilných s OpenAI**
- `qw/qwen3-coder-plus`
- `qw/qwen3-coder-flash`
- Mnohí poskytovatelia nevystavujú koncový bod `/models`
- OmniRoute v1.0.6+ zahŕňa záložné overenie prostredníctvom dokončenia chatu
- Uistite sa, že základná adresa URL obsahuje príponu `/v1`
**Kiro (`kr/`)** ZDARMA:
- `kr/claude-sonnet-4.5`
- `kr/claude-haiku-4.5`
**OpenRouter (`or/`)** viac ako 100 modelov:
- `or/anthropic/claude-4-sonnet`
- `or/google/gemini-2.5-pro`
- Akýkoľvek model od [openrouter.ai/models](https://openrouter.ai/models)
</details>
---
## 🧪 Hodnotenia (Evals)
OmniRoute obsahuje vstavaný hodnotiaci rámec na testovanie kvality odozvy LLM oproti zlatému súboru. Prístup k nej získate cez **Analytics → Evals** na hlavnom paneli.
### Vstavaná zlatá súprava
Predinštalovaná sada „OmniRoute Golden Set“ obsahuje 10 testovacích prípadov, ktoré zahŕňajú:
- Pozdravy, matematika, geografia, generovanie kódu
- Súlad s formátom JSON, preklad, zníženie
- Bezpečnostné odmietnutie (škodlivý obsah), počítanie, booleovská logika
### Stratégie hodnotenia
| Stratégia | Popis | Príklad |
| ---------- | ---------------------------------------------------------------------- | -------------------------------- |
| `exact` | Výstup sa musí presne zhodovať | `"4"` |
| `contains` | Výstup musí obsahovať podreťazec (nerozlišujú sa malé a veľké písmená) | `"Paris"` |
| `regex` | Výstup musí zodpovedať vzoru regulárneho výrazu | `"1.*2.*3"` |
| `custom` | Vlastná funkcia JS vracia true/false | `(output) => output.length > 10` |
---
## 🔐 OAuth em Servidor Remoto (Vzdialené nastavenie OAuth)
### 🔐 OAuth
<a name="oauth-em-servidor-remoto"></a>
> **⚠️ DÔLEŽITÉ pre používateľov s OmniRoute a diaľkovým ovládaním VPS/Docker/servidor**
### Od OAuth do Antigravity / Gemini CLI falha em servidores remotos?
### OAuth
Osvedčuje **Antigravity** a **Gemini CLI** používame **Google OAuth 2.0** ako autentifikáciu. O Google exige que a `redirect_uri` usada no fluxo OAuth saja **exatamente** uma das URI pre-kadastradas no Google Cloud Console to use.
@@ -982,64 +1440,11 @@ Ak chcete získať prístup k dôvere, môžete použiť **príručku URL**:
> Toto riešenie funguje pomocou autorizačného kódu na adrese URL a nezávislého presmerovania.
---
## 🐛 Riešenie problémov
<details>
<summary><b>Kliknutím rozbalíte sprievodcu riešením problémov</b></summary>
**„Jazykový model neposkytol správy“**
- Kvóta poskytovateľa je vyčerpaná → Skontrolujte sledovanie kvót na paneli
- Riešenie: Použite záložnú kombináciu alebo prejdite na lacnejšiu úroveň
**Obmedzenie sadzby**
- Vyčerpaná kvóta predplatného → Návrat na GLM/MiniMax
- Pridať kombináciu: `cc/claude-opus-4-6 → glm/glm-4.7 → if/kimi-k2-thinking`
**Platnosť tokenu OAuth vypršala**
- Automaticky obnovuje OmniRoute
- Ak problémy pretrvávajú: Dashboard → Provider → Reconnect
**Vysoké náklady**
- Skontrolujte štatistiky používania v hlavnom paneli → Náklady
- Prepnite primárny model na GLM/MiniMax
- Používajte bezplatnú vrstvu (Gemini CLI, iFlow) pre nekritické úlohy
**Palubná doska sa otvára na nesprávnom porte**
- Nastavte `PORT=20128` a `NEXT_PUBLIC_BASE_URL=http://localhost:20128`
**Chyby synchronizácie v cloude**
- Overte `BASE_URL` body na vašu spustenú inštanciu
Overte `CLOUD_URL` bodov k očakávanému koncovému bodu cloudu
- Ponechajte hodnoty `NEXT_PUBLIC_*` zarovnané s hodnotami na strane servera
**Prvé prihlásenie nefunguje**
- Skontrolujte `INITIAL_PASSWORD` v `.env`
Ak nie je nastavené, záložné heslo je `123456`
**Žiadne záznamy žiadostí**
- Nastaviť `ENABLE_REQUEST_LOGS=true` v `.env`
**Test pripojenia ukazuje „Neplatné“ pre poskytovateľov kompatibilných s OpenAI**
- Mnohí poskytovatelia nevystavujú koncový bod `/models`
- OmniRoute v1.0.6+ zahŕňa záložné overenie prostredníctvom dokončenia chatu
- Uistite sa, že základná adresa URL obsahuje príponu `/v1`
</details>
---
## 🛠️ Tech Stack
## 🛠️
- **Runtime**: Node.js 1822 LTS (⚠️ Node.js 24+ nie je **podporovaný**`better-sqlite3` natívne binárne súbory sú nekompatibilné)
**Jazyk**: TypeScript 5.9 — **100 % TypeScript** v `src/` a `open-sse/` (v1.0.6)
@@ -1091,7 +1496,7 @@ Ak chcete získať prístup k dôvere, môžete použiť **príručku URL**:
---
## 🗺️ Cestovná mapa
## 🗺️
OmniRoute má naplánovaných **210+ funkcií** vo viacerých fázach vývoja. Tu sú kľúčové oblasti:
@@ -1116,18 +1521,6 @@ OmniRoute má naplánovaných **210+ funkcií** vo viacerých fázach vývoja. T
---
## 📧 Podpora
> 💬 **Pripojte sa k našej komunite!** [WhatsApp Group](https://chat.whatsapp.com/JI7cDQ1GyaiDHhVBpLxf8b?mode=gi_t) — Získajte pomoc, zdieľajte tipy a buďte informovaní.
- **Web**: [omniroute.online](https://omniroute.online)
- **GitHub**: [github.com/diegosouzapw/OmniRoute](https://github.com/diegosouzapw/OmniRoute)
- **Problémy**: [github.com/diegosouzapw/OmniRoute/issues](https://github.com/diegosouzapw/OmniRoute/issues)
- **WhatsApp**: [Community Group](https://chat.whatsapp.com/JI7cDQ1GyaiDHhVBpLxf8b?mode=gi_t)
- **Pôvodný projekt**: [9router by decolua](https://github.com/decolua/9router)
---
## 👥 Prispievatelia
[![Contributors](https://contrib.rocks/image?repo=diegosouzapw/OmniRoute&max=100&columns=20&anon=1)](https://github.com/diegosouzapw/OmniRoute/graphs/contributors)
@@ -1177,85 +1570,6 @@ Licencia MIT podrobnosti nájdete na stránke [LICENSE](LICENSE).
---
---
## 🇧🇷 OmniRoute — Gateway de IA Gratuito
<a name="-omniroute--gateway-de-ia-gratuito"></a>
### Nunca pare de codar. Roteamento inteligentné pre **modely IA GRATUITOS a vlastné zálohy** s záložným autom.
_Seu proxy universal de API um koncový bod, 36+ overorov, nulové prestoje._
### 🌐 Internacionalização (i18n)
Prístrojová doska podporuje OmniRoute **múltiplos idiomas**. Aktuálne k dispozícii:
| Idióm | Código | Stav |
| ----------------------- | ------- | ------------ |
| 🇺🇸 anglicky | `en` | ✅ Kompletné |
| 🇧🇷 Português (Brazília) | `pt-BR` | ✅ Kompletné |
**Para trocar o idioma:** Clique no seletor de idioma (🇺🇸 EN) no header to dashboard → selectione o idioma desejado.
**Pre nový idióm:**
1. Plač `src/i18n/messages/{codigo}.json` baseado em `en.json`
2. Adicione o kódigo em `src/i18n/config.ts``LOCALES` a `LANGUAGES`
3. Reinicie o servidor
### ⚡ Início Rápido
```bash
# Instalar via npm
npx omniroute@latest
# Ou rodar do código-fonte
cp .env.example .env
npm install
PORT=20128 NEXT_PUBLIC_BASE_URL=http://localhost:20128 npm run dev
```
### 🐳 Docker
```bash
docker run -d --name omniroute -p 20128:20128 diegosouzapw/omniroute:latest
```
### 🔑 Funcionalidades Principais
- **36+ overores de IA** Claude, GPT, Gemini, Llama, Qwen, DeepSeek a ďalšie
- **Roteamento inteligente** — Záložné automaty entre proveores
- **Preklad formátu** — OpenAI ↔ Claude ↔ Gemini automaticamente
- **Multi-conta** — Viacnásobné obsahy s vybranými inteligentnými
- **Cache semântico** — Reduz custos e latência
- **OAuth automático** — Tokeny renovam automaticamente
- **Combos personalizados** — 6 estratégias de roteamento
- **Úplný informačný panel** Monitorovanie, protokoly, analýzy, konfigurácie
- **Nástroje CLI** Konfigurácia Claude Code, Codex, Cursor, Cline com um clique
- **100 % TypeScript** jednoduché a jednoduché označenie
### 📖 Dokumentácia
| Documento | Popis |
| ----------------------------------------------- | --------------------------------------- |
| [Guia do Usuário](docs/USER_GUIDE.md) | Provedores, combá, CLI, deploy |
| [Referência da API](docs/API_REFERENCE.md) | Todos os endpoints com exemplos |
| [Solução de Problemas](docs/TROUBLESHOOTING.md) | Problemas comuns e soluções |
| [Arquitetura](docs/ARCHITECTURE.md) | Arquitetura e internos do systému |
| [Contribuição](CONTRIBUTING.md) | Nastavenie desenvolvimento e guidelines |
| [Deploy em VM](docs/VM_DEPLOYMENT_GUIDE.md) | Guia komplet: VM + nginx + Cloudflare |
### 📧 Podporte
> 💬 **Entre para a comunidade!** [Grupo WhatsApp](https://chat.whatsapp.com/JI7cDQ1GyaiDHhVBpLxf8b?mode=gi_t) — pneumatiky dúvidas, compartilhe dicas e fique atualizado.
- **Web**: [omniroute.online](https://omniroute.online)
- **GitHub**: [github.com/diegosouzapw/OmniRoute](https://github.com/diegosouzapw/OmniRoute)
- **Problémy**: [github.com/diegosouzapw/OmniRoute/issues](https://github.com/diegosouzapw/OmniRoute/issues)
---
<div align="center">
<sub>Vytvorené pomocou ❤️ pre vývojárov, ktorí kódujú 24/7</sub>
<br/>

View File

@@ -3,8 +3,6 @@
# 🚀 OmniRoute — Den kostnadsfria AI-gatewayen
🌐 **[English](#-omniroute--the-free-ai-gateway)** | **[Português (BR)](#-omniroute--gateway-de-ia-gratuito)**
### Sluta aldrig koda. Smart routing till **GRATIS & lågkostnads AI-modeller** med automatisk reserv.
_Din universella API-proxy — en slutpunkt, 36+ leverantörer, noll driftstopp._
@@ -112,6 +110,35 @@ _Anslut alla AI-drivna IDE- eller CLI-verktyg via OmniRoute — gratis API-gatew
---
## 🖼️
<div align="center">
<img src="./docs/screenshots/MainOmniRoute.png" alt="OmniRoute" width="800"/>
</div>
---
## 📸
<details>
<summary><b>...</b></summary>
| # | # |
| ----- | ---------------------------------------- |
| **1** | ![1](docs/screenshots/01-providers.png) |
| **2** | ![2](docs/screenshots/02-combos.png) |
| **3** | ![3](docs/screenshots/03-analytics.png) |
| **4** | ![4](docs/screenshots/04-health.png) |
| **5** | ![5](docs/screenshots/05-translator.png) |
| **6** | ![6](docs/screenshots/06-settings.png) |
| **7** | ![7](docs/screenshots/07-cli-tools.png) |
| **8** | ![8](docs/screenshots/08-usage.png) |
| **9** | ![9](docs/screenshots/09-endpoint.png) |
</details>
---
## 🤔 Varför OmniRoute?
**Sluta slösa pengar och nå gränser:**
@@ -130,6 +157,18 @@ _Anslut alla AI-drivna IDE- eller CLI-verktyg via OmniRoute — gratis API-gatew
---
## 📧 Support
> 💬 **Gå med i vår community!** [WhatsApp Group](https://chat.whatsapp.com/JI7cDQ1GyaiDHhVBpLxf8b?mode=gi_t) — Få hjälp, dela tips och håll dig uppdaterad.
- **Webbplats**: [omniroute.online](https://omniroute.online)
- **GitHub**: [github.com/diegosouzapw/OmniRoute](https://github.com/diegosouzapw/OmniRoute)
- **Frågor**: [github.com/diegosouzapw/OmniRoute/issues](https://github.com/diegosouzapw/OmniRoute/issues)
- **WhatsApp**: [Community Group](https://chat.whatsapp.com/JI7cDQ1GyaiDHhVBpLxf8b?mode=gi_t)
- **Originalprojekt**: [9router by decolua](https://github.com/decolua/9router)
---
## 🔄 Hur det fungerar
```
@@ -159,6 +198,497 @@ Result: Never stop coding, minimal cost
---
## 🎯 Vad OmniRoute löser — 30 verkliga smärtpunkter och användningsfall
> **Varje utvecklare som använder AI-verktyg möter dessa problem dagligen.** OmniRoute byggdes för att lösa dem alla — från kostnadsöverskridanden till regionala block, från trasiga OAuth-flöden till protokolloperationer och observerbarhet i företag.
<details>
<summary><b>💸 1. "Jag betalar för ett dyrt abonnemang men blir ändå avbruten av limits" </b></summary>
Utvecklare betalar $20200/månad för Claude Pro, Codex Pro eller GitHub Copilot. Även om du betalar har kvoten ett tak - 5 timmars användning, veckogränser eller gränser per minut. Mid-coding session, leverantören slutar svara och utvecklaren tappar flöde och produktivitet.
**Hur OmniRoute löser det:**
- **Smart 4-lagers fallback** — Om prenumerationskvoten tar slut, omdirigeras automatiskt till API-nyckel → Billigt → Gratis med noll manuellt ingrepp
- **Kvotspårning i realtid** — Visar tokenförbrukning i realtid med återställningsnedräkning (5 timmar, dagligen, veckovis)
- **Multi-Account Support** — Flera konton per leverantör med automatisk round-robin — när ett tar slut, byter du till nästa
- **Anpassade kombinationer** — Anpassningsbara reservkedjor med 6 balanseringsstrategier (fill-first, round-robin, P2C, slumpmässig, minst använda, kostnadsoptimerad)
- **Codex Business Quotas** — Övervakning av företags-/teamarbetsutrymmeskvoter direkt i instrumentpanelen
</details>
<details>
<summary><b>🔌 2. "Jag måste använda flera leverantörer men alla har olika API" </b></summary>
OpenAI använder ett format, Claude (Anthropic) använder ett annat, Gemini ännu ett annat. Om en utvecklare vill testa modeller från olika leverantörer eller fallback mellan dem måste de konfigurera om SDK:er, ändra slutpunkter, hantera inkompatibla format. Anpassade leverantörer (FriendLI, NIM) har icke-standardiserade modellslutpunkter.
**Hur OmniRoute löser det:**
- **Unified Endpoint** — En enda `http://localhost:20128/v1` fungerar som proxy för alla 36+ leverantörer
- **Formatöversättning** — Automatisk och transparent: OpenAI ↔ Claude ↔ Gemini ↔ Responses API
- **Responssanering** — Tar bort icke-standardiserade fält (`x_groq`, `usage_breakdown`, `service_tier`) som bryter OpenAI SDK v1.83+
- **Rollnormalisering** — Konverterar `developer``system` för icke-OpenAI-leverantörer; `system``user` för GLM/ERNIE
- **Think Tag Extraction** — Extraherar `<think>`-block från modeller som DeepSeek R1 till standardiserade `reasoning_content`
- **Structured Output for Gemini** — `json_schema``responseMimeType`/`responseSchema` automatisk konvertering
- **`stream` är standard till `false`** — Justerar med OpenAI-specifikationen, undviker oväntad SSE i Python/Rust/Go SDK:er
</details>
<details>
<summary><b>🌐 3. "Min AI-leverantör blockerar min region/land" </b></summary>
Leverantörer som OpenAI/Codex blockerar åtkomst från vissa geografiska regioner. Användare får fel som `unsupported_country_region_territory` under OAuth- och API-anslutningar. Detta är särskilt frustrerande för utvecklare från utvecklingsländer.
**Hur OmniRoute löser det:**
- **3-Level Proxy Config** — Konfigurerbar proxy på 3 nivåer: global (all trafik), per leverantör (endast en leverantör) och per anslutning/nyckel
- **Färgkodade proxymärken** — Visuella indikatorer: 🟢 global proxy, 🟡 leverantörsproxy, 🔵 anslutningsproxy, visar alltid IP:n
- **OAuth Token Exchange Through Proxy** — OAuth-flödet går också genom proxyn, vilket löser `unsupported_country_region_territory`
- **Anslutningstester via proxy** — Anslutningstester använder den konfigurerade proxyn (ingen mer direkt förbikoppling)
- **SOCKS5-stöd** — Fullständigt SOCKS5-proxystöd för utgående routing
- **TLS Fingerprint Spoofing** — Webbläsarliknande TLS-fingeravtryck via `wreq-js` för att kringgå botdetektering
</details>
<details>
<summary><b>🆓 4. "Jag vill använda AI för kodning men jag har inga pengar" </b></summary>
Alla kan inte betala $20200/månad för AI-prenumerationer. Studenter, utvecklare från tillväxtländer, hobbyister och frilansare behöver tillgång till kvalitetsmodeller utan kostnad.
**Hur OmniRoute löser det:**
- **Gratis leverantörer inbyggda** — Inbyggt stöd för 100 % gratis leverantörer: iFlow (8 obegränsade modeller), Qwen (3 obegränsade modeller), Kiro (Claude gratis), Gemini CLI (180K/månad gratis)
- **Free-Only Combos** — Chain `gc/gemini-3-flash → if/kimi-k2-thinking → qw/qwen3-coder-plus` = $0/månad utan stilleståndstid
- **NVIDIA NIM gratis krediter** — 1000 gratis krediter integrerade
- **Kostnadsoptimerad strategi** — Routingstrategi som automatiskt väljer den billigaste tillgängliga leverantören
</details>
<details>
<summary><b>🔒 5. "Jag behöver skydda min AI-gateway från obehörig åtkomst" </b></summary>
När du exponerar en AI-gateway för nätverket (LAN, VPS, Docker) kan vem som helst med adressen konsumera utvecklarens tokens/kvot. Utan skydd är API:er sårbara för missbruk, snabb injektion och missbruk.
**Hur OmniRoute löser det:**
- **API Key Management** — Generering, rotation och omfattning per leverantör med en dedikerad `/dashboard/api-manager`-sida
- **Behörigheter på modellnivå** — Begränsa API-nycklar till specifika modeller (`openai/*`, jokerteckenmönster), med växlaren Tillåt allt/Begränsa
- **API Endpoint Protection** — Kräv en nyckel för `/v1/models` och blockera specifika leverantörer från listan
- **Auth Guard + CSRF Protection** — Alla instrumentpanelsrutter skyddade med `withAuth` middleware + CSRF-tokens
- **Rate Limiter** — Per-IP-hastighetsbegränsning med konfigurerbara fönster
- **IP-filtrering** — Tillåtelselista/blockeringslista för åtkomstkontroll
- **Prompt Injection Guard** — Sanering mot skadliga promptmönster
- **AES-256-GCM-kryptering** — Autentiseringsuppgifter krypterade i vila
</details>
<details>
<summary><b>🛑 6. "Min leverantör gick ner och jag tappade mitt kodningsflöde" </b></summary>
AI-leverantörer kan bli instabila, returnera 5xx-fel eller nå tillfälliga hastighetsgränser. Om en utvecklare är beroende av en enskild leverantör avbryts de. Utan strömbrytare kan upprepade försök krascha programmet.
**Hur OmniRoute löser det:**
- **Circuit Breaker per leverantör** — Autoöppning/stängning med konfigurerbara trösklar och nedkylning (stängd/öppen/halvöppen)
- **Exponentiell backoff** — Progressiva fördröjningar igen
- **Anti-Thundering Herd** — Mutex + semaforskydd mot samtidiga stormar igen
- **Combo reservkedjor** — Om den primära leverantören misslyckas, faller den automatiskt genom kedjan utan ingrepp
- **Combo Circuit Breaker** - Inaktiverar automatiskt felande leverantörer inom en kombinationskedja
- **Health Dashboard** — Drifttidsövervakning, strömbrytartillstånd, låsningar, cachestatistik, p50/p95/p99 latens
</details>
<details>
<summary><b>🔧 7. "Att konfigurera varje AI-verktyg är tråkigt och repetitivt" </b></summary>
Utvecklare använder Cursor, Claude Code, Codex CLI, OpenClaw, Gemini CLI, Kilo Code... Varje verktyg behöver en annan konfiguration (API-slutpunkt, nyckel, modell). Att konfigurera om när man byter leverantör eller modell är ett slöseri med tid.
**Hur OmniRoute löser det:**
- **CLI Tools Dashboard** — Dedikerad sida med ett-klicksinställningar för Claude Code, Codex CLI, OpenClaw, Kilo Code, Antigravity, Cline
- **GitHub Copilot Config Generator** — Genererar `chatLanguageModels.json` för VS-kod med bulkmodellval
- **Onboarding Wizard** — Guidad 4-stegs installation för förstagångsanvändare
- **En slutpunkt, alla modeller** — Konfigurera `http://localhost:20128/v1` en gång, få tillgång till 36+ leverantörer
</details>
<details>
<summary><b>🔑 8. "Hantera OAuth-tokens från flera leverantörer är ett helvete" </b></summary>
Claude Code, Codex, Gemini CLI, Copilot — alla använder OAuth 2.0 med utgående tokens. Utvecklare måste autentisera på nytt hela tiden, hantera `client_secret is missing`, `redirect_uri_mismatch` och fel på fjärrservrar. OAuth på LAN/VPS är särskilt problematiskt.
**Hur OmniRoute löser det:**
- **Automatisk uppdatering av token** — OAuth-tokens uppdateras i bakgrunden innan de löper ut
- **OAuth 2.0 (PKCE) Inbyggd** — Automatiskt flöde för Claude Code, Codex, Gemini CLI, Copilot, Kiro, Qwen, iFlow
- **Multi-Account OAuth** — Flera konton per leverantör via JWT/ID-tokenextraktion
- **OAuth LAN/Remote Fix** — Privat IP-detektering för `redirect_uri` + manuellt URL-läge för fjärrservrar
- **OAuth Behind Nginx** — Använder `window.location.origin` för omvänd proxykompatibilitet
- **Remote OAuth Guide** — Steg-för-steg-guide för Google Cloud-uppgifter på VPS/Docker
</details>
<details>
<summary><b>📊 9. "Jag vet inte hur mycket jag spenderar eller var" </b></summary>
Utvecklare använder flera betalleverantörer men har ingen enhetlig syn på utgifter. Varje leverantör har sin egen faktureringspanel, men det finns ingen konsoliderad vy. Oväntade kostnader kan hopa sig.
**Hur OmniRoute löser det:**
- **Kostnadsanalysinstrumentpanel** — Kostnadsspårning per token och budgethantering per leverantör
- **Budgetgränser per nivå** — Utgiftstak per nivå som utlöser automatisk reserv
- **Priskonfiguration per modell** — Konfigurerbara priser per modell
- **Användningsstatistik per API-nyckel** — Antal förfrågningar och senast använda tidsstämpel per nyckel
- **Analytics Dashboard** — Statistikkort, modellanvändningsdiagram, leverantörstabell med framgångsfrekvens och latens
</details>
<details>
<summary><b>🐛 10. "Jag kan inte diagnostisera fel och problem i AI-samtal" </b></summary>
När ett samtal misslyckas vet inte utvecklaren om det var en hastighetsgräns, utgången token, fel format eller leverantörsfel. Fragmenterade loggar över olika terminaler. Utan observerbarhet är felsökning att trial-and-error.
**Hur OmniRoute löser det:**
- **Unified Logs Dashboard** — 4 flikar: Request Logs, Proxy Logs, Audit Logs, Console
- **Console Log Viewer** — Viewer i realtid i terminalstil med färgkodade nivåer, automatisk rullning, sökning, filtrering
- **SQLite Proxy-loggar** — Beständiga loggar som överlever serverstarter
- **Translator Playground** — 4 felsökningslägen: Playground (formatöversättning), Chat Tester (tur och retur), Testbänk (batch), Live Monitor (realtid)
- **Request Telemetri** — p50/p95/p99 latens + X-Request-Id-spårning
- **Filbaserad loggning med rotation** — Konsolinterceptor fångar allt till JSON-logg med storleksbaserad rotation
</details>
<details>
<summary><b>🏗️ 11. "Det är komplext att distribuera och underhålla gatewayen" </b></summary>
Att installera, konfigurera och underhålla en AI-proxy i olika miljöer (lokalt, VPS, Docker, moln) är arbetskrävande. Problem som hårdkodade sökvägar, `EACCES` på kataloger, portkonflikter och plattformsoberoende konstruktioner ger friktion.
**Hur OmniRoute löser det:**
- **npm global installation** — `npm install -g omniroute && omniroute` — klar
- **Docker Multi-Platform** — AMD64 + ARM64 inbyggt (Apple Silicon, AWS Graviton, Raspberry Pi)
- **Docker Compose Profiles** — `base` (inga CLI-verktyg) och `cli` (med Claude Code, Codex, OpenClaw)
- **Electron Desktop App** — Inbyggd app för Windows/macOS/Linux med systemfältet, autostart, offlineläge
- **Split-Port Mode** — API och Dashboard på separata portar för avancerade scenarier (omvänd proxy, containernätverk)
- **Cloud Sync** — Konfigurera synkronisering mellan enheter via Cloudflare Workers
- **DB-säkerhetskopior** — Automatisk säkerhetskopiering, återställning, export och import av alla inställningar
</details>
<details>
<summary><b>🌍 12. "Gränssnittet är endast engelska och mitt team talar inte engelska" </b></summary>
Lag i icke-engelsktalande länder, särskilt i Latinamerika, Asien och Europa, kämpar med enbart engelska gränssnitt. Språkbarriärer minskar användningen och ökar konfigurationsfelen.
**Hur OmniRoute löser det:**
- **Dashboard i18n — 30 språk** — Alla 500+ nycklar översatta, inklusive arabiska, bulgariska, danska, tyska, spanska, finska, franska, hebreiska, hindi, ungerska, indonesiska, italienska, japanska, koreanska, malaysiska, holländska, norska, polska, portugisiska (PT/BR), rumänska, ryska, thailändska, ukrainska, ukrainska, kinesiska, engelska, ukrainska, vietnamesiska, ukrainska, svenska, ukrainska
- **RTL-stöd** — Höger-till-vänster-stöd för arabiska och hebreiska
- **Multi-Language READMEs** — 30 fullständiga dokumentationsöversättningar
- **Språkväljare** — Globikon i rubriken för växling i realtid
</details>
<details>
<summary><b>🔄 13. "Jag behöver mer än chatt — jag behöver inbäddningar, bilder, ljud"</b></summary>
AI är inte bara att slutföra chatt. Utvecklare måste generera bilder, transkribera ljud, skapa inbäddningar för RAG, ranka om dokument och moderera innehåll. Varje API har olika slutpunkt och format.
**Hur OmniRoute löser det:**
- **Inbäddningar** — `/v1/embeddings` med 6 leverantörer och 9+ modeller
- **Bildgenerering** — `/v1/images/generations` med 10 leverantörer och 20+ modeller (OpenAI, xAI, Together, Fireworks, Nebius, Hyperbolic, NanoBanana, Antigravity, SD WebUI, ComfyUI)
- **Text-till-video** — `/v1/videos/generations` — ComfyUI (AnimateDiff, SVD) och SD WebUI
- **Text-to-Music** — `/v1/music/generations` — ComfyUI (Stable Audio Open, MusicGen)
- **Ljudtranskription** — `/v1/audio/transcriptions` — Whisper + Nvidia NIM, HuggingFace, Qwen3
- **Text-till-tal** — `/v1/audio/speech` — ElevenLabs, Nvidia NIM, HuggingFace, Coqui, Tortoise, Qwen3, + befintliga leverantörer
- **Moderationer** — `/v1/moderations` — Innehållssäkerhetskontroller
- **Omrankning** — `/v1/rerank` — Omrankning av dokumentrelevans
- **Responses API** — Fullständigt `/v1/responses`-stöd för Codex
</details>
<details>
<summary><b>🧪 14. "Jag har inget sätt att testa och jämföra kvalitet mellan olika modeller" </b></summary>
Utvecklare vill veta vilken modell som är bäst för deras användningsfall - kod, översättning, resonemang - men det går långsamt att jämföra manuellt. Det finns inga integrerade utvärderingsverktyg.
**Hur OmniRoute löser det:**
- **LLM-utvärderingar** — Golden set-testning med 10 förinstallerade fall som täcker hälsningar, matematik, geografi, kodgenerering, JSON-efterlevnad, översättning, markdown, säkerhetsvägran
- **4 matchningsstrategier** — `exact`, `contains`, `regex`, `custom` (JS-funktion)
- **Translator Playground Test Bench** — Batchtestning med flera ingångar och förväntade utgångar, jämförelse mellan olika leverantörer
- **Chatttestare** — Fullständig tur och retur med visuell responsåtergivning
- **Live Monitor** — Realtidsström av alla förfrågningar som flödar genom proxyn
</details>
<details>
<summary><b>📈 15. "Jag behöver skala utan att förlora prestanda" </b></summary>
När förfrågningsvolymen ökar, utan att cachelagra genererar samma frågor dubbla kostnader. Utan idempotens, dubbletter begär avfallshantering. Prisgränser per leverantör måste respekteras.
**Hur OmniRoute löser det:**
- **Semantisk cache** — Tvåskiktscache (signatur + semantisk) minskar kostnaden och fördröjningen
- **Request Idempotency** — 5s dedupliceringsfönster för identiska förfrågningar
- **Rate Limit Detection** — RPM per leverantör, min gap och max samtidig spårning
- **Redigerbara hastighetsgränser** — Konfigurerbara standardinställningar i Inställningar → Motståndskraft med uthållighet
- **API Key Validation Cache** — 3-lagers cache för produktionsprestanda
- **Hälsoinstrumentpanel med telemetri** — p50/p95/p99 latens, cachestatistik, drifttid
</details>
<details>
<summary><b>🤖 16. "Jag vill kontrollera modellens beteende globalt" </b></summary>
Utvecklare som vill ha alla svar på ett specifikt språk, med en specifik ton, eller som vill begränsa resonemangstokens. Att konfigurera detta i varje verktyg/förfrågan är opraktiskt.
**Hur OmniRoute löser det:**
- **System Prompt Injection** — Global prompt tillämpas på alla förfrågningar
- **Thinking Budget Validation** — Reasoning token allocation control per request (passthrough, auto, custom, adaptive)
- **6 routingstrategier** — Globala strategier som avgör hur förfrågningar distribueras
- **Wildcard Router** — `provider/*`-mönster dirigerar dynamiskt till vilken leverantör som helst
- **Kombo Aktivera/Inaktivera Växla** — Växla kombinationer direkt från instrumentpanelen
- **Visa leverantör** — Aktivera/inaktivera alla anslutningar för en leverantör med ett klick
- **Blockerade leverantörer** — Uteslut specifika leverantörer från `/v1/models`-listan
</details>
<details>
<summary><b>🧰 17. "Jag behöver MCP-verktyg som förstklassiga produktegenskaper" </b></summary>
Många AI-gateways exponerar MCP endast som en dold implementeringsdetalj. Team behöver ett synligt, hanterbart driftlager.
**Hur OmniRoute löser det:**
- MCP visas på navigeringspanelen och fliken för slutpunktsprotokoll
- Dedikerad MCP-hanteringssida med process, verktyg, omfattningar och revision
- Inbyggd snabbstart för `omniroute --mcp` och klientintroduktion
</details>
<details>
<summary><b>🧠 18. "Jag behöver A2A-orkestrering med synkronisering + strömningsuppgiftsvägar" </b></summary>
Agentarbetsflöden kräver både direkta svar och långvarig streamad exekvering med livscykelkontroll.
**Hur OmniRoute löser det:**
- A2A JSON-RPC-ändpunkt (`POST /a2a`) med `message/send` och `message/stream`
- SSE-strömning med terminaltillståndspridning
- Task lifecycle API:er för `tasks/get` och `tasks/cancel`
</details>
<details>
<summary><b>🛰️ 19. "Jag behöver riktig MCP-processhälsa, inte gissad status" </b></summary>
Operativa team måste veta om MCP faktiskt lever, inte bara om ett API är tillgängligt.
**Hur OmniRoute löser det:**
- Runtime heartbeat-fil med PID, tidsstämplar, transport, verktygsräkning och scope-läge
- MCP status API som kombinerar hjärtslag + senaste aktivitet
- UI-statuskort för process/upptid/hjärtslagsnyhet
</details>
<details>
<summary><b>📋 20. "Jag behöver revisionsbart MCP-verktygsexekvering" </b></summary>
När verktyg muterar konfiguration eller utlöser operationsåtgärder behöver team rättsmedicinsk spårbarhet.
**Hur OmniRoute löser det:**
- SQLite-stödd revisionsloggning för MCP-verktygsanrop
- Filtrerar efter verktyg, framgång/misslyckande, API-nyckel och paginering
- Dashboard revisionstabell + statistikslutpunkter för automatisering
</details>
<details>
<summary><b>🔐 21. "Jag behöver scoped MCP-behörigheter per integration" </b></summary>
Olika klienter bör ha minst privilegierad åtkomst till verktygskategorier.
**Hur OmniRoute löser det:**
- 9 granulära MCP-scopes för kontrollerad verktygsåtkomst
- Tillämpning av omfattning och synlighet i MCP-hanteringsgränssnitt
- Säker standardställning för operativa verktyg
</details>
<details>
<summary><b>⚙️ 22. "Jag behöver driftskontroller utan att omdistribuera" </b></summary>
Team behöver snabba körtidsförändringar under incidenter eller kostnadshändelser.
**Hur OmniRoute löser det:**
- Växla kombinationsaktivering direkt från MCP-instrumentpanelen
- Tillämpa motståndskraftsprofiler från fördefinierade policypaket
- Återställ strömbrytarens tillstånd från samma manöverpanel
</details>
<details>
<summary><b>🔄 23. "I need live A2A task lifecycle synibility and cancellation"</b></summary>
Utan livscykelsynlighet blir uppgiftsincidenter svåra att triage.
**Hur OmniRoute löser det:**
- Uppgiftslista/filtrering efter stat/färdighet med sidnumrering
- Drill down på uppgiftens metadata, händelser och artefakter
- Slutpunkt för annullering av uppgifter och gränssnittsåtgärd med bekräftelse
</details>
<details>
<summary><b>🌊 24. "Jag behöver mätvärden för aktiv strömning för A2A-laddning" </b></summary>
Strömmande arbetsflöden kräver operativ insikt i samtidighet och direktanslutningar.
**Hur OmniRoute löser det:**
- Aktiva strömräknare integrerade i A2A-status
- Tidsstämpel för senaste uppgift och antal per stat
- A2A instrumentpanelskort för operationsövervakning i realtid
</details>
<details>
<summary><b>🪪 25. "Jag behöver standardagentupptäckt för klienter" </b></summary>
Externa klienter och orkestratorer behöver maskinläsbar metadata för onboarding.
**Hur OmniRoute löser det:**
- Agentkort exponerat på `/.well-known/agent.json`
- Förmåga och färdigheter som visas i ledningsgränssnittet
- A2A status API inkluderar upptäcktsmetadata för automatisering
</details>
<details>
<summary><b>🧭 26. "Jag behöver protokollupptäckbarhet i produktens UX" </b></summary>
Om användare inte kan upptäcka protokollytor, sjunker kvaliteten på adoption och support.
**Hur OmniRoute löser det:**
- Sidofältsposter för MCP och A2A
- Slutpunktssida Protokoll-fliken med snabbstart och status
- Länkar från översikt till dedikerade hanteringspaneler
</details>
<details>
<summary><b>🧪 27. "Jag behöver end-to-end protokollvalidering med riktiga klienter" </b></summary>
Mock-tester räcker inte för att validera protokollkompatibilitet före release.
**Hur OmniRoute löser det:**
- E2E-svit som startar appen och använder riktig MCP SDK-klienttransport
- A2A-klient testar för upptäckt, skicka, streama, hämta och avbryta flöden
- Korskontrollera påståenden mot MCP-revision och A2A-uppgifter API:er
</details>
<details>
<summary><b>📡 28. "Jag behöver enhetlig observerbarhet över alla gränssnitt" </b></summary>
Att dela upp observerbarheten enligt protokoll skapar blinda fläckar och längre MTTR.
**Hur OmniRoute löser det:**
- Enhetliga instrumentpaneler/loggar/analyser i en produkt
- Hälsa + revision + begäran om telemetri över OpenAI-, MCP- och A2A-lager
- Operativa API:er för status och automatisering
</details>
<details>
<summary><b>💼 29. "Jag behöver en körtid för proxy + verktyg + agentorkestrering" </b></summary>
Att köra många separata tjänster ökar driftskostnaderna och fellägen.
**Hur OmniRoute löser det:**
- OpenAI-kompatibel proxy, MCP-server och A2A-server i en stack
- Delad autentisering, resiliens, datalagring och observerbarhet
- Konsekvent policymodell över alla interaktionsytor
</details>
<details>
<summary><b>🚀 30. "Jag behöver skicka agentiska arbetsflöden utan limkodsprawl" </b></summary>
Lag tappar hastighet när de sammanfogar flera ad-hoc-tjänster och skript.
**Hur OmniRoute löser det:**
- Enhetlig slutpunktsstrategi för kunder och agenter
- Inbyggda gränssnitt för protokollhantering och rökvalideringsvägar
- Produktionsfärdiga grunder (säkerhet, loggning, resiliens, backup)
</details>
### Exempel på Playbooks (integrerade användningsfall)
**Playbook A: Maximera betald prenumeration + billig backup**
```txt
Combo: "maximize-claude"
1. cc/claude-opus-4-6
2. glm/glm-4.7
3. if/kimi-k2-thinking
Monthly cost: $20 + small backup spend
Outcome: higher quality, near-zero interruption
```
**Playbook B: Noll-kostnad kodningsstack**
```txt
Combo: "free-forever"
1. gc/gemini-3-flash
2. if/kimi-k2-thinking
3. qw/qwen3-coder-plus
Monthly cost: $0
Outcome: stable free coding workflow
```
**Playbook C: 24/7 alltid-på reservkedja**
```txt
Combo: "always-on"
1. cc/claude-opus-4-6
2. cx/gpt-5.2-codex
3. glm/glm-4.7
4. minimax/MiniMax-M2.1
5. if/kimi-k2-thinking
Outcome: deep fallback depth for deadline-critical workloads
```
**Playbook D: Agent ops med MCP + A2A**
```txt
1) Start MCP transport (`omniroute --mcp`) for tool-driven operations
2) Run A2A tasks via `message/send` and `message/stream`
3) Observe via /dashboard/mcp and /dashboard/a2a
4) Control incidents with resilience profile + task cancellation
```
---
## ⚡ Snabbstart
**1. Installera globalt:**
@@ -251,7 +781,7 @@ docker compose --profile cli up -d
---
## 🖥️ Desktop App — Offline & Always-On
## 🖥️
> 🆕 **NEW!** OmniRoute is now available as a **native desktop application** for Windows, macOS, and Linux.
@@ -298,67 +828,6 @@ npm run electron:build:linux # Linux (.AppImage)
---
## 🎯 Användningsfall
### Fall 1: "Jag har Claude Pro-abonnemang"
**Problem:** Kvoten går ut oanvänd, hastighetsgränser under tung kodning
```
Combo: "maximize-claude"
1. cc/claude-opus-4-6 (use subscription fully)
2. glm/glm-4.7 (cheap backup when quota out)
3. if/kimi-k2-thinking (free emergency fallback)
Monthly cost: $20 (subscription) + ~$5 (backup) = $25 total
vs. $20 + hitting limits = frustration
```
### Fall 2: "Jag vill ha noll kostnad"
**Problem:** Har inte råd med prenumerationer, behöver pålitlig AI-kodning
```
Combo: "free-forever"
1. gc/gemini-3-flash (180K free/month)
2. if/kimi-k2-thinking (unlimited free)
3. qw/qwen3-coder-plus (unlimited free)
Monthly cost: $0
Quality: Production-ready models
```
### Fall 3: "Jag behöver kodning dygnet runt, inga avbrott"
**Problem:** Deadlines, har inte råd med driftstopp
```
Combo: "always-on"
1. cc/claude-opus-4-6 (best quality)
2. cx/gpt-5.2-codex (second subscription)
3. glm/glm-4.7 (cheap, resets daily)
4. minimax/MiniMax-M2.1 (cheapest, 5h reset)
5. if/kimi-k2-thinking (free unlimited)
Result: 5 layers of fallback = zero downtime
```
### Fall 4: "Jag vill ha GRATIS AI i OpenClaw"
**Problem:** Behöver AI-assistent i meddelandeappar, helt gratis
```
Combo: "openclaw-free"
1. if/glm-4.7 (unlimited free)
2. if/minimax-m2.1 (unlimited free)
3. if/kimi-k2-thinking (unlimited free)
Monthly cost: $0
Access via: WhatsApp, Telegram, Slack, Discord, iMessage, Signal...
```
---
## 💡 Nyckelfunktioner
### 🧠 Core Routing & Intelligence
@@ -374,6 +843,8 @@ Access via: WhatsApp, Telegram, Slack, Discord, iMessage, Signal...
| 🧩 **Anpassade modeller** | Lägg till valfritt modell-ID till valfri leverantör |
| 🌐 **Wildcard-router** | Dirigera `provider/*`-mönster till valfri leverantör dynamiskt |
| 🧠 **Tänkande budget** | Genomgång, auto, anpassade och adaptiva lägen för resonerande modeller |
| 🔀 **Model Aliases** | Auto-forward deprecated model IDs to current replacements (built-in + custom) |
| ⚡ **Background Degradation** | Auto-route background tasks (titles, summaries) to cheaper models |
| 💬 **System Prompt Injection** | Global systemprompt tillämpas på alla förfrågningar |
| 📄 **Responses API** | Fullständigt stöd för OpenAI Responses API (`/v1/responses`) för Codex |
@@ -393,12 +864,15 @@ Access via: WhatsApp, Telegram, Slack, Discord, iMessage, Signal...
| Funktion | Vad det gör |
| -------------------------------------- | --------------------------------------------------------------------------------- |
| 🔌 **Circuit Breaker** | Autoöppna/stäng per leverantör med konfigurerbara trösklar |
| 🎯 **Endpoint-Aware Models** | Custom models declare supported endpoints + API format |
| 🛡️ **Anti-ånflock** | Mutex + semaforhastighetsgräns för API-nyckelleverantörer |
| 🧠 **Semantisk cache** | Tvåskiktscache (signatur + semantisk) minskar kostnaden och fördröjningen |
| ⚡ **Begär idempotens** | 5s dedup-fönster för dubblettförfrågningar |
| 🔒 **TLS Fingerprint Spoofing** | Förbi TLS-baserad botdetektering via wreq-js |
| 🌐 **IP-filtrering** | Tillåtelselista/blockeringslista för API-åtkomstkontroll |
| 📊 **Redigerbara hastighetsgränser** | Konfigurerbart RPM, min gap och max samtidiga på systemnivå |
| 💾 **Rate Limit Persistence** | Learned limits survive restarts via SQLite with 60s debounce + 24h staleness |
| 🔄 **Token Refresh Resilience** | Per-provider circuit breaker (5 fails→30min) + 30s timeout per attempt |
| 🛡 **API Endpoint Protection** | Auth gating + leverantörsblockering för `/models` slutpunkt |
| 🔒 **Proxysynlighet** | Färgkodade märken: 🟢 global, 🟡 leverantör, 🔵 per anslutning med IP-display |
| 🌐 **Proxykonfiguration med 3 nivåer** | Konfigurera proxyservrar på global nivå, per leverantör eller per anslutningsnivå |
@@ -517,6 +991,27 @@ OmniRoute inkluderar en kraftfull inbyggd översättarlekplats med **4 lägen**
</details>
## 🧪 Utvärderingar (Evals)
OmniRoute inkluderar ett inbyggt utvärderingsramverk för att testa LLM-svarskvalitet mot en gyllene uppsättning. Få åtkomst till det via **Analytics → Evals** i instrumentpanelen.
### Inbyggt gyllene set
Det förinstallerade "OmniRoute Golden Set" innehåller 10 testfall som täcker:
- Hälsningar, matematik, geografi, kodgenerering
- JSON-formatöverensstämmelse, översättning, markdown
- Säkerhetsvägran (skadligt innehåll), räkning, boolesk logik
### Utvärderingsstrategier
| Strategi | Beskrivning | Exempel |
| ---------- | ---------------------------------------------------- | -------------------------------- |
| `exact` | Utdata måste matcha exakt | `"4"` |
| `contains` | Utdata måste innehålla delsträng (skiftlägeskänslig) | `"Paris"` |
| `regex` | Utdata måste matcha regexmönster | `"1.*2.*3"` |
| `custom` | Anpassad JS-funktion returnerar true/false | `(output) => output.length > 10` |
---
## 📖 Installationsguide
@@ -799,98 +1294,58 @@ Settings → API Configuration:
---
## 📊 Tillgängliga modeller
## 🐛 Felsökning
<details>
<summary><b>Visa alla tillgängliga modeller</b></summary>
<summary><b>Klicka för att expandera felsökningsguide</b></summary>
**Claude Code (`cc/`)** - Pro/Max:
**"Språkmodellen gav inga meddelanden"**
- `cc/claude-opus-4-6`
- `cc/claude-sonnet-4-5-20250929`
- `cc/claude-haiku-4-5-20251001`
- Leverantörskvoten är slut → Kontrollera instrumentpanelens kvotföljare
- Lösning: Använd kombinationsalternativ eller byt till billigare nivå
**Codex (`cx/`)** - Plus/Pro:
**Taxebegränsning**
- `cx/gpt-5.2-codex`
- `cx/gpt-5.1-codex-max`
- Prenumerationskvot ute → Fallback till GLM/MiniMax
- Lägg till kombination: `cc/claude-opus-4-6 → glm/glm-4.7 → if/kimi-k2-thinking`
**Gemini CLI (`gc/`)** - GRATIS:
**OAuth-token har löpt ut**
- `gc/gemini-3-flash-preview`
- `gc/gemini-2.5-pro`
- Automatisk uppdatering av OmniRoute
- Om problemen kvarstår: Dashboard → Leverantör → Återanslut
**GitHub Copilot (`gh/`)**:
**Höga kostnader**
- `gh/gpt-5`
- `gh/claude-4.5-sonnet`
- Kontrollera användningsstatistik i Dashboard → Kostnader
- Byt primär modell till GLM/MiniMax
- Använd gratis nivå (Gemini CLI, iFlow) för icke-kritiska uppgifter
**NVIDIA NIM (`nvidia/`)** - GRATIS krediter:
**Dashboard öppnas på fel port**
- `nvidia/llama-3.3-70b-instruct`
- `nvidia/mistral-7b-instruct`
- 50+ modeller till på [build.nvidia.com](https://build.nvidia.com)
- Set `PORT=20128` och `NEXT_PUBLIC_BASE_URL=http://localhost:20128`
**GLM (`glm/`)** - $0,6/1M:
**Molnsynkroniseringsfel**
- `glm/glm-4.7`
- Verifiera att `BASE_URL` pekar på din löpinstans
- Verifiera `CLOUD_URL` poäng till din förväntade molnslutpunkt
- Håll `NEXT_PUBLIC_*` värden i linje med värden på serversidan
**MiniMax (`minimax/`)** - $0,2/1M:
**Första inloggningen fungerar inte**
- `minimax/MiniMax-M2.1`
- Kontrollera `INITIAL_PASSWORD` i `.env`
- Om det inte är inställt är reservlösenordet `123456`
**iFlow (`if/`)** - GRATIS:
**Inga förfrågningsloggar**
- `if/kimi-k2-thinking`
- `if/qwen3-coder-plus`
- `if/deepseek-r1`
- `if/glm-4.7`
- `if/minimax-m2`
- Ställ in `ENABLE_REQUEST_LOGS=true` i `.env`
**Qwen (`qw/`)** - GRATIS:
**Anslutningstest visar "Invalid" för OpenAI-kompatibla leverantörer**
- `qw/qwen3-coder-plus`
- `qw/qwen3-coder-flash`
- Många leverantörer exponerar inte en `/models` slutpunkt
- OmniRoute v1.0.6+ inkluderar reservvalidering via chattslutföranden
- Se till att baswebbadressen innehåller suffixet `/v1`
**Kiro (`kr/`)** - GRATIS:
- `kr/claude-sonnet-4.5`
- `kr/claude-haiku-4.5`
**OpenRouter (`or/`)** - 100+ modeller:
- `or/anthropic/claude-4-sonnet`
- `or/google/gemini-2.5-pro`
- Alla modeller från [openrouter.ai/models](https://openrouter.ai/models)
</details>
---
## 🧪 Utvärderingar (Evals)
OmniRoute inkluderar ett inbyggt utvärderingsramverk för att testa LLM-svarskvalitet mot en gyllene uppsättning. Få åtkomst till det via **Analytics → Evals** i instrumentpanelen.
### Inbyggt gyllene set
Det förinstallerade "OmniRoute Golden Set" innehåller 10 testfall som täcker:
- Hälsningar, matematik, geografi, kodgenerering
- JSON-formatöverensstämmelse, översättning, markdown
- Säkerhetsvägran (skadligt innehåll), räkning, boolesk logik
### Utvärderingsstrategier
| Strategi | Beskrivning | Exempel |
| ---------- | ---------------------------------------------------- | -------------------------------- |
| `exact` | Utdata måste matcha exakt | `"4"` |
| `contains` | Utdata måste innehålla delsträng (skiftlägeskänslig) | `"Paris"` |
| `regex` | Utdata måste matcha regexmönster | `"1.*2.*3"` |
| `custom` | Anpassad JS-funktion returnerar true/false | `(output) => output.length > 10` |
---
## 🔐 OAuth em Servidor Remoto (Remote OAuth Setup)
### 🔐 OAuth
<a name="oauth-em-servidor-remoto"></a>
@@ -981,64 +1436,11 @@ Se não quiser criar credenciais próprias agora, ainda é possível usar o flux
> Este workaround funciona porque o código de autorização na URL é válido independente do redirect ter carregado ou não.
---
## 🐛 Felsökning
<details>
<summary><b>Klicka för att expandera felsökningsguide</b></summary>
**"Språkmodellen gav inga meddelanden"**
- Leverantörskvoten är slut → Kontrollera instrumentpanelens kvotföljare
- Lösning: Använd kombinationsalternativ eller byt till billigare nivå
**Taxebegränsning**
- Prenumerationskvot ute → Fallback till GLM/MiniMax
- Lägg till kombination: `cc/claude-opus-4-6 → glm/glm-4.7 → if/kimi-k2-thinking`
**OAuth-token har löpt ut**
- Automatisk uppdatering av OmniRoute
- Om problemen kvarstår: Dashboard → Leverantör → Återanslut
**Höga kostnader**
- Kontrollera användningsstatistik i Dashboard → Kostnader
- Byt primär modell till GLM/MiniMax
- Använd gratis nivå (Gemini CLI, iFlow) för icke-kritiska uppgifter
**Dashboard öppnas på fel port**
- Set `PORT=20128` och `NEXT_PUBLIC_BASE_URL=http://localhost:20128`
**Molnsynkroniseringsfel**
- Verifiera att `BASE_URL` pekar på din löpinstans
- Verifiera `CLOUD_URL` poäng till din förväntade molnslutpunkt
- Håll `NEXT_PUBLIC_*` värden i linje med värden på serversidan
**Första inloggningen fungerar inte**
- Kontrollera `INITIAL_PASSWORD` i `.env`
- Om det inte är inställt är reservlösenordet `123456`
**Inga förfrågningsloggar**
- Ställ in `ENABLE_REQUEST_LOGS=true` i `.env`
**Anslutningstest visar "Invalid" för OpenAI-kompatibla leverantörer**
- Många leverantörer exponerar inte en `/models` slutpunkt
- OmniRoute v1.0.6+ inkluderar reservvalidering via chattslutföranden
- Se till att baswebbadressen innehåller suffixet `/v1`
</details>
---
## 🛠️ Tech Stack
## 🛠️
- **Körtid**: Node.js 1822 LTS (⚠️ Node.js 24+ stöds **inte**`better-sqlite3` inbyggda binärer är inkompatibla)
- **Språk**: TypeScript 5.9 — **100 % TypeScript** över `src/` och `open-sse/` (v1.0.6)
@@ -1090,7 +1492,7 @@ Se não quiser criar credenciais próprias agora, ainda é possível usar o flux
---
## 🗺️ Färdkarta
## 🗺️
OmniRoute har **210+ funktioner planerade** över flera utvecklingsfaser. Här är nyckelområdena:
@@ -1115,18 +1517,6 @@ OmniRoute har **210+ funktioner planerade** över flera utvecklingsfaser. Här
---
## 📧 Support
> 💬 **Gå med i vår community!** [WhatsApp Group](https://chat.whatsapp.com/JI7cDQ1GyaiDHhVBpLxf8b?mode=gi_t) — Få hjälp, dela tips och håll dig uppdaterad.
- **Webbplats**: [omniroute.online](https://omniroute.online)
- **GitHub**: [github.com/diegosouzapw/OmniRoute](https://github.com/diegosouzapw/OmniRoute)
- **Frågor**: [github.com/diegosouzapw/OmniRoute/issues](https://github.com/diegosouzapw/OmniRoute/issues)
- **WhatsApp**: [Community Group](https://chat.whatsapp.com/JI7cDQ1GyaiDHhVBpLxf8b?mode=gi_t)
- **Originalprojekt**: [9router by decolua](https://github.com/decolua/9router)
---
## 👥 Bidragsgivare
[![Contributors](https://contrib.rocks/image?repo=diegosouzapw/OmniRoute&max=100&columns=20&anon=1)](https://github.com/diegosouzapw/OmniRoute/graphs/contributors)
@@ -1176,85 +1566,6 @@ MIT-licens - se [LICENSE](LICENSE) för detaljer.
---
---
## 🇧🇷 OmniRoute — Gateway de IA Gratuito
<a name="-omniroute--gateway-de-ia-gratuito"></a>
### Nunca pare de codar. Roteamento inteligente para **modeller de IA GRATUITOS e de baixo custo** com reservautomatisk.
_Seu proxy universal de API — um endpoint, 36+ tester, noll driftstopp._
### 🌐 Internacionalização (i18n)
O instrumentpanelen gör OmniRoute stöder **múltiplos idiomas**. Attualmente disponível em:
| Idiom | Código | Status |
| ------------------------ | ------- | ----------- |
| 🇺🇸 engelska | `en` | ✅ Komplett |
| 🇧🇷 Português (Brasilien) | `pt-BR` | ✅ Komplett |
**Para trocar o idioma:** Clique no selector de idioma (🇺🇸 EN) no header do dashboard → selecione o idioma desejado.
**För att lägga till ett nytt uttryck:**
1. Crie `src/i18n/messages/{codigo}.json` baseado em `en.json`
2. Adicione o código em `src/i18n/config.ts``LOCALES` och `LANGUAGES`
3. Reinicie o servidor
### ⚡ Início Rápido
```bash
# Instalar via npm
npx omniroute@latest
# Ou rodar do código-fonte
cp .env.example .env
npm install
PORT=20128 NEXT_PUBLIC_BASE_URL=http://localhost:20128 npm run dev
```
### 🐳 Hamnarbetare
```bash
docker run -d --name omniroute -p 20128:20128 diegosouzapw/omniroute:latest
```
### 🔑 Funcionalidades Principais
- **36+ provedores de IA** — Claude, GPT, Gemini, Llama, Qwen, DeepSeek, e mais
- **Roteamento inteligente** — Fallback automático entre provedores
- **Tradução de formato** — OpenAI ↔ Claude ↔ Gemini automaticamente
- **Multi-conta** — Múltiplas contas por provedor com seleção inteligente
- **Cache semântico** — Reduz custos e latência
- **OAuth automático** — Tokens renovam automaticamente
- **Combos personalizados** — 6 estratégias de roteamento
- **Dashboard komplett** — Övervakning, loggar, analyser, konfigurationer
- **CLI-verktyg** — Konfigurera Claude Code, Codex, Cursor, Cline com um clique
- **100 % TypeScript** — Código limpo e tipado
### 📖 Dokumentation
| Dokument | Beskrivning |
| ----------------------------------------------- | --------------------------------------------- |
| [Guia do Usuário](docs/USER_GUIDE.md) | Provedores, combos, CLI, distribuera |
| [Referência da API](docs/API_REFERENCE.md) | Todos os endpoints com exemplos |
| [Solução de Problemas](docs/TROUBLESHOOTING.md) | Problemas comuns e soluções |
| [Arquitetura](docs/ARCHITECTURE.md) | Arquitetura e internos do sistema |
| [Contribuição](CONTRIBUTING.md) | Inställning av desenvolvimento och riktlinjer |
| [Deploy em VM](docs/VM_DEPLOYMENT_GUIDE.md) | Komplettera med: VM + nginx + Cloudflare |
### 📧 Stöd
> 💬 **Entre para a comunidade!** [Grupo WhatsApp](https://chat.whatsapp.com/JI7cDQ1GyaiDHhVBpLxf8b?mode=gi_t) — Tire dúvidas, compartilhe dicas e fique atualizado.
- **Webbplats**: [omniroute.online](https://omniroute.online)
- **GitHub**: [github.com/diegosouzapw/OmniRoute](https://github.com/diegosouzapw/OmniRoute)
- **Frågor**: [github.com/diegosouzapw/OmniRoute/issues](https://github.com/diegosouzapw/OmniRoute/issues)
---
<div align="center">
<sub>Byggd med ❤️ för utvecklare som kodar 24/7</sub>
<br/>

File diff suppressed because it is too large Load Diff

View File

@@ -3,8 +3,6 @@
# 🚀 OmniRoute — безкоштовний ШІ-шлюз
🌐 **[English](#-omniroute--the-free-ai-gateway)** | **[Português (BR)](#-omniroute--gateway-de-ia-gratuito)**
### Ніколи не припиняйте кодувати. Розумна маршрутизація до **БЕЗКОШТОВНИХ і недорогих моделей штучного інтелекту** з автоматичним резервним копіюванням.
_Ваш універсальний API-проксі — одна кінцева точка, понад 36 провайдерів, нуль простоїв._
@@ -112,6 +110,35 @@ _Підключіть будь-який інструмент IDE або CLI на
---
## 🖼️
<div align="center">
<img src="./docs/screenshots/MainOmniRoute.png" alt="OmniRoute" width="800"/>
</div>
---
## 📸
<details>
<summary><b>...</b></summary>
| # | # |
| ----- | ---------------------------------------- |
| **1** | ![1](docs/screenshots/01-providers.png) |
| **2** | ![2](docs/screenshots/02-combos.png) |
| **3** | ![3](docs/screenshots/03-analytics.png) |
| **4** | ![4](docs/screenshots/04-health.png) |
| **5** | ![5](docs/screenshots/05-translator.png) |
| **6** | ![6](docs/screenshots/06-settings.png) |
| **7** | ![7](docs/screenshots/07-cli-tools.png) |
| **8** | ![8](docs/screenshots/08-usage.png) |
| **9** | ![9](docs/screenshots/09-endpoint.png) |
</details>
---
## 🤔 Чому OmniRoute?
**Припиніть витрачати гроші та досягати лімітів:**
@@ -130,6 +157,18 @@ _Підключіть будь-який інструмент IDE або CLI на
---
## 📧 Підтримка
> 💬 **Приєднуйтесь до нашої спільноти!** [WhatsApp Group](https://chat.whatsapp.com/JI7cDQ1GyaiDHhVBpLxf8b?mode=gi_t) — отримуйте допомогу, діліться порадами та будьте в курсі подій.
- **Веб-сайт**: [omniroute.online](https://omniroute.online)
- **GitHub**: [github.com/diegosouzapw/OmniRoute](https://github.com/diegosouzapw/OmniRoute)
- **Проблеми**: [github.com/diegosouzapw/OmniRoute/issues](https://github.com/diegosouzapw/OmniRoute/issues)
- **WhatsApp**: [Community Group](https://chat.whatsapp.com/JI7cDQ1GyaiDHhVBpLxf8b?mode=gi_t)
- **Оригінальний проект**: [9router by decolua](https://github.com/decolua/9router)
---
## 🔄 Як це працює
```
@@ -159,6 +198,502 @@ Result: Never stop coding, minimal cost
---
## 🎯 Що вирішує OmniRoute — 30 реальних проблем і варіантів використання
> **Кожен розробник, який використовує інструменти штучного інтелекту, щодня стикається з цими проблемами.** OmniRoute було створено, щоб вирішити їх усі — від перевитрати коштів до регіональних блокувань, від порушених потоків OAuth до операцій протоколу та спостережуваності підприємства.
<details>
<summary><b>💸 1. «Я плачу за дорогу підписку, але мене все одно переривають через обмеження» </b></summary>
Розробники платять 20200 доларів на місяць за Claude Pro, Codex Pro або GitHub Copilot. Навіть якщо платити, квота має максимальну межу — 5 годин використання, тижневі ліміти або ліміти за хвилину. У середині сеансу кодування постачальник перестає відповідати, а розробник втрачає швидкість і продуктивність.
**Як це вирішує OmniRoute:**
- **Smart 4-Tier Fallback** — якщо квота підписки закінчується, автоматично перенаправляється до API Key → Дешево → Безкоштовно без ручного втручання
- **Відстеження квот у реальному часі** — показує споживання токенів у реальному часі зі зворотним відліком скидання (5 годин, щодня, щотижня)
- **Підтримка кількох облікових записів** — кілька облікових записів у кожного постачальника з автоматичним циклічним перебором — коли один закінчується, перемикається на наступний
- **Користувацькі комбінації** — резервні ланцюжки, які можна налаштувати, із 6 стратегіями балансування (спочатку заповнення, циклічний, P2C, випадковий, найменш використовуваний, економічно оптимізований)
- **Бізнес-квоти Codex** — Моніторинг квот робочого простору бізнесу/команди безпосередньо на інформаційній панелі
</details>
<details>
<summary><b>🔌 2. «Мені потрібно використовувати кілька постачальників, але кожен має різний API» </b></summary>
OpenAI використовує один формат, Claude (Anthropic) використовує інший, Gemini ще інший. Якщо розробник хоче перевірити моделі від різних постачальників або повернутися до них, йому потрібно переналаштувати SDK, змінити кінцеві точки, мати справу з несумісними форматами. Спеціальні постачальники (FriendLI, NIM) мають нестандартні кінцеві точки моделі.
**Як це вирішує OmniRoute:**
- **Уніфікована кінцева точка** — один `http://localhost:20128/v1` служить проксі для всіх 36+ постачальників
- **Переклад форматів** — автоматичний і прозорий: OpenAI ↔ Claude ↔ Gemini ↔ Responses API
- **Response Sanitization** — видаляє нестандартні поля (`x_groq`, `usage_breakdown`, `service_tier`), які порушують роботу OpenAI SDK v1.83+
- **Нормалізація ролі** — перетворює `developer``system` для постачальників, які не є OpenAI; `system``user` для GLM/ERNIE
- **Think Tag Extraction** — витягує блоки `<think>` із таких моделей, як DeepSeek R1, у стандартизований `reasoning_content`
- **Структурований вихід для Gemini** — `json_schema``responseMimeType`/`responseSchema` автоматичне перетворення
- **`stream` за замовчуванням — `false`** — відповідає специфікації OpenAI, уникаючи неочікуваних SSE у Python/Rust/Go SDK.
</details>
<details>
<summary><b>🌐 3. «Мій постачальник штучного інтелекту блокує мій регіон/країну» </b></summary>
Такі постачальники, як OpenAI/Codex, блокують доступ із певних географічних регіонів. Користувачі отримують помилки на зразок `unsupported_country_region_territory` під час з’єднань OAuth і API. Це особливо засмучує розробників із країн, що розвиваються.
**Як це вирішує OmniRoute:**
- **3-рівнева конфігурація проксі-сервера** — налаштовується проксі-сервер на 3 рівнях: глобальний (увесь трафік), для кожного постачальника (лише один постачальник) і для кожного підключення/ключа
- **Значки проксі-сервера з кольоровим кодуванням** — Візуальні індикатори: 🟢 глобальний проксі, 🟡 проксі-сервер постачальника, 🔵 проксі-сервер підключення, завжди показує IP-адресу
- **Обмін маркерами OAuth через проксі** — потік OAuth також проходить через проксі, вирішуючи `unsupported_country_region_territory`
- **Тестування з’єднання через проксі** — тестування з’єднання використовує налаштований проксі (без прямого обходу)
- **Підтримка SOCKS5** — повна підтримка проксі SOCKS5 для вихідної маршрутизації
- **TLS Fingerprint Spoofing** — TLS-відбиток, як у браузері, через `wreq-js` для обходу виявлення ботів
</details>
<details>
<summary><b>🆓 4. «Я хочу використовувати ШІ для кодування, але в мене немає грошей» </b></summary>
Не кожен може платити 20200 доларів на місяць за підписку на AI. Студентам, розробникам із країн, що розвиваються, любителям і фрілансерам потрібен доступ до якісних моделей за нульовою ціною.
**Як це вирішує OmniRoute:**
- **Вбудовані безкоштовні постачальники рівня** — Вбудована підтримка 100% безкоштовних постачальників: iFlow (8 необмежених моделей), Qwen (3 необмежені моделі), Kiro (Claude безкоштовно), Gemini CLI (180K/місяць безкоштовно)
- **Безкоштовні комбінації** — ланцюжок `gc/gemini-3-flash → if/kimi-k2-thinking → qw/qwen3-coder-plus` = 0 доларів США/місяць без простоїв
- **Безкоштовні кредити NVIDIA NIM** — інтегровано 1000 безкоштовних кредитів
- **Стратегія оптимізації витрат** — стратегія маршрутизації, яка автоматично вибирає найдешевшого доступного постачальника
</details>
<details>
<summary><b>🔒 5. «Мені потрібно захистити свій ШІ-шлюз від несанкціонованого доступу» </b></summary>
Коли шлюз штучного інтелекту надається мережі (LAN, VPS, Docker), будь-хто, хто має адресу, може використовувати токени/квоту розробника. Без захисту API вразливі до неправильного використання, швидкого впровадження та зловживання.
**Як це вирішує OmniRoute:**
- **Керування ключами API** — генерація, ротація та визначення обсягу для кожного постачальника за допомогою спеціальної сторінки `/dashboard/api-manager`
- **Дозволи на рівні моделі** — обмежте ключі API певними моделями (`openai/*`, шаблони узагальнення) із перемикачем «Дозволити все»/«Обмежити»
- **API Endpoint Protection** — вимагати ключ для `/v1/models` і блокувати певних постачальників зі списку
- **Auth Guard + CSRF Protection** — усі маршрути інформаційної панелі захищені проміжним програмним забезпеченням `withAuth` + маркерами CSRF
- **Обмежувач швидкості** — обмеження швидкості за IP-адресою з настроюваними вікнами
- **IP Filtering** — список дозволених/чорних адрес для контролю доступу
- **Prompt Injection Guard** — очищення від шкідливих шаблонів підказок
- **Шифрування AES-256-GCM** — облікові дані зашифровані в стані спокою
</details>
<details>
<summary><b>🛑 6. «Мій постачальник не працює, і я втратив потік кодування» </b></summary>
Постачальники AI можуть стати нестабільними, повертати помилки 5xx або досягати тимчасових обмежень швидкості. Якщо розробник залежить від одного постачальника, вони перериваються. Без автоматичних вимикачів повторні спроби можуть призвести до збою програми.
**Як це вирішує OmniRoute:**
- **Автоматичний вимикач для кожного постачальника** — автоматичне розмикання/замикання з настроюваними пороговими значеннями та часом відновлення (закрито/розімкнуто/напіврозімкнуто)
- **Exponential Backoff** — прогресивні затримки повторних спроб
- **Anti-Thundering Herd** — Mutex + захист семафора від одночасних повторних штормів
- **Комбіновані запасні ланцюги** — якщо основний постачальник виходить з ладу, автоматично проходить через ланцюжок без втручання.
- **Combo Circuit Breaker** — автоматично вимикає несправні постачальники в комбінованому ланцюжку
| 🎯 **Endpoint-Aware Models** | Custom models declare supported endpoints + API format |
- **Health Dashboard** — Моніторинг безвідмовної роботи, стани автоматичного вимикача, блокування, статистика кешу, затримка p50/p95/p99
</details>
<details>
<summary><b>🔧 7. «Налаштування кожного інструменту штучного інтелекту є виснажливим і повторюваним процесом» </b></summary>
Розробники використовують Cursor, Claude Code, Codex CLI, OpenClaw, Gemini CLI, Kilo Code... Кожному інструменту потрібна інша конфігурація (кінцева точка API, ключ, модель). Перенастроювання при зміні постачальника чи моделі марна трата часу.
**Як це вирішує OmniRoute:**
- **Панель інструментів CLI** — спеціальна сторінка з налаштуванням одним клацанням для Claude Code, Codex CLI, OpenClaw, Kilo Code, Antigravity, Cline
- **GitHub Copilot Config Generator** — генерує `chatLanguageModels.json` для коду VS із масовим вибором моделі
- **Майстер адаптації** — 4-етапне налаштування для тих, хто вперше користується
- **Одна кінцева точка, усі моделі** — налаштуйте `http://localhost:20128/v1` один раз, отримайте доступ до 36+ постачальників
</details>
<details>
<summary><b>🔑 8. «Керування токенами OAuth від кількох постачальників — це пекло» </b></summary>
Claude Code, Codex, Gemini CLI, Copilot — усі використовують OAuth 2.0 із терміном дії маркерів. Розробникам необхідно постійно проходити повторну автентифікацію, мати справу з `client_secret is missing`, `redirect_uri_mismatch` і збоями на віддалених серверах. OAuth у LAN/VPS є особливо проблематичним.
**Як це вирішує OmniRoute:**
- **Auto Token Refresh** — маркери OAuth оновлюються у фоновому режимі до завершення терміну дії
- **Вбудований OAuth 2.0 (PKCE)** — автоматичний потік для Claude Code, Codex, Gemini CLI, Copilot, Kiro, Qwen, iFlow
- **Multi-Account OAuth** — кілька облікових записів на постачальника за допомогою вилучення токенів JWT/ID
- **OAuth LAN/Remote Fix** — виявлення приватної IP-адреси для `redirect_uri` + ручний режим URL-адреси для віддалених серверів
- **OAuth за Nginx** — використовує `window.location.origin` для зворотної сумісності проксі
- **Remote OAuth Guide** — покроковий посібник для облікових даних Google Cloud на VPS/Docker
</details>
<details>
<summary><b>📊 9. «Я не знаю, скільки я витрачаю і куди» </b></summary>
Розробники використовують кілька платних постачальників, але не мають єдиного уявлення про витрати. Кожен постачальник має власну платіжну панель, але немає консолідованого перегляду. Несподівані витрати можуть накопичитися.
**Як це вирішує OmniRoute:**
- **Інформаційна панель аналізу витрат** — відстеження вартості кожного токена та керування бюджетом для кожного постачальника
- **Бюджетні обмеження на рівень** — максимальна сума витрат на рівень, що запускає автоматичний відкат
- **Конфігурація ціни за модель** — налаштовувані ціни за модель
- **Статистика використання за ключ API** — кількість запитів і позначка часу останнього використання для кожного ключа
- **Інформаційна панель аналітики** — картки зі статистичними даними, діаграма використання моделі, таблиця постачальників із показниками успіху та затримкою
</details>
<details>
<summary><b>🐛 10. «Я не можу діагностувати помилки та проблеми під час викликів ШІ» </b></summary>
Коли виклик не вдається, розробник не знає, чи це було обмеження швидкості, прострочений маркер, неправильний формат чи помилка постачальника. Фрагментовані журнали на різних терміналах. Без спостережливості налагодження відбувається методом проб і помилок.
**Як це вирішує OmniRoute:**
- **Інформаційна панель уніфікованих журналів** — 4 вкладки: журнали запитів, журнали проксі, журнали аудиту, консоль
- **Console Log Viewer** — засіб перегляду терміналу в режимі реального часу з кольоровими рівнями, автопрокручуванням, пошуком, фільтром
- **Проксі-журнали SQLite** — постійні журнали, які залишаються після перезапуску сервера
- **Translator Playground** — 4 режими налагодження: Playground (переклад формату), Chat Tester (туди й назад), Test Bench (пакет), Live Monitor (у реальному часі)
- **Запит телеметрії** — затримка p50/p95/p99 + трасування X-Request-Id
- **Логування на основі файлів із ротацією** — консольний перехоплювач записує все в журнал JSON із ротацією на основі розміру
</details>
<details>
<summary><b>🏗️ 11. «Розгортання та підтримка шлюзу є складною справою» </b></summary>
Встановлення, налаштування та обслуговування проксі ШІ в різних середовищах (локальне, VPS, Docker, хмара) є трудомістким. Такі проблеми, як жорстко закодовані шляхи, `EACCES` у каталогах, конфлікти портів і кросплатформні збірки, додають тертя.
**Як це вирішує OmniRoute:**
- **npm global install** — `npm install -g omniroute && omniroute` — готово
- **Мультиплатформенний Docker** — нативний AMD64 + ARM64 (Apple Silicon, AWS Graviton, Raspberry Pi)
- **Профілі створення Docker** — `base` (без інструментів CLI) і `cli` (з Claude Code, Codex, OpenClaw)
- **Electron Desktop App** — рідна програма для Windows/macOS/Linux із системним треєм, автозапуском, офлайн-режимом
- **Режим розділеного порту** — API та інформаційна панель на окремих портах для розширених сценаріїв (зворотний проксі, мережа контейнерів)
- **Cloud Sync** — синхронізація налаштувань між пристроями через Cloudflare Workers
- **Резервне копіювання БД** — автоматичне резервне копіювання, відновлення, експорт та імпорт усіх налаштувань
</details>
<details>
<summary><b>🌍 12. «Інтерфейс лише англійською мовою, і моя команда не розмовляє англійською» </b></summary>
Команди в неангломовних країнах, особливо в Латинській Америці, Азії та Європі, стикаються з інтерфейсами лише англійською мовою. Мовні бар’єри зменшують адаптацію та збільшують кількість помилок конфігурації.
**Як це вирішує OmniRoute:**
- **Інформаційна панель i18n — 30 мов** — перекладено всі 500+ клавіш, включаючи арабську, болгарську, датську, німецьку, іспанську, фінську, французьку, іврит, гінді, угорську, індонезійську, італійську, японську, корейську, малайську, голландську, норвезьку, польську, португальську (PT/BR), румунську, російську, словацьку, шведську, тайську, українську, в’єтнамську, китайська, філіппінська, англійська
- **Підтримка RTL** — підтримка арабської та івриту справа наліво
- **Багатомовні файли README** — 30 повних перекладів документації
- **Вибір мови** — значок глобуса в заголовку для перемикання в реальному часі
</details>
<details>
<summary><b>🔄 13. «Мені потрібно більше, ніж чат — мені потрібні вставки, зображення, аудіо» </b></summary>
ШІ — це не просто завершення чату. Розробникам потрібно генерувати зображення, транскрибувати аудіо, створювати вбудовування для RAG, змінювати рейтинг документів і модерувати вміст. Кожен API має різну кінцеву точку та формат.
**Як це вирішує OmniRoute:**
- **Вбудовування** — `/v1/embeddings` із 6 постачальниками та 9+ моделями
- **Генерація зображень** — `/v1/images/generations` із 10 постачальниками та понад 20 моделями (OpenAI, xAI, Together, Fireworks, Nebius, Hyperbolic, NanoBanana, Antigravity, SD WebUI, ComfyUI)
- **Текст у відео** — `/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/moderations` — Перевірки безпеки вмісту
- **Переранжування** — `/v1/rerank` — Переранжування релевантності документа
- **Responses API** — повна підтримка `/v1/responses` для Codex
</details>
<details>
<summary><b>🧪 14. «У мене немає можливості перевірити та порівняти якість різних моделей» </b></summary>
Розробники хочуть знати, яка модель найкраще підходить для їхнього випадку використання — код, переклад, міркування — але порівнювати вручну повільно. Інтегрованих інструментів оцінювання не існує.
**Як це вирішує OmniRoute:**
- **Оцінки LLM** — Золотий набір тестів із 10 попередньо завантаженими випадками, що охоплюють привітання, математику, географію, генерацію коду, відповідність JSON, переклад, уцінку, відмову безпеки
- **4 стратегії збігу** — `exact`, `contains`, `regex`, `custom` (функція JS)
- **Translator Playground Test Bench** — Пакетне тестування з кількома входами та очікуваними результатами, порівняння між постачальниками
- **Chat Tester** — повний цикл із візуальним відтворенням відповідей
- **Live Monitor** — потік усіх запитів, що проходять через проксі, у реальному часі
</details>
<details>
<summary><b>📈 15. «Мені потрібно масштабувати без втрати продуктивності» </b></summary>
Оскільки кількість запитів зростає, без кешування ті самі запитання створюють дублюючі витрати. Без ідемпотентності, дублікат запитів обробки відходів. Необхідно дотримуватися обмежень тарифів для кожного постачальника.
**Як це вирішує OmniRoute:**
- **Семантичний кеш** — дворівневий кеш (підпис + семантичний) зменшує вартість і затримку
- **Request Idempotency** — вікно дедуплікації 5 с для ідентичних запитів
- **Виявлення ліміту швидкості** — RPM для кожного постачальника, мінімальний розрив і максимальне одночасне відстеження
- **Обмеження швидкості, які можна редагувати** — налаштування за замовчуванням у Параметрах → Стійкість із наполегливістю
- **API Key Validation Cache** — 3-рівневий кеш для продуктивності
- **Інформаційна панель справності з телеметрією** — затримка p50/p95/p99, статистика кешу, час роботи
</details>
<details>
<summary><b>🤖 16. «Я хочу глобально контролювати поведінку моделі» </b></summary>
Розробники, які хочуть, щоб усі відповіді відповідали певною мовою, з певним тоном або хочуть обмежити маркери міркування. Налаштовувати це в кожному інструменті/запиті є недоцільним.
**Як це вирішує OmniRoute:**
- **Впровадження системної підказки** — глобальна підказка застосовується до всіх запитів
- **Thinking Budget Validation** — Контроль розподілу токенів міркувань за запитом (прохідний, автоматичний, спеціальний, адаптивний)
- **6 стратегій маршрутизації** — глобальні стратегії, які визначають спосіб розподілу запитів
- **Wildcard Router** — шаблони `provider/*` динамічно маршрутизують до будь-якого постачальника
- **Увімкнути/вимкнути комбо** — перемикайте комбо безпосередньо з інформаційної панелі
- **Перемикнути постачальника** — увімкнути/вимкнути всі з’єднання для постачальника одним клацанням миші
- **Заблоковані постачальники** — виключити певних постачальників зі списку `/v1/models`
</details>
<details>
<summary><b>🧰 17. «Мені потрібні інструменти MCP як першокласні можливості продукту» </b></summary>
Багато шлюзів ШІ розкривають MCP лише як приховану деталь реалізації. Командам потрібен видимий, керований рівень операцій.
**Як це вирішує OmniRoute:**
- MCP з’являється на панелі навігації та на вкладці протоколу кінцевої точки
- Спеціальна сторінка керування MCP із процесом, інструментами, обсягами й аудитом
- Вбудований швидкий запуск для `omniroute --mcp` і адаптація клієнта
</details>
<details>
<summary><b>🧠 18. «Мені потрібна оркестровка A2A із синхронізацією + шляхи завдань потоку» </b></summary>
Робочі процеси агента потребують як прямих відповідей, так і тривалого потокового виконання з контролем життєвого циклу.
**Як це вирішує OmniRoute:**
- Кінцева точка A2A JSON-RPC (`POST /a2a`) з `message/send` і `message/stream`
- Потокова передача SSE з розповсюдженням стану терміналу
- API життєвого циклу завдань для `tasks/get` і `tasks/cancel`
</details>
<details>
<summary><b>🛰️ 19. «Мені потрібна реальна справність процесу MCP, а не вгаданий статус» </b></summary>
Операційним групам потрібно знати, чи справді MCP активний, а не лише те, чи доступний API.
**Як це вирішує OmniRoute:**
- Файл серцевого ритму виконання з PID, часовими мітками, транспортом, кількістю інструментів і режимом області
- API статусу MCP, що поєднує серцебиття + останню активність
- Картки стану інтерфейсу користувача для процесу/часу безперебійної роботи/свіжості пульсу
</details>
<details>
<summary><b>📋 20. «Мені потрібне виконання інструменту MCP з можливістю перевірки» </b></summary>
Коли інструменти змінюють конфігурацію або запускають операційні дії, командам потрібна криміналістична відстежуваність.
**Як це вирішує OmniRoute:**
— Журнал аудиту з підтримкою SQLite для викликів інструментів MCP
- Фільтри за інструментом, успіхом/невдачею, ключем API та розбивкою на сторінки
- Таблиця аудиту інформаційної панелі + кінцеві точки статистики для автоматизації
</details>
<details>
<summary><b>🔐 21. «Мені потрібні обмежені дозволи MCP для інтеграції» </b></summary>
Різні клієнти повинні мати мінімальний доступ до категорій інструментів.
**Як це вирішує OmniRoute:**
- 9 детальних областей MCP для контрольованого доступу до інструменту
- Застосування обсягу та видимість в інтерфейсі користувача керування MCP
- Безпечна поза за замовчуванням для робочих інструментів
</details>
<details>
<summary><b>⚙️ 22. «Мені потрібен оперативний контроль без перерозподілу» </b></summary>
Командам потрібні швидкі зміни часу виконання під час інцидентів або витрат.
**Як це вирішує OmniRoute:**
- Перемикання комбо-активації безпосередньо з інформаційної панелі MCP
- Застосовуйте профілі стійкості з попередньо визначених пакетів політик
- Скинути стан автоматичного вимикача з тієї ж панелі керування
</details>
<details>
<summary><b>🔄 23. «Мені потрібна видимість і скасування життєвого циклу завдання A2A» </b></summary>
Без видимості життєвого циклу інциденти завдань стає важко сортувати.
**Як це вирішує OmniRoute:**
— Список завдань/фільтрування за станом/навиками з розбивкою на сторінки
- Деталізація метаданих завдань, подій і артефактів
- Кінцева точка скасування завдання та дія інтерфейсу користувача з підтвердженням
</details>
<details>
<summary><b>🌊 24. «Мені потрібні активні показники потоку для завантаження A2A» </b></summary>
Робочі процеси потокової передачі вимагають оперативного розуміння паралельності та живих з’єднань.
**Як це вирішує OmniRoute:**
— Лічильники активних потоків інтегровані в статус A2A
- Мітка часу останнього завдання та підрахунок стану
- Картки інформаційної панелі A2A для моніторингу операцій у реальному часі
</details>
<details>
<summary><b>🪪 25. «Мені потрібне стандартне виявлення агентів для клієнтів» </b></summary>
Зовнішнім клієнтам і оркестрантам потрібні машинозчитувані метадані для адаптації.
**Як це вирішує OmniRoute:**
- Картка агента розкрита на `/.well-known/agent.json`
- Можливості та навички, показані в інтерфейсі користувача користувача
- API стану A2A включає метадані виявлення для автоматизації
</details>
<details>
<summary><b>🧭 26. «Мені потрібна можливість виявлення протоколу в UX продукту» </b></summary>
Якщо користувачі не можуть виявити поверхні протоколу, якість впровадження та підтримки падає.
**Як це вирішує OmniRoute:**
— Записи бічної панелі для MCP і A2A
- Сторінка кінцевої точки Вкладка протоколів із швидким запуском і статусом
- Посилання з огляду на спеціальні інформаційні панелі керування
</details>
<details>
<summary><b>🧪 27. «Мені потрібна наскрізна перевірка протоколу з реальними клієнтами» </b></summary>
Пробних тестів недостатньо для перевірки сумісності протоколу перед випуском.
**Як це вирішує OmniRoute:**
- Комплект E2E, який завантажує програму та використовує реальний клієнтський транспорт MCP SDK
- Клієнт A2A перевіряє потоки виявлення, надсилання, потокової передачі, отримання та скасування
- Перехресна перевірка тверджень щодо аудиту MCP та API завдань A2A
</details>
<details>
<summary><b>📡 28. «Мені потрібна уніфікована можливість спостереження через усі інтерфейси» </b></summary>
Поділ спостережуваності за протоколом створює сліпі зони та довший MTTR.
**Як це вирішує OmniRoute:**
- Уніфіковані інформаційні панелі/журнали/аналітика в одному продукті
- Справність + аудит + телеметрія запитів на рівнях OpenAI, MCP і A2A
- Операційні API для статусу та автоматизації
</details>
<details>
<summary><b>💼 29. «Мені потрібне одне середовище виконання для проксі + інструментів + оркестровки агента» </b></summary>
Запуск багатьох окремих служб збільшує експлуатаційні витрати та частоту збоїв.
**Як це вирішує OmniRoute:**
- OpenAI-сумісний проксі, сервер MCP і сервер A2A в одному стеку
- Спільна автентифікація, стійкість, зберігання даних і можливість спостереження
- Послідовна модель політики на всіх поверхнях взаємодії
</details>
<details>
<summary><b>🚀 30. «Мені потрібно надсилати агентські робочі процеси без розповсюдження клею-коду» </b></summary>
Команди втрачають швидкість під час з’єднання кількох спеціальних служб і сценаріїв.
**Як це вирішує OmniRoute:**
- Уніфікована стратегія кінцевих точок для клієнтів і агентів
— Вбудовані інтерфейси керування протоколами та шляхи перевірки диму
- Основи, готові до виробництва (безпека, журналювання, стійкість, резервне копіювання)
</details>
### Приклади Playbooks
**Playbook A: Максимальна кількість платної підписки + дешеве резервне копіювання**
```txt
Combo: "maximize-claude"
1. cc/claude-opus-4-6
2. glm/glm-4.7
3. if/kimi-k2-thinking
Monthly cost: $20 + small backup spend
Outcome: higher quality, near-zero interruption
```
**Playbook B: стек кодування без витрат**
```txt
Combo: "free-forever"
1. gc/gemini-3-flash
2. if/kimi-k2-thinking
3. qw/qwen3-coder-plus
Monthly cost: $0
Outcome: stable free coding workflow
```
**Playbook C: резервний ланцюжок 24/7**
```txt
Combo: "always-on"
1. cc/claude-opus-4-6
2. cx/gpt-5.2-codex
3. glm/glm-4.7
4. minimax/MiniMax-M2.1
5. if/kimi-k2-thinking
Outcome: deep fallback depth for deadline-critical workloads
```
**Playbook D: Операції агента з MCP + A2A**
```txt
1) Start MCP transport (`omniroute --mcp`) for tool-driven operations
2) Run A2A tasks via `message/send` and `message/stream`
3) Observe via /dashboard/mcp and /dashboard/a2a
4) Control incidents with resilience profile + task cancellation
```
---
## ⚡ Швидкий старт
**1. Встановити глобально:**
@@ -251,7 +786,7 @@ docker compose --profile cli up -d
---
## 🖥️ Desktop App — Offline & Always-On
## 🖥️
> 🆕 **NEW!** OmniRoute is now available as a **native desktop application** for Windows, macOS, and Linux.
@@ -298,67 +833,6 @@ npm run electron:build:linux # Linux (.AppImage)
---
## 🎯 Випадки використання
### Випадок 1: «У мене є підписка на Claude Pro»
**Проблема:** Квота закінчується невикористаною, обмеження швидкості під час інтенсивного кодування
```
Combo: "maximize-claude"
1. cc/claude-opus-4-6 (use subscription fully)
2. glm/glm-4.7 (cheap backup when quota out)
3. if/kimi-k2-thinking (free emergency fallback)
Monthly cost: $20 (subscription) + ~$5 (backup) = $25 total
vs. $20 + hitting limits = frustration
```
### Випадок 2: "Я хочу нульову вартість"
**Проблема:** не можу дозволити собі підписку, потрібне надійне кодування ШІ
```
Combo: "free-forever"
1. gc/gemini-3-flash (180K free/month)
2. if/kimi-k2-thinking (unlimited free)
3. qw/qwen3-coder-plus (unlimited free)
Monthly cost: $0
Quality: Production-ready models
```
### Випадок 3: «Мені потрібне кодування 24/7, без перерв»
**Проблема:** Дедлайни, не можу дозволити собі простою
```
Combo: "always-on"
1. cc/claude-opus-4-6 (best quality)
2. cx/gpt-5.2-codex (second subscription)
3. glm/glm-4.7 (cheap, resets daily)
4. minimax/MiniMax-M2.1 (cheapest, 5h reset)
5. if/kimi-k2-thinking (free unlimited)
Result: 5 layers of fallback = zero downtime
```
### Випадок 4: «Я хочу БЕЗКОШТОВНОГО ШІ в OpenClaw»
**Проблема:** потрібен помічник штучного інтелекту в програмах для обміну повідомленнями, повністю безкоштовний
```
Combo: "openclaw-free"
1. if/glm-4.7 (unlimited free)
2. if/minimax-m2.1 (unlimited free)
3. if/kimi-k2-thinking (unlimited free)
Monthly cost: $0
Access via: WhatsApp, Telegram, Slack, Discord, iMessage, Signal...
```
---
## 💡 Основні характеристики
### 🧠 Основна маршрутизація та інтелект
@@ -374,6 +848,8 @@ Access via: WhatsApp, Telegram, Slack, Discord, iMessage, Signal...
| 🧩 **Користувацькі моделі** | Додайте будь-який ідентифікатор моделі до будь-якого постачальника |
| 🌐 **Wildcard Router** | Динамічно направляйте шаблони `provider/*` до будь-якого постачальника |
| 🧠 **Мислення про бюджет** | Наскрізний, автоматичний, настроюваний і адаптивний режими для моделей міркування |
| 🔀 **Model Aliases** | Auto-forward deprecated model IDs to current replacements (built-in + custom) |
| ⚡ **Background Degradation** | Auto-route background tasks (titles, summaries) to cheaper models |
| 💬 **Швидке впровадження системи** | Глобальне системне підказка застосовується до всіх запитів |
| 📄 **API відповідей** | Повна підтримка OpenAI Responses API (`/v1/responses`) для Codex |
@@ -399,6 +875,8 @@ Access via: WhatsApp, Telegram, Slack, Discord, iMessage, Signal...
| 🔒 **Підробка відбитків пальців TLS** | Обійти виявлення ботів на основі TLS через wreq-js |
| 🌐 **IP-фільтрація** | Білий/чорний список для керування доступом API |
| 📊 **Редаговані ліміти ставок** | Конфігурація RPM, мінімальний проміжок і максимальна одночасність на рівні системи |
| 💾 **Rate Limit Persistence** | Learned limits survive restarts via SQLite with 60s debounce + 24h staleness |
| 🔄 **Token Refresh Resilience** | Per-provider circuit breaker (5 fails→30min) + 30s timeout per attempt |
| 🛡 **API Endpoint Protection** | Аутентифікація + блокування постачальника для кінцевої точки `/models` |
| 🔒 **Видимість проксі** | Кольорові значки: 🟢 глобальний, 🟡 постачальник, 🔵 кожне підключення з відображенням IP |
| 🌐 **3-рівнева конфігурація проксі** | Налаштуйте проксі-сервери на глобальному рівні, на рівні кожного постачальника чи кожного підключення |
@@ -517,6 +995,27 @@ OmniRoute містить потужний вбудований Translator Playgr
</details>
## 🧪 Оцінки (Evals)
OmniRoute містить вбудовану систему оцінювання для перевірки якості відповіді LLM на відповідність золотому набору. Доступ до нього через **Аналітика → Оцінки** на інформаційній панелі.
### Вбудований Золотий набір
Попередньо завантажений "Золотий набір OmniRoute" містить 10 тестів, які охоплюють:
- Привітання, математика, географія, генерація коду
- Відповідність формату JSON, переклад, розмітка
- Відмова безпеки (шкідливий контент), підрахунок, булева логіка
### Стратегії оцінювання
| Стратегія | Опис | Приклад |
| ---------- | -------------------------------------------------------------- | -------------------------------- |
| `exact` | Вихідні дані повинні точно відповідати | `"4"` |
| `contains` | Вихідні дані повинні містити підрядок (незалежно від регістру) | `"Paris"` |
| `regex` | Вихідні дані мають відповідати шаблону регулярного виразу | `"1.*2.*3"` |
| `custom` | Спеціальна функція JS повертає true/false | `(output) => output.length > 10` |
---
## 📖 Посібник із налаштування
@@ -799,104 +1298,66 @@ Settings → API Configuration:
---
## 📊 Доступні моделі
## 🐛 Усунення несправностей
<details>
<summary><b>Переглянути всі доступні моделі</b></summary>
<summary><b>Натисніть, щоб розгорнути посібник з усунення несправностей</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`
— Вичерпана квота на підписку → Повернення до GLM/MiniMax
**Gemini CLI (`gc/`)** - БЕЗКОШТОВНО:
- Додати комбо: `cc/claude-opus-4-6 → glm/glm-4.7 → if/kimi-k2-thinking`
- `gc/gemini-3-flash-preview`
- `gc/gemini-2.5-pro`
**Термін дії маркера OAuth минув**
**Копілот GitHub (`gh/`)**:
— Автоматично оновлено OmniRoute
- `gh/gpt-5`
- `gh/claude-4.5-sonnet`
- Якщо проблеми не зникають: Інформаційна панель → Постачальник → Повторне підключення
**NVIDIA NIM (`nvidia/`)** - БЕЗКОШТОВНІ кредити:
**Високі витрати**
- `nvidia/llama-3.3-70b-instruct`
- `nvidia/mistral-7b-instruct`
- більше 50 моделей на [build.nvidia.com](https://build.nvidia.com)
- Перевірте статистику використання в Інформаційній панелі → Витрати
- Переключіть основну модель на GLM/MiniMax
- Використовуйте безкоштовний рівень (Gemini CLI, iFlow) для некритичних завдань
**GLM (`glm/`)** - 0,6 $/1 млн:
**Інформаційна панель відкривається через неправильний порт**
- `glm/glm-4.7`
- Встановити `PORT=20128` та `NEXT_PUBLIC_BASE_URL=http://localhost:20128`
**MiniMax (`minimax/`)** - $0,2/1 млн.:
**Помилки хмарної синхронізації**
- `minimax/MiniMax-M2.1`
- Переконайтеся, що `BASE_URL` вказує на ваш запущений екземпляр
- Перевірте `CLOUD_URL` вказує на очікувану кінцеву точку хмари
- Зберігайте значення `NEXT_PUBLIC_*` у відповідності зі значеннями на стороні сервера
**iFlow (`if/`)** - БЕЗКОШТОВНО:
**Перший вхід не працює**
- `if/kimi-k2-thinking`
- `if/qwen3-coder-plus`
- `if/deepseek-r1`
- `if/glm-4.7`
- `if/minimax-m2`
- Перевірте `INITIAL_PASSWORD` в `.env`
- Якщо не встановлено, резервний пароль `123456`
**Qwen (`qw/`)** - БЕЗКОШТОВНО:
**Немає журналів запитів**
- `qw/qwen3-coder-plus`
- `qw/qwen3-coder-flash`
- Установіть `ENABLE_REQUEST_LOGS=true` в `.env`
**Kiro (`kr/`)** - БЕЗКОШТОВНО:
**Тест з’єднання показує «Недійсне» для OpenAI-сумісних постачальників**
- `kr/claude-sonnet-4.5`
- `kr/claude-haiku-4.5`
- Багато постачальників не розкривають кінцеву точку `/models`
- OmniRoute v1.0.6+ включає резервну перевірку через завершення чату
- Переконайтеся, що базова URL-адреса містить суфікс `/v1`
**OpenRouter (`or/`)** - 100+ моделей:
- `or/anthropic/claude-4-sonnet`
- `or/google/gemini-2.5-pro`
- Будь-яка модель від [openrouter.ai/models](https://openrouter.ai/models)
</details>
---
## 🧪 Оцінки (Evals)
OmniRoute містить вбудовану систему оцінювання для перевірки якості відповіді LLM на відповідність золотому набору. Доступ до нього через **Аналітика → Оцінки** на інформаційній панелі.
### Вбудований Золотий набір
Попередньо завантажений "Золотий набір OmniRoute" містить 10 тестів, які охоплюють:
- Привітання, математика, географія, генерація коду
- Відповідність формату JSON, переклад, розмітка
- Відмова безпеки (шкідливий контент), підрахунок, булева логіка
### Стратегії оцінювання
| Стратегія | Опис | Приклад |
| ---------- | -------------------------------------------------------------- | -------------------------------- |
| `exact` | Вихідні дані повинні точно відповідати | `"4"` |
| `contains` | Вихідні дані повинні містити підрядок (незалежно від регістру) | `"Paris"` |
| `regex` | Вихідні дані мають відповідати шаблону регулярного виразу | `"1.*2.*3"` |
| `custom` | Спеціальна функція JS повертає true/false | `(output) => output.length > 10` |
---
## 🔐 OAuth em Servidor Remoto (віддалене налаштування OAuth)
### 🔐 OAuth
<a name="oauth-em-servidor-remoto"></a>
> **⚠️ ВАЖЛИВО для використання OmniRoute у віддаленому VPS/Docker/сервері**
### Чи OAuth для Antigravity / Gemini CLI не підтримує віддалені сервери?
### OAuth
Провідники **Antigravity** і **Gemini CLI** використовують **Google OAuth 2.0** для автентифікації. Google вимагає, щоб `redirect_uri` не використовував fluxo OAuth, який **exatamente** має URI перед кадастрадами без додатка Google Cloud Console.
@@ -981,66 +1442,11 @@ Se não quiser criar credenciais próprias agora, ainda é possível usar o flux
> Este workaround funciona porque o código de autorização na URL é válido independente do redirect ter carregado ou não.
---
## 🐛 Усунення несправностей
<details>
<summary><b>Натисніть, щоб розгорнути посібник з усунення несправностей</b></summary>
**"Мовна модель не надавала повідомлень"**
- Квота постачальника вичерпана → Перевірте систему відстеження квот на інформаційній панелі
- Рішення: скористайтеся комбінованим альтернативним варіантом або перейдіть на дешевший рівень
**Обмеження швидкості**
— Вичерпана квота на підписку → Повернення до GLM/MiniMax
- Додати комбо: `cc/claude-opus-4-6 → glm/glm-4.7 → if/kimi-k2-thinking`
**Термін дії маркера OAuth минув**
— Автоматично оновлено OmniRoute
- Якщо проблеми не зникають: Інформаційна панель → Постачальник → Повторне підключення
**Високі витрати**
- Перевірте статистику використання в Інформаційній панелі → Витрати
- Переключіть основну модель на GLM/MiniMax
- Використовуйте безкоштовний рівень (Gemini CLI, iFlow) для некритичних завдань
**Інформаційна панель відкривається через неправильний порт**
- Встановити `PORT=20128` та `NEXT_PUBLIC_BASE_URL=http://localhost:20128`
**Помилки хмарної синхронізації**
- Переконайтеся, що `BASE_URL` вказує на ваш запущений екземпляр
- Перевірте `CLOUD_URL` вказує на очікувану кінцеву точку хмари
- Зберігайте значення `NEXT_PUBLIC_*` у відповідності зі значеннями на стороні сервера
**Перший вхід не працює**
- Перевірте `INITIAL_PASSWORD` в `.env`
- Якщо не встановлено, резервний пароль `123456`
**Немає журналів запитів**
- Установіть `ENABLE_REQUEST_LOGS=true` в `.env`
**Тест з’єднання показує «Недійсне» для OpenAI-сумісних постачальників**
- Багато постачальників не розкривають кінцеву точку `/models`
- OmniRoute v1.0.6+ включає резервну перевірку через завершення чату
- Переконайтеся, що базова URL-адреса містить суфікс `/v1`
</details>
---
## 🛠️ Tech Stack
## 🛠️
- **Серед виконання**: Node.js 1822 LTS (⚠️ Node.js 24+ **не підтримується** — рідні двійкові файли `better-sqlite3` несумісні)
- **Мова**: TypeScript 5.9 — **100% TypeScript** для `src/` та `open-sse/` (версія 1.0.6)
@@ -1092,7 +1498,7 @@ Se não quiser criar credenciais próprias agora, ainda é possível usar o flux
---
## 🗺️ Дорожня карта
## 🗺️
OmniRoute має **заплановано понад 210 функцій** на кількох етапах розробки. Ось ключові області:
@@ -1117,18 +1523,6 @@ OmniRoute має **заплановано понад 210 функцій** на
---
## 📧 Підтримка
> 💬 **Приєднуйтесь до нашої спільноти!** [WhatsApp Group](https://chat.whatsapp.com/JI7cDQ1GyaiDHhVBpLxf8b?mode=gi_t) — отримуйте допомогу, діліться порадами та будьте в курсі подій.
- **Веб-сайт**: [omniroute.online](https://omniroute.online)
- **GitHub**: [github.com/diegosouzapw/OmniRoute](https://github.com/diegosouzapw/OmniRoute)
- **Проблеми**: [github.com/diegosouzapw/OmniRoute/issues](https://github.com/diegosouzapw/OmniRoute/issues)
- **WhatsApp**: [Community Group](https://chat.whatsapp.com/JI7cDQ1GyaiDHhVBpLxf8b?mode=gi_t)
- **Оригінальний проект**: [9router by decolua](https://github.com/decolua/9router)
---
## 👥 Автори
[![Contributors](https://contrib.rocks/image?repo=diegosouzapw/OmniRoute&max=100&columns=20&anon=1)](https://github.com/diegosouzapw/OmniRoute/graphs/contributors)
@@ -1178,85 +1572,6 @@ gh release create v1.0.6 --title "v1.0.6" --generate-notes
---
---
## 🇧🇷 OmniRoute — Gateway de IA Gratuito
<a name="-omniroute--gateway-de-ia-gratuito"></a>
### Nunca pare de codar. Roteamento inteligente para **modelos de IA GRATUITOS e de baixo custo** com reserve automático.
_Універсальний проксі-сервер API — кінцева точка, 36+ постачальників, нуль простоїв._
### 🌐 Internacionalização (i18n)
Інформаційна панель OmniRoute підтримує **багато ідіом**. Актуально доступні:
| Ідіома | Código | Статус |
| ----------------------- | ------- | -------- |
| 🇺🇸 англійська | `en` | ✅ Повне |
| 🇧🇷 Português (Бразилія) | `pt-BR` | ✅ Повне |
**Параметр троакар або ідіома:** Натисніть без вибору ідіоми (🇺🇸 EN) без заголовка на інформаційній панелі → вибір ідіоми.
**Para adicionar um nova idioma:**
1. Викличте `src/i18n/messages/{codigo}.json` на основі `en.json`
2. Додайте код `src/i18n/config.ts``LOCALES` і `LANGUAGES`
3. Reinicie або сервер
### ⚡ Início Rápido
```bash
# Instalar via npm
npx omniroute@latest
# Ou rodar do código-fonte
cp .env.example .env
npm install
PORT=20128 NEXT_PUBLIC_BASE_URL=http://localhost:20128 npm run dev
```
### 🐳 Докер
```bash
docker run -d --name omniroute -p 20128:20128 diegosouzapw/omniroute:latest
```
### 🔑 Funcionalidades Principais
- **36+ провідників IA** — Claude, GPT, Gemini, Llama, Qwen, DeepSeek та ін.
- **Roteamento inteligente** — Запасні автоматичні постачальники
- **Tradução de formato** — OpenAI ↔ Claude ↔ Gemini automaticamente
- **Multi-conta** — Múltiplas contas por provedor com seleção inteligente
- **Cache semântico** — Зменшити налаштування та затримку
- **OAuth automático** — автоматичне оновлення токенів
- **Combos personalizados** — 6 estratégias de roteamento
- **Помна панель приладів** — Моніторинг, журнали, аналізи, конфігурації
- **Інструменти CLI** — налаштуйте Claude Code, Codex, Cursor, Cline за допомогою кліка
- **100% TypeScript** — Código limpo e tipado
### 📖 Documentação
| Documento | Опис |
| ----------------------------------------------- | ------------------------------------- |
| [Guia do Usuário](docs/USER_GUIDE.md) | Провідори, комбо, CLI, розгортання |
| [Referência da API](docs/API_REFERENCE.md) | Усі кінцеві точки з прикладами |
| [Solução de Problemas](docs/TROUBLESHOOTING.md) | Problemas comuns e soluções |
| [Arquitetura](docs/ARCHITECTURE.md) | Arquitetura e internos do sistema |
| [Contribuição](CONTRIBUTING.md) | Setup de desenvolvimento e guidelines |
| [Deploy em VM](docs/VM_DEPLOYMENT_GUIDE.md) | Повна версія: VM + nginx + Cloudflare |
### 📧 Підтримуйте
> 💬 **Entre para a comunidade!** [Grupo WhatsApp](https://chat.whatsapp.com/JI7cDQ1GyaiDHhVBpLxf8b?mode=gi_t) — Тир dúvidas, compartilhe dicas e fique atualizado.
- **Веб-сайт**: [omniroute.online](https://omniroute.online)
- **GitHub**: [github.com/diegosouzapw/OmniRoute](https://github.com/diegosouzapw/OmniRoute)
- **Проблеми**: [github.com/diegosouzapw/OmniRoute/issues](https://github.com/diegosouzapw/OmniRoute/issues)
---
<div align="center">
<sub>Створено з ❤️ для розробників, які працюють у режимі 24/7</sub>
<br/>

View File

@@ -3,8 +3,6 @@
# 🚀 OmniRoute — Cổng AI miễn phí
🌐 **[English](#-omniroute--the-free-ai-gateway)** | **[Português (BR)](#-omniroute--gateway-de-ia-gratuito)**
### Không bao giờ ngừng viết mã. Định tuyến thông minh tới **Mô hình AI MIỄN PHÍ và chi phí thấp** với tính năng dự phòng tự động.
_Proxy API phổ quát của bạn — một điểm cuối, hơn 36 nhà cung cấp, không có thời gian ngừng hoạt động._
@@ -112,6 +110,35 @@ _Kết nối mọi công cụ IDE hoặc CLI được hỗ trợ bởi AI thông
---
## 🖼️
<div align="center">
<img src="./docs/screenshots/MainOmniRoute.png" alt="OmniRoute" width="800"/>
</div>
---
## 📸
<details>
<summary><b>...</b></summary>
| # | # |
| ----- | ---------------------------------------- |
| **1** | ![1](docs/screenshots/01-providers.png) |
| **2** | ![2](docs/screenshots/02-combos.png) |
| **3** | ![3](docs/screenshots/03-analytics.png) |
| **4** | ![4](docs/screenshots/04-health.png) |
| **5** | ![5](docs/screenshots/05-translator.png) |
| **6** | ![6](docs/screenshots/06-settings.png) |
| **7** | ![7](docs/screenshots/07-cli-tools.png) |
| **8** | ![8](docs/screenshots/08-usage.png) |
| **9** | ![9](docs/screenshots/09-endpoint.png) |
</details>
---
## 🤔 Tại sao lại là OmniRoute?
**Ngưng lãng phí tiền và đạt đến giới hạn:**
@@ -130,6 +157,18 @@ _Kết nối mọi công cụ IDE hoặc CLI được hỗ trợ bởi AI thông
---
## 📧 Hỗ trợ
> 💬 **Tham gia cộng đồng của chúng tôi!** [WhatsApp Group](https://chat.whatsapp.com/JI7cDQ1GyaiDHhVBpLxf8b?mode=gi_t) — Nhận trợ giúp, chia sẻ mẹo và luôn cập nhật.
- **Trang web**: [omniroute.online](https://omniroute.online)
- **GitHub**: [github.com/diegosouzapw/OmniRoute](https://github.com/diegosouzapw/OmniRoute)
- **Vấn đề**: [github.com/diegosouzapw/OmniRoute/issues](https://github.com/diegosouzapw/OmniRoute/issues)
- **WhatsApp**: [Community Group](https://chat.whatsapp.com/JI7cDQ1GyaiDHhVBpLxf8b?mode=gi_t)
- **Dự án gốc**: [9router by decolua](https://github.com/decolua/9router)
---
## 🔄 Nó hoạt động như thế nào
```
@@ -159,6 +198,498 @@ Result: Never stop coding, minimal cost
---
## 🎯 OmniRoute giải quyết được gì — 30 điểm khó thực sự và trường hợp sử dụng
> **Mọi nhà phát triển sử dụng công cụ AI đều phải đối mặt với những vấn đề này hàng ngày.** OmniRoute được xây dựng để giải quyết tất cả — từ chi phí vượt mức cho đến chặn khu vực, từ luồng OAuth bị hỏng đến hoạt động giao thức và khả năng quan sát của doanh nghiệp.
<details>
<summary><b>💸 1. "Tôi trả tiền cho một thuê bao đắt tiền nhưng vẫn bị gián đoạn bởi các giới hạn"</b></summary>
Các nhà phát triển trả 20200 USD/tháng cho Claude Pro, Codex Pro hoặc GitHub Copilot. Ngay cả khi trả tiền, hạn ngạch vẫn có mức trần - 5 giờ sử dụng, giới hạn hàng tuần hoặc giới hạn tốc độ mỗi phút. Giữa phiên mã hóa, nhà cung cấp ngừng phản hồi và nhà phát triển mất đi dòng chảy và năng suất.
**Cách OmniRoute giải quyết vấn đề này:**
- **Dự phòng 4 tầng thông minh** — Nếu hết hạn ngạch đăng ký, tự động chuyển hướng đến Khóa API → Giá rẻ → Miễn phí mà không cần can thiệp thủ công
- **Theo dõi hạn ngạch theo thời gian thực** — Hiển thị mức tiêu thụ mã thông báo trong thời gian thực với tính năng đếm ngược đặt lại (5 giờ, hàng ngày, hàng tuần)
- **Hỗ trợ nhiều tài khoản** — Nhiều tài khoản cho mỗi nhà cung cấp với tính năng tự động quay vòng — khi hết một tài khoản, hãy chuyển sang tài khoản tiếp theo
- **Combo tùy chỉnh** — Chuỗi dự phòng có thể tùy chỉnh với 6 chiến lược cân bằng (điền trước, quay vòng, P2C, ngẫu nhiên, ít sử dụng nhất, tối ưu hóa chi phí)
- **Hạn ngạch kinh doanh Codex** — Giám sát hạn ngạch không gian làm việc của Doanh nghiệp/Nhóm trực tiếp trong bảng điều khiển
</details>
<details>
<summary><b>🔌 2. "Tôi cần sử dụng nhiều nhà cung cấp nhưng mỗi nhà cung cấp có một API khác nhau"</b></summary>
OpenAI sử dụng một định dạng, Claude (Anthropic) sử dụng một định dạng khác, Gemini lại sử dụng một định dạng khác. Nếu nhà phát triển muốn thử nghiệm các mô hình từ các nhà cung cấp khác nhau hoặc dự phòng giữa các nhà cung cấp đó, họ cần phải định cấu hình lại SDK, thay đổi điểm cuối, xử lý các định dạng không tương thích. Các nhà cung cấp tùy chỉnh (FriendLI, NIM) có các điểm cuối mô hình không chuẩn.
**Cách OmniRoute giải quyết vấn đề này:**
- **Điểm cuối hợp nhất** — Một `http://localhost:20128/v1` duy nhất đóng vai trò là proxy cho tất cả hơn 36 nhà cung cấp
- **Dịch định dạng** — Tự động và minh bạch: OpenAI ↔ Claude ↔ Gemini ↔ API phản hồi
- **Sạch hóa phản hồi** — Loại bỏ các trường không chuẩn (`x_groq`, `usage_breakdown`, `service_tier`) phá vỡ OpenAI SDK v1.83+
- **Chuẩn hóa vai trò** — Chuyển đổi `developer``system` cho các nhà cung cấp không thuộc OpenAI; `system``user` cho GLM/ERNIE
- **Think Tag Extraction** — Trích xuất các khối `<think>` từ các mô hình như DeepSeek R1 thành `reasoning_content` được tiêu chuẩn hóa
- **Đầu ra có cấu trúc cho Gemini** — `json_schema``responseMimeType`/`responseSchema` chuyển đổi tự động
- **`stream` mặc định là `false`** — Phù hợp với thông số OpenAI, tránh SSE không mong muốn trong SDK Python/Rust/Go
</details>
<details>
<summary><b>🌐 3. "Nhà cung cấp AI của tôi chặn khu vực/quốc gia của tôi"</b></summary>
Các nhà cung cấp như OpenAI/Codex chặn quyền truy cập từ các khu vực địa lý nhất định. Người dùng gặp phải các lỗi như `unsupported_country_region_territory` trong quá trình kết nối OAuth và API. Điều này đặc biệt gây khó chịu cho các nhà phát triển từ các nước đang phát triển.
**Cách OmniRoute giải quyết vấn đề này:**
- **Cấu hình proxy 3 cấp** — Proxy có thể định cấu hình ở 3 cấp độ: toàn cầu (tất cả lưu lượng truy cập), mỗi nhà cung cấp (chỉ một nhà cung cấp) và mỗi kết nối/khóa
- **Huy hiệu proxy được mã hóa màu** — Chỉ báo trực quan: 🟢 proxy toàn cầu, 🟡 proxy nhà cung cấp, 🔵 proxy kết nối, luôn hiển thị IP
- **Trao đổi mã thông báo OAuth thông qua proxy** — Luồng OAuth cũng đi qua proxy, giải quyết `unsupported_country_region_territory`
- **Kiểm tra kết nối qua Proxy** — Kiểm tra kết nối sử dụng proxy đã định cấu hình (không cần bỏ qua trực tiếp nữa)
- **Hỗ trợ SOCKS5** — Hỗ trợ proxy SOCKS5 đầy đủ cho định tuyến đi
- **Giả mạo dấu vân tay TLS** — Dấu vân tay TLS giống trình duyệt thông qua `wreq-js` để vượt qua khả năng phát hiện bot
</details>
<details>
<summary><b>🆓 4. "Tôi muốn sử dụng AI để viết mã nhưng tôi không có tiền"</b></summary>
Không phải ai cũng có thể trả 20200 USD/tháng để đăng ký AI. Sinh viên, nhà phát triển từ các quốc gia mới nổi, những người có sở thích và người làm nghề tự do cần được tiếp cận với các mô hình chất lượng với chi phí bằng 0.
**Cách OmniRoute giải quyết vấn đề này:**
- **Tích hợp sẵn nhà cung cấp cấp miễn phí** — Hỗ trợ riêng cho các nhà cung cấp miễn phí 100%: iFlow (8 mẫu không giới hạn), Qwen (3 mẫu không giới hạn), Kiro (Claude miễn phí), Gemini CLI (miễn phí 180K/tháng)
- **Combo chỉ miễn phí** — Chuỗi `gc/gemini-3-flash → if/kimi-k2-thinking → qw/qwen3-coder-plus` = $0/tháng mà không có thời gian ngừng hoạt động
- **Tín dụng miễn phí NVIDIA NIM** — Tích hợp 1000 tín dụng miễn phí
- **Chiến lược tối ưu hóa chi phí** — Chiến lược định tuyến tự động chọn nhà cung cấp sẵn có rẻ nhất
</details>
<details>
<summary><b>🔒 5. "Tôi cần bảo vệ cổng AI của mình khỏi bị truy cập trái phép"</b></summary>
Khi đưa cổng AI vào mạng (LAN, VPS, Docker), bất kỳ ai có địa chỉ đều có thể sử dụng mã thông báo/hạn ngạch của nhà phát triển. Nếu không có biện pháp bảo vệ, các API dễ bị lạm dụng, chèn ép và lạm dụng.
**Cách OmniRoute giải quyết vấn đề này:**
- **Quản lý khóa API** — Tạo, xoay vòng và xác định phạm vi cho mỗi nhà cung cấp bằng trang `/dashboard/api-manager` chuyên dụng
- **Quyền cấp mô hình** — Hạn chế khóa API đối với các mô hình cụ thể (`openai/*`, mẫu ký tự đại diện), với nút chuyển đổi Cho phép tất cả/Hạn chế
- **Bảo vệ điểm cuối API** — Yêu cầu khóa cho `/v1/models` và chặn các nhà cung cấp cụ thể khỏi danh sách
- **Auth Guard + CSRF Protection** — Tất cả các tuyến bảng điều khiển được bảo vệ bằng phần mềm trung gian `withAuth` + mã thông báo CSRF
- **Giới hạn tốc độ** — Giới hạn tốc độ trên mỗi IP với các cửa sổ có thể định cấu hình
- **Lọc IP** — Danh sách cho phép/danh sách chặn để kiểm soát truy cập
- **Prompt Tiêm Guard** — Khử trùng các mẫu nhắc nhở độc hại
- **Mã hóa AES-256-GCM** — Thông tin xác thực được mã hóa ở trạng thái lưu trữ
</details>
<details>
<summary><b>🛑 6. "Nhà cung cấp của tôi ngừng hoạt động và tôi mất luồng mã hóa"</b></summary>
Các nhà cung cấp AI có thể trở nên không ổn định, trả về lỗi 5xx hoặc đạt giới hạn tốc độ tạm thời. Nếu một nhà phát triển phụ thuộc vào một nhà cung cấp duy nhất thì họ sẽ bị gián đoạn. Nếu không có bộ ngắt mạch, việc thử lại nhiều lần có thể làm hỏng ứng dụng.
**Cách OmniRoute giải quyết vấn đề này:**
- **Bộ ngắt mạch cho mỗi nhà cung cấp** — Tự động mở/đóng với ngưỡng có thể định cấu hình và thời gian hồi chiêu (Đóng/Mở/Nửa mở)
- **Thời gian chờ theo cấp số nhân** — Độ trễ thử lại lũy tiến
- **Bầy chống sấm sét** — Mutex + bảo vệ semaphore chống lại các cơn bão thử lại đồng thời
- **Chuỗi dự phòng kết hợp** — Nếu nhà cung cấp chính không thành công, nó sẽ tự động rơi qua chuỗi mà không cần can thiệp
- **Combo Circuit Breaker** — Tự động vô hiệu hóa các nhà cung cấp bị lỗi trong chuỗi kết hợp
| 🎯 **Endpoint-Aware Models** | Custom models declare supported endpoints + API format |
- **Bảng thông tin sức khỏe** — Giám sát thời gian hoạt động, trạng thái ngắt mạch, khóa, số liệu thống kê bộ nhớ đệm, độ trễ p50/p95/p99
</details>
<details>
<summary><b>🔧 7. "Cấu hình từng công cụ AI thật tẻ nhạt và lặp đi lặp lại"</b></summary>
Nhà phát triển sử dụng Cursor, Claude Code, Codex CLI, OpenClaw, Gemini CLI, Kilo Code... Mỗi công cụ cần một cấu hình khác nhau (điểm cuối API, khóa, mô hình). Việc cấu hình lại khi chuyển đổi nhà cung cấp hoặc mô hình là một sự lãng phí thời gian.
**Cách OmniRoute giải quyết vấn đề này:**
- **Bảng điều khiển công cụ CLI** — Trang chuyên dụng với thiết lập bằng một cú nhấp chuột cho Claude Code, Codex CLI, OpenClaw, Kilo Code, AntiGravity, Cline
- **Trình tạo cấu hình GitHub Copilot** — Tạo `chatLanguageModels.json` cho Mã VS với lựa chọn mô hình hàng loạt
- **Trình hướng dẫn tích hợp** — Thiết lập 4 bước có hướng dẫn cho người dùng lần đầu
- **Một điểm cuối, tất cả các kiểu máy** — Định cấu hình `http://localhost:20128/v1` một lần, truy cập hơn 36 nhà cung cấp
</details>
<details>
<summary><b>🔑 8. "Quản lý mã thông báo OAuth từ nhiều nhà cung cấp là địa ngục"</b></summary>
Claude Code, Codex, Gemini CLI, Copilot — tất cả đều sử dụng OAuth 2.0 với các mã thông báo sắp hết hạn. Các nhà phát triển cần liên tục xác thực lại, xử lý `client_secret is missing`, `redirect_uri_mismatch` và các lỗi trên máy chủ từ xa. OAuth trên LAN/VPS đặc biệt có vấn đề.
**Cách OmniRoute giải quyết vấn đề này:**
- **Tự động làm mới mã thông báo** — Làm mới mã thông báo OAuth ở chế độ nền trước khi hết hạn
- **Tích hợp OAuth 2.0 (PKCE)** — Luồng tự động cho Claude Code, Codex, Gemini CLI, Copilot, Kiro, Qwen, iFlow
- **OAuth nhiều tài khoản** — Nhiều tài khoản cho mỗi nhà cung cấp thông qua trích xuất mã thông báo JWT/ID
- **OAuth LAN/Remote Fix** — Phát hiện IP riêng cho `redirect_uri` + chế độ URL thủ công cho máy chủ từ xa
- **OAuth đằng sau Nginx** — Sử dụng `window.location.origin` để tương thích với proxy ngược
- **Hướng dẫn OAuth từ xa** — Hướng dẫn từng bước về thông tin đăng nhập Google Cloud trên VPS/Docker
</details>
<details>
<summary><b>📊 9. "Tôi không biết mình đang chi bao nhiêu hay ở đâu"</b></summary>
Các nhà phát triển sử dụng nhiều nhà cung cấp trả phí nhưng không có quan điểm thống nhất về chi tiêu. Mỗi nhà cung cấp có trang tổng quan thanh toán riêng nhưng không có chế độ xem tổng hợp. Chi phí bất ngờ có thể chồng chất.
**Cách OmniRoute giải quyết vấn đề này:**
- **Bảng thông tin phân tích chi phí** — Theo dõi chi phí mỗi mã thông báo và quản lý ngân sách cho mỗi nhà cung cấp
- **Giới hạn ngân sách cho mỗi cấp** — Mức chi tiêu trần cho mỗi cấp kích hoạt dự phòng tự động
- **Cấu hình định giá theo mẫu** — Giá có thể định cấu hình cho mỗi mẫu
- **Thống kê sử dụng trên mỗi khóa API** — Số lượng yêu cầu và dấu thời gian được sử dụng lần cuối trên mỗi khóa
- **Bảng thông tin phân tích** — Thẻ thống kê, biểu đồ sử dụng mô hình, bảng nhà cung cấp với tỷ lệ thành công và độ trễ
</details>
<details>
<summary><b>🐛 10. "Tôi không thể chẩn đoán lỗi và sự cố trong cuộc gọi AI"</b></summary>
Khi cuộc gọi không thành công, nhà phát triển không biết liệu đó có phải là giới hạn tốc độ, mã thông báo đã hết hạn, sai định dạng hay lỗi nhà cung cấp hay không. Nhật ký bị phân mảnh trên các thiết bị đầu cuối khác nhau. Nếu không có khả năng quan sát được thì việc gỡ lỗi chỉ là thử và sai.
**Cách OmniRoute giải quyết vấn đề này:**
- **Bảng điều khiển nhật ký hợp nhất** — 4 tab: Nhật ký yêu cầu, Nhật ký proxy, Nhật ký kiểm tra, Bảng điều khiển
- **Trình xem nhật ký bảng điều khiển** — Trình xem kiểu thiết bị đầu cuối thời gian thực với các cấp độ được mã hóa màu, tự động cuộn, tìm kiếm, lọc
- **Nhật ký proxy SQLite** — Nhật ký liên tục vẫn tồn tại khi máy chủ khởi động lại
- **Sân chơi dịch thuật** — 4 chế độ gỡ lỗi: Sân chơi (dịch định dạng), Trình kiểm tra trò chuyện (khứ hồi), Bàn thử nghiệm (hàng loạt), Giám sát trực tiếp (thời gian thực)
- **Yêu cầu đo từ xa** — độ trễ p50/p95/p99 + truy tìm X-Request-Id
- **Ghi nhật ký dựa trên tệp bằng xoay vòng** — Trình chặn chặn bảng điều khiển ghi lại mọi thứ vào nhật ký JSON bằng cách xoay vòng dựa trên kích thước
</details>
<details>
<summary><b>🏗️ 11. "Việc triển khai và bảo trì cổng rất phức tạp"</b></summary>
Việc cài đặt, định cấu hình và duy trì proxy AI trên các môi trường khác nhau (cục bộ, VPS, Docker, đám mây) tốn nhiều công sức. Các vấn đề như đường dẫn được mã hóa cứng, `EACCES` trên thư mục, xung đột cổng và các bản dựng đa nền tảng sẽ gây thêm rắc rối.
**Cách OmniRoute giải quyết vấn đề này:**
- **npm cài đặt toàn cầu** — `npm install -g omniroute && omniroute` — đã xong
- **Docker Đa nền tảng** — AMD64 + ARM64 gốc (Apple Silicon, AWS Graviton, Raspberry Pi)
- **Hồ sơ soạn thảo Docker** — `base` (không có công cụ CLI) và `cli` (với Claude Code, Codex, OpenClaw)
- **Ứng dụng máy tính để bàn điện tử** — Ứng dụng gốc dành cho Windows/macOS/Linux với khay hệ thống, tự động khởi động, chế độ ngoại tuyến
- **Chế độ chia cổng** — API và Bảng điều khiển trên các cổng riêng biệt cho các tình huống nâng cao (proxy ngược, mạng vùng chứa)
- **Cloud Sync** — Đồng bộ hóa cấu hình giữa các thiết bị thông qua Cloudflare Workers
- **Sao lưu DB** — Tự động sao lưu, khôi phục, xuất và nhập tất cả cài đặt
</details>
<details>
<summary><b>🌍 12. "Giao diện chỉ có tiếng Anh và nhóm của tôi không nói được tiếng Anh"</b></summary>
Các đội ở các quốc gia không nói tiếng Anh, đặc biệt là ở Châu Mỹ Latinh, Châu Á và Châu Âu, gặp khó khăn với giao diện chỉ có tiếng Anh. Rào cản ngôn ngữ làm giảm khả năng tiếp nhận và tăng lỗi cấu hình.
**Cách OmniRoute giải quyết vấn đề này:**
- **Bảng điều khiển i18n — 30 ngôn ngữ** — Tất cả hơn 500 phím được dịch bao gồm tiếng Ả Rập, tiếng Bungari, tiếng Đan Mạch, tiếng Đức, tiếng Tây Ban Nha, tiếng Phần Lan, tiếng Pháp, tiếng Do Thái, tiếng Hindi, tiếng Hungary, tiếng Indonesia, tiếng Ý, tiếng Nhật, tiếng Hàn, tiếng Mã Lai, tiếng Hà Lan, tiếng Na Uy, tiếng Ba Lan, tiếng Bồ Đào Nha (PT/BR), tiếng Rumani, tiếng Nga, tiếng Slovak, tiếng Thụy Điển, tiếng Thái, tiếng Ukraina, tiếng Việt, tiếng Trung, tiếng Philipin, tiếng Anh
- **Hỗ trợ RTL** — Hỗ trợ từ phải sang trái cho tiếng Ả Rập và tiếng Do Thái
- **README đa ngôn ngữ** — 30 bản dịch tài liệu hoàn chỉnh
- **Bộ chọn ngôn ngữ** — Biểu tượng quả cầu trong tiêu đề để chuyển đổi theo thời gian thực
</details>
<details>
<summary><b>🔄 13. "Tôi cần nhiều hơn là trò chuyện - tôi cần nội dung nhúng, hình ảnh, âm thanh"</b></summary>
AI không chỉ hoàn thành cuộc trò chuyện. Nhà phát triển cần tạo hình ảnh, phiên âm âm thanh, tạo phần nhúng cho RAG, sắp xếp lại tài liệu và kiểm duyệt nội dung. Mỗi API có điểm cuối và định dạng khác nhau.
**Cách OmniRoute giải quyết vấn đề này:**
- **Nhúng** — `/v1/embeddings` với 6 nhà cung cấp và hơn 9 mẫu máy
- **Tạo hình ảnh** — `/v1/images/generations` với 10 nhà cung cấp và hơn 20 mô hình (OpenAI, xAI, Together, Fireworks, Nebius, Hyperbolic, NanoBanana, AntiGravity, SD WebUI, ComfyUI)
- **Chuyển văn bản thành video** — `/v1/videos/generations` — ComfyUI (AnimateDiff, SVD) và SD WebUI
- **Chuyển văn bản thành nhạc** — `/v1/music/generations` — ComfyUI (Mở âm thanh ổn định, MusicGen)
- **Phiên âm âm thanh** — `/v1/audio/transcriptions` — Whisper + Nvidia NIM, HuggingFace, Qwen3
- **Chuyển văn bản thành giọng nói** — `/v1/audio/speech` — ElevenLabs, Nvidia NIM, HuggingFace, Coqui, Tortoise, Qwen3, + các nhà cung cấp hiện có
- **Kiểm duyệt** — `/v1/moderations` — Kiểm tra an toàn nội dung
- **Sắp xếp lại** — `/v1/rerank` — Sắp xếp lại mức độ liên quan của tài liệu
- **API phản hồi** — Hỗ trợ đầy đủ `/v1/responses` cho Codex
</details>
<details>
<summary><b>🧪 14. "Tôi không có cách nào để kiểm tra và so sánh chất lượng giữa các mẫu"</b></summary>
Các nhà phát triển muốn biết mô hình nào là tốt nhất cho trường hợp sử dụng của họ — mã, dịch thuật, lý luận — nhưng việc so sánh thủ công rất chậm. Không có công cụ đánh giá tích hợp nào tồn tại.
**Cách OmniRoute giải quyết vấn đề này:**
- **Đánh giá LLM** — Bộ thử nghiệm vàng với 10 trường hợp tải sẵn bao gồm lời chào, toán, địa lý, tạo mã, tuân thủ JSON, dịch thuật, đánh dấu, từ chối an toàn
- **4 Chiến lược kết hợp** — `exact`, `contains`, `regex`, `custom` (chức năng JS)
- **Băng thử nghiệm sân chơi dịch giả** — Thử nghiệm hàng loạt với nhiều đầu vào và đầu ra dự kiến, so sánh giữa các nhà cung cấp
- **Trình kiểm tra trò chuyện** — Toàn bộ chuyến đi với kết xuất phản hồi trực quan
- **Live Monitor** — Luồng thời gian thực của tất cả các yêu cầu truyền qua proxy
</details>
<details>
<summary><b>📈 15. "Tôi cần mở rộng quy mô mà không làm giảm hiệu suất"</b></summary>
Khi khối lượng yêu cầu tăng lên mà không lưu vào bộ nhớ đệm thì các câu hỏi tương tự sẽ tạo ra chi phí trùng lặp. Nếu không có tính tạm thời, các yêu cầu trùng lặp sẽ bị lãng phí. Giới hạn tỷ lệ cho mỗi nhà cung cấp phải được tôn trọng.
**Cách OmniRoute giải quyết vấn đề này:**
- **Bộ nhớ đệm ngữ nghĩa** — Bộ nhớ đệm hai tầng (chữ ký + ngữ nghĩa) giúp giảm chi phí và độ trễ
- **Yêu cầu Idempotency** — Khoảng thời gian loại bỏ trùng lặp 5 giây cho các yêu cầu giống hệt nhau
- **Phát hiện giới hạn tỷ lệ** — RPM của mỗi nhà cung cấp, khoảng cách tối thiểu và theo dõi đồng thời tối đa
- **Giới hạn tỷ lệ có thể chỉnh sửa** — Giá trị mặc định có thể định cấu hình trong Cài đặt → Khả năng phục hồi với tính bền bỉ
- **Bộ đệm xác thực khóa API** — Bộ đệm 3 tầng cho hiệu suất sản xuất
- **Bảng thông tin sức khỏe với phép đo từ xa** — độ trễ p50/p95/p99, số liệu thống kê bộ nhớ đệm, thời gian hoạt động
</details>
<details>
<summary><b>🤖 16. "Tôi muốn kiểm soát hành vi của mô hình trên toàn cầu"</b></summary>
Các nhà phát triển muốn tất cả phản hồi bằng một ngôn ngữ cụ thể, với giọng điệu cụ thể hoặc muốn giới hạn các mã thông báo lý luận. Việc định cấu hình điều này trong mọi công cụ/yêu cầu là không thực tế.
**Cách OmniRoute giải quyết vấn đề này:**
- **Tiêm nhắc nhở hệ thống** — Lời nhắc chung được áp dụng cho tất cả các yêu cầu
- **Xác thực ngân sách tư duy** — Kiểm soát phân bổ mã thông báo hợp lý cho mỗi yêu cầu (chuyển qua, tự động, tùy chỉnh, thích ứng)
- **6 Chiến lược định tuyến** — Chiến lược toàn cầu xác định cách phân phối yêu cầu
- **Bộ định tuyến ký tự đại diện** — Các mẫu `provider/*` tự động định tuyến tới bất kỳ nhà cung cấp nào
- **Bật/Tắt kết hợp chuyển đổi** — Chuyển đổi kết hợp trực tiếp từ bảng điều khiển
- **Chuyển đổi nhà cung cấp** — Bật/tắt tất cả kết nối cho nhà cung cấp chỉ bằng một cú nhấp chuột
- **Nhà cung cấp bị chặn** — Loại trừ các nhà cung cấp cụ thể khỏi danh sách `/v1/models`
</details>
<details>
<summary><b>🧰 17. "Tôi cần các công cụ MCP làm khả năng của sản phẩm hạng nhất"</b></summary>
Nhiều cổng AI chỉ hiển thị MCP dưới dạng chi tiết triển khai ẩn. Các nhóm cần một lớp hoạt động rõ ràng và dễ quản lý.
**Cách OmniRoute giải quyết vấn đề này:**
- MCP xuất hiện trong tab điều hướng bảng điều khiển và giao thức điểm cuối
- Trang quản lý MCP chuyên dụng với quy trình, công cụ, phạm vi và kiểm tra
- Tích hợp tính năng khởi động nhanh cho `omniroute --mcp` và quá trình cài đặt ứng dụng khách
</details>
<details>
<summary><b>🧠 18. "Tôi cần phối hợp A2A với đường dẫn tác vụ đồng bộ hóa + truyền phát"</b></summary>
Quy trình làm việc của tổng đài viên cần cả phản hồi trực tiếp và thực thi theo luồng trong thời gian dài với khả năng kiểm soát vòng đời.
**Cách OmniRoute giải quyết vấn đề này:**
- Điểm cuối JSON-RPC A2A (`POST /a2a`) với `message/send``message/stream`
- Truyền phát SSE với sự lan truyền trạng thái đầu cuối
- API vòng đời tác vụ cho `tasks/get``tasks/cancel`
</details>
<details>
<summary><b>🛰️ 19. "Tôi cần tình trạng quy trình MCP thực sự, trạng thái không đoán được"</b></summary>
Các nhóm vận hành cần biết liệu MCP có thực sự tồn tại hay không, chứ không chỉ là liệu API có thể truy cập được hay không.
**Cách OmniRoute giải quyết vấn đề này:**
- Tệp nhịp tim thời gian chạy với PID, dấu thời gian, vận chuyển, số lượng công cụ và chế độ phạm vi
- API trạng thái MCP kết hợp nhịp tim + hoạt động gần đây
- Thẻ trạng thái giao diện người dùng về độ mới của quy trình/thời gian hoạt động/nhịp tim
</details>
<details>
<summary><b>📋 20. "Tôi cần thực thi công cụ MCP có thể kiểm tra được"</b></summary>
Khi các công cụ thay đổi cấu hình hoặc kích hoạt các hành động vận hành, các nhóm cần truy xuất nguồn gốc pháp lý.
**Cách OmniRoute giải quyết vấn đề này:**
- Ghi nhật ký kiểm tra được hỗ trợ bởi SQLite cho các lệnh gọi công cụ MCP
- Bộ lọc theo công cụ, thành công/thất bại, khóa API và phân trang
- Bảng kiểm tra bảng điều khiển + điểm cuối thống kê để tự động hóa
</details>
<details>
<summary><b>🔐 21. "Tôi cần quyền MCP trong phạm vi cho mỗi lần tích hợp"</b></summary>
Các khách hàng khác nhau phải có quyền truy cập ít đặc quyền nhất vào các danh mục công cụ.
**Cách OmniRoute giải quyết vấn đề này:**
- 9 phạm vi MCP chi tiết để truy cập công cụ được kiểm soát
- Thực thi phạm vi và khả năng hiển thị trong giao diện người dùng quản lý MCP
- Tư thế mặc định an toàn cho dụng cụ vận hành
</details>
<details>
<summary><b>⚙️ 22. "Tôi cần kiểm soát hoạt động mà không cần triển khai lại"</b></summary>
Các nhóm cần thay đổi thời gian chạy nhanh trong các sự cố hoặc sự kiện tốn kém.
**Cách OmniRoute giải quyết vấn đề này:**
- Chuyển đổi kích hoạt kết hợp trực tiếp từ bảng điều khiển MCP
- Áp dụng hồ sơ khả năng phục hồi từ các gói chính sách được xác định trước
- Đặt lại trạng thái ngắt mạch từ cùng bảng vận hành
</details>
<details>
<summary><b>🔄 23. "Tôi cần khả năng hiển thị và hủy trực tiếp trong vòng đời nhiệm vụ A2A"</b></summary>
Nếu không có khả năng hiển thị vòng đời, các sự cố trong nhiệm vụ sẽ khó phân loại.
**Cách OmniRoute giải quyết vấn đề này:**
- Liệt kê/lọc nhiệm vụ theo trạng thái/kỹ năng với phân trang
- Xem chi tiết về siêu dữ liệu, sự kiện và hiện vật của nhiệm vụ
- Điểm cuối hủy tác vụ và hành động UI có xác nhận
</details>
<details>
<summary><b>🌊 24. "Tôi cần số liệu luồng hoạt động cho tải A2A"</b></summary>
Luồng công việc phát trực tuyến yêu cầu hiểu biết sâu sắc về hoạt động đồng thời và kết nối trực tiếp.
**Cách OmniRoute giải quyết vấn đề này:**
- Bộ đếm luồng hoạt động được tích hợp vào trạng thái A2A
- Dấu thời gian nhiệm vụ cuối cùng và số lượng trên mỗi trạng thái
- Thẻ bảng điều khiển A2A để theo dõi hoạt động theo thời gian thực
</details>
<details>
<summary><b>🪪 25. "Tôi cần phát hiện đại lý tiêu chuẩn cho khách hàng"</b></summary>
Máy khách và người điều phối bên ngoài cần siêu dữ liệu có thể đọc được bằng máy để triển khai.
**Cách OmniRoute giải quyết vấn đề này:**
- Thẻ đại lý bị lộ tại `/.well-known/agent.json`
- Khả năng và kỹ năng thể hiện trong UI quản lý
- API trạng thái A2A bao gồm siêu dữ liệu khám phá để tự động hóa
</details>
<details>
<summary><b>🧭 26. "Tôi cần khả năng khám phá giao thức trong UX sản phẩm"</b></summary>
Nếu người dùng không thể khám phá các bề mặt giao thức, chất lượng chấp nhận và hỗ trợ sẽ giảm.
**Cách OmniRoute giải quyết vấn đề này:**
- Các mục thanh bên cho MCP và A2A
- Tab Giao thức của trang điểm cuối với trạng thái và khởi động nhanh
- Liên kết từ tổng quan đến bảng điều khiển quản lý chuyên dụng
</details>
<details>
<summary><b>🧪 27. "Tôi cần xác thực giao thức end-to-end với khách hàng thực"</b></summary>
Các thử nghiệm mô phỏng không đủ để xác thực tính tương thích của giao thức trước khi phát hành.
**Cách OmniRoute giải quyết vấn đề này:**
- Bộ E2E khởi động ứng dụng và sử dụng vận chuyển máy khách MCP SDK thực
- Máy khách A2A kiểm tra các luồng khám phá, gửi, truyền phát, nhận và hủy
- Kiểm tra chéo các xác nhận đối với kiểm tra MCP và API nhiệm vụ A2A
</details>
<details>
<summary><b>📡 28. "Tôi cần khả năng quan sát thống nhất trên tất cả các giao diện"</b></summary>
Việc phân chia khả năng quan sát theo giao thức sẽ tạo ra các điểm mù và MTTR dài hơn.
**Cách OmniRoute giải quyết vấn đề này:**
- Bảng điều khiển/nhật ký/phân tích thống nhất trong một sản phẩm
- Sức khỏe + kiểm toán + yêu cầu đo từ xa trên các lớp OpenAI, MCP và A2A
- API hoạt động cho trạng thái và tự động hóa
</details>
<details>
<summary><b>💼 29. "Tôi cần một thời gian chạy cho proxy + công cụ + điều phối tác nhân"</b></summary>
Việc chạy nhiều dịch vụ riêng biệt làm tăng chi phí vận hành và các chế độ lỗi.
**Cách OmniRoute giải quyết vấn đề này:**
- Proxy tương thích với OpenAI, máy chủ MCP và máy chủ A2A trong một ngăn xếp
- Chia sẻ xác thực, khả năng phục hồi, lưu trữ dữ liệu và khả năng quan sát
- Mô hình chính sách nhất quán trên tất cả các bề mặt tương tác
</details>
<details>
<summary><b>🚀 30. "Tôi cần gửi quy trình công việc tổng thể mà không cần sử dụng quá nhiều mã keo"</b></summary>
Các nhóm bị mất tốc độ khi kết hợp nhiều dịch vụ và tập lệnh đặc biệt.
**Cách OmniRoute giải quyết vấn đề này:**
- Chiến lược điểm cuối thống nhất cho khách hàng và đại lý
- Giao diện người dùng quản lý giao thức tích hợp và đường dẫn xác thực khói
- Nền tảng sẵn sàng sản xuất (bảo mật, ghi nhật ký, khả năng phục hồi, sao lưu)
</details>
### Sách hướng dẫn ví dụ (Trường hợp sử dụng tích hợp)
**Playbook A: Tối đa hóa đăng ký trả phí + dự phòng giá rẻ**
```txt
Combo: "maximize-claude"
1. cc/claude-opus-4-6
2. glm/glm-4.7
3. if/kimi-k2-thinking
Monthly cost: $20 + small backup spend
Outcome: higher quality, near-zero interruption
```
**Playbook B: Ngăn xếp mã hóa không tốn phí**
```txt
Combo: "free-forever"
1. gc/gemini-3-flash
2. if/kimi-k2-thinking
3. qw/qwen3-coder-plus
Monthly cost: $0
Outcome: stable free coding workflow
```
**Playbook C: chuỗi dự phòng luôn hoạt động 24/7**
```txt
Combo: "always-on"
1. cc/claude-opus-4-6
2. cx/gpt-5.2-codex
3. glm/glm-4.7
4. minimax/MiniMax-M2.1
5. if/kimi-k2-thinking
Outcome: deep fallback depth for deadline-critical workloads
```
**Playbook D: Tác nhân hoạt động với MCP + A2A**
```txt
1) Start MCP transport (`omniroute --mcp`) for tool-driven operations
2) Run A2A tasks via `message/send` and `message/stream`
3) Observe via /dashboard/mcp and /dashboard/a2a
4) Control incidents with resilience profile + task cancellation
```
---
## ⚡ Bắt đầu nhanh
**1. Cài đặt trên toàn cầu:**
@@ -251,7 +782,7 @@ docker compose --profile cli up -d
---
## 🖥️ Desktop App — Offline & Always-On
## 🖥️
> 🆕 **NEW!** OmniRoute is now available as a **native desktop application** for Windows, macOS, and Linux.
@@ -298,67 +829,6 @@ npm run electron:build:linux # Linux (.AppImage)
---
## 🎯 Trường hợp sử dụng
### Trường hợp 1: "Tôi có đăng ký Claude Pro"
**Vấn đề:** Hạn ngạch hết hạn không được sử dụng, giới hạn tốc độ trong quá trình mã hóa nặng
```
Combo: "maximize-claude"
1. cc/claude-opus-4-6 (use subscription fully)
2. glm/glm-4.7 (cheap backup when quota out)
3. if/kimi-k2-thinking (free emergency fallback)
Monthly cost: $20 (subscription) + ~$5 (backup) = $25 total
vs. $20 + hitting limits = frustration
```
### Trường hợp 2: "Tôi muốn chi phí bằng 0"
**Vấn đề:** Không đủ khả năng đăng ký, cần mã hóa AI đáng tin cậy
```
Combo: "free-forever"
1. gc/gemini-3-flash (180K free/month)
2. if/kimi-k2-thinking (unlimited free)
3. qw/qwen3-coder-plus (unlimited free)
Monthly cost: $0
Quality: Production-ready models
```
### Trường hợp 3: "Tôi cần code 24/7, không bị gián đoạn"
**Vấn đề:** Thời hạn, không đủ khả năng cho thời gian ngừng hoạt động
```
Combo: "always-on"
1. cc/claude-opus-4-6 (best quality)
2. cx/gpt-5.2-codex (second subscription)
3. glm/glm-4.7 (cheap, resets daily)
4. minimax/MiniMax-M2.1 (cheapest, 5h reset)
5. if/kimi-k2-thinking (free unlimited)
Result: 5 layers of fallback = zero downtime
```
### Trường hợp 4: "Tôi muốn AI MIỄN PHÍ trong OpenClaw"
**Vấn đề:** Cần trợ lý AI trong ứng dụng nhắn tin, hoàn toàn miễn phí
```
Combo: "openclaw-free"
1. if/glm-4.7 (unlimited free)
2. if/minimax-m2.1 (unlimited free)
3. if/kimi-k2-thinking (unlimited free)
Monthly cost: $0
Access via: WhatsApp, Telegram, Slack, Discord, iMessage, Signal...
```
---
## 💡 Tính năng chính
### 🧠 Định tuyến lõi & thông minh
@@ -374,6 +844,8 @@ Access via: WhatsApp, Telegram, Slack, Discord, iMessage, Signal...
| 🧩 **Mẫu tùy chỉnh** | Thêm bất kỳ ID mẫu nào vào bất kỳ nhà cung cấp nào |
| 🌐 **Bộ định tuyến ký tự đại diện** | Định tuyến động các mẫu `provider/*` tới bất kỳ nhà cung cấp nào |
| 🧠 **Ngân sách suy nghĩ** | Các chế độ truyền qua, tự động, tùy chỉnh và thích ứng cho các mô hình lý luận |
| 🔀 **Model Aliases** | Auto-forward deprecated model IDs to current replacements (built-in + custom) |
| ⚡ **Background Degradation** | Auto-route background tasks (titles, summaries) to cheaper models |
| 💬 **Tiêm nhắc nhở hệ thống** | Lời nhắc hệ thống toàn cầu được áp dụng cho tất cả các yêu cầu |
| 📄 **API phản hồi** | Hỗ trợ đầy đủ API phản hồi OpenAI (`/v1/responses`) cho Codex |
@@ -399,6 +871,8 @@ Access via: WhatsApp, Telegram, Slack, Discord, iMessage, Signal...
| 🔒 **Giả mạo vân tay TLS** | Bỏ qua việc phát hiện bot dựa trên TLS thông qua wreq-js |
| 🌐 **Lọc IP** | Danh sách cho phép/danh sách chặn để kiểm soát truy cập API |
| 📊 **Giới hạn tỷ lệ có thể chỉnh sửa** | RPM có thể định cấu hình, khoảng cách tối thiểu và đồng thời tối đa ở cấp hệ thống |
| 💾 **Rate Limit Persistence** | Learned limits survive restarts via SQLite with 60s debounce + 24h staleness |
| 🔄 **Token Refresh Resilience** | Per-provider circuit breaker (5 fails→30min) + 30s timeout per attempt |
| 🛡 **Bảo vệ điểm cuối API** | Kiểm soát xác thực + chặn nhà cung cấp cho điểm cuối `/models` |
| 🔒 **Khả năng hiển thị proxy** | Huy hiệu được mã hóa màu: 🟢 toàn cầu, 🟡 nhà cung cấp, 🔵 mỗi kết nối với màn hình IP |
| 🌐 **Cấu hình proxy 3 cấp** | Định cấu hình proxy ở cấp độ toàn cầu, theo nhà cung cấp hoặc theo từng kết nối |
@@ -517,6 +991,27 @@ OmniRoute bao gồm Sân chơi dịch thuật tích hợp mạnh mẽ với **4
</details>
## 🧪 Đánh giá (Evals)
OmniRoute bao gồm khung đánh giá tích hợp để kiểm tra chất lượng phản hồi LLM dựa trên bộ vàng. Truy cập thông qua **Analytics → Đánh giá** trong bảng điều khiển.
### Bộ vàng tích hợp
"Bộ vàng OmniRoute" được tải sẵn chứa 10 trường hợp thử nghiệm bao gồm:
- Lời chào, toán, địa lý, tạo mã
- Tuân thủ định dạng JSON, dịch thuật, đánh dấu
- Từ chối an toàn (nội dung có hại), đếm, logic boolean
### Chiến lược đánh giá
| Chiến lược | Mô tả | Ví dụ |
| ---------- | --------------------------------------------------------------- | -------------------------------- |
| `exact` | Đầu ra phải khớp chính xác | `"4"` |
| `contains` | Đầu ra phải chứa chuỗi con (không phân biệt chữ hoa chữ thường) | `"Paris"` |
| `regex` | Đầu ra phải khớp với mẫu biểu thức chính quy | `"1.*2.*3"` |
| `custom` | Hàm JS tùy chỉnh trả về true/false | `(output) => output.length > 10` |
---
## 📖 Hướng dẫn thiết lập
@@ -799,104 +1294,64 @@ Settings → API Configuration:
---
## 📊 Mẫu có sẵn
## 🐛 Khắc phục sự cố
<details>
<summary><b>Xem tất cả các mẫu có sẵn</b></summary>
<summary><b>Nhấp để mở rộng hướng dẫn khắc phục sự cố</b></summary>
**Mã Claude (`cc/`)** - Pro/Max:
**"Mô hình ngôn ngữ không cung cấp tin nhắn"**
- `cc/claude-opus-4-6`
- `cc/claude-sonnet-4-5-20250929`
- `cc/claude-haiku-4-5-20251001`
- Đã hết hạn ngạch nhà cung cấp → Kiểm tra trình theo dõi hạn ngạch bảng điều khiển
- Giải pháp: Sử dụng combo dự phòng hoặc chuyển sang tầng rẻ hơn
**Codex (`cx/`)** - Plus/Pro:
**Giới hạn tỷ lệ**
- `cx/gpt-5.2-codex`
- `cx/gpt-5.1-codex-max`
- Hết hạn ngạch đăng ký → Dự phòng sang GLM/MiniMax
- Thêm tổ hợp: `cc/claude-opus-4-6 → glm/glm-4.7 → if/kimi-k2-thinking`
**Gemini CLI (`gc/`)** - MIỄN PHÍ:
**Mã thông báo OAuth đã hết hạn**
- `gc/gemini-3-flash-preview`
- `gc/gemini-2.5-pro`
- Tự động làm mới bởi OmniRoute
- Nếu sự cố vẫn tiếp diễn: Bảng điều khiển → Nhà cung cấp → Kết nối lại
**Phi công phụ GitHub (`gh/`)**:
**Chi phí cao**
- `gh/gpt-5`
- `gh/claude-4.5-sonnet`
- Kiểm tra số liệu thống kê sử dụng trong Bảng điều khiển → Chi phí
- Chuyển mô hình chính sang GLM/MiniMax
- Sử dụng bậc miễn phí (Gemini CLI, iFlow) cho các tác vụ không quan trọng
**NVIDIA NIM (`nvidia/`)** - Tín dụng MIỄN PHÍ:
**Bảng điều khiển mở sai cổng**
- `nvidia/llama-3.3-70b-instruct`
- `nvidia/mistral-7b-instruct`
- Hơn 50 mẫu khác trên [build.nvidia.com](https://build.nvidia.com)
- Đặt `PORT=20128``NEXT_PUBLIC_BASE_URL=http://localhost:20128`
**GLM (`glm/`)** - 0,6 USD/1 triệu:
**Lỗi đồng bộ hóa đám mây**
- `glm/glm-4.7`
- Xác minh `BASE_URL` trỏ tới phiên bản đang chạy của bạn
- Xác minh `CLOUD_URL` điểm tới điểm cuối đám mây dự kiến của bạn
- Giữ các giá trị `NEXT_PUBLIC_*` được căn chỉnh với các giá trị phía máy chủ
**MiniMax (`minimax/`)** - 0,2 USD/1 triệu:
**Đăng nhập lần đầu không hoạt động**
- `minimax/MiniMax-M2.1`
- Kiểm tra `INITIAL_PASSWORD` trong `.env`
- Nếu không được đặt, mật khẩu dự phòng là `123456`
**iFlow (`if/`)** - MIỄN PHÍ:
**Không có nhật ký yêu cầu**
- `if/kimi-k2-thinking`
- `if/qwen3-coder-plus`
- `if/deepseek-r1`
- `if/glm-4.7`
- `if/minimax-m2`
- Đặt `ENABLE_REQUEST_LOGS=true` trong `.env`
**Qwen (`qw/`)** - MIỄN PHÍ:
**Kiểm tra kết nối cho thấy "Không hợp lệ" đối với các nhà cung cấp tương thích với OpenAI**
- `qw/qwen3-coder-plus`
- `qw/qwen3-coder-flash`
- Nhiều nhà cung cấp không hiển thị điểm cuối `/models`
- OmniRoute v1.0.6+ bao gồm xác thực dự phòng thông qua hoàn thành trò chuyện
- Đảm bảo URL cơ sở bao gồm hậu tố `/v1`
**Kiro (`kr/`)** - MIỄN PHÍ:
- `kr/claude-sonnet-4.5`
- `kr/claude-haiku-4.5`
**OpenRouter (`or/`)** - Hơn 100 mẫu:
- `or/anthropic/claude-4-sonnet`
- `or/google/gemini-2.5-pro`
- Bất kỳ mẫu nào từ [openrouter.ai/models](https://openrouter.ai/models)
</details>
---
## 🧪 Đánh giá (Evals)
OmniRoute bao gồm khung đánh giá tích hợp để kiểm tra chất lượng phản hồi LLM dựa trên bộ vàng. Truy cập thông qua **Analytics → Đánh giá** trong bảng điều khiển.
### Bộ vàng tích hợp
"Bộ vàng OmniRoute" được tải sẵn chứa 10 trường hợp thử nghiệm bao gồm:
- Lời chào, toán, địa lý, tạo mã
- Tuân thủ định dạng JSON, dịch thuật, đánh dấu
- Từ chối an toàn (nội dung có hại), đếm, logic boolean
### Chiến lược đánh giá
| Chiến lược | Mô tả | Ví dụ |
| ---------- | --------------------------------------------------------------- | -------------------------------- |
| `exact` | Đầu ra phải khớp chính xác | `"4"` |
| `contains` | Đầu ra phải chứa chuỗi con (không phân biệt chữ hoa chữ thường) | `"Paris"` |
| `regex` | Đầu ra phải khớp với mẫu biểu thức chính quy | `"1.*2.*3"` |
| `custom` | Hàm JS tùy chỉnh trả về true/false | `(output) => output.length > 10` |
---
## 🔐 OAuth trên Servidor Remoto (Thiết lập OAuth từ xa)
### 🔐 OAuth
<a name="oauth-em-servidor-remoto"></a>
> **⚠️ QUAN TRỌNG đối với người sử dụng OmniRoute trên VPS/Docker/servidor remoto**
### Bởi vì OAuth làm cho AntiGravity / Gemini CLI có bị ảnh hưởng bởi các dịch vụ điều khiển từ xa không?
### OAuth
Os đã được chứng minh **AntiGravity** e **Gemini CLI** sử dụng **Google OAuth 2.0** để xác thực. O Google exige que a `redirect_uri` usada no fluxo OAuth seja **exatamente** một trong các URI trước khi lập danh sách trên Google Cloud Console để ứng dụng.
@@ -981,64 +1436,11 @@ Nếu không có câu hỏi nào về thông tin xác thực trước đây, b
> Chức năng giải pháp này có thể giúp tự động cấp quyền cho URL và có thể chuyển hướng độc lập đến mục tiêu hoặc không.
---
## 🐛 Khắc phục sự cố
<details>
<summary><b>Nhấp để mở rộng hướng dẫn khắc phục sự cố</b></summary>
**"Mô hình ngôn ngữ không cung cấp tin nhắn"**
- Đã hết hạn ngạch nhà cung cấp → Kiểm tra trình theo dõi hạn ngạch bảng điều khiển
- Giải pháp: Sử dụng combo dự phòng hoặc chuyển sang tầng rẻ hơn
**Giới hạn tỷ lệ**
- Hết hạn ngạch đăng ký → Dự phòng sang GLM/MiniMax
- Thêm tổ hợp: `cc/claude-opus-4-6 → glm/glm-4.7 → if/kimi-k2-thinking`
**Mã thông báo OAuth đã hết hạn**
- Tự động làm mới bởi OmniRoute
- Nếu sự cố vẫn tiếp diễn: Bảng điều khiển → Nhà cung cấp → Kết nối lại
**Chi phí cao**
- Kiểm tra số liệu thống kê sử dụng trong Bảng điều khiển → Chi phí
- Chuyển mô hình chính sang GLM/MiniMax
- Sử dụng bậc miễn phí (Gemini CLI, iFlow) cho các tác vụ không quan trọng
**Bảng điều khiển mở sai cổng**
- Đặt `PORT=20128``NEXT_PUBLIC_BASE_URL=http://localhost:20128`
**Lỗi đồng bộ hóa đám mây**
- Xác minh `BASE_URL` trỏ tới phiên bản đang chạy của bạn
- Xác minh `CLOUD_URL` điểm tới điểm cuối đám mây dự kiến của bạn
- Giữ các giá trị `NEXT_PUBLIC_*` được căn chỉnh với các giá trị phía máy chủ
**Đăng nhập lần đầu không hoạt động**
- Kiểm tra `INITIAL_PASSWORD` trong `.env`
- Nếu không được đặt, mật khẩu dự phòng là `123456`
**Không có nhật ký yêu cầu**
- Đặt `ENABLE_REQUEST_LOGS=true` trong `.env`
**Kiểm tra kết nối cho thấy "Không hợp lệ" đối với các nhà cung cấp tương thích với OpenAI**
- Nhiều nhà cung cấp không hiển thị điểm cuối `/models`
- OmniRoute v1.0.6+ bao gồm xác thực dự phòng thông qua hoàn thành trò chuyện
- Đảm bảo URL cơ sở bao gồm hậu tố `/v1`
</details>
---
## 🛠️ Ngăn xếp công nghệ
## 🛠️
- **Thời gian chạy**: Node.js 1822 LTS (⚠️ Node.js 24+ **không được hỗ trợ**`better-sqlite3` các tệp nhị phân gốc không tương thích)
- **Ngôn ngữ**: TypeScript 5.9 — **100% TypeScript** trên `src/``open-sse/` (v1.0.6)
@@ -1090,7 +1492,7 @@ Nếu không có câu hỏi nào về thông tin xác thực trước đây, b
---
## 🗺️ Lộ trình
## 🗺️
OmniRoute có **210+ tính năng được lên kế hoạch** qua nhiều giai đoạn phát triển. Dưới đây là các lĩnh vực chính:
@@ -1115,18 +1517,6 @@ OmniRoute có **210+ tính năng được lên kế hoạch** qua nhiều giai
---
## 📧 Hỗ trợ
> 💬 **Tham gia cộng đồng của chúng tôi!** [WhatsApp Group](https://chat.whatsapp.com/JI7cDQ1GyaiDHhVBpLxf8b?mode=gi_t) — Nhận trợ giúp, chia sẻ mẹo và luôn cập nhật.
- **Trang web**: [omniroute.online](https://omniroute.online)
- **GitHub**: [github.com/diegosouzapw/OmniRoute](https://github.com/diegosouzapw/OmniRoute)
- **Vấn đề**: [github.com/diegosouzapw/OmniRoute/issues](https://github.com/diegosouzapw/OmniRoute/issues)
- **WhatsApp**: [Community Group](https://chat.whatsapp.com/JI7cDQ1GyaiDHhVBpLxf8b?mode=gi_t)
- **Dự án gốc**: [9router by decolua](https://github.com/decolua/9router)
---
## 👥 Người đóng góp
[![Contributors](https://contrib.rocks/image?repo=diegosouzapw/OmniRoute&max=100&columns=20&anon=1)](https://github.com/diegosouzapw/OmniRoute/graphs/contributors)
@@ -1176,85 +1566,6 @@ Giấy phép MIT - xem [LICENSE](LICENSE) để biết chi tiết.
---
---
## 🇧🇷 OmniRoute — Gateway de IA Gratuito
<a name="-omniroute--gateway-de-ia-gratuito"></a>
### Nunca pare de codar. Roteamento thông minh cho **mô hình IA MIỄN PHÍ và baixo tùy chỉnh** và tự động dự phòng.
_Seu proxy phổ quát de API — ừm điểm cuối, hơn 36 điểm đã được chứng minh, không có thời gian ngừng hoạt động._
### 🌐 Quốc tế hóa (i18n)
O bảng điều khiển hỗ trợ OmniRoute **nhiều thành ngữ**. Cuối cùng, bạn có thể giải quyết:
| Thành ngữ | Código | Trạng thái |
| --------------------- | ------- | ------------- |
| 🇺🇸 Tiếng Anh | `en` | ✅ Hoàn thiện |
| 🇧🇷 Português (Brasil) | `pt-BR` | ✅ Hoàn thiện |
**Para trocar o thành ngữ:** Clique no seletor de Idi chỉ (🇺🇸 EN) không có tiêu đề làm bảng điều khiển → chọn lựa hoặc thành ngữ desejado.
**Thêm một thành ngữ mới:**
1. Khóc `src/i18n/messages/{codigo}.json` dựa trên `en.json`
2. Adicione hoặc código em `src/i18n/config.ts``LOCALES` e `LANGUAGES`
3. Phục hồi hoặc phục vụ
### ⚡ Início Rápido
```bash
# Instalar via npm
npx omniroute@latest
# Ou rodar do código-fonte
cp .env.example .env
npm install
PORT=20128 NEXT_PUBLIC_BASE_URL=http://localhost:20128 npm run dev
```
### 🐳 Docker
```bash
docker run -d --name omniroute -p 20128:20128 diegosouzapw/omniroute:latest
```
### 🔑 Chức năng chính
- **36+ chứng minh của IA** — Claude, GPT, Gemini, Llama, Qwen, DeepSeek, và nhiều hơn nữa
- **Roteamento inteligente** — Tự động dự phòng trong các phương pháp được chứng minh
- **Giao dịch định dạng** — OpenAI ↔ Claude ↔ Gemini tự động
- **Multi-conta** — Nhiều conta được chứng minh bằng cách lựa chọn thông minh
- **Cache semântico** — Reduz custos và latência
- **Tự động OAuth** — Tự động đổi mới mã thông báo
- **Combo cá nhân hóa** — 6 chiến lược roteamento
- **Hoàn thành bảng điều khiển** — Màn hình, nhật ký, phân tích, cấu hình
- **Công cụ CLI** — Định cấu hình Mã Claude, Codex, Con trỏ, Cline với một nhóm
- **100% TypeScript** — Código limbo e tipado
### 📖 Tài liệu
| Tài liệu | Mô tả |
| ----------------------------------------------- | --------------------------------------------------- |
| [Guia do Usuário](docs/USER_GUIDE.md) | Provedores, combo, CLI, triển khai |
| [Referência da API](docs/API_REFERENCE.md) | Tất cả các điểm cuối của hệ điều hành như các ví dụ |
| [Solução de Problemas](docs/TROUBLESHOOTING.md) | Các vấn đề công cộng và giải pháp |
| [Arquitetura](docs/ARCHITECTURE.md) | Hệ thống Arquitetura và internos |
| [Contribuição](CONTRIBUTING.md) | Thiết lập các nguyên tắc phát triển |
| [Deploy em VM](docs/VM_DEPLOYMENT_GUIDE.md) | Hướng dẫn hoàn chỉnh: VM + nginx + Cloudflare |
### 📧 Hỗ trợ
> 💬 **Entre para a communidade!** [Grupo WhatsApp](https://chat.whatsapp.com/JI7cDQ1GyaiDHhVBpLxf8b?mode=gi_t) — Tyre duvidas, compartilhe dicas and fique atualizado.
- **Trang web**: [omniroute.online](https://omniroute.online)
- **GitHub**: [github.com/diegosouzapw/OmniRoute](https://github.com/diegosouzapw/OmniRoute)
- **Vấn đề**: [github.com/diegosouzapw/OmniRoute/issues](https://github.com/diegosouzapw/OmniRoute/issues)
---
<div align="center">
<sub>Được xây dựng với ❤️ dành cho nhà phát triển viết mã 24/7</sub>
<br/>

View File

@@ -110,6 +110,35 @@ _通过 OmniRoute 连接任何 AI 驱动的 IDE 或 CLI 工具 — 免费 API
---
## 🖼️
<div align="center">
<img src="./docs/screenshots/MainOmniRoute.png" alt="OmniRoute" width="800"/>
</div>
---
## 📸
<details>
<summary><b>...</b></summary>
| # | # |
| ----- | ---------------------------------------- |
| **1** | ![1](docs/screenshots/01-providers.png) |
| **2** | ![2](docs/screenshots/02-combos.png) |
| **3** | ![3](docs/screenshots/03-analytics.png) |
| **4** | ![4](docs/screenshots/04-health.png) |
| **5** | ![5](docs/screenshots/05-translator.png) |
| **6** | ![6](docs/screenshots/06-settings.png) |
| **7** | ![7](docs/screenshots/07-cli-tools.png) |
| **8** | ![8](docs/screenshots/08-usage.png) |
| **9** | ![9](docs/screenshots/09-endpoint.png) |
</details>
---
## 🤔 为什么选择 OmniRoute
**停止浪费金钱和遭遇限制:**
@@ -128,6 +157,18 @@ _通过 OmniRoute 连接任何 AI 驱动的 IDE 或 CLI 工具 — 免费 API
---
## 📧 支持
> 💬 **加入我们的社区!** [WhatsApp 群组](https://chat.whatsapp.com/JI7cDQ1GyaiDHhVBpLxf8b?mode=gi_t) — 获取帮助、分享技巧、了解最新动态。
- **网站**: [omniroute.online](https://omniroute.online)
- **GitHub**: [github.com/diegosouzapw/OmniRoute](https://github.com/diegosouzapw/OmniRoute)
- **Issues**: [github.com/diegosouzapw/OmniRoute/issues](https://github.com/diegosouzapw/OmniRoute/issues)
- **WhatsApp**: [社区群组](https://chat.whatsapp.com/JI7cDQ1GyaiDHhVBpLxf8b?mode=gi_t)
- **原始项目**: [decolua 的 9router](https://github.com/decolua/9router)
---
## 🔄 工作原理
```
@@ -157,6 +198,497 @@ _通过 OmniRoute 连接任何 AI 驱动的 IDE 或 CLI 工具 — 免费 API
---
## 🎯 OmniRoute 解决了什么 — 30 个真正的痛点和用例
> **每个使用 AI 工具的开发人员每天都会面临这些问题。** OmniRoute 的构建是为了解决所有这些问题 - 从成本超支到区域封锁,从损坏的 OAuth 流程到协议操作和企业可观察性。
<details>
<summary><b>💸 1.“我支付了昂贵的订阅费用,但仍然受到限制的干扰”</b></summary>
开发人员每月为 Claude Pro、Codex Pro 或 GitHub Copilot 支付 20-200 美元。即使付费配额也有上限——5 小时的使用时间、每周限制或每分钟的费率限制。在编码会话中,提供商停止响应,开发人员失去流量和生产力。
**OmniRoute 如何解决:**
- **智能 4 层回退** — 如果订阅配额用完,自动重定向到 API 密钥 → 便宜 → 免费,零手动干预
- **实时配额跟踪** — 实时显示代币消耗情况并重置倒计时5 小时、每日、每周)
- **多帐户支持** — 每个提供商有多个帐户,具有自动循环 — 当一个帐户用完时,切换到下一个帐户
- **自定义组合** — 可定制的后备链,具有 6 种平衡策略先填充、循环、P2C、随机、最少使用、成本优化
- **Codex Business Quotas** — 直接在仪表板中监控业务/团队工作空间配额
</details>
<details>
<summary><b>🔌 2.“我需要使用多个提供程序,但每个提供程序都有不同的 API”</b></summary>
OpenAI 使用一种格式ClaudeAnthropic使用另一种格式Gemini 使用另一种格式。如果开发人员想要测试来自不同提供商的模型或在它们之间进行回退,他们需要重新配置 SDK、更改端点、处理不兼容的格式。自定义提供程序FriendLI、NIM具有非标准模型端点。
**OmniRoute 如何解决:**
- **统一端点** — 单个 `http://localhost:20128/v1` 充当所有 36 个以上提供商的代理
- **格式翻译** — 自动且透明OpenAI ↔ Claude ↔ Gemini ↔ Responses API
- **响应清理** — 删除破坏 OpenAI SDK v1.83+ 的非标准字段(`x_groq``usage_breakdown``service_tier`
- **角色标准化** — 对于非 OpenAI 提供商,将 `developer``system` 转换; `system``user` 适用于 GLM/ERNIE
- **Think Tag Extraction** — 将 DeepSeek R1 等模型中的 `<think>` 块提取为标准化 `reasoning_content`
- **Gemini 的结构化输出** — `json_schema``responseMimeType`/`responseSchema` 自动转换
- **`stream` 默认为 `false`** — 与 OpenAI 规范保持一致,避免 Python/Rust/Go SDK 中出现意外的 SSE
</details>
<details>
<summary><b>🌐 3.“我的人工智能提供商封锁了我的地区/国家”</b></summary>
OpenAI/Codex 等提供商会阻止来自某些地理区域的访问。用户在 OAuth 和 API 连接期间收到类似 `unsupported_country_region_territory` 的错误。这对于发展中国家的开发商来说尤其令人沮丧。
**OmniRoute 如何解决:**
- **3 级代理配置** — 3 级可配置代理:全局(所有流量)、每个提供商(仅一个提供商)和每个连接/密钥
- **颜色编码的代理徽章** — 视觉指示器:🟢 全局代理、🟡 提供商代理、🔵 连接代理,始终显示 IP
- **通过代理进行 OAuth 令牌交换** — OAuth 流程也通过代理,解决了 `unsupported_country_region_territory`
- **通过代理进行连接测试** — 连接测试使用配置的代理(不再直接绕过)
- **SOCKS5 支持** — 对出站路由的完整 SOCKS5 代理支持
- **TLS 指纹欺骗** — 通过 `wreq-js` 的类似浏览器的 TLS 指纹来绕过机器人检测
</details>
<details>
<summary><b>🆓 4.“我想用AI编码但我没有钱”</b></summary>
并不是每个人都能每月支付 20-200 美元来订阅 AI。来自新兴国家的学生、开发人员、业余爱好者和自由职业者需要以零成本获得优质模型。
**OmniRoute 如何解决:**
- **内置免费层级提供商** — 对 100% 免费提供商的本机支持iFlow8 个无限型号、Qwen3 个无限型号、KiroClaude 免费、Gemini CLI180K/月免费)
- **仅限免费组合** — 链 `gc/gemini-3-flash → if/kimi-k2-thinking → qw/qwen3-coder-plus` = 0 美元/月,零停机时间
- **NVIDIA NIM 免费积分** — 集成 1000 个免费积分
- **成本优化策略** — 自动选择最便宜的可用提供商的路由策略
</details>
<details>
<summary><b>🔒 5.“我需要保护我的AI网关免遭未经授权的访问”</b></summary>
当将人工智能网关暴露到网络LAN、VPS、Docker任何拥有该地址的人都可以消耗开发者的代币/配额。如果没有保护API 很容易被误用、提示注入和滥用。
**OmniRoute 如何解决:**
- **API 密钥管理** — 使用专用的 `/dashboard/api-manager` 页面为每个提供商生成、轮换和范围界定
- **模型级权限** — 将 API 密钥限制为特定模型(`openai/*`、通配符模式),并具有“允许全部”/“限制”切换功能
- **API 端点保护** — 需要 `/v1/models` 的密钥并阻止列表中的特定提供商
- **Auth Guard + CSRF 保护** — 所有仪表板路由均受 `withAuth` 中间件 + CSRF 令牌保护
- **速率限制器** — 通过可配置窗口限制每个 IP 的速率
- **IP 过滤** — 用于访问控制的允许列表/阻止列表
- **Prompt Injection Guard** — 针对恶意提示模式的清理
- **AES-256-GCM 加密** — 静态加密的凭证
</details>
<details>
<summary><b>🛑 6.“我的提供商宕机了,我失去了编码流程”</b></summary>
AI 提供商可能会变得不稳定、返回 5xx 错误或达到临时速率限制。如果开发人员依赖于单一提供商,他们就会受到干扰。如果没有断路器,重复重试可能会使应用程序崩溃。
**OmniRoute 如何解决:**
- **每个提供商的断路器** — 自动打开/关闭,具有可配置的阈值和冷却时间(关闭/打开/半打开)
- **指数退避** — 渐进式重试延迟
- **Anti-Thundering Herd** — 互斥锁 + 信号量保护,防止并发重试风暴
- **组合后备链** — 如果主要提供商发生故障,则自动从该链中掉下来,无需干预
- **组合断路器** — 自动禁用组合链中出现故障的提供商
- **运行状况仪表板** — 正常运行时间监控、断路器状态、锁定、缓存统计、p50/p95/p99 延迟
</details>
<details>
<summary><b>🔧 7. “配置每个AI工具都是繁琐且重复的”</b></summary>
开发人员使用 Cursor、Claude Code、Codex CLI、OpenClaw、Gemini CLI、Kilo Code...每个工具都需要不同的配置API 端点、密钥、模型)。切换提供商或模型时重新配置是浪费时间。
**OmniRoute 如何解决:**
- **CLI 工具仪表板** — 专用页面,可一键设置 Claude Code、Codex CLI、OpenClaw、Kilo Code、Antigravity、Cline
- **GitHub Copilot 配置生成器** — 通过批量模型选择为 VS Code 生成 `chatLanguageModels.json`
- **入门向导** — 为首次使用的用户提供 4 步设置指导
- **一个端点,所有型号** — 配置 `http://localhost:20128/v1` 一次,访问 36 个以上提供商
</details>
<details>
<summary><b>🔑 8.“管理来自多个提供商的 OAuth 令牌简直就是地狱”</b></summary>
Claude Code、Codex、Gemini CLI、Copilot — 全部使用带有过期令牌的 OAuth 2.0。开发人员需要不断地重新进行身份验证,处理`client_secret is missing``redirect_uri_mismatch`以及远程服务器上的故障。 LAN/VPS 上的 OAuth 问题尤其严重。
**OmniRoute 如何解决:**
- **自动令牌刷新** — OAuth 令牌在过期前在后台刷新
- **OAuth 2.0 (PKCE) 内置** — Claude Code、Codex、Gemini CLI、Copilot、Kiro、Qwen、iFlow 的自动流程
- **多帐户 OAuth** — 每个提供商通过 JWT/ID 令牌提取多个帐户
- **OAuth LAN/远程修复** — `redirect_uri` 的私有 IP 检测 + 远程服务器的手动 URL 模式
- **Nginx 背后的 OAuth** — 使用 `window.location.origin` 实现反向代理兼容性
- **远程 OAuth 指南** — VPS/Docker 上的 Google Cloud 凭据分步指南
</details>
<details>
<summary><b>📊 9.“我不知道我花了多少钱或在哪里”</b></summary>
开发商使用多个付费提供商,但对支出没有统一的看法。每个提供商都有自己的计费仪表板,但没有统一的视图。意外的成本可能会不断增加。
**OmniRoute 如何解决:**
- **成本分析仪表板** — 每个提供商的每个代币成本跟踪和预算管理
- **每层预算限制** — 触发自动回退的每层支出上限
- **按型号定价配置** — 每个型号的可配置价格
- **每个 API 密钥的使用统计信息** — 每个密钥的请求计数和上次使用的时间戳
- **分析仪表板** — 统计卡、模型使用图表、包含成功率和延迟的提供商表
</details>
<details>
<summary><b>🐛 10.“我无法诊断人工智能调用中的错误和问题”</b></summary>
当调用失败时,开发人员不知道这是否是速率限制、令牌过期、格式错误或提供商错误。跨不同终端的碎片日志。如果没有可观察性,调试就是反复试验。
**OmniRoute 如何解决:**
- **统一日志仪表板** — 4 个选项卡:请求日志、代理日志、审核日志、控制台
- **控制台日志查看器** — 实时终端式查看器,具有颜色编码级别、自动滚动、搜索、过滤功能
- **SQLite 代理日志** — 服务器重新启动后仍保留的持久日志
- **Translator Playground** — 4 种调试模式Playground格式翻译、Chat Tester往返、Test Bench批量、Live Monitor实时
- **请求遥测** — p50/p95/p99 延迟 + X-Request-Id 跟踪
- **基于文件的日志记录与旋转** — 控制台拦截器通过基于大小的旋转将所有内容捕获到 JSON 日志
</details>
<details>
<summary><b>🏗️ 11.“部署和维护网关很复杂”</b></summary>
跨不同环境本地、VPS、Docker、云安装、配置和维护 AI 代理是一项劳动密集型工作。硬编码路径、目录上的 `EACCES`、端口冲突和跨平台构建等问题会增加摩擦。
**OmniRoute 如何解决:**
- **npm 全局安装** — `npm install -g omniroute && omniroute` — 完成
- **Docker 多平台** — AMD64 + ARM64 本机Apple Silicon、AWS Graviton、Raspberry Pi
- **Docker Compose Profiles** — `base`(无 CLI 工具)和 `cli`(带有 Claude Code、Codex、OpenClaw
- **Electron 桌面应用程序** — 适用于 Windows/macOS/Linux 的本机应用程序,带系统托盘、自动启动、离线模式
- **分割端口模式** — API 和仪表板位于单独的端口上,适用于高级场景(反向代理、容器网络)
- **云同步** — 通过 Cloudflare Workers 跨设备配置同步
- **数据库备份** — 自动备份、恢复、导出和导入所有设置
</details>
<details>
<summary><b>🌍 12.“界面只有英文,我的团队不会说英语”</b></summary>
非英语国家的团队,尤其是拉丁美洲、亚洲和欧洲的团队,在纯英文界面上遇到了困难。语言障碍会降低采用率并增加配置错误。
**OmniRoute 如何解决:**
- **仪表板 i18n — 30 种语言** — 所有 500 多个按键已翻译包括阿拉伯语、保加利亚语、丹麦语、德语、西班牙语、芬兰语、法语、希伯来语、印地语、匈牙利语、印度尼西亚语、意大利语、日语、韩语、马来语、荷兰语、挪威语、波兰语、葡萄牙语PT/BR、罗马尼亚语、俄语、斯洛伐克语、瑞典语、泰语、乌克兰语、越南语、中文、菲律宾语、英语
- **RTL 支持** — 从右到左支持阿拉伯语和希伯来语
- **多语言自述文件** — 30 个完整的文档翻译
- **语言选择器** — 标题中的地球图标用于实时切换
</details>
<details>
<summary><b>🔄 13.“我需要的不仅仅是聊天 - 我需要嵌入、图像、音频”</b></summary>
人工智能不仅仅是完成聊天。开发人员需要生成图像、转录音频、为 RAG 创建嵌入、重新排列文档以及审核内容。每个 API 都有不同的端点和格式。
**OmniRoute 如何解决:**
- **嵌入** — `/v1/embeddings` 具有 6 个提供商和 9 个以上模型
- **图像生成** — `/v1/images/generations` 具有 10 个提供商和 20 多个模型OpenAI、xAI、Together、Fireworks、Nebius、Hyperbolic、NanoBanana、Antigravity、SD WebUI、ComfyUI
- **文本到视频** — `/v1/videos/generations` — ComfyUIAnimateDiff、SVD和 SD WebUI
- **文本转音乐** — `/v1/music/generations` — ComfyUI稳定音频打开MusicGen
- **音频转录** — `/v1/audio/transcriptions` — Whisper + Nvidia NIM、HuggingFace、Qwen3
- **文本转语音** — `/v1/audio/speech` — ElevenLabs、Nvidia NIM、HuggingFace、Coqui、Tortoise、Qwen3 以及现有提供商
- **审核** — `/v1/moderations` — 内容安全检查
- **重新排名** — `/v1/rerank` — 文档相关性重新排名
- **响应 API** — 对 Codex 的完整 `/v1/responses` 支持
</details>
<details>
<summary><b>🧪 14.“我无法测试和比较不同型号的质量”</b></summary>
开发人员想知道哪种模型最适合他们的用例(代码、翻译、推理),但手动比较速度很慢。不存在集成的评估工具。
**OmniRoute 如何解决:**
- **LLM 评估** — 黄金套装测试,包含 10 个预加载案例涵盖问候语、数学、地理、代码生成、JSON 合规性、翻译、降价、安全拒绝
- **4种匹配策略** — `exact``contains``regex``custom`JS函数
- **Translator Playground 测试台** — 使用多个输入和预期输出进行批量测试、跨提供商比较
- **聊天测试器** — 带有视觉响应渲染的完整往返
- **实时监控** — 流经代理的所有请求的实时流
</details>
<details>
<summary><b>📈 15.“我需要在不损失性能的情况下进行扩展”</b></summary>
随着请求量的增长,如果不缓存相同的问题,就会产生重复的成本。如果没有幂等性,重复的请求就会浪费处理。必须遵守每个提供商的速率限制。
**OmniRoute 如何解决:**
- **语义缓存** - 两层缓存(签名+语义)降低成本和延迟
- **请求幂等性** — 相同请求的 5 秒重复数据删除窗口
- **速率限制检测** — 每个提供商的 RPM、最小间隙和最大并发跟踪
- **可编辑的速率限制** — 可在“设置”→“持久弹性”中配置默认值
- **API 密钥验证缓存** — 用于提高生产性能的 3 层缓存
- **带有遥测功能的运行状况仪表板** — p50/p95/p99 延迟、缓存统计数据、正常运行时间
</details>
<details>
<summary><b>🤖 16.“我想全局控制模型行为”</b></summary>
希望所有响应都以特定语言、特定语气或想要限制推理标记的开发人员。在每个工具/请求中配置此功能是不切实际的。
**OmniRoute 如何解决:**
- **系统提示注入** — 全局提示应用于所有请求
- **思考预算验证** - 每个请求的推理令牌分配控制(直通、自动、自定义、自适应)
- **6 种路由策略** — 确定如何分发请求的全局策略
- **通配符路由器** — `provider/*` 模式动态路由到任何提供商
- **组合启用/禁用切换** — 直接从仪表板切换组合
- **提供商切换** — 一键启用/禁用提供商的所有连接
- **阻止的提供商** — 从 `/v1/models` 列表中排除特定提供商
</details>
<details>
<summary><b>🧰 17.“我需要MCP工具作为一流的产品能力”</b></summary>
许多 AI 网关仅将 MCP 作为隐藏的实现细节公开。团队需要一个可见的、可管理的操作层。
**OmniRoute 如何解决:**
- MCP 显示在仪表板导航和端点协议选项卡中
- 专用 MCP 管理页面,包含流程、工具、范围和审计
- `omniroute --mcp` 和客户入门的内置快速启动
</details>
<details>
<summary><b>🧠 18.“我需要具有同步+流任务路径的 A2A 编排”</b></summary>
代理工作流程需要直接回复和具有生命周期控制的长时间运行的流式执行。
**OmniRoute 如何解决:**
- A2A JSON-RPC 端点 (`POST /a2a`) 与 `message/send``message/stream`
- 具有终端状态传播的 SSE 流式传输
- `tasks/get``tasks/cancel` 的任务生命周期 API
</details>
<details>
<summary><b>🛰️ 19.“我需要真实的 MCP 进程运行状况,而不是猜测的状态”</b></summary>
运营团队需要知道 MCP 是否确实存在,而不仅仅是 API 是否可访问。
**OmniRoute 如何解决:**
- 带有 PID、时间戳、传输、工具计数和范围模式的运行时心跳文件
- MCP状态API结合心跳+最近的活动
- 用于流程/正常运行时间/心跳新鲜度的 UI 状态卡
</details>
<details>
<summary><b>📋 20.“我需要可审核的 MCP 工具执行”</b></summary>
当工具改变配置或触发操作操作时,团队需要取证可追溯性。
**OmniRoute 如何解决:**
- SQLite 支持的 MCP 工具调用审核日志记录
- 按工具、成功/失败、API 密钥和分页过滤
- 仪表板审核表+自动化统计端点
</details>
<details>
<summary><b>🔐 21.“每次集成我都需要范围内的 MCP 权限”</b></summary>
不同的客户端应该具有对工具类别的最低权限访问权限。
**OmniRoute 如何解决:**
- 9 个粒度 MCP 范围,用于受控工具访问
- MCP 管理 UI 中的范围执行和可见性
- 操作工具的安全默认姿势
</details>
<details>
<summary><b>⚙️ 22.“我需要操作控制而不重新部署”</b></summary>
团队需要在事件或成本事件期间快速更改运行时。
**OmniRoute 如何解决:**
- 直接从 MCP 仪表板切换组合激活
- 应用预定义策略包中的弹性配置文件
- 从同一操作面板重置断路器状态
</details>
<details>
<summary><b>🔄 23.“我需要实时 A2A 任务生命周期可见性和取消”</b></summary>
如果没有生命周期可见性,任务事件就很难分类。
**OmniRoute 如何解决:**
- 任务列表/按状态/技能过滤并分页
- 深入了解任务元数据、事件和工件
- 任务取消端点和带有确认的 UI 操作
</details>
<details>
<summary><b>🌊 24.“我需要 A2A 负载的活动流指标”</b></summary>
流媒体工作流程需要对并发和实时连接的操作洞察。
**OmniRoute 如何解决:**
- 活动流计数器集成到 A2A 状态中
- 最后任务时间戳和每个状态计数
- 用于实时操作监控的 A2A 仪表板卡
</details>
<details>
<summary><b>🪪 25.“我需要为客户发现标准代理”</b></summary>
外部客户端和协调器需要机器可读的元数据来进行引导。
**OmniRoute 如何解决:**
- 特工卡暴露在`/.well-known/agent.json`
- 管理 UI 中显示的能力和技能
- A2A 状态 API 包括用于自动化的发现元数据
</details>
<details>
<summary><b>🧭 26.“我需要产品 UX 中的协议可发现性”</b></summary>
如果用户无法发现协议表面,采用和支持质量就会下降。
**OmniRoute 如何解决:**
- MCP 和 A2A 的侧边栏条目
- 端点页面“协议”选项卡包含快速启动和状态
- 从概述到专用管理仪表板的链接
</details>
<details>
<summary><b>🧪 27.“我需要与真实客户端进行端到端协议验证”</b></summary>
模拟测试不足以在发布前验证协议兼容性。
**OmniRoute 如何解决:**
- E2E 套件,可启动应用程序并使用真正的 MCP SDK 客户端传输
- A2A 客户端测试发现、发送、流式传输、获取和取消流程
- 针对 MCP 审计和 A2A 任务 API 交叉检查断言
</details>
<details>
<summary><b>📡 28.“我需要跨所有接口的统一可观察性”</b></summary>
按协议分割可观察性会产生盲点和更长的 MTTR。
**OmniRoute 如何解决:**
- 一个产品中的统一仪表板/日志/分析
- 跨 OpenAI、MCP 和 A2A 层的运行状况 + 审计 + 请求遥测
- 用于状态和自动化的操作 API
</details>
<details>
<summary><b>💼 29.“我需要一个用于代理+工具+代理编排的运行时”</b></summary>
运行许多单独的服务会增加运营成本和故障模式。
**OmniRoute 如何解决:**
- 兼容 OpenAI 的代理、MCP 服务器和 A2A 服务器位于一个堆栈中
- 共享身份验证、弹性、数据存储和可观察性
- 所有交互界面上一致的策略模型
</details>
<details>
<summary><b>🚀 30.“我需要在没有胶水代码蔓延的情况下交付代理工作流程”</b></summary>
拼接多个临时服务和脚本时,团队会失去速度。
**OmniRoute 如何解决:**
- 客户端和代理的统一端点策略
- 内置协议管理 UI 和烟雾验证路径
- 生产就绪的基础(安全性、日志记录、弹性、备份)
</details>
### 示例手册(集成用例)
**剧本 A最大化付费订阅 + 廉价备份**
```txt
Combo: "maximize-claude"
1. cc/claude-opus-4-6
2. glm/glm-4.7
3. if/kimi-k2-thinking
Monthly cost: $20 + small backup spend
Outcome: higher quality, near-zero interruption
```
**剧本 B零成本编码堆栈**
```txt
Combo: "free-forever"
1. gc/gemini-3-flash
2. if/kimi-k2-thinking
3. qw/qwen3-coder-plus
Monthly cost: $0
Outcome: stable free coding workflow
```
**剧本 C24/7 始终在线的后备链**
```txt
Combo: "always-on"
1. cc/claude-opus-4-6
2. cx/gpt-5.2-codex
3. glm/glm-4.7
4. minimax/MiniMax-M2.1
5. if/kimi-k2-thinking
Outcome: deep fallback depth for deadline-critical workloads
```
**剧本 D使用 MCP + A2A 的特工操作**
```txt
1) Start MCP transport (`omniroute --mcp`) for tool-driven operations
2) Run A2A tasks via `message/send` and `message/stream`
3) Observe via /dashboard/mcp and /dashboard/a2a
4) Control incidents with resilience profile + task cancellation
```
---
## ⚡ 快速开始
**1. 全局安装:**
@@ -249,7 +781,7 @@ docker compose --profile cli up -d
---
## 🖥️ 桌面应用 — 离线 & 始终在线
## 🖥️
> 🆕 **全新!** OmniRoute 现已提供适用于 Windows、macOS 和 Linux 的**原生桌面应用程序**。
@@ -296,84 +828,25 @@ npm run electron:build:linux # Linux (.AppImage)
---
## 🎯 使用场景
### 场景 1"我有 Claude Pro 订阅"
**问题:** 配额未使用就过期,编程高峰期遇到速率限制
```
Combo: "maximize-claude"
1. cc/claude-opus-4-6 (充分使用订阅)
2. glm/glm-4.7 (配额用完时的便宜备用)
3. if/kimi-k2-thinking (免费应急后备)
每月成本:$20订阅+ ~$5备用= $25 总计
对比:$20 + 遇到限制 = 受挫
```
### 场景 2"我想要零成本"
**问题:** 无法承担订阅费用,需要可靠的 AI 编程
```
Combo: "free-forever"
1. gc/gemini-3-flash (每月 180K 免费)
2. if/kimi-k2-thinking (无限免费)
3. qw/qwen3-coder-plus (无限免费)
每月成本:$0
质量:生产级模型
```
### 场景 3"我需要 24/7 编程,不中断"
**问题:** 截止日期紧迫,不能有停机时间
```
Combo: "always-on"
1. cc/claude-opus-4-6 (最佳质量)
2. cx/gpt-5.2-codex (第二个订阅)
3. glm/glm-4.7 (便宜,每日重置)
4. minimax/MiniMax-M2.1 最便宜5小时重置
5. if/kimi-k2-thinking (免费无限制)
结果5 层故障转移 = 零停机
```
### 场景 4"我想在 OpenClaw 中使用免费 AI"
**问题:** 需要在消息应用中使用 AI 助手,完全免费
```
Combo: "openclaw-free"
1. if/glm-4.7 (无限免费)
2. if/minimax-m2.1 (无限免费)
3. if/kimi-k2-thinking (无限免费)
每月成本:$0
访问方式WhatsApp、Telegram、Slack、Discord、iMessage、Signal...
```
---
## 💡 核心功能
### 🧠 路由与智能
| 功能 | 功能描述 |
| ------------------------- | -------------------------------------------------------------------------- |
| 🎯 **智能 4 层故障转移** | 自动路由:订阅 → API Key → 低价 → 免费 |
| 📊 **实时配额追踪** | 实时 Token 计数 + 每个提供商的重置倒计时 |
| 🔄 **格式转换** | OpenAI ↔ Claude ↔ Gemini ↔ Cursor ↔ Kiro 无缝切换 |
| 👥 **多账号支持** | 每个提供商多个账号,智能选择 |
| 🔄 **自动令牌刷新** | OAuth 令牌自动刷新并重试 |
| 🎨 **自定义组合** | 6 种策略fill-first、round-robin、p2c、random、least-used、cost-optimized |
| 🧩 **自定义模型** | 为任何提供商添加任何模型 ID |
| 🌐 **通配符路由** | 动态路由 `provider/*` 模式到任何提供商 |
| 🧠 **推理预算** | passthrough、auto、custom 和 adaptive 模式用于推理模型 |
| 💬 **System Prompt 注入** | 全局 System Prompt 应用于所有请求 |
| 📄 **Responses API** | 完整支持 OpenAI Responses API (`/v1/responses`) 用于 Codex |
| 功能 | 功能描述 |
| ----------------------------- | ----------------------------------------------------------------------------- |
| 🎯 **智能 4 层故障转移** | 自动路由:订阅 → API Key → 低价 → 免费 |
| 📊 **实时配额追踪** | 实时 Token 计数 + 每个提供商的重置倒计时 |
| 🔄 **格式转换** | OpenAI ↔ Claude ↔ Gemini ↔ Cursor ↔ Kiro 无缝切换 |
| 👥 **多账号支持** | 每个提供商多个账号,智能选择 |
| 🔄 **自动令牌刷新** | OAuth 令牌自动刷新并重试 |
| 🎨 **自定义组合** | 6 种策略fill-first、round-robin、p2c、random、least-used、cost-optimized |
| 🧩 **自定义模型** | 为任何提供商添加任何模型 ID |
| 🌐 **通配符路由** | 动态路由 `provider/*` 模式到任何提供商 |
| 🧠 **推理预算** | passthrough、auto、custom 和 adaptive 模式用于推理模型 |
| 🔀 **Model Aliases** | Auto-forward deprecated model IDs to current replacements (built-in + custom) |
| **Background Degradation** | Auto-route background tasks (titles, summaries) to cheaper models |
| 💬 **System Prompt 注入** | 全局 System Prompt 应用于所有请求 |
| 📄 **Responses API** | 完整支持 OpenAI Responses API (`/v1/responses`) 用于 Codex |
### 🎵 多模态 API
@@ -388,15 +861,17 @@ Combo: "openclaw-free"
### 🛡️ 弹性与安全
| 功能 | 功能描述 |
| --------------------- | -------------------------------------- |
| 🔌 **断路器** | 每个提供商自动打开/关闭,可配置阈值 |
| 🛡️ **反惊群** | Mutex + 信号量限速用于 API Key 提供商 |
| 🧠 **语义缓存** | 两层缓存(签名 + 语义)降低成本和延迟 |
| ⚡ **请求幂等性** | 5 秒去重窗口防止重复请求 |
| 🔒 **TLS 指纹伪装** | 通过 wreq-js 绕过基于 TLS 的机器人检测 |
| 🌐 **IP 过滤** | 白名单/黑名单用于 API 访问控制 |
| 📊 **可编辑速率限制** | 可配置的 RPM、最小间隔和最大并发 |
| 功能 | 功能描述 |
| ------------------------------- | ---------------------------------------------------------------------------- |
| 🔌 **断路器** | 每个提供商自动打开/关闭,可配置阈值 |
| 🛡️ **反惊群** | Mutex + 信号量限速用于 API Key 提供商 |
| 🧠 **语义缓存** | 两层缓存(签名 + 语义)降低成本和延迟 |
| ⚡ **请求幂等性** | 5 秒去重窗口防止重复请求 |
| 🔒 **TLS 指纹伪装** | 通过 wreq-js 绕过基于 TLS 的机器人检测 |
| 🌐 **IP 过滤** | 白名单/黑名单用于 API 访问控制 |
| 📊 **可编辑速率限制** | 可配置的 RPM、最小间隔和最大并发 |
| 💾 **Rate Limit Persistence** | Learned limits survive restarts via SQLite with 60s debounce + 24h staleness |
| 🔄 **Token Refresh Resilience** | Per-provider circuit breaker (5 fails→30min) + 30s timeout per attempt |
### 📊 可观察性与分析
@@ -496,6 +971,27 @@ Combo: "my-coding-stack"
</details>
## 🧪 评估 (Evals)
OmniRoute 包含内置评估框架,用于针对黄金集测试 LLM 响应质量。通过仪表板中的 **Analytics → Evals** 访问。
### 内置黄金集
预加载的「OmniRoute Golden Set」包含 10 个测试用例:
- 问候、数学、地理、代码生成
- JSON 格式合规性、翻译、markdown
- 安全拒绝(有害内容)、计数、布尔逻辑
### 评估策略
| 策略 | 描述 | 示例 |
| ---------- | -------------------------------- | -------------------------------- |
| `exact` | 输出必须完全匹配 | `"4"` |
| `contains` | 输出必须包含子串(不区分大小写) | `"Paris"` |
| `regex` | 输出必须匹配正则表达式模式 | `"1.*2.*3"` |
| `custom` | 自定义 JS 函数返回 true/false | `(output) => output.length > 10` |
---
## 📖 设置指南
@@ -778,97 +1274,6 @@ codex "your prompt"
---
## 📊 可用模型
<details>
<summary><b>查看所有可用模型</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`
**GitHub Copilot (`gh/`)**:
- `gh/gpt-5`
- `gh/claude-4.5-sonnet`
**NVIDIA NIM (`nvidia/`)** - 免费积分:
- `nvidia/llama-3.3-70b-instruct`
- `nvidia/mistral-7b-instruct`
- 50+ 更多模型在 [build.nvidia.com](https://build.nvidia.com)
**GLM (`glm/`)** - $0.6/1M:
- `glm/glm-4.7`
**MiniMax (`minimax/`)** - $0.2/1M:
- `minimax/MiniMax-M2.1`
**iFlow (`if/`)** - 免费:
- `if/kimi-k2-thinking`
- `if/qwen3-coder-plus`
- `if/deepseek-r1`
- `if/glm-4.7`
- `if/minimax-m2`
**Qwen (`qw/`)** - 免费:
- `qw/qwen3-coder-plus`
- `qw/qwen3-coder-flash`
**Kiro (`kr/`)** - 免费:
- `kr/claude-sonnet-4.5`
- `kr/claude-haiku-4.5`
**OpenRouter (`or/`)** - 100+ 模型:
- `or/anthropic/claude-4-sonnet`
- `or/google/gemini-2.5-pro`
- [openrouter.ai/models](https://openrouter.ai/models) 上的任何模型
</details>
---
## 🧪 评估 (Evals)
OmniRoute 包含内置评估框架,用于针对黄金集测试 LLM 响应质量。通过仪表板中的 **Analytics → Evals** 访问。
### 内置黄金集
预加载的「OmniRoute Golden Set」包含 10 个测试用例:
- 问候、数学、地理、代码生成
- JSON 格式合规性、翻译、markdown
- 安全拒绝(有害内容)、计数、布尔逻辑
### 评估策略
| 策略 | 描述 | 示例 |
| ---------- | -------------------------------- | -------------------------------- |
| `exact` | 输出必须完全匹配 | `"4"` |
| `contains` | 输出必须包含子串(不区分大小写) | `"Paris"` |
| `regex` | 输出必须匹配正则表达式模式 | `"1.*2.*3"` |
| `custom` | 自定义 JS 函数返回 true/false | `(output) => output.length > 10` |
---
## 🐛 故障排除
<details>
@@ -924,7 +1329,7 @@ OmniRoute 包含内置评估框架,用于针对黄金集测试 LLM 响应质
---
## 🛠️ 技术栈
## 🛠️
- **运行时**: Node.js 20+
- **语言**: TypeScript 5.9 — `src/``open-sse/`**100% TypeScript**v1.0.6
@@ -943,29 +1348,20 @@ OmniRoute 包含内置评估框架,用于针对黄金集测试 LLM 响应质
## 📖 文档
| 文档 | 描述 |
| ----------------------------------- | ---------------------------- |
| [用户指南](docs/USER_GUIDE.md) | 提供商、组合、CLI 集成、部署 |
| [API 参考](docs/API_REFERENCE.md) | 所有端点及示例 |
| [故障排除](docs/TROUBLESHOOTING.md) | 常见问题和解决方案 |
| [架构](docs/ARCHITECTURE.md) | 系统架构和内部机制 |
| [贡献指南](CONTRIBUTING.md) | 开发设置和指南 |
| [OpenAPI 规范](docs/openapi.yaml) | OpenAPI 3.0 规范 |
| [安全策略](SECURITY.md) | 漏洞报告和安全实践 |
| 文档 | 描述 |
| ----------------------------------- | ------------------------------------------------------ |
| 🎯 **Endpoint-Aware Models** | Custom models declare supported endpoints + API format |
| [用户指南](docs/USER_GUIDE.md) | 提供商、组合、CLI 集成、部署 |
| [API 参考](docs/API_REFERENCE.md) | 所有端点及示例 |
| [故障排除](docs/TROUBLESHOOTING.md) | 常见问题和解决方案 |
| [架构](docs/ARCHITECTURE.md) | 系统架构和内部机制 |
| [贡献指南](CONTRIBUTING.md) | 开发设置和指南 |
| [OpenAPI 规范](docs/openapi.yaml) | OpenAPI 3.0 规范 |
| [安全策略](SECURITY.md) | 漏洞报告和安全实践 |
---
## 📧 支持
> 💬 **加入我们的社区!** [WhatsApp 群组](https://chat.whatsapp.com/JI7cDQ1GyaiDHhVBpLxf8b?mode=gi_t) — 获取帮助、分享技巧、了解最新动态。
- **网站**: [omniroute.online](https://omniroute.online)
- **GitHub**: [github.com/diegosouzapw/OmniRoute](https://github.com/diegosouzapw/OmniRoute)
- **Issues**: [github.com/diegosouzapw/OmniRoute/issues](https://github.com/diegosouzapw/OmniRoute/issues)
- **WhatsApp**: [社区群组](https://chat.whatsapp.com/JI7cDQ1GyaiDHhVBpLxf8b?mode=gi_t)
- **原始项目**: [decolua 的 9router](https://github.com/decolua/9router)
---
## 🗺️
## 👥 贡献者

65
bin/mcp-server.mjs Normal file
View File

@@ -0,0 +1,65 @@
#!/usr/bin/env node
import { spawn } from "node:child_process";
import { existsSync } from "node:fs";
import { dirname, join } from "node:path";
import { fileURLToPath } from "node:url";
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
const ROOT = join(__dirname, "..");
function resolveMcpEntry(rootDir = ROOT) {
const candidates = [
// Preferred distributable JS entry (npm publish artifact)
join(rootDir, "app", "open-sse", "mcp-server", "server.js"),
// Local workspace TypeScript source fallback
join(rootDir, "open-sse", "mcp-server", "server.ts"),
];
for (const entry of candidates) {
if (existsSync(entry)) return entry;
}
return null;
}
function formatSpawnError(exitCode, signal) {
if (signal) return `MCP server exited by signal ${signal}`;
return `MCP server exited with code ${exitCode ?? 1}`;
}
export async function startMcpCli(rootDir = ROOT) {
const mcpEntry = resolveMcpEntry(rootDir);
if (!mcpEntry) {
throw new Error(
"MCP server entrypoint not found. Expected app/open-sse/mcp-server/server.js or open-sse/mcp-server/server.ts."
);
}
// `tsx` loader is only required for local `.ts` fallback; JS entry works without it.
const loaderArgs = mcpEntry.endsWith(".ts") ? ["--import", "tsx/esm"] : [];
await new Promise((resolve, reject) => {
const child = spawn(process.execPath, [...loaderArgs, mcpEntry], {
cwd: rootDir,
env: process.env,
stdio: "inherit",
});
child.once("error", reject);
child.once("exit", (code, signal) => {
if ((code ?? 0) === 0 && !signal) {
resolve(undefined);
return;
}
reject(new Error(formatSpawnError(code, signal)));
});
});
}
if (process.argv[1] && fileURLToPath(import.meta.url) === process.argv[1]) {
startMcpCli().catch((err) => {
console.error("\x1b[31m✖ Failed to start MCP server:\x1b[0m", err?.message || err);
process.exit(1);
});
}

View File

@@ -7,6 +7,7 @@
* omniroute Start the server (default port 20128)
* omniroute --port 3000 Start on custom port
* omniroute --no-open Start without opening browser
* omniroute --mcp Start MCP server (stdio transport for IDEs)
* omniroute --help Show help
* omniroute --version Show version
*/
@@ -86,9 +87,17 @@ if (args.includes("--help") || args.includes("-h")) {
omniroute Start the server
omniroute --port <port> Use custom API port (default: 20128)
omniroute --no-open Don't open browser automatically
omniroute --mcp Start MCP server (stdio transport for IDEs)
omniroute --help Show this help
omniroute --version Show version
\x1b[1mMCP Integration:\x1b[0m
The --mcp flag starts an MCP server over stdio, exposing OmniRoute
tools for AI agents in VS Code, Cursor, Claude Desktop, and Copilot.
Available tools: omniroute_get_health, omniroute_list_combos,
omniroute_check_quota, omniroute_route_request, and more.
\x1b[1mConfig:\x1b[0m
Loads .env from: ~/.omniroute/.env or ./.env
Memory limit: OMNIROUTE_MEMORY_MB (default: 512)
@@ -116,6 +125,18 @@ if (args.includes("--version") || args.includes("-v")) {
process.exit(0);
}
// ── MCP Server Mode ───────────────────────────────────────
if (args.includes("--mcp")) {
try {
const { startMcpCli } = await import(join(ROOT, "bin", "mcp-server.mjs"));
await startMcpCli(ROOT);
} catch (err) {
console.error("\x1b[31m✖ Failed to start MCP server:\x1b[0m", err.message || err);
process.exit(1);
}
process.exit(0);
}
function parsePort(value, fallback) {
const parsed = parseInt(String(value), 10);
return Number.isFinite(parsed) && parsed > 0 && parsed <= 65535 ? parsed : fallback;

View File

@@ -2,7 +2,7 @@
🌐 **Languages:** 🇺🇸 [English](ARCHITECTURE.md) | 🇧🇷 [Português (Brasil)](i18n/pt-BR/ARCHITECTURE.md) | 🇪🇸 [Español](i18n/es/ARCHITECTURE.md) | 🇫🇷 [Français](i18n/fr/ARCHITECTURE.md) | 🇮🇹 [Italiano](i18n/it/ARCHITECTURE.md) | 🇷🇺 [Русский](i18n/ru/ARCHITECTURE.md) | 🇨🇳 [中文 (简体)](i18n/zh-CN/ARCHITECTURE.md) | 🇩🇪 [Deutsch](i18n/de/ARCHITECTURE.md) | 🇮🇳 [हिन्दी](i18n/in/ARCHITECTURE.md) | 🇹🇭 [ไทย](i18n/th/ARCHITECTURE.md) | 🇺🇦 [Українська](i18n/uk-UA/ARCHITECTURE.md) | 🇸🇦 [العربية](i18n/ar/ARCHITECTURE.md) | 🇯🇵 [日本語](i18n/ja/ARCHITECTURE.md) | 🇻🇳 [Tiếng Việt](i18n/vi/ARCHITECTURE.md) | 🇧🇬 [Български](i18n/bg/ARCHITECTURE.md) | 🇩🇰 [Dansk](i18n/da/ARCHITECTURE.md) | 🇫🇮 [Suomi](i18n/fi/ARCHITECTURE.md) | 🇮🇱 [עברית](i18n/he/ARCHITECTURE.md) | 🇭🇺 [Magyar](i18n/hu/ARCHITECTURE.md) | 🇮🇩 [Bahasa Indonesia](i18n/id/ARCHITECTURE.md) | 🇰🇷 [한국어](i18n/ko/ARCHITECTURE.md) | 🇲🇾 [Bahasa Melayu](i18n/ms/ARCHITECTURE.md) | 🇳🇱 [Nederlands](i18n/nl/ARCHITECTURE.md) | 🇳🇴 [Norsk](i18n/no/ARCHITECTURE.md) | 🇵🇹 [Português (Portugal)](i18n/pt/ARCHITECTURE.md) | 🇷🇴 [Română](i18n/ro/ARCHITECTURE.md) | 🇵🇱 [Polski](i18n/pl/ARCHITECTURE.md) | 🇸🇰 [Slovenčina](i18n/sk/ARCHITECTURE.md) | 🇸🇪 [Svenska](i18n/sv/ARCHITECTURE.md) | 🇵🇭 [Filipino](i18n/phi/ARCHITECTURE.md)
_Last updated: 2026-02-18_
_Last updated: 2026-03-04_
## Executive Summary
@@ -81,8 +81,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]
@@ -144,7 +144,7 @@ Management domains:
- 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/catalog` (GET)
- Model catalog: `src/app/api/models/route.ts` (GET)
- Proxy config: `src/app/api/settings/proxy` (GET/PUT/DELETE) + `src/app/api/settings/proxy/test` (POST)
- OAuth: `src/app/api/oauth/*`
- Keys/aliases/combos/pricing: `src/app/api/keys*`, `src/app/api/models/alias`, `src/app/api/combos*`, `src/app/api/pricing`
@@ -225,18 +225,19 @@ OAuth provider modules (12 individual files under `src/lib/oauth/providers/`):
## 3) Persistence Layer
Primary state DB:
Primary state DB (SQLite):
- `src/lib/localDb.ts`
- file: `${DATA_DIR}/db.json` (or `$XDG_CONFIG_HOME/omniroute/db.json` when set, else `~/.omniroute/db.json`)
- entities: providerConnections, providerNodes, modelAliases, combos, apiKeys, settings, pricing, **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 DB:
Usage persistence:
- `src/lib/usageDb.ts`
- files: `${DATA_DIR}/usage.json`, `${DATA_DIR}/log.txt`, `${DATA_DIR}/call_logs/`
- follows same base directory policy as `localDb` (`DATA_DIR`, then `XDG_CONFIG_HOME/omniroute` when set)
- decomposed into focused sub-modules: `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
Domain State DB (SQLite):
@@ -505,9 +506,9 @@ erDiagram
Physical storage files:
- main state: `${DATA_DIR}/db.json` (or `$XDG_CONFIG_HOME/omniroute/db.json` when set, else `~/.omniroute/db.json`)
- usage stats: `${DATA_DIR}/usage.json`
- request log lines: `${DATA_DIR}/log.txt`
- 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
@@ -522,8 +523,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]
@@ -550,7 +551,7 @@ flowchart LR
- `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/catalog`: full model catalog API (all types grouped by provider)
- `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
@@ -582,8 +583,9 @@ flowchart LR
### Persistence
- `src/lib/localDb.ts`: persistent config/state
- `src/lib/usageDb.ts`: usage history and rolling request logs
- `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)
@@ -724,23 +726,23 @@ Files are written to `<repo>/logs/<session>/` for each request session.
## 5) Data Integrity
- DB shape migration/repair for missing keys
- corrupt JSON reset safeguards for localDb and usageDb
- SQLite schema migrations and auto-upgrade hooks at startup
- legacy JSON → SQLite migration compatibility path
## Observability and Operational Signals
Runtime visibility sources:
- console logs from `src/sse/utils/logger.ts`
- per-request usage aggregates in `usage.json`
- textual request status log in `log.txt`
- per-request usage aggregates in SQLite (`usage_history`, `call_logs`, `proxy_logs`)
- textual request status log in `log.txt` (optional/compat)
- optional deep request/translation logs under `logs/` when `ENABLE_REQUEST_LOGS=true`
- dashboard usage endpoints (`/api/usage/*`) for UI consumption
## Security-Sensitive Boundaries
- JWT secret (`JWT_SECRET`) secures dashboard session cookie verification/signing
- Initial password fallback (`INITIAL_PASSWORD`, default `123456`) must be overridden in real deployments
- 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
@@ -762,13 +764,13 @@ Environment variables actively used by code:
## Known Architectural Notes
1. `usageDb` and `localDb` now share the same base directory policy (`DATA_DIR` -> `XDG_CONFIG_HOME/omniroute` -> `~/.omniroute`) with legacy file migration.
2. `/api/v1/route.ts` returns a static model list and is not the main models source used by `/v1/models`.
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:plan3`. Source code under `src/` is **TypeScript** (`.ts`/`.tsx`); the `open-sse/` workspace remains JavaScript (`.js`).
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

View File

@@ -48,7 +48,7 @@ Four modes for debugging API translations: **Playground** (format converter), **
## ⚙️ Settings
General settings, system storage, backup management (export/import database), appearance (dark/light mode), security (includes API endpoint protection and custom provider blocking), routing, resilience, and advanced configuration.
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.
![Settings Dashboard](screenshots/06-settings.png)
@@ -56,7 +56,7 @@ 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, and Antigravity.
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`).
![CLI Tools Dashboard](screenshots/07-cli-tools.png)
@@ -75,3 +75,19 @@ Real-time request logging with filtering by provider, model, account, and API ke
Your unified API endpoint with capability breakdown: Chat Completions, Embeddings, Image Generation, Reranking, Audio Transcription, and registered API keys.
![Endpoint Dashboard](screenshots/09-endpoint.png)
---
## 🖥️ 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.
Key features:
- Server readiness polling (no blank screen on cold start)
- System tray with port management
- Content Security Policy
- Single-instance lock
- Platform-conditional UI (macOS traffic lights, Windows/Linux default titlebar)
📖 See [`electron/README.md`](../electron/README.md) for full documentation.

33
docs/RELEASE_CHECKLIST.md Normal file
View File

@@ -0,0 +1,33 @@
# 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).

View File

@@ -10,7 +10,7 @@ Common problems and solutions for OmniRoute.
| Problem | Solution |
| ----------------------------- | ------------------------------------------------------------------ |
| First login not working | Check `INITIAL_PASSWORD` in `.env` (default: `123456`) |
| 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` |
@@ -120,8 +120,8 @@ curl http://localhost:20128/api/monitoring/health
### Runtime Storage
- Main state: `${DATA_DIR}/db.json` (providers, combos, aliases, keys, settings)
- Usage: `${DATA_DIR}/usage.json`, `${DATA_DIR}/log.txt`, `${DATA_DIR}/call_logs/`
- 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`)
---
@@ -210,6 +210,41 @@ When many concurrent requests hit a rate-limited provider, OmniRoute uses mutex
---
## Optional RAG / LLM failure taxonomy (16 problems)
Some OmniRoute users place the gateway in front of RAG or agent stacks. In those setups it is common to see a strange pattern: OmniRoute looks healthy (providers up, routing profiles ok, no rate limit alerts) but the final answer is still wrong.
In practice these incidents usually come from the downstream RAG pipeline, not from the gateway itself.
If you want a shared vocabulary to describe those failures you can use the WFGY ProblemMap, an external MIT license text resource that defines sixteen recurring RAG / LLM failure patterns. At a high level it covers:
- retrieval drift and broken context boundaries
- empty or stale indexes and vector stores
- embedding versus semantic mismatch
- prompt assembly and context window issues
- logic collapse and overconfident answers
- long chain and agent coordination failures
- multi agent memory and role drift
- deployment and bootstrap ordering problems
The idea is simple:
1. When you investigate a bad response, capture:
- user task and request
- route or provider combo in OmniRoute
- any RAG context used downstream (retrieved documents, tool calls, etc)
2. Map the incident to one or two WFGY ProblemMap numbers (`No.1``No.16`).
3. Store the number in your own dashboard, runbook, or incident tracker next to the OmniRoute logs.
4. Use the corresponding WFGY page to decide whether you need to change your RAG stack, retriever, or routing strategy.
Full text and concrete recipes live here (MIT license, text only):
[WFGY ProblemMap README](https://github.com/onestardao/WFGY/blob/main/ProblemMap/README.md)
You can ignore this section if you do not run RAG or agent pipelines behind OmniRoute.
---
## Still Stuck?
- **GitHub Issues**: [github.com/diegosouzapw/OmniRoute/issues](https://github.com/diegosouzapw/OmniRoute/issues)

View File

@@ -755,3 +755,55 @@ Access via **Dashboard → Health**. Real-time system health overview with 6 car
| **Latency Telemetry** | p50/p95/p99 latency aggregation per provider |
**Pro Tip:** The Health page auto-refreshes every 10 seconds. Use the circuit breaker card to identify which providers are experiencing issues.
---
## 🖥️ Desktop Application (Electron)
OmniRoute is available as a native desktop application for Windows, macOS, and Linux.
### 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)

View File

@@ -16,7 +16,7 @@ Administrer AI-udbyderforbindelser: OAuth-udbydere (Claude Code, Codex, Gemini C
## 🎨 Kombinationer
Opret modelrouting-kombinationer med 6 strategier: Fyld-først, round-robin, power-of-to-choices, tilfældig, mindst brugt og omkostningsoptimeret. Hver combo kæder flere modeller med automatisk fallback.
Opret modelrouting (model aliases, background task degradation)-kombinationer med 6 strategier: Fyld-først, round-robin, power-of-to-choices, tilfældig, mindst brugt og omkostningsoptimeret. Hver combo kæder flere modeller med automatisk fallback.
![Combos Dashboard](screenshots/02-combos.png)

View File

@@ -16,7 +16,7 @@ Gestisci le connessioni dei provider AI: provider OAuth (Claude Code, Codex, Gem
## 🎨Combo
Crea combinazioni di routing del modello con 6 strategie: riempimento prima, round robin, scelta potenza di due, casuale, meno utilizzata e con ottimizzazione dei costi. Ogni combo concatena più modelli con fallback automatico.
Crea combinazioni di routing (model aliases, background task degradation) del modello con 6 strategie: riempimento prima, round robin, scelta potenza di due, casuale, meno utilizzata e con ottimizzazione dei costi. Ogni combo concatena più modelli con fallback automatico.
![Combos Dashboard](screenshots/02-combos.png)

View File

@@ -48,7 +48,7 @@ Vier modi voor het debuggen van API-vertalingen: **Playground** (formaatconverte
## ⚙️ Instellingen
Algemene instellingen, systeemopslag, back-upbeheer (database exporteren/importeren), uiterlijk (donker/licht-modus), beveiliging (inclusief API-eindpuntbescherming en aangepaste providerblokkering), routing, veerkracht en geavanceerde configuratie.
Algemene instellingen, systeemopslag, back-upbeheer (database exporteren/importeren), uiterlijk (donker/licht-modus), beveiliging (inclusief API-eindpuntbescherming en aangepaste providerblokkering), routing (model aliases, background task degradation), veerkracht en geavanceerde configuratie.
![Settings Dashboard](screenshots/06-settings.png)

View File

@@ -48,7 +48,7 @@ Apat na mode para sa pag-debug ng mga pagsasalin ng API: **Playground** (format
## ⚙️ Mga Setting
Mga pangkalahatang setting, system storage, backup management (export/import database), hitsura (dark/light mode), seguridad (kasama ang API endpoint protection at custom provider blocking), routing, resilience, at advanced configuration.
Mga pangkalahatang setting, system storage, backup management (export/import database), hitsura (dark/light mode), seguridad (kasama ang API endpoint protection at custom provider blocking), routing (model aliases, background task degradation), resilience, at advanced configuration.
![Settings Dashboard](screenshots/06-settings.png)

View File

@@ -16,7 +16,7 @@ Zarządzaj połączeniami dostawców AI: dostawcy OAuth (Claude Code, Codex, Gem
## 🎨 Kombinacje
Twórz kombinacje routingu modeli za pomocą 6 strategii: najpierw wypełnij, okrężnie, siła dwóch wyborów, losowa, najrzadziej używana i zoptymalizowana pod względem kosztów. Każda kombinacja łączy wiele modeli z automatycznym cofaniem.
Twórz kombinacje routing (model aliases, background task degradation)u modeli za pomocą 6 strategii: najpierw wypełnij, okrężnie, siła dwóch wyborów, losowa, najrzadziej używana i zoptymalizowana pod względem kosztów. Każda kombinacja łączy wiele modeli z automatycznym cofaniem.
![Combos Dashboard](screenshots/02-combos.png)

View File

@@ -16,7 +16,7 @@ Hantera AI-leverantörsanslutningar: OAuth-leverantörer (Claude Code, Codex, Ge
## 🎨 Combos
Skapa modell routing-kombinationer med 6 strategier: fyll först, round-robin, kraft-av-två-val, slumpmässig, minst använda och kostnadsoptimerad. Varje combo kedjer flera modeller med automatisk reserv.
Skapa modell routing (model aliases, background task degradation)-kombinationer med 6 strategier: fyll först, round-robin, kraft-av-två-val, slumpmässig, minst använda och kostnadsoptimerad. Varje combo kedjer flera modeller med automatisk reserv.
![Combos Dashboard](screenshots/02-combos.png)

View File

@@ -1,7 +1,7 @@
openapi: 3.1.0
info:
title: OmniRoute API
version: 0.5.0
version: 2.0.0
description: |
OmniRoute is a local-first AI API proxy router. It provides an OpenAI-compatible
endpoint that routes requests to multiple AI providers with load balancing,

View File

@@ -2,27 +2,43 @@
This directory contains the Electron desktop application wrapper for OmniRoute.
## Structure
## Architecture (v1.6.4)
```
electron/
├── main.js # Main process (window management, IPC)
├── preload.js # Preload script (secure bridge to renderer)
├── package.json # Electron-specific dependencies
├── types.d.ts # TypeScript definitions
├── main.js # Main process window, tray, server lifecycle, CSP, IPC
├── preload.js # Preload script secure IPC bridge with disposer pattern
├── package.json # Electron-specific dependencies & electron-builder config
├── types.d.ts # TypeScript definitions (AppInfo, ServerStatus, ElectronAPI)
└── assets/ # Application icons and resources
src/shared/hooks/
└── useElectron.ts # React hooks — useSyncExternalStore, zero re-renders
```
## Key Design Decisions
| Decision | Rationale |
| ----------------------------- | ------------------------------------------------------------------------------------------------ |
| `waitForServer()` polling | Prevents blank screen on cold start — polls `http://localhost:PORT` before loading |
| `stdio: 'pipe'` | Captures server stdout/stderr for logging + readiness detection (not `inherit`) |
| Disposer pattern | `onServerStatus()` returns `() => void` for precise listener cleanup (no `removeAllListeners`) |
| `useSyncExternalStore` | Zero re-renders for `useIsElectron()` — no `useState` + `useEffect` cycle |
| CSP via session headers | `Content-Security-Policy` restricts `script-src`, `connect-src` etc. per Electron best practices |
| Platform-conditional titlebar | `titleBarStyle: 'hiddenInset'` only on macOS; `default` on Windows/Linux |
## Development
### Prerequisites
1. Build the Next.js app first:
```bash
npm run build
```
2. Install Electron dependencies:
```bash
cd electron
npm install
@@ -31,11 +47,13 @@ npm install
### Running in Development
1. Start the Next.js development server:
```bash
npm run dev
```
2. In another terminal, start Electron:
```bash
cd electron
npm run dev
@@ -44,11 +62,13 @@ npm run dev
### Running in Production Mode
1. Build Next.js in standalone mode:
```bash
npm run build
```
2. Start Electron:
```bash
cd electron
npm start
@@ -57,6 +77,7 @@ npm start
## Building
### Build for Current Platform
```bash
cd electron
npm run build
@@ -68,7 +89,7 @@ npm run build
# Windows
npm run build:win
# macOS
# macOS (x64 + arm64)
npm run build:mac
# Linux
@@ -78,72 +99,151 @@ npm run build:linux
## Output
Built applications are placed in `dist-electron/`:
- Windows: `.exe` installer (NSIS)
- macOS: `.dmg` installer
- Windows: `.exe` installer (NSIS) + portable `.exe`
- macOS: `.dmg` installer (Intel + Apple Silicon)
- Linux: `.AppImage`
## Installation
### macOS
1. Download the latest `.dmg` from the [Releases](https://github.com/diegosouzapw/OmniRoute/releases) page.
2. Open the `.dmg` file.
3. Drag `OmniRoute.app` to the Applications folder.
4. Launch from Applications.
> ⚠️ **Note:** The app is not signed with an Apple Developer certificate yet. If macOS blocks the app, run:
> ```bash
> xattr -cr /Applications/OmniRoute.app
> ```
> Or right-click the app → Open → Open (to bypass Gatekeeper on first launch).
### Windows
**Installer (Recommended):**
1. Download `OmniRoute.Setup.*.exe` from [Releases](https://github.com/diegosouzapw/OmniRoute/releases).
2. Run the installer.
3. Launch from Start Menu or Desktop shortcut.
**Portable (No Installation):**
1. Download `OmniRoute.exe` from [Releases](https://github.com/diegosouzapw/OmniRoute/releases).
2. Run directly from any folder.
### Linux
1. Download the `.AppImage` from [Releases](https://github.com/diegosouzapw/OmniRoute/releases).
2. Make it executable:
```bash
chmod +x OmniRoute-*.AppImage
```
3. Run:
```bash
./OmniRoute-*.AppImage
```
## Features
- **System Tray Integration**: Minimize to tray, quick actions
- **Native Notifications**: Desktop notifications
- **Window Management**: Minimize, maximize, close
- **Auto-start**: Option to launch on system startup
- **Offline Support**: Local server bundled with the app
- **Server Readiness** — Waits for health check before showing window
- **System Tray** — Minimize to tray with quick actions (open, port change, quit)
- **Port Management** — Change port from tray menu (server restarts automatically)
- **Window Controls** — Custom minimize, maximize, close via IPC
- **Content Security Policy** — Restrictive CSP via session headers
- **Offline Support** — Bundled Next.js standalone server
- **Single Instance** — Only one app instance can run at a time
## Configuration
### Environment Variables
The Electron app respects these environment variables:
- `OMNIROUTE_PORT`: Server port (default: 20128)
- `NODE_ENV`: Set to 'production' for production builds
| Variable | Default | Description |
| --------------------- | ------------ | --------------------------------- |
| `OMNIROUTE_PORT` | `20128` | Server port |
| `OMNIROUTE_MEMORY_MB` | `512` | Node.js heap limit (6416384 MB) |
| `NODE_ENV` | `production` | Set to `development` for dev mode |
### Custom Icon
Place your icons in `assets/`:
- `icon.ico` - Windows icon (256x256)
- `icon.icns` - macOS icon bundle
- `icon.png` - Linux/general use (512x512)
- `tray-icon.png` - System tray icon (16x16 or 32x32)
- `icon.ico` — Windows icon (256×256)
- `icon.icns` — macOS icon bundle
- `icon.png` — Linux/general use (512×512)
- `tray-icon.png` — System tray icon (16×16 or 32×32)
## IPC Channels
| Channel | Direction | Description |
|---------|-----------|-------------|
| `get-app-info` | Renderer → Main | Get app name, version, platform |
| `open-external` | Renderer → Main | Open URL in default browser |
| `get-data-dir` | Renderer → Main | Get data directory path |
| `restart-server` | Renderer → Main | Restart the internal server |
| `server-status` | Main → Renderer | Server status updates |
| `port-changed` | Main → Renderer | Port change notifications |
### Invoke (Renderer → Main, async)
| Channel | Returns | Description |
| ---------------- | ------------- | --------------------------------------------- |
| `get-app-info` | `AppInfo` | App name, version, platform, isDev, port |
| `open-external` | `void` | Open URL in default browser (http/https only) |
| `get-data-dir` | `string` | Get userData directory path |
| `restart-server` | `{ success }` | Stop + restart server (5s timeout + SIGKILL) |
### Send (Renderer → Main, fire-and-forget)
| Channel | Description |
| ----------------- | ------------------------------- |
| `window-minimize` | Minimize window |
| `window-maximize` | Toggle maximize/restore |
| `window-close` | Close window (minimize to tray) |
### Receive (Main → Renderer, events)
| Channel | Payload | Emitted When |
| --------------- | -------------- | ----------------------------------------- |
| `server-status` | `ServerStatus` | Server starts, stops, errors, or restarts |
| `port-changed` | `number` | Port change via tray menu |
> **Note**: Listeners return disposer functions for precise cleanup. See `useServerStatus` and `usePortChanged` hooks.
## Security
- `contextIsolation: true` - Isolates renderer from Node.js
- `nodeIntegration: false` - No direct Node.js access in renderer
- Preload script validates IPC channels
- No remote code execution
| Feature | Implementation |
| ----------------- | ------------------------------------------------------------------------------- |
| Context Isolation | `contextIsolation: true` — renderer cannot access Node.js |
| Node Integration | `nodeIntegration: false` — no `require()` in renderer |
| IPC Whitelist | Channel names validated in preload via `safeInvoke`/`safeSend`/`safeOn` |
| URL Validation | `shell.openExternal()` only allows `http:` / `https:` protocols |
| CSP | `Content-Security-Policy` header set via `session.webRequest.onHeadersReceived` |
| Web Security | `webSecurity: true` — same-origin policy enforced |
## React Hooks
| Hook | Returns | Description |
| ---------------------- | ------------------------------- | ------------------------------------------------ |
| `useIsElectron()` | `boolean` | Zero-render detection via `useSyncExternalStore` |
| `useElectronAppInfo()` | `{ appInfo, loading, error }` | App info from main process |
| `useDataDir()` | `{ dataDir, loading, error }` | User data directory |
| `useWindowControls()` | `{ minimize, maximize, close }` | Window control actions |
| `useOpenExternal()` | `{ openExternal }` | Open URLs in browser |
| `useServerControls()` | `{ restart, restarting }` | Server restart control |
| `useServerStatus(cb)` | Disposer | Listen for server status events |
| `usePortChanged(cb)` | Disposer | Listen for port change events |
## Troubleshooting
### App Won't Start
1. Check if port 20128 is available
2. Check logs in the console
3. Verify the build output exists
1. Check if port 20128 is available: `lsof -i :20128`
2. Check console logs for `[Electron]` prefix
3. Verify the build output exists in `.next/standalone`
### White Screen
1. Verify Next.js build exists
2. Check the server URL in main.js
3. Check for console errors
1. Verify Next.js build exists — server readiness waits 30s max
2. Check `[Server]` and `[Server:err]` log output
3. Look for CSP violations in developer console
### Build Fails
1. Ensure you have build tools installed:
- Windows: Visual Studio Build Tools
- macOS: Xcode Command Line Tools
- Linux: build-essential, libsecret-1-dev
Ensure you have build tools installed:
- Windows: Visual Studio Build Tools
- macOS: Xcode Command Line Tools
- Linux: `build-essential`, `libsecret-1-dev`
## License

BIN
electron/assets/icon.icns Normal file

Binary file not shown.

BIN
electron/assets/icon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 138 KiB

BIN
electron/assets/icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 713 B

View File

@@ -1,6 +1,6 @@
{
"name": "omniroute-desktop",
"version": "1.6.4",
"version": "1.6.9",
"description": "OmniRoute Desktop Application",
"main": "main.js",
"author": "OmniRoute Team",
@@ -17,7 +17,7 @@
},
"dependencies": {},
"devDependencies": {
"electron": "^33.0.0",
"electron": "^40.6.1",
"electron-builder": "^25.1.8"
},
"build": {
@@ -63,6 +63,12 @@
"arch": [
"x64"
]
},
{
"target": "portable",
"arch": [
"x64"
]
}
],
"icon": "assets/icon.ico"

View File

@@ -70,6 +70,40 @@ export const AUDIO_TRANSCRIPTION_PROVIDERS: Record<string, AudioProvider> = {
{ id: "universal-2", name: "Universal 2" },
],
},
nvidia: {
id: "nvidia",
baseUrl: "https://integrate.api.nvidia.com/v1/audio/transcriptions",
authType: "apikey",
authHeader: "bearer",
format: "nvidia-asr",
models: [
{ id: "nvidia/parakeet-ctc-1.1b-asr", name: "Parakeet CTC 1.1B" },
],
},
huggingface: {
id: "huggingface",
baseUrl: "https://api-inference.huggingface.co/models",
authType: "apikey",
authHeader: "bearer",
format: "huggingface-asr",
models: [
{ id: "openai/whisper-large-v3", name: "Whisper Large v3 (HF)" },
{ id: "openai/whisper-small", name: "Whisper Small (HF)" },
],
},
qwen: {
id: "qwen",
baseUrl: "http://localhost:8000/v1/audio/transcriptions",
authType: "none",
authHeader: "none",
format: "openai",
models: [
{ id: "qwen3-asr", name: "Qwen3 ASR" },
],
},
};
export const AUDIO_SPEECH_PROVIDERS: Record<string, AudioProvider> = {
@@ -106,6 +140,75 @@ export const AUDIO_SPEECH_PROVIDERS: Record<string, AudioProvider> = {
{ id: "aura-stella-en", name: "Aura Stella (EN)" },
],
},
nvidia: {
id: "nvidia",
baseUrl: "https://integrate.api.nvidia.com/v1/audio/speech",
authType: "apikey",
authHeader: "bearer",
format: "nvidia-tts",
models: [
{ id: "nvidia/fastpitch", name: "FastPitch" },
{ id: "nvidia/tacotron2", name: "Tacotron2" },
],
},
elevenlabs: {
id: "elevenlabs",
baseUrl: "https://api.elevenlabs.io/v1/text-to-speech",
authType: "apikey",
authHeader: "xi-api-key",
format: "elevenlabs",
models: [
{ id: "eleven_multilingual_v2", name: "Eleven Multilingual v2" },
{ id: "eleven_turbo_v2_5", name: "Eleven Turbo v2.5" },
],
},
huggingface: {
id: "huggingface",
baseUrl: "https://api-inference.huggingface.co/models",
authType: "apikey",
authHeader: "bearer",
format: "huggingface-tts",
models: [
{ id: "facebook/mms-tts-eng", name: "MMS TTS English" },
{ id: "microsoft/speecht5_tts", name: "SpeechT5 TTS" },
],
},
coqui: {
id: "coqui",
baseUrl: "http://localhost:5002/api/tts",
authType: "none",
authHeader: "none",
format: "coqui",
models: [
{ id: "tts_models/en/ljspeech/tacotron2-DDC", name: "Tacotron2 DDC (LJSpeech)" },
],
},
tortoise: {
id: "tortoise",
baseUrl: "http://localhost:5000/api/tts",
authType: "none",
authHeader: "none",
format: "tortoise",
models: [
{ id: "tortoise-v2", name: "Tortoise v2" },
],
},
qwen: {
id: "qwen",
baseUrl: "http://localhost:8000/v1/audio/speech",
authType: "none",
authHeader: "none",
format: "openai",
models: [
{ id: "qwen3-tts", name: "Qwen3 TTS" },
],
},
};
/**

View File

@@ -55,7 +55,7 @@ When you are running with \`approval_policy == on-request\`, and sandboxing enab
- You are about to take a potentially destructive action such as an \`rm\` or \`git reset\` that the user did not explicitly ask for
- (for all of these, you should weigh alternative paths that do not require approval)
When \`sandbox_mode\` is set to read-only, you'll need to request approval for any command that isn't a read.
When \`sandbox_mode\` is set to read-only, you'll need to request approval for each command that isn't a read.
You will be told what filesystem sandboxing, network sandboxing, and approval mode are active in a developer or user message. If you are not told about this, assume that you are running with workspace-write, network sandboxing enabled, and approval on-failure.
@@ -68,7 +68,7 @@ When requesting approval to execute a command that will require escalated privil
## Special user requests
- If the user makes a simple request (such as asking for the time) which you can fulfill by running a terminal command (such as \`date\`), you should do so.
- If the user asks for a "review", default to a code review mindset: prioritise identifying bugs, risks, behavioural regressions, and missing tests. Findings must be the primary focus of the response - keep summaries or overviews brief and only after enumerating the issues. Present findings first (ordered by severity with file/line references), follow with open questions or assumptions, and offer a change-summary only as a secondary detail. If no findings are discovered, state that explicitly and mention any residual risks or testing gaps.
- If the user asks for a "review", default to a code review mindset: prioritise identifying bugs, risks, behavioural regressions, and missing tests. Findings must be the primary focus of the response - keep summaries or overviews brief and only after enumerating the issues. Present findings first (ordered by severity with file/line references), follow with open questions or assumptions, and offer a change-summary only as a secondary detail. If no findings are discovered, state that explicitly and mention residual risks or testing gaps.
## Frontend tasks
When doing frontend design tasks, avoid collapsing into "AI slop" or safe, average-looking layouts.

View File

@@ -108,6 +108,32 @@ export const IMAGE_PROVIDERS = {
],
supportedSizes: ["1024x1024"],
},
sdwebui: {
id: "sdwebui",
baseUrl: "http://localhost:7860/sdapi/v1/txt2img",
authType: "none",
authHeader: "none",
format: "sdwebui",
models: [
{ id: "stable-diffusion-v1-5", name: "Stable Diffusion v1.5" },
{ id: "sdxl-base-1.0", name: "SDXL Base 1.0" },
],
supportedSizes: ["512x512", "768x768", "1024x1024"],
},
comfyui: {
id: "comfyui",
baseUrl: "http://localhost:8188",
authType: "none",
authHeader: "none",
format: "comfyui",
models: [
{ id: "flux-dev", name: "FLUX Dev" },
{ id: "sdxl", name: "SDXL" },
],
supportedSizes: ["512x512", "768x768", "1024x1024"],
},
};
/**
@@ -131,7 +157,7 @@ export function parseImageModel(modelStr) {
}
}
// No provider prefix — try to find the model in any provider
// No provider prefix — try to find the model in every provider
for (const [providerId, config] of Object.entries(IMAGE_PROVIDERS)) {
if (config.models.some((m) => m.id === modelStr)) {
return { provider: providerId, model: modelStr };

View File

@@ -0,0 +1,57 @@
/**
* Music Generation Provider Registry
*
* Defines providers that support the /v1/music/generations endpoint.
* Currently supports local providers (ComfyUI with audio models).
*/
import { parseModelFromRegistry, getAllModelsFromRegistry } from "./registryUtils.ts";
interface MusicModel {
id: string;
name: string;
}
interface MusicProvider {
id: string;
baseUrl: string;
authType: string;
authHeader: string;
format: string;
models: MusicModel[];
}
export const MUSIC_PROVIDERS: Record<string, MusicProvider> = {
comfyui: {
id: "comfyui",
baseUrl: "http://localhost:8188",
authType: "none",
authHeader: "none",
format: "comfyui",
models: [
{ id: "stable-audio-open", name: "Stable Audio Open" },
{ id: "musicgen-medium", name: "MusicGen Medium" },
],
},
};
/**
* Get music provider config by ID
*/
export function getMusicProvider(providerId: string): MusicProvider | null {
return MUSIC_PROVIDERS[providerId] || null;
}
/**
* Parse music model string (format: "provider/model" or just "model")
*/
export function parseMusicModel(modelStr: string | null) {
return parseModelFromRegistry(modelStr, MUSIC_PROVIDERS);
}
/**
* Get all music models as a flat list
*/
export function getAllMusicModels() {
return getAllModelsFromRegistry(MUSIC_PROVIDERS);
}

View File

@@ -1,4 +1,4 @@
import { generateModels, generateAliasMap } from "./providerRegistry.ts";
import { generateModels, generateAliasMap, type RegistryModel } from "./providerRegistry.ts";
// Provider models - Generated from providerRegistry.js (single source of truth)
export const PROVIDER_MODELS = generateModels();
@@ -7,37 +7,41 @@ export const PROVIDER_MODELS = generateModels();
export const PROVIDER_ID_TO_ALIAS = generateAliasMap();
// Helper functions
export function getProviderModels(aliasOrId) {
export function getProviderModels(aliasOrId: string): RegistryModel[] {
return PROVIDER_MODELS[aliasOrId] || [];
}
export function getDefaultModel(aliasOrId) {
export function getDefaultModel(aliasOrId: string): string | null {
const models = PROVIDER_MODELS[aliasOrId];
return models?.[0]?.id || null;
}
export function isValidModel(aliasOrId, modelId, passthroughProviders = new Set()) {
export function isValidModel(
aliasOrId: string,
modelId: string,
passthroughProviders = new Set<string>()
): boolean {
if (passthroughProviders.has(aliasOrId)) return true;
const models = PROVIDER_MODELS[aliasOrId];
if (!models) return false;
return models.some((m) => m.id === modelId);
}
export function findModelName(aliasOrId, modelId) {
export function findModelName(aliasOrId: string, modelId: string): string {
const models = PROVIDER_MODELS[aliasOrId];
if (!models) return modelId;
const found = models.find((m) => m.id === modelId);
return found?.name || modelId;
}
export function getModelTargetFormat(aliasOrId, modelId) {
export function getModelTargetFormat(aliasOrId: string, modelId: string): string | null {
const models = PROVIDER_MODELS[aliasOrId];
if (!models) return null;
const found = models.find((m) => m.id === modelId);
return found?.targetFormat || null;
}
export function getModelsByProviderId(providerId) {
export function getModelsByProviderId(providerId: string): RegistryModel[] {
const alias = PROVIDER_ID_TO_ALIAS[providerId] || providerId;
return PROVIDER_MODELS[alias] || [];
}

View File

@@ -49,6 +49,21 @@ export interface RegistryEntry {
passthroughModels?: boolean;
}
interface LegacyProvider {
format: string;
baseUrl?: string;
baseUrls?: string[];
responsesBaseUrl?: string;
headers?: Record<string, string>;
clientId?: string;
clientSecret?: string;
tokenUrl?: string;
refreshUrl?: string;
authUrl?: string;
chatPath?: string;
clientVersion?: string;
}
// ── Registry ──────────────────────────────────────────────────────────────
export const REGISTRY: Record<string, RegistryEntry> = {
@@ -108,10 +123,13 @@ export const REGISTRY: Record<string, RegistryEntry> = {
clientIdEnv: "GEMINI_OAUTH_CLIENT_ID",
clientIdDefault: "681255809395-oo8ft2oprdrnp9e3aqf6av3hmdib135j.apps.googleusercontent.com",
clientSecretEnv: "GEMINI_OAUTH_CLIENT_SECRET",
clientSecretDefault: "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",
clientSecretDefault: "",
},
models: [
{ id: "gemini-3-pro-preview", name: "Gemini 3 Pro Preview" },
{ id: "gemini-3.1-pro", name: "Gemini 3.1 Pro" },
{ id: "gemini-3.1-flash", name: "Gemini 3.1 Flash" },
{ id: "gemini-3-pro-preview", name: "Gemini 3.0 Pro Preview" },
{ id: "gemini-3-flash-preview", name: "Gemini 3.0 Flash Preview" },
{ id: "gemini-2.5-pro", name: "Gemini 2.5 Pro" },
{ id: "gemini-2.5-flash", name: "Gemini 2.5 Flash" },
{ id: "gemini-2.5-flash-lite", name: "Gemini 2.5 Flash Lite" },
@@ -134,11 +152,13 @@ export const REGISTRY: Record<string, RegistryEntry> = {
clientIdEnv: "GEMINI_CLI_OAUTH_CLIENT_ID",
clientIdDefault: "681255809395-oo8ft2oprdrnp9e3aqf6av3hmdib135j.apps.googleusercontent.com",
clientSecretEnv: "GEMINI_CLI_OAUTH_CLIENT_SECRET",
clientSecretDefault: "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",
clientSecretDefault: "",
},
models: [
{ id: "gemini-3-flash-preview", name: "Gemini 3 Flash Preview" },
{ id: "gemini-3-pro-preview", name: "Gemini 3 Pro Preview" },
{ id: "gemini-3.1-pro", name: "Gemini 3.1 Pro" },
{ id: "gemini-3.1-flash", name: "Gemini 3.1 Flash" },
{ id: "gemini-3-flash-preview", name: "Gemini 3.0 Flash Preview" },
{ id: "gemini-3-pro-preview", name: "Gemini 3.0 Pro Preview" },
{ id: "gemini-2.5-pro", name: "Gemini 2.5 Pro" },
{ id: "gemini-2.5-flash", name: "Gemini 2.5 Flash" },
{ id: "gemini-2.5-flash-lite", name: "Gemini 2.5 Flash Lite" },
@@ -223,7 +243,7 @@ export const REGISTRY: Record<string, RegistryEntry> = {
clientIdEnv: "IFLOW_OAUTH_CLIENT_ID",
clientIdDefault: "10009311001",
clientSecretEnv: "IFLOW_OAUTH_CLIENT_SECRET",
clientSecretDefault: "4Z3YjXycVsQvyGF1etiNlIBB4RsqSDtW",
clientSecretDefault: "",
tokenUrl: "https://iflow.cn/oauth/token",
authUrl: "https://iflow.cn/oauth",
},
@@ -261,14 +281,15 @@ export const REGISTRY: Record<string, RegistryEntry> = {
clientIdEnv: "ANTIGRAVITY_OAUTH_CLIENT_ID",
clientIdDefault: "1071006060591-tmhssin2h21lcre235vtolojh4g403ep.apps.googleusercontent.com",
clientSecretEnv: "ANTIGRAVITY_OAUTH_CLIENT_SECRET",
clientSecretDefault: "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",
clientSecretDefault: "",
},
models: [
{ id: "claude-opus-4-6-thinking", name: "Claude Opus 4.6 Thinking" },
{ id: "claude-sonnet-4-6", name: "Claude Sonnet 4.6" },
{ id: "gemini-3.1-pro-high", name: "Gemini 3.1 Pro High" },
{ id: "gemini-3.1-pro-low", name: "Gemini 3.1 Pro Low" },
{ id: "gemini-3-flash", name: "Gemini 3 Flash" },
{ id: "gemini-3.1-flash", name: "Gemini 3.1 Flash" },
{ id: "gemini-3-flash", name: "Gemini 3.0 Flash" },
{ id: "gpt-oss-120b-medium", name: "GPT OSS 120B Medium" },
],
},
@@ -635,6 +656,25 @@ export const REGISTRY: Record<string, RegistryEntry> = {
],
},
blackbox: {
id: "blackbox",
alias: "bb",
format: "openai",
executor: "default",
baseUrl: "https://api.blackbox.ai/v1/chat/completions",
modelsUrl: "https://api.blackbox.ai/v1/models",
authType: "apikey",
authHeader: "bearer",
models: [
{ id: "gpt-4o", name: "GPT-4o" },
{ id: "gemini-2.5-flash", name: "Gemini 2.5 Flash" },
{ id: "claude-sonnet-4", name: "Claude Sonnet 4" },
{ id: "deepseek-v3", name: "DeepSeek V3" },
{ id: "blackboxai", name: "Blackbox AI" },
{ id: "blackboxai-pro", name: "Blackbox AI Pro" },
],
},
xai: {
id: "xai",
alias: "xai",
@@ -819,10 +859,10 @@ export const REGISTRY: Record<string, RegistryEntry> = {
// ── Generator Functions ───────────────────────────────────────────────────
/** Generate legacy PROVIDERS object shape for constants.js backward compatibility */
export function generateLegacyProviders(): Record<string, any> {
const providers: Record<string, any> = {};
export function generateLegacyProviders(): Record<string, LegacyProvider> {
const providers: Record<string, LegacyProvider> = {};
for (const [id, entry] of Object.entries(REGISTRY)) {
const p: Record<string, any> = { format: entry.format };
const p: LegacyProvider = { format: entry.format };
// URL(s)
if (entry.baseUrls) {
@@ -892,7 +932,7 @@ export function generateAliasMap(): Record<string, string> {
// ── Registry Lookup Helpers ───────────────────────────────────────────────
const _byAlias = new Map();
const _byAlias = new Map<string, RegistryEntry>();
for (const entry of Object.values(REGISTRY)) {
if (entry.alias && entry.alias !== entry.id) {
_byAlias.set(entry.alias, entry);

View File

@@ -0,0 +1,99 @@
/**
* Shared Registry Utilities
*
* Common interfaces and helpers used by all provider registries
* (audio, image, video, music). Extracts duplicated patterns into
* reusable functions.
*/
export interface BaseModel {
id: string;
name: string;
}
export interface BaseProvider<M extends BaseModel = BaseModel> {
id: string;
baseUrl: string;
authType: string; // "apikey" | "oauth" | "none"
authHeader: string; // "bearer" | "token" | "xi-api-key" | "x-api-key" | "none"
format?: string;
models: M[];
}
/**
* Parse a "provider/model" string against a registry.
* Supports both "provider/model" prefix and bare "model" lookup.
*/
export function parseModelFromRegistry<P extends BaseProvider>(
modelStr: string | null,
registry: Record<string, P>
): { provider: string | null; model: string | null } {
if (!modelStr) return { provider: null, model: null };
// Try each provider prefix
for (const [providerId] of Object.entries(registry)) {
if (modelStr.startsWith(providerId + "/")) {
return { provider: providerId, model: modelStr.slice(providerId.length + 1) };
}
}
// No provider prefix — try to find the model in every provider
for (const [providerId, config] of Object.entries(registry)) {
if (config.models.some((m) => m.id === modelStr)) {
return { provider: providerId, model: modelStr };
}
}
return { provider: null, model: modelStr };
}
/**
* Flatten all models from a registry into a list with provider info.
* Optionally merge extra fields per provider via the `extra` callback.
*/
export function getAllModelsFromRegistry<P extends BaseProvider>(
registry: Record<string, P>,
extra?: (providerId: string, config: P) => Record<string, unknown>
): Array<{ id: string; name: string; provider: string } & Record<string, unknown>> {
const models: Array<{ id: string; name: string; provider: string } & Record<string, unknown>> =
[];
for (const [providerId, config] of Object.entries(registry)) {
const extraFields = extra ? extra(providerId, config) : {};
for (const model of config.models) {
models.push({
id: `${providerId}/${model.id}`,
name: model.name,
provider: providerId,
...extraFields,
});
}
}
return models;
}
/**
* Build auth headers for a provider.
* Handles bearer, token, xi-api-key, x-api-key, and none.
*/
export function buildAuthHeaders(
provider: BaseProvider,
token: string | null
): Record<string, string> {
if (provider.authType === "none" || provider.authHeader === "none" || !token) {
return {};
}
switch (provider.authHeader) {
case "token":
return { Authorization: `Token ${token}` };
case "xi-api-key":
return { "xi-api-key": token };
case "x-api-key":
return { "x-api-key": token };
case "bearer":
default:
return { Authorization: `Bearer ${token}` };
}
}

View File

@@ -0,0 +1,68 @@
/**
* Video Generation Provider Registry
*
* Defines providers that support the /v1/videos/generations endpoint.
* Currently supports local providers (ComfyUI, SD WebUI with AnimateDiff).
*/
import { parseModelFromRegistry, getAllModelsFromRegistry } from "./registryUtils.ts";
interface VideoModel {
id: string;
name: string;
}
interface VideoProvider {
id: string;
baseUrl: string;
authType: string;
authHeader: string;
format: string;
models: VideoModel[];
}
export const VIDEO_PROVIDERS: Record<string, VideoProvider> = {
comfyui: {
id: "comfyui",
baseUrl: "http://localhost:8188",
authType: "none",
authHeader: "none",
format: "comfyui",
models: [
{ id: "animatediff", name: "AnimateDiff" },
{ id: "svd-xt", name: "Stable Video Diffusion XT" },
],
},
sdwebui: {
id: "sdwebui",
baseUrl: "http://localhost:7860",
authType: "none",
authHeader: "none",
format: "sdwebui-video",
models: [
{ id: "animatediff-webui", name: "AnimateDiff (WebUI)" },
],
},
};
/**
* Get video provider config by ID
*/
export function getVideoProvider(providerId: string): VideoProvider | null {
return VIDEO_PROVIDERS[providerId] || null;
}
/**
* Parse video model string (format: "provider/model" or just "model")
*/
export function parseVideoModel(modelStr: string | null) {
return parseModelFromRegistry(modelStr, VIDEO_PROVIDERS);
}
/**
* Get all video models as a flat list
*/
export function getAllVideoModels() {
return getAllModelsFromRegistry(VIDEO_PROVIDERS);
}

View File

@@ -5,7 +5,7 @@ import { PROVIDERS, OAUTH_ENDPOINTS, HTTP_STATUS } from "../config/constants.ts"
const MAX_RETRY_AFTER_MS = 10000;
/**
* Strip any provider prefix (e.g. "antigravity/model" → "model").
* Strip provider prefixes (e.g. "antigravity/model" → "model").
* Ensures the model name sent to the upstream API never contains a routing prefix.
*/
function cleanModelName(model: string): string {
@@ -36,7 +36,18 @@ export class AntigravityExecutor extends BaseExecutor {
}
transformRequest(model, body, stream, credentials) {
const projectId = credentials?.projectId || this.generateProjectId();
const bodyProjectId = body?.project;
const credentialsProjectId = credentials?.projectId;
const hasExplicitProject = !!(bodyProjectId || credentialsProjectId);
const projectId = bodyProjectId || credentialsProjectId || this.generateProjectId();
if (!hasExplicitProject) {
console.warn(
`[Antigravity] ⚠️ No projectId provided via body or credentials — using generated fallback "${projectId}". ` +
`This may cause 404 errors if the account has no active GCP project. ` +
`Ensure the OAuth token includes a valid project or the request includes a project field.`
);
}
// Fix contents for Claude models via Antigravity
const normalizedContents =

View File

@@ -1,15 +1,75 @@
import { HTTP_STATUS, FETCH_TIMEOUT_MS } from "../config/constants.ts";
type JsonRecord = Record<string, unknown>;
export type ProviderConfig = {
id?: string;
baseUrl?: string;
baseUrls?: string[];
responsesBaseUrl?: string;
chatPath?: string;
clientVersion?: string;
clientId?: string;
clientSecret?: string;
tokenUrl?: string;
refreshUrl?: string;
authUrl?: string;
headers?: Record<string, string>;
};
export type ProviderCredentials = {
accessToken?: string;
refreshToken?: string;
apiKey?: string;
expiresAt?: string;
providerSpecificData?: JsonRecord;
};
export type ExecutorLog = {
debug?: (tag: string, message: string) => void;
info?: (tag: string, message: string) => void;
warn?: (tag: string, message: string) => void;
error?: (tag: string, message: string) => void;
};
export type ExecuteInput = {
model: string;
body: unknown;
stream: boolean;
credentials: ProviderCredentials;
signal?: AbortSignal | null;
log?: ExecutorLog | null;
};
function mergeAbortSignals(primary: AbortSignal, secondary: AbortSignal): AbortSignal {
const controller = new AbortController();
const abortBoth = () => {
if (!controller.signal.aborted) {
controller.abort();
}
};
if (primary.aborted || secondary.aborted) {
abortBoth();
return controller.signal;
}
primary.addEventListener("abort", abortBoth, { once: true });
secondary.addEventListener("abort", abortBoth, { once: true });
return controller.signal;
}
/**
* BaseExecutor - Base class for provider executors.
* Implements the Strategy pattern: subclasses override specific methods
* (buildUrl, buildHeaders, transformRequest, etc.) for each provider.
*/
export class BaseExecutor {
provider: any;
config: any;
provider: string;
config: ProviderConfig;
constructor(provider: any, config: any) {
constructor(provider: string, config: ProviderConfig) {
this.provider = provider;
this.config = config;
}
@@ -26,9 +86,19 @@ export class BaseExecutor {
return this.getBaseUrls().length || 1;
}
buildUrl(model, stream, urlIndex = 0, credentials = null) {
buildUrl(
model: string,
stream: boolean,
urlIndex = 0,
credentials: ProviderCredentials | null = null
) {
void model;
void stream;
if (this.provider?.startsWith?.("openai-compatible-")) {
const baseUrl = credentials?.providerSpecificData?.baseUrl || "https://api.openai.com/v1";
const baseUrl =
typeof credentials?.providerSpecificData?.baseUrl === "string"
? credentials.providerSpecificData.baseUrl
: "https://api.openai.com/v1";
const normalized = baseUrl.replace(/\/$/, "");
const path = this.provider.includes("responses") ? "/responses" : "/chat/completions";
return `${normalized}${path}`;
@@ -37,12 +107,25 @@ export class BaseExecutor {
return baseUrls[urlIndex] || baseUrls[0] || this.config.baseUrl;
}
buildHeaders(credentials, stream = true) {
const headers = {
buildHeaders(credentials: ProviderCredentials, stream = true): Record<string, string> {
const headers: Record<string, string> = {
"Content-Type": "application/json",
...this.config.headers,
};
// Allow per-provider User-Agent override via environment variable.
// Example: CLAUDE_USER_AGENT="my-agent/2.0" overrides the default for the Claude provider.
const providerId = this.config?.id || this.provider;
if (providerId) {
const envKey = `${providerId.toUpperCase().replace(/[^A-Z0-9]/g, "_")}_USER_AGENT`;
const envUA = process.env[envKey]?.trim();
if (envUA) {
// Override both common casing variants
headers["User-Agent"] = envUA;
if (headers["user-agent"]) headers["user-agent"] = envUA;
}
}
if (credentials.accessToken) {
headers["Authorization"] = `Bearer ${credentials.accessToken}`;
} else if (credentials.apiKey) {
@@ -57,32 +140,42 @@ export class BaseExecutor {
}
// Override in subclass for provider-specific transformations
transformRequest(model, body, stream, credentials) {
transformRequest(
model: string,
body: unknown,
stream: boolean,
credentials: ProviderCredentials
): unknown {
void model;
void stream;
void credentials;
return body;
}
shouldRetry(status, urlIndex) {
shouldRetry(status: number, urlIndex: number) {
return status === HTTP_STATUS.RATE_LIMITED && urlIndex + 1 < this.getFallbackCount();
}
// Override in subclass for provider-specific refresh
async refreshCredentials(credentials, log) {
async refreshCredentials(credentials: ProviderCredentials, log: ExecutorLog | null) {
void credentials;
void log;
return null;
}
needsRefresh(credentials) {
needsRefresh(credentials: ProviderCredentials) {
if (!credentials.expiresAt) return false;
const expiresAtMs = new Date(credentials.expiresAt).getTime();
return expiresAtMs - Date.now() < 5 * 60 * 1000;
}
parseError(response, bodyText) {
parseError(response: Response, bodyText: string) {
return { status: response.status, message: bodyText || `HTTP ${response.status}` };
}
async execute({ model, body, stream, credentials, signal, log }) {
async execute({ model, body, stream, credentials, signal, log }: ExecuteInput) {
const fallbackCount = this.getFallbackCount();
let lastError = null;
let lastError: unknown = null;
let lastStatus = 0;
for (let urlIndex = 0; urlIndex < fallbackCount; urlIndex++) {
@@ -96,10 +189,10 @@ export class BaseExecutor {
const timeoutSignal = !stream ? AbortSignal.timeout(FETCH_TIMEOUT_MS) : null;
const combinedSignal =
signal && timeoutSignal
? AbortSignal.any([signal, timeoutSignal])
? mergeAbortSignals(signal, timeoutSignal)
: signal || timeoutSignal;
const fetchOptions: Record<string, any> = {
const fetchOptions: RequestInit = {
method: "POST",
headers,
body: JSON.stringify(transformedBody),
@@ -117,15 +210,16 @@ export class BaseExecutor {
return { response, url, headers, transformedBody };
} catch (error) {
// Distinguish timeout errors from other abort errors
if (error.name === "TimeoutError") {
const err = error instanceof Error ? error : new Error(String(error));
if (err.name === "TimeoutError") {
log?.warn?.("TIMEOUT", `Fetch timeout after ${FETCH_TIMEOUT_MS}ms on ${url}`);
}
lastError = error;
lastError = err;
if (urlIndex + 1 < fallbackCount) {
log?.debug?.("RETRY", `Error on ${url}, trying fallback ${urlIndex + 1}`);
continue;
}
throw error;
throw err;
}
}

View File

@@ -1,4 +1,4 @@
declare var EdgeRuntime: any;
declare const EdgeRuntime: string | undefined;
/**
* CursorExecutor — Handles communication with the Cursor IDE API.
*
@@ -121,13 +121,19 @@ function createErrorResponse(jsonError) {
);
}
type CursorHttpResponse = {
status: number;
headers: Record<string, unknown>;
body: Buffer;
};
export class CursorExecutor extends BaseExecutor {
constructor() {
super("cursor", PROVIDERS.cursor);
}
buildUrl() {
return `${this.config.baseUrl}${this.config.chatPath}`;
return `${this.config.baseUrl}${this.config.chatPath || ""}`;
}
// Jyh cipher checksum for Cursor API authentication
@@ -217,27 +223,37 @@ export class CursorExecutor extends BaseExecutor {
return generateCursorBody(messages, model, tools, reasoningEffort);
}
async makeFetchRequest(url, headers, body, signal) {
async makeFetchRequest(
url: string,
headers: Record<string, string>,
body: Uint8Array,
signal?: AbortSignal
): Promise<CursorHttpResponse> {
const response = await fetch(url, {
method: "POST",
headers,
body,
body: body as unknown as BodyInit,
signal,
});
return {
status: response.status,
headers: Object.fromEntries((response.headers as any).entries()),
headers: Object.fromEntries(response.headers.entries()),
body: Buffer.from(await response.arrayBuffer()),
};
}
makeHttp2Request(url, headers, body, signal) {
makeHttp2Request(
url: string,
headers: Record<string, string>,
body: Uint8Array,
signal?: AbortSignal
): Promise<CursorHttpResponse> {
if (!http2) {
throw new Error("http2 module not available");
}
return new Promise((resolve, reject) => {
return new Promise<CursorHttpResponse>((resolve, reject) => {
const urlObj = new URL(url);
const client = http2.connect(`https://${urlObj.host}`);
const chunks = [];
@@ -262,7 +278,10 @@ export class CursorExecutor extends BaseExecutor {
req.on("end", () => {
client.close();
resolve({
status: responseHeaders[":status"],
status:
typeof responseHeaders[":status"] === "number"
? responseHeaders[":status"]
: Number(responseHeaders[":status"] || HTTP_STATUS.SERVER_ERROR),
headers: responseHeaders,
body: Buffer.concat(chunks),
});
@@ -291,7 +310,7 @@ export class CursorExecutor extends BaseExecutor {
const transformedBody = this.transformRequest(model, body, stream, credentials);
try {
const response: any = http2
const response: CursorHttpResponse = http2
? await this.makeHttp2Request(url, headers, transformedBody, signal)
: await this.makeFetchRequest(url, headers, transformedBody, signal);
@@ -459,7 +478,8 @@ export class CursorExecutor extends BaseExecutor {
console.log(`[CURSOR BUFFER] Final toolCalls count: ${toolCalls.length}`);
const message: Record<string, any> = { role: "assistant",
const message: Record<string, unknown> = {
role: "assistant",
content: totalContent || null,
};

View File

@@ -74,7 +74,7 @@ export class DefaultExecutor extends BaseExecutor {
/**
* For compatible providers, ensure the model name sent upstream
* is the clean model name without any internal routing prefix.
* is the clean model name without internal routing prefixes.
* e.g. "openapi-chat-anti/claude-opus-4-6-thinking" → "claude-opus-4-6-thinking"
*/
transformRequest(model, body, stream, credentials) {

View File

@@ -2,6 +2,11 @@ import crypto from "crypto";
import { BaseExecutor } from "./base.ts";
import { PROVIDERS } from "../config/constants.ts";
type IFlowCredentials = {
apiKey?: string;
accessToken?: string;
};
/**
* IFlowExecutor - Executor for iFlow API with HMAC-SHA256 signature.
*
@@ -41,7 +46,7 @@ export class IFlowExecutor extends BaseExecutor {
* Build headers with iFlow-specific HMAC-SHA256 signature.
* Includes session-id, x-iflow-timestamp, and x-iflow-signature.
*/
buildHeaders(credentials: any, stream = true) {
buildHeaders(credentials: IFlowCredentials, stream = true) {
// Generate session ID and timestamp
const sessionID = `session-${crypto.randomUUID()}`;
const timestamp = Date.now();
@@ -82,14 +87,26 @@ export class IFlowExecutor extends BaseExecutor {
/**
* Build URL for iFlow API — uses baseUrl directly.
*/
buildUrl(model: string, stream: boolean, urlIndex = 0, credentials: any = null) {
buildUrl(
model: string,
stream: boolean,
urlIndex = 0,
credentials: IFlowCredentials | null = null
) {
void model;
void stream;
void urlIndex;
void credentials;
return this.config.baseUrl;
}
/**
* Transform request body (passthrough for iFlow).
*/
transformRequest(model: string, body: any, stream: boolean, credentials: any) {
transformRequest(model: string, body: unknown, stream: boolean, credentials: IFlowCredentials) {
void model;
void stream;
void credentials;
return body;
}
}

View File

@@ -1,8 +1,39 @@
import { BaseExecutor } from "./base.ts";
import {
BaseExecutor,
type ExecuteInput,
type ExecutorLog,
type ProviderCredentials,
} from "./base.ts";
import { PROVIDERS } from "../config/constants.ts";
import { v4 as uuidv4 } from "uuid";
import { refreshKiroToken } from "../services/tokenRefresh.ts";
type JsonRecord = Record<string, unknown>;
type UsageSummary = {
prompt_tokens: number;
completion_tokens: number;
total_tokens: number;
};
type KiroStreamState = {
endDetected: boolean;
finishEmitted: boolean;
hasToolCalls: boolean;
toolCallIndex: number;
seenToolIds: Map<string, number>;
totalContentLength?: number;
contextUsagePercentage?: number;
hasContextUsage?: boolean;
hasMeteringEvent?: boolean;
usage?: UsageSummary;
};
type EventFrame = {
headers: Record<string, string>;
payload: JsonRecord | null;
};
// ── CRC32 lookup table (IEEE polynomial, no dependency) ──
const CRC32_TABLE = new Uint32Array(256);
for (let i = 0; i < 256; i++) {
@@ -13,7 +44,7 @@ for (let i = 0; i < 256; i++) {
CRC32_TABLE[i] = c >>> 0;
}
function crc32(buf) {
function crc32(buf: Uint8Array) {
let crc = 0xffffffff;
for (let i = 0; i < buf.length; i++) {
crc = CRC32_TABLE[(crc ^ buf[i]) & 0xff] ^ (crc >>> 8);
@@ -30,7 +61,8 @@ export class KiroExecutor extends BaseExecutor {
super("kiro", PROVIDERS.kiro);
}
buildHeaders(credentials, stream = true) {
buildHeaders(credentials: ProviderCredentials, stream = true) {
void stream;
const headers = {
...this.config.headers,
"Amz-Sdk-Request": "attempt=1; max=3",
@@ -44,14 +76,17 @@ export class KiroExecutor extends BaseExecutor {
return headers;
}
transformRequest(model, body, stream, credentials) {
transformRequest(model: string, body: unknown, stream: boolean, credentials: unknown): unknown {
void model;
void stream;
void credentials;
return body;
}
/**
* Custom execute for Kiro - handles AWS EventStream binary response
*/
async execute({ model, body, stream, credentials, signal, log }) {
async execute({ model, body, stream, credentials, signal, log }: ExecuteInput) {
const url = this.buildUrl(model, stream, 0);
const headers = this.buildHeaders(credentials, stream);
const transformedBody = this.transformRequest(model, body, stream, credentials);
@@ -78,12 +113,13 @@ export class KiroExecutor extends BaseExecutor {
* Transform AWS EventStream binary response to SSE text stream
* Using TransformStream instead of ReadableStream.pull() to avoid Workers timeout
*/
transformEventStreamToSSE(response, model) {
transformEventStreamToSSE(response: Response, model: string) {
let buffer = new Uint8Array(0);
let chunkIndex = 0;
const responseId = `chatcmpl-${Date.now()}`;
const created = Math.floor(Date.now() / 1000);
const state: Record<string, any> = { endDetected: false,
const state: KiroStreamState = {
endDetected: false,
finishEmitted: false,
hasToolCalls: false,
toolCallIndex: 0,
@@ -121,11 +157,14 @@ export class KiroExecutor extends BaseExecutor {
if (!state.contextUsagePercentage) state.contextUsagePercentage = 0;
// Handle assistantResponseEvent
if (eventType === "assistantResponseEvent" && event.payload?.content) {
const content = event.payload.content;
if (eventType === "assistantResponseEvent") {
const content = typeof event.payload?.content === "string" ? event.payload.content : "";
if (!content) {
continue;
}
state.totalContentLength += content.length;
const chunk: Record<string, any> = {
const chunk: JsonRecord = {
id: responseId,
object: "chat.completion.chunk",
created,
@@ -144,7 +183,7 @@ export class KiroExecutor extends BaseExecutor {
// Handle codeEvent
if (eventType === "codeEvent" && event.payload?.content) {
const chunk: Record<string, any> = {
const chunk: JsonRecord = {
id: responseId,
object: "chat.completion.chunk",
created,
@@ -256,7 +295,7 @@ export class KiroExecutor extends BaseExecutor {
// Handle messageStopEvent
if (eventType === "messageStopEvent") {
const chunk: Record<string, any> = {
const chunk: JsonRecord = {
id: responseId,
object: "chat.completion.chunk",
created,
@@ -274,8 +313,15 @@ export class KiroExecutor extends BaseExecutor {
}
// Handle contextUsageEvent to extract contextUsagePercentage
if (eventType === "contextUsageEvent" && event.payload?.contextUsagePercentage) {
state.contextUsagePercentage = event.payload.contextUsagePercentage;
if (eventType === "contextUsageEvent") {
const contextUsage =
typeof event.payload?.contextUsagePercentage === "number"
? event.payload.contextUsagePercentage
: 0;
if (contextUsage <= 0) {
continue;
}
state.contextUsagePercentage = contextUsage;
// Mark that we received context usage event
state.hasContextUsage = true;
}
@@ -290,8 +336,14 @@ export class KiroExecutor extends BaseExecutor {
// Extract usage data from metricsEvent payload
const metrics = event.payload?.metricsEvent || event.payload;
if (metrics && typeof metrics === "object") {
const inputTokens = metrics.inputTokens || 0;
const outputTokens = metrics.outputTokens || 0;
const inputTokens =
typeof (metrics as JsonRecord).inputTokens === "number"
? ((metrics as JsonRecord).inputTokens as number)
: 0;
const outputTokens =
typeof (metrics as JsonRecord).outputTokens === "number"
? ((metrics as JsonRecord).outputTokens as number)
: 0;
if (inputTokens > 0 || outputTokens > 0) {
state.usage = {
@@ -329,7 +381,7 @@ export class KiroExecutor extends BaseExecutor {
};
}
const finishChunk: Record<string, any> = {
const finishChunk: JsonRecord = {
id: responseId,
object: "chat.completion.chunk",
created,
@@ -398,7 +450,7 @@ export class KiroExecutor extends BaseExecutor {
});
}
async refreshCredentials(credentials, log) {
async refreshCredentials(credentials: ProviderCredentials, log?: ExecutorLog | null) {
if (!credentials.refreshToken) return null;
try {
@@ -411,7 +463,8 @@ export class KiroExecutor extends BaseExecutor {
return result;
} catch (error) {
log?.error?.("TOKEN", `Kiro refresh error: ${error.message}`);
const err = error instanceof Error ? error : new Error(String(error));
log?.error?.("TOKEN", `Kiro refresh error: ${err.message}`);
return null;
}
}
@@ -420,7 +473,7 @@ export class KiroExecutor extends BaseExecutor {
/**
* Parse AWS EventStream frame
*/
function parseEventFrame(data) {
function parseEventFrame(data: Uint8Array): EventFrame | null {
try {
const view = new DataView(data.buffer, data.byteOffset);
const totalLength = view.getUint32(0, false);
@@ -447,7 +500,7 @@ function parseEventFrame(data) {
return null;
}
// Parse headers
const headers = {};
const headers: Record<string, string> = {};
let offset = 12; // After prelude
const headerEnd = 12 + headersLength;
@@ -480,7 +533,7 @@ function parseEventFrame(data) {
const payloadStart = 12 + headersLength;
const payloadEnd = data.length - 4; // Exclude message CRC
let payload = null;
let payload: JsonRecord | null = null;
if (payloadEnd > payloadStart) {
const payloadStr = new TextDecoder().decode(data.slice(payloadStart, payloadEnd));
@@ -492,9 +545,10 @@ function parseEventFrame(data) {
try {
payload = JSON.parse(payloadStr);
} catch (parseError) {
const err = parseError instanceof Error ? parseError : new Error(String(parseError));
// Log parse error for debugging
console.warn(
`[Kiro] Failed to parse payload: ${parseError.message} | payload: ${payloadStr.substring(0, 100)}`
`[Kiro] Failed to parse payload: ${err.message} | payload: ${payloadStr.substring(0, 100)}`
);
payload = { raw: payloadStr };
}
@@ -502,7 +556,8 @@ function parseEventFrame(data) {
return { headers, payload };
} catch (err) {
console.warn(`[Kiro] Frame parse error: ${err.message}`);
const error = err instanceof Error ? err : new Error(String(err));
console.warn(`[Kiro] Frame parse error: ${error.message}`);
return null;
}
}

View File

@@ -6,22 +6,54 @@ import { getCorsOrigin } from "../utils/cors.ts";
* Returns audio binary stream.
*
* Supported provider formats:
* - OpenAI: standard JSON → audio stream proxy
* - OpenAI / Qwen3 (openai-compatible): standard JSON → audio stream proxy
* - Hyperbolic: POST { text } → { audio: base64 }
* - Deepgram: POST { text } with model via query param, Token auth
* - ElevenLabs: POST { text, model_id } to /v1/text-to-speech/{voice_id}
* - Nvidia NIM: POST { input: { text }, voice, model } → audio binary
* - HuggingFace Inference: POST { inputs: text } to /models/{model_id}
* - Coqui TTS: POST { text, speaker_id } → WAV audio (local, no auth)
* - Tortoise TTS: POST { text, voice } → audio binary (local, no auth)
*/
import { getSpeechProvider, parseSpeechModel } from "../config/audioRegistry.ts";
import { buildAuthHeaders } from "../config/registryUtils.ts";
import { errorResponse } from "../utils/error.ts";
/**
* Build auth header for a speech provider
* Return a CORS error response from an upstream fetch failure
*/
function buildAuthHeader(providerConfig, token) {
if (providerConfig.authHeader === "token") {
return { Authorization: `Token ${token}` };
}
return { Authorization: `Bearer ${token}` };
function upstreamErrorResponse(res, errText) {
return new Response(errText, {
status: res.status,
headers: {
"Content-Type": "application/json",
"Access-Control-Allow-Origin": getCorsOrigin(),
},
});
}
/**
* Return a CORS audio stream response
*/
function audioStreamResponse(res, defaultContentType = "audio/mpeg") {
const contentType = res.headers.get("content-type") || defaultContentType;
return new Response(res.body, {
status: 200,
headers: {
"Content-Type": contentType,
"Access-Control-Allow-Origin": getCorsOrigin(),
"Transfer-Encoding": "chunked",
},
});
}
/**
* Validate a path segment to prevent path traversal / SSRF.
* Returns true if safe, false if it contains traversal sequences.
*/
function isValidPathSegment(segment: string): boolean {
return !segment.includes("..") && !segment.includes("//");
}
/**
@@ -32,20 +64,13 @@ async function handleHyperbolicSpeech(providerConfig, body, token) {
method: "POST",
headers: {
"Content-Type": "application/json",
...buildAuthHeader(providerConfig, token),
...buildAuthHeaders(providerConfig, token),
},
body: JSON.stringify({ text: body.input }),
});
if (!res.ok) {
const errText = await res.text();
return new Response(errText, {
status: res.status,
headers: {
"Content-Type": "application/json",
"Access-Control-Allow-Origin": getCorsOrigin(),
},
});
return upstreamErrorResponse(res, await res.text());
}
const data = await res.json();
@@ -72,29 +97,153 @@ async function handleDeepgramSpeech(providerConfig, body, modelId, token) {
method: "POST",
headers: {
"Content-Type": "application/json",
...buildAuthHeader(providerConfig, token),
...buildAuthHeaders(providerConfig, token),
},
body: JSON.stringify({ text: body.input }),
});
if (!res.ok) {
const errText = await res.text();
return new Response(errText, {
status: res.status,
headers: {
"Content-Type": "application/json",
"Access-Control-Allow-Origin": getCorsOrigin(),
},
});
return upstreamErrorResponse(res, await res.text());
}
const contentType = res.headers.get("content-type") || "audio/mpeg";
return audioStreamResponse(res);
}
/**
* Handle ElevenLabs TTS
* POST {baseUrl}/{voice_id} with { text, model_id }
* voice_id is mapped from the OpenAI `voice` parameter
*/
async function handleElevenLabsSpeech(providerConfig, body, modelId, token) {
// ElevenLabs uses voice_id in URL path; default to "21m00Tcm4TlvDq8ikWAM" (Rachel)
const voiceId = body.voice || "21m00Tcm4TlvDq8ikWAM";
if (!isValidPathSegment(voiceId)) {
return errorResponse(400, "Invalid voice ID");
}
const url = `${providerConfig.baseUrl}/${voiceId}`;
const res = await fetch(url, {
method: "POST",
headers: {
"Content-Type": "application/json",
...buildAuthHeaders(providerConfig, token),
},
body: JSON.stringify({
text: body.input,
model_id: modelId,
}),
});
if (!res.ok) {
return upstreamErrorResponse(res, await res.text());
}
return audioStreamResponse(res);
}
/**
* Handle Nvidia NIM TTS
* POST with { input: { text }, voice, model } → audio binary
*/
async function handleNvidiaTtsSpeech(providerConfig, body, modelId, token) {
const res = await fetch(providerConfig.baseUrl, {
method: "POST",
headers: {
"Content-Type": "application/json",
...buildAuthHeaders(providerConfig, token),
},
body: JSON.stringify({
input: { text: body.input },
voice: body.voice || "default",
model: modelId,
}),
});
if (!res.ok) {
return upstreamErrorResponse(res, await res.text());
}
return audioStreamResponse(res, "audio/wav");
}
/**
* Handle HuggingFace Inference TTS
* POST {baseUrl}/{model_id} with { inputs: text } → audio binary
*/
async function handleHuggingFaceTtsSpeech(providerConfig, body, modelId, token) {
if (!isValidPathSegment(modelId)) {
return errorResponse(400, "Invalid model ID");
}
const url = `${providerConfig.baseUrl}/${modelId}`;
const res = await fetch(url, {
method: "POST",
headers: {
"Content-Type": "application/json",
...buildAuthHeaders(providerConfig, token),
},
body: JSON.stringify({ inputs: body.input }),
});
if (!res.ok) {
return upstreamErrorResponse(res, await res.text());
}
return audioStreamResponse(res, "audio/wav");
}
/**
* Handle Coqui TTS (local, no auth)
* POST {baseUrl} with { text, speaker_id } → WAV audio
*/
async function handleCoquiSpeech(providerConfig, body) {
const res = await fetch(providerConfig.baseUrl, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
text: body.input,
speaker_id: body.voice || undefined,
}),
});
if (!res.ok) {
return upstreamErrorResponse(res, await res.text());
}
const contentType = res.headers.get("content-type") || "audio/wav";
return new Response(res.body, {
status: 200,
headers: {
"Content-Type": contentType,
"Access-Control-Allow-Origin": getCorsOrigin(),
},
});
}
/**
* Handle Tortoise TTS (local, no auth)
* POST {baseUrl} with { text, voice } → audio binary
*/
async function handleTortoiseSpeech(providerConfig, body) {
const res = await fetch(providerConfig.baseUrl, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
text: body.input,
voice: body.voice || "random",
}),
});
if (!res.ok) {
return upstreamErrorResponse(res, await res.text());
}
const contentType = res.headers.get("content-type") || "audio/wav";
return new Response(res.body, {
status: 200,
headers: {
"Content-Type": contentType,
"Access-Control-Allow-Origin": getCorsOrigin(),
"Transfer-Encoding": "chunked",
},
});
}
@@ -107,7 +256,7 @@ async function handleDeepgramSpeech(providerConfig, body, modelId, token) {
* @param {Object} options.credentials - Provider credentials { apiKey }
* @returns {Response}
*/
/** @returns {Promise<any>} */
/** @returns {Promise<unknown>} */
export async function handleAudioSpeech({ body, credentials }) {
if (!body.model) {
return errorResponse(400, "model is required");
@@ -122,12 +271,14 @@ export async function handleAudioSpeech({ body, credentials }) {
if (!providerConfig) {
return errorResponse(
400,
`No speech provider found for model "${body.model}". Available: openai, hyperbolic, deepgram`
`No speech provider found for model "${body.model}". Available: openai, hyperbolic, deepgram, nvidia, elevenlabs, huggingface, coqui, tortoise, qwen`
);
}
const token = credentials?.apiKey || credentials?.accessToken;
if (!token) {
// Skip credential check for local providers (authType: "none")
const token =
providerConfig.authType === "none" ? null : credentials?.apiKey || credentials?.accessToken;
if (providerConfig.authType !== "none" && !token) {
return errorResponse(401, `No credentials for speech provider: ${providerId}`);
}
@@ -141,12 +292,32 @@ export async function handleAudioSpeech({ body, credentials }) {
return handleDeepgramSpeech(providerConfig, body, modelId, token);
}
// Default: OpenAI-compatible JSON → audio stream proxy
if (providerConfig.format === "elevenlabs") {
return handleElevenLabsSpeech(providerConfig, body, modelId, token);
}
if (providerConfig.format === "nvidia-tts") {
return handleNvidiaTtsSpeech(providerConfig, body, modelId, token);
}
if (providerConfig.format === "huggingface-tts") {
return handleHuggingFaceTtsSpeech(providerConfig, body, modelId, token);
}
if (providerConfig.format === "coqui") {
return handleCoquiSpeech(providerConfig, body);
}
if (providerConfig.format === "tortoise") {
return handleTortoiseSpeech(providerConfig, body);
}
// Default: OpenAI-compatible JSON → audio stream proxy (also used by Qwen3)
const res = await fetch(providerConfig.baseUrl, {
method: "POST",
headers: {
"Content-Type": "application/json",
...buildAuthHeader(providerConfig, token),
...buildAuthHeaders(providerConfig, token),
},
body: JSON.stringify({
model: modelId,
@@ -158,26 +329,10 @@ export async function handleAudioSpeech({ body, credentials }) {
});
if (!res.ok) {
const errText = await res.text();
return new Response(errText, {
status: res.status,
headers: {
"Content-Type": "application/json",
"Access-Control-Allow-Origin": getCorsOrigin(),
},
});
return upstreamErrorResponse(res, await res.text());
}
// Stream audio response back to client
const contentType = res.headers.get("content-type") || "audio/mpeg";
return new Response(res.body, {
status: 200,
headers: {
"Content-Type": contentType,
"Access-Control-Allow-Origin": getCorsOrigin(),
"Transfer-Encoding": "chunked",
},
});
return audioStreamResponse(res);
} catch (err) {
return errorResponse(500, `Speech request failed: ${err.message}`);
}

View File

@@ -6,22 +6,44 @@ import { getCorsOrigin } from "../utils/cors.ts";
* Proxies multipart/form-data to upstream providers.
*
* Supported provider formats:
* - OpenAI/Groq: standard multipart form-data proxy
* - OpenAI/Groq/Qwen3: standard multipart form-data proxy
* - Deepgram: raw binary audio POST with model via query param
* - AssemblyAI: async workflow (upload → submit → poll)
* - Nvidia NIM: multipart POST, transform response to { text }
* - HuggingFace Inference: POST raw binary to /models/{model_id}
*/
import { getTranscriptionProvider, parseTranscriptionModel } from "../config/audioRegistry.ts";
import { buildAuthHeaders } from "../config/registryUtils.ts";
import { errorResponse } from "../utils/error.ts";
type TranscriptionCredentials = {
apiKey?: string;
accessToken?: string;
};
/**
* Build auth header for a transcription provider
* Return a CORS error response from an upstream fetch failure
*/
function buildAuthHeader(providerConfig, token) {
if (providerConfig.authHeader === "token") {
return { Authorization: `Token ${token}` };
}
return { Authorization: `Bearer ${token}` };
function upstreamErrorResponse(res, errText) {
return new Response(errText, {
status: res.status,
headers: {
"Content-Type": "application/json",
"Access-Control-Allow-Origin": getCorsOrigin(),
},
});
}
/**
* Validate a path segment to prevent path traversal / SSRF.
*/
function isValidPathSegment(segment: string): boolean {
return !segment.includes("..") && !segment.includes("//");
}
function getUploadedFileName(file: Blob & { name?: unknown }): string {
return typeof file.name === "string" && file.name.length > 0 ? file.name : "audio.wav";
}
/**
@@ -37,21 +59,14 @@ async function handleDeepgramTranscription(providerConfig, file, modelId, token)
const res = await fetch(url.toString(), {
method: "POST",
headers: {
...buildAuthHeader(providerConfig, token),
...buildAuthHeaders(providerConfig, token),
"Content-Type": file.type || "audio/wav",
},
body: arrayBuffer,
});
if (!res.ok) {
const errText = await res.text();
return new Response(errText, {
status: res.status,
headers: {
"Content-Type": "application/json",
"Access-Control-Allow-Origin": getCorsOrigin(),
},
});
return upstreamErrorResponse(res, await res.text());
}
const data = await res.json();
@@ -65,7 +80,7 @@ async function handleDeepgramTranscription(providerConfig, file, modelId, token)
* Handle AssemblyAI transcription (async: upload file → submit → poll)
*/
async function handleAssemblyAITranscription(providerConfig, file, modelId, token) {
const authHeaders = buildAuthHeader(providerConfig, token);
const authHeaders = buildAuthHeaders(providerConfig, token);
// Step 1: Upload the audio file
const arrayBuffer = await file.arrayBuffer();
@@ -79,14 +94,7 @@ async function handleAssemblyAITranscription(providerConfig, file, modelId, toke
});
if (!uploadRes.ok) {
const errText = await uploadRes.text();
return new Response(errText, {
status: uploadRes.status,
headers: {
"Content-Type": "application/json",
"Access-Control-Allow-Origin": getCorsOrigin(),
},
});
return upstreamErrorResponse(uploadRes, await uploadRes.text());
}
const { upload_url } = await uploadRes.json();
@@ -106,14 +114,7 @@ async function handleAssemblyAITranscription(providerConfig, file, modelId, toke
});
if (!submitRes.ok) {
const errText = await submitRes.text();
return new Response(errText, {
status: submitRes.status,
headers: {
"Content-Type": "application/json",
"Access-Control-Allow-Origin": getCorsOrigin(),
},
});
return upstreamErrorResponse(submitRes, await submitRes.text());
}
const { id: transcriptId } = await submitRes.json();
@@ -146,6 +147,63 @@ async function handleAssemblyAITranscription(providerConfig, file, modelId, toke
return errorResponse(504, "AssemblyAI transcription timed out after 120s");
}
/**
* Handle Nvidia NIM transcription
* Multipart POST, transform response to { text }
*/
async function handleNvidiaTranscription(providerConfig, file, modelId, token) {
const upstreamForm = new FormData();
upstreamForm.append("file", file, getUploadedFileName(file));
upstreamForm.append("model", modelId);
const res = await fetch(providerConfig.baseUrl, {
method: "POST",
headers: buildAuthHeaders(providerConfig, token),
body: upstreamForm,
});
if (!res.ok) {
return upstreamErrorResponse(res, await res.text());
}
const data = await res.json();
// Normalize to { text } — Nvidia may return { text } directly or nested
const text = data.text || data.transcript || "";
return Response.json({ text }, { headers: { "Access-Control-Allow-Origin": getCorsOrigin() } });
}
/**
* Handle HuggingFace Inference transcription
* POST raw binary audio to {baseUrl}/{model_id}, returns { text }
*/
async function handleHuggingFaceTranscription(providerConfig, file, modelId, token) {
if (!isValidPathSegment(modelId)) {
return errorResponse(400, "Invalid model ID");
}
const url = `${providerConfig.baseUrl}/${modelId}`;
const arrayBuffer = await file.arrayBuffer();
const res = await fetch(url, {
method: "POST",
headers: {
...buildAuthHeaders(providerConfig, token),
"Content-Type": file.type || "audio/wav",
},
body: arrayBuffer,
});
if (!res.ok) {
return upstreamErrorResponse(res, await res.text());
}
const data = await res.json();
// HuggingFace returns { text } directly
const text = data.text || "";
return Response.json({ text }, { headers: { "Access-Control-Allow-Origin": getCorsOrigin() } });
}
/**
* Handle audio transcription request
*
@@ -154,17 +212,23 @@ async function handleAssemblyAITranscription(providerConfig, file, modelId, toke
* @param {Object} options.credentials - Provider credentials { apiKey }
* @returns {Response}
*/
/** @returns {Promise<any>} */
export async function handleAudioTranscription({ formData, credentials }) {
export async function handleAudioTranscription({
formData,
credentials,
}: {
formData: FormData;
credentials?: TranscriptionCredentials | null;
}): Promise<Response> {
const model = formData.get("model");
if (!model) {
if (typeof model !== "string" || !model) {
return errorResponse(400, "model is required");
}
const file = formData.get("file");
if (!file) {
const fileEntry = formData.get("file");
if (!(fileEntry instanceof Blob)) {
return errorResponse(400, "file is required");
}
const file = fileEntry as Blob & { name?: unknown };
const { provider: providerId, model: modelId } = parseTranscriptionModel(model);
const providerConfig = providerId ? getTranscriptionProvider(providerId) : null;
@@ -172,12 +236,14 @@ export async function handleAudioTranscription({ formData, credentials }) {
if (!providerConfig) {
return errorResponse(
400,
`No transcription provider found for model "${model}". Available: openai, groq, deepgram, assemblyai`
`No transcription provider found for model "${model}". Available: openai, groq, deepgram, assemblyai, nvidia, huggingface, qwen`
);
}
const token = credentials?.apiKey || credentials?.accessToken;
if (!token) {
// Skip credential check for local providers (authType: "none")
const token =
providerConfig.authType === "none" ? null : credentials?.apiKey || credentials?.accessToken;
if (providerConfig.authType !== "none" && !token) {
return errorResponse(401, `No credentials for transcription provider: ${providerId}`);
}
@@ -190,13 +256,17 @@ export async function handleAudioTranscription({ formData, credentials }) {
return handleAssemblyAITranscription(providerConfig, file, modelId, token);
}
// Default: OpenAI/Groq-compatible multipart proxy
if (providerConfig.format === "nvidia-asr") {
return handleNvidiaTranscription(providerConfig, file, modelId, token);
}
if (providerConfig.format === "huggingface-asr") {
return handleHuggingFaceTranscription(providerConfig, file, modelId, token);
}
// Default: OpenAI/Groq/Qwen3-compatible multipart proxy
const upstreamForm = new FormData();
upstreamForm.append(
"file",
/** @type {Blob} */ file,
/** @type {any} */ file.name || "audio.wav"
);
upstreamForm.append("file", file, getUploadedFileName(file));
upstreamForm.append("model", modelId);
// Forward optional parameters
@@ -216,19 +286,12 @@ export async function handleAudioTranscription({ formData, credentials }) {
try {
const res = await fetch(providerConfig.baseUrl, {
method: "POST",
headers: buildAuthHeader(providerConfig, token),
headers: buildAuthHeaders(providerConfig, token),
body: upstreamForm,
});
if (!res.ok) {
const errText = await res.text();
return new Response(errText, {
status: res.status,
headers: {
"Content-Type": "application/json",
"Access-Control-Allow-Origin": getCorsOrigin(),
},
});
return upstreamErrorResponse(res, await res.text());
}
const data = await res.text();
@@ -239,6 +302,7 @@ export async function handleAudioTranscription({ formData, credentials }) {
headers: { "Content-Type": contentType, "Access-Control-Allow-Origin": getCorsOrigin() },
});
} catch (err) {
return errorResponse(500, `Transcription request failed: ${err.message}`);
const error = err instanceof Error ? err : new Error(String(err));
return errorResponse(500, `Transcription request failed: ${error.message}`);
}
}

View File

@@ -54,7 +54,6 @@ import { createProgressTransform, wantsProgress } from "../utils/progressTracker
* @param {string} options.connectionId - Connection ID for usage tracking
* @param {object} options.apiKeyInfo - API key metadata for usage attribution
*/
/** @param {any} options */
export async function handleChatCore({
body,
modelInfo,
@@ -135,7 +134,7 @@ export async function handleChatCore({
// Create request logger for this session: sourceFormat_targetFormat_model
const reqLogger = await createRequestLogger(sourceFormat, targetFormat, model);
// 0. Log client raw request (before any conversion)
// 0. Log client raw request (before format conversion)
if (clientRawRequest) {
reqLogger.logClientRawRequest(
clientRawRequest.endpoint,
@@ -152,11 +151,18 @@ export async function handleChatCore({
// Translate request (pass reqLogger for intermediate logging)
let translatedBody = body;
try {
// Issue #199: Disable tool name prefix when routing Claude-format requests
// to non-Claude backends (prefix causes tool name mismatches)
const claudeProviders = ["claude", "anthropic"];
if (targetFormat === FORMATS.CLAUDE && !claudeProviders.includes(provider?.toLowerCase?.())) {
translatedBody = { ...translatedBody, _disableToolPrefix: true };
}
translatedBody = translateRequest(
sourceFormat,
targetFormat,
model,
body,
translatedBody,
stream,
credentials,
provider,
@@ -203,6 +209,7 @@ export async function handleChatCore({
// Extract toolNameMap for response translation (Claude OAuth)
const toolNameMap = translatedBody._toolNameMap;
delete translatedBody._toolNameMap;
delete translatedBody._disableToolPrefix;
// Update model in body
translatedBody.model = model;
@@ -283,6 +290,7 @@ export async function handleChatCore({
comboName,
apiKeyId: apiKeyInfo?.id || null,
apiKeyName: apiKeyInfo?.name || null,
noLog: apiKeyInfo?.noLog === true,
}).catch(() => {});
if (error.name === "AbortError") {
streamController.handleError(error);
@@ -298,11 +306,14 @@ export async function handleChatCore({
providerResponse.status === HTTP_STATUS.UNAUTHORIZED ||
providerResponse.status === HTTP_STATUS.FORBIDDEN
) {
const newCredentials = await refreshWithRetry(
const newCredentials = (await refreshWithRetry(
() => executor.refreshCredentials(credentials, log),
3,
log
);
)) as null | {
accessToken?: string;
copilotToken?: string;
};
if (newCredentials?.accessToken || newCredentials?.copilotToken) {
log?.info?.("TOKEN", `${provider.toUpperCase()} | refreshed`);
@@ -363,6 +374,7 @@ export async function handleChatCore({
comboName,
apiKeyId: apiKeyInfo?.id || null,
apiKeyName: apiKeyInfo?.name || null,
noLog: apiKeyInfo?.noLog === true,
}).catch(() => {});
const errMsg = formatProviderError(new Error(message), provider, model, statusCode);
console.log(`${COLORS.red}[ERROR] ${errMsg}${COLORS.reset}`);
@@ -454,6 +466,7 @@ export async function handleChatCore({
comboName,
apiKeyId: apiKeyInfo?.id || null,
apiKeyName: apiKeyInfo?.name || null,
noLog: apiKeyInfo?.noLog === true,
}).catch(() => {});
if (usage && typeof usage === "object") {
const msg = `[${new Date().toLocaleTimeString("en-US", { hour12: false, hour: "2-digit", minute: "2-digit" })}] 📊 [USAGE] ${provider.toUpperCase()} | in=${usage?.prompt_tokens || 0} | out=${usage?.completion_tokens || 0}${connectionId ? ` | account=${connectionId.slice(0, 8)}...` : ""}`;
@@ -489,7 +502,7 @@ export async function handleChatCore({
const buffered = addBufferToUsage(translatedResponse.usage);
translatedResponse.usage = filterUsageForFormat(buffered, sourceFormat);
} else {
// Fallback: estimate usage when provider didn't return any
// Fallback: estimate usage when provider returned no usage block
const contentLength = JSON.stringify(
translatedResponse?.choices?.[0]?.message?.content || ""
).length;
@@ -556,6 +569,7 @@ export async function handleChatCore({
comboName,
apiKeyId: apiKeyInfo?.id || null,
apiKeyName: apiKeyInfo?.name || null,
noLog: apiKeyInfo?.noLog === true,
}).catch(() => {});
};

View File

@@ -52,7 +52,7 @@ export async function handleEmbedding({ body, credentials, log }) {
}
// Build upstream request
const upstreamBody: Record<string, any> = {
const upstreamBody: Record<string, unknown> = {
model: model,
input: body.input,
};

View File

@@ -17,6 +17,12 @@
import { getImageProvider, parseImageModel } from "../config/imageRegistry.ts";
import { saveCallLog } from "@/lib/usageDb";
import {
submitComfyWorkflow,
pollComfyResult,
fetchComfyOutput,
extractComfyOutputFiles,
} from "../utils/comfyuiClient.ts";
/**
* Handle image generation request
@@ -72,6 +78,14 @@ export async function handleImageGeneration({ body, credentials, log }) {
});
}
if (providerConfig.format === "sdwebui") {
return handleSDWebUIImageGeneration({ model, provider, providerConfig, body, log });
}
if (providerConfig.format === "comfyui") {
return handleComfyUIImageGeneration({ model, provider, providerConfig, body, log });
}
return handleOpenAIImageGeneration({ model, provider, providerConfig, body, credentials, log });
}
@@ -232,7 +246,7 @@ async function handleOpenAIImageGeneration({
};
// Build upstream request (OpenAI-compatible format)
const upstreamBody: Record<string, any> = {
const upstreamBody: Record<string, unknown> = {
model: model,
prompt: body.prompt,
};
@@ -560,3 +574,194 @@ async function handleNanoBananaImageGeneration({
return { success: false, status: 502, error: `Image provider error: ${err.message}` };
}
}
/**
* Handle SD WebUI image generation (local, no auth)
* POST {baseUrl} with { prompt, negative_prompt, width, height, steps }
* Response: { images: ["base64..."] }
*/
async function handleSDWebUIImageGeneration({ model, provider, providerConfig, body, log }) {
const startTime = Date.now();
const [width, height] = (body.size || "512x512").split("x").map(Number);
const upstreamBody = {
prompt: body.prompt,
negative_prompt: body.negative_prompt || "",
width: width || 512,
height: height || 512,
steps: body.steps || 20,
cfg_scale: body.cfg_scale || 7,
sampler_name: body.sampler || "Euler a",
batch_size: body.n || 1,
override_settings: {
sd_model_checkpoint: model,
},
};
if (log) {
const promptPreview = String(body.prompt ?? "").slice(0, 60);
log.info("IMAGE", `${provider}/${model} (sdwebui) | prompt: "${promptPreview}..."`);
}
try {
const response = await fetch(providerConfig.baseUrl, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(upstreamBody),
});
if (!response.ok) {
const errorText = await response.text();
if (log)
log.error("IMAGE", `${provider} error ${response.status}: ${errorText.slice(0, 200)}`);
saveCallLog({
method: "POST",
path: "/v1/images/generations",
status: response.status,
model: `${provider}/${model}`,
provider,
duration: Date.now() - startTime,
error: errorText.slice(0, 500),
}).catch(() => {});
return { success: false, status: response.status, error: errorText };
}
const data = await response.json();
// SD WebUI returns { images: ["base64...", ...] }
const images = (data.images || []).map((b64) => ({
b64_json: b64,
revised_prompt: body.prompt,
}));
saveCallLog({
method: "POST",
path: "/v1/images/generations",
status: 200,
model: `${provider}/${model}`,
provider,
duration: Date.now() - startTime,
responseBody: { images_count: images.length },
}).catch(() => {});
return {
success: true,
data: { created: Math.floor(Date.now() / 1000), data: images },
};
} catch (err) {
if (log) log.error("IMAGE", `${provider} sdwebui error: ${err.message}`);
saveCallLog({
method: "POST",
path: "/v1/images/generations",
status: 502,
model: `${provider}/${model}`,
provider,
duration: Date.now() - startTime,
error: err.message,
}).catch(() => {});
return { success: false, status: 502, error: `Image provider error: ${err.message}` };
}
}
/**
* Handle ComfyUI image generation (local, no auth)
* Submits a txt2img workflow, polls for completion, fetches output
*/
async function handleComfyUIImageGeneration({ model, provider, providerConfig, body, log }) {
const startTime = Date.now();
const [width, height] = (body.size || "1024x1024").split("x").map(Number);
// Default txt2img workflow template for ComfyUI
const workflow = {
"3": {
class_type: "KSampler",
inputs: {
seed: Math.floor(Math.random() * 2 ** 32),
steps: body.steps || 20,
cfg: body.cfg_scale || 7,
sampler_name: "euler",
scheduler: "normal",
denoise: 1,
model: ["4", 0],
positive: ["6", 0],
negative: ["7", 0],
latent_image: ["5", 0],
},
},
"4": {
class_type: "CheckpointLoaderSimple",
inputs: { ckpt_name: model },
},
"5": {
class_type: "EmptyLatentImage",
inputs: { width: width || 1024, height: height || 1024, batch_size: body.n || 1 },
},
"6": {
class_type: "CLIPTextEncode",
inputs: { text: body.prompt, clip: ["4", 1] },
},
"7": {
class_type: "CLIPTextEncode",
inputs: { text: body.negative_prompt || "", clip: ["4", 1] },
},
"8": {
class_type: "VAEDecode",
inputs: { samples: ["3", 0], vae: ["4", 2] },
},
"9": {
class_type: "SaveImage",
inputs: { filename_prefix: "omniroute", images: ["8", 0] },
},
};
if (log) {
const promptPreview = String(body.prompt ?? "").slice(0, 60);
log.info("IMAGE", `${provider}/${model} (comfyui) | prompt: "${promptPreview}..."`);
}
try {
const promptId = await submitComfyWorkflow(providerConfig.baseUrl, workflow);
const historyEntry = await pollComfyResult(providerConfig.baseUrl, promptId);
const outputFiles = extractComfyOutputFiles(historyEntry);
const images = [];
for (const file of outputFiles) {
const buffer = await fetchComfyOutput(
providerConfig.baseUrl,
file.filename,
file.subfolder,
file.type
);
const base64 = Buffer.from(buffer).toString("base64");
images.push({ b64_json: base64, revised_prompt: body.prompt });
}
saveCallLog({
method: "POST",
path: "/v1/images/generations",
status: 200,
model: `${provider}/${model}`,
provider,
duration: Date.now() - startTime,
responseBody: { images_count: images.length },
}).catch(() => {});
return {
success: true,
data: { created: Math.floor(Date.now() / 1000), data: images },
};
} catch (err) {
if (log) log.error("IMAGE", `${provider} comfyui error: ${err.message}`);
saveCallLog({
method: "POST",
path: "/v1/images/generations",
status: 502,
model: `${provider}/${model}`,
provider,
duration: Date.now() - startTime,
error: err.message,
}).catch(() => {});
return { success: false, status: 502, error: `Image provider error: ${err.message}` };
}
}

View File

@@ -16,7 +16,7 @@ import { errorResponse } from "../utils/error.ts";
* @param {Object} options.credentials - Provider credentials { apiKey }
* @returns {Response}
*/
/** @returns {Promise<any>} */
/** @returns {Promise<unknown>} */
export async function handleModeration({ body, credentials }) {
if (!body.input) {
return errorResponse(400, "input is required");

View File

@@ -0,0 +1,159 @@
/**
* Music Generation Handler
*
* Handles POST /v1/music/generations requests.
* Proxies to upstream music generation providers.
*
* Supported provider formats:
* - ComfyUI: submit audio workflow → poll → fetch output
*
* Response format (OpenAI-like):
* {
* "created": 1234567890,
* "data": [{ "b64_json": "...", "format": "wav" }]
* }
*/
import { getMusicProvider, parseMusicModel } from "../config/musicRegistry.ts";
import {
submitComfyWorkflow,
pollComfyResult,
fetchComfyOutput,
extractComfyOutputFiles,
} from "../utils/comfyuiClient.ts";
import { saveCallLog } from "@/lib/usageDb";
/**
* Handle music generation request
*/
export async function handleMusicGeneration({ body, credentials, log }) {
const { provider, model } = parseMusicModel(body.model);
if (!provider) {
return {
success: false,
status: 400,
error: `Invalid music model: ${body.model}. Use format: provider/model`,
};
}
const providerConfig = getMusicProvider(provider);
if (!providerConfig) {
return {
success: false,
status: 400,
error: `Unknown music provider: ${provider}`,
};
}
if (providerConfig.format === "comfyui") {
return handleComfyUIMusicGeneration({ model, provider, providerConfig, body, log });
}
return { success: false, status: 400, error: `Unsupported music format: ${providerConfig.format}` };
}
/**
* Handle ComfyUI music generation
* Submits an audio generation workflow (Stable Audio / MusicGen), polls, fetches output
*/
async function handleComfyUIMusicGeneration({ model, provider, providerConfig, body, log }) {
const startTime = Date.now();
const duration = body.duration || 10; // seconds
// Audio generation workflow template for ComfyUI
const workflow = {
"1": {
class_type: "CheckpointLoaderSimple",
inputs: { ckpt_name: model },
},
"2": {
class_type: "CLIPTextEncode",
inputs: { text: body.prompt, clip: ["1", 1] },
},
"3": {
class_type: "CLIPTextEncode",
inputs: { text: body.negative_prompt || "", clip: ["1", 1] },
},
"4": {
class_type: "EmptyLatentAudio",
inputs: { seconds: duration },
},
"5": {
class_type: "KSampler",
inputs: {
seed: Math.floor(Math.random() * 2 ** 32),
steps: body.steps || 100,
cfg: body.cfg_scale || 7,
sampler_name: "euler",
scheduler: "normal",
denoise: 1,
model: ["1", 0],
positive: ["2", 0],
negative: ["3", 0],
latent_image: ["4", 0],
},
},
"6": {
class_type: "VAEDecodeAudio",
inputs: { samples: ["5", 0], vae: ["1", 2] },
},
"7": {
class_type: "SaveAudio",
inputs: {
filename_prefix: "omniroute_music",
audio: ["6", 0],
},
},
};
if (log) {
const promptPreview = String(body.prompt ?? "").slice(0, 60);
log.info("MUSIC", `${provider}/${model} (comfyui) | prompt: "${promptPreview}..." | duration: ${duration}s`);
}
try {
const promptId = await submitComfyWorkflow(providerConfig.baseUrl, workflow);
const historyEntry = await pollComfyResult(providerConfig.baseUrl, promptId, 300_000);
const outputFiles = extractComfyOutputFiles(historyEntry);
const audioFiles = [];
for (const file of outputFiles) {
const buffer = await fetchComfyOutput(
providerConfig.baseUrl,
file.filename,
file.subfolder,
file.type
);
const base64 = Buffer.from(buffer).toString("base64");
audioFiles.push({ b64_json: base64, format: "wav" });
}
saveCallLog({
method: "POST",
path: "/v1/music/generations",
status: 200,
model: `${provider}/${model}`,
provider,
duration: Date.now() - startTime,
responseBody: { audio_count: audioFiles.length },
}).catch(() => {});
return {
success: true,
data: { created: Math.floor(Date.now() / 1000), data: audioFiles },
};
} catch (err) {
if (log) log.error("MUSIC", `${provider} comfyui error: ${err.message}`);
saveCallLog({
method: "POST",
path: "/v1/music/generations",
status: 502,
model: `${provider}/${model}`,
provider,
duration: Date.now() - startTime,
error: err.message,
}).catch(() => {});
return { success: false, status: 502, error: `Music provider error: ${err.message}` };
}
}

View File

@@ -70,7 +70,7 @@ function transformResponseFromProvider(providerConfig, data) {
* @param {Object} options.credentials - Provider credentials { apiKey, accessToken }
* @returns {Response}
*/
/** @returns {Promise<any>} */
/** @returns {Promise<unknown>} */
export async function handleRerank({
model,
query,

View File

@@ -9,17 +9,6 @@
* 4. Converts developer role → system for non-OpenAI providers
*/
// ── Standard OpenAI ChatCompletion fields ──────────────────────────────────
const ALLOWED_TOP_LEVEL_FIELDS = new Set([
"id",
"object",
"created",
"model",
"choices",
"usage",
"system_fingerprint",
]);
const ALLOWED_USAGE_FIELDS = new Set([
"prompt_tokens",
"completion_tokens",
@@ -28,16 +17,20 @@ const ALLOWED_USAGE_FIELDS = new Set([
"completion_tokens_details",
]);
const ALLOWED_MESSAGE_FIELDS = new Set([
"role",
"content",
"tool_calls",
"function_call",
"refusal",
"reasoning_content",
]);
type JsonRecord = Record<string, unknown>;
const ALLOWED_CHOICE_FIELDS = new Set(["index", "message", "delta", "finish_reason", "logprobs"]);
function toRecord(value: unknown): JsonRecord | null {
if (!value || typeof value !== "object" || Array.isArray(value)) return null;
return value as JsonRecord;
}
function toString(value: unknown): string | undefined {
return typeof value === "string" ? value : undefined;
}
function toNumber(value: unknown): number | undefined {
return typeof value === "number" && Number.isFinite(value) ? value : undefined;
}
// ── Think tag regex ────────────────────────────────────────────────────────
// Matches <think>...</think> blocks (greedy, dotAll)
@@ -81,33 +74,34 @@ export function extractThinkingFromContent(text: string): {
* Sanitize a non-streaming OpenAI ChatCompletion response.
* Strips non-standard fields and normalizes required fields.
*/
export function sanitizeOpenAIResponse(body: any): any {
if (!body || typeof body !== "object") return body;
export function sanitizeOpenAIResponse(body: unknown): unknown {
const bodyRecord = toRecord(body);
if (!bodyRecord) return body;
// Build sanitized response with only allowed top-level fields
const sanitized: Record<string, any> = {};
const sanitized: JsonRecord = {};
// Ensure required fields exist
sanitized.id = normalizeResponseId(body.id);
sanitized.object = body.object || "chat.completion";
sanitized.created = body.created || Math.floor(Date.now() / 1000);
sanitized.model = body.model || "unknown";
sanitized.id = normalizeResponseId(bodyRecord.id);
sanitized.object = toString(bodyRecord.object) || "chat.completion";
sanitized.created = toNumber(bodyRecord.created) ?? Math.floor(Date.now() / 1000);
sanitized.model = toString(bodyRecord.model) || "unknown";
// Sanitize choices
if (Array.isArray(body.choices)) {
sanitized.choices = body.choices.map((choice: any, idx: number) => sanitizeChoice(choice, idx));
if (Array.isArray(bodyRecord.choices)) {
sanitized.choices = bodyRecord.choices.map((choice, idx) => sanitizeChoice(choice, idx));
} else {
sanitized.choices = [];
}
// Sanitize usage
if (body.usage && typeof body.usage === "object") {
sanitized.usage = sanitizeUsage(body.usage);
if (bodyRecord.usage !== undefined) {
sanitized.usage = sanitizeUsage(bodyRecord.usage);
}
// Keep system_fingerprint if present (it's a valid OpenAI field)
if (body.system_fingerprint) {
sanitized.system_fingerprint = body.system_fingerprint;
if (bodyRecord.system_fingerprint) {
sanitized.system_fingerprint = bodyRecord.system_fingerprint;
}
return sanitized;
@@ -116,23 +110,32 @@ export function sanitizeOpenAIResponse(body: any): any {
/**
* Sanitize a single choice object.
*/
function sanitizeChoice(choice: any, defaultIndex: number): any {
const sanitized: Record<string, any> = {
index: choice.index ?? defaultIndex,
finish_reason: choice.finish_reason || null,
function sanitizeChoice(choice: unknown, defaultIndex: number): JsonRecord {
const choiceRecord = toRecord(choice);
const sanitized: JsonRecord = {
index: defaultIndex,
finish_reason: null,
};
// Sanitize message (non-streaming) or delta (streaming)
if (choice.message) {
sanitized.message = sanitizeMessage(choice.message);
if (choiceRecord?.index !== undefined) {
sanitized.index = choiceRecord.index;
}
if (choice.delta) {
sanitized.delta = sanitizeMessage(choice.delta);
if (choiceRecord?.finish_reason !== undefined) {
sanitized.finish_reason = choiceRecord.finish_reason;
}
// Sanitize message (non-streaming) or delta (streaming)
if (choiceRecord?.message !== undefined) {
sanitized.message = sanitizeMessage(choiceRecord.message);
}
if (choiceRecord?.delta !== undefined) {
sanitized.delta = sanitizeMessage(choiceRecord.delta);
}
// Keep logprobs if present
if (choice.logprobs !== undefined) {
sanitized.logprobs = choice.logprobs;
if (choiceRecord?.logprobs !== undefined) {
sanitized.logprobs = choiceRecord.logprobs;
}
return sanitized;
@@ -141,41 +144,42 @@ function sanitizeChoice(choice: any, defaultIndex: number): any {
/**
* Sanitize a message object, extracting <think> tags if present.
*/
function sanitizeMessage(msg: any): any {
if (!msg || typeof msg !== "object") return msg;
function sanitizeMessage(msg: unknown): unknown {
const msgRecord = toRecord(msg);
if (!msgRecord) return msg;
const sanitized: Record<string, any> = {};
const sanitized: JsonRecord = {};
// Copy only allowed fields
if (msg.role) sanitized.role = msg.role;
if (msg.refusal !== undefined) sanitized.refusal = msg.refusal;
if (msgRecord.role) sanitized.role = msgRecord.role;
if (msgRecord.refusal !== undefined) sanitized.refusal = msgRecord.refusal;
// Handle content — extract <think> tags
if (typeof msg.content === "string") {
const { content, thinking } = extractThinkingFromContent(msg.content);
if (typeof msgRecord.content === "string") {
const { content, thinking } = extractThinkingFromContent(msgRecord.content);
sanitized.content = content;
// Set reasoning_content from <think> tags (if not already set)
if (thinking && !msg.reasoning_content) {
if (thinking && !msgRecord.reasoning_content) {
sanitized.reasoning_content = thinking;
}
} else if (msg.content !== undefined) {
sanitized.content = msg.content;
} else if (msgRecord.content !== undefined) {
sanitized.content = msgRecord.content;
}
// Preserve existing reasoning_content (from providers that natively support it)
if (msg.reasoning_content && !sanitized.reasoning_content) {
sanitized.reasoning_content = msg.reasoning_content;
if (msgRecord.reasoning_content && !sanitized.reasoning_content) {
sanitized.reasoning_content = msgRecord.reasoning_content;
}
// Preserve tool_calls
if (msg.tool_calls) {
sanitized.tool_calls = msg.tool_calls;
if (msgRecord.tool_calls) {
sanitized.tool_calls = msgRecord.tool_calls;
}
// Preserve function_call (legacy)
if (msg.function_call) {
sanitized.function_call = msg.function_call;
if (msgRecord.function_call) {
sanitized.function_call = msgRecord.function_call;
}
return sanitized;
@@ -184,22 +188,25 @@ function sanitizeMessage(msg: any): any {
/**
* Sanitize usage object — keep only standard fields.
*/
function sanitizeUsage(usage: any): any {
if (!usage || typeof usage !== "object") return usage;
function sanitizeUsage(usage: unknown): unknown {
const usageRecord = toRecord(usage);
if (!usageRecord) return usage;
const sanitized: Record<string, any> = {};
const sanitized: JsonRecord = {};
for (const key of ALLOWED_USAGE_FIELDS) {
if (usage[key] !== undefined) {
sanitized[key] = usage[key];
if (usageRecord[key] !== undefined) {
sanitized[key] = usageRecord[key];
}
}
// Ensure required fields
if (sanitized.prompt_tokens === undefined) sanitized.prompt_tokens = 0;
if (sanitized.completion_tokens === undefined) sanitized.completion_tokens = 0;
if (sanitized.total_tokens === undefined) {
sanitized.total_tokens = sanitized.prompt_tokens + sanitized.completion_tokens;
}
const promptTokens = toNumber(sanitized.prompt_tokens) ?? 0;
const completionTokens = toNumber(sanitized.completion_tokens) ?? 0;
const totalTokens = toNumber(sanitized.total_tokens) ?? promptTokens + completionTokens;
sanitized.prompt_tokens = promptTokens;
sanitized.completion_tokens = completionTokens;
sanitized.total_tokens = totalTokens;
return sanitized;
}
@@ -207,7 +214,7 @@ function sanitizeUsage(usage: any): any {
/**
* Normalize response ID to use chatcmpl- prefix.
*/
function normalizeResponseId(id: any): string {
function normalizeResponseId(id: unknown): string {
if (!id || typeof id !== "string") {
return `chatcmpl-${crypto.randomUUID().replace(/-/g, "").slice(0, 29)}`;
}
@@ -221,48 +228,60 @@ function normalizeResponseId(id: any): string {
* Sanitize a streaming SSE chunk for passthrough mode.
* Lighter than full sanitization — only strips problematic extra fields.
*/
export function sanitizeStreamingChunk(parsed: any): any {
if (!parsed || typeof parsed !== "object") return parsed;
export function sanitizeStreamingChunk(parsed: unknown): unknown {
const parsedRecord = toRecord(parsed);
if (!parsedRecord) return parsed;
// Build sanitized chunk
const sanitized: Record<string, any> = {};
const sanitized: JsonRecord = {};
// Keep only standard fields
if (parsed.id !== undefined) sanitized.id = parsed.id;
sanitized.object = parsed.object || "chat.completion.chunk";
if (parsed.created !== undefined) sanitized.created = parsed.created;
if (parsed.model !== undefined) sanitized.model = parsed.model;
if (parsedRecord.id !== undefined) sanitized.id = parsedRecord.id;
sanitized.object = toString(parsedRecord.object) || "chat.completion.chunk";
if (parsedRecord.created !== undefined) sanitized.created = parsedRecord.created;
if (parsedRecord.model !== undefined) sanitized.model = parsedRecord.model;
// Sanitize choices with delta
if (Array.isArray(parsed.choices)) {
sanitized.choices = parsed.choices.map((choice: any) => {
const c: Record<string, any> = {
index: choice.index ?? 0,
};
if (choice.delta !== undefined) {
c.delta = {};
const delta = choice.delta;
if (delta.role !== undefined) c.delta.role = delta.role;
if (delta.content !== undefined) c.delta.content = delta.content;
if (delta.reasoning_content !== undefined)
c.delta.reasoning_content = delta.reasoning_content;
if (delta.tool_calls !== undefined) c.delta.tool_calls = delta.tool_calls;
if (delta.function_call !== undefined) c.delta.function_call = delta.function_call;
if (Array.isArray(parsedRecord.choices)) {
sanitized.choices = parsedRecord.choices.map((choice) => {
const c: JsonRecord = { index: 0 };
const choiceRecord = toRecord(choice);
if (!choiceRecord) return c;
c.index = toNumber(choiceRecord.index) ?? 0;
if (choiceRecord.delta !== undefined) {
const deltaRecord = toRecord(choiceRecord.delta);
if (deltaRecord) {
const delta: JsonRecord = {};
if (deltaRecord.role !== undefined) delta.role = deltaRecord.role;
if (deltaRecord.content !== undefined) delta.content = deltaRecord.content;
if (deltaRecord.reasoning_content !== undefined) {
delta.reasoning_content = deltaRecord.reasoning_content;
}
if (deltaRecord.tool_calls !== undefined) delta.tool_calls = deltaRecord.tool_calls;
if (deltaRecord.function_call !== undefined)
delta.function_call = deltaRecord.function_call;
c.delta = delta;
} else {
c.delta = choiceRecord.delta;
}
}
if (choice.finish_reason !== undefined) c.finish_reason = choice.finish_reason;
if (choice.logprobs !== undefined) c.logprobs = choice.logprobs;
if (choiceRecord.finish_reason !== undefined) c.finish_reason = choiceRecord.finish_reason;
if (choiceRecord.logprobs !== undefined) c.logprobs = choiceRecord.logprobs;
return c;
});
}
// Sanitize usage if present
if (parsed.usage && typeof parsed.usage === "object") {
sanitized.usage = sanitizeUsage(parsed.usage);
if (parsedRecord.usage !== undefined) {
sanitized.usage = sanitizeUsage(parsedRecord.usage);
}
// Keep system_fingerprint if present
if (parsed.system_fingerprint) {
sanitized.system_fingerprint = parsed.system_fingerprint;
if (parsedRecord.system_fingerprint) {
sanitized.system_fingerprint = parsedRecord.system_fingerprint;
}
return sanitized;

View File

@@ -1,10 +1,34 @@
import { FORMATS } from "../translator/formats.ts";
type JsonRecord = Record<string, unknown>;
function toRecord(value: unknown): JsonRecord {
return value && typeof value === "object" && !Array.isArray(value) ? (value as JsonRecord) : {};
}
function toString(value: unknown, fallback = ""): string {
return typeof value === "string" ? value : fallback;
}
function toNumber(value: unknown, fallback = 0): number {
const parsed =
typeof value === "number"
? value
: typeof value === "string" && value.trim().length > 0
? Number(value)
: Number.NaN;
return Number.isFinite(parsed) ? parsed : fallback;
}
/**
* Translate non-streaming response to OpenAI format
* Handles different provider response formats (Gemini, Claude, etc.)
*/
export function translateNonStreamingResponse(responseBody, targetFormat, sourceFormat) {
export function translateNonStreamingResponse(
responseBody: unknown,
targetFormat: string,
sourceFormat: string
): unknown {
// If already in source format (usually OpenAI), return as-is
if (targetFormat === sourceFormat || targetFormat === FORMATS.OPENAI) {
return responseBody;
@@ -12,51 +36,60 @@ export function translateNonStreamingResponse(responseBody, targetFormat, source
// Handle OpenAI Responses API format
if (targetFormat === FORMATS.OPENAI_RESPONSES) {
const responseRoot = toRecord(responseBody);
const response =
responseBody?.object === "response" ? responseBody : responseBody?.response || responseBody;
const output = Array.isArray(response?.output) ? response.output : [];
const usage = response?.usage || responseBody?.usage;
responseRoot.object === "response"
? responseRoot
: toRecord(responseRoot.response ?? responseRoot);
const output = Array.isArray(response.output) ? response.output : [];
const usage = toRecord(response.usage ?? responseRoot.usage);
let textContent = "";
let reasoningContent = "";
const toolCalls = [];
const toolCalls: JsonRecord[] = [];
for (const item of output) {
if (!item || typeof item !== "object") continue;
const itemObj = toRecord(item);
if (item.type === "message" && Array.isArray(item.content)) {
for (const part of item.content) {
if (itemObj.type === "message" && Array.isArray(itemObj.content)) {
for (const part of itemObj.content) {
if (!part || typeof part !== "object") continue;
if (part.type === "output_text" && typeof part.text === "string") {
textContent += part.text;
} else if (part.type === "summary_text" && typeof part.text === "string") {
reasoningContent += part.text;
const partObj = toRecord(part);
if (partObj.type === "output_text" && typeof partObj.text === "string") {
textContent += partObj.text;
} else if (partObj.type === "summary_text" && typeof partObj.text === "string") {
reasoningContent += partObj.text;
}
}
} else if (item.type === "reasoning" && Array.isArray(item.summary)) {
for (const part of item.summary) {
if (part?.type === "summary_text" && typeof part.text === "string") {
reasoningContent += part.text;
} else if (itemObj.type === "reasoning" && Array.isArray(itemObj.summary)) {
for (const part of itemObj.summary) {
const partObj = toRecord(part);
if (partObj.type === "summary_text" && typeof partObj.text === "string") {
reasoningContent += partObj.text;
}
}
} else if (item.type === "function_call") {
const callId = item.call_id || item.id || `call_${Date.now()}_${toolCalls.length}`;
} else if (itemObj.type === "function_call") {
const callId =
toString(itemObj.call_id) ||
toString(itemObj.id) ||
`call_${Date.now()}_${toolCalls.length}`;
const fnArgs =
typeof item.arguments === "string"
? item.arguments
: JSON.stringify(item.arguments || {});
typeof itemObj.arguments === "string"
? itemObj.arguments
: JSON.stringify(itemObj.arguments || {});
toolCalls.push({
id: callId,
type: "function",
function: {
name: item.name || "",
name: toString(itemObj.name),
arguments: fnArgs,
},
});
}
}
const message: Record<string, any> = { role: "assistant" };
const message: JsonRecord = { role: "assistant" };
if (textContent) {
message.content = textContent;
}
@@ -70,12 +103,12 @@ export function translateNonStreamingResponse(responseBody, targetFormat, source
message.content = "";
}
const createdAt = Number(response?.created_at) || Math.floor(Date.now() / 1000);
const model = response?.model || responseBody?.model || "openai-responses";
const createdAt = toNumber(response.created_at, Math.floor(Date.now() / 1000));
const model = toString(response.model || responseRoot.model, "openai-responses");
const finishReason = toolCalls.length > 0 ? "tool_calls" : "stop";
const result: Record<string, any> = {
id: `chatcmpl-${response?.id || Date.now()}`,
const result: JsonRecord = {
id: `chatcmpl-${toString(response.id, String(Date.now()))}`,
object: "chat.completion",
created: createdAt,
model,
@@ -88,28 +121,31 @@ export function translateNonStreamingResponse(responseBody, targetFormat, source
],
};
if (usage && typeof usage === "object") {
const inputTokens = usage.input_tokens || 0;
const outputTokens = usage.output_tokens || 0;
if (Object.keys(usage).length > 0) {
const inputTokens = toNumber(usage.input_tokens, 0);
const outputTokens = toNumber(usage.output_tokens, 0);
result.usage = {
prompt_tokens: inputTokens,
completion_tokens: outputTokens,
total_tokens: inputTokens + outputTokens,
};
if (usage.reasoning_tokens > 0) {
result.usage.completion_tokens_details = {
reasoning_tokens: usage.reasoning_tokens,
if (toNumber(usage.reasoning_tokens, 0) > 0) {
(result.usage as JsonRecord).completion_tokens_details = {
reasoning_tokens: toNumber(usage.reasoning_tokens, 0),
};
}
if (usage.cache_read_input_tokens > 0 || usage.cache_creation_input_tokens > 0) {
result.usage.prompt_tokens_details = {};
if (usage.cache_read_input_tokens > 0) {
result.usage.prompt_tokens_details.cached_tokens = usage.cache_read_input_tokens;
if (
toNumber(usage.cache_read_input_tokens, 0) > 0 ||
toNumber(usage.cache_creation_input_tokens, 0) > 0
) {
(result.usage as JsonRecord).prompt_tokens_details = {};
const promptDetails = (result.usage as JsonRecord).prompt_tokens_details as JsonRecord;
if (toNumber(usage.cache_read_input_tokens, 0) > 0) {
promptDetails.cached_tokens = toNumber(usage.cache_read_input_tokens, 0);
}
if (usage.cache_creation_input_tokens > 0) {
result.usage.prompt_tokens_details.cache_creation_tokens =
usage.cache_creation_input_tokens;
if (toNumber(usage.cache_creation_input_tokens, 0) > 0) {
promptDetails.cache_creation_tokens = toNumber(usage.cache_creation_input_tokens, 0);
}
}
}
@@ -123,38 +159,42 @@ export function translateNonStreamingResponse(responseBody, targetFormat, source
targetFormat === FORMATS.ANTIGRAVITY ||
targetFormat === FORMATS.GEMINI_CLI
) {
const response = responseBody.response || responseBody;
if (!response?.candidates?.[0]) {
const root = toRecord(responseBody);
const response = toRecord(root.response ?? root);
const candidates = Array.isArray(response.candidates) ? response.candidates : [];
if (!candidates[0]) {
return responseBody; // Can't translate, return raw
}
const candidate = response.candidates[0];
const content = candidate.content;
const usage = response.usageMetadata || responseBody.usageMetadata;
const candidate = toRecord(candidates[0]);
const content = toRecord(candidate.content);
const usage = toRecord(response.usageMetadata ?? root.usageMetadata);
// Build message content
let textContent = "";
const toolCalls = [];
const toolCalls: JsonRecord[] = [];
let reasoningContent = "";
if (content?.parts) {
if (Array.isArray(content.parts)) {
for (const part of content.parts) {
const partObj = toRecord(part);
// Handle thinking/reasoning
if (part.thought === true && part.text) {
reasoningContent += part.text;
if (partObj.thought === true && typeof partObj.text === "string") {
reasoningContent += partObj.text;
}
// Regular text
else if (part.text !== undefined) {
textContent += part.text;
else if (typeof partObj.text === "string") {
textContent += partObj.text;
}
// Function calls
if (part.functionCall) {
if (partObj.functionCall) {
const fn = toRecord(partObj.functionCall);
toolCalls.push({
id: `call_${part.functionCall.name}_${Date.now()}_${toolCalls.length}`,
id: `call_${toString(fn.name, "unknown")}_${Date.now()}_${toolCalls.length}`,
type: "function",
function: {
name: part.functionCall.name,
arguments: JSON.stringify(part.functionCall.args || {}),
name: toString(fn.name),
arguments: JSON.stringify(fn.args || {}),
},
});
}
@@ -162,7 +202,7 @@ export function translateNonStreamingResponse(responseBody, targetFormat, source
}
// Build OpenAI format message
const message: Record<string, any> = { role: "assistant" };
const message: JsonRecord = { role: "assistant" };
if (textContent) {
message.content = textContent;
}
@@ -178,16 +218,21 @@ export function translateNonStreamingResponse(responseBody, targetFormat, source
}
// Determine finish reason
let finishReason = (candidate.finishReason || "stop").toLowerCase();
let finishReason = toString(candidate.finishReason, "stop").toLowerCase();
if (finishReason === "stop" && toolCalls.length > 0) {
finishReason = "tool_calls";
}
const result: Record<string, any> = {
id: `chatcmpl-${response.responseId || Date.now()}`,
const createdMs = Date.parse(toString(response.createTime));
const created = Number.isFinite(createdMs)
? Math.floor(createdMs / 1000)
: Math.floor(Date.now() / 1000);
const result: JsonRecord = {
id: `chatcmpl-${toString(response.responseId, String(Date.now()))}`,
object: "chat.completion",
created: Math.floor(new Date(response.createTime || Date.now()).getTime() / 1000),
model: response.modelVersion || "gemini",
created,
model: toString(response.modelVersion, "gemini"),
choices: [
{
index: 0,
@@ -198,15 +243,15 @@ export function translateNonStreamingResponse(responseBody, targetFormat, source
};
// Add usage if available (match streaming translator: add thoughtsTokenCount to prompt_tokens)
if (usage) {
if (Object.keys(usage).length > 0) {
result.usage = {
prompt_tokens: (usage.promptTokenCount || 0) + (usage.thoughtsTokenCount || 0),
completion_tokens: usage.candidatesTokenCount || 0,
total_tokens: usage.totalTokenCount || 0,
prompt_tokens: toNumber(usage.promptTokenCount, 0) + toNumber(usage.thoughtsTokenCount, 0),
completion_tokens: toNumber(usage.candidatesTokenCount, 0),
total_tokens: toNumber(usage.totalTokenCount, 0),
};
if (usage.thoughtsTokenCount > 0) {
result.usage.completion_tokens_details = {
reasoning_tokens: usage.thoughtsTokenCount,
if (toNumber(usage.thoughtsTokenCount, 0) > 0) {
(result.usage as JsonRecord).completion_tokens_details = {
reasoning_tokens: toNumber(usage.thoughtsTokenCount, 0),
};
}
}
@@ -216,32 +261,35 @@ export function translateNonStreamingResponse(responseBody, targetFormat, source
// Handle Claude format
if (targetFormat === FORMATS.CLAUDE) {
if (!responseBody.content) {
const root = toRecord(responseBody);
const contentBlocks = Array.isArray(root.content) ? root.content : [];
if (contentBlocks.length === 0) {
return responseBody; // Can't translate, return raw
}
let textContent = "";
let thinkingContent = "";
const toolCalls = [];
const toolCalls: JsonRecord[] = [];
for (const block of responseBody.content) {
if (block.type === "text") {
textContent += block.text;
} else if (block.type === "thinking") {
thinkingContent += block.thinking || "";
} else if (block.type === "tool_use") {
for (const block of contentBlocks) {
const blockObj = toRecord(block);
if (blockObj.type === "text") {
textContent += toString(blockObj.text);
} else if (blockObj.type === "thinking") {
thinkingContent += toString(blockObj.thinking);
} else if (blockObj.type === "tool_use") {
toolCalls.push({
id: block.id,
id: toString(blockObj.id, `call_${Date.now()}_${toolCalls.length}`),
type: "function",
function: {
name: block.name,
arguments: JSON.stringify(block.input || {}),
name: toString(blockObj.name),
arguments: JSON.stringify(blockObj.input || {}),
},
});
}
}
const message: Record<string, any> = { role: "assistant" };
const message: JsonRecord = { role: "assistant" };
if (textContent) {
message.content = textContent;
}
@@ -255,15 +303,15 @@ export function translateNonStreamingResponse(responseBody, targetFormat, source
message.content = "";
}
let finishReason = responseBody.stop_reason || "stop";
let finishReason = toString(root.stop_reason, "stop");
if (finishReason === "end_turn") finishReason = "stop";
if (finishReason === "tool_use") finishReason = "tool_calls";
const result: Record<string, any> = {
id: `chatcmpl-${responseBody.id || Date.now()}`,
const result: JsonRecord = {
id: `chatcmpl-${toString(root.id, String(Date.now()))}`,
object: "chat.completion",
created: Math.floor(Date.now() / 1000),
model: responseBody.model || "claude",
model: toString(root.model, "claude"),
choices: [
{
index: 0,
@@ -273,12 +321,14 @@ export function translateNonStreamingResponse(responseBody, targetFormat, source
],
};
if (responseBody.usage) {
const usage = toRecord(root.usage);
if (Object.keys(usage).length > 0) {
const promptTokens = toNumber(usage.input_tokens, 0);
const completionTokens = toNumber(usage.output_tokens, 0);
result.usage = {
prompt_tokens: responseBody.usage.input_tokens || 0,
completion_tokens: responseBody.usage.output_tokens || 0,
total_tokens:
(responseBody.usage.input_tokens || 0) + (responseBody.usage.output_tokens || 0),
prompt_tokens: promptTokens,
completion_tokens: completionTokens,
total_tokens: promptTokens + completionTokens,
};
}

View File

@@ -50,7 +50,7 @@ export async function handleResponsesCore({
connectionId,
userAgent: null,
comboName: null,
} as any);
});
if (!result.success || !result.response) {
return result;

View File

@@ -44,14 +44,15 @@ export function parseSSEToOpenAIResponse(rawSSE, fallbackModel) {
}
}
const message: Record<string, any> = { role: "assistant",
const message: Record<string, unknown> = {
role: "assistant",
content: contentParts.join(""),
};
if (reasoningParts.length > 0) {
message.reasoning_content = reasoningParts.join("");
}
const result: Record<string, any> = {
const result: Record<string, unknown> = {
id: first.id || `chatcmpl-${Date.now()}`,
object: "chat.completion",
created: first.created || Math.floor(Date.now() / 1000),

View File

@@ -0,0 +1,256 @@
/**
* Video Generation Handler
*
* Handles POST /v1/videos/generations requests.
* Proxies to upstream video generation providers.
*
* Supported provider formats:
* - ComfyUI: submit AnimateDiff/SVD workflow → poll → fetch video
* - SD WebUI: POST to AnimateDiff extension endpoint
*
* Response format (OpenAI-like):
* {
* "created": 1234567890,
* "data": [{ "b64_json": "...", "format": "mp4" }]
* }
*/
import { getVideoProvider, parseVideoModel } from "../config/videoRegistry.ts";
import {
submitComfyWorkflow,
pollComfyResult,
fetchComfyOutput,
extractComfyOutputFiles,
} from "../utils/comfyuiClient.ts";
import { saveCallLog } from "@/lib/usageDb";
/**
* Handle video generation request
*/
export async function handleVideoGeneration({ body, credentials, log }) {
const { provider, model } = parseVideoModel(body.model);
if (!provider) {
return {
success: false,
status: 400,
error: `Invalid video model: ${body.model}. Use format: provider/model`,
};
}
const providerConfig = getVideoProvider(provider);
if (!providerConfig) {
return {
success: false,
status: 400,
error: `Unknown video provider: ${provider}`,
};
}
if (providerConfig.format === "comfyui") {
return handleComfyUIVideoGeneration({ model, provider, providerConfig, body, log });
}
if (providerConfig.format === "sdwebui-video") {
return handleSDWebUIVideoGeneration({ model, provider, providerConfig, body, log });
}
return { success: false, status: 400, error: `Unsupported video format: ${providerConfig.format}` };
}
/**
* Handle ComfyUI video generation
* Submits an AnimateDiff or SVD workflow, polls for completion, fetches output video
*/
async function handleComfyUIVideoGeneration({ model, provider, providerConfig, body, log }) {
const startTime = Date.now();
const [width, height] = (body.size || "512x512").split("x").map(Number);
const frames = body.frames || 16;
// AnimateDiff workflow template
const workflow = {
"1": {
class_type: "CheckpointLoaderSimple",
inputs: { ckpt_name: model },
},
"2": {
class_type: "CLIPTextEncode",
inputs: { text: body.prompt, clip: ["1", 1] },
},
"3": {
class_type: "CLIPTextEncode",
inputs: { text: body.negative_prompt || "", clip: ["1", 1] },
},
"4": {
class_type: "EmptyLatentImage",
inputs: { width: width || 512, height: height || 512, batch_size: frames },
},
"5": {
class_type: "KSampler",
inputs: {
seed: Math.floor(Math.random() * 2 ** 32),
steps: body.steps || 20,
cfg: body.cfg_scale || 7,
sampler_name: "euler",
scheduler: "normal",
denoise: 1,
model: ["1", 0],
positive: ["2", 0],
negative: ["3", 0],
latent_image: ["4", 0],
},
},
"6": {
class_type: "VAEDecode",
inputs: { samples: ["5", 0], vae: ["1", 2] },
},
"7": {
class_type: "SaveAnimatedWEBP",
inputs: {
filename_prefix: "omniroute_video",
fps: body.fps || 8,
lossless: false,
quality: 80,
method: "default",
images: ["6", 0],
},
},
};
if (log) {
const promptPreview = String(body.prompt ?? "").slice(0, 60);
log.info("VIDEO", `${provider}/${model} (comfyui) | prompt: "${promptPreview}..." | frames: ${frames}`);
}
try {
const promptId = await submitComfyWorkflow(providerConfig.baseUrl, workflow);
const historyEntry = await pollComfyResult(providerConfig.baseUrl, promptId, 300_000);
const outputFiles = extractComfyOutputFiles(historyEntry);
const videos = [];
for (const file of outputFiles) {
const buffer = await fetchComfyOutput(
providerConfig.baseUrl,
file.filename,
file.subfolder,
file.type
);
const base64 = Buffer.from(buffer).toString("base64");
videos.push({ b64_json: base64, format: "webp" });
}
saveCallLog({
method: "POST",
path: "/v1/videos/generations",
status: 200,
model: `${provider}/${model}`,
provider,
duration: Date.now() - startTime,
responseBody: { videos_count: videos.length },
}).catch(() => {});
return {
success: true,
data: { created: Math.floor(Date.now() / 1000), data: videos },
};
} catch (err) {
if (log) log.error("VIDEO", `${provider} comfyui error: ${err.message}`);
saveCallLog({
method: "POST",
path: "/v1/videos/generations",
status: 502,
model: `${provider}/${model}`,
provider,
duration: Date.now() - startTime,
error: err.message,
}).catch(() => {});
return { success: false, status: 502, error: `Video provider error: ${err.message}` };
}
}
/**
* Handle SD WebUI video generation via AnimateDiff extension
* POST to the AnimateDiff API endpoint
*/
async function handleSDWebUIVideoGeneration({ model, provider, providerConfig, body, log }) {
const startTime = Date.now();
const [width, height] = (body.size || "512x512").split("x").map(Number);
const url = `${providerConfig.baseUrl}/animatediff/v1/generate`;
const upstreamBody = {
prompt: body.prompt,
negative_prompt: body.negative_prompt || "",
width: width || 512,
height: height || 512,
steps: body.steps || 20,
cfg_scale: body.cfg_scale || 7,
frames: body.frames || 16,
fps: body.fps || 8,
};
if (log) {
const promptPreview = String(body.prompt ?? "").slice(0, 60);
log.info("VIDEO", `${provider}/${model} (sdwebui) | prompt: "${promptPreview}..."`);
}
try {
const response = await fetch(url, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(upstreamBody),
});
if (!response.ok) {
const errorText = await response.text();
if (log) log.error("VIDEO", `${provider} error ${response.status}: ${errorText.slice(0, 200)}`);
saveCallLog({
method: "POST",
path: "/v1/videos/generations",
status: response.status,
model: `${provider}/${model}`,
provider,
duration: Date.now() - startTime,
error: errorText.slice(0, 500),
}).catch(() => {});
return { success: false, status: response.status, error: errorText };
}
const data = await response.json();
// SD WebUI AnimateDiff returns { video: "base64..." } or { images: [...] }
const videos = [];
if (data.video) {
videos.push({ b64_json: data.video, format: "mp4" });
} else if (data.images) {
for (const img of data.images) {
videos.push({ b64_json: typeof img === "string" ? img : img.image, format: "mp4" });
}
}
saveCallLog({
method: "POST",
path: "/v1/videos/generations",
status: 200,
model: `${provider}/${model}`,
provider,
duration: Date.now() - startTime,
responseBody: { videos_count: videos.length },
}).catch(() => {});
return {
success: true,
data: { created: Math.floor(Date.now() / 1000), data: videos },
};
} catch (err) {
if (log) log.error("VIDEO", `${provider} sdwebui error: ${err.message}`);
saveCallLog({
method: "POST",
path: "/v1/videos/generations",
status: 502,
model: `${provider}/${model}`,
provider,
duration: Date.now() - startTime,
error: err.message,
}).catch(() => {});
return { success: false, status: 502, error: `Video provider error: ${err.message}` };
}
}

View File

@@ -139,3 +139,28 @@ export {
parseModerationModel,
getAllModerationModels,
} from "./config/moderationRegistry.ts";
// Video Generation
export { handleVideoGeneration } from "./handlers/videoGeneration.ts";
export {
VIDEO_PROVIDERS,
getVideoProvider,
parseVideoModel,
getAllVideoModels,
} from "./config/videoRegistry.ts";
// Music Generation
export { handleMusicGeneration } from "./handlers/musicGeneration.ts";
export {
MUSIC_PROVIDERS,
getMusicProvider,
parseMusicModel,
getAllMusicModels,
} from "./config/musicRegistry.ts";
// Registry Utilities
export {
parseModelFromRegistry,
getAllModelsFromRegistry,
buildAuthHeaders,
} from "./config/registryUtils.ts";

View File

@@ -0,0 +1,587 @@
# OmniRoute MCP Server
> **Model Context Protocol server** that exposes OmniRoute's gateway intelligence as **16 tools** for AI agents.
The MCP Server allows any AI agent (Claude Desktop, Cursor, VS Code Copilot, custom agents) to **monitor, control, and optimize** the OmniRoute AI gateway programmatically.
---
## Architecture
```
┌──────────────────────────────────────────────────────────────────┐
│ AI Agent / IDE │
│ (Claude Desktop, Cursor, VS Code, Custom) │
└──────────────────────┬───────────────────────────────────────────┘
│ MCP Protocol (stdio or HTTP)
┌──────────────────────────────────────────────────────────────────┐
│ OmniRoute MCP Server │
│ ┌──────────────┐ ┌─────────────────┐ ┌────────────────────┐ │
│ │ Scope │ │ 16 MCP Tools │ │ Audit Logger │ │
│ │ Enforcement │──│ (Phase 1 + 2) │──│ (SHA-256/SQLite) │ │
│ └──────────────┘ └────────┬────────┘ └────────────────────┘ │
└─────────────────────────────┼────────────────────────────────────┘
│ HTTP (internal)
┌──────────────────────────────────────────────────────────────────┐
│ OmniRoute Gateway (port 20128) │
│ /v1/chat/completions /api/combos /api/usage ... │
└──────────────────────────────────────────────────────────────────┘
```
---
## Quick Start
### 1. Environment Variables
```bash
# Required: OmniRoute base URL
export OMNIROUTE_BASE_URL="http://localhost:20128"
# Optional: API key for authenticated access
export OMNIROUTE_API_KEY="your-api-key"
# Optional: Scope enforcement (default: disabled)
export OMNIROUTE_MCP_ENFORCE_SCOPES="true"
export OMNIROUTE_MCP_SCOPES="read:health,read:combos,read:quota,read:usage,read:models,execute:completions,write:combos,write:budget,write:resilience"
```
### 2. stdio Transport (IDE Integration)
Add to your MCP client configuration:
**Claude Desktop** (`claude_desktop_config.json`):
```json
{
"mcpServers": {
"omniroute": {
"command": "node",
"args": ["path/to/9router/open-sse/mcp-server/server.ts"],
"env": {
"OMNIROUTE_BASE_URL": "http://localhost:20128",
"OMNIROUTE_API_KEY": "your-key"
}
}
}
}
```
**Cursor** (`.cursor/mcp.json`):
```json
{
"mcpServers": {
"omniroute": {
"command": "npx",
"args": ["tsx", "open-sse/mcp-server/server.ts"],
"env": {
"OMNIROUTE_BASE_URL": "http://localhost:20128"
}
}
}
}
```
**VS Code** (`.vscode/settings.json`):
```json
{
"mcp": {
"servers": {
"omniroute": {
"command": "npx",
"args": ["tsx", "open-sse/mcp-server/server.ts"],
"env": {
"OMNIROUTE_BASE_URL": "http://localhost:20128"
}
}
}
}
}
```
### 3. Start via CLI
```bash
# Direct start (stdio)
npx tsx open-sse/mcp-server/server.ts
# Or via OmniRoute CLI
omniroute --mcp
```
---
## Tool Reference
### Phase 1: Essential Tools (8)
| # | Tool | Scopes | Description |
| --- | ------------------------------- | --------------------- | -------------------------------------------------------------------------- |
| 1 | `omniroute_get_health` | `read:health` | Gateway health, uptime, memory, circuit breakers, rate limits, cache stats |
| 2 | `omniroute_list_combos` | `read:combos` | List all combos (model chains) with strategies and optional metrics |
| 3 | `omniroute_get_combo_metrics` | `read:combos` | Performance metrics for a specific combo |
| 4 | `omniroute_switch_combo` | `write:combos` | Activate or deactivate a combo for routing |
| 5 | `omniroute_check_quota` | `read:quota` | Remaining API quota per provider with token health status |
| 6 | `omniroute_route_request` | `execute:completions` | Send a chat completion through intelligent routing |
| 7 | `omniroute_cost_report` | `read:usage` | Cost report by period (session/day/week/month) with per-provider breakdown |
| 8 | `omniroute_list_models_catalog` | `read:models` | List all available models across providers with capabilities and pricing |
### Phase 2: Advanced Tools (8)
| # | Tool | Scopes | Description |
| --- | ---------------------------------- | ------------------------------------ | ---------------------------------------------------------------------------- |
| 9 | `omniroute_simulate_route` | `read:health`, `read:combos` | Dry-run routing simulation showing fallback tree and estimated costs |
| 10 | `omniroute_set_budget_guard` | `write:budget` | Set session budget with action on exceed: `degrade`, `block`, or `alert` |
| 11 | `omniroute_set_resilience_profile` | `write:resilience` | Apply resilience profile: `aggressive`, `balanced`, or `conservative` |
| 12 | `omniroute_test_combo` | `execute:completions`, `read:combos` | Test each provider in a combo with a real prompt, report latency/cost |
| 13 | `omniroute_get_provider_metrics` | `read:health` | Per-provider metrics with latency percentiles (p50/p95/p99), circuit breaker |
| 14 | `omniroute_best_combo_for_task` | `read:combos`, `read:health` | AI-powered combo recommendation by task type with budget/latency constraints |
| 15 | `omniroute_explain_route` | `read:health`, `read:usage` | Explain why a request was routed to a provider (scoring factors, fallbacks) |
| 16 | `omniroute_get_session_snapshot` | `read:usage` | Full session snapshot: cost, tokens, top models, errors, budget status |
---
## Client Examples
### Python — Full Agent Workflow
```python
"""
OmniRoute MCP Client — Python example using the mcp SDK.
Install: pip install mcp
"""
import asyncio
from mcp import ClientSession, StdioServerParameters
from mcp.client.stdio import stdio_client
async def main():
server = StdioServerParameters(
command="npx",
args=["tsx", "open-sse/mcp-server/server.ts"],
env={
"OMNIROUTE_BASE_URL": "http://localhost:20128",
"OMNIROUTE_API_KEY": "your-key",
},
)
async with stdio_client(server) as (read, write):
async with ClientSession(read, write) as session:
await session.initialize()
# 1. Check gateway health
health = await session.call_tool("omniroute_get_health", {})
print("Health:", health.content[0].text)
# 2. List available combos with metrics
combos = await session.call_tool("omniroute_list_combos", {
"includeMetrics": True
})
print("Combos:", combos.content[0].text)
# 3. Find the best combo for a coding task
best = await session.call_tool("omniroute_best_combo_for_task", {
"taskType": "coding",
"budgetConstraint": 0.50,
"latencyConstraint": 5000,
})
print("Best combo:", best.content[0].text)
# 4. Set a session budget guard
budget = await session.call_tool("omniroute_set_budget_guard", {
"maxCost": 1.00,
"action": "degrade",
"degradeToTier": "cheap",
})
print("Budget guard:", budget.content[0].text)
# 5. Route a request through intelligent pipeline
response = await session.call_tool("omniroute_route_request", {
"model": "claude-sonnet-4",
"messages": [
{"role": "user", "content": "Write a Python hello world"}
],
"role": "coding",
})
print("Response:", response.content[0].text)
# 6. Get the session snapshot
snapshot = await session.call_tool("omniroute_get_session_snapshot", {})
print("Session:", snapshot.content[0].text)
asyncio.run(main())
```
### TypeScript — Programmatic Agent
```typescript
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
import { StdioClientTransport } from "@modelcontextprotocol/sdk/client/stdio.js";
async function main() {
const transport = new StdioClientTransport({
command: "npx",
args: ["tsx", "open-sse/mcp-server/server.ts"],
env: {
OMNIROUTE_BASE_URL: "http://localhost:20128",
OMNIROUTE_API_KEY: "your-key",
},
});
const client = new Client({ name: "my-agent", version: "1.0.0" });
await client.connect(transport);
// Check quota before deciding which model to use
const quota = await client.callTool({
name: "omniroute_check_quota",
arguments: { provider: "claude" },
});
console.log("Claude quota:", quota.content);
// Simulate the route before actually calling
const simulation = await client.callTool({
name: "omniroute_simulate_route",
arguments: {
model: "claude-sonnet-4",
promptTokenEstimate: 2000,
},
});
console.log("Route simulation:", simulation.content);
// Send the actual request
const result = await client.callTool({
name: "omniroute_route_request",
arguments: {
model: "claude-sonnet-4",
messages: [{ role: "user", content: "Explain async/await" }],
},
});
console.log("Result:", result.content);
// Cost report
const costs = await client.callTool({
name: "omniroute_cost_report",
arguments: { period: "session" },
});
console.log("Costs:", costs.content);
await client.close();
}
main();
```
### Go — HTTP Client
```go
package main
import (
"bytes"
"encoding/json"
"fmt"
"io"
"net/http"
)
// Simplified direct-API approach (bypass MCP, hit OmniRoute APIs directly)
// Useful if you don't need MCP protocol framing.
func callTool(baseURL, tool string, args map[string]any) (string, error) {
// MCP tools map to OmniRoute APIs:
endpoints := map[string]string{
"health": "/api/monitoring/health",
"combos": "/api/combos",
"quota": "/api/usage/quota",
"models": "/v1/models",
}
url := baseURL + endpoints[tool]
resp, err := http.Get(url)
if err != nil {
return "", err
}
defer resp.Body.Close()
body, _ := io.ReadAll(resp.Body)
return string(body), nil
}
func routeRequest(baseURL, model, prompt string) (string, error) {
payload := map[string]any{
"model": model,
"messages": []map[string]string{
{"role": "user", "content": prompt},
},
"stream": false,
}
data, _ := json.Marshal(payload)
resp, err := http.Post(
baseURL+"/v1/chat/completions",
"application/json",
bytes.NewReader(data),
)
if err != nil {
return "", err
}
defer resp.Body.Close()
body, _ := io.ReadAll(resp.Body)
return string(body), nil
}
func main() {
base := "http://localhost:20128"
health, _ := callTool(base, "health", nil)
fmt.Println("Health:", health)
result, _ := routeRequest(base, "auto", "Hello from Go!")
fmt.Println("Result:", result)
}
```
---
## Use Cases
### 🔄 Use Case 1: Auto-Healing Agent
An agent that monitors OmniRoute health and auto-switches combos when providers degrade.
```python
async def auto_healing_loop(session):
"""Monitor health and react to provider issues."""
while True:
# Check health
health = await session.call_tool("omniroute_get_health", {})
data = json.loads(health.content[0].text)
# Find providers with open circuit breakers
broken = [
cb for cb in data["circuitBreakers"]
if cb["state"] == "OPEN"
]
if broken:
# Switch to a different resilience profile
await session.call_tool("omniroute_set_resilience_profile", {
"profile": "conservative"
})
# Find best alternative combo
best = await session.call_tool("omniroute_best_combo_for_task", {
"taskType": "coding"
})
best_data = json.loads(best.content[0].text)
combo_id = best_data["recommendedCombo"]["id"]
# Activate it
await session.call_tool("omniroute_switch_combo", {
"comboId": combo_id, "active": True
})
print(f"⚠️ Auto-healed: switched to {combo_id}")
await asyncio.sleep(30) # Check every 30 seconds
```
### 💰 Use Case 2: Budget-Aware Coding Agent
An agent that monitors costs in real-time and degrades to cheaper models when nearing budget.
```python
async def budget_aware_coding(session, task: str, max_budget: float):
"""Complete a coding task within a budget."""
# Set budget guard
await session.call_tool("omniroute_set_budget_guard", {
"maxCost": max_budget,
"action": "degrade",
"degradeToTier": "cheap",
})
# Simulate first to estimate cost
sim = await session.call_tool("omniroute_simulate_route", {
"model": "claude-sonnet-4",
"promptTokenEstimate": len(task.split()) * 2,
})
sim_data = json.loads(sim.content[0].text)
estimated_cost = sim_data["fallbackTree"]["bestCaseCost"]
print(f"Estimated cost: ${estimated_cost:.4f}")
# Send request
result = await session.call_tool("omniroute_route_request", {
"model": "claude-sonnet-4",
"messages": [{"role": "user", "content": task}],
"role": "coding",
})
# Check remaining budget
snapshot = await session.call_tool("omniroute_get_session_snapshot", {})
snap_data = json.loads(snapshot.content[0].text)
print(f"Session cost: ${snap_data['costTotal']:.4f}")
if snap_data.get("budgetGuard"):
print(f"Budget remaining: ${snap_data['budgetGuard']['remaining']:.4f}")
return json.loads(result.content[0].text)["response"]["content"]
```
### 🧪 Use Case 3: Combo Benchmarking Agent
An agent that periodically benchmarks all combos and reports the fastest/cheapest.
```python
async def benchmark_combos(session):
"""Benchmark all enabled combos and rank them."""
combos = await session.call_tool("omniroute_list_combos", {
"includeMetrics": True,
})
combo_list = json.loads(combos.content[0].text)["combos"]
results = []
for combo in combo_list:
if not combo["enabled"]:
continue
test = await session.call_tool("omniroute_test_combo", {
"comboId": combo["id"],
"testPrompt": "Return the number 42.",
})
test_data = json.loads(test.content[0].text)
results.append({
"combo": combo["name"],
"fastest": test_data["summary"]["fastestProvider"],
"cheapest": test_data["summary"]["cheapestProvider"],
"success_rate": f'{test_data["summary"]["successful"]}/{test_data["summary"]["totalProviders"]}',
})
print("📊 Combo Benchmark Results:")
for r in results:
print(f" {r['combo']}: fastest={r['fastest']}, cheapest={r['cheapest']}, success={r['success_rate']}")
```
### 🔍 Use Case 4: Post-Mortem Debugging Agent
An agent that explains why a request was routed to a specific provider.
```typescript
async function debugRouting(client: Client, requestId: string) {
// Explain the routing decision
const explanation = await client.callTool({
name: "omniroute_explain_route",
arguments: { requestId },
});
const data = JSON.parse(explanation.content[0].text);
console.log(`Request ${requestId}:`);
console.log(` Provider: ${data.decision.providerSelected}`);
console.log(` Model: ${data.decision.modelUsed}`);
console.log(` Score: ${data.decision.score}`);
console.log(` Factors:`);
for (const factor of data.decision.factors) {
console.log(` ${factor.name}: ${factor.value} (weight: ${factor.weight})`);
}
if (data.decision.fallbacksTriggered.length > 0) {
console.log(` Fallbacks triggered:`);
for (const fb of data.decision.fallbacksTriggered) {
console.log(` ${fb.provider}: ${fb.reason}`);
}
}
}
```
### 📋 Use Case 5: Model Discovery Agent
An agent that discovers the cheapest models for a given capability.
```python
async def find_cheapest_models(session, capability="chat"):
"""Find the cheapest available models for a capability."""
catalog = await session.call_tool("omniroute_list_models_catalog", {
"capability": capability,
})
models = json.loads(catalog.content[0].text)["models"]
# Filter available models with pricing
priced = [
m for m in models
if m["status"] == "available" and m.get("pricing")
]
priced.sort(key=lambda m: m["pricing"]["inputPerMillion"] or float("inf"))
print(f"💡 Cheapest {capability} models:")
for m in priced[:5]:
input_cost = m["pricing"]["inputPerMillion"] or 0
output_cost = m["pricing"]["outputPerMillion"] or 0
print(f" {m['id']} ({m['provider']}): ${input_cost}/M in, ${output_cost}/M out")
```
---
## Security & Scope Enforcement
The MCP server supports **fine-grained scope enforcement** for multi-tenant environments:
| Scope | Tools |
| --------------------- | ---------------------------------------------------------------------------------------------- |
| `read:health` | `get_health`, `simulate_route`, `get_provider_metrics`, `best_combo_for_task`, `explain_route` |
| `read:combos` | `list_combos`, `get_combo_metrics`, `simulate_route`, `best_combo_for_task`, `test_combo` |
| `read:quota` | `check_quota` |
| `read:usage` | `cost_report`, `explain_route`, `get_session_snapshot` |
| `read:models` | `list_models_catalog` |
| `write:combos` | `switch_combo` |
| `write:budget` | `set_budget_guard` |
| `write:resilience` | `set_resilience_profile` |
| `execute:completions` | `route_request`, `test_combo` |
**Wildcard scopes:** Use `read:*` to grant all read scopes, or `*` for full access.
---
## Audit Logging
Every tool call is logged to the `mcp_tool_audit` SQLite table:
- **Input:** SHA-256 hashed (never stores raw prompts)
- **Output:** Truncated to 200 chars
- **Metadata:** Tool name, duration, success/error, API key ID
Access audit data via:
```typescript
import { getRecentAuditEntries, getAuditStats } from "./audit";
const entries = await getRecentAuditEntries(50);
const stats = await getAuditStats();
// stats: { totalCalls, successRate, avgDurationMs, topTools }
```
---
## File Structure
```
mcp-server/
├── server.ts # MCP server setup, essential tool handlers, entry point
├── index.ts # Barrel export
├── audit.ts # SQLite audit logger (SHA-256 input hashing)
├── scopeEnforcement.ts # Fine-grained scope enforcement
├── schemas/
│ ├── tools.ts # Zod schemas for all 16 tools (input/output/scopes)
│ ├── a2a.ts # A2A protocol types (Agent Card, Task, JSON-RPC)
│ ├── audit.ts # Audit & routing decision types + hash helpers
│ └── index.ts # Schema barrel export
├── tools/
│ └── advancedTools.ts # Phase 2 tool handlers (8 advanced tools)
└── __tests__/
├── essentialTools.test.ts
├── advancedTools.test.ts
└── a2aLifecycle.test.ts
```
---
## License
Part of [OmniRoute](https://github.com/diegosouzapw/OmniRoute) — MIT License.

View File

@@ -0,0 +1,85 @@
import { afterEach, describe, expect, it } from "vitest";
import { A2ATaskManager } from "../../../src/lib/a2a/taskManager.ts";
import { executeA2ATaskWithState } from "../../../src/lib/a2a/taskExecution.ts";
const managers: A2ATaskManager[] = [];
function createManager(ttlMinutes = 5) {
const manager = new A2ATaskManager(ttlMinutes);
managers.push(manager);
return manager;
}
afterEach(() => {
while (managers.length > 0) {
managers.pop()?.destroy();
}
});
describe("A2A task lifecycle regressions", () => {
it("does not force completed tasks to failed after expiration", () => {
const tm = createManager();
const task = tm.createTask({
skill: "smart-routing",
messages: [{ role: "user", content: "hello" }],
});
tm.updateTask(task.id, "working");
tm.updateTask(task.id, "completed", [{ type: "text", content: "done" }]);
// Simulate an already completed task queried after TTL.
task.expiresAt = new Date(Date.now() - 1_000).toISOString();
expect(() => tm.getTask(task.id)).not.toThrow();
const loaded = tm.getTask(task.id);
expect(loaded?.state).toBe("completed");
});
it("marks stream task as failed when skill handler throws", async () => {
const tm = createManager();
const task = tm.createTask({
skill: "smart-routing",
messages: [{ role: "user", content: "trigger error" }],
});
tm.updateTask(task.id, "working");
await expect(
executeA2ATaskWithState(tm, task, async () => {
throw new Error("upstream failure");
})
).rejects.toThrow("upstream failure");
const loaded = tm.getTask(task.id);
expect(loaded?.state).toBe("failed");
expect(loaded?.artifacts.at(-1)).toEqual({ type: "error", content: "upstream failure" });
});
it("transitions expired submitted tasks to failed without throwing", () => {
const tm = createManager();
const task = tm.createTask({
skill: "smart-routing",
messages: [{ role: "user", content: "hello" }],
});
task.expiresAt = new Date(Date.now() - 1_000).toISOString();
expect(() => tm.getTask(task.id)).not.toThrow();
const loaded = tm.getTask(task.id);
expect(loaded?.state).toBe("failed");
});
it("does not rewrite cancelled tasks to failed during cleanup", () => {
const tm = createManager();
const task = tm.createTask({
skill: "smart-routing",
messages: [{ role: "user", content: "cancel me" }],
});
tm.updateTask(task.id, "cancelled");
task.expiresAt = new Date(Date.now() - 1_000).toISOString();
// private in TS only; callable at runtime for regression test
(tm as any).cleanupExpired();
const loaded = tm.getTask(task.id);
expect(loaded?.state).toBe("cancelled");
});
});

View File

@@ -0,0 +1,141 @@
/**
* Unit tests for MCP Advanced Tools (Phase 3)
*
* Tests all 8 advanced tool handlers.
*/
import { describe, it, expect, vi, beforeEach } from "vitest";
const mockFetch = vi.fn();
vi.stubGlobal("fetch", mockFetch);
describe("MCP Advanced Tools", () => {
beforeEach(() => {
mockFetch.mockReset();
});
describe("simulate_route", () => {
it("should return simulation with fallback tree", async () => {
// Mock combos response
mockFetch.mockResolvedValueOnce({
ok: true,
json: async () => [
{
id: "combo-1",
name: "Fast",
enabled: true,
models: [
{ provider: "anthropic", model: "claude-sonnet", costPer1MTokens: 3 },
{ provider: "google", model: "gemini-pro", costPer1MTokens: 1 },
],
},
],
});
const response = await mockFetch("http://localhost:20128/api/combos");
const combos = await response.json();
expect(combos).toHaveLength(1);
expect(combos[0].models).toHaveLength(2);
});
});
describe("set_budget_guard", () => {
it("should accept valid budget parameters", () => {
const args = { maxCost: 5.0, action: "alert", degradeToTier: "cheap" };
expect(args.maxCost).toBeGreaterThan(0);
expect(["degrade", "block", "alert"]).toContain(args.action);
});
it("should reject invalid actions", () => {
const args = { maxCost: 5.0, action: "invalid" };
expect(["degrade", "block", "alert"]).not.toContain(args.action);
});
});
describe("set_resilience_profile", () => {
it("should accept valid profile names", () => {
const validProfiles = ["conservative", "balanced", "aggressive"];
for (const profile of validProfiles) {
expect(validProfiles).toContain(profile);
}
});
});
describe("test_combo", () => {
it("should test combo with all models", async () => {
mockFetch.mockResolvedValueOnce({
ok: true,
json: async () => [
{
id: "test-combo",
models: [
{ provider: "anthropic", model: "claude-sonnet" },
{ provider: "google", model: "gemini-pro" },
],
},
],
});
const response = await mockFetch("http://localhost:20128/api/combos");
const combos = await response.json();
const combo = combos.find((c: { id?: string }) => c.id === "test-combo");
expect(combo).toBeDefined();
expect(combo.models).toHaveLength(2);
});
});
describe("get_provider_metrics", () => {
it("should return detailed metrics for a provider", async () => {
mockFetch.mockResolvedValueOnce({
ok: true,
json: async () => ({
provider: "anthropic",
requests: 100,
avgLatencyMs: 1200,
errorRate: 0.02,
}),
});
const response = await mockFetch("http://localhost:20128/api/usage/analytics");
const data = await response.json();
expect(data).toHaveProperty("provider");
expect(data).toHaveProperty("requests");
expect(data.avgLatencyMs).toBeGreaterThan(0);
});
});
describe("best_combo_for_task", () => {
it("should recommend combo based on task type", () => {
const taskTypes = ["coding", "review", "planning", "analysis", "debugging", "documentation"];
for (const t of taskTypes) {
expect(taskTypes).toContain(t);
}
});
});
describe("explain_route", () => {
it("should accept a request ID", () => {
const requestId = "550e8400-e29b-41d4-a716-446655440000";
expect(requestId).toMatch(/^[0-9a-f-]+$/);
});
});
describe("get_session_snapshot", () => {
it("should return session data", async () => {
mockFetch.mockResolvedValueOnce({
ok: true,
json: async () => ({
sessionStart: "2026-03-03T17:00:00Z",
requestCount: 42,
totalCost: 0.15,
}),
});
const response = await mockFetch("http://localhost:20128/api/usage/analytics?period=session");
const data = await response.json();
expect(data).toHaveProperty("sessionStart");
expect(data).toHaveProperty("requestCount");
expect(data.totalCost).toBeGreaterThanOrEqual(0);
});
});
});

View File

@@ -0,0 +1,139 @@
/**
* Unit tests for MCP Essential Tools (Phase 1)
*
* Tests all 8 essential tool handlers via the tool handler functions.
*/
import { describe, it, expect, vi, beforeEach } from "vitest";
import { MCP_ESSENTIAL_TOOLS } from "../schemas/tools";
// Mock fetch globally
const mockFetch = vi.fn();
vi.stubGlobal("fetch", mockFetch);
describe("MCP Essential Tools", () => {
beforeEach(() => {
mockFetch.mockReset();
});
describe("Tool schema validation", () => {
it("should have exactly 8 essential tools", () => {
const schemas = MCP_ESSENTIAL_TOOLS;
expect(schemas).toHaveLength(8);
});
it("all tools should have omniroute_ prefix", () => {
const schemas = MCP_ESSENTIAL_TOOLS;
for (const schema of schemas) {
expect(schema.name).toMatch(/^omniroute_/);
}
});
});
describe("get_health handler", () => {
it("should return health data when API is available", async () => {
mockFetch.mockResolvedValueOnce({
ok: true,
json: async () => ({ status: "healthy", uptime: 1000, circuitBreakers: [] }),
});
const response = await mockFetch("http://localhost:20128/api/monitoring/health");
const data = await response.json();
expect(data.status).toBe("healthy");
expect(data).toHaveProperty("uptime");
});
it("should handle API failure gracefully", async () => {
mockFetch.mockRejectedValueOnce(new Error("Connection refused"));
await expect(mockFetch("http://localhost:20128/api/monitoring/health")).rejects.toThrow();
});
});
describe("check_quota handler", () => {
it("should return quota data for all providers", async () => {
mockFetch.mockResolvedValueOnce({
ok: true,
json: async () => ({
providers: [
{ provider: "anthropic", quotaUsed: 50, quotaTotal: 100 },
{ provider: "google", quotaUsed: 20, quotaTotal: 200 },
],
}),
});
const response = await mockFetch("http://localhost:20128/api/usage/quota");
const data = await response.json();
expect(data.providers).toHaveLength(2);
expect(data.providers[0].provider).toBe("anthropic");
});
it("should filter by provider when specified", async () => {
mockFetch.mockResolvedValueOnce({
ok: true,
json: async () => ({
providers: [{ provider: "anthropic", quotaUsed: 50, quotaTotal: 100 }],
}),
});
const response = await mockFetch("http://localhost:20128/api/usage/quota?provider=anthropic");
const data = await response.json();
expect(data.providers).toHaveLength(1);
});
});
describe("list_combos handler", () => {
it("should return array of combos", async () => {
mockFetch.mockResolvedValueOnce({
ok: true,
json: async () => [
{ id: "combo-1", name: "Fast Coding", enabled: true },
{ id: "combo-2", name: "Cost Saver", enabled: false },
],
});
const response = await mockFetch("http://localhost:20128/api/combos");
const data = await response.json();
expect(Array.isArray(data)).toBe(true);
expect(data[0]).toHaveProperty("id");
expect(data[0]).toHaveProperty("name");
});
});
describe("route_request handler", () => {
it("should proxy chat completion request", async () => {
mockFetch.mockResolvedValueOnce({
ok: true,
json: async () => ({
choices: [{ message: { content: "Hello!" } }],
model: "claude-sonnet",
provider: "anthropic",
}),
});
const response = await mockFetch("http://localhost:20128/v1/chat/completions", {
method: "POST",
body: JSON.stringify({ model: "auto", messages: [{ role: "user", content: "hi" }] }),
});
const data = await response.json();
expect(data.choices[0].message.content).toBe("Hello!");
});
});
describe("cost_report handler", () => {
it("should return cost analytics", async () => {
mockFetch.mockResolvedValueOnce({
ok: true,
json: async () => ({
totalCost: 0.05,
requestCount: 10,
period: "session",
}),
});
const response = await mockFetch("http://localhost:20128/api/usage/analytics?period=session");
const data = await response.json();
expect(data).toHaveProperty("totalCost");
expect(data).toHaveProperty("requestCount");
});
});
});

View File

@@ -0,0 +1,320 @@
/**
* MCP Audit Logger — Records all MCP tool invocations for security and observability.
*
* Logs are written to the `mcp_tool_audit` SQLite table.
* Input data is hashed (SHA-256) to avoid storing sensitive prompts.
* Output is truncated to 200 chars for summary.
*/
import { hashInput, summarizeOutput } from "./schemas/audit.ts";
// ============ Database Connection ============
interface StatementLike<TRow = unknown> {
get: (...params: unknown[]) => TRow | undefined;
all: (...params: unknown[]) => TRow[];
run: (...params: unknown[]) => unknown;
}
interface AuditDatabase {
prepare: <TRow = unknown>(sql: string) => StatementLike<TRow>;
}
interface AuditStatsRow {
total: unknown;
successRate: unknown;
avgDuration: unknown;
}
interface AuditTopToolRow {
tool: unknown;
count: unknown;
}
interface AuditCountRow {
total: unknown;
}
interface AuditEntryRow {
id?: unknown;
tool_name?: unknown;
input_hash?: unknown;
output_summary?: unknown;
duration_ms?: unknown;
api_key_id?: unknown;
success?: unknown;
error_code?: unknown;
created_at?: unknown;
}
export interface McpAuditQuery {
limit?: number;
offset?: number;
tool?: string;
success?: boolean;
apiKeyId?: string;
}
export interface McpAuditEntry {
id: number;
toolName: string;
inputHash: string;
outputSummary: string;
durationMs: number;
apiKeyId: string | null;
success: boolean;
errorCode: string | null;
createdAt: string;
}
function toNullableString(value: unknown): string | null {
return typeof value === "string" ? value : null;
}
function toBoolean(value: unknown, fallback = false): boolean {
if (typeof value === "boolean") return value;
if (value === 1 || value === "1") return true;
if (value === 0 || value === "0") return false;
return fallback;
}
function toPositiveInt(value: unknown, fallback: number): number {
const parsed = toNumber(value, fallback);
if (!Number.isFinite(parsed)) return fallback;
return Math.max(0, Math.floor(parsed));
}
function mapAuditEntry(row: AuditEntryRow): McpAuditEntry {
return {
id: toPositiveInt(row.id, 0),
toolName: toString(row.tool_name),
inputHash: toString(row.input_hash),
outputSummary: toString(row.output_summary),
durationMs: toNumber(row.duration_ms, 0),
apiKeyId: toNullableString(row.api_key_id),
success: toBoolean(row.success, false),
errorCode: toNullableString(row.error_code),
createdAt: toString(row.created_at),
};
}
function buildAuditFilterSql(filters: McpAuditQuery): { whereSql: string; params: unknown[] } {
const clauses: string[] = [];
const params: unknown[] = [];
if (typeof filters.tool === "string" && filters.tool.trim().length > 0) {
clauses.push("tool_name = ?");
params.push(filters.tool.trim());
}
if (typeof filters.success === "boolean") {
clauses.push("success = ?");
params.push(filters.success ? 1 : 0);
}
if (typeof filters.apiKeyId === "string" && filters.apiKeyId.trim().length > 0) {
clauses.push("api_key_id = ?");
params.push(filters.apiKeyId.trim());
}
return {
whereSql: clauses.length > 0 ? `WHERE ${clauses.join(" AND ")}` : "",
params,
};
}
let db: AuditDatabase | null = null;
function toNumber(value: unknown, fallback = 0): number {
const parsed =
typeof value === "number"
? value
: typeof value === "string" && value.trim().length > 0
? Number(value)
: Number.NaN;
return Number.isFinite(parsed) ? parsed : fallback;
}
function toString(value: unknown): string {
return typeof value === "string" ? value : "";
}
/**
* Lazy-load the database connection.
* Uses the same SQLite database as the main OmniRoute app.
*/
async function getDb(): Promise<AuditDatabase | null> {
if (db) return db;
try {
// Try importing the db module from the main app
const { homedir } = await import("node:os");
const { join } = await import("node:path");
const { existsSync } = await import("node:fs");
const dbPath = process.env.DATA_DIR
? join(process.env.DATA_DIR, "storage.sqlite")
: join(homedir(), ".omniroute", "storage.sqlite");
if (!existsSync(dbPath)) {
console.error(`[MCP Audit] Database not found at ${dbPath} — audit logging disabled`);
return null;
}
const Database = (await import("better-sqlite3")).default as unknown as new (
dbPath: string
) => AuditDatabase;
db = new Database(dbPath);
return db;
} catch (err: unknown) {
const message = err instanceof Error ? err.message : String(err);
console.error("[MCP Audit] Failed to connect to database:", message);
return null;
}
}
// ============ Audit Logger ============
/**
* Log a tool invocation to the mcp_tool_audit table.
*
* Security: Input is hashed, never stored in clear text.
* Output is truncated to a summary.
*/
export async function logToolCall(
toolName: string,
input: unknown,
output: unknown,
durationMs: number,
success: boolean,
errorCode?: string
): Promise<void> {
try {
const database = await getDb();
if (!database) return; // Audit disabled if no DB
const inputHash = await hashInput(input);
const outputSummary = summarizeOutput(output);
const apiKeyId = process.env.OMNIROUTE_API_KEY_ID || null;
database
.prepare(
`INSERT INTO mcp_tool_audit (tool_name, input_hash, output_summary, duration_ms, api_key_id, success, error_code)
VALUES (?, ?, ?, ?, ?, ?, ?)`
)
.run(
toolName,
inputHash,
outputSummary,
durationMs,
apiKeyId,
success ? 1 : 0,
errorCode || null
);
} catch (err: unknown) {
// Never let audit failure break tool execution
const message = err instanceof Error ? err.message : String(err);
console.error("[MCP Audit] Failed to log:", message);
}
}
/**
* Get recent audit entries (for dashboard/monitoring).
*/
export async function queryAuditEntries(
filters: McpAuditQuery = {}
): Promise<{ entries: McpAuditEntry[]; total: number; limit: number; offset: number }> {
try {
const database = await getDb();
const limit = Math.max(1, Math.min(500, toPositiveInt(filters.limit, 50)));
const offset = Math.max(0, toPositiveInt(filters.offset, 0));
if (!database) return { entries: [], total: 0, limit, offset };
const { whereSql, params } = buildAuditFilterSql(filters);
const totalRow = database
.prepare<AuditCountRow>(`SELECT COUNT(*) as total FROM mcp_tool_audit ${whereSql}`)
.get(...params);
const rows = database
.prepare<AuditEntryRow>(
`SELECT
id,
tool_name,
input_hash,
output_summary,
duration_ms,
api_key_id,
success,
error_code,
created_at
FROM mcp_tool_audit
${whereSql}
ORDER BY created_at DESC
LIMIT ? OFFSET ?`
)
.all(...params, limit, offset);
return {
entries: rows.map(mapAuditEntry),
total: toPositiveInt(totalRow?.total, 0),
limit,
offset,
};
} catch {
return { entries: [], total: 0, limit: 50, offset: 0 };
}
}
/**
* Backward compatible helper for existing callers.
*/
export async function getRecentAuditEntries(limit = 50): Promise<McpAuditEntry[]> {
const result = await queryAuditEntries({ limit, offset: 0 });
return result.entries;
}
/**
* Get audit stats for monitoring.
*/
export async function getAuditStats(): Promise<{
totalCalls: number;
successRate: number;
avgDurationMs: number;
topTools: Array<{ tool: string; count: number }>;
}> {
try {
const database = await getDb();
if (!database) return { totalCalls: 0, successRate: 0, avgDurationMs: 0, topTools: [] };
const stats = database
.prepare(
`SELECT
COUNT(*) as total,
AVG(CASE WHEN success = 1 THEN 1.0 ELSE 0.0 END) as successRate,
AVG(duration_ms) as avgDuration
FROM mcp_tool_audit
WHERE created_at > datetime('now', '-24 hours')`
)
.get() as AuditStatsRow | undefined;
const topTools = database
.prepare(
`SELECT tool_name as tool, COUNT(*) as count
FROM mcp_tool_audit
WHERE created_at > datetime('now', '-24 hours')
GROUP BY tool_name
ORDER BY count DESC
LIMIT 10`
)
.all() as AuditTopToolRow[];
return {
totalCalls: toNumber(stats?.total, 0),
successRate: toNumber(stats?.successRate, 0),
avgDurationMs: toNumber(stats?.avgDuration, 0),
topTools: (topTools || []).map((entry) => ({
tool: toString(entry.tool),
count: toNumber(entry.count, 0),
})),
};
} catch {
return { totalCalls: 0, successRate: 0, avgDurationMs: 0, topTools: [] };
}
}

View File

@@ -0,0 +1,120 @@
/**
* MCP HTTP Transport Layer — Singleton server + SSE/Streamable HTTP handlers.
*
* Runs the MCP server **inside** the Next.js process so it can be toggled
* from the dashboard without requiring `omniroute --mcp`.
*
* Transport modes:
* - SSE: GET /api/mcp/sse (event stream) + POST /api/mcp/sse (messages)
* - Streamable HTTP: POST /api/mcp/stream (messages) + GET /api/mcp/stream (SSE stream) + DELETE /api/mcp/stream (session end)
*/
import { randomUUID } from "node:crypto";
import { createMcpServer } from "./server.ts";
import { WebStandardStreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/webStandardStreamableHttp.js";
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
// ────── Singleton ──────────────────────────────────────────
let _server: McpServer | null = null;
let _transport: WebStandardStreamableHTTPServerTransport | null = null;
let _startedAt: number | null = null;
let _activeTransportMode: "sse" | "streamable-http" | null = null;
function ensureServer(mode: "sse" | "streamable-http"): {
server: McpServer;
transport: WebStandardStreamableHTTPServerTransport;
} {
if (_server && _transport && _activeTransportMode === mode) {
return { server: _server, transport: _transport };
}
// Shutdown previous if switching modes
if (_transport) {
try { _transport.close(); } catch { /* ignore */ }
}
_server = createMcpServer();
_transport = new WebStandardStreamableHTTPServerTransport({
sessionIdGenerator: () => randomUUID(),
});
_activeTransportMode = mode;
_startedAt = Date.now();
// Connect server to transport (fire-and-forget, will be ready by first request)
void _server.connect(_transport);
console.log(`[MCP] HTTP transport started (${mode})`);
return { server: _server, transport: _transport };
}
// ────── Streamable HTTP Handler ────────────────────────────
/**
* Handle Streamable HTTP requests (POST / GET / DELETE).
* Used by the Next.js route at /api/mcp/stream.
*/
export async function handleMcpStreamableHTTP(request: Request): Promise<Response> {
const { transport } = ensureServer("streamable-http");
try {
return await transport.handleRequest(request);
} catch (err) {
console.error("[MCP] Streamable HTTP error:", err);
return new Response(
JSON.stringify({ error: "MCP transport error" }),
{ status: 500, headers: { "Content-Type": "application/json" } },
);
}
}
/**
* Handle SSE requests.
* SSE transport is implemented via Streamable HTTP transport with GET for SSE stream
* and POST for messages (the Streamable HTTP transport supports both patterns).
*/
export async function handleMcpSSE(request: Request): Promise<Response> {
const { transport } = ensureServer("sse");
try {
return await transport.handleRequest(request);
} catch (err) {
console.error("[MCP] SSE error:", err);
return new Response(
JSON.stringify({ error: "MCP SSE transport error" }),
{ status: 500, headers: { "Content-Type": "application/json" } },
);
}
}
// ────── Status & Lifecycle ─────────────────────────────────
export function getMcpHttpStatus(): {
online: boolean;
transport: string | null;
startedAt: number | null;
uptime: string | null;
} {
const online = _transport !== null && _activeTransportMode !== null;
return {
online,
transport: _activeTransportMode,
startedAt: _startedAt,
uptime: _startedAt ? `${Math.floor((Date.now() - _startedAt) / 1000)}s` : null,
};
}
export function shutdownMcpHttp(): void {
if (_transport) {
try { _transport.close(); } catch { /* ignore */ }
}
_server = null;
_transport = null;
_activeTransportMode = null;
_startedAt = null;
console.log("[MCP] HTTP transport shutdown");
}
export function isMcpHttpActive(): boolean {
return _transport !== null;
}

View File

@@ -0,0 +1,20 @@
/**
* OmniRoute MCP Server — barrel export.
*/
export { createMcpServer, startMcpStdio } from "./server.ts";
export { logToolCall, getRecentAuditEntries, getAuditStats, queryAuditEntries } from "./audit.ts";
export {
resolveMcpHeartbeatPath,
readMcpHeartbeat,
isMcpHeartbeatOnline,
isProcessAlive,
} from "./runtimeHeartbeat.ts";
export {
handleMcpSSE,
handleMcpStreamableHTTP,
getMcpHttpStatus,
shutdownMcpHttp,
isMcpHttpActive,
} from "./httpTransport.ts";
export * from "./schemas/index.ts";

View File

@@ -0,0 +1,162 @@
/**
* MCP Runtime Heartbeat
*
* Persists MCP stdio process liveness into DATA_DIR/runtime/mcp-heartbeat.json
* so dashboard APIs can report real online/offline state.
*/
import { promises as fs } from "node:fs";
import { homedir } from "node:os";
import { join } from "node:path";
export type McpHeartbeatSnapshot = {
pid: number;
startedAt: string;
lastHeartbeatAt: string;
version: string;
transport: "stdio";
scopesEnforced: boolean;
allowedScopes: string[];
toolCount: number;
};
const HEARTBEAT_FILE = "mcp-heartbeat.json";
const RUNTIME_DIR = "runtime";
const DEFAULT_INTERVAL_MS = 5000;
function resolveDataDir(): string {
const configured = process.env.DATA_DIR;
if (typeof configured === "string" && configured.trim().length > 0) {
return configured.trim();
}
return join(homedir(), ".omniroute");
}
export function resolveMcpHeartbeatPath(): string {
return join(resolveDataDir(), RUNTIME_DIR, HEARTBEAT_FILE);
}
async function writeHeartbeat(snapshot: McpHeartbeatSnapshot): Promise<void> {
const heartbeatPath = resolveMcpHeartbeatPath();
const runtimeDir = join(resolveDataDir(), RUNTIME_DIR);
await fs.mkdir(runtimeDir, { recursive: true });
await fs.writeFile(heartbeatPath, JSON.stringify(snapshot, null, 2), "utf-8");
}
export function startMcpHeartbeat(config: {
version: string;
scopesEnforced: boolean;
allowedScopes: string[];
toolCount: number;
intervalMs?: number;
}): () => void {
const startedAt = new Date().toISOString();
let timer: ReturnType<typeof setInterval> | null = null;
let stopped = false;
const intervalMs =
typeof config.intervalMs === "number" && config.intervalMs > 0
? config.intervalMs
: DEFAULT_INTERVAL_MS;
const tick = async () => {
if (stopped) return;
const snapshot: McpHeartbeatSnapshot = {
pid: process.pid,
startedAt,
lastHeartbeatAt: new Date().toISOString(),
version: config.version,
transport: "stdio",
scopesEnforced: config.scopesEnforced,
allowedScopes: [...config.allowedScopes],
toolCount: config.toolCount,
};
try {
await writeHeartbeat(snapshot);
} catch (error) {
const message = error instanceof Error ? error.message : String(error);
console.error("[MCP Heartbeat] Failed to write heartbeat:", message);
}
};
void tick();
timer = setInterval(() => {
void tick();
}, intervalMs);
return () => {
if (stopped) return;
stopped = true;
if (timer) {
clearInterval(timer);
timer = null;
}
// Keep last snapshot on disk for post-mortem/offline reporting.
void tick();
};
}
export async function readMcpHeartbeat(): Promise<McpHeartbeatSnapshot | null> {
const heartbeatPath = resolveMcpHeartbeatPath();
try {
const raw = await fs.readFile(heartbeatPath, "utf-8");
const parsed = JSON.parse(raw) as Partial<McpHeartbeatSnapshot>;
if (!parsed || typeof parsed !== "object") return null;
if (
typeof parsed.pid !== "number" ||
typeof parsed.startedAt !== "string" ||
typeof parsed.lastHeartbeatAt !== "string" ||
typeof parsed.version !== "string" ||
parsed.transport !== "stdio" ||
typeof parsed.scopesEnforced !== "boolean" ||
!Array.isArray(parsed.allowedScopes) ||
typeof parsed.toolCount !== "number"
) {
return null;
}
const allowedScopes = parsed.allowedScopes.filter((scope): scope is string => {
return typeof scope === "string";
});
return {
pid: parsed.pid,
startedAt: parsed.startedAt,
lastHeartbeatAt: parsed.lastHeartbeatAt,
version: parsed.version,
transport: "stdio",
scopesEnforced: parsed.scopesEnforced,
allowedScopes,
toolCount: parsed.toolCount,
};
} catch {
return null;
}
}
export function isProcessAlive(pid: number): boolean {
if (!Number.isFinite(pid) || pid <= 0) return false;
try {
process.kill(pid, 0);
return true;
} catch {
return false;
}
}
export function isMcpHeartbeatOnline(
snapshot: McpHeartbeatSnapshot | null,
options?: { staleAfterMs?: number; requireLivePid?: boolean }
): boolean {
if (!snapshot) return false;
const staleAfterMs =
typeof options?.staleAfterMs === "number" && options.staleAfterMs > 0
? options.staleAfterMs
: DEFAULT_INTERVAL_MS * 3;
const elapsed = Date.now() - new Date(snapshot.lastHeartbeatAt).getTime();
if (!Number.isFinite(elapsed) || elapsed > staleAfterMs) return false;
if (options?.requireLivePid === false) return true;
return isProcessAlive(snapshot.pid);
}

View File

@@ -0,0 +1,203 @@
/**
* A2A (Agent-to-Agent) Schemas — Contracts for OmniRoute A2A Server.
*
* Defines the Agent Card structure, Task lifecycle, Message format,
* and all A2A protocol types conforming to A2A Protocol v0.3.
*/
import { z } from "zod";
// ============ Agent Card Schema ============
export const AgentSkillSchema = z.object({
id: z.string(),
name: z.string(),
description: z.string(),
tags: z.array(z.string()),
examples: z.array(z.string()).optional(),
});
export const AgentCardSchema = z.object({
name: z.string(),
description: z.string(),
url: z.string().url(),
version: z.string(),
capabilities: z.object({
streaming: z.boolean(),
pushNotifications: z.boolean(),
}),
skills: z.array(AgentSkillSchema),
authentication: z.object({
schemes: z.array(z.string()),
apiKeyHeader: z.string().optional(),
}),
});
export type AgentCard = z.infer<typeof AgentCardSchema>;
export type AgentSkill = z.infer<typeof AgentSkillSchema>;
// ============ Task Schema ============
export const TaskStateEnum = z.enum(["submitted", "working", "completed", "failed", "cancelled"]);
export type TaskState = z.infer<typeof TaskStateEnum>;
export const TaskInputSchema = z.object({
messages: z
.array(
z.object({
role: z.string(),
content: z.string(),
})
)
.optional(),
model: z.string().optional(),
combo: z.string().optional(),
budget: z.number().optional(),
role: z
.enum(["coding", "review", "planning", "analysis", "debugging", "documentation"])
.optional(),
metadata: z.record(z.unknown()).optional(),
});
export const CostEnvelopeSchema = z.object({
estimated: z.number(),
actual: z.number(),
currency: z.string().default("USD"),
});
export const ResilienceTraceEventSchema = z.object({
event: z.string(),
provider: z.string().optional(),
reason: z.string().optional(),
timestamp: z.string(),
});
export const PolicyVerdictSchema = z.object({
allowed: z.boolean(),
reason: z.string(),
restrictions: z.array(z.string()).optional(),
});
export const TaskOutputSchema = z.object({
response: z
.object({
content: z.string(),
model: z.string(),
tokens: z.object({
prompt: z.number(),
completion: z.number(),
}),
})
.optional(),
routingExplanation: z.string().optional(),
costEnvelope: CostEnvelopeSchema.optional(),
resilienceTrace: z.array(ResilienceTraceEventSchema).optional(),
policyVerdict: PolicyVerdictSchema.optional(),
});
export const TaskSchema = z.object({
id: z.string().uuid(),
state: TaskStateEnum,
skillId: z.string(),
input: TaskInputSchema.optional(),
output: TaskOutputSchema.optional(),
createdAt: z.string().datetime(),
updatedAt: z.string().datetime(),
completedAt: z.string().datetime().nullable().optional(),
expiresAt: z.string().datetime().nullable().optional(),
});
export type Task = z.infer<typeof TaskSchema>;
export type TaskInput = z.infer<typeof TaskInputSchema>;
export type TaskOutput = z.infer<typeof TaskOutputSchema>;
export type CostEnvelope = z.infer<typeof CostEnvelopeSchema>;
export type ResilienceTraceEvent = z.infer<typeof ResilienceTraceEventSchema>;
export type PolicyVerdict = z.infer<typeof PolicyVerdictSchema>;
// ============ JSON-RPC 2.0 Schemas ============
export const JsonRpcRequestSchema = z.object({
jsonrpc: z.literal("2.0"),
method: z.enum(["message/send", "message/stream", "tasks/get", "tasks/cancel"]),
params: z.record(z.unknown()),
id: z.union([z.string(), z.number()]),
});
export const JsonRpcResponseSchema = z.object({
jsonrpc: z.literal("2.0"),
result: z.unknown().optional(),
error: z
.object({
code: z.number(),
message: z.string(),
data: z.unknown().optional(),
})
.optional(),
id: z.union([z.string(), z.number()]).nullable(),
});
export type JsonRpcRequest = z.infer<typeof JsonRpcRequestSchema>;
export type JsonRpcResponse = z.infer<typeof JsonRpcResponseSchema>;
// ============ Message Schemas ============
export const MessageSendParamsSchema = z.object({
task: z
.object({
skillId: z.string(),
})
.optional(),
message: z.object({
role: z.string().default("user"),
content: z.string(),
metadata: z.record(z.unknown()).optional(),
}),
config: z
.object({
model: z.string().optional(),
combo: z.string().optional(),
budget: z.number().optional(),
taskRole: z
.enum(["coding", "review", "planning", "analysis", "debugging", "documentation"])
.optional(),
})
.optional(),
});
export const TasksGetParamsSchema = z.object({
taskId: z.string().uuid(),
});
export const TasksCancelParamsSchema = z.object({
taskId: z.string().uuid(),
});
export type MessageSendParams = z.infer<typeof MessageSendParamsSchema>;
export type TasksGetParams = z.infer<typeof TasksGetParamsSchema>;
export type TasksCancelParams = z.infer<typeof TasksCancelParamsSchema>;
// ============ SSE Event Types ============
export const A2A_SSE_EVENTS = {
TASK_STATUS: "task.status",
TASK_ARTIFACT: "task.artifact",
TASK_CHUNK: "task.chunk",
TASK_COMPLETE: "task.complete",
TASK_ERROR: "task.error",
HEARTBEAT: "heartbeat",
} as const;
// ============ A2A Error Codes ============
export const A2A_ERROR_CODES = {
INVALID_REQUEST: -32600,
METHOD_NOT_FOUND: -32601,
INVALID_PARAMS: -32602,
INTERNAL_ERROR: -32603,
TASK_NOT_FOUND: -32001,
TASK_ALREADY_COMPLETED: -32002,
UNAUTHORIZED: -32003,
BUDGET_EXCEEDED: -32004,
PROVIDER_UNAVAILABLE: -32005,
} as const;

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